// GPIO LED
#define RedLEDPin 4
#define GreenLEDPin 14

// Using C++ Class + Static Blink Function 
class LED_Blinker {
  // private members
  uint8_t LEDpin;
  unsigned long delay_ms;
public:
  // public constructor
  LED_Blinker(uint8_t pin, unsigned long ms) : 
    LEDpin(pin), 
    delay_ms(ms) {}

  // static function member used in the Task Function
  static void blinkLED(void *arg) {
    LED_Blinker *myLED = (LED_Blinker *)arg;

    pinMode(myLED->LEDpin, OUTPUT);
    while (1) {
      digitalWrite(myLED->LEDpin, HIGH);
      delay(myLED->delay_ms);
      digitalWrite(myLED->LEDpin, LOW);
      delay(myLED->delay_ms);
    }
  }
};

// 2 LED behaviours - C++ Objects
LED_Blinker redLED(RedLEDPin, 500);
LED_Blinker greenLED(GreenLEDPin, 200);

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

  // One single Task Function using a C++ class pointer as parameter
  xTaskCreate(
    LED_Blinker::blinkLED // Single C++ Static Function Member Task Function
    ,  "Red LED Blinker"  // A name just for humans
    ,  2048               // The stack size
    ,  &redLED            // Task parameter - C++ Object pointer - RedLED object
    ,  2                  // Priority
    ,  NULL               // Task handle is not used here - simply pass NULL
    );
  xTaskCreate(
    LED_Blinker::blinkLED  // Single C++ Static Function Member Task Function
    ,  "Green LED Blinker" // A name just for humans
    ,  2048                // The stack size
    ,  &greenLED           // Task parameter - C++ Object pointer - GreenLED object
    ,  2                   // Priority
    ,  NULL                // Task handle is not used here - simply pass NULL
    );
}

void loop() {
  // When using Task, loop() is free for any other need.
  // Blinking the LED is done in the Task Function
  Serial.println("Looping...");
  delay(5000);
}