blob: 5ee816cfe65c7ff746252c759f94fdb3f38ebcbe [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
b.liud0ba7152024-06-19 14:47:21 +080078static int msg_insert(uint8 gid, uint8 sid)
79{
80 int i = 0;
81 while(i < ARRAY_SIZE(msg_array)) {
82 if(!msg_array[i].enable)
83 break;
84 i++;
85 }
86
87 if(i == ARRAY_SIZE(msg_array)) {
88 LOGE("Msg full : %d", i);
89 return -1;
90 } else {
91 msg_array[i].enable = TRUE;
92 msg_array[i].gid = gid;
93 msg_array[i].sid = sid;
94 return 0;
95 }
96}
97
98static int msg_find(uint8 gid, uint8 sid)
99{
100 int i = 0;
101 while(i < ARRAY_SIZE(msg_array)) {
102 if(msg_array[i].enable && gid == msg_array[i].gid && sid == msg_array[i].sid)
103 break;
104 i++;
105 }
106
107 if(i == ARRAY_SIZE(msg_array)) {
108 LOGE("No found %d - %d", gid, sid);
109 return -1;
110 } else {
111 return i;
112 }
113}
114
115static int msg_remove(uint8 gid, uint8 sid)
116{
117 int i = msg_find(gid, sid);
118 if(i >= 0) {
119 msg_array[i].enable = FALSE;
120 msg_array[i].gid = 0;
121 msg_array[i].sid = 0;
122 return 0;
123 } else {
124 return -1;
125 }
126}
127
128static int msg_count()
129{
130 int i = 0;
131 int count = 0;
132 while(i < ARRAY_SIZE(msg_array)) {
133 if(msg_array[i].enable)
134 count++;
135 i++;
136 }
137 return count;
138}
b.liu5f950c52024-06-15 20:13:12 +0800139
140static int pack_create(hd8122_id_type_enum id_type, uint8 id, uint16 data_len, const uint8 *data, uint8 *pack, int pack_len)
141{
142 if(pack == NULL || pack_len < HD8122_PACK_LEN_MIN) {
143 return -1;
144 }
145 memset(pack, 0, pack_len);
146 uint8 *data_ptr = pack;
147 data_ptr += uint16_2_byte(HD8122_PACK_HEAD, data_ptr, false);
148 *data_ptr++ = (uint8)id_type;
149 *data_ptr++ = id;
150 data_ptr += uint16_2_byte(data_len, data_ptr, false);
151 if(data_len > 0) {
152 memcpy(data_ptr, data, data_len);
153 data_ptr += data_len;
154 }
155 data_ptr += uint16_2_byte(fletcher16(pack + 2, 4 + data_len), data_ptr, false);
156 return (data_ptr - pack);
157}
158
b.liud0ba7152024-06-19 14:47:21 +0800159// f1 d9 05 01 02 00 06 01 0f 38
160// or
161// f1 d9 05 00 02 00 06 01 0f 38
162static int msg_array_change(const uint8 *pack, int pack_len, hd8122_id_ack_enum *ack_nak)
163{
164 if(pack_len == 0 || pack_len % 10) {
165 LOGE("pack_len(%d) error.", pack_len);
166 return -1;
167 }
168 int count = pack_len / 10;
169 int i = 0;
170 while(i < count) {
171 uint8 *ptr = pack + i * 10;
172 if(ptr[0] != 0xf1 || ptr[1] != 0xd9) {
173 LOGE("Pack head error : %02x %02x", ptr[0], ptr[1]);
174 return -1;
175 }
176
177 if(ptr[2] != 0x05) {
178 LOGE("Type not 0x05 : %02x", ptr[2]);
179 return -1;
180 }
181
182 int index = msg_find(ptr[6], ptr[7]);
183 if(index >= 0) {
184 if(ptr[3] == 0x01) {
185 msg_array[index].ack_nak = HD8122_ID_ACK_ACK;
186 } else if(ptr[3] == 0x00) {
187 msg_array[index].ack_nak = HD8122_ID_ACK_NAK;
188
189 // There is a nak as a failure.
190 *ack_nak = HD8122_ID_ACK_NAK;
191 } else {
192 LOGE("ID not 0x00 or 0x01 : %02x", ptr[3]);
193 return -1;
194 }
195
196 msg_array[index].enable = FALSE;
197 } else {
198 LOGE("Unknown gid - %d, sid - %d", ptr[6], ptr[7]);
199 return -1;
200 }
201 i++;
202 }
203
204 return 0;
205}
206
b.liu5f950c52024-06-15 20:13:12 +0800207static void gnss_cmd_rsp_process(const void *data, int data_len) {
208 const char *ptr = (const char*)data;
209 log_hex("RSP", data, data_len);
b.liu5f950c52024-06-15 20:13:12 +0800210
b.liud0ba7152024-06-19 14:47:21 +0800211 hd8122_id_ack_enum ack_nak = HD8122_ID_ACK_ACK;
212 if(!msg_array_change((const uint8*)data, data_len, &ack_nak)) {
213 if(setting_waitting && msg_count() == 0)
214 {
215 if(ack_nak == HD8122_ID_ACK_ACK) {
216 gnss_set_result = GNSS_ERR_OK;
217 } else {
218 gnss_set_result = GNSS_ERR_UNKNOWN;
219 }
220
221 mbtk_timer_clear();
222
223 pthread_mutex_lock(&read_mutex);
224 pthread_cond_signal(&read_cond);
225 pthread_mutex_unlock(&read_mutex);
226 setting_waitting = FALSE;
227 }
228 } else {
229 LOGW("Unknown rsp data.");
b.liu5f950c52024-06-15 20:13:12 +0800230 }
231}
232
b.liud0ba7152024-06-19 14:47:21 +0800233static gnss_err_enum gnss_8122_reset(int fd, uint8 reset)
b.liu5f950c52024-06-15 20:13:12 +0800234{
235 uint8 buff[GNSS_PACK_BUFF_SIZE];
236 LOGD("RESET");
237 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_SIMPLERST, 1, (uint8*)(&reset), buff, sizeof(buff));
238 if(len <= 0) {
239 LOGE("pack_create() fail.");
240 return GNSS_ERR_ARG;
241 }
242 log_hex("PACK", buff, len);
243 gnss_write(fd, buff, len);
244 return GNSS_ERR_OK;
245}
b.liuf9fbfa12024-06-14 15:53:59 +0800246
b.liud0ba7152024-06-19 14:47:21 +0800247static gnss_err_enum gnss_8122_syscfg(int fd, uint32 mode)
248{
249 uint8 buff[GNSS_PACK_BUFF_SIZE];
250 LOGD("SYSCFG");
251 //uint8 mode_str[4];
252 //uint32_2_byte(mode, mode_str, TRUE);
253 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_NAVSAT, 4, (uint8*)(&mode), buff, sizeof(buff));
254 if(len <= 0) {
255 LOGE("pack_create() fail.");
256 return GNSS_ERR_ARG;
257 }
258 log_hex("PACK", buff, len);
259 gnss_write(fd, buff, len);
260 msg_insert(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_NAVSAT);
261 return GNSS_ERR_OK;
262}
263
264static gnss_err_enum gnss_8122_msgcfg(int fd, uint8 type, uint8 id, uint8 period)
265{
266 uint8 buff[GNSS_PACK_BUFF_SIZE];
267 LOGD("MSGCFG");
268 uint8 data[3];
269 data[0] = type;
270 data[1] = id;
271 data[2] = period;
272 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_MSG, 3, data, buff, sizeof(buff));
273 if(len <= 0) {
274 LOGE("pack_create() fail.");
275 return GNSS_ERR_ARG;
276 }
277 log_hex("PACK", buff, len);
278 gnss_write(fd, buff, len);
279 msg_insert(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_MSG);
280 return GNSS_ERR_OK;
281}
282
283static gnss_err_enum gnss_8122_minel(int fd, float *elev)
284{
285 uint8 buff[GNSS_PACK_BUFF_SIZE];
286 LOGD("ELEV");
287 //uint8 elev_buff[4];
288 //uint32_2_byte((uint32)elev, elev_buff, TRUE);
289 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_ELEV, 8, (uint8*)elev, buff, sizeof(buff));
290 if(len <= 0) {
291 LOGE("pack_create() fail.");
292 return GNSS_ERR_ARG;
293 }
294 log_hex("PACK", buff, len);
295 gnss_write(fd, buff, len);
296 return GNSS_ERR_OK;
297}
298
299static gnss_err_enum gnss_8122_nmeaver(int fd, uint8 ver)
300{
301 uint8 buff[GNSS_PACK_BUFF_SIZE];
302 LOGD("NMEA-VER");
303 int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_NMEAVER, 1, (uint8*)(&ver), buff, sizeof(buff));
304 if(len <= 0) {
305 LOGE("pack_create() fail.");
306 return GNSS_ERR_ARG;
307 }
308 log_hex("PACK", buff, len);
309 gnss_write(fd, buff, len);
310 return GNSS_ERR_OK;
311}
312
b.liuf9fbfa12024-06-14 15:53:59 +0800313int gnss_8122_dev_open()
314{
315 return mbtk_gpio_value_set(GNSS_POWER_GPIO, MBTK_GPIO_DIRECT_OUT, 1);
316}
317
318int gnss_8122_dev_close()
319{
320 return mbtk_gpio_value_set(GNSS_POWER_GPIO, MBTK_GPIO_DIRECT_OUT, 0);
321}
322
323int gnss_8122_open(const char *dev)
324{
325 pthread_mutex_init(&read_mutex, NULL);
326 pthread_cond_init(&read_cond, NULL);
327 return gnss_port_open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY, UART_BITRATE_NMEA_DEF_FW, TRUE);
328}
329
330int gnss_8122_close(int fd)
331{
332 pthread_mutex_destroy(&read_mutex);
333 pthread_cond_destroy(&read_cond);
334 return gnss_port_close(fd);
335}
336
b.liu99c645d2024-06-20 10:52:15 +0800337int gnss_8122_fw_dl(int fd, const char *dev)
b.liuf9fbfa12024-06-14 15:53:59 +0800338{
339 return 0;
340}
341
b.liu5f950c52024-06-15 20:13:12 +0800342void gnss_8122_set_cb(const void *data, int data_len)
343{
344 const char *buff = (const char*)data;
b.liud0ba7152024-06-19 14:47:21 +0800345 if(setting_busy) { // Has setting cmd process.
b.liu5f950c52024-06-15 20:13:12 +0800346 gnss_cmd_rsp_process(data, data_len);
347 }
348}
b.liuf9fbfa12024-06-14 15:53:59 +0800349
350gnss_err_enum gnss_8122_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len)
351{
b.liu5f950c52024-06-15 20:13:12 +0800352 if(setting_busy) {
353 return GNSS_ERR_SET_BUSY;
354 } else {
355 bool should_wait_rsp = TRUE;
356 setting_busy = TRUE;
357 gnss_set_rsp_ptr = cmd_rsp;
358 gnss_set_result = GNSS_ERR_OK;
b.liud0ba7152024-06-19 14:47:21 +0800359 msg_init();
b.liu5f950c52024-06-15 20:13:12 +0800360 mbtk_timer_set(gnss_set_timer_cb, GNSS_SET_TIMEOUT);
361
b.liud0ba7152024-06-19 14:47:21 +0800362 if(memcmp(cmd, "$RESET", 6) == 0) { // $RESET,<mode>
363 gnss_reset_type_enum mode = (gnss_reset_type_enum)atoi(cmd + 7);
364 if(mode == GNSS_RESET_TYPE_HOT) {
365 gnss_set_result = gnss_8122_reset(fd, 3);
366 } else if(mode == GNSS_RESET_TYPE_WARM) {
367 gnss_set_result = gnss_8122_reset(fd, 2);
368 } else if(mode == GNSS_RESET_TYPE_COLD) {
369 gnss_set_result = gnss_8122_reset(fd, 1);
370 } else {
371 gnss_set_result = GNSS_ERR_ARG;
372 goto set_fail;
373 }
b.liu5f950c52024-06-15 20:13:12 +0800374 if(gnss_set_result != GNSS_ERR_OK) {
375 goto set_fail;
376 }
377 should_wait_rsp = FALSE;
b.liud0ba7152024-06-19 14:47:21 +0800378 } else if(memcmp(cmd, "$SYSCFG", 7) == 0) { // $SYSCFG,<mode>
379 uint32 mode = 0;
380 mode = (uint32)atoi(cmd + 8);
381 uint32 new_mode = 0;
382 if(((GNSS_SET_SYSCFG_GPS | GNSS_SET_SYSCFG_BDS | GNSS_SET_SYSCFG_GLO | GNSS_SET_SYSCFG_GAL) & mode) != mode) {
383 gnss_set_result = GNSS_ERR_ARG;
384 goto set_fail;
385 }
386
387 if(mode & GNSS_SET_SYSCFG_GPS) { // GPS
388 new_mode |= 0x00000001;
389 }
390 if(mode & GNSS_SET_SYSCFG_BDS) { // BDS
391 new_mode |= 0x00000002;
392 }
393 if(mode & GNSS_SET_SYSCFG_GLO) { // GLO
394 new_mode |= 0x00000004;
395 }
396 if(mode & GNSS_SET_SYSCFG_GAL) { // GAL
397 new_mode |= 0x00000010;
398 }
399
400 gnss_set_result = gnss_8122_syscfg(fd, new_mode);
401 if(gnss_set_result != GNSS_ERR_OK) {
402 goto set_fail;
403 }
404 should_wait_rsp = TRUE;
405 } else if(memcmp(cmd, "$MSGCFG", 7) == 0) { // $MSGCFG,<mode>,<rate>
406 uint32 mode;
407 int rate;
408 if(2 == sscanf(cmd, "$MSGCFG,%d,%d", &mode, &rate)) {
409 int time = rate / 1000; // s
410 if(time < 0) {
411 gnss_set_result = GNSS_ERR_ARG;
412 goto set_fail;
413 }
414
415 if(((GNSS_SET_MSGCFG_RMC | GNSS_SET_MSGCFG_VTG | GNSS_SET_MSGCFG_GGA | GNSS_SET_MSGCFG_GSA
416 | GNSS_SET_MSGCFG_GRS | GNSS_SET_MSGCFG_GSV | GNSS_SET_MSGCFG_GLL | GNSS_SET_MSGCFG_ZDA
417 | GNSS_SET_MSGCFG_GST | GNSS_SET_MSGCFG_TXT) & mode) != mode) {
418 gnss_set_result = GNSS_ERR_ARG;
419 goto set_fail;
420 }
421
422 if(mode & GNSS_SET_MSGCFG_RMC) {
423 gnss_set_result = gnss_8122_msgcfg(fd, 0xF8, 0x05, time);
424 if(gnss_set_result != GNSS_ERR_OK) {
425 goto set_fail;
426 }
427 }
428
429 if(mode & GNSS_SET_MSGCFG_VTG) {
430 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x06, time);
431 if(gnss_set_result != GNSS_ERR_OK) {
432 goto set_fail;
433 }
434 }
435
436 if(mode & GNSS_SET_MSGCFG_GGA) {
437 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x00, time);
438 if(gnss_set_result != GNSS_ERR_OK) {
439 goto set_fail;
440 }
441 }
442
443 if(mode & GNSS_SET_MSGCFG_GSA) {
444 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x02, time);
445 if(gnss_set_result != GNSS_ERR_OK) {
446 goto set_fail;
447 }
448 }
449
450 if(mode & GNSS_SET_MSGCFG_GRS) {
451 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x03, time);
452 if(gnss_set_result != GNSS_ERR_OK) {
453 goto set_fail;
454 }
455 }
456
457 if(mode & GNSS_SET_MSGCFG_GSV) {
458 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x04, time);
459 if(gnss_set_result != GNSS_ERR_OK) {
460 goto set_fail;
461 }
462 }
463
464 if(mode & GNSS_SET_MSGCFG_GLL) {
465 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x01, time);
466 if(gnss_set_result != GNSS_ERR_OK) {
467 goto set_fail;
468 }
469 }
470
471 if(mode & GNSS_SET_MSGCFG_ZDA) {
472 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x07, time);
473 if(gnss_set_result != GNSS_ERR_OK) {
474 goto set_fail;
475 }
476 }
477
478 if(mode & GNSS_SET_MSGCFG_GST) {
479 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x08, time);
480 if(gnss_set_result != GNSS_ERR_OK) {
481 goto set_fail;
482 }
483 }
484
485 if(mode & GNSS_SET_MSGCFG_TXT) {
486 gnss_set_result = gnss_8122_msgcfg(fd, 0xF0, 0x20, time);
487 if(gnss_set_result != GNSS_ERR_OK) {
488 goto set_fail;
489 }
490 }
491 } else {
492 gnss_set_result = GNSS_ERR_ARG;
493 goto set_fail;
494 }
495
496 should_wait_rsp = TRUE;
497 } else if(memcmp(cmd, "$MINEL", 6) == 0) { // $MINEL,<elev>
498#if 0
499 float elev = 0.0f;
500 elev = (float)atof(cmd + 7);
501// LOGD("ELEV : %f", elev);
502// log_hex("ELEV", &elev, sizeof(double));
503 if(elev < -90.0f || elev > 90.0f) {
504 gnss_set_result = GNSS_ERR_ARG;
505 goto set_fail;
506 }
507 float elevs[2];
508 elevs[0] = elev;
509 elevs[1] = elev;
510 gnss_set_result = gnss_8122_minel(fd, elevs);
511 if(gnss_set_result != GNSS_ERR_OK) {
512 goto set_fail;
513 }
514 should_wait_rsp = FALSE;
515#else
516 gnss_set_result = GNSS_ERR_UNSUPPORT;
517 goto set_fail;
518#endif
519 } else if(memcmp(cmd, "$NMEACFG", 8) == 0) { // $NMEACFG,<ver>
520#if 0
521 gnss_memaver_type_enum version = (gnss_memaver_type_enum)atoi(cmd + 9);
522 if(version == GNSS_MEMAVER_TYPE_3_0) {
523 gnss_set_result = gnss_8122_nmeaver(fd, 1);
524 } else if(version == GNSS_MEMAVER_TYPE_4_0) {
525 gnss_set_result = gnss_8122_nmeaver(fd, 2);
526 } else if(version == GNSS_MEMAVER_TYPE_4_1) {
527 gnss_set_result = gnss_8122_nmeaver(fd, 3);
528 } else {
529 gnss_set_result = GNSS_ERR_ARG;
530 goto set_fail;
531 }
532 if(gnss_set_result != GNSS_ERR_OK) {
533 goto set_fail;
534 }
535 should_wait_rsp = FALSE;
536#else
537 gnss_set_result = GNSS_ERR_UNSUPPORT;
538 goto set_fail;
539#endif
b.liu5f950c52024-06-15 20:13:12 +0800540 }
541 else
542 {
543 LOGW("Unknown cmd:%s", cmd);
544 gnss_set_result = GNSS_ERR_UNSUPPORT;
545 goto set_fail;
546 }
547
548set_success:
549 if(should_wait_rsp) {
b.liud0ba7152024-06-19 14:47:21 +0800550 setting_waitting = TRUE;
b.liu5f950c52024-06-15 20:13:12 +0800551 pthread_mutex_lock(&read_mutex);
552 pthread_cond_wait(&read_cond, &read_mutex);
553 pthread_mutex_unlock(&read_mutex);
554 } else {
555 mbtk_timer_clear();
556 }
557
558 setting_busy = FALSE;
559 return gnss_set_result;
560set_fail:
561 setting_busy = FALSE;
562 mbtk_timer_clear();
563 return gnss_set_result;
564 }
b.liuf9fbfa12024-06-14 15:53:59 +0800565}
566
b.liu5f950c52024-06-15 20:13:12 +0800567