From 4d55b178a965aa467b8b8816e8841792324238e5 Mon Sep 17 00:00:00 2001 From: Marshal Horn Date: Mon, 6 Jul 2020 11:48:09 -0700 Subject: [PATCH] Drafted decimation filter for qsd receiver --- NIL-STM32F051-DISCOVERY/.cproject | 18 ++---- NIL-STM32F051-DISCOVERY/Makefile | 2 +- NIL-STM32F051-DISCOVERY/dsp.c | 88 ++++++++++++++++++++++++++++++ NIL-STM32F051-DISCOVERY/dsp.h | 32 +++++++++++ NIL-STM32F051-DISCOVERY/radio/rx.c | 29 ++++++++++ NIL-STM32F051-DISCOVERY/radio/rx.h | 19 +++++++ 6 files changed, 174 insertions(+), 14 deletions(-) create mode 100644 NIL-STM32F051-DISCOVERY/dsp.c create mode 100644 NIL-STM32F051-DISCOVERY/dsp.h create mode 100644 NIL-STM32F051-DISCOVERY/radio/rx.c create mode 100644 NIL-STM32F051-DISCOVERY/radio/rx.h diff --git a/NIL-STM32F051-DISCOVERY/.cproject b/NIL-STM32F051-DISCOVERY/.cproject index d4bd69a..c826a93 100644 --- a/NIL-STM32F051-DISCOVERY/.cproject +++ b/NIL-STM32F051-DISCOVERY/.cproject @@ -65,21 +65,13 @@ - + - - - - - - - - - - - + + + - + diff --git a/NIL-STM32F051-DISCOVERY/Makefile b/NIL-STM32F051-DISCOVERY/Makefile index b7222b1..45900fe 100644 --- a/NIL-STM32F051-DISCOVERY/Makefile +++ b/NIL-STM32F051-DISCOVERY/Makefile @@ -120,7 +120,7 @@ LDSCRIPT= $(STARTUPLD)/STM32F051x8.ld # setting. CSRC = $(ALLCSRC) \ $(TESTSRC) \ - main.c + main.c dsp.c radio/rx.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/NIL-STM32F051-DISCOVERY/dsp.c b/NIL-STM32F051-DISCOVERY/dsp.c new file mode 100644 index 0000000..7ef5832 --- /dev/null +++ b/NIL-STM32F051-DISCOVERY/dsp.c @@ -0,0 +1,88 @@ +/* + * dsp.c + * + * Created on: Jul 6, 2020 + * Author: marshal + */ +#include "dsp.h" +#include "radio/rx.h" +/* + * ADC streaming callback. + * + * We sampled at 500kHz, but our bandwidth of interest is only + * 2kHz. (Since it's quadrature sampling, nyquist rate is 1x) + * We use a second-order IIR filter to prevent aliasing, followed + * by an accumulate for decimation + */ +static void adccallback(ADCDriver *adcp) { + adcsample_t * ptr = adcp->samples; + size_t len = adcp->depth/2; // This also determines downsample ratio + // These are persistent variables for filter history + static uint32_t a1 = 0; + static uint32_t b1 = 0; + static uint32_t a2 = 0; + static uint32_t b2 = 0; + // These are temporary variables to return the downsampled signal + uint32_t c1 = 0; + uint32_t c2 = 0; + /* This determines the corner frequency of our IIR filter. + * It's actually 1/log2 of the corner + */ + const uint8_t corner = 7; + for(unsigned int i=0; i>corner); // 12+7 = 19 bits + b1 += a1 - (b1>>corner); // 19+7 = 26 bits + a2 += *ptr++ - (a2>>corner); + b2 += a2 - (b2>>corner); + // If len>64, we need to shift right to prevent overflow. + const uint8_t shift = 0; + c1 += b1>>shift; // 26+6=32 bits + c2 += b2>>shift; + } + struct complex c; + c.real = (c1>>16) - 0x8000; + c.imag = (c2>>16) - 0x8000; + chMsgSend((void*)radio_rx, (msg_t)&c); +} + +static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) { + + (void)adcp; + (void)err; +} + +/* + * ADC conversion group. + * Mode: Linear buffer, 8 samples of 1 channel, SW triggered. + * Channels: IN10. + */ +static const ADCConversionGroup qsd_in = { + TRUE, // continuous + 2, // 2 channels + adccallback, + adcerrorcallback, + ADC_CFGR1_RES_12BIT, /* CFGR1 */ + ADC_TR(0, 0), /* TR */ + ADC_SMPR_SMP_1P5, /* SMPR */ + ADC_CHSELR_CHSEL6 | ADC_CHSELR_CHSEL7 /* CHSELR */ +}; + + +/** ADC init + */ +void adc_rx_init(void){ + static char re_init = 0; + static adcsample_t * samples; + const int len = 64; + if(!re_init){ + re_init=1; + // Allocate MxN buffer for continuous ADC + samples = chCoreAllocFromBase( + len * qsd_in.num_channels * sizeof(adcsample_t), + sizeof(adcsample_t), 0); + } + // Start the continuous conversion + adcStart(&ADCD1, NULL); + adcStartConversion(&ADCD1, &qsd_in, samples, len); +} + diff --git a/NIL-STM32F051-DISCOVERY/dsp.h b/NIL-STM32F051-DISCOVERY/dsp.h new file mode 100644 index 0000000..fc861f0 --- /dev/null +++ b/NIL-STM32F051-DISCOVERY/dsp.h @@ -0,0 +1,32 @@ +/* + * dsp.h + * + * Created on: Jul 6, 2020 + * Author: marshal + */ + +#ifndef DSP_H_ +#define DSP_H_ + +#include "hal.h" +#include "ch.h" + +/** ADC streaming callback for radio RX + * + * We sampled at 500kHz, but our bandwidth of interest is only + * 2kHz. (Since it's quadrature sampling, nyquist rate is 1x) + * We use a second-order IIR filter to prevent aliasing, followed + * by an accumulate and decimation + */ + +/** Datatype for complex numbers */ +struct complex{ + int16_t real; + int16_t imag; +}; + +/** ADC init + */ +void adc_rx_init(void); + +#endif /* DSP_H_ */ diff --git a/NIL-STM32F051-DISCOVERY/radio/rx.c b/NIL-STM32F051-DISCOVERY/radio/rx.c new file mode 100644 index 0000000..5676353 --- /dev/null +++ b/NIL-STM32F051-DISCOVERY/radio/rx.c @@ -0,0 +1,29 @@ +/* + * rx.c + * + * Created on: Jul 6, 2020 + * Author: marshal + */ + +#include "rx.h" +#include "dsp.h" + +/** Mailbox for received data */ +msg_t new_sample; + +THD_WORKING_AREA(waradio_rx, 128); +THD_FUNCTION(radio_rx, arg){ + (void)arg; + const int len = 256; + int16_t * data = chCoreAllocFromBase(len*sizeof(int16_t), sizeof(int16_t), 0); + while(1){ + for( int i=0; ireal; + data[i++] = c->imag; + chMsgRelease(thd, MSG_OK); + } + /** Here would be a good place to do a FFT or other processing */ + } +} diff --git a/NIL-STM32F051-DISCOVERY/radio/rx.h b/NIL-STM32F051-DISCOVERY/radio/rx.h new file mode 100644 index 0000000..dd1f633 --- /dev/null +++ b/NIL-STM32F051-DISCOVERY/radio/rx.h @@ -0,0 +1,19 @@ +/* + * rx.h + * + * Created on: Jul 6, 2020 + * Author: marshal + */ + +#ifndef RX_H_ +#define RX_H_ + +#include "hal.h" +#include "ch.h" + +THD_FUNCTION(radio_rx, arg); + +/** Mailbox for received data */ +extern msg_t new_sample; + +#endif /* RX_H_ */