#define MSG1_DELAY 500
#define MSG2_DELAY 250

#define SLOCKER 0  // 0 to disable Serial Lock or 1 to enable it

#define PRINT(msg)  print1by1(msg)
//#define PRINT(msg)  printCounted(msg)


xSemaphoreHandle sLock;
#if SLOCKER
#define SERIAL_LOCK()    do {} while (xSemaphoreTake(sLock, portMAX_DELAY) != pdPASS)
#define SERIAL_UNLOCK()  xSemaphoreGive(sLock)
#else
#define SERIAL_LOCK()
#define SERIAL_UNLOCK()
#endif

void print1by1(const char *str) {
  uint32_t s = strlen(str);
  SERIAL_LOCK();
  for (uint32_t i = 0; i < s; i++) {
    Serial.print(str[i]);
    delay(random(25));
  }
  Serial.println();
  SERIAL_UNLOCK();
}

void printCounted(const char *str) {
    static uint32_t counter = 0;
    char msg[256];
    sprintf(msg, "#%d [%s]", counter++, str);
    print1by1(msg);
}

void msg1Writer(void *arg) {
  (void) arg;
  while (1) {
    PRINT("TASK 1 -- 1111");
    delay(MSG1_DELAY);
  }
}

void msg2Writer(void *arg) {
  (void) arg;
  while (1) {
    PRINT("TASK 2 -- 2222");
    delay(MSG2_DELAY);
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("Printing in different times:");

  sLock = xSemaphoreCreateMutex();
  if(sLock == NULL) {
    while(1) {
      Serial.println("\n------------\nSerial Lock Failure\n------------\n");
      delay(10000);
    }
  }

  xTaskCreate(
    msg1Writer     // Specific Task Function for Message 1
    ,  "PRINT 1"   // A name just for humans
    ,  2048        // The stack size
    ,  NULL        // Task parameter - NONE
    ,  2           // Priority
    ,  NULL        // Task handle is not used here - simply pass NULL
    );

  xTaskCreate(
    msg2Writer     // Specific Task Function for Message 2
    ,  "PRINT 2"   // A name just for humans
    ,  2048        // The stack size
    ,  NULL        // Task parameter - NONE
    ,  2           // Priority
    ,  NULL        // Task handle is not used here - simply pass NULL
    );
}

void loop() {
  static unsigned long msg1Time_ms = 0;
  static unsigned long msg2Time_ms = 0;

  if (millis() > msg1Time_ms + MSG1_DELAY) {
    PRINT("Message 1 -- 1111");
    msg1Time_ms = millis();
  }

  if (millis() > msg2Time_ms + MSG2_DELAY) {
    PRINT("Message 2 -- 2222");
    msg2Time_ms = millis();
  }
}