mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-05-14 20:52:12 -04:00
ADS-B frame struct, callsign decode
This commit is contained in:
parent
32e8bc4c65
commit
93c5959df6
8 changed files with 193 additions and 111 deletions
|
@ -47,32 +47,28 @@ ADSBRxView::~ADSBRxView() {
|
|||
//baseband::shutdown();
|
||||
}
|
||||
|
||||
void ADSBRxView::analyze(uint64_t offset) {
|
||||
size_t c;
|
||||
bool ADSBRxView::analyze(uint64_t offset) {
|
||||
Coord lcd_x = 0, lcd_y = 0;
|
||||
adsb_frame frame;
|
||||
int16_t file_data[128]; // 256 bytes / 2 IQ / 16 bits = 64 samples
|
||||
complex8_t iq_data[256]; // 256 samples
|
||||
uint64_t file_offset = 0;
|
||||
uint8_t data_put = 0, data_get = 0;
|
||||
int16_t f_re, f_im;
|
||||
int8_t re, im;
|
||||
uint32_t c;
|
||||
uint8_t level, bit, byte;
|
||||
Color mark_color;
|
||||
size_t preamble_count = 0, null_count = 0, bit_count = 0, sample_count = 0;
|
||||
bool decoding = false;
|
||||
float prev_mag, mag;
|
||||
float prev_mag = 0, mag;
|
||||
float threshold, threshold_low, threshold_high;
|
||||
std::string bits;
|
||||
std::string hex_str;
|
||||
bool confidence, first_in_window, last_in_window;
|
||||
uint8_t frame_index;
|
||||
uint8_t adsb_frame[256];
|
||||
std::pair<float, uint8_t> shifter[ADSB_PREAMBLE_LENGTH];
|
||||
|
||||
// Use vectors and std::rotate !
|
||||
float shifter[16];
|
||||
uint8_t shifter_bits[16];
|
||||
|
||||
iq_file.seek(offset * 256);
|
||||
iq_file.seek(offset * 2048); // 256
|
||||
|
||||
for (;;) {
|
||||
if (data_put == data_get) {
|
||||
|
@ -80,21 +76,21 @@ void ADSBRxView::analyze(uint64_t offset) {
|
|||
if (!result.is_error()) {
|
||||
// Convert file's C16 to C8
|
||||
for (c = 0; c < (result.value() / 4); c++) {
|
||||
f_re = file_data[(c * 2) + 0] >> 5;
|
||||
f_re = file_data[(c * 2) + 0] >> 5; // >> 8 (<< 3 amp.)
|
||||
f_im = file_data[(c * 2) + 1] >> 5;
|
||||
iq_data[data_put] = { f_re, f_im };
|
||||
iq_data[data_put] = { (int8_t)f_re, (int8_t)f_im };
|
||||
data_put++;
|
||||
}
|
||||
|
||||
file_offset += result.value();
|
||||
|
||||
if (file_offset >= 4096) {
|
||||
text_debug_e.set("Read @ " + to_string_dec_uint(offset * 256 / 2000 / 4) + "ms ");
|
||||
if (file_offset >= 2048) {
|
||||
//text_debug_e.set("Read @ " + to_string_dec_uint(offset * 256 / 2000 / 4) + "ms ");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
text_debug_a.set("Read error");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +106,8 @@ void ADSBRxView::analyze(uint64_t offset) {
|
|||
if (decoding) {
|
||||
// Decode
|
||||
mark_color = Color::grey();
|
||||
|
||||
// 1 bit lasts 2 samples
|
||||
if (sample_count & 1) {
|
||||
if ((prev_mag < threshold_low) && (mag < threshold_low)) {
|
||||
// Both under window, silence.
|
||||
|
@ -117,7 +115,15 @@ void ADSBRxView::analyze(uint64_t offset) {
|
|||
if (null_count > 3) {
|
||||
text_debug_b.set("Bits:" + bits.substr(0, 25));
|
||||
text_debug_c.set("Hex:" + hex_str.substr(0, 26));
|
||||
text_debug_d.set("DF=" + to_string_dec_uint(adsb_frame[0] >> 3) + " ICAO=" + to_string_hex((adsb_frame[1] << 16) + (adsb_frame[2] << 8) + adsb_frame[3], 6));
|
||||
text_debug_d.set("DF=" + to_string_dec_uint(frame.get_DF()) + " ICAO=" + to_string_hex(frame.get_ICAO_address(), 6));
|
||||
if ((frame.get_DF() == 17) && (frame.get_msg_type() >= 1) && (frame.get_msg_type() <= 4)) {
|
||||
text_debug_a.set("Callsign:" + frame.get_callsign());
|
||||
return true;
|
||||
} else {
|
||||
text_debug_a.set("No ID data");
|
||||
return false;
|
||||
}
|
||||
|
||||
decoding = false;
|
||||
} else
|
||||
null_count++;
|
||||
|
@ -154,13 +160,13 @@ void ADSBRxView::analyze(uint64_t offset) {
|
|||
mark_color = bit ? Color::red() : Color::green();
|
||||
}
|
||||
|
||||
bits.append(bit ? "1" : "0");
|
||||
bits.append(bit ? "1" : "0"); // DEBUG
|
||||
byte = bit | (byte << 1);
|
||||
bit_count++;
|
||||
if (!(bit_count & 7)) {
|
||||
// Got one byte
|
||||
hex_str += to_string_hex(byte, 2);
|
||||
adsb_frame[frame_index++] = byte;
|
||||
hex_str += to_string_hex(byte, 2); // DEBUG
|
||||
frame.push_byte(byte);
|
||||
}
|
||||
}
|
||||
sample_count++;
|
||||
|
@ -168,25 +174,26 @@ void ADSBRxView::analyze(uint64_t offset) {
|
|||
// Look for preamble
|
||||
mark_color = Color::white();
|
||||
|
||||
// TODO: Stop using 2 separate shift registers for float and bit...
|
||||
for (c = 0; c < 15; c++)
|
||||
// Shift
|
||||
for (c = 0; c < (ADSB_PREAMBLE_LENGTH - 1); c++)
|
||||
shifter[c] = shifter[c + 1];
|
||||
shifter[15] = mag;
|
||||
shifter[15] = std::make_pair(mag, level);
|
||||
|
||||
for (c = 0; c < 15; c++)
|
||||
shifter_bits[c] = shifter_bits[c + 1];
|
||||
shifter_bits[15] = level;
|
||||
|
||||
if (!memcmp(shifter_bits, adsb_preamble, 16)) {
|
||||
// Compare
|
||||
for (c = 0; c < ADSB_PREAMBLE_LENGTH; c++) {
|
||||
if (shifter[c].second != adsb_preamble[c])
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == ADSB_PREAMBLE_LENGTH) {
|
||||
preamble_count++;
|
||||
if (preamble_count == 1) {
|
||||
// Try decoding the first frame found
|
||||
decoding = true;
|
||||
sample_count = 0;
|
||||
frame_index = 0;
|
||||
|
||||
// Compute preamble pulses power to set thresholds
|
||||
threshold = (shifter[0] + shifter[2] + shifter[7] + shifter[9]) / 4;
|
||||
threshold = (shifter[0].first + shifter[2].first + shifter[7].first + shifter[9].first) / 4;
|
||||
threshold_high = threshold * 1.414; // +3dB
|
||||
threshold_low = threshold * 0.707; // -3dB
|
||||
}
|
||||
|
@ -200,28 +207,29 @@ void ADSBRxView::analyze(uint64_t offset) {
|
|||
display.fill_rectangle({c * 4, 300, 4, 16}, shifter[c] ? Color::white() : Color::blue());
|
||||
}*/
|
||||
|
||||
if (lcd_y < 188) {
|
||||
mag *= 16;
|
||||
// Background
|
||||
display.fill_rectangle({lcd_x, 100 + lcd_y, 2, 32 - mag}, decoding ? mark_color : Color::grey());
|
||||
// Bar
|
||||
display.fill_rectangle({lcd_x, 132 + lcd_y - mag, 2, mag}, Color::white());
|
||||
// Level
|
||||
display.fill_rectangle({lcd_x, 132 + lcd_y, 2, 4}, decoding ? ((sample_count & 1) ? Color::white() : Color::light_grey()) : (level ? Color::white() : Color::dark_blue()));
|
||||
if (lcd_x == 238) {
|
||||
lcd_x = 0;
|
||||
lcd_y += 40;
|
||||
} else {
|
||||
lcd_x += 2;
|
||||
if (preamble_count) {
|
||||
if (lcd_y < 188) {
|
||||
mag *= 16;
|
||||
// Background
|
||||
display.fill_rectangle({lcd_x, 100 + lcd_y, 2, 32 - (int)mag}, decoding ? mark_color : Color::grey());
|
||||
// Bar
|
||||
display.fill_rectangle({lcd_x, 132 + lcd_y - (int)mag, 2, (int)mag}, Color::white());
|
||||
// Level
|
||||
display.fill_rectangle({lcd_x, 132 + lcd_y, 2, 4}, decoding ? ((sample_count & 1) ? Color::white() : Color::light_grey()) : (level ? Color::white() : Color::dark_blue()));
|
||||
if (lcd_x == 238) {
|
||||
lcd_x = 0;
|
||||
lcd_y += 40;
|
||||
} else {
|
||||
lcd_x += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
text_debug_a.set("Found " + to_string_dec_uint(preamble_count) + " preambles ");
|
||||
return false;
|
||||
}
|
||||
|
||||
ADSBRxView::ADSBRxView(NavigationView& nav) {
|
||||
uint32_t c;
|
||||
|
||||
//baseband::run_image(portapack::spi_flash::image_tag_adsb_rx);
|
||||
|
||||
|
@ -244,11 +252,16 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
|
|||
}
|
||||
|
||||
offset_field.on_change = [this, &nav](int32_t value) {
|
||||
analyze(value);
|
||||
// TODO
|
||||
};
|
||||
|
||||
button_ffw.on_select = [this, &nav](Button&) {
|
||||
offset_field.set_value(offset_field.value() + 1562);
|
||||
while (!analyze(f_offset)) {
|
||||
f_offset++;
|
||||
}
|
||||
offset_field.set_value(f_offset);
|
||||
f_offset++;
|
||||
//offset_field.set_value(offset_field.value() + 1562);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue