/********************************************************************** * Copyright: (C)2023 LingYun IoT System Studio * Author: GuoWenxue QQ: 281143292 * Description: ISKBoard WS2812B strip lights Hardware Abstract Layer driver * Reference: https://blog.csdn.net/Lennon8_8/article/details/108980808 * * ChangeLog: * Version Date Author Description * V1.0.0 2023.04.3 GuoWenxue Release initial version ***********************************************************************/ #include #include #include "ws2812b.h" #include "miscdev.h" 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 => 100ns = 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 delay_us(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 delay_us(1); } byte<<=1; } return ; } void ws2812b_reset(void) { /* Sequence Reset: Treset >280us: * * + + * |<- Treset ->| * +--------------+ */ ws_setpin(0); delay_us(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 ) 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