RISC-V/V203F6P6/ws2812b/ws2812b.h
2025-01-25 15:08:53 +01:00

55 lines
2.1 KiB
C++

#ifndef WS2812B_H
#define WS2812B_H
#include <stdint.h>
#include "oneway.h"
#include "fifo.h"
static constexpr int BWW = 3;
struct OneColor {
uint32_t b0 : BWW;
uint32_t b1 : BWW;
uint32_t b2 : BWW;
uint32_t b3 : BWW;
uint32_t b4 : BWW;
uint32_t b5 : BWW;
uint32_t b6 : BWW;
uint32_t b7 : BWW;
explicit OneColor (const uint8_t c) noexcept;
unsigned to_string (char * ptr, const int m = BWW);
}__attribute__((packed));
struct Color {
OneColor g,r,b;
}__attribute__((packed));
union Entry {
struct _ws {
uint8_t g,r,b;
uint8_t order; // určuje pořadí LED
} ws;
uint32_t number;
explicit Entry (const uint32_t e) noexcept { number = e; }
};
/*************************************************************************************/
static constexpr unsigned NUMLEDS = 4u;
static constexpr unsigned FIFOLEN = 8u; // min. depth je 8, jinak mocnina 2 >= NUMLEDS
/*************************************************************************************/
/** @class ws2812b
* @brief Driver pro WS2812B
* On ten driver je trochu divný. Běží nad SPI s použitím pinu MOSI, 1 bit barvy
* jsou 3 bity SPI. Funguje to tak, že SPI běží přes DMA v cirkulárním módu, tedy
* pořád, v 1. části dělá "reset", tedy časování rámce (vysílá nuly).
* V 2. části si vybere z fronty ring data a uloží je do buferu ve správném
* tvaru. Využívá se toho, že přerušení přijde až na konci a naplnění daty
* netrvá dlouho, takže se přepisuje jen část, která se právě nevysílá.
* Fronta byla použita (celkem zbytečně) protože zatím netuším jaká data posílat.
* NOTE
* Protože WS2812B je 5V záležitost a procesor je napájen jen 3.3V, funguje to
* na hraně a je dobré zapojit mezi MOSI a +5V rezistor 1k. Je to pak stabilnější.
* */
class ws2812b : public OneWay<uint8_t> {
FIFO<uint32_t,FIFOLEN> & ring;
public:
explicit ws2812b (FIFO<uint32_t,FIFOLEN> & r) noexcept : OneWay (), ring(r) {}
unsigned int Send (uint8_t * const ptr, const unsigned int len) override;
protected:
};
#endif // WS2812B_H