123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- #include "gpsd_config.h"
- #include <stdbool.h>
- #include "gpsd.h"
- #define MAG_SHIFT 6u
- #define MAG_TAG_DATA (1 << MAG_SHIFT)
- #define MAG_TAG_MASK (3 << MAG_SHIFT)
- #define W_DATA_MASK 0x3fffffc0u
- static unsigned char parity_array[] = {
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
- };
- static unsigned int reverse_bits[] = {
- 0, 32, 16, 48, 8, 40, 24, 56, 4, 36, 20, 52, 12, 44, 28, 60,
- 2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62,
- 1, 33, 17, 49, 9, 41, 25, 57, 5, 37, 21, 53, 13, 45, 29, 61,
- 3, 35, 19, 51, 11, 43, 27, 59, 7, 39, 23, 55, 15, 47, 31, 63
- };
- unsigned int isgps_parity(isgps30bits_t th)
- {
- #define P_30_MASK 0x40000000u
- #define PARITY_25 0xbb1f3480u
- #define PARITY_26 0x5d8f9a40u
- #define PARITY_27 0xaec7cd00u
- #define PARITY_28 0x5763e680u
- #define PARITY_29 0x6bb1f340u
- #define PARITY_30 0x8b7a89c0u
- isgps30bits_t t;
- unsigned int p;
- /*
- * if (th & P_30_MASK)
- * th ^= W_DATA_MASK;
- */
- t = th & PARITY_25;
- p = parity_array[t & 0xff] ^ parity_array[(t >> 8) & 0xff] ^
- parity_array[(t >> 16) & 0xff] ^ parity_array[(t >> 24) & 0xff];
- t = th & PARITY_26;
- p = (p << 1) | (parity_array[t & 0xff] ^ parity_array[(t >> 8) & 0xff] ^
- parity_array[(t >> 16) & 0xff] ^ parity_array[(t >> 24) &
- 0xff]);
- t = th & PARITY_27;
- p = (p << 1) | (parity_array[t & 0xff] ^ parity_array[(t >> 8) & 0xff] ^
- parity_array[(t >> 16) & 0xff] ^ parity_array[(t >> 24) &
- 0xff]);
- t = th & PARITY_28;
- p = (p << 1) | (parity_array[t & 0xff] ^ parity_array[(t >> 8) & 0xff] ^
- parity_array[(t >> 16) & 0xff] ^ parity_array[(t >> 24) &
- 0xff]);
- t = th & PARITY_29;
- p = (p << 1) | (parity_array[t & 0xff] ^ parity_array[(t >> 8) & 0xff] ^
- parity_array[(t >> 16) & 0xff] ^ parity_array[(t >> 24) &
- 0xff]);
- t = th & PARITY_30;
- p = (p << 1) | (parity_array[t & 0xff] ^ parity_array[(t >> 8) & 0xff] ^
- parity_array[(t >> 16) & 0xff] ^ parity_array[(t >> 24) &
- 0xff]);
- #ifdef __UNUSED__
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 2, errout, "ISGPS parity %u\n", p);
- #endif
- return (p);
- }
- #define isgps_parityok(w) (isgps_parity(w) == ((w) & 0x3f))
- void isgps_init(struct gps_lexer_t *lexer)
- {
- lexer->isgps.curr_word = 0;
- lexer->isgps.curr_offset = 24;
- lexer->isgps.locked = false;
- lexer->isgps.bufindex = 0;
- lexer->isgps.buflen = 0;
- }
- enum isgpsstat_t isgps_decode(struct gps_lexer_t *lexer,
- bool(*preamble_match) (isgps30bits_t *),
- bool(*length_check) (struct gps_lexer_t *),
- size_t maxlen, unsigned int c)
- {
-
- if ((c & MAG_TAG_MASK) != MAG_TAG_DATA) {
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 1, &lexer->errout,
- "ISGPS word tag not correct, skipping byte\n");
- return ISGPS_SKIP;
- }
- c = reverse_bits[c & 0x3f];
- if (!lexer->isgps.locked) {
- lexer->isgps.curr_offset = -5;
- lexer->isgps.bufindex = 0;
- while (lexer->isgps.curr_offset <= 0) {
- lexer->isgps.curr_word <<= 1;
- if (lexer->isgps.curr_offset > 0) {
- lexer->isgps.curr_word |= c << lexer->isgps.curr_offset;
- } else {
- lexer->isgps.curr_word |=
- c >> -(lexer->isgps.curr_offset);
- }
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 2, &lexer->errout,
- "ISGPS syncing at byte %lu: 0x%08x\n",
- lexer->char_counter, lexer->isgps.curr_word);
- if (preamble_match(&lexer->isgps.curr_word)) {
- if (isgps_parityok(lexer->isgps.curr_word)) {
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 1, &lexer->errout,
- "ISGPS preamble ok, parity ok -- locked\n");
- lexer->isgps.locked = true;
- break;
- }
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 1, &lexer->errout,
- "ISGPS preamble ok, parity fail\n");
- }
- lexer->isgps.curr_offset++;
- }
- }
- if (lexer->isgps.locked) {
- enum isgpsstat_t res;
- res = ISGPS_SYNC;
- if (lexer->isgps.curr_offset > 0) {
- lexer->isgps.curr_word |= c << lexer->isgps.curr_offset;
- } else {
- lexer->isgps.curr_word |= c >> -(lexer->isgps.curr_offset);
- }
- if (lexer->isgps.curr_offset <= 0) {
-
- if (lexer->isgps.curr_word & P_30_MASK)
- lexer->isgps.curr_word ^= W_DATA_MASK;
- if (isgps_parityok(lexer->isgps.curr_word)) {
- #if 0
-
- if (preamble_match(&lexer->isgps.curr_word)) {
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 2, &lexer->errout,
- "ISGPS preamble spotted (index: %u)\n",
- lexer->isgps.bufindex);
- lexer->isgps.bufindex = 0;
- }
- #endif
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 2, &lexer->errout,
- "ISGPS processing word %u (offset %d)\n",
- lexer->isgps.bufindex,
- lexer->isgps.curr_offset);
- {
-
- if (lexer->isgps.bufindex >= (unsigned)maxlen) {
- lexer->isgps.bufindex = 0;
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 1, &lexer->errout,
- "ISGPS buffer overflowing -- resetting\n");
- return ISGPS_NO_SYNC;
- }
- lexer->isgps.buf[lexer->isgps.bufindex] =
- lexer->isgps.curr_word;
-
- if ((lexer->isgps.bufindex == 0) &&
- !preamble_match((isgps30bits_t *) lexer->isgps.buf)) {
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 1, &lexer->errout,
- "ISGPS word 0 not a preamble- punting\n");
- return ISGPS_NO_SYNC;
- }
-
- lexer->isgps.bufindex++;
- if (length_check(lexer)) {
-
- lexer->isgps.buflen = lexer->isgps.bufindex *
- sizeof(isgps30bits_t);
- lexer->isgps.bufindex = 0;
- res = ISGPS_MESSAGE;
- }
- }
- lexer->isgps.curr_word <<= 30;
- lexer->isgps.curr_offset += 30;
- if (lexer->isgps.curr_offset > 0) {
- lexer->isgps.curr_word |=
- c << lexer->isgps.curr_offset;
- } else {
- lexer->isgps.curr_word |=
- c >> -(lexer->isgps.curr_offset);
- }
- } else {
- GPSD_LOG(ISGPS_ERRLEVEL_BASE, &lexer->errout,
- "ISGPS parity failure, lost lock\n");
- lexer->isgps.locked = false;
- }
- }
- lexer->isgps.curr_offset -= 6;
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 2, &lexer->errout,
- "ISGPS residual %d\n",
- lexer->isgps.curr_offset);
- return res;
- }
-
- GPSD_LOG(ISGPS_ERRLEVEL_BASE + 1, &lexer->errout,
- "ISGPS lock never achieved\n");
- return ISGPS_NO_SYNC;
- }
|