WS2812B Liblary this use SPI

WS2812B.cpp

Committer:
Suzutomo
Date:
2019-12-21
Revision:
6:21a721b31a20
Parent:
5:62b6ac21c199

File content as of revision 6:21a721b31a20:

//--------------------------------------------------------
//  SPI を使って WS2812B を点灯するためのクラス
//      サポートするボード: Nucleo-F446RE
//--------------------------------------------------------

#include "WS2812B.h"
#include "PeripheralPins.h"     // for pinmap_peripheral()

WS2812B::WS2812B(PinName pin, int num, bool inv)
    : spi_(pin, NC, NC),
      mySpi_((SPI_TypeDef *)pinmap_peripheral(pin, PinMap_SPI_MOSI))
{
    spi_.format(8, 0);
#if defined(STM32F446xx)
    spi_.frequency(22500000);
#else
#error This code is not move this board.
#endif
    if (!inv) fp = &WS2812B::SendByteNorm;
    else      fp = &WS2812B::SendByteInv;

    bright = 1.0;
    Normalize();
    
    bufferSize = num;
    colors = (uint32_t *)calloc(bufferSize,sizeof(uint32_t));
    if (colors == NULL) printf("can not reserve memory\n");
}

uint8_t WS2812B::getRGB(uint32_t x,RGB rgb)
{
    return (uint8_t)((x >> (rgb * 8)) & 0xFF);
}

uint32_t WS2812B::BrightAdjust(uint32_t x,double brightness)
{
    uint8_t r = getRGB(x,R) * brightness;
    uint8_t g = getRGB(x,G) * brightness;
    uint8_t b = getRGB(x,B) * brightness;
    x = (r << 16) | (g << 8) | b;
    return x;
}

uint32_t WS2812B::NormalizeAdjust(uint32_t x) {
    double m = 0;
    for (int i = 0;i < 3;i++) m += (double)getRGB(x,(RGB)i);
    return BrightAdjust(x,(0xFF / m) * (m / (0xFF * 3)));
}

// 特定の位置の色を変更する
void WS2812B::Write(int index,uint32_t x,double brightness)
{
    if (index >= 0 && index < bufferSize) colors[index] = BrightAdjust(x,brightness);
}

// すべての色を変更する
void WS2812B::Write(uint32_t x,double brightness)
{
    for (int i = 0; i < bufferSize; i++) colors[i] = BrightAdjust(x,brightness);
}

// バッファの色情報を送る
void WS2812B::Send()
{
    static const uint32_t bit23 = 0x800000;
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
                 // SysTick_CTRL_TICKINT_Msk   |  ←割り込みを無効
                    SysTick_CTRL_ENABLE_Msk; 
    for (int i = 0; i < bufferSize; i++) {
        uint32_t x_rgb;
        if (normalize) x_rgb = NormalizeAdjust(colors[i]);
        else x_rgb = colors[i];
        x_rgb = BrightAdjust(x_rgb,bright);
        uint32_t x_grb = getRGB(x_rgb,G) << 16 | getRGB(x_rgb,R) << 8 | getRGB(x_rgb,B);
        
        for (int n=0; n<24; n++) {
            if ((x_grb & bit23) == bit23) T1HL();
            else                      T0HL();
            x_grb <<= 1;
        }
    }
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // enable interrupt
    Reset();
}

void WS2812B::Clear(int k)
{
    for (int n=0; n<k; n++) colors[n] = 0;
    Send();
    Reset();
}

void WS2812B::Send3Bytes(uint16_t x0, uint16_t x1, uint16_t x2)
{
    SendByte(x0);
    SendByte(x1);
    SendByte(x2);
}

void WS2812B::SendByteNorm(uint8_t x)
{
    while ((mySpi_->SR & SPI_SR_TXE) != SPI_SR_TXE) {}
    mySpi_->DR = x;
}

void WS2812B::SendByteInv(uint8_t x)
{
    while ((mySpi_->SR & SPI_SR_TXE) != SPI_SR_TXE) {}
    mySpi_->DR = ~x;
}

void WS2812B::Brightness(double brightness)
{
    bright = brightness;
}

void WS2812B::Normalize(bool a) {
    normalize = a;
}