Add LED animatinos
This commit is contained in:
parent
3b2dac7240
commit
57c94b2423
|
@ -21,6 +21,7 @@
|
||||||
/* Includes ------------------------------------------------------------------*/
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "app_azure_rtos.h"
|
#include "app_azure_rtos.h"
|
||||||
|
#include "leds.h"
|
||||||
#include "stm32h7xx.h"
|
#include "stm32h7xx.h"
|
||||||
|
|
||||||
/* Private includes ----------------------------------------------------------*/
|
/* Private includes ----------------------------------------------------------*/
|
||||||
|
@ -68,6 +69,7 @@ static TX_BYTE_POOL tx_app_byte_pool;
|
||||||
TX_THREAD app_thread;
|
TX_THREAD app_thread;
|
||||||
TX_THREAD ui_thread;
|
TX_THREAD ui_thread;
|
||||||
TX_THREAD vehicle_thread;
|
TX_THREAD vehicle_thread;
|
||||||
|
TX_THREAD led_thread;
|
||||||
TX_QUEUE gui_button_queue;
|
TX_QUEUE gui_button_queue;
|
||||||
TX_EVENT_FLAGS_GROUP gui_update_events;
|
TX_EVENT_FLAGS_GROUP gui_update_events;
|
||||||
/* USER CODE END PV */
|
/* USER CODE END PV */
|
||||||
|
@ -198,6 +200,17 @@ VOID tx_application_define(VOID *first_unused_memory) {
|
||||||
Error_Handler();
|
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) {
|
if (MX_TouchGFX_Init(mem) != TX_SUCCESS) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ extern "C" {
|
||||||
#define THREAD_PRIO_APP 10
|
#define THREAD_PRIO_APP 10
|
||||||
#define THREAD_PRIO_UI 6
|
#define THREAD_PRIO_UI 6
|
||||||
#define THREAD_PRIO_VEHICLE 7
|
#define THREAD_PRIO_VEHICLE 7
|
||||||
|
#define THREAD_PRIO_LED 11
|
||||||
|
#define THREAD_PRIO_LED_CHILD 12
|
||||||
#define UI_QUEUE_SIZE 10
|
#define UI_QUEUE_SIZE 10
|
||||||
#define VEHICLE_UPDATE_QUEUE_SIZE 100
|
#define VEHICLE_UPDATE_QUEUE_SIZE 100
|
||||||
/* USER CODE END EC */
|
/* USER CODE END EC */
|
||||||
|
|
|
@ -6,6 +6,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "stm32h7xx_hal.h"
|
#include "stm32h7xx_hal.h"
|
||||||
|
#include "tx_port.h"
|
||||||
|
|
||||||
#define N_LEDS 9
|
#define N_LEDS 9
|
||||||
|
|
||||||
|
@ -16,6 +17,23 @@ extern "C" {
|
||||||
void led_init(SPI_HandleTypeDef *spi, TIM_HandleTypeDef *pwmtim);
|
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_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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
141
Core/Src/leds.c
141
Core/Src/leds.c
|
@ -1,17 +1,21 @@
|
||||||
#include "leds.h"
|
#include "leds.h"
|
||||||
|
|
||||||
|
#include "app_azure_rtos.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include "stm32h7xx_hal_dma.h"
|
#include "stm32h7xx_hal_dma.h"
|
||||||
#include "stm32h7xx_hal_gpio.h"
|
#include "stm32h7xx_hal_gpio.h"
|
||||||
#include "stm32h7xx_hal_spi.h"
|
#include "stm32h7xx_hal_spi.h"
|
||||||
#include "stm32h7xx_hal_tim.h"
|
#include "stm32h7xx_hal_tim.h"
|
||||||
|
#include "tx_api.h"
|
||||||
|
|
||||||
SPI_HandleTypeDef *hspi;
|
SPI_HandleTypeDef *hspi;
|
||||||
TIM_HandleTypeDef *htim;
|
TIM_HandleTypeDef *htim;
|
||||||
|
|
||||||
extern uint16_t led_buf[256][3];
|
extern uint16_t led_buf[256][3];
|
||||||
static size_t led_buf_idx = 0;
|
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) {
|
void led_init(SPI_HandleTypeDef *spi, TIM_HandleTypeDef *pwmtim) {
|
||||||
hspi = spi;
|
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) {
|
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *handle) {
|
||||||
if (handle != hspi) {
|
if (handle != hspi) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue