diff --git a/airspy_adsb.c b/airspy_adsb.c index 36f09c4..53efdeb 100644 --- a/airspy_adsb.c +++ b/airspy_adsb.c @@ -6,6 +6,8 @@ #include "receive.h" #include "airspy_adsb.h" +#define SEND_MHZ 20 + struct __attribute__((packed)) airspy_adsb_common_overlay { char mlat_timestamp[8]; char semicolon1; @@ -85,6 +87,42 @@ static bool airspy_adsb_parse_mode_s_long(struct buf *buf, struct packet *packet 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); @@ -98,3 +136,19 @@ bool airspy_adsb_parse(struct buf *buf, struct packet *packet, void *state_in) { 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/airspy_adsb.h b/airspy_adsb.h index 30fc266..0eb08c0 100644 --- a/airspy_adsb.h +++ b/airspy_adsb.h @@ -7,3 +7,4 @@ 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/common.c b/common.c index d9b9692..0d7e631 100644 --- a/common.c +++ b/common.c @@ -163,6 +163,14 @@ void hex_from_bin(char *out, const uint8_t *in, size_t bytes) { } } +void hex_from_int(char *out, uint64_t in, size_t bytes) { + bytes *= 2; + for (int o = bytes - 1; o >= 0; o--) { + out[o] = hex_char_table[in & 0xf]; + in >>= 4; + } +} + void uuid_gen(char *out) { uuid_t uuid; diff --git a/common.h b/common.h index a189b7e..8d663fd 100644 --- a/common.h +++ b/common.h @@ -85,6 +85,7 @@ void hex_init(); void hex_to_bin(uint8_t *, const char *, size_t); uint64_t hex_to_int(const char *, size_t); void hex_from_bin(char *, const uint8_t *, size_t); +void hex_from_int(char *, uint64_t, size_t); ///////// uuid diff --git a/send.c b/send.c index 03da67f..0f69147 100644 --- a/send.c +++ b/send.c @@ -11,6 +11,7 @@ #include "send.h" +#include "airspy_adsb.h" #include "beast.h" #include "json.h" #include "raw.h" @@ -30,6 +31,10 @@ struct serializer { serializer serialize; struct send *send_head; } serializers[] = { + { + .name = "airspy_adsb", + .serialize = airspy_adsb_serialize, + }, { .name = "beast", .serialize = beast_serialize,