// button_task.c #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "driver/gpio.h" #include "esp_log.h" // For ESP_LOG macros #include "button_task.h" // For start_button_monitor_task declaration #include "button_led_comm.h" // For start_button_monitor_task declaration // #include "button_led_comm.h" // Removed - no longer needed if button doesn't control LED // Include the game header to access xJumpBirdGameInputQueue #include "game/jump_bird_game.h" // Make sure this path is correct #include "game/jump_bird_game_input_queue.h" // For xJumpBirdGameInputQueue static const char *TAG = "BUTTON_TASK"; #define BUTTON_GPIO 37 /** * @brief FreeRTOS task to monitor the button state and send jump signals to the game. * * This task configures the button GPIO as an input with an internal pull-down * resistor. It continuously reads the button's state. When the button * is pressed (goes HIGH), it sends a 'true' signal to the xJumpBirdGameInputQueue, * triggering a jump action in the Jump Bird game. It specifically detects * a button press (rising edge) to ensure a single jump per press. * * @param pvParameters Not used in this task. */ static void button_monitor_task(void *pvParameters) { // --- Button Configuration --- gpio_reset_pin(BUTTON_GPIO); gpio_set_direction(BUTTON_GPIO, GPIO_MODE_INPUT); gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLDOWN_ONLY); int last_button_state = gpio_get_level(BUTTON_GPIO); // Initialize with current state int current_button_state; bool jump_signal = true; // Value to send to the queue for a jump event ESP_LOGI(TAG, "Button Monitor Task started. Monitoring GPIO %d for Jump Bird game input.", BUTTON_GPIO); while (1) { current_button_state = gpio_get_level(BUTTON_GPIO); // Detect a button press (rising edge: went from LOW to HIGH) if (current_button_state == 1 && last_button_state == 0) // Button was just pressed { ESP_LOGI(TAG, "Button PRESSED detected (rising edge)."); // --- Game Input Logic --- if (xJumpBirdGameInputQueue != NULL) { // Attempt to send the signal to the queue (non-blocking) if (xQueueSend(xJumpBirdGameInputQueue, &jump_signal, 0) != pdTRUE) { ESP_LOGW(TAG, "Failed to send jump signal to game input queue (queue full?)."); } else { ESP_LOGI(TAG, "Jump signal SENT successfully!"); } } else { ESP_LOGE(TAG, "xJumpBirdGameInputQueue is NULL! Cannot send jump signal."); } } // --- END Game Input Logic --- // --- Removed LED Control Logic --- // The original logic to send to xLedControlQueue on state change is removed. // If the LED is controlled by other means, that logic will be elsewhere. // If you need the LED to do something else (e.g., blink during game over), // that logic would go in the display_manager_task or a separate LED control task. // --- END Removed LED Control Logic --- last_button_state = current_button_state; // Update the last known state // A small delay is still recommended to prevent busy-waiting, // even without debounce logic. This allows other tasks to run. vTaskDelay(pdMS_TO_TICKS(50)); // Check button every 50ms } } /** * @brief Initializes and starts the button monitoring task. */ esp_err_t start_button_monitor_task(void) { if (xTaskCreate(button_monitor_task, "Button_Monitor_Task", configMINIMAL_STACK_SIZE * 3, NULL, 5, NULL) != pdPASS) { ESP_LOGE(TAG, "Failed to create Button Monitor task!"); return ESP_FAIL; } ESP_LOGI(TAG, "Button Monitor task created successfully!"); return ESP_OK; }