gps.c
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:27k
源码类别:

uCOS

开发平台:

C/C++

  1. #define  GPS_GLOBALS
  2. #include <includes.h>
  3. #if GPS_MODULE == DEF_ENABLED
  4. #define MAXFIELD 25 // maximum field length
  5. static  OS_STK     GPS_TaskStk[GPS_TASK_STK_SIZE];
  6. static  OS_EVENT  *GPS_Sem;
  7. NP_STATE m_nState; // Current state protocol parser is in
  8. INT8U m_btChecksum; // Calculated NMEA sentence checksum
  9. INT8U m_btReceivedChecksum; // Received NMEA sentence checksum (if exists)
  10. INT16U m_wIndex; // Index used for command and data
  11. INT8U m_pCommand[NP_MAX_CMD_LEN]; // NMEA command
  12. INT8U m_pData[NP_MAX_DATA_LEN]; // NMEA data
  13. static  void    GPS_InitOS(void);
  14. static  void    GPS_Task(void *p_arg);
  15. /*
  16. *********************************************************************************************************
  17. *                                       INITIALIZE GPS
  18. *********************************************************************************************************
  19. */
  20. void  GPS_Init (void)
  21. {
  22. m_nState = NP_STATE_SOM;
  23. m_dwCommandCount = 0;
  24. GPDataReset();
  25.     GPS_InitOS();
  26.     GPS_InitTarget();                            /* Initialize target specific code                 */
  27. }
  28. /*
  29. *********************************************************************************************************
  30. *                             INITIALIZE THE uC/OS-View TASK AND OS OBJECTS
  31. *********************************************************************************************************
  32. */
  33. static  void  GPS_InitOS (void)
  34. {
  35. #if OS_TASK_NAME_SIZE > 7 || OS_EVENT_NAME_SIZE > 7
  36.     INT8U  err;
  37. #endif
  38.     GPS_Sem = OSSemCreate(0);
  39. #if OS_EVENT_NAME_SIZE > 17
  40.     OSEventNameSet(GPS_Sem, (INT8U *)"GPS Signal", &err);
  41. #else
  42. #if OS_EVENT_NAME_SIZE > 7
  43.     OSEventNameSet(GPS_Sem, (INT8U *)"GPS", &err);
  44. #endif
  45. #endif
  46.     (void)OSTaskCreateExt(GPS_Task,
  47.                           (void *)0,                                   /* No arguments passed to OSView_Task() */
  48.                           &GPS_TaskStk[GPS_TASK_STK_SIZE - 1],  /* Set Top-Of-Stack                     */
  49.                           GPS_TASK_PRIO,                           /* Lowest priority level                */
  50.                           GPS_TASK_PRIO,
  51.                           &GPS_TaskStk[0],                          /* Set Bottom-Of-Stack                  */
  52.                           GPS_TASK_STK_SIZE,
  53.                           (void *)0,                                   /* No TCB extension                     */
  54.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear stack  */
  55. #if OS_TASK_NAME_SIZE > 10
  56.     OSTaskNameSet(GPS_TASK_PRIO, (INT8U *)"GPS Task", &err);
  57. #else
  58. #if OS_TASK_NAME_SIZE > 7
  59.     OSTaskNameSet(GPS_TASK_PRIO, (INT8U *)"GPS", &err);
  60. #endif
  61. #endif
  62. }
  63. /*
  64. *********************************************************************************************************
  65. *                                           GPS TASK
  66. *********************************************************************************************************
  67. */
  68. static  void  GPS_Task (void *p_arg)
  69. {
  70.     //INT8U      err;
  71.     //INT8U      s[100];
  72. while(1) {
  73. //(void)OSSemPend(GPS_Sem, 0, &err);
  74. OSTimeDlyHMSM(0, 0, 0, 500);
  75. //sprintf((char *)s, "n时:%2d 分:%2d 秒:%2d 纬度:%f 经度:%f 高度:%fn", GPGGAData.Hour, GPGGAData.Minute, GPGGAData.Second, GPGGAData.Latitude, GPGGAData.Longitude, GPGGAData.Altitude);
  76. //OSView_TxStr(s, 1);
  77. }
  78. }
  79. /*
  80. *********************************************************************************************************
  81. *                                              Rx Handler
  82. *
  83. * Description: This routine is called from the Rx interrupt service handler.
  84. *********************************************************************************************************
  85. */
  86. void  GPS_RxHandler (INT8U rx_data)
  87. {
  88. ProcessNMEA(rx_data);
  89. }
  90. /*
  91. *********************************************************************************************************
  92. *                                               Tx Handler
  93. *
  94. * Description: This routine is called from the transmitter buffer empty interrupt service handler.
  95. *              It will send out the next byte in the buffer.
  96. *
  97. * Returns:     none
  98. *********************************************************************************************************
  99. */
  100. void  GPS_TxHandler (void)
  101. {
  102. }
  103. ///////////////////////////////////////////////////////////////////////////////
  104. // Reset: Reset all NMEA data to start-up default values.
  105. ///////////////////////////////////////////////////////////////////////////////
  106. void GPDataReset(void)
  107. {
  108. int i;
  109. //
  110. // GPGGA Data
  111. //
  112. GPGGAData.Hour = 0; //
  113. GPGGAData.Minute = 0; //
  114. GPGGAData.Second = 0; //
  115. GPGGAData.Latitude = 0.0; // < 0 = South, > 0 = North 
  116. GPGGAData.Longitude = 0.0; // < 0 = West, > 0 = East
  117. GPGGAData.GPSQuality = 0; // 0 = fix not available, 1 = GPS sps mode, 2 = Differential GPS, SPS mode, fix valid, 3 = GPS PPS mode, fix valid
  118. GPGGAData.NumOfSatsInUse = 0; //
  119. GPGGAData.HDOP = 0.0; //
  120. GPGGAData.Altitude = 0.0; // Altitude: mean-sea-level (geoid) meters
  121. GPGGAData.Count = 0; //
  122. GPGGAData.OldVSpeedSeconds = 0; //
  123. GPGGAData.OldVSpeedAlt = 0.0; //
  124. GPGGAData.VertSpeed = 0.0; //
  125. //
  126. // GPGSA
  127. //
  128. GPGSAData.Mode = 'M'; // M = manual, A = automatic 2D/3D
  129. GPGSAData.FixMode = 1; // 1 = fix not available, 2 = 2D, 3 = 3D
  130. for(i = 0; i < NP_MAX_CHAN; i++)
  131. {
  132. GPGSAData.SatsInSolution[i] = 0; // ID of sats in solution
  133. }
  134. GPGSAData.PDOP = 0.0; //
  135. GPGSAData.HDOP = 0.0; //
  136. GPGSAData.VDOP = 0.0; //
  137. GPGSAData.Count = 0; //
  138. //
  139. // GPGSV
  140. //
  141. GPGSVData.TotalNumOfMsg = 0; //
  142. GPGSVData.TotalNumSatsInView = 0; //
  143. for(i = 0; i < NP_MAX_CHAN; i++)
  144. {
  145. GPGSVData.SatInfo[i].Azimuth = 0;
  146. GPGSVData.SatInfo[i].Elevation = 0;
  147. GPGSVData.SatInfo[i].PRN = 0;
  148. GPGSVData.SatInfo[i].SignalQuality = 0;
  149. GPGSVData.SatInfo[i].UsedInSolution = FALSE;
  150. }
  151. GPGSVData.Count = 0;
  152. //
  153. // GPRMB
  154. //
  155. GPRMBData.DataStatus = 'V'; // A = data valid, V = navigation receiver warning
  156. GPRMBData.CrosstrackError = 0.0; // nautical miles
  157. GPRMBData.DirectionToSteer = '?'; // L/R
  158. GPRMBData.OriginWaypoint[0] = ''; // Origin Waypoint ID
  159. GPRMBData.DestWaypoint[0] = ''; // Destination waypoint ID
  160. GPRMBData.DestLatitude = 0.0; // destination waypoint latitude
  161. GPRMBData.DestLongitude = 0.0; // destination waypoint longitude
  162. GPRMBData.RangeToDest = 0.0; // Range to destination nautical mi
  163. GPRMBData.BearingToDest = 0.0; // Bearing to destination, degrees true
  164. GPRMBData.DestClosingVelocity = 0.0; // Destination closing velocity, knots
  165. GPRMBData.ArrivalStatus = 'V'; // A = arrival circle entered, V = not entered
  166. GPRMBData.Count = 0; //
  167. //
  168. // GPRMC
  169. //
  170. GPRMCData.Hour = 0; //
  171. GPRMCData.Minute = 0; //
  172. GPRMCData.Second = 0; //
  173. GPRMCData.DataValid = 'V'; // A = Data valid, V = navigation rx warning
  174. GPRMCData.Latitude = 0.0; // current latitude
  175. GPRMCData.Longitude = 0.0; // current longitude
  176. GPRMCData.GroundSpeed = 0.0; // speed over ground, knots
  177. GPRMCData.Course = 0.0; // course over ground, degrees true
  178. GPRMCData.Day = 1; //
  179. GPRMCData.Month = 1; //
  180. GPRMCData.Year = 2000; //
  181. GPRMCData.MagVar = 0.0; // magnitic variation, degrees East(+)/West(-)
  182. GPRMCData.Count = 0; //
  183. //
  184. // GPZDA
  185. //
  186. GPZDAData.Hour = 0; //
  187. GPZDAData.Minute = 0; //
  188. GPZDAData.Second = 0; //
  189. GPZDAData.Day = 1; // 1 - 31
  190. GPZDAData.Month = 1; // 1 - 12
  191. GPZDAData.Year = 2000; //
  192. GPZDAData.LocalZoneHour = 0; // 0 to +/- 13
  193. GPZDAData.LocalZoneMinute = 0; // 0 - 59
  194. GPZDAData.Count = 0; //
  195. }
  196. ///////////////////////////////////////////////////////////////////////////////
  197. // ProcessNMEA: This method is the main state machine which processes individual
  198. // bytes from the buffer and parses a NMEA sentence. A typical
  199. // sentence is constructed as:
  200. //
  201. // $CMD,DDDD,DDDD,....DD*CS<CR><LF>
  202. //
  203. // Where:
  204. // '$' HEX 24 Start of sentence
  205. // 'CMD' Address/NMEA command
  206. // ',DDDD' Zero or more data fields
  207. // '*CS' Checksum field
  208. // <CR><LF> Hex 0d 0A End of sentence
  209. //
  210. // When a valid sentence is received, this function sends the
  211. // NMEA command and data to the ProcessCommand method for
  212. // individual field parsing.
  213. //
  214. // NOTE:
  215. //
  216. ///////////////////////////////////////////////////////////////////////////////
  217. void ProcessNMEA(INT8U btData)
  218. {
  219. switch(m_nState)
  220. {
  221. ///////////////////////////////////////////////////////////////////////
  222. // Search for start of message '$'
  223. case NP_STATE_SOM :
  224. if(btData == '$')
  225. {
  226. m_btChecksum = 0; // reset checksum
  227. m_wIndex = 0; // reset index
  228. m_nState = NP_STATE_CMD;
  229. }
  230. break;
  231. ///////////////////////////////////////////////////////////////////////
  232. // Retrieve command (NMEA Address)
  233. case NP_STATE_CMD :
  234. if(btData != ',' && btData != '*')
  235. {
  236. m_pCommand[m_wIndex++] = btData;
  237. m_btChecksum ^= btData;
  238. // Check for command overflow
  239. if(m_wIndex >= NP_MAX_CMD_LEN)
  240. {
  241. m_nState = NP_STATE_SOM;
  242. }
  243. }
  244. else
  245. {
  246. m_pCommand[m_wIndex] = ''; // terminate command
  247. m_btChecksum ^= btData;
  248. m_wIndex = 0;
  249. m_nState = NP_STATE_DATA; // goto get data state
  250. }
  251. break;
  252. ///////////////////////////////////////////////////////////////////////
  253. // Store data and check for end of sentence or checksum flag
  254. case NP_STATE_DATA :
  255. if(btData == '*') // checksum flag?
  256. {
  257. m_pData[m_wIndex] = '';
  258. m_nState = NP_STATE_CHECKSUM_1;
  259. }
  260. else // no checksum flag, store data
  261. {
  262. //
  263. // Check for end of sentence with no checksum
  264. //
  265. if(btData == 'r')
  266. {
  267. m_pData[m_wIndex] = '';
  268. ProcessCommand(m_pCommand, m_pData);
  269. m_nState = NP_STATE_SOM;
  270. return;
  271. }
  272. //
  273. // Store data and calculate checksum
  274. //
  275. m_btChecksum ^= btData;
  276. m_pData[m_wIndex] = btData;
  277. if(++m_wIndex >= NP_MAX_DATA_LEN) // Check for buffer overflow
  278. {
  279. m_nState = NP_STATE_SOM;
  280. }
  281. }
  282. break;
  283. ///////////////////////////////////////////////////////////////////////
  284. case NP_STATE_CHECKSUM_1 :
  285. if( (btData - '0') <= 9)
  286. {
  287. m_btReceivedChecksum = (btData - '0') << 4;
  288. }
  289. else
  290. {
  291. m_btReceivedChecksum = (btData - 'A' + 10) << 4;
  292. }
  293. m_nState = NP_STATE_CHECKSUM_2;
  294. break;
  295. ///////////////////////////////////////////////////////////////////////
  296. case NP_STATE_CHECKSUM_2 :
  297. if( (btData - '0') <= 9)
  298. {
  299. m_btReceivedChecksum |= (btData - '0');
  300. }
  301. else
  302. {
  303. m_btReceivedChecksum |= (btData - 'A' + 10);
  304. }
  305. if(m_btChecksum == m_btReceivedChecksum)
  306. {
  307. ProcessCommand(m_pCommand, m_pData);
  308. }
  309. m_nState = NP_STATE_SOM;
  310. break;
  311. ///////////////////////////////////////////////////////////////////////
  312. default : m_nState = NP_STATE_SOM;
  313. }
  314. }
  315. ///////////////////////////////////////////////////////////////////////////////
  316. // Process NMEA sentence - Use the NMEA address (*pCommand) and call the
  317. // appropriate sentense data prossor.
  318. ///////////////////////////////////////////////////////////////////////////////
  319. BOOLEAN ProcessCommand(INT8U *pCommand, INT8U *pData)
  320. {
  321. //
  322. // GPGGA
  323. //
  324. if( strcmp((char *)pCommand, "GPGGA") == NULL )
  325. {
  326. ProcessGPGGA(pData);
  327. OSSemPost(GPS_Sem);
  328. }
  329. //
  330. // GPGSA
  331. //
  332. else if( strcmp((char *)pCommand, "GPGSA") == NULL )
  333. {
  334. ProcessGPGSA(pData);
  335. }
  336. //
  337. // GPGSV
  338. //
  339. else if( strcmp((char *)pCommand, "GPGSV") == NULL )
  340. {
  341. ProcessGPGSV(pData);
  342. }
  343. //
  344. // GPRMB
  345. //
  346. else if( strcmp((char *)pCommand, "GPRMB") == NULL )
  347. {
  348. ProcessGPRMB(pData);
  349. }
  350. //
  351. // GPRMC
  352. //
  353. else if( strcmp((char *)pCommand, "GPRMC") == NULL )
  354. {
  355. ProcessGPRMC(pData);
  356. }
  357. //
  358. // GPZDA
  359. //
  360. else if( strcmp((char *)pCommand, "GPZDA") == NULL )
  361. {
  362. ProcessGPZDA(pData);
  363. }
  364. m_dwCommandCount++;
  365. return TRUE;
  366. }
  367. ///////////////////////////////////////////////////////////////////////////////
  368. // Check to see if supplied satellite ID is used in the GPS solution.
  369. // Retruned: BOOL - TRUE if satellate ID is used in solution
  370. // FALSE if not used in solution.
  371. ///////////////////////////////////////////////////////////////////////////////
  372. BOOLEAN IsSatUsedInSolution(INT16U wSatID)
  373. {
  374. INT32S i;
  375. if(wSatID == 0) return FALSE;
  376. for(i = 0; i < 12; i++)
  377. {
  378. if(wSatID == GPGSAData.SatsInSolution[i])
  379. {
  380. return TRUE;
  381. }
  382. }
  383. return FALSE;
  384. }
  385. ///////////////////////////////////////////////////////////////////////////////
  386. // Name: GetField
  387. //
  388. // Description: This function will get the specified field in a NMEA string.
  389. //
  390. // Entry: INT8U *pData - Pointer to NMEA string
  391. // INT8U *pField - pointer to returned field
  392. // INT32S nfieldNum - Field offset to get
  393. // INT32S nMaxFieldLen - Maximum of bytes pFiled can handle
  394. ///////////////////////////////////////////////////////////////////////////////
  395. BOOLEAN GetField(INT8U *pData, INT8U *pField, INT32S nFieldNum, INT32S nMaxFieldLen)
  396. {
  397. INT32S i, i2, nField;
  398. //
  399. // Validate params
  400. //
  401. if(pData == NULL || pField == NULL || nMaxFieldLen <= 0)
  402. {
  403. return FALSE;
  404. }
  405. //
  406. // Go to the beginning of the selected field
  407. //
  408. i = 0;
  409. nField = 0;
  410. while(nField != nFieldNum && pData[i])
  411. {
  412. if(pData[i] == ',')
  413. {
  414. nField++;
  415. }
  416. i++;
  417. if(pData[i] == NULL)
  418. {
  419. pField[0] = '';
  420. return FALSE;
  421. }
  422. }
  423. if(pData[i] == ',' || pData[i] == '*')
  424. {
  425. pField[0] = '';
  426. return FALSE;
  427. }
  428. //
  429. // copy field from pData to Field
  430. //
  431. i2 = 0;
  432. while(pData[i] != ',' && pData[i] != '*' && pData[i])
  433. {
  434. pField[i2] = pData[i];
  435. i2++; i++;
  436. //
  437. // check if field is too big to fit on passed parameter. If it is,
  438. // crop returned field to its max length.
  439. //
  440. if(i2 >= nMaxFieldLen)
  441. {
  442. i2 = nMaxFieldLen-1;
  443. break;
  444. }
  445. }
  446. pField[i2] = '';
  447. return TRUE;
  448. }
  449. ///////////////////////////////////////////////////////////////////////////////
  450. ///////////////////////////////////////////////////////////////////////////////
  451. void ProcessGPZDA(INT8U *pData)
  452. {
  453. char  pBuff[10];
  454. INT8U  pField[MAXFIELD];
  455. //
  456. // Time
  457. //
  458. if(GetField(pData, pField, 0, MAXFIELD))
  459. {
  460. // Hour
  461. pBuff[0] = pField[0];
  462. pBuff[1] = pField[1];
  463. pBuff[2] = '';
  464. GPZDAData.Hour = atoi(pBuff);
  465. // minute
  466. pBuff[0] = pField[2];
  467. pBuff[1] = pField[3];
  468. pBuff[2] = '';
  469. GPZDAData.Minute = atoi(pBuff);
  470. // Second
  471. pBuff[0] = pField[4];
  472. pBuff[1] = pField[5];
  473. pBuff[2] = '';
  474. GPZDAData.Second = atoi(pBuff);
  475. }
  476. //
  477. // Day
  478. //
  479. if(GetField(pData, pField, 1, MAXFIELD))
  480. {
  481. GPZDAData.Day = atoi((char *)pField);
  482. }
  483. else
  484. {
  485. GPZDAData.Day = 1;
  486. }
  487. //
  488. // Month
  489. //
  490. if(GetField(pData, pField, 2, MAXFIELD))
  491. {
  492. GPZDAData.Month = atoi((char *)pField);
  493. }
  494. else
  495. {
  496. GPZDAData.Month = 1;
  497. }
  498. //
  499. // Year
  500. //
  501. if(GetField(pData, pField, 3, MAXFIELD))
  502. {
  503. GPZDAData.Year = atoi((char *)pField);
  504. }
  505. else
  506. {
  507. GPZDAData.Year = 1;
  508. }
  509. //
  510. // Local zone hour
  511. //
  512. if(GetField(pData, pField, 4, MAXFIELD))
  513. {
  514. GPZDAData.LocalZoneHour = atoi((char *)pField);
  515. }
  516. else
  517. {
  518. GPZDAData.LocalZoneHour = 0;
  519. }
  520. //
  521. // Local zone hour
  522. //
  523. if(GetField(pData, pField, 5, MAXFIELD))
  524. {
  525. GPZDAData.LocalZoneMinute = atoi((char *)pField);
  526. }
  527. else
  528. {
  529. GPZDAData.LocalZoneMinute = 0;
  530. }
  531. GPZDAData.Count++;
  532. }
  533. ///////////////////////////////////////////////////////////////////////////////
  534. ///////////////////////////////////////////////////////////////////////////////
  535. void ProcessGPRMC(INT8U *pData)
  536. {
  537. char pBuff[10];
  538. INT8U pField[MAXFIELD];
  539. //
  540. // Time
  541. //
  542. if(GetField(pData, pField, 0, MAXFIELD))
  543. {
  544. // Hour
  545. pBuff[0] = pField[0];
  546. pBuff[1] = pField[1];
  547. pBuff[2] = '';
  548. GPRMCData.Hour = atoi(pBuff);
  549. // minute
  550. pBuff[0] = pField[2];
  551. pBuff[1] = pField[3];
  552. pBuff[2] = '';
  553. GPRMCData.Minute = atoi(pBuff);
  554. // Second
  555. pBuff[0] = pField[4];
  556. pBuff[1] = pField[5];
  557. pBuff[2] = '';
  558. GPRMCData.Second = atoi(pBuff);
  559. }
  560. //
  561. // Data valid
  562. //
  563. if(GetField(pData, pField, 1, MAXFIELD))
  564. {
  565. GPRMCData.DataValid = pField[0];
  566. }
  567. else
  568. {
  569. GPRMCData.DataValid = 'V';
  570. }
  571. //
  572. // latitude
  573. //
  574. if(GetField(pData, pField, 2, MAXFIELD))
  575. {
  576. GPRMCData.Latitude = atof((char *)pField+2) / 60.0;
  577. pField[2] = '';
  578. GPRMCData.Latitude += atof((char *)pField);
  579. }
  580. if(GetField(pData, pField, 3, MAXFIELD))
  581. {
  582. if(pField[0] == 'S')
  583. {
  584. GPRMCData.Latitude = -GPRMCData.Latitude;
  585. }
  586. }
  587. //
  588. // Longitude
  589. //
  590. if(GetField(pData, pField, 4, MAXFIELD))
  591. {
  592. GPRMCData.Longitude = atof((char *)pField+3) / 60.0;
  593. pField[3] = '';
  594. GPRMCData.Longitude += atof((char *)pField);
  595. }
  596. if(GetField(pData, pField, 5, MAXFIELD))
  597. {
  598. if(pField[0] == 'W')
  599. {
  600. GPRMCData.Longitude = -GPRMCData.Longitude;
  601. }
  602. }
  603. //
  604. // Ground speed
  605. //
  606. if(GetField(pData, pField, 6, MAXFIELD))
  607. {
  608. GPRMCData.GroundSpeed = atof((char *)pField);
  609. }
  610. else
  611. {
  612. GPRMCData.GroundSpeed = 0.0;
  613. }
  614. //
  615. // course over ground, degrees true
  616. //
  617. if(GetField(pData, pField, 7, MAXFIELD))
  618. {
  619. GPRMCData.Course = atof((char *)pField);
  620. }
  621. else
  622. {
  623. GPRMCData.Course = 0.0;
  624. }
  625. //
  626. // Date
  627. //
  628. if(GetField(pData, pField, 8, MAXFIELD))
  629. {
  630. // Day
  631. pBuff[0] = pField[0];
  632. pBuff[1] = pField[1];
  633. pBuff[2] = '';
  634. GPRMCData.Day = atoi(pBuff);
  635. // Month
  636. pBuff[0] = pField[2];
  637. pBuff[1] = pField[3];
  638. pBuff[2] = '';
  639. GPRMCData.Month = atoi(pBuff);
  640. // Year (Only two digits. I wonder why?)
  641. pBuff[0] = pField[4];
  642. pBuff[1] = pField[5];
  643. pBuff[2] = '';
  644. GPRMCData.Year = atoi(pBuff);
  645. GPRMCData.Year += 2000; // make 4 digit date -- What assumptions should be made here?
  646. }
  647. //
  648. // course over ground, degrees true
  649. //
  650. if(GetField(pData, pField, 9, MAXFIELD))
  651. {
  652. GPRMCData.MagVar = atof((char *)pField);
  653. }
  654. else
  655. {
  656. GPRMCData.MagVar = 0.0;
  657. }
  658. if(GetField(pData, pField, 10, MAXFIELD))
  659. {
  660. if(pField[0] == 'W')
  661. {
  662. GPRMCData.MagVar = -GPRMCData.MagVar;
  663. }
  664. }
  665. GPRMCData.Count++;
  666. }
  667. ///////////////////////////////////////////////////////////////////////////////
  668. ///////////////////////////////////////////////////////////////////////////////
  669. void ProcessGPRMB(INT8U *pData)
  670. {
  671. INT8U pField[MAXFIELD];
  672. //
  673. // Data status
  674. //
  675. if(GetField(pData, pField, 0, MAXFIELD))
  676. {
  677. GPRMBData.DataStatus = pField[0];
  678. }
  679. else
  680. {
  681. GPRMBData.DataStatus = 'V';
  682. }
  683. //
  684. // Cross track error
  685. //
  686. if(GetField(pData, pField, 1, MAXFIELD))
  687. {
  688. GPRMBData.CrosstrackError = atof((char *)pField);
  689. }
  690. else
  691. {
  692. GPRMBData.CrosstrackError = 0.0;
  693. }
  694. //
  695. // Direction to steer
  696. //
  697. if(GetField(pData, pField, 2, MAXFIELD))
  698. {
  699. GPRMBData.DirectionToSteer = pField[0];
  700. }
  701. else
  702. {
  703. GPRMBData.DirectionToSteer = '?';
  704. }
  705. //
  706. // Orgin waypoint ID
  707. //
  708. if(GetField(pData, pField, 3, MAXFIELD))
  709. {
  710. strcpy(GPRMBData.OriginWaypoint, (char *)pField);
  711. }
  712. else
  713. {
  714. GPRMBData.OriginWaypoint[0] = '';
  715. }
  716. //
  717. // Destination waypoint ID
  718. //
  719. if(GetField(pData, pField, 4, MAXFIELD))
  720. {
  721. strcpy(GPRMBData.DestWaypoint, (char *)pField);
  722. }
  723. else
  724. {
  725. GPRMBData.DestWaypoint[0] = '';
  726. }
  727. //
  728. // Destination latitude
  729. //
  730. if(GetField(pData, pField, 5, MAXFIELD))
  731. {
  732. GPRMBData.DestLatitude = atof((char *)pField+2) / 60.0;
  733. pField[2] = '';
  734. GPRMBData.DestLatitude += atof((char *)pField);
  735. }
  736. if(GetField(pData, pField, 6, MAXFIELD))
  737. {
  738. if(pField[0] == 'S')
  739. {
  740. GPRMBData.DestLatitude = -GPRMBData.DestLatitude;
  741. }
  742. }
  743. //
  744. // Destination Longitude
  745. //
  746. if(GetField(pData, pField, 7, MAXFIELD))
  747. {
  748. GPRMBData.DestLongitude = atof((char *)pField+3) / 60.0;
  749. pField[3] = '';
  750. GPRMBData.DestLongitude += atof((char *)pField);
  751. }
  752. if(GetField(pData, pField, 8, MAXFIELD))
  753. {
  754. if(pField[0] == 'W')
  755. {
  756. GPRMBData.DestLongitude = -GPRMBData.DestLongitude;
  757. }
  758. }
  759. //
  760. // Range to destination nautical mi
  761. //
  762. if(GetField(pData, pField, 9, MAXFIELD))
  763. {
  764. GPRMBData.RangeToDest = atof((char *)pField);
  765. }
  766. else
  767. {
  768. GPRMBData.CrosstrackError = 0.0;
  769. }
  770. //
  771. // Bearing to destination degrees true
  772. //
  773. if(GetField(pData, pField, 10, MAXFIELD))
  774. {
  775. GPRMBData.BearingToDest = atof((char *)pField);
  776. }
  777. else
  778. {
  779. GPRMBData.BearingToDest = 0.0;
  780. }
  781. //
  782. // Closing velocity
  783. //
  784. if(GetField(pData, pField, 11, MAXFIELD))
  785. {
  786. GPRMBData.DestClosingVelocity = atof((char *)pField);
  787. }
  788. else
  789. {
  790. GPRMBData.DestClosingVelocity = 0.0;
  791. }
  792. //
  793. // Arrival status
  794. //
  795. if(GetField(pData, pField, 12, MAXFIELD))
  796. {
  797. GPRMBData.ArrivalStatus = pField[0];
  798. }
  799. else
  800. {
  801. GPRMBData.DestClosingVelocity = 'V';
  802. }
  803. GPRMBData.Count++;
  804. }
  805.  ///////////////////////////////////////////////////////////////////////////////
  806. ///////////////////////////////////////////////////////////////////////////////
  807. void ProcessGPGSV(INT8U *pData)
  808. {
  809. INT32S i, nTotalNumOfMsg = 0, nMsgNum = 0;
  810. INT8U pField[MAXFIELD];
  811. //
  812. // Total number of messages
  813. //
  814. if(GetField(pData, pField, 0, MAXFIELD))
  815. {
  816. nTotalNumOfMsg = atoi((char *)pField);
  817. //
  818. // Make sure that the nTotalNumOfMsg is valid. This is used to
  819. // calculate indexes into an array. I've seen corrept NMEA strings
  820. // with no checksum set this to large values.
  821. //
  822. if(nTotalNumOfMsg > 9 || nTotalNumOfMsg < 0) return; 
  823. }
  824. if(nTotalNumOfMsg < 1 || nTotalNumOfMsg*4 >= NP_MAX_CHAN)
  825. {
  826. return;
  827. }
  828. //
  829. // message number
  830. //
  831. if(GetField(pData, pField, 1, MAXFIELD))
  832. {
  833. nMsgNum = atoi((char *)pField);
  834. //
  835. // Make sure that the message number is valid. This is used to
  836. // calculate indexes into an array
  837. //
  838. if(nMsgNum > 9 || nMsgNum < 0) return; 
  839. }
  840. //
  841. // Total satellites in view
  842. //
  843. if(GetField(pData, pField, 2, MAXFIELD))
  844. {
  845. GPGSVData.TotalNumSatsInView = atoi((char *)pField);
  846. }
  847. //
  848. // Satelite data
  849. //
  850. for(i = 0; i < 4; i++)
  851. {
  852. // Satellite ID
  853. if(GetField(pData, pField, 3 + 4*i, MAXFIELD))
  854. {
  855. GPGSVData.SatInfo[i+(nMsgNum-1)*4].PRN = atoi((char *)pField);
  856. }
  857. else
  858. {
  859. GPGSVData.SatInfo[i+(nMsgNum-1)*4].PRN = 0;
  860. }
  861. // Elevarion
  862. if(GetField(pData, pField, 4 + 4*i, MAXFIELD))
  863. {
  864. GPGSVData.SatInfo[i+(nMsgNum-1)*4].Elevation = atoi((char *)pField);
  865. }
  866. else
  867. {
  868. GPGSVData.SatInfo[i+(nMsgNum-1)*4].Elevation = 0;
  869. }
  870. // Azimuth
  871. if(GetField(pData, pField, 5 + 4*i, MAXFIELD))
  872. {
  873. GPGSVData.SatInfo[i+(nMsgNum-1)*4].Azimuth = atoi((char *)pField);
  874. }
  875. else
  876. {
  877. GPGSVData.SatInfo[i+(nMsgNum-1)*4].Azimuth = 0;
  878. }
  879. // SNR
  880. if(GetField(pData, pField, 6 + 4*i, MAXFIELD))
  881. {
  882. GPGSVData.SatInfo[i+(nMsgNum-1)*4].SignalQuality = atoi((char *)pField);
  883. }
  884. else
  885. {
  886. GPGSVData.SatInfo[i+(nMsgNum-1)*4].SignalQuality = 0;
  887. }
  888. //
  889. // Update "used in solution" (m_bUsedInSolution) flag. This is base
  890. // on the GSA message and is an added convenience for post processing
  891. //
  892. GPGSVData.SatInfo[i+(nMsgNum-1)*4].UsedInSolution = IsSatUsedInSolution(GPGSVData.SatInfo[i+(nMsgNum-1)*4].PRN);
  893. }
  894. GPGSVData.Count++;
  895. }
  896. ///////////////////////////////////////////////////////////////////////////////
  897. ///////////////////////////////////////////////////////////////////////////////
  898. void ProcessGPGSA(INT8U *pData)
  899. {
  900. INT8U pField[MAXFIELD];
  901. char pBuff[10];
  902. INT32S i;
  903. //
  904. // Mode
  905. //
  906. if(GetField(pData, pField, 0, MAXFIELD))
  907. {
  908. GPGSAData.Mode = pField[0];
  909. }
  910. //
  911. // Fix Mode
  912. //
  913. if(GetField(pData, pField, 1, MAXFIELD))
  914. {
  915. GPGSAData.FixMode = pField[0] - '0';
  916. }
  917. //
  918. // Active satellites
  919. //
  920. for(i = 0; i < 12; i++)
  921. {
  922. if(GetField(pData, pField, 2 + i, MAXFIELD))
  923. {
  924. pBuff[0] = pField[0];
  925. pBuff[1] = pField[1];
  926. pBuff[2] = '';
  927. GPGSAData.SatsInSolution[i] = atoi(pBuff);
  928. }
  929. else
  930. {
  931. GPGSAData.SatsInSolution[i] = 0;
  932. }
  933. }
  934. //
  935. // PDOP
  936. //
  937. if(GetField(pData, pField, 14, MAXFIELD))
  938. {
  939. GPGSAData.PDOP = atof((char *)pField);
  940. }
  941. else
  942. {
  943. GPGSAData.PDOP = 0.0;
  944. }
  945. //
  946. // HDOP
  947. //
  948. if(GetField(pData, pField, 15, MAXFIELD))
  949. {
  950. GPGSAData.HDOP = atof((char *)pField);
  951. }
  952. else
  953. {
  954. GPGSAData.HDOP = 0.0;
  955. }
  956. //
  957. // VDOP
  958. //
  959. if(GetField(pData, pField, 16, MAXFIELD))
  960. {
  961. GPGSAData.VDOP = atof((char *)pField);
  962. }
  963. else
  964. {
  965. GPGSAData.VDOP = 0.0;
  966. }
  967. GPGSAData.Count++;
  968. }
  969. ///////////////////////////////////////////////////////////////////////////////
  970. ///////////////////////////////////////////////////////////////////////////////
  971. void ProcessGPGGA(INT8U *pData)
  972. {
  973. INT8U pField[MAXFIELD];
  974. char pBuff[10];
  975. INT32S nSeconds;
  976. //
  977. // Time
  978. //
  979. if(GetField(pData, pField, 0, MAXFIELD))
  980. {
  981. // Hour
  982. pBuff[0] = pField[0];
  983. pBuff[1] = pField[1];
  984. pBuff[2] = '';
  985. GPGGAData.Hour = atoi(pBuff);
  986. // minute
  987. pBuff[0] = pField[2];
  988. pBuff[1] = pField[3];
  989. pBuff[2] = '';
  990. GPGGAData.Minute = atoi(pBuff);
  991. // Second
  992. pBuff[0] = pField[4];
  993. pBuff[1] = pField[5];
  994. pBuff[2] = '';
  995. GPGGAData.Second = atoi(pBuff);
  996. }
  997. //
  998. // Latitude
  999. //
  1000. if(GetField(pData, pField, 1, MAXFIELD))
  1001. {
  1002. GPGGAData.Latitude = atof((char *)pField+2) / 60.0;
  1003. pField[2] = '';
  1004. GPGGAData.Latitude += atof((char *)pField);
  1005. }
  1006. if(GetField(pData, pField, 2, MAXFIELD))
  1007. {
  1008. if(pField[0] == 'S')
  1009. {
  1010. GPGGAData.Latitude = -GPGGAData.Latitude;
  1011. }
  1012. }
  1013. //
  1014. // Longitude
  1015. //
  1016. if(GetField(pData, pField, 3, MAXFIELD))
  1017. {
  1018. GPGGAData.Longitude = atof((char *)pField+3) / 60.0;
  1019. pField[3] = '';
  1020. GPGGAData.Longitude += atof((char *)pField);
  1021. }
  1022. if(GetField(pData, pField, 4, MAXFIELD))
  1023. {
  1024. if(pField[0] == 'W')
  1025. {
  1026. GPGGAData.Longitude = -GPGGAData.Longitude;
  1027. }
  1028. }
  1029. //
  1030. // GPS quality
  1031. //
  1032. if(GetField(pData, pField, 5, MAXFIELD))
  1033. {
  1034. GPGGAData.GPSQuality = pField[0] - '0';
  1035. }
  1036. //
  1037. // Satellites in use
  1038. //
  1039. if(GetField(pData, pField, 6, MAXFIELD))
  1040. {
  1041. pBuff[0] = pField[0];
  1042. pBuff[1] = pField[1];
  1043. pBuff[2] = '';
  1044. GPGGAData.NumOfSatsInUse = atoi(pBuff);
  1045. }
  1046. //
  1047. // HDOP
  1048. //
  1049. if(GetField(pData, pField, 7, MAXFIELD))
  1050. {
  1051. GPGGAData.HDOP = atof((char *)pField);
  1052. }
  1053. //
  1054. // Altitude
  1055. //
  1056. if(GetField(pData, pField, 8, MAXFIELD))
  1057. {
  1058. GPGGAData.Altitude = atof((char *)pField);
  1059. }
  1060. //
  1061. // Durive vertical speed (bonus)
  1062. //
  1063. nSeconds = (INT32S)GPGGAData.Minute * 60 + (INT32S)GPGGAData.Second;
  1064. if(nSeconds > GPGGAData.OldVSpeedSeconds)
  1065. {
  1066. double dDiff = (double)(GPGGAData.OldVSpeedSeconds-nSeconds);
  1067. double dVal = dDiff/60.0;
  1068. if(dVal != 0.0)
  1069. {
  1070. GPGGAData.VertSpeed = (GPGGAData.OldVSpeedAlt - GPGGAData.Altitude) / dVal;
  1071. }
  1072. }
  1073. GPGGAData.OldVSpeedAlt = GPGGAData.Altitude;
  1074. GPGGAData.OldVSpeedSeconds = nSeconds;
  1075. GPGGAData.Count++;
  1076. }
  1077. #endif