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);
 | 
						|
		}
 | 
						|
	}
 | 
						|
} |