mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-14 10:37:44 +00:00
Significantly improved adsb demod
Change preamble detection, reduce cpu load
This commit is contained in:
@@ -34,68 +34,45 @@ void ADSBRXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
int8_t re, im;
|
||||
float mag;
|
||||
uint32_t c;
|
||||
uint8_t level, bit, byte { };
|
||||
//bool confidence;
|
||||
bool first_in_window, last_in_window;
|
||||
uint8_t bit, byte{};
|
||||
|
||||
// This is called at 2M/2048 = 977Hz
|
||||
// One pulse = 500ns = 2 samples
|
||||
// One bit = 2 pulses = 1us = 4 samples
|
||||
|
||||
|
||||
if (!configured) return;
|
||||
|
||||
for (size_t i = 0; i < buffer.count; i++) {
|
||||
|
||||
// Compute sample's magnitude
|
||||
re = buffer.p[i].real();
|
||||
im = buffer.p[i].imag();
|
||||
mag = __builtin_sqrtf((re * re) + (im * im)) * k;
|
||||
|
||||
// Only used for preamble detection and visualisation
|
||||
level = (mag < 0.3) ? 0 : // Blank weak signals
|
||||
(mag > prev_mag) ? 1 : 0;
|
||||
|
||||
re = buffer.p[i].real(); // make re float and scale it
|
||||
im = buffer.p[i].imag(); // make re float and scale it
|
||||
mag = ((re * re) + (im * im)) * (k*k);
|
||||
|
||||
if (decoding) {
|
||||
// Decode
|
||||
|
||||
// 1 bit lasts 2 samples
|
||||
if (sample_count & 1) {
|
||||
if ((prev_mag < threshold_low) && (mag < threshold_low)) {
|
||||
// Both under window, silence.
|
||||
if (null_count > 3) {
|
||||
const ADSBFrameMessage message(frame);
|
||||
shared_memory.application_queue.push(message);
|
||||
|
||||
decoding = false;
|
||||
} else
|
||||
null_count++;
|
||||
|
||||
//confidence = false;
|
||||
if (bit_count >= 112)
|
||||
{
|
||||
const ADSBFrameMessage message(frame);
|
||||
shared_memory.application_queue.push(message);
|
||||
decoding = false;
|
||||
|
||||
if (prev_mag > mag)
|
||||
bit = 1;
|
||||
else
|
||||
bit = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//confidence = true;
|
||||
if (prev_mag > mag)
|
||||
bit = 1;
|
||||
else
|
||||
bit = 0;
|
||||
|
||||
} else {
|
||||
|
||||
null_count = 0;
|
||||
|
||||
first_in_window = ((prev_mag >= threshold_low) && (prev_mag <= threshold_high));
|
||||
last_in_window = ((mag >= threshold_low) && (mag <= threshold_high));
|
||||
|
||||
if ((first_in_window && !last_in_window) || (!first_in_window && last_in_window)) {
|
||||
//confidence = true;
|
||||
if (prev_mag > mag)
|
||||
bit = 1;
|
||||
else
|
||||
bit = 0;
|
||||
} else {
|
||||
//confidence = false;
|
||||
if (prev_mag > mag)
|
||||
bit = 1;
|
||||
else
|
||||
bit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
byte = bit | (byte << 1);
|
||||
@@ -104,34 +81,66 @@ void ADSBRXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
// Got one byte
|
||||
frame.push_byte(byte);
|
||||
}
|
||||
}
|
||||
} // Second sample of each bit
|
||||
sample_count++;
|
||||
} else {
|
||||
// Look for preamble
|
||||
|
||||
// Shift
|
||||
// FIXSBT make this a ring buffer
|
||||
// FIXSBT store level in int16 for quick compare to preamble
|
||||
for (c = 0; c < (ADSB_PREAMBLE_LENGTH - 1); c++)
|
||||
{
|
||||
shifter[c] = shifter[c + 1];
|
||||
shifter[15] = std::make_pair(mag, level);
|
||||
}
|
||||
shifter[15] = mag;
|
||||
|
||||
// Compare
|
||||
for (c = 0; c < ADSB_PREAMBLE_LENGTH; c++) {
|
||||
if (shifter[c].second != adsb_preamble[c])
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == ADSB_PREAMBLE_LENGTH) {
|
||||
decoding = true;
|
||||
sample_count = 0;
|
||||
null_count = 0;
|
||||
bit_count = 0;
|
||||
frame.clear();
|
||||
|
||||
// Compute preamble pulses power to set thresholds
|
||||
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
|
||||
}
|
||||
// First check of relations between the first 10 samples
|
||||
// representing a valid preamble. We don't even investigate further
|
||||
// if this simple test is not passed
|
||||
if (shifter[0] > shifter[1] &&
|
||||
shifter[1] < shifter[2] &&
|
||||
shifter[2] > shifter[3] &&
|
||||
shifter[3] < shifter[0] &&
|
||||
shifter[4] < shifter[0] &&
|
||||
shifter[5] < shifter[0] &&
|
||||
shifter[6] < shifter[0] &&
|
||||
shifter[7] > shifter[8] &&
|
||||
shifter[8] < shifter[9] &&
|
||||
shifter[9] > shifter[6])
|
||||
{
|
||||
// The samples between the two spikes must be < than the average
|
||||
// of the high spikes level. We don't test bits too near to
|
||||
// the high levels as signals can be out of phase so part of the
|
||||
// energy can be in the near samples
|
||||
float high = (shifter[0] + shifter[2] + shifter[7] + shifter[9]) / 12;
|
||||
if (shifter[4] < high &&
|
||||
shifter[5] < high)
|
||||
{
|
||||
|
||||
// Similarly samples in the range 11-14 must be low, as it is the
|
||||
// space between the preamble and real data. Again we don't test
|
||||
// bits too near to high levels, see above
|
||||
if (shifter[11] < high &&
|
||||
shifter[12] < high &&
|
||||
shifter[13] < high &&
|
||||
shifter[14] < high)
|
||||
{
|
||||
//if (c == ADSB_PREAMBLE_LENGTH) {
|
||||
decoding = true;
|
||||
sample_count = 0;
|
||||
bit_count = 0;
|
||||
frame.clear();
|
||||
|
||||
// Compute preamble pulses power to set thresholds
|
||||
//threshold = (shifter[0] + shifter[2] + shifter[7] + shifter[9]) / 4;
|
||||
// FIXSBT other use max * 0.2
|
||||
// FIXSBT threshold_high and threshold_low should be ditched
|
||||
//threshold_high = threshold * 1.414f; // +3dB
|
||||
//threshold_low = threshold * 0.707f; // -3dB
|
||||
} // 11-14 low
|
||||
} // 4 & 5 high
|
||||
} // Check for preamble pattern
|
||||
}
|
||||
|
||||
prev_mag = mag;
|
||||
@@ -140,7 +149,6 @@ void ADSBRXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
|
||||
void ADSBRXProcessor::on_message(const Message* const message) {
|
||||
if (message->id == Message::ID::ADSBConfigure) {
|
||||
null_count = 0;
|
||||
bit_count = 0;
|
||||
sample_count = 0;
|
||||
decoding = false;
|
||||
@@ -148,8 +156,10 @@ void ADSBRXProcessor::on_message(const Message* const message) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<ADSBRXProcessor>() };
|
||||
event_dispatcher.run();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@@ -51,8 +51,10 @@ private:
|
||||
bool configured { false };
|
||||
float prev_mag { 0 };
|
||||
float threshold { }, threshold_low { }, threshold_high { };
|
||||
size_t null_count { 0 }, bit_count { 0 }, sample_count { 0 };
|
||||
std::pair<float, uint8_t> shifter[ADSB_PREAMBLE_LENGTH];
|
||||
//size_t null_count{ 0 };
|
||||
size_t bit_count { 0 }, sample_count { 0 };
|
||||
//std::pair<float, uint8_t> shifter[ADSB_PREAMBLE_LENGTH];
|
||||
float shifter[ADSB_PREAMBLE_LENGTH];
|
||||
bool decoding { };
|
||||
bool preamble { }, active { };
|
||||
uint16_t bit_pos { 0 };
|
||||
|
Reference in New Issue
Block a user