// (C)  JDN 20260324 vrs 0.1234

#include "Arduino.h"
#include "esp_task_wdt.h"
#include "esp_task.h"
//#include "task.h"

// https://forum.arduino.cc/t/esp32-c3-watch-dog-timer-wdt/1308760/4

void testTask1(void* parms);



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

  vTaskDelay(200);
  Serial.println("Starting");

  esp_task_wdt_config_t twdt_config = {
    .timeout_ms = 10000,
    .idle_core_mask = (1 << configNUM_CORES) - 1,  // Bitmask of all cores,
    .trigger_panic = true,
  };

  ESP_ERROR_CHECK(esp_task_wdt_reconfigure(&twdt_config));

  xTaskCreatePinnedToCore(testTask1, "core0", 2000, (void *)1, 5, NULL, 0);
  xTaskCreatePinnedToCore(testTask1, "core1", 2000, (void *)2, 5, NULL, 1);
  xTaskCreatePinnedToCore(testTask1, "ardCore", 2000, (void *)3, 5, NULL, ARDUINO_RUNNING_CORE);
  xTaskCreate(testTask1, "noCore", 2000, (void *)5, 4,NULL);

  {
    TaskStatus_t pxTaskStatusArray[20];
    unsigned long tTime;
    char pcWriteBuffer[200];

    UBaseType_t t = uxTaskGetSystemState(pxTaskStatusArray, 20, &tTime);

    Serial.print("configMAX_PRIORITIES: ");
    Serial.println(configMAX_PRIORITIES);


    Serial.print("ARDUINO_RUNNING_CORE ");
    Serial.println(ARDUINO_RUNNING_CORE);



    Serial.print(t);
    Serial.println(" tasks");

    Serial.println("nr  aff core Prio name");

    // dump all tasks
    for (int i = 0; i < t; i++) {
      int vv;

      // 1
      vv = pxTaskStatusArray[i].xTaskNumber;
      if (vv < 10)
        Serial.print(" ");
      Serial.print(vv, DEC);
      Serial.print(" - ");

      // https://www.freertos.org/Documentation/02-Kernel/02-Kernel-features/13-Symmetric-multiprocessing-introduction#vtaskcoreaffinityget
      // JDN: der er noget rod omkring "arduino/esp" port af freertos især omkring affinity

      //     vv = xTaskCoreAffinityGet(pxTaskStatusArray[i].xHandle);
      vv = xTaskGetAffinity(pxTaskStatusArray[i].xHandle);

      // 2

      Serial.print(vv, BIN);

      Serial.print(" - ");

      vv = xTaskGetCoreID(pxTaskStatusArray[i].xHandle);

      Serial.print(vv, BIN);
      Serial.print(" - ");


      vv = pxTaskStatusArray[i].uxCurrentPriority;
      if (vv < 10)
        Serial.print(" ");

      Serial.print(pxTaskStatusArray[i].uxCurrentPriority, DEC);
      Serial.print(" - ");

      Serial.print(pxTaskStatusArray[i].pcTaskName);


      Serial.println();
    }
    Serial.println("done");

    vTaskDelay(100000);
  }

  disableLoopWDT();
}

void loop() {
  vTaskDelete(NULL);
}

void testTask1(void* parms) {
  int64_t prevMicros = esp_timer_get_time();
  const int64_t watchDogResetTime = 2000000;
  bool resetWdt = true;
  int pp;


  pp = (int)parms;

  // ESP_ERROR_CHECK(esp_task_wdt_add(NULL));
  // ½ ESP_ERROR_CHECK(esp_task_wdt_status(NULL));
  vTaskDelay(2000);
  for (;;) {
    int64_t currentMicros = esp_timer_get_time();
    Serial.print("(");
    Serial.print(pp);
    Serial.println(")");
    continue;
    if ((resetWdt) && (currentMicros - prevMicros > watchDogResetTime)) {
      prevMicros = currentMicros;
      Serial.println("Resetting Watchdog");
      esp_task_wdt_reset();
    }

    if (Serial.read() == 's') {
      Serial.println("Halting Watch Dog Resets");
      resetWdt = false;
    }

    // vTaskDelay(100);  // Allow Idle Task to run and reset its watch dog
  }
}

#ifdef NEVER

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


  typedef struct xTASK_STATUS {
  /* The handle of the task to which the rest of the information in the
      structure relates. */
  TaskHandle_t xHandle;

  /* A pointer to the task's name. This value will be invalid if the task was
      deleted since the structure was populated! */
  const char* pcTaskName;

  /* A number unique to the task. */
  UBaseType_t xTaskNumber;

  /* The state in which the task existed when the structure was populated. */
  eTaskState eCurrentState;

  /* The priority at which the task was running (may be inherited) when the
      structure was populated. */
  UBaseType_t uxCurrentPriority;

  /* The priority to which the task will return if the task's current priority
      has been inherited to avoid unbounded priority inversion when obtaining a
      mutex. Only valid if configUSE_MUTEXES is defined as 1 in
      FreeRTOSConfig.h. */
  UBaseType_t uxBasePriority;

  /* The total run time allocated to the task so far, as defined by the run time stats clock. 
      Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
  unsigned long ulRunTimeCounter;

  /* Points to the lowest address of the task's stack area. */
  StackType_t* pxStackBase;

#if (configRECORD_STACK_HIGH_ADDRESS == 1)
  /* Points to the top address of the task's stack area. */
  StackType_t* pxTopOfStack;

  /* Points to the bottom address of the task's stack area. */
  StackType_t* pxEndOfStack;
#endif

  /* The minimum amount of stack space that has remained for the task since
      the task was created. The closer this value is to zero the closer the task
      has come to overflowing its stack. */
  configSTACK_DEPTH_TYPE usStackHighWaterMark;
} TaskStatus_t;

#endif

#ifdef NEVER
/* 
  xTaskCreatePinnedToCore(testTask1, "core0", 2000, (void *)1, 5, NULL, 0);
  xTaskCreatePinnedToCore(testTask1, "core1", 2000, (void *)2, 5, NULL, 1);
  xTaskCreatePinnedToCore(testTask1, "ardCore", 2000, (void *)3, 5, NULL, ARDUINO_RUNNING_CORE);
  xTaskCreate(testTask1, "noCore", 2000, (void *)5, 4,NULL);

Starting
configMAX_PRIORITIES: 25
ARDUINO_RUNNING_CORE 1
11 tasks
nr  aff core Prio name
 8 - 1 - 1 -  1 - loopTask
 5 - 0 - 0 -  0 - IDLE0
 6 - 1 - 1 -  0 - IDLE1
11 - 1 - 1 -  5 - core1
12 - 1 - 1 -  5 - ardCore
13 - 1111111111111111111111111111111 - 1111111111111111111111111111111 -  4 - noCore
10 - 0 - 0 -  5 - core0
 3 - 0 - 0 - 22 - esp_timer
 7 - 1111111111111111111111111111111 - 1111111111111111111111111111111 -  1 - Tmr Svc
 2 - 1 - 1 - 24 - ipc1
 1 - 0 - 0 - 24 - ipc0
done

*/
#endif