125 lines
2.7 KiB
C
125 lines
2.7 KiB
C
#include "stm32f030x6.h"
|
|
#include <poti.h>
|
|
#include <stdint.h>
|
|
|
|
const uint8_t adc_channels[POTI_COUNT] = {POTI_ADC_CHANNELS};
|
|
|
|
static volatile uint16_t adc_raw_values[POTI_COUNT];
|
|
|
|
static volatile uint16_t adc_moving_avg[POTI_COUNT];
|
|
|
|
static volatile uint8_t adc_moving_avg_out[POTI_COUNT];
|
|
|
|
/**
|
|
* @brief Perform calibration. ADC must be disabled
|
|
*/
|
|
static void perform_cal(void)
|
|
{
|
|
ADC1->CR = ADC_CR_ADCAL;
|
|
while (ADC1->CR & ADC_CR_ADCAL);
|
|
(void)ADC1->DR;
|
|
}
|
|
|
|
void poti_init_adc(void)
|
|
{
|
|
int i;
|
|
uint32_t reg;
|
|
|
|
RCC->APB2ENR |= RCC_APB2ENR_ADCEN;
|
|
RCC->AHBENR |= RCC_AHBENR_DMAEN;
|
|
|
|
for (i = 0; i < POTI_COUNT; i++) {
|
|
adc_moving_avg[i] = 0u;
|
|
}
|
|
|
|
DMA1_Channel1->CCR = 0ul;
|
|
|
|
/* Clear ADC ready bit */
|
|
ADC1->ISR = ADC_ISR_ADRDY;
|
|
|
|
ADC1->CFGR1 = 0;
|
|
|
|
/* Start calibration */
|
|
perform_cal();
|
|
|
|
/* Activate channels to convert */
|
|
reg = 0ul;
|
|
for (i = 0; i < POTI_COUNT; i++) {
|
|
if (adc_channels[i] <= 17)
|
|
reg |= (1<<adc_channels[i]);
|
|
}
|
|
ADC1->CHSELR = reg;
|
|
|
|
/* Setup sample time (239.5 cycles) */
|
|
ADC1->SMPR = ADC_SMPR_SMP_2 | ADC_SMPR_SMP_1 | ADC_SMPR1_SMPR_0;
|
|
|
|
/* Setup ADC clock (PCLK / 4) */
|
|
ADC1->CFGR2 = ADC_CFGR2_CKMODE_1;
|
|
|
|
/* Setup continuous sample mode with DMA in circular mode */
|
|
ADC1->CFGR1 = ADC_CFGR1_CONT | ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG;
|
|
|
|
/* Enable ADC and wait for ready */
|
|
ADC1->CR = ADC_CR_ADEN;
|
|
while (!(ADC1->ISR & ADC_ISR_ADRDY));
|
|
|
|
/* Setup DMA channel 1 */
|
|
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
|
|
DMA1_Channel1->CMAR = (uint32_t)adc_raw_values;
|
|
|
|
DMA1_Channel1->CNDTR = POTI_COUNT;
|
|
|
|
DMA1_Channel1->CCR = DMA_CCR_PL_0 | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_MINC |
|
|
DMA_CCR_CIRC | DMA_CCR_TCIE | DMA_CCR_EN;
|
|
|
|
|
|
/* Enable Interrupt with lower priority. Prevents jitter on the DMX lines */
|
|
NVIC_SetPriority(DMA1_Channel1_IRQn, 1);
|
|
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
|
|
|
|
/* Start the conversion */
|
|
ADC1->CR |= ADC_CR_ADSTART;
|
|
}
|
|
|
|
void poti_get_values(struct poti_values *out_val)
|
|
{
|
|
int i;
|
|
|
|
if (!out_val)
|
|
return;
|
|
|
|
for (i = 0; i < POTI_COUNT; i++) {
|
|
/* return iverted values, because of potentiometer polarities */
|
|
out_val->current_pot_vals[i] = ~adc_raw_values[i];
|
|
out_val->pot_vals_filtered[i] = ~adc_moving_avg_out[i];
|
|
}
|
|
}
|
|
|
|
static uint16_t calc_moving_avg(uint16_t adc_val, uint16_t prev_avg)
|
|
{
|
|
uint32_t val;
|
|
|
|
val = (uint32_t)prev_avg;
|
|
val /= 16u;
|
|
val *= 15u;
|
|
val += adc_val;
|
|
|
|
return val;
|
|
}
|
|
|
|
void DMA_CH1_IRQHandler(void)
|
|
{
|
|
uint32_t isr;
|
|
int i;
|
|
|
|
isr = DMA1->ISR;
|
|
DMA1->IFCR = isr & DMA_ISR_TCIF1;
|
|
|
|
if (isr & DMA_ISR_TCIF1) {
|
|
/* All ADC samples converted */
|
|
for (i = 0; i < POTI_COUNT; i++) {
|
|
adc_moving_avg[i] = calc_moving_avg(adc_raw_values[i], adc_moving_avg[i]);
|
|
adc_moving_avg_out[i] = (uint8_t)(adc_moving_avg[i] / 16u / 16u);
|
|
}
|
|
}
|
|
} |