blob: dff45999264e3c6e96ff340810cdeeeb386b3283 [file] [log] [blame]
b.liuf9fbfa12024-06-14 15:53:59 +08001/*
2* gnss_hd8122.c
3*
4* HD8122 GNSS source.
5*
6*/
7/******************************************************************************
8
9 EDIT HISTORY FOR FILE
10
11 WHEN WHO WHAT,WHERE,WHY
12-------- -------- -------------------------------------------------------
132024/6/14 LiuBin Initial version
14
15******************************************************************************/
16#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19#include <errno.h>
20#include <fcntl.h>
21
22#include "mbtk_log.h"
23#include "mbtk_type.h"
24#include "mbtk_gpio.h"
25#include "gnss_utils.h"
26#include "gnss_hd8122.h"
27
28#define UART_BITRATE_NMEA_DEF_FW 115200 // Default bitrate.
29#define GNSS_POWER_GPIO 43
b.liu5f950c52024-06-15 20:13:12 +080030#define GNSS_SET_TIMEOUT 3000 // 3s
31#define GNSS_PACK_BUFF_SIZE 1024
b.liud0ba7152024-06-19 14:47:21 +080032#define GNSS_MSG_NUM_MAX 30
b.liu5f950c52024-06-15 20:13:12 +080033
b.liuf9fbfa12024-06-14 15:53:59 +080034
35static pthread_cond_t read_cond;
36static pthread_mutex_t read_mutex;
b.liud0ba7152024-06-19 14:47:21 +080037static bool setting_waitting = FALSE;
b.liu5f950c52024-06-15 20:13:12 +080038static bool setting_busy = FALSE;
39static void *gnss_set_rsp_ptr = NULL;
40static gnss_err_enum gnss_set_result = GNSS_ERR_OK;
b.liud0ba7152024-06-19 14:47:21 +080041static hd8122_msg_id_t msg_array[GNSS_MSG_NUM_MAX];
b.liuf9fbfa12024-06-14 15:53:59 +080042
b.liu5f950c52024-06-15 20:13:12 +080043int gnss_write(int fd, const void *data, int data_len);
44
45static uint16 fletcher16(const uint8_t* data, int data_len) {
b.liud0ba7152024-06-19 14:47:21 +080046 uint32_t sum1 = 0;
47 uint32_t sum2 = 0;
b.liu5f950c52024-06-15 20:13:12 +080048 int index;
49
50 for (index = 0; index < data_len; ++index ) {
b.liud0ba7152024-06-19 14:47:21 +080051 sum1 += data[index];
52 sum2 += sum1;
b.liu5f950c52024-06-15 20:13:12 +080053 }
54
b.liud0ba7152024-06-19 14:47:21 +080055 return ((0xFF & sum2) << 8) | (0xFF & sum1);
b.liu5f950c52024-06-15 20:13:12 +080056}
57
58static void gnss_set_timer_cb(int signo)
59{
60 if(setting_busy) {
61 pthread_mutex_lock(&read_mutex);
62 pthread_cond_signal(&read_cond);
63 pthread_mutex_unlock(&read_mutex);
64 gnss_set_result = GNSS_ERR_TIMEOUT;
65 }
66 return;
67}
68
b.liud0ba7152024-06-19 14:47:21 +080069static void msg_init()
70{
71 int i = 0;
72 while(i < ARRAY_SIZE(msg_array)) {
73 msg_array[i].enable = FALSE;
74 i++;
75 }
76}
77
78
79static int msg_insert(uint8 gid, uint8 sid)
80{
81 int i = 0;
82 while(i < ARRAY_SIZE(msg_array)) {
83 if(!msg_array[i].enable)
84 break;
85 i++;
86 }
87
88 if(i == ARRAY_SIZE(msg_array)) {
89 LOGE("Msg full : %d", i);
90 return -1;
91 } else {
92 msg_array[i].enable = TRUE;
93 msg_array[i].gid = gid;
94 msg_array[i].sid = sid;
95 return 0;
96 }
97}
98
99static int msg_find(uint8 gid, uint8 sid)
100{
101 int i = 0;
102 while(i < ARRAY_SIZE(msg_array)) {
103 if(msg_array[i].enable && gid == msg_array[i].gid && sid == msg_array[i].sid)
104 break;
105 i++;
106 }
107
108 if(i == ARRAY_SIZE(msg_array)) {
109 LOGE("No found %d - %d", gid, sid);
110 return -1;
111 } else {
112 return i;
113 }
114}
115
116static int msg_remove(uint8 gid, uint8 sid)
117{
118 int i = msg_find(gid, sid);
119 if(i >= 0) {
120 msg_array[i].enable = FALSE;
121 msg_array[i].gid = 0;
122 msg_array[i].sid = 0;
123 return 0;
124 } else {
125 return -1;
126 }
127}
128
129static int msg_count()
130{
131 int i = 0;
132 int count = 0;
133 while(i < ARRAY_SIZE(msg_array)) {
134 if(msg_array[i].enable)
135 count++;
136 i++;
137 }
138 return count;
139}
b.liu5f950c52024-06-15 20:13:12 +0800140
141static int pack_create(hd8122_id_type_enum id_type, uint8 id, uint16 data_len, const uint8 *data, uint8 *pack, int pack_len)
142{
143 if(pack == NULL || pack_len < HD8122_PACK_LEN_MIN) {
144 return -1;
145 }
146 memset(pack, 0, pack_len);
147 uint8 *data_ptr = pack;
148 data_ptr += uint16_2_byte(HD8122_PACK_HEAD, data_ptr, false);
149 *data_ptr++ = (uint8)id_type;
150 *data_ptr++ = id;
151 data_ptr += uint16_2_byte(data_len, data_ptr, false);
152 if(data_len > 0) {
153 memcpy(data_ptr, data, data_len);
154 data_ptr += data_len;
155 }
156 data_ptr += uint16_2_byte(fletcher16(pack + 2, 4 + data_len), data_ptr, false);
157 return (data_ptr - pack);
158}
159
b.liud0ba7152024-06-19 14:47:21 +0800160// f1 d9 05 01 02 00 06 01 0f 38
161// or
162// f1 d9 05 00 02 00 06 01 0f 38
163static int msg_array_change(const uint8 *pack, int pack_len, hd8122_id_ack_enum *ack_nak)
164{
165 if(pack_len == 0 || pack_len % 10) {
166 LOGE("pack_len(%d) error.", pack_len);
167 return -1;
168 }
169 int count = pack_len / 10;
170 int i = 0;
171 while(i < count) {
172 uint8 *ptr = pack + i * 10;
173 if(ptr[0] != 0xf1 || ptr[1] != 0xd9) {
174 LOGE("Pack head error : %02x %02x", ptr[0], ptr[1]);
175 return -1;
176 }
177
178 if(ptr[2] != 0x05) {
179 LOGE("Type not 0x05 : %02x", ptr[2]);
180 return -1;
181 }
182
183 int index = msg_find(ptr[6], ptr[7]);
184 if(index >= 0) {
185 if(ptr[3] == 0x01) {
186 msg_array[index].ack_nak = HD8122_ID_ACK_ACK;
187 } else if(ptr[3] == 0x00) {
188 msg_array[index].ack_nak = HD8122_ID_ACK_NAK;
189
190 // There is a nak as a failure.
191 *ack_nak = HD8122_ID_ACK_NAK;
192 } else {
193 LOGE("ID not 0x00 or 0x01 : %02x", ptr[3]);
194 return -1;
195 }
196
197 msg_array[index].enable = FALSE;
198 } else {
199 LOGE("Unknown gid - %d, sid - %d", ptr[6], ptr[7]);
200 return -1;
201 }
202 i++;
203 }
204
205 return 0;
206}
207
b.liu5f950c52024-06-15 20:13:12 +0800208static void gnss_cmd_rsp_process(const void *data, int data_len) {
209 const char *ptr = (const char*)data;
210 log_hex("RSP", data, data_len);
b.liu5f950c52024-06-15 20:13:12 +0800211
b.liud0ba7152024-06-19 14:47:21 +0800212 hd8122_id_ack_enum ack_nak = HD8122_ID_ACK_ACK;
213 if(!msg_array_change((const uint8*)data, data_len, &ack_nak)) {
214 if(setting_waitting && msg_count() == 0)
215 {
216 if(ack_nak == HD8122_ID_ACK_ACK) {
217 gnss_set_result = GNSS_ERR_OK;
218 } else {
219 gnss_set_result = GNSS_ERR_UNKNOWN;
220 }
221
222 mbtk_timer_clear();
223
224 pthread_mutex_lock(&read_mutex);
225 pthread_cond_signal(&read_cond);
226 pthread_mutex_unlock(&read_mutex);
227 setting_waitting = FALSE;
228 }
229 } else {
230 LOGW("Unknown rsp data.");
b.liu5f950c52024-06-15 20:13:12 +0800231 }
232}
233
b.liud0ba7152024-06-19 14:47:21 +0800234static gnss_err_enum gnss_8122_reset(int fd, uint8 reset)
b.liu5f950c52024-06-15 20:13:12 +0800235{
236 uint8 buff[GNSS_PACK_BUFF_SIZE];
237 LOGD("RESET");
238 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_SIMPLERST, 1, (uint8*)(&reset), buff, sizeof(buff));
239 if(len <= 0) {
240 LOGE("pack_create() fail.");
241 return GNSS_ERR_ARG;
242 }
243 log_hex("PACK", buff, len);
244 gnss_write(fd, buff, len);
245 return GNSS_ERR_OK;
246}
b.liuf9fbfa12024-06-14 15:53:59 +0800247
b.liud0ba7152024-06-19 14:47:21 +0800248static gnss_err_enum gnss_8122_syscfg(int fd, uint32 mode)
249{
250 uint8 buff[GNSS_PACK_BUFF_SIZE];
251 LOGD("SYSCFG");
252 //uint8 mode_str[4];
253 //uint32_2_byte(mode, mode_str, TRUE);
254 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_NAVSAT, 4, (uint8*)(&mode), buff, sizeof(buff));
255 if(len <= 0) {
256 LOGE("pack_create() fail.");
257 return GNSS_ERR_ARG;
258 }
259 log_hex("PACK", buff, len);
260 gnss_write(fd, buff, len);
261 msg_insert(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_NAVSAT);
262 return GNSS_ERR_OK;
263}
264
265static gnss_err_enum gnss_8122_msgcfg(int fd, uint8 type, uint8 id, uint8 period)
266{
267 uint8 buff[GNSS_PACK_BUFF_SIZE];
268 LOGD("MSGCFG");
269 uint8 data[3];
270 data[0] = type;
271 data[1] = id;
272 data[2] = period;
273 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_MSG, 3, data, buff, sizeof(buff));
274 if(len <= 0) {
275 LOGE("pack_create() fail.");
276 return GNSS_ERR_ARG;
277 }
278 log_hex("PACK", buff, len);
279 gnss_write(fd, buff, len);
280 msg_insert(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_MSG);
281 return GNSS_ERR_OK;
282}
283
284static gnss_err_enum gnss_8122_minel(int fd, float *elev)
285{
286 uint8 buff[GNSS_PACK_BUFF_SIZE];
287 LOGD("ELEV");
288 //uint8 elev_buff[4];
289 //uint32_2_byte((uint32)elev, elev_buff, TRUE);
290 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_ELEV, 8, (uint8*)elev, buff, sizeof(buff));
291 if(len <= 0) {
292 LOGE("pack_create() fail.");
293 return GNSS_ERR_ARG;
294 }
295 log_hex("PACK", buff, len);
296 gnss_write(fd, buff, len);
297 return GNSS_ERR_OK;
298}
299
300static gnss_err_enum gnss_8122_nmeaver(int fd, uint8 ver)
301{
302 uint8 buff[GNSS_PACK_BUFF_SIZE];
303 LOGD("NMEA-VER");
304 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_NMEAVER, 1, (uint8*)(&ver), buff, sizeof(buff));
305 if(len <= 0) {
306 LOGE("pack_create() fail.");
307 return GNSS_ERR_ARG;
308 }
309 log_hex("PACK", buff, len);
310 gnss_write(fd, buff, len);
311 return GNSS_ERR_OK;
312}
313
b.liuf9fbfa12024-06-14 15:53:59 +0800314int gnss_8122_dev_open()
315{
316 return mbtk_gpio_value_set(GNSS_POWER_GPIO, MBTK_GPIO_DIRECT_OUT, 1);
317}
318
319int gnss_8122_dev_close()
320{
321 return mbtk_gpio_value_set(GNSS_POWER_GPIO, MBTK_GPIO_DIRECT_OUT, 0);
322}
323
324int gnss_8122_open(const char *dev)
325{
326 pthread_mutex_init(&read_mutex, NULL);
327 pthread_cond_init(&read_cond, NULL);
328 return gnss_port_open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY, UART_BITRATE_NMEA_DEF_FW, TRUE);
329}
330
331int gnss_8122_close(int fd)
332{
333 pthread_mutex_destroy(&read_mutex);
334 pthread_cond_destroy(&read_cond);
335 return gnss_port_close(fd);
336}
337
338int gnss_8122_fw_dl()
339{
340 return 0;
341}
342
b.liu5f950c52024-06-15 20:13:12 +0800343void gnss_8122_set_cb(const void *data, int data_len)
344{
345 const char *buff = (const char*)data;
b.liud0ba7152024-06-19 14:47:21 +0800346 if(setting_busy) { // Has setting cmd process.
b.liu5f950c52024-06-15 20:13:12 +0800347 gnss_cmd_rsp_process(data, data_len);
348 }
349}
b.liuf9fbfa12024-06-14 15:53:59 +0800350
351gnss_err_enum gnss_8122_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len)
352{
b.liu5f950c52024-06-15 20:13:12 +0800353 if(setting_busy) {
354 return GNSS_ERR_SET_BUSY;
355 } else {
356 bool should_wait_rsp = TRUE;
357 setting_busy = TRUE;
358 gnss_set_rsp_ptr = cmd_rsp;
359 gnss_set_result = GNSS_ERR_OK;
b.liud0ba7152024-06-19 14:47:21 +0800360 msg_init();
b.liu5f950c52024-06-15 20:13:12 +0800361 mbtk_timer_set(gnss_set_timer_cb, GNSS_SET_TIMEOUT);
362
b.liud0ba7152024-06-19 14:47:21 +0800363 if(memcmp(cmd, "$RESET", 6) == 0) { // $RESET,<mode>
364 gnss_reset_type_enum mode = (gnss_reset_type_enum)atoi(cmd + 7);
365 if(mode == GNSS_RESET_TYPE_HOT) {
366 gnss_set_result = gnss_8122_reset(fd, 3);
367 } else if(mode == GNSS_RESET_TYPE_WARM) {
368 gnss_set_result = gnss_8122_reset(fd, 2);
369 } else if(mode == GNSS_RESET_TYPE_COLD) {
370 gnss_set_result = gnss_8122_reset(fd, 1);
371 } else {
372 gnss_set_result = GNSS_ERR_ARG;
373 goto set_fail;
374 }
b.liu5f950c52024-06-15 20:13:12 +0800375 if(gnss_set_result != GNSS_ERR_OK) {
376 goto set_fail;
377 }
378 should_wait_rsp = FALSE;
b.liud0ba7152024-06-19 14:47:21 +0800379 } else if(memcmp(cmd, "$SYSCFG", 7) == 0) { // $SYSCFG,<mode>
380 uint32 mode = 0;
381 mode = (uint32)atoi(cmd + 8);
382 uint32 new_mode = 0;
383 if(((GNSS_SET_SYSCFG_GPS | GNSS_SET_SYSCFG_BDS | GNSS_SET_SYSCFG_GLO | GNSS_SET_SYSCFG_GAL) & mode) != mode) {
384 gnss_set_result = GNSS_ERR_ARG;
385 goto set_fail;
386 }
387
388 if(mode & GNSS_SET_SYSCFG_GPS) { // GPS
389 new_mode |= 0x00000001;
390 }
391 if(mode & GNSS_SET_SYSCFG_BDS) { // BDS
392 new_mode |= 0x00000002;
393 }
394 if(mode & GNSS_SET_SYSCFG_GLO) { // GLO
395 new_mode |= 0x00000004;
396 }
397 if(mode & GNSS_SET_SYSCFG_GAL) { // GAL
398 new_mode |= 0x00000010;
399 }
400
401 gnss_set_result = gnss_8122_syscfg(fd, new_mode);
402 if(gnss_set_result != GNSS_ERR_OK) {
403 goto set_fail;
404 }
405 should_wait_rsp = TRUE;
406 } else if(memcmp(cmd, "$MSGCFG", 7) == 0) { // $MSGCFG,<mode>,<rate>
407 uint32 mode;
408 int rate;
409 if(2 == sscanf(cmd, "$MSGCFG,%d,%d", &mode, &rate)) {
410 int time = rate / 1000; // s
411 if(time < 0) {
412 gnss_set_result = GNSS_ERR_ARG;
413 goto set_fail;
414 }
415
416 if(((GNSS_SET_MSGCFG_RMC | GNSS_SET_MSGCFG_VTG | GNSS_SET_MSGCFG_GGA | GNSS_SET_MSGCFG_GSA
417 | GNSS_SET_MSGCFG_GRS | GNSS_SET_MSGCFG_GSV | GNSS_SET_MSGCFG_GLL | GNSS_SET_MSGCFG_ZDA
418 | GNSS_SET_MSGCFG_GST | GNSS_SET_MSGCFG_TXT) & mode) != mode) {
419 gnss_set_result = GNSS_ERR_ARG;
420 goto set_fail;
421 }
422
423 if(mode & GNSS_SET_MSGCFG_RMC) {
424 gnss_set_result = gnss_8122_msgcfg(fd, 0xF8, 0x05, time);
425 if(gnss_set_result != GNSS_ERR_OK) {
426 goto set_fail;
427 }
428 }
429
430 if(mode & GNSS_SET_MSGCFG_VTG) {
431 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x06, time);
432 if(gnss_set_result != GNSS_ERR_OK) {
433 goto set_fail;
434 }
435 }
436
437 if(mode & GNSS_SET_MSGCFG_GGA) {
438 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x00, time);
439 if(gnss_set_result != GNSS_ERR_OK) {
440 goto set_fail;
441 }
442 }
443
444 if(mode & GNSS_SET_MSGCFG_GSA) {
445 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x02, time);
446 if(gnss_set_result != GNSS_ERR_OK) {
447 goto set_fail;
448 }
449 }
450
451 if(mode & GNSS_SET_MSGCFG_GRS) {
452 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x03, time);
453 if(gnss_set_result != GNSS_ERR_OK) {
454 goto set_fail;
455 }
456 }
457
458 if(mode & GNSS_SET_MSGCFG_GSV) {
459 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x04, time);
460 if(gnss_set_result != GNSS_ERR_OK) {
461 goto set_fail;
462 }
463 }
464
465 if(mode & GNSS_SET_MSGCFG_GLL) {
466 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x01, time);
467 if(gnss_set_result != GNSS_ERR_OK) {
468 goto set_fail;
469 }
470 }
471
472 if(mode & GNSS_SET_MSGCFG_ZDA) {
473 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x07, time);
474 if(gnss_set_result != GNSS_ERR_OK) {
475 goto set_fail;
476 }
477 }
478
479 if(mode & GNSS_SET_MSGCFG_GST) {
480 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x08, time);
481 if(gnss_set_result != GNSS_ERR_OK) {
482 goto set_fail;
483 }
484 }
485
486 if(mode & GNSS_SET_MSGCFG_TXT) {
487 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x20, time);
488 if(gnss_set_result != GNSS_ERR_OK) {
489 goto set_fail;
490 }
491 }
492 } else {
493 gnss_set_result = GNSS_ERR_ARG;
494 goto set_fail;
495 }
496
497 should_wait_rsp = TRUE;
498 } else if(memcmp(cmd, "$MINEL", 6) == 0) { // $MINEL,<elev>
499#if 0
500 float elev = 0.0f;
501 elev = (float)atof(cmd + 7);
502// LOGD("ELEV : %f", elev);
503// log_hex("ELEV", &elev, sizeof(double));
504 if(elev < -90.0f || elev > 90.0f) {
505 gnss_set_result = GNSS_ERR_ARG;
506 goto set_fail;
507 }
508 float elevs[2];
509 elevs[0] = elev;
510 elevs[1] = elev;
511 gnss_set_result = gnss_8122_minel(fd, elevs);
512 if(gnss_set_result != GNSS_ERR_OK) {
513 goto set_fail;
514 }
515 should_wait_rsp = FALSE;
516#else
517 gnss_set_result = GNSS_ERR_UNSUPPORT;
518 goto set_fail;
519#endif
520 } else if(memcmp(cmd, "$NMEACFG", 8) == 0) { // $NMEACFG,<ver>
521#if 0
522 gnss_memaver_type_enum version = (gnss_memaver_type_enum)atoi(cmd + 9);
523 if(version == GNSS_MEMAVER_TYPE_3_0) {
524 gnss_set_result = gnss_8122_nmeaver(fd, 1);
525 } else if(version == GNSS_MEMAVER_TYPE_4_0) {
526 gnss_set_result = gnss_8122_nmeaver(fd, 2);
527 } else if(version == GNSS_MEMAVER_TYPE_4_1) {
528 gnss_set_result = gnss_8122_nmeaver(fd, 3);
529 } else {
530 gnss_set_result = GNSS_ERR_ARG;
531 goto set_fail;
532 }
533 if(gnss_set_result != GNSS_ERR_OK) {
534 goto set_fail;
535 }
536 should_wait_rsp = FALSE;
537#else
538 gnss_set_result = GNSS_ERR_UNSUPPORT;
539 goto set_fail;
540#endif
b.liu5f950c52024-06-15 20:13:12 +0800541 }
542 else
543 {
544 LOGW("Unknown cmd:%s", cmd);
545 gnss_set_result = GNSS_ERR_UNSUPPORT;
546 goto set_fail;
547 }
548
549set_success:
550 if(should_wait_rsp) {
b.liud0ba7152024-06-19 14:47:21 +0800551 setting_waitting = TRUE;
b.liu5f950c52024-06-15 20:13:12 +0800552 pthread_mutex_lock(&read_mutex);
553 pthread_cond_wait(&read_cond, &read_mutex);
554 pthread_mutex_unlock(&read_mutex);
555 } else {
556 mbtk_timer_clear();
557 }
558
559 setting_busy = FALSE;
560 return gnss_set_result;
561set_fail:
562 setting_busy = FALSE;
563 mbtk_timer_clear();
564 return gnss_set_result;
565 }
b.liuf9fbfa12024-06-14 15:53:59 +0800566}
567
b.liu5f950c52024-06-15 20:13:12 +0800568