oversample for lower rates; add iir templates

pull/3/head
Clyne 4 years ago
parent f559e9fbef
commit 6395d1d18b

@ -0,0 +1,13 @@
adcsample_t *process_data(adcsample_t *samples, unsigned int size)
{
constexpr float alpha = 0.7;
static adcsample_t prev = 2048;
samples[0] = (1 - alpha) * samples[0] + alpha * prev;
for (unsigned int i = 1; i < size; i++)
samples[i] = (1 - alpha) * samples[i] + alpha * samples[i - 1];
prev = samples[size - 1];
return samples;
}

@ -0,0 +1,22 @@
adcsample_t *process_data(adcsample_t *samples, unsigned int size)
{
constexpr float alpha = 0.75;
constexpr unsigned int D = 100;
static adcsample_t output[SIZE];
static adcsample_t prev[D]; // prev[0] = output[0 - D]
// Do calculations with previous output
for (unsigned int i = 0; i < D; i++)
output[i] = samples[i] + alpha * (prev[i] - 2048);
// Do calculations with current samples
for (unsigned int i = D; i < size; i++)
output[i] = samples[i] + alpha * (output[i - D] - 2048);
// Save outputs for next computation
for (unsigned int i = 0; i < D; i++)
prev[i] = output[size - (D - i)];
return output;
}

@ -68,11 +68,11 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50)
auto comp = new wxButton(panelToolbar, Id::MCodeCompile, "Compile"); auto comp = new wxButton(panelToolbar, Id::MCodeCompile, "Compile");
static const wxString srateValues[] = { static const wxString srateValues[] = {
"8 kS/s",
"16 kS/s", "16 kS/s",
"20 kS/s", "20 kS/s",
"32 kS/s", "32 kS/s",
"48 kS/s", "48 kS/s",
"60 kS/s",
"96 kS/s" "96 kS/s"
}; };
m_rate_select = new wxComboBox(panelToolbar, wxID_ANY, m_rate_select = new wxComboBox(panelToolbar, wxID_ANY,

@ -23,8 +23,8 @@ ADCConversionGroup ADC::m_group_config = {
.num_channels = 1, .num_channels = 1,
.end_cb = ADC::conversionCallback, .end_cb = ADC::conversionCallback,
.error_cb = nullptr, .error_cb = nullptr,
.cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM4_TRGO */ .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */
.cfgr2 = 0,//ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1, // Oversampling 2x .cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1, // Oversampling 2x
.tr1 = ADC_TR(0, 4095), .tr1 = ADC_TR(0, 4095),
.smpr = { .smpr = {
ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_12P5), 0 ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_12P5), 0
@ -43,13 +43,13 @@ const GPTConfig ADC::m_timer_config = {
}; };
std::array<std::array<uint32_t, 4>, 6> ADC::m_rate_presets = {{ std::array<std::array<uint32_t, 4>, 6> ADC::m_rate_presets = {{
// Rate PLLSAI2N ADC_PRESC ADC_SMPR GPT_DIV // Rate PLLSAI2N R OVERSAMPLE 2x? GPT_DIV
{/* 16k */ 8, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 2250}, {/* 8k */ 16, 3, 1, 4500},
{/* 20k */ 10, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 1800}, {/* 16k */ 32, 3, 1, 2250},
{/* 32k */ 16, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 1125}, {/* 20k */ 40, 3, 1, 1800},
{/* 48k */ 24, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 750}, {/* 32k */ 64, 3, 1, 1125},
{/* 60k */ 30, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 600}, {/* 48k */ 24, 3, 0, 750},
{/* 96k */ 48, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 375} {/* 96k */ 48, 3, 0, 375}
}}; }};
adcsample_t *ADC::m_current_buffer = nullptr; adcsample_t *ADC::m_current_buffer = nullptr;
@ -66,7 +66,7 @@ void ADC::begin()
adcSTM32EnableVREF(m_driver); adcSTM32EnableVREF(m_driver);
gptStart(m_timer, &m_timer_config); gptStart(m_timer, &m_timer_config);
setRate(Rate::R96K); setRate(Rate::R32K);
} }
void ADC::start(adcsample_t *buffer, size_t count, Operation operation) void ADC::start(adcsample_t *buffer, size_t count, Operation operation)
@ -92,9 +92,9 @@ void ADC::stop()
void ADC::setRate(ADC::Rate rate) void ADC::setRate(ADC::Rate rate)
{ {
auto& preset = m_rate_presets[static_cast<int>(rate)]; auto& preset = m_rate_presets[static_cast<int>(rate)];
auto plln = preset[0] << RCC_PLLSAI2CFGR_PLLSAI2N_Pos; auto pllnr = (preset[0] << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
auto presc = preset[1] << ADC_CCR_PRESC_Pos; (preset[1] << RCC_PLLSAI2CFGR_PLLSAI2R_Pos);
auto smp = preset[2]; bool oversample = preset[2] != 0;
m_timer_divisor = preset[3]; m_timer_divisor = preset[3];
adcStop(m_driver); adcStop(m_driver);
@ -102,12 +102,12 @@ void ADC::setRate(ADC::Rate rate)
// Adjust PLLSAI2 // Adjust PLLSAI2
RCC->CR &= ~(RCC_CR_PLLSAI2ON); RCC->CR &= ~(RCC_CR_PLLSAI2ON);
while ((RCC->CR & RCC_CR_PLLSAI2RDY) == RCC_CR_PLLSAI2RDY); while ((RCC->CR & RCC_CR_PLLSAI2RDY) == RCC_CR_PLLSAI2RDY);
RCC->PLLSAI2CFGR = (RCC->PLLSAI2CFGR & ~(RCC_PLLSAI2CFGR_PLLSAI2N_Msk)) | plln; RCC->PLLSAI2CFGR = (RCC->PLLSAI2CFGR & ~(RCC_PLLSAI2CFGR_PLLSAI2N_Msk | RCC_PLLSAI2CFGR_PLLSAI2R_Msk)) | pllnr;
RCC->CR |= RCC_CR_PLLSAI2ON; RCC->CR |= RCC_CR_PLLSAI2ON;
// Set ADC prescaler while ((RCC->CR & RCC_CR_PLLSAI2RDY) != RCC_CR_PLLSAI2RDY);
m_driver->adcc->CCR = (m_driver->adcc->CCR & ~(ADC_CCR_PRESC_Msk)) | presc;
// Set sampling time // Set 2x oversampling
m_group_config.smpr[0] = ADC_SMPR1_SMP_AN5(smp); m_group_config.cfgr2 = oversample ? ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1 : 0;
adcStart(m_driver, &m_config); adcStart(m_driver, &m_config);
} }

@ -22,12 +22,11 @@ public:
using Operation = void (*)(adcsample_t *buffer, size_t count); using Operation = void (*)(adcsample_t *buffer, size_t count);
enum class Rate : int { enum class Rate : int {
//R8K = 0, R8K = 0,
R16K = 0, R16K,
R20K, R20K,
R32K, R32K,
R48K, R48K,
R60K,
R96K R96K
}; };

Loading…
Cancel
Save