/**********************************************************************
|
* Copyright: (C)2023 LingYun IoT System Studio
|
* Author: GuoWenxue<guowenxue@gmail.com> 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 <string.h>
|
#include <stdint.h>
|
#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; 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]);
|
HAL_Delay(100);
|
ws2812b_turn(i, (color_t)color_off);
|
HAL_Delay(100);
|
}
|
}
|
}
|