mirror of
https://github.com/clockworkpi/PicoCalc.git
synced 2025-12-12 10:18:54 +01:00
update multi booter
switch order of picomite and sd_boot to make more space for progs of multi booter bin folder name changed to firmware ui interface improvments
This commit is contained in:
parent
3009ce75ba
commit
5276f48b6d
@ -72,19 +72,19 @@ add_custom_target(BUILT_${BOOT}
|
|||||||
|
|
||||||
add_dependencies(BUILT_boot boot)
|
add_dependencies(BUILT_boot boot)
|
||||||
|
|
||||||
add_dependencies(PREPARE_picomite BUILT_boot)
|
add_dependencies(PREPARE_sd_boot BUILT_boot)
|
||||||
add_dependencies(picomite PREPARE_picomite)
|
|
||||||
add_dependencies(BUILT_picomite picomite)
|
|
||||||
|
|
||||||
add_dependencies(PREPARE_sd_boot BUILT_picomite)
|
|
||||||
add_dependencies(sd_boot PREPARE_sd_boot)
|
add_dependencies(sd_boot PREPARE_sd_boot)
|
||||||
add_dependencies(BUILT_sd_boot sd_boot)
|
add_dependencies(BUILT_sd_boot sd_boot)
|
||||||
|
|
||||||
|
add_dependencies(PREPARE_picomite BUILT_sd_boot)
|
||||||
|
add_dependencies(picomite PREPARE_picomite)
|
||||||
|
add_dependencies(BUILT_picomite picomite)
|
||||||
|
|
||||||
|
|
||||||
# ***************************************************************************
|
# ***************************************************************************
|
||||||
# * Join the BOOT and all APP '.uf2' files together *
|
# * Join the BOOT and all APP '.uf2' files together *
|
||||||
# ***************************************************************************
|
# ***************************************************************************
|
||||||
set(UF2S boot.uf2 picomite.uf2 sd_boot.uf2)
|
set(UF2S boot.uf2 sd_boot.uf2 picomite.uf2)
|
||||||
|
|
||||||
add_custom_target(JOIN
|
add_custom_target(JOIN
|
||||||
COMMENT "Combine the '.uf2' files"
|
COMMENT "Combine the '.uf2' files"
|
||||||
@ -95,7 +95,7 @@ add_custom_target(JOIN
|
|||||||
${UF2S}
|
${UF2S}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(JOIN BUILT_sd_boot)
|
add_dependencies(JOIN BUILT_picomite)
|
||||||
|
|
||||||
add_custom_target(${PROJECT} ALL DEPENDS JOIN)
|
add_custom_target(${PROJECT} ALL DEPENDS JOIN)
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
Here is a bootloader for PicoCalc combined slightly modified [PicoMite](https://github.com/madcock/PicoMiteAllVersions) and [SD boot](https://github.com/adwuard/Picocalc_SD_Boot)
|
Here is a bootloader for PicoCalc combined slightly modified [PicoMite](https://github.com/madcock/PicoMiteAllVersions) and [SD boot](https://github.com/adwuard/Picocalc_SD_Boot)
|
||||||
|
|
||||||
- Pico1
|
- Pico1
|
||||||
- No sdcard inserted ,PicoMite will show up.
|
- No sdcard inserted,load default app to run from flash.
|
||||||
- Sdcard inserted, SD boot menu will show up, load third pico app bin to run at FLASH TARGET OFFSET 2048k-940k
|
- Sdcard inserted, SD boot menu will show up, load third pico app bin to run at FLASH TARGET OFFSET 2048k-152k
|
||||||
|
|
||||||
## How to compile
|
## How to compile
|
||||||
```
|
```
|
||||||
@ -29,13 +29,13 @@ configuration.h
|
|||||||
|
|
||||||
config.h
|
config.h
|
||||||
```
|
```
|
||||||
#define SD_BOOT_FLASH_OFFSET (940 * 1024)
|
#define SD_BOOT_FLASH_OFFSET (152 * 1024)
|
||||||
```
|
```
|
||||||
|
|
||||||
### SD Card Application Build and Deployment
|
### SD Card Application Build and Deployment
|
||||||
**Important Note:**
|
**Important Note:**
|
||||||
```
|
```
|
||||||
Applications intended for SD card boot "MUST REBUILD" using a custom linker script to accommodate the program's offset(940k) address.
|
Applications intended for SD card boot "MUST REBUILD" using a custom linker script to accommodate the program's offset(152k) address.
|
||||||
|
|
||||||
Applications intended for SD card boot is in **bin** format, not uf2.
|
Applications intended for SD card boot is in **bin** format, not uf2.
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ make
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Step 3 Your Custom Application Is Ready For SD Card Boot
|
#### Step 3 Your Custom Application Is Ready For SD Card Boot
|
||||||
Once the build is complete, copy the generated `.bin` file to the `/sd` directory of the SD card.
|
Once the build is complete, copy the generated `.bin` file to the `/firmware` directory of the SD card.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -150,6 +150,7 @@ int main(void) {
|
|||||||
printf("max %d \n",max);
|
printf("max %d \n",max);
|
||||||
|
|
||||||
// Choose an app to launch
|
// Choose an app to launch
|
||||||
|
/*
|
||||||
int chosen;
|
int chosen;
|
||||||
if(!sd_card_inserted()){
|
if(!sd_card_inserted()){
|
||||||
printf("No sd card\n");
|
printf("No sd card\n");
|
||||||
@ -159,7 +160,8 @@ int main(void) {
|
|||||||
chosen = max-1;
|
chosen = max-1;
|
||||||
if(chosen <0 ) chosen = 0;
|
if(chosen <0 ) chosen = 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
int chosen = 0;
|
||||||
// Get start address of app
|
// Get start address of app
|
||||||
addr = PEEK32( info + ((chosen * 16)));
|
addr = PEEK32( info + ((chosen * 16)));
|
||||||
printf("Application at %08lX\n", addr);
|
printf("Application at %08lX\n", addr);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*arduino-pico*/
|
/*arduino-pico*/
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
FLASH(rx) : ORIGIN = 0x10000000 + 940k, LENGTH = __FLASH_LENGTH__ - 940k
|
FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = __FLASH_LENGTH__ - 152k
|
||||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = __RAM_LENGTH__
|
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = __RAM_LENGTH__
|
||||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
FLASH(rx) : ORIGIN = 0x10000000 + 940k, LENGTH = 2048k - 940k
|
FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = 2048k - 152k
|
||||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
||||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
FLASH(rx) : ORIGIN = 0x10000000 + 940k, LENGTH = 2048k - 940k
|
FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = 2048k - 152k
|
||||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
||||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
FLASH(rx) : ORIGIN = 0x10000000 + 940k, LENGTH = 2048k - 940k
|
FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = 2048k - 152k
|
||||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
||||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
FLASH(rx) : ORIGIN = 0x10000000 + 940k, LENGTH = 4096k - 940k
|
FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = 4096k - 152k
|
||||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k
|
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k
|
||||||
SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
|
SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
|
||||||
SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
|
SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
// According to the applink.map ,with combined PicoMite, here is 920k
|
// According to the applink.map ,with combined PicoMite, here is 920k
|
||||||
// This offset is used to ensure that the bootloader does not get overwritten
|
// This offset is used to ensure that the bootloader does not get overwritten
|
||||||
// when loading a new application from the SD card
|
// when loading a new application from the SD card
|
||||||
#define SD_BOOT_FLASH_OFFSET (940 * 1024)
|
#define SD_BOOT_FLASH_OFFSET (152 * 1024)
|
||||||
|
|
||||||
// Maximum size of the application that can be loaded
|
// Maximum size of the application that can be loaded
|
||||||
// This ensures we don't overwrite the bootloader itself
|
// This ensures we don't overwrite the bootloader itself
|
||||||
|
|||||||
@ -207,15 +207,18 @@ int load_firmware_by_path(const char *path)
|
|||||||
|
|
||||||
// Attempt to load the application from the SD card
|
// Attempt to load the application from the SD card
|
||||||
// bool load_success = load_program(FIRMWARE_PATH);
|
// bool load_success = load_program(FIRMWARE_PATH);
|
||||||
bool load_success = load_program(path);
|
bool load_success=false;
|
||||||
|
|
||||||
// Get the pointer to the application flash area
|
// Get the pointer to the application flash area
|
||||||
uint32_t *app_location = (uint32_t *)(XIP_BASE + SD_BOOT_FLASH_OFFSET);
|
uint32_t *app_location = (uint32_t *)(XIP_BASE + SD_BOOT_FLASH_OFFSET);
|
||||||
|
|
||||||
// Check if there is an already valid application in flash
|
// Check if there is an already valid application in flash
|
||||||
bool has_valid_app = is_valid_application(app_location);
|
bool has_valid_app = is_valid_application(app_location);
|
||||||
|
|
||||||
|
if(path == NULL) {
|
||||||
|
load_success = true;
|
||||||
|
}else{
|
||||||
|
load_success = load_program(path);
|
||||||
|
}
|
||||||
|
|
||||||
if (load_success || has_valid_app)
|
if (load_success || has_valid_app)
|
||||||
{
|
{
|
||||||
@ -245,11 +248,21 @@ int load_firmware_by_path(const char *path)
|
|||||||
|
|
||||||
void final_selection_callback(const char *path)
|
void final_selection_callback(const char *path)
|
||||||
{
|
{
|
||||||
|
char status_message[128];
|
||||||
|
const char *extension = ".bin";
|
||||||
|
if(path == NULL) {
|
||||||
|
//load default app from flash
|
||||||
|
|
||||||
|
snprintf(status_message, sizeof(status_message), "SEL: %s", "FLASH+152k");
|
||||||
|
text_directory_ui_set_status(status_message);
|
||||||
|
sleep_ms(200);
|
||||||
|
load_firmware_by_path(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Trigger firmware loading with the selected path
|
// Trigger firmware loading with the selected path
|
||||||
DEBUG_PRINT("selected: %s\n", path);
|
DEBUG_PRINT("selected: %s\n", path);
|
||||||
|
|
||||||
char status_message[128];
|
|
||||||
const char *extension = ".bin";
|
|
||||||
size_t path_len = strlen(path);
|
size_t path_len = strlen(path);
|
||||||
size_t ext_len = strlen(extension);
|
size_t ext_len = strlen(extension);
|
||||||
|
|
||||||
@ -286,7 +299,6 @@ int main()
|
|||||||
keypad_init();
|
keypad_init();
|
||||||
lcd_init();
|
lcd_init();
|
||||||
lcd_clear();
|
lcd_clear();
|
||||||
text_directory_ui_init();
|
|
||||||
|
|
||||||
// Check for SD card presence
|
// Check for SD card presence
|
||||||
DEBUG_PRINT("Checking for SD card...\n");
|
DEBUG_PRINT("Checking for SD card...\n");
|
||||||
|
|||||||
@ -54,11 +54,14 @@ extern bool fs_init(void);
|
|||||||
// Maximum number of directory entries
|
// Maximum number of directory entries
|
||||||
#define MAX_ENTRIES 128
|
#define MAX_ENTRIES 128
|
||||||
|
|
||||||
|
#define IS_DIR 1
|
||||||
|
#define IS_FILE 0
|
||||||
|
#define IS_LAST_APP 2
|
||||||
// Data structure for directory entries
|
// Data structure for directory entries
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char name[256];
|
char name[256];
|
||||||
int is_dir; // 1 if directory, 0 if file
|
int is_dir; // 1 if directory, 0 if file 2 == last run
|
||||||
off_t file_size; // Size of the file in bytes
|
off_t file_size; // Size of the file in bytes
|
||||||
} dir_entry_t;
|
} dir_entry_t;
|
||||||
|
|
||||||
@ -72,12 +75,11 @@ typedef struct
|
|||||||
#define SCROLL_DELAY_MS 300
|
#define SCROLL_DELAY_MS 300
|
||||||
|
|
||||||
// Global variables for UI state
|
// Global variables for UI state
|
||||||
static char current_path[512] = "/sd"; // Current directory path
|
static char current_path[512] = "/firmware"; // Current directory path
|
||||||
static dir_entry_t entries[MAX_ENTRIES]; // Directory entries
|
static dir_entry_t entries[MAX_ENTRIES]; // Directory entries
|
||||||
static int entry_count = 0; // Number of entries in the current directory
|
static int entry_count = 0; // Number of entries in the current directory
|
||||||
static int selected_index = 0; // Currently selected entry index
|
static int selected_index = 0; // Currently selected entry index
|
||||||
static char status_message[256] = ""; // Status message
|
static char status_message[256] = ""; // Status message
|
||||||
static uint32_t status_timestamp = 0; // Timestamp for status message
|
|
||||||
static final_selection_callback_t final_callback = NULL; // Callback for file selection
|
static final_selection_callback_t final_callback = NULL; // Callback for file selection
|
||||||
static uint32_t last_scrolling = 0; // for text scrolling in selected entry
|
static uint32_t last_scrolling = 0; // for text scrolling in selected entry
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
@ -90,6 +92,7 @@ static void ui_draw_directory_list(void);
|
|||||||
static void ui_draw_directory_entry(int entry_idx, int posY, int font_height, int is_selected);
|
static void ui_draw_directory_entry(int entry_idx, int posY, int font_height, int is_selected);
|
||||||
static void ui_update_selected_entry(void);
|
static void ui_update_selected_entry(void);
|
||||||
static void ui_draw_status_bar(void);
|
static void ui_draw_status_bar(void);
|
||||||
|
static void ui_draw_empty_tip(void);
|
||||||
static void format_file_size(off_t size, int is_dir, char *buf, size_t buf_size);
|
static void format_file_size(off_t size, int is_dir, char *buf, size_t buf_size);
|
||||||
static void get_scrolling_text(const char *text, char *out, size_t out_size, int visible_chars);
|
static void get_scrolling_text(const char *text, char *out, size_t out_size, int visible_chars);
|
||||||
|
|
||||||
@ -112,7 +115,7 @@ static void draw_text(int x, int y, const char *text, int foreground, int backgr
|
|||||||
*/
|
*/
|
||||||
static void format_file_size(off_t size, int is_dir, char *buf, size_t buf_size)
|
static void format_file_size(off_t size, int is_dir, char *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
if (is_dir)
|
if (is_dir == IS_DIR)
|
||||||
{
|
{
|
||||||
snprintf(buf, buf_size, "DIR");
|
snprintf(buf, buf_size, "DIR");
|
||||||
}
|
}
|
||||||
@ -168,6 +171,12 @@ static void load_directory(const char *path)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entry_count = 0;
|
entry_count = 0;
|
||||||
|
strncpy(entries[entry_count].name, "[Last app]", sizeof(entries[entry_count].name) - 1);
|
||||||
|
entries[entry_count].name[sizeof(entries[entry_count].name) - 1] = '\0';
|
||||||
|
entries[0].is_dir = IS_LAST_APP;
|
||||||
|
entries[0].file_size = 0;
|
||||||
|
|
||||||
|
entry_count = 1;
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
while ((ent = readdir(dir)) != NULL && entry_count < MAX_ENTRIES)
|
while ((ent = readdir(dir)) != NULL && entry_count < MAX_ENTRIES)
|
||||||
{
|
{
|
||||||
@ -185,7 +194,7 @@ static void load_directory(const char *path)
|
|||||||
// Determine if the entry is a directory and get file size
|
// Determine if the entry is a directory and get file size
|
||||||
if (ent->d_type != DT_UNKNOWN)
|
if (ent->d_type != DT_UNKNOWN)
|
||||||
{
|
{
|
||||||
entries[entry_count].is_dir = (ent->d_type == DT_DIR) ? 1 : 0;
|
entries[entry_count].is_dir = (ent->d_type == DT_DIR) ? IS_DIR : IS_FILE;
|
||||||
|
|
||||||
// Get file size using stat even if we know the type from d_type
|
// Get file size using stat even if we know the type from d_type
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
@ -216,9 +225,6 @@ static void load_directory(const char *path)
|
|||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
selected_index = 0;
|
selected_index = 0;
|
||||||
if(entry_count == 0) {
|
|
||||||
text_directory_ui_set_status("No firmware found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +235,28 @@ static void ui_draw_title(void)
|
|||||||
draw_text(UI_X + 2, UI_Y + 2, "PicoCalc SD Firmware Loader", WHITE, BLACK);
|
draw_text(UI_X + 2, UI_Y + 2, "PicoCalc SD Firmware Loader", WHITE, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ui_draw_empty_tip(){
|
||||||
|
|
||||||
|
|
||||||
|
int y = UI_Y + UI_HEIGHT/2;//center
|
||||||
|
int y_start = UI_Y + HEADER_TITLE_HEIGHT + PATH_HEADER_HEIGHT;
|
||||||
|
draw_rect_spi(UI_X, y_start, UI_X + UI_WIDTH - 1, UI_Y + UI_HEIGHT - STATUS_BAR_HEIGHT - 1, COLOR_BG);
|
||||||
|
|
||||||
|
//draw_rect_spi(UI_X, UI_Y + HEADER_TITLE_HEIGHT+1, UI_X + UI_WIDTH - 1, UI_Y + UI_HEIGHT - 2, COLOR_BG);
|
||||||
|
|
||||||
|
draw_text(UI_X + 2, y + 2, "No .bin files in \"firmware\" folder" , COLOR_FG, COLOR_BG);
|
||||||
|
draw_text(UI_X + 2, y + 12+2, "Please copy .bin files to the" , COLOR_FG, COLOR_BG);
|
||||||
|
draw_text(UI_X + 2, y + 24+2, "\"firmware\" folder" , COLOR_FG, COLOR_BG);
|
||||||
|
|
||||||
|
|
||||||
|
strncpy(entries[entry_count].name, "Load default", sizeof(entries[entry_count].name) - 1);
|
||||||
|
entries[entry_count].name[sizeof(entries[entry_count].name) - 1] = '\0';
|
||||||
|
entries[0].is_dir = IS_LAST_APP;
|
||||||
|
entries[0].file_size = 0;
|
||||||
|
// Draw the entry using the helper function
|
||||||
|
ui_draw_directory_entry(0, y_start, 12, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Draw the current path header
|
// Draw the current path header
|
||||||
static void ui_draw_path_header(void)
|
static void ui_draw_path_header(void)
|
||||||
{
|
{
|
||||||
@ -260,7 +288,7 @@ static void ui_draw_directory_entry(int entry_idx, int posY, int font_height, in
|
|||||||
char full_file_name[300];
|
char full_file_name[300];
|
||||||
snprintf(full_file_name, sizeof(full_file_name), "%s%s",
|
snprintf(full_file_name, sizeof(full_file_name), "%s%s",
|
||||||
entries[entry_idx].name,
|
entries[entry_idx].name,
|
||||||
entries[entry_idx].is_dir ? "/" : "");
|
(entries[entry_idx].is_dir == IS_DIR) ? "/" : "");
|
||||||
|
|
||||||
// Prepare display text with scrolling for selected items
|
// Prepare display text with scrolling for selected items
|
||||||
char display_buffer[300];
|
char display_buffer[300];
|
||||||
@ -326,6 +354,7 @@ static void ui_update_selected_entry(void)
|
|||||||
// Draw the directory list
|
// Draw the directory list
|
||||||
static void ui_draw_directory_list(void)
|
static void ui_draw_directory_list(void)
|
||||||
{
|
{
|
||||||
|
if(entry_count <=0 ) return;
|
||||||
const int font_height = 12;
|
const int font_height = 12;
|
||||||
const int entry_padding = 2;
|
const int entry_padding = 2;
|
||||||
int y_start = UI_Y + HEADER_TITLE_HEIGHT + PATH_HEADER_HEIGHT;
|
int y_start = UI_Y + HEADER_TITLE_HEIGHT + PATH_HEADER_HEIGHT;
|
||||||
@ -366,12 +395,10 @@ static void ui_refresh(void)
|
|||||||
ui_draw_path_header();
|
ui_draw_path_header();
|
||||||
ui_draw_directory_list();
|
ui_draw_directory_list();
|
||||||
ui_draw_status_bar();
|
ui_draw_status_bar();
|
||||||
|
if(entry_count == 0) {
|
||||||
|
ui_draw_empty_tip();
|
||||||
|
}
|
||||||
|
|
||||||
if (status_message[0] != '\0' && ((time_us_64() / 1000) - status_timestamp) > 3000)
|
|
||||||
{
|
|
||||||
status_message[0] = '\0';
|
|
||||||
ui_draw_status_bar();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle key events for navigation and selection
|
// Handle key events for navigation and selection
|
||||||
@ -383,40 +410,50 @@ static void process_key_event(int key)
|
|||||||
if (selected_index > 0)
|
if (selected_index > 0)
|
||||||
selected_index--;
|
selected_index--;
|
||||||
ui_draw_directory_list();
|
ui_draw_directory_list();
|
||||||
|
text_directory_ui_set_status("");
|
||||||
break;
|
break;
|
||||||
case KEY_ARROW_DOWN:
|
case KEY_ARROW_DOWN:
|
||||||
if (selected_index < entry_count - 1)
|
if (selected_index < entry_count - 1)
|
||||||
selected_index++;
|
selected_index++;
|
||||||
ui_draw_directory_list();
|
ui_draw_directory_list();
|
||||||
|
text_directory_ui_set_status("");
|
||||||
break;
|
break;
|
||||||
case KEY_ENTER:
|
case KEY_ENTER:
|
||||||
|
if(entry_count == 0) {
|
||||||
|
//directly load app from flash
|
||||||
|
final_callback(NULL);
|
||||||
|
}
|
||||||
if (entry_count > 0)
|
if (entry_count > 0)
|
||||||
{
|
{
|
||||||
char new_path[512];
|
char new_path[512];
|
||||||
if (entries[selected_index].is_dir)
|
if (entries[selected_index].is_dir == IS_DIR)
|
||||||
{
|
{
|
||||||
snprintf(new_path, sizeof(new_path), "%s/%s", current_path, entries[selected_index].name);
|
snprintf(new_path, sizeof(new_path), "%s/%s", current_path, entries[selected_index].name);
|
||||||
strncpy(current_path, new_path, sizeof(current_path) - 1);
|
strncpy(current_path, new_path, sizeof(current_path) - 1);
|
||||||
load_directory(current_path);
|
load_directory(current_path);
|
||||||
ui_draw_path_header();
|
ui_draw_path_header();
|
||||||
ui_draw_directory_list();
|
ui_draw_directory_list();
|
||||||
}
|
}else if(entries[selected_index].is_dir == IS_LAST_APP){
|
||||||
else if (final_callback)
|
if(final_callback){
|
||||||
{
|
final_callback(NULL);
|
||||||
char final_selected[512];
|
}
|
||||||
snprintf(final_selected, sizeof(final_selected), "%s/%s", current_path, entries[selected_index].name);
|
}else {
|
||||||
final_callback(final_selected);
|
if (final_callback){
|
||||||
|
char final_selected[512];
|
||||||
|
snprintf(final_selected, sizeof(final_selected), "%s/%s", current_path, entries[selected_index].name);
|
||||||
|
final_callback(final_selected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_BACKSPACE:
|
case KEY_BACKSPACE:
|
||||||
if (strcmp(current_path, "/sd") != 0)
|
if (strcmp(current_path, "/firmware") != 0)
|
||||||
{
|
{
|
||||||
char *last_slash = strrchr(current_path, '/');
|
char *last_slash = strrchr(current_path, '/');
|
||||||
if (last_slash)
|
if (last_slash)
|
||||||
*last_slash = '\0';
|
*last_slash = '\0';
|
||||||
if (current_path[0] == '\0')
|
if (current_path[0] == '\0')
|
||||||
strncpy(current_path, "/sd", sizeof(current_path) - 1);
|
strncpy(current_path, "/firmware", sizeof(current_path) - 1);
|
||||||
load_directory(current_path);
|
load_directory(current_path);
|
||||||
ui_draw_path_header();
|
ui_draw_path_header();
|
||||||
ui_draw_directory_list();
|
ui_draw_directory_list();
|
||||||
@ -438,8 +475,9 @@ void text_directory_ui_set_final_callback(final_selection_callback_t callback)
|
|||||||
bool text_directory_ui_init(void)
|
bool text_directory_ui_init(void)
|
||||||
{
|
{
|
||||||
draw_filled_rect(UI_X, UI_Y, UI_WIDTH, UI_HEIGHT, COLOR_BG);
|
draw_filled_rect(UI_X, UI_Y, UI_WIDTH, UI_HEIGHT, COLOR_BG);
|
||||||
strncpy(current_path, "/sd", sizeof(current_path));
|
strncpy(current_path, "/firmware", sizeof(current_path));
|
||||||
load_directory(current_path);
|
load_directory(current_path);
|
||||||
|
text_directory_ui_set_status("");
|
||||||
ui_refresh();
|
ui_refresh();
|
||||||
last_scrolling = time_us_64()/1000;
|
last_scrolling = time_us_64()/1000;
|
||||||
return true;
|
return true;
|
||||||
@ -450,7 +488,6 @@ void text_directory_ui_set_status(const char *msg)
|
|||||||
{
|
{
|
||||||
strncpy(status_message, msg, sizeof(status_message) - 1);
|
strncpy(status_message, msg, sizeof(status_message) - 1);
|
||||||
status_message[sizeof(status_message) - 1] = '\0';
|
status_message[sizeof(status_message) - 1] = '\0';
|
||||||
status_timestamp = (time_us_64() / 1000);
|
|
||||||
ui_draw_status_bar();
|
ui_draw_status_bar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,13 +517,6 @@ void text_directory_ui_run(void)
|
|||||||
last_scroll_update = current_time;
|
last_scroll_update = current_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear status message after timeout
|
|
||||||
if (status_message[0] != '\0' && (current_time - status_timestamp) > 3000)
|
|
||||||
{
|
|
||||||
status_message[0] = '\0';
|
|
||||||
ui_draw_status_bar();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for SD card removal during runtime
|
// Check for SD card removal during runtime
|
||||||
if (!sd_card_inserted()) {
|
if (!sd_card_inserted()) {
|
||||||
text_directory_ui_set_status("SD card removed. Please reinsert card.");
|
text_directory_ui_set_status("SD card removed. Please reinsert card.");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user