
#include "leds.h"

#include "loopScanner.h"

#include <Adafruit_NeoPixel.h>

// LED blinking indicator
volatile int blinkDivider;
volatile int blinkstepnumber;
volatile byte ledState;
String ledStateString;


const int blinkprogram[72] = {     BLC_ON,   12, BLC_OFF,  13, BLC_BRR, -6,                                                           // INIT      blink pattern: 4   Hz 1:1,   length =  6,  pos:    0
                                   BLC_ON,   25, BLC_OFF, 975, BLC_BRR, -6,                                                           // CONN      blink pattern: 0.1 Hz 45:1,  length =  6,  pos:    6
                                   BLC_ON,    5, BLC_OFF,   5, BLC_BRR, -6,                                                           // NOTCONN   blink pattern: 10  Hz 1:1,   length =  6,  pos:   12
                                   BLC_ON,  100, BLC_OFF, 100, BLC_BRR, -6,                                                           // IDLE      blink pattern: 0.5 Hz 1:1,   length =  6,  pos:   18
                                   BLC_ON,   25, BLC_OFF,  25, BLC_ON,  25, BLC_OFF,  25,  BLC_ON,  25, BLC_OFF,  75,
                                   BLC_ON,   75, BLC_OFF,  25, BLC_ON,  75, BLC_OFF,  25,  BLC_ON,  75, BLC_OFF,  75, 
                                   BLC_ON,   25, BLC_OFF,  25, BLC_ON,  25, BLC_OFF,  25,  BLC_ON,  25, BLC_OFF, 175, BLC_BRR, -38,   // SOS       blink pattern,               length = 38,  pos:   24  
                                   BLC_ON,   25, BLC_OFF,  25, BLC_ON,  25, BLC_OFF, 225,  BLC_BRR,-10                                // CONFUSED  blink pattern: 2bl2'' pause, length = 10,  pos:   62
                                };

void setBlinkStep(int newBlinkStep) {
  blinkstepnumber = newBlinkStep;
}

int getBlinkStep() {
  return blinkstepnumber;
}

// set the LED
extern void setLED(bool newLEDstate) {
  if (newLEDstate) {
    digitalWrite(LED,HIGH);
    ledStateString = String("On");
    ledState = HIGH;
  } else {
    digitalWrite(LED, LOW);
    ledStateString = String("Off");
    ledState = LOW;
  }
}

// this is to be called every basic tick (per definition 10ms) and will generate the configured blink pattern(s)
void blinkTicker(int blinkParam) {
  blinkDivider--;
  if (blinkDivider<1) {
    while (blinkDivider<1) {
      
      // SERIAL_PRINTF("blink command at %d: %d\n",blinkstepnumber,blinkprogram[blinkstepnumber]));
      
      switch (blinkprogram[blinkstepnumber++]) {
        case BLC_ON:      ledState = HIGH;
                          digitalWrite(LED,ledState);
                          blinkDivider = blinkprogram[blinkstepnumber++];
                          break;
        case BLC_OFF:     ledState = LOW;
                          digitalWrite(LED,ledState);
                          blinkDivider = blinkprogram[blinkstepnumber++];
                          break;
        case BLC_BRR:     blinkstepnumber += blinkprogram[blinkstepnumber++];
                          blinkDivider = 0;
                          break; 
      }
    }
  }
}

/* *****************************************************************************
 *    NeoPixel functions
 * *****************************************************************************/
//
// I/O resources
//
Adafruit_NeoPixel neopixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_RGB + NEO_KHZ800);

int colorR = 0;
int colorG = 0;
int colorB = 0;

void allOn(uint32_t color) {
  for(int i=0; i<neopixels.numPixels(); i++) {      // For each pixel in strip...
    neopixels.setPixelColor(i, color);          //  Set pixel's color (in RAM)
    delay(1);
    neopixels.show();                           //  Update strip to match
  }
}

void setPixels(int sequence, uint32_t color) {
  if (sequence == SEQ_ALLON) {
    allOn (color);
  }
}

void setupNeoPixel() {
  neopixels.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  neopixels.show();            // Turn OFF all pixels ASAP
  neopixels.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
  setPixels(SEQ_ALLON, neopixels.Color(colorR, colorG, colorB));
}


/* *****************************************************************************
 *  FUNCTION:       neoPixelLoop
 *  DESCRIPTION:    to be called periodically
 *                  cycles through 8 colours with change each second
 */
 void neoPixelLoop(int param) {
  // bump up neopixels color every second
  colorR = (colorR>0?0:255);        // toggle R
  if (colorR==0) {
    colorG = (colorG>0?0:255);      // toggle G at half of R frequency
    if (colorG==0) {
      colorB = (colorB>0?0:255);    // toggle B at half of G frequency
    }
  }
  /*
  Serial.print("NeoPixel Colors (RGB): ");
  Serial.print(colorR);
  Serial.print("/");
  Serial.print(colorG);
  Serial.print("/");
  Serial.print(colorB);
  Serial.println();
  */
  setPixels(SEQ_ALLON, neopixels.Color(colorR, colorG, colorB));
 }


//
// -------- setup board LED status display function ----------------------------------
//
void initLEDs() {
  pinMode(LED,OUTPUT);
  setLED(false);
  blinkstepnumber = BLE_CONFUSED;
  blinkDivider = NUMOFBLINKTICKS;
  addLoopScanner(10,blinkTicker,0,"blinkTicker");       // blinkTicker called every 10ms
  setupNeoPixel();
  addLoopScanner(5000,neoPixelLoop,5000,"4 second neoPixel loop");
  SERIAL_PRINTLN("Indicators (LEDs / neoPixels) initialized");
}
