From 4bce2c9f2391dd84e03cd8be4d33bbcf5a7b8bb8 Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Mon, 7 Feb 2022 22:01:14 +0100 Subject: [PATCH] Fixed bugs in MDx and Module17 input stream drivers causing errors in sample rate: one due to wrong configuration of TIM2 registers and one due to wrong configuration of ADC channel sample time. --- platform/drivers/audio/inputStream_MDx.cpp | 24 ++++--- platform/drivers/audio/inputStream_Mod17.cpp | 24 ++++--- platform/mcu/STM32F4xx/drivers/timers.h | 72 ++++++++++++++++++++ 3 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 platform/mcu/STM32F4xx/drivers/timers.h diff --git a/platform/drivers/audio/inputStream_MDx.cpp b/platform/drivers/audio/inputStream_MDx.cpp index 834fc553..db6c6622 100644 --- a/platform/drivers/audio/inputStream_MDx.cpp +++ b/platform/drivers/audio/inputStream_MDx.cpp @@ -1,8 +1,8 @@ /*************************************************************************** - * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, * - * Niccolò Izzo IU2KIN * - * Frederik Saraci IU2NRO * - * Silvano Seva IU2KWO * + * Copyright (C) 2021 - 2022 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -25,6 +25,7 @@ #include #include #include +#include using namespace miosix; @@ -120,8 +121,8 @@ streamId inputStream_start(const enum AudioSource source, * AP1 frequency is 42MHz but timer runs at 84MHz, tick rate is 1MHz, * reload register is configured based on desired sample rate. */ - TIM2->PSC = 83; - TIM2->ARR = (1000000/sampleRate) - 1; + tim_setUpdateFreqency(TIM2, sampleRate, 84000000); + TIM2->CNT = 0; TIM2->EGR = TIM_EGR_UG; TIM2->CR2 = TIM_CR2_MMS_1; @@ -181,14 +182,15 @@ streamId inputStream_start(const enum AudioSource source, /* * ADC2 configuration. * - * ADC clock is APB2 frequency divided by 8, giving 10.5MHz. - * Channel sample time set to 144 cycles, total conversion time 156 cycles. + * ADC clock is APB2 frequency divided by 4, giving 21MHz. + * Channel sample time set to 84 cycles, total conversion time is 100 + * cycles: this leads to a maximum sampling frequency of 210kHz. * Convert one channel only, no overrun interrupt, 12-bit resolution, * no analog watchdog, discontinuous mode, no end of conversion interrupts. */ - ADC->CCR |= ADC_CCR_ADCPRE; - ADC2->SMPR2 = ADC_SMPR2_SMP2 - | ADC_SMPR2_SMP1; + ADC->CCR |= ADC_CCR_ADCPRE_0; + ADC2->SMPR2 = ADC_SMPR2_SMP2_2 + | ADC_SMPR2_SMP1_2; ADC2->SQR1 = 0; // Convert one channel ADC2->CR1 |= ADC_CR1_DISCEN; ADC2->CR2 |= ADC_CR2_EXTEN_0 // Trigger on rising edge diff --git a/platform/drivers/audio/inputStream_Mod17.cpp b/platform/drivers/audio/inputStream_Mod17.cpp index 899c0af8..5abd47d2 100644 --- a/platform/drivers/audio/inputStream_Mod17.cpp +++ b/platform/drivers/audio/inputStream_Mod17.cpp @@ -1,8 +1,8 @@ /*************************************************************************** - * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, * - * Niccolò Izzo IU2KIN * - * Frederik Saraci IU2NRO * - * Silvano Seva IU2KWO * + * Copyright (C) 2021 - 2022 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -25,6 +25,7 @@ #include #include #include +#include using namespace miosix; @@ -120,8 +121,8 @@ streamId inputStream_start(const enum AudioSource source, * AP1 frequency is 42MHz but timer runs at 84MHz, tick rate is 1MHz, * reload register is configured based on desired sample rate. */ - TIM2->PSC = 83; - TIM2->ARR = (1000000/sampleRate) - 1; + tim_setUpdateFreqency(TIM2, sampleRate, 84000000); + TIM2->CNT = 0; TIM2->EGR = TIM_EGR_UG; TIM2->CR2 = TIM_CR2_MMS_1; @@ -181,14 +182,15 @@ streamId inputStream_start(const enum AudioSource source, /* * ADC2 configuration. * - * ADC clock is APB2 frequency divided by 8, giving 10.5MHz. - * Channel sample time set to 144 cycles, total conversion time 156 cycles. + * ADC clock is APB2 frequency divided by 4, giving 21MHz. + * Channel sample time set to 84 cycles, total conversion time is 100 + * cycles: this leads to a maximum sampling frequency of 210kHz. * Convert one channel only, no overrun interrupt, 12-bit resolution, * no analog watchdog, discontinuous mode, no end of conversion interrupts. */ - ADC->CCR |= ADC_CCR_ADCPRE; - ADC2->SMPR2 = ADC_SMPR2_SMP2 - | ADC_SMPR2_SMP1; + ADC->CCR |= ADC_CCR_ADCPRE_0; + ADC2->SMPR2 = ADC_SMPR2_SMP2_2 + | ADC_SMPR2_SMP1_2; ADC2->SQR1 = 0; // Convert one channel ADC2->CR1 |= ADC_CR1_DISCEN; ADC2->CR2 |= ADC_CR2_EXTEN_0 // Trigger on rising edge diff --git a/platform/mcu/STM32F4xx/drivers/timers.h b/platform/mcu/STM32F4xx/drivers/timers.h new file mode 100644 index 00000000..6e336ef5 --- /dev/null +++ b/platform/mcu/STM32F4xx/drivers/timers.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (C) 2022 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef TIMERS_H +#define TIMERS_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Configure prescaler and auto-reload register of a timer peripheral for a + * given update frequency. + * + * @param tim: timer peripheral to be configured. + * @param updFreq: desidered update frequency, in Hz. + * @param busFreq: frequency of the APB bus the timer is attached to, in Hz. + * @return effective timer update frequency, in Hz. + */ +inline uint32_t tim_setUpdateFreqency(TIM_TypeDef *tim, uint32_t updFreq, + uint32_t busFreq) +{ + /* + * Timer update frequency is given by: + * Fupd = (Fbus / prescaler) / autoreload + * + * First of all we fix the prescaler to 1 and compute the autoreload: if + * the result is greater than the maximum autoreload value, we proceed + * iteratively. + */ + uint32_t psc = 1; + uint32_t arr = busFreq/updFreq; + + while(arr >= 0xFFFF) + { + psc += 1; + arr = (busFreq / psc) / updFreq; + } + + /* Values put in registers have to be decremented by one, see RM */ + tim->PSC = psc - 1; + tim->ARR = arr - 1; + + return (busFreq/psc)/arr; +} + + +#ifdef __cplusplus +} +#endif + +#endif /* USART3_H */