kopia lustrzana https://github.com/OpenRTX/OpenRTX
238 wiersze
9.5 KiB
C++
238 wiersze
9.5 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2021 - 2023 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/> *
|
|
***************************************************************************/
|
|
|
|
// Test private methods
|
|
#define private public
|
|
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <M17/M17DSP.h>
|
|
#include <M17/M17Demodulator.h>
|
|
#include <M17/M17Utils.h>
|
|
#include <audio_stream.h>
|
|
|
|
using namespace std;
|
|
|
|
/**
|
|
* Test the different demodulation steps
|
|
*/
|
|
|
|
int main()
|
|
{
|
|
// Open file
|
|
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)
|
|
{
|
|
perror("Error in reading test baseband");
|
|
return -1;
|
|
}
|
|
|
|
// Get file size
|
|
fseek(baseband_file, 0L, SEEK_END);
|
|
long baseband_size = ftell(baseband_file);
|
|
unsigned baseband_samples = baseband_size / 2;
|
|
fseek(baseband_file, 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_file);
|
|
if (read_items != baseband_samples)
|
|
{
|
|
perror("Error in reading input file");
|
|
return -1;
|
|
}
|
|
fclose(baseband_file);
|
|
|
|
// Apply RRC on the baseband buffer
|
|
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 >(M17::rrc(elem));
|
|
}
|
|
fwrite(filtered_buffer, baseband_samples, 2, baseband_out);
|
|
fclose(baseband_out);
|
|
|
|
M17::M17Demodulator m17Demodulator = M17::M17Demodulator();
|
|
m17Demodulator.init();
|
|
dataBlock_t baseband = { nullptr, 0 };
|
|
baseband.data = filtered_buffer;
|
|
baseband.len = baseband_samples;
|
|
dataBlock_t old_baseband = m17Demodulator.baseband;
|
|
m17Demodulator.baseband = baseband;
|
|
|
|
FILE *output_csv_1 = fopen("M17_demodulator_output_1.csv", "w");
|
|
fprintf(output_csv_1, "Input,RRCSignal,LSFConvolution,FrameConvolution,Stddev\n");
|
|
// Test convolution
|
|
m17Demodulator.resetCorrelationStats();
|
|
for(unsigned i = 0; i < baseband_samples - m17Demodulator.M17_SYNCWORD_SYMBOLS * m17Demodulator.M17_SAMPLES_PER_SYMBOL; i++)
|
|
{
|
|
int32_t lsf_conv =
|
|
m17Demodulator.convolution(i,
|
|
m17Demodulator.lsf_syncword,
|
|
m17Demodulator.M17_SYNCWORD_SYMBOLS);
|
|
int32_t stream_conv =
|
|
m17Demodulator.convolution(i,
|
|
m17Demodulator.stream_syncword,
|
|
m17Demodulator.M17_SYNCWORD_SYMBOLS);
|
|
m17Demodulator.updateCorrelationStats(stream_conv);
|
|
fprintf(output_csv_1, "%" PRId16 ",%" PRId16 ",%d,%d,%f\n",
|
|
baseband_buffer[i],
|
|
baseband.data[i],
|
|
lsf_conv + (int32_t) m17Demodulator.getCorrelationEma(),
|
|
stream_conv - (int32_t) m17Demodulator.getCorrelationEma(),
|
|
m17Demodulator.conv_threshold_factor *
|
|
m17Demodulator.getCorrelationStddev());
|
|
}
|
|
fclose(output_csv_1);
|
|
|
|
// Test syncword detection
|
|
printf("Testing syncword detection!\n");
|
|
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();
|
|
int i = 0;
|
|
do
|
|
{
|
|
int expected_syncword = 0;
|
|
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);
|
|
if (syncword.index != expected_syncword)
|
|
{
|
|
fprintf(stderr, "Error in syncwords detection #%d!\n", i);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
printf("SYNC: %d...OK!\n", syncword.index);
|
|
}
|
|
i++;
|
|
} while (syncword.index != -1);
|
|
fclose(syncword_ref);
|
|
|
|
FILE *output_csv_2 = fopen("M17_demodulator_output_2.csv", "w");
|
|
fprintf(output_csv_2, "RRCSignal,SyncDetect,QntMax,QntMin,Symbol\n");
|
|
uint32_t detect = 0, symbol = 0;
|
|
offset = 0;
|
|
syncword = { -1, false };
|
|
m17Demodulator.resetCorrelationStats();
|
|
syncword = m17Demodulator.nextFrameSync(offset);
|
|
for(unsigned i = 0; i < baseband_samples - m17Demodulator.M17_SYNCWORD_SYMBOLS * m17Demodulator.M17_SAMPLES_PER_SYMBOL; i++)
|
|
{
|
|
if ((int) i == (syncword.index + 1)) {
|
|
if (syncword.lsf)
|
|
detect = -4000;
|
|
else
|
|
detect = 4000;
|
|
syncword = m17Demodulator.nextFrameSync(syncword.index + m17Demodulator.M17_SYNCWORD_SYMBOLS * m17Demodulator.M17_SAMPLES_PER_SYMBOL);
|
|
} else if (((int) i % 10) == ((syncword.index + 1) % 10)) {
|
|
m17Demodulator.updateQuantizationStats(i);
|
|
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] - (int16_t) m17Demodulator.getQuantizationEma(),
|
|
detect,
|
|
m17Demodulator.getQuantizationMax() / 2,
|
|
m17Demodulator.getQuantizationMin() / 2,
|
|
symbol);
|
|
}
|
|
fclose(output_csv_2);
|
|
|
|
// TODO: Test symbol quantization
|
|
FILE *symbols_ref = fopen("../tests/unit/assets/M17_test_baseband.bin", "rb");
|
|
// Skip preamble
|
|
fseek(symbols_ref, 0x30, SEEK_SET);
|
|
uint32_t failed_bytes = 0, total_bytes = 0;
|
|
syncword = { -1, false };
|
|
offset = 0;
|
|
syncword = m17Demodulator.nextFrameSync(offset);
|
|
std::array< uint8_t, m17Demodulator.M17_FRAME_BYTES > frame;
|
|
// Preheat quantizer
|
|
for(int i = 0; i < 10; i++)
|
|
m17Demodulator.updateQuantizationStats(i);
|
|
if (syncword.index != -1)
|
|
{
|
|
// Next syncword does not overlap with current syncword
|
|
offset = syncword.index + m17Demodulator.M17_SAMPLES_PER_SYMBOL;
|
|
// Slice the input buffer to extract a frame and quantize
|
|
for(uint32_t j = 0;
|
|
syncword.index + 2 + m17Demodulator.M17_SAMPLES_PER_SYMBOL * (j + i) < m17Demodulator.baseband.len;
|
|
j+= m17Demodulator.M17_FRAME_SYMBOLS)
|
|
{
|
|
for(uint16_t i = 0; i < m17Demodulator.M17_FRAME_SYMBOLS; i++)
|
|
{
|
|
// Quantize
|
|
uint32_t symbol_index = syncword.index + 2 +
|
|
m17Demodulator.M17_SAMPLES_PER_SYMBOL * (j + i);
|
|
m17Demodulator.updateQuantizationStats(symbol_index);
|
|
int8_t symbol = m17Demodulator.quantize(symbol_index);
|
|
setSymbol<m17Demodulator.M17_FRAME_BYTES>(frame, i, symbol);
|
|
}
|
|
for(uint16_t i = 0; i < m17Demodulator.M17_FRAME_BYTES; i+=2) {
|
|
if (i % 16 == 0)
|
|
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++;
|
|
//}
|
|
total_bytes += 1;
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
printf("Failed decoding %d/%d bytes!\n", failed_bytes, total_bytes);
|
|
|
|
// TODO: when stream is over pad with zeroes to avoid corrupting the last symbols
|
|
|
|
m17Demodulator.baseband = old_baseband;
|
|
free(baseband_buffer);
|
|
free(filtered_buffer);
|
|
return 0;
|
|
}
|