From 6104ccd08a7d500265e169c0f0aeb252579d3ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Thu, 11 Aug 2022 23:24:24 +0200 Subject: [PATCH] Add ADC Handling. Write first draft of operating modes for testing --- Makefile | 1 + dmx.c | 16 +++---- include/dmx.h | 10 ++++ include/poti.h | 19 ++++++++ main.c | 111 +++++++++++++++++++++++++++++++++----------- poti.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 243 insertions(+), 36 deletions(-) create mode 100644 include/poti.h create mode 100644 poti.c diff --git a/Makefile b/Makefile index 29935f7..bec72c9 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ endif CFILES := main.c setup/system_init.c startup/startup_stm32f0xx.c systick.c CFILES += i2c.c CFILES += dmx.c +CFILES += poti.c ASFILES = INCLUDEPATH = -Iinclude -Iinclude/cmsis diff --git a/dmx.c b/dmx.c index cb1b372..da87503 100644 --- a/dmx.c +++ b/dmx.c @@ -12,15 +12,6 @@ static uint8_t *dmx_data_ptr; static uint16_t dmx_tx_break_len; static uint16_t dmx_tx_break_pause; -enum dmx_tx_state { - DMX_TX_OFF, - DMX_TX_IDLE, - DMX_TX_BREAK, - DMX_TX_BREAK_PAUSE, - DMX_TX_NULLBYTE, - DMX_TX_DATA, -}; - static volatile enum dmx_tx_state tx_state; /* USART1 TX is mapped on DMA Channel2 */ @@ -147,6 +138,11 @@ void TIM14_IRQHandler(void) } } +enum dmx_tx_state dmx_tx_get_current_state(void) +{ + return tx_state; +} + void USART1_IRQHandler(void) { uint32_t isr; @@ -175,7 +171,7 @@ void DMA_CH2_3_DMA2_CH1_2_IRQHandler(void) uint32_t isr; isr = DMA1->ISR; - DMA1->IFCR = isr; + DMA1->IFCR = isr & DMA_ISR_TCIF2; if (isr & DMA_ISR_TCIF2) { /* Channnel 2 trasnfer complete. Universe trasnferred */ diff --git a/include/dmx.h b/include/dmx.h index 151dc10..03c4735 100644 --- a/include/dmx.h +++ b/include/dmx.h @@ -3,6 +3,14 @@ #include +enum dmx_tx_state { + DMX_TX_OFF, + DMX_TX_IDLE, + DMX_TX_BREAK, + DMX_TX_BREAK_PAUSE, + DMX_TX_NULLBYTE, + DMX_TX_DATA, +}; void dmx_init(uint8_t *data, uint32_t universe_length, GPIO_TypeDef *tx_port, uint8_t tx_pin, uint16_t dmx_delay, uint16_t dmx_break_len, uint16_t break_pause); @@ -11,4 +19,6 @@ void dmx_stream_start(void); void dmx_stream_stop(void); +enum dmx_tx_state dmx_tx_get_current_state(void); + #endif /* _DMX_H_ */ \ No newline at end of file diff --git a/include/poti.h b/include/poti.h new file mode 100644 index 0000000..ae2b01f --- /dev/null +++ b/include/poti.h @@ -0,0 +1,19 @@ +#ifndef _POTI_H_ +#define _POTI_H_ + +#include + +#define POTI_COUNT (3) + +#define POTI_ADC_CHANNELS 0, 1, 4 + +struct poti_values { + uint16_t current_pot_vals[POTI_COUNT]; + uint8_t pot_vals_filtered[POTI_COUNT]; +}; + +void poti_init_adc(void); + +void poti_get_values(struct poti_values *out_val); + +#endif /* _POTI_H_ */ \ No newline at end of file diff --git a/main.c b/main.c index 3ec2bea..bf072d0 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -15,8 +16,36 @@ #define PCA9555_REG_CONFIG0 (0x6) #define PCA9555_REG_CONFIG1 (0x7) + +static const uint8_t gamma8[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, + 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, + 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, + 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, + 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, + 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114, + 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142, + 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175, + 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213, + 215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 +}; + static uint8_t dmx_universe[129]; +enum color_mode { + MODE_RED, + MODE_GREEN, + MODE_BLUE, + MODE_RGB, + MODE_WHITE_DISCRETE, +}; + static void setup_pins(void) { uint32_t tmp; @@ -26,8 +55,8 @@ static void setup_pins(void) tmp = GPIOA->MODER; /* Reset all used port pins */ - tmp &= MODER_DELETE(0) & MODER_DELETE(1) & MODER_DELETE(2) & MODER_DELETE(3) & \ - MODER_DELETE(4) & MODER_DELETE(5) & MODER_DELETE(6) & MODER_DELETE(7) & \ + tmp &= MODER_DELETE(0) & MODER_DELETE(1) & MODER_DELETE(2) & MODER_DELETE(3) & + MODER_DELETE(4) & MODER_DELETE(5) & MODER_DELETE(6) & MODER_DELETE(7) & MODER_DELETE(8) & MODER_DELETE(9) & MODER_DELETE(10); /* Analog ports for POTIs */ @@ -58,24 +87,18 @@ static void setup_pins(void) GPIOB->PUPDR = PULLUP(1); } -static void zero_dmx_universe(void) -{ - int i; - - for (i = 0; i < sizeof(dmx_universe); i++) { - dmx_universe[i] = 0; - } -} - int main(void) { uint8_t i2c_command[2]; uint8_t port; uint32_t odr; + enum color_mode mode = MODE_RED; + struct poti_values poti_vals; setup_pins(); i2c_init(); dmx_init(dmx_universe, sizeof(dmx_universe), GPIOA, 2u, 2300u, 10u, 5u); + poti_init_adc(); /* Setup Systick for 1ms ticks */ SysTick_Config(48000000UL/1000); @@ -98,33 +121,69 @@ int main(void) /* Blink the LEDs */ while (1) { - systick_wait_ms(3); + systick_wait_ms(10); + poti_get_values(&poti_vals); i2c_read(PCA9555_ADDR, PCA9555_REG_IN_PORT0, &port, 1u); i2c_command[0] = PCA9555_REG_OUT_PORT1; i2c_command[1] = ~port; + i2c_write(PCA9555_ADDR, i2c_command, 2u); odr = GPIOA->ODR; odr &= ~((1<<5) | (1<<6) | (1<<7)); if (port & (1<<0)) { - zero_dmx_universe(); - for (int i = 0; i < 32; i++) { - dmx_universe[i*4] = 0xFF; - } + mode = MODE_RED; } if (port & (1<<1)) { - zero_dmx_universe(); - for (int i = 0; i < 32; i++) { - dmx_universe[i*4+1] = 0xFF; - } + mode = MODE_GREEN; } if (port & (1<<2)) { - zero_dmx_universe(); - for (int i = 0; i < 32; i++) { - dmx_universe[i*4+2] = 0xFF; - } + mode = MODE_BLUE; + } + if (port & (1<<3)) { + mode = MODE_RGB; + } + if (port & (1<<4)) { + mode = MODE_WHITE_DISCRETE; } - GPIOA->ODR = odr; - i2c_write(PCA9555_ADDR, i2c_command, 2u); + + switch (mode) { + case MODE_RED: + case MODE_GREEN: + case MODE_BLUE: + for (int i = 0; i < 32; i++) { + dmx_universe[i*4] = mode == MODE_RED ? poti_vals.pot_vals_filtered[0] : 0; + dmx_universe[i*4+1] = mode == MODE_GREEN ? poti_vals.pot_vals_filtered[0] : 0; + dmx_universe[i*4+2] = mode == MODE_BLUE ? poti_vals.pot_vals_filtered[0] : 0; + dmx_universe[i*4+3] = 0x0; + } + dmx_universe[128] = 0; + odr |= (1<<5); + break; + case MODE_RGB: + odr |= (1<<5) | (1<<6) | (1<<7); + for (int i = 0; i < 32; i++) { + dmx_universe[i*4] =poti_vals.pot_vals_filtered[0]; + dmx_universe[i*4+1] = poti_vals.pot_vals_filtered[1]; + dmx_universe[i*4+2] = poti_vals.pot_vals_filtered[2]; + dmx_universe[i*4+3] = 0x0; + } + dmx_universe[128] = 0; + break; + case MODE_WHITE_DISCRETE: + odr |= (1<<5); + for (int i = 0; i < 32; i++) { + dmx_universe[i*4] = 0; + dmx_universe[i*4+1] = 0; + dmx_universe[i*4+2] = 0; + dmx_universe[i*4+3] = 0; + } + dmx_universe[128] = gamma8[poti_vals.pot_vals_filtered[0]]; + break; + default: + break; + } + + GPIOA->ODR = odr; } } diff --git a/poti.c b/poti.c new file mode 100644 index 0000000..faea0ce --- /dev/null +++ b/poti.c @@ -0,0 +1,122 @@ +#include "stm32f030x6.h" +#include +#include + +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<CHSELR = reg; + + /* Setup sample time (71.5 cycles) */ + ADC1->SMPR = ADC_SMPR_SMP_2 | ADC_SMPR_SMP_1; + + /* 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; + + + 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++) { + 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); + } + } +} \ No newline at end of file