/*

Name    : Adyen IPP Staging Terminal State Indicator
Version : 0.8-RP2040 only
Date    : 2025-03-22
Author  : Bas van Ritbergen <[email protected]>   

RP2040      : Make sure to use Mbed OS setup for the MCU

*/


// Basic defaults 
#define CONFIG_IDENTIFIER "ADYENLED"
#define IDENTIFIER_DEFAULT "STGSTRIP"
#define NUM_LEDS_PER_STRIP_DEFAULT 48
#define NUM_STRIPS_DEFAULT 6
#define NUM_GROUPS_PER_STRIP_DEFAULT 6
#define SPACER_WIDTH_DEFAULT 1
#define MAX_TERMINALS 48
#define BLINK_INTERVAL 200
#define COLOR_STATE_1 CRGB::Green
#define COLOR_STATE_2 CRGB::DarkOrange
#define COLOR_STATE_3 CRGB::Red
#define COLOR_STATE_4 0x000080

#define DEBUG true

//  ###########################################################################
// No configurable items below

#define VERSION 0.8

// Define max length for Input/Ouput buffers:
#define MAX_INPUT_LEN 50
#define MAX_OUTPUT_LEN 60


#define RP2040 1
#define MCU "RP2040"
#define CPULED 25

// We definitely need these libraries
#include <Arduino.h>
#include <FastLED.h>

#include "LittleFS_Mbed_RP2040.h"
#include "mbed.h"
#define HAS_LittleFS true
#define _LFS_LOGLEVEL_          1
#define RP2040_FS_SIZE_KB       16
#define FORCE_REFORMAT          false
#define CONFIG_FILENAME MBED_LITTLEFS_FILE_PREFIX"/config.bin"
LittleFS_MBED *mbed_FS;

// Figure MCU type/serial
#include <MicrocontrollerID.h>
char MCUid [41];

// Declare LedStrip control arrays
//CRGB leds[NUM_STRIPS_DEFAULT+1][NUM_LEDS_PER_STRIP_DEFAULT];
// We cannot dynamically change this without crashing... :-(
CRGB leds[NUM_STRIPS_DEFAULT+1][144];
//leds = new CRGB[NUM_STRIPS_DEFAULT+1][144];

// Config data is conviently stored in a struct (to easy store and retrieve from EEPROM/Flash)
// Set defaults, they will be overwritten by load from EEPROM
struct LedData {
  //char *identifier = nullptr;
  char identifier[16] = IDENTIFIER_DEFAULT;
  uint16_t numLedsPerStrip = NUM_LEDS_PER_STRIP_DEFAULT;
  uint8_t numStrips = NUM_STRIPS_DEFAULT;
  uint8_t numGroupsPerStrip = NUM_GROUPS_PER_STRIP_DEFAULT;
  uint8_t spacerWidth = SPACER_WIDTH_DEFAULT;
  uint16_t blinkinterval = BLINK_INTERVAL;
  CRGB state_color[5] = {CRGB::Black, COLOR_STATE_1, COLOR_STATE_2, COLOR_STATE_3, COLOR_STATE_4 };
} LedConfig = {};


// Input data from serial is stores in an array for further processing.
char inputBuffer[MAX_INPUT_LEN + 1]; // +1 for null terminator
uint8_t bufferIndex = 0;


// For blinking feature we need some extra global parameters
bool BlinkState[MAX_TERMINALS] = {0};
CRGB BlinkColor[MAX_TERMINALS] = {0};
bool blink=false;
uint32_t lastToggleTimes;


// For heartbeat-led on RP2040-zero (array with 1 position)
CRGB cpuled[1];

// HelpText
const char HelpText[850] PROGMEM = 
  "  Syntax:\n"
  "    H                          This help\n"
  "    T<TermID>:<State>          Set Terminal state. TermID: 1-48 and State: 0-9\n"
  "    X                          Set all states to off (same as sending'A:0'\n"
  "    M:<State><State><State>... Set state for multiple Terminals, sequentually listed\n"
  "    A:<State>                  Set state for all Terminals, state (0-9)\n"
  "    D                          Show current configuration\n"
  "    C<iltswb>:value            Set config for [i]dentifier, [l]eds per shelf, [t]erminals per shelf, amount of [s]helves, spacer-[w]idth, [b]link-interval.\n"
  "    S                          Store current configuration in EEPROM/FLASH\n"
  "    L                          Load stored cofiguration from EEPROM/FLASH\n"
  "    R                          Reboot controller (Disconnects serial!)\n"
  "    W                          Show startup loop\n"
  "\n" ;

