twinkle_stick/source/led.h

123 lines
3.0 KiB
C

#ifndef LED_H
#define LED_H
#include "ch.h"
#include "hal.h"
#include <stdint.h>
#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