明石高専ロボ研 mbedライブラリ

Dependencies:   mbed

neopixel.cpp

Committer:
TanakaRobo
Date:
2020-11-12
Revision:
5:a7894e6982ea
Parent:
0:ca84ed7518f5
Child:
7:4ad54efe2fdd

File content as of revision 5:a7894e6982ea:

#include "mbed.h"
#include "neopixel.h"

const int wait_time[4][2] = {
    {6, 9},
    {2, 5},
    {2, 4},
    {5, 9}
};
    
NeoPixelOut::NeoPixelOut(PinName pin, int num) : DigitalOut(pin)
{
    normalize = false;
    global_scale = 1.0f;
    #if  defined(TARGET_NUCLEO_L432KC)
        board_ = 0;
    #elif defined(TARGET_NUCLEO_F446RE)
        board_ = 1;
    #else
    #error "This board is not supported"
    #endif
    num_pixels_ = num;
    strip_.resize(num);
}

// The timing should be approximately 800ns/300ns, 300ns/800ns
void NeoPixelOut::byte(register uint32_t byte)
{        
    for (int i = 0; i < 8; i++) {
        gpio_write(&gpio, 1);
        
        // duty cycle determines bit value
        if (byte & 0x80) {
            // one
            for(int j = 0; j < wait_time[0][board_]; j++) asm("NOP");//6 9
            
            gpio_write(&gpio, 0);
            for(int j = 0; j < wait_time[1][board_]; j++) asm("NOP");//2 5
        }
        else {
            // zero
            for(int j = 0; j < wait_time[2][board_]; j++) asm("NOP");//2 4
            
            gpio_write(&gpio, 0);
            for(int j = 0; j < wait_time[3][board_]; j++) asm("NOP");//5 9
        }

        byte = byte << 1; // shift to next bit
    }
    
}

void NeoPixelOut::setPixelColor(uint32_t i,uint32_t color){
    if(i >= num_pixels_){
        return;
    }
    strip_[i].hex = color;
}
    
void NeoPixelOut::show(){
    // Disable interrupts in the critical section
    __disable_irq();

    float fr,fg,fb;
    int count = strip_.size();
    for (int i = 0; i < count; i++) {
        fr = strip_[i].r;
        fg = strip_[i].g;
        fb = strip_[i].b;
        
        if (normalize) {
            float scale = 255.0f/(fr+fg+fb);           
            fr *= scale;
            fg *= scale;
            fb *= scale;            
        }
        
        fr *= global_scale;
        fg *= global_scale;
        fb *= global_scale;
        
        if (fr > 255) fr = 255; 
        if (fg > 255) fg = 255;
        if (fb > 255) fb = 255;
        if (fr < 0) fr = 0; 
        if (fg < 0) fg = 0;
        if (fb < 0) fb = 0;
        
        // Black magic to fix distorted timing
        #ifdef __HAL_FLASH_INSTRUCTION_CACHE_DISABLE
        __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
        #endif
        
        byte((int)fg);
        byte((int)fr);
        byte((int)fb);
        
        #ifdef __HAL_FLASH_INSTRUCTION_CACHE_ENABLE
        __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
        #endif
    }

    __enable_irq();

    flip();
}

void NeoPixelOut::send(Pixel *colors, uint32_t count, bool flipwait)
{
    // Disable interrupts in the critical section
    __disable_irq();

    Pixel* rgb;
    float fr,fg,fb;
    for (int i = 0; i < count; i++) {
        rgb = colors++;
        fr = (int)rgb->r;
        fg = (int)rgb->g;
        fb = (int)rgb->b;
        
        if (normalize) {
            float scale = 255.0f/(fr+fg+fb);           
            fr *= scale;
            fg *= scale;
            fb *= scale;            
        }
        
        fr *= global_scale;
        fg *= global_scale;
        fb *= global_scale;
        
        if (fr > 255) fr = 255; 
        if (fg > 255) fg = 255;
        if (fb > 255) fb = 255;
        if (fr < 0) fr = 0; 
        if (fg < 0) fg = 0;
        if (fb < 0) fb = 0;
        
        // Black magic to fix distorted timing
        #ifdef __HAL_FLASH_INSTRUCTION_CACHE_DISABLE
        __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
        #endif
        
        byte((int)fg);
        byte((int)fr);
        byte((int)fb);
        
        #ifdef __HAL_FLASH_INSTRUCTION_CACHE_ENABLE
        __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
        #endif
    }

    __enable_irq();

    if (flipwait) flip();
}

uint32_t NeoPixelOut::color(uint32_t b,uint32_t g,uint32_t r){
    return b + (g << 8) + (r << 16);
}
 
int NeoPixelOut::numPixels(){
    return num_pixels_;
}

void NeoPixelOut::off(bool flag){
    for(int i = 0;i < strip_.size();i++){
        strip_[i].hex = 0;
    }
    if(flag){
        show();
    }
}

void NeoPixelOut::changeNum(uint32_t num){
    strip_.resize(num);
    num_pixels_ = num;
}

void NeoPixelOut::setBrightness(float brightness){
    global_scale = brightness;
}

void NeoPixelOut::flip(void)
{
    wait_us(50);    
}