From 57c94b242340dc1414a9ff4fe4495d1a9c208a5c Mon Sep 17 00:00:00 2001 From: "Jasper v. Blanckenburg" Date: Sat, 25 Mar 2023 00:36:56 +0100 Subject: [PATCH] Add LED animatinos --- AZURE_RTOS/App/app_azure_rtos.c | 13 +++ AZURE_RTOS/App/app_azure_rtos.h | 2 + Core/Inc/leds.h | 18 ++++ Core/Src/leds.c | 141 ++++++++++++++++++++++++++++++++ 4 files changed, 174 insertions(+) diff --git a/AZURE_RTOS/App/app_azure_rtos.c b/AZURE_RTOS/App/app_azure_rtos.c index dc6f155..c5641e8 100644 --- a/AZURE_RTOS/App/app_azure_rtos.c +++ b/AZURE_RTOS/App/app_azure_rtos.c @@ -21,6 +21,7 @@ /* Includes ------------------------------------------------------------------*/ #include "app_azure_rtos.h" +#include "leds.h" #include "stm32h7xx.h" /* Private includes ----------------------------------------------------------*/ @@ -68,6 +69,7 @@ static TX_BYTE_POOL tx_app_byte_pool; TX_THREAD app_thread; TX_THREAD ui_thread; TX_THREAD vehicle_thread; +TX_THREAD led_thread; TX_QUEUE gui_button_queue; TX_EVENT_FLAGS_GROUP gui_update_events; /* USER CODE END PV */ @@ -198,6 +200,17 @@ VOID tx_application_define(VOID *first_unused_memory) { Error_Handler(); } + void *led_thread_stack = mem; + mem += THREAD_STACK_SIZE; + void *led_child_thread_stack = mem; + mem += THREAD_STACK_SIZE; + if (tx_thread_create(&led_thread, "LED Thread", led_thread_entry, + (ULONG)led_child_thread_stack, led_thread_stack, + THREAD_STACK_SIZE, THREAD_PRIO_LED, THREAD_PRIO_LED, 0, + TX_AUTO_START) != TX_SUCCESS) { + Error_Handler(); + } + if (MX_TouchGFX_Init(mem) != TX_SUCCESS) { Error_Handler(); } diff --git a/AZURE_RTOS/App/app_azure_rtos.h b/AZURE_RTOS/App/app_azure_rtos.h index da8dc99..34bb52e 100644 --- a/AZURE_RTOS/App/app_azure_rtos.h +++ b/AZURE_RTOS/App/app_azure_rtos.h @@ -46,6 +46,8 @@ extern "C" { #define THREAD_PRIO_APP 10 #define THREAD_PRIO_UI 6 #define THREAD_PRIO_VEHICLE 7 +#define THREAD_PRIO_LED 11 +#define THREAD_PRIO_LED_CHILD 12 #define UI_QUEUE_SIZE 10 #define VEHICLE_UPDATE_QUEUE_SIZE 100 /* USER CODE END EC */ diff --git a/Core/Inc/leds.h b/Core/Inc/leds.h index abf121b..475dd9e 100644 --- a/Core/Inc/leds.h +++ b/Core/Inc/leds.h @@ -6,6 +6,7 @@ extern "C" { #endif #include "stm32h7xx_hal.h" +#include "tx_port.h" #define N_LEDS 9 @@ -16,6 +17,23 @@ extern "C" { void led_init(SPI_HandleTypeDef *spi, TIM_HandleTypeDef *pwmtim); void led_set(size_t idx, uint8_t r, uint8_t g, uint8_t b); +void led_all_off(); + +void led_thread_entry(ULONG child_thread_stack_addr); + +typedef enum { + ANIM_TE_STARTUP, + ANIM_FT_STARTUP, + ANIM_KNIGHT_RIDER, +} LEDAnimation; + +void led_start_animation(LEDAnimation anim); +void led_anim_te_startup(ULONG _); +void led_anim_ft_startup(ULONG _); +void led_anim_knight_rider(ULONG _); +void led_anim_blinker(uint8_t r, uint8_t g, uint8_t b, + uint32_t brightness_steps, uint32_t next_led_steps, + uint32_t delay); #ifdef __cplusplus } diff --git a/Core/Src/leds.c b/Core/Src/leds.c index 204bfd3..d08a9bb 100644 --- a/Core/Src/leds.c +++ b/Core/Src/leds.c @@ -1,17 +1,21 @@ #include "leds.h" +#include "app_azure_rtos.h" #include "main.h" #include "stm32h7xx_hal_dma.h" #include "stm32h7xx_hal_gpio.h" #include "stm32h7xx_hal_spi.h" #include "stm32h7xx_hal_tim.h" +#include "tx_api.h" SPI_HandleTypeDef *hspi; TIM_HandleTypeDef *htim; extern uint16_t led_buf[256][3]; static size_t led_buf_idx = 0; +static TX_THREAD child_thread; +static void *child_thread_stack; void led_init(SPI_HandleTypeDef *spi, TIM_HandleTypeDef *pwmtim) { hspi = spi; @@ -55,6 +59,143 @@ void led_set(size_t idx, uint8_t r, uint8_t g, uint8_t b) { } } +void led_all_off() { memset(led_buf, 0, sizeof(led_buf)); } + +void led_thread_entry(ULONG child_thread_stack_addr) { + child_thread_stack = (void *)child_thread_stack_addr; + led_start_animation(ANIM_KNIGHT_RIDER); + while (1) { + tx_thread_sleep(10); + if (child_thread.tx_thread_state == TX_COMPLETED) { + tx_thread_sleep(20); + led_start_animation(ANIM_FT_STARTUP); + } + } +} + +void led_start_animation(LEDAnimation anim) { + if (child_thread.tx_thread_stack_start && // Check if any thread was started + // previously + child_thread.tx_thread_state != TX_COMPLETED && + child_thread.tx_thread_state != TX_TERMINATED) { + if (tx_thread_terminate(&child_thread) != TX_SUCCESS) { + Error_Handler(); + } + } + if (child_thread.tx_thread_stack_start && // Check if any thread was started + // previously + tx_thread_delete(&child_thread) != TX_SUCCESS) { + Error_Handler(); + } + + void (*animation_entry)(ULONG); + switch (anim) { + case ANIM_TE_STARTUP: + animation_entry = led_anim_te_startup; + break; + case ANIM_FT_STARTUP: + animation_entry = led_anim_ft_startup; + break; + case ANIM_KNIGHT_RIDER: + animation_entry = led_anim_knight_rider; + break; + default: + return; + } + + led_all_off(); + if (tx_thread_create(&child_thread, "LED Animation Thread", animation_entry, + 0, child_thread_stack, THREAD_STACK_SIZE, + THREAD_PRIO_LED_CHILD, THREAD_PRIO_LED_CHILD, 0, + TX_AUTO_START) != TX_SUCCESS) { + Error_Handler(); + } +} + +void led_anim_te_startup(ULONG _) { + led_anim_blinker(0xF2, 0x8B, 0x00, 20, 7, 2); +} + +void led_anim_ft_startup(ULONG _) { led_anim_blinker(0xC5, 0, 0, 20, 7, 2); } + +void led_anim_knight_rider(ULONG _) { + const size_t num_leds = 5; + int tail_right = 1; + size_t tail = 0; + while (1) { + size_t x = tail; + int x_right = tail_right; + uint8_t red = 0; + for (size_t i = 0; i < num_leds + 1; i++) { + led_set(x, red, 0, 0); + if (x == 8) { + x_right = 0; + } else if (x == 0) { + x_right = 1; + } + if (x_right) { + x++; + } else { + x--; + } + red += 0xFF / num_leds; + } + if (tail == 8) { + tail_right = 0; + } else if (tail == 0) { + tail_right = 1; + } + if (tail_right) { + tail++; + } else { + tail--; + } + tx_thread_sleep(5); + } +} + +void led_anim_blinker(uint8_t r, uint8_t g, uint8_t b, + uint32_t brightness_steps, uint32_t next_led_steps, + uint32_t delay) { + uint8_t colors[brightness_steps][3]; + for (int i = brightness_steps - 1; i >= 0; i--) { + colors[i][0] = r * i / (brightness_steps - 1); + colors[i][1] = g * i / (brightness_steps - 1); + colors[i][2] = b * i / (brightness_steps - 1); + } + size_t simultaneous_leds = brightness_steps / next_led_steps; + if (simultaneous_leds * next_led_steps != brightness_steps) { + simultaneous_leds++; + } + int inc = 1; + for (int i = 0; i < 2; i++) { + int32_t furthest = 0; + size_t color_idx = 0; + while (furthest < 5 + simultaneous_leds) { + for (size_t offset = 0; offset < simultaneous_leds; offset++) { + int32_t diff = furthest - offset; + size_t led_color_idx = color_idx + offset * next_led_steps; + if (diff < 0 || diff > 4 || led_color_idx >= brightness_steps) { + continue; + } + if (!inc) { + led_color_idx = brightness_steps - led_color_idx - 1; + } + uint8_t *color = colors[led_color_idx]; + led_set(4 + diff, color[0], color[1], color[2]); + led_set(4 - diff, color[0], color[1], color[2]); + } + color_idx++; + if (color_idx == next_led_steps) { + color_idx = 0; + furthest++; + } + tx_thread_sleep(delay); + } + inc = !inc; + } +} + void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *handle) { if (handle != hspi) { return;