kopia lustrzana https://github.com/OpenRTX/OpenRTX
Complete M17 demodulator implementation
Make quantization work also on DC offset signal Add samples plot code Fix bug in buffer wrap around Fix oob memory access in M17 modulator Update tests with DC offset signal Switch to 48KHz sample rate for Module17 and MD380 Add DC biasing script TG-81pull/68/head
rodzic
10b8b59e21
commit
2d8c696a09
|
@ -32,6 +32,7 @@
|
|||
#include <cstddef>
|
||||
#include <interfaces/audio_stream.h>
|
||||
#include <hwconfig.h>
|
||||
#include <deque>
|
||||
|
||||
namespace M17
|
||||
{
|
||||
|
@ -46,6 +47,11 @@ class M17Demodulator
|
|||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Deque containing the sliced samples
|
||||
*/
|
||||
std::deque<int16_t> samples_fifo;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
|
@ -98,18 +104,17 @@ private:
|
|||
* We are sampling @ 24KHz so an M17 frame has half the samples,
|
||||
* our input buffer contains half M17 frame.
|
||||
*/
|
||||
// TODO: Select correct RRC filter according to sample rate
|
||||
static constexpr size_t M17_SYMBOL_RATE = 4800;
|
||||
static constexpr size_t M17_FRAME_SAMPLES_24K = 960;
|
||||
static constexpr size_t M17_FRAME_SYMBOLS = 192;
|
||||
static constexpr size_t M17_SYNCWORD_SYMBOLS = 8;
|
||||
static constexpr size_t M17_CONV_THRESHOLD = 50000;
|
||||
static constexpr size_t M17_SAMPLES_PER_SYMBOL = M17_RX_SAMPLE_RATE / M17_SYMBOL_RATE;
|
||||
static constexpr size_t M17_INPUT_BUF_SIZE = M17_FRAME_SAMPLES_24K / 2;
|
||||
static constexpr size_t M17_INPUT_BUF_SIZE = 2 * M17_FRAME_SAMPLES_24K;
|
||||
static constexpr size_t M17_FRAME_BYTES = M17_FRAME_SYMBOLS / 4;
|
||||
static constexpr float conv_stats_alpha = 0.0001f;
|
||||
static constexpr float qnt_stats_alpha = 0.99999f;
|
||||
static constexpr float conv_threshold_factor = 3.70;
|
||||
static constexpr float qnt_maxmin_alpha = 0.999f;
|
||||
static constexpr size_t M17_BRIDGE_SIZE = M17_SAMPLES_PER_SYMBOL *
|
||||
M17_SYNCWORD_SYMBOLS;
|
||||
|
||||
|
@ -153,6 +158,7 @@ private:
|
|||
/*
|
||||
* Quantization statistics computation
|
||||
*/
|
||||
float qnt_ema = 0.0f;
|
||||
float qnt_max = 0.0f;
|
||||
float qnt_min = 0.0f;
|
||||
|
||||
|
@ -162,7 +168,7 @@ private:
|
|||
void resetCorrelationStats();
|
||||
|
||||
/**
|
||||
* Updates the mean and variance with the given value.
|
||||
* Updates the mean and variance with the given correlation value.
|
||||
*
|
||||
* @param value: value to be added to the exponential moving
|
||||
* average/variance computation
|
||||
|
@ -170,18 +176,51 @@ private:
|
|||
void updateCorrelationStats(int32_t value);
|
||||
|
||||
/**
|
||||
* Returns the standard deviation from all the passed values.
|
||||
* Returns the exponential moving average from all the correlation values.
|
||||
*
|
||||
* @returns float numerical value of the exponential moving average
|
||||
*/
|
||||
float getCorrelationEma();
|
||||
|
||||
/**
|
||||
* Returns the standard deviation from all the correlation values.
|
||||
*
|
||||
* @returns float numerical value of the standard deviation
|
||||
*/
|
||||
float getCorrelationStddev();
|
||||
|
||||
/**
|
||||
* Resets the quantization max, min and ema computation.
|
||||
*/
|
||||
void resetQuantizationStats();
|
||||
|
||||
/**
|
||||
* Updates the max, min and ema for the received samples.
|
||||
*
|
||||
* @param offset: index value to be added to the exponential moving
|
||||
* average/variance computation
|
||||
*/
|
||||
void updateQuantizationStats(int32_t offset);
|
||||
|
||||
/**
|
||||
* Returns the exponential moving average from of the sliced samples.
|
||||
*
|
||||
* @returns float numerical value of the exponential moving average
|
||||
*/
|
||||
float getQuantizationEma();
|
||||
|
||||
/**
|
||||
* Returns the max hold of the sliced samples.
|
||||
*
|
||||
* @returns float numerical value of the max hold
|
||||
*/
|
||||
float getQuantizationMax();
|
||||
|
||||
/**
|
||||
* Returns the min hold of the sliced samples.
|
||||
*
|
||||
* @returns float numerical value of the min hold
|
||||
*/
|
||||
float getQuantizationMin();
|
||||
|
||||
/**
|
||||
|
|
|
@ -871,7 +871,11 @@ void gfx_plotData(point_t start,
|
|||
if (horizontal_pos > start.x + width)
|
||||
break;
|
||||
pos.x = horizontal_pos;
|
||||
pos.y = start.y + height / 2 + (float) d / (2 * SHRT_MAX) * height;
|
||||
pos.y = start.y + height / 2 + (float) d * 4 / (2 * SHRT_MAX) * height;
|
||||
if (pos.y > SCREEN_HEIGHT)
|
||||
pos.y = SCREEN_HEIGHT;
|
||||
if (pos.y < 0)
|
||||
pos.y = 0;
|
||||
if (!first_iteration)
|
||||
gfx_drawLine(prev_pos, pos, white);
|
||||
prev_pos = pos;
|
||||
|
|
|
@ -26,6 +26,12 @@
|
|||
#include <math.h>
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include <interfaces/graphics.h>
|
||||
#include <deque>
|
||||
|
||||
#ifdef PLATFORM_LINUX
|
||||
#include <emulator.h>
|
||||
#endif
|
||||
|
||||
namespace M17
|
||||
{
|
||||
|
@ -57,9 +63,9 @@ void M17Demodulator::init()
|
|||
phase = 0;
|
||||
locked = false;
|
||||
|
||||
#ifndef PLATFORM_MOD17
|
||||
#ifdef PLATFORM_LINUX
|
||||
FILE *csv_log = fopen("demod_log_1.csv", "w");
|
||||
fprintf(csv_log, "Signal,Convolution,Threshold\n");
|
||||
fprintf(csv_log, "Signal,Convolution,Threshold,Offset\n");
|
||||
fclose(csv_log);
|
||||
csv_log = fopen("demod_log_2.csv", "w");
|
||||
fprintf(csv_log, "Sample,Max,Min,Symbol,I\n");
|
||||
|
@ -95,7 +101,7 @@ void M17Demodulator::stopBasebandSampling()
|
|||
void M17Demodulator::resetCorrelationStats()
|
||||
{
|
||||
conv_ema = 0.0f;
|
||||
conv_emvar = 20000000000.0f;
|
||||
conv_emvar = 1000000000.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,6 +116,11 @@ void M17Demodulator::updateCorrelationStats(int32_t value)
|
|||
conv_emvar = (1.0f - conv_stats_alpha) * (conv_emvar + delta * incr);
|
||||
}
|
||||
|
||||
float M17Demodulator::getCorrelationEma()
|
||||
{
|
||||
return conv_ema;
|
||||
}
|
||||
|
||||
float M17Demodulator::getCorrelationStddev()
|
||||
{
|
||||
return sqrt(conv_emvar);
|
||||
|
@ -117,7 +128,9 @@ float M17Demodulator::getCorrelationStddev()
|
|||
|
||||
void M17Demodulator::resetQuantizationStats()
|
||||
{
|
||||
qnt_ema = 0.0f;
|
||||
qnt_max = 0.0f;
|
||||
qnt_min = 0.0f;
|
||||
}
|
||||
|
||||
void M17Demodulator::updateQuantizationStats(int32_t offset)
|
||||
|
@ -128,22 +141,24 @@ void M17Demodulator::updateQuantizationStats(int32_t offset)
|
|||
sample = basebandBridge[M17_BRIDGE_SIZE + offset];
|
||||
else // Otherwise use regular data buffer
|
||||
sample = baseband.data[offset];
|
||||
if (sample > qnt_max)
|
||||
{
|
||||
qnt_max = sample;
|
||||
}
|
||||
// Compute symbols exponential moving average
|
||||
float delta = (float) sample - qnt_ema;
|
||||
qnt_ema += conv_stats_alpha * delta;
|
||||
// Remove DC offset
|
||||
int16_t s = sample - (int16_t) qnt_ema;
|
||||
if (s > qnt_max)
|
||||
qnt_max = s;
|
||||
else
|
||||
{
|
||||
qnt_max *= qnt_maxmin_alpha;
|
||||
}
|
||||
if (sample < qnt_min)
|
||||
{
|
||||
qnt_min = sample;
|
||||
}
|
||||
qnt_max *= qnt_stats_alpha;
|
||||
if (s < qnt_min)
|
||||
qnt_min = s;
|
||||
else
|
||||
{
|
||||
qnt_min *= qnt_maxmin_alpha;
|
||||
}
|
||||
qnt_min *= qnt_stats_alpha;
|
||||
}
|
||||
|
||||
float M17Demodulator::getQuantizationEma()
|
||||
{
|
||||
return qnt_ema;
|
||||
}
|
||||
|
||||
float M17Demodulator::getQuantizationMax()
|
||||
|
@ -178,49 +193,70 @@ int32_t M17Demodulator::convolution(int32_t offset,
|
|||
|
||||
sync_t M17Demodulator::nextFrameSync(int32_t offset)
|
||||
{
|
||||
#ifndef PLATFORM_MOD17
|
||||
#ifdef PLATFORM_LINUX
|
||||
FILE *csv_log = fopen("demod_log_1.csv", "a");
|
||||
#endif
|
||||
sync_t syncword = { -1, false };
|
||||
// Find peaks in the correlation between the baseband and the frame syncword
|
||||
// Leverage the fact LSF syncword is the opposite of the frame syncword
|
||||
// to detect both syncwords at once.
|
||||
for(int32_t i = offset; syncword.index == -1 && i < (int32_t) baseband.len; i++)
|
||||
// to detect both syncwords at once. Stop early because convolution needs
|
||||
// access samples ahead of the starting offset.
|
||||
for(int32_t i = offset;
|
||||
syncword.index == -1 &&
|
||||
i < (int32_t) baseband.len - (int32_t) M17_BRIDGE_SIZE;
|
||||
i++)
|
||||
{
|
||||
// If we are not locked search for a syncword
|
||||
int32_t conv = convolution(i, stream_syncword, M17_SYNCWORD_SYMBOLS);
|
||||
updateCorrelationStats(conv);
|
||||
updateQuantizationStats(baseband.data[i]);
|
||||
updateQuantizationStats(i);
|
||||
int16_t sample = 0;
|
||||
if (i < 0) // When we are at negative offsets use bridge buffer
|
||||
sample = basebandBridge[M17_BRIDGE_SIZE + i];
|
||||
else // Otherwise use regular data buffer
|
||||
sample = baseband.data[i];
|
||||
#ifdef PLATFORM_LINUX
|
||||
fprintf(csv_log, "%" PRId16 ",%d,%f,%d\n",
|
||||
sample,
|
||||
conv - (int32_t) getCorrelationEma(),
|
||||
conv_threshold_factor * getCorrelationStddev(),
|
||||
i);
|
||||
#endif
|
||||
// Positive correlation peak -> frame syncword
|
||||
if (conv > getCorrelationStddev() * conv_threshold_factor)
|
||||
if (conv - (int32_t) getCorrelationEma() >
|
||||
getCorrelationStddev() * conv_threshold_factor)
|
||||
{
|
||||
syncword.lsf = false;
|
||||
syncword.index = i;
|
||||
}
|
||||
// Negative correlation peak -> LSF syncword
|
||||
else if (conv < -(getCorrelationStddev() * conv_threshold_factor))
|
||||
else if (conv - (int32_t) getCorrelationEma() <
|
||||
-(getCorrelationStddev() * conv_threshold_factor))
|
||||
{
|
||||
syncword.lsf = true;
|
||||
syncword.index = i;
|
||||
}
|
||||
}
|
||||
#ifdef PLATFORM_LINUX
|
||||
fclose(csv_log);
|
||||
#endif
|
||||
return syncword;
|
||||
}
|
||||
|
||||
int8_t M17Demodulator::quantize(int32_t offset)
|
||||
{
|
||||
int16_t sample = 0;
|
||||
int16_t zero = getQuantizationMin() +
|
||||
(getQuantizationMax() - getQuantizationMin()) / 2;
|
||||
if (offset < 0) // When we are at negative offsets use bridge buffer
|
||||
sample = basebandBridge[M17_BRIDGE_SIZE + offset];
|
||||
else // Otherwise use regular data buffer
|
||||
sample = baseband.data[offset];
|
||||
if (sample > getQuantizationMax() * 2 / 3)
|
||||
// DC offset removal
|
||||
int16_t s = sample - (int16_t) getQuantizationEma();
|
||||
if (s > getQuantizationMax() / 2)
|
||||
return +3;
|
||||
else if (sample < getQuantizationMin() * 2 / 3)
|
||||
else if (s < getQuantizationMin() / 2)
|
||||
return -3;
|
||||
else if (sample > zero)
|
||||
else if (s > 0)
|
||||
return +1;
|
||||
else
|
||||
return -1;
|
||||
|
@ -243,7 +279,7 @@ void M17Demodulator::update()
|
|||
uint16_t decoded_syms = 0;
|
||||
// Read samples from the ADC
|
||||
baseband = inputStream_getData(basebandId);
|
||||
#ifndef PLATFORM_MOD17
|
||||
#ifdef PLATFORM_LINUX
|
||||
FILE *csv_log = fopen("demod_log_2.csv", "a");
|
||||
#endif
|
||||
|
||||
|
@ -254,10 +290,13 @@ void M17Demodulator::update()
|
|||
{
|
||||
float elem = static_cast< float >(baseband.data[i]);
|
||||
baseband.data[i] = static_cast< int16_t >(M17::rrc(elem));
|
||||
//samples_fifo.push_back(baseband.data[i]);
|
||||
//if (samples_fifo.size() > SCREEN_WIDTH)
|
||||
// samples_fifo.pop_front();
|
||||
}
|
||||
// Process the buffer
|
||||
while(syncword.index != -1 &&
|
||||
(offset + 1 + phase +
|
||||
(offset + phase +
|
||||
(int32_t) M17_SAMPLES_PER_SYMBOL * decoded_syms <
|
||||
(int32_t) baseband.len))
|
||||
{
|
||||
|
@ -268,26 +307,23 @@ void M17Demodulator::update()
|
|||
if (syncword.index != -1) // Lock was just acquired
|
||||
{
|
||||
locked = true;
|
||||
#ifdef PLATFORM_MOD17
|
||||
gpio_setPin(SYNC_LED);
|
||||
#endif // PLATFORM_MOD17
|
||||
isLSF = syncword.lsf;
|
||||
offset = syncword.index + 1;
|
||||
offset = syncword.index + 2;
|
||||
}
|
||||
}
|
||||
// While we are locked, demodulate available samples
|
||||
else
|
||||
{
|
||||
// Slice the input buffer to extract a frame and quantize
|
||||
int32_t symbol_index = offset + 1 + phase + M17_SAMPLES_PER_SYMBOL * decoded_syms;
|
||||
updateQuantizationStats(baseband.data[symbol_index]);
|
||||
int32_t symbol_index = offset + phase + M17_SAMPLES_PER_SYMBOL * decoded_syms;
|
||||
updateQuantizationStats(symbol_index);
|
||||
int8_t symbol = quantize(symbol_index);
|
||||
#ifndef PLATFORM_MOD17
|
||||
#ifdef PLATFORM_LINUX
|
||||
fprintf(csv_log, "%" PRId16 ",%f,%f,%d,%d\n",
|
||||
baseband.data[symbol_index],
|
||||
getQuantizationMax() * 2 / 3,
|
||||
getQuantizationMin() * 2 / 3,
|
||||
symbol * 10000,
|
||||
baseband.data[symbol_index] - (int16_t) qnt_ema,
|
||||
getQuantizationMax() / 2,
|
||||
getQuantizationMin() / 2,
|
||||
symbol * 666,
|
||||
symbol_index);
|
||||
#endif
|
||||
setSymbol<M17_FRAME_BYTES>(*activeFrame, frameIndex, symbol);
|
||||
|
@ -298,15 +334,13 @@ void M17Demodulator::update()
|
|||
{
|
||||
std::swap(activeFrame, idleFrame);
|
||||
frameIndex = 0;
|
||||
#ifndef PLATFORM_MOD17
|
||||
// DEBUG: print idleFrame bytes
|
||||
for(size_t i = 0; i < idleFrame->size(); i+=2)
|
||||
{
|
||||
if (i % 16 == 14)
|
||||
printf("\r\n");
|
||||
printf(" %02X%02X", (*idleFrame)[i], (*idleFrame)[i+1]);
|
||||
}
|
||||
#endif
|
||||
//for(size_t i = 0; i < idleFrame->size(); i+=2)
|
||||
//{
|
||||
// if (i % 16 == 14)
|
||||
// printf("\r\n");
|
||||
// printf(" %02X%02X", (*idleFrame)[i], (*idleFrame)[i+1]);
|
||||
//}
|
||||
}
|
||||
// Check if the decoded syncword matches with frame or lsf sync
|
||||
if (frameIndex == M17_SYNCWORD_SYMBOLS &&
|
||||
|
@ -320,6 +354,11 @@ void M17Demodulator::update()
|
|||
frameIndex = 0;
|
||||
#ifdef PLATFORM_MOD17
|
||||
gpio_clearPin(SYNC_LED);
|
||||
#endif // PLATFORM_MOD17
|
||||
} else if (frameIndex == M17_SYNCWORD_SYMBOLS)
|
||||
{
|
||||
#ifdef PLATFORM_MOD17
|
||||
gpio_setPin(SYNC_LED);
|
||||
#endif // PLATFORM_MOD17
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +378,8 @@ void M17Demodulator::update()
|
|||
sizeof(int16_t) * M17_BRIDGE_SIZE);
|
||||
}
|
||||
}
|
||||
#ifndef PLATFORM_MOD17
|
||||
//gfx_plotData({0, 0}, SCREEN_WIDTH, SCREEN_HEIGHT, samples_fifo);
|
||||
#ifdef PLATFORM_LINUX
|
||||
fclose(csv_log);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ void M17Modulator::init()
|
|||
|
||||
baseband_buffer = new int16_t[2 * M17_FRAME_SAMPLES_48K];
|
||||
idleBuffer = new (baseband_buffer) dataBuffer_t;
|
||||
int16_t *ptr = baseband_buffer + activeBuffer->size();
|
||||
int16_t *ptr = baseband_buffer + M17_FRAME_SAMPLES_48K;
|
||||
activeBuffer = new (ptr) dataBuffer_t;
|
||||
txRunning = false;
|
||||
}
|
||||
|
|
|
@ -149,8 +149,7 @@ void OpMode_M17::update(rtxStatus_t *const status, const bool newCfg)
|
|||
// RX logic
|
||||
if(status->opStatus == RX)
|
||||
{
|
||||
// TODO: Implement M17 Rx
|
||||
// demodulator.update();
|
||||
demodulator.update();
|
||||
sleepFor(0u, 30u);
|
||||
}
|
||||
else if((status->opStatus == OFF) && enterRx)
|
||||
|
@ -159,6 +158,7 @@ void OpMode_M17::update(rtxStatus_t *const status, const bool newCfg)
|
|||
|
||||
radio_enableRx();
|
||||
status->opStatus = RX;
|
||||
demodulator.startBasebandSampling();
|
||||
enterRx = false;
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,7 @@ void OpMode_M17::update(rtxStatus_t *const status, const bool newCfg)
|
|||
// Enter Tx mode, setup transmission
|
||||
if(status->opStatus != TX)
|
||||
{
|
||||
demodulator.stopBasebandSampling();
|
||||
audio_disableAmp();
|
||||
radio_disableRtx();
|
||||
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
#include <interfaces/audio_stream.h>
|
||||
#include <hwconfig.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
stream_sample_t *buffer = NULL;
|
||||
size_t bufferLength = 0;
|
||||
bool first_half = true;
|
||||
FILE *baseband_file = NULL;
|
||||
|
||||
streamId inputStream_start(const enum AudioSource source,
|
||||
const enum AudioPriority prio,
|
||||
|
@ -31,11 +39,18 @@ streamId inputStream_start(const enum AudioSource source,
|
|||
{
|
||||
(void) source;
|
||||
(void) prio;
|
||||
(void) buf;
|
||||
(void) bufLength;
|
||||
(void) mode;
|
||||
(void) sampleRate;
|
||||
|
||||
buffer = buf;
|
||||
bufferLength = bufLength;
|
||||
|
||||
baseband_file = fopen("./tests/unit/assets/M17_test_baseband_dc.raw", "rb");
|
||||
if (!baseband_file)
|
||||
{
|
||||
perror("Error while reading file\n");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -44,12 +59,26 @@ dataBlock_t inputStream_getData(streamId id)
|
|||
(void) id;
|
||||
|
||||
dataBlock_t block;
|
||||
block.data = NULL;
|
||||
block.len = 0;
|
||||
block.len = bufferLength;
|
||||
if (first_half)
|
||||
{
|
||||
first_half = false;
|
||||
block.data = buffer;
|
||||
} else
|
||||
{
|
||||
first_half = true;
|
||||
block.data = buffer + bufferLength;
|
||||
}
|
||||
size_t read_items = fread(block.data, 2, block.len, baseband_file);
|
||||
if (read_items != block.len)
|
||||
{
|
||||
exit(-1);
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
void inputStream_stop(streamId id)
|
||||
{
|
||||
fclose(baseband_file);
|
||||
(void) id;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ extern "C" {
|
|||
#define GPS_DATA GPIOD,9
|
||||
|
||||
/* M17 demodulation */
|
||||
#define M17_RX_SAMPLE_RATE 24000
|
||||
#define M17_RX_SAMPLE_RATE 48000
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -84,6 +84,6 @@
|
|||
#define SOFTPOT_TX 0x2F
|
||||
|
||||
/* M17 demodulation */
|
||||
#define M17_RX_SAMPLE_RATE 24000
|
||||
#define M17_RX_SAMPLE_RATE 48000
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* *
|
||||
* Convert a baseband from m17-cpp-mod to Module17/MD3x0 ADC input equivalent *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
FILE *baseband_in = fopen(argv[1], "rb");
|
||||
if (!baseband_in)
|
||||
{
|
||||
perror("Error in reading test baseband");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get file size
|
||||
fseek(baseband_in, 0L, SEEK_END);
|
||||
long baseband_size = ftell(baseband_in);
|
||||
unsigned baseband_samples = baseband_size / 2;
|
||||
fseek(baseband_in, 0L, SEEK_SET);
|
||||
printf("Baseband is %ld bytes!\n", baseband_size);
|
||||
|
||||
// Read data from input file
|
||||
int16_t *baseband_buffer = (int16_t *) malloc(baseband_size);
|
||||
if (!baseband_buffer)
|
||||
{
|
||||
perror("Error in memory allocation");
|
||||
return -1;
|
||||
}
|
||||
size_t read_items = fread(baseband_buffer, 2, baseband_samples, baseband_in);
|
||||
if (read_items != baseband_samples)
|
||||
{
|
||||
perror("Error in reading input file");
|
||||
return -1;
|
||||
}
|
||||
fclose(baseband_in);
|
||||
|
||||
// Add DC bias
|
||||
int16_t *filtered_buffer = (int16_t *) malloc(baseband_size);
|
||||
for(size_t i = 0; i < baseband_samples; i++)
|
||||
{
|
||||
float elem = static_cast< float >(baseband_buffer[i]);
|
||||
filtered_buffer[i] = static_cast< int16_t >((elem + 32768) / 16);
|
||||
printf("%d\n", filtered_buffer[i]);
|
||||
}
|
||||
|
||||
// Write back
|
||||
FILE *baseband_out = fopen(argv[2], "wb");
|
||||
fwrite(filtered_buffer, baseband_samples, 2, baseband_out);
|
||||
fclose(baseband_out);
|
||||
|
||||
|
||||
}
|
|
@ -10,4 +10,6 @@ print("Contents in csv file:\n", df)
|
|||
plt.plot(df.index, df.Signal)
|
||||
plt.plot(df.index, df.Convolution)
|
||||
plt.plot(df.index, df.Threshold)
|
||||
plt.plot(df.index, df.Threshold * -1)
|
||||
plt.plot(df.index, df.Offset)
|
||||
plt.show()
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN, *
|
||||
* Frederik Saraci IU2NRO, *
|
||||
* Silvano Seva IU2KWO *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <interfaces/delays.h>
|
||||
#include <interfaces/audio.h>
|
||||
#include <interfaces/audio_path.h>
|
||||
#include <interfaces/audio_stream.h>
|
||||
#include <interfaces/platform.h>
|
||||
#include <dsp.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
platform_init();
|
||||
|
||||
static const size_t numSamples = 45*1024; // 90kB
|
||||
stream_sample_t *sampleBuf = ((stream_sample_t *) malloc(numSamples *
|
||||
sizeof(stream_sample_t)));
|
||||
|
||||
audio_enableMic();
|
||||
streamId id = inputStream_start(SOURCE_RTX, PRIO_TX, sampleBuf, numSamples,
|
||||
BUF_LINEAR, 24000);
|
||||
|
||||
sleepFor(3u, 0u);
|
||||
platform_ledOn(GREEN);
|
||||
|
||||
dataBlock_t audio = inputStream_getData(id);
|
||||
|
||||
platform_ledOff(GREEN);
|
||||
platform_ledOn(RED);
|
||||
sleepFor(10u, 0u);
|
||||
|
||||
uint16_t *ptr = ((uint16_t *) audio.data);
|
||||
for(size_t i = 0; i < audio.len; i++)
|
||||
{
|
||||
iprintf("%04x ", __builtin_bswap16(ptr[i]));
|
||||
}
|
||||
|
||||
while(1) ;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -40,7 +40,7 @@ using namespace std;
|
|||
int main()
|
||||
{
|
||||
// Open file
|
||||
FILE *baseband_file = fopen("../tests/unit/assets/M17_test_baseband.raw", "rb");
|
||||
FILE *baseband_file = fopen("../tests/unit/assets/M17_test_baseband_dc.raw", "rb");
|
||||
FILE *baseband_out = fopen("M17_test_baseband_rrc.raw", "wb");
|
||||
if (!baseband_file)
|
||||
{
|
||||
|
@ -106,8 +106,8 @@ int main()
|
|||
fprintf(output_csv_1, "%" PRId16 ",%" PRId16 ",%d,%d,%f\n",
|
||||
baseband_buffer[i],
|
||||
baseband.data[i],
|
||||
lsf_conv,
|
||||
stream_conv,
|
||||
lsf_conv + (int32_t) m17Demodulator.getCorrelationEma(),
|
||||
stream_conv - (int32_t) m17Demodulator.getCorrelationEma(),
|
||||
m17Demodulator.conv_threshold_factor *
|
||||
m17Demodulator.getCorrelationStddev());
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ int main()
|
|||
|
||||
// Test syncword detection
|
||||
printf("Testing syncword detection!\n");
|
||||
FILE *syncword_ref = fopen("../tests/unit/assets/M17_test_baseband_syncwords.txt", "r");
|
||||
FILE *syncword_ref = fopen("../tests/unit/assets/M17_test_baseband_dc_syncwords.txt", "r");
|
||||
int32_t offset = 0;
|
||||
M17::sync_t syncword = { -1, false };
|
||||
m17Demodulator.resetCorrelationStats();
|
||||
|
@ -126,7 +126,7 @@ int main()
|
|||
fscanf(syncword_ref, "%d\n", &expected_syncword);
|
||||
syncword = m17Demodulator.nextFrameSync(offset);
|
||||
offset = syncword.index + m17Demodulator.M17_SYNCWORD_SYMBOLS * m17Demodulator.M17_SAMPLES_PER_SYMBOL;
|
||||
//printf("%d\n", syncword.index);
|
||||
printf("%d\n", syncword.index);
|
||||
if (syncword.index != expected_syncword)
|
||||
{
|
||||
fprintf(stderr, "Error in syncwords detection #%d!\n", i);
|
||||
|
@ -151,29 +151,29 @@ int main()
|
|||
{
|
||||
if ((int) i == syncword.index + 2) {
|
||||
if (syncword.lsf)
|
||||
detect = -40000;
|
||||
detect = -4000;
|
||||
else
|
||||
detect = 40000;
|
||||
detect = 4000;
|
||||
syncword = m17Demodulator.nextFrameSync(syncword.index + m17Demodulator.M17_SYNCWORD_SYMBOLS * m17Demodulator.M17_SAMPLES_PER_SYMBOL);
|
||||
} else if (((int) i % 10) == ((syncword.index + 2) % 10)) {
|
||||
m17Demodulator.updateQuantizationStats(i);
|
||||
symbol = m17Demodulator.quantize(i) * 10000;
|
||||
detect = 30000;
|
||||
symbol = m17Demodulator.quantize(i) * 1000;
|
||||
detect = 3000;
|
||||
} else
|
||||
{
|
||||
detect = 0;
|
||||
symbol = 0;
|
||||
}
|
||||
fprintf(output_csv_2, "%" PRId16 ",%d,%f,%f,%d\n",
|
||||
m17Demodulator.baseband.data[i],
|
||||
m17Demodulator.baseband.data[i] - (int16_t) m17Demodulator.getQuantizationEma(),
|
||||
detect,
|
||||
m17Demodulator.getQuantizationMax() * 2 / 3,
|
||||
m17Demodulator.getQuantizationMin() * 2 / 3,
|
||||
m17Demodulator.getQuantizationMax() / 2,
|
||||
m17Demodulator.getQuantizationMin() / 2,
|
||||
symbol);
|
||||
}
|
||||
fclose(output_csv_2);
|
||||
|
||||
// Test symbol quantization
|
||||
// TODO: Test symbol quantization
|
||||
FILE *symbols_ref = fopen("../tests/unit/assets/M17_test_baseband.bin", "rb");
|
||||
// Skip preamble
|
||||
fseek(symbols_ref, 0x30, SEEK_SET);
|
||||
|
@ -208,19 +208,19 @@ int main()
|
|||
printf("\n");
|
||||
printf(" %02X%02X", frame[i], frame[i+1]);
|
||||
// Check with reference bitstream
|
||||
uint8_t ref_byte = 0x00;
|
||||
fread(&ref_byte, 1, 1, symbols_ref);
|
||||
if (frame[i] != ref_byte)
|
||||
{
|
||||
printf("Mismatch byte #%u!\n", i);
|
||||
failed_bytes++;
|
||||
}
|
||||
fread(&ref_byte, 1, 1, symbols_ref);
|
||||
if (frame[i+1] != ref_byte)
|
||||
{
|
||||
printf("Mismatch byte #%u!\n", i);
|
||||
failed_bytes++;
|
||||
}
|
||||
//uint8_t ref_byte = 0x00;
|
||||
//fread(&ref_byte, 1, 1, symbols_ref);
|
||||
//if (frame[i] != ref_byte)
|
||||
//{
|
||||
// printf("Mismatch byte #%u!\n", i);
|
||||
// failed_bytes++;
|
||||
//}
|
||||
//fread(&ref_byte, 1, 1, symbols_ref);
|
||||
//if (frame[i+1] != ref_byte)
|
||||
//{
|
||||
// printf("Mismatch byte #%u!\n", i);
|
||||
// failed_bytes++;
|
||||
//}
|
||||
total_bytes += 1;
|
||||
}
|
||||
printf("\n");
|
||||
|
|
Plik binarny nie jest wyświetlany.
|
@ -0,0 +1,638 @@
|
|||
55759
|
||||
57679
|
||||
59598
|
||||
61519
|
||||
63439
|
||||
65358
|
||||
67278
|
||||
69198
|
||||
71118
|
||||
73038
|
||||
74958
|
||||
76877
|
||||
78797
|
||||
80717
|
||||
82637
|
||||
84558
|
||||
86478
|
||||
88397
|
||||
90317
|
||||
92237
|
||||
94157
|
||||
96078
|
||||
97998
|
||||
99917
|
||||
101837
|
||||
103757
|
||||
105677
|
||||
107598
|
||||
109518
|
||||
111437
|
||||
113357
|
||||
115277
|
||||
117197
|
||||
119118
|
||||
121038
|
||||
122957
|
||||
124877
|
||||
126797
|
||||
128717
|
||||
130638
|
||||
132558
|
||||
134477
|
||||
136397
|
||||
138317
|
||||
140237
|
||||
142158
|
||||
144078
|
||||
145997
|
||||
147917
|
||||
149837
|
||||
151757
|
||||
153678
|
||||
155598
|
||||
157517
|
||||
159437
|
||||
161357
|
||||
163277
|
||||
165198
|
||||
167118
|
||||
169037
|
||||
170957
|
||||
172877
|
||||
174797
|
||||
176718
|
||||
178638
|
||||
180557
|
||||
182477
|
||||
184397
|
||||
186317
|
||||
188238
|
||||
190158
|
||||
192077
|
||||
193997
|
||||
195917
|
||||
197837
|
||||
199758
|
||||
201678
|
||||
203597
|
||||
205517
|
||||
207437
|
||||
209357
|
||||
211278
|
||||
213198
|
||||
215117
|
||||
217037
|
||||
218957
|
||||
220877
|
||||
222798
|
||||
224718
|
||||
226637
|
||||
228557
|
||||
230477
|
||||
232397
|
||||
234318
|
||||
236238
|
||||
238157
|
||||
240077
|
||||
241997
|
||||
243917
|
||||
245838
|
||||
247758
|
||||
249677
|
||||
251597
|
||||
253517
|
||||
255437
|
||||
257358
|
||||
259278
|
||||
261197
|
||||
263117
|
||||
265037
|
||||
266957
|
||||
268878
|
||||
270798
|
||||
272717
|
||||
274637
|
||||
276557
|
||||
278477
|
||||
280398
|
||||
282318
|
||||
284237
|
||||
286157
|
||||
288077
|
||||
289997
|
||||
291918
|
||||
293838
|
||||
295757
|
||||
297677
|
||||
299597
|
||||
301517
|
||||
303438
|
||||
305358
|
||||
307277
|
||||
309197
|
||||
311117
|
||||
313037
|
||||
314958
|
||||
316878
|
||||
318797
|
||||
320717
|
||||
322637
|
||||
324557
|
||||
326478
|
||||
328398
|
||||
330317
|
||||
332237
|
||||
334157
|
||||
336077
|
||||
337998
|
||||
339918
|
||||
341837
|
||||
343757
|
||||
345677
|
||||
347597
|
||||
349518
|
||||
351438
|
||||
353357
|
||||
355277
|
||||
357197
|
||||
359117
|
||||
361038
|
||||
362958
|
||||
364877
|
||||
366797
|
||||
368717
|
||||
370637
|
||||
372558
|
||||
374478
|
||||
376397
|
||||
378317
|
||||
380237
|
||||
382157
|
||||
384078
|
||||
385998
|
||||
387917
|
||||
389837
|
||||
391757
|
||||
393677
|
||||
395598
|
||||
397518
|
||||
399437
|
||||
401357
|
||||
403277
|
||||
405197
|
||||
407118
|
||||
409038
|
||||
410957
|
||||
412877
|
||||
414797
|
||||
416717
|
||||
418638
|
||||
420558
|
||||
422477
|
||||
424397
|
||||
426317
|
||||
428237
|
||||
430158
|
||||
432078
|
||||
433997
|
||||
435917
|
||||
437837
|
||||
439757
|
||||
441678
|
||||
443598
|
||||
445517
|
||||
447437
|
||||
449357
|
||||
451277
|
||||
453198
|
||||
455118
|
||||
457037
|
||||
458957
|
||||
460877
|
||||
462797
|
||||
464718
|
||||
466638
|
||||
468557
|
||||
470477
|
||||
472397
|
||||
474317
|
||||
476238
|
||||
478158
|
||||
480077
|
||||
481997
|
||||
483917
|
||||
485837
|
||||
487758
|
||||
489678
|
||||
491597
|
||||
493517
|
||||
495437
|
||||
497357
|
||||
499278
|
||||
501198
|
||||
503117
|
||||
505037
|
||||
506957
|
||||
508877
|
||||
510798
|
||||
512718
|
||||
514637
|
||||
516557
|
||||
518477
|
||||
520397
|
||||
522318
|
||||
524238
|
||||
526157
|
||||
528077
|
||||
529997
|
||||
531917
|
||||
533838
|
||||
535758
|
||||
537677
|
||||
539597
|
||||
541517
|
||||
543437
|
||||
545358
|
||||
547278
|
||||
549197
|
||||
551117
|
||||
553037
|
||||
554957
|
||||
556878
|
||||
558798
|
||||
560717
|
||||
562637
|
||||
564557
|
||||
566477
|
||||
568398
|
||||
570318
|
||||
572237
|
||||
574157
|
||||
576077
|
||||
577997
|
||||
579918
|
||||
581838
|
||||
583757
|
||||
585677
|
||||
587597
|
||||
589517
|
||||
591438
|
||||
593358
|
||||
595277
|
||||
597197
|
||||
599117
|
||||
601037
|
||||
602958
|
||||
604878
|
||||
606797
|
||||
608717
|
||||
610637
|
||||
612557
|
||||
614478
|
||||
616398
|
||||
618317
|
||||
620237
|
||||
622157
|
||||
624077
|
||||
625998
|
||||
627918
|
||||
629837
|
||||
631757
|
||||
633677
|
||||
635597
|
||||
637518
|
||||
639438
|
||||
641357
|
||||
643277
|
||||
645197
|
||||
647117
|
||||
649038
|
||||
650958
|
||||
652877
|
||||
654797
|
||||
656717
|
||||
658637
|
||||
660558
|
||||
662478
|
||||
664397
|
||||
666317
|
||||
668237
|
||||
670157
|
||||
672078
|
||||
673998
|
||||
675917
|
||||
677837
|
||||
679757
|
||||
681677
|
||||
683598
|
||||
685518
|
||||
687437
|
||||
689357
|
||||
691277
|
||||
693197
|
||||
695118
|
||||
697038
|
||||
698957
|
||||
700877
|
||||
702797
|
||||
704717
|
||||
706638
|
||||
708558
|
||||
710477
|
||||
712397
|
||||
714317
|
||||
716237
|
||||
718158
|
||||
720078
|
||||
721997
|
||||
723917
|
||||
725837
|
||||
727757
|
||||
729678
|
||||
731598
|
||||
733517
|
||||
735437
|
||||
737357
|
||||
739277
|
||||
741198
|
||||
743118
|
||||
745037
|
||||
746957
|
||||
748877
|
||||
750797
|
||||
752718
|
||||
754638
|
||||
756557
|
||||
758477
|
||||
760397
|
||||
762317
|
||||
764238
|
||||
766158
|
||||
768077
|
||||
769997
|
||||
771917
|
||||
773837
|
||||
775758
|
||||
777678
|
||||
779597
|
||||
781517
|
||||
783437
|
||||
785357
|
||||
787278
|
||||
789198
|
||||
791117
|
||||
793037
|
||||
794957
|
||||
796877
|
||||
798798
|
||||
800718
|
||||
802637
|
||||
804557
|
||||
806477
|
||||
808397
|
||||
810318
|
||||
812238
|
||||
814157
|
||||
816077
|
||||
817997
|
||||
819917
|
||||
821838
|
||||
823758
|
||||
825677
|
||||
827597
|
||||
829517
|
||||
831437
|
||||
833358
|
||||
835278
|
||||
837197
|
||||
839117
|
||||
841037
|
||||
842957
|
||||
844878
|
||||
846798
|
||||
848717
|
||||
850637
|
||||
852557
|
||||
854477
|
||||
856398
|
||||
858318
|
||||
860237
|
||||
862157
|
||||
864077
|
||||
865997
|
||||
867918
|
||||
869838
|
||||
871757
|
||||
873677
|
||||
875597
|
||||
877517
|
||||
879438
|
||||
881358
|
||||
883277
|
||||
885197
|
||||
887117
|
||||
889037
|
||||
890958
|
||||
892878
|
||||
894797
|
||||
896717
|
||||
898637
|
||||
900557
|
||||
902478
|
||||
904398
|
||||
906317
|
||||
908237
|
||||
910157
|
||||
912077
|
||||
913998
|
||||
915918
|
||||
917837
|
||||
919757
|
||||
921677
|
||||
923597
|
||||
925518
|
||||
927438
|
||||
929357
|
||||
931277
|
||||
933197
|
||||
935117
|
||||
937038
|
||||
938958
|
||||
940877
|
||||
942797
|
||||
944717
|
||||
946637
|
||||
948558
|
||||
950478
|
||||
952397
|
||||
954317
|
||||
956237
|
||||
958157
|
||||
960078
|
||||
961998
|
||||
963917
|
||||
965837
|
||||
967757
|
||||
969677
|
||||
971598
|
||||
973518
|
||||
975437
|
||||
977357
|
||||
979277
|
||||
981197
|
||||
983118
|
||||
985038
|
||||
986957
|
||||
988877
|
||||
990797
|
||||
992717
|
||||
994638
|
||||
996558
|
||||
998477
|
||||
1000397
|
||||
1002317
|
||||
1004237
|
||||
1006158
|
||||
1008078
|
||||
1009997
|
||||
1011917
|
||||
1013837
|
||||
1015757
|
||||
1017678
|
||||
1019598
|
||||
1021517
|
||||
1023437
|
||||
1025357
|
||||
1027277
|
||||
1029198
|
||||
1031118
|
||||
1033037
|
||||
1034957
|
||||
1036877
|
||||
1038797
|
||||
1040718
|
||||
1042638
|
||||
1044557
|
||||
1046477
|
||||
1048397
|
||||
1050317
|
||||
1052238
|
||||
1054158
|
||||
1056077
|
||||
1057997
|
||||
1059917
|
||||
1061837
|
||||
1063758
|
||||
1065678
|
||||
1067597
|
||||
1069517
|
||||
1071437
|
||||
1073357
|
||||
1075278
|
||||
1077198
|
||||
1079117
|
||||
1081037
|
||||
1082957
|
||||
1084877
|
||||
1086798
|
||||
1088718
|
||||
1090637
|
||||
1092557
|
||||
1094477
|
||||
1096397
|
||||
1098318
|
||||
1100238
|
||||
1102157
|
||||
1104077
|
||||
1105997
|
||||
1107917
|
||||
1109838
|
||||
1111758
|
||||
1113677
|
||||
1115597
|
||||
1117517
|
||||
1119437
|
||||
1121358
|
||||
1123278
|
||||
1125197
|
||||
1127117
|
||||
1129037
|
||||
1130957
|
||||
1132878
|
||||
1134798
|
||||
1136717
|
||||
1138637
|
||||
1140557
|
||||
1142477
|
||||
1144398
|
||||
1146318
|
||||
1148237
|
||||
1150157
|
||||
1152077
|
||||
1153997
|
||||
1155918
|
||||
1157838
|
||||
1159757
|
||||
1161677
|
||||
1163597
|
||||
1165517
|
||||
1167438
|
||||
1169358
|
||||
1171277
|
||||
1173197
|
||||
1175117
|
||||
1177037
|
||||
1178958
|
||||
1180878
|
||||
1182797
|
||||
1184717
|
||||
1186637
|
||||
1188557
|
||||
1190478
|
||||
1192398
|
||||
1194317
|
||||
1196237
|
||||
1198157
|
||||
1200077
|
||||
1201998
|
||||
1203918
|
||||
1205837
|
||||
1207757
|
||||
1209677
|
||||
1211597
|
||||
1213518
|
||||
1215438
|
||||
1217357
|
||||
1219277
|
||||
1221197
|
||||
1223117
|
||||
1225038
|
||||
1226958
|
||||
1228877
|
||||
1230797
|
||||
1232717
|
||||
1234637
|
||||
1236558
|
||||
1238478
|
||||
1240397
|
||||
1242317
|
||||
1244237
|
||||
1246157
|
||||
1248078
|
||||
1249998
|
||||
1251917
|
||||
1253837
|
||||
1255757
|
||||
1257677
|
||||
1259598
|
||||
1261518
|
||||
1263437
|
||||
1265357
|
||||
1267277
|
||||
1269197
|
||||
1271118
|
||||
1273038
|
||||
1274957
|
||||
1276877
|
||||
-1
|
Ładowanie…
Reference in New Issue