// Reminder...
// For M5Stamp C3 -> Arduino IDE -> Tools -> USB CDC On Boot: --> "Disable"
// For M5Stamp C3U -> Arduino IDE -> Tools -> USB CDC On Boot: --> "Enable"
//
// For ESP32C3 SuperMini & M5Stamp C3U (using "ESP32C3 Dev Module" board)
//    -> USB off + Left Button pressed -> USB on + Left button pressed -> Release Left button
//    -> After Upload the code, press Right button (reset) 

/* >>> ESP32C3 Stamp C3U board <<< */

/*
  
  [3]   ->  --                
  [4]   ->  RGB strip 1       
  [5]   ->  RGB strip 2         [3V3] ->  SSD1306 (3V3)
  [6]   ->  RGB strip 3         [21]  ->  UP switch
  [7]   ->  RGB strip 4         [20]  ->  OK switch
  [8]   ->  --                  [EN]  ->  --
  [10]  ->  --                  [9]   ->  DW switch
  [5V]  ->  --                  [GND] ->  --
  [GND] ->  GND COMMON          [18]  ->  RI switch
  [5V]  ->  --                  [19]  ->  LF switch
  [G1]  ->  I2C_SDA             [5V]  ->  -- 
  [G0]  ->  I2C_SCL             [GND] ->  -- 

                   [USB]

*/


// NeoPixel inicializations >>>

#include <Adafruit_NeoPixel.h>


// define Neopixel LEDs

//#define PinRGBled         2 // Internal Pin LED SK6812 for M5Stamp C3
#define PinRGBstrip1      4 // WS2812B Strip 1
#define PinRGBstrip2      5 // WS2812B Strip 2
#define PinRGBstrip3      6 // WS2812B Strip 3
#define PinRGBstrip4      7 // WS2812B Strip 4

#define NUMPIXELSstrip1   12
#define NUMPIXELSstrip2   16 // 12
#define NUMPIXELSstrip3   16 // 12
#define NUMPIXELSstrip4   16 // 12

Adafruit_NeoPixel pixelsStrip1 = Adafruit_NeoPixel(NUMPIXELSstrip1, PinRGBstrip1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixelsStrip2 = Adafruit_NeoPixel(NUMPIXELSstrip2, PinRGBstrip2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixelsStrip3 = Adafruit_NeoPixel(NUMPIXELSstrip3, PinRGBstrip3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixelsStrip4 = Adafruit_NeoPixel(NUMPIXELSstrip4, PinRGBstrip4, NEO_GRB + NEO_KHZ800);


// OLED display SSD1306 I2C inicialization >>>

#include <Wire.h>
#include <U8g2lib.h>

#define I2C_SDA   1   // 1 // 21    //I2C_SDA -> Pin 1 for ESP32C3 -> Pin 21 for ESP32 
#define I2C_SCL   0   // 0 // 22    //I2C_SCL -> Pin 0 for ESP32C3 -> Pin 22 for ESP32

  // OLED display 0.96 128x64 SSD1306 BiColor 0..14 Yellow 15..63 Blue
    // --> u8g2.setFont(u8g2_font_scrum_tr); //https://github.com/olikraus/u8g2/wiki/fntlist8  fuente muy equilibrada, la _tf tambien
    // --> u8g2.setFont(u8g2_font_bpixeldouble_tr); fuente un poco más BOLD (negrita)

//U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ SCL, /* data=*/ SDA);   // 0.91 Display
//U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);  //M0/ESP32/ESP8266/mega2560/Uno/Leonardo
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);  // 0.91 Display
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);  // 1.3 Display

#define u8g_logo_width 128
#define u8g_logo_height 64

// Bender logo
static unsigned char u8g_logo_bits[] = {
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7, 0x0f, 0xf8, 0x73, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf1, 0x1f, 0xfc, 0xc7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf1, 0x3f, 0xfe, 0xc7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf8, 0x3f, 0xfe, 0x8f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x78, 0x7c, 0x1f, 0x8f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x78, 0x7c, 0x1f, 0x8f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x78, 0x7c, 0x1e, 0x8f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf8, 0x3f, 0xfe, 0x8f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf1, 0x3f, 0xfe, 0xc7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xe1, 0x1f, 0xfc, 0xc7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe7, 0x0f, 0xf8, 0x73, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0xce, 0x39, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0xce, 0x39, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0xce, 0x39, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x63, 0xce, 0x39, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xce, 0x39, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xcc, 0x19, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};



// >> External Interruptions inicializations

  // define a structure for interruption buttons

struct ButtonISR
{
  const uint8_t PIN;
  byte bttnNumberPressed;   // Not used
  bool pressed;
};

  // define the iterruption buttons values  
ButtonISR bttnUP = {21, 0, false};  // Pin 0
ButtonISR bttnDW = {9, 0, false}; // Pin 21
ButtonISR bttnOK = {20, 0, false};  // Pin 1
ButtonISR bttnLF = {19, 0, false}; // Pin 20
ButtonISR bttnRI = {18, 0, false};  // Pin 2



// >> other variables and definitions

byte bttnNumberPressed;   // 0=No bttn pressed, 1=UP, 2=DW, 3=LF, 4=RI, 5=OK

volatile unsigned long oldtime_ISRbttn = 0;
bool flaganybttnpressed = false;

#define timePressingButton   5  // Wait 5ms pressing button


  // for Screen Menu

int MenuSTATUS = 0;     // Estado de representación de pantalla. 0 = ilde, 1 = Main, 2 = Brightness, 3 = Color, 4 = About

bool flag_MenuMAIN = false;
bool flag_MenuBrightness = false;
bool flag_MenuColor = false;
bool flag_MenuAbout = false;

int VerPosM1 = 1;   // Posición vertical del Menu1
int VerPosM2 = 1;   // Posición vertical del Menu2
int VerPosM3 = 1;   // Posición vertical del Menu3
int HorPosM1 = 1;   // Posición horizontal en el Menu1
int HorPosM2 = 1;   // Posición horizontal en el Menu2
int HorPosM3 = 1;   // Posición horizontal en el Menu3

volatile unsigned long oldtime_MENU = 0;  // variable para guardar millis en el momento de comparar con timeoutMENU
#define timeoutMENU   10000   // tiempo que esperamos en el menu sin actividad 
bool flag_timerMenu = false;   // activa / desactiva el timer del tiempo inactivo en el menu
bool flag_timeoutMENU = false;   // se activa cuando el tiempo a pasado, para dar una activación extra al refresco de la pantalla y actualizar el estatus

  // for LED strips
int LEDbrightnessVal = 50;    // Brightness (0 .. 100%), inicialmente 50% --> para mapear (0 ... 255) pero usaremos de (0 ... 200)
int LEDbrightnessStep = 10;    // contaremos los pasos de brillo de 10 en 10
int LEDcolorSelection = 1;     // Posición del selector de color

/*
#define LED_OFF (0,0,0);
#define LED_BLUE (0,0,255);
#define LED_CYAN (0,255,255);
#define LED_RED (255,0,0);
#define LED_GREEN (0,255,0);
#define LED_WHITE (255,255,255);
#define LED_ORANGE (255,165,0);
#define LED_PURPLE (255,0,255);
*/



// @@@--- INTERRUPTIONS ---@@@ //


void IRAM_ATTR ISR_UPbttn()
{
  f_detachInterrupt_ISRbttns();
  flaganybttnpressed = true;
  oldtime_ISRbttn = millis();
  
  bttnNumberPressed = 1;
}

void IRAM_ATTR ISR_DWbttn()
{
  f_detachInterrupt_ISRbttns();
  flaganybttnpressed = true;
  oldtime_ISRbttn = millis();

  bttnNumberPressed = 2;
}

void IRAM_ATTR ISR_OKbttn()
{
  f_detachInterrupt_ISRbttns();
  flaganybttnpressed = true;
  oldtime_ISRbttn = millis();

  bttnNumberPressed = 5;
}

void IRAM_ATTR ISR_LFbttn()
{
  f_detachInterrupt_ISRbttns();
  flaganybttnpressed = true;
  oldtime_ISRbttn = millis();

  bttnNumberPressed = 3;
}

void IRAM_ATTR ISR_RIbttn()
{
  f_detachInterrupt_ISRbttns();
  flaganybttnpressed = true;
  oldtime_ISRbttn = millis();

  bttnNumberPressed = 4;
}



// @@@--- SETUP ---@@@ //


void setup()
{
  Serial.begin(115200);

  setupSSD1306();

  setup_Neopixel();

  setup_ISRbttns();
}


  void setupSSD1306()
  {
    Wire.setPins(I2C_SDA, I2C_SCL);
    Wire.begin();
    u8g2.begin();
      
    draw_welcome_display();
  }

    void draw_welcome_display()
    {
      u8g2.firstPage();
      do {

        u8g2.drawXBM( 0, 0, u8g_logo_width, u8g_logo_height, u8g_logo_bits);
      
      } while (u8g2.nextPage());

      delay(4000);

      u8g2.firstPage();
      do {
        u8g2.setFont(u8g2_font_scrum_tr);
        u8g2.drawStr(0,14,"ADN electronics");
        u8g2.setFont(u8g2_font_profont15_tr); //https://github.com/olikraus/u8g2/wiki/fntlist8
        u8g2.drawStr(4,40,"ESP32C3");
        u8g2.drawStr(6,60,"U8g2-SSD1306");
      } while (u8g2.nextPage());

      delay(4000);

      u8g2.clear();
    }
       

  void setup_Neopixel()
  {
    pixelsStrip1.begin(); // Inicializamos la librería Neopixel
    pixelsStrip2.begin(); // Inicializamos la librería Neopixel
    pixelsStrip3.begin(); // Inicializamos la librería Neopixel
    pixelsStrip4.begin(); // Inicializamos la librería Neopixel

    pixelsStrip1.setBrightness(200); // Fijamos un nivel de brillo (0 .. 255) moderado al inicio.
    pixelsStrip2.setBrightness(200); // Fijamos un nivel de brillo (0 .. 255) moderado al inicio.
    pixelsStrip3.setBrightness(200); // Fijamos un nivel de brillo (0 .. 255) moderado al inicio.
    pixelsStrip4.setBrightness(200); // Fijamos un nivel de brillo (0 .. 255) moderado al inicio.

    s_Neopixel_start_sequence1();   // Welcome sequence (enumeramos la tiras de leds)
    //s_Neopixel_start_sequence2();   // Welcome sequence (animación para testear todos los LEDs)

    flag_timeoutMENU = true;    // para que aparezca la primera vez el mensaje principal
  }

    void s_Neopixel_start_sequence1()
    {
      for (int i=0; i<4; i++)
      {  
        if (i<1)
        {
          pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(0,0,255));   // Ponemos el LED en color AZUL para comprobar que funciona correctamente
        }
        if (i<2)
        {          
          pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(255,0,0));   // Ponemos el LED en color ROJO para comprobar que funciona correctamente
        }
        if (i<3)
        {          
          pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(0,255,0));   // Ponemos el LED en color VERDE para comprobar que funciona correctamente
        }
        if (i<4)
        {          
          pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(255,255,255));   // Ponemos el LED en color BLANCO para comprobar que funciona correctamente
        }
        pixelsStrip1.show();
        pixelsStrip2.show();
        pixelsStrip3.show();
        pixelsStrip4.show();

        delay(250);
      }

      delay (3000);

      //for (int i=3; i>=0; i--)
      for (int i=0; i<4; i++)
      {  
        if (i<1)
        {
          pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(0,0,0));   // Ponemos el LED en color APAGADO
        }
        if (i<2)
        {          
          pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(0,0,0));   // Ponemos el LED en color APAGADO
        }
        if (i<3)
        {          
          pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(0,0,0));   // Ponemos el LED en color APAGADO
        }
        if (i<4)
        {          
          pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(0,0,0));   // Ponemos el LED en color APAGADO
        }
        pixelsStrip1.show();
        pixelsStrip2.show();
        pixelsStrip3.show();
        pixelsStrip4.show();

        delay(250);
      }

      delay (3000);
    }
    
    void s_Neopixel_start_sequence2()
    {
      for (int i=0; i<16; i++)
      {
        if (i<12)
        {
          pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(0,0,255));
        }
        pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(0,0,255));
        pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(0,0,255));
        pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(0,0,255));           
        pixelsStrip1.show();
        pixelsStrip2.show();
        pixelsStrip3.show();
        pixelsStrip4.show();

        delay(100);
      }

      delay(3000);

      //for (int i=15; i>=0; i--)
      for (int i=0; i<16; i++)
      {
        if (i<12)
        {
          pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(0,0,0));
        }
        pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(0,0,0));
        pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(0,0,0));
        pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(0,0,0));           
        pixelsStrip1.show();
        pixelsStrip2.show();
        pixelsStrip3.show();
        pixelsStrip4.show();
        
        delay(100);
      }

      delay (3000);
    }


  void setup_ISRbttns()
  {
    //pinMode(LED, OUTPUT);
    
    pinMode(bttnUP.PIN, INPUT_PULLUP);   // PULLUP --> Switch Pin to GND  // PULLDOWN --> Switch Pin to 5V or 3V3 
    pinMode(bttnDW.PIN, INPUT_PULLUP);   // PULLUP --> Switch Pin to GND  // PULLDOWN --> Switch Pin to 5V or 3V3
    pinMode(bttnOK.PIN, INPUT_PULLUP);   // PULLUP --> Switch Pin to GND  // PULLDOWN --> Switch Pin to 5V or 3V3
    pinMode(bttnLF.PIN, INPUT_PULLUP);   // PULLUP --> Switch Pin to GND  // PULLDOWN --> Switch Pin to 5V or 3V3
    pinMode(bttnRI.PIN, INPUT_PULLUP);   // PULLUP --> Switch Pin to GND  // PULLDOWN --> Switch Pin to 5V or 3V3

    f_attachInterrupt_ISRbttns();
  }


    void f_attachInterrupt_ISRbttns() // atach all ISRs
    {
      attachInterrupt(digitalPinToInterrupt(bttnUP.PIN), ISR_UPbttn, HIGH);  //LOW, HIGH, CHANGE, FALLING, RISING
      attachInterrupt(digitalPinToInterrupt(bttnDW.PIN), ISR_DWbttn, HIGH);  //LOW, HIGH, CHANGE, FALLING, RISING
      attachInterrupt(digitalPinToInterrupt(bttnOK.PIN), ISR_OKbttn, HIGH);  //LOW, HIGH, CHANGE, FALLING, RISING
      attachInterrupt(digitalPinToInterrupt(bttnLF.PIN), ISR_LFbttn, HIGH);  //LOW, HIGH, CHANGE, FALLING, RISING
      attachInterrupt(digitalPinToInterrupt(bttnRI.PIN), ISR_RIbttn, HIGH);  //LOW, HIGH, CHANGE, FALLING, RISING      
    }

    void f_detachInterrupt_ISRbttns() // detach all ISRs 
    {
      detachInterrupt(digitalPinToInterrupt(bttnUP.PIN));
      detachInterrupt(digitalPinToInterrupt(bttnDW.PIN));
      detachInterrupt(digitalPinToInterrupt(bttnOK.PIN));
      detachInterrupt(digitalPinToInterrupt(bttnLF.PIN));
      detachInterrupt(digitalPinToInterrupt(bttnRI.PIN));      
    }



// @@@--- MAIN PROGRAM ---@@@ //


void loop()
{
  if(flaganybttnpressed == true || flag_timeoutMENU == true)
  {
    f_evaluateISRbttn();

    f_updatebttnstatus();
  }

  if (flag_timerMenu == true)
  {
    if(timeoutMENU < (millis()-oldtime_MENU))
    {
      MenuSTATUS = 0;
      flag_timerMenu = false;
      flag_timeoutMENU = true;
      VerPosM1 = 1;   // Inicilizamos la posición vertical del Menu 1
    }
  }
  
}


  void f_evaluateISRbttn()
  {
    if(millis()-oldtime_ISRbttn > timePressingButton)
    {
      if(digitalRead(bttnUP.PIN)==LOW)
      {
        bttnUP.pressed = true;
        bttnNumberPressed = 1;
        flaganybttnpressed = false;
      }

      if(digitalRead(bttnDW.PIN)==LOW)
      {
        bttnDW.pressed = true;
        bttnNumberPressed = 2;
        flaganybttnpressed = false;
      }

      if(digitalRead(bttnOK.PIN)==LOW)
      {
        bttnOK.pressed = true;
        bttnNumberPressed = 5;
        flaganybttnpressed = false;
      }

      if(digitalRead(bttnLF.PIN)==LOW)
      {
        bttnLF.pressed = true;
        bttnNumberPressed = 3;
        flaganybttnpressed = false;
      }

      if(digitalRead(bttnRI.PIN)==LOW)
      {
        bttnRI.pressed = true;
        bttnNumberPressed = 4;
        flaganybttnpressed = false;
      }

      // Restrablecemos los flags de los pulsadores en la función "void f_updatebttnstatus()"
      //bttnUP.pressed = false;
      //bttnDW.pressed = false;
      //bttnOK.pressed = false;
      //bttnLF.pressed = false;
      //bttnRI.pressed = false;

      // Restrablecemos las interrupciones en la función "void f_updatebttnstatus()"
      //f_attachInterrupt_ISRbttns();
    }
  }


  void f_updatebttnstatus()
  {
    if (bttnUP.pressed || bttnDW.pressed || bttnOK.pressed || bttnLF.pressed || bttnRI.pressed || flag_timeoutMENU)
    {  
      flag_timeoutMENU = false;   // sólo queremos que entre 1 vez por timeout

      ff_StatusMachine();
      
      ff_ScreenRefresh();

      ff_LEDstripRefresh();

      // restablecemos los flags de las interrupciones
      bttnUP.pressed = false;
      bttnDW.pressed = false;
      bttnOK.pressed = false;
      bttnLF.pressed = false;
      bttnRI.pressed = false;

      f_attachInterrupt_ISRbttns();
    }
  }


    void ff_StatusMachine()
    {
      switch (MenuSTATUS)   // 0 = ilde, 1 = Main, 2 = Brightness, 3 = Color, 4 = About
      {
        case 0:   // ilde

            if (bttnOK.pressed == true)   // OK bttn
            {
              MenuSTATUS = 1;
              
              oldtime_MENU = millis();    // Capturamos el tiempo para empezar a contar el tiempo de timeout
              flag_timerMenu = true;    // activamos el temporizador
            }

          break;

        case 1:   // Main

            if (bttnOK.pressed == true)   // OK bttn
            {
              oldtime_MENU = millis();    // Volvemos a capturar el tiempo para empezar a contar el tiempo de timeout

              if (VerPosM1 == 1)  { MenuSTATUS = 2; }  // Brightness
              if (VerPosM1 == 2)  { MenuSTATUS = 3; }  // Color
              if (VerPosM1 == 3)  { MenuSTATUS = 4; }  // About
            }

            if (bttnUP.pressed == true)   // UP bttn
            {
              oldtime_MENU = millis();    // Volvemos a capturar el tiempo para empezar a contar el tiempo de timeout

              if(VerPosM1 > 1)  { VerPosM1--; }  // Si no estamos en la primera opción sube un menu
            }              

            if (bttnDW.pressed == true)   // DW bttn
            {
              oldtime_MENU = millis();    // Volvemos a capturar el tiempo para empezar a contar el tiempo de timeout

              if(VerPosM1 < 3)  { VerPosM1++; }  // Si no estamos en la tercera opción baja un menu
            }

          break;

        case 2:   // Brightness

            if (bttnOK.pressed == true)   // OK bttn
            {
              MenuSTATUS = 1;
            }

            if (bttnLF.pressed == true)   // LF bttn
            {
              oldtime_MENU = millis();    // Volvemos a capturar el tiempo para empezar a contar el tiempo de timeout

              if(LEDbrightnessVal > 0)  { LEDbrightnessVal = LEDbrightnessVal - LEDbrightnessStep; }  // Si no estamos en la Brightness = 0 disminuimos el valor de LEDbrightnessStep
            }              

            if (bttnRI.pressed == true)   // RI bttn
            {
              oldtime_MENU = millis();    // Volvemos a capturar el tiempo para empezar a contar el tiempo de timeout

              if(LEDbrightnessVal < 100)  { LEDbrightnessVal = LEDbrightnessVal + LEDbrightnessStep; }  // Si no estamos en la Brightness = 100 aumentamos el valor de LEDbrightnessStep
            }

          break;

        case 3:   // Color

            if (bttnOK.pressed == true)   // OK bttn
            {
              MenuSTATUS = 1;
            }

            if (bttnLF.pressed == true)   // LF bttn
            {
              oldtime_MENU = millis();    // Volvemos a capturar el tiempo para empezar a contar el tiempo de timeout

              if(LEDcolorSelection> 1)  { LEDcolorSelection--; }  // Si no estamos en la primera opción sube un menu
            }              

            if (bttnRI.pressed == true)   // RI bttn
            {
              oldtime_MENU = millis();    // Volvemos a capturar el tiempo para empezar a contar el tiempo de timeout

              if(LEDcolorSelection < 8)  { LEDcolorSelection++; }  // Si no estamos en la tercera opción baja un menu
            }

          break;
        
        case 4:   // About

            if (bttnOK.pressed == true)   // OK bttn
            {
              MenuSTATUS = 1;
            }            

          break;

        default:
          break;       
      } 
/*
      if (flag_timerMenu == true)
      {
        if(timeoutMENU < (millis()-oldtime_MENU))
        {
          MenuSTATUS = 0;
          flag_timerMenu = false;
          flag_timeoutMENU = true;
          VerPosM1 = 1;
        }
      }
*/
    }


    void ff_ScreenRefresh()
    {
      switch (MenuSTATUS)
      {
        case 0:

            u8g2.firstPage();
            do {
              u8g2.setFont(u8g2_font_helvR10_tr);   //u8g2.setFont(u8g2_font_helvR08_tr);
              u8g2.drawStr(6,20,"PRUSA LIGHTING ");
              u8g2.setFont(u8g2_font_helvR08_tr);   //u8g2.setFont(u8g2_font_helvR10_tr);
              u8g2.drawStr(24,38,"Press OK button");
              u8g2.drawStr(28,56,"to enter MENU");

            } while (u8g2.nextPage());  

          break;

        case 1:

            u8g2.firstPage();
            do {
              u8g2.setFont(u8g2_font_helvR10_tr);   //u8g2.setFont(u8g2_font_helvR08_tr);

              if (VerPosM1==1) {u8g2.drawButtonUTF8(64, 15, U8G2_BTN_INV|U8G2_BTN_HCENTER|U8G2_BTN_BW1, 0,  6,  1, "Brightness" );}
              else {u8g2.drawButtonUTF8(64, 15, U8G2_BTN_HCENTER, 0,  6,  1, "Brightness" );}

              if (VerPosM1==2) {u8g2.drawButtonUTF8(64, 35, U8G2_BTN_INV|U8G2_BTN_HCENTER|U8G2_BTN_BW1, 0,  6,  1, "Color" );}
              else {u8g2.drawButtonUTF8(64, 35, U8G2_BTN_HCENTER, 0,  6,  1, "Color" );}

              if (VerPosM1==3) {u8g2.drawButtonUTF8(64, 55, U8G2_BTN_INV|U8G2_BTN_HCENTER|U8G2_BTN_BW1, 0,  6,  1, "About" );}
              else {u8g2.drawButtonUTF8(64, 55, U8G2_BTN_HCENTER, 0,  6,  1, "About" );}

            } while (u8g2.nextPage());

          break;

        case 2:

            u8g2.firstPage();
            do {
              u8g2.setFont(u8g2_font_helvR10_tr);   //u8g2.setFont(u8g2_font_helvR08_tr);
              u8g2.drawButtonUTF8(64, 15, U8G2_BTN_HCENTER, 0,  6,  1, "Brightness" );

              u8g2.drawFrame(14, 26, 100, 20);
              u8g2.drawBox(14, 26, LEDbrightnessVal, 20);

              u8g2.setFont(u8g2_font_helvR08_tr);   //u8g2.setFont(u8g2_font_helvR10_tr);
              u8g2.drawStr(22,62,"set value:  ");
              u8g2.setFont(u8g2_font_helvR10_tr);   //u8g2.setFont(u8g2_font_helvR08_tr);
              u8g2.setCursor(72,62);
              u8g2.print(LEDbrightnessVal);   //u8g2.print(LEDbrightnessVal,1); // El 1 es para definir el redondeo a 1 decimal
              u8g2.setFont(u8g2_font_helvR08_tr);   //u8g2.setFont(u8g2_font_helvR10_tr);
              u8g2.drawStr(96,62,"%");

            } while (u8g2.nextPage());

          break;

        case 3:

            u8g2.firstPage();
            do {
              u8g2.setFont(u8g2_font_helvR10_tr);   //u8g2.setFont(u8g2_font_helvR08_tr);
              u8g2.drawButtonUTF8(64, 15, U8G2_BTN_HCENTER, 0,  6,  1, "Color" );

              u8g2.setFont(u8g2_font_helvR08_tr);   //u8g2.setFont(u8g2_font_helvR10_tr);

              if (LEDcolorSelection==1) {u8g2.drawButtonUTF8(4, 34, U8G2_BTN_INV|U8G2_BTN_BW1, 28,  1,  4, "   B" );}
              else {u8g2.drawButtonUTF8(4, 34, U8G2_BTN_BW1, 28,  1,  4, "   B" );}

              if (LEDcolorSelection==2) {u8g2.drawButtonUTF8(34, 34, U8G2_BTN_INV|U8G2_BTN_BW1, 28,  1,  4, "   R" );}
              else {u8g2.drawButtonUTF8(34, 34, U8G2_BTN_BW1, 28,  1,  4, "   R" );}

              if (LEDcolorSelection==3) {u8g2.drawButtonUTF8(64, 34, U8G2_BTN_INV|U8G2_BTN_BW1, 28,  1,  4, "   G" );}
              else {u8g2.drawButtonUTF8(64, 34, U8G2_BTN_BW1, 28,  1,  4, "   G" );}

              if (LEDcolorSelection==4) {u8g2.drawButtonUTF8(94, 34, U8G2_BTN_INV|U8G2_BTN_BW1, 28,  1,  4, "   W" );}
              else {u8g2.drawButtonUTF8(94, 34, U8G2_BTN_BW1, 28,  1,  4, "   W" );}              

              if (LEDcolorSelection==5) {u8g2.drawButtonUTF8(4, 56, U8G2_BTN_INV|U8G2_BTN_BW1, 28,  1,  4, " OFF" );}
              else {u8g2.drawButtonUTF8(4, 56, U8G2_BTN_BW1, 28,  1,  4, " OFF" );}

              if (LEDcolorSelection==6) {u8g2.drawButtonUTF8(34, 56, U8G2_BTN_INV|U8G2_BTN_BW1, 28,  1,  4, "  M1" );}
              else {u8g2.drawButtonUTF8(34, 56, U8G2_BTN_BW1, 28,  1,  4, "  M1" );}

              if (LEDcolorSelection==7) {u8g2.drawButtonUTF8(64, 56, U8G2_BTN_INV|U8G2_BTN_BW1, 28,  1,  4, "  M2" );}
              else {u8g2.drawButtonUTF8(64, 56, U8G2_BTN_BW1, 28,  1,  4, "  M2" );}

              if (LEDcolorSelection==8) {u8g2.drawButtonUTF8(94, 56, U8G2_BTN_INV|U8G2_BTN_BW1, 28,  1,  4, "  M3" );}
              else {u8g2.drawButtonUTF8(94, 56, U8G2_BTN_BW1, 28,  1,  4, "  M3" );}

            } while (u8g2.nextPage());

          break;

        case 4:

            u8g2.firstPage();
            do {
              u8g2.setFont(u8g2_font_helvR08_tr);   //u8g2.setFont(u8g2_font_helvR10_tr);
              u8g2.drawStr(4,14,"[ V1.0  November 2023 ]");
              u8g2.drawStr(4,28," > SSD1306 (u8g2)");
              u8g2.drawStr(4,42," > ISR 5pos Navi button");
              u8g2.drawStr(4,56," > WS2812B (Neopixel)");

            } while (u8g2.nextPage());      

          break;
      }
    }


    void ff_LEDstripRefresh()
    {
      // Fijamos la intesidad seleccionada para los LEDs

      int LEDbrightnessValMapped = map(LEDbrightnessVal, 0, 100, 0, 200);    // map(value, fromLow, fromHigh, toLow, toHigh) 
      
      pixelsStrip1.setBrightness(LEDbrightnessValMapped);
      pixelsStrip2.setBrightness(LEDbrightnessValMapped);
      pixelsStrip3.setBrightness(LEDbrightnessValMapped);
      pixelsStrip4.setBrightness(LEDbrightnessValMapped);   

      // Fijamos el color seleccionado para los LEDs

      switch (LEDcolorSelection)
      {
        case 1:     // BLUE (0,0,255)

            for (int i=0; i<16; i++)
            {
              if (i<12)
              {
                pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(0,0,255));
              }
              pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(0,0,255));
              pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(0,0,255));
              pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(0,0,255));           
              pixelsStrip1.show();
              pixelsStrip2.show();
              pixelsStrip3.show();
              pixelsStrip4.show();
            }

          break;

        case 2:     // RED  (255,0,0)

            for (int i=0; i<16; i++)
            {
              if (i<12)
              {
                pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(255,0,0));
              }
              pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(255,0,0));
              pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(255,0,0));
              pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(255,0,0));           
              pixelsStrip1.show();
              pixelsStrip2.show();
              pixelsStrip3.show();
              pixelsStrip4.show();
            }

          break;

        case 3:     // GREEN  (0,255,0)

            for (int i=0; i<16; i++)
            {
              if (i<12)
              {
                pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(0,255,0));
              }
              pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(0,255,0));
              pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(0,255,0));
              pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(0,255,0));           
              pixelsStrip1.show();
              pixelsStrip2.show();
              pixelsStrip3.show();
              pixelsStrip4.show();
            }

          break;

        case 4:     // WHITE (255,255,255)

            for (int i=0; i<16; i++)
            {
              if (i<12)
              {
                pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(255,255,255));
              }
              pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(255,255,255));
              pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(255,255,255));
              pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(255,255,255));           
              pixelsStrip1.show();
              pixelsStrip2.show();
              pixelsStrip3.show();
              pixelsStrip4.show();
            }

          break;

        case 5:     // OFF (0,0,0)    

            for (int i=0; i<16; i++)
            {
              if (i<12)
              {
                pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(0,0,0));
              }
              pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(0,0,0));
              pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(0,0,0));
              pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(0,0,0));           
              pixelsStrip1.show();
              pixelsStrip2.show();
              pixelsStrip3.show();
              pixelsStrip4.show();
            }

          break;

        case 6:     // M1 (CYAN (0,255,255))

            for (int i=0; i<16; i++)
            {
              if (i<12)
              {
                pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(0,255,255));
              }
              pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(0,255,255));
              pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(0,255,255));
              pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(0,255,255));           
              pixelsStrip1.show();
              pixelsStrip2.show();
              pixelsStrip3.show();
              pixelsStrip4.show();
            }

          break;

        case 7:     // M2 (ORANGE (255,165,0))

            for (int i=0; i<16; i++)
            {
              if (i<12)
              {
                pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(255,165,0));
              }
              pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(255,165,0));
              pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(255,165,0));
              pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(255,165,0));           
              pixelsStrip1.show();
              pixelsStrip2.show();
              pixelsStrip3.show();
              pixelsStrip4.show();
            }

          break;

        case 8:     // M3 (PURPLE (255,0,255))

            for (int i=0; i<16; i++)
            {
              if (i<12)
              {
                pixelsStrip1.setPixelColor(i, pixelsStrip1.Color(255,0,255));
              }
              pixelsStrip2.setPixelColor(i, pixelsStrip2.Color(255,0,255));
              pixelsStrip3.setPixelColor(i, pixelsStrip3.Color(255,0,255));
              pixelsStrip4.setPixelColor(i, pixelsStrip4.Color(255,0,255));           
              pixelsStrip1.show();
              pixelsStrip2.show();
              pixelsStrip3.show();
              pixelsStrip4.show();
            }

          break;                  

      }
    }