Newer
Older
ESP32-RetroPlay / main / tasks / button_task.c
// 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;
}