From 6420bd4f58ef6f6157a2882fdc7b0cc7843433eb Mon Sep 17 00:00:00 2001 From: Rob Riggs Date: Tue, 14 Apr 2020 21:02:15 -0500 Subject: [PATCH] Add StdDev/SNR calc for debug. --- .settings/language.settings.xml | 4 +-- Src/main.c | 8 +++-- TNC/Fsk9600Demodulator.cpp | 24 ++++++++++++++ TNC/Fsk9600Demodulator.hpp | 3 ++ TNC/HDLCEncoder.hpp | 1 + TNC/HdlcDecoder.hpp | 5 +++ TNC/KissHardware.cpp | 2 +- TNC/KissHardware.hpp | 4 +++ TNC/StandardDeviation.hpp | 59 +++++++++++++++++++++++++++++++++ stlink-tnc3.cfg | 2 +- 10 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 TNC/StandardDeviation.hpp diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index 3d08f16..8fe73b1 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -3,7 +3,7 @@ - + @@ -14,7 +14,7 @@ - + diff --git a/Src/main.c b/Src/main.c index 92ddd7a..d1bdce7 100644 --- a/Src/main.c +++ b/Src/main.c @@ -895,7 +895,7 @@ static void MX_DAC1_Init(void) sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; sConfig.DAC_Trigger = DAC_TRIGGER_T7_TRGO; sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; - sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE; + sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE; sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY; if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK) { @@ -904,9 +904,11 @@ static void MX_DAC1_Init(void) /**DAC channel OUT2 config */ + sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; sConfig.DAC_Trigger = DAC_TRIGGER_NONE; - sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE; - sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_ENABLE; + sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE; + sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY; if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_2) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); diff --git a/TNC/Fsk9600Demodulator.cpp b/TNC/Fsk9600Demodulator.cpp index 18e198a..187bdcf 100644 --- a/TNC/Fsk9600Demodulator.cpp +++ b/TNC/Fsk9600Demodulator.cpp @@ -5,6 +5,7 @@ #include "Goertzel.h" #include "AudioInput.hpp" #include "GPIO.hpp" +#include "Log.h" namespace mobilinkd { namespace tnc { @@ -32,8 +33,31 @@ hdlc::IoFrame* Fsk9600Demodulator::operator()(const q15_t* samples) if (tmp) hdlc::release(tmp); } else { result = hdlc_decoder_(nrzi_.decode(lfsr_(bit)), locked_); +#ifdef KISS_LOGGING + if (result) { + INFO("samples = %ld, mean = %d, dev = %d", + snr_.samples, int(snr_.mean), int(snr_.stdev())); + INFO("SNR = %dmB", int(snr_.SNR() * 100.0f)); + snr_.reset(); + } +#endif } + +#ifdef KISS_LOGGING + if (hdlc_decoder_.active()) + { + if (!decoding_) + { + snr_.reset(); + decoding_ = true; + } + snr_.capture(float(abs(sample))); + } else { + decoding_ = false; + } +#endif } + } return result; } diff --git a/TNC/Fsk9600Demodulator.hpp b/TNC/Fsk9600Demodulator.hpp index a4ce20d..3e914c2 100644 --- a/TNC/Fsk9600Demodulator.hpp +++ b/TNC/Fsk9600Demodulator.hpp @@ -10,6 +10,7 @@ #include "NRZI.hpp" #include "HdlcDecoder.hpp" #include "KissHardware.hpp" +#include "StandardDeviation.hpp" namespace mobilinkd { namespace tnc { @@ -46,6 +47,8 @@ struct Fsk9600Demodulator : IDemodulator Descrambler lfsr_; libafsk::NRZI nrzi_; hdlc::NewDecoder hdlc_decoder_; + StandardDeviation snr_; + bool decoding_{false}; virtual ~Fsk9600Demodulator() {} diff --git a/TNC/HDLCEncoder.hpp b/TNC/HDLCEncoder.hpp index 4e90897..079fe9c 100644 --- a/TNC/HDLCEncoder.hpp +++ b/TNC/HDLCEncoder.hpp @@ -205,6 +205,7 @@ struct Encoder { void send_delay() { const size_t tmp = tx_delay_ * 1.25 * modulator_->bits_per_ms(); + INFO("Sending %u IDLE bytes", tmp); for (size_t i = 0; i != tmp; i++) { send_raw(IDLE); diff --git a/TNC/HdlcDecoder.hpp b/TNC/HdlcDecoder.hpp index 2307dd5..aa971d3 100644 --- a/TNC/HdlcDecoder.hpp +++ b/TNC/HdlcDecoder.hpp @@ -68,6 +68,11 @@ struct NewDecoder { dcd = config; } + + bool active() const + { + return state != State::IDLE; + } }; }}} // mobilinkd::tnc::hdlc diff --git a/TNC/KissHardware.cpp b/TNC/KissHardware.cpp index bd8f67e..8ad3618 100644 --- a/TNC/KissHardware.cpp +++ b/TNC/KissHardware.cpp @@ -112,7 +112,7 @@ void reply16(uint8_t cmd, uint16_t result) { ioport->write(data, 3, 6, osWaitForever); } -inline void reply(uint8_t cmd, const uint8_t* data, uint16_t len) { +void reply(uint8_t cmd, const uint8_t* data, uint16_t len) { uint8_t* buffer = static_cast(alloca(len + 1)); buffer[0] = cmd; for (uint16_t i = 0; i != len; i++) diff --git a/TNC/KissHardware.hpp b/TNC/KissHardware.hpp index 1dc3bbb..0533d6b 100644 --- a/TNC/KissHardware.hpp +++ b/TNC/KissHardware.hpp @@ -105,6 +105,8 @@ constexpr const uint8_t GET_MAC_ADDRESS = 48; constexpr const uint8_t GET_DATETIME = 49; constexpr const uint8_t SET_DATETIME = 50; constexpr const uint8_t GET_ERROR_MSG = 51; +constexpr const uint8_t GET_SNR = 52; +constexpr const uint8_t GET_BER = 53; constexpr const uint8_t SET_BLUETOOTH_NAME = 65; constexpr const uint8_t GET_BLUETOOTH_NAME = 66; @@ -402,4 +404,6 @@ void reply8(uint8_t cmd, uint8_t result) __attribute__((noinline)); void reply16(uint8_t cmd, uint16_t result) __attribute__((noinline)); +void reply(uint8_t cmd, const uint8_t* data, uint16_t len) __attribute__((noinline)); + }}} // mobilinkd::tnc::kiss diff --git a/TNC/StandardDeviation.hpp b/TNC/StandardDeviation.hpp new file mode 100644 index 0000000..e014476 --- /dev/null +++ b/TNC/StandardDeviation.hpp @@ -0,0 +1,59 @@ +// Copyright 2020 Mobilinkd LLC +// All rights reserved. + +#pragma once + +#include "main.h" + +#include + +#include + +namespace mobilinkd { + +/** + * Compute a running standard deviation. + * + * Based on https://dsp.stackexchange.com/a/1187/36581 + */ +struct StandardDeviation +{ + float mean{0.0}; + float S{0.0}; + uint32_t samples{0}; + + void reset() + { + mean = 0.0; + S = 0.0; + samples = 0; + } + + void capture(float sample) + { + auto prev = mean; + samples += 1; + mean = mean + (sample - mean) / samples; + S = S + (sample - mean) * (sample - prev); + } + + float variance() const + { + return samples == 0 ? -1.0 : S / samples; + } + + float stdev() const + { + float result = -1.0; + arm_sqrt_f32(variance(), &result); + return result; + } + + // SNR in dB + float SNR() const + { + return 10.0 * log10(mean / stdev()); + } +}; + +} // mobilinkd diff --git a/stlink-tnc3.cfg b/stlink-tnc3.cfg index adcea77..19fd821 100644 --- a/stlink-tnc3.cfg +++ b/stlink-tnc3.cfg @@ -9,4 +9,4 @@ source [find target/stm32l4x.cfg] reset_config srst_only itm port 0 on -tpiu config internal swv uart off 48000000 +tpiu config internal swv uart off 80000000