New file |
| | |
| | | /********************************************************************** |
| | | * Copyright: (C)2024 LingYun IoT System Studio |
| | | * Author: GuoWenxue<guowenxue@gmail.com> |
| | | * |
| | | * Description: WS2812B strip lights driver on ISKBoard |
| | | * |
| | | * Reference : https://blog.csdn.net/Lennon8_8/article/details/108980808 |
| | | * |
| | | * ChangeLog: |
| | | * Version Date Author Description |
| | | * V1.0.0 2024.08.29 GuoWenxue Release initial version |
| | | * |
| | | ***********************************************************************/ |
| | | #include <string.h> |
| | | #include <stdint.h> |
| | | #include "ws2812b.h" |
| | | #include "miscdev.h" |
| | | |
| | | #ifdef USE_FREERTOS |
| | | #include "cmsis_os.h" |
| | | #define mdelay(ms) osDelay(ms) |
| | | #else |
| | | #define mdelay(ms) HAL_Delay(ms) |
| | | #endif |
| | | |
| | | static color_t g_ColorPanel[WS2812_NUM]; |
| | | |
| | | typedef struct ws_gpio_s |
| | | { |
| | | GPIO_TypeDef *group; |
| | | uint16_t pin; |
| | | } ws_gpio_t; |
| | | |
| | | static ws_gpio_t ws_gpio = /* IO pin connected to PC2 */ |
| | | { |
| | | .group = GPIOC, |
| | | .pin = GPIO_PIN_2, |
| | | }; |
| | | |
| | | #define ws_setpin(x) if(!x) ws_gpio.group->BRR=ws_gpio.pin; else ws_gpio.group->BSRR=ws_gpio.pin |
| | | |
| | | /* |
| | | * 1 NOP = 1/80MHz = 12.5ns => 200ns = 8 * NOP |
| | | * |
| | | * */ |
| | | #define delay_200ns() { __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); \ |
| | | __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); } |
| | | |
| | | void ws2812b_init(void) |
| | | { |
| | | GPIO_InitTypeDef GPIO_InitStruct = {0}; |
| | | |
| | | GPIO_InitStruct.Pin = ws_gpio.pin; |
| | | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; |
| | | GPIO_InitStruct.Pull = GPIO_NOPULL; |
| | | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; |
| | | |
| | | HAL_GPIO_Init(ws_gpio.group, &GPIO_InitStruct); |
| | | |
| | | ws2812b_reset(); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | static inline void ws2812b_WriteByte(uint8_t byte) |
| | | { |
| | | int i; |
| | | |
| | | for(i=0; i<8; i++) |
| | | { |
| | | if(byte & 0x80) |
| | | { |
| | | /* Sequence Send 1: T1H: 580ns~1.6us T1L: 200ns~420ns: |
| | | * |
| | | * +--------------+ + |
| | | * |<- T1H ->|<- T1L ->| |
| | | * | +---------+ |
| | | */ |
| | | ws_setpin(1); // T1H |
| | | udelay(1); |
| | | |
| | | ws_setpin(0); // T1L |
| | | delay_200ns(); //200ns test okay |
| | | } |
| | | else |
| | | { |
| | | /* Sequence Send 0: T0H: 220ns~380ns T0L: 580ns~1.6ns: |
| | | * |
| | | * +---------+ + |
| | | * |<- T0H ->|<- T0L ->| |
| | | * | +--------------+ |
| | | */ |
| | | ws_setpin(1); // T0H |
| | | delay_200ns(); //200ns test okay |
| | | |
| | | ws_setpin(0); // T0L |
| | | udelay(1); |
| | | } |
| | | |
| | | byte<<=1; |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |
| | | void ws2812b_reset(void) |
| | | { |
| | | /* Sequence Reset: Treset >280us: |
| | | * |
| | | * + + |
| | | * |<- Treset ->| |
| | | * +--------------+ |
| | | */ |
| | | ws_setpin(0); |
| | | udelay(300); |
| | | |
| | | memset(g_ColorPanel, 0, sizeof(g_ColorPanel)); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | static inline void ws2812b_SendColor(color_t color) |
| | | { |
| | | ws2812b_WriteByte(color.pixel.green); |
| | | ws2812b_WriteByte(color.pixel.red); |
| | | ws2812b_WriteByte(color.pixel.blue); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | static inline void ws2812b_Refresh(void) |
| | | { |
| | | int i; |
| | | |
| | | for(i=0; i<WS2812_NUM; i++) |
| | | { |
| | | ws2812b_SendColor(g_ColorPanel[i]); |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |
| | | static inline int ws2812b_SetPixel(int which, color_t color) |
| | | { |
| | | if( which<0 || which>=WS2812_NUM ) |
| | | return -1; |
| | | |
| | | g_ColorPanel[which].pixel.red = color.pixel.red; |
| | | g_ColorPanel[which].pixel.green = color.pixel.green; |
| | | g_ColorPanel[which].pixel.blue = color.pixel.blue; |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int ws2812b_turn(int which, color_t color) |
| | | { |
| | | if( which<0 || which>=WS2812_NUM ) |
| | | return -1; |
| | | |
| | | ws2812b_SetPixel(which, color); |
| | | ws2812b_Refresh(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | void ws2812b_blink(void) |
| | | { |
| | | int c, i; |
| | | color_t colors[4] = {[0].data=PIXEL_B, [1].data=PIXEL_R, [2].data=PIXEL_G, [3].data=PIXEL_W}; |
| | | color_t color_off = {.data = PIXEL_OFF}; |
| | | |
| | | for(c=0; c<4; c++) /* color */ |
| | | { |
| | | for(i=0; i<WS2812_NUM; i++) |
| | | { |
| | | ws2812b_turn(i, colors[c]); |
| | | mdelay(200); |
| | | ws2812b_turn(i, (color_t)color_off); |
| | | mdelay(200); |
| | | } |
| | | } |
| | | } |
| | | |