#define LED_PIN 4  // GPIO pin connected to the LED       // GPIO pin connected to the LED
#define BUTTON_PIN 16      // GPIO pin connected to the button

SemaphoreHandle_t xSemaphore = NULL;

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

  // Initialize LED pin
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  // Initialize button pin
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  // Create a binary semaphore
  xSemaphore = xSemaphoreCreateBinary();
  if (xSemaphore == NULL) {
    Serial.println("Failed to create semaphore");
    while (1);
  }

  // Create FreeRTOS tasks
  xTaskCreatePinnedToCore(buttonTask, "Button Task", 1024, NULL, 1, NULL, 0);
  xTaskCreatePinnedToCore(ledTask, "LED Task", 1024, NULL, 1, NULL, 1);
}

void loop() {
  // Nothing to do here, everything is handled by tasks
}

void buttonTask(void *pvParameters) {
  while (true) {
    // Check if the button is pressed
    if (digitalRead(BUTTON_PIN) == LOW) {
      // Debounce delay
      vTaskDelay(50 / portTICK_PERIOD_MS);
      if (digitalRead(BUTTON_PIN) == LOW) {
        // Give the semaphore
        xSemaphoreGive(xSemaphore);
        Serial.println("Semaphore given by button press");

        // Wait for the button to be released
        while (digitalRead(BUTTON_PIN) == LOW) {
          vTaskDelay(10 / portTICK_PERIOD_MS);
        }
      }
    }
    vTaskDelay(10 / portTICK_PERIOD_MS);  // Short delay to debounce
  }
}

void ledTask(void *pvParameters) {
  while (true) {
    // Wait for the semaphore to be given
    if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
      // Toggle LED
      digitalWrite(LED_PIN, !digitalRead(LED_PIN));
      Serial.println("Semaphore taken by LED task - LED toggled");
      // Short delay to visualize the LED toggle
      vTaskDelay(500 / portTICK_PERIOD_MS);
    }
  }
}