Fork of lichtspiel for mbed

Dependencies:   PololuLedStrip mbed

LEDs.cpp

Committer:
thegink
Date:
2018-05-19
Revision:
0:8dc213146b30

File content as of revision 0:8dc213146b30:

#include "LEDs.h"

LEDs::LEDs(PinName main, PinName single):
    mainStrip(main),
    singleStrip(single)
{
  currentIndex = 0;
}

void LEDs::updateSingleLED(uint8_t colorH, uint8_t colorS, uint8_t colorV) {
  hsv_color hsv = {colorH, colorS, colorV};
  for (uint8_t i=0; i < LEDS_SINGLE_STRIP_NUM_LEDS; i++)
    singleColours[i] = HsvToRgb(hsv);
  show();
}

void LEDs::updateStripLED(uint8_t index, uint8_t colorH, uint8_t colorS, uint8_t colorV) {
hsv_color hsv = {colorH, colorS, colorV};
  uint8_t stripIndex = LEDS_MAIN_STRIP_TOGGLE_OFFSET + index;
  mainColours[stripIndex] = HsvToRgb(hsv);
  show();
}

void LEDs::setStripLEDRGB(uint8_t index, uint8_t colorR, uint8_t colorG, uint8_t colorB) {
  rgb_color rgb = {colorR, colorG, colorB};
  mainColours[index] = rgb;
}


void LEDs::setStripLED(uint8_t index, uint8_t colorH, uint8_t colorS, uint8_t colorV) {
  hsv_color hsv = {colorH, colorS, colorV};
  mainColours[index] = HsvToRgb(hsv);
}

void LEDs::turnOffStripLED(uint8_t index) {
  uint8_t stripIndex = LEDS_MAIN_STRIP_TOGGLE_OFFSET + index;
  rgb_color rgb = {0,0,0};
  mainColours[stripIndex] = rgb;
  show();
}

bool LEDs::isStripLEDOn(uint8_t index) {
  uint8_t stripIndex = LEDS_MAIN_STRIP_TOGGLE_OFFSET + index;
  return mainColours[stripIndex].red != 0 || mainColours[stripIndex].green != 0 || mainColours[stripIndex].blue != 0;
}

void LEDs::scrollStripToLeft() {
  rgb_color first = mainColours[0];
  for (uint8_t i = 0; i < LEDS_MAIN_STRIP_NUM_LEDS - 1; i++) {
    mainColours[i] = mainColours[i + 1];
  }
  mainColours[LEDS_MAIN_STRIP_NUM_LEDS - 1] = first;
}

void LEDs::scrollStripToRight() {
  rgb_color last = mainColours[LEDS_MAIN_STRIP_NUM_LEDS - 1];
  for (uint8_t i = LEDS_MAIN_STRIP_NUM_LEDS - 1; i > 0; i--) {
    mainColours[i] = mainColours[i - 1];
  }
  mainColours[0] = last;
}

void LEDs::show() {
  mainStrip.write(mainColours, LEDS_MAIN_STRIP_NUM_LEDS);
  singleStrip.write(singleColours, LEDS_SINGLE_STRIP_NUM_LEDS);
}

void LEDs::off() {
  
  rgb_color black = {0,0,0};
  
  for (uint8_t j = 0; j < 10; j++) {
    for (uint8_t i = 0; i < LEDS_MAIN_STRIP_NUM_LEDS; i++) 
    {
        fadeToBlackBy(64,mainColours[i]);
    }
    
    for (uint8_t i = 0; i < LEDS_SINGLE_STRIP_NUM_LEDS; i++)
    {
        fadeToBlackBy(64, singleColours[i]);
    }
    
    show();
    wait_ms(50);
  }

  for (uint8_t i = 0; i < LEDS_MAIN_STRIP_NUM_LEDS; i++) {
    mainColours[i] = black;
  }
  for (uint8_t i = 0; i < LEDS_SINGLE_STRIP_NUM_LEDS; i++) {
    singleColours[i] = black;
  }
  
  show();
}

