From d7ce66b1d8e673856aab4a83e11895146476cf9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 21 Jun 2022 20:33:23 +0200 Subject: [PATCH 1/7] Prepare DMX development --- firmware/Makefile | 1 + firmware/dmx.c | 1 + firmware/include/ring-light/dmx.h | 4 ++++ 3 files changed, 6 insertions(+) create mode 100644 firmware/dmx.c create mode 100644 firmware/include/ring-light/dmx.h diff --git a/firmware/Makefile b/firmware/Makefile index 8c1d6c5..4dbf383 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -13,6 +13,7 @@ endif #Add Files and Folders below######################################################### CFILES = main.c syscalls/syscalls.c setup/system_init.c startup/startup_stm32f0xx.c CFILES += temp-adc.c +CFILES += dmx.c ASFILES = sk6812.S INCLUDEPATH = -Iinclude -Iinclude/cmsis diff --git a/firmware/dmx.c b/firmware/dmx.c new file mode 100644 index 0000000..6202a36 --- /dev/null +++ b/firmware/dmx.c @@ -0,0 +1 @@ +#include diff --git a/firmware/include/ring-light/dmx.h b/firmware/include/ring-light/dmx.h new file mode 100644 index 0000000..a50d261 --- /dev/null +++ b/firmware/include/ring-light/dmx.h @@ -0,0 +1,4 @@ +#ifndef _DMX_H_ +#define _DMX_H_ + +#endif /* _DMX_H_ */ -- 2.47.0 From 4166396f75d03f5b69a4cbfe0c2d9ac09426ad95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 21 Jun 2022 20:57:56 +0200 Subject: [PATCH 2/7] Add detailed memory usage output to Makefile --- firmware/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/Makefile b/firmware/Makefile index 4dbf383..bb57a08 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -38,7 +38,7 @@ SIZE=arm-none-eabi-size LFLAGS = -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork LFLAGS += -mfloat-abi=soft --disable-newlib-supplied-syscalls -nostartfiles -LFLAGS += -Tstartup/stm32f030.ld -Wl,-Map=$(mapfile).map -Wl,--gc-sections -g +LFLAGS += -Tstartup/stm32f030.ld -Wl,-Map=$(mapfile).map -Wl,--gc-sections -Wl,--print-memory-usage -g CFLAGS = -c -fmessage-length=0 -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork CFLAGS += -mfloat-abi=soft -nostartfiles -Wall -g3 -O0 -- 2.47.0 From 3faab7173cc8260205083602bb62362f4bbca458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 21 Jun 2022 22:04:44 +0200 Subject: [PATCH 3/7] Implement Uart RX functionality. UART RX works. DMX frame detection not yet implemented. --- firmware/dmx.c | 64 +++++++++++++++++++++++++++++++ firmware/include/ring-light/dmx.h | 39 +++++++++++++++++++ firmware/main.c | 13 +++++-- 3 files changed, 113 insertions(+), 3 deletions(-) diff --git a/firmware/dmx.c b/firmware/dmx.c index 6202a36..63c1868 100644 --- a/firmware/dmx.c +++ b/firmware/dmx.c @@ -1 +1,65 @@ #include +#include + +static volatile bool dmx_new_data_avail = false; +static uint32_t dmx_base_channel; +static uint8_t dmx_channel_data[DMX_USED_CHANNEL_COUNT]; + +void dmx_init(uint32_t base_channel) +{ + int i; + uint8_t *ptr; + + dmx_new_data_avail = false; + for (i = 0, ptr = dmx_channel_data; i < DMX_USED_CHANNEL_COUNT; i++, ptr++) { + *ptr = 0u; + } + + dmx_base_channel = base_channel; + + /* Enable GPIOA and USART1 clock */ + RCC->AHBENR |= RCC_AHBENR_GPIOAEN; + RCC->APB2ENR |= RCC_APB2ENR_USART1EN; + + /* Switch RXTX pin low, activating permanent READ mode */ + GPIOA->MODER |= (0x1<<(2*5)); + GPIOA->BRR |= (1<<5); + + /* Switch PA10 to RX alternate function of USART1 (AF1) */ + GPIOA->MODER |= (0x2<<(2*10)); + GPIOA->AFR[1] |=(0x1<<(4*2)); + + /* Set baudrate: 48MHz / 250k = 129 */ + USART1->BRR = 192u; + USART1->CR3 = USART_CR3_EIE; + USART1->CR2 = USART_CR2_STOP_1; + USART1->CR1 = USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_UE; + + NVIC_EnableIRQ(USART1_IRQn); +} + +bool dmx_new_data_available() +{ + return dmx_new_data_avail; +} + +const uint8_t *dmx_get_data() +{ + return dmx_channel_data; +} + +void USART1_IRQHandler(void) +{ + uint32_t isr; + volatile uint8_t dreg; + + isr = USART1->ISR; + USART1->ICR = USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF; + + if (isr & USART_ISR_RXNE) { + dreg = (uint8_t)USART1->RDR; + dmx_channel_data[0] = dreg; + } + + __DSB(); +} diff --git a/firmware/include/ring-light/dmx.h b/firmware/include/ring-light/dmx.h index a50d261..2c35889 100644 --- a/firmware/include/ring-light/dmx.h +++ b/firmware/include/ring-light/dmx.h @@ -1,4 +1,43 @@ #ifndef _DMX_H_ #define _DMX_H_ + + +#include +#include + +#define DMX_UNIVERSE_SIZE (255u) +#define DMX_USED_CHANNEL_COUNT (129u) + +/** + * @brief Init DMX reception + * + * DMX data is received from the base channel onwards: + * - R LED1 + * - G LED1 + * - B LED1 + * - W LED1 + * - R LED2 + * ... + * - W LED32 + * - W DISCRETE + * + * In Sum: 129 8 bit channels + * + * @param base_channel Base channel the ring light will listen on + */ +void dmx_init(uint32_t base_channel); + +/** + * @brief Has new DMX data been received? + * @return true if new data is available + */ +bool dmx_new_data_available(void); + +/** + * @brief Returns the array of the 129 DMX channels + * @return + */ +const uint8_t *dmx_get_data(void); + #endif /* _DMX_H_ */ diff --git a/firmware/main.c b/firmware/main.c index a42b06c..1bba292 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -2,6 +2,7 @@ #include #include #include +#include #define RING_MAX_LED 32u #define MAX_TEMP_CELSIUS 70 @@ -37,7 +38,7 @@ int main(void) uint8_t led_pwm_val = 0u; bool button_pressed = false; - enum ring_modes mode = RING_MODE_ALL; + enum ring_modes mode; RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; @@ -83,6 +84,7 @@ int main(void) mode = RING_MODE_WHITE_DISCRETE; temperature_adc_init(); + dmx_init(0u); SysTick_Config(800000); while(1) { @@ -171,11 +173,16 @@ int main(void) } TIM14->CCR1 = led_pwm_val; - __disable_irq(); + for(int i = 0; i < RING_MAX_LED; i ++) { + /* Allow interrupts in between LEDs. + * They must not exceed the reset length of 80us of SK6812. + */ + __disable_irq(); sk6812_send_led(led_calc_val[i]); + __enable_irq(); } - __enable_irq(); + wait_for_ticks(5); if((int16_t)TIM3->CNT > (int16_t)led_val) { -- 2.47.0 From d06b2b7eafa9e6fd761c755b6072de82bea4b33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Fri, 24 Jun 2022 18:08:28 +0200 Subject: [PATCH 4/7] Implement test RX for DMX. Still no functionality --- firmware/dmx.c | 58 ++++++++++++++++++++++++------- firmware/include/ring-light/dmx.h | 6 ---- firmware/temp-adc.c | 2 +- 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/firmware/dmx.c b/firmware/dmx.c index 63c1868..5986a57 100644 --- a/firmware/dmx.c +++ b/firmware/dmx.c @@ -1,21 +1,34 @@ #include #include -static volatile bool dmx_new_data_avail = false; static uint32_t dmx_base_channel; -static uint8_t dmx_channel_data[DMX_USED_CHANNEL_COUNT]; + +enum dmx_rx_state_enum { + DMX_RX_WAIT_FOR_BREAK = 0, + DMX_RX_DATA, +}; + +/** + * @brief DMX data received. Contains the whole DMX universe including the first 0 byte. + * The controller does check the first byte to be zero. + */ +static volatile uint8_t dmx_channel_data[DMX_UNIVERSE_SIZE + 1]; + +static volatile enum dmx_rx_state_enum dmx_rx_state; +static volatile uint32_t dmx_write_pointer; void dmx_init(uint32_t base_channel) { int i; - uint8_t *ptr; + volatile uint8_t *ptr; - dmx_new_data_avail = false; for (i = 0, ptr = dmx_channel_data; i < DMX_USED_CHANNEL_COUNT; i++, ptr++) { *ptr = 0u; } dmx_base_channel = base_channel; + dmx_write_pointer = 0u; + dmx_rx_state = DMX_RX_WAIT_FOR_BREAK; /* Enable GPIOA and USART1 clock */ RCC->AHBENR |= RCC_AHBENR_GPIOAEN; @@ -35,31 +48,52 @@ void dmx_init(uint32_t base_channel) USART1->CR2 = USART_CR2_STOP_1; USART1->CR1 = USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_UE; + /* Map USART1 RX to DMA Channel 3 */ + SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_USART1RX_DMA_RMP; + NVIC_EnableIRQ(USART1_IRQn); } -bool dmx_new_data_available() -{ - return dmx_new_data_avail; -} const uint8_t *dmx_get_data() { - return dmx_channel_data; + return (const uint8_t *)&dmx_channel_data[1]; } void USART1_IRQHandler(void) { uint32_t isr; - volatile uint8_t dreg; + uint8_t dreg; isr = USART1->ISR; USART1->ICR = USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF; - if (isr & USART_ISR_RXNE) { + if (isr & USART_ISR_FE) { + /* Frame error received. Start of DMX frame */ + dmx_write_pointer = 0u; + dmx_rx_state = DMX_RX_DATA; + /* Flush RX data */ + USART1->RQR = USART_RQR_RXFRQ; + } else if (isr & USART_ISR_RXNE) { + /* Received valid symbol */ dreg = (uint8_t)USART1->RDR; - dmx_channel_data[0] = dreg; + + if (dmx_rx_state == DMX_RX_DATA) { + /* Ready to recieve data */ + if (dmx_write_pointer < (DMX_UNIVERSE_SIZE + 1)) { + dmx_channel_data[dmx_write_pointer] = dreg; + dmx_write_pointer++; + } else { + dmx_rx_state = DMX_RX_WAIT_FOR_BREAK; + } + } + } __DSB(); } + +void DMA_CH2_3_DMA2_CH1_2_IRQHandler() +{ + +} diff --git a/firmware/include/ring-light/dmx.h b/firmware/include/ring-light/dmx.h index 2c35889..748f11b 100644 --- a/firmware/include/ring-light/dmx.h +++ b/firmware/include/ring-light/dmx.h @@ -28,12 +28,6 @@ */ void dmx_init(uint32_t base_channel); -/** - * @brief Has new DMX data been received? - * @return true if new data is available - */ -bool dmx_new_data_available(void); - /** * @brief Returns the array of the 129 DMX channels * @return diff --git a/firmware/temp-adc.c b/firmware/temp-adc.c index a488a55..d3c019c 100644 --- a/firmware/temp-adc.c +++ b/firmware/temp-adc.c @@ -96,7 +96,7 @@ void DMA_CH1_IRQHandler(void) uint32_t isr; isr = DMA1->ISR; - DMA1->IFCR = isr; + DMA1->IFCR = isr & 0xF; if (isr & DMA_ISR_TCIF1) { process_adc_samples(); -- 2.47.0 From 60f1923abee1f08c26f3d962e47d2615109d8481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Fri, 24 Jun 2022 19:43:00 +0200 Subject: [PATCH 5/7] Implement first draft of working DMX. Still needs rework and beatifying --- firmware/dmx.c | 73 +++++++++++++++++++++---------- firmware/include/ring-light/dmx.h | 12 +++++ firmware/main.c | 65 +++++++++++++++++++++------ 3 files changed, 114 insertions(+), 36 deletions(-) diff --git a/firmware/dmx.c b/firmware/dmx.c index 5986a57..16636cc 100644 --- a/firmware/dmx.c +++ b/firmware/dmx.c @@ -8,15 +8,14 @@ enum dmx_rx_state_enum { DMX_RX_DATA, }; +static volatile bool break_received; + /** * @brief DMX data received. Contains the whole DMX universe including the first 0 byte. * The controller does check the first byte to be zero. */ static volatile uint8_t dmx_channel_data[DMX_UNIVERSE_SIZE + 1]; -static volatile enum dmx_rx_state_enum dmx_rx_state; -static volatile uint32_t dmx_write_pointer; - void dmx_init(uint32_t base_channel) { int i; @@ -27,11 +26,10 @@ void dmx_init(uint32_t base_channel) } dmx_base_channel = base_channel; - dmx_write_pointer = 0u; - dmx_rx_state = DMX_RX_WAIT_FOR_BREAK; + break_received = false; /* Enable GPIOA and USART1 clock */ - RCC->AHBENR |= RCC_AHBENR_GPIOAEN; + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_DMAEN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN; /* Switch RXTX pin low, activating permanent READ mode */ @@ -51,49 +49,78 @@ void dmx_init(uint32_t base_channel) /* Map USART1 RX to DMA Channel 3 */ SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_USART1RX_DMA_RMP; + DMA1_Channel3->CCR = DMA_CCR_PL_1 | DMA_CCR_MINC | DMA_CCR_TCIE; + + NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); NVIC_EnableIRQ(USART1_IRQn); } const uint8_t *dmx_get_data() { - return (const uint8_t *)&dmx_channel_data[1]; + return (const uint8_t *)dmx_channel_data; } void USART1_IRQHandler(void) { uint32_t isr; - uint8_t dreg; isr = USART1->ISR; USART1->ICR = USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF; if (isr & USART_ISR_FE) { /* Frame error received. Start of DMX frame */ - dmx_write_pointer = 0u; - dmx_rx_state = DMX_RX_DATA; /* Flush RX data */ USART1->RQR = USART_RQR_RXFRQ; + USART1->CR3 |= USART_CR3_DMAR; + DMA1_Channel3->CCR &= ~DMA_CCR_EN; + DMA1_Channel3->CMAR = (uint32_t)dmx_channel_data; + DMA1_Channel3->CPAR = (uint32_t)&USART1->RDR; + DMA1_Channel3->CNDTR = DMX_UNIVERSE_SIZE + 1; + DMA1_Channel3->CCR |= DMA_CCR_EN; + USART1->CR3 |= USART_CR3_DMAR; + break_received = true; } else if (isr & USART_ISR_RXNE) { - /* Received valid symbol */ - dreg = (uint8_t)USART1->RDR; - - if (dmx_rx_state == DMX_RX_DATA) { - /* Ready to recieve data */ - if (dmx_write_pointer < (DMX_UNIVERSE_SIZE + 1)) { - dmx_channel_data[dmx_write_pointer] = dreg; - dmx_write_pointer++; - } else { - dmx_rx_state = DMX_RX_WAIT_FOR_BREAK; - } - } } __DSB(); } -void DMA_CH2_3_DMA2_CH1_2_IRQHandler() +void DMA_CH2_3_DMA2_CH1_2_IRQHandler(void) { + uint32_t isr; + isr = DMA1->ISR; + /* Only clear the interupts of channel 2 (bits 11:9) */ + DMA1->IFCR = isr & 0xF00; + + if (isr & DMA_ISR_TCIF3) { + DMA1->ISR; + } + __DSB(); +} + +bool dmx_poll_break_received(void) +{ + bool ret; + + /* Atomically reset the flag */ + __disable_irq(); + ret = break_received; + break_received = false; + __enable_irq(); + + return ret; +} + +bool dmx_enough_data_received() +{ + uint32_t received_count = (DMX_UNIVERSE_SIZE + 1) - DMA1_Channel3->CNDTR; + + if (received_count > (dmx_base_channel + DMX_USED_CHANNEL_COUNT)) { + return true; + } + + return false; } diff --git a/firmware/include/ring-light/dmx.h b/firmware/include/ring-light/dmx.h index 748f11b..68970db 100644 --- a/firmware/include/ring-light/dmx.h +++ b/firmware/include/ring-light/dmx.h @@ -34,4 +34,16 @@ void dmx_init(uint32_t base_channel); */ const uint8_t *dmx_get_data(void); +/** + * @brief Check if a break was received. This resets the flag + * @return true if a break was received since the last time calling this function + */ +bool dmx_poll_break_received(void); + +/** + * @brief The DMX receiver has received all data for the ring light. It can be read + * @return + */ +bool dmx_enough_data_received(void); + #endif /* _DMX_H_ */ diff --git a/firmware/main.c b/firmware/main.c index 1bba292..add76ee 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -16,7 +16,9 @@ enum ring_modes { RING_MODE_ARC, /*!< SK6812 closing ring */ RING_MODE_QUARTER, /*!< SK6812 walking quarter */ RING_MODE_IN_FARBE_UND_BUNT, /*!< SK6812 color mix */ - RING_MODE_MAX /*!< end of list */ + RING_MODE_MAX, /*!< end of list */ + RING_MODE_WAIT_DMX, + RING_MODE_WAIT_DMX_BREAK }; volatile int32_t temperature; @@ -34,10 +36,13 @@ static void wait_for_ticks(uint32_t ticks) int main(void) { uint32_t led_val = 0x00UL; + uint32_t last_led_val = 0x00UL; uint32_t led_calc_val[RING_MAX_LED] = {0x00UL}; uint8_t led_pwm_val = 0u; + const uint8_t *dmx_data; bool button_pressed = false; + bool force_led_update; enum ring_modes mode; RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; @@ -88,14 +93,23 @@ int main(void) SysTick_Config(800000); while(1) { + force_led_update = false; temperature = temperature_adc_get_temp(); + if (led_val != last_led_val || button_pressed) { + force_led_update = true; + } + /*! -# Gradually dim down the LED brightness in case the temperature is too high */ if (temperature > ((MAX_TEMP_CELSIUS) * 10)) { if (led_val > 20) led_val--; } + if (dmx_poll_break_received()) { + mode = RING_MODE_WAIT_DMX; + } + led_pwm_val = 0u; switch (mode) { @@ -165,6 +179,26 @@ int main(void) } } break; + case RING_MODE_WAIT_DMX: + force_led_update = false; + if (dmx_enough_data_received()) { + dmx_data = dmx_get_data(); + mode = RING_MODE_WAIT_DMX_BREAK; + if (dmx_data[0] != 0) + break; + for (int i = 0; i < RING_MAX_LED; i++) { + led_calc_val[i] = (dmx_data[1 + i*4 + 3]) | + (dmx_data[1 + i*4 + 2] << 8) | + (dmx_data[1 + i*4 + 0] << 16) | + (dmx_data[1 + i*4 + 1] << 24); + } + led_pwm_val = dmx_data[129]; + force_led_update = true; + } + break; + case RING_MODE_WAIT_DMX_BREAK: + force_led_update = false; + break; default: for(int i = 0; i < RING_MAX_LED; i ++) { led_calc_val[i] = 0x00000000UL; @@ -172,30 +206,35 @@ int main(void) break; } - TIM14->CCR1 = led_pwm_val; + if (force_led_update) { + TIM14->CCR1 = led_pwm_val; - for(int i = 0; i < RING_MAX_LED; i ++) { - /* Allow interrupts in between LEDs. - * They must not exceed the reset length of 80us of SK6812. - */ - __disable_irq(); - sk6812_send_led(led_calc_val[i]); - __enable_irq(); + for(int i = 0; i < RING_MAX_LED; i ++) { + /* Allow interrupts in between LEDs. + * They must not exceed the reset length of 80us of SK6812. + */ + __disable_irq(); + sk6812_send_led(led_calc_val[i]); + __enable_irq(); + } + last_led_val = led_val; } + + wait_for_ticks(5); if((int16_t)TIM3->CNT > (int16_t)led_val) { led_val = 0u; - } - else if(((int16_t)led_val - (int16_t)TIM3->CNT) > UINT8_MAX) { + } else if(((int16_t)led_val - (int16_t)TIM3->CNT) > UINT8_MAX) { led_val = 255u; - } - else { + } else { led_val = (int16_t)led_val - (int16_t)TIM3->CNT; } + TIM3->CNT = 0u; + if(button_pressed) { if(GPIOA->IDR & GPIO_IDR_0) { button_pressed = false; -- 2.47.0 From 8dc30f15fbd5c16c5bfe2af18b7bab96d898f460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Thu, 7 Jul 2022 17:40:25 +0200 Subject: [PATCH 6/7] Implement first working version of DMX receiver. Might still be buggy --- firmware/dmx.c | 14 ++++++++++++-- firmware/include/ring-light/dmx.h | 2 +- firmware/main.c | 6 +++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/firmware/dmx.c b/firmware/dmx.c index 16636cc..82da070 100644 --- a/firmware/dmx.c +++ b/firmware/dmx.c @@ -3,11 +3,15 @@ static uint32_t dmx_base_channel; + enum dmx_rx_state_enum { DMX_RX_WAIT_FOR_BREAK = 0, DMX_RX_DATA, }; +static volatile enum dmx_rx_state_enum dmx_state; + + static volatile bool break_received; /** @@ -71,17 +75,22 @@ void USART1_IRQHandler(void) if (isr & USART_ISR_FE) { /* Frame error received. Start of DMX frame */ /* Flush RX data */ + USART1->CR3 &= ~USART_CR3_DMAR; USART1->RQR = USART_RQR_RXFRQ; - USART1->CR3 |= USART_CR3_DMAR; DMA1_Channel3->CCR &= ~DMA_CCR_EN; + while (DMA1_Channel3->CCR & DMA_CCR_EN); DMA1_Channel3->CMAR = (uint32_t)dmx_channel_data; DMA1_Channel3->CPAR = (uint32_t)&USART1->RDR; DMA1_Channel3->CNDTR = DMX_UNIVERSE_SIZE + 1; DMA1_Channel3->CCR |= DMA_CCR_EN; + USART1->RQR = USART_RQR_RXFRQ; USART1->CR3 |= USART_CR3_DMAR; break_received = true; + dmx_state = DMX_RX_DATA; } else if (isr & USART_ISR_RXNE) { - + if (dmx_state != DMX_RX_DATA) { + USART1->RQR = USART_RQR_RXFRQ; + } } __DSB(); @@ -97,6 +106,7 @@ void DMA_CH2_3_DMA2_CH1_2_IRQHandler(void) if (isr & DMA_ISR_TCIF3) { DMA1->ISR; + dmx_state = DMX_RX_WAIT_FOR_BREAK; } __DSB(); } diff --git a/firmware/include/ring-light/dmx.h b/firmware/include/ring-light/dmx.h index 68970db..6fdcbf1 100644 --- a/firmware/include/ring-light/dmx.h +++ b/firmware/include/ring-light/dmx.h @@ -6,7 +6,7 @@ #include #include -#define DMX_UNIVERSE_SIZE (255u) +#define DMX_UNIVERSE_SIZE (512u) #define DMX_USED_CHANNEL_COUNT (129u) /** diff --git a/firmware/main.c b/firmware/main.c index add76ee..34d978a 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -220,9 +220,9 @@ int main(void) last_led_val = led_val; } - - - wait_for_ticks(5); + /* Only wait in case of non-DMX mode */ + if (!(mode == RING_MODE_WAIT_DMX_BREAK || mode == RING_MODE_WAIT_DMX)) + wait_for_ticks(5); if((int16_t)TIM3->CNT > (int16_t)led_val) { led_val = 0u; -- 2.47.0 From be3efc07d3ca2b8747398b2a72475c8f7ad71f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Fri, 15 Jul 2022 19:48:55 +0200 Subject: [PATCH 7/7] Improve implementation. Add blinking red led to overtemperature mode --- firmware/main.c | 63 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/firmware/main.c b/firmware/main.c index 34d978a..0cdc88e 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -26,6 +26,7 @@ volatile int32_t temperature; extern void sk6812_send_led(uint32_t rgbw); volatile uint32_t wait_tick = 0; +volatile bool blink_tick = false; static void wait_for_ticks(uint32_t ticks) { @@ -43,8 +44,13 @@ int main(void) bool button_pressed = false; bool force_led_update; + bool overtemp_flag = false; enum ring_modes mode; + /* Led value / mode before going to DMX */ + uint32_t led_val_before_dmx = 0u; + enum ring_modes mode_before_dmx = RING_MODE_RED; /* Init to save value */ + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; @@ -101,12 +107,26 @@ int main(void) } /*! -# Gradually dim down the LED brightness in case the temperature is too high */ - if (temperature > ((MAX_TEMP_CELSIUS) * 10)) { - if (led_val > 20) + if (overtemp_flag) { + if (temperature < (MAX_TEMP_CELSIUS-15) * 10) { + overtemp_flag = false; + } + } else { + overtemp_flag = temperature > ((MAX_TEMP_CELSIUS) * 10) ? true : false; + } + if (overtemp_flag) { + if (led_val > 2 && mode < RING_MODE_MAX) led_val--; } if (dmx_poll_break_received()) { + /* DMX received. Go to DMX mode. + * Save old state + */ + if (mode < RING_MODE_MAX) { + led_val_before_dmx = led_val; + mode_before_dmx = mode; + } mode = RING_MODE_WAIT_DMX; } @@ -181,7 +201,7 @@ int main(void) break; case RING_MODE_WAIT_DMX: force_led_update = false; - if (dmx_enough_data_received()) { + if (dmx_enough_data_received() && !overtemp_flag) { dmx_data = dmx_get_data(); mode = RING_MODE_WAIT_DMX_BREAK; if (dmx_data[0] != 0) @@ -194,6 +214,12 @@ int main(void) } led_pwm_val = dmx_data[129]; force_led_update = true; + } else if (overtemp_flag) { + force_led_update = true; + for (int i = 0; i < RING_MAX_LED; i++) { + led_calc_val[i] = 0ul; + } + led_pwm_val = 0; } break; case RING_MODE_WAIT_DMX_BREAK: @@ -206,6 +232,11 @@ int main(void) break; } + if (overtemp_flag) { + force_led_update = true; + led_calc_val[0] = blink_tick ? 0x00FF0000UL : 0UL; + } + if (force_led_update) { TIM14->CCR1 = led_pwm_val; @@ -221,7 +252,7 @@ int main(void) } /* Only wait in case of non-DMX mode */ - if (!(mode == RING_MODE_WAIT_DMX_BREAK || mode == RING_MODE_WAIT_DMX)) + if (!(mode == RING_MODE_WAIT_DMX_BREAK || mode == RING_MODE_WAIT_DMX) || overtemp_flag) wait_for_ticks(5); if((int16_t)TIM3->CNT > (int16_t)led_val) { @@ -239,14 +270,30 @@ int main(void) if(GPIOA->IDR & GPIO_IDR_0) { button_pressed = false; } - } - else if(!(GPIOA->IDR & GPIO_IDR_0)) { - mode = (mode + 1) % RING_MODE_MAX; + } else if(!(GPIOA->IDR & GPIO_IDR_0)) { button_pressed = true; + /* Button pressed */ + if (mode > RING_MODE_MAX) { + /* In DMX mode. Abort DMX mode */ + mode = mode_before_dmx; + led_val = led_val_before_dmx; + } else { + /* Normal mode switching */ + mode = (mode + 1) % RING_MODE_MAX; + } } } } -void SysTick_Handler(void) { +void SysTick_Handler(void) +{ + static uint32_t tick = 10; + + if (!--tick) { + tick = 10; + blink_tick = !blink_tick; + } + + wait_tick++; } -- 2.47.0