Browse Source

Fix the DC offset computation. The previous computation would occassionally get stuck with an incorrect offset.

dds
Konstantin Lopyrev 8 years ago
parent
commit
dde07982b0
2 changed files with 18 additions and 9 deletions
  1. +16
    -8
      input_adc.cpp
  2. +2
    -1
      input_adc.h

+ 16
- 8
input_adc.cpp View File

DMAMEM static uint16_t analog_rx_buffer[AUDIO_BLOCK_SAMPLES]; DMAMEM static uint16_t analog_rx_buffer[AUDIO_BLOCK_SAMPLES];
audio_block_t * AudioInputAnalog::block_left = NULL; audio_block_t * AudioInputAnalog::block_left = NULL;
uint16_t AudioInputAnalog::block_offset = 0; uint16_t AudioInputAnalog::block_offset = 0;
uint16_t AudioInputAnalog::dc_average = 0;
int32_t AudioInputAnalog::dc_average_hist[16];
int32_t AudioInputAnalog::current_dc_average_index = 0;
bool AudioInputAnalog::update_responsibility = false; bool AudioInputAnalog::update_responsibility = false;
DMAChannel AudioInputAnalog::dma(false); DMAChannel AudioInputAnalog::dma(false);


for (i=0; i < 1024; i++) { for (i=0; i < 1024; i++) {
sum += analogRead(pin); sum += analogRead(pin);
} }
dc_average = sum >> 10;
for (i = 0; i < 16; i++) {
dc_average_hist[i] = sum >> 10;
}


// set the programmable delay block to trigger the ADC at 44.1 kHz // set the programmable delay block to trigger the ADC at 44.1 kHz
#if defined(KINETISK) #if defined(KINETISK)
void AudioInputAnalog::update(void) void AudioInputAnalog::update(void)
{ {
audio_block_t *new_left=NULL, *out_left=NULL; audio_block_t *new_left=NULL, *out_left=NULL;
unsigned int dc, offset;
uint32_t i, dc, offset;
int32_t tmp; int32_t tmp;
int16_t s, *p, *end; int16_t s, *p, *end;


block_offset = 0; block_offset = 0;
__enable_irq(); __enable_irq();


// find and subtract DC offset....
// TODO: this may not be correct, needs testing with more types of signals
dc = dc_average;
// Find and subtract DC offset... We use an average of the
// last 16 * AUDIO_BLOCK_SAMPLES samples.
dc = 0;
for (i = 0; i < 16; i++) {
dc += dc_average_hist[i];
}
dc /= 16 * AUDIO_BLOCK_SAMPLES;
dc_average_hist[current_dc_average_index] = 0;
p = out_left->data; p = out_left->data;
end = p + AUDIO_BLOCK_SAMPLES; end = p + AUDIO_BLOCK_SAMPLES;
do { do {
dc_average_hist[current_dc_average_index] += (uint16_t)(*p);
tmp = (uint16_t)(*p) - (int32_t)dc; tmp = (uint16_t)(*p) - (int32_t)dc;
s = signed_saturate_rshift(tmp, 16, 0); s = signed_saturate_rshift(tmp, 16, 0);
*p++ = s; *p++ = s;
dc += s / 12000; // slow response, remove DC component
} while (p < end); } while (p < end);
dc_average = dc;
current_dc_average_index = (current_dc_average_index + 1) % 16;


// then transmit the AC data // then transmit the AC data
transmit(out_left); transmit(out_left);

+ 2
- 1
input_adc.h View File

private: private:
static audio_block_t *block_left; static audio_block_t *block_left;
static uint16_t block_offset; static uint16_t block_offset;
static uint16_t dc_average;
static int32_t dc_average_hist[16];
static int32_t current_dc_average_index;
static bool update_responsibility; static bool update_responsibility;
static DMAChannel dma; static DMAChannel dma;
static void isr(void); static void isr(void);

Loading…
Cancel
Save