Add LED animatinos
This commit is contained in:
		@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										141
									
								
								Core/Src/leds.c
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								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;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user