GEX core repository.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gex-core/units/neopixel/ws2812.c

96 lines
2.4 KiB

7 years ago
#include "platform.h"
#include "ws2812.h"
static //inline __attribute__((always_inline))
void ws2812_byte(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t b)
{
__disable_irq();
for (register volatile uint8_t i = 0; i < 8; i++) {
LL_GPIO_SetOutputPin(port, ll_pin);
// duty cycle determines bit value
if (b & 0x80) {
for(uint32_t _i = 0; _i < 10; _i++) asm volatile("nop");
LL_GPIO_ResetOutputPin(port, ll_pin);
for(uint32_t _i = 0; _i < 10; _i++) asm volatile("nop");
} else {
for(uint32_t _i = 0; _i < 5; _i++) asm volatile("nop");
LL_GPIO_ResetOutputPin(port, ll_pin);
for(uint32_t _i = 0; _i < 10; _i++) asm volatile("nop");
}
b <<= 1; // shift to next bit
}
__enable_irq();
}
/** Set many RGBs */
void ws2812_load(GPIO_TypeDef *port, uint32_t ll_pin, uint32_t *rgbs, uint32_t count)
{
vPortEnterCritical();
for (uint32_t i = 0; i < count; i++) {
uint32_t rgb = *rgbs++;
ws2812_byte(port, ll_pin, rgb_g(rgb));
ws2812_byte(port, ll_pin, rgb_r(rgb));
ws2812_byte(port, ll_pin, rgb_b(rgb));
}
vPortExitCritical();
// TODO: Delay 50 us
}
/** Set many RGBs from packed stream */
void ws2812_load_raw(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t *rgbs, uint32_t count)
{
vPortEnterCritical();
uint8_t b, g, r;
for (uint32_t i = 0; i < count; i++) {
r = *rgbs++;
g = *rgbs++;
b = *rgbs++;
ws2812_byte(port, ll_pin, g);
ws2812_byte(port, ll_pin, r);
ws2812_byte(port, ll_pin, b);
}
vPortExitCritical();
// TODO: Delay 50 us
}
/** Set many RGBs from uint32 stream */
void ws2812_load_sparse(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t *rgbs, uint32_t count, bool bigendian)
{
vPortEnterCritical();
uint8_t b, g, r;
for (uint32_t i = 0; i < count; i++) {
if (bigendian) {
rgbs++; // skip
b = *rgbs++;
g = *rgbs++;
r = *rgbs++;
} else {
r = *rgbs++;
g = *rgbs++;
b = *rgbs++;
rgbs++; // skip
}
ws2812_byte(port, ll_pin, g);
ws2812_byte(port, ll_pin, r);
ws2812_byte(port, ll_pin, b);
}
vPortExitCritical();
// TODO: Delay 50 us
}
/** Set many RGBs */
void ws2812_clear(GPIO_TypeDef *port, uint32_t ll_pin, uint32_t count)
{
vPortEnterCritical();
for (uint32_t i = 0; i < count*3; i++) {
ws2812_byte(port, ll_pin, 0);
}
vPortExitCritical();
// TODO: Delay 50 us
}