// All the messages are stored in program-memory to save CPU-memory (especially for AVR type mcu's)
const uint8_t MSG_MAX_NUMBER = 38;
const uint8_t MSG_MAX_SIZE = 50;
const char messages [MSG_MAX_NUMBER] [MSG_MAX_SIZE] PROGMEM = { 
  { "-=[ USB LedStrip ]=-\n" },                         // 0  
  { "Invalid state, use 0-9\n" },                       // 1
  { "Invalid Terminal-ID, use 1-48\n" },                // 2
  { "Syntax error: Use T<TERMINAL-ID>:<STATE>\n" },     // 3 
  { "Syntax error: Use A:<STATE>\n" },                  // 4
  { "Display configuration:\n" },                       // 5
  { "Save configuration: " },                           // 6
  { "Configuration saved in EEPROM.\n" },               // 7
  { "Reset all Terminal states.\n" },                   // 8
  { "Showing startup loop.\n" },                        // 9
  { "ERROR: command unknown.\n" },                      // 10
  { "SYNTAX ERROR: Use <A-Z>, H for help.\n" },         // 11
  { "Identifier           : " },                        // 12
  { "LEDs per shelf       : " },                        // 13
  { "Terminals per shelf  : " },                        // 14
  { "Amount of shelves    : " },                        // 15
  { "Spacer width         : " },                        // 16
  { "Blinking interval    : " },                        // 17
  { "No EEPROM or FLASH on this MCU\n" },               // 18 !!!!
  { "Rebooting contoller...\n" },                       // 19
  { "Load configuration: " },                           // 20
  { "All terminals set to state " },                    // 21
  { "Configuration loaded\n" },                         // 22
  { "* Opening Failed\n" },                             // 23
  { "* Writing failed\n" },                             // 24
  { "ERROR, configfile is empty" },                     // 25
  { "Valid config found in EEPROM, loading it.\n" },    // 26 !!!!
  { "No config stored in EEPROM, using defaults.\n\n" },// 27 !!!!
  { "Configuration stored in EEPROM.\n" },              // 28
  { "Version " },                                       // 29
  { "MCU          : " },                                // 30
  { "SN           : " },                                // 31
  { " compiled for " },                                 // 32 ????
  { "Testing EEPROM availability & contents\n" },       // 33 !!!!
  { "Failed to initialise EEPROM, Restarting...\n" },   // 34 !!!!
  { "LITTLEFS Mount Failed, Restarting...\n" },         // 35
  { "Ok\n"},                                            // 36
  { "Syntax error: Use M:<STATE><STATE<<STATE>...\n" }  // 37
};


// Setup MCU
void setup() {
  // Setup USB-serial port
  Serial.begin(115200);
  //Serial.setTimeout(0);

  // Initialize status led, set to blue to show we are waitong for input
  // FastLED.addLeds<WS2812B, 16, GRB>(cpuled, 1);
  // FastLED.addLeds<WS2812B, 23, GRB>(cpuled, 1);
  FastLED.addLeds<WS2812B, 24, GRB>(cpuled, 1);
  
  cpuled[0] = CRGB::Blue;
  FastLED.show();

  while (!Serial) {
    // wait for serial port to connect.
    // Flash the status led green to indicate we are ready to start.
    delay(750);
    digitalWrite(CPULED, HIGH);
    cpuled[0] = CRGB::Green;
    FastLED.show();
    delay(750);
    digitalWrite(CPULED, LOW);
    cpuled[0] = CRGB::Black;
    FastLED.show();
  }

  // Set led to blue and Show welcome to let us know the controller is booting.
  // Also show some details abour the MCU and the codeversion
  cpuled[0] = CRGB::Blue;
  FastLED.show();
 
  printMSG(0);
  printMSG(29);
  Serial.print(VERSION);
  printMSG(32);
  Serial.println(MCU);
  Serial.println();
 
  printMSG(30);
  Serial.println(BOARD_NAME);
 
  printMSG(31);
  MicroID.getUniqueIDString(MCUid,16);
  Serial.println(MCUid);
  Serial.println();

  // Initialize LittleFS if available
  mbed_FS = new LittleFS_MBED();
  if (!mbed_FS->init()) {
    printMSG(35);
    delay(2000);
    //RebootMCU();
  } else {  
    loadConfiguration();
  }
  // Enable current config (default or loaded from EEPRON/Flash)
  //updateConfiguration();
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT); 
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT); 
  pinMode(9, OUTPUT); 

  // This cannot yet be change in runtime without chrashes or FastLED to break...
  // FastLED class expects the pin to be a constant!
  FastLED.addLeds<WS2812B, 2, GRB>(leds[0], LedConfig.numLedsPerStrip);
  FastLED.addLeds<WS2812B, 3, GRB>(leds[1], LedConfig.numLedsPerStrip);
  FastLED.addLeds<WS2812B, 4, GRB>(leds[2], LedConfig.numLedsPerStrip);
  FastLED.addLeds<WS2812B, 5, GRB>(leds[3], LedConfig.numLedsPerStrip);
  FastLED.addLeds<WS2812B, 6, GRB>(leds[4], LedConfig.numLedsPerStrip);
  FastLED.addLeds<WS2812B, 7, GRB>(leds[5], LedConfig.numLedsPerStrip);

  //startupAnimation();
  StartupLoop();

  // Show help & config:
  // ShowHelp();
  displayConfiguration() ;

  // Ready to go, show prompt.
  Serial.print("> ");
}
 

