Merge pull request #55 from badgeteam/renze/factory
Factory test, theming and proper fix for appfs corruption
|
@ -1,4 +1,8 @@
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
|
||||||
|
set(PROJECT_NAME "MCH2022 launcher")
|
||||||
|
set(PROJECT_VER "0.1")
|
||||||
|
|
||||||
project(main)
|
project(main)
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,10 @@ idf_component_register(
|
||||||
"menus/wifi.c"
|
"menus/wifi.c"
|
||||||
"uninstall.c"
|
"uninstall.c"
|
||||||
"file_browser.c"
|
"file_browser.c"
|
||||||
|
"test_common.c"
|
||||||
|
"factory_test.c"
|
||||||
|
"animation.c"
|
||||||
|
"button_test.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
"include"
|
"include"
|
||||||
"menus"
|
"menus"
|
||||||
|
@ -30,4 +34,37 @@ idf_component_register(
|
||||||
${project_dir}/resources/boot.snd
|
${project_dir}/resources/boot.snd
|
||||||
${project_dir}/resources/mch2022_logo.png
|
${project_dir}/resources/mch2022_logo.png
|
||||||
${project_dir}/resources/logo_screen.png
|
${project_dir}/resources/logo_screen.png
|
||||||
|
${project_dir}/resources/icons/dev.png
|
||||||
|
${project_dir}/resources/icons/home.png
|
||||||
|
${project_dir}/resources/icons/settings.png
|
||||||
|
${project_dir}/resources/icons/apps.png
|
||||||
|
${project_dir}/resources/icons/hatchery.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_1.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_2.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_3.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_4.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_5.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_6.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_7.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_8.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_9.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_10.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_11.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_12.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_13.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_14.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_15.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_16.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_17.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_18.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_19.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_20.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_21.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_22.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_23.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_24.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_25.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_26.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_27.png
|
||||||
|
${project_dir}/resources/animation/animation_frame_28.png
|
||||||
)
|
)
|
||||||
|
|
167
main/animation.c
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include <driver/gpio.h>
|
||||||
|
#include "pax_gfx.h"
|
||||||
|
#include "pax_codecs.h"
|
||||||
|
#include "ili9341.h"
|
||||||
|
#include "ws2812.h"
|
||||||
|
#include "hardware.h"
|
||||||
|
|
||||||
|
extern const uint8_t animation_frame_1_start[] asm("_binary_animation_frame_1_png_start");
|
||||||
|
extern const uint8_t animation_frame_1_end[] asm("_binary_animation_frame_1_png_end");
|
||||||
|
extern const uint8_t animation_frame_2_start[] asm("_binary_animation_frame_2_png_start");
|
||||||
|
extern const uint8_t animation_frame_2_end[] asm("_binary_animation_frame_2_png_end");
|
||||||
|
extern const uint8_t animation_frame_3_start[] asm("_binary_animation_frame_3_png_start");
|
||||||
|
extern const uint8_t animation_frame_3_end[] asm("_binary_animation_frame_3_png_end");
|
||||||
|
extern const uint8_t animation_frame_4_start[] asm("_binary_animation_frame_4_png_start");
|
||||||
|
extern const uint8_t animation_frame_4_end[] asm("_binary_animation_frame_4_png_end");
|
||||||
|
extern const uint8_t animation_frame_5_start[] asm("_binary_animation_frame_5_png_start");
|
||||||
|
extern const uint8_t animation_frame_5_end[] asm("_binary_animation_frame_5_png_end");
|
||||||
|
extern const uint8_t animation_frame_6_start[] asm("_binary_animation_frame_6_png_start");
|
||||||
|
extern const uint8_t animation_frame_6_end[] asm("_binary_animation_frame_6_png_end");
|
||||||
|
extern const uint8_t animation_frame_7_start[] asm("_binary_animation_frame_7_png_start");
|
||||||
|
extern const uint8_t animation_frame_7_end[] asm("_binary_animation_frame_7_png_end");
|
||||||
|
extern const uint8_t animation_frame_8_start[] asm("_binary_animation_frame_8_png_start");
|
||||||
|
extern const uint8_t animation_frame_8_end[] asm("_binary_animation_frame_8_png_end");
|
||||||
|
extern const uint8_t animation_frame_9_start[] asm("_binary_animation_frame_9_png_start");
|
||||||
|
extern const uint8_t animation_frame_9_end[] asm("_binary_animation_frame_9_png_end");
|
||||||
|
extern const uint8_t animation_frame_10_start[] asm("_binary_animation_frame_10_png_start");
|
||||||
|
extern const uint8_t animation_frame_10_end[] asm("_binary_animation_frame_10_png_end");
|
||||||
|
extern const uint8_t animation_frame_11_start[] asm("_binary_animation_frame_11_png_start");
|
||||||
|
extern const uint8_t animation_frame_11_end[] asm("_binary_animation_frame_11_png_end");
|
||||||
|
extern const uint8_t animation_frame_12_start[] asm("_binary_animation_frame_12_png_start");
|
||||||
|
extern const uint8_t animation_frame_12_end[] asm("_binary_animation_frame_12_png_end");
|
||||||
|
extern const uint8_t animation_frame_13_start[] asm("_binary_animation_frame_13_png_start");
|
||||||
|
extern const uint8_t animation_frame_13_end[] asm("_binary_animation_frame_13_png_end");
|
||||||
|
extern const uint8_t animation_frame_14_start[] asm("_binary_animation_frame_14_png_start");
|
||||||
|
extern const uint8_t animation_frame_14_end[] asm("_binary_animation_frame_14_png_end");
|
||||||
|
extern const uint8_t animation_frame_15_start[] asm("_binary_animation_frame_15_png_start");
|
||||||
|
extern const uint8_t animation_frame_15_end[] asm("_binary_animation_frame_15_png_end");
|
||||||
|
extern const uint8_t animation_frame_16_start[] asm("_binary_animation_frame_16_png_start");
|
||||||
|
extern const uint8_t animation_frame_16_end[] asm("_binary_animation_frame_16_png_end");
|
||||||
|
extern const uint8_t animation_frame_17_start[] asm("_binary_animation_frame_17_png_start");
|
||||||
|
extern const uint8_t animation_frame_17_end[] asm("_binary_animation_frame_17_png_end");
|
||||||
|
extern const uint8_t animation_frame_18_start[] asm("_binary_animation_frame_18_png_start");
|
||||||
|
extern const uint8_t animation_frame_18_end[] asm("_binary_animation_frame_18_png_end");
|
||||||
|
extern const uint8_t animation_frame_19_start[] asm("_binary_animation_frame_19_png_start");
|
||||||
|
extern const uint8_t animation_frame_19_end[] asm("_binary_animation_frame_19_png_end");
|
||||||
|
extern const uint8_t animation_frame_20_start[] asm("_binary_animation_frame_20_png_start");
|
||||||
|
extern const uint8_t animation_frame_20_end[] asm("_binary_animation_frame_20_png_end");
|
||||||
|
extern const uint8_t animation_frame_21_start[] asm("_binary_animation_frame_21_png_start");
|
||||||
|
extern const uint8_t animation_frame_21_end[] asm("_binary_animation_frame_21_png_end");
|
||||||
|
extern const uint8_t animation_frame_22_start[] asm("_binary_animation_frame_22_png_start");
|
||||||
|
extern const uint8_t animation_frame_22_end[] asm("_binary_animation_frame_22_png_end");
|
||||||
|
extern const uint8_t animation_frame_23_start[] asm("_binary_animation_frame_23_png_start");
|
||||||
|
extern const uint8_t animation_frame_23_end[] asm("_binary_animation_frame_23_png_end");
|
||||||
|
extern const uint8_t animation_frame_24_start[] asm("_binary_animation_frame_24_png_start");
|
||||||
|
extern const uint8_t animation_frame_24_end[] asm("_binary_animation_frame_24_png_end");
|
||||||
|
extern const uint8_t animation_frame_25_start[] asm("_binary_animation_frame_25_png_start");
|
||||||
|
extern const uint8_t animation_frame_25_end[] asm("_binary_animation_frame_25_png_end");
|
||||||
|
extern const uint8_t animation_frame_26_start[] asm("_binary_animation_frame_26_png_start");
|
||||||
|
extern const uint8_t animation_frame_26_end[] asm("_binary_animation_frame_26_png_end");
|
||||||
|
extern const uint8_t animation_frame_27_start[] asm("_binary_animation_frame_27_png_start");
|
||||||
|
extern const uint8_t animation_frame_27_end[] asm("_binary_animation_frame_27_png_end");
|
||||||
|
extern const uint8_t animation_frame_28_start[] asm("_binary_animation_frame_28_png_start");
|
||||||
|
extern const uint8_t animation_frame_28_end[] asm("_binary_animation_frame_28_png_end");
|
||||||
|
|
||||||
|
const uint8_t* animation_frames[] = {
|
||||||
|
animation_frame_1_start,
|
||||||
|
animation_frame_2_start,
|
||||||
|
animation_frame_3_start,
|
||||||
|
animation_frame_4_start,
|
||||||
|
animation_frame_5_start,
|
||||||
|
animation_frame_6_start,
|
||||||
|
animation_frame_7_start,
|
||||||
|
animation_frame_8_start,
|
||||||
|
animation_frame_9_start,
|
||||||
|
animation_frame_10_start,
|
||||||
|
animation_frame_11_start,
|
||||||
|
animation_frame_12_start,
|
||||||
|
animation_frame_13_start,
|
||||||
|
animation_frame_14_start,
|
||||||
|
animation_frame_15_start,
|
||||||
|
animation_frame_16_start,
|
||||||
|
animation_frame_17_start,
|
||||||
|
animation_frame_18_start,
|
||||||
|
animation_frame_19_start,
|
||||||
|
animation_frame_20_start,
|
||||||
|
animation_frame_21_start,
|
||||||
|
animation_frame_22_start,
|
||||||
|
animation_frame_23_start,
|
||||||
|
animation_frame_24_start,
|
||||||
|
animation_frame_25_start,
|
||||||
|
animation_frame_26_start,
|
||||||
|
animation_frame_27_start,
|
||||||
|
animation_frame_28_start
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t* animation_frames_end[] = {
|
||||||
|
animation_frame_1_end,
|
||||||
|
animation_frame_2_end,
|
||||||
|
animation_frame_3_end,
|
||||||
|
animation_frame_4_end,
|
||||||
|
animation_frame_5_end,
|
||||||
|
animation_frame_6_end,
|
||||||
|
animation_frame_7_end,
|
||||||
|
animation_frame_8_end,
|
||||||
|
animation_frame_9_end,
|
||||||
|
animation_frame_10_end,
|
||||||
|
animation_frame_11_end,
|
||||||
|
animation_frame_12_end,
|
||||||
|
animation_frame_13_end,
|
||||||
|
animation_frame_14_end,
|
||||||
|
animation_frame_15_end,
|
||||||
|
animation_frame_16_end,
|
||||||
|
animation_frame_17_end,
|
||||||
|
animation_frame_18_end,
|
||||||
|
animation_frame_19_end,
|
||||||
|
animation_frame_20_end,
|
||||||
|
animation_frame_21_end,
|
||||||
|
animation_frame_22_end,
|
||||||
|
animation_frame_23_end,
|
||||||
|
animation_frame_24_end,
|
||||||
|
animation_frame_25_end,
|
||||||
|
animation_frame_26_end,
|
||||||
|
animation_frame_27_end,
|
||||||
|
animation_frame_28_end
|
||||||
|
};
|
||||||
|
|
||||||
|
void display_animation(pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
|
|
||||||
|
gpio_set_direction(GPIO_SD_PWR, GPIO_MODE_OUTPUT);
|
||||||
|
gpio_set_level(GPIO_SD_PWR, 1);
|
||||||
|
ws2812_init(GPIO_LED_DATA);
|
||||||
|
uint8_t led_data[15] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
ws2812_send_data(led_data, sizeof(led_data));
|
||||||
|
|
||||||
|
pax_noclip(pax_buffer);
|
||||||
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
|
|
||||||
|
for (uint8_t frame = 0; frame < 28; frame++) {
|
||||||
|
pax_buf_t image;
|
||||||
|
pax_decode_png_buf(&image, (void*) animation_frames[frame], animation_frames_end[frame] - animation_frames[frame], PAX_BUF_16_565RGB, 0);
|
||||||
|
pax_draw_image(pax_buffer, &image, 0, 0);
|
||||||
|
pax_buf_destroy(&image);
|
||||||
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
|
uint8_t brightness = (frame > 14) ? (frame - 14) : (0);
|
||||||
|
led_data[1] = brightness;
|
||||||
|
led_data[3] = brightness;
|
||||||
|
led_data[8] = brightness;
|
||||||
|
led_data[9] = brightness / 2;
|
||||||
|
led_data[10] = brightness / 2;
|
||||||
|
led_data[14] = brightness;
|
||||||
|
ws2812_send_data(led_data, sizeof(led_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t brightness = 14; brightness < 50; brightness++) {
|
||||||
|
led_data[1] = brightness;
|
||||||
|
led_data[3] = brightness;
|
||||||
|
led_data[8] = brightness;
|
||||||
|
led_data[9] = brightness / 2;
|
||||||
|
led_data[10] = brightness / 2;
|
||||||
|
led_data[14] = brightness;
|
||||||
|
ws2812_send_data(led_data, sizeof(led_data));
|
||||||
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,15 +72,24 @@ void appfs_store_app(pax_buf_t* pax_buffer, ILI9341* ili9341, char* path, char*
|
||||||
|
|
||||||
res = appfsCreateFile(label, app_size, &handle);
|
res = appfsCreateFile(label, app_size, &handle);
|
||||||
if (res != ESP_OK) {
|
if (res != ESP_OK) {
|
||||||
display_boot_screen(pax_buffer, ili9341, "Failed to create on AppFS");
|
display_boot_screen(pax_buffer, ili9341, "Failed to create file");
|
||||||
ESP_LOGE(TAG, "Failed to create file on AppFS (%d)", res);
|
ESP_LOGE(TAG, "Failed to create file on AppFS (%d)", res);
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
free(app);
|
free(app);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int roundedSize=(app_size+(SPI_FLASH_MMU_PAGE_SIZE-1))&(~(SPI_FLASH_MMU_PAGE_SIZE-1));
|
||||||
|
res = appfsErase(handle, 0, roundedSize);
|
||||||
|
if (res != ESP_OK) {
|
||||||
|
display_boot_screen(pax_buffer, ili9341, "Failed to erase file");
|
||||||
|
ESP_LOGE(TAG, "Failed to erase file on AppFS (%d)", res);
|
||||||
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
|
free(app);
|
||||||
|
return;
|
||||||
|
}
|
||||||
res = appfsWrite(handle, 0, app, app_size);
|
res = appfsWrite(handle, 0, app, app_size);
|
||||||
if (res != ESP_OK) {
|
if (res != ESP_OK) {
|
||||||
display_boot_screen(pax_buffer, ili9341, "Failed to write to AppFS");
|
display_boot_screen(pax_buffer, ili9341, "Failed to write file");
|
||||||
ESP_LOGE(TAG, "Failed to write to file on AppFS (%d)", res);
|
ESP_LOGE(TAG, "Failed to write to file on AppFS (%d)", res);
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
free(app);
|
free(app);
|
||||||
|
|
106
main/button_test.c
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include <freertos/queue.h>
|
||||||
|
#include "ili9341.h"
|
||||||
|
#include "pax_gfx.h"
|
||||||
|
#include "rp2040.h"
|
||||||
|
|
||||||
|
void test_buttons(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
|
bool render = true;
|
||||||
|
bool quit = false;
|
||||||
|
|
||||||
|
bool btn_joy_down = false;
|
||||||
|
bool btn_joy_up = false;
|
||||||
|
bool btn_joy_left = false;
|
||||||
|
bool btn_joy_right = false;
|
||||||
|
bool btn_joy_press = false;
|
||||||
|
bool btn_home = false;
|
||||||
|
bool btn_menu = false;
|
||||||
|
bool btn_select = false;
|
||||||
|
bool btn_start = false;
|
||||||
|
bool btn_accept = false;
|
||||||
|
bool btn_back = false;
|
||||||
|
|
||||||
|
while (!quit) {
|
||||||
|
rp2040_input_message_t buttonMessage = {0};
|
||||||
|
if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) {
|
||||||
|
uint8_t pin = buttonMessage.input;
|
||||||
|
bool value = buttonMessage.state;
|
||||||
|
render = true;
|
||||||
|
switch(pin) {
|
||||||
|
case RP2040_INPUT_JOYSTICK_DOWN:
|
||||||
|
btn_joy_down = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_JOYSTICK_UP:
|
||||||
|
btn_joy_up = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_JOYSTICK_LEFT:
|
||||||
|
btn_joy_left = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_JOYSTICK_RIGHT:
|
||||||
|
btn_joy_right = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_JOYSTICK_PRESS:
|
||||||
|
btn_joy_press = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_BUTTON_HOME:
|
||||||
|
btn_home = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_BUTTON_MENU:
|
||||||
|
btn_menu = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_BUTTON_SELECT:
|
||||||
|
btn_select = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_BUTTON_START:
|
||||||
|
btn_start = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_BUTTON_ACCEPT:
|
||||||
|
btn_accept = value;
|
||||||
|
break;
|
||||||
|
case RP2040_INPUT_BUTTON_BACK:
|
||||||
|
btn_back = value;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (render) {
|
||||||
|
pax_noclip(pax_buffer);
|
||||||
|
pax_background(pax_buffer, 0x325aa8);
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*0, "Press HOME + START to exit");
|
||||||
|
char buffer[64];
|
||||||
|
snprintf(buffer, sizeof(buffer), "JOY DOWN %s", btn_joy_down ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*1, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "JOY UP %s", btn_joy_up ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*2, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "JOY LEFT %s", btn_joy_left ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*3, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "JOY RIGHT %s", btn_joy_right ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*4, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "JOY PRESS %s", btn_joy_press ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*5, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "BTN HOME %s", btn_home ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*6, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "BTN MENU %s", btn_menu ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*7, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "BTN SELECT %s", btn_select ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*8, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "BTN START %s", btn_start ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*9, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "BTN A %s", btn_accept ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*10, buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "BTN B %s", btn_back ? "PRESSED" : "released");
|
||||||
|
pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*11, buffer);
|
||||||
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
|
render = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btn_home && btn_start) {
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
174
main/factory_test.c
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/queue.h>
|
||||||
|
#include <driver/gpio.h>
|
||||||
|
#include "hardware.h"
|
||||||
|
#include "ili9341.h"
|
||||||
|
#include "ice40.h"
|
||||||
|
#include "rp2040.h"
|
||||||
|
#include "fpga_test.h"
|
||||||
|
#include "pax_gfx.h"
|
||||||
|
#include "test_common.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "ws2812.h"
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
|
static const char *TAG = "factory";
|
||||||
|
|
||||||
|
/* Test routines */
|
||||||
|
|
||||||
|
bool test_rp2040_init(uint32_t* rc) {
|
||||||
|
esp_err_t res = bsp_rp2040_init();
|
||||||
|
*rc = (uint32_t) res;
|
||||||
|
return (res == ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_ice40_init(uint32_t* rc) {
|
||||||
|
esp_err_t res = bsp_ice40_init();
|
||||||
|
*rc = (uint32_t) res;
|
||||||
|
return (res == ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_bno055_init(uint32_t* rc) {
|
||||||
|
esp_err_t res = bsp_bno055_init();
|
||||||
|
*rc = (uint32_t) res;
|
||||||
|
return (res == ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_bme680_init(uint32_t* rc) {
|
||||||
|
esp_err_t res = bsp_bme680_init();
|
||||||
|
*rc = (uint32_t) res;
|
||||||
|
return (res == ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_stuck_buttons(uint32_t* rc) {
|
||||||
|
RP2040* rp2040 = get_rp2040();
|
||||||
|
uint16_t state;
|
||||||
|
esp_err_t res = rp2040_read_buttons(rp2040, &state);
|
||||||
|
if (res != ESP_OK) {
|
||||||
|
*rc = 0xFFFFFFFF;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
state &= ~(1 << RP2040_INPUT_FPGA_CDONE); // Ignore FPGA CDONE
|
||||||
|
|
||||||
|
*rc = state;
|
||||||
|
|
||||||
|
return (state == 0x0000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_sd_power(uint32_t* rc) {
|
||||||
|
*rc = 0x00000000;
|
||||||
|
// Init all GPIO pins for SD card and LED
|
||||||
|
if (gpio_reset_pin(GPIO_SD_PWR) != ESP_OK) return false;
|
||||||
|
if (gpio_set_direction(GPIO_SD_PWR, GPIO_MODE_INPUT) != ESP_OK) return false;
|
||||||
|
if (gpio_reset_pin(GPIO_SD_CMD) != ESP_OK) return false;
|
||||||
|
if (gpio_set_direction(GPIO_SD_CMD, GPIO_MODE_INPUT) != ESP_OK) return false;
|
||||||
|
if (gpio_reset_pin(GPIO_SD_CLK) != ESP_OK) return false;
|
||||||
|
if (gpio_set_direction(GPIO_SD_CLK, GPIO_MODE_INPUT) != ESP_OK) return false;
|
||||||
|
if (gpio_reset_pin(GPIO_SD_D0) != ESP_OK) return false;
|
||||||
|
if (gpio_set_direction(GPIO_SD_D0, GPIO_MODE_INPUT) != ESP_OK) return false;
|
||||||
|
if (gpio_reset_pin(GPIO_LED_DATA) != ESP_OK) return false;
|
||||||
|
if (gpio_set_direction(GPIO_LED_DATA, GPIO_MODE_INPUT) != ESP_OK) return false;
|
||||||
|
|
||||||
|
if (gpio_get_level(GPIO_SD_PWR)) {*rc = 0x01; return false;} // Check that power enable is pulled low
|
||||||
|
|
||||||
|
if (gpio_set_direction(GPIO_SD_PWR, GPIO_MODE_OUTPUT) != ESP_OK) return false;
|
||||||
|
if (gpio_set_level(GPIO_SD_PWR, 1) != ESP_OK) return false;
|
||||||
|
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
// SD pins should be pulled high
|
||||||
|
if (!gpio_get_level(GPIO_SD_CMD)) {*rc = 0x02; return false;}
|
||||||
|
if (!gpio_get_level(GPIO_SD_CLK)) {*rc = 0x04; return false;}
|
||||||
|
if (!gpio_get_level(GPIO_SD_D0)) {*rc = 0x08; return false;}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run_basic_tests(pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
|
const pax_font_t *font;
|
||||||
|
int line = 0;
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
/* Screen init */
|
||||||
|
font = pax_get_font("sky mono");
|
||||||
|
|
||||||
|
pax_noclip(pax_buffer);
|
||||||
|
pax_background(pax_buffer, 0x8060f0);
|
||||||
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
|
|
||||||
|
/* Run mandatory tests */
|
||||||
|
RUN_TEST_MANDATORY("RP2040", test_rp2040_init);
|
||||||
|
RUN_TEST_MANDATORY("ICE40", test_ice40_init);
|
||||||
|
RUN_TEST_MANDATORY("BNO055", test_bno055_init);
|
||||||
|
RUN_TEST_MANDATORY("BME680", test_bme680_init);
|
||||||
|
RUN_TEST_MANDATORY("STUCK BUTTONS", test_stuck_buttons);
|
||||||
|
RUN_TEST_MANDATORY("SD/LED POWER", test_sd_power);
|
||||||
|
|
||||||
|
|
||||||
|
error:
|
||||||
|
/* Fail result on screen */
|
||||||
|
if (!ok) pax_draw_text(pax_buffer, 0xffff0000, font, 36, 0, 20*line, "FAIL");
|
||||||
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t led_green[15] = {50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0};
|
||||||
|
const uint8_t led_red[15] = {0, 50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0};
|
||||||
|
const uint8_t led_blue[15] = {0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0, 50};
|
||||||
|
|
||||||
|
void factory_test(pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
|
uint8_t factory_test_done = nvs_get_u8_default("system", "factory_test", 0);
|
||||||
|
if (!factory_test_done) {
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Factory test start");
|
||||||
|
|
||||||
|
result = run_basic_tests(pax_buffer, ili9341);
|
||||||
|
|
||||||
|
gpio_set_direction(GPIO_SD_PWR, GPIO_MODE_OUTPUT);
|
||||||
|
gpio_set_level(GPIO_SD_PWR, 1);
|
||||||
|
ws2812_init(GPIO_LED_DATA);
|
||||||
|
if (result) {
|
||||||
|
ws2812_send_data(led_blue, sizeof(led_blue));
|
||||||
|
} else {
|
||||||
|
ws2812_send_data(led_red, sizeof(led_red));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) goto test_end;
|
||||||
|
|
||||||
|
RP2040* rp2040 = get_rp2040();
|
||||||
|
|
||||||
|
result = run_fpga_tests(rp2040->queue, pax_buffer, ili9341);
|
||||||
|
if (!result) {
|
||||||
|
ws2812_send_data(led_red, sizeof(led_red));
|
||||||
|
goto test_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ws2812_send_data(led_green, sizeof(led_green));
|
||||||
|
|
||||||
|
// Wait for the operator to unplug the badge
|
||||||
|
test_end:
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
esp_err_t res = nvs_set_u8_fixed("system", "factory_test", 1);
|
||||||
|
if (res != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to store test result %d\n", res);
|
||||||
|
result = false;
|
||||||
|
ws2812_send_data(led_red, sizeof(led_red));
|
||||||
|
pax_noclip(pax_buffer);
|
||||||
|
pax_background(pax_buffer, 0xa85a32);
|
||||||
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (result) play_bootsound();
|
||||||
|
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "rp2040.h"
|
#include "rp2040.h"
|
||||||
#include "appfs_wrapper.h"
|
#include "appfs_wrapper.h"
|
||||||
|
#include "bootscreen.h"
|
||||||
|
|
||||||
static const char *TAG = "file browser";
|
static const char *TAG = "file browser";
|
||||||
|
|
||||||
|
@ -104,20 +105,24 @@ void find_parent_dir(char* path, char* parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, const char* initial_path) {
|
void file_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, const char* initial_path) {
|
||||||
|
display_boot_screen(pax_buffer, ili9341, "Please wait...");
|
||||||
char path[512] = {0};
|
char path[512] = {0};
|
||||||
strncpy(path, initial_path, sizeof(path));
|
strncpy(path, initial_path, sizeof(path));
|
||||||
while (true) {
|
while (true) {
|
||||||
menu_t* menu = menu_alloc(path);
|
menu_t* menu = menu_alloc(path, 20, 18);
|
||||||
DIR* dir = opendir(path);
|
DIR* dir = opendir(path);
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to open directory %s", path);
|
if (path[0] != 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open directory %s", path);
|
||||||
|
display_boot_screen(pax_buffer, ili9341, "Failed to open directory");
|
||||||
|
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
file_browser_menu_args_t* pd_args = malloc(sizeof(file_browser_menu_args_t));
|
file_browser_menu_args_t* pd_args = malloc(sizeof(file_browser_menu_args_t));
|
||||||
pd_args->type = 'd';
|
pd_args->type = 'd';
|
||||||
find_parent_dir(path, pd_args->path);
|
find_parent_dir(path, pd_args->path);
|
||||||
printf("Parent dir: %s\n", pd_args->path);
|
|
||||||
menu_insert_item(menu, "../", NULL, pd_args, -1);
|
menu_insert_item(menu, "../", NULL, pd_args, -1);
|
||||||
|
|
||||||
while ((ent = readdir(dir)) != NULL) {
|
while ((ent = readdir(dir)) != NULL) {
|
||||||
|
@ -134,8 +139,6 @@ void file_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9
|
||||||
args->type = 'd';
|
args->type = 'd';
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%c %s %s\r\n", args->type, ent->d_name, args->path);
|
|
||||||
|
|
||||||
snprintf(args->label, sizeof(args->label), "%s%s", ent->d_name, (args->type == 'd') ? "/" : "");
|
snprintf(args->label, sizeof(args->label), "%s%s", ent->d_name, (args->type == 'd') ? "/" : "");
|
||||||
menu_insert_item(menu, args->label, NULL, args, -1);
|
menu_insert_item(menu, args->label, NULL, args, -1);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +189,8 @@ void file_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9
|
||||||
if (renderbg) {
|
if (renderbg) {
|
||||||
pax_background(pax_buffer, 0xFFFFFF);
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
pax_noclip(pax_buffer);
|
pax_noclip(pax_buffer);
|
||||||
pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 5, 240 - 19, "[A] install [B] back");
|
const pax_font_t *font = pax_get_font("saira regular");
|
||||||
|
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] install [B] back");
|
||||||
renderbg = false;
|
renderbg = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
135
main/fpga_test.c
|
@ -11,6 +11,7 @@
|
||||||
#include "rp2040.h"
|
#include "rp2040.h"
|
||||||
#include "fpga_test.h"
|
#include "fpga_test.h"
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
|
#include "test_common.h"
|
||||||
|
|
||||||
extern const uint8_t fpga_selftest_bin_start[] asm("_binary_fpga_selftest_bin_start");
|
extern const uint8_t fpga_selftest_bin_start[] asm("_binary_fpga_selftest_bin_start");
|
||||||
extern const uint8_t fpga_selftest_bin_end[] asm("_binary_fpga_selftest_bin_end");
|
extern const uint8_t fpga_selftest_bin_end[] asm("_binary_fpga_selftest_bin_end");
|
||||||
|
@ -114,7 +115,8 @@ static bool soc_message(ICE40* ice40, uint8_t cmd, uint32_t param, uint32_t *res
|
||||||
|
|
||||||
/* Test routines */
|
/* Test routines */
|
||||||
|
|
||||||
static bool test_bitstream_load(ICE40* ice40, uint32_t *rc) {
|
static bool test_bitstream_load(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
esp_err_t res;
|
esp_err_t res;
|
||||||
|
|
||||||
res = ice40_load_bitstream(ice40, fpga_selftest_bin_start, fpga_selftest_bin_end - fpga_selftest_bin_start);
|
res = ice40_load_bitstream(ice40, fpga_selftest_bin_start, fpga_selftest_bin_end - fpga_selftest_bin_start);
|
||||||
|
@ -127,7 +129,7 @@ static bool test_bitstream_load(ICE40* ice40, uint32_t *rc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_spi_loopback_one(ICE40* ice40) {
|
static bool _test_spi_loopback_one(ICE40* ice40) {
|
||||||
esp_err_t res;
|
esp_err_t res;
|
||||||
uint8_t data_tx[257];
|
uint8_t data_tx[257];
|
||||||
uint8_t data_rx[258];
|
uint8_t data_rx[258];
|
||||||
|
@ -219,12 +221,14 @@ static bool test_spi_loopback_one(ICE40* ice40) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_spi_loopback(ICE40* ice40, uint32_t *rc) {
|
static bool test_spi_loopback(uint32_t *rc) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
|
|
||||||
/* Run test 256 times */
|
/* Run test 256 times */
|
||||||
for (i=0; i<256; i++) {
|
for (i=0; i<256; i++) {
|
||||||
if (!test_spi_loopback_one(ice40))
|
if (!_test_spi_loopback_one(ice40))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +243,9 @@ static bool test_spi_loopback(ICE40* ice40, uint32_t *rc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_soc_loopback(ICE40 *ice40, uint32_t *rc) {
|
static bool test_soc_loopback(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
|
|
||||||
/* Execute command */
|
/* Execute command */
|
||||||
if (!soc_message(ice40, SOC_CMD_PING, SOC_CMD_PING_PARAM, rc, 0)) {
|
if (!soc_message(ice40, SOC_CMD_PING, SOC_CMD_PING_PARAM, rc, 0)) {
|
||||||
*rc = -1;
|
*rc = -1;
|
||||||
|
@ -255,7 +261,9 @@ static bool test_soc_loopback(ICE40 *ice40, uint32_t *rc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_uart_loopback(ICE40* ice40, uint32_t *rc) {
|
static bool test_uart_loopback(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
|
|
||||||
/* Enable loopback mode of RP2040 */
|
/* Enable loopback mode of RP2040 */
|
||||||
rp2040_set_fpga_loopback(get_rp2040(), true, true);
|
rp2040_set_fpga_loopback(get_rp2040(), true, true);
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
@ -273,7 +281,9 @@ static bool test_uart_loopback(ICE40* ice40, uint32_t *rc) {
|
||||||
return *rc == SOC_RESP_OK;
|
return *rc == SOC_RESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_psram(ICE40* ice40, uint32_t *rc) {
|
static bool test_psram(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
|
|
||||||
/* Execute command */
|
/* Execute command */
|
||||||
if (!soc_message(ice40, SOC_CMD_PSRAM_TEST, 0, rc, pdMS_TO_TICKS(1000))) {
|
if (!soc_message(ice40, SOC_CMD_PSRAM_TEST, 0, rc, pdMS_TO_TICKS(1000))) {
|
||||||
*rc = -1;
|
*rc = -1;
|
||||||
|
@ -284,7 +294,9 @@ static bool test_psram(ICE40* ice40, uint32_t *rc) {
|
||||||
return *rc == SOC_RESP_OK;
|
return *rc == SOC_RESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_irq_n(ICE40* ice40, uint32_t *rc) {
|
static bool test_irq_n(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
|
|
||||||
esp_err_t res;
|
esp_err_t res;
|
||||||
|
|
||||||
/* Set pin as input */
|
/* Set pin as input */
|
||||||
|
@ -327,7 +339,8 @@ static bool test_irq_n(ICE40* ice40, uint32_t *rc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_lcd_mode(ICE40* ice40, uint32_t *rc) {
|
static bool test_lcd_mode(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
esp_err_t res;
|
esp_err_t res;
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
|
@ -371,7 +384,8 @@ static bool test_lcd_mode(ICE40* ice40, uint32_t *rc) {
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_pmod_open(ICE40* ice40, uint32_t *rc) {
|
static bool test_pmod_open(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
/* Execute command */
|
/* Execute command */
|
||||||
if (!soc_message(ice40, SOC_CMD_PMOD_OPEN_TEST, 0, rc, 0)) {
|
if (!soc_message(ice40, SOC_CMD_PMOD_OPEN_TEST, 0, rc, 0)) {
|
||||||
*rc = -1;
|
*rc = -1;
|
||||||
|
@ -382,7 +396,9 @@ static bool test_pmod_open(ICE40* ice40, uint32_t *rc) {
|
||||||
return *rc == SOC_RESP_OK;
|
return *rc == SOC_RESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_pmod_plug(ICE40* ice40, uint32_t *rc) {
|
static bool test_pmod_plug(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
|
|
||||||
/* Execute command */
|
/* Execute command */
|
||||||
if (!soc_message(ice40, SOC_CMD_PMOD_PLUG_TEST, 0, rc, 0)) {
|
if (!soc_message(ice40, SOC_CMD_PMOD_PLUG_TEST, 0, rc, 0)) {
|
||||||
*rc = -1;
|
*rc = -1;
|
||||||
|
@ -393,7 +409,9 @@ static bool test_pmod_plug(ICE40* ice40, uint32_t *rc) {
|
||||||
return *rc == SOC_RESP_OK;
|
return *rc == SOC_RESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_lcd_init(ICE40* ice40, uint32_t *rc) {
|
static bool test_lcd_init(uint32_t *rc) {
|
||||||
|
ICE40* ice40 = get_ice40();
|
||||||
|
|
||||||
/* Execute command */
|
/* Execute command */
|
||||||
if (!soc_message(ice40, SOC_CMD_LCD_INIT_TEST, 0, rc, 0)) {
|
if (!soc_message(ice40, SOC_CMD_LCD_INIT_TEST, 0, rc, 0)) {
|
||||||
*rc = -1;
|
*rc = -1;
|
||||||
|
@ -404,83 +422,8 @@ static bool test_lcd_init(ICE40* ice40, uint32_t *rc) {
|
||||||
return *rc == SOC_RESP_OK;
|
return *rc == SOC_RESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool run_fpga_tests(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
typedef bool (*test_fn)(ICE40 *ice40, uint32_t *rc);
|
ICE40* ice40 = get_ice40();
|
||||||
|
|
||||||
|
|
||||||
static bool wait_button(xQueueHandle buttonQueue) {
|
|
||||||
rp2040_input_message_t buttonMessage = {0};
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (xQueueReceive(buttonQueue, &buttonMessage, 0) == pdTRUE) {
|
|
||||||
if (buttonMessage.state) {
|
|
||||||
switch(buttonMessage.input) {
|
|
||||||
case RP2040_INPUT_BUTTON_HOME:
|
|
||||||
case RP2040_INPUT_BUTTON_MENU:
|
|
||||||
case RP2040_INPUT_BUTTON_BACK:
|
|
||||||
return false;
|
|
||||||
case RP2040_INPUT_BUTTON_ACCEPT:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool run_test(ICE40* ice40, pax_buf_t* pax_buffer, const pax_font_t *font, ILI9341* ili9341, int line,
|
|
||||||
const char *test_name, test_fn fn) {
|
|
||||||
bool rv;
|
|
||||||
uint32_t rc;
|
|
||||||
|
|
||||||
/* Test name */
|
|
||||||
pax_draw_text(pax_buffer, 0xffffffff, font, 18, 0, 20*line, test_name);
|
|
||||||
if (ili9341)
|
|
||||||
ili9341_write(ili9341, pax_buffer->buf);
|
|
||||||
|
|
||||||
/* Run the test */
|
|
||||||
rv = fn(ice40, &rc);
|
|
||||||
|
|
||||||
/* Display result */
|
|
||||||
if (!rv) {
|
|
||||||
/* Error */
|
|
||||||
char buf[10];
|
|
||||||
snprintf(buf, sizeof(buf), "%08x", rc);
|
|
||||||
pax_draw_text(pax_buffer, 0xffff0000, font, 18, 200, 20*line, buf);
|
|
||||||
} else {
|
|
||||||
/* OK ! */
|
|
||||||
pax_draw_text(pax_buffer, 0xff00ff00, font, 18, 200, 20*line, " OK");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ili9341)
|
|
||||||
ili9341_write(ili9341, pax_buffer->buf);
|
|
||||||
|
|
||||||
/* Pass through the 'OK' status */
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RUN_TEST(name, fn) do {\
|
|
||||||
ok &= run_test(ice40, pax_buffer, font, ili9341, line++, name, fn); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define RUN_TEST_MANDATORY(name, fn) do {\
|
|
||||||
if (!run_test(ice40, pax_buffer, font, ili9341, line++, name, fn)) { \
|
|
||||||
pax_draw_text(pax_buffer, 0xffff0000, font, 18, 0, 20*line, "Aborted"); \
|
|
||||||
ili9341_write(ili9341, pax_buffer->buf); \
|
|
||||||
ok = false; \
|
|
||||||
goto error; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define RUN_TEST_BLIND(name, fn) do {\
|
|
||||||
ok &= run_test(ice40, pax_buffer, font, NULL, line++, name, fn); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
bool run_fpga_tests(xQueueHandle buttonQueue, ICE40* ice40, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
|
||||||
const pax_font_t *font;
|
const pax_font_t *font;
|
||||||
int line = 0;
|
int line = 0;
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
@ -534,9 +477,7 @@ bool run_fpga_tests(xQueueHandle buttonQueue, ICE40* ice40, pax_buf_t* pax_buffe
|
||||||
soc_message(ice40, SOC_CMD_LCD_RGB_CYCLE_SET, 1, NULL, 0);
|
soc_message(ice40, SOC_CMD_LCD_RGB_CYCLE_SET, 1, NULL, 0);
|
||||||
|
|
||||||
/* Wait for button */
|
/* Wait for button */
|
||||||
if (!wait_button(buttonQueue)) {
|
RUN_TEST("LCD control", test_wait_for_response);
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stop LCD / RGB cycling */
|
/* Stop LCD / RGB cycling */
|
||||||
soc_message(ice40, SOC_CMD_LCD_RGB_CYCLE_SET, 0, NULL, 0);
|
soc_message(ice40, SOC_CMD_LCD_RGB_CYCLE_SET, 0, NULL, 0);
|
||||||
|
@ -550,9 +491,9 @@ error:
|
||||||
|
|
||||||
/* Pass / Fail result on screen */
|
/* Pass / Fail result on screen */
|
||||||
if (ok)
|
if (ok)
|
||||||
pax_draw_text(pax_buffer, 0xff00ff00, font, 36, 0, 20*line, "FPGA PASS");
|
pax_draw_text(pax_buffer, 0xff00ff00, font, 36, 0, 20*line, "PASS");
|
||||||
else
|
else
|
||||||
pax_draw_text(pax_buffer, 0xffff0000, font, 36, 0, 20*line, "FPGA FAIL");
|
pax_draw_text(pax_buffer, 0xffff0000, font, 36, 0, 20*line, "FAIL");
|
||||||
|
|
||||||
ili9341_write(ili9341, pax_buffer->buf);
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
|
|
||||||
|
@ -562,7 +503,7 @@ error:
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpga_test(xQueueHandle buttonQueue, ICE40* ice40, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
void fpga_test(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
run_fpga_tests(buttonQueue, ice40, pax_buffer, ili9341);
|
run_fpga_tests(buttonQueue, pax_buffer, ili9341);
|
||||||
wait_button(buttonQueue);
|
test_wait_for_response(NULL);
|
||||||
}
|
}
|
||||||
|
|
4
main/include/animation.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#include "pax_gfx.h"
|
||||||
|
#include "ili9341.h"
|
||||||
|
|
||||||
|
void display_animation(pax_buf_t* pax_buffer, ILI9341* ili9341);
|
9
main/include/button_test.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include <freertos/queue.h>
|
||||||
|
#include "ili9341.h"
|
||||||
|
#include "pax_gfx.h"
|
||||||
|
|
||||||
|
void test_buttons(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341);
|
10
main/include/factory_test.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include <freertos/queue.h>
|
||||||
|
#include "ili9341.h"
|
||||||
|
#include "pax_gfx.h"
|
||||||
|
|
||||||
|
void factory_test(pax_buf_t* pax_buffer, ILI9341* ili9341);
|
|
@ -10,4 +10,5 @@
|
||||||
#include "ice40.h"
|
#include "ice40.h"
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
|
|
||||||
void fpga_test(xQueueHandle buttonQueue, ICE40* ice40, pax_buf_t* pax_buffer, ILI9341* ili9341);
|
void fpga_test(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341);
|
||||||
|
bool run_fpga_tests(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341);
|
||||||
|
|
|
@ -17,6 +17,8 @@ typedef struct _menu_item {
|
||||||
menu_callback_t callback;
|
menu_callback_t callback;
|
||||||
void* callbackArgs;
|
void* callbackArgs;
|
||||||
|
|
||||||
|
pax_buf_t* icon;
|
||||||
|
|
||||||
// Linked list
|
// Linked list
|
||||||
struct _menu_item* previousItem;
|
struct _menu_item* previousItem;
|
||||||
struct _menu_item* nextItem;
|
struct _menu_item* nextItem;
|
||||||
|
@ -27,11 +29,27 @@ typedef struct menu {
|
||||||
menu_item_t* firstItem;
|
menu_item_t* firstItem;
|
||||||
size_t length;
|
size_t length;
|
||||||
size_t position;
|
size_t position;
|
||||||
|
float entry_height;
|
||||||
|
float text_height;
|
||||||
|
pax_buf_t* icon;
|
||||||
|
|
||||||
|
pax_col_t fgColor;
|
||||||
|
pax_col_t bgColor;
|
||||||
|
pax_col_t selectedItemColor;
|
||||||
|
pax_col_t bgTextColor;
|
||||||
|
pax_col_t borderColor;
|
||||||
|
pax_col_t titleColor;
|
||||||
|
pax_col_t titleBgColor;
|
||||||
|
pax_col_t scrollbarBgColor;
|
||||||
|
pax_col_t scrollbarFgColor;
|
||||||
|
|
||||||
} menu_t;
|
} menu_t;
|
||||||
|
|
||||||
menu_t* menu_alloc(const char* aTitle);
|
menu_t* menu_alloc(const char* aTitle, float arg_entry_height, float arg_text_height);
|
||||||
void menu_free(menu_t* aMenu);
|
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(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_remove_item(menu_t* aMenu, size_t aPosition);
|
||||||
bool menu_navigate_to(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_previous(menu_t* aMenu);
|
||||||
|
|
|
@ -6,3 +6,6 @@
|
||||||
#include "ice40.h"
|
#include "ice40.h"
|
||||||
|
|
||||||
esp_err_t nvs_init();
|
esp_err_t nvs_init();
|
||||||
|
esp_err_t nvs_get_str_fixed(const char* nvs_namespace, const char* key, char* target, size_t target_size, size_t* size);
|
||||||
|
uint8_t nvs_get_u8_default(const char* nvs_namespace, const char* key, uint8_t default_value);
|
||||||
|
esp_err_t nvs_set_u8_fixed(const char* nvs_namespace, const char* key, uint8_t value);
|
||||||
|
|
28
main/include/test_common.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "ili9341.h"
|
||||||
|
#include "pax_gfx.h"
|
||||||
|
|
||||||
|
typedef bool (*test_fn)(uint32_t *rc);
|
||||||
|
|
||||||
|
bool test_wait_for_response(uint32_t *rc);
|
||||||
|
bool run_test(pax_buf_t* pax_buffer, const pax_font_t *font, ILI9341* ili9341, int line, const char *test_name, test_fn fn);
|
||||||
|
|
||||||
|
#define RUN_TEST(name, fn) do {\
|
||||||
|
ok &= run_test(pax_buffer, font, ili9341, line++, name, fn); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RUN_TEST_MANDATORY(name, fn) do {\
|
||||||
|
if (!run_test(pax_buffer, font, ili9341, line++, name, fn)) { \
|
||||||
|
pax_draw_text(pax_buffer, 0xffff0000, font, 18, 0, 20*line, "Aborted"); \
|
||||||
|
ili9341_write(ili9341, pax_buffer->buf); \
|
||||||
|
ok = false; \
|
||||||
|
goto error; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RUN_TEST_BLIND(name, fn) do {\
|
||||||
|
ok &= run_test(pax_buffer, font, NULL, line++, name, fn); \
|
||||||
|
} while (0)
|
44
main/main.c
|
@ -15,7 +15,7 @@
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
#include "sdcard.h"
|
#include "sdcard.h"
|
||||||
#include "appfs.h"
|
#include "appfs.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
#include "rp2040.h"
|
#include "rp2040.h"
|
||||||
#include "rp2040bl.h"
|
#include "rp2040bl.h"
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@
|
||||||
|
|
||||||
#include "menus/start.h"
|
#include "menus/start.h"
|
||||||
|
|
||||||
|
#include "factory_test.h"
|
||||||
|
|
||||||
extern const uint8_t wallpaper_png_start[] asm("_binary_wallpaper_png_start");
|
extern const uint8_t wallpaper_png_start[] asm("_binary_wallpaper_png_start");
|
||||||
extern const uint8_t wallpaper_png_end[] asm("_binary_wallpaper_png_end");
|
extern const uint8_t wallpaper_png_end[] asm("_binary_wallpaper_png_end");
|
||||||
|
|
||||||
|
@ -70,6 +72,10 @@ void display_fatal_error(pax_buf_t* pax_buffer, ILI9341* ili9341, const char* li
|
||||||
void app_main(void) {
|
void app_main(void) {
|
||||||
esp_err_t res;
|
esp_err_t res;
|
||||||
|
|
||||||
|
const esp_app_desc_t *app_description = esp_ota_get_app_description();
|
||||||
|
ESP_LOGI(TAG, "App version: %s", app_description->version);
|
||||||
|
//ESP_LOGI(TAG, "Project name: %s", app_description->project_name);
|
||||||
|
|
||||||
/* Initialize memory */
|
/* Initialize memory */
|
||||||
uint8_t* framebuffer = heap_caps_malloc(ILI9341_BUFFER_SIZE, MALLOC_CAP_8BIT);
|
uint8_t* framebuffer = heap_caps_malloc(ILI9341_BUFFER_SIZE, MALLOC_CAP_8BIT);
|
||||||
if (framebuffer == NULL) {
|
if (framebuffer == NULL) {
|
||||||
|
@ -102,10 +108,18 @@ void app_main(void) {
|
||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
display_boot_screen(pax_buffer, ili9341, "Starting...");
|
/* Start NVS */
|
||||||
|
res = nvs_init();
|
||||||
|
if (res != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "NVS init failed: %d", res);
|
||||||
|
display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "NVS failed to initialize", "Flash may be corrupted", NULL);
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
|
|
||||||
audio_init();
|
audio_init();
|
||||||
|
|
||||||
|
display_boot_screen(pax_buffer, ili9341, "Starting...");
|
||||||
|
|
||||||
if (bsp_rp2040_init() != ESP_OK) {
|
if (bsp_rp2040_init() != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to initialize the RP2040 co-processor");
|
ESP_LOGE(TAG, "Failed to initialize the RP2040 co-processor");
|
||||||
display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "RP2040 co-processor error", NULL, NULL);
|
display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "RP2040 co-processor error", NULL, NULL);
|
||||||
|
@ -120,6 +134,8 @@ void app_main(void) {
|
||||||
|
|
||||||
rp2040_updater(rp2040, pax_buffer, ili9341); // Handle RP2040 firmware update & bootloader mode
|
rp2040_updater(rp2040, pax_buffer, ili9341); // Handle RP2040 firmware update & bootloader mode
|
||||||
|
|
||||||
|
factory_test(pax_buffer, ili9341);
|
||||||
|
|
||||||
/*uint8_t rp2040_uid[8];
|
/*uint8_t rp2040_uid[8];
|
||||||
if (rp2040_get_uid(rp2040, rp2040_uid) != ESP_OK) {
|
if (rp2040_get_uid(rp2040, rp2040_uid) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to get RP2040 UID");
|
ESP_LOGE(TAG, "Failed to get RP2040 UID");
|
||||||
|
@ -179,16 +195,6 @@ void app_main(void) {
|
||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
//display_boot_screen(pax_buffer, ili9341, "Initializing NVS...");
|
|
||||||
|
|
||||||
/* Start NVS */
|
|
||||||
res = nvs_init();
|
|
||||||
if (res != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "NVS init failed: %d", res);
|
|
||||||
display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "NVS failed to initialize", "Flash may be corrupted", NULL);
|
|
||||||
esp_restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
//display_boot_screen(pax_buffer, ili9341, "Initializing filesystem...");
|
//display_boot_screen(pax_buffer, ili9341, "Initializing filesystem...");
|
||||||
|
|
||||||
/* Start internal filesystem */
|
/* Start internal filesystem */
|
||||||
|
@ -217,12 +223,14 @@ void app_main(void) {
|
||||||
bool sdcard_ready = (res == ESP_OK);
|
bool sdcard_ready = (res == ESP_OK);
|
||||||
if (sdcard_ready) {
|
if (sdcard_ready) {
|
||||||
ESP_LOGI(TAG, "SD card filesystem mounted");
|
ESP_LOGI(TAG, "SD card filesystem mounted");
|
||||||
}
|
|
||||||
|
|
||||||
/* Start LEDs */
|
/* LED power is on: start LED driver and turn LEDs off */
|
||||||
ws2812_init(GPIO_LED_DATA);
|
ws2812_init(GPIO_LED_DATA);
|
||||||
uint8_t ledBuffer[15] = {50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0};
|
const uint8_t led_off[15] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
ws2812_send_data(ledBuffer, sizeof(ledBuffer));
|
ws2812_send_data(led_off, sizeof(led_off));
|
||||||
|
} else {
|
||||||
|
gpio_set_level(GPIO_SD_PWR, 0); // Disable power to LEDs and SD card
|
||||||
|
}
|
||||||
|
|
||||||
/* Start WiFi */
|
/* Start WiFi */
|
||||||
wifi_init();
|
wifi_init();
|
||||||
|
@ -232,7 +240,7 @@ void app_main(void) {
|
||||||
|
|
||||||
/* Launcher menu */
|
/* Launcher menu */
|
||||||
while (true) {
|
while (true) {
|
||||||
menu_start(rp2040->queue, pax_buffer, ili9341);
|
menu_start(rp2040->queue, pax_buffer, ili9341, app_description->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(framebuffer);
|
free(framebuffer);
|
||||||
|
|
97
main/menu.c
|
@ -1,9 +1,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
|
#include "pax_codecs.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
|
|
||||||
menu_t* menu_alloc(const char* aTitle) {
|
menu_t* menu_alloc(const char* aTitle, float arg_entry_height, float arg_text_height) {
|
||||||
if (aTitle == NULL) return NULL;
|
if (aTitle == NULL) return NULL;
|
||||||
menu_t* menu = malloc(sizeof(menu_t));
|
menu_t* menu = malloc(sizeof(menu_t));
|
||||||
if (menu == NULL) return NULL;
|
if (menu == NULL) return NULL;
|
||||||
|
@ -17,6 +18,20 @@ menu_t* menu_alloc(const char* aTitle) {
|
||||||
menu->firstItem = NULL;
|
menu->firstItem = NULL;
|
||||||
menu->length = 0;
|
menu->length = 0;
|
||||||
menu->position = 0;
|
menu->position = 0;
|
||||||
|
menu->entry_height = (arg_entry_height > 0) ? arg_entry_height : 20;
|
||||||
|
menu->text_height = (arg_text_height > 0) ? arg_text_height : (arg_entry_height - 2);
|
||||||
|
menu->icon = NULL;
|
||||||
|
|
||||||
|
menu->fgColor = 0xFF000000;
|
||||||
|
menu->bgColor = 0xFFFFFFFF;
|
||||||
|
menu->bgTextColor = 0xFFFFFFFF;
|
||||||
|
menu->selectedItemColor = 0xFF000000;
|
||||||
|
menu->borderColor = 0x88000000;
|
||||||
|
menu->titleColor = 0xFFFFFFFF;
|
||||||
|
menu->titleBgColor = 0xFF000000;
|
||||||
|
menu->scrollbarBgColor = 0xFFCCCCCC;
|
||||||
|
menu->scrollbarFgColor = 0xFF555555;
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +52,10 @@ void menu_free(menu_t* aMenu) {
|
||||||
free(aMenu);
|
free(aMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menu_set_icon(menu_t* aMenu, pax_buf_t* icon) {
|
||||||
|
aMenu->icon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
menu_item_t* _menu_find_item(menu_t* aMenu, size_t aPosition) {
|
menu_item_t* _menu_find_item(menu_t* aMenu, size_t aPosition) {
|
||||||
menu_item_t* currentItem = aMenu->firstItem;
|
menu_item_t* currentItem = aMenu->firstItem;
|
||||||
if (currentItem == NULL) return NULL;
|
if (currentItem == NULL) return NULL;
|
||||||
|
@ -66,11 +85,12 @@ bool menu_insert_item(menu_t* aMenu, const char* aLabel, menu_callback_t aCallba
|
||||||
newItem->label = malloc(labelSize);
|
newItem->label = malloc(labelSize);
|
||||||
if (newItem->label == NULL) {
|
if (newItem->label == NULL) {
|
||||||
free(newItem);
|
free(newItem);
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy(newItem->label, aLabel, labelSize);
|
memcpy(newItem->label, aLabel, labelSize);
|
||||||
newItem->callback = aCallback;
|
newItem->callback = aCallback;
|
||||||
newItem->callbackArgs = aCallbackArgs;
|
newItem->callbackArgs = aCallbackArgs;
|
||||||
|
newItem->icon = NULL;
|
||||||
if (aMenu->firstItem == NULL) {
|
if (aMenu->firstItem == NULL) {
|
||||||
newItem->nextItem = NULL;
|
newItem->nextItem = NULL;
|
||||||
newItem->previousItem = NULL;
|
newItem->previousItem = NULL;
|
||||||
|
@ -91,6 +111,21 @@ bool menu_insert_item(menu_t* aMenu, const char* aLabel, menu_callback_t aCallba
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool menu_insert_item_icon(menu_t* aMenu, const char* aLabel, menu_callback_t aCallback, void* aCallbackArgs, size_t aPosition, pax_buf_t* icon) {
|
||||||
|
if (!menu_insert_item(aMenu, aLabel, aCallback, aCallbackArgs, aPosition)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
menu_item_t* item;
|
||||||
|
if (aPosition >= aMenu->length - 1) {
|
||||||
|
item = _menu_find_last_item(aMenu);
|
||||||
|
} else {
|
||||||
|
item = _menu_find_item(aMenu, aPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
item->icon = icon;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool menu_remove_item(menu_t* aMenu, size_t aPosition) {
|
bool menu_remove_item(menu_t* aMenu, size_t aPosition) {
|
||||||
if (aMenu == NULL) return false; // Can't delete an item from a menu that doesn't exist
|
if (aMenu == NULL) return false; // Can't delete an item from a menu that doesn't exist
|
||||||
if (aMenu->length <= aPosition) return false; // Can't delete an item that doesn't exist
|
if (aMenu->length <= aPosition) return false; // Can't delete an item that doesn't exist
|
||||||
|
@ -175,17 +210,11 @@ 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) {
|
void menu_render(pax_buf_t *aBuffer, menu_t* aMenu, float aPosX, float aPosY, float aWidth, float aHeight, pax_col_t aColor) {
|
||||||
pax_col_t fgColor = aColor;
|
|
||||||
pax_col_t bgColor = 0xFFFFFFFF;
|
|
||||||
pax_col_t bgTextColor = 0xFFFFFFFF;
|
|
||||||
pax_col_t borderColor = 0x88000000;
|
|
||||||
pax_col_t titleColor = 0xFFFFFFFF;
|
|
||||||
pax_col_t titleBgColor = aColor;
|
|
||||||
pax_col_t scrollbarBgColor = 0xFFCCCCCC;
|
|
||||||
pax_col_t scrollbarFgColor = 0xFF555555;
|
|
||||||
const pax_font_t *font = pax_get_font("saira regular");
|
const pax_font_t *font = pax_get_font("saira regular");
|
||||||
|
|
||||||
float entry_height = 18 + 2;
|
float entry_height = aMenu->entry_height;//18 + 2;
|
||||||
|
float text_height = aMenu->text_height;
|
||||||
|
float text_offset = ((entry_height - text_height) / 2) + 1;
|
||||||
size_t maxItems = aHeight / entry_height;
|
size_t maxItems = aHeight / entry_height;
|
||||||
|
|
||||||
float posY = aPosY;
|
float posY = aPosY;
|
||||||
|
@ -193,12 +222,20 @@ void menu_render(pax_buf_t *aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl
|
||||||
pax_noclip(aBuffer);
|
pax_noclip(aBuffer);
|
||||||
|
|
||||||
if (maxItems > 1) {
|
if (maxItems > 1) {
|
||||||
|
float offsetX = 0;
|
||||||
|
if (aMenu->icon != NULL) {
|
||||||
|
offsetX = aMenu->icon->width;
|
||||||
|
}
|
||||||
|
|
||||||
maxItems--;
|
maxItems--;
|
||||||
pax_simple_rect(aBuffer, titleBgColor, aPosX, posY, aWidth, entry_height);
|
pax_simple_rect(aBuffer, aMenu->titleBgColor, aPosX, posY, aWidth, entry_height);
|
||||||
pax_simple_line(aBuffer, titleColor, aPosX + 1, aPosY + entry_height, aPosX + aWidth - 2, aPosY + entry_height - 1);
|
//pax_simple_line(aBuffer, aMenu->titleColor, aPosX + 1, aPosY + entry_height, aPosX + aWidth - 2, aPosY + entry_height - 1);
|
||||||
pax_clip(aBuffer, aPosX + 1, posY + 1, aWidth - 2, entry_height - 2);
|
pax_clip(aBuffer, aPosX + 1, posY + text_offset, aWidth - 2, text_height);
|
||||||
pax_draw_text(aBuffer, titleColor, font, entry_height - 2, aPosX + 1, posY + 1, aMenu->title);
|
pax_draw_text(aBuffer, aMenu->titleColor, font, text_height, aPosX + offsetX + 1, posY + text_offset, aMenu->title);
|
||||||
pax_noclip(aBuffer);
|
pax_noclip(aBuffer);
|
||||||
|
if (aMenu->icon != NULL) {
|
||||||
|
pax_draw_image(aBuffer, aMenu->icon, aPosX, posY);
|
||||||
|
}
|
||||||
posY += entry_height;
|
posY += entry_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,8 +244,8 @@ void menu_render(pax_buf_t *aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl
|
||||||
itemOffset = aMenu->position - maxItems + 1;
|
itemOffset = aMenu->position - maxItems + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pax_outline_rect(aBuffer, borderColor, aPosX, aPosY, aWidth, aHeight);
|
pax_outline_rect(aBuffer, aMenu->borderColor, aPosX, aPosY, aWidth, aHeight);
|
||||||
pax_simple_rect(aBuffer, bgColor, aPosX, posY, aWidth, aHeight - posY + aPosY);
|
pax_simple_rect(aBuffer, aMenu->bgColor, aPosX, posY, aWidth, aHeight - posY + aPosY);
|
||||||
|
|
||||||
for (size_t index = itemOffset; (index < itemOffset + maxItems) && (index < aMenu->length); index++) {
|
for (size_t index = itemOffset; (index < itemOffset + maxItems) && (index < aMenu->length); index++) {
|
||||||
menu_item_t* item = _menu_find_item(aMenu, index);
|
menu_item_t* item = _menu_find_item(aMenu, index);
|
||||||
|
@ -217,17 +254,27 @@ void menu_render(pax_buf_t *aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float iconWidth = 0;
|
||||||
|
if (item->icon != NULL) {
|
||||||
|
iconWidth = item->icon->width + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (index == aMenu->position) {
|
if (index == aMenu->position) {
|
||||||
pax_simple_rect(aBuffer, fgColor, aPosX + 1, posY, aWidth - 2, entry_height);
|
pax_simple_rect(aBuffer, aMenu->selectedItemColor, aPosX + 1, posY, aWidth - 2, entry_height);
|
||||||
pax_clip(aBuffer, aPosX + 1, posY + 1, aWidth - 4, entry_height - 2);
|
pax_clip(aBuffer, aPosX + 1, posY + text_offset, aWidth - 4, text_height);
|
||||||
pax_draw_text(aBuffer, bgTextColor, font, entry_height - 2, aPosX + 1, posY + 1, item->label);
|
pax_draw_text(aBuffer, aMenu->bgTextColor, font, text_height, aPosX + iconWidth + 1, posY + text_offset, item->label);
|
||||||
pax_noclip(aBuffer);
|
pax_noclip(aBuffer);
|
||||||
} else {
|
} else {
|
||||||
pax_simple_rect(aBuffer, bgColor, aPosX + 1, posY, aWidth - 2, entry_height);
|
pax_simple_rect(aBuffer, aMenu->bgColor, aPosX + 1, posY, aWidth - 2, entry_height);
|
||||||
pax_clip(aBuffer, aPosX + 1, posY + 1, aWidth - 4, entry_height - 2);
|
pax_clip(aBuffer, aPosX + 1, posY + text_offset, aWidth - 4, text_height);
|
||||||
pax_draw_text(aBuffer, fgColor, font, entry_height - 2, aPosX + 1, posY + 1, item->label);
|
pax_draw_text(aBuffer, aMenu->fgColor, font, text_height, aPosX + iconWidth + 1, posY + text_offset, item->label);
|
||||||
pax_noclip(aBuffer);
|
pax_noclip(aBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item->icon != NULL) {
|
||||||
|
pax_draw_image(aBuffer, item->icon, aPosX + 1, posY);
|
||||||
|
}
|
||||||
|
|
||||||
posY += entry_height;
|
posY += entry_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,8 +289,8 @@ void menu_render(pax_buf_t *aBuffer, menu_t* aMenu, float aPosX, float aPosY, fl
|
||||||
float scrollbarStart = scrollbarHeight * fractionStart;
|
float scrollbarStart = scrollbarHeight * fractionStart;
|
||||||
float scrollbarEnd = scrollbarHeight * fractionEnd;
|
float scrollbarEnd = scrollbarHeight * fractionEnd;
|
||||||
|
|
||||||
pax_simple_rect(aBuffer, scrollbarBgColor, aPosX + aWidth - 5, aPosY + entry_height - 1, 4, scrollbarHeight);
|
pax_simple_rect(aBuffer, aMenu->scrollbarBgColor, aPosX + aWidth - 5, aPosY + entry_height - 1, 4, scrollbarHeight);
|
||||||
pax_simple_rect(aBuffer, scrollbarFgColor, aPosX + aWidth - 5, aPosY + entry_height - 1 + scrollbarStart, 4, scrollbarEnd - scrollbarStart);
|
pax_simple_rect(aBuffer, aMenu->scrollbarFgColor, aPosX + aWidth - 5, aPosY + entry_height - 1 + scrollbarStart, 4, scrollbarEnd - scrollbarStart);
|
||||||
|
|
||||||
pax_noclip(aBuffer);
|
pax_noclip(aBuffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "appfs.h"
|
#include "appfs.h"
|
||||||
#include "ili9341.h"
|
#include "ili9341.h"
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
|
#include "pax_codecs.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "rp2040.h"
|
#include "rp2040.h"
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
|
@ -19,6 +20,11 @@
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "file_browser.h"
|
#include "file_browser.h"
|
||||||
#include "fpga_test.h"
|
#include "fpga_test.h"
|
||||||
|
#include "animation.h"
|
||||||
|
#include "button_test.h"
|
||||||
|
|
||||||
|
extern const uint8_t dev_png_start[] asm("_binary_dev_png_start");
|
||||||
|
extern const uint8_t dev_png_end[] asm("_binary_dev_png_end");
|
||||||
|
|
||||||
typedef enum action {
|
typedef enum action {
|
||||||
ACTION_NONE,
|
ACTION_NONE,
|
||||||
|
@ -27,21 +33,41 @@ typedef enum action {
|
||||||
ACTION_FPGA_TEST,
|
ACTION_FPGA_TEST,
|
||||||
ACTION_FILE_BROWSER,
|
ACTION_FILE_BROWSER,
|
||||||
ACTION_FILE_BROWSER_INT,
|
ACTION_FILE_BROWSER_INT,
|
||||||
|
ACTION_ANIMATION,
|
||||||
|
ACTION_BUTTON_TEST
|
||||||
} menu_dev_action_t;
|
} menu_dev_action_t;
|
||||||
|
|
||||||
void render_dev_help(pax_buf_t* pax_buffer) {
|
void render_dev_help(pax_buf_t* pax_buffer) {
|
||||||
const pax_font_t *font = pax_get_font("saira regular");
|
const pax_font_t *font = pax_get_font("saira regular");
|
||||||
pax_background(pax_buffer, 0xFFFFFF);
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
pax_noclip(pax_buffer);
|
pax_noclip(pax_buffer);
|
||||||
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] accept [B] back");
|
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 18, "[A] accept [B] back");
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_dev(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
void menu_dev(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
menu_t* menu = menu_alloc("Development tools");
|
menu_t* menu = menu_alloc("Development tools", 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_dev;
|
||||||
|
pax_decode_png_buf(&icon_dev, (void*) dev_png_start, dev_png_end - dev_png_start, PAX_BUF_32_8888ARGB, 0);
|
||||||
|
|
||||||
|
menu_set_icon(menu, &icon_dev);
|
||||||
|
|
||||||
menu_insert_item(menu, "FPGA download mode", NULL, (void*) ACTION_FPGA_DL, -1);
|
menu_insert_item(menu, "FPGA download mode", NULL, (void*) ACTION_FPGA_DL, -1);
|
||||||
menu_insert_item(menu, "FPGA selftest", NULL, (void*) ACTION_FPGA_TEST, -1);
|
menu_insert_item(menu, "FPGA selftest", NULL, (void*) ACTION_FPGA_TEST, -1);
|
||||||
menu_insert_item(menu, "File browser (SD card)", NULL, (void*) ACTION_FILE_BROWSER, -1);
|
menu_insert_item(menu, "File browser (SD card)", NULL, (void*) ACTION_FILE_BROWSER, -1);
|
||||||
menu_insert_item(menu, "File browser (internal)", NULL, (void*) ACTION_FILE_BROWSER_INT, -1);
|
menu_insert_item(menu, "File browser (internal)", NULL, (void*) ACTION_FILE_BROWSER_INT, -1);
|
||||||
|
menu_insert_item(menu, "Animation", NULL, (void*) ACTION_ANIMATION, -1);
|
||||||
|
menu_insert_item(menu, "Button test", NULL, (void*) ACTION_BUTTON_TEST, -1);
|
||||||
|
|
||||||
bool render = true;
|
bool render = true;
|
||||||
menu_dev_action_t action = ACTION_NONE;
|
menu_dev_action_t action = ACTION_NONE;
|
||||||
|
@ -86,7 +112,7 @@ void menu_dev(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (render) {
|
if (render) {
|
||||||
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF000000);
|
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF491d88);
|
||||||
ili9341_write(ili9341, pax_buffer->buf);
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
render = false;
|
render = false;
|
||||||
}
|
}
|
||||||
|
@ -95,11 +121,15 @@ void menu_dev(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341)
|
||||||
if (action == ACTION_FPGA_DL) {
|
if (action == ACTION_FPGA_DL) {
|
||||||
fpga_download(buttonQueue, get_ice40(), pax_buffer, ili9341);
|
fpga_download(buttonQueue, get_ice40(), pax_buffer, ili9341);
|
||||||
} else if (action == ACTION_FPGA_TEST) {
|
} else if (action == ACTION_FPGA_TEST) {
|
||||||
fpga_test(buttonQueue, get_ice40(), pax_buffer, ili9341);
|
fpga_test(buttonQueue, pax_buffer, ili9341);
|
||||||
} else if (action == ACTION_FILE_BROWSER) {
|
} else if (action == ACTION_FILE_BROWSER) {
|
||||||
file_browser(buttonQueue, pax_buffer, ili9341, "/sd");
|
file_browser(buttonQueue, pax_buffer, ili9341, "/sd");
|
||||||
} else if (action == ACTION_FILE_BROWSER_INT) {
|
} else if (action == ACTION_FILE_BROWSER_INT) {
|
||||||
file_browser(buttonQueue, pax_buffer, ili9341, "/internal");
|
file_browser(buttonQueue, pax_buffer, ili9341, "/internal");
|
||||||
|
} else if (action == ACTION_ANIMATION) {
|
||||||
|
display_animation(pax_buffer, ili9341);
|
||||||
|
} else if (action == ACTION_BUTTON_TEST) {
|
||||||
|
test_buttons(buttonQueue, pax_buffer, ili9341);
|
||||||
} else if (action == ACTION_BACK) {
|
} else if (action == ACTION_BACK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -110,4 +140,6 @@ void menu_dev(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341)
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_free(menu);
|
menu_free(menu);
|
||||||
|
|
||||||
|
pax_buf_destroy(&icon_dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,14 @@
|
||||||
#include "appfs.h"
|
#include "appfs.h"
|
||||||
#include "ili9341.h"
|
#include "ili9341.h"
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
|
#include "pax_codecs.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "rp2040.h"
|
#include "rp2040.h"
|
||||||
#include "appfs_wrapper.h"
|
#include "appfs_wrapper.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 enum {
|
typedef enum {
|
||||||
ACTION_NONE,
|
ACTION_NONE,
|
||||||
ACTION_APPFS,
|
ACTION_APPFS,
|
||||||
|
@ -26,7 +30,23 @@ typedef struct {
|
||||||
} menu_launcher_args_t;
|
} menu_launcher_args_t;
|
||||||
|
|
||||||
void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
menu_t* menu = menu_alloc("Apps");
|
menu_t* menu = menu_alloc("Apps", 34, 18);
|
||||||
|
|
||||||
|
menu->fgColor = 0xFF000000;
|
||||||
|
menu->bgColor = 0xFFFFFFFF;
|
||||||
|
menu->bgTextColor = 0xFFFFFFFF;
|
||||||
|
menu->selectedItemColor = 0xFFfa448c;
|
||||||
|
menu->borderColor = 0xFF491d88;
|
||||||
|
menu->titleColor = 0xFFfa448c;
|
||||||
|
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);
|
||||||
|
|
||||||
|
menu_set_icon(menu, &icon_apps);
|
||||||
|
|
||||||
const pax_font_t *font = pax_get_font("saira regular");
|
const pax_font_t *font = pax_get_font("saira regular");
|
||||||
|
|
||||||
appfs_handle_t appfs_fd = APPFS_INVALID_FD;
|
appfs_handle_t appfs_fd = APPFS_INVALID_FD;
|
||||||
|
@ -46,7 +66,7 @@ void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili
|
||||||
|
|
||||||
pax_background(pax_buffer, 0xFFFFFF);
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
pax_noclip(pax_buffer);
|
pax_noclip(pax_buffer);
|
||||||
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] start app [B] back");
|
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 18, "[A] start app [B] back");
|
||||||
|
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
|
|
||||||
|
@ -88,7 +108,7 @@ void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili
|
||||||
}
|
}
|
||||||
|
|
||||||
if (render) {
|
if (render) {
|
||||||
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF000000);
|
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF491d88);
|
||||||
ili9341_write(ili9341, pax_buffer->buf);
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
render = false;
|
render = false;
|
||||||
}
|
}
|
||||||
|
@ -110,4 +130,5 @@ void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_free(menu);
|
menu_free(menu);
|
||||||
|
pax_buf_destroy(&icon_apps);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "appfs.h"
|
#include "appfs.h"
|
||||||
#include "ili9341.h"
|
#include "ili9341.h"
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
|
#include "pax_codecs.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "rp2040.h"
|
#include "rp2040.h"
|
||||||
#include "appfs_wrapper.h"
|
#include "appfs_wrapper.h"
|
||||||
|
@ -21,6 +22,9 @@
|
||||||
#include "wifi.h"
|
#include "wifi.h"
|
||||||
#include "uninstall.h"
|
#include "uninstall.h"
|
||||||
|
|
||||||
|
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 {
|
typedef enum action {
|
||||||
ACTION_NONE,
|
ACTION_NONE,
|
||||||
ACTION_BACK,
|
ACTION_BACK,
|
||||||
|
@ -34,11 +38,27 @@ void render_settings_help(pax_buf_t* pax_buffer) {
|
||||||
const pax_font_t *font = pax_get_font("saira regular");
|
const pax_font_t *font = pax_get_font("saira regular");
|
||||||
pax_background(pax_buffer, 0xFFFFFF);
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
pax_noclip(pax_buffer);
|
pax_noclip(pax_buffer);
|
||||||
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] accept [B] back");
|
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 18, "[A] accept [B] back");
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
void menu_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
menu_t* menu = menu_alloc("Settings");
|
menu_t* menu = menu_alloc("Settings", 34, 18);
|
||||||
|
|
||||||
|
menu->fgColor = 0xFF000000;
|
||||||
|
menu->bgColor = 0xFFFFFFFF;
|
||||||
|
menu->bgTextColor = 0xFFFFFFFF;
|
||||||
|
menu->selectedItemColor = 0xFF491d88;
|
||||||
|
menu->borderColor = 0xFF43b5a0;
|
||||||
|
menu->titleColor = 0xFF491d88;
|
||||||
|
menu->titleBgColor = 0xFF43b5a0;
|
||||||
|
menu->scrollbarBgColor = 0xFFCCCCCC;
|
||||||
|
menu->scrollbarFgColor = 0xFF555555;
|
||||||
|
|
||||||
|
pax_buf_t icon_settings;
|
||||||
|
pax_decode_png_buf(&icon_settings, (void*) settings_png_start, settings_png_end - settings_png_start, PAX_BUF_32_8888ARGB, 0);
|
||||||
|
|
||||||
|
menu_set_icon(menu, &icon_settings);
|
||||||
|
|
||||||
menu_insert_item(menu, "WiFi configuration", NULL, (void*) ACTION_WIFI, -1);
|
menu_insert_item(menu, "WiFi configuration", NULL, (void*) ACTION_WIFI, -1);
|
||||||
menu_insert_item(menu, "Firmware update", NULL, (void*) ACTION_OTA, -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, "Flash RP2040 firmware", NULL, (void*) ACTION_RP2040_BL, -1);
|
||||||
|
@ -87,7 +107,7 @@ void menu_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili
|
||||||
}
|
}
|
||||||
|
|
||||||
if (render) {
|
if (render) {
|
||||||
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF000000);
|
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF491d88);
|
||||||
ili9341_write(ili9341, pax_buffer->buf);
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
render = false;
|
render = false;
|
||||||
}
|
}
|
||||||
|
@ -120,4 +140,5 @@ void menu_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_free(menu);
|
menu_free(menu);
|
||||||
|
pax_buf_destroy(&icon_settings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,37 +10,86 @@
|
||||||
#include "appfs.h"
|
#include "appfs.h"
|
||||||
#include "ili9341.h"
|
#include "ili9341.h"
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
|
#include "pax_codecs.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "rp2040.h"
|
#include "rp2040.h"
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
|
#include "bootscreen.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");
|
||||||
|
|
||||||
|
extern const uint8_t apps_png_start[] asm("_binary_apps_png_start");
|
||||||
|
extern const uint8_t apps_png_end[] asm("_binary_apps_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");
|
||||||
|
|
||||||
|
extern const uint8_t dev_png_start[] asm("_binary_dev_png_start");
|
||||||
|
extern const uint8_t dev_png_end[] asm("_binary_dev_png_end");
|
||||||
|
|
||||||
|
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 {
|
typedef enum action {
|
||||||
ACTION_NONE,
|
ACTION_NONE,
|
||||||
ACTION_APPS,
|
ACTION_APPS,
|
||||||
|
ACTION_HATCHERY,
|
||||||
ACTION_DEV,
|
ACTION_DEV,
|
||||||
ACTION_SETTINGS
|
ACTION_SETTINGS
|
||||||
} menu_start_action_t;
|
} menu_start_action_t;
|
||||||
|
|
||||||
void render_start_help(pax_buf_t* pax_buffer) {
|
void render_start_help(pax_buf_t* pax_buffer, const char* version) {
|
||||||
const pax_font_t *font = pax_get_font("saira regular");
|
const pax_font_t *font = pax_get_font("saira regular");
|
||||||
pax_background(pax_buffer, 0xFFFFFF);
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
pax_noclip(pax_buffer);
|
pax_noclip(pax_buffer);
|
||||||
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] accept");
|
pax_draw_text(pax_buffer, 0xFF491d88, font, 18, 5, 240 - 18, "[A] accept");
|
||||||
|
|
||||||
|
char version_text[64];
|
||||||
|
snprintf(version_text, sizeof(version_text), "v%s", version);
|
||||||
|
|
||||||
|
pax_vec1_t version_size = pax_text_size(font, 18, version_text);
|
||||||
|
pax_draw_text(pax_buffer, 0xFF491d88, font, 18, 320 - 5 - version_size.x, 240 - 18, version_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, const char* version) {
|
||||||
menu_t* menu = menu_alloc("Main menu");
|
menu_t* menu = menu_alloc("Main menu", 34, 18);
|
||||||
menu_insert_item(menu, "Apps", NULL, (void*) ACTION_APPS, -1);
|
|
||||||
menu_insert_item(menu, "Development tools", NULL, (void*) ACTION_DEV, -1);
|
menu->fgColor = 0xFF000000;
|
||||||
menu_insert_item(menu, "Settings", NULL, (void*) ACTION_SETTINGS, -1);
|
menu->bgColor = 0xFFFFFFFF;
|
||||||
|
menu->bgTextColor = 0xFF000000;
|
||||||
|
menu->selectedItemColor = 0xFFfec859;
|
||||||
|
menu->borderColor = 0xFF491d88;
|
||||||
|
menu->titleColor = 0xFFfec859;
|
||||||
|
menu->titleBgColor = 0xFF491d88;
|
||||||
|
menu->scrollbarBgColor = 0xFFCCCCCC;
|
||||||
|
menu->scrollbarFgColor = 0xFF555555;
|
||||||
|
|
||||||
|
pax_buf_t icon_home;
|
||||||
|
pax_decode_png_buf(&icon_home, (void*) home_png_start, home_png_end - home_png_start, PAX_BUF_32_8888ARGB, 0);
|
||||||
|
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_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);
|
||||||
|
pax_buf_t icon_dev;
|
||||||
|
pax_decode_png_buf(&icon_dev, (void*) dev_png_start, dev_png_end - dev_png_start, PAX_BUF_32_8888ARGB, 0);
|
||||||
|
pax_buf_t icon_settings;
|
||||||
|
pax_decode_png_buf(&icon_settings, (void*) settings_png_start, settings_png_end - settings_png_start, PAX_BUF_32_8888ARGB, 0);
|
||||||
|
|
||||||
|
menu_set_icon(menu, &icon_home);
|
||||||
|
|
||||||
|
menu_insert_item_icon(menu, "Apps", NULL, (void*) ACTION_APPS, -1, &icon_apps);
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
bool render = true;
|
bool render = true;
|
||||||
menu_start_action_t action = ACTION_NONE;
|
menu_start_action_t action = ACTION_NONE;
|
||||||
|
|
||||||
render_start_help(pax_buffer);
|
render_start_help(pax_buffer, version);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
rp2040_input_message_t buttonMessage = {0};
|
rp2040_input_message_t buttonMessage = {0};
|
||||||
|
@ -74,7 +123,7 @@ void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili934
|
||||||
}
|
}
|
||||||
|
|
||||||
if (render) {
|
if (render) {
|
||||||
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF000000);
|
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF491d88);
|
||||||
ili9341_write(ili9341, pax_buffer->buf);
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
render = false;
|
render = false;
|
||||||
}
|
}
|
||||||
|
@ -82,6 +131,9 @@ void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili934
|
||||||
if (action != ACTION_NONE) {
|
if (action != ACTION_NONE) {
|
||||||
if (action == ACTION_APPS) {
|
if (action == ACTION_APPS) {
|
||||||
menu_launcher(buttonQueue, pax_buffer, ili9341);
|
menu_launcher(buttonQueue, pax_buffer, ili9341);
|
||||||
|
} else if (action == ACTION_HATCHERY) {
|
||||||
|
// Not implemented
|
||||||
|
display_boot_screen(pax_buffer, ili9341, "Not implemented");
|
||||||
} else if (action == ACTION_SETTINGS) {
|
} else if (action == ACTION_SETTINGS) {
|
||||||
menu_settings(buttonQueue, pax_buffer, ili9341);
|
menu_settings(buttonQueue, pax_buffer, ili9341);
|
||||||
} else if (action == ACTION_DEV) {
|
} else if (action == ACTION_DEV) {
|
||||||
|
@ -89,9 +141,14 @@ void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili934
|
||||||
}
|
}
|
||||||
action = ACTION_NONE;
|
action = ACTION_NONE;
|
||||||
render = true;
|
render = true;
|
||||||
render_start_help(pax_buffer);
|
render_start_help(pax_buffer, version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_free(menu);
|
menu_free(menu);
|
||||||
|
pax_buf_destroy(&icon_home);
|
||||||
|
pax_buf_destroy(&icon_apps);
|
||||||
|
pax_buf_destroy(&icon_hatchery);
|
||||||
|
pax_buf_destroy(&icon_dev);
|
||||||
|
pax_buf_destroy(&icon_settings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,4 +5,4 @@
|
||||||
#include "pax_gfx.h"
|
#include "pax_gfx.h"
|
||||||
#include "ili9341.h"
|
#include "ili9341.h"
|
||||||
|
|
||||||
void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341);
|
void menu_start(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, const char* version);
|
||||||
|
|
|
@ -63,7 +63,7 @@ void render_wifi_help(pax_buf_t* pax_buffer) {
|
||||||
const pax_font_t *font = pax_get_font("saira regular");
|
const pax_font_t *font = pax_get_font("saira regular");
|
||||||
pax_background(pax_buffer, 0xFFFFFF);
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
pax_noclip(pax_buffer);
|
pax_noclip(pax_buffer);
|
||||||
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] accept [B] back");
|
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 18, "[A] accept [B] back");
|
||||||
}
|
}
|
||||||
|
|
||||||
void wifi_show(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341);
|
void wifi_show(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341);
|
||||||
|
@ -73,7 +73,7 @@ int wifi_auth_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili
|
||||||
int wifi_phase2_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, esp_eap_ttls_phase2_types default_mode);
|
int wifi_phase2_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, esp_eap_ttls_phase2_types default_mode);
|
||||||
|
|
||||||
void menu_wifi(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
void menu_wifi(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
menu_t* menu = menu_alloc("WiFi configuration");
|
menu_t* menu = menu_alloc("WiFi configuration", 34, 18);
|
||||||
menu_insert_item(menu, "Show current settings", NULL, (void*) ACTION_SHOW, -1);
|
menu_insert_item(menu, "Show current settings", NULL, (void*) ACTION_SHOW, -1);
|
||||||
menu_insert_item(menu, "Scan for networks", NULL, (void*) ACTION_SCAN, -1);
|
menu_insert_item(menu, "Scan for networks", NULL, (void*) ACTION_SCAN, -1);
|
||||||
menu_insert_item(menu, "Configure manually", NULL, (void*) ACTION_MANUAL, -1);
|
menu_insert_item(menu, "Configure manually", NULL, (void*) ACTION_MANUAL, -1);
|
||||||
|
@ -121,7 +121,7 @@ void menu_wifi(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341
|
||||||
}
|
}
|
||||||
|
|
||||||
if (render) {
|
if (render) {
|
||||||
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF2f55a8);
|
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF491d88);
|
||||||
ili9341_write(ili9341, pax_buffer->buf);
|
ili9341_write(ili9341, pax_buffer->buf);
|
||||||
render = false;
|
render = false;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ void wifi_show(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341
|
||||||
}
|
}
|
||||||
|
|
||||||
wifi_ap_record_t *wifi_scan_results(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, size_t num_aps, wifi_ap_record_t *aps) {
|
wifi_ap_record_t *wifi_scan_results(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, size_t num_aps, wifi_ap_record_t *aps) {
|
||||||
menu_t *menu = menu_alloc("Select network");
|
menu_t *menu = menu_alloc("Select network", 20, 18);
|
||||||
wifi_ap_record_t *picked = NULL;
|
wifi_ap_record_t *picked = NULL;
|
||||||
|
|
||||||
render_wifi_help(pax_buffer);
|
render_wifi_help(pax_buffer);
|
||||||
|
@ -269,7 +269,7 @@ wifi_ap_record_t *wifi_scan_results(xQueueHandle buttonQueue, pax_buf_t* pax_buf
|
||||||
}
|
}
|
||||||
|
|
||||||
int wifi_auth_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, wifi_auth_mode_t default_mode) {
|
int wifi_auth_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, wifi_auth_mode_t default_mode) {
|
||||||
menu_t* menu = menu_alloc("Authentication mode");
|
menu_t* menu = menu_alloc("Authentication mode", 20, 18);
|
||||||
menu_insert_item(menu, "Insecure", NULL, (void*) ACTION_AUTH_OPEN, -1);
|
menu_insert_item(menu, "Insecure", NULL, (void*) ACTION_AUTH_OPEN, -1);
|
||||||
menu_insert_item(menu, "WEP", NULL, (void*) ACTION_AUTH_WEP, -1);
|
menu_insert_item(menu, "WEP", NULL, (void*) ACTION_AUTH_WEP, -1);
|
||||||
menu_insert_item(menu, "WPA PSK", NULL, (void*) ACTION_AUTH_WPA_PSK, -1);
|
menu_insert_item(menu, "WPA PSK", NULL, (void*) ACTION_AUTH_WPA_PSK, -1);
|
||||||
|
@ -347,7 +347,7 @@ int wifi_auth_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili
|
||||||
}
|
}
|
||||||
|
|
||||||
int wifi_phase2_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, esp_eap_ttls_phase2_types default_mode) {
|
int wifi_phase2_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, esp_eap_ttls_phase2_types default_mode) {
|
||||||
menu_t* menu = menu_alloc("Phase 2 authentication mode");
|
menu_t* menu = menu_alloc("Phase 2 authentication mode", 20, 18);
|
||||||
menu_insert_item(menu, "ESP", NULL, (void*) ACTION_PHASE2_EAP, -1);
|
menu_insert_item(menu, "ESP", NULL, (void*) ACTION_PHASE2_EAP, -1);
|
||||||
menu_insert_item(menu, "MSCHAPv2", NULL, (void*) ACTION_PHASE2_MSCHAPV2, -1);
|
menu_insert_item(menu, "MSCHAPv2", NULL, (void*) ACTION_PHASE2_MSCHAPV2, -1);
|
||||||
menu_insert_item(menu, "MSCHAP", NULL, (void*) ACTION_PHASE2_MSCHAP, -1);
|
menu_insert_item(menu, "MSCHAP", NULL, (void*) ACTION_PHASE2_MSCHAP, -1);
|
||||||
|
|
|
@ -23,3 +23,62 @@ esp_err_t nvs_init() {
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t nvs_get_str_fixed(const char* nvs_namespace, const char* key, char* target, size_t target_size, size_t* size) {
|
||||||
|
nvs_handle_t handle;
|
||||||
|
esp_err_t res;
|
||||||
|
|
||||||
|
res = nvs_open(nvs_namespace, NVS_READWRITE, &handle);
|
||||||
|
if (res != ESP_OK) return res;
|
||||||
|
|
||||||
|
size_t required_size;
|
||||||
|
res = nvs_get_str(handle, key, NULL, &required_size);
|
||||||
|
if (res != ESP_OK) {
|
||||||
|
nvs_close(handle);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (required_size > target_size) {
|
||||||
|
nvs_close(handle);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = nvs_get_str(handle, key, target, &required_size);
|
||||||
|
|
||||||
|
if (size != NULL) *size = required_size;
|
||||||
|
|
||||||
|
nvs_close(handle);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nvs_get_u8_default(const char* nvs_namespace, const char* key, uint8_t default_value) {
|
||||||
|
nvs_handle_t handle;
|
||||||
|
esp_err_t res;
|
||||||
|
|
||||||
|
res = nvs_open(nvs_namespace, NVS_READWRITE, &handle);
|
||||||
|
if (res != ESP_OK) return default_value;
|
||||||
|
|
||||||
|
uint8_t target;
|
||||||
|
res = nvs_get_u8(handle, key, &target);
|
||||||
|
if (res != ESP_OK) {
|
||||||
|
nvs_close(handle);
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_close(handle);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t nvs_set_u8_fixed(const char* nvs_namespace, const char* key, uint8_t value) {
|
||||||
|
nvs_handle_t handle;
|
||||||
|
esp_err_t res;
|
||||||
|
|
||||||
|
res = nvs_open(nvs_namespace, NVS_READWRITE, &handle);
|
||||||
|
if (res != ESP_OK) return res;
|
||||||
|
|
||||||
|
res = nvs_set_u8(handle, key, value);
|
||||||
|
nvs_close(handle);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
65
main/test_common.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/queue.h>
|
||||||
|
#include <driver/gpio.h>
|
||||||
|
#include "hardware.h"
|
||||||
|
#include "ili9341.h"
|
||||||
|
#include "ice40.h"
|
||||||
|
#include "rp2040.h"
|
||||||
|
#include "pax_gfx.h"
|
||||||
|
|
||||||
|
typedef bool (*test_fn)(uint32_t *rc);
|
||||||
|
|
||||||
|
bool test_wait_for_response(uint32_t *rc) {
|
||||||
|
RP2040* rp2040 = get_rp2040();
|
||||||
|
rp2040_input_message_t button_message = {0};
|
||||||
|
if (rc != NULL) *rc = 0;
|
||||||
|
while (1) {
|
||||||
|
if (xQueueReceive(rp2040->queue, &button_message, portMAX_DELAY) == pdTRUE) {
|
||||||
|
if (button_message.state) {
|
||||||
|
switch(button_message.input) {
|
||||||
|
case RP2040_INPUT_BUTTON_HOME:
|
||||||
|
case RP2040_INPUT_BUTTON_MENU:
|
||||||
|
case RP2040_INPUT_BUTTON_BACK:
|
||||||
|
return false;
|
||||||
|
case RP2040_INPUT_BUTTON_ACCEPT:
|
||||||
|
if (rc != NULL) *rc = 1;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run_test(pax_buf_t* pax_buffer, const pax_font_t *font, ILI9341* ili9341, int line, const char *test_name, test_fn fn) {
|
||||||
|
bool test_result;
|
||||||
|
uint32_t rc;
|
||||||
|
|
||||||
|
/* Test name */
|
||||||
|
pax_draw_text(pax_buffer, 0xffffffff, font, 18, 0, 20*line, test_name);
|
||||||
|
if (ili9341) ili9341_write(ili9341, pax_buffer->buf);
|
||||||
|
|
||||||
|
/* Run the test */
|
||||||
|
test_result = fn(&rc);
|
||||||
|
|
||||||
|
/* Display result */
|
||||||
|
if (!test_result) {
|
||||||
|
/* Error */
|
||||||
|
char buf[10];
|
||||||
|
snprintf(buf, sizeof(buf), "%08x", rc);
|
||||||
|
pax_draw_text(pax_buffer, 0xffff0000, font, 18, 200, 20*line, buf);
|
||||||
|
} else {
|
||||||
|
/* OK ! */
|
||||||
|
pax_draw_text(pax_buffer, 0xff00ff00, font, 18, 200, 20*line, " OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ili9341) ili9341_write(ili9341, pax_buffer->buf);
|
||||||
|
|
||||||
|
/* Pass through the 'OK' status */
|
||||||
|
return test_result;
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ typedef struct _uninstall_menu_args {
|
||||||
} uninstall_menu_args_t;
|
} uninstall_menu_args_t;
|
||||||
|
|
||||||
void uninstall_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
void uninstall_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
|
||||||
menu_t* menu = menu_alloc("Uninstall application");
|
menu_t* menu = menu_alloc("Uninstall application", 20, 18);
|
||||||
const pax_font_t *font = pax_get_font("saira regular");
|
const pax_font_t *font = pax_get_font("saira regular");
|
||||||
|
|
||||||
appfs_handle_t appfs_fd = APPFS_INVALID_FD;
|
appfs_handle_t appfs_fd = APPFS_INVALID_FD;
|
||||||
|
@ -50,7 +50,7 @@ void uninstall_browser(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341*
|
||||||
|
|
||||||
pax_background(pax_buffer, 0xFFFFFF);
|
pax_background(pax_buffer, 0xFFFFFF);
|
||||||
pax_noclip(pax_buffer);
|
pax_noclip(pax_buffer);
|
||||||
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 19, "[A] uninstall app [B] back");
|
pax_draw_text(pax_buffer, 0xFF000000, font, 18, 5, 240 - 18, "[A] uninstall app [B] back");
|
||||||
|
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
|
|
||||||
|
|
BIN
resources/animation/animation_frame_1.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resources/animation/animation_frame_10.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
resources/animation/animation_frame_11.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
resources/animation/animation_frame_12.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resources/animation/animation_frame_13.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
resources/animation/animation_frame_14.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
resources/animation/animation_frame_15.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
resources/animation/animation_frame_16.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
resources/animation/animation_frame_17.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
resources/animation/animation_frame_18.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
resources/animation/animation_frame_19.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
resources/animation/animation_frame_2.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resources/animation/animation_frame_20.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
resources/animation/animation_frame_21.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
resources/animation/animation_frame_22.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
resources/animation/animation_frame_23.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
resources/animation/animation_frame_24.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
resources/animation/animation_frame_25.png
Normal file
After Width: | Height: | Size: 706 B |
BIN
resources/animation/animation_frame_26.png
Normal file
After Width: | Height: | Size: 468 B |
BIN
resources/animation/animation_frame_27.png
Normal file
After Width: | Height: | Size: 395 B |
BIN
resources/animation/animation_frame_28.png
Normal file
After Width: | Height: | Size: 164 B |
BIN
resources/animation/animation_frame_3.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resources/animation/animation_frame_4.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resources/animation/animation_frame_5.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resources/animation/animation_frame_6.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resources/animation/animation_frame_7.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
resources/animation/animation_frame_8.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
resources/animation/animation_frame_9.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
resources/icons/apps.png
Normal file
After Width: | Height: | Size: 700 B |
BIN
resources/icons/dev.png
Normal file
After Width: | Height: | Size: 857 B |
BIN
resources/icons/hatchery.png
Normal file
After Width: | Height: | Size: 725 B |
BIN
resources/icons/home.png
Normal file
After Width: | Height: | Size: 439 B |
BIN
resources/icons/settings.png
Normal file
After Width: | Height: | Size: 1 KiB |
10
sdkconfig
|
@ -157,15 +157,15 @@ CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y
|
||||||
CONFIG_APP_BUILD_GENERATE_BINARIES=y
|
CONFIG_APP_BUILD_GENERATE_BINARIES=y
|
||||||
CONFIG_APP_BUILD_BOOTLOADER=y
|
CONFIG_APP_BUILD_BOOTLOADER=y
|
||||||
CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y
|
CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y
|
||||||
CONFIG_APP_REPRODUCIBLE_BUILD=y
|
# CONFIG_APP_REPRODUCIBLE_BUILD is not set
|
||||||
# end of Build type
|
# end of Build type
|
||||||
|
|
||||||
#
|
#
|
||||||
# Application manager
|
# Application manager
|
||||||
#
|
#
|
||||||
# CONFIG_APP_COMPILE_TIME_DATE is not set
|
# CONFIG_APP_COMPILE_TIME_DATE is not set
|
||||||
CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y
|
# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set
|
||||||
CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y
|
# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set
|
||||||
# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set
|
# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set
|
||||||
CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16
|
CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16
|
||||||
# end of Application manager
|
# end of Application manager
|
||||||
|
@ -675,7 +675,7 @@ CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
||||||
|
|
||||||
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
|
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
|
||||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304
|
||||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||||
CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y
|
CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y
|
||||||
# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set
|
# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set
|
||||||
# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set
|
# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set
|
||||||
|
@ -1475,7 +1475,7 @@ CONFIG_ESP32S2_PANIC_PRINT_HALT=y
|
||||||
# CONFIG_ESP32S2_PANIC_GDBSTUB is not set
|
# CONFIG_ESP32S2_PANIC_GDBSTUB is not set
|
||||||
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
|
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
|
||||||
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
|
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
|
||||||
CONFIG_MAIN_TASK_STACK_SIZE=3584
|
CONFIG_MAIN_TASK_STACK_SIZE=8192
|
||||||
CONFIG_CONSOLE_UART_DEFAULT=y
|
CONFIG_CONSOLE_UART_DEFAULT=y
|
||||||
# CONFIG_CONSOLE_UART_CUSTOM is not set
|
# CONFIG_CONSOLE_UART_CUSTOM is not set
|
||||||
# CONFIG_ESP_CONSOLE_UART_NONE is not set
|
# CONFIG_ESP_CONSOLE_UART_NONE is not set
|
||||||
|
|