From c5a87e89a47de26741c6b35085defad6fe5e26ca Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 21 Feb 2016 16:52:36 -0800 Subject: [PATCH] Restore airspy_adsb --- adsbus/Makefile | 4 +- adsbus/airspy_adsb.c | 154 +++++++++++++++++++++++++++++++++++++++++++ adsbus/airspy_adsb.h | 10 +++ adsbus/receive.c | 5 ++ adsbus/send.c | 5 ++ 5 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 adsbus/airspy_adsb.c create mode 100644 adsbus/airspy_adsb.h diff --git a/adsbus/Makefile b/adsbus/Makefile index cb4fc94..92fb54c 100644 --- a/adsbus/Makefile +++ b/adsbus/Makefile @@ -11,5 +11,5 @@ clean: %.o: %.c *.h $(CC) -c $(CFLAGS) $< -o $@ -adsbus: adsbus.o receive.o send.o incoming.o outgoing.o beast.o json.o raw.o stats.o wakeup.o opts.o common.o - $(CC) $(LDFLAGS) -o adsbus adsbus.o receive.o send.o incoming.o outgoing.o beast.o json.o raw.o stats.o wakeup.o opts.o common.o $(LIBS) +adsbus: adsbus.o receive.o send.o incoming.o outgoing.o airspy_adsb.o beast.o json.o raw.o stats.o wakeup.o opts.o common.o + $(CC) $(LDFLAGS) -o adsbus adsbus.o receive.o send.o incoming.o outgoing.o airspy_adsb.o beast.o json.o raw.o stats.o wakeup.o opts.o common.o $(LIBS) diff --git a/adsbus/airspy_adsb.c b/adsbus/airspy_adsb.c new file mode 100644 index 0000000..53efdeb --- /dev/null +++ b/adsbus/airspy_adsb.c @@ -0,0 +1,154 @@ +#include +#include +#include + +#include "common.h" +#include "receive.h" +#include "airspy_adsb.h" + +#define SEND_MHZ 20 + +struct __attribute__((packed)) airspy_adsb_common_overlay { + char mlat_timestamp[8]; + char semicolon1; + char mlat_precision[2]; + char semicolon2; + char rssi[4]; + char semicolon3; +}; + +struct __attribute__((packed)) airspy_adsb_mode_s_short_overlay { + char asterisk; + char payload[14]; + char semicolon; + struct airspy_adsb_common_overlay common; + char cr; + char lf; +}; + +struct __attribute__((packed)) airspy_adsb_mode_s_long_overlay { + char asterisk; + char payload[28]; + char semicolon; + struct airspy_adsb_common_overlay common; + char cr; + char lf; +}; + +struct airspy_adsb_parser_state { + struct mlat_state mlat_state; +}; + +static bool airspy_adsb_parse_common(const struct airspy_adsb_common_overlay *overlay, struct packet *packet, struct airspy_adsb_parser_state *state) { + if (overlay->semicolon1 != ';' || + overlay->semicolon2 != ';' || + overlay->semicolon3 != ';') { + return false; + } + uint16_t mlat_mhz = 2 * hex_to_int(overlay->mlat_precision, sizeof(overlay->mlat_precision) / 2); + packet->mlat_timestamp = mlat_timestamp_scale_in(hex_to_int(overlay->mlat_timestamp, sizeof(overlay->mlat_timestamp) / 2), UINT32_MAX, mlat_mhz, &state->mlat_state); + packet->rssi = rssi_scale_in(hex_to_int(overlay->rssi, sizeof(overlay->rssi) / 2), UINT16_MAX); + return true; +} + +static bool airspy_adsb_parse_mode_s_short(struct buf *buf, struct packet *packet, struct airspy_adsb_parser_state *state) { + struct airspy_adsb_mode_s_short_overlay *short_overlay = (struct airspy_adsb_mode_s_short_overlay *) buf_at(buf, 0); + if (buf->length < sizeof(*short_overlay) || + short_overlay->asterisk != '*' || + short_overlay->semicolon != ';' || + short_overlay->cr != '\r' || + short_overlay->lf != '\n') { + return false; + } + if (!airspy_adsb_parse_common(&short_overlay->common, packet, state)) { + return false; + } + packet->type = MODE_S_SHORT; + hex_to_bin(packet->payload, short_overlay->payload, sizeof(short_overlay->payload) / 2); + buf_consume(buf, sizeof(*short_overlay)); + return true; +} + +static bool airspy_adsb_parse_mode_s_long(struct buf *buf, struct packet *packet, struct airspy_adsb_parser_state *state) { + struct airspy_adsb_mode_s_long_overlay *long_overlay = (struct airspy_adsb_mode_s_long_overlay *) buf_at(buf, 0); + if (buf->length < sizeof(*long_overlay) || + long_overlay->asterisk != '*' || + long_overlay->semicolon != ';' || + long_overlay->cr != '\r' || + long_overlay->lf != '\n') { + return false; + } + if (!airspy_adsb_parse_common(&long_overlay->common, packet, state)) { + return false; + } + packet->type = MODE_S_LONG; + hex_to_bin(packet->payload, long_overlay->payload, sizeof(long_overlay->payload) / 2); + buf_consume(buf, sizeof(*long_overlay)); + return true; +} + +static void airspy_adsb_fill_common(struct packet *packet, struct airspy_adsb_common_overlay *overlay) { + overlay->semicolon1 = overlay->semicolon2 = overlay->semicolon3 = ';'; + hex_from_int( + overlay->mlat_timestamp, + mlat_timestamp_scale_out(packet->mlat_timestamp, UINT32_MAX, SEND_MHZ), + sizeof(overlay->mlat_timestamp) / 2); + hex_from_int(overlay->mlat_precision, SEND_MHZ / 2, sizeof(overlay->mlat_precision) / 2); + hex_from_int(overlay->rssi, rssi_scale_out(packet->rssi, UINT16_MAX), sizeof(overlay->rssi) / 2); +} + +static void airspy_adsb_serialize_mode_s_short(struct packet *packet, struct buf *buf) { + struct airspy_adsb_mode_s_short_overlay *overlay = (struct airspy_adsb_mode_s_short_overlay *) buf_at(buf, 0); + overlay->asterisk = '*'; + overlay->semicolon = ';'; + overlay->cr = '\r'; + overlay->lf = '\n'; + hex_from_bin(overlay->payload, packet->payload, sizeof(overlay->payload) / 2); + + airspy_adsb_fill_common(packet, &overlay->common); + + buf->length = sizeof(*overlay); +} + +static void airspy_adsb_serialize_mode_s_long(struct packet *packet, struct buf *buf) { + struct airspy_adsb_mode_s_long_overlay *overlay = (struct airspy_adsb_mode_s_long_overlay *) buf_at(buf, 0); + overlay->asterisk = '*'; + overlay->semicolon = ';'; + overlay->cr = '\r'; + overlay->lf = '\n'; + hex_from_bin(overlay->payload, packet->payload, sizeof(overlay->payload) / 2); + + airspy_adsb_fill_common(packet, &overlay->common); + + buf->length = sizeof(*overlay); +} + +void airspy_adsb_init() { + assert(sizeof(struct airspy_adsb_parser_state) <= PARSER_STATE_LEN); + assert(sizeof(struct airspy_adsb_mode_s_short_overlay) < BUF_LEN_MAX); + assert(sizeof(struct airspy_adsb_mode_s_long_overlay) < BUF_LEN_MAX); +} + +bool airspy_adsb_parse(struct buf *buf, struct packet *packet, void *state_in) { + struct airspy_adsb_parser_state *state = (struct airspy_adsb_parser_state *) state_in; + + return ( + airspy_adsb_parse_mode_s_short(buf, packet, state) || + airspy_adsb_parse_mode_s_long(buf, packet, state)); +} + +void airspy_adsb_serialize(struct packet *packet, struct buf *buf) { + if (!packet) { + return; + } + + switch (packet->type) { + case MODE_S_SHORT: + airspy_adsb_serialize_mode_s_short(packet, buf); + break; + + case MODE_S_LONG: + airspy_adsb_serialize_mode_s_long(packet, buf); + break; + } +} diff --git a/adsbus/airspy_adsb.h b/adsbus/airspy_adsb.h new file mode 100644 index 0000000..0eb08c0 --- /dev/null +++ b/adsbus/airspy_adsb.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +struct buf; +struct packet; + +void airspy_adsb_init(); +bool airspy_adsb_parse(struct buf *, struct packet *, void *); +void airspy_adsb_serialize(struct packet *, struct buf *); diff --git a/adsbus/receive.c b/adsbus/receive.c index 9a5c041..4414042 100644 --- a/adsbus/receive.c +++ b/adsbus/receive.c @@ -4,6 +4,7 @@ #include #include +#include "airspy_adsb.h" #include "beast.h" #include "raw.h" @@ -27,6 +28,10 @@ struct parser { char *name; parser parse; } parsers[] = { + { + .name = "airspy_adsb", + .parse = airspy_adsb_parse, + }, { .name = "beast", .parse = beast_parse, diff --git a/adsbus/send.c b/adsbus/send.c index c6706ec..424dce8 100644 --- a/adsbus/send.c +++ b/adsbus/send.c @@ -10,6 +10,7 @@ #include "send.h" +#include "airspy_adsb.h" #include "beast.h" #include "json.h" #include "raw.h" @@ -29,6 +30,10 @@ struct serializer { serializer serialize; struct send *send_head; } serializers[] = { + { + .name = "airspy_adsb", + .serialize = airspy_adsb_serialize, + }, { .name = "beast", .serialize = beast_serialize,