// Main loop
void loop() {
  while (Serial.available() > 0) {
    CRGB curcol = cpuled[0];
    cpuled[0] = CRGB::Blue;
    FastLED.show();
    char c = Serial.read();
    if (c == '\n' || c == '\r') {
      inputBuffer[bufferIndex] = '\0'; // Null-terminate the string
      Serial.println();
      checkInput(inputBuffer);
      Serial.print("> ");
      bufferIndex = 0;
    } else if ( c == 0x08 ) {   // Backspace
      inputBuffer[bufferIndex--] = '\0';
      Serial.print(c);  
      Serial.print(' ');  
      Serial.print(c);  
    } else if (bufferIndex < MAX_INPUT_LEN - 1 && c >= 0x20 && c < 0x7E && c!= 0x5C && c!=0x60 ) { // only printable chars, -1 to leave space for null terminator at end.
      inputBuffer[bufferIndex++] = c;
      Serial.print(c);
    }
    cpuled[0] = curcol;
    SetLEDs();
  }
  // delay(10);
  SetLEDs();
}

void DEBUGLOG(String *message){
  if (DEBUG == true) {
    Serial.println(*message);
  }
}


void printMSG (int i) {
  if (i <= MSG_MAX_NUMBER) { 
    const char *ptr = reinterpret_cast<const char*>(&messages[i]);    
    char chr;
    if (!ptr) 
      return;
    while ((chr = pgm_read_byte(ptr++))) {
      Serial.print(chr);
    }
  }
}


char* readFile(const char * path) {
  // Serial.print("Reading file: ");
  // Serial.println(path);
  FILE *file = fopen(path, "r");
  if (!file) {
    printMSG(23);
    return 0;
  }
  fseek(file, 0, SEEK_END);
  long fileSize = ftell(file);
  fseek(file, 0, SEEK_SET);
  if (fileSize == 0) {
    printMSG(25);
    fclose(file);
    return 0;
  }

  char *data = new char[fileSize];
  int pos=0;
  char c;
  uint32_t numRead = 1;
  while (numRead) {
    numRead = fread((uint8_t *) &c, sizeof(c), 1, file);
    if (numRead)
      data[pos++]=(char)c;
  }

  fclose(file);
  return data;
}

bool writeFile(const char * path, const char * message, size_t messageSize) {
  FILE *file = fopen(path, "w");
  if (!file) {
    printMSG(23);
    return false;
  }
  if (!fwrite((uint8_t *) message, 1, messageSize, file)) {
    printMSG(24);
    return false;
  }
  fclose(file);
  return true;
}

void loadConfiguration() {
  char *buffer;
  buffer = readFile(CONFIG_FILENAME);
  if (buffer != 0) {
    // DeSeriallize buffer into LedData Struct
    int structSize=sizeof(LedData);
    memcpy(&LedConfig, buffer, structSize);
  }
}

bool saveConfiguration() {
  // Seriallize LedData Struct into char-array so we can save it
  char buffer[sizeof(LedData)];
  memcpy(buffer, &LedConfig, sizeof(LedData));
  writeFile(CONFIG_FILENAME, buffer, sizeof(buffer));
}

