diff --git a/adsbus.c b/adsbus.c index 161ba60..4a0adaa 100644 --- a/adsbus.c +++ b/adsbus.c @@ -131,7 +131,7 @@ static int loop(int bfd) { while (airspy_adsb_parse(&buf, &packet)) { } - if (buf.length == BUF_LEN) { + if (buf.length == BUF_LEN_MAX) { fprintf(stderr, "Input buffer overrun. This probably means that adsbus doesn't understand the protocol that this source is speaking.\n"); return -1; } @@ -142,6 +142,8 @@ static int loop(int bfd) { int main(int argc, char *argv[]) { + hex_init(); + struct opts opts = { .backend_node = "localhost", .backend_service = "30006", diff --git a/airspy_adsb.c b/airspy_adsb.c index ea64312..b4a5489 100644 --- a/airspy_adsb.c +++ b/airspy_adsb.c @@ -1,27 +1,53 @@ +#include #include #include #include "common.h" #include "airspy_adsb.h" +static bool airspy_adsb_parse_common(char *, struct packet *); + + bool airspy_adsb_parse(struct buf *buf, struct packet *packet) { if (buf->length < 35 || buf_chr(buf, 0) != '*') { return false; } if (buf->length >= 35 && + buf_chr(buf, 33) == '\r' && buf_chr(buf, 34) == '\n' && buf_chr(buf, 15) == ';') { + if (!airspy_adsb_parse_common(buf_at(buf, 16), packet)) { + return false; + } packet->type = MODE_S_SHORT; + hex_to_bin(packet->data, buf_at(buf, 1), 7); buf_consume(buf, 35); return true; } if (buf->length >= 49 && + buf_chr(buf, 47) == '\r' && buf_chr(buf, 48) == '\n' && buf_chr(buf, 29) == ';') { + if (!airspy_adsb_parse_common(buf_at(buf, 30), packet)) { + return false; + } packet->type = MODE_S_LONG; + hex_to_bin(packet->data, buf_at(buf, 1), 14); buf_consume(buf, 49); return true; } return false; } + +static bool airspy_adsb_parse_common(char *in, struct packet *packet) { + if (in[8] != ';' || + in[11] != ';' || + in[16] != ';') { + return false; + } + uint16_t mlat_mhz = 2 * hex_to_int(&in[9], 1); + packet->mlat_timestamp = hex_to_int(in, 4) * (MLAT_MHZ / mlat_mhz); + packet->rssi = hex_to_int(&in[12], 2) * (RSSI_MAX / (1 << 16)); + return true; +} diff --git a/common.c b/common.c index e0e25fd..c01b2f8 100644 --- a/common.c +++ b/common.c @@ -8,13 +8,13 @@ ssize_t buf_fill(struct buf *buf, int fd) { - if (buf->start + buf->length == BUF_LEN) { + if (buf->start + buf->length == BUF_LEN_MAX) { assert(buf->start > 0); memmove(buf->buf, buf_at(buf, 0), buf->length); buf->start = 0; } - size_t space = BUF_LEN - buf->length - buf->start; + size_t space = BUF_LEN_MAX - buf->length - buf->start; ssize_t in = read(fd, buf_at(buf, buf->length), space); if (in < 0) { return in; @@ -33,3 +33,36 @@ void buf_consume(struct buf *buf, size_t length) { buf->start = 0; } } + + +static uint8_t hex_table[256] = {0}; + +void hex_init() { + for (int i = '0'; i <= '9'; i++) { + hex_table[i] = i - '0'; + } + for (int i = 'a'; i <= 'f'; i++) { + hex_table[i] = 10 + i - 'a'; + } + for (int i = 'A'; i <= 'F'; i++) { + hex_table[i] = 10 + i - 'A'; + } +} + +void hex_to_bin(char *out, char *in, size_t bytes) { + uint8_t *in2 = (uint8_t *) in; + for (size_t i = 0, j = 0; i < bytes; i++, j += 2) { + out[i] = (hex_table[in2[j]] << 4) | hex_table[in2[j + 1]]; + } +} + +uint64_t hex_to_int(char *in, size_t bytes) { + uint8_t *in2 = (uint8_t *) in; + uint64_t ret = 0; + bytes *= 2; + for (size_t i = 0; i < bytes; i++) { + ret <<= 4; + ret |= hex_table[in2[i]]; + } + return ret; +} diff --git a/common.h b/common.h index 7e7a7af..e6db328 100644 --- a/common.h +++ b/common.h @@ -4,9 +4,9 @@ //////// buf -#define BUF_LEN 4096 +#define BUF_LEN_MAX 256 struct buf { - char buf[BUF_LEN]; + char buf[BUF_LEN_MAX]; size_t start; size_t length; }; @@ -20,18 +20,22 @@ void buf_consume(struct buf *, size_t); //////// packet -#define MLAT_HZ 60000000 -#define DATA_MAX 14 +#define MLAT_MHZ 120 +#define RSSI_MAX UINT32_MAX +#define DATA_LEN_MAX 14 struct packet { enum { MODE_AC, MODE_S_SHORT, MODE_S_LONG, } type; - char data[DATA_MAX]; + char data[DATA_LEN_MAX]; uint64_t mlat_timestamp; uint32_t rssi; }; //////// hex +void hex_init(); +void hex_to_bin(char *, char *, size_t); +uint64_t hex_to_int(char *, size_t);