#include <Arduino_FreeRTOS.h>
#include <semphr.h>

#define LED_PIN 13
#define INTERRUPT_PIN 2
#define LED_DELAY_MS 3000 // 3秒間

SemaphoreHandle_t xSemaphore;

void Task1(void *pvParameters);
void Task2(void *pvParameters);
void handleInterrupt();

TaskHandle_t Task2Handle = NULL;

void setup() {
  Serial.begin(115200); // デバッグ用シリアル通信開始
  pinMode(LED_PIN, OUTPUT);
  pinMode(INTERRUPT_PIN, INPUT_PULLUP); // 外部割り込みピンを入力に設定し、内部のプルアップ抵抗を有効化する

  // 外部割り込みを設定し、立ち下がりエッジ(SWを押したタイミング)に反応するようにする
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), handleInterrupt, FALLING);

  // 2つのタスク間でバイナリセマフォンを作成する
  xSemaphore = xSemaphoreCreateBinary();

  // タスク1を作成 (優先度が高い)
  xTaskCreate(
    Task1,
    "Task1", // LEDを点灯させるタスク
    128,    // スタックサイズ
    NULL,
    2,      // 優先度
    NULL
  );

  // タスク2を作成 (優先度が低い)
  xTaskCreate(
    Task2,
    "Task2", // セマフォを返却するタスク
    128,    // スタックサイズ
    NULL,
    1,      // 優先度
    &Task2Handle
  );
}

void loop() {
  // 空のループ。処理はタスク内で実行される
}

void Task1(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    // セマフォを待ち続け、割り込みで解放されるまで停止する
    if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
      Serial.println("Task1: セマフォを取得しました LEDを3秒点灯します");
      digitalWrite(LED_PIN, HIGH); // LEDを点灯させる
      vTaskDelay(LED_DELAY_MS / portTICK_PERIOD_MS); // 指定された時間待機する
      digitalWrite(LED_PIN, LOW); // LEDを消灯させる
      Serial.println("Task1: LEDを消灯しました。セマフォ待ちに戻ります");
    }
  }
}

void Task2(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    // タスクが一時停止から再開されるのを待つ
    vTaskSuspend(NULL); // タスクを一時停止する
    Serial.println("Task2: セマフォを返却します");
    xSemaphoreGive(xSemaphore);

  }
}

// 割り込みハンドラ
void handleInterrupt() {
  // 割り込みハンドラからTask2を再開する
  Serial.println("スイッチにより割り込みハンドラが起動し、Task2を再開します。");
  xTaskResumeFromISR(Task2Handle);
}