Browse Source
supports WS2811, WS2812, WS2813, SK6812, and SK6812RGBW families does not yet map colors correctly (e.g. WS2812 orders colors 'GRB' whereas others use RGB) removed ws2812b_fx codemaster
6 changed files with 260 additions and 2517 deletions
@ -1,51 +0,0 @@ |
|||||||
/*
|
|
||||||
* ws2812b.h |
|
||||||
* |
|
||||||
* The MIT License. |
|
||||||
* Created on: 14.07.2017 |
|
||||||
* Author: Mateusz Salamon |
|
||||||
* www.msalamon.pl |
|
||||||
* mateusz@msalamon.pl |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef WS2812B_H_ |
|
||||||
#define WS2812B_H_ |
|
||||||
|
|
||||||
/* Includes */ |
|
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
/* Defintions */ |
|
||||||
#define WS2812B_LEDS (1) |
|
||||||
|
|
||||||
/* Data Structures */ |
|
||||||
typedef union __attribute__((packed, aligned(4))) ws2812b_color_u { |
|
||||||
struct __attribute__((packed, aligned(4))) rgbx_s { |
|
||||||
uint8_t green; |
|
||||||
uint8_t red; |
|
||||||
uint8_t blue; |
|
||||||
uint8_t x; |
|
||||||
} rgbx; |
|
||||||
struct __attribute__((packed, aligned(4))) rgb_s { |
|
||||||
uint8_t _pad; |
|
||||||
uint8_t green; |
|
||||||
uint8_t red; |
|
||||||
uint8_t blue; |
|
||||||
} rgb; |
|
||||||
uint32_t u32; |
|
||||||
uint8_t u8[4]; |
|
||||||
} ws2812b_color; |
|
||||||
|
|
||||||
/* Function Prototypes */ |
|
||||||
void ws2812_init(SPI_HandleTypeDef *hspi); |
|
||||||
void ws2812_set_led_color_val(uint16_t diode_id, uint32_t color); |
|
||||||
void ws2812_set_led_color(uint16_t diode_id, ws2812b_color color); |
|
||||||
void ws2812_set_led_rgb(uint16_t diode_id, uint8_t r, uint8_t g, uint8_t b); |
|
||||||
void ws2812_set_led_rgbx(uint16_t diode_id, uint8_t r, uint8_t g, uint8_t b, uint8_t x); |
|
||||||
void ws2812_set_led_hsv(uint16_t diode_id, uint16_t hue, uint8_t sat, uint8_t value); |
|
||||||
uint32_t ws2812_get_color(uint16_t diode_id); |
|
||||||
uint8_t *ws2812_get_pixels(); |
|
||||||
void ws2812_refresh(); |
|
||||||
uint8_t sine8(uint8_t x); |
|
||||||
uint8_t gamma8(uint8_t x); |
|
||||||
|
|
||||||
#endif /* WS2812B_H_ */ |
|
@ -1,153 +0,0 @@ |
|||||||
/*
|
|
||||||
* ws2812b_fx.h |
|
||||||
* |
|
||||||
* Library based on Harm Aldick's Arduino library |
|
||||||
* https://github.com/kitesurfer1404/WS2812FX
|
|
||||||
* |
|
||||||
* The MIT License. |
|
||||||
* Created on: 20.10.2018 |
|
||||||
* Author: Mateusz Salamon |
|
||||||
* www.msalamon.pl |
|
||||||
* mateusz@msalamon.pl |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef WS2812B_FX_H_ |
|
||||||
#define WS2812B_FX_H_ |
|
||||||
|
|
||||||
/* Includes */ |
|
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
/* Definitions */ |
|
||||||
#define DEFAULT_COLOR (0x00F0000000) |
|
||||||
#define NUM_COLORS (4) |
|
||||||
#define SPEED_MIN (10) |
|
||||||
#define DEFAULT_SPEED (150) |
|
||||||
#define SPEED_MAX (65535) |
|
||||||
#define MODE_COUNT (59) |
|
||||||
#define DEFAULT_MODE (0) |
|
||||||
#define FADE_RATE (2) |
|
||||||
/* some common colors */ |
|
||||||
#define RED (0xFF0000U) |
|
||||||
#define GREEN (0x00FF00U) |
|
||||||
#define BLUE (0x0000FFU) |
|
||||||
#define WHITE (0xFFFFFFU) |
|
||||||
#define BLACK (0x000000U) |
|
||||||
#define YELLOW (0xFFFF00U) |
|
||||||
#define CYAN (0x00FFFFU) |
|
||||||
#define MAGENTA (0xFF00FFU) |
|
||||||
#define PURPLE (0x400080U) |
|
||||||
#define ORANGE (0xFF3000U) |
|
||||||
#define PINK (0xFF1493U) |
|
||||||
|
|
||||||
/* Data Structures */ |
|
||||||
typedef enum { |
|
||||||
FX_OK = 0, |
|
||||||
FX_ERROR = 1 |
|
||||||
} FX_STATUS; |
|
||||||
typedef enum { |
|
||||||
FX_MODE_STATIC, |
|
||||||
FX_MODE_WHITE_TO_COLOR, |
|
||||||
FX_MODE_BLACK_TO_COLOR, |
|
||||||
FX_MODE_BLINK, |
|
||||||
FX_MODE_BLINK_RAINBOW, |
|
||||||
FX_MODE_STROBE, |
|
||||||
FX_MODE_STROBE_RAINBOW, |
|
||||||
FX_MODE_BREATH, |
|
||||||
FX_MODE_COLOR_WIPE, |
|
||||||
FX_MODE_COLOR_WIPE_INV, |
|
||||||
FX_MODE_COLOR_WIPE_REV, |
|
||||||
FX_MODE_COLOR_WIPE_REV_INV, |
|
||||||
FX_MODE_COLOR_WIPE_RANDOM, |
|
||||||
FX_MODE_COLOR_SWEEP_RANDOM, |
|
||||||
FX_MODE_RANDOM_COLOR, |
|
||||||
FX_MODE_SINGLE_DYNAMIC, |
|
||||||
FX_MODE_MULTI_DYNAMIC, |
|
||||||
FX_MODE_RAINBOW, |
|
||||||
FX_MODE_RAINBOW_CYCLE, |
|
||||||
FX_MODE_FADE, |
|
||||||
FX_MODE_SCAN, |
|
||||||
FX_MODE_DUAL_SCAN, |
|
||||||
FX_MODE_THEATER_CHASE, |
|
||||||
FX_MODE_THEATER_CHASE_RAINBOW, |
|
||||||
FX_MODE_RUNNING_LIGHTS, |
|
||||||
FX_MODE_TWINKLE, |
|
||||||
FX_MODE_TWINKLE_RANDOM, |
|
||||||
FX_MODE_TWINKLE_FADE, |
|
||||||
FX_MODE_TWINKLE_FADE_RANDOM, |
|
||||||
FX_MODE_SPARKLE, |
|
||||||
FX_MODE_FLASH_SPARKLE, |
|
||||||
FX_MODE_HYPER_SPARKLE, |
|
||||||
FX_MODE_MULTI_STROBE, |
|
||||||
FX_MODE_CHASE_WHITE, |
|
||||||
FX_MODE_CHASE_COLOR, |
|
||||||
FX_MODE_CHASE_RANDOM, |
|
||||||
FX_MODE_CHASE_RAINBOW, |
|
||||||
FX_MODE_CHASE_FLASH, |
|
||||||
FX_MODE_CHASE_FLASH_RANDOM, |
|
||||||
FX_MODE_CHASE_RAINBOW_WHITE, |
|
||||||
FX_MODE_CHASE_BLACKOUT, |
|
||||||
FX_MODE_CHASE_BLACKOUT_RAINBOW, |
|
||||||
FX_MODE_RUNNING_COLOR, |
|
||||||
FX_MODE_RUNNING_RED_BLUE, |
|
||||||
FX_MODE_RUNNING_RANDOM, |
|
||||||
FX_MODE_LARSON_SCANNER, |
|
||||||
FX_MODE_COMET, |
|
||||||
FX_MODE_FIREWORKS, |
|
||||||
FX_MODE_FIREWORKS_RANDOM, |
|
||||||
FX_MODE_MERRY_CHRISTMAS, |
|
||||||
FX_MODE_FIRE_FLICKER, |
|
||||||
FX_MODE_FIRE_FLICKER_SOFT, |
|
||||||
FX_MODE_FIRE_FLICKER_INTENSE, |
|
||||||
FX_MODE_CIRCUS_COMBUSTUS, |
|
||||||
FX_MODE_HALLOWEEN, |
|
||||||
FX_MODE_BICOLOR_CHASE, |
|
||||||
FX_MODE_TRICOLOR_CHASE, |
|
||||||
FX_MODE_QUADCOLOR_CHASE, |
|
||||||
FX_MODE_ICU |
|
||||||
} fx_mode; |
|
||||||
|
|
||||||
/* Function Prototypes */ |
|
||||||
FX_STATUS WS2812BFX_Init(uint16_t Segments); |
|
||||||
FX_STATUS WS2812BFX_SegmentIncrease(void); |
|
||||||
FX_STATUS WS2812BFX_SegmentDecrease(void); |
|
||||||
uint8_t WS2812BFX_GetSegmentsQuantity(void); |
|
||||||
|
|
||||||
void WS2812BFX_SysTickCallback(void); |
|
||||||
void WS2812BFX_Callback(void); |
|
||||||
|
|
||||||
FX_STATUS WS2812BFX_Start(uint16_t Segment); |
|
||||||
FX_STATUS WS2812BFX_Stop(uint16_t Segment); |
|
||||||
FX_STATUS WS2812BFX_IsRunning(uint16_t Segment, uint8_t *Running); |
|
||||||
|
|
||||||
FX_STATUS WS2812BFX_SetMode(uint16_t Segment, fx_mode Mode); |
|
||||||
FX_STATUS WS2812BFX_GetMode(uint16_t Segment, fx_mode *Mode); |
|
||||||
FX_STATUS WS2812BFX_NextMode(uint16_t Segment); |
|
||||||
FX_STATUS WS2812BFX_PrevMode(uint16_t Segment); |
|
||||||
FX_STATUS WS2812BFX_SetReverse(uint16_t Segment, uint8_t Reverse); |
|
||||||
FX_STATUS WS2812BFX_GetReverse(uint16_t Segment, uint8_t *Reverse); |
|
||||||
|
|
||||||
FX_STATUS WS2812BFX_SetSegmentSize(uint16_t Segment, uint16_t Start, uint16_t Stop); |
|
||||||
FX_STATUS WS2812BFX_GetSegmentSize(uint16_t Segment, uint16_t *Start, uint16_t *Stop); |
|
||||||
FX_STATUS WS2812BFX_SegmentIncreaseEnd(uint16_t Segment); |
|
||||||
FX_STATUS WS2812BFX_SegmentDecreaseEnd(uint16_t Segment); |
|
||||||
FX_STATUS WS2812BFX_SegmentIncreaseStart(uint16_t Segment); |
|
||||||
FX_STATUS WS2812BFX_SegmentDecreaseStart(uint16_t Segment); |
|
||||||
|
|
||||||
FX_STATUS WS2812BFX_SetSpeed(uint16_t Segment, uint16_t Speed); |
|
||||||
FX_STATUS WS2812BFX_GetSpeed(uint16_t Segment, uint16_t *Speed); |
|
||||||
FX_STATUS WS2812BFX_IncreaseSpeed(uint16_t Segment, uint16_t Speed); |
|
||||||
FX_STATUS WS2812BFX_DecreaseSpeed(uint16_t Segment, uint16_t Speed); |
|
||||||
|
|
||||||
void WS2812BFX_SetColorStruct(uint8_t id, ws2812b_color c); |
|
||||||
void WS2812BFX_SetColorRGB(uint8_t id, uint8_t r, uint8_t g, uint8_t b); |
|
||||||
FX_STATUS WS2812BFX_GetColorRGB(uint8_t id, uint8_t *r, uint8_t *g, uint8_t *b); |
|
||||||
void WS2812BFX_SetColorHSV(uint8_t id, uint16_t h, uint8_t s, uint8_t v); |
|
||||||
void WS2812BFX_SetColor(uint8_t id, uint32_t c); |
|
||||||
|
|
||||||
FX_STATUS WS2812BFX_SetAll(uint16_t Segment, uint32_t c); |
|
||||||
FX_STATUS WS2812BFX_SetAllRGB(uint16_t Segment, uint8_t r, uint8_t g, uint8_t b); |
|
||||||
|
|
||||||
void WS2812BFX_RGBtoHSV(uint8_t r, uint8_t g, uint8_t b, uint16_t *h, uint8_t *s, uint8_t *v); |
|
||||||
void WS2812BFX_HSVtoRGB(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); |
|
||||||
|
|
||||||
#endif /* WS2812B_FX_H_ */ |
|
@ -0,0 +1,47 @@ |
|||||||
|
/*
|
||||||
|
* ws281x.h |
||||||
|
* |
||||||
|
* The MIT License. |
||||||
|
* Created on: 14.07.2017 |
||||||
|
* Author: Mateusz Salamon |
||||||
|
* www.msalamon.pl |
||||||
|
* mateusz@msalamon.pl |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef WS281X_H_ |
||||||
|
#define WS281X_H_ |
||||||
|
|
||||||
|
/* Includes */ |
||||||
|
#include <stdint.h> |
||||||
|
#include "main.h" |
||||||
|
|
||||||
|
/* Defintions */ |
||||||
|
|
||||||
|
/* Data Structures */ |
||||||
|
typedef enum ws281x_type_e { |
||||||
|
WS281X_TYPE_WS2811 = 0, |
||||||
|
WS281X_TYPE_WS2812, |
||||||
|
WS281X_TYPE_WS2812B, |
||||||
|
WS281X_TYPE_SK6812, |
||||||
|
WS281X_TYPE_SK6812RGBW, |
||||||
|
WS281X_TYPE_WS2813B, |
||||||
|
WS281X_TYPE_END |
||||||
|
} ws281x_type_t; |
||||||
|
typedef union __attribute__((packed, aligned(4))) ws281x_color_u { |
||||||
|
struct __attribute__((packed, aligned(4))) rgbx_s { |
||||||
|
uint8_t r; /* red */ |
||||||
|
uint8_t g; /* green */ |
||||||
|
uint8_t b; /* blue */ |
||||||
|
uint8_t x; /* additional color channel - commonly white or warm white */ |
||||||
|
} rgbx; |
||||||
|
uint32_t u32; |
||||||
|
uint8_t u8[4]; |
||||||
|
} ws281x_color_t; |
||||||
|
typedef struct ws281x_s ws281x_t; |
||||||
|
|
||||||
|
/* Function Prototypes */ |
||||||
|
ws281x_t *ws281x_init(ws281x_type_t type, SPI_HandleTypeDef *hspi, ws281x_color_t *leds, int32_t num_leds); |
||||||
|
void ws281x_refresh(ws281x_t *ws281x); |
||||||
|
int32_t ws281x_set_led(ws281x_t *ws281x, uint16_t led_id, ws281x_color_t color); |
||||||
|
|
||||||
|
#endif /* WS281X_H_ */ |
@ -1,271 +0,0 @@ |
|||||||
/*
|
|
||||||
* ws2812b.c |
|
||||||
* |
|
||||||
* The MIT License. |
|
||||||
* Created on: 14.07.2017 |
|
||||||
* Author: Mateusz Salamon |
|
||||||
* www.msalamon.pl |
|
||||||
* mateusz@msalamon.pl |
|
||||||
*/ |
|
||||||
|
|
||||||
/* Includes */ |
|
||||||
#include "main.h" |
|
||||||
#include "spi.h" |
|
||||||
#include "dma.h" |
|
||||||
#include "gpio.h" |
|
||||||
#include "math.h" |
|
||||||
#include "ws2812b.h" |
|
||||||
|
|
||||||
/* Definitions */ |
|
||||||
#define ZERO (0b11000000) |
|
||||||
#define ONE (0b11111000) |
|
||||||
#define WORD_SIZE (32U) |
|
||||||
#define BUFFER_SIZE (WORD_SIZE * 2) |
|
||||||
|
|
||||||
/* Macros */ |
|
||||||
#define ws2812_return_if_fail(cond) if(!(cond)) { return; } |
|
||||||
#define ws2812_return_val_if_fail(cond, val) if(!(cond)) { return (val); } |
|
||||||
#define ws2812_return_null_if_fail(cond) ws2812_return_val_if_fail((cond), NULL) |
|
||||||
|
|
||||||
/* Private Constants */ |
|
||||||
static const uint8_t sine_lut8[256] = { |
|
||||||
128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173, |
|
||||||
176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215, |
|
||||||
218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244, |
|
||||||
245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255, |
|
||||||
255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246, |
|
||||||
245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220, |
|
||||||
218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179, |
|
||||||
176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131, |
|
||||||
128,124,121,118,115,112,109,106,103,100, 97, 93, 90, 88, 85, 82, |
|
||||||
79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40, |
|
||||||
37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11, |
|
||||||
10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, |
|
||||||
10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, |
|
||||||
37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76, |
|
||||||
79, 82, 85, 88, 90, 93, 97,100,103,106,109,112,115,118,121,124}; |
|
||||||
|
|
||||||
static const uint8_t gamma_lut8[256] = { |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, |
|
||||||
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, |
|
||||||
3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, |
|
||||||
7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, |
|
||||||
13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, |
|
||||||
20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29, |
|
||||||
30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, |
|
||||||
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, |
|
||||||
58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 75, |
|
||||||
76, 77, 78, 80, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96, |
|
||||||
97, 99,100,102,103,105,106,108,109,111,112,114,115,117,119,120, |
|
||||||
122,124,125,127,129,130,132,134,136,137,139,141,143,145,146,148, |
|
||||||
150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180, |
|
||||||
182,184,186,188,191,193,195,197,199,202,204,206,209,211,213,215, |
|
||||||
218,220,223,225,227,230,232,235,237,240,242,245,247,250,252,255}; |
|
||||||
|
|
||||||
/* Public Global Variables */ |
|
||||||
SPI_HandleTypeDef *hspi_ws2812b; |
|
||||||
ws2812b_color ws2812b_array[WS2812B_LEDS]; |
|
||||||
|
|
||||||
/* Private Global Variables */ |
|
||||||
static uint8_t buffer[BUFFER_SIZE]; |
|
||||||
static uint16_t curr_led; |
|
||||||
static uint8_t reset_sig; |
|
||||||
|
|
||||||
/* Function Definitions */ |
|
||||||
void ws2812_init(SPI_HandleTypeDef *hspi) |
|
||||||
{ |
|
||||||
hspi_ws2812b = hspi; |
|
||||||
} |
|
||||||
|
|
||||||
void ws2812_set_led_color_val(uint16_t diode_id, uint32_t color) |
|
||||||
{ |
|
||||||
ws2812_return_if_fail(diode_id < WS2812B_LEDS); |
|
||||||
ws2812b_array[diode_id].u32 = color; |
|
||||||
} |
|
||||||
|
|
||||||
void ws2812_set_led_color(uint16_t diode_id, ws2812b_color color) |
|
||||||
{ |
|
||||||
ws2812_return_if_fail(diode_id < WS2812B_LEDS); |
|
||||||
ws2812b_array[diode_id] = color; |
|
||||||
} |
|
||||||
|
|
||||||
void ws2812_set_led_rgb(uint16_t diode_id, uint8_t r, uint8_t g, uint8_t b) |
|
||||||
{ |
|
||||||
ws2812_return_if_fail(diode_id < WS2812B_LEDS); |
|
||||||
ws2812b_array[diode_id].rgb.red = r; |
|
||||||
ws2812b_array[diode_id].rgb.green = g; |
|
||||||
ws2812b_array[diode_id].rgb.blue = b; |
|
||||||
} |
|
||||||
|
|
||||||
void ws2812_set_led_rgbx(uint16_t diode_id, uint8_t r, uint8_t g, uint8_t b, uint8_t x) |
|
||||||
{ |
|
||||||
ws2812_return_if_fail(diode_id < WS2812B_LEDS); |
|
||||||
ws2812b_array[diode_id].rgbx.red = r; |
|
||||||
ws2812b_array[diode_id].rgbx.green = g; |
|
||||||
ws2812b_array[diode_id].rgbx.blue = b; |
|
||||||
ws2812b_array[diode_id].rgbx.x = x; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Set diode with HSV model |
|
||||||
* |
|
||||||
* Hue 0-359 |
|
||||||
* Saturation 0-255 |
|
||||||
* Value 0-255 |
|
||||||
*/ |
|
||||||
void ws2812_set_led_hsv(uint16_t diode_id, uint16_t hue, uint8_t sat, uint8_t value) |
|
||||||
{ |
|
||||||
uint16_t sector, fract, p, q, t; |
|
||||||
|
|
||||||
ws2812_return_if_fail(diode_id < WS2812B_LEDS); |
|
||||||
|
|
||||||
if(sat == 0) |
|
||||||
{ |
|
||||||
ws2812b_array[diode_id].rgb.red = value; |
|
||||||
ws2812b_array[diode_id].rgb.green = value; |
|
||||||
ws2812b_array[diode_id].rgb.blue = value; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
if(hue >= 360) hue = 359; |
|
||||||
|
|
||||||
sector = hue / 60; /* hexcone HSV model -- 6 sectors */ |
|
||||||
fract = hue % 60; |
|
||||||
p = (value * (255 - sat)) / 256; |
|
||||||
q = (value * (255 - (sat * fract) / 60)) / 256; |
|
||||||
t = (value * (255 - (sat * (59 - fract)) / 60)) / 256; |
|
||||||
|
|
||||||
|
|
||||||
switch(sector) |
|
||||||
{ |
|
||||||
case 0: |
|
||||||
ws2812b_array[diode_id].rgb.red = value; |
|
||||||
ws2812b_array[diode_id].rgb.green = (uint8_t)t; |
|
||||||
ws2812b_array[diode_id].rgb.blue = (uint8_t)p; |
|
||||||
break; |
|
||||||
case 1: |
|
||||||
ws2812b_array[diode_id].rgb.red = (uint8_t)q; |
|
||||||
ws2812b_array[diode_id].rgb.green = value; |
|
||||||
ws2812b_array[diode_id].rgb.blue = (uint8_t)p; |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
ws2812b_array[diode_id].rgb.red = (uint8_t)p; |
|
||||||
ws2812b_array[diode_id].rgb.green = value; |
|
||||||
ws2812b_array[diode_id].rgb.blue = (uint8_t)t; |
|
||||||
break; |
|
||||||
case 3: |
|
||||||
ws2812b_array[diode_id].rgb.red = (uint8_t)p; |
|
||||||
ws2812b_array[diode_id].rgb.green = (uint8_t)q; |
|
||||||
ws2812b_array[diode_id].rgb.blue = value; |
|
||||||
break; |
|
||||||
case 4: |
|
||||||
ws2812b_array[diode_id].rgb.red = (uint8_t)t; |
|
||||||
ws2812b_array[diode_id].rgb.green = (uint8_t)p; |
|
||||||
ws2812b_array[diode_id].rgb.blue = value; |
|
||||||
break; |
|
||||||
case 5: |
|
||||||
default: |
|
||||||
ws2812b_array[diode_id].rgb.red = value; |
|
||||||
ws2812b_array[diode_id].rgb.green = (uint8_t)p; |
|
||||||
ws2812b_array[diode_id].rgb.blue = (uint8_t)q; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
uint32_t ws2812_get_color(uint16_t diode_id) |
|
||||||
{ |
|
||||||
ws2812_return_val_if_fail(diode_id < WS2812B_LEDS, 0); |
|
||||||
|
|
||||||
return ws2812b_array[diode_id].u32; |
|
||||||
} |
|
||||||
|
|
||||||
uint8_t *ws2812_get_pixels() |
|
||||||
{ |
|
||||||
return (uint8_t*)ws2812b_array; |
|
||||||
} |
|
||||||
|
|
||||||
void ws2812_refresh() |
|
||||||
{ |
|
||||||
curr_led = 0; |
|
||||||
reset_sig = 0; |
|
||||||
|
|
||||||
for(uint8_t i = 0; i < BUFFER_SIZE; i++) |
|
||||||
buffer[i] = 0x00; |
|
||||||
HAL_SPI_Transmit_DMA(hspi_ws2812b, buffer, BUFFER_SIZE); |
|
||||||
while(HAL_DMA_STATE_READY != HAL_DMA_GetState(hspi_ws2812b->hdmatx)); |
|
||||||
} |
|
||||||
|
|
||||||
uint8_t sine8(uint8_t x) |
|
||||||
{ |
|
||||||
return sine_lut8[x]; |
|
||||||
} |
|
||||||
|
|
||||||
uint8_t gamma8(uint8_t x) |
|
||||||
{ |
|
||||||
return gamma_lut8[x]; |
|
||||||
} |
|
||||||
|
|
||||||
/* Private Function Definitions */ |
|
||||||
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi) |
|
||||||
{ |
|
||||||
if(hspi == hspi_ws2812b) |
|
||||||
{ |
|
||||||
if(!reset_sig) |
|
||||||
{ |
|
||||||
for(uint8_t k = 0; k < WORD_SIZE; k++) |
|
||||||
{ |
|
||||||
buffer[k] = 0x00; |
|
||||||
} |
|
||||||
reset_sig = 1; /* End reset signal */ |
|
||||||
} |
|
||||||
else /* Odd LEDs 1, 3, 5, ... */ |
|
||||||
{ |
|
||||||
if(curr_led > WS2812B_LEDS) |
|
||||||
{ |
|
||||||
HAL_SPI_DMAStop(hspi_ws2812b); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
uint8_t i = 0; |
|
||||||
for(int8_t j = WORD_SIZE - 1; j >= 0; j--) |
|
||||||
{ |
|
||||||
if((ws2812b_array[curr_led].u32 & (1 << j)) == 0) |
|
||||||
buffer[i] = ZERO; |
|
||||||
else |
|
||||||
buffer[i] = ONE; |
|
||||||
i++; |
|
||||||
} |
|
||||||
curr_led++; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) |
|
||||||
{ |
|
||||||
if(hspi == hspi_ws2812b) |
|
||||||
{ |
|
||||||
if(curr_led > WS2812B_LEDS) |
|
||||||
{ |
|
||||||
HAL_SPI_DMAStop(hspi_ws2812b); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
/* Even LEDs 0, 2, 4, ... */ |
|
||||||
uint8_t i = WORD_SIZE; |
|
||||||
for(int8_t j = WORD_SIZE - 1; j >= 0; j--) |
|
||||||
{ |
|
||||||
if((ws2812b_array[curr_led].u32 & (1 << j)) == 0) |
|
||||||
buffer[i] = ZERO; |
|
||||||
else |
|
||||||
buffer[i] = ONE; |
|
||||||
i++; |
|
||||||
} |
|
||||||
curr_led++; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,213 @@ |
|||||||
|
/*
|
||||||
|
* ws281x.c |
||||||
|
* |
||||||
|
* The MIT License. |
||||||
|
* Created on: 14.07.2017 |
||||||
|
* Author: Mateusz Salamon |
||||||
|
* www.msalamon.pl |
||||||
|
* mateusz@msalamon.pl |
||||||
|
*/ |
||||||
|
|
||||||
|
/* Includes */ |
||||||
|
#include <ws281x.h> |
||||||
|
|
||||||
|
/* Definitions */ |
||||||
|
#define WS281X_MAX (16U) |
||||||
|
#define ZERO (0b11000000) |
||||||
|
#define ONE (0b11111000) |
||||||
|
|
||||||
|
/* Macros */ |
||||||
|
#define ws281x_return_if_fail(cond) if(!(cond)) { return; } |
||||||
|
#define ws281x_return_val_if_fail(cond, val) if(!(cond)) { return (val); } |
||||||
|
#define ws281x_return_null_if_fail(cond) ws281x_return_val_if_fail((cond), NULL) |
||||||
|
|
||||||
|
/* Data Structures */ |
||||||
|
struct ws281x_s { |
||||||
|
ws281x_type_t type; |
||||||
|
SPI_HandleTypeDef *hspi; |
||||||
|
ws281x_color_t *leds; |
||||||
|
int32_t num_leds; |
||||||
|
int32_t curr_led; |
||||||
|
uint8_t wordlen; |
||||||
|
uint8_t buf[64]; /* enough to hold even/odd 32-bit words */ |
||||||
|
uint8_t reset; |
||||||
|
}; |
||||||
|
|
||||||
|
/* Private Constants */ |
||||||
|
|
||||||
|
/* Public Global Variables */ |
||||||
|
|
||||||
|
/* Private Global Variables */ |
||||||
|
static ws281x_t ws281x[WS281X_MAX]; |
||||||
|
static int32_t ws281x_count = 0; |
||||||
|
static uint8_t wordlen[WS281X_TYPE_END] = { |
||||||
|
24, /* WS281X_TYPE_WS2811 */ |
||||||
|
24, /* WS281X_TYPE_WS2812*/ |
||||||
|
24, /* WS281X_TYPE_WS2812B */ |
||||||
|
24, /* WS281X_TYPE_SK6812 */ |
||||||
|
32, /* WS281X_TYPE_SK6812RGBW */ |
||||||
|
24 /* WS281X_TYPE_WS2813B */ |
||||||
|
}; |
||||||
|
|
||||||
|
/* Function Prototypes */ |
||||||
|
static ws281x_t *ws281x_lookup(SPI_HandleTypeDef *hspi); |
||||||
|
static void ws281x_update_half(ws281x_t *ws281x, uint8_t even); |
||||||
|
|
||||||
|
/* Function Definitions */ |
||||||
|
/**
|
||||||
|
* \brief Creates a new `ws281x_t` instance. |
||||||
|
* |
||||||
|
* This function initializes a new `ws281x_t` object which is controlled by |
||||||
|
* a SPI peripheral and DMA. |
||||||
|
* |
||||||
|
* \param type The type of addressable LED(s). |
||||||
|
* \param hspi Pointer to the SPI device handle. The `hspi` handle must be |
||||||
|
* unique for each obect initialized. |
||||||
|
* \param leds Pointer to an array of `ws281x_color_t` which holds all of the |
||||||
|
* LED color information. |
||||||
|
* \param num_leds The number of LEDs to control. |
||||||
|
* |
||||||
|
* \return Pointer to the created ws281x_t object, NULL on failure. |
||||||
|
*/ |
||||||
|
ws281x_t *ws281x_init(ws281x_type_t type, SPI_HandleTypeDef *hspi, ws281x_color_t *leds, int32_t num_leds) |
||||||
|
{ |
||||||
|
ws281x_return_null_if_fail(ws281x_count < WS281X_MAX); |
||||||
|
ws281x_return_null_if_fail(type < WS281X_TYPE_END); |
||||||
|
ws281x_return_null_if_fail(hspi); |
||||||
|
ws281x_return_null_if_fail(leds); |
||||||
|
ws281x_return_null_if_fail(num_leds > 0); |
||||||
|
ws281x_return_null_if_fail(ws281x_lookup(hspi) == NULL); |
||||||
|
|
||||||
|
ws281x[ws281x_count].hspi = hspi; |
||||||
|
ws281x[ws281x_count].type = type; |
||||||
|
ws281x[ws281x_count].leds = leds; |
||||||
|
ws281x[ws281x_count].num_leds = num_leds; |
||||||
|
ws281x[ws281x_count].curr_led = 0; |
||||||
|
ws281x[ws281x_count].wordlen = wordlen[type]; |
||||||
|
ws281x[ws281x_count].reset = 0; |
||||||
|
|
||||||
|
return &ws281x[ws281x_count++]; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Refreshes the LED(s). |
||||||
|
* |
||||||
|
* All of the LEDs in the string are sent the current color information. |
||||||
|
* |
||||||
|
* \param ws281x Pointer to a `ws281x_t` object. |
||||||
|
*/ |
||||||
|
void ws281x_refresh(ws281x_t *ws281x) |
||||||
|
{ |
||||||
|
uint8_t i; |
||||||
|
|
||||||
|
ws281x_return_if_fail(ws281x); |
||||||
|
|
||||||
|
ws281x->curr_led = 0; |
||||||
|
ws281x->reset = 1; |
||||||
|
for(i = 0; i < ws281x->wordlen * 2; i++) |
||||||
|
{ |
||||||
|
ws281x->buf[i] = 0x00; |
||||||
|
} |
||||||
|
HAL_SPI_Transmit_DMA(ws281x->hspi, ws281x->buf, ws281x->wordlen * 2); |
||||||
|
while(HAL_DMA_GetState(ws281x->hspi->hdmatx) != HAL_DMA_STATE_READY); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sets an LED color. |
||||||
|
* |
||||||
|
* This function sets the color of the LED at index `led_id`. |
||||||
|
* |
||||||
|
* \param ws281x Pointer to a `ws281x_t` object. |
||||||
|
* \param led_id Index of the LED which is to have its color assigned. |
||||||
|
* \param color A ws281x_color_t object which contains the color information |
||||||
|
* to be assigned. |
||||||
|
* |
||||||
|
* \return `led_id` on success, -1 on failure. |
||||||
|
*/ |
||||||
|
int32_t ws281x_set_led(ws281x_t *ws281x, uint16_t led_id, ws281x_color_t color) |
||||||
|
{ |
||||||
|
ws281x_return_val_if_fail(ws281x, -1); |
||||||
|
ws281x_return_val_if_fail(led_id < ws281x->num_leds, -1); |
||||||
|
|
||||||
|
ws281x->leds[led_id] = color; |
||||||
|
|
||||||
|
return led_id; |
||||||
|
} |
||||||
|
|
||||||
|
/* Private Function Definitions */ |
||||||
|
static ws281x_t *ws281x_lookup(SPI_HandleTypeDef *hspi) |
||||||
|
{ |
||||||
|
int32_t i; |
||||||
|
|
||||||
|
ws281x_return_val_if_fail(hspi, NULL); |
||||||
|
ws281x_return_val_if_fail(ws281x_count > 0, NULL); |
||||||
|
|
||||||
|
for(i = 0; i < ws281x_count; i++) |
||||||
|
{ |
||||||
|
if(ws281x[i].hspi == hspi) |
||||||
|
{ |
||||||
|
return &ws281x[i]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
static void ws281x_update_half(ws281x_t *ws281x, uint8_t even) |
||||||
|
{ |
||||||
|
uint8_t i = even ? ws281x->wordlen : 0; |
||||||
|
int8_t j; |
||||||
|
|
||||||
|
if(ws281x->curr_led > ws281x->num_leds) |
||||||
|
{ |
||||||
|
HAL_SPI_DMAStop(ws281x->hspi); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
for(j = ws281x->wordlen - 1; j >= 0; j--) |
||||||
|
{ |
||||||
|
if((ws281x->leds[ws281x->curr_led].u32 & (1 << j))) |
||||||
|
{ |
||||||
|
ws281x->buf[i] = ONE; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
ws281x->buf[i] = ZERO; |
||||||
|
} |
||||||
|
i++; |
||||||
|
} |
||||||
|
ws281x->curr_led++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* HAL Callbacks */ |
||||||
|
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi) |
||||||
|
{ |
||||||
|
ws281x_t *ws281x = ws281x_lookup(hspi); |
||||||
|
uint8_t i; |
||||||
|
|
||||||
|
ws281x_return_if_fail(ws281x); |
||||||
|
|
||||||
|
if(ws281x->reset) |
||||||
|
{ |
||||||
|
for(i = 0; i < ws281x->wordlen; i++) |
||||||
|
{ |
||||||
|
ws281x->buf[i] = 0x00; |
||||||
|
} |
||||||
|
ws281x->reset = 0; |
||||||
|
} |
||||||
|
else /* odd LEDs -- 1, 3, 5, ... */ |
||||||
|
{ |
||||||
|
ws281x_update_half(ws281x, 0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) |
||||||
|
{ |
||||||
|
ws281x_t *ws281x = ws281x_lookup(hspi); |
||||||
|
|
||||||
|
ws281x_return_if_fail(ws281x); |
||||||
|
|
||||||
|
/* even LEDs -- 2, 4, 6, ... */ |
||||||
|
ws281x_update_half(ws281x, 1); |
||||||
|
} |
Loading…
Reference in new issue