diff --git a/stm32/aioc-fw/Src/led.c b/stm32/aioc-fw/Src/led.c index 1cbee73..00e6cdf 100644 --- a/stm32/aioc-fw/Src/led.c +++ b/stm32/aioc-fw/Src/led.c @@ -1,5 +1,75 @@ #include "led.h" #include "stm32f3xx_hal.h" +#include + +uint8_t LedStates[2] = {0, 0}; +uint8_t LedModes[2] = {LED_MODE_SOLID, LED_MODE_SOLID}; +uint8_t LedLevels[2] = {LED_IDLE_LEVEL, LED_IDLE_LEVEL}; +uint16_t LedCounter = 0; +uint16_t LedCounterPrev = 0; + +#define LED_SET1(x) LED_TIMER->CCR3 = (512 - ( ((uint32_t) (x)) & 0xFF )) +#define LED_SET2(x) LED_TIMER->CCR4 = ( ((uint32_t) (x)) & 0xFF ) + +void LED_TIMER_IRQ(void) +{ + LED_TIMER->SR = (uint32_t) ~TIM_SR_UIF; + + for (uint8_t i=0; i<2; i++) { + uint8_t mode = LedModes[i]; + + switch (mode) { + case LED_MODE_SLOWPULSE4X: + case LED_MODE_SLOWPULSE3X: + case LED_MODE_SLOWPULSE2X: + case LED_MODE_SLOWPULSE: + if ( !(LedCounterPrev & 0x200) && (LedCounter & 0x200) ) { + /* Rising Edge */ + LedLevels[i] = LED_FULL_LEVEL; + } else if ( (LedCounterPrev & 0x200) && !(LedCounter & 0x200) ) { + /* Falling Edge */ + if (LedLevels[i] != LED_IDLE_LEVEL) { + /* Only reset colors and mode when a pulse has been carried out */ + LedLevels[i] = LED_IDLE_LEVEL; + LedModes[i] = mode > LED_MODE_SLOWPULSE ? mode - 1 : LED_MODE_SOLID; + } + } + break; + + case LED_MODE_FASTPULSE4X: + case LED_MODE_FASTPULSE3X: + case LED_MODE_FASTPULSE2X: + case LED_MODE_FASTPULSE: + if ( !(LedCounterPrev & 0x40) && (LedCounter & 0x40) ) { + /* Rising Edge */ + LedLevels[i] = LED_FULL_LEVEL; + } else if ( (LedCounterPrev & 0x40) && !(LedCounter & 0x40) ) { + /* Falling Edge */ + if (LedLevels[i] != LED_IDLE_LEVEL) { + LedLevels[i] = LED_IDLE_LEVEL; + LedModes[i] = mode > LED_MODE_FASTPULSE ? mode - 1 : LED_MODE_SOLID; + } + } + break; + + case LED_MODE_SOLID: + LedLevels[i] = LedStates[i] ? LED_FULL_LEVEL : LED_IDLE_LEVEL; + break; + + default: + assert(0); + break; + } + } + + /* LEDs are connected anti-parallel */ + LED_TIMER->CCR3 = (512 - (uint32_t) LedLevels[0]); + LED_TIMER->CCR4 = ( (uint32_t) LedLevels[1]); + + /* Advance counters */ + LedCounterPrev = LedCounter; + LedCounter = (LedCounter + 1) & 0xFFF; +} void LED_Init(void) { @@ -27,5 +97,9 @@ void LED_Init(void) LED_TIMER->CCR3 = 0; LED_TIMER->CCR4 = 512; LED_TIMER->EGR = TIM_EGR_UG; + LED_TIMER->DIER = TIM_DIER_UIE; LED_TIMER->CR1 |= TIM_CR1_CEN; + + + NVIC_EnableIRQ(TIM4_IRQn); } diff --git a/stm32/aioc-fw/Src/led.h b/stm32/aioc-fw/Src/led.h index ddf8f74..0ca80ba 100644 --- a/stm32/aioc-fw/Src/led.h +++ b/stm32/aioc-fw/Src/led.h @@ -4,15 +4,31 @@ #include "stm32f3xx_hal.h" #define LED_TIMER TIM4 +#define LED_TIMER_IRQ TIM4_IRQHandler #define LED_GPIO GPIOB #define LED_GPIO_PIN1 GPIO_PIN_8 #define LED_GPIO_PIN2 GPIO_PIN_9 -#define LED_IDLE_LEVEL 0.1 -#define LED_FULL_LEVEL 1.0 +#define LED_IDLE_LEVEL 25 +#define LED_FULL_LEVEL 255 -#define LED_SET1(x) LED_TIMER->CCR3 = (512 - ( ((uint32_t) ((x) * 255)) & 0xFF )) -#define LED_SET2(x) LED_TIMER->CCR4 = ( ((uint32_t) ((x) * 255)) & 0xFF ) +typedef enum { + LED_MODE_SOLID = 0, + LED_MODE_SLOWPULSE = 4, + LED_MODE_SLOWPULSE2X = 5, + LED_MODE_SLOWPULSE3X = 6, + LED_MODE_SLOWPULSE4X = 7, + LED_MODE_FASTPULSE = 8, + LED_MODE_FASTPULSE2X = 9, + LED_MODE_FASTPULSE3X = 10, + LED_MODE_FASTPULSE4X = 11 +} Led_Mode; + +extern uint8_t LedStates[2]; +extern uint8_t LedModes[2]; + +#define LED_SET(i, onOff) { __disable_irq(); LedStates[i] = !!(onOff); __enable_irq(); } +#define LED_MODE(i, mode) { __disable_irq(); LedModes[i] = (mode); __enable_irq(); } void LED_Init(void); diff --git a/stm32/aioc-fw/Src/main.c b/stm32/aioc-fw/Src/main.c index 20c31e2..bf343c1 100644 --- a/stm32/aioc-fw/Src/main.c +++ b/stm32/aioc-fw/Src/main.c @@ -66,10 +66,11 @@ int main(void) LED_Init(); + LED_MODE(0, LED_MODE_SLOWPULSE3X); + LED_MODE(1, LED_MODE_SLOWPULSE3X); + USB_Init(); - LED_SET1(LED_IDLE_LEVEL); - LED_SET2(LED_IDLE_LEVEL); while (1) { USB_Task(); diff --git a/stm32/aioc-fw/Src/usb_serial.c b/stm32/aioc-fw/Src/usb_serial.c index 1c6837b..f0fadc2 100644 --- a/stm32/aioc-fw/Src/usb_serial.c +++ b/stm32/aioc-fw/Src/usb_serial.c @@ -16,6 +16,7 @@ void USB_SERIAL_UART_IRQ(void) int32_t c = tud_cdc_n_read_char(ITF_NUM_CDC_0); assert(c != -1); USB_SERIAL_UART->TDR = (uint8_t) c; + LED_MODE(1, LED_MODE_FASTPULSE); } else { /* No char left in fifo. Disable TX-empty interrupt */ __disable_irq(); @@ -29,6 +30,7 @@ void USB_SERIAL_UART_IRQ(void) if (tud_cdc_n_write_available(ITF_NUM_CDC_0) > 0) { uint8_t c = USB_SERIAL_UART->RDR; tud_cdc_n_write(ITF_NUM_CDC_0, &c, 1); + LED_MODE(0, LED_MODE_FASTPULSE); } else { /* No space in fifo currently. Pause this interrupt and re-enable later */ __disable_irq(); @@ -132,19 +134,19 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) if (dtr & !rts) { /* PTT1 */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); - LED_SET2(LED_FULL_LEVEL); + LED_SET(1, 1); } else { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); - LED_SET2(LED_IDLE_LEVEL); + LED_SET(1, 0); } if (!dtr & rts) { /* PTT2 */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); - LED_SET1(LED_FULL_LEVEL); + LED_SET(0, 1); } else { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); - LED_SET1(LED_IDLE_LEVEL); + LED_SET(0, 0); } }