Drafted decimation filter for qsd receiver

chibios
Marshal Horn 2020-07-06 11:48:09 -07:00
rodzic ace1e657b8
commit 4d55b178a9
6 zmienionych plików z 174 dodań i 14 usunięć

Wyświetl plik

@ -65,21 +65,13 @@
</folderInfo>
<folderInfo id="0.87736009.1762812655" name="/" resourcePath="board">
<sourceEntries>
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.1198201678" name="No ToolChain" superClass="org.eclipse.cdt.build.core.prefbase.toolchain" unusedChildren="">
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.117598285" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs.686764108"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.1159330235" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder.1629275092"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.1564596667" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder.1369722403"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.797214978" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder.883301168"/>
</toolChain>
<entry excluding="radio" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="radio"/>
</folderInfo>
</sourceEntries>
</configuration>

Wyświetl plik

@ -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.

Wyświetl plik

@ -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<len; ++i){
a1 += *ptr++ - (a1>>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);
}

Wyświetl plik

@ -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_ */

Wyświetl plik

@ -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; i<len;){
thread_t * thd = chMsgWait();
struct complex * c = (struct complex *)chMsgGet(thd);
data[i++] = c->real;
data[i++] = c->imag;
chMsgRelease(thd, MSG_OK);
}
/** Here would be a good place to do a FFT or other processing */
}
}

Wyświetl plik

@ -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_ */