rgb_color LEDs::HsvToRgb(hsv_color hsv)
{
    rgb_color rgb;
    unsigned char region, p, q, t;
    unsigned int h, s, v, remainder;

    if (hsv.s == 0)
    {
        rgb.red = hsv.v;
        rgb.green = hsv.v;
        rgb.blue = hsv.v;
        return rgb;
    }

    // converting to 16 bit to prevent overflow
    h = hsv.h;
    s = hsv.s;
    v = hsv.v;

    region = h / 43;
    remainder = (h - (region * 43)) * 6; 

    p = (v * (255 - s)) >> 8;
    q = (v * (255 - ((s * remainder) >> 8))) >> 8;
    t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;

    switch (region)
    {
        case 0:
            rgb.red = v;
            rgb.green = t;
            rgb.blue = p;
            break;
        case 1:
            rgb.red = q;
            rgb.green = v;
            rgb.blue = p;
            break;
        case 2:
            rgb.red = p;
            rgb.green = v;
            rgb.blue = t;
            break;
        case 3:
            rgb.red = p;
            rgb.green = q;
            rgb.blue = v;
            break;
        case 4:
            rgb.red = t;
            rgb.green = p;
            rgb.blue = v;
            break;
        default:
            rgb.red = v;
            rgb.green = p;
            rgb.blue = q;
            break;
    }

    return rgb;
}

hsv_color LEDs::RgbToHsv(rgb_color rgb)
{
    hsv_color hsv;
    unsigned char rgbMin, rgbMax;

    rgbMin = rgb.red < rgb.green ? (rgb.red < rgb.blue ? rgb.red : rgb.blue) : (rgb.green < rgb.blue ? rgb.green : rgb.blue);
    rgbMax = rgb.red > rgb.green ? (rgb.red > rgb.blue ? rgb.red : rgb.blue) : (rgb.green > rgb.blue ? rgb.green : rgb.blue);

    hsv.v = rgbMax;
    if (hsv.v == 0)
    {
        hsv.h = 0;
        hsv.s = 0;
        return hsv;
    }

    hsv.s = 255 * ((long)(rgbMax - rgbMin)) / hsv.v;
    if (hsv.s == 0)
    {
        hsv.h = 0;
        return hsv;
    }

    if (rgbMax == rgb.red)
        hsv.h = 0 + 43 * (rgb.green - rgb.blue) / (rgbMax - rgbMin);
    else if (rgbMax == rgb.green)
        hsv.h = 85 + 43 * (rgb.blue - rgb.red) / (rgbMax - rgbMin);
    else
        hsv.h = 171 + 43 * (rgb.red - rgb.green) / (rgbMax - rgbMin);

    return hsv;
}

void LEDs::saveStateToEEPROM() {
  for (uint8_t i = 0; i < LEDS_MAIN_STRIP_NUM_LEDS; i++) 
  {
    eeprom.update(i * 3 + 0, mainColours[i].red);
    eeprom.update(i * 3 + 1, mainColours[i].green);
    eeprom.update(i * 3 + 2, mainColours[i].blue);
  }
}

void LEDs::loadStateFromEEPROM() {
  for (int16_t j = 255; j > 0; j -= 26) 
  {
    loadStateFromEEPROMAndDim(j);
    wait_ms(30);
  }
  loadStateFromEEPROMAndDim(0);
}

void LEDs::loadStateFromEEPROMAndDim(uint8_t dimAmount) {
  for (uint8_t i = 0; i < LEDS_MAIN_STRIP_NUM_LEDS; i++) {
    mainColours[i].red = eeprom.read(i * 3 + 0);
    mainColours[i].green = eeprom.read(i * 3 + 1);
    mainColours[i].blue = eeprom.read(i * 3 + 2);
    fadeToBlackBy(dimAmount, mainColours[i]);
  }
  show();
}

void LEDs::fadeToBlackBy(uint8_t amount, rgb_color& colour)
{
    //fades colour by 'amount' 256ths
    if (amount)
    {
        colour.red = (uint8_t)(((uint16_t)colour.red * (uint16_t)amount + 128)/256);
        colour.green = (uint8_t)(((uint16_t)colour.green * (uint16_t)amount + 128)/256);
        colour.blue = (uint8_t)(((uint16_t)colour.blue * (uint16_t)amount + 128)/256);
    }
}