// void updateConfiguration() {
//   // delete[] leds;
//   ///CRGB leds[LedConfig.numStrips][LedConfig.numLedsPerStrip];
//   // leds = new CRGB[LedConfig.numStrips][LedConfig.numLedsPerStrip];

//   // Code below does not work as the FastLED class expects the pin to be a constant :-/
//   // FastLED.addLeds<[LEDTYPE], [PIN], [RGB-ORDER]>( [LED-array], [NUMBER OF LEDS]);
//   // for (const int n = 0; n < LedConfig.numStrips; n++) {
//   //   FastLED.addLeds<WS2812, n+2, GRB>(leds[n], LedConfig.numLedsPerStrip);
//   // }

//   pinMode(2, OUTPUT);
//   pinMode(3, OUTPUT); 
//   pinMode(4, OUTPUT);
//   pinMode(5, OUTPUT);
//   pinMode(6, OUTPUT);
//   pinMode(7, OUTPUT);
//   pinMode(8, OUTPUT); 
//   pinMode(9, OUTPUT); 
//   // Reconfiguring these cause a crash... :-(
//   FastLED.addLeds<WS2812B, 2, GRB>(leds[0], LedConfig.numLedsPerStrip);
//   FastLED.addLeds<WS2812B, 3, GRB>(leds[1], LedConfig.numLedsPerStrip);
//   FastLED.addLeds<WS2812B, 4, GRB>(leds[2], LedConfig.numLedsPerStrip);
//   FastLED.addLeds<WS2812B, 5, GRB>(leds[3], LedConfig.numLedsPerStrip);
//   FastLED.addLeds<WS2812B, 6, GRB>(leds[4], LedConfig.numLedsPerStrip);
//   FastLED.addLeds<WS2812B, 7, GRB>(leds[5], LedConfig.numLedsPerStrip);
// }



void checkInput(char input[16]) { 

  if (input[0] == 0) {
    Serial.println("");
    return;
  }

  char output[MAX_OUTPUT_LEN];
  memset(output, '\0', sizeof(output));

  int test=0;
  int State;
  String AllStates;
  int TermID;

  // sprintf(output,"Input: [%s].",input);      
  // Serial.println(output); 

  char Command = input[0];
  char *Data = input +1; 

  if (Command >= 'A' && Command <= 'Z') {
    // sprintf(output,"Command [%c] with Data [%s]",Command, Data); 
    // Serial.println(output);

    switch(Command) {
      // Display curren configuration
      case 'D':
        printMSG(5);
        displayConfiguration();
        break;

      // Set configuration
      case 'C':
        SetConfigParameters(Data);
        break;

      // Store current configuration
      case 'S':
        printMSG(6);
        saveConfiguration();
        printMSG(36);
        break;

      // Load configuration from Flash/EEPROM
      case 'L':
        printMSG(20);
        loadConfiguration();
        printMSG(22);
        break;

      // Set Terminal state 
      case 'T':
        test = sscanf(Data, "%2d:%d", &TermID, &State);
        if ( test == 2) {
          if (TermID >= 1 && TermID <= MAX_TERMINALS) {
            if (State >= 0 && State <= 9) {
              setGroupState(TermID -1,State);
              sprintf(output,"Terminal %d state set to %d", TermID, State);
              Serial.println(output);
            } else {
              printMSG(1);
            }
          } else { 
            printMSG(2);
          }
        } else {
          printMSG(3);
        }
        break;
               
      // Set state for all Terminals 
      case 'A':
        test = sscanf(Data, ":%d", &State);
        if (test == 1) {
          if (State >= 0 && State <= 9) {
            printMSG(21);
            Serial.println(State);
            for(int i=0; i < MAX_TERMINALS; i++){
              setGroupState(i,State);
            }
          } else {
            printMSG(1);
          }
        } else 
          printMSG(4);
        break;
      
      // Set mass state, a digit for each terminal (48 max)
      case 'M':
        char ST;
        Serial.println();
        if ( Data[0] == ':') {
          int Term=1;
          while ( Data[Term] != 0 && Term<=MAX_TERMINALS ) {
            // Serial.print("Set Terminal ");
            // Serial.print(i);
            ST=Data[Term];
            State = atoi(&ST);
            if (State >= 0 && State <= 9) {
              // Serial.print(" to state ");
              // Serial.print(State);
              setGroupState(Term -1,State);
            }
            Term++;
            // Serial.println();
          }
          // Serial.println();
        } else 
          printMSG(37);
        break;

      // Reset all states to off
      case 'X':
        printMSG(8);
        for(int i=0; i < MAX_TERMINALS; i++){
          setGroupState(i,0);
        }
        SetAllLEDs(CRGB::Black);
        break;

      // Show startup loop
      case 'W':
        printMSG(9);
        StartupLoop();
        break;

      // Reboot controller
      case 'R':
        printMSG(19);
        RebootMCU();
        break;

      // Show help
      case 'H':
        ShowHelp();
        break;

      default:
        printMSG(10);
        break;
    }
  } else
    printMSG(11); 
}

void RebootMCU() {
  NVIC_SystemReset();
}


void ShowHelp(){
    const char *ptr = reinterpret_cast<const char*>(&HelpText);
    char chr;
    if (!ptr) 
      return;
    while ((chr = pgm_read_byte(ptr++))) {
      Serial.print(chr);
    }
}

void SetConfigParameters(char *Data){
  char ConfigItem = Data[0];
  char *Value = Data +2; 

  //               1111
  // Data: 012356890123
  // Data: i:bastest 
  // Value:  0123456789
    if (Data[1] == ':') {
    switch (ConfigItem) {
      // set Idenitfier
      case 'i':
        Serial.println();
        printMSG(12);
        strcpy(LedConfig.identifier,Value);
        Serial.println(LedConfig.identifier);
        break;
      // set led per strip
      case 'l':
        Serial.println();
        printMSG(13);
        LedConfig.numLedsPerStrip = atoi(Value);
        Serial.println(LedConfig.numLedsPerStrip);
        break;
      // set terminals per shelf
      case 't':
        Serial.println();
        printMSG(14);
        LedConfig.numGroupsPerStrip = atoi(Value);
        Serial.println(LedConfig.numGroupsPerStrip);
        break;
      // set number of shelves
      case 's':
        Serial.println();
        printMSG(15);
        LedConfig.numStrips = atoi(Value);
        Serial.println(LedConfig.numStrips);
        break;
      // set spacer width
      case 'w':
        Serial.println();
        printMSG(16);
        LedConfig.spacerWidth = atoi(Value);
        Serial.println(LedConfig.spacerWidth);
        break;
      // Set blink interval
      case 'b':
        Serial.println();
        printMSG(17);
        LedConfig.blinkinterval = atoi(Value);
        Serial.println(LedConfig.blinkinterval);
        break;
      // set colors
      //               1111
      // Data: 012356890123
      // Data: c:1:0000FF 
      // Value:  0123456789
      case 'c':
        char buffer[8];
        Serial.println();
        if (Value[1] == ':') {
          char StateChar = Data[2];
          int state = atoi(&StateChar);
          if ( state >0 and state<5) {
            char *Color = Data +5; 
            uint32_t RGB=strtoul(Color, NULL, 16);
            Serial.println(RGB);
            if (RGB >0 and RGB < 0xFFFFFFFF) {
              LedConfig.state_color[state] = RGB;;
              Serial.print("Color for state ");
              Serial.print(state);
              Serial.print(" is set to : ");
              sprintf(buffer, "%06X", LedConfig.state_color[state]);
              Serial.print(buffer);
              Serial.println (" (BBGGRR)");
            } else {
              Serial.println("invalid color");
            }
          } 
          else {
            Serial.println("invalid state, 1-4 only");
          }
        }
        else {
          Serial.println("syntax error:  use Cc:<STATE_1-4>:<BBGGRR HEX>\n");
        }
        break;
      default:
        printMSG(11);
        break;
    }
  } else {
    printMSG(11);
  } 
}


void displayConfiguration() {
  char output[MAX_OUTPUT_LEN];
  memset(output, '\0', sizeof(output));

  printMSG(12);
  sprintf(output,"%s",LedConfig.identifier);      
  Serial.println(output); 

  printMSG(13);
  sprintf(output,"%d",LedConfig.numLedsPerStrip);      
  Serial.println(output); 

  printMSG(14);
  sprintf(output,"%d",LedConfig.numGroupsPerStrip);      
  Serial.println(output); 

  printMSG(15);
  sprintf(output,"%d",LedConfig.numStrips);      
  Serial.println(output); 

  printMSG(16);
  sprintf(output,"%d",LedConfig.spacerWidth);      
  Serial.println(output); 

  printMSG(17);
  sprintf(output,"%d",LedConfig.blinkinterval);      
  Serial.println(output); 
  char buffer[6];
  for (int state=1; state<5; state++){
    Serial.print("Color state ");
    Serial.print(state);
    Serial.print(" : ");
    sprintf(buffer, "%06X", LedConfig.state_color[state]);
    Serial.print(buffer);
    Serial.println (" (BBGGRR)");
    Serial.println((uint32_t)LedConfig.state_color[state]);
  }
  Serial.println(); 
}

void setGroupState(int group, int state) {
  switch (state) {

    case 0:
      BlinkState[group] = false;
      BlinkColor[group] = CRGB::Black;
      break;

    case 1:
    case 2:
    case 3:
    case 4:
      BlinkState[group] = false;
      BlinkColor[group] = LedConfig.state_color[state];
      break;

    case 5:
    case 6:
    case 7:
    case 8:
      BlinkState[group] = true;
      BlinkColor[group] = LedConfig.state_color[state -4];
      break;

    case 9:
      BlinkState[group] = false;
      BlinkColor[group] = CRGB::White;
      break;
  }
}


void SetLEDGroupColor(int group, CRGB color) {
  int stripIndex = (group / LedConfig.numGroupsPerStrip);
  int groupIndex = group % LedConfig.numGroupsPerStrip;
  int startLEDIndex = groupIndex * (LedConfig.numLedsPerStrip / LedConfig.numGroupsPerStrip);
  int widthLED = (LedConfig.numLedsPerStrip / LedConfig.numGroupsPerStrip) - LedConfig.spacerWidth;
  fill_solid(&(leds[stripIndex][startLEDIndex]), widthLED, color);
}


void FadeAll(int StartLed=1, int EndLed=LedConfig.numLedsPerStrip) {
  for(int i = StartLed; i < EndLed; i++)
    for(int n = 0; n < LedConfig.numStrips; n++)
      leds[n][i].nscale8(200); 
}


void StartupLoop() {
  // Boot animation

  // Blue ><><
  uint8_t DELAY (LedConfig.numLedsPerStrip / 6);
  CRGB color = 0x00FF00;
  for(int i = 0; i < LedConfig.numLedsPerStrip/2; i+=1) {
    for(int n = 0; n < LedConfig.numStrips; n++) {
      leds[n][i] = color; 
      leds[n][LedConfig.numLedsPerStrip -i -1] = color;
    }
    FastLED.show();
    FadeAll(0,LedConfig.numLedsPerStrip);
    delay(DELAY);
  }
 
  // White Flash
  SetAllLEDs(CRGB::Green);
  FastLED.show();
  delay(75);
  for(int i = 0; i < 12; i++) {
    FadeAll(0,LedConfig.numLedsPerStrip);
    FastLED.show();
    delay(65);
  }
 
  // All Off
  //SetAllLEDs(CRGB::Black);
  FastLED.clear(true);
}


void SetAllLEDs(CRGB color){
  for(int n = 0; n < LedConfig.numStrips; n++)
    fill_solid(leds[n], LedConfig.numLedsPerStrip, color);
  FastLED.show();
}


void SetLEDs() {
  // Check if it's time to toggle each group's state
  if ( millis() - lastToggleTimes >= LedConfig.blinkinterval ) { 
    lastToggleTimes = millis(); // Update last toggle time
    blink = blink == 0 ? 1 : 0;
    digitalWrite(CPULED, blink);
    cpuled[0] = blink ==1 ? CRGB::Red : CRGB::Black;


    for(int i=0; i < LedConfig.numGroupsPerStrip*LedConfig.numStrips; i++){
      if (BlinkState[i] == true) {
        if (blink == true){ 
          SetLEDGroupColor(i, BlinkColor[i]);
        } else {
          SetLEDGroupColor(i, CRGB::Black);
        }
      } else {
        SetLEDGroupColor(i, BlinkColor[i]);
      }
    }
    //FastLED.show();  // Update on change only
  }
  // Update 4 times within a flashing cyclus.
  if ( millis() - lastToggleTimes >= LedConfig.blinkinterval/4) {
    FastLED.show();  // Updat on change only
  } 
  // FastLED.show(); // Update every loop, to fastfor WS2812B? 
}
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT