#include <stdio.h> #include <inttypes.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" // Needed for xQueueCreate #include "esp_chip_info.h" #include "esp_flash.h" #include "esp_system.h" #include "esp_log.h" // For ESP_LOG macros // Include our modular task headers #include "tasks/button_led_comm.h" // Keep this for LED queue #include "tasks/button_task.h" // Now expects a game input queue handle #include "tasks/led_task.h" // Keep this for LED task #include "tasks/display_task.h" // Generic display task #include "tasks/game/jump_bird_game.h" // Specific game instance header (to get JumpBirdGame) // #include "tasks/game/jump_bird_game_input_queue.h" // No longer directly included in main.c static const char *TAG_MAIN = "APP_MAIN"; // The game input queue is now managed internally by the game module. // No longer globally defined here. // QueueHandle_t xJumpBirdGameInputQueue; // Define the global LED control queue here (its definition) QueueHandle_t xLedControlQueue; // Keep this definition /** * @brief Prints detailed information about the ESP chip and flash. */ static void print_chip_info(void) { esp_chip_info_t chip_info; uint32_t flash_size; esp_chip_info(&chip_info); printf("This is %s chip with %d CPU core(s), ", CONFIG_IDF_TARGET, chip_info.cores); if (chip_info.features & CHIP_FEATURE_WIFI_BGN) { printf("WiFi/"); } if (chip_info.features & CHIP_FEATURE_BT) { printf("BT"); } if (chip_info.features & CHIP_FEATURE_BLE) { printf("BLE"); } if (chip_info.features & CHIP_FEATURE_IEEE802154) { printf(", 802.15.4 (Zigbee/Thread)"); } printf(", "); unsigned major_rev = chip_info.revision / 100; unsigned minor_rev = chip_info.revision % 100; printf("silicon revision v%d.%d, ", major_rev, minor_rev); if (esp_flash_get_size(NULL, &flash_size) != ESP_OK) { printf("Get flash size failed\n"); return; } printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024), (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size()); } /** * @brief Main application entry point. * Initializes the system, prints chip information, and starts the necessary tasks. */ void app_main(void) { print_chip_info(); ESP_LOGI(TAG_MAIN, "Minimum free heap size: %" PRIu32 " bytes", esp_get_minimum_free_heap_size()); // --- 1. The game input queue is now initialized and managed by the game itself. --- // We will initialize the game first to ensure its input queue is ready. // This call will also initialize the internal queue for JumpBirdGame. if (JumpBirdGame.init_game == NULL) { ESP_LOGE(TAG_MAIN, "JumpBirdGame.init_game is NULL! Halting."); while(1) { vTaskDelay(100); } } JumpBirdGame.init_game(); // Initialize the game state and its internal queue ESP_LOGI(TAG_MAIN, "JumpBirdGame initialized, including its input queue."); // --- 2. Create the LED control queue --- xLedControlQueue = xQueueCreate(1, sizeof(bool)); if (xLedControlQueue == NULL) { ESP_LOGE(TAG_MAIN, "Failed to create LED control queue! Halting."); // No game queue to delete here as it's managed internally by the game while (1) { vTaskDelay(100); // Fatal error, halt } } ESP_LOGI(TAG_MAIN, "LED control queue created successfully."); // --- 3. Initialize and start the display task --- // The display task will now handle the game loop and rendering ESP_LOGI(TAG_MAIN, "Attempting to start display task..."); // Pass the JumpBirdGame instance to the generic display task if (start_display_task(&JumpBirdGame) != ESP_OK) { ESP_LOGE(TAG_MAIN, "Failed to start display task! Halting."); // No game queue to delete here as it's managed internally by the game vQueueDelete(xLedControlQueue); // Clean up while (1) { vTaskDelay(100); // Fatal error, halt } } ESP_LOGI(TAG_MAIN, "Display task created successfully."); // --- 4. Start the LED control task --- ESP_LOGI(TAG_MAIN, "Attempting to start LED control task..."); if (start_led_control_task() != ESP_OK) { ESP_LOGE(TAG_MAIN, "Failed to start LED control task! Halting."); // No game queue to delete here vQueueDelete(xLedControlQueue); // Consider stopping display task here too if it's dependent while (1) { vTaskDelay(100); // Fatal error, halt } } ESP_LOGI(TAG_MAIN, "LED control task created successfully."); // --- 5. Start the button monitor task --- // This task will send jump signals to the game's input queue (obtained generically) // AND LED signals to xLedControlQueue. QueueHandle_t game_input_queue = NULL; if (JumpBirdGame.get_input_queue) { game_input_queue = JumpBirdGame.get_input_queue(); } else { ESP_LOGE(TAG_MAIN, "JumpBirdGame.get_input_queue is NULL! Cannot get game input queue."); // Proceeding but button input to game will not work. } ESP_LOGI(TAG_MAIN, "Attempting to start button monitor task..."); // Pass both the game's input queue and the LED control queue if (start_button_monitor_task(game_input_queue, xLedControlQueue) != ESP_OK) { ESP_LOGE(TAG_MAIN, "Failed to start button monitor task! Halting."); // No game queue to delete here vQueueDelete(xLedControlQueue); // Consider stopping display task and LED task here too if they're dependent while (1) { vTaskDelay(100); // Fatal error, halt } } ESP_LOGI(TAG_MAIN, "Button Monitor task created successfully."); // --- 6. Initial Game State or Menu --- // Display an initial message on the OLED. const char *initial_messages[] = { " JUMP BIRD! ", " ", " PRESS BUTTON ", " TO START ", " ", " ", " ", " "}; display_update_text(initial_messages, 8); // Display on OLED // Allow some time for the display to show the message vTaskDelay(pdMS_TO_TICKS(1000)); // At this point, the system is running: // - Display task is ready to show graphics/text and will manage the game loop. // - Button task is ready to send jump events. // - LED task is ready to control the LED. ESP_LOGI(TAG_MAIN, "All core tasks and queues initialized. Main idle loop..."); while (true) { // This task (app_main) now becomes an idle task or can manage high-level states // (e.g., switch between game mode, info mode, etc., based on long button presses or other inputs). vTaskDelay(pdMS_TO_TICKS(1000)); } }