diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 44d8bff..4741926 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -21,6 +21,7 @@ idf_component_register( "menus/wifi.c" "menus/sao.c" "menus/ir.c" + "menus/python.c" "nametag.c" "uninstall.c" "file_browser.c" diff --git a/main/appfs_wrapper.c b/main/appfs_wrapper.c index a0b6fdf..91e9409 100644 --- a/main/appfs_wrapper.c +++ b/main/appfs_wrapper.c @@ -26,16 +26,6 @@ static const char* TAG = "appfs wrapper"; esp_err_t appfs_init(void) { return appfsInit(APPFS_PART_TYPE, APPFS_PART_SUBTYPE); } -static uint8_t* load_file_to_ram(FILE* fd, size_t* fsize) { - fseek(fd, 0, SEEK_END); - *fsize = ftell(fd); - fseek(fd, 0, SEEK_SET); - uint8_t* file = malloc(*fsize); - if (file == NULL) return NULL; - fread(file, *fsize, 1, fd); - return file; -} - void appfs_boot_app(int fd) { if (fd < 0 || fd > 255) { REG_WRITE(RTC_CNTL_STORE0_REG, 0); @@ -59,8 +49,8 @@ void appfs_store_app(pax_buf_t* pax_buffer, ILI9341* ili9341, const char* path, vTaskDelay(100 / portTICK_PERIOD_MS); return; } - size_t app_size; - uint8_t* app = load_file_to_ram(app_fd, &app_size); + size_t app_size = get_file_size(app_fd); + uint8_t* app = load_file_to_ram(app_fd); fclose(app_fd); if (app == NULL) { display_boot_screen(pax_buffer, ili9341, "Failed to load app to RAM"); diff --git a/main/factory_test.c b/main/factory_test.c index 6e444af..d99ece7 100644 --- a/main/factory_test.c +++ b/main/factory_test.c @@ -194,7 +194,7 @@ void factory_test(pax_buf_t* pax_buffer, ILI9341* ili9341) { pax_background(pax_buffer, 0xa85a32); ili9341_write(ili9341, pax_buffer->buf); } - nvs_set_u8_fixed("system", "force_sponsors", 0x01); // Force showing sponsors on first boot + nvs_set_u8_fixed("system", "force_sponsors", 0x01); // Force showing sponsors on first boot } while (true) { diff --git a/main/file_browser.c b/main/file_browser.c index 7466175..f40ca13 100644 --- a/main/file_browser.c +++ b/main/file_browser.c @@ -21,6 +21,7 @@ #include "menu.h" #include "pax_gfx.h" #include "rp2040.h" +#include "system_wrapper.h" static const char* TAG = "file browser"; @@ -115,41 +116,6 @@ void find_parent_dir(char* path, char* parent) { parent[last_separator] = '\0'; } -static bool wait_for_button(xQueueHandle buttonQueue) { - while (1) { - rp2040_input_message_t buttonMessage = {0}; - if (xQueueReceive(buttonQueue, &buttonMessage, 1000 / portTICK_PERIOD_MS) == pdTRUE) { - uint8_t pin = buttonMessage.input; - bool value = buttonMessage.state; - if (value) { - if (pin == RP2040_INPUT_BUTTON_BACK) { - return false; - } - if (pin == RP2040_INPUT_BUTTON_ACCEPT) { - return true; - } - } - } - } -} - -static uint8_t* load_file_to_ram(FILE* fd) { - fseek(fd, 0, SEEK_END); - size_t fsize = ftell(fd); - fseek(fd, 0, SEEK_SET); - uint8_t* file = malloc(fsize); - if (file == NULL) return NULL; - fread(file, fsize, 1, fd); - return file; -} - -static size_t get_file_size(FILE* fd) { - fseek(fd, 0, SEEK_END); - size_t fsize = ftell(fd); - fseek(fd, 0, SEEK_SET); - return fsize; -} - static bool is_esp32_binary(FILE* fd) { if (get_file_size(fd) < 1) return false; fseek(fd, 0, SEEK_SET); diff --git a/main/graphics_wrapper.c b/main/graphics_wrapper.c index 7404e83..81c3012 100644 --- a/main/graphics_wrapper.c +++ b/main/graphics_wrapper.c @@ -7,14 +7,14 @@ #include "rp2040.h" void render_message(pax_buf_t* pax_buffer, char* message) { - const pax_font_t* font = pax_get_font("saira regular"); - pax_vec1_t size = pax_text_size(font, 18, message); - float width = size.x + 4; - float posX = (pax_buffer->width - width) / 2; - float height = size.y + 4; - float posY = (pax_buffer->height - height) / 2; - pax_col_t fgColor = 0xFFfa448c; - pax_col_t bgColor = 0xFFFFFFFF; + const pax_font_t* font = pax_get_font("saira regular"); + pax_vec1_t size = pax_text_size(font, 18, message); + float width = size.x + 4; + float posX = (pax_buffer->width - width) / 2; + float height = size.y + 4; + float posY = (pax_buffer->height - height) / 2; + pax_col_t fgColor = 0xFFfa448c; + pax_col_t bgColor = 0xFFFFFFFF; pax_simple_rect(pax_buffer, bgColor, posX, posY, width, height); pax_outline_rect(pax_buffer, fgColor, posX, posY, width, height); pax_clip(pax_buffer, posX + 1, posY + 1, width - 2, height - 2); diff --git a/main/hatchery_client.c b/main/hatchery_client.c index 561a5f2..e8ff22d 100644 --- a/main/hatchery_client.c +++ b/main/hatchery_client.c @@ -1,21 +1,21 @@ #include "hatchery_client.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_system.h" -#include "esp_event.h" -#include "esp_log.h" #include +#include + +#include "bootscreen.h" +#include "esp_crt_bundle.h" +#include "esp_event.h" #include "esp_http_client.h" #include "esp_https_ota.h" -#include "string.h" -#include "esp_crt_bundle.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "nvs.h" #include "nvs_flash.h" -#include -#include "esp_wifi.h" -#include "bootscreen.h" - +#include "string.h" #include "wifi_connect.h" #define HASH_LEN 32 @@ -31,57 +31,53 @@ struct data_callback_t { void (*fn)(void *callback_data, const char *data, int data_len); }; -static esp_err_t _http_event_handler_data_callback(esp_http_client_event_t *evt) -{ +static esp_err_t _http_event_handler_data_callback(esp_http_client_event_t *evt) { switch (evt->event_id) { - case HTTP_EVENT_ERROR: - ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); - break; - case HTTP_EVENT_ON_CONNECTED: - ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); - break; - case HTTP_EVENT_HEADERS_SENT: - ESP_LOGD(TAG, "HTTP_EVENT_HEADERS_SENT"); - break; - case HTTP_EVENT_ON_HEADER: - ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); - break; - case HTTP_EVENT_ON_DATA: - ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); - data_callback_t *data_callback = (data_callback_t*)evt->user_data; - data_callback->fn(data_callback->data, (const char*)evt->data, evt->data_len); - break; - case HTTP_EVENT_ON_FINISH: - ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); - break; - case HTTP_EVENT_DISCONNECTED: - ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); - break; + case HTTP_EVENT_ERROR: + ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADERS_SENT: + ESP_LOGD(TAG, "HTTP_EVENT_HEADERS_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + data_callback_t *data_callback = (data_callback_t *) evt->user_data; + data_callback->fn(data_callback->data, (const char *) evt->data, evt->data_len); + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); + break; } return ESP_OK; } -static esp_err_t hatchery_http_get(const char *url, data_callback_t *data_callback) -{ +static esp_err_t hatchery_http_get(const char *url, data_callback_t *data_callback) { if (!wifi_connect_to_stored()) { return ESP_ERR_ESP_NETIF_INIT_FAILED; } - //esp_wifi_set_ps(WIFI_PS_NONE); // Disable any WiFi power save mode + // esp_wifi_set_ps(WIFI_PS_NONE); // Disable any WiFi power save mode ESP_LOGI(TAG, "http get"); - esp_http_client_config_t config = { - .url = url, - .crt_bundle_attach = esp_crt_bundle_attach, - .cert_pem = (char *)server_cert_pem_start, - .event_handler = _http_event_handler_data_callback, - .user_data = data_callback, - .keep_alive_enable = true - }; - + esp_http_client_config_t config = {.url = url, + .crt_bundle_attach = esp_crt_bundle_attach, + .cert_pem = (char *) server_cert_pem_start, + .event_handler = _http_event_handler_data_callback, + .user_data = data_callback, + .keep_alive_enable = true}; + esp_http_client_handle_t client = esp_http_client_init(&config); - esp_err_t err = esp_http_client_perform(client); + esp_err_t err = esp_http_client_perform(client); esp_http_client_cleanup(client); ESP_LOGI(TAG, "http get done %d", err); @@ -95,73 +91,66 @@ typedef struct string_appender_t string_appender_t; typedef struct string_buffer_t string_buffer_t; struct string_buffer_t { - char buffer[100]; - string_buffer_t* next; -}; + char buffer[100]; + string_buffer_t *next; +}; struct string_appender_t { - string_buffer_t *head; + string_buffer_t *head; string_buffer_t **cur; - int tot_len; - int cur_len; + int tot_len; + int cur_len; }; -static void string_appender_init(string_appender_t *str_app) -{ - str_app->head = 0; - str_app->cur = &str_app->head; +static void string_appender_init(string_appender_t *str_app) { + str_app->head = 0; + str_app->cur = &str_app->head; str_app->tot_len = 0; str_app->cur_len = 0; } -static void string_appender_clear(string_appender_t *str_app) -{ +static void string_appender_clear(string_appender_t *str_app) { str_app->tot_len = 0; str_app->cur_len = 0; } -static void string_appender_close(string_appender_t *str_app) -{ +static void string_appender_close(string_appender_t *str_app) { string_buffer_t *buf = str_app->head; - while (buf != 0) - { + while (buf != 0) { string_buffer_t *cur = buf; - buf = buf->next; + buf = buf->next; free(cur); } } -static void string_appender_append(string_appender_t *str_app, char ch) -{ +static void string_appender_append(string_appender_t *str_app, char ch) { if (*str_app->cur == 0) { - *str_app->cur = (string_buffer_t*)malloc(sizeof(string_buffer_t)); + *str_app->cur = (string_buffer_t *) malloc(sizeof(string_buffer_t)); if (str_app->cur == 0) { return; } (*str_app->cur)->next = 0; } (*str_app->cur)->buffer[str_app->cur_len++] = ch; - if (str_app->cur_len == 100) - { - str_app->cur = &(*str_app->cur)->next; + if (str_app->cur_len == 100) { + str_app->cur = &(*str_app->cur)->next; str_app->cur_len = 0; } str_app->tot_len++; } -static char *string_appender_copy(string_appender_t *str_app) -{ - char *result = (char*)malloc((str_app->tot_len + 1)*sizeof(char)); +static char *string_appender_copy(string_appender_t *str_app) { + char *result = (char *) malloc((str_app->tot_len + 1) * sizeof(char)); if (result == 0) { return 0; } - int tot_len = str_app->tot_len; - int cur_pos = 0; - string_buffer_t *buf = str_app->head; + int tot_len = str_app->tot_len; + int cur_pos = 0; + string_buffer_t *buf = str_app->head; for (int i = 0; i < tot_len; i++) { result[i] = buf->buffer[cur_pos++]; if (cur_pos == 100) { - buf = buf->next; + buf = buf->next; cur_pos = 0; } } @@ -169,18 +158,17 @@ static char *string_appender_copy(string_appender_t *str_app) return result; } -static int string_appender_compare(string_appender_t *str_app, const char *s) -{ - int tot_len = str_app->tot_len; - int cur_pos = 0; - string_buffer_t *buf = str_app->head; +static int string_appender_compare(string_appender_t *str_app, const char *s) { + int tot_len = str_app->tot_len; + int cur_pos = 0; + string_buffer_t *buf = str_app->head; for (int i = 0; i < tot_len; i++) { int c = *s++ - buf->buffer[cur_pos++]; if (c != 0) { return c; } if (cur_pos == 100) { - buf = buf->next; + buf = buf->next; cur_pos = 0; } } @@ -201,105 +189,97 @@ enum json_cb_parser_state_t { typedef struct json_cb_parser_t json_cb_parser_t; typedef void (*json_cb_parser_callback_t)(json_cb_parser_t *parser, json_parser_state_t state); -static struct json_cb_parser_t -{ - int lc; - string_appender_t string_appender; - int int_value; +static struct json_cb_parser_t { + int lc; + string_appender_t string_appender; + int int_value; json_cb_parser_callback_t callback; - void *data; + void *data; }; -static void json_cb_parser_init(json_cb_parser_t *parser, json_cb_parser_callback_t callback, void *data) -{ +static void json_cb_parser_init(json_cb_parser_t *parser, json_cb_parser_callback_t callback, void *data) { parser->lc = 0; string_appender_init(&parser->string_appender); parser->callback = callback; - parser->data = data; + parser->data = data; } -static void json_cb_parser_close(json_cb_parser_t *parser) -{ - string_appender_close(&parser->string_appender); -} +static void json_cb_parser_close(json_cb_parser_t *parser) { string_appender_close(&parser->string_appender); } -static void json_cb_process(void *callback_data, const char *data, int data_len) -{ +static void json_cb_process(void *callback_data, const char *data, int data_len) { ESP_LOGI(TAG, "received data %d", data_len); -#define JSON_NEXT_CH parser->lc = __LINE__; goto next; case __LINE__:; +#define JSON_NEXT_CH \ + parser->lc = __LINE__; \ + goto next; \ + case __LINE__:; - json_cb_parser_t *parser = (json_cb_parser_t*)callback_data; + json_cb_parser_t *parser = (json_cb_parser_t *) callback_data; for (int i = 0; i < data_len; i++) { char ch = data[i]; ESP_LOGI(TAG, "'%c' %d", ch, parser->lc); - switch(parser->lc) { case 0: - - for (;;) { - if ('0' <= ch && ch <= '9') { - parser->int_value = 0; - do { - parser->int_value = 10 * parser->int_value + ch - '0'; + switch (parser->lc) { + case 0: + + for (;;) { + if ('0' <= ch && ch <= '9') { + parser->int_value = 0; + do { + parser->int_value = 10 * parser->int_value + ch - '0'; + JSON_NEXT_CH + } while ('0' <= ch && ch <= '9'); + parser->callback(parser, json_cb_int); + } + if (ch == '"') { + string_appender_clear(&parser->string_appender); JSON_NEXT_CH - } while ('0' <= ch && ch <= '9'); - parser->callback(parser, json_cb_int); - } - if (ch == '"') { - string_appender_clear(&parser->string_appender); - JSON_NEXT_CH - while (ch != '"') { - if (ch == '\\') { + while (ch != '"') { + if (ch == '\\') { + JSON_NEXT_CH + if (ch == 't') + ch = '\t'; + else if (ch == 'n') + ch = '\n'; + else if (ch == 'r') + ch = '\r'; + string_appender_append(&parser->string_appender, ch); + } else { + string_appender_append(&parser->string_appender, ch); + } JSON_NEXT_CH - if (ch == 't') - ch = '\t'; - else if (ch == 'n') - ch = '\n'; - else if (ch == 'r') - ch = '\r'; - string_appender_append(&parser->string_appender, ch); - } - else { - string_appender_append(&parser->string_appender, ch); } - JSON_NEXT_CH + parser->callback(parser, json_cb_string); + } else if (ch == '{') { + parser->callback(parser, json_cb_open_object); + } else if (ch == '}') { + parser->callback(parser, json_cb_close_object); + } else if (ch == '[') { + parser->callback(parser, json_cb_open_array); + } else if (ch == ']') { + parser->callback(parser, json_cb_close_array); + } else { + // skip } - parser->callback(parser, json_cb_string); - } - else if (ch == '{') { - parser->callback(parser, json_cb_open_object); - } - else if (ch == '}') { - parser->callback(parser, json_cb_close_object); - } - else if (ch == '[') { - parser->callback(parser, json_cb_open_array); - } - else if (ch == ']') { - parser->callback(parser, json_cb_close_array); - } - else { - // skip + JSON_NEXT_CH } - JSON_NEXT_CH - } } - next:; - } - #undef JSON_NEXT_CH + next:; + } +#undef JSON_NEXT_CH } // Query app types hatchery_app_type_t *new_app_type(hatchery_server_t *server) { - hatchery_app_type_t *app_type = (hatchery_app_type_t*)malloc(sizeof(hatchery_app_type_t)); + hatchery_app_type_t *app_type = (hatchery_app_type_t *) malloc(sizeof(hatchery_app_type_t)); if (app_type != NULL) { - app_type->slug = NULL; - app_type->name = NULL; - app_type->server = server; + app_type->slug = NULL; + app_type->name = NULL; + app_type->server = server; app_type->categories = NULL; - app_type->next = NULL; + app_type->next = NULL; } return app_type; } @@ -311,7 +291,7 @@ esp_err_t hatchery_query_app_types(hatchery_server_t *server) { hatchery_app_type_t *app_type = new_app_type(server); if (app_type != NULL) { - app_type->name = (char*)malloc(sizeof(char)*4); + app_type->name = (char *) malloc(sizeof(char) * 4); strcpy(app_type->name, "App"); server->app_types = app_type; } @@ -320,7 +300,6 @@ esp_err_t hatchery_query_app_types(hatchery_server_t *server) { } void hatchery_app_type_free(hatchery_app_type_t *app_types) { - while (app_types != NULL) { free(app_types->name); free(app_types->slug); @@ -331,108 +310,102 @@ void hatchery_app_type_free(hatchery_app_type_t *app_types) { } } - // Query categories typedef struct process_categories_t process_categories_t; struct process_categories_t { - int cl; - hatchery_app_type_t *app_type; + int cl; + hatchery_app_type_t *app_type; hatchery_category_t **cur; }; static hatchery_category_t *new_category(hatchery_app_type_t *app_type) { - hatchery_category_t *category = (hatchery_category_t*)malloc(sizeof(hatchery_category_t )); + hatchery_category_t *category = (hatchery_category_t *) malloc(sizeof(hatchery_category_t)); if (category != NULL) { - category->name = NULL; - category->slug = NULL; - category->nr_apps = -1; // Unknown + category->name = NULL; + category->slug = NULL; + category->nr_apps = -1; // Unknown category->app_type = app_type; - category->apps = NULL; - category->next = NULL; + category->apps = NULL; + category->next = NULL; } return category; } -static void hatchery_process_categories(json_cb_parser_t *parser, enum json_cb_parser_state_t state) -{ - process_categories_t *process_categories = (process_categories_t*)(parser->data); +static void hatchery_process_categories(json_cb_parser_t *parser, enum json_cb_parser_state_t state) { + process_categories_t *process_categories = (process_categories_t *) (parser->data); ESP_LOGI(TAG, "category %d at line %d", state, process_categories->cl); -#define NEXT process_categories->cl = __LINE__; return; case __LINE__:; - - switch(process_categories->cl) { case 0: - - if (state == json_cb_open_array) { - NEXT - while (state == json_cb_open_object) { - *process_categories->cur = new_category(process_categories->app_type); - NEXT - while (state == json_cb_string) { - if (string_appender_compare(&parser->string_appender, "slug") == 0) { - NEXT - if (state == json_cb_string) { - if ((*process_categories->cur) != NULL && (*process_categories->cur)->slug == NULL) { - (*process_categories->cur)->slug = string_appender_copy(&parser->string_appender); +#define NEXT \ + process_categories->cl = __LINE__; \ + return; \ + case __LINE__:; + + switch (process_categories->cl) { + case 0: + + if (state == json_cb_open_array) { + NEXT while (state == json_cb_open_object) { + *process_categories->cur = new_category(process_categories->app_type); + NEXT while (state == json_cb_string) { + if (string_appender_compare(&parser->string_appender, "slug") == 0) { + NEXT if (state == json_cb_string) { + if ((*process_categories->cur) != NULL && (*process_categories->cur)->slug == NULL) { + (*process_categories->cur)->slug = string_appender_copy(&parser->string_appender); + } + // printf("slug '%s'\n", slug); + NEXT } - //printf("slug '%s'\n", slug); - NEXT - } - } - else if (string_appender_compare(&parser->string_appender, "name") == 0) { - NEXT - if (state == json_cb_string) { - if ((*process_categories->cur) != NULL && (*process_categories->cur)->name == NULL) { - (*process_categories->cur)->name = string_appender_copy(&parser->string_appender); + } else if (string_appender_compare(&parser->string_appender, "name") == 0) { + NEXT if (state == json_cb_string) { + if ((*process_categories->cur) != NULL && (*process_categories->cur)->name == NULL) { + (*process_categories->cur)->name = string_appender_copy(&parser->string_appender); + } + // printf("name '%s'\n", name); + NEXT + } + } else if (string_appender_compare(&parser->string_appender, "eggs") == 0) { + NEXT if (state == json_cb_int) { + if ((*process_categories->cur) != NULL && (*process_categories->cur)->nr_apps == -1) { + (*process_categories->cur)->nr_apps = parser->int_value; + } } - //printf("name '%s'\n", name); - NEXT } } - else if (string_appender_compare(&parser->string_appender, "eggs") == 0) { - NEXT - if (state == json_cb_int) { - if ((*process_categories->cur) != NULL && (*process_categories->cur)->nr_apps == -1) { - (*process_categories->cur)->nr_apps = parser->int_value; - } + if (state == json_cb_close_object) { + if ((*process_categories->cur) != NULL) { + process_categories->cur = &(*process_categories->cur)->next; } + NEXT } } - if (state == json_cb_close_object) { - if ((*process_categories->cur) != NULL) { - process_categories->cur = &(*process_categories->cur)->next; - } + if (state == json_cb_close_array) { NEXT } } - if (state == json_cb_close_array) { - NEXT - } - } } #undef NEXT } esp_err_t hatchery_query_categories(hatchery_app_type_t *app_type) { - if (app_type->categories != NULL) { return ESP_OK; } process_categories_t process_categories_data; - process_categories_data.cl = 0; + process_categories_data.cl = 0; process_categories_data.app_type = app_type; - process_categories_data.cur = &app_type->categories; - + process_categories_data.cur = &app_type->categories; + json_cb_parser_t parser; json_cb_parser_init(&parser, hatchery_process_categories, &process_categories_data); data_callback_t data_callback; data_callback.data = &parser; - data_callback.fn = json_cb_process; + data_callback.fn = json_cb_process; - const char *url = app_type->server->url; - esp_err_t result = hatchery_http_get(url, &data_callback); + const char *url = app_type->server->url; + esp_err_t result = hatchery_http_get(url, &data_callback); json_cb_parser_close(&parser); @@ -440,7 +413,6 @@ esp_err_t hatchery_query_categories(hatchery_app_type_t *app_type) { } void hatchery_category_free(hatchery_category_t *catagories) { - while (catagories != NULL) { free(catagories->slug); free(catagories->name); @@ -452,7 +424,6 @@ void hatchery_category_free(hatchery_category_t *catagories) { } void hatchery_app_free(hatchery_app_t *apps) { - while (apps != NULL) { free(apps->slug); free(apps->name); diff --git a/main/include/graphics_wrapper.h b/main/include/graphics_wrapper.h index ab91d22..9f4e22e 100644 --- a/main/include/graphics_wrapper.h +++ b/main/include/graphics_wrapper.h @@ -12,5 +12,5 @@ #include "pax_gfx.h" void render_message(pax_buf_t* pax_buffer, char* message); -bool keyboard(xQueueHandle buttonQueue, pax_buf_t* aBuffer, ILI9341* ili9341, float aPosX, float aPosY, float aWidth, float aHeight, const char* aTitle, - const char* aHint, char* aOutput, size_t aOutputSize); +bool keyboard(xQueueHandle buttonQueue, pax_buf_t* aBuffer, ILI9341* ili9341, float aPosX, float aPosY, float aWidth, float aHeight, const char* aTitle, + const char* aHint, char* aOutput, size_t aOutputSize); diff --git a/main/include/hatchery_client.h b/main/include/hatchery_client.h index a5325c7..cf82e90 100644 --- a/main/include/hatchery_client.h +++ b/main/include/hatchery_client.h @@ -2,23 +2,21 @@ #include - -typedef struct hatchery_server_t hatchery_server_t; +typedef struct hatchery_server_t hatchery_server_t; typedef struct hatchery_app_type_t hatchery_app_type_t; typedef struct hatchery_category_t hatchery_category_t; -typedef struct hatchery_app_t hatchery_app_t; +typedef struct hatchery_app_t hatchery_app_t; struct hatchery_server_t { - const char *url; + const char *url; hatchery_app_type_t *app_types; }; - struct hatchery_app_type_t { - char *name; - char *slug; + char *name; + char *slug; hatchery_category_t *categories; - hatchery_server_t *server; + hatchery_server_t *server; hatchery_app_type_t *next; }; @@ -26,12 +24,11 @@ esp_err_t hatchery_query_app_types(hatchery_server_t *server); void hatchery_app_type_free(hatchery_app_type_t *app_type); - struct hatchery_category_t { - char *name; - char *slug; - int nr_apps; // -1: Unknown - hatchery_app_t *apps; + char *name; + char *slug; + int nr_apps; // -1: Unknown + hatchery_app_t *apps; hatchery_app_type_t *app_type; hatchery_category_t *next; }; @@ -40,24 +37,23 @@ esp_err_t hatchery_query_categories(hatchery_app_type_t *app_type); void hatchery_category_free(hatchery_category_t *catagories); - typedef struct hatchery_file_t hatchery_file_t; struct hatchery_file_t { - char *name; - char *url; - int size; + char *name; + char *url; + int size; hatchery_category_t *category; - hatchery_file_t *next; + hatchery_file_t *next; }; struct hatchery_app_t { - char *name; - char *slug; - char *author; - char *license; - char *description; + char *name; + char *slug; + char *author; + char *license; + char *description; hatchery_file_t *files; - hatchery_app_t *next; + hatchery_app_t *next; }; esp_err_t hatchery_query_apps(hatchery_category_t *category); diff --git a/main/include/menu.h b/main/include/menu.h index c0b9792..4b44bb6 100644 --- a/main/include/menu.h +++ b/main/include/menu.h @@ -45,20 +45,21 @@ typedef struct menu { } menu_t; -menu_t* menu_alloc(const char* aTitle, float arg_entry_height, float arg_text_height); -void menu_free(menu_t* aMenu); -void menu_set_icon(menu_t* aMenu, pax_buf_t* icon); -bool menu_insert_item(menu_t* aMenu, const char* aLabel, menu_callback_t aCallback, void* aCallbackArgs, size_t aPosition); -bool menu_insert_item_icon(menu_t* aMenu, const char* aLabel, menu_callback_t aCallback, void* aCallbackArgs, size_t aPosition, pax_buf_t* icon); -bool menu_remove_item(menu_t* aMenu, size_t aPosition); -bool menu_navigate_to(menu_t* aMenu, size_t aPosition); -void menu_navigate_previous(menu_t* aMenu); -void menu_navigate_next(menu_t* aMenu); -size_t menu_get_position(menu_t* aMenu); -size_t menu_get_length(menu_t* aMenu); -void* menu_get_callback_args(menu_t* aMenu, size_t aPosition); -void menu_debug(menu_t* aMenu); -void menu_render(pax_buf_t* aBuffer, menu_t* aMenu, float aPosX, float aPosY, float aWidth, float aHeight, pax_col_t aColor); +menu_t* menu_alloc(const char* aTitle, float arg_entry_height, float arg_text_height); +void menu_free(menu_t* aMenu); +void menu_set_icon(menu_t* aMenu, pax_buf_t* icon); +bool menu_insert_item(menu_t* aMenu, const char* aLabel, menu_callback_t aCallback, void* aCallbackArgs, size_t aPosition); +bool menu_insert_item_icon(menu_t* aMenu, const char* aLabel, menu_callback_t aCallback, void* aCallbackArgs, size_t aPosition, pax_buf_t* icon); +bool menu_remove_item(menu_t* aMenu, size_t aPosition); +bool menu_navigate_to(menu_t* aMenu, size_t aPosition); +void menu_navigate_previous(menu_t* aMenu); +void menu_navigate_next(menu_t* aMenu); +size_t menu_get_position(menu_t* aMenu); +size_t menu_get_length(menu_t* aMenu); +void* menu_get_callback_args(menu_t* aMenu, size_t aPosition); +pax_buf_t* menu_get_icon(menu_t* aMenu, size_t aPosition); +void menu_debug(menu_t* aMenu); +void menu_render(pax_buf_t* aBuffer, menu_t* aMenu, float aPosX, float aPosY, float aWidth, float aHeight, pax_col_t aColor); #ifdef __cplusplus } diff --git a/main/include/nametag.h b/main/include/nametag.h index 594d59c..e7678fe 100644 --- a/main/include/nametag.h +++ b/main/include/nametag.h @@ -4,8 +4,8 @@ #include #include -#include "pax_gfx.h" #include "ili9341.h" +#include "pax_gfx.h" #include "rp2040.h" // Shows the name tag. diff --git a/main/include/system_wrapper.h b/main/include/system_wrapper.h index a29f052..e859ea9 100644 --- a/main/include/system_wrapper.h +++ b/main/include/system_wrapper.h @@ -1,3 +1,14 @@ #pragma once -void restart(); +#include +#include +#include +#include + +#include "esp_vfs.h" +#include "esp_vfs_fat.h" + +void restart(); +bool wait_for_button(xQueueHandle buttonQueue); +uint8_t* load_file_to_ram(FILE* fd); +size_t get_file_size(FILE* fd); diff --git a/main/main.c b/main/main.c index ecf8a23..65962f4 100644 --- a/main/main.c +++ b/main/main.c @@ -33,6 +33,7 @@ #include "rp2040.h" #include "rp2040_updater.h" #include "rp2040bl.h" +#include "rtc_memory.h" #include "sao_eeprom.h" #include "sdcard.h" #include "settings.h" @@ -41,7 +42,6 @@ #include "wifi_connection.h" #include "wifi_ota.h" #include "ws2812.h" -#include "rtc_memory.h" extern const uint8_t wallpaper_png_start[] asm("_binary_wallpaper_png_start"); extern const uint8_t wallpaper_png_end[] asm("_binary_wallpaper_png_end"); @@ -62,24 +62,6 @@ void display_fatal_error(pax_buf_t* pax_buffer, ILI9341* ili9341, const char* li ili9341_write(ili9341, pax_buffer->buf); } -static bool wait_for_button(xQueueHandle buttonQueue) { - while (1) { - rp2040_input_message_t buttonMessage = {0}; - if (xQueueReceive(buttonQueue, &buttonMessage, 1000 / portTICK_PERIOD_MS) == pdTRUE) { - uint8_t pin = buttonMessage.input; - bool value = buttonMessage.state; - if (value) { - if (pin == RP2040_INPUT_BUTTON_BACK) { - return false; - } - if (pin == RP2040_INPUT_BUTTON_ACCEPT) { - return true; - } - } - } - } -} - void display_rp2040_crashed_message(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { const pax_font_t* font = pax_get_font("saira regular"); pax_noclip(pax_buffer); @@ -251,7 +233,7 @@ void app_main(void) { /* Start WiFi */ wifi_init(); - + /* Clear RTC memory */ rtc_memory_clear(); @@ -270,7 +252,7 @@ void app_main(void) { if (webusb_mode == 0x00) { // Normal boot /* Sponsors check */ nvs_handle_t handle; - esp_err_t res = nvs_open("system", NVS_READWRITE, &handle); + esp_err_t res = nvs_open("system", NVS_READWRITE, &handle); if (res != ESP_OK) { display_fatal_error(&pax_buffer, ili9341, fatal_error_str, "Failed to open NVS namespace", "Flash may be corrupted", reset_board_str); stop(); @@ -289,7 +271,7 @@ void app_main(void) { } nvs_close(handle); - + /* Rick that roll */ play_bootsound(); diff --git a/main/menu.c b/main/menu.c index 5a05483..6449753 100644 --- a/main/menu.c +++ b/main/menu.c @@ -190,6 +190,12 @@ void* menu_get_callback_args(menu_t* aMenu, size_t aPosition) { return item->callbackArgs; } +pax_buf_t* menu_get_icon(menu_t* aMenu, size_t aPosition) { + menu_item_t* item = _menu_find_item(aMenu, aPosition); + if (item == NULL) return NULL; + return item->icon; +} + void menu_debug(menu_t* aMenu) { if (aMenu == NULL) { printf("Menu pointer is NULL\n"); @@ -225,7 +231,7 @@ void menu_render(pax_buf_t* aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl if (maxItems > 1) { float offsetX = 0; if (aMenu->icon != NULL) { - offsetX = aMenu->icon->width; + offsetX = 32; // Fixed width by choice, could also use "aMenu->icon->width" } maxItems--; @@ -233,10 +239,11 @@ void menu_render(pax_buf_t* aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl // pax_simple_line(aBuffer, aMenu->titleColor, aPosX + 1, aPosY + entry_height, aPosX + aWidth - 2, aPosY + entry_height - 1); pax_clip(aBuffer, aPosX + 1, posY + text_offset, aWidth - 2, text_height); pax_draw_text(aBuffer, aMenu->titleColor, font, text_height, aPosX + offsetX + 1, posY + text_offset, aMenu->title); - pax_noclip(aBuffer); if (aMenu->icon != NULL) { + pax_clip(aBuffer, aPosX, posY, 32, 32); pax_draw_image(aBuffer, aMenu->icon, aPosX, posY); } + pax_noclip(aBuffer); posY += entry_height; } @@ -257,7 +264,7 @@ void menu_render(pax_buf_t* aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl float iconWidth = 0; if (item->icon != NULL) { - iconWidth = item->icon->width + 1; + iconWidth = 33; // Fixed width by choice, could also use "item->icon->width + 1" } if (index == aMenu->position) { diff --git a/main/menus/dev.c b/main/menus/dev.c index 574eaba..0ddf8ba 100644 --- a/main/menus/dev.c +++ b/main/menus/dev.c @@ -43,7 +43,7 @@ typedef enum action { ACTION_IR } menu_dev_action_t; -void render_dev_help(pax_buf_t* pax_buffer) { +static void render_help(pax_buf_t* pax_buffer) { const pax_font_t* font = pax_get_font("saira regular"); pax_background(pax_buffer, 0xFFFFFF); pax_noclip(pax_buffer); @@ -80,7 +80,7 @@ void menu_dev(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) bool render = true; menu_dev_action_t action = ACTION_NONE; - render_dev_help(pax_buffer); + render_help(pax_buffer); while (1) { rp2040_input_message_t buttonMessage = {0}; @@ -147,7 +147,7 @@ void menu_dev(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) } action = ACTION_NONE; render = true; - render_dev_help(pax_buffer); + render_help(pax_buffer); } } diff --git a/main/menus/hatchery.c b/main/menus/hatchery.c index bd8426e..d820d6e 100644 --- a/main/menus/hatchery.c +++ b/main/menus/hatchery.c @@ -1,26 +1,28 @@ -#include -#include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include + +#include "hatchery_client.h" #include "ili9341.h" -#include "pax_gfx.h" -#include "pax_codecs.h" #include "menu.h" +#include "pax_codecs.h" +#include "pax_gfx.h" #include "rp2040.h" -#include "hatchery_client.h" extern const uint8_t apps_png_start[] asm("_binary_apps_png_start"); extern const uint8_t apps_png_end[] asm("_binary_apps_png_end"); typedef void (*fill_menu_items_fn_t)(menu_t *menu, void *context); -typedef void (*action_fn_t)(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, void *args); +typedef void (*action_fn_t)(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341, void *args); -static void menu_generic(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, const char *select, fill_menu_items_fn_t fill_menu_items, action_fn_t action, void *context); +static void menu_generic(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341, const char *select, fill_menu_items_fn_t fill_menu_items, + action_fn_t action, void *context); static void add_menu_item(menu_t *menu, const char *name, void *callback_args); // Apps menu @@ -31,13 +33,12 @@ static void fill_menu_items_apps(menu_t *menu, void *context) { add_menu_item(menu, "App xx", NULL); } -static void action_apps(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, void *args) { -} +static void action_apps(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341, void *args) {} // Category menu static void fill_menu_items_categories(menu_t *menu, void *context) { - hatchery_app_type_t *app_type = (hatchery_app_type_t*)context; + hatchery_app_type_t *app_type = (hatchery_app_type_t *) context; hatchery_query_categories(app_type); for (hatchery_category_t *category = app_type->categories; category != NULL; category = category->next) { @@ -45,14 +46,14 @@ static void fill_menu_items_categories(menu_t *menu, void *context) { } } -static void action_categories(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, void *args) { +static void action_categories(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341, void *args) { menu_generic(buttonQueue, pax_buffer, ili9341, "[A] select app [B] back", fill_menu_items_apps, action_apps, args); } // App types menu static void fill_menu_items_types(menu_t *menu, void *context) { - hatchery_server_t *server = (hatchery_server_t*)context; + hatchery_server_t *server = (hatchery_server_t *) context; hatchery_query_app_types(server); for (hatchery_app_type_t *app_type = server->app_types; app_type != NULL; app_type = app_type->next) { @@ -60,15 +61,15 @@ static void fill_menu_items_types(menu_t *menu, void *context) { } } -static void action_types(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, void *args) { +static void action_types(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341, void *args) { menu_generic(buttonQueue, pax_buffer, ili9341, "[A] select category [B] back", fill_menu_items_categories, action_categories, args); } // Main entry function -void menu_hatchery(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { +void menu_hatchery(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341) { hatchery_server_t server; - server.url = "https://hatchery.badge.team/basket/sha2017/categories/json"; + server.url = "https://hatchery.badge.team/basket/sha2017/categories/json"; server.app_types = NULL; menu_generic(buttonQueue, pax_buffer, ili9341, "[A] select type [B] back", fill_menu_items_types, action_types, &server); hatchery_app_type_free(server.app_types); @@ -80,13 +81,14 @@ static void add_menu_item(menu_t *menu, const char *name, void *callback_args) { static int nothing; if (callback_args == NULL) { callback_args = ¬hing; - } + } menu_insert_item(menu, name, NULL, callback_args, -1); } -static void menu_generic(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, const char *select, fill_menu_items_fn_t fill_menu_items, action_fn_t action, void *context) { - menu_t* menu = menu_alloc("Hatchery", 34, 18); - +static void menu_generic(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341, const char *select, fill_menu_items_fn_t fill_menu_items, + action_fn_t action, void *context) { + menu_t *menu = menu_alloc("Hatchery", 34, 18); + menu->fgColor = 0xFF000000; menu->bgColor = 0xFFFFFFFF; menu->bgTextColor = 0xFFFFFFFF; @@ -96,19 +98,19 @@ static void menu_generic(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI934 menu->titleBgColor = 0xFF491d88; menu->scrollbarBgColor = 0xFFCCCCCC; menu->scrollbarFgColor = 0xFF555555; - + pax_buf_t icon_apps; - pax_decode_png_buf(&icon_apps, (void*) apps_png_start, apps_png_end - apps_png_start, PAX_BUF_32_8888ARGB, 0); - + pax_decode_png_buf(&icon_apps, (void *) apps_png_start, apps_png_end - apps_png_start, PAX_BUF_32_8888ARGB, 0); + menu_set_icon(menu, &icon_apps); const pax_font_t *font = pax_get_font("saira regular"); fill_menu_items(menu, context); - - bool render = true; - void* menuArgs = NULL; - + + bool render = true; + void *menuArgs = NULL; + pax_background(pax_buffer, 0xFFFFFF); pax_noclip(pax_buffer); pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 18, select); @@ -118,9 +120,9 @@ static void menu_generic(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI934 while (1) { rp2040_input_message_t buttonMessage = {0}; if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) { - uint8_t pin = buttonMessage.input; - bool value = buttonMessage.state; - switch(pin) { + uint8_t pin = buttonMessage.input; + bool value = buttonMessage.state; + switch (pin) { case RP2040_INPUT_JOYSTICK_DOWN: if (value) { menu_navigate_next(menu); @@ -159,7 +161,7 @@ static void menu_generic(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI934 if (menuArgs != NULL) { action(buttonQueue, pax_buffer, ili9341, menuArgs); menuArgs = NULL; - render = true; + render = true; } if (render) { diff --git a/main/menus/hatchery.h b/main/menus/hatchery.h index 14538fd..7cfbaf3 100644 --- a/main/menus/hatchery.h +++ b/main/menus/hatchery.h @@ -1,8 +1,9 @@ -#include #include -#include #include -#include "pax_gfx.h" +#include +#include + #include "ili9341.h" +#include "pax_gfx.h" void menu_hatchery(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341); \ No newline at end of file diff --git a/main/menus/launcher.c b/main/menus/launcher.c index 0530a84..300bb64 100644 --- a/main/menus/launcher.c +++ b/main/menus/launcher.c @@ -24,35 +24,33 @@ static bool populate(menu_t* menu) { for (size_t index = 0; index < menu_get_length(menu); index++) { free(menu_get_callback_args(menu, index)); } - while (menu_remove_item(menu, 0)) { /* Empty. */ } + while (menu_remove_item(menu, 0)) { /* Empty. */ + } - bool empty = true; + bool empty = true; appfs_handle_t appfs_fd = appfsNextEntry(APPFS_INVALID_FD); while (appfs_fd != APPFS_INVALID_FD) { - empty = false; + empty = false; const char* name = NULL; const char* title = NULL; uint16_t version = 0xFFFF; appfsEntryInfoExt(appfs_fd, &name, &title, &version, NULL); appfs_handle_t* args = malloc(sizeof(appfs_handle_t)); - *args = appfs_fd; + *args = appfs_fd; menu_insert_item(menu, title, NULL, (void*) args, -1); appfs_fd = appfsNextEntry(appfs_fd); } return empty; } -typedef enum { - CONTEXT_ACTION_NONE, - CONTEXT_ACTION_UNINSTALL -} context_menu_action_t; +typedef enum { CONTEXT_ACTION_NONE, CONTEXT_ACTION_UNINSTALL } context_menu_action_t; void context_menu(appfs_handle_t fd, xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { const char* name = NULL; const char* title = NULL; uint16_t version = 0xFFFF; appfsEntryInfoExt(fd, &name, &title, &version, NULL); - menu_t* menu = menu_alloc(title, 20, 18); + menu_t* menu = menu_alloc(title, 20, 18); menu->fgColor = 0xFF000000; menu->bgColor = 0xFFFFFFFF; menu->bgTextColor = 0xFFFFFFFF; @@ -62,13 +60,13 @@ void context_menu(appfs_handle_t fd, xQueueHandle buttonQueue, pax_buf_t* pax_bu menu->titleBgColor = 0xFF491d88; menu->scrollbarBgColor = 0xFFCCCCCC; menu->scrollbarFgColor = 0xFF555555; - + menu_insert_item(menu, "Uninstall", NULL, (void*) CONTEXT_ACTION_UNINSTALL, -1); - + bool render = true; - bool quit = false; + bool quit = false; while (!quit) { - context_menu_action_t action = CONTEXT_ACTION_NONE; + context_menu_action_t action = CONTEXT_ACTION_NONE; rp2040_input_message_t buttonMessage = {0}; if (xQueueReceive(buttonQueue, &buttonMessage, 1000 / portTICK_PERIOD_MS) == pdTRUE) { if (buttonMessage.state) { @@ -103,7 +101,7 @@ void context_menu(appfs_handle_t fd, xQueueHandle buttonQueue, pax_buf_t* pax_bu ili9341_write(ili9341, pax_buffer->buf); render = false; } - + if (action == CONTEXT_ACTION_UNINSTALL) { render_message(pax_buffer, "Uninstalling app..."); ili9341_write(ili9341, pax_buffer->buf); @@ -117,7 +115,7 @@ void context_menu(appfs_handle_t fd, xQueueHandle buttonQueue, pax_buf_t* pax_bu void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { pax_noclip(pax_buffer); - menu_t* menu = menu_alloc("ESP32 apps", 34, 18); + menu_t* menu = menu_alloc("ESP32 apps", 34, 18); menu->fgColor = 0xFF000000; menu->bgColor = 0xFFFFFFFF; menu->bgTextColor = 0xFFFFFFFF; @@ -136,9 +134,9 @@ void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili bool empty = populate(menu); - bool render = true; - appfs_handle_t* appfs_fd_to_start = NULL; - bool quit = false; + bool render = true; + appfs_handle_t* appfs_fd_to_start = NULL; + bool quit = false; appfs_handle_t* appfs_fd_context_menu = NULL; while (!quit) { rp2040_input_message_t buttonMessage = {0}; @@ -171,12 +169,12 @@ void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili } } } - + if (appfs_fd_context_menu != NULL) { context_menu(*appfs_fd_context_menu, buttonQueue, pax_buffer, ili9341); - empty = populate(menu); + empty = populate(menu); appfs_fd_context_menu = NULL; - render = true; + render = true; } if (render) { diff --git a/main/menus/python.c b/main/menus/python.c new file mode 100644 index 0000000..dd9766a --- /dev/null +++ b/main/menus/python.c @@ -0,0 +1,267 @@ +#include "python.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appfs.h" +#include "appfs_wrapper.h" +#include "bootscreen.h" +#include "hardware.h" +#include "ili9341.h" +#include "menu.h" +#include "pax_codecs.h" +#include "pax_gfx.h" +#include "rp2040.h" +#include "rtc_memory.h" +#include "system_wrapper.h" + +extern const uint8_t python_png_start[] asm("_binary_python_png_start"); +extern const uint8_t python_png_end[] asm("_binary_python_png_end"); + +extern const uint8_t hatchery_png_start[] asm("_binary_hatchery_png_start"); +extern const uint8_t hatchery_png_end[] asm("_binary_hatchery_png_end"); + +static appfs_handle_t python_appfs_fd = APPFS_INVALID_FD; + +typedef enum action { ACTION_NONE, ACTION_TEST } menu_python_action_t; + +void start_python_app(const char* application) { + rtc_memory_string_write(application); + appfs_boot_app(python_appfs_fd); +} + +void parse_metadata(const char* path, char** name, char** description, char** category, char** author, int* revision) { + FILE* fd = fopen(path, "r"); + if (fd == NULL) return; + char* json_data = (char*) load_file_to_ram(fd); + fclose(fd); + if (json_data == NULL) return; + cJSON* root = cJSON_Parse(json_data); + if (root == NULL) { + free(json_data); + return; + } + if (name) { + cJSON* name_obj = cJSON_GetObjectItem(root, "name"); + if (name_obj) { + *name = strdup(name_obj->valuestring); + } + } + if (description) { + cJSON* description_obj = cJSON_GetObjectItem(root, "description"); + if (description_obj) { + *description = strdup(description_obj->valuestring); + } + } + if (category) { + cJSON* category_obj = cJSON_GetObjectItem(root, "category"); + if (category_obj) { + *category = strdup(category_obj->valuestring); + } + } + if (author) { + cJSON* author_obj = cJSON_GetObjectItem(root, "author"); + if (author_obj) { + *author = strdup(author_obj->valuestring); + } + } + if (revision) { + cJSON* revision_obj = cJSON_GetObjectItem(root, "revision"); + if (revision_obj) { + *revision = revision_obj->valueint; + } + } + cJSON_Delete(root); +} + +void populate_menu_entry_from_path(menu_t* menu, const char* path, + const char* name) { // Path is here the folder of a specific app, for example /internal/apps/event_schedule + char metadata_file_path[128]; + snprintf(metadata_file_path, sizeof(metadata_file_path), "%s/%s/metadata.json", path, name); + char init_file_path[128]; + snprintf(init_file_path, sizeof(init_file_path), "%s/%s/__init__.py", path, name); + char icon_file_path[128]; + snprintf(icon_file_path, sizeof(icon_file_path), "%s/%s/icon.png", path, name); + + char* title = NULL; + /*char* description = NULL; + char* category = NULL; + char* author = NULL; + int revision = -1;*/ + + // parse_metadata(metadata_file_path, &title, &description, &category, &author, &revision); + parse_metadata(metadata_file_path, &title, NULL, NULL, NULL, NULL); + + /*if (title != NULL) printf("Name: %s\n", title); + if (description != NULL) printf("Description: %s\n", description); + if (category != NULL) printf("Category: %s\n", category); + if (author != NULL) printf("Author: %s\n", author); + if (revision >= 0) printf("Revision: %u\n", revision);*/ + + pax_buf_t* icon = NULL; + + FILE* icon_fd = fopen(icon_file_path, "rb"); + if (icon_fd != NULL) { + size_t icon_size = get_file_size(icon_fd); + uint8_t* icon_data = load_file_to_ram(icon_fd); + if (icon_data != NULL) { + icon = malloc(sizeof(pax_buf_t)); + if (icon != NULL) { + pax_decode_png_buf(icon, (void*) icon_data, icon_size, PAX_BUF_32_8888ARGB, 0); + } + free(icon_data); + } + fclose(icon_fd); + } + + if (icon == NULL) { + icon = malloc(sizeof(pax_buf_t)); + if (icon != NULL) { + pax_decode_png_buf(icon, (void*) python_png_start, python_png_end - python_png_start, PAX_BUF_32_8888ARGB, 0); + } + } + + menu_insert_item_icon(menu, (title != NULL) ? title : name, NULL, (void*) strdup(name), -1, icon); + + if (title) free(title); + /*if (description) free(description); + if (category) free(category); + if (author) free(author);*/ +} + +bool populate_menu_from_path(menu_t* menu, const char* path) { // Path is here the folder containing the Python apps, for example /internal/apps + DIR* dir = opendir(path); + if (dir == NULL) { + printf("Failed to populate menu, directory not found: %s\n", path); + return false; + } + struct dirent* ent; + while ((ent = readdir(dir)) != NULL) { + if (ent->d_type == DT_REG) continue; // Skip files, only parse directories + populate_menu_entry_from_path(menu, path, ent->d_name); + } + closedir(dir); + return true; +} + +bool populate_menu(menu_t* menu) { + bool internal_result = populate_menu_from_path(menu, "/internal/apps"); + bool sdcard_result = populate_menu_from_path(menu, "/sd/apps"); + return internal_result | sdcard_result; +} + +void menu_python(xQueueHandle button_queue, pax_buf_t* pax_buffer, ILI9341* ili9341) { + python_appfs_fd = appfsOpen("python"); + + if (python_appfs_fd == APPFS_INVALID_FD) { + pax_noclip(pax_buffer); + const pax_font_t* font = pax_get_font("saira regular"); + pax_background(pax_buffer, 0xFFFFFF); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, 0, 0, + "BadgePython not installed!\nPlease install BadgePython\nusing the Hatchery.\n\nPress A or B to return."); + ili9341_write(ili9341, pax_buffer->buf); + wait_for_button(button_queue); + return; + } + + menu_t* menu = menu_alloc("BadgePython apps", 34, 18); + + menu->fgColor = 0xFF000000; + menu->bgColor = 0xFFFFFFFF; + menu->bgTextColor = 0xFF000000; + menu->selectedItemColor = 0xFFfec859; + menu->borderColor = 0xFFfa448c; + menu->titleColor = 0xFFfec859; + menu->titleBgColor = 0xFFfa448c; + menu->scrollbarBgColor = 0xFFCCCCCC; + menu->scrollbarFgColor = 0xFF555555; + + pax_buf_t icon_python; + pax_decode_png_buf(&icon_python, (void*) python_png_start, python_png_end - python_png_start, PAX_BUF_32_8888ARGB, 0); + menu_set_icon(menu, &icon_python); + + pax_buf_t icon_hatchery; + pax_decode_png_buf(&icon_hatchery, (void*) hatchery_png_start, hatchery_png_end - hatchery_png_start, PAX_BUF_32_8888ARGB, 0); + + populate_menu(menu); + menu_insert_item_icon(menu, "Python Hatchery", NULL, (void*) strdup("dashboard.installer"), -1, &icon_hatchery); + // menu_insert_item(menu, "Home", NULL, (void*) strdup("dashboard.home"), -1); + // menu_insert_item(menu, "Launcher", NULL, (void*) strdup("dashboard.launcher"), -1); + // menu_insert_item(menu, "About", NULL, (void*) strdup("dashboard.other.about"), -1); + + char* app_to_start = NULL; + bool render = true; + bool render_help = true; + bool quit = false; + while (!quit) { + rp2040_input_message_t buttonMessage = {0}; + if (xQueueReceive(button_queue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) { + if (buttonMessage.state) { + switch (buttonMessage.input) { + case RP2040_INPUT_JOYSTICK_DOWN: + menu_navigate_next(menu); + render = true; + break; + case RP2040_INPUT_JOYSTICK_UP: + menu_navigate_previous(menu); + render = true; + break; + case RP2040_INPUT_BUTTON_HOME: + case RP2040_INPUT_BUTTON_BACK: + quit = true; + break; + case RP2040_INPUT_BUTTON_ACCEPT: + case RP2040_INPUT_JOYSTICK_PRESS: + case RP2040_INPUT_BUTTON_SELECT: + case RP2040_INPUT_BUTTON_START: + app_to_start = (char*) menu_get_callback_args(menu, menu_get_position(menu)); + break; + default: + break; + } + } + } + + if (render_help) { + const pax_font_t* font = pax_get_font("saira regular"); + pax_background(pax_buffer, 0xFFFFFF); + pax_noclip(pax_buffer); + pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 18, "[A] start app [B] back"); + render_help = false; + } + + if (render) { + menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF491d88); + ili9341_write(ili9341, pax_buffer->buf); + render = false; + } + + if (app_to_start != NULL) { + display_boot_screen(pax_buffer, ili9341, "Starting app..."); + start_python_app(app_to_start); + app_to_start = NULL; + render = true; + render_help = true; + } + } + + for (size_t index = 0; index < menu_get_length(menu); index++) { + pax_buf_t* icon = menu_get_icon(menu, index); + if (icon != NULL) pax_buf_destroy(icon); + free(menu_get_callback_args(menu, index)); + } + + menu_free(menu); + pax_buf_destroy(&icon_python); + pax_buf_destroy(&icon_hatchery); +} diff --git a/main/menus/python.h b/main/menus/python.h new file mode 100644 index 0000000..52a97ff --- /dev/null +++ b/main/menus/python.h @@ -0,0 +1,9 @@ +#include +#include +#include +#include + +#include "ili9341.h" +#include "pax_gfx.h" + +void menu_python(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341); diff --git a/main/menus/settings.c b/main/menus/settings.c index d426d79..b784bba 100644 --- a/main/menus/settings.c +++ b/main/menus/settings.c @@ -4,14 +4,15 @@ #include #include #include +#include #include #include #include -#include #include "appfs.h" #include "appfs_wrapper.h" #include "bootscreen.h" +#include "graphics_wrapper.h" #include "hardware.h" #include "ili9341.h" #include "menu.h" @@ -24,17 +25,16 @@ #include "wifi_connect.h" #include "wifi_ota.h" #include "wifi_test.h" -#include "graphics_wrapper.h" static void edit_nickname(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { nvs_handle_t handle; - esp_err_t res = nvs_open("owner", NVS_READWRITE, &handle); + esp_err_t res = nvs_open("owner", NVS_READWRITE, &handle); if (res != ESP_OK) return; char nickname[128] = {0}; size_t size = 0; - res = nvs_get_str(handle, "nickname", NULL, &size); + res = nvs_get_str(handle, "nickname", NULL, &size); if ((res == ESP_OK) && (size <= sizeof(nickname) - 1)) { res = nvs_get_str(handle, "nickname", nickname, &size); if (res != ESP_OK) { @@ -42,8 +42,9 @@ static void edit_nickname(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI93 } } - bool accepted = keyboard(buttonQueue, pax_buffer, ili9341, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "Nickname", "Press HOME to cancel", nickname, sizeof(nickname) - 1); - + bool accepted = keyboard(buttonQueue, pax_buffer, ili9341, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "Nickname", "Press HOME to cancel", + nickname, sizeof(nickname) - 1); + if (accepted) { nvs_set_str(handle, "nickname", nickname); } @@ -53,7 +54,16 @@ static void edit_nickname(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI93 extern const uint8_t settings_png_start[] asm("_binary_settings_png_start"); extern const uint8_t settings_png_end[] asm("_binary_settings_png_end"); -typedef enum action { ACTION_NONE, ACTION_BACK, ACTION_WIFI, ACTION_OTA, ACTION_RP2040_BL, ACTION_UNINSTALL, ACTION_WIFI_TEST, ACTION_NICKNAME } menu_settings_action_t; +typedef enum action { + ACTION_NONE, + ACTION_BACK, + ACTION_WIFI, + ACTION_OTA, + ACTION_RP2040_BL, + ACTION_UNINSTALL, + ACTION_WIFI_TEST, + ACTION_NICKNAME +} menu_settings_action_t; void render_settings_help(pax_buf_t* pax_buffer) { const pax_font_t* font = pax_get_font("saira regular"); @@ -85,7 +95,7 @@ void menu_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili menu_insert_item(menu, "Test WiFi connection", NULL, (void*) ACTION_WIFI_TEST, -1); menu_insert_item(menu, "Firmware update", NULL, (void*) ACTION_OTA, -1); menu_insert_item(menu, "Flash RP2040 firmware", NULL, (void*) ACTION_RP2040_BL, -1); - //menu_insert_item(menu, "Uninstall app", NULL, (void*) ACTION_UNINSTALL, -1); + // menu_insert_item(menu, "Uninstall app", NULL, (void*) ACTION_UNINSTALL, -1); bool render = true; menu_settings_action_t action = ACTION_NONE; diff --git a/main/menus/start.c b/main/menus/start.c index 66000e1..b432a8b 100644 --- a/main/menus/start.c +++ b/main/menus/start.c @@ -8,8 +8,6 @@ #include #include -#include "appfs.h" -#include "appfs_wrapper.h" #include "bootscreen.h" #include "dev.h" #include "hardware.h" @@ -18,12 +16,12 @@ #include "launcher.h" #include "math.h" #include "menu.h" +#include "nametag.h" #include "pax_codecs.h" #include "pax_gfx.h" +#include "python.h" #include "rp2040.h" #include "settings.h" -#include "nametag.h" -#include "rtc_memory.h" extern const uint8_t home_png_start[] asm("_binary_home_png_start"); extern const uint8_t home_png_end[] asm("_binary_home_png_end"); @@ -93,8 +91,8 @@ void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili934 menu_set_icon(menu, &icon_home); menu_insert_item_icon(menu, "Name tag", NULL, (void*) ACTION_NAMETAG, -1, &icon_tag); menu_insert_item_icon(menu, "ESP32 apps", NULL, (void*) ACTION_APPS, -1, &icon_apps); - menu_insert_item_icon(menu, "FPGA apps", NULL, (void*) ACTION_FPGA, -1, &icon_bitstream); menu_insert_item_icon(menu, "BadgePython apps", NULL, (void*) ACTION_PYTHON, -1, &icon_python); + menu_insert_item_icon(menu, "FPGA apps", NULL, (void*) ACTION_FPGA, -1, &icon_bitstream); menu_insert_item_icon(menu, "Hatchery", NULL, (void*) ACTION_HATCHERY, -1, &icon_hatchery); menu_insert_item_icon(menu, "Development tools", NULL, (void*) ACTION_DEV, -1, &icon_dev); menu_insert_item_icon(menu, "Settings", NULL, (void*) ACTION_SETTINGS, -1, &icon_settings); @@ -188,14 +186,7 @@ void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili934 } else if (action == ACTION_DEV) { menu_dev(buttonQueue, pax_buffer, ili9341); } else if (action == ACTION_PYTHON) { - // Test - appfs_handle_t appfs_fd = appfsOpen("python"); - if (appfs_fd != APPFS_INVALID_FD) { - rtc_memory_string_write("dashboard.other.about"); - appfs_boot_app(appfs_fd); - } else { - printf("Python not installed, can't start BadgePython app!\n"); - } + menu_python(buttonQueue, pax_buffer, ili9341); } action = ACTION_NONE; render = true; diff --git a/main/menus/wifi.c b/main/menus/wifi.c index a2c33f8..0e9a936 100644 --- a/main/menus/wifi.c +++ b/main/menus/wifi.c @@ -63,24 +63,12 @@ typedef enum action { ACTION_PHASE2_CHAP, } menu_wifi_action_t; -static const char *wifi_auth_names[] = { - "None", - "WEP", - "WPA1", - "WPA2", - "WPA1/2", - "WPA2 Ent", - "WPA3", - "WPA2/3", - "WAPI", +static const char* wifi_auth_names[] = { + "None", "WEP", "WPA1", "WPA2", "WPA1/2", "WPA2 Ent", "WPA3", "WPA2/3", "WAPI", }; -static const char *wifi_phase2_names[] = { - "EAP", - "MSCHAPv2", - "MSCHAP", - "PAP", - "CHAP", +static const char* wifi_phase2_names[] = { + "EAP", "MSCHAPv2", "MSCHAP", "PAP", "CHAP", }; void render_wifi_help(pax_buf_t* pax_buffer) { @@ -221,7 +209,8 @@ void wifi_show(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341 pax_noclip(pax_buffer); pax_background(pax_buffer, 0xFFFFFF); if (authmode == WIFI_AUTH_WPA2_ENTERPRISE) { - snprintf(buffer, sizeof(buffer), "WiFi SSID:\n %s\nSecurity:\n WPA2 Ent + %s\nUsername:\n %s\nPassword:\n %s", ssid, wifi_phase2_names[phase2], username, password); + snprintf(buffer, sizeof(buffer), "WiFi SSID:\n %s\nSecurity:\n WPA2 Ent + %s\nUsername:\n %s\nPassword:\n %s", ssid, wifi_phase2_names[phase2], + username, password); } else { snprintf(buffer, sizeof(buffer), "WiFi SSID:\n %s\nSecurity:\n %s\nWiFi password:\n %s", ssid, wifi_auth_names[authmode], password); } diff --git a/main/nametag.c b/main/nametag.c index 098fac1..d18bbc9 100644 --- a/main/nametag.c +++ b/main/nametag.c @@ -1,21 +1,22 @@ +#include "nametag.h" + +#include #include #include +#include #include +#include #include #include #include #include #include #include -#include -#include -#include -#include "nametag.h" -#include "nvs.h" #include "hardware.h" -#include "pax_gfx.h" #include "ili9341.h" +#include "nvs.h" +#include "pax_gfx.h" #include "rp2040.h" #include "wifi_connect.h" @@ -27,27 +28,27 @@ static void show_name(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 * // Shows the name tag. // Will fall into deep sleep if left alone for long enough. -void show_nametag(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { +void show_nametag(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341) { // Open NVS. nvs_handle_t handle; - esp_err_t res = nvs_open("owner", NVS_READWRITE, &handle); - + esp_err_t res = nvs_open("owner", NVS_READWRITE, &handle); + // Read nickname. size_t required = 0; - res = nvs_get_str(handle, "nickname", NULL, &required); + res = nvs_get_str(handle, "nickname", NULL, &required); char *buffer; if (res) { ESP_LOGE(TAG, "Error reading nickname: %s", esp_err_to_name(res)); buffer = strdup("Fancy Name!"); } else { - buffer = malloc(required + 1); + buffer = malloc(required + 1); buffer[required] = 0; - res = nvs_get_str(handle, "nickname", buffer, &required); + res = nvs_get_str(handle, "nickname", buffer, &required); if (res) { *buffer = 0; } } - + // Schedule sleep time. uint64_t sleep_time = esp_timer_get_time() / 1000 + SLEEP_DELAY; ESP_LOGI(TAG, "Scheduled sleep in %d millis", SLEEP_DELAY); @@ -56,7 +57,7 @@ void show_nametag(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9 // Display the name. show_name(buttonQueue, pax_buffer, ili9341, buffer); // Await buttons. - if (xQueueReceive(buttonQueue, &msg, pdMS_TO_TICKS(SLEEP_DELAY+10))) { + if (xQueueReceive(buttonQueue, &msg, pdMS_TO_TICKS(SLEEP_DELAY + 10))) { // Check for go back buttons. if (msg.input == RP2040_INPUT_BUTTON_HOME && msg.state) { goto exit; @@ -73,8 +74,8 @@ void show_nametag(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9 goto exit; } } - - exit: + +exit: free(buffer); nvs_close(handle); } @@ -82,43 +83,33 @@ void show_nametag(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9 // Show them names. static void show_name(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341, const char *name) { const pax_font_t *font = pax_get_font("saira condensed"); - + // Set name scale. - float scale = font->default_size; - pax_vec1_t dims = pax_text_size(font, scale, name); + float scale = font->default_size; + pax_vec1_t dims = pax_text_size(font, scale, name); if (dims.x > pax_buffer->width) { scale *= pax_buffer->width / dims.x; dims = pax_text_size(font, scale, name); } - + // Center vertically. pax_background(pax_buffer, 0); - pax_center_text( - pax_buffer, -1, - font, scale, - pax_buffer->width / 2, (pax_buffer->height - dims.y) / 2, - name - ); + pax_center_text(pax_buffer, -1, font, scale, pax_buffer->width / 2, (pax_buffer->height - dims.y) / 2, name); ili9341_write(ili9341, pax_buffer->buf); } // TODO: Place the ESP32 in sleep with button wakeup. static void place_in_sleep(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9341 *ili9341) { ESP_LOGW(TAG, "About to enter sleep!"); - + // Notify the user of the slumber. const pax_font_t *font = pax_get_font("saira regular"); - pax_draw_text( - pax_buffer, -1, - font, font->default_size, - 5, pax_buffer->height - 5 - font->default_size, - "Sleeping..." - ); + pax_draw_text(pax_buffer, -1, font, font->default_size, 5, pax_buffer->height - 5 - font->default_size, "Sleeping..."); ili9341_write(ili9341, pax_buffer->buf); - + // TODO: Power off peripherals to conserve power. - - #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP + +#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP // Deep sleep if we can wake from it. // Set wakeup pins. uint64_t mask = 1 << GPIO_INT_RP2040; @@ -129,8 +120,8 @@ static void place_in_sleep(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9 fflush(stderr); vTaskDelay(pdMS_TO_TICKS(100)); esp_deep_sleep_start(); - - #else + +#else // Light sleep because we can't wake from deep sleep. // Disable WiFi. wifi_disconnect_and_disable(); @@ -149,6 +140,6 @@ static void place_in_sleep(xQueueHandle buttonQueue, pax_buf_t *pax_buffer, ILI9 // Consume the button event, if any. rp2040_input_message_t msg; xQueueReceive(buttonQueue, &msg, pdMS_TO_TICKS(10)); - - #endif + +#endif } diff --git a/main/rtc_memory.c b/main/rtc_memory.c index 35f72ed..7264587 100644 --- a/main/rtc_memory.c +++ b/main/rtc_memory.c @@ -1,58 +1,59 @@ +#include "rtc_memory.h" + +#include #include #include #include +#include #include #include -#include -#include -#include "rtc_memory.h" #define RTC_MEM_INT_SIZE 64 #define RTC_MEM_STR_SIZE 512 -static int *const rtc_mem_int = (int *const) (RTC_SLOW_MEM + CONFIG_ESP32_ULP_COPROC_RESERVE_MEM); +static int *const rtc_mem_int = (int *const) (RTC_SLOW_MEM + CONFIG_ESP32_ULP_COPROC_RESERVE_MEM); static uint16_t *const rtc_mem_int_crc = (uint16_t *const) (rtc_mem_int + (sizeof(int) * RTC_MEM_INT_SIZE)); -static char *const rtc_mem_str = (char *const) (rtc_mem_int_crc + sizeof(uint16_t)); +static char *const rtc_mem_str = (char *const) (rtc_mem_int_crc + sizeof(uint16_t)); static uint16_t *const rtc_mem_str_crc = (uint16_t *const) (rtc_mem_str + (RTC_MEM_STR_SIZE * sizeof(char))); esp_err_t rtc_memory_int_write(int pos, int val) { if (pos >= RTC_MEM_INT_SIZE) return ESP_FAIL; rtc_mem_int[pos] = val; - *rtc_mem_int_crc = crc16_le(0, (uint8_t const *)rtc_mem_int, RTC_MEM_INT_SIZE*sizeof(int)); + *rtc_mem_int_crc = crc16_le(0, (uint8_t const *) rtc_mem_int, RTC_MEM_INT_SIZE * sizeof(int)); return ESP_OK; } -esp_err_t rtc_memory_int_read(int pos, int* val) { +esp_err_t rtc_memory_int_read(int pos, int *val) { if (pos >= RTC_MEM_INT_SIZE) return ESP_FAIL; - if (*rtc_mem_int_crc != crc16_le(0, (uint8_t const *)rtc_mem_int, RTC_MEM_INT_SIZE*sizeof(int))) return ESP_FAIL; + if (*rtc_mem_int_crc != crc16_le(0, (uint8_t const *) rtc_mem_int, RTC_MEM_INT_SIZE * sizeof(int))) return ESP_FAIL; *val = rtc_mem_int[pos]; return ESP_OK; } -esp_err_t rtc_memory_string_write(const char* str) { +esp_err_t rtc_memory_string_write(const char *str) { if (strlen(str) >= RTC_MEM_STR_SIZE) return ESP_FAIL; - memset(rtc_mem_str, 0, RTC_MEM_STR_SIZE*sizeof(char)); + memset(rtc_mem_str, 0, RTC_MEM_STR_SIZE * sizeof(char)); strcpy(rtc_mem_str, str); - *rtc_mem_str_crc = crc16_le(0, (uint8_t const *)rtc_mem_str, RTC_MEM_STR_SIZE); + *rtc_mem_str_crc = crc16_le(0, (uint8_t const *) rtc_mem_str, RTC_MEM_STR_SIZE); printf("RTC memory @ %p written, CRC %04X\n", rtc_mem_str, *rtc_mem_str_crc); return ESP_OK; } -esp_err_t rtc_memory_string_read(const char** str) { - printf("RTC memory @ %p read\n", rtc_mem_str); - uint16_t crc = crc16_le(0, (uint8_t const *)rtc_mem_str, RTC_MEM_STR_SIZE); +esp_err_t rtc_memory_string_read(const char **str) { + printf("RTC memory @ %p read\n", rtc_mem_str); + uint16_t crc = crc16_le(0, (uint8_t const *) rtc_mem_str, RTC_MEM_STR_SIZE); if (*rtc_mem_str_crc != crc) { - printf("RTC memory @ %p invalid %04X != %04x\n", rtc_mem_str, *rtc_mem_str_crc, crc); - return ESP_FAIL; - } - printf("RTC memory @ %p valid: %s\n", rtc_mem_str, rtc_mem_str); + printf("RTC memory @ %p invalid %04X != %04x\n", rtc_mem_str, *rtc_mem_str_crc, crc); + return ESP_FAIL; + } + printf("RTC memory @ %p valid: %s\n", rtc_mem_str, rtc_mem_str); *str = rtc_mem_str; return ESP_OK; } esp_err_t rtc_memory_clear() { - memset(rtc_mem_int, 0, RTC_MEM_INT_SIZE*sizeof(int)); - memset(rtc_mem_str, 0, RTC_MEM_STR_SIZE*sizeof(char)); + memset(rtc_mem_int, 0, RTC_MEM_INT_SIZE * sizeof(int)); + memset(rtc_mem_str, 0, RTC_MEM_STR_SIZE * sizeof(char)); *rtc_mem_int_crc = 0; *rtc_mem_str_crc = 0; return ESP_OK; diff --git a/main/system_wrapper.c b/main/system_wrapper.c index 21a29ec..605f319 100644 --- a/main/system_wrapper.c +++ b/main/system_wrapper.c @@ -2,11 +2,14 @@ #include #include +#include #include #include #include #include +#include "rp2040.h" + void restart() { /*for (int i = 3; i >= 0; i--) { printf("Restarting in %d seconds...\n", i); @@ -17,3 +20,38 @@ void restart() { fflush(stdout); esp_restart(); } + +bool wait_for_button(xQueueHandle buttonQueue) { + while (1) { + rp2040_input_message_t buttonMessage = {0}; + if (xQueueReceive(buttonQueue, &buttonMessage, 1000 / portTICK_PERIOD_MS) == pdTRUE) { + uint8_t pin = buttonMessage.input; + bool value = buttonMessage.state; + if (value) { + if (pin == RP2040_INPUT_BUTTON_BACK) { + return false; + } + if (pin == RP2040_INPUT_BUTTON_ACCEPT) { + return true; + } + } + } + } +} + +uint8_t* load_file_to_ram(FILE* fd) { + fseek(fd, 0, SEEK_END); + size_t fsize = ftell(fd); + fseek(fd, 0, SEEK_SET); + uint8_t* file = malloc(fsize); + if (file == NULL) return NULL; + fread(file, fsize, 1, fd); + return file; +} + +size_t get_file_size(FILE* fd) { + fseek(fd, 0, SEEK_END); + size_t fsize = ftell(fd); + fseek(fd, 0, SEEK_SET); + return fsize; +}