driver_tsip.c 151 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394
  1. /*
  2. * Handle the Trimble TSIP packet format
  3. * by Rob Janssen, PE1CHL.
  4. * Acutime Gold support by Igor Socec <igorsocec@gmail.com>
  5. * Trimble RES multi-constellation support by Nuno Goncalves <nunojpg@gmail.com>
  6. *
  7. * Week counters are not limited to 10 bits. It's unknown what
  8. * the firmware is doing to disambiguate them, if anything; it might just
  9. * be adding a fixed offset based on a hidden epoch value, in which case
  10. * unhappy things will occur on the next rollover.
  11. *
  12. * TSIPv1 and RES270 support added by Gary E. Miller <gem@rellim.com>
  13. *
  14. * This file is Copyright 2010 by the GPSD project
  15. * SPDX-License-Identifier: BSD-2-clause
  16. */
  17. #include "../include/gpsd_config.h" /* must be before all includes */
  18. #include <math.h>
  19. #include <stdbool.h>
  20. #include <stdio.h>
  21. #include <stdlib.h> // For llabs()
  22. #include <string.h>
  23. #include <time.h>
  24. #include <unistd.h>
  25. #include "../include/compiler.h" // for FALLTHROUGH
  26. #include "../include/gpsd.h"
  27. #include "../include/bits.h"
  28. #include "../include/strfuncs.h"
  29. #include "../include/timespec.h"
  30. #ifdef TSIP_ENABLE
  31. // RES SMT 360 has 32 max channels, use 64 for next gen
  32. #define TSIP_CHANNELS 64
  33. /* defines for Set or Request I/O Options (0x35)
  34. * SMT 360 default: IO1_DP|IO1_LLA, IO2_ENU, 0, IO4_DBHZ */
  35. // byte 1 Position
  36. #define IO1_ECEF 1
  37. #define IO1_LLA 2
  38. #define IO1_MSL 4
  39. #define IO1_DP 0x10
  40. // IO1_8F20 not in SMT 360
  41. #define IO1_8F20 0x20
  42. // byte 2 Velocity
  43. #define IO2_VECEF 1
  44. #define IO2_ENU 2
  45. // byte 3 Timing
  46. #define IO3_UTC 1
  47. // byte 4 Aux/Reserved
  48. #define IO4_RAW 1
  49. #define IO4_DBHZ 8
  50. #define SEMI_2_DEG (180.0 / 2147483647) /* 2^-31 semicircle to deg */
  51. void configuration_packets_acutime_gold(struct gps_device_t *session);
  52. void configuration_packets_res360(struct gps_device_t *session);
  53. void configuration_packets_generic(struct gps_device_t *session);
  54. /* convert TSIP SV Type to satellite_t.gnssid and satellite_t.svid
  55. * return gnssid directly, svid indirectly through pointer */
  56. static unsigned char tsip_gnssid(unsigned svtype, short prn,
  57. unsigned char *svid)
  58. {
  59. // initialized to shut up clang
  60. unsigned char gnssid = 0;
  61. *svid = 0;
  62. switch (svtype) {
  63. case 0:
  64. if (0 < prn && 33 > prn) {
  65. gnssid = GNSSID_GPS;
  66. *svid = prn;
  67. } else if (32 < prn && 55 > prn) {
  68. // RES SMT 360 and ICM SMT 360 put SBAS in 33-54
  69. gnssid = GNSSID_SBAS;
  70. *svid = prn + 87;
  71. } else if (64 < prn && 97 > prn) {
  72. // RES SMT 360 and ICM SMT 360 put GLONASS in 65-96
  73. gnssid = GNSSID_GLO;
  74. *svid = prn - 64;
  75. } else if (96 < prn && 134 > prn) {
  76. // RES SMT 360 and ICM SMT 360 put Galileo in 97-133
  77. gnssid = GNSSID_GAL;
  78. *svid = prn - 96;
  79. } else if (119 < prn && 139 > prn) {
  80. // Copernicus (II) put SBAS in 120-138
  81. gnssid = GNSSID_SBAS;
  82. *svid = prn + 87;
  83. } else if (183 == prn) {
  84. gnssid = GNSSID_QZSS;
  85. *svid = 1;
  86. } else if (192 <= prn && 193 >= prn) {
  87. gnssid = GNSSID_QZSS;
  88. *svid = prn - 190;
  89. } else if (200 == prn) {
  90. gnssid = GNSSID_QZSS;
  91. *svid = 4;
  92. } else if (200 < prn && 238 > prn) {
  93. // BeidDou in 201-237
  94. gnssid = GNSSID_BD;
  95. *svid = prn - 200;
  96. }
  97. // else: huh?
  98. break;
  99. case 1:
  100. gnssid = GNSSID_GLO; // GLONASS
  101. *svid = prn - 64;
  102. break;
  103. case 2:
  104. gnssid = GNSSID_BD; // BeiDou
  105. *svid = prn - 200;
  106. break;
  107. case 3:
  108. gnssid = GNSSID_GAL; // Galileo
  109. *svid = prn - 96;
  110. break;
  111. case 5:
  112. gnssid = GNSSID_QZSS; // QZSS
  113. switch (prn) {
  114. case 183:
  115. *svid = 1;
  116. break;
  117. case 192:
  118. *svid = 2;
  119. break;
  120. case 193:
  121. *svid = 3;
  122. break;
  123. case 200:
  124. *svid = 4;
  125. break;
  126. default:
  127. *svid = prn;
  128. break;
  129. }
  130. break;
  131. case 4:
  132. FALLTHROUGH
  133. case 6:
  134. FALLTHROUGH
  135. case 7:
  136. FALLTHROUGH
  137. default:
  138. *svid = 0;
  139. gnssid = 0;
  140. break;
  141. }
  142. return gnssid;
  143. }
  144. /* tsip1_checksum()
  145. * compute TSIP version 1 checksum
  146. *
  147. * Return: checksum
  148. */
  149. static char tsip1_checksum(const char *buf, size_t len)
  150. {
  151. char checksum = 0;
  152. size_t index;
  153. for(index = 0; index < len; index++) {
  154. checksum ^= buf[index];
  155. }
  156. return checksum;
  157. }
  158. /* tsip_write1() - send old style TSIP message, improved tsip_write()
  159. * buf - the packet
  160. * len - length of buf
  161. *
  162. * Adds leading DLE, and the trailing DLE, ETX
  163. *
  164. * Return: 0 == OK
  165. * -1 == write fail
  166. */
  167. static ssize_t tsip_write1(struct gps_device_t *session,
  168. char *buf, size_t len)
  169. {
  170. char *ep, *cp;
  171. char obuf[100];
  172. size_t olen = len;
  173. if (session->context->readonly) {
  174. return 0;
  175. }
  176. if ((NULL == buf) ||
  177. 0 == len ||
  178. (sizeof(session->msgbuf) / 2) < len) {
  179. // could over run, do not chance it
  180. return -1;
  181. }
  182. session->msgbuf[0] = '\x10';
  183. ep = session->msgbuf + 1;
  184. for (cp = buf; olen-- > 0; cp++) {
  185. if ('\x10' == *cp) {
  186. *ep++ = '\x10';
  187. }
  188. *ep++ = *cp;
  189. }
  190. *ep++ = '\x10';
  191. *ep++ = '\x03';
  192. session->msgbuflen = (size_t)(ep - session->msgbuf);
  193. GPSD_LOG(LOG_PROG, &session->context->errout,
  194. "TSIP: tsip_write1(0x%s)\n",
  195. gpsd_hexdump(obuf, sizeof(obuf), &session->msgbuf[1], len + 1));
  196. if (gpsd_write(session, session->msgbuf, session->msgbuflen) !=
  197. (ssize_t) session->msgbuflen)
  198. return -1;
  199. return 0;
  200. }
  201. /* tsip_detect()
  202. *
  203. * see if it looks like a TSIP device (speaking 9600O81) is listening and
  204. * return 1 if found, 0 if not
  205. */
  206. static bool tsip_detect(struct gps_device_t *session)
  207. {
  208. char buf[BUFSIZ];
  209. bool ret = false;
  210. int myfd;
  211. speed_t old_baudrate;
  212. char old_parity;
  213. unsigned int old_stopbits;
  214. old_baudrate = session->gpsdata.dev.baudrate;
  215. old_parity = session->gpsdata.dev.parity;
  216. old_stopbits = session->gpsdata.dev.stopbits;
  217. // FIXME. Should respect fixed speed/framing
  218. gpsd_set_speed(session, 9600, 'O', 1);
  219. /* request firmware revision and look for a valid response */
  220. putbyte(buf, 0, 0x10);
  221. putbyte(buf, 1, 0x1f);
  222. putbyte(buf, 2, 0x10);
  223. putbyte(buf, 3, 0x03);
  224. myfd = session->gpsdata.gps_fd;
  225. if (write(myfd, buf, 4) == 4) {
  226. unsigned int n;
  227. struct timespec to;
  228. // FIXME: this holds the main loop from running...
  229. for (n = 0; n < 3; n++) {
  230. // wait one second
  231. to.tv_sec = 1;
  232. to.tv_nsec = 0;
  233. if (!nanowait(myfd, &to))
  234. break;
  235. if (generic_get(session) >= 0) {
  236. if (session->lexer.type == TSIP_PACKET) {
  237. GPSD_LOG(LOG_RAW, &session->context->errout,
  238. "TSIP: tsip_detect found\n");
  239. ret = true;
  240. break;
  241. }
  242. }
  243. }
  244. }
  245. if (!ret)
  246. /* return serial port to original settings */
  247. gpsd_set_speed(session, old_baudrate, old_parity, old_stopbits);
  248. return ret;
  249. }
  250. /* send the next TSIPv1 query
  251. * Return: void
  252. */
  253. static void tsipv1_query(struct gps_device_t *session, int index)
  254. {
  255. char snd_buf[24]; // send buffer
  256. switch (index) {
  257. case 0:
  258. // x90-01, GNSS config
  259. snd_buf[0] = 0x91; // id
  260. snd_buf[1] = 0x01; // sub id
  261. putbe16(snd_buf, 2, 2); // length
  262. snd_buf[4] = 0; // mode: query
  263. snd_buf[5] = tsip1_checksum(snd_buf, 5); // checksum
  264. (void)tsip_write1(session, snd_buf, 6);
  265. break;
  266. case 1:
  267. // x90-00, query protocol version
  268. snd_buf[0] = 0x90; // id
  269. snd_buf[1] = 0x00; // sub id
  270. putbe16(snd_buf, 2, 2); // length
  271. snd_buf[4] = 0; // mode: query
  272. snd_buf[5] = tsip1_checksum(snd_buf, 5); // checksum
  273. (void)tsip_write1(session, snd_buf, 6);
  274. break;
  275. case 2:
  276. // x90-01, query GNSS config version
  277. snd_buf[0] = 0x90; // id
  278. snd_buf[1] = 0x01; // sub id
  279. putbe16(snd_buf, 2, 2); // length
  280. snd_buf[4] = 0; // mode: query
  281. snd_buf[5] = tsip1_checksum(snd_buf, 5); // checksum
  282. (void)tsip_write1(session, snd_buf, 6);
  283. break;
  284. case 3:
  285. // x91-03, query timing config
  286. snd_buf[0] = 0x91; // id
  287. snd_buf[1] = 0x03; // sub id
  288. putbe16(snd_buf, 2, 2); // length
  289. snd_buf[4] = 0; // mode: query
  290. snd_buf[5] = tsip1_checksum(snd_buf, 5); // checksum
  291. (void)tsip_write1(session, snd_buf, 6);
  292. break;
  293. case 4:
  294. // x91-04, self survey config
  295. snd_buf[0] = 0x91; // id
  296. snd_buf[1] = 0x04; // sub id
  297. putbe16(snd_buf, 2, 2); // length
  298. snd_buf[4] = 0; // mode: query
  299. snd_buf[5] = tsip1_checksum(snd_buf, 5); // checksum
  300. (void)tsip_write1(session, snd_buf, 6);
  301. break;
  302. case 5:
  303. // x93-00, production info
  304. snd_buf[0] = 0x93; // id
  305. snd_buf[1] = 0x00; // sub id
  306. putbe16(snd_buf, 2, 2); // length
  307. snd_buf[4] = 0; // mode: query
  308. snd_buf[5] = tsip1_checksum(snd_buf, 5); // checksum
  309. (void)tsip_write1(session, snd_buf, 6);
  310. break;
  311. case 6:
  312. if (session->context->passive) {
  313. // x91-05, query current periodic messages
  314. snd_buf[0] = 0x91; // id
  315. snd_buf[1] = 0x05; // sub id
  316. putbe16(snd_buf, 2, 3); // length
  317. snd_buf[4] = 0; // mode: query
  318. snd_buf[5] = 0xff; // port: current port
  319. snd_buf[6] = tsip1_checksum(snd_buf, 6); // checksum
  320. (void)tsip_write1(session, snd_buf, 7);
  321. } else {
  322. /* request everything periodically, x91-05
  323. * little harm at 115.2 kbps, this also responses as a query */
  324. snd_buf[0] = 0x91; // id
  325. snd_buf[1] = 0x05; // sub id
  326. putbe16(snd_buf, 2, 19); // length
  327. snd_buf[4] = 0x01; // mode: set
  328. snd_buf[5] = 0xff; // port: current port
  329. putbe32(snd_buf, 6, 0x02aaa);
  330. putbe32(snd_buf, 10, 0); // reserved
  331. putbe32(snd_buf, 14, 0); // reserved
  332. putbe32(snd_buf, 18, 0); // reserved
  333. snd_buf[22] = tsip1_checksum(snd_buf, 22); // checksum
  334. (void)tsip_write1(session, snd_buf, 23);
  335. }
  336. break;
  337. default:
  338. // nothing to do
  339. break;
  340. }
  341. }
  342. /* tsipv1_svtype()
  343. * convert TSIPv1 SV Type to satellite_t.gnssid and satellite_t.sigid
  344. * PRN is already GNSS specific (1-99)
  345. * return gnssid directly, sigid indirectly through pointer
  346. *
  347. * Return: gnssid
  348. * 0xff on error
  349. */
  350. static unsigned char tsipv1_svtype(unsigned svtype, unsigned char *sigid)
  351. {
  352. unsigned char gnssid;
  353. switch (svtype) {
  354. case 1: // GPS L1C
  355. gnssid = GNSSID_GPS;
  356. *sigid = 0;
  357. break;
  358. case 2: // GPS L2. CL or CM?
  359. gnssid = GNSSID_GPS;
  360. *sigid = 3; // or, maybe 4
  361. break;
  362. case 3: // GPS L5. I or Q?
  363. gnssid = GNSSID_GPS;
  364. *sigid = 6; // or maybe 7
  365. break;
  366. case 5: // GLONASS G1
  367. gnssid = GNSSID_GLO;
  368. *sigid = 0;
  369. break;
  370. case 6: // GLONASS G2
  371. gnssid = GNSSID_GLO;
  372. *sigid = 2;
  373. break;
  374. case 9: // SBAS, assume L1
  375. gnssid = GNSSID_SBAS;
  376. *sigid = 0;
  377. break;
  378. case 13: // Beidou B1, D1 or D2?
  379. gnssid = GNSSID_BD;
  380. *sigid = 0; // or maybe 1
  381. break;
  382. case 14: // Beidou B2i
  383. gnssid = GNSSID_BD;
  384. *sigid = 2;
  385. break;
  386. case 15: // Beidou B2a
  387. gnssid = GNSSID_BD;
  388. *sigid = 3;
  389. break;
  390. case 17: // Galileo E1, C or B?
  391. gnssid = GNSSID_GAL;
  392. *sigid = 0; // or maybe 1
  393. break;
  394. case 18: // Galileo E5a, aI or aQ?
  395. gnssid = GNSSID_GAL;
  396. *sigid = 3; // or maybe 4?
  397. break;
  398. case 19: // Galileo E5b, bI or bQ?
  399. gnssid = GNSSID_GAL;
  400. *sigid = 5; // or maybe 6
  401. break;
  402. case 20: // Galileo E6
  403. gnssid = GNSSID_GAL;
  404. *sigid = 8; // no idea
  405. break;
  406. case 22: // QZSS L1
  407. gnssid = GNSSID_QZSS;
  408. *sigid = 0;
  409. break;
  410. case 23: // QZSS L2C
  411. gnssid = GNSSID_QZSS;
  412. *sigid = 4; // or maybe 5
  413. break;
  414. case 24: // QZSS L5
  415. gnssid = GNSSID_QZSS;
  416. *sigid = 8; // no idea
  417. break;
  418. case 26: // IRNSS L5
  419. gnssid = GNSSID_IRNSS;
  420. *sigid = 8; // no idea
  421. break;
  422. case 4: // Reserved
  423. FALLTHROUGH
  424. case 7: // Reserved
  425. FALLTHROUGH
  426. case 8: // Reserved
  427. FALLTHROUGH
  428. case 10: // Reservced
  429. FALLTHROUGH
  430. case 11: // Reservced
  431. FALLTHROUGH
  432. case 12: // Reservced
  433. FALLTHROUGH
  434. case 16: // Reserved
  435. FALLTHROUGH
  436. case 21: // Reserved
  437. FALLTHROUGH
  438. case 25: // Reserved
  439. FALLTHROUGH
  440. default:
  441. *sigid = 0xff;
  442. return 0xff;
  443. }
  444. return gnssid;
  445. }
  446. /* parse TSIP v1 packages.
  447. * Currently only in RES720 devices, from 2020 onward.
  448. * buf: raw data, with DLE stuffing removed
  449. * len: length of data in buf
  450. *
  451. * return: mask
  452. */
  453. static gps_mask_t tsipv1_parse(struct gps_device_t *session, unsigned id,
  454. const char *buf, int len)
  455. {
  456. gps_mask_t mask = 0;
  457. unsigned sub_id, length, mode;
  458. unsigned short week;
  459. uint32_t tow; // time of week in milli seconds
  460. timespec_t ts_tow;
  461. unsigned u1, u2, u3, u4, u5, u6, u7, u8, u9;
  462. unsigned u10, u11, u12, u13, u14, u15; // , u16, u17, u18, u19;
  463. int s1;
  464. double d1, d2, d3, d4, d5, d6, d7, d8, d9;
  465. struct tm date = {0};
  466. bool bad_len = false;
  467. unsigned char chksum;
  468. char buf2[BUFSIZ];
  469. unsigned char gnssid, sigid;
  470. if (4 > len) {
  471. // should never happen
  472. GPSD_LOG(LOG_WARN, &session->context->errout,
  473. "TSIPv1 0x%02x: runt, got len %u\n",
  474. id, len);
  475. return mask;
  476. }
  477. sub_id = (unsigned)buf[0];
  478. length = getbeu16(buf, 1); // expected length
  479. mode = (unsigned)buf[3];
  480. if ((length + 3) != (unsigned)len) {
  481. GPSD_LOG(LOG_WARN, &session->context->errout,
  482. "TSIPv1 x%02x-%02x: Bad Length, "
  483. "length got %d expected %u mode %u\n",
  484. id, sub_id, len, length + 3, mode);
  485. return mask;
  486. }
  487. // checksum is id, sub id, length, mode, data, not including trailer
  488. // length is mode + data + checksum
  489. chksum = id;
  490. for (u1 = 0; u1 < (length + 3); u1++ ) {
  491. chksum ^= buf[u1];
  492. }
  493. if (0 != chksum) {
  494. GPSD_LOG(LOG_WARN, &session->context->errout,
  495. "TSIPv1 x%02x-%02x: Bad Checksum "
  496. "length %d/%u mode %u\n",
  497. id, sub_id, len, length + 3, mode);
  498. return mask;
  499. }
  500. GPSD_LOG(LOG_DATA, &session->context->errout,
  501. "TSIPv1 x%02x-%02x: length %d/%u mode %u\n",
  502. id, sub_id, len, length + 3, mode);
  503. if (2 != mode) {
  504. /* Don't decode queries (mode 0) or set (mode 1).
  505. * Why would we even see one? */
  506. return mask;
  507. }
  508. // FIXME: check len/length and checksum
  509. switch ((id << 8) | sub_id) {
  510. case 0x9000:
  511. // Protocol Version
  512. if (11 > length) {
  513. bad_len = true;
  514. break;
  515. }
  516. u1 = (unsigned)buf[4]; // NMEA Major version
  517. u2 = (unsigned)buf[5]; // NMEA Minor version
  518. u3 = (unsigned)buf[6]; // TSIP version
  519. u4 = (unsigned)buf[7]; // Trimble NMEA version
  520. u6 = getbeu32(buf, 8); // reserved
  521. u7 = (unsigned)buf[12]; // reserved
  522. GPSD_LOG(LOG_PROG, &session->context->errout,
  523. "TSIPv1 x90-00: NMEA %u.%u TSIP %u TNMEA %u "
  524. "res x%04x x%02x \n",
  525. u1, u2, u3, u4, u6, u7);
  526. tsipv1_query(session, 0);
  527. break;
  528. case 0x9001:
  529. /* Receiver Version Information
  530. * Received in response to the TSIPv1 probe */
  531. if (11 > length) {
  532. bad_len = true;
  533. break;
  534. }
  535. u1 = (unsigned)buf[4]; // Major version
  536. u2 = (unsigned)buf[5]; // Minor version
  537. u3 = (unsigned)buf[6]; // Build number
  538. u4 = (unsigned)buf[7]; // Build month
  539. u5 = (unsigned)buf[8]; // Build day
  540. u6 = getbeu16(buf, 9); // Build year
  541. u7 = getbeu16(buf, 11); // Hardware ID
  542. u8 = (unsigned)buf[13]; // Product Name length
  543. session->driver.tsip.hardware_code = u7;
  544. // check for valid module name length
  545. // RES720 is 27 long
  546. // check for valid module name length, again
  547. if (40 < u8) {
  548. u8 = 40;
  549. }
  550. if ((int)u8 > (len - 13)) {
  551. u8 = (unsigned)len - 13;
  552. }
  553. memcpy(buf2, &buf[14], u8);
  554. buf2[u8] = '\0';
  555. (void)snprintf(session->subtype, sizeof(session->subtype),
  556. "fw %u.%u %u %02u/%02u/%04u %.40s",
  557. u1, u2, u3, u6, u5, u4, buf2);
  558. GPSD_LOG(LOG_PROG, &session->context->errout,
  559. "TSIPv1 x90-01: Version %u.%u Build %u %u/%u/%u hwid %u, "
  560. "%.*s[%u]\n",
  561. u1, u2, u3, u6, u5, u4, u7, u8, buf2, u8);
  562. mask |= DEVICEID_SET;
  563. tsipv1_query(session, 1);
  564. break;
  565. case 0x9100:
  566. // Port Configuration
  567. if (18 > length) {
  568. bad_len = true;
  569. break;
  570. }
  571. u1 = (unsigned)buf[4]; // port
  572. u2 = (unsigned)buf[5]; // port type
  573. u3 = (unsigned)buf[6]; // protocol
  574. u4 = (unsigned)buf[7]; // baud rate
  575. u5 = (unsigned)buf[8]; // data bits
  576. u6 = (unsigned)buf[9]; // parity
  577. u7 = (unsigned)buf[10]; // stop bits
  578. u8 = getbeu32(buf, 11); // reserved
  579. u9 = getbeu32(buf, 12); // reserved
  580. GPSD_LOG(LOG_PROG, &session->context->errout,
  581. "TSIPv1 x91-00: port %u type %u proto %u baud %u bits %u "
  582. "parity %u stop %u res x%04x %04x\n",
  583. u1, u2, u3, u4, u5, u6, u7, u8, u9);
  584. tsipv1_query(session, 2);
  585. break;
  586. case 0x9101:
  587. // GNSS Configuration
  588. if (28 > length) {
  589. bad_len = true;
  590. break;
  591. }
  592. // constellation, 0 to 26, mashup of constellation and signal
  593. u1 = getbeu32(buf, 4); // constellation
  594. d1 = getbef32((char *)buf, 8); // elevation mask
  595. d2 = getbef32((char *)buf, 12); // signal mask
  596. d3 = getbef32((char *)buf, 16); // PDOP mask
  597. u2 = (unsigned)buf[20]; // anti-jamming
  598. u3 = (unsigned)buf[21]; // fix rate
  599. d4 = getbef32((char *)buf, 22); // Antenna CAble delay, seconds
  600. u4 = getbeu32(buf, 26); // reserved
  601. GPSD_LOG(LOG_PROG, &session->context->errout,
  602. "TSIPv1 x91-01: cons %u el %f signal %f PDOP %f jam %u "
  603. "rate %u delay %f res x%04x\n",
  604. u1, d1, d2, d3, u2, u3, d4, u4);
  605. tsipv1_query(session, 3);
  606. break;
  607. case 0x9102:
  608. // NVS Configuration
  609. if (8 > length) {
  610. bad_len = true;
  611. break;
  612. }
  613. u1 = (unsigned)buf[6]; // status
  614. u2 = getbeu32(buf, 7); // reserved
  615. GPSD_LOG(LOG_PROG, &session->context->errout,
  616. "TSIPv1 x91-02: status %u res x%04x\n",
  617. u1, u2);
  618. break;
  619. case 0x9103:
  620. // Timing Configuration
  621. if (19 > length) {
  622. bad_len = true;
  623. break;
  624. }
  625. u1 = (unsigned)buf[4]; // time basee
  626. u2 = (unsigned)buf[5]; // PPS base
  627. u3 = (unsigned)buf[6]; // PPS mask
  628. u4 = getbeu16(buf, 7); // reserved
  629. u5 = getbeu16(buf, 9); // PPS width
  630. d1 = getbed64((char *)buf, 11); // PPS offset, in seconds
  631. GPSD_LOG(LOG_PROG, &session->context->errout,
  632. "TSIPv1 x91-03: time base %u PPS base %u mask %u res x%04x "
  633. "width %u offset %f\n",
  634. u1, u2, u3, u4, u5, d1);
  635. tsipv1_query(session, 4);
  636. break;
  637. case 0x9104:
  638. // Self-Survey Configuration
  639. if (11 > length) {
  640. bad_len = true;
  641. break;
  642. }
  643. u1 = (unsigned)buf[4]; // self-survey mask
  644. u2 = getbeu32(buf, 5); // self-survey length, # fixes
  645. u3 = getbeu16(buf, 9); // horz uncertainty, meters
  646. u4 = getbeu16(buf, 11); // vert uncertainty, meters
  647. GPSD_LOG(LOG_PROG, &session->context->errout,
  648. "TSIPv1 x91-04: mask %u length %u eph %u epv %u\n",
  649. u1, u2, u3, u4);
  650. tsipv1_query(session, 5);
  651. break;
  652. case 0x9105:
  653. // x91-05 Receiver Configuration
  654. if (19 > length) {
  655. bad_len = true;
  656. break;
  657. }
  658. u1 = (unsigned)buf[4]; // port
  659. u2 = getbeu32(buf, 5); // type of output
  660. u3 = getbeu32(buf, 9); // reserved
  661. u4 = getbeu32(buf, 13); // reserved
  662. u5 = getbeu32(buf, 17); // reserved
  663. GPSD_LOG(LOG_PROG, &session->context->errout,
  664. "TSIPv1 x91-05: port %u type x%04x res x%04x x%04x x%04x\n",
  665. u1, u2, u3, u4, u5);
  666. tsipv1_query(session, 7);
  667. break;
  668. case 0x9201:
  669. // Reset Cause
  670. if (3 > length) {
  671. bad_len = true;
  672. break;
  673. }
  674. u1 = (unsigned)buf[6]; // reset cause
  675. GPSD_LOG(LOG_WARN, &session->context->errout,
  676. "TSIPv1 x92-01: cause %u\n", u1);
  677. break;
  678. case 0x9300:
  679. // Production Information
  680. if (78 > length) {
  681. bad_len = true;
  682. break;
  683. }
  684. u1 = (unsigned)buf[4]; // reserved
  685. u2 = getbeu32(buf, 5); // serial number
  686. u3 = getbeu64(buf, 9); // extended serial number
  687. u4 = getbeu64(buf, 17); // extended serial number
  688. u5 = (unsigned)buf[25]; // build day
  689. u6 = (unsigned)buf[26]; // build month
  690. u7 = getbeu16(buf, 27); // build year
  691. u8 = (unsigned)buf[29]; // build hour
  692. u9 = getbeu16(buf, 30); // machine id
  693. u10 = getbeu64(buf, 32); // hardware ID string
  694. u11 = getbeu64(buf, 40); // hardware ID string
  695. u12 = getbeu64(buf, 48); // product ID string
  696. u13 = getbeu64(buf, 56); // product ID string
  697. u14 = getbeu32(buf, 64); // premium options
  698. u15 = getbeu32(buf, 78); // reserved
  699. // ignore 77 Osc search range, and 78–81 Osc offset, always 0xff
  700. (void)snprintf(session->subtype1, sizeof(session->subtype1),
  701. "hw %u %02u/%02u/%04u",
  702. u9, u5, u6, u7);
  703. GPSD_LOG(LOG_WARN, &session->context->errout,
  704. "TSIPv1 x93-00: res %u ser %u x%04x %04x Build %u/%u/%u %u "
  705. "machine %u hardware x%04x %04x product x%04x %04x "
  706. "options x%04x res x%04x\n",
  707. u1, u2, u3, u4, u7, u6, u5, u8, u9, u10,
  708. u11, u12, u13, u14, u15);
  709. tsipv1_query(session, 6);
  710. mask |= DEVICEID_SET;
  711. break;
  712. case 0xa000:
  713. // Firmware Upload
  714. // could be length 3, or 8, different data...
  715. switch (length) {
  716. case 3:
  717. u1 = (unsigned)buf[6]; // command
  718. GPSD_LOG(LOG_PROG, &session->context->errout,
  719. "TSIPv1 xa0-00: command %u\n", u1);
  720. break;
  721. case 8:
  722. // ACK/NAK
  723. u1 = (unsigned)buf[6]; // command
  724. u2 = (unsigned)buf[7]; // status
  725. u3 = getbeu16(buf, 8); // frame
  726. GPSD_LOG(LOG_PROG, &session->context->errout,
  727. "TSIPv1 xa0-00: command %u status %u frame %u\n",
  728. u1, u2, u3);
  729. break;
  730. default:
  731. bad_len = true;
  732. break;
  733. }
  734. break;
  735. case 0xa100:
  736. // Timing Information
  737. // the only message on by default
  738. if (32 > length) {
  739. bad_len = true;
  740. break;
  741. }
  742. tow = getbeu32(buf, 4);
  743. week = getbeu16(buf, 8);
  744. session->context->gps_week = week;
  745. date.tm_hour = (unsigned)buf[10]; // hours 0 - 23
  746. date.tm_min = (unsigned)buf[11]; // minutes 0 -59
  747. date.tm_sec = (unsigned)buf[12]; // seconds 0 - 60
  748. date.tm_mon = (unsigned)buf[13] - 1; // month 1 - 12
  749. date.tm_mday = (unsigned)buf[14]; // day of month 1 - 31
  750. date.tm_year = getbeu16(buf, 15) - 1900; // year
  751. u1 = (unsigned)buf[17]; // time base
  752. u2 = (unsigned)buf[18]; // PPS base
  753. u3 = (unsigned)buf[19]; // flags
  754. s1 = getbes16(buf, 20); // UTC Offset
  755. d1 = getbef32((char *)buf, 22); // PPS Quantization Error
  756. d2 = getbef32((char *)buf, 26); // Bias
  757. d3 = getbef32((char *)buf, 30); // Bias Rate
  758. // convert seconds to pico seconds
  759. session->gpsdata.qErr = (long)(d1 * 10e12);
  760. // fix.time is w/o leap seconds...
  761. session->newdata.time.tv_sec = mkgmtime(&date) - s1;
  762. session->newdata.time.tv_nsec = 0;
  763. session->context->leap_seconds = s1;
  764. session->context->valid |= LEAP_SECOND_VALID;
  765. GPSD_LOG(LOG_PROG, &session->context->errout,
  766. "TSIPv1 xa1-00: tow %u week %u %02u:%02u:%02u %4u/%02u/%02u "
  767. "base %u/%u flagsx%x UTC offset %d qErr %f Bias %f/%f\n",
  768. tow, week, date.tm_hour, date.tm_min, date.tm_sec,
  769. date.tm_year + 1900, date.tm_mon, date.tm_mday,
  770. u1, u2, u3, s1, d1, d2, d3);
  771. if (2 == (u3 & 2)) {
  772. // flags say we have good time
  773. // if we have good time, can we guess at fix mode?
  774. mask |= TIME_SET;
  775. if (1 == (u3 & 1)) {
  776. // good UTC
  777. mask |= NTPTIME_IS;
  778. }
  779. }
  780. if (0 == session->driver.tsip.hardware_code) {
  781. // Query Receiver Version Information
  782. (void)tsip_write1(session, "\x90\x01\x00\x02\x00\x93", 6);
  783. }
  784. mask |= CLEAR_IS; // ssems to always be first. Time to clear.
  785. break;
  786. case 0xa102:
  787. // Frequency Information
  788. if (17 > length) {
  789. bad_len = true;
  790. break;
  791. }
  792. d1 = getbef32((char *)buf, 6); // DAC voltage
  793. u1 = getbeu16(buf, 10); // DAC value
  794. u2 = (unsigned)buf[12]; // holdover status
  795. u3 = getbeu32(buf, 13); // holdover time
  796. d2 = getbef32((char *)buf, 17); // temperature, degrees C
  797. GPSD_LOG(LOG_PROG, &session->context->errout,
  798. "TSIPv1 xa1-02: DAC voltage %f value %u Holdover status %u "
  799. "time %u temp %f\n",
  800. d1, u1, u2, u3, d2);
  801. break;
  802. case 0xa111:
  803. // Position Information
  804. if (52 > length) {
  805. bad_len = true;
  806. break;
  807. }
  808. u1 = (unsigned)buf[4]; // position mask
  809. u2 = (unsigned)buf[5]; // fix type
  810. d1 = getbed64((char *)buf, 6); // latitude or X
  811. d2 = getbed64((char *)buf, 14); // longitude or Y
  812. d3 = getbed64((char *)buf, 22); // altitude or Z
  813. d4 = getbef32((char *)buf, 30); // velocity X or E
  814. d5 = getbef32((char *)buf, 34); // velocity Y or N
  815. d6 = getbef32((char *)buf, 38); // velocity Z or U
  816. d7 = getbef32((char *)buf, 42); // PDOP, surveyed or current
  817. d8 = getbef32((char *)buf, 46); // horz uncertainty
  818. d9 = getbef32((char *)buf, 50); // vert uncertainty
  819. session->gpsdata.dop.pdop = d7;
  820. mask |= DOP_SET;
  821. if (0 == (u1 & 1)) {
  822. session->newdata.status = STATUS_GPS;
  823. } else {
  824. session->newdata.status = STATUS_TIME;
  825. }
  826. if (0 == (u1 & 2)) {
  827. // LLA
  828. session->newdata.latitude = d1;
  829. session->newdata.longitude = d2;
  830. if (0 == (u1 & 4)) {
  831. // HAE
  832. session->newdata.altHAE = d3;
  833. } else {
  834. // MSL
  835. session->newdata.altMSL = d3;
  836. }
  837. mask |= LATLON_SET | ALTITUDE_SET;
  838. } else {
  839. // XYZ ECEF
  840. session->newdata.ecef.x = d1;
  841. session->newdata.ecef.y = d2;
  842. session->newdata.ecef.z = d3;
  843. mask |= ECEF_SET;
  844. }
  845. if (0 == (u1 & 1)) {
  846. // valid velocity
  847. if (0 == (u1 & 8)) {
  848. // Velocity ENU
  849. session->newdata.NED.velN = d5;
  850. session->newdata.NED.velE = d4;
  851. session->newdata.NED.velD = -d6;
  852. mask |= VNED_SET;
  853. } else {
  854. // Velocity ECEF
  855. session->newdata.ecef.vx = d4;
  856. session->newdata.ecef.vy = d5;
  857. session->newdata.ecef.vz = d6;
  858. mask |= VECEF_SET;
  859. }
  860. }
  861. switch (u2) {
  862. default:
  863. FALLTHROUGH
  864. case 0:
  865. session->newdata.mode = MODE_NO_FIX;
  866. break;
  867. case 1:
  868. session->newdata.mode = MODE_2D;
  869. break;
  870. case 2:
  871. session->newdata.mode = MODE_3D;
  872. }
  873. session->gpsdata.dop.pdop = d7;
  874. session->newdata.eph = d8; // 0 - 100, unknown units
  875. session->newdata.epv = d9; // 0 - 100, unknown units
  876. mask |= MODE_SET | STATUS_SET | DOP_SET | HERR_SET | VERR_SET;
  877. GPSD_LOG(LOG_PROG, &session->context->errout,
  878. "TSIPv1 xa1-11: mask %u fix %u Pos %f %f %f Vel %f %f %f "
  879. "PDOP %f eph %f epv %f\n",
  880. u1, u2, d1, d2, d3, d4, d5, d6, d7, d8, d9);
  881. break;
  882. case 0xa200:
  883. // Satellite Information
  884. if (25 > length) {
  885. bad_len = true;
  886. break;
  887. }
  888. u1 = (unsigned)buf[4]; // message number, 1 to X
  889. if (1 == u1) {
  890. // message number starts at 1, no way to know last number
  891. gpsd_zero_satellites(&session->gpsdata);
  892. // start of new cycle, save last count
  893. session->gpsdata.satellites_visible =
  894. session->driver.tsip.last_chan_seen;
  895. }
  896. session->driver.tsip.last_chan_seen = u1;
  897. // SV type, 0 to 26, mashup of constellation and signal
  898. u2 = (unsigned)buf[5];
  899. u3 = (unsigned)buf[6]; // PRN (svid) 1 to 32 (99)
  900. d1 = getbef32((char *)buf, 7); // azimuth, degrees
  901. d2 = getbef32((char *)buf, 11); // elevation, degrees
  902. d3 = getbef32((char *)buf, 15); // signal level, db-Hz
  903. u4 = getbeu32(buf, 19); // Flags
  904. // TOW of measurement, not current TOW!
  905. tow = getbeu32(buf, 23); // TOW, seconds
  906. session->driver.tsip.last_a200 = tow;
  907. ts_tow.tv_sec = tow;
  908. ts_tow.tv_nsec = 0;
  909. session->gpsdata.skyview_time =
  910. gpsd_gpstime_resolv(session, session->context->gps_week,
  911. ts_tow);
  912. // convert svtype to gnssid and svid
  913. gnssid = tsipv1_svtype(u2, &sigid);
  914. session->gpsdata.skyview[u1 - 1].gnssid = gnssid;
  915. session->gpsdata.skyview[u1 - 1].svid = u3;
  916. session->gpsdata.skyview[u1 - 1].sigid = sigid;
  917. // "real" NMEA 4.0 (not 4.10 ir 4.11) PRN
  918. session->gpsdata.skyview[u1 - 1].PRN = ubx2_to_prn(gnssid, u3);
  919. if (0 != (1 & u4)) {
  920. if (90.0 >= fabs(d2)) {
  921. session->gpsdata.skyview[u1 - 1].elevation = d2;
  922. }
  923. if (360.0 >= d1 &&
  924. 0.0 <= d1) {
  925. session->gpsdata.skyview[u1 - 1].azimuth = d1;
  926. }
  927. }
  928. session->gpsdata.skyview[u1 - 1].ss = d3;
  929. if (0 != (6 & u4)) {
  930. session->gpsdata.skyview[u1 - 1].used = true;
  931. }
  932. if ((int)u1 >= session->gpsdata.satellites_visible) {
  933. /* Last of the series? Assume same number of sats as
  934. * last cycle.
  935. * This will cause extra SKY if this set has more
  936. * sats than the last set. Will cause drop outs when
  937. * number of sats decreases. */
  938. if (10 < llabs(session->driver.tsip.last_a311 -
  939. session->driver.tsip.last_a200)) {
  940. // no xa3-11 in 10 seconds, so push out now
  941. mask |= SATELLITE_SET;
  942. session->driver.tsip.last_a200 = 0;
  943. }
  944. }
  945. /* If this series has fewer than last series there will
  946. * be no SKY, unless the cycle ender pushes the SKY */
  947. GPSD_LOG(LOG_PROG, &session->context->errout,
  948. "TSIPv1 xa2-00: num %u type %u (gnss %u sigid %u) PRN %u "
  949. "az %f el %f snr %f flags x%0x4 tow %u\n",
  950. u1, u2, gnssid, sigid, u3, d1, d2, d3, u4, tow);
  951. break;
  952. case 0xa300:
  953. // System Alarms
  954. if (18 > length) {
  955. bad_len = true;
  956. break;
  957. }
  958. u1 = getbeu32(buf, 4); // Minor Alarms
  959. u2 = getbeu32(buf, 8); // reserved
  960. u3 = getbeu32(buf, 12); // Major Alarms
  961. u4 = getbeu32(buf, 16); // reserved
  962. GPSD_LOG(LOG_PROG, &session->context->errout,
  963. "TSIPv1 xa3-00: Minor x%04x res x%04x Major x%04x "
  964. "res x%04u\n",
  965. u1, u2, u3, u4);
  966. break;
  967. case 0xa311:
  968. // Receiver Status
  969. if (29 > length) {
  970. bad_len = true;
  971. break;
  972. }
  973. u1 = (unsigned)buf[4]; // receiver mode
  974. u2 = (unsigned)buf[5]; // status
  975. u3 = (unsigned)buf[6]; // self survey progress 0 - 100
  976. d1 = getbef32((char *)buf, 7); // PDOP
  977. d2 = getbef32((char *)buf, 11); // HDOP
  978. d3 = getbef32((char *)buf, 15); // VDOP
  979. d4 = getbef32((char *)buf, 19); // TDOP
  980. d5 = getbef32((char *)buf, 23); // Temperature, degrees C
  981. session->gpsdata.dop.pdop = d1;
  982. session->gpsdata.dop.hdop = d2;
  983. session->gpsdata.dop.vdop = d3;
  984. session->gpsdata.dop.tdop = d4;
  985. // don't have tow, so use the one from xa2-00, if any
  986. session->driver.tsip.last_a311 = session->driver.tsip.last_a200;
  987. if (0 < session->driver.tsip.last_a200) {
  988. session->driver.tsip.last_a200 = 0;
  989. // TSIPv1 seem to be sent in numerical order, so this
  990. // is after xa2-00 and the sats. Push out any lingering sats.
  991. mask |= SATELLITE_SET;
  992. }
  993. mask |= REPORT_IS | DOP_SET;
  994. switch (u2) {
  995. case 0: // doing position fixes
  996. FALLTHROUGH
  997. case 4: // using 1 sat
  998. FALLTHROUGH
  999. case 5: // using 2 sat
  1000. FALLTHROUGH
  1001. case 6: // using 3 sat
  1002. session->newdata.status = STATUS_GPS;
  1003. mask |= STATUS_SET;
  1004. break;
  1005. case 1: // no GPS time
  1006. FALLTHROUGH
  1007. case 2: // PDOP too high
  1008. FALLTHROUGH
  1009. case 3: // no sats
  1010. session->newdata.status = STATUS_UNK;
  1011. mask |= STATUS_SET;
  1012. break;
  1013. case 255:
  1014. session->newdata.status = STATUS_TIME;
  1015. mask |= STATUS_SET;
  1016. break;
  1017. default:
  1018. // huh?
  1019. break;
  1020. }
  1021. GPSD_LOG(LOG_PROG, &session->context->errout,
  1022. "TSIPv1 xa3-11: mode %u status %u survey %u PDOP %f HDOP %f "
  1023. "VDOP %f TDOP %f temp %f\n",
  1024. u1, u2, u3, d1, d2, d3, d4, d5);
  1025. // usually the last message, except for A2-00
  1026. break;
  1027. case 0xa321:
  1028. /* Error Report
  1029. * expect errors for x1c-03 and x35-32 from TSIP probes
  1030. * 1 - Parameter error
  1031. * 2 - Length error
  1032. * 3 - Invalid packet format
  1033. * 4 - Invalid checksum
  1034. * 5 - Incorrect TNL/User mode
  1035. * 6 - Invalid Packet ID
  1036. * 7 - Invalid subpacket ID
  1037. * 8 - Update in progress
  1038. * 9 - Internal error caused div by 0
  1039. * 10 - Internal error (failed queuing)
  1040. */
  1041. if (5 > length) {
  1042. bad_len = true;
  1043. break;
  1044. }
  1045. u1 = (unsigned)buf[4]; // reference packet id
  1046. u2 = (unsigned)buf[5]; // reference sub packet id
  1047. u3 = (unsigned)buf[6]; // error code
  1048. GPSD_LOG(LOG_WARN, &session->context->errout,
  1049. "TSIPv1 xa3-21: id x%02x-%02x error: %u\n",
  1050. u1, u2, u3);
  1051. break;
  1052. case 0xd000:
  1053. // Debug Output type packet
  1054. if (3 > length) {
  1055. bad_len = true;
  1056. break;
  1057. }
  1058. u1 = (unsigned)buf[6]; // debug output type
  1059. GPSD_LOG(LOG_WARN, &session->context->errout,
  1060. "TSIPv1 xd0-00: debug %u\n", u1);
  1061. break;
  1062. case 0xd001:
  1063. // Trimble Debug config packet
  1064. if (4 > length) {
  1065. bad_len = true;
  1066. break;
  1067. }
  1068. u1 = (unsigned)buf[6]; // debug type
  1069. u2 = (unsigned)buf[7]; // debug level
  1070. GPSD_LOG(LOG_WARN, &session->context->errout,
  1071. "TSIPv1 xd0-01: debug type %u level %u\n", u1, u2);
  1072. break;
  1073. case 0xd040:
  1074. // Trimble Raw GNSS Debug Output packet
  1075. // length can be zero, contents undefined
  1076. GPSD_LOG(LOG_WARN, &session->context->errout,
  1077. "TSIPv1 xd0-40: raw GNSS data\n");
  1078. break;
  1079. case 0xd041:
  1080. // Trimble Raw GNSS Debug Output packet
  1081. // length can be zero, contents undefined
  1082. GPSD_LOG(LOG_WARN, &session->context->errout,
  1083. "TSIPv1 xd0-41: raw GNSS data\n");
  1084. break;
  1085. // undecoded:
  1086. case 0x9200:
  1087. // Receiver Reset, send only
  1088. FALLTHROUGH
  1089. case 0xa400:
  1090. // AGNSS, send only
  1091. FALLTHROUGH
  1092. default:
  1093. // Huh?
  1094. GPSD_LOG(LOG_WARN, &session->context->errout,
  1095. "TSIPv1 x%02x-%02x: unknown packet id/su-id\n",
  1096. id, sub_id);
  1097. break;
  1098. }
  1099. if (bad_len) {
  1100. GPSD_LOG(LOG_WARN, &session->context->errout,
  1101. "TSIPv1 0x%02x-%02x: runt, got length %u\n",
  1102. id, sub_id, length);
  1103. mask = 0;
  1104. }
  1105. return mask;
  1106. }
  1107. /* This is the meat of parsing all the TSIP packets, except v1
  1108. *
  1109. * Return: mask
  1110. */
  1111. static gps_mask_t tsip_parse_input(struct gps_device_t *session)
  1112. {
  1113. int i, j, len, count;
  1114. gps_mask_t mask = 0;
  1115. unsigned int id;
  1116. unsigned short week;
  1117. uint8_t u1, u2, u3, u4, u5, u6, u7, u8, u9, u10;
  1118. int16_t s1, s2, s3, s4;
  1119. int32_t sl1, sl2, sl3;
  1120. uint32_t ul1, ul2;
  1121. float f1, f2, f3, f4;
  1122. double d1, d2, d3, d4, d5;
  1123. time_t now;
  1124. char buf[BUFSIZ];
  1125. char buf2[BUFSIZ];
  1126. uint32_t tow; // time of week in milli seconds
  1127. double ftow; // time of week in seconds
  1128. double temp; // temperature in degrees C
  1129. double fqErr; // PPS Offset. positive is slow.
  1130. timespec_t ts_tow;
  1131. char ts_buf[TIMESPEC_LEN];
  1132. int bad_len = 0;
  1133. if (TSIP_PACKET != session->lexer.type) {
  1134. // this should not happen
  1135. GPSD_LOG(LOG_INF, &session->context->errout,
  1136. "TSIP: tsip_analyze packet type %d\n",
  1137. session->lexer.type);
  1138. return 0;
  1139. }
  1140. if (4 > session->lexer.outbuflen ||
  1141. 0x10 != session->lexer.outbuffer[0]) {
  1142. // packet too short, or does not start with DLE
  1143. GPSD_LOG(LOG_INF, &session->context->errout,
  1144. "TSIP: tsip_analyze packet bad packet\n");
  1145. return 0;
  1146. }
  1147. // get receive time, first
  1148. (void)time(&now);
  1149. // put data part of message in buf
  1150. memset(buf, 0, sizeof(buf));
  1151. len = 0;
  1152. for (i = 2; i < (int)session->lexer.outbuflen; i++) {
  1153. if (0x10 == session->lexer.outbuffer[i] &&
  1154. 0x03 == session->lexer.outbuffer[++i]) {
  1155. // DLE, STX. end of packet, we know the length
  1156. break;
  1157. }
  1158. buf[len++] = session->lexer.outbuffer[i];
  1159. }
  1160. id = (unsigned)session->lexer.outbuffer[1];
  1161. #ifdef __UNUSED__ // debug code
  1162. GPSD_LOG(LOG_SHOUT, &session->context->errout,
  1163. "TSIP x%02x: length %d: %s\n",
  1164. id, len, gpsd_hexdump(buf2, sizeof(buf2),
  1165. (char *)session->lexer.outbuffer, session->lexer.outbuflen));
  1166. #endif // __UNUSED__
  1167. GPSD_LOG(LOG_DATA, &session->context->errout,
  1168. "TSIP x%02x: length %d: %s\n",
  1169. id, len, gpsd_hexdump(buf2, sizeof(buf2), buf, len));
  1170. // session->cycle_end_reliable = true;
  1171. switch (id) {
  1172. case 0x13:
  1173. /* Packet Received
  1174. * Present in:
  1175. * pre-2000 models
  1176. * ICM SMT 360 (2018)
  1177. * RES SMT 360 (2018)
  1178. * Not present in:
  1179. * Copernicus II
  1180. */
  1181. if (1 > len) {
  1182. bad_len = 1;
  1183. break;
  1184. }
  1185. u1 = getub(buf, 0); // Packet ID of non-parsable packet
  1186. if (2 <= len) {
  1187. u2 = getub(buf, 1); // Data byte 0 of non-parsable packet
  1188. } else {
  1189. u2 = 0;
  1190. }
  1191. GPSD_LOG(LOG_WARN, &session->context->errout,
  1192. "TSIP x13: Report Packet type x%02x %02x "
  1193. "cannot be parsed\n",
  1194. u1, u2);
  1195. // ignore the rest of the bad data
  1196. if ((int)u1 == 0x8e && (int)u2 == 0x23) {
  1197. /* no Compact Super Packet 0x8e-23 */
  1198. GPSD_LOG(LOG_WARN, &session->context->errout,
  1199. "TSIP x8e-23: no available, use LFwEI (0x8f-20)\n");
  1200. /* Request LFwEI Super Packet instead
  1201. * SMT 360 does not support 0x8e-20 either */
  1202. (void)tsip_write1(session, "\x8e\x20\x01", 3);
  1203. }
  1204. break;
  1205. case 0x1c: // Hardware/Software Version Information
  1206. /* Present in:
  1207. * Acutime Gold
  1208. * Lassen iQ (2005) fw 1.16+
  1209. * Copernicus (2006)
  1210. * Copernicus II (2009)
  1211. * Thunderbolt E (2012)
  1212. * RES SMT 360 (2018)
  1213. * ICM SMT 360 (2018)
  1214. * RES360 17x22 (2018)
  1215. * Acutime 360
  1216. * Not Present in:
  1217. * pre-2000 models
  1218. * ACE II (1999)
  1219. * ACE III (2000)
  1220. * Lassen SQ (2002)
  1221. * Lassen iQ (2005) pre fw 1.16
  1222. */
  1223. u1 = (uint8_t)getub(buf, 0);
  1224. // decode by sub-code
  1225. switch (u1) {
  1226. case 0x81:
  1227. /* Firmware component version information (0x1c-81)
  1228. * polled by 0x1c-01
  1229. * Present in:
  1230. * Copernicus II (2009)
  1231. */
  1232. // byte 1, reserved
  1233. u2 = getub(buf, 2); // Major version
  1234. u3 = getub(buf, 3); // Minor version
  1235. u4 = getub(buf, 4); // Build number
  1236. u5 = getub(buf, 5); // Build Month
  1237. u6 = getub(buf, 6); // Build Day
  1238. ul1 = getbeu16(buf, 7); // Build Year
  1239. u7 = getub(buf, 9); // Length of product name
  1240. // check for valid module name length
  1241. if (40 < u7) {
  1242. u7 = 40;
  1243. }
  1244. // check for valid module name length, again
  1245. if (u7 > (len - 10)) {
  1246. u7 = len - 10;
  1247. }
  1248. // Product name in ASCII
  1249. memcpy(buf2, &buf[10], u7);
  1250. buf2[u7] = '\0';
  1251. (void)snprintf(session->subtype, sizeof(session->subtype),
  1252. "fw %u.%u %u %02u/%02u/%04u %.40s",
  1253. u2, u3, u4, u6, u5, ul1, buf2);
  1254. GPSD_LOG(LOG_PROG, &session->context->errout,
  1255. "TSIP x1c-81: Firmware version: %s\n",
  1256. session->subtype);
  1257. mask |= DEVICEID_SET;
  1258. if ('\0' == session->subtype1[0]) {
  1259. // request actual subtype1 from 0x1c-83
  1260. (void)tsip_write1(session, "\x1c\x03", 2);
  1261. }
  1262. break;
  1263. case 0x83:
  1264. /* Hardware component version information (0x1c-83)
  1265. * polled by 0x1c-03
  1266. * Not Present in:
  1267. * LassenSQ (2002)
  1268. * Copernicus II (2009)
  1269. */
  1270. ul1 = getbeu32(buf, 1); // Serial number
  1271. u2 = getub(buf, 5); // Build day
  1272. u3 = getub(buf, 6); // Build month
  1273. ul2 = getbeu16(buf, 7); // Build year
  1274. u4 = getub(buf, 9); // Build hour
  1275. /* Hardware Code */
  1276. session->driver.tsip.hardware_code = getbeu16(buf, 10);
  1277. u5 = getub(buf, 12); /* Length of Hardware ID */
  1278. // check for valid module name length
  1279. // copernicus ii is 27 long
  1280. if (40 < u5) {
  1281. u5 = 40;
  1282. }
  1283. // check for valid module name length, again
  1284. if (u5 > (len - 13)) {
  1285. u5 = len - 13;
  1286. }
  1287. memcpy(buf2, &buf[13], u5);
  1288. buf2[u5] = '\0';
  1289. (void)snprintf(session->subtype1, sizeof(session->subtype1),
  1290. "hw %u %02u/%02u/%04u %02u %04u %.40s",
  1291. ul1, u2, u3, ul2, u4,
  1292. session->driver.tsip.hardware_code,
  1293. buf2);
  1294. GPSD_LOG(LOG_PROG, &session->context->errout,
  1295. "TSIP x1c-83: Hardware version: %s\n",
  1296. session->subtype1);
  1297. mask |= DEVICEID_SET;
  1298. /* Detecting device by Hardware Code */
  1299. switch (session->driver.tsip.hardware_code) {
  1300. case 3001: // Acutime Gold
  1301. session->driver.tsip.subtype = TSIP_ACUTIME_GOLD;
  1302. configuration_packets_acutime_gold(session);
  1303. break;
  1304. case 3023: // RES SMT 360
  1305. session->driver.tsip.subtype = TSIP_RESSMT360;
  1306. configuration_packets_res360(session);
  1307. break;
  1308. case 3026: // ICM SMT 360
  1309. session->driver.tsip.subtype = TSIP_ICMSMT360;
  1310. configuration_packets_res360(session);
  1311. break;
  1312. case 3031: // RES360 17x22
  1313. session->driver.tsip.subtype = TSIP_RES36017x22;
  1314. configuration_packets_res360(session);
  1315. break;
  1316. case 1001: // Lassen iQ
  1317. FALLTHROUGH
  1318. case 1002: // Copernicus, Copernicus II
  1319. FALLTHROUGH
  1320. case 3007: // Thunderbolt E
  1321. FALLTHROUGH
  1322. case 3032: // Acutime 360
  1323. FALLTHROUGH
  1324. default:
  1325. configuration_packets_generic(session);
  1326. break;
  1327. }
  1328. break;
  1329. default:
  1330. GPSD_LOG(LOG_ERROR, &session->context->errout,
  1331. "TSIP x1c-%02x: Unhandled subpacket\n", u1);
  1332. break;
  1333. }
  1334. break;
  1335. case 0x41:
  1336. /* GPS Time (0x41). polled by 0x21
  1337. * Note: this is not the time of current fix
  1338. * Present in:
  1339. * pre-2000 models
  1340. * Copernicus II (2009)
  1341. * ICM SMT 360 (2018)
  1342. * RES SMT 360 (2018)
  1343. */
  1344. if (len != 10) {
  1345. bad_len = 10;
  1346. break;
  1347. }
  1348. session->driver.tsip.last_41 = now; // keep timestamp for request
  1349. ftow = getbef32(buf, 0); // gpstime
  1350. week = getbeu16(buf, 4); // week
  1351. f2 = getbef32(buf, 6); // leap seconds
  1352. if (0.0 <= ftow &&
  1353. 10.0 < f2) {
  1354. session->context->leap_seconds = (int)round(f2);
  1355. session->context->valid |= LEAP_SECOND_VALID;
  1356. DTOTS(&ts_tow, ftow);
  1357. session->newdata.time =
  1358. gpsd_gpstime_resolv(session, week, ts_tow);
  1359. mask |= TIME_SET | NTPTIME_IS;
  1360. /* Note: this is not the time of current fix
  1361. * Do not use in tsip.last_tow */
  1362. }
  1363. GPSD_LOG(LOG_PROG, &session->context->errout,
  1364. "TSIP x41: GPS Time: tow %.2f week %u ls %.1f %s\n",
  1365. ftow, week, f2,
  1366. timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)));
  1367. break;
  1368. case 0x42:
  1369. /* Single-Precision Position Fix, XYZ ECEF
  1370. * Present in:
  1371. * pre-2000 models
  1372. * Copernicus II (2009)
  1373. * ICM SMT 360 (2018)
  1374. * RES SMT 360 (2018)
  1375. */
  1376. if (16 > len) {
  1377. bad_len = 16;
  1378. break;
  1379. }
  1380. session->newdata.ecef.x = getbef32(buf, 0); // X
  1381. session->newdata.ecef.y = getbef32(buf, 4); // Y
  1382. session->newdata.ecef.z = getbef32(buf, 8); // Z
  1383. ftow = getbef32(buf, 12); // time-of-fix
  1384. DTOTS(&ts_tow, ftow);
  1385. session->newdata.time = gpsd_gpstime_resolv(session,
  1386. session->context->gps_week,
  1387. ts_tow);
  1388. GPSD_LOG(LOG_PROG, &session->context->errout,
  1389. "TSIP x42: SP-XYZ: %f %f %f ftow %f\n",
  1390. session->newdata.ecef.x,
  1391. session->newdata.ecef.y,
  1392. session->newdata.ecef.z,
  1393. ftow);
  1394. mask = ECEF_SET | TIME_SET | NTPTIME_IS;
  1395. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  1396. mask |= CLEAR_IS;
  1397. session->driver.tsip.last_tow = ts_tow;
  1398. }
  1399. break;
  1400. case 0x43:
  1401. /* Velocity Fix, XYZ ECEF
  1402. * Present in:
  1403. * pre-2000 models
  1404. * ICM SMT 360 (2018)
  1405. * RES SMT 360 (2018)
  1406. * Not Present in:
  1407. * Copernicus II (2009)
  1408. */
  1409. if (len != 20) {
  1410. bad_len = 20;
  1411. break;
  1412. }
  1413. session->newdata.ecef.vx = getbef32(buf, 0); // X velocity
  1414. session->newdata.ecef.vy = getbef32(buf, 4); // Y velocity
  1415. session->newdata.ecef.vz = getbef32(buf, 8); // Z velocity
  1416. f4 = getbef32(buf, 12); // bias rate
  1417. ftow = getbef32(buf, 16); // time-of-fix
  1418. DTOTS(&ts_tow, ftow);
  1419. session->newdata.time = gpsd_gpstime_resolv(session,
  1420. session->context->gps_week,
  1421. ts_tow);
  1422. GPSD_LOG(LOG_PROG, &session->context->errout,
  1423. "TSIP x43: Vel XYZ: %f %f %f %f ftow %f\n",
  1424. session->newdata.ecef.vx,
  1425. session->newdata.ecef.vy,
  1426. session->newdata.ecef.vz,
  1427. f4, ftow);
  1428. mask = VECEF_SET | TIME_SET | NTPTIME_IS;
  1429. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  1430. mask |= CLEAR_IS;
  1431. session->driver.tsip.last_tow = ts_tow;
  1432. }
  1433. break;
  1434. case 0x45:
  1435. /* Software Version Information (0x45)
  1436. * Present in:
  1437. * pre-2000 models
  1438. * ACE II (1999)
  1439. * ACE III (2000)
  1440. * Lassen SQ (2002)
  1441. * Lassen iQ (2005)
  1442. * Copernicus II (2009)
  1443. * ICM SMT 360
  1444. * RES SMT 360
  1445. * Probably all TSIP
  1446. */
  1447. if (10 > len) {
  1448. bad_len = 10;
  1449. break;
  1450. }
  1451. // convert 2 digit years to 4 digit years
  1452. ul1 = getub(buf, 3);
  1453. if (80 > ul1) {
  1454. ul1 += 2000;
  1455. } else {
  1456. ul1 += 1900;
  1457. }
  1458. ul2 = getub(buf, 8);
  1459. if (80 > ul2) {
  1460. ul2 += 2000;
  1461. } else {
  1462. ul2 += 1900;
  1463. }
  1464. /* ACE calls these "NAV processor firmware" and
  1465. * "SIG processor firmware".
  1466. * RES SMT 360 calls these "application" and "GPS core".
  1467. */
  1468. (void)snprintf(session->subtype, sizeof(session->subtype),
  1469. "sw %u.%u %02u/%02u/%04u hw %u.%u %02u/%02u/%04u",
  1470. getub(buf, 0),
  1471. getub(buf, 1),
  1472. getub(buf, 4),
  1473. getub(buf, 2),
  1474. ul1,
  1475. getub(buf, 5),
  1476. getub(buf, 6),
  1477. getub(buf, 9),
  1478. getub(buf, 7),
  1479. ul2);
  1480. GPSD_LOG(LOG_PROG, &session->context->errout,
  1481. "TSIP x45: Software version: %s\n", session->subtype);
  1482. mask |= DEVICEID_SET;
  1483. break;
  1484. case 0x46:
  1485. /* Health of Receiver (0x46). Poll with 0x26
  1486. * Present in:
  1487. * pre-2000 models
  1488. * Copernicus II (2009)
  1489. * ICM SMT 360 (2018)
  1490. * RES SMT 360 (2018)
  1491. * all models?
  1492. * RES SMT 360 says use 0x8f-ab or 0x8f-ac instead
  1493. */
  1494. if ( 2 > len) {
  1495. bad_len = 2;
  1496. break;
  1497. }
  1498. session->driver.tsip.last_46 = now;
  1499. u1 = getub(buf, 0); /* Status code */
  1500. /* Error codes, model dependent
  1501. * 0x01 -- no battery, always set on RES SMT 360
  1502. * 0x10 -- antenna fault
  1503. * 0x20 -- antenna is shorted
  1504. */
  1505. u2 = getub(buf, 1);
  1506. if ((uint8_t)0 != u1) {
  1507. session->newdata.status = STATUS_UNK;
  1508. mask |= STATUS_SET;
  1509. } else if (STATUS_GPS > session->newdata.status) {
  1510. session->newdata.status = STATUS_GPS;
  1511. mask |= STATUS_SET;
  1512. }
  1513. GPSD_LOG(LOG_PROG, &session->context->errout,
  1514. "TSIP x46: Receiver Health: %x %x\n", u1, u2);
  1515. break;
  1516. case 0x47:
  1517. /* Signal Levels for all Satellites
  1518. * Present in:
  1519. * pre-2000 models
  1520. * Copernicus II (2009)
  1521. * ICM SMT 360 (2018)
  1522. * RES SMT 360 (2018)
  1523. */
  1524. if (1 > len) {
  1525. bad_len = 1;
  1526. break;
  1527. }
  1528. gpsd_zero_satellites(&session->gpsdata);
  1529. /* satellite count, RES SMT 360 doc says 12 max */
  1530. count = (int)getub(buf, 0);
  1531. if (len != (5 * count + 1)) {
  1532. bad_len = 5 * count + 1;
  1533. break;
  1534. }
  1535. buf2[0] = '\0';
  1536. for (i = 0; i < count; i++) {
  1537. u1 = getub(buf, 5 * i + 1);
  1538. if ((f1 = getbef32((char *)buf, 5 * i + 2)) < 0)
  1539. f1 = 0.0;
  1540. for (j = 0; j < TSIP_CHANNELS; j++)
  1541. if (session->gpsdata.skyview[j].PRN == (short)u1) {
  1542. session->gpsdata.skyview[j].ss = f1;
  1543. break;
  1544. }
  1545. str_appendf(buf2, sizeof(buf2), " %d=%.1f", (int)u1, f1);
  1546. }
  1547. GPSD_LOG(LOG_PROG, &session->context->errout,
  1548. "TSIP x47: Signal Levels: (%d):%s\n", count, buf2);
  1549. mask |= SATELLITE_SET;
  1550. break;
  1551. case 0x48:
  1552. /* GPS System Message
  1553. * Present in:
  1554. * pre-2000 models
  1555. * Not Present in:
  1556. * Copernicus II (2009)
  1557. * ICM SMT 360 (2018)
  1558. * RES SMT 360 (2018)
  1559. */
  1560. buf[len] = '\0';
  1561. GPSD_LOG(LOG_PROG, &session->context->errout,
  1562. "TSIP x48: GPS System Message: %s\n", buf);
  1563. break;
  1564. case 0x4a:
  1565. /* Single-Precision Position LLA
  1566. * Only sent when valid
  1567. * Present in:
  1568. * pre-2000 models
  1569. * Copernicus II (2009)
  1570. * ICM SMT 360 (2018)
  1571. * RES SMT 360 (2018)
  1572. */
  1573. if (len != 20) {
  1574. bad_len = 20;
  1575. break;
  1576. }
  1577. session->newdata.latitude = getbef32((char *)buf, 0) * RAD_2_DEG;
  1578. session->newdata.longitude = getbef32((char *)buf, 4) * RAD_2_DEG;
  1579. /* depending on GPS config, could be either WGS84 or MSL */
  1580. d1 = getbef32((char *)buf, 8);
  1581. if (0 == session->driver.tsip.alt_is_msl) {
  1582. session->newdata.altHAE = d1;
  1583. } else {
  1584. session->newdata.altMSL = d1;
  1585. }
  1586. //f1 = getbef32((char *)buf, 12); // clock bias
  1587. ftow = getbef32((char *)buf, 16); // time-of-fix
  1588. if (0 != (session->context->valid & GPS_TIME_VALID)) {
  1589. DTOTS(&ts_tow, ftow);
  1590. session->newdata.time =
  1591. gpsd_gpstime_resolv(session, session->context->gps_week,
  1592. ts_tow);
  1593. mask |= TIME_SET | NTPTIME_IS;
  1594. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  1595. mask |= CLEAR_IS;
  1596. session->driver.tsip.last_tow = ts_tow;
  1597. }
  1598. }
  1599. // this seems to be often first in cycle
  1600. // REPORT_IS here breaks reports in read-only mode
  1601. mask |= LATLON_SET | ALTITUDE_SET;
  1602. GPSD_LOG(LOG_PROG, &session->context->errout,
  1603. "TSIP x4a: SP-LLA: time=%s lat=%.2f lon=%.2f "
  1604. "alt=%.2f\n",
  1605. timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)),
  1606. session->newdata.latitude,
  1607. session->newdata.longitude, d1);
  1608. break;
  1609. case 0x4b:
  1610. /* Machine/Code ID and Additional Status (0x4b)
  1611. * polled by i0x25 or 0x26. Sent with 0x46.
  1612. * Present in:
  1613. * pre-2000 models
  1614. * Copernicus II (2009)
  1615. * ICM SMT 360 (2018)
  1616. * RES SMT 360 (2018)
  1617. * all receivers?
  1618. */
  1619. if (len != 3) {
  1620. bad_len = 3;
  1621. break;
  1622. }
  1623. session->driver.tsip.machine_id = getub(buf, 0); /* Machine ID */
  1624. /* Status 1
  1625. * bit 1 -- No RTC at power up
  1626. * bit 3 -- almanac not complete and current */
  1627. u2 = getub(buf, 1);
  1628. u3 = getub(buf, 2); /* Status 2/Superpacket Support */
  1629. GPSD_LOG(LOG_PROG, &session->context->errout,
  1630. "TSIP x4b: Machine ID: %02x %02x %02x\n",
  1631. session->driver.tsip.machine_id,
  1632. u2, u3);
  1633. if ('\0' == session->subtype[0]) {
  1634. const char *name;
  1635. // better than nothing
  1636. switch (session->driver.tsip.machine_id) {
  1637. case 1:
  1638. // should use better name from superpacket
  1639. name = " SMT 360";
  1640. /* request actual subtype from 0x1c-81
  1641. * which in turn requests 0x1c-83 */
  1642. (void)tsip_write1(session, "\x1c\x01", 2);
  1643. break;
  1644. case 0x32:
  1645. name = " Acutime 360";
  1646. break;
  1647. case 0x5a:
  1648. name = " Lassen iQ";
  1649. /* request actual subtype from 0x1c-81
  1650. * which in turn requests 0x1c-83.
  1651. * Only later firmware Lassen iQ supports this */
  1652. (void)tsip_write1(session, "\x1c\x01", 2);
  1653. break;
  1654. case 0x61:
  1655. name = " Acutime 2000";
  1656. break;
  1657. case 0x62:
  1658. name = " ACE UTC";
  1659. break;
  1660. case 0x96:
  1661. // Also Copernicus II
  1662. name = " Copernicus, Thunderbolt E";
  1663. /* so request actual subtype from 0x1c-81
  1664. * which in turn requests 0x1c-83 */
  1665. (void)tsip_write1(session, "\x1c\x01", 2);
  1666. break;
  1667. default:
  1668. name = "";
  1669. }
  1670. (void)snprintf(session->subtype, sizeof(session->subtype),
  1671. "Machine ID x%x%s",
  1672. session->driver.tsip.machine_id, name);
  1673. }
  1674. if (u3 != session->driver.tsip.superpkt) {
  1675. session->driver.tsip.superpkt = u3;
  1676. GPSD_LOG(LOG_PROG, &session->context->errout,
  1677. "TSIP: Switching to Super Packet mode %d\n", u3);
  1678. switch (u3){
  1679. default:
  1680. FALLTHROUGH
  1681. case 0:
  1682. // old Trimble, no superpackets
  1683. break;
  1684. case 1:
  1685. // 1 == superpacket is acutime 360, support 0x8f-20
  1686. /* set I/O Options for Super Packet output */
  1687. /* Position: 8F20, ECEF, DP */
  1688. buf[0] = 0x35;
  1689. buf[1] = IO1_8F20|IO1_DP|IO1_ECEF;
  1690. buf[2] = 0x00; // Velocity: none (via SP)
  1691. buf[3] = 0x00; // Time: GPS
  1692. buf[4] = IO4_DBHZ; // Aux: dBHz
  1693. (void)tsip_write1(session, buf, 5);
  1694. break;
  1695. case 2:
  1696. // 2 == SMT 360, no 0x8f-20
  1697. break;
  1698. }
  1699. }
  1700. break;
  1701. case 0x4c:
  1702. /* Operating Parameters Report (0x4c). Polled by 0x2c
  1703. * Present in:
  1704. * pre-2000 models
  1705. * Lassen iQ, but not documented
  1706. * Not Present in:
  1707. * Copernicus II (2009)
  1708. * ICM SMT 360 (2018)
  1709. * RES SMT 360 (2018)
  1710. */
  1711. if (len != 17) {
  1712. bad_len = 17;
  1713. break;
  1714. }
  1715. u1 = getub(buf, 0); // Dynamics Code
  1716. f1 = getbef32((char *)buf, 1); // Elevation Mask
  1717. f2 = getbef32((char *)buf, 5); // Signal Level Mask
  1718. f3 = getbef32((char *)buf, 9); // PDOP Mask
  1719. f4 = getbef32((char *)buf, 13); // PDOP Switch
  1720. GPSD_LOG(LOG_PROG, &session->context->errout,
  1721. "TSIP x4c: Operating Params: x%02x %f %f %f %f\n",
  1722. u1, f1, f2, f3, f4);
  1723. break;
  1724. case 0x54:
  1725. /* Bias and Bias Rate Report (0x54)
  1726. * Present in:
  1727. * pre-2000 models
  1728. * Acutime 360
  1729. * ICM SMT 360 (undocumented)
  1730. * RES SMT 360 (undocumented)
  1731. * Not Present in:
  1732. * Copernicus II (2009)
  1733. */
  1734. {
  1735. float bias, bias_rate;
  1736. bias = getbef32((char *)buf, 0); // Bias
  1737. bias_rate = getbef32((char *)buf, 4); // Bias rate
  1738. ftow = getbef32((char *)buf, 8); // tow
  1739. DTOTS(&ts_tow, ftow);
  1740. session->newdata.time =
  1741. gpsd_gpstime_resolv(session, session->context->gps_week,
  1742. ts_tow);
  1743. GPSD_LOG(LOG_PROG, &session->context->errout,
  1744. "TSIP x54: Bias and Bias Rate Report: %f %f %f\n",
  1745. bias, bias_rate, ftow);
  1746. mask |= TIME_SET | NTPTIME_IS;
  1747. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  1748. mask |= CLEAR_IS;
  1749. session->driver.tsip.last_tow = ts_tow;
  1750. }
  1751. }
  1752. break;
  1753. case 0x55:
  1754. /* IO Options (0x55), polled by 0x35
  1755. * Present in:
  1756. * pre-2000 models
  1757. * ICM SMT 360 (2018)
  1758. * RES SMT 360 (2018)
  1759. * all TSIP?
  1760. *
  1761. * Lassen iQ defaults: 02 02 00 00
  1762. * RES SMT 360 defaults: 12 02 00 08
  1763. */
  1764. if (len != 4) {
  1765. bad_len = 4;
  1766. break;
  1767. }
  1768. u1 = getub(buf, 0); /* Position */
  1769. // decode HAE/MSL from Position byte
  1770. if (IO1_MSL == (IO1_MSL & u1)) {
  1771. session->driver.tsip.alt_is_msl = 1;
  1772. } else {
  1773. session->driver.tsip.alt_is_msl = 0;
  1774. }
  1775. u2 = getub(buf, 1); /* Velocity */
  1776. /* Timing
  1777. * bit 0 - reserved use 0x8e-a2 ?
  1778. */
  1779. u3 = getub(buf, 2);
  1780. /* Aux
  1781. * bit 0 - packet 0x5a (raw data)
  1782. * bit 3 -- Output dbHz
  1783. */
  1784. u4 = getub(buf, 3);
  1785. GPSD_LOG(LOG_PROG, &session->context->errout,
  1786. "TSIP x55: IO Options: %02x %02x %02x %02x\n",
  1787. u1, u2, u3, u4);
  1788. if ((u1 & 0x20) != (uint8_t) 0) {
  1789. /* Try to get Super Packets
  1790. * Turn off 0x8f-20 LFwEI Super Packet */
  1791. (void)tsip_write1(session, "\x8e\x20\x00", 3);
  1792. // Turn on Compact Super Packet 0x8f-23
  1793. (void)tsip_write1(session, "\x8e\x23\x01", 3);
  1794. session->driver.tsip.req_compact = now;
  1795. }
  1796. break;
  1797. case 0x56:
  1798. /* Velocity Fix, East-North-Up (ENU)
  1799. * Present in:
  1800. * pre-2000 models
  1801. * Copernicus II (2009)
  1802. * ICM SMT 360 (2018)
  1803. * RES SMT 360 (2018)
  1804. */
  1805. if (len != 20) {
  1806. bad_len = 20;
  1807. break;
  1808. }
  1809. f1 = getbef32((char *)buf, 0); // East velocity
  1810. f2 = getbef32((char *)buf, 4); // North velocity
  1811. f3 = getbef32((char *)buf, 8); // Up velocity
  1812. f4 = getbef32((char *)buf, 12); // clock bias rate
  1813. ftow = getbef32((char *)buf, 16); // time-of-fix
  1814. DTOTS(&ts_tow, ftow);
  1815. session->newdata.time = gpsd_gpstime_resolv(session,
  1816. session->context->gps_week,
  1817. ts_tow);
  1818. session->newdata.NED.velN = f2;
  1819. session->newdata.NED.velE = f1;
  1820. session->newdata.NED.velD = -f3;
  1821. mask |= VNED_SET | TIME_SET | NTPTIME_IS;
  1822. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  1823. mask |= CLEAR_IS;
  1824. session->driver.tsip.last_tow = ts_tow;
  1825. }
  1826. GPSD_LOG(LOG_PROG, &session->context->errout,
  1827. "TSIP x56: Vel ENU: %f %f %f %f ftow %f\n",
  1828. f1, f2, f3, f4, ftow);
  1829. break;
  1830. case 0x57:
  1831. /* Information About Last Computed Fix
  1832. * Present in:
  1833. * pre-2000 models
  1834. * Copernicus II (2009)
  1835. * ICM SMT 360 (2018)
  1836. * RES SMT 360 (2018)
  1837. */
  1838. if (8 != len) {
  1839. bad_len = 8;
  1840. break;
  1841. }
  1842. u1 = getub(buf, 0); // Source of information
  1843. u2 = getub(buf, 1); // Mfg. diagnostic
  1844. ftow = getbef32((char *)buf, 2); // gps_time
  1845. week = getbeu16(buf, 6); // tsip.gps_week
  1846. if (0x01 == getub(buf, 0)) {
  1847. // good current fix
  1848. DTOTS(&ts_tow, ftow);
  1849. (void)gpsd_gpstime_resolv(session, week, ts_tow);
  1850. mask |= TIME_SET | NTPTIME_IS;
  1851. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  1852. mask |= CLEAR_IS;
  1853. session->driver.tsip.last_tow = ts_tow;
  1854. }
  1855. }
  1856. GPSD_LOG(LOG_PROG, &session->context->errout,
  1857. "TSIP x57: Fix info: %02x %02x %u %f\n",
  1858. u1, u2, week, ftow);
  1859. break;
  1860. case 0x5a:
  1861. /* Raw Measurement Data
  1862. * Present in:
  1863. * pre-2000 models
  1864. * Copernicus II (2009)
  1865. * ICM SMT 360 (2018)
  1866. * RES SMT 360 (2018)
  1867. */
  1868. if (25 > len) {
  1869. bad_len = 25;
  1870. break;
  1871. }
  1872. // Useless without the pseudorange...
  1873. u1 = getub(buf, 0); // PRN 1-237
  1874. f1 = getbef32((char *)buf, 1); // sample length
  1875. f2 = getbef32((char *)buf, 5); // Signal Level, dbHz
  1876. f3 = getbef32((char *)buf, 9); // Code phase, 1/16th chip
  1877. f4 = getbef32((char *)buf, 13); // Doppler, Hz @ L1
  1878. d1 = getbed64((char *)buf, 17); // Time of Measurement
  1879. GPSD_LOG(LOG_PROG, &session->context->errout,
  1880. "TSIP x5a: Raw Measurement Data: %d %f %f %f %f %f\n",
  1881. u1, f1, f2, f3, f4, d1);
  1882. break;
  1883. case 0x5c:
  1884. /* Satellite Tracking Status (0x5c) polled by 0x3c
  1885. *
  1886. * GPS only, no WAAS reported here or used in fix
  1887. * Present in:
  1888. * pre-2000 models
  1889. * Copernicus, Copernicus II
  1890. * Thunderbold E
  1891. * Not Present in:
  1892. * ICM SMT 360 (2018)
  1893. * RES SMT 360 (2018)
  1894. */
  1895. if (24 != len) {
  1896. bad_len = 24;
  1897. break;
  1898. }
  1899. u1 = getub(buf, 0); // PRN 1-32
  1900. u2 = getub(buf, 1); // slot:chan
  1901. u3 = getub(buf, 2); // Acquisition flag
  1902. u4 = getub(buf, 3); // Ephemeris flag
  1903. f1 = getbef32((char *)buf, 4); // Signal level
  1904. // time of skyview, not current time, or time of fix
  1905. ftow = getbef32((char *)buf, 8);
  1906. DTOTS(&session->gpsdata.skyview_time, ftow);
  1907. d1 = getbef32((char *)buf, 12) * RAD_2_DEG; // Elevation
  1908. d2 = getbef32((char *)buf, 16) * RAD_2_DEG; // Azimuth
  1909. /* Channel number, bits 0-2 reserved/unused as of 1999.
  1910. * Seems to always start series at zero and increment to last one.
  1911. * No way to know how many there will be.
  1912. * Save current channel to check for last 0x5c message
  1913. */
  1914. i = (int)(u2 >> 3); // channel number, starting at 0
  1915. if (0 == i) {
  1916. // start of new cycle, save last count
  1917. session->gpsdata.satellites_visible =
  1918. session->driver.tsip.last_chan_seen;
  1919. }
  1920. session->driver.tsip.last_chan_seen = i;
  1921. GPSD_LOG(LOG_PROG, &session->context->errout,
  1922. "TSIP x5c: Satellite Tracking Status: Ch %2d PRN %3d "
  1923. "es %d Acq %d Eph %2d SNR %4.1f LMT %.04f El %4.1f Az %5.1f\n",
  1924. i, u1, u2 & 7, u3, u4, f1, ftow, d1, d2);
  1925. if (i < TSIP_CHANNELS) {
  1926. session->gpsdata.skyview[i].PRN = (short)u1;
  1927. session->gpsdata.skyview[i].svid = (unsigned char)u1;
  1928. session->gpsdata.skyview[i].gnssid = GNSSID_GPS;
  1929. session->gpsdata.skyview[i].ss = (double)f1;
  1930. session->gpsdata.skyview[i].elevation = (double)d1;
  1931. session->gpsdata.skyview[i].azimuth = (double)d2;
  1932. session->gpsdata.skyview[i].used = false;
  1933. session->gpsdata.skyview[i].gnssid = tsip_gnssid(0, u1,
  1934. &session->gpsdata.skyview[i].svid);
  1935. if (0.1 < f1) {
  1936. // check used list, if ss is non-zero
  1937. for (j = 0; j < session->gpsdata.satellites_used; j++) {
  1938. if (session->gpsdata.skyview[i].PRN != 0 &&
  1939. session->driver.tsip.sats_used[j] != 0) {
  1940. session->gpsdata.skyview[i].used = true;
  1941. }
  1942. }
  1943. }
  1944. /* when polled by 0x3c, all the skyview times will be the same
  1945. * in one cluster */
  1946. if (0.0 < ftow) {
  1947. DTOTS(&ts_tow, ftow);
  1948. session->gpsdata.skyview_time =
  1949. gpsd_gpstime_resolv(session, session->context->gps_week,
  1950. ts_tow);
  1951. /* do not save in session->driver.tsip.last_tow
  1952. * as this is skyview time, not fix time */
  1953. }
  1954. if (++i >= session->gpsdata.satellites_visible) {
  1955. /* Last of the series?
  1956. * This will cause extra SKY if this set has more
  1957. * sats than the last set */
  1958. mask |= SATELLITE_SET;
  1959. session->gpsdata.satellites_visible = i;
  1960. }
  1961. /* If this series has fewer than last series there will
  1962. * be no SKY, unless the cycle ender pushes the SKY */
  1963. }
  1964. break;
  1965. case 0x5d:
  1966. /* GNSS Satellite Tracking Status (multi-GNSS operation) (0x5d)
  1967. * polled by 0x3c
  1968. *
  1969. * GNSS only, no WAAS reported here or used in fix
  1970. * Present in:
  1971. * ICM SMT 360 (2018)
  1972. * RES SMT 360 (2018)
  1973. * Not Present in:
  1974. * pre-2000 models
  1975. * Copernicus, Copernicus II
  1976. * Thunderbold E
  1977. */
  1978. if (len != 26) {
  1979. bad_len = 26;
  1980. break;
  1981. }
  1982. u1 = getub(buf, 0); /* PRN */
  1983. /* Channel number, bits 0-2 reserved/unused as of 1999.
  1984. * Seems to always start series at zero and increment to last one.
  1985. * No way to know how many there will be.
  1986. * Save current channel to check for last 0x5d message
  1987. */
  1988. i = getub(buf, 1); /* chan */
  1989. if (0 == i) {
  1990. // start of new cycle, save last count
  1991. session->gpsdata.satellites_visible =
  1992. session->driver.tsip.last_chan_seen;
  1993. }
  1994. session->driver.tsip.last_chan_seen = i;
  1995. u3 = getub(buf, 2); /* Acquisition flag */
  1996. u4 = getub(buf, 3); /* SV used in Position or Time calculation*/
  1997. f1 = getbef32((char *)buf, 4); /* Signal level */
  1998. // This can be one second behind the TPV on RES SMT 360
  1999. ftow = getbef32((char *)buf, 8); /* time of Last measurement */
  2000. d1 = getbef32((char *)buf, 12) * RAD_2_DEG; /* Elevation */
  2001. d2 = getbef32((char *)buf, 16) * RAD_2_DEG; /* Azimuth */
  2002. u5 = getub(buf, 20); /* old measurement flag */
  2003. u6 = getub(buf, 21); /* integer msec flag */
  2004. u7 = getub(buf, 22); /* bad data flag */
  2005. u8 = getub(buf, 23); /* data collection flag */
  2006. u9 = getub(buf, 24); /* Used flags */
  2007. u10 = getub(buf, 25); /* SV Type */
  2008. GPSD_LOG(LOG_PROG, &session->context->errout,
  2009. "TSIP x5d: Satellite Tracking Status: Ch %2d Con %d PRN %3d "
  2010. "Acq %d Use %d SNR %4.1f LMT %.04f El %4.1f Az %5.1f Old %d "
  2011. "Int %d Bad %d Col %d TPF %d SVT %d\n",
  2012. i, u10, u1, u3, u4, f1, ftow, d1, d2, u5, u6, u7, u8, u9, u10);
  2013. if (i < TSIP_CHANNELS) {
  2014. session->gpsdata.skyview[i].PRN = (short)u1;
  2015. session->gpsdata.skyview[i].ss = (double)f1;
  2016. session->gpsdata.skyview[i].elevation = (double)d1;
  2017. session->gpsdata.skyview[i].azimuth = (double)d2;
  2018. session->gpsdata.skyview[i].used = (bool)u4;
  2019. session->gpsdata.skyview[i].gnssid = tsip_gnssid(u10, u1,
  2020. &session->gpsdata.skyview[i].svid);
  2021. if (0 == u7) {
  2022. session->gpsdata.skyview[i].health = SAT_HEALTH_OK;
  2023. } else {
  2024. session->gpsdata.skyview[i].health = SAT_HEALTH_BAD;
  2025. }
  2026. /* when polled by 0x3c, all the skyview times will be the same
  2027. * in one cluster */
  2028. if (0.0 < ftow) {
  2029. DTOTS(&ts_tow, ftow);
  2030. session->gpsdata.skyview_time =
  2031. gpsd_gpstime_resolv(session, session->context->gps_week,
  2032. ts_tow);
  2033. /* do not save in session->driver.tsip.last_tow
  2034. * as this is skyview time, not fix time */
  2035. }
  2036. if (++i >= session->gpsdata.satellites_visible) {
  2037. /* Last of the series?
  2038. * This will cause extra SKY if this set has more
  2039. * sats than the last set */
  2040. mask |= SATELLITE_SET;
  2041. session->gpsdata.satellites_visible = i;
  2042. }
  2043. /* If this series has fewer than last series there will
  2044. * be no SKY, unless the cycle ender pushes the SKY */
  2045. }
  2046. break;
  2047. case 0x6c:
  2048. /* Satellite Selection List (0x6c) polled by 0x24
  2049. *
  2050. * Present in:
  2051. * ICM SMT 360 (2018)
  2052. * RES SMT 360 (2018)
  2053. * Not present in:
  2054. * pre-2000 models
  2055. * Copernicus II (2009)
  2056. * Lassen SQ (2002)
  2057. * Lassen iQ (2005) */
  2058. if (18 > len) {
  2059. bad_len = 18;
  2060. break;
  2061. }
  2062. u1 = getub(buf, 0); // fix dimension, mode
  2063. count = (int)getub(buf, 17);
  2064. if (len != (18 + count)) {
  2065. bad_len = 18 + count;
  2066. break;
  2067. }
  2068. // why same as 6d?
  2069. session->driver.tsip.last_6d = now; /* keep timestamp for request */
  2070. /*
  2071. * This looks right, but it sets a spurious mode value when
  2072. * the satellite constellation looks good to the chip but no
  2073. * actual fix has yet been acquired. We should set the mode
  2074. * field (which controls gpsd's fix reporting) only from sentences
  2075. * that convey actual fix information, like 0x8f-20, but some
  2076. * TSIP do not support 0x8f-20, and 0x6c may be all we got.
  2077. */
  2078. switch (u1 & 7) { /* dimension */
  2079. case 1: // clock fix (surveyed in)
  2080. FALLTHROUGH
  2081. case 5: // Overdetermined clock fix
  2082. session->newdata.status = STATUS_TIME;
  2083. session->newdata.mode = MODE_3D;
  2084. break;
  2085. case 3:
  2086. session->newdata.status = STATUS_GPS;
  2087. session->newdata.mode = MODE_2D;
  2088. break;
  2089. case 4:
  2090. session->newdata.status = STATUS_GPS;
  2091. session->newdata.mode = MODE_3D;
  2092. break;
  2093. case 2:
  2094. FALLTHROUGH
  2095. case 6:
  2096. FALLTHROUGH
  2097. case 7:
  2098. FALLTHROUGH
  2099. default:
  2100. session->newdata.status = STATUS_UNK;
  2101. session->newdata.mode = MODE_NO_FIX;
  2102. break;
  2103. }
  2104. if (8 == (u1 & 8)) {
  2105. // Surveyed in
  2106. session->newdata.status = STATUS_TIME;
  2107. }
  2108. mask |= MODE_SET | STATUS_SET;
  2109. session->gpsdata.satellites_used = count;
  2110. session->gpsdata.dop.pdop = getbef32((char *)buf, 1);
  2111. session->gpsdata.dop.hdop = getbef32((char *)buf, 5);
  2112. session->gpsdata.dop.vdop = getbef32((char *)buf, 9);
  2113. // RES SMT 360 and ICM SMT 360 always report tdop == 1
  2114. session->gpsdata.dop.tdop = getbef32((char *)buf, 13);
  2115. session->gpsdata.dop.gdop =
  2116. sqrt(pow(session->gpsdata.dop.pdop, 2) +
  2117. pow(session->gpsdata.dop.tdop, 2));
  2118. mask |= DOP_SET;
  2119. memset(session->driver.tsip.sats_used, 0,
  2120. sizeof(session->driver.tsip.sats_used));
  2121. buf2[0] = '\0';
  2122. for (i = 0; i < count; i++) {
  2123. session->driver.tsip.sats_used[i] = (short)getub(buf, 18 + i);
  2124. if (session->context->errout.debug >= LOG_PROG) {
  2125. str_appendf(buf2, sizeof(buf2),
  2126. " %d", session->driver.tsip.sats_used[i]);
  2127. }
  2128. }
  2129. GPSD_LOG(LOG_PROG, &session->context->errout,
  2130. "TSIP x5c: AIVSS: mode %d status %d used %d "
  2131. "pdop %.1f hdop %.1f vdop %.1f tdop %.1f gdop %.1f Used %s\n",
  2132. session->newdata.mode,
  2133. session->newdata.status,
  2134. session->gpsdata.satellites_used,
  2135. session->gpsdata.dop.pdop,
  2136. session->gpsdata.dop.hdop,
  2137. session->gpsdata.dop.vdop,
  2138. session->gpsdata.dop.tdop,
  2139. session->gpsdata.dop.gdop,
  2140. buf2);
  2141. mask |= USED_IS;
  2142. break;
  2143. case 0x6d:
  2144. /* All-In-View Satellite Selection (0x6d) polled by 0x24
  2145. * Sent after every fix
  2146. *
  2147. * Present in:
  2148. * pre-2000 models
  2149. * Copernicus II (2009)
  2150. * Lassen SQ
  2151. * Lassen iQ
  2152. * Not present in:
  2153. * ICM SMT 360 (2018)
  2154. * RES SMT 360 (2018)
  2155. */
  2156. if (1 > len) {
  2157. bad_len = 1;
  2158. break;
  2159. }
  2160. u1 = getub(buf, 0); /* nsvs/dimension */
  2161. count = (int)((u1 >> 4) & 0x0f);
  2162. if (len != (17 + count)) {
  2163. bad_len = 17 + count;
  2164. break;
  2165. }
  2166. session->driver.tsip.last_6d = now; /* keep timestamp for request */
  2167. /*
  2168. * This looks right, but it sets a spurious mode value when
  2169. * the satellite constellation looks good to the chip but no
  2170. * actual fix has yet been acquired. We should set the mode
  2171. * field (which controls gpsd's fix reporting) only from sentences
  2172. * that convey actual fix information, like 0x8f-20, but some
  2173. * TSIP do not support 0x8f-20, and 0x6c may be all we got.
  2174. */
  2175. if (0 != isfinite(session->gpsdata.fix.longitude)) {
  2176. // have a fix
  2177. switch (u1 & 7) { /* dimension */
  2178. case 1: // clock fix (surveyed in)
  2179. FALLTHROUGH
  2180. case 5: // Overdetermined clock fix
  2181. session->newdata.status = STATUS_TIME;
  2182. session->newdata.mode = MODE_3D;
  2183. break;
  2184. case 3:
  2185. session->newdata.status = STATUS_GPS;
  2186. session->newdata.mode = MODE_2D;
  2187. break;
  2188. case 4:
  2189. session->newdata.status = STATUS_GPS;
  2190. session->newdata.mode = MODE_3D;
  2191. break;
  2192. case 2:
  2193. FALLTHROUGH
  2194. case 6:
  2195. FALLTHROUGH
  2196. case 7:
  2197. FALLTHROUGH
  2198. default:
  2199. session->newdata.status = STATUS_UNK;
  2200. session->newdata.mode = MODE_NO_FIX;
  2201. break;
  2202. }
  2203. } else {
  2204. session->newdata.status = STATUS_UNK;
  2205. session->newdata.mode = MODE_NO_FIX;
  2206. }
  2207. mask |= MODE_SET | STATUS_SET;
  2208. session->gpsdata.satellites_used = count;
  2209. session->gpsdata.dop.pdop = getbef32((char *)buf, 1);
  2210. session->gpsdata.dop.hdop = getbef32((char *)buf, 5);
  2211. session->gpsdata.dop.vdop = getbef32((char *)buf, 9);
  2212. session->gpsdata.dop.tdop = getbef32((char *)buf, 13);
  2213. session->gpsdata.dop.gdop =
  2214. sqrt(pow(session->gpsdata.dop.pdop, 2) +
  2215. pow(session->gpsdata.dop.tdop, 2));
  2216. mask |= DOP_SET;
  2217. memset(session->driver.tsip.sats_used, 0,
  2218. sizeof(session->driver.tsip.sats_used));
  2219. buf2[0] = '\0';
  2220. for (i = 0; i < count; i++) {
  2221. // negative PRN means sat unhealthy
  2222. session->driver.tsip.sats_used[i] = (short)getub(buf, 17 + i);
  2223. if (session->context->errout.debug >= LOG_PROG) {
  2224. str_appendf(buf2, sizeof(buf2),
  2225. " %d", session->driver.tsip.sats_used[i]);
  2226. }
  2227. }
  2228. GPSD_LOG(LOG_PROG, &session->context->errout,
  2229. "TSIP x6d: AIVSS: u1=x%x status=%d mode=%d used=%d "
  2230. "pdop=%.1f hdop=%.1f vdop=%.1f tdop=%.1f gdop=%.1f used:%s\n",
  2231. u1,
  2232. session->newdata.status,
  2233. session->newdata.mode,
  2234. session->gpsdata.satellites_used,
  2235. session->gpsdata.dop.pdop,
  2236. session->gpsdata.dop.hdop,
  2237. session->gpsdata.dop.vdop,
  2238. session->gpsdata.dop.tdop,
  2239. session->gpsdata.dop.gdop, buf2);
  2240. mask |= USED_IS;
  2241. break;
  2242. case 0x82:
  2243. /* Differential Position Fix Mode (0x82) poll with 0x62-ff
  2244. * Sent after every position fix in Auto GPS/DGPS,
  2245. * so potential cycle ender
  2246. *
  2247. * Present in:
  2248. * pre-2000 models
  2249. * Copernicus II (2009)
  2250. * Lassen SQ
  2251. * Lassen iQ, deprecated use 0xbb instead
  2252. * Not Present in:
  2253. * ICM SMT 360 (2018)
  2254. * RES SMT 360 (2018)
  2255. */
  2256. if (len != 1) {
  2257. bad_len = 1;
  2258. break;
  2259. }
  2260. /* differential position fix mode */
  2261. u1 = getub(buf, 0);
  2262. if (3 == (u1 & 3)) {
  2263. /* currently mode 3 (auto DGPS) and so have DGPS */
  2264. session->newdata.status = STATUS_DGPS;
  2265. mask |= STATUS_SET;
  2266. }
  2267. GPSD_LOG(LOG_PROG, &session->context->errout,
  2268. "TSIP x82: DPFM: mode %d status=%d\n",
  2269. u1, session->newdata.status);
  2270. break;
  2271. case 0x83:
  2272. /* Double-Precision XYZ Position Fix and Bias Information
  2273. * Only sent when valid
  2274. * Present in:
  2275. * pre-2000 models
  2276. * LasenSQ (2002)
  2277. * Copernicus II (2009)
  2278. * ICM SMT 360 (2018)
  2279. * RES SMT 360 (2018)
  2280. */
  2281. if (36 > len) {
  2282. bad_len = 36;
  2283. break;
  2284. }
  2285. session->newdata.ecef.x = getbed64((char *)buf, 0); /* X */
  2286. session->newdata.ecef.y = getbed64((char *)buf, 8); /* Y */
  2287. session->newdata.ecef.z = getbed64((char *)buf, 16); /* Z */
  2288. d4 = getbed64((char *)buf, 24); /* clock bias */
  2289. ftow = getbef32((char *)buf, 32); /* time-of-fix */
  2290. DTOTS(&ts_tow, ftow);
  2291. session->newdata.time = gpsd_gpstime_resolv(session,
  2292. session->context->gps_week,
  2293. ts_tow);
  2294. /* No fix mode info!! That comes later in 0x6d.
  2295. * This message only sent when there is 2D or 3D fix.
  2296. * This is a problem as gpsd will send a report with no mode.
  2297. * Steal mode from last fix.
  2298. * The last fix is likely lastfix, not oldfix, as this is likely
  2299. * a new time and starts a new cycle! */
  2300. session->newdata.status = session->lastfix.status;
  2301. if (MODE_2D > session->oldfix.mode) {
  2302. session->newdata.mode = MODE_2D; // At least 2D
  2303. } else {
  2304. session->newdata.mode = session->lastfix.mode;
  2305. }
  2306. mask |= STATUS_SET | MODE_SET;
  2307. GPSD_LOG(LOG_PROG, &session->context->errout,
  2308. "TSIP x83: DP-XYZ: %f %f %f %f tow %f mode %u\n",
  2309. session->newdata.ecef.x,
  2310. session->newdata.ecef.y,
  2311. session->newdata.ecef.z,
  2312. d4, ftow,
  2313. session->newdata.mode);
  2314. mask |= ECEF_SET | TIME_SET | NTPTIME_IS;
  2315. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  2316. // New time, so new fix.
  2317. mask |= CLEAR_IS;
  2318. session->driver.tsip.last_tow = ts_tow;
  2319. }
  2320. break;
  2321. case 0x84:
  2322. /* Double-Precision LLA Position Fix and Bias Information
  2323. * Present in:
  2324. * pre-2000 models
  2325. * Copernicus II (2009)
  2326. * LassenSQ (2002)
  2327. * ICM SMT 360 (2018)
  2328. * RES SMT 360 (2018)
  2329. */
  2330. if (len != 36) {
  2331. bad_len = 36;
  2332. break;
  2333. }
  2334. session->newdata.latitude = getbed64((char *)buf, 0) * RAD_2_DEG;
  2335. session->newdata.longitude = getbed64((char *)buf, 8) * RAD_2_DEG;
  2336. /* depending on GPS config, could be either WGS84 or MSL */
  2337. d1 = getbed64((char *)buf, 16);
  2338. if (0 == session->driver.tsip.alt_is_msl) {
  2339. session->newdata.altHAE = d1;
  2340. } else {
  2341. session->newdata.altMSL = d1;
  2342. }
  2343. mask |= ALTITUDE_SET;
  2344. //d1 = getbed64((char *)buf, 24); clock bias */
  2345. ftow = getbef32((char *)buf, 32); /* time-of-fix */
  2346. if ((session->context->valid & GPS_TIME_VALID)!=0) {
  2347. // fingers crossed receiver set to UTC, not GPS.
  2348. DTOTS(&ts_tow, ftow);
  2349. session->newdata.time =
  2350. gpsd_gpstime_resolv(session, session->context->gps_week,
  2351. ts_tow);
  2352. mask |= TIME_SET | NTPTIME_IS;
  2353. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  2354. mask |= CLEAR_IS;
  2355. session->driver.tsip.last_tow = ts_tow;
  2356. }
  2357. }
  2358. mask |= LATLON_SET;
  2359. /* No fix mode info!! That comes later in 0x6d.
  2360. * Message sent when there is 2D or 3D fix.
  2361. * This is a problem as gpsd will send a report with no mode.
  2362. * This message only sent on 2D or 3D fix.
  2363. * Steal mode from last fix. */
  2364. session->newdata.status = session->oldfix.status;
  2365. session->newdata.mode = session->oldfix.mode;
  2366. mask |= STATUS_SET | MODE_SET;
  2367. GPSD_LOG(LOG_PROG, &session->context->errout,
  2368. "TSIP x84: DP-LLA: time=%s lat=%.2f lon=%.2f alt=%.2f\n",
  2369. timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)),
  2370. session->newdata.latitude,
  2371. session->newdata.longitude, d1);
  2372. break;
  2373. case 0x8f:
  2374. /* Super Packet.
  2375. * Present in:
  2376. * pre-2000 models
  2377. * ACE II
  2378. * ACE III
  2379. * Copernicus II (2009)
  2380. * ICM SMT 360
  2381. * RES SMT 360
  2382. */
  2383. u1 = (uint8_t) getub(buf, 0);
  2384. switch (u1) { // sub-code ID
  2385. case 0x15:
  2386. /* Current Datum Values
  2387. * Not Present in:
  2388. * pre-2000 models
  2389. * Copernicus II (2009)
  2390. * ICM SMT 360 (2018)
  2391. * RES SMT 360 (2018)
  2392. */
  2393. if (len != 43) {
  2394. bad_len = 43;
  2395. break;
  2396. }
  2397. s1 = getbes16(buf, 1); // Datum Index
  2398. d1 = getbed64((char *)buf, 3); // DX
  2399. d2 = getbed64((char *)buf, 11); // DY
  2400. d3 = getbed64((char *)buf, 19); // DZ
  2401. d4 = getbed64((char *)buf, 27); // A-axis
  2402. d5 = getbed64((char *)buf, 35); // Eccentricity Squared
  2403. GPSD_LOG(LOG_PROG, &session->context->errout,
  2404. "TSIP x8f-15: Current Datum: %d %f %f %f %f %f\n",
  2405. s1, d1, d2, d3, d4, d5);
  2406. break;
  2407. case 0x20:
  2408. /* Last Fix with Extra Information (binary fixed point) 0x8f-20
  2409. * Only output when fix is available.
  2410. * CSK sez "why does my Lassen SQ output oversize packets?"
  2411. * Present in:
  2412. * pre-2000 models
  2413. * ACE II
  2414. * Copernicus, Copernicus II (64-bytes)
  2415. * Not present in:
  2416. * ICM SMT 360
  2417. * RES SMT 360
  2418. */
  2419. if ((len != 56) &&
  2420. (len != 64)) {
  2421. bad_len = 56;
  2422. break;
  2423. }
  2424. s1 = getbes16(buf, 2); // east velocity
  2425. s2 = getbes16(buf, 4); // north velocity
  2426. s3 = getbes16(buf, 6); // up velocity
  2427. tow = getbeu32(buf, 8); // time in ms
  2428. sl1 = getbes32(buf, 12); // latitude
  2429. ul2 = getbeu32(buf, 16); // longitude
  2430. // Lassen iQ, and copernicus (ii) doc says this is always altHAE
  2431. sl2 = getbes32(buf, 20); // altitude
  2432. u1 = getub(buf, 24); // velocity scaling
  2433. u2 = getub(buf, 27); // fix flags
  2434. u3 = getub(buf, 28); // num svs
  2435. u4 = getub(buf, 29); // utc offset
  2436. week = getbeu16(buf, 30); // tsip.gps_week
  2437. // PRN/IODE data follows
  2438. GPSD_LOG(LOG_PROG, &session->context->errout,
  2439. "TSIP x8f-20: LFwEI: %d %d %d tow %u %d "
  2440. " %u %u %x %x %u leap %u week %d\n",
  2441. s1, s2, s3, tow, sl1, ul2, sl2, u1, u2, u3, u4, week);
  2442. if ((u1 & 0x01) != (uint8_t) 0) { // check velocity scaling
  2443. d5 = 0.02;
  2444. } else {
  2445. d5 = 0.005;
  2446. }
  2447. // 0x8000 is over-range
  2448. if ((int16_t)0x8000 != s2) {
  2449. d2 = (double)s2 * d5; // north velocity m/s
  2450. session->newdata.NED.velN = d2;
  2451. }
  2452. if ((int16_t)0x8000 != s1) {
  2453. d1 = (double)s1 * d5; // east velocity m/s
  2454. session->newdata.NED.velE = d1;
  2455. }
  2456. if ((int16_t)0x8000 != s3) {
  2457. d3 = (double)s3 * d5; // up velocity m/s
  2458. session->newdata.NED.velD = -d3;
  2459. }
  2460. session->newdata.latitude = (double)sl1 * SEMI_2_DEG;
  2461. session->newdata.longitude = (double)ul2 * SEMI_2_DEG;
  2462. if (session->newdata.longitude > 180.0)
  2463. session->newdata.longitude -= 360.0;
  2464. // Lassen iQ doc says this is always altHAE in mm
  2465. session->newdata.altHAE = (double)sl2 * 1e-3;
  2466. mask |= ALTITUDE_SET;
  2467. session->newdata.status = STATUS_UNK;
  2468. session->newdata.mode = MODE_NO_FIX;
  2469. if ((u2 & 0x01) == (uint8_t)0) { // Fix Available
  2470. session->newdata.status = STATUS_GPS;
  2471. if ((u2 & 0x02) != (uint8_t)0) { // DGPS Corrected
  2472. session->newdata.status = STATUS_DGPS;
  2473. }
  2474. if ((u2 & 0x04) != (uint8_t)0) { // Fix Dimension
  2475. session->newdata.mode = MODE_2D;
  2476. } else {
  2477. session->newdata.mode = MODE_3D;
  2478. }
  2479. }
  2480. session->gpsdata.satellites_used = (int)u3;
  2481. if ((int)u4 > 10) {
  2482. session->context->leap_seconds = (int)u4;
  2483. session->context->valid |= LEAP_SECOND_VALID;
  2484. /* check for week rollover
  2485. * Trimble uses 15 bit weeks, but can guess the epoch wrong
  2486. * Can not be in gpsd_gpstime_resolv() because that
  2487. * may see BUILD_LEAPSECONDS instead of leap_seconds
  2488. * from receiver.
  2489. */
  2490. if (17 < u4 &&
  2491. 1930 > week) {
  2492. // leap second 18 added in gps week 1930
  2493. week += 1024;
  2494. if (1930 > week) {
  2495. // and again?
  2496. week += 1024;
  2497. }
  2498. }
  2499. }
  2500. MSTOTS(&ts_tow, tow);
  2501. session->newdata.time = gpsd_gpstime_resolv(session, week,
  2502. ts_tow);
  2503. mask |= TIME_SET | NTPTIME_IS | LATLON_SET |
  2504. STATUS_SET | MODE_SET | VNED_SET;
  2505. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  2506. mask |= CLEAR_IS;
  2507. session->driver.tsip.last_tow = ts_tow;
  2508. }
  2509. GPSD_LOG(LOG_PROG, &session->context->errout,
  2510. "TSIP x8f-20: LFwEI: time=%s lat=%.2f lon=%.2f "
  2511. "altHAE=%.2f mode=%d status=%d\n",
  2512. timespec_str(&session->newdata.time, ts_buf,
  2513. sizeof(ts_buf)),
  2514. session->newdata.latitude, session->newdata.longitude,
  2515. session->newdata.altHAE,
  2516. session->newdata.mode, session->newdata.status);
  2517. break;
  2518. case 0x23:
  2519. /* Compact Super Packet (0x8f-23)
  2520. * Present in:
  2521. * Copernicus, Copernicus II
  2522. * Not present in:
  2523. * pre-2000 models
  2524. * Lassen iQ
  2525. * ICM SMT 360
  2526. * RES SMT 360
  2527. */
  2528. session->driver.tsip.req_compact = 0;
  2529. // CSK sez "i don't trust this to not be oversized either."
  2530. if (29 > len) {
  2531. bad_len = 29;
  2532. break;
  2533. }
  2534. tow = getbeu32(buf, 1); // time in ms
  2535. week = getbeu16(buf, 5); // tsip.gps_week
  2536. u1 = getub(buf, 7); // utc offset
  2537. u2 = getub(buf, 8); // fix flags
  2538. sl1 = getbes32(buf, 9); // latitude
  2539. ul2 = getbeu32(buf, 13); // longitude
  2540. // Copernicus (ii) doc says this is always altHAE in mm
  2541. sl3 = getbes32(buf, 17); // altitude
  2542. // set xNED here
  2543. s2 = getbes16(buf, 21); // east velocity
  2544. s3 = getbes16(buf, 23); // north velocity
  2545. s4 = getbes16(buf, 25); // up velocity
  2546. GPSD_LOG(LOG_PROG, &session->context->errout,
  2547. "TSIP x8f-23: CSP: %u %d %u %u %d %u %d %d %d %d\n",
  2548. tow, week, u1, u2, sl1, ul2, sl3, s2, s3, s4);
  2549. if ((int)u1 > 10) {
  2550. session->context->leap_seconds = (int)u1;
  2551. session->context->valid |= LEAP_SECOND_VALID;
  2552. }
  2553. MSTOTS(&ts_tow, tow);
  2554. session->newdata.time =
  2555. gpsd_gpstime_resolv(session, week, ts_tow);
  2556. session->newdata.status = STATUS_UNK;
  2557. session->newdata.mode = MODE_NO_FIX;
  2558. if ((u2 & 0x01) == (uint8_t)0) { // Fix Available
  2559. session->newdata.status = STATUS_GPS;
  2560. if ((u2 & 0x02) != (uint8_t)0) { // DGPS Corrected
  2561. session->newdata.status = STATUS_DGPS;
  2562. }
  2563. if ((u2 & 0x04) != (uint8_t)0) { // Fix Dimension
  2564. session->newdata.mode = MODE_2D;
  2565. } else {
  2566. session->newdata.mode = MODE_3D;
  2567. }
  2568. }
  2569. session->newdata.latitude = (double)sl1 * SEMI_2_DEG;
  2570. session->newdata.longitude = (double)ul2 * SEMI_2_DEG;
  2571. if (session->newdata.longitude > 180.0)
  2572. session->newdata.longitude -= 360.0;
  2573. // Copernicus (ii) doc says this is always altHAE in mm
  2574. session->newdata.altHAE = (double)sl3 * 1e-3;
  2575. mask |= ALTITUDE_SET;
  2576. if ((u2 & 0x20) != (uint8_t)0) { // check velocity scaling
  2577. d5 = 0.02;
  2578. } else {
  2579. d5 = 0.005;
  2580. }
  2581. d1 = (double)s2 * d5; // east velocity m/s
  2582. d2 = (double)s3 * d5; // north velocity m/s
  2583. d3 = (double)s4 * d5; // up velocity m/s
  2584. session->newdata.NED.velN = d2;
  2585. session->newdata.NED.velE = d1;
  2586. session->newdata.NED.velD = -d3;
  2587. mask |= TIME_SET | NTPTIME_IS | LATLON_SET |
  2588. STATUS_SET | MODE_SET | VNED_SET;
  2589. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  2590. mask |= CLEAR_IS;
  2591. session->driver.tsip.last_tow = ts_tow;
  2592. }
  2593. GPSD_LOG(LOG_PROG, &session->context->errout,
  2594. "TSIP x8f-23: SP-CSP: time %s lat %.2f lon %.2f "
  2595. "altHAE %.2f mode %d status %d\n",
  2596. timespec_str(&session->newdata.time, ts_buf,
  2597. sizeof(ts_buf)),
  2598. session->newdata.latitude, session->newdata.longitude,
  2599. session->newdata.altHAE,
  2600. session->newdata.mode, session->newdata.status);
  2601. break;
  2602. case 0xa5:
  2603. /* Packet Broadcast Mask (0x8f-a5) polled by 0x8e-a5
  2604. *
  2605. * Present in:
  2606. * ICM SMT 360
  2607. * RES SMT 360
  2608. * Not Present in:
  2609. * pre-2000 models
  2610. * Copernicus II (2009)
  2611. */
  2612. {
  2613. uint16_t mask0, mask1;
  2614. if (5 > len) {
  2615. bad_len = 5;
  2616. break;
  2617. }
  2618. mask0 = getbeu16(buf, 1); // Mask 0
  2619. mask1 = getbeu16(buf, 3); // Mask 1
  2620. GPSD_LOG(LOG_PROG, &session->context->errout,
  2621. "TSIP x8f-a5: PBM: mask0 x%04x mask1 x%04x\n",
  2622. mask0, mask1);
  2623. }
  2624. // RES SMT 360 default 5, 0
  2625. break;
  2626. case 0xa6:
  2627. /* Self-Survey Command (0x8f-a6) polled by 0x8e-a6
  2628. *
  2629. * Present in:
  2630. * ICM SMT 360
  2631. * RES SMT 360
  2632. * Not Present in:
  2633. * pre-2000 models
  2634. * Copernicus II (2009)
  2635. */
  2636. if (3 > len) {
  2637. bad_len = 3;
  2638. break;
  2639. }
  2640. u2 = getub(buf, 1); // Command
  2641. u3 = getub(buf, 2); // Status
  2642. GPSD_LOG(LOG_PROG, &session->context->errout,
  2643. "TSIP x8f-a6: SSC: command x%x status x%x\n",
  2644. u2, u3);
  2645. break;
  2646. case 0xab:
  2647. /* Thunderbolt Timing Superpacket
  2648. * Not Present in:
  2649. * pre-2000 models
  2650. * Copernicus II (2009)
  2651. */
  2652. if (17 > len) {
  2653. bad_len = 17;
  2654. break;
  2655. }
  2656. session->driver.tsip.last_41 = now; // keep timestamp for request
  2657. // we assume the receiver not in some crazy mode, and is GPS time
  2658. tow = getbeu32(buf, 1); // gpstime in seconds
  2659. ts_tow.tv_sec = tow;
  2660. ts_tow.tv_nsec = 0;
  2661. week = getbeu16(buf, 5); // week
  2662. /* leap seconds */
  2663. session->context->leap_seconds = (int)getbes16(buf, 7);
  2664. u2 = buf[9]; // Time Flag
  2665. // should check time valid?
  2666. /* ignore the broken down time, use the GNSS time.
  2667. * Hope it is not BeiDou time */
  2668. // how do we know leap valid?
  2669. session->context->valid |= LEAP_SECOND_VALID;
  2670. session->newdata.time = gpsd_gpstime_resolv(session, week, ts_tow);
  2671. mask |= TIME_SET | NTPTIME_IS;
  2672. if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
  2673. mask |= CLEAR_IS;
  2674. session->driver.tsip.last_tow = ts_tow;
  2675. }
  2676. GPSD_LOG(LOG_PROG, &session->context->errout,
  2677. "TSIP x8f-ab: SP-TTS: tow %u wk %u ls %d flag x%x "
  2678. "time %s mask %s\n",
  2679. tow, week, session->context->leap_seconds, u2,
  2680. timespec_str(&session->newdata.time, ts_buf,
  2681. sizeof(ts_buf)),
  2682. gps_maskdump(mask));
  2683. break;
  2684. case 0xac:
  2685. /* Supplemental Timing Packet (0x8f-ac)
  2686. * present in:
  2687. * ThunderboltE
  2688. * ICM SMT 360
  2689. * RES SMT 360
  2690. * Not Present in:
  2691. * pre-2000 models
  2692. * Lassen iQ
  2693. * Copernicus II (2009)
  2694. */
  2695. if (len != 68) {
  2696. bad_len = 68;
  2697. break;
  2698. }
  2699. // byte 0 is Subpacket ID
  2700. u2 = getub(buf, 1); /* Receiver Mode */
  2701. u3 = getub(buf, 12); /* GNSS Decoding Status */
  2702. // ignore 2, Disciplining Mode
  2703. // ignore 3, Self-Survey Progress
  2704. // ignore 4-7, Holdover Duration
  2705. // ignore 8-9, Critical Alarms
  2706. // ignore 10-11, Minor Alarms
  2707. // ignore 12, GNSS Decoding Status
  2708. // ignore 13, Disciplining Activity
  2709. // ignore 14, PPS indication
  2710. // ignore 15, PPS reference
  2711. /* PPS Offset in ns
  2712. * save as (long)pico seconds
  2713. * can't really use it as it is not referenced to any PPS */
  2714. fqErr = getbef32((char *)buf, 16);
  2715. session->gpsdata.qErr = (long)(fqErr * 1000);
  2716. // ignore 20-23, Clock Offset
  2717. // ignore 24-27, DAC Value
  2718. // ignore 28-31, DAC Voltage
  2719. // 32-35, Temperature degrees C
  2720. temp = getbef32((char *)buf, 32);
  2721. session->newdata.latitude = getbed64((char *)buf, 36) * RAD_2_DEG;
  2722. session->newdata.longitude = getbed64((char *)buf, 44) * RAD_2_DEG;
  2723. // SMT 360 doc says this is always altHAE in meters
  2724. session->newdata.altHAE = getbed64((char *)buf, 52);
  2725. // ignore 60-63, always zero
  2726. // ignore 64-67, reserved
  2727. if (u3 != (uint8_t)0) {
  2728. // not exactly true, could be sort of Dead Reckoning
  2729. session->newdata.status = STATUS_UNK;
  2730. mask |= STATUS_SET;
  2731. } else {
  2732. if (session->newdata.status < STATUS_GPS) {
  2733. session->newdata.status = STATUS_GPS;
  2734. mask |= STATUS_SET;
  2735. }
  2736. }
  2737. /* Decode Fix modes */
  2738. switch (u2 & 7) {
  2739. case 0: /* Auto */
  2740. /*
  2741. * According to the Thunderbolt Manual, the
  2742. * first byte of the supplemental timing packet
  2743. * simply indicates the configuration of the
  2744. * device, not the actual lock, so we need to
  2745. * look at the decode status.
  2746. */
  2747. switch (u3) {
  2748. case 0: /* "Doing Fixes" */
  2749. session->newdata.mode = MODE_3D;
  2750. break;
  2751. case 0x0B: /* "Only 3 usable sats" */
  2752. session->newdata.mode = MODE_2D;
  2753. break;
  2754. case 0x1: /* "Don't have GPS time" */
  2755. FALLTHROUGH
  2756. case 0x3: /* "PDOP is too high" */
  2757. FALLTHROUGH
  2758. case 0x8: /* "No usable sats" */
  2759. FALLTHROUGH
  2760. case 0x9: /* "Only 1 usable sat" */
  2761. FALLTHROUGH
  2762. case 0x0A: /* "Only 2 usable sats */
  2763. FALLTHROUGH
  2764. case 0x0C: /* "The chosen sat is unusable" */
  2765. FALLTHROUGH
  2766. case 0x10: /* TRAIM rejected the fix */
  2767. FALLTHROUGH
  2768. default:
  2769. session->newdata.mode = MODE_NO_FIX;
  2770. break;
  2771. }
  2772. break;
  2773. case 6: /* Clock Hold 2D */
  2774. /* Not present:
  2775. * SMT 360
  2776. * Acutime 360
  2777. */
  2778. FALLTHROUGH
  2779. case 3: // forced 2D Position Fix
  2780. //session->newdata.status = STATUS_GPS;
  2781. session->newdata.mode = MODE_2D;
  2782. break;
  2783. case 1: // Single Satellite Time
  2784. /* Present in:
  2785. * Acutime 360
  2786. */
  2787. FALLTHROUGH
  2788. case 7: // overdetermined clock
  2789. /* Present in:
  2790. * Acutiome 360
  2791. */
  2792. FALLTHROUGH
  2793. case 4: // forced 3D position Fix
  2794. //session->newdata.status = STATUS_GPS;
  2795. session->newdata.mode = MODE_3D;
  2796. break;
  2797. default:
  2798. //session->newdata.status = STATUS_UNK;
  2799. session->newdata.mode = MODE_NO_FIX;
  2800. break;
  2801. }
  2802. mask |= LATLON_SET | ALTITUDE_SET | MODE_SET;
  2803. GPSD_LOG(LOG_PROG, &session->context->errout,
  2804. "TSIP x8f-ac: SP-TPS: lat=%.2f lon=%.2f altHAE=%.2f "
  2805. "mode %d temp %.1f fqErr %.4f\n",
  2806. session->newdata.latitude,
  2807. session->newdata.longitude,
  2808. session->newdata.altHAE,
  2809. session->newdata.mode,
  2810. temp, fqErr);
  2811. break;
  2812. case 0x02:
  2813. /* UTC Information
  2814. * Present in:
  2815. * ICM SMT 360 (2018)
  2816. * RES SMT 360 (2018)
  2817. * Not Present in:
  2818. * pre-2000 models
  2819. * Copernicus II (2009)
  2820. */
  2821. FALLTHROUGH
  2822. case 0x21:
  2823. /* Request accuracy information
  2824. * Present in:
  2825. * Copernicus II (2009)
  2826. * Not Present in:
  2827. * pre-2000 models
  2828. */
  2829. FALLTHROUGH
  2830. case 0x2a:
  2831. /* Request Fix and Channel Tracking info, Type 1
  2832. * Present in:
  2833. * Copernicus II (2009)
  2834. * Not Present in:
  2835. * pre-2000 models
  2836. */
  2837. FALLTHROUGH
  2838. case 0x2b:
  2839. /* Request Fix and Channel Tracking info, Type 2
  2840. * Present in:
  2841. * Copernicus II (2009)
  2842. * Not Present in:
  2843. * pre-2000 models
  2844. */
  2845. FALLTHROUGH
  2846. case 0x41:
  2847. /* Stored manufacturing operating parameters
  2848. * Present in:
  2849. * ICM SMT 360 (2018)
  2850. * RES SMT 360 (2018)
  2851. * Not Present in:
  2852. * pre-2000 models
  2853. * Copernicus II (2009)
  2854. */
  2855. FALLTHROUGH
  2856. case 0x42:
  2857. /* Stored production parameters
  2858. * Present in:
  2859. * ICM SMT 360 (2018)
  2860. * RES SMT 360 (2018)
  2861. * Not Present in:
  2862. * pre-2000 models
  2863. * Copernicus II (2009)
  2864. */
  2865. FALLTHROUGH
  2866. case 0x4a:
  2867. /* PPS characteristics
  2868. * Present in:
  2869. * ICM SMT 360 (2018)
  2870. * RES SMT 360 (2018)
  2871. * Copernicus II (2009)
  2872. * Not Present in:
  2873. * pre-2000 models
  2874. */
  2875. FALLTHROUGH
  2876. case 0x4e:
  2877. /* PPS Output options
  2878. * Present in:
  2879. * ICM SMT 360 (2018)
  2880. * RES SMT 360 (2018)
  2881. * Not Present in:
  2882. * pre-2000 models
  2883. * Copernicus II (2009)
  2884. */
  2885. FALLTHROUGH
  2886. case 0x4f:
  2887. /* Set PPS Width
  2888. * Present in:
  2889. * Copernicus II (2009)
  2890. * Not Present in:
  2891. * pre-2000 models
  2892. * ICM SMT 360 (2018)
  2893. * RES SMT 360 (2018)
  2894. */
  2895. FALLTHROUGH
  2896. case 0x60:
  2897. /* DR Calibration and Status Report
  2898. * Present in:
  2899. * pre-2000 models
  2900. * Not Present in:
  2901. * Copernicus II (2009)
  2902. * ICM SMT 360 (2018)
  2903. * RES SMT 360 (2018)
  2904. */
  2905. FALLTHROUGH
  2906. case 0x62:
  2907. /* GPS/DR Position/Velocity Report
  2908. * Present in:
  2909. * pre-2000 models
  2910. * Not Present in:
  2911. * Copernicus II (2009)
  2912. * ICM SMT 360 (2018)
  2913. * RES SMT 360 (2018)
  2914. */
  2915. FALLTHROUGH
  2916. case 0x64:
  2917. /* Firmware Version and Configuration Report
  2918. * Present in:
  2919. * pre-2000 models
  2920. * Not Present in:
  2921. * Copernicus II (2009)
  2922. * ICM SMT 360 (2018)
  2923. * RES SMT 360 (2018)
  2924. */
  2925. FALLTHROUGH
  2926. case 0x6b:
  2927. /* Last Gyroscope Readings Report
  2928. * Present in:
  2929. * pre-2000 models
  2930. * Not Present in:
  2931. * Copernicus II (2009)
  2932. * ICM SMT 360 (2018)
  2933. * RES SMT 360 (2018)
  2934. */
  2935. FALLTHROUGH
  2936. case 0x6d:
  2937. /* Last Odometer Readings Report
  2938. * Present in:
  2939. * pre-2000 models
  2940. * Not Present in:
  2941. * Copernicus II (2009)
  2942. * ICM SMT 360 (2018)
  2943. * RES SMT 360 (2018)
  2944. */
  2945. FALLTHROUGH
  2946. case 0x6f:
  2947. /* Firmware Version Name Report
  2948. * Present in:
  2949. * pre-2000 models
  2950. * Not Present in:
  2951. * Copernicus II (2009)
  2952. * ICM SMT 360 (2018)
  2953. * RES SMT 360 (2018)
  2954. */
  2955. FALLTHROUGH
  2956. case 0x70:
  2957. /* Beacon Channel Status Report
  2958. * Present in:
  2959. * pre-2000 models
  2960. * Not Present in:
  2961. * Copernicus II (2009)
  2962. * ICM SMT 360 (2018)
  2963. * RES SMT 360 (2018)
  2964. */
  2965. FALLTHROUGH
  2966. case 0x71:
  2967. /* DGPS Station Database Reports
  2968. * Present in:
  2969. * pre-2000 models
  2970. * Not Present in:
  2971. * Copernicus II (2009)
  2972. * ICM SMT 360 (2018)
  2973. * RES SMT 360 (2018)
  2974. */
  2975. FALLTHROUGH
  2976. case 0x73:
  2977. /* Beacon Channel Control Acknowledgment
  2978. * Present in:
  2979. * pre-2000 models
  2980. * Not Present in:
  2981. * Copernicus II (2009)
  2982. * ICM SMT 360 (2018)
  2983. * RES SMT 360 (2018)
  2984. */
  2985. FALLTHROUGH
  2986. case 0x74:
  2987. /* Clear Beacon Database Acknowledgment
  2988. * Present in:
  2989. * pre-2000 models
  2990. * Not Present in:
  2991. * Copernicus II (2009)
  2992. * ICM SMT 360 (2018)
  2993. * RES SMT 360 (2018)
  2994. */
  2995. FALLTHROUGH
  2996. case 0x75:
  2997. /* FFT Start Acknowledgment
  2998. * Present in:
  2999. * pre-2000 models
  3000. * Not Present in:
  3001. * Copernicus II (2009)
  3002. * ICM SMT 360 (2018)
  3003. * RES SMT 360 (2018)
  3004. */
  3005. FALLTHROUGH
  3006. case 0x76:
  3007. /* FFT Stop Acknowledgment
  3008. * Present in:
  3009. * pre-2000 models
  3010. * Not Present in:
  3011. * Copernicus II (2009)
  3012. * ICM SMT 360 (2018)
  3013. * RES SMT 360 (2018)
  3014. */
  3015. FALLTHROUGH
  3016. case 0x77:
  3017. /* FFT Reports
  3018. * Present in:
  3019. * pre-2000 models
  3020. * Not Present in:
  3021. * Copernicus II (2009)
  3022. * ICM SMT 360 (2018)
  3023. * RES SMT 360 (2018)
  3024. */
  3025. FALLTHROUGH
  3026. case 0x78:
  3027. /* RTCM Reports
  3028. * Present in:
  3029. * pre-2000 models
  3030. * Not Present in:
  3031. * Copernicus II (2009)
  3032. * ICM SMT 360 (2018)
  3033. * RES SMT 360 (2018)
  3034. */
  3035. FALLTHROUGH
  3036. case 0x79:
  3037. /* Beacon Station Attributes Acknowledgment
  3038. * Present in:
  3039. * pre-2000 models
  3040. * Not Present in:
  3041. * Copernicus II (2009)
  3042. * ICM SMT 360 (2018)
  3043. * RES SMT 360 (2018)
  3044. */
  3045. FALLTHROUGH
  3046. case 0x7a:
  3047. /* Beacon Station Attributes Report
  3048. * Present in:
  3049. * pre-2000 models
  3050. * Not Present in:
  3051. * Copernicus II (2009)
  3052. * ICM SMT 360 (2018)
  3053. * RES SMT 360 (2018)
  3054. */
  3055. FALLTHROUGH
  3056. case 0x7b:
  3057. /* DGPS Receiver RAM Configuration Block Report
  3058. * Present in:
  3059. * pre-2000 models
  3060. * Not Present in:
  3061. * Copernicus II (2009)
  3062. * ICM SMT 360 (2018)
  3063. * RES SMT 360 (2018)
  3064. */
  3065. FALLTHROUGH
  3066. case 0x7c:
  3067. /* DGPS Receiver Configuration Block Acknowledgment
  3068. * Present in:
  3069. * pre-2000 models
  3070. * Not Present in:
  3071. * Copernicus II (2009)
  3072. * ICM SMT 360 (2018)
  3073. * RES SMT 360 (2018)
  3074. */
  3075. FALLTHROUGH
  3076. case 0x7e:
  3077. /* Satellite Line-of-Sight (LOS) Message
  3078. * Present in:
  3079. * pre-2000 models
  3080. * Not Present in:
  3081. * Copernicus II (2009)
  3082. * ICM SMT 360 (2018)
  3083. * RES SMT 360 (2018)
  3084. */
  3085. FALLTHROUGH
  3086. case 0x7f:
  3087. /* DGPS Receiver ROM Configuration Block Report
  3088. * Present in:
  3089. * pre-2000 models
  3090. * Not Present in:
  3091. * Copernicus II (2009)
  3092. * ICM SMT 360 (2018)
  3093. * RES SMT 360 (2018)
  3094. */
  3095. FALLTHROUGH
  3096. case 0x80:
  3097. /* DGPS Service Provider System Information Report
  3098. * Present in:
  3099. * pre-2000 models
  3100. * Not Present in:
  3101. * Copernicus II (2009)
  3102. * ICM SMT 360 (2018)
  3103. * RES SMT 360 (2018)
  3104. */
  3105. FALLTHROUGH
  3106. case 0x81:
  3107. /* Decoder Station Information Report and Selection Acknowledgment
  3108. * Present in:
  3109. * pre-2000 models
  3110. * Not Present in:
  3111. * Copernicus II (2009)
  3112. * ICM SMT 360 (2018)
  3113. * RES SMT 360 (2018)
  3114. */
  3115. FALLTHROUGH
  3116. case 0x82:
  3117. /* Decoder Diagnostic Information Report
  3118. * Present in:
  3119. * pre-2000 models
  3120. * Not Present in:
  3121. * Copernicus II (2009)
  3122. * ICM SMT 360 (2018)
  3123. * RES SMT 360 (2018)
  3124. */
  3125. FALLTHROUGH
  3126. case 0x84:
  3127. /* Satellite FFT Control Acknowledgment
  3128. * Present in:
  3129. * pre-2000 models
  3130. * Not Present in:
  3131. * Copernicus II (2009)
  3132. * ICM SMT 360 (2018)
  3133. * RES SMT 360 (2018)
  3134. */
  3135. FALLTHROUGH
  3136. case 0x85:
  3137. /* DGPS Source Tracking Status Report
  3138. * Present in:
  3139. * pre-2000 models
  3140. * Not Present in:
  3141. * Copernicus II (2009)
  3142. * ICM SMT 360 (2018)
  3143. * RES SMT 360 (2018)
  3144. */
  3145. FALLTHROUGH
  3146. case 0x86:
  3147. /* Clear Satellite Database Acknowledgment
  3148. * Present in:
  3149. * pre-2000 models
  3150. * Not Present in:
  3151. * Copernicus II (2009)
  3152. * ICM SMT 360 (2018)
  3153. * RES SMT 360 (2018)
  3154. */
  3155. FALLTHROUGH
  3156. case 0x87:
  3157. /* Network Statistics Report
  3158. * Present in:
  3159. * pre-2000 models
  3160. * Not Present in:
  3161. * Copernicus II (2009)
  3162. * ICM SMT 360 (2018)
  3163. * RES SMT 360 (2018)
  3164. */
  3165. FALLTHROUGH
  3166. case 0x88:
  3167. /* Diagnostic Output Options Report
  3168. * Present in:
  3169. * pre-2000 models
  3170. * Not Present in:
  3171. * Copernicus II (2009)
  3172. * ICM SMT 360 (2018)
  3173. * RES SMT 360 (2018)
  3174. */
  3175. FALLTHROUGH
  3176. case 0x89:
  3177. /* DGPS Source Control Report /Acknowledgment
  3178. * Present in:
  3179. * pre-2000 models
  3180. * Not Present in:
  3181. * Copernicus II (2009)
  3182. * ICM SMT 360 (2018)
  3183. * RES SMT 360 (2018)
  3184. */
  3185. FALLTHROUGH
  3186. case 0x8a:
  3187. /* Service Provider Information Report and Acknowledgment
  3188. * Present in:
  3189. * pre-2000 models
  3190. * Not Present in:
  3191. * Copernicus II (2009)
  3192. * ICM SMT 360 (2018)
  3193. * RES SMT 360 (2018)
  3194. */
  3195. FALLTHROUGH
  3196. case 0x8b:
  3197. /* Service Provider Activation Information Report & Acknowledgment
  3198. * Present in:
  3199. * pre-2000 models
  3200. * Not Present in:
  3201. * Copernicus II (2009)
  3202. * ICM SMT 360 (2018)
  3203. * RES SMT 360 (2018)
  3204. */
  3205. FALLTHROUGH
  3206. case 0x8e:
  3207. /* Service Provider Data Load Report
  3208. * Present in:
  3209. * pre-2000 models
  3210. * Not Present in:
  3211. * Copernicus II (2009)
  3212. * ICM SMT 360 (2018)
  3213. * RES SMT 360 (2018)
  3214. */
  3215. FALLTHROUGH
  3216. case 0x8f:
  3217. /* Receiver Identity Report
  3218. * Present in:
  3219. * pre-2000 models
  3220. * Not Present in:
  3221. * Copernicus II (2009)
  3222. * ICM SMT 360 (2018)
  3223. * RES SMT 360 (2018)
  3224. */
  3225. FALLTHROUGH
  3226. case 0x90:
  3227. /* Guidance Status Report
  3228. * Present in:
  3229. * pre-2000 models
  3230. * Not Present in:
  3231. * Copernicus II (2009)
  3232. * ICM SMT 360 (2018)
  3233. * RES SMT 360 (2018)
  3234. */
  3235. FALLTHROUGH
  3236. case 0x91:
  3237. /* Guidance Configuration Report
  3238. * Present in:
  3239. * pre-2000 models
  3240. * Not Present in:
  3241. * Copernicus II (2009)
  3242. * ICM SMT 360 (2018)
  3243. * RES SMT 360 (2018)
  3244. */
  3245. FALLTHROUGH
  3246. case 0x92:
  3247. /* Lightbar Configuration Report
  3248. * Present in:
  3249. * pre-2000 models
  3250. * Not Present in:
  3251. * Copernicus II (2009)
  3252. * ICM SMT 360 (2018)
  3253. * RES SMT 360 (2018)
  3254. */
  3255. FALLTHROUGH
  3256. case 0x94:
  3257. /* Guidance Operation Acknowledgment
  3258. * Present in:
  3259. * pre-2000 models
  3260. * Not Present in:
  3261. * Copernicus II (2009)
  3262. * ICM SMT 360 (2018)
  3263. * RES SMT 360 (2018)
  3264. */
  3265. FALLTHROUGH
  3266. case 0x95:
  3267. /* Button Box Configuration Type Report
  3268. * Present in:
  3269. * pre-2000 models
  3270. * Not Present in:
  3271. * Copernicus II (2009)
  3272. * ICM SMT 360 (2018)
  3273. * RES SMT 360 (2018)
  3274. */
  3275. FALLTHROUGH
  3276. case 0x96:
  3277. /* Point Manipulation Report
  3278. * Present in:
  3279. * pre-2000 models
  3280. * Not Present in:
  3281. * Copernicus II (2009)
  3282. * ICM SMT 360 (2018)
  3283. * RES SMT 360 (2018)
  3284. */
  3285. FALLTHROUGH
  3286. case 0x97:
  3287. /* Utility Information Report
  3288. * Present in:
  3289. * pre-2000 models
  3290. * Not Present in:
  3291. * Copernicus II (2009)
  3292. * ICM SMT 360 (2018)
  3293. * RES SMT 360 (2018)
  3294. */
  3295. FALLTHROUGH
  3296. case 0x98:
  3297. /* Individual Button Configuration Report
  3298. * Present in:
  3299. * pre-2000 models
  3300. * Not Present in:
  3301. * Copernicus II (2009)
  3302. * ICM SMT 360 (2018)
  3303. * RES SMT 360 (2018)
  3304. */
  3305. FALLTHROUGH
  3306. case 0x9a:
  3307. /* Differential Correction Information Report
  3308. * Present in:
  3309. * pre-2000 models
  3310. * Not Present in:
  3311. * Copernicus II (2009)
  3312. * ICM SMT 360 (2018)
  3313. * RES SMT 360 (2018)
  3314. */
  3315. FALLTHROUGH
  3316. case 0xa0:
  3317. /* DAC value
  3318. * Present in:
  3319. * ICM SMT 360 (2018)
  3320. * RES SMT 360 (2018)
  3321. * Not Present in:
  3322. * pre-2000 models
  3323. * Copernicus II (2009)
  3324. */
  3325. FALLTHROUGH
  3326. case 0xa2:
  3327. /* UTC/GPS timing
  3328. * Present in:
  3329. * ICM SMT 360 (2018)
  3330. * RES SMT 360 (2018)
  3331. * Not Present in:
  3332. * pre-2000 models
  3333. * Copernicus II (2009)
  3334. */
  3335. FALLTHROUGH
  3336. case 0xa3:
  3337. /* Oscillator disciplining command
  3338. * Present in:
  3339. * ICM SMT 360 (2018)
  3340. * RES SMT 360 (2018)
  3341. * Not Present in:
  3342. * pre-2000 models
  3343. * Copernicus II (2009)
  3344. */
  3345. FALLTHROUGH
  3346. case 0xa8:
  3347. /* Oscillator disciplining parameters
  3348. * Present in:
  3349. * ICM SMT 360 (2018)
  3350. * RES SMT 360 (2018)
  3351. * Not Present in:
  3352. * pre-2000 models
  3353. * Copernicus II (2009)
  3354. */
  3355. FALLTHROUGH
  3356. case 0xa9:
  3357. /* self-survey parameters
  3358. * Present in:
  3359. * ICM SMT 360 (2018)
  3360. * RES SMT 360 (2018)
  3361. * Not Present in:
  3362. * pre-2000 models
  3363. * Copernicus II (2009)
  3364. */
  3365. FALLTHROUGH
  3366. default:
  3367. GPSD_LOG(LOG_WARN, &session->context->errout,
  3368. "TSIP x8f-%02x: Unhandled TSIP superpacket\n", u1);
  3369. }
  3370. break;
  3371. // Start of TSIP V1
  3372. case 0x90:
  3373. /* Version Information, TSIP v1
  3374. * Present in:
  3375. * RES720
  3376. */
  3377. FALLTHROUGH
  3378. case 0x91:
  3379. /* Receiver Configuration, TSIP v1
  3380. * Present in:
  3381. * RES720
  3382. */
  3383. FALLTHROUGH
  3384. case 0x92:
  3385. /* Resets, TSIP v1
  3386. * Present in:
  3387. * RES720
  3388. */
  3389. FALLTHROUGH
  3390. case 0x93:
  3391. /* Production & Manufacturing, TSIP v1
  3392. * Present in:
  3393. * RES720
  3394. */
  3395. FALLTHROUGH
  3396. case 0xa0:
  3397. /* Firmware Upload, TSIP v1
  3398. * Present in:
  3399. * RES720
  3400. */
  3401. FALLTHROUGH
  3402. case 0xa1:
  3403. /* PVT, TSIP v1
  3404. * Present in:
  3405. * RES720
  3406. */
  3407. FALLTHROUGH
  3408. case 0xa2:
  3409. /* GNSS Information, TSIP v1
  3410. * Present in:
  3411. * RES720
  3412. */
  3413. FALLTHROUGH
  3414. case 0xa3:
  3415. /* Alarms % Status, TSIP v1
  3416. * Present in:
  3417. * RES720
  3418. */
  3419. FALLTHROUGH
  3420. case 0xa4:
  3421. /* AGNSS, TSIP v1
  3422. * Present in:
  3423. * RES720
  3424. */
  3425. FALLTHROUGH
  3426. case 0xa5:
  3427. /* Miscellaneous, TSIP v1
  3428. * Present in:
  3429. * RES720
  3430. */
  3431. FALLTHROUGH
  3432. case 0xd0:
  3433. /* Debug & Logging, TSIP v1
  3434. * Present in:
  3435. * RES720
  3436. */
  3437. return tsipv1_parse(session, id, buf, len);
  3438. // end of TSIP V1
  3439. case 0xbb:
  3440. /* Navigation Configuration
  3441. * Present in:
  3442. * pre-2000 models
  3443. * Copernicus II (2009)
  3444. * ICM SMT 360 (2018)
  3445. * RES SMT 360 (2018)
  3446. */
  3447. if (len != 40 && len != 43) {
  3448. /* see packet.c for explamation */
  3449. bad_len = 40;
  3450. break;
  3451. }
  3452. u1 = getub(buf, 0); // Subcode, always zero?
  3453. u2 = getub(buf, 1); // Operating Dimension
  3454. u3 = getub(buf, 2); // DGPS Mode (not in Acutime Gold)
  3455. u4 = getub(buf, 3); // Dynamics Code
  3456. f1 = getbef32((char *)buf, 5); // Elevation Mask
  3457. f2 = getbef32((char *)buf, 9); // AMU Mask
  3458. f3 = getbef32((char *)buf, 13); // DOP Mask
  3459. f4 = getbef32((char *)buf, 17); // DOP Switch
  3460. u5 = getub(buf, 21); // DGPS Age Limit (not in Acutime Gold)
  3461. /* Constellation
  3462. * bit 0 - GPS
  3463. * bit 1 - GLONASS
  3464. * bit 2 - reserved
  3465. * bit 3 - BeiDou
  3466. * bit 4 - Galileo
  3467. * bit 5 - QZSS
  3468. * bit 6 - reserved
  3469. * bit 7 - reserved
  3470. */
  3471. u6 = getub(buf, 27);
  3472. GPSD_LOG(LOG_PROG, &session->context->errout,
  3473. "TSIP xbb: Navigation Configuration: %u %u %u %u %f %f %f "
  3474. "%f %u x%x\n",
  3475. u1, u2, u3, u4, f1, f2, f3, f4, u5, u6);
  3476. // RES SMT 360 defaults to Mode 7, Constellation 3
  3477. break;
  3478. case 0x1a:
  3479. /* TSIP RTCM Wrapper Command
  3480. * Present in:
  3481. * pre-2000 models
  3482. * Not Present in:
  3483. * ICM SMT 360 (2018)
  3484. * RES SMT 360 (2018)
  3485. * Copernicus II (2009)
  3486. */
  3487. FALLTHROUGH
  3488. case 0x2e:
  3489. /* Request GPS Time
  3490. * Present in:
  3491. * ICM SMT 360 (2018)
  3492. * RES SMT 360 (2018)
  3493. * Not Present in:
  3494. * pre-2000 models
  3495. * Copernicus II (2009)
  3496. */
  3497. FALLTHROUGH
  3498. case 0x32:
  3499. /* Request Unit Position
  3500. * Present in:
  3501. * ICM SMT 360 (2018)
  3502. * RES SMT 360 (2018)
  3503. * Not Present in:
  3504. * pre-2000 models
  3505. * Copernicus II (2009)
  3506. */
  3507. FALLTHROUGH
  3508. case 0x38:
  3509. /* Request SV System data
  3510. * Present in:
  3511. * ICM SMT 360 (2018)
  3512. * RES SMT 360 (2018)
  3513. * Not Present in:
  3514. * pre-2000 models
  3515. * Copernicus II (2009)
  3516. */
  3517. FALLTHROUGH
  3518. case 0x40:
  3519. /* Almanac Data for Single Satellite Report
  3520. * Present in:
  3521. * pre-2000 models
  3522. * Not Present in:
  3523. * ICM SMT 360 (2018)
  3524. * RES SMT 360 (2018)
  3525. * Copernicus II (2009)
  3526. */
  3527. FALLTHROUGH
  3528. case 0x44:
  3529. /* Non-Overdetermined Satellite Selection Report
  3530. * Present in:
  3531. * pre-2000 models
  3532. * Not Present in:
  3533. * ICM SMT 360 (2018)
  3534. * RES SMT 360 (2018)
  3535. * Copernicus II (2009)
  3536. */
  3537. FALLTHROUGH
  3538. case 0x49:
  3539. /* Almanac Health Page
  3540. * Present in:
  3541. * pre-2000 models
  3542. * Not Present in:
  3543. * Copernicus II (2009)
  3544. */
  3545. FALLTHROUGH
  3546. case 0x4d:
  3547. /* Oscillator Offset
  3548. * Present in:
  3549. * pre-2000 models
  3550. * Copernicus II (2009)
  3551. */
  3552. FALLTHROUGH
  3553. case 0x4e:
  3554. /* Response to set GPS time
  3555. * Present in:
  3556. * pre-2000 models
  3557. * Copernicus II (2009)
  3558. * ICM SMT 360 (2018)
  3559. * RES SMT 360 (2018)
  3560. */
  3561. FALLTHROUGH
  3562. case 0x4f:
  3563. /* UTC Parameters Report
  3564. * Present in:
  3565. * pre-2000 models
  3566. * Not Present in:
  3567. * ICM SMT 360 (2018)
  3568. * RES SMT 360 (2018)
  3569. * Copernicus II (2009)
  3570. */
  3571. FALLTHROUGH
  3572. case 0x53:
  3573. /* Analog-to-Digital Readings Report
  3574. * Present in:
  3575. * pre-2000 models
  3576. * Not Present in:
  3577. * ICM SMT 360 (2018)
  3578. * RES SMT 360 (2018)
  3579. * Copernicus II (2009)
  3580. */
  3581. FALLTHROUGH
  3582. case 0x58:
  3583. /* Satellite System Data/Acknowledge from Receiver
  3584. * Present in:
  3585. * pre-2000 models
  3586. * Copernicus II (2009)
  3587. * ICM SMT 360 (2018)
  3588. * RES SMT 360 (2018)
  3589. */
  3590. FALLTHROUGH
  3591. case 0x59:
  3592. /* Status of Satellite Disable or Ignore Health
  3593. * aka Satellite Attribute Database Status Report
  3594. * Present in:
  3595. * pre-2000 models
  3596. * ICM SMT 360 (2018)
  3597. * RES SMT 360 (2018)
  3598. * Not Present in:
  3599. * Copernicus II (2009)
  3600. */
  3601. FALLTHROUGH
  3602. case 0x5b:
  3603. /* Satellite Ephemeris Status
  3604. * Present in:
  3605. * pre-2000 models
  3606. * Not Present in:
  3607. * Copernicus II (2009)
  3608. * ICM SMT 360 (2018)
  3609. * RES SMT 360 (2018)
  3610. */
  3611. FALLTHROUGH
  3612. case 0x5e:
  3613. /* Additional Fix Status Report
  3614. * Present in:
  3615. * pre-2000 models
  3616. * Not Present in:
  3617. * Copernicus II (2009)
  3618. * ICM SMT 360 (2018)
  3619. * RES SMT 360 (2018)
  3620. */
  3621. FALLTHROUGH
  3622. case 0x5f:
  3623. /* Severe Failure Notification
  3624. * Present in:
  3625. * pre-2000 models
  3626. * Not Present in:
  3627. * ICM SMT 360 (2018)
  3628. * RES SMT 360 (2018)
  3629. * Copernicus II (2009)
  3630. */
  3631. FALLTHROUGH
  3632. case 0x60:
  3633. /* Differential GPS Pseudorange Corrections Report
  3634. * Present in:
  3635. * pre-2000 models
  3636. * Not Present in:
  3637. * ICM SMT 360 (2018)
  3638. * RES SMT 360 (2018)
  3639. * Copernicus II (2009)
  3640. */
  3641. FALLTHROUGH
  3642. case 0x61:
  3643. /* Differential GPS Delta Pseudorange Corrections Report
  3644. * Present in:
  3645. * pre-2000 models
  3646. * Not Present in:
  3647. * ICM SMT 360 (2018)
  3648. * RES SMT 360 (2018)
  3649. * Copernicus II (2009)
  3650. */
  3651. FALLTHROUGH
  3652. case 0x6a:
  3653. /* Differential Corrections Used in the Fix Repor
  3654. * Present in:
  3655. * pre-2000 models
  3656. * Not Present in:
  3657. * ICM SMT 360 (2018)
  3658. * RES SMT 360 (2018)
  3659. * Copernicus II (2009)
  3660. */
  3661. FALLTHROUGH
  3662. case 0x6e:
  3663. /* Synchronized Measurements
  3664. * Present in:
  3665. * pre-2000 models
  3666. * Not Present in:
  3667. * Copernicus II (2009)
  3668. * ICM SMT 360 (2018)
  3669. * RES SMT 360 (2018)
  3670. */
  3671. FALLTHROUGH
  3672. case 0x6f:
  3673. /* Synchronized Measurements Report
  3674. * Present in:
  3675. * pre-2000 models
  3676. * Not Present in:
  3677. * Copernicus II (2009)
  3678. * ICM SMT 360 (2018)
  3679. * RES SMT 360 (2018)
  3680. */
  3681. FALLTHROUGH
  3682. case 0x70:
  3683. /* Filter Report
  3684. * Present in:
  3685. * pre-2000 models
  3686. * Not Present in:
  3687. * Copernicus II (2009)
  3688. * ICM SMT 360 (2018)
  3689. * RES SMT 360 (2018)
  3690. */
  3691. FALLTHROUGH
  3692. case 0x76:
  3693. /* Overdetermined Mode Report
  3694. * Present in:
  3695. * pre-2000 models
  3696. * Not Present in:
  3697. * ICM SMT 360 (2018)
  3698. * RES SMT 360 (2018)
  3699. * Copernicus II (2009)
  3700. */
  3701. FALLTHROUGH
  3702. case 0x78:
  3703. /* Maximum PRC Age Report
  3704. * Present in:
  3705. * pre-2000 models
  3706. * Not Present in:
  3707. * ICM SMT 360 (2018)
  3708. * RES SMT 360 (2018)
  3709. * Copernicus II (2009)
  3710. */
  3711. FALLTHROUGH
  3712. case 0x7a:
  3713. /* NMEA settings
  3714. * Not Present in:
  3715. * pre-2000 models
  3716. * Copernicus II (2009)
  3717. * ICM SMT 360 (2018)
  3718. * RES SMT 360 (2018)
  3719. */
  3720. FALLTHROUGH
  3721. case 0x7b:
  3722. /* NMEA interval and message mask response
  3723. * Present in:
  3724. * pre-2000 models
  3725. * ICM SMT 360 (2018)
  3726. * RES SMT 360 (2018)
  3727. * Not Present in:
  3728. * Copernicus II (2009)
  3729. */
  3730. FALLTHROUGH
  3731. case 0x7d:
  3732. /* Position Fix Rate Configuration Reports
  3733. * Present in:
  3734. * pre-2000 models
  3735. * Not Present in:
  3736. * ICM SMT 360 (2018)
  3737. * RES SMT 360 (2018)
  3738. * Copernicus II (2009)
  3739. */
  3740. FALLTHROUGH
  3741. case 0x85:
  3742. /* Differential Correction Status Report
  3743. * Present in:
  3744. * pre-2000 models
  3745. * Not Present in:
  3746. * ICM SMT 360 (2018)
  3747. * RES SMT 360 (2018)
  3748. * Copernicus II (2009)
  3749. */
  3750. FALLTHROUGH
  3751. case 0x87:
  3752. /* Reference Station Parameters Report
  3753. * Present in:
  3754. * pre-2000 models
  3755. * Not Present in:
  3756. * ICM SMT 360 (2018)
  3757. * RES SMT 360 (2018)
  3758. * Copernicus II (2009)
  3759. */
  3760. FALLTHROUGH
  3761. case 0x89:
  3762. /* Receiver acquisition sensitivity mode
  3763. * Present in:
  3764. * Copernicus II (2009)
  3765. * Not Present in:
  3766. * pre-2000 models
  3767. * ICM SMT 360 (2018)
  3768. * RES SMT 360 (2018)
  3769. */
  3770. FALLTHROUGH
  3771. case 0x88:
  3772. /* Mobile Differential Parameters Report
  3773. * Present in:
  3774. * pre-2000 models
  3775. * Not Present in:
  3776. * ICM SMT 360 (2018)
  3777. * RES SMT 360 (2018)
  3778. * Copernicus II (2009)
  3779. */
  3780. FALLTHROUGH
  3781. case 0x8b:
  3782. /* QA/QC Reports
  3783. * Present in:
  3784. * pre-2000 models
  3785. * Not Present in:
  3786. * ICM SMT 360 (2018)
  3787. * RES SMT 360 (2018)
  3788. * Copernicus II (2009)
  3789. */
  3790. FALLTHROUGH
  3791. case 0x8d:
  3792. /* Average Position Reports
  3793. * Present in:
  3794. * pre-2000 models
  3795. * Not Present in:
  3796. * ICM SMT 360 (2018)
  3797. * RES SMT 360 (2018)
  3798. * Copernicus II (2009)
  3799. */
  3800. FALLTHROUGH
  3801. case 0xb0:
  3802. /* PPS and Event Report Packets
  3803. * Present in:
  3804. * pre-2000 models
  3805. * Not Present in:
  3806. * ICM SMT 360 (2018)
  3807. * RES SMT 360 (2018)
  3808. * Copernicus II (2009)
  3809. */
  3810. FALLTHROUGH
  3811. case 0xbc:
  3812. /* Receiver port configuration
  3813. * Present in:
  3814. * pre-2000 models
  3815. * Copernicus II (2009)
  3816. * Not Present in:
  3817. * ICM SMT 360 (2018)
  3818. * RES SMT 360 (2018)
  3819. */
  3820. FALLTHROUGH
  3821. case 0xc1:
  3822. /* Bit Mask for GPIOs in Standby Mode
  3823. * Present in:
  3824. * Copernicus II (2009)
  3825. * ICM SMT 360 (2018)
  3826. * RES SMT 360 (2018)
  3827. * Not Present in:
  3828. * pre-2000 models
  3829. */
  3830. FALLTHROUGH
  3831. case 0xc2:
  3832. /* SBAS SV Mask
  3833. * Present in:
  3834. * Copernicus II (2009)
  3835. * ICM SMT 360 (2018)
  3836. * RES SMT 360 (2018)
  3837. * Not Present in:
  3838. * pre-2000 models
  3839. */
  3840. FALLTHROUGH
  3841. default:
  3842. GPSD_LOG(LOG_WARN, &session->context->errout,
  3843. "TSIP x%02x: Unhandled packet type\n", id);
  3844. break;
  3845. }
  3846. #ifdef __UNUSED__
  3847. // #if 1
  3848. // full reset
  3849. (void)tsip_write1(session, "\x1e\x46", 2);
  3850. #endif
  3851. if (bad_len) {
  3852. GPSD_LOG(LOG_WARNING, &session->context->errout,
  3853. "TSIP x%02x: wrong len %d s/b >= %d \n", id, len, bad_len);
  3854. } else {
  3855. GPSD_LOG(LOG_PROG, &session->context->errout,
  3856. "TSIP x%02x: mask %s\n", id, gps_maskdump(mask));
  3857. }
  3858. /* See if it is time to send some request packets for reports that.
  3859. * The receiver won't send at fixed intervals.
  3860. * Use llabs() as time sometimes goes backwards. */
  3861. if (5 < llabs(now - session->driver.tsip.last_41)) {
  3862. /* Request Current Time returns 0x41.
  3863. * Easiest way to get GPS weeks and current leap seconds */
  3864. (void)tsip_write1(session, "\x21", 1);
  3865. session->driver.tsip.last_41 = now;
  3866. }
  3867. if (5 < llabs(now - session->driver.tsip.last_6d)) {
  3868. /* Request GPS Receiver Position Fix Mode
  3869. * Returns 0x44, 0x6c, or 0x6d. */
  3870. (void)tsip_write1(session, "\x24", 1);
  3871. session->driver.tsip.last_6d = now;
  3872. #ifdef __UNUSED__
  3873. // #if 1
  3874. // request Receiver Configuration (0xbb)
  3875. (void)tsip_write1(session, "\xbb\x00", 2);
  3876. // request Packet Broadcast Mask
  3877. (void)tsip_write1(session, "\x8e\xa5", 2);
  3878. #endif // UNUSED
  3879. }
  3880. if (1 > session->driver.tsip.superpkt &&
  3881. 60 < llabs(now - session->driver.tsip.last_48)) {
  3882. /* Request GPS System Message
  3883. * Returns 0x48.
  3884. * not supported on:
  3885. * Lassen SQ (2002)
  3886. * Lassen iQ (2005)
  3887. * ICM SMT 360
  3888. * RES SMT 360
  3889. * and post 2005
  3890. * SuperPackets replaced 0x28 */
  3891. (void)tsip_write1(session, "\x28", 1);
  3892. session->driver.tsip.last_48 = now;
  3893. }
  3894. if (5 < llabs(now - session->driver.tsip.last_5c)) {
  3895. /* Request Current Satellite Tracking Status
  3896. * Returns: 0x5c or 0x5d
  3897. * 5c from GPS only devices
  3898. * 5d from multi-gnss devices */
  3899. // 00 == All satellites
  3900. (void)tsip_write1(session, "\x3c\x00", 2);
  3901. session->driver.tsip.last_5c = now;
  3902. }
  3903. if (5 < llabs(now - session->driver.tsip.last_46)) {
  3904. /* Request Health of Receiver
  3905. * Returns 0x46 and 0x4b. */
  3906. (void)tsip_write1(session, "\x26", 1);
  3907. session->driver.tsip.last_46 = now;
  3908. }
  3909. if ((session->driver.tsip.req_compact > 0) &&
  3910. (5 < llabs(now - session->driver.tsip.req_compact))) {
  3911. /* Compact Superpacket requested but no response
  3912. * Not in:
  3913. * ICM SMT 360
  3914. * RES SMT 360
  3915. */
  3916. session->driver.tsip.req_compact = 0;
  3917. GPSD_LOG(LOG_WARN, &session->context->errout,
  3918. "TSIP x8f-23: No Compact Super Packet, "
  3919. "try LFwEI (0x8f-20)\n");
  3920. // Request LFwEI Super Packet 0x8f-20, enabled
  3921. (void)tsip_write1(session, "\x8e\x20\x01", 3);
  3922. }
  3923. return mask;
  3924. }
  3925. static void tsip_init_query(struct gps_device_t *session)
  3926. {
  3927. // Use 0x1C-03 to Request Hardware Version Information (0x1C-83)
  3928. (void)tsip_write1(session, "\x1c\x03", 2);
  3929. /*
  3930. * After HW information packet is received, a
  3931. * decision is made how to configure the device.
  3932. */
  3933. }
  3934. static void tsip_event_hook(struct gps_device_t *session, event_t event)
  3935. {
  3936. char buf[100];
  3937. GPSD_LOG(LOG_SPIN, &session->context->errout,
  3938. "TSIP: event_hook event %d ro %d\n",
  3939. event, session->context->readonly);
  3940. if (session->context->readonly ||
  3941. session->context->passive) {
  3942. return;
  3943. }
  3944. switch (event) {
  3945. case event_identified:
  3946. FALLTHROUGH
  3947. case event_reactivate:
  3948. // FIXME: reactivate style should depend on model
  3949. /*
  3950. * Set basic configuration, using Set or Request I/O Options (0x35).
  3951. * in case no hardware config response comes back.
  3952. */
  3953. // Position: enable: Double Precision, LLA, disable: ECEF
  3954. buf[0] = 0x35;
  3955. // Velocity: enable: ENU, disable vECEF */
  3956. buf[1] = IO1_8F20|IO1_DP|IO1_LLA;
  3957. // Time: enable: 0x42, 0x43, 0x4a, disable: 0x83, 0x84, 0x56
  3958. buf[2] = IO2_ENU;
  3959. buf[3] = 0x00; // Aux: enable: 0x5A, dBHz
  3960. buf[4] = IO4_DBHZ;
  3961. (void)tsip_write1(session, buf, 5);
  3962. break;
  3963. case event_configure:
  3964. // this seems to get called on every packet...
  3965. if (session->lexer.counter == 0) {
  3966. /* but the above if() makes it never execute
  3967. * formerely tried to force 801 here, but luckily it
  3968. * never fired as some Trimble are 8N1 */
  3969. }
  3970. break;
  3971. case event_deactivate:
  3972. // used to revert serial port parms here. No need for that.
  3973. FALLTHROUGH
  3974. default:
  3975. break;
  3976. }
  3977. }
  3978. static bool tsip_speed_switch(struct gps_device_t *session,
  3979. speed_t speed, char parity, int stopbits)
  3980. {
  3981. char buf[100];
  3982. switch (parity) {
  3983. case 'E':
  3984. case 2:
  3985. parity = (char)2;
  3986. break;
  3987. case 'O':
  3988. case 1:
  3989. parity = (char)1;
  3990. break;
  3991. case 'N':
  3992. case 0:
  3993. default:
  3994. parity = (char)0;
  3995. break;
  3996. }
  3997. buf[0] = 0xbc; // Set Port Configuration (0xbc)
  3998. buf[1] = 0xff; // current port
  3999. // input dev.baudrate
  4000. buf[2] = (round(log((double)speed / 300) / GPS_LN2)) + 2;
  4001. buf[3] = buf[2]; // output baudrate
  4002. buf[4] = 3; // character width (8 bits)
  4003. buf[5] = parity; // parity (normally odd)
  4004. buf[6] = stopbits - 1; // stop bits (normally 1 stopbit)
  4005. buf[7] = 0; // flow control (none)
  4006. buf[8] = 0x02; // input protocol (TSIP)
  4007. buf[9] = 0x02; // output protocol (TSIP)
  4008. buf[10] = 0; // reserved
  4009. (void)tsip_write1(session, buf, 11);
  4010. return true; // it would be nice to error-check this
  4011. }
  4012. static void tsip_mode(struct gps_device_t *session, int mode)
  4013. {
  4014. if (MODE_NMEA == mode) {
  4015. char buf[16];
  4016. /* send NMEA Interval and Message Mask Command (0x7a)
  4017. * First turn on the NMEA messages we want */
  4018. buf[0] = 0x7a;
  4019. buf[1] = 0x00; // subcode 0
  4020. buf[2] = 0x01; // 1-second fix interval
  4021. buf[3] = 0x00; // Reserved
  4022. buf[4] = 0x00; // Reserved
  4023. buf[5] = 0x01; // 1=GST, Reserved
  4024. /* 1=GGA, 2=GGL, 4=VTG, 8=GSV, */
  4025. /* 0x10=GSA, 0x20=ZDA, 0x40=Reserved, 0x80=RMC */
  4026. buf[6] = 0x19;
  4027. (void)tsip_write1(session, buf, 7);
  4028. // Now switch to NMEA mode
  4029. memset(buf, 0, sizeof(buf));
  4030. buf[0] = 0x8c; // Set Port Configuration (0xbc)
  4031. buf[1] = 0xff; // current port
  4032. buf[2] = 0x06; // 4800 bps input. 4800, really?
  4033. buf[3] = buf[2]; // output SAME AS INPUT
  4034. buf[4] = 0x03; // 8 data bits
  4035. buf[5] = 0x00; // No parity
  4036. buf[6] = 0x00; // 1 stop bit
  4037. buf[7] = 0x00; // No flow control
  4038. buf[8] = 0x02; // Input protocol TSIP
  4039. buf[9] = 0x04; // Output protocol NMEA
  4040. buf[10] = 0x00; // Reserved
  4041. (void)tsip_write1(session, buf, 11);
  4042. } else if (MODE_BINARY == mode) {
  4043. /* The speed switcher also puts us back in TSIP, so call it
  4044. * with the default 9600 8O1. */
  4045. // FIXME: Should preserve the current speed.
  4046. // (void)tsip_speed_switch(session, 9600, 'O', 1);
  4047. // FIXME: should config TSIP binary!
  4048. ;
  4049. } else {
  4050. GPSD_LOG(LOG_ERROR, &session->context->errout,
  4051. "TSIP: unknown mode %i requested\n", mode);
  4052. }
  4053. }
  4054. // configure generic Trimble TSIP device to a known state
  4055. void configuration_packets_generic(struct gps_device_t *session)
  4056. {
  4057. char buf[100];
  4058. GPSD_LOG(LOG_PROG, &session->context->errout,
  4059. "TSIP: configuration_packets_generic()\n");
  4060. // Set basic configuration, using Set or Request I/O Options (0x35).
  4061. // Position: enable: Double Precision, LLA, disable: ECEF
  4062. buf[0] = 0x35;
  4063. // Time: enable: 0x42, 0x43, 0x4a, disable: 0x83, 0x84, 0x56 */
  4064. buf[1] = IO1_8F20|IO1_DP|IO1_LLA;
  4065. // Velocity: enable: ENU, disable ECEF
  4066. buf[2] = IO2_ENU;
  4067. buf[3] = 0x00;
  4068. buf[4] = IO4_DBHZ; // Aux: enable: 0x5A, dBHz
  4069. (void)tsip_write1(session, buf, 5);
  4070. // Request Software Version (0x1f), returns 0x45
  4071. (void)tsip_write1(session, "\x1f", 1);
  4072. // Current Time Request (0x21), returns 0x41
  4073. (void)tsip_write1(session, "\x21", 1);
  4074. /* Set Operating Parameters (0x2c)
  4075. * not present in:
  4076. * Lassen SQ (2002)
  4077. * Lassen iQ (2005)
  4078. * RES SMT 360 */
  4079. /* dynamics code: enabled: 1=land
  4080. * disabled: 2=sea, 3=air, 4=static
  4081. * default is land */
  4082. buf[0] = 0x2c;
  4083. buf[1] = 0x01;
  4084. // elevation mask, 10 degrees is a common default, TSIP default is 15
  4085. putbef32(buf, 2, (float)10.0 * DEG_2_RAD);
  4086. // signal level mask, default is 2.0 AMU. 5.0 to 6.0 for high accuracy
  4087. putbef32(buf, 6, (float)06.0);
  4088. // PDOP mask default is 12. 5.0 to 6.0 for high accuracy
  4089. putbef32(buf, 10, (float)8.0);
  4090. // PDOP switch, default is 8.0
  4091. putbef32(buf, 14, (float)6.0);
  4092. (void)tsip_write1(session, buf, 18);
  4093. /* Set Position Fix Mode (0x22)
  4094. * 0=auto 2D/3D, 1=time only, 3=2D, 4=3D, 10=Overdetermined clock */
  4095. (void)tsip_write1(session, "\x22\x00", 2);
  4096. /* Request GPS System Message (0x48)
  4097. * not supported on model RES SMT 360 */
  4098. (void)tsip_write1(session, "\x28", 1);
  4099. /* Last Position and Velocity Request (0x37)
  4100. * returns 0x57 and (0x42, 0x4a, 0x83, or 0x84) and (0x43 or 0x56) */
  4101. (void)tsip_write1(session, "\x37", 1);
  4102. // 0x8e-15 request output datum
  4103. (void)tsip_write1(session, "\x8e\x15", 2);
  4104. /* Primary Receiver Configuration Parameters Request (0xbb-00)
  4105. * returns Primary Receiver Configuration Block (0xbb-00) */
  4106. (void)tsip_write1(session, "\xbb\x00", 2);
  4107. }
  4108. /* configure Acutime Gold to a known state */
  4109. void configuration_packets_acutime_gold(struct gps_device_t *session)
  4110. {
  4111. char buf[100];
  4112. GPSD_LOG(LOG_PROG, &session->context->errout,
  4113. "TSIP: configuration_packets_acutime_gold()\n");
  4114. /* Request Firmware Version (0x1c-01)
  4115. * returns Firmware component version information (0x1x-81) */
  4116. (void)tsip_write1(session, "\x1c\x01", 2);
  4117. buf[0] = 0x8e; // Set Self-Survey Parameters (0x8e-a9)
  4118. buf[1] = 0xa9; // Subcode
  4119. buf[2] = 0x01; // Self-Survey Enable = enable
  4120. buf[3] = 0x01; // Position Save Flag = save position
  4121. putbe32(buf, 4, 2000); // Self-Survey Length = 2000 fixes, default 2000
  4122. // Horizontal Uncertainty, 1-100, 1=best, 100=worst, default 100
  4123. putbef32(buf, 8, 100);
  4124. // Verical Uncertainty, 1-100, 1=best, 100=worst, default 100
  4125. putbef32(buf, 12, 100);
  4126. (void)tsip_write1(session, buf, 16);
  4127. /* Set PPS Output Option (0x8e-4e)
  4128. * 0x4e Subcode
  4129. * 2 == PPS driver switch (PPS is always output) */
  4130. (void)tsip_write1(session, "\x8e\x4e\x02", 3);
  4131. buf[0] = 0xbb; // Set Primary Receiver Configuration (0xbb-00)
  4132. buf[1] = 0x00; // 00 = Subcode
  4133. buf[2] = 0x07; // Receiver mode, 7 = Force Overdetermined clock
  4134. buf[3] = 0xff; // Not enabled = unchanged, must be 0xff on RES SMT 360
  4135. buf[4] = 0x01; // Dynamics code = default must be 0xff on RES SMT 360
  4136. buf[5] = 0x01; // Solution Mode = default must be 0xff on RES SMT 360
  4137. // Elevation Mask = 10 deg
  4138. putbef32((char *)buf, 6, (float)10.0 * DEG_2_RAD);
  4139. // AMU Mask. 0 to 55. default is 4.0
  4140. putbef32((char *)buf, 10, (float)4.0);
  4141. // PDOP Mask = 8.0, default = 6
  4142. putbef32((char *)buf, 14, (float)8.0);
  4143. // PDOP Switch = 6.0, ignored in RES SMT 360
  4144. putbef32((char *)buf, 18, (float)6.0);
  4145. buf[22] = 0xff; // must be 0xff
  4146. buf[23] = 0x0; // Anti-Jam Mode, 0=Off, 1=On
  4147. putbe16(buf, 24, 0xffff); // Reserved. Must be 0xffff
  4148. /* Measurement Rate and Position Fix Rate = default
  4149. * must be 0xffff on res smt 360 */
  4150. putbe16(buf, 26, 0x0000);
  4151. /* 27 is Constellation on RES SMT 360.
  4152. * 1 = GPS, 2=GLONASS, 8=BeiDou, 0x10=Galileo, 5=QZSS */
  4153. putbe32(buf, 28, 0xffffffff); // Reserved
  4154. putbe32(buf, 32, 0xffffffff); // Reserved
  4155. putbe32(buf, 36, 0xffffffff); // Reserved
  4156. putbe32(buf, 40, 0xffffffff); // Reserved
  4157. (void)tsip_write1(session, buf, 44);
  4158. buf[0] = 0x8e; // Set Packet Broadcast Mask (0x8e-a5)
  4159. buf[1] = 0xa5; // Subcode a5
  4160. /* Packets bit field = default + Primary timing,
  4161. * Supplemental timing 32e1
  4162. * 1=0x8f-ab, 4=0x8f-ac, 0x40=Automatic Output Packets */
  4163. putbe16(buf, 2, 0x32e1);
  4164. buf[4] = 0x00; // not used
  4165. buf[5] = 0x00; // not used
  4166. (void)tsip_write1(session, buf, 6);
  4167. }
  4168. // configure RES 360 to a known state
  4169. void configuration_packets_res360(struct gps_device_t *session)
  4170. {
  4171. char buf[100];
  4172. GPSD_LOG(LOG_PROG, &session->context->errout,
  4173. "TSIP: configuration_packets_res360()\n");
  4174. // should already have versions 0x8f-81 and 0x8f-83.
  4175. /* Self-Survey Parameters (0x8e-a9) is default on
  4176. * query them? */
  4177. // PPS Output Option (0x8e-4e) is default on
  4178. buf[0] = 0x8e; // Set Packet Broadcast Mask (0x8e-a5)
  4179. buf[1] = 0xa5; // a5 = Subcode
  4180. /* Packets bit field = default + Auto output packets
  4181. * 1=0x8f-ab, 4=0x8f-ac, 0x40=Automatic Output Packets */
  4182. putbe16(buf, 2, 0x0045);
  4183. putbe16(buf, 4, 0x0000);
  4184. (void)tsip_write1(session, buf, 6);
  4185. buf[0] = 0x35; // set I/O Options
  4186. // RES SMT 360 defaults: 12 02 00 08
  4187. // position and velocity only sent during self-survey.
  4188. // Position
  4189. buf[1] = IO1_DP|IO1_LLA|IO1_ECEF;
  4190. // Velocity
  4191. buf[2] =IO2_VECEF|IO2_ENU;
  4192. // Timing
  4193. buf[3] = 0x01; // Use 0x8e-a2
  4194. // Auxiliary
  4195. buf[4] = 0x08; // Packet 0x5a off, dBHz
  4196. (void)tsip_write1(session, buf, 5);
  4197. #ifdef __UNUSED__
  4198. // request I/O Options (0x55)
  4199. (void)tsip_write1(session, "\x35", 1);
  4200. // request Receiver Configuration (0xbb)
  4201. (void)tsip_write1(session, "\xbb\x00", 2);
  4202. // Restart Self-Survey (0x8e-a6)
  4203. // which gives us 2,000 normal fixes, before going quiet again.
  4204. (void)tsip_write1(session, "\x8e\xa6\x00", 3);
  4205. #endif // __UNUSED__
  4206. }
  4207. /* this is everything we export */
  4208. /* *INDENT-OFF* */
  4209. const struct gps_type_t driver_tsip =
  4210. {
  4211. .type_name = "Trimble TSIP", // full name of type
  4212. .packet_type = TSIP_PACKET, // associated lexer packet type
  4213. .flags = DRIVER_STICKY, // remember this
  4214. .trigger = NULL, // no trigger
  4215. .channels = TSIP_CHANNELS, // consumer-grade GPS
  4216. .probe_detect = tsip_detect, // probe for 9600O81 device
  4217. .get_packet = generic_get, // use the generic packet getter
  4218. .parse_packet = tsip_parse_input, // parse message packets
  4219. .rtcm_writer = NULL, // doesn't accept DGPS corrections
  4220. .init_query = tsip_init_query, // non-perturbing initial query
  4221. .event_hook = tsip_event_hook, // fire on various lifetime events
  4222. .speed_switcher = tsip_speed_switch, // change baud rate
  4223. .mode_switcher = tsip_mode, // there is a mode switcher
  4224. .rate_switcher = NULL, // no rate switcher
  4225. .min_cycle.tv_sec = 1, // not relevant, no rate switch
  4226. .min_cycle.tv_nsec = 0, // not relevant, no rate switch
  4227. .control_send = tsip_write1, // how to send commands
  4228. .time_offset = NULL,
  4229. };
  4230. /* *INDENT-ON* */
  4231. #endif /* TSIP_ENABLE */
  4232. // vim: set expandtab shiftwidth=4