#define MSG1_DELAY 500
#define MSG2_DELAY 250

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


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

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:");

  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();
  }
}