#ifndef LED_H #define LED_H #include "ch.h" #include "hal.h" #include #define PWM_TIM_FREQ STM32_PCLK #define PWM_FREQ 800000 #define PWM_PERIOD (PWM_TIM_FREQ/PWM_FREQ) #define ACT_PWM_TIM_FREQ STM32_PCLK #define ACT_PWM_FREQ 1 #define ACT_PWM_PERIOD (ACT_PWM_TIM_FREQ/ACT_PWM_FREQ) #define SIG_LOW (((PWM_PERIOD * 1) / 4) - 1) #define SIG_HIGH (((PWM_PERIOD * 3) / 4) - 1) #define SIG_RESET (PWM_PERIOD - 1) #define LEDS_PER_IRQ (30) #define BYTES_PER_LED 3 #define BITS_PER_LED (8*BYTES_PER_LED) #define DMA_BUF_HALF (LEDS_PER_IRQ * BITS_PER_LED) #define DMA_BUF_LEN (2 * DMA_BUF_HALF) #define RESET_PERIOD_US (25) #define LED_UNIT_US ((BITS_PER_LED * 1000000) / PWM_FREQ) // one "led" is BITS_PER_LED bits / PWM_FREQ seconds long #define RESET_UNITS ((((RESET_PERIOD_US*10) / (LED_UNIT_US)) / 10)) #define RESET_PRE 2 #define LED_EVENT(x) ((eventflags_t)(1 << x)) #define LED_EVENT_DONE LED_EVENT(0) #define LED_EVENT_BUFRDY LED_EVENT(1) #define NUM_DRIVERS 5 #define LEDS_PER_DRIVER 14 #define DRIVER_FB_SIZE (LEDS_PER_DRIVER*NUM_DRIVERS) typedef struct { uint8_t g; uint8_t r; uint8_t b; } led_t; typedef enum { C_OFF = 0, C_DARK_GREEN = 1, C_DARK_RED = 2, C_DARK_BLUE = 3, C_DARK_PURPLE = 4, C_DARK_CYAN = 5, C_DARK_WHITE = 6, C_GREEN = 7, C_RED = 8, C_BLUE = 9, C_WHITE = 10, C_GRAY = 11, C_PALETTE_SIZE = 12, } palette_colour_t; typedef struct led_ctx led_ctx_t; typedef void (*led_done_callback_t)(led_ctx_t * driver); typedef struct { uint8_t bit_sigs[BITS_PER_LED]; } ws2812_signal_t; // Instance of LED driver typedef struct led_ctx { // 1 if the leds are currently updating, 0 if the driver is idle volatile int upd_lck; // dma storage uint8_t dma_buf[DMA_BUF_LEN]; uint8_t * dma_buf_ptr; // number of leds(reset and real) that have been transmitted uint32_t tx_cnt; // number of real and reset leds that have been commited to the buffer uint32_t buf_cnt; // number of leds(reset and real) to be transmitted uint32_t tx_led_cnt; const stm32_dma_stream_t * dma_stream; PWMDriver * pwm_driver; uint8_t tim_channel; uint8_t done; event_source_t event_source; stm32_gpio_t * port; uint8_t pin; uint8_t * framebuffer; uint8_t num; thread_t * draw_thread; } led_ctx_t; typedef struct led_cfg { uint32_t dma_stream_id; PWMDriver * pwm_driver; uint8_t tim_channel; stm32_gpio_t * port; uint8_t pin; uint8_t af; uint8_t num; } led_cfg_t; typedef struct dma_ctx { uint8_t id; volatile bool done; const stm32_dma_stream_t * stream; } dma_ctx_t; extern led_ctx_t led_drivers[NUM_DRIVERS]; extern uint8_t framebuffer[NUM_DRIVERS*LEDS_PER_DRIVER]; extern led_t palette[C_PALETTE_SIZE]; extern event_listener_t event_listeners[NUM_DRIVERS]; int start_led_transfer(led_ctx_t * driver); int setup_led_transfer(led_ctx_t * driver); void led_init(thread_t * draw_thread); void led_draw(event_listener_t* event_listeners); void fill_dmabuf(led_ctx_t * driver); #endif // LED_H