#include #include #include #include #include #include #include #include #include #include "hardware.h" #include "managed_i2c.h" #include "pax_gfx.h" #include "sdcard.h" #include "appfs.h" #include "driver_framebuffer.h" #include "rp2040.h" #include "fpga_test.h" #include "menu.h" #include "button_wrapper.h" #include "system_wrapper.h" #include "graphics_wrapper.h" #include "appfs_wrapper.h" static const char *TAG = "main"; typedef enum action { ACTION_NONE, ACTION_APPFS, ACTION_INSTALLER, ACTION_SETTINGS, ACTION_OTA, ACTION_FPGA } menu_action_t; typedef struct _menu_args { appfs_handle_t fd; menu_action_t action; } menu_args_t; void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, uint8_t* framebuffer, menu_action_t* menu_action, appfs_handle_t* appfs_fd) { menu_t* menu = menu_alloc("Main menu"); *appfs_fd = APPFS_INVALID_FD; *menu_action = ACTION_NONE; while (1) { *appfs_fd = appfsNextEntry(*appfs_fd); if (*appfs_fd == APPFS_INVALID_FD) break; const char* name = NULL; appfsEntryInfo(*appfs_fd, &name, NULL); menu_args_t* args = malloc(sizeof(menu_args_t)); args->fd = *appfs_fd; args->action = ACTION_APPFS; menu_insert_item(menu, name, NULL, (void*) args, -1); } *appfs_fd = APPFS_INVALID_FD; menu_args_t* install_args = malloc(sizeof(menu_args_t)); install_args->action = ACTION_INSTALLER; menu_insert_item(menu, "Hatchery", NULL, install_args, -1); menu_args_t* settings_args = malloc(sizeof(menu_args_t)); settings_args->action = ACTION_SETTINGS; menu_insert_item(menu, "System settings", NULL, settings_args, -1); menu_args_t* ota_args = malloc(sizeof(menu_args_t)); ota_args->action = ACTION_OTA; menu_insert_item(menu, "Firmware update", NULL, ota_args, -1); menu_args_t* fpga_args = malloc(sizeof(menu_args_t)); fpga_args->action = ACTION_FPGA; menu_insert_item(menu, "FPGA", NULL, fpga_args, -1); for (uint8_t i = 0; i < 30; i++) { menu_args_t* dummy_args = malloc(sizeof(menu_args_t)); dummy_args->action = ACTION_NONE; menu_insert_item(menu, "Dummy menu item", NULL, dummy_args, -1); } bool render = true; menu_args_t* menuArgs = NULL; while (1) { button_message_t buttonMessage = {0}; if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) { uint8_t pin = buttonMessage.button; bool value = buttonMessage.state; switch(pin) { case PCA9555_PIN_BTN_JOY_DOWN: if (value) { menu_navigate_next(menu); render = true; } break; case PCA9555_PIN_BTN_JOY_UP: if (value) { menu_navigate_previous(menu); render = true; } break; case PCA9555_PIN_BTN_ACCEPT: if (value) { menuArgs = menu_get_callback_args(menu, menu_get_position(menu)); } break; default: break; } } if (render) { graphics_task(pax_buffer, ili9341, framebuffer, menu, NULL); render = false; } if (menuArgs != NULL) { *appfs_fd = menuArgs->fd; *menu_action = menuArgs->action; graphics_task(pax_buffer, ili9341, framebuffer, menu, "Please wait..."); break; } } for (size_t index = 0; index < menu_get_length(menu); index++) { free(menu_get_callback_args(menu, index)); } menu_free(menu); } void app_main(void) { esp_err_t res; /* Initialize memory */ xQueueHandle buttonQueue = xQueueCreate(10, sizeof(button_message_t)); if (buttonQueue == NULL) { ESP_LOGE(TAG, "Failed to allocate queue"); restart(); } uint8_t* framebuffer = heap_caps_malloc(ILI9341_BUFFER_SIZE, MALLOC_CAP_8BIT); if (framebuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate framebuffer"); restart(); } memset(framebuffer, 0, ILI9341_BUFFER_SIZE); pax_buf_t* pax_buffer = malloc(sizeof(pax_buf_t)); if (framebuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate pax buffer"); restart(); } memset(pax_buffer, 0, sizeof(pax_buf_t)); pax_buf_init(pax_buffer, framebuffer, ILI9341_WIDTH, ILI9341_HEIGHT, PAX_BUF_16_565RGB); driver_framebuffer_init(framebuffer); /* Initialize hardware */ res = board_init(); if (res != ESP_OK) { printf("Failed to initialize hardware!\n"); restart(); } ILI9341* ili9341 = get_ili9341(); ICE40* ice40 = get_ice40(); BNO055* bno055 = get_bno055(); RP2040* rp2040 = get_rp2040(); PCA9555* pca9555 = get_pca9555(); graphics_task(pax_buffer, ili9341, framebuffer, NULL, "Button init..."); button_init(pca9555, buttonQueue); rp2040_set_led_mode(rp2040, true, true); graphics_task(pax_buffer, ili9341, framebuffer, NULL, "AppFS init..."); res = appfs_init(); if (res != ESP_OK) { ESP_LOGE(TAG, "AppFS init failed: %d", res); return; } ESP_LOGI(TAG, "AppFS initialized"); graphics_task(pax_buffer, ili9341, framebuffer, NULL, "Mount SD card..."); res = mount_sd(SD_CMD, SD_CLK, SD_D0, SD_PWR, "/sd", false, 5); bool sdcard_ready = (res == ESP_OK); if (sdcard_ready) { graphics_task(pax_buffer, ili9341, framebuffer, NULL, "SD card mounted"); } while (true) { menu_action_t menu_action; appfs_handle_t appfs_fd; menu_launcher(buttonQueue, pax_buffer, ili9341, framebuffer, &menu_action, &appfs_fd); if (menu_action == ACTION_APPFS) { appfs_boot_app(appfs_fd); } else if (menu_action == ACTION_FPGA) { graphics_task(pax_buffer, ili9341, framebuffer, NULL, "FPGA TEST"); fpga_test(ili9341, ice40, buttonQueue); } else if (menu_action == ACTION_INSTALLER) { graphics_task(pax_buffer, ili9341, framebuffer, NULL, "INSTALLER"); //appfs_store_app(); } graphics_task(pax_buffer, ili9341, framebuffer, NULL, "Loop!"); } free(framebuffer); }