gnss_demo.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550
  1. /*================================================================
  2. Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  3. Quectel Wireless Solution Proprietary and Confidential.
  4. =================================================================*/
  5. /*=================================================================
  6. EDIT HISTORY FOR MODULE
  7. This section contains comments describing changes made to the module.
  8. Notice that changes are listed in reverse chronological order.
  9. WHEN WHO WHAT, WHERE, WHY
  10. ------------ ------- -------------------------------------------------------------------------------
  11. =================================================================*/
  12. /*===========================================================================
  13. * include files
  14. ===========================================================================*/
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include "ql_api_osi.h"
  19. #include "ql_log.h"
  20. #include "gnss_demo.h"
  21. #include "ql_api_datacall.h"
  22. /*===========================================================================
  23. * Macro Definition
  24. ===========================================================================*/
  25. #define MAX_UINT32 4294967295U
  26. #define QL_GNSSDEMO_LOG_LEVEL QL_LOG_LEVEL_INFO
  27. #define QL_GNSSDEMO_LOG(msg, ...) QL_LOG(QL_GNSSDEMO_LOG_LEVEL, "ql_GNSSDEMO", msg, ##__VA_ARGS__)
  28. #define nmea_dbg_log(msg, ...) QL_LOG(QL_GNSSDEMO_LOG_LEVEL,"ql_nmaea", msg, ##__VA_ARGS__)
  29. /*===========================================================================
  30. * Variate
  31. ===========================================================================*/
  32. ql_task_t gnss_task = NULL;
  33. ql_gnss_data_t g_gps_data = {0};
  34. static uint32 prev_ms_gsv =0;
  35. static bool tick_overflow = FALSE;
  36. ql_gnss_startmode_e gnss_startmode = GNSS_START_MAX; //gnss冷启动/热启动模式,内核侧上报(具体参考优先级设定,关系到lte是否能够使用)
  37. ql_gnss_state_ind_t gnss_state_ind = {0}; //gnss运行状态,内核侧上报状态以及状态错误码
  38. /*===========================================================================
  39. * Functions
  40. ===========================================================================*/
  41. void ql_gnss_notify_cb(const ql_event_t *event)
  42. {
  43. QL_GNSSDEMO_LOG("nmea nodify: eventId:%d", event->id);
  44. ql_event_t ql_event = *event;
  45. ql_event.id = QUEC_GNSS_REC_NMEA_IND;
  46. ql_rtos_event_send(gnss_task, (ql_event_t *)&ql_event);
  47. }
  48. void ql_gnss_coexist_cb(uint32 ind_type, void *ctx)
  49. {
  50. ql_event_t event = {0};
  51. if(QUEC_GNSS_STARTMODE_IND == ind_type) //gnss 当前冷热模式通知
  52. {
  53. event.id = ind_type;
  54. event.param1 = *(ql_gnss_startmode_e *)ctx;
  55. ql_rtos_event_send(gnss_task, &event);
  56. }
  57. else if(QUEC_GNSS_STATE_IND == ind_type) //gnss 当前运行状态通知
  58. {
  59. ql_gnss_state_ind_t *state_ind = (ql_gnss_state_ind_t *)ctx;
  60. event.id = ind_type;
  61. event.param1 = state_ind->state; //gnss运行状态
  62. event.param2 = state_ind->errcode; //状态错误码
  63. ql_rtos_event_send(gnss_task, &event);
  64. }
  65. else
  66. {
  67. QL_GNSSDEMO_LOG("ind err");
  68. }
  69. }
  70. static void ql_gnss_demo_thread(void *param)
  71. {
  72. QL_GNSSDEMO_LOG("gnss demo thread enter, param 0x%x", param);
  73. ql_event_t event = {0};
  74. int ret = 0;
  75. uint32_t length = 0;
  76. uint16_t type = 0;
  77. uint8_t *start=NULL, *end=NULL;
  78. uint8_t nmea_buff[256]={0};
  79. struct nmea_s *nmea = NULL;
  80. ql_gnss_output_info_ind_t *data_info = NULL;
  81. uint8_t *recbuff=NULL;
  82. uint8_t nSim = 0;
  83. int wait_cnt = 0;
  84. uint8_t priority = 0;
  85. /* gnss lte set priority */
  86. while(1)
  87. {
  88. ql_gnss_lte_priority_set(GNSS_PRIORITY_GROUP_1); //配置优先级
  89. if(QL_GNSS_SUCCESS == ql_gnss_lte_priority_get(&priority))
  90. {
  91. if(GNSS_PRIORITY_GROUP_1 == priority) //优先级设置需要等待CP侧初始化后才能设置成功
  92. {
  93. QL_GNSSDEMO_LOG("set priority ok");
  94. break;
  95. }
  96. }
  97. ql_rtos_task_sleep_ms(1000);
  98. }
  99. /* gnss cold start is highest priority when gnss priority group set 0/1/2. Directly opening gnss may disrupt registration networks process.
  100. Waiting register network time is set by yourself (default 60s), if you not want wait register networks, you can mark this code. */
  101. while((ret = ql_network_register_wait(nSim, 1)) != 0 && wait_cnt < 30)
  102. {
  103. wait_cnt++;
  104. QL_GNSSDEMO_LOG("wait network register count: %d",wait_cnt);
  105. ql_rtos_task_sleep_ms(1000);
  106. }
  107. /* register nmea cb */
  108. ret = ql_gnss_callback_register(ql_gnss_notify_cb);
  109. if(ret ==QL_GNSS_CB_NULL_ERR)
  110. {
  111. goto exit;
  112. }
  113. /* register coexist cb */
  114. ret = ql_gnss_coexist_callback_register(ql_gnss_coexist_cb); //注册共存callback,内核侧会将当前gnss的运行状态以及启动模式上报
  115. if(ret == QL_GNSS_CB_NULL_ERR)
  116. {
  117. goto exit;
  118. }
  119. /* open GNSS */
  120. ret = ql_gnss_switch(GNSS_ENABLE);
  121. if(ret == QL_GNSS_ALREADY_OPEN)
  122. {
  123. QL_GNSSDEMO_LOG("already open");
  124. }
  125. else if(ret == QL_GNSS_INVALID_PARAM_ERR)
  126. {
  127. goto exit;
  128. }
  129. /* get gnss sys type */
  130. ql_gnss_cfg_s gnss_cfg = {0};
  131. ret = ql_gnss_get_cfg(&gnss_cfg);
  132. if (ret == QL_GNSS_SUCCESS)
  133. {
  134. QL_GNSSDEMO_LOG("get sys_type=%d", gnss_cfg.nmea_cfg.gnss_nmea_sys_type);
  135. }
  136. while(1)
  137. {
  138. if( ql_event_try_wait(&event) != 0 )
  139. {
  140. continue;
  141. }
  142. if( event.id == QUEC_GNSS_REC_NMEA_IND )
  143. {
  144. if((void *)event.param1 == NULL)
  145. {
  146. QL_GNSSDEMO_LOG("param err\r\n");
  147. break;
  148. }
  149. recbuff=calloc(1,QUEC_GPS_RECBUF_LEN_MAX);
  150. if(NULL==recbuff)
  151. {
  152. QL_GNSSDEMO_LOG("malloc err\r\n");
  153. if((void *)event.param1 != NULL)
  154. {
  155. free((void *)event.param1);
  156. }
  157. break;
  158. }
  159. //get nmea source info
  160. data_info = (ql_gnss_output_info_ind_t *)event.param1;
  161. type = data_info->type;
  162. length = data_info->length;
  163. if(length)
  164. {
  165. memcpy(recbuff, data_info->data, length);
  166. QL_GNSSDEMO_LOG("length=%d,type=%d",length,type);
  167. end=recbuff;
  168. while(1)
  169. {
  170. start = memchr(end, '$', length-(end-recbuff));
  171. if (NULL == start)
  172. {
  173. QL_GNSSDEMO_LOG("notfind $");
  174. break;
  175. }
  176. end = memchr(start, NMEA_END_CHAR_1, length-(start-recbuff));
  177. if (NULL==end || NMEA_END_CHAR_2 != *(++end))
  178. {
  179. QL_GNSSDEMO_LOG("notfind r/n");
  180. break;
  181. }
  182. memset(nmea_buff, 0, sizeof(nmea_buff));
  183. memcpy(nmea_buff, start, jmin(sizeof(nmea_buff)-1, end-start-1));
  184. QL_GNSSDEMO_LOG("%s\r\n", nmea_buff);
  185. /* nmea string parse */
  186. nmea = nmea_parse((char *)start, end-start+1, 1);
  187. if (nmea)
  188. {
  189. ret=nmea_value_update(nmea, &g_gps_data);
  190. if(ret)
  191. {
  192. QL_GNSSDEMO_LOG("nmea_value_update error. \r\n");
  193. QL_GNSSDEMO_LOG("update err: %s", nmea_buff);
  194. }
  195. if (nmea->data)
  196. {
  197. free(nmea->data);
  198. nmea->data = NULL;
  199. }
  200. free(nmea);
  201. nmea = NULL;
  202. }
  203. if(end==recbuff+length-1)
  204. {
  205. break;
  206. }
  207. end=end+1;
  208. }
  209. }
  210. if((void *)event.param1 != NULL)
  211. {
  212. free((void *)event.param1);
  213. }
  214. if(NULL != recbuff)
  215. {
  216. free(recbuff);
  217. recbuff=NULL;
  218. }
  219. }
  220. else if(event.id == QUEC_GNSS_STARTMODE_IND) //内核侧上报gnss冷热启动模式,(具体参考设置优先级关系,关系到lte是否能够使用)
  221. {
  222. if((ql_gnss_startmode_e)event.param1 >= GNSS_START_MAX)
  223. {
  224. QL_GNSSDEMO_LOG("param err");
  225. continue;
  226. }
  227. gnss_startmode = (ql_gnss_startmode_e)event.param1; //若设置优先级模式1,则必须等到热启动之后,lte的数据业务才可以进行
  228. QL_GNSSDEMO_LOG("start mode %d",gnss_startmode);
  229. }
  230. else if(event.id == QUEC_GNSS_STATE_IND) //内核侧上报gnss当前的运行状态,
  231. {
  232. gnss_state_ind.state = (ql_GnssState)event.param1;
  233. gnss_state_ind.errcode = (ql_errcode_gnss)event.param2;
  234. QL_GNSSDEMO_LOG("gnss state/%d,errcode/0x%x",gnss_state_ind.state, gnss_state_ind.errcode);
  235. }
  236. }
  237. exit:
  238. if(NULL != recbuff)
  239. {
  240. free(recbuff);
  241. recbuff=NULL;
  242. }
  243. ql_gnss_switch(GNSS_DISABLE);
  244. QL_GNSSDEMO_LOG("gnss demo thread exit, param 0x%x", param);
  245. ql_rtos_task_delete(NULL);
  246. }
  247. void ql_gnss_app_init(void)
  248. {
  249. QlOSStatus err = QL_OSI_SUCCESS;
  250. err = ql_rtos_task_create(&gnss_task, 4096*2, APP_PRIORITY_HIGH, "ql_gnssdemo", ql_gnss_demo_thread, NULL, 20);
  251. if( err != QL_OSI_SUCCESS )
  252. {
  253. QL_GNSSDEMO_LOG("gnss demo task created failed");
  254. }
  255. }
  256. /**
  257. * strptime
  258. **/
  259. #define TM_YEAR_BASE 1900
  260. /*
  261. * We do not implement alternate representations. However, we always
  262. * check whether a given modifier is allowed for a certain conversion.
  263. */
  264. #define ALT_E 0x01
  265. #define ALT_O 0x02
  266. #define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
  267. static const char *day[7] = {
  268. "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
  269. "Friday", "Saturday"
  270. };
  271. static const char *abday[7] = {
  272. "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
  273. };
  274. static const char *mon[12] = {
  275. "January", "February", "March", "April", "May", "June", "July",
  276. "August", "September", "October", "November", "December"
  277. };
  278. static const char *abmon[12] = {
  279. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  280. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  281. };
  282. static const char *am_pm[2] = {
  283. "AM", "PM"
  284. };
  285. char nmea_get_checksum(const char *sentence)
  286. {
  287. const char *n = sentence + 1;
  288. char chk = 0;
  289. /* While current char isn't '*' or sentence ending (newline) */
  290. while ('*' != *n && NMEA_END_CHAR_1 != *n && '\0' != *n) {
  291. chk ^= (char) *n;
  292. n++;
  293. }
  294. return chk;
  295. }
  296. int nmea_has_checksum(const char *sentence, int length)
  297. {
  298. if ('*' == sentence[length - 5]) {
  299. return 0;
  300. }
  301. return -1;
  302. }
  303. int nmea_validate(const char *sentence, int length, int check_checksum)
  304. {
  305. const char *n = NULL;
  306. //nmea_dbg_log("%s\n", __FUNCTION__);
  307. /* should have atleast 9 characters */
  308. if (9 > length) {
  309. return -1;
  310. }
  311. /* should be less or equal to 82 characters */
  312. if (NMEA_MAX_LENGTH < length) {
  313. return -1;
  314. }
  315. /* should start with $ */
  316. if ('$' != *sentence) {
  317. return -1;
  318. }
  319. /* should end with \r\n, or other... */
  320. if (NMEA_END_CHAR_2 != sentence[length - 1] || NMEA_END_CHAR_1 != sentence[length - 2]) {
  321. nmea_dbg_log("\r\n");
  322. return -1;
  323. }
  324. /* should have a 5 letter, uppercase word */
  325. n = sentence;
  326. while (++n < sentence + 6) {
  327. if (*n < 'A' || *n > 'Z') {
  328. /* not uppercase letter */
  329. return -1;
  330. }
  331. }
  332. /* should have a comma after the type word */
  333. if (',' != sentence[6]) {
  334. nmea_dbg_log("\r\n");
  335. return -1;
  336. }
  337. /* check for checksum */
  338. if (1 == check_checksum && 0 == nmea_has_checksum(sentence, length)) {
  339. char actual_chk=0;
  340. char expected_chk=0;
  341. char checksum[3]={0};
  342. checksum[0] = sentence[length - 4];
  343. checksum[1] = sentence[length - 3];
  344. checksum[2] = '\0';
  345. actual_chk = nmea_get_checksum(sentence);
  346. expected_chk = (char) strtol(checksum, NULL, 16);
  347. if (expected_chk != actual_chk) {
  348. nmea_dbg_log("\r\n");
  349. return -1;
  350. }
  351. }
  352. return 0;
  353. }
  354. /**
  355. * Crop a sentence from the type word and checksum.
  356. *
  357. * The type word at the beginning along with the dollar sign ($) will be
  358. * removed. If there is a checksum, it will also be removed. The two end
  359. * characters (usually <CR><LF>) will not be included in the new string.
  360. *
  361. * sentence is a validated NMEA sentence string.
  362. * length is the char length of the sentence string.
  363. *
  364. * Returns pointer (char *) to the new string.
  365. */
  366. static char * _crop_sentence(char *sentence, size_t length)
  367. {
  368. /* Skip type word, 7 characters (including $ and ,) */
  369. sentence += NMEA_PREFIX_LENGTH + 2;
  370. /* Null terminate before end of line/sentence, 2 characters */
  371. sentence[length - 9] = '\0';
  372. /* Remove checksum, if there is one */
  373. if ('*' == sentence[length - 12]) {
  374. sentence[length - 12] = '\0';
  375. }
  376. return sentence;
  377. }
  378. /**
  379. * Splits a string by comma.
  380. *
  381. * string is the string to split, will be manipulated. Needs to be
  382. * null-terminated.
  383. * values is a char pointer array that will be filled with pointers to the
  384. * splitted values in the string.
  385. * max_values is the maximum number of values to be parsed.
  386. *
  387. * Returns the number of values found in string.
  388. */
  389. static int _split_string_by_comma(char *string, char **values, int max_values)
  390. {
  391. int i = 0;
  392. values[i++] = string;
  393. while (i < max_values && NULL != (string = strchr(string, ','))) {
  394. *string = '\0';
  395. values[i++] = ++string;
  396. }
  397. return i;
  398. }
  399. nmea_type nmea_get_type(const char *sentence)
  400. {
  401. if (strncmp(sentence + 3, "RMC", 3) == 0)
  402. {
  403. return NMEA_RMC;
  404. }
  405. else if (strncmp(sentence + 3, "GGA", 3) == 0)
  406. {
  407. return NMEA_GGA;
  408. }
  409. else if (strncmp(sentence + 3, "GSA", 3) == 0)
  410. {
  411. return NMEA_GSA;
  412. }
  413. else if (strncmp(sentence + 3, "GSV", 3) == 0)
  414. {
  415. return NMEA_GSV;
  416. }
  417. else if (strncmp(sentence + 3, "TXT", 3) == 0)
  418. {
  419. return NMEA_TXT;
  420. }
  421. else if (strncmp(sentence + 3, "VTG", 3) == 0)
  422. {
  423. return NMEA_VTG;
  424. }
  425. return NMEA_UNKNOWN;
  426. }
  427. /**
  428. * Check if a value is not NULL and not empty.
  429. *
  430. * Returns 0 if set, otherwise -1.
  431. */
  432. static int _is_value_set(const char *value)
  433. {
  434. if (NULL == value || '\0' == *value) {
  435. return -1;
  436. }
  437. return 0;
  438. }
  439. int nmea_position_parse(char *s, struct nmea_position *pos)
  440. {
  441. char *cursor=NULL;
  442. pos->degrees = 0;
  443. pos->minutes = 0;
  444. if (s == NULL || *s == '\0') {
  445. return -1;
  446. }
  447. /* decimal minutes */
  448. if (NULL == (cursor = strchr(s, '.'))) {
  449. return -1;
  450. }
  451. /* minutes starts 2 digits before dot */
  452. cursor -= 2;
  453. pos->minutes = atof(cursor);
  454. *cursor = '\0';
  455. /* integer degrees */
  456. cursor = s;
  457. pos->degrees = atoi(cursor);
  458. return 0;
  459. }
  460. nmea_cardinal_t nmea_cardinal_direction_parse(char *s)
  461. {
  462. if (NULL == s || '\0'== *s) {
  463. return NMEA_CARDINAL_DIR_UNKNOWN;
  464. }
  465. switch (*s) {
  466. case NMEA_CARDINAL_DIR_NORTH:
  467. return NMEA_CARDINAL_DIR_NORTH;
  468. case NMEA_CARDINAL_DIR_EAST:
  469. return NMEA_CARDINAL_DIR_EAST;
  470. case NMEA_CARDINAL_DIR_SOUTH:
  471. return NMEA_CARDINAL_DIR_SOUTH;
  472. case NMEA_CARDINAL_DIR_WEST:
  473. return NMEA_CARDINAL_DIR_WEST;
  474. default:
  475. break;
  476. }
  477. return NMEA_CARDINAL_DIR_UNKNOWN;
  478. }
  479. int nmea_validate_parse(char *s)
  480. {
  481. if (NULL == s || '\0'== *s) {
  482. return 0;
  483. }
  484. return (*s == 'A');
  485. }
  486. int nmea_time_parse(char *s, struct tm *time)
  487. {
  488. //char *rv;
  489. memset(time, 0, sizeof (struct tm));
  490. if (s == NULL || *s == '\0') {
  491. return -1;
  492. }
  493. strptime(s, NMEA_TIME_FORMAT, time);
  494. // if (NULL == rv || (int) (rv - s) != NMEA_TIME_FORMAT_LEN) {
  495. // return -1;
  496. // }
  497. return 0;
  498. }
  499. int nmea_date_parse(char *s, struct tm *time)
  500. {
  501. //char *rv;
  502. // Assume it has been already cleared
  503. memset(time, 0, sizeof (struct tm));
  504. if (s == NULL || *s == '\0') {
  505. return -1;
  506. }
  507. strptime(s, NMEA_DATE_FORMAT, time);
  508. // if (NULL == rv || (int) (rv - s) != NMEA_DATE_FORMAT_LEN) {
  509. // return -1;
  510. // }
  511. return 0;
  512. }
  513. int nmea_parse_rmc(struct nmea_s *nmea, char *sentence)
  514. {
  515. unsigned int n_vals=0, val_index=0;
  516. char *value=NULL;
  517. char *values[255]={NULL};
  518. struct nmea_gprmc_s *data = NULL;
  519. /* Split the sentence into values */
  520. n_vals = _split_string_by_comma(sentence, values, ARRAY_LENGTH(values));
  521. if (0 == n_vals)
  522. {
  523. return -1;
  524. }
  525. data = malloc(sizeof(struct nmea_gprmc_s));
  526. if (data == NULL)
  527. {
  528. nmea_dbg_log("rmc nmea data malloc error. \r\n");
  529. return -1;
  530. }
  531. memset(data, 0, sizeof(struct nmea_gprmc_s));
  532. for (val_index = 0; val_index < n_vals; val_index++)
  533. {
  534. value = values[val_index];
  535. if (-1 == _is_value_set(value))
  536. {
  537. continue;
  538. }
  539. switch (val_index)
  540. {
  541. case NMEA_GPRMC_TIME:
  542. /* Parse time */
  543. if (-1 == nmea_time_parse(value, &data->time))
  544. {
  545. nmea_dbg_log("nmea_time_parse error. \r\n");
  546. goto _error;
  547. }
  548. break;
  549. case NMEA_GPRMC_STATUS:
  550. data->valid = nmea_validate_parse(value);
  551. break;
  552. case NMEA_GPRMC_LATITUDE:
  553. /* Parse latitude */
  554. if (-1 == nmea_position_parse(value, &data->latitude))
  555. {
  556. nmea_dbg_log("nmea_position_parse error. \r\n");
  557. goto _error;
  558. }
  559. break;
  560. case NMEA_GPRMC_LATITUDE_CARDINAL:
  561. /* Parse cardinal direction */
  562. data->latitude.cardinal = nmea_cardinal_direction_parse(value);
  563. if (NMEA_CARDINAL_DIR_UNKNOWN == data->latitude.cardinal)
  564. {
  565. nmea_dbg_log("nmea_cardinal_direction_parse error. \r\n");
  566. goto _error;
  567. }
  568. break;
  569. case NMEA_GPRMC_LONGITUDE:
  570. /* Parse longitude */
  571. if (-1 == nmea_position_parse(value, &data->longitude))
  572. {
  573. nmea_dbg_log("nmea_position_parse error. \r\n");
  574. goto _error;
  575. }
  576. break;
  577. case NMEA_GPRMC_LONGITUDE_CARDINAL:
  578. /* Parse cardinal direction */
  579. data->longitude.cardinal = nmea_cardinal_direction_parse(value);
  580. if (NMEA_CARDINAL_DIR_UNKNOWN == data->longitude.cardinal)
  581. {
  582. nmea_dbg_log("nmea_cardinal_direction_parse error. \r\n");
  583. goto _error;
  584. }
  585. break;
  586. case NMEA_GPRMC_DATE:
  587. /* Parse date */
  588. if (-1 == nmea_date_parse(value, &data->time))
  589. {
  590. nmea_dbg_log("nmea_date_parse error. \r\n");
  591. goto _error;
  592. }
  593. break;
  594. case NMEA_GPRMC_COURSE:
  595. data->course = atof(value);
  596. break;
  597. case NMEA_GPRMC_SPEED:
  598. /* Parse ground speed in knots */
  599. data->speed = atof(value);
  600. break;
  601. default:
  602. break;
  603. }
  604. }
  605. nmea->data = data;
  606. return 0;
  607. _error:
  608. if (data)
  609. {
  610. free(data);
  611. data = NULL;
  612. }
  613. return -1;
  614. }
  615. int nmea_parse_gsv(struct nmea_s *nmea, char *sentence)
  616. {
  617. unsigned int n_vals=0, val_index=0;
  618. char *value=NULL;
  619. char *values[255]={NULL};
  620. struct nmea_gpgsv_s *data = NULL;
  621. /* Split the sentence into values */
  622. n_vals = _split_string_by_comma(sentence, values, ARRAY_LENGTH(values));
  623. if (0 == n_vals)
  624. {
  625. return -1;
  626. }
  627. data = malloc(sizeof(struct nmea_gpgsv_s));
  628. if (data == NULL)
  629. {
  630. nmea_dbg_log("nmea data malloc error. \r\n");
  631. return -1;
  632. }
  633. memset(data, 0, sizeof(struct nmea_gpgsv_s));
  634. data->sig_id = 0;
  635. data->cur_sats = (n_vals-3)/4;
  636. for (val_index = 0; val_index < n_vals; val_index++)
  637. {
  638. value = values[val_index];
  639. if (-1 == _is_value_set(value))
  640. {
  641. continue;
  642. }
  643. switch (val_index)
  644. {
  645. case NMEA_GPGSV_TOTAL_MSGS:
  646. data->total_msgs = atoi(value);
  647. break;
  648. case NMEA_GPGSV_MSG_NR:
  649. data->msg_nr = atoi(value);
  650. break;
  651. case NMEA_GPGSV_SATS:
  652. data->total_sats = atoi(value);
  653. break;
  654. case NMEA_GPGSV_SAT_INFO_NR1:
  655. data->sats[0].nr = atoi(value);
  656. break;
  657. case NMEA_GPGSV_SAT_INFO_ELEV1:
  658. data->sats[0].elevation = atoi(value);
  659. break;
  660. case NMEA_GPGSV_SAT_INFO_AZIMUTH1:
  661. data->sats[0].azimuth = atoi(value);
  662. break;
  663. case NMEA_GPGSV_SAT_INFO_SNR1:
  664. data->sats[0].snr = atoi(value);
  665. break;
  666. case NMEA_GPGSV_SAT_INFO_NR2:
  667. data->sats[1].nr = atoi(value);
  668. break;
  669. case NMEA_GPGSV_SAT_INFO_ELEV2:
  670. data->sats[1].elevation = atoi(value);
  671. break;
  672. case NMEA_GPGSV_SAT_INFO_AZIMUTH2:
  673. data->sats[1].azimuth = atoi(value);
  674. break;
  675. case NMEA_GPGSV_SAT_INFO_SNR2:
  676. data->sats[1].snr = atoi(value);
  677. break;
  678. case NMEA_GPGSV_SAT_INFO_NR3:
  679. data->sats[2].nr = atoi(value);
  680. break;
  681. case NMEA_GPGSV_SAT_INFO_ELEV3:
  682. data->sats[2].elevation = atoi(value);
  683. break;
  684. case NMEA_GPGSV_SAT_INFO_AZIMUTH3:
  685. data->sats[2].azimuth = atoi(value);
  686. break;
  687. case NMEA_GPGSV_SAT_INFO_SNR3:
  688. data->sats[2].snr = atoi(value);
  689. break;
  690. case NMEA_GPGSV_SAT_INFO_NR4:
  691. data->sats[3].nr = atoi(value);
  692. break;
  693. case NMEA_GPGSV_SAT_INFO_ELEV4:
  694. data->sats[3].elevation = atoi(value);
  695. break;
  696. case NMEA_GPGSV_SAT_INFO_AZIMUTH4:
  697. data->sats[3].azimuth = atoi(value);
  698. break;
  699. case NMEA_GPGSV_SAT_INFO_SNR4:
  700. data->sats[3].snr = atoi(value);
  701. break;
  702. case NMEA_GPGSV_SAT_INFO_SIGID:
  703. if(nmea->sat_type == SAT_GPS)
  704. {
  705. data->sig_id = atoi(value);
  706. }
  707. break;
  708. default:
  709. break;
  710. }
  711. }
  712. nmea->data = data;
  713. return 0;
  714. }
  715. int nmea_parse_gga(struct nmea_s *nmea, char *sentence)
  716. {
  717. unsigned int n_vals=0, val_index=0;
  718. char *value=NULL;
  719. char *values[255]={NULL};
  720. struct nmea_gpgga_s *data = NULL;
  721. /* Split the sentence into values */
  722. n_vals = _split_string_by_comma(sentence, values, ARRAY_LENGTH(values));
  723. if (0 == n_vals)
  724. {
  725. return -1;
  726. }
  727. data = malloc(sizeof(struct nmea_gpgga_s));
  728. if (data == NULL)
  729. {
  730. nmea_dbg_log("gga nmea data malloc error. \r\n");
  731. return -1;
  732. }
  733. memset(data, 0, sizeof(struct nmea_gpgga_s));
  734. for (val_index = 0; val_index < n_vals; val_index++)
  735. {
  736. value = values[val_index];
  737. if (-1 == _is_value_set(value))
  738. {
  739. continue;
  740. }
  741. switch (val_index)
  742. {
  743. case NMEA_GPGGA_UTC:
  744. data->time = atof(value);
  745. break;
  746. case NMEA_GPGGA_LATITUDE:
  747. if (-1 == nmea_position_parse(value, &data->latitude))
  748. {
  749. goto _error;
  750. }
  751. break;
  752. case NMEA_GPGGA_LATITUDE_CARDINAL:
  753. data->latitude.cardinal = nmea_cardinal_direction_parse(value);
  754. if (NMEA_CARDINAL_DIR_UNKNOWN == data->latitude.cardinal)
  755. {
  756. goto _error;
  757. }
  758. break;
  759. case NMEA_GPGGA_LONGITUDE:
  760. if (-1 == nmea_position_parse(value, &data->longitude))
  761. {
  762. goto _error;
  763. }
  764. break;
  765. case NMEA_GPGGA_LONGITUDE_CARDINAL:
  766. data->longitude.cardinal = nmea_cardinal_direction_parse(value);
  767. if (NMEA_CARDINAL_DIR_UNKNOWN == data->longitude.cardinal)
  768. {
  769. goto _error;
  770. }
  771. break;
  772. case NMEA_GPGGA_QUALITY:
  773. data->quality = atoi(value);
  774. break;
  775. case NMEA_GPGGA_SATELLITES_TRACKED:
  776. data->satellites_tracked = atoi(value);
  777. break;
  778. case NMEA_GPGGA_HDOP:
  779. data->hdop = atof(value);
  780. break;
  781. case NMEA_GPGGA_ALTITUDE:
  782. data->altitude = atof(value);
  783. break;
  784. default:
  785. break;
  786. }
  787. }
  788. nmea->data = data;
  789. return 0;
  790. _error:
  791. if (data)
  792. {
  793. free(data);
  794. data = NULL;
  795. }
  796. return -1;
  797. }
  798. int nmea_parse_gsa(struct nmea_s *nmea, char *sentence)
  799. {
  800. unsigned int n_vals=0, val_index=0;
  801. char *value=NULL;
  802. char *values[255]={NULL};
  803. struct nmea_gpgsa_s *data = NULL;
  804. /* Split the sentence into values */
  805. n_vals = _split_string_by_comma(sentence, values, ARRAY_LENGTH(values));
  806. if (0 == n_vals)
  807. {
  808. return -1;
  809. }
  810. data = malloc(sizeof(struct nmea_gpgsa_s));
  811. if (data == NULL)
  812. {
  813. nmea_dbg_log("gsa nmea data malloc error. \r\n");
  814. return -1;
  815. }
  816. memset(data, 0, sizeof(struct nmea_gpgsa_s));
  817. for (val_index = 0; val_index < n_vals; val_index++)
  818. {
  819. value = values[val_index];
  820. if (-1 == _is_value_set(value))
  821. {
  822. continue;
  823. }
  824. switch (val_index)
  825. {
  826. case NMEA_GPGSA_MODE:
  827. data->mode = *value;
  828. break;
  829. case NMEA_GPGSA_NAVMODE:
  830. data->navmode = atoi(value);
  831. break;
  832. case NMEA_GPGSA_PDOP:
  833. data->pdop = atof(value);
  834. break;
  835. case NMEA_GPGSA_HDOP:
  836. data->hdop = atof(value);
  837. break;
  838. case NMEA_GPGSA_VDOP:
  839. data->vdop = atof(value);
  840. break;
  841. case NMEA_GPGSA_systemID:
  842. data->systemid = atoi(value);
  843. default:
  844. break;
  845. }
  846. }
  847. nmea->data = data;
  848. return 0;
  849. }
  850. satellite_type nmea_satellite_check(char *sentence)
  851. {
  852. if (strncmp(sentence + 1, "GP", 2) == 0)
  853. {
  854. return SAT_GPS;
  855. }
  856. else if ((strncmp(sentence + 1, "GB", 2) == 0)||(strncmp(sentence + 1, "BD", 2) == 0))
  857. {
  858. memcpy(sentence+1,"PQ",2);
  859. return SAT_BDS;
  860. }
  861. else if (strncmp(sentence + 1, "GN", 2) == 0)
  862. {
  863. return SAT_MULSYS;
  864. }
  865. else if (strncmp(sentence + 1, "GA", 2) == 0)
  866. {
  867. return SAT_GALILEO;
  868. }
  869. else if (strncmp(sentence + 1, "GL", 2) == 0)
  870. {
  871. return SAT_GLONASS;
  872. }
  873. return SAT_UNKNOWN;
  874. }
  875. static int conv_num(const char **buf, int *dest, int llim, int ulim)
  876. {
  877. int result = 0;
  878. /* The limit also determines the number of valid digits. */
  879. int rulim = ulim;
  880. if (**buf < '0' || **buf > '9')
  881. return (0);
  882. do {
  883. result *= 10;
  884. result += *(*buf)++ - '0';
  885. rulim /= 10;
  886. } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
  887. if (result < llim || result > ulim)
  888. return (0);
  889. *dest = result;
  890. return (1);
  891. }
  892. //window上自己实现strptime函数,linux已经提供strptime
  893. //strptime函数windows平台上实现
  894. char *strptime(const char *buf, const char *fmt, struct tm *tm)
  895. {
  896. char c=0;
  897. const char *bp=NULL;
  898. size_t len = 0;
  899. int alt_format=0, i=0, split_year = 0;
  900. bp = buf;
  901. while ((c = *fmt) != '\0') {
  902. /* Clear `alternate' modifier prior to new conversion. */
  903. alt_format = 0;
  904. /* Eat up white-space. */
  905. if (ql_isspace(c)) {
  906. while (ql_isspace(*bp))
  907. bp++;
  908. fmt++;
  909. continue;
  910. }
  911. if ((c = *fmt++) != '%')
  912. goto literal;
  913. again: switch (c = *fmt++) {
  914. case '%': /* "%%" is converted to "%". */
  915. literal:
  916. if (c != *bp++)
  917. return (0);
  918. break;
  919. /*
  920. * "Alternative" modifiers. Just set the appropriate flag
  921. * and start over again.
  922. */
  923. case 'E': /* "%E?" alternative conversion modifier. */
  924. LEGAL_ALT(0);
  925. alt_format |= ALT_E;
  926. goto again;
  927. case 'O': /* "%O?" alternative conversion modifier. */
  928. LEGAL_ALT(0);
  929. alt_format |= ALT_O;
  930. goto again;
  931. /*
  932. * "Complex" conversion rules, implemented through recursion.
  933. */
  934. case 'c': /* Date and time, using the locale's format. */
  935. LEGAL_ALT(ALT_E);
  936. if (!(bp = strptime(bp, "%x %X", tm)))
  937. return (0);
  938. break;
  939. case 'D': /* The date as "%m/%d/%y". */
  940. LEGAL_ALT(0);
  941. if (!(bp = strptime(bp, "%m/%d/%y", tm)))
  942. return (0);
  943. break;
  944. case 'R': /* The time as "%H:%M". */
  945. LEGAL_ALT(0);
  946. if (!(bp = strptime(bp, "%H:%M", tm)))
  947. return (0);
  948. break;
  949. case 'r': /* The time in 12-hour clock representation. */
  950. LEGAL_ALT(0);
  951. if (!(bp = strptime(bp, "%I:%M:%S %p", tm)))
  952. return (0);
  953. break;
  954. case 'T': /* The time as "%H:%M:%S". */
  955. LEGAL_ALT(0);
  956. if (!(bp = strptime(bp, "%H:%M:%S", tm)))
  957. return (0);
  958. break;
  959. case 'X': /* The time, using the locale's format. */
  960. LEGAL_ALT(ALT_E);
  961. if (!(bp = strptime(bp, "%H:%M:%S", tm)))
  962. return (0);
  963. break;
  964. case 'x': /* The date, using the locale's format. */
  965. LEGAL_ALT(ALT_E);
  966. if (!(bp = strptime(bp, "%m/%d/%y", tm)))
  967. return (0);
  968. break;
  969. /*
  970. * "Elementary" conversion rules.
  971. */
  972. case 'A': /* The day of week, using the locale's form. */
  973. case 'a':
  974. LEGAL_ALT(0);
  975. for (i = 0; i < 7; i++) {
  976. /* Full name. */
  977. len = strlen(day[i]);
  978. if (strncmp(day[i], bp, len) == 0)
  979. break;
  980. /* Abbreviated name. */
  981. len = strlen(abday[i]);
  982. if (strncmp(abday[i], bp, len) == 0)
  983. break;
  984. }
  985. /* Nothing matched. */
  986. if (i == 7)
  987. return (0);
  988. tm->tm_wday = i;
  989. bp += len;
  990. break;
  991. case 'B': /* The month, using the locale's form. */
  992. case 'b':
  993. case 'h':
  994. LEGAL_ALT(0);
  995. for (i = 0; i < 12; i++) {
  996. /* Full name. */
  997. len = strlen(mon[i]);
  998. if (strncmp(mon[i], bp, len) == 0)
  999. break;
  1000. /* Abbreviated name. */
  1001. len = strlen(abmon[i]);
  1002. if (strncmp(abmon[i], bp, len) == 0)
  1003. break;
  1004. }
  1005. /* Nothing matched. */
  1006. if (i == 12)
  1007. return (0);
  1008. tm->tm_mon = i;
  1009. bp += len;
  1010. break;
  1011. case 'C': /* The century number. */
  1012. LEGAL_ALT(ALT_E);
  1013. if (!(conv_num(&bp, &i, 0, 99)))
  1014. return (0);
  1015. if (split_year) {
  1016. tm->tm_year = (tm->tm_year % 100) + (i * 100);
  1017. } else {
  1018. tm->tm_year = i * 100;
  1019. split_year = 1;
  1020. }
  1021. break;
  1022. case 'd': /* The day of month. */
  1023. case 'e':
  1024. LEGAL_ALT(ALT_O);
  1025. if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
  1026. return (0);
  1027. break;
  1028. case 'k': /* The hour (24-hour clock representation). */
  1029. LEGAL_ALT(0);
  1030. /* FALLTHROUGH */
  1031. case 'H':
  1032. LEGAL_ALT(ALT_O);
  1033. if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
  1034. return (0);
  1035. break;
  1036. case 'l': /* The hour (12-hour clock representation). */
  1037. LEGAL_ALT(0);
  1038. /* FALLTHROUGH */
  1039. case 'I':
  1040. LEGAL_ALT(ALT_O);
  1041. if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
  1042. return (0);
  1043. if (tm->tm_hour == 12)
  1044. tm->tm_hour = 0;
  1045. break;
  1046. case 'j': /* The day of year. */
  1047. LEGAL_ALT(0);
  1048. if (!(conv_num(&bp, &i, 1, 366)))
  1049. return (0);
  1050. tm->tm_yday = i - 1;
  1051. break;
  1052. case 'M': /* The minute. */
  1053. LEGAL_ALT(ALT_O);
  1054. if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
  1055. return (0);
  1056. break;
  1057. case 'm': /* The month. */
  1058. LEGAL_ALT(ALT_O);
  1059. if (!(conv_num(&bp, &i, 1, 12)))
  1060. return (0);
  1061. tm->tm_mon = i - 1;
  1062. break;
  1063. case 'p': /* The locale's equivalent of AM/PM. */
  1064. LEGAL_ALT(0);
  1065. /* AM? */
  1066. if (strcmp(am_pm[0], bp) == 0) {
  1067. if (tm->tm_hour > 11)
  1068. return (0);
  1069. bp += strlen(am_pm[0]);
  1070. break;
  1071. }
  1072. /* PM? */
  1073. else if (strcmp(am_pm[1], bp) == 0) {
  1074. if (tm->tm_hour > 11)
  1075. return (0);
  1076. tm->tm_hour += 12;
  1077. bp += strlen(am_pm[1]);
  1078. break;
  1079. }
  1080. /* Nothing matched. */
  1081. return (0);
  1082. case 'S': /* The seconds. */
  1083. LEGAL_ALT(ALT_O);
  1084. if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
  1085. return (0);
  1086. break;
  1087. case 'U': /* The week of year, beginning on sunday. */
  1088. case 'W': /* The week of year, beginning on monday. */
  1089. LEGAL_ALT(ALT_O);
  1090. /*
  1091. * XXX This is bogus, as we can not assume any valid
  1092. * information present in the tm structure at this
  1093. * point to calculate a real value, so just check the
  1094. * range for now.
  1095. */
  1096. if (!(conv_num(&bp, &i, 0, 53)))
  1097. return (0);
  1098. break;
  1099. case 'w': /* The day of week, beginning on sunday. */
  1100. LEGAL_ALT(ALT_O);
  1101. if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
  1102. return (0);
  1103. break;
  1104. case 'Y': /* The year. */
  1105. LEGAL_ALT(ALT_E);
  1106. if (!(conv_num(&bp, &i, 0, 9999)))
  1107. return (0);
  1108. tm->tm_year = i - TM_YEAR_BASE;
  1109. break;
  1110. case 'y': /* The year within 100 years of the epoch. */
  1111. LEGAL_ALT(ALT_E | ALT_O);
  1112. if (!(conv_num(&bp, &tm->tm_year, 0, 99)))
  1113. return (0);
  1114. // if (split_year) {
  1115. // tm->tm_year = ((tm->tm_year / 100) * 100) + i;
  1116. // break;
  1117. // }
  1118. // split_year = 1;
  1119. // if (i <= 68)
  1120. // tm->tm_year = i + 2000 - TM_YEAR_BASE;
  1121. // else
  1122. // tm->tm_year = i + 1900 - TM_YEAR_BASE;
  1123. // break;
  1124. /*
  1125. * Miscellaneous conversions.
  1126. */
  1127. case 'n': /* Any kind of white-space. */
  1128. case 't':
  1129. LEGAL_ALT(0);
  1130. while (ql_isspace(*bp))
  1131. bp++;
  1132. break;
  1133. default: /* Unknown/unsupported conversion. */
  1134. return (0);
  1135. }
  1136. }
  1137. /* LINTED functional specification */
  1138. return ((char *)bp);
  1139. }
  1140. int nmea_value_update(struct nmea_s *nmea, ql_gnss_data_t *gps_data)
  1141. {
  1142. int i=0;
  1143. struct nmea_gprmc_s *rmc = NULL;
  1144. struct nmea_gpgsv_s *gsv = NULL;
  1145. struct nmea_gpgga_s *gga = NULL;
  1146. struct nmea_gpgsa_s *gsa = NULL;
  1147. if(nmea == NULL || gps_data == NULL)
  1148. {
  1149. nmea_dbg_log("param invalid. \r\n");
  1150. return -1;
  1151. }
  1152. if(nmea->type == NMEA_UNKNOWN)
  1153. {
  1154. nmea_dbg_log("gps nmea type is unknown! \r\n");
  1155. return -1;
  1156. }
  1157. switch(nmea->type)
  1158. {
  1159. case NMEA_RMC:
  1160. rmc = (struct nmea_gprmc_s*)nmea->data;
  1161. if(rmc)
  1162. {
  1163. gps_data->valid = rmc->valid;
  1164. if(gps_data->valid==1)
  1165. {
  1166. //nmea_dbg_log("GNSS_FIX \r\n");
  1167. }
  1168. else
  1169. {
  1170. //nmea_dbg_log("GNSS_POSITIONING \r\n");
  1171. }
  1172. gps_data->longitude = rmc->longitude.degrees + (rmc->longitude.minutes / 60);
  1173. gps_data->longitude_cardinal = rmc->longitude.cardinal;
  1174. gps_data->latitude = rmc->latitude.degrees + (rmc->latitude.minutes / 60);
  1175. gps_data->latitude_cardinal = rmc->latitude.cardinal;
  1176. gps_data->heading = rmc->course;
  1177. gps_data->gps_speed = rmc->speed * KNOTS_CONVERSION_FACTOR;
  1178. gps_data->time.tm_year = rmc->time.tm_year;
  1179. gps_data->time.tm_mon = rmc->time.tm_mon+1;
  1180. gps_data->time.tm_mday = rmc->time.tm_mday;
  1181. gps_data->time.tm_hour = rmc->time.tm_hour;
  1182. gps_data->time.tm_min = rmc->time.tm_min;
  1183. gps_data->time.tm_sec = rmc->time.tm_sec;
  1184. }
  1185. break;
  1186. case NMEA_GSV:
  1187. gsv = (struct nmea_gpgsv_s*)nmea->data;
  1188. if(gsv)
  1189. {
  1190. unsigned int cnr_value = 0;
  1191. static unsigned int total_cnr = 0;
  1192. static unsigned int snr_num = 0;
  1193. static unsigned int max_cnr = 0;
  1194. static unsigned int min_cnr = 0;
  1195. if((prev_ms_gsv < ql_rtos_get_system_tick()) && ((tick_overflow == FALSE) || (((MAX_UINT32 - ql_rtos_get_system_tick())>10))))
  1196. {
  1197. gps_data->avg_cnr = total_cnr / snr_num;
  1198. gps_data->max_cnr=max_cnr;
  1199. gps_data->min_cnr=min_cnr;
  1200. gps_data->cnrs_index=snr_num;
  1201. total_cnr=0;
  1202. snr_num=0;
  1203. max_cnr=0;
  1204. min_cnr=0;
  1205. }
  1206. for(i = 0; i < gsv->cur_sats; i++)
  1207. {
  1208. cnr_value = gsv->sats[i].snr;
  1209. gps_data->cnrs[snr_num]=cnr_value;
  1210. max_cnr = jmax(max_cnr, cnr_value);
  1211. if(cnr_value > 0)
  1212. {
  1213. min_cnr = min_cnr > 0 ? (jmin(min_cnr, cnr_value)) : (cnr_value);
  1214. }
  1215. total_cnr += cnr_value;
  1216. if(snr_num<(QL_GSV_MAX_SATS-1))
  1217. {
  1218. snr_num ++;
  1219. }
  1220. }
  1221. prev_ms_gsv=ql_rtos_get_system_tick()+10;
  1222. if(prev_ms_gsv < 10)
  1223. {
  1224. tick_overflow = TRUE;
  1225. }
  1226. else
  1227. {
  1228. tick_overflow = FALSE;
  1229. }
  1230. }
  1231. break;
  1232. case NMEA_GGA:
  1233. gga = (struct nmea_gpgga_s*)nmea->data;
  1234. if(gga != NULL)
  1235. {
  1236. gps_data->UTC = (unsigned int)(gga->time);
  1237. gps_data->altitude = gga->altitude;
  1238. gps_data->satellites_num=gga->satellites_tracked;
  1239. }
  1240. break;
  1241. case NMEA_GSA:
  1242. gsa = (struct nmea_gpgsa_s*)nmea->data;
  1243. if(gsa != NULL)
  1244. {
  1245. gps_data->navmode = gsa->navmode;
  1246. gps_data->hdop = gsa->hdop;
  1247. gps_data->pdop = gsa->pdop;
  1248. }
  1249. break;
  1250. default:
  1251. break;
  1252. }
  1253. return 0;
  1254. }
  1255. struct nmea_s* nmea_parse(char *sentence, int length, int check_checksum)
  1256. {
  1257. int ret = -1;
  1258. nmea_type type = 0;
  1259. char *val_string = NULL;
  1260. struct nmea_s * nmea = NULL;
  1261. satellite_type sat_type = 0;
  1262. /* Validate sentence string */
  1263. if (-1 == nmea_validate(sentence, length, check_checksum))
  1264. {
  1265. nmea_dbg_log("nmea validate false! \r\n");
  1266. return NULL;
  1267. }
  1268. type = nmea_get_type(sentence);
  1269. if (NMEA_UNKNOWN == type)
  1270. {
  1271. nmea_dbg_log("nmea get type unknown! \r\n");
  1272. return NULL;
  1273. }
  1274. sat_type = nmea_satellite_check(sentence);
  1275. nmea = malloc(sizeof(struct nmea_s));
  1276. if(nmea == NULL)
  1277. {
  1278. nmea_dbg_log("nmea malloc error. \r\n");
  1279. return NULL;
  1280. }
  1281. memset(nmea, 0, sizeof(struct nmea_s));
  1282. nmea->type = type;
  1283. nmea->sat_type = sat_type;
  1284. /* Crop sentence from type word and checksum */
  1285. val_string = _crop_sentence(sentence, length);
  1286. if (NULL == val_string) {
  1287. if(nmea)
  1288. {
  1289. if(nmea->data)
  1290. {
  1291. free(nmea->data);
  1292. }
  1293. free(nmea);
  1294. nmea = NULL;
  1295. }
  1296. nmea_dbg_log("_crop_sentence failed! \r\n");
  1297. return NULL;
  1298. }
  1299. switch(type)
  1300. {
  1301. case NMEA_GGA:
  1302. {
  1303. ret = nmea_parse_gga(nmea, val_string);
  1304. if(ret)
  1305. {
  1306. nmea_dbg_log("nmea_parse_gga failed. \r\n");
  1307. goto _error;
  1308. }
  1309. }
  1310. break;
  1311. case NMEA_GSA:
  1312. {
  1313. ret = nmea_parse_gsa(nmea, val_string);
  1314. if(ret)
  1315. {
  1316. nmea_dbg_log("nmea_parse_gsa failed. \r\n");
  1317. goto _error;
  1318. }
  1319. }
  1320. break;
  1321. case NMEA_GSV:
  1322. {
  1323. ret = nmea_parse_gsv(nmea, val_string);
  1324. if(ret)
  1325. {
  1326. nmea_dbg_log("nmea_parse_gsv failed. \r\n");
  1327. goto _error;
  1328. }
  1329. }
  1330. break;
  1331. case NMEA_RMC:
  1332. {
  1333. ret = nmea_parse_rmc(nmea, val_string);
  1334. if(ret)
  1335. {
  1336. nmea_dbg_log("nmea_parse_rmc failed. \r\n");
  1337. goto _error;
  1338. }
  1339. }
  1340. break;
  1341. #if 0
  1342. case NMEA_TXT:
  1343. {
  1344. ret = nmea_parse_txt(nmea, val_string);
  1345. if(ret)
  1346. {
  1347. nmea_dbg_log("nmea_parse_txt failed. \r\n");
  1348. goto _error;
  1349. }
  1350. }
  1351. #endif
  1352. default:
  1353. break;
  1354. }
  1355. return nmea;
  1356. _error:
  1357. if(nmea)
  1358. {
  1359. if(nmea->data)
  1360. {
  1361. free(nmea->data);
  1362. }
  1363. free(nmea);
  1364. nmea = NULL;
  1365. }
  1366. return NULL;
  1367. }
  1368. int ql_get_gnss_info(ql_gnss_data_t *data)
  1369. {
  1370. if(data == NULL)
  1371. {
  1372. return -1;
  1373. }
  1374. memcpy(data, &g_gps_data, sizeof(g_gps_data));
  1375. return 0;
  1376. }