2021-12-29 17:34:55 +00:00
# include <stdio.h>
2022-01-01 04:51:12 +00:00
# include <string.h>
2021-12-29 23:32:55 +00:00
# include <sdkconfig.h>
# include <freertos/FreeRTOS.h>
# include <freertos/task.h>
2022-04-08 21:15:57 +00:00
# include <freertos/queue.h>
2021-12-29 23:32:55 +00:00
# include <esp_system.h>
# include <esp_err.h>
2022-01-01 02:06:55 +00:00
# include <esp_log.h>
2022-04-16 21:31:18 +00:00
# include <nvs_flash.h>
# include <nvs.h>
2022-05-03 18:44:45 +00:00
# include "driver/uart.h"
2021-12-29 23:32:55 +00:00
# include "hardware.h"
2022-01-04 23:58:13 +00:00
# include "managed_i2c.h"
2022-01-05 22:20:01 +00:00
# include "pax_gfx.h"
# include "sdcard.h"
# include "appfs.h"
2022-01-11 23:53:38 +00:00
# include "driver_framebuffer.h"
2021-12-29 17:34:55 +00:00
2022-01-24 21:32:33 +00:00
# include "rp2040.h"
2022-04-08 21:15:57 +00:00
# include "fpga_test.h"
# include "menu.h"
2022-04-15 23:16:36 +00:00
# include "system_wrapper.h"
# include "graphics_wrapper.h"
# include "appfs_wrapper.h"
2022-04-16 00:14:28 +00:00
# include "settings.h"
2022-04-18 00:10:44 +00:00
# include "wifi_connection.h"
2022-02-04 00:04:51 +00:00
2022-04-23 02:00:55 +00:00
# include "ws2812.h"
2022-05-03 18:44:45 +00:00
# include "rp2040firmware.h"
2022-05-03 21:45:50 +00:00
# include "esp32/rom/crc.h"
2022-01-01 02:06:55 +00:00
static const char * TAG = " main " ;
2022-01-24 22:41:03 +00:00
typedef enum action {
ACTION_NONE ,
2022-04-08 21:15:57 +00:00
ACTION_APPFS ,
2022-02-04 00:04:51 +00:00
ACTION_INSTALLER ,
2022-04-15 23:16:36 +00:00
ACTION_SETTINGS ,
ACTION_OTA ,
2022-04-16 00:14:28 +00:00
ACTION_FPGA ,
2022-05-03 18:44:45 +00:00
ACTION_RP2040_BL ,
ACTION_WIFI_CONNECT ,
2022-04-16 00:14:28 +00:00
ACTION_WIFI_SCAN ,
ACTION_WIFI_MANUAL ,
ACTION_WIFI_LIST ,
ACTION_BACK
2022-01-24 22:41:03 +00:00
} menu_action_t ;
2022-04-08 21:15:57 +00:00
typedef struct _menu_args {
2022-01-24 22:41:03 +00:00
appfs_handle_t fd ;
menu_action_t action ;
2022-04-08 21:15:57 +00:00
} menu_args_t ;
2022-01-23 00:27:22 +00:00
2022-05-03 18:44:45 +00:00
void appfs_store_app ( pax_buf_t * pax_buffer , ILI9341 * ili9341 , uint8_t * framebuffer ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Installing app... " ) ;
esp_err_t res ;
appfs_handle_t handle ;
FILE * app_fd = fopen ( " /sd/gnuboy.bin " , " rb " ) ;
if ( app_fd = = NULL ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Failed to open gnuboy.bin " ) ;
ESP_LOGE ( TAG , " Failed to open gnuboy.bin " ) ;
vTaskDelay ( 100 / portTICK_PERIOD_MS ) ;
return ;
}
size_t app_size ;
uint8_t * app = load_file_to_ram ( app_fd , & app_size ) ;
if ( app = = NULL ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Failed to load app to RAM " ) ;
ESP_LOGE ( TAG , " Failed to load application into RAM " ) ;
vTaskDelay ( 100 / portTICK_PERIOD_MS ) ;
return ;
}
ESP_LOGI ( TAG , " Application size %d " , app_size ) ;
res = appfsCreateFile ( " gnuboy " , app_size , & handle ) ;
if ( res ! = ESP_OK ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Failed to create on AppFS " ) ;
ESP_LOGE ( TAG , " Failed to create file on AppFS (%d) " , res ) ;
vTaskDelay ( 100 / portTICK_PERIOD_MS ) ;
free ( app ) ;
return ;
}
res = appfsWrite ( handle , 0 , app , app_size ) ;
if ( res ! = ESP_OK ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Failed to write to AppFS " ) ;
ESP_LOGE ( TAG , " Failed to write to file on AppFS (%d) " , res ) ;
vTaskDelay ( 100 / portTICK_PERIOD_MS ) ;
free ( app ) ;
return ;
}
free ( app ) ;
ESP_LOGI ( TAG , " Application is now stored in AppFS " ) ;
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " App installed! " ) ;
vTaskDelay ( 100 / portTICK_PERIOD_MS ) ;
return ;
}
2022-04-15 23:16:36 +00:00
void menu_launcher ( xQueueHandle buttonQueue , pax_buf_t * pax_buffer , ILI9341 * ili9341 , uint8_t * framebuffer , menu_action_t * menu_action , appfs_handle_t * appfs_fd ) {
menu_t * menu = menu_alloc ( " Main menu " ) ;
* appfs_fd = APPFS_INVALID_FD ;
* menu_action = ACTION_NONE ;
while ( 1 ) {
* appfs_fd = appfsNextEntry ( * appfs_fd ) ;
if ( * appfs_fd = = APPFS_INVALID_FD ) break ;
const char * name = NULL ;
appfsEntryInfo ( * appfs_fd , & name , NULL ) ;
menu_args_t * args = malloc ( sizeof ( menu_args_t ) ) ;
args - > fd = * appfs_fd ;
args - > action = ACTION_APPFS ;
menu_insert_item ( menu , name , NULL , ( void * ) args , - 1 ) ;
2021-12-29 17:34:55 +00:00
}
2022-04-15 23:16:36 +00:00
* appfs_fd = APPFS_INVALID_FD ;
2021-12-29 17:34:55 +00:00
2022-04-15 23:16:36 +00:00
menu_args_t * install_args = malloc ( sizeof ( menu_args_t ) ) ;
install_args - > action = ACTION_INSTALLER ;
menu_insert_item ( menu , " Hatchery " , NULL , install_args , - 1 ) ;
2022-01-04 23:58:13 +00:00
2022-04-15 23:16:36 +00:00
menu_args_t * settings_args = malloc ( sizeof ( menu_args_t ) ) ;
settings_args - > action = ACTION_SETTINGS ;
2022-04-16 00:14:28 +00:00
menu_insert_item ( menu , " WiFi settings " , NULL , settings_args , - 1 ) ;
2022-04-15 23:16:36 +00:00
menu_args_t * ota_args = malloc ( sizeof ( menu_args_t ) ) ;
ota_args - > action = ACTION_OTA ;
menu_insert_item ( menu , " Firmware update " , NULL , ota_args , - 1 ) ;
2022-01-01 02:06:55 +00:00
2022-04-15 23:16:36 +00:00
menu_args_t * fpga_args = malloc ( sizeof ( menu_args_t ) ) ;
fpga_args - > action = ACTION_FPGA ;
2022-04-16 00:14:28 +00:00
menu_insert_item ( menu , " FPGA test " , NULL , fpga_args , - 1 ) ;
2022-05-03 18:44:45 +00:00
menu_args_t * rp2040bl_args = malloc ( sizeof ( menu_args_t ) ) ;
rp2040bl_args - > action = ACTION_RP2040_BL ;
menu_insert_item ( menu , " RP2040 bootloader " , NULL , rp2040bl_args , - 1 ) ;
menu_args_t * wifi_connect_args = malloc ( sizeof ( menu_args_t ) ) ;
wifi_connect_args - > action = ACTION_WIFI_CONNECT ;
menu_insert_item ( menu , " WiFi connect " , NULL , wifi_connect_args , - 1 ) ;
2022-01-05 22:20:01 +00:00
2022-04-16 00:14:28 +00:00
bool render = true ;
menu_args_t * menuArgs = NULL ;
while ( 1 ) {
2022-04-23 02:00:55 +00:00
rp2040_input_message_t buttonMessage = { 0 } ;
2022-04-16 00:14:28 +00:00
if ( xQueueReceive ( buttonQueue , & buttonMessage , 16 / portTICK_PERIOD_MS ) = = pdTRUE ) {
2022-04-23 02:00:55 +00:00
uint8_t pin = buttonMessage . input ;
2022-04-16 00:14:28 +00:00
bool value = buttonMessage . state ;
switch ( pin ) {
2022-04-23 02:00:55 +00:00
case RP2040_INPUT_JOYSTICK_DOWN :
2022-04-16 00:14:28 +00:00
if ( value ) {
menu_navigate_next ( menu ) ;
render = true ;
}
break ;
2022-04-23 02:00:55 +00:00
case RP2040_INPUT_JOYSTICK_UP :
2022-04-16 00:14:28 +00:00
if ( value ) {
menu_navigate_previous ( menu ) ;
render = true ;
}
break ;
2022-04-23 02:00:55 +00:00
case RP2040_INPUT_BUTTON_ACCEPT :
2022-04-16 00:14:28 +00:00
if ( value ) {
menuArgs = menu_get_callback_args ( menu , menu_get_position ( menu ) ) ;
}
break ;
default :
break ;
}
}
if ( render ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , menu , NULL ) ;
render = false ;
}
if ( menuArgs ! = NULL ) {
* appfs_fd = menuArgs - > fd ;
* menu_action = menuArgs - > action ;
break ;
}
2022-04-15 23:16:36 +00:00
}
2022-04-16 00:14:28 +00:00
for ( size_t index = 0 ; index < menu_get_length ( menu ) ; index + + ) {
free ( menu_get_callback_args ( menu , index ) ) ;
}
menu_free ( menu ) ;
}
void menu_wifi_settings ( xQueueHandle buttonQueue , pax_buf_t * pax_buffer , ILI9341 * ili9341 , uint8_t * framebuffer , menu_action_t * menu_action ) {
menu_t * menu = menu_alloc ( " WiFi settings " ) ;
* menu_action = ACTION_NONE ;
menu_args_t * wifi_scan_args = malloc ( sizeof ( menu_args_t ) ) ;
wifi_scan_args - > action = ACTION_WIFI_SCAN ;
menu_insert_item ( menu , " Add by scan... " , NULL , wifi_scan_args , - 1 ) ;
menu_args_t * wifi_manual_args = malloc ( sizeof ( menu_args_t ) ) ;
wifi_manual_args - > action = ACTION_WIFI_MANUAL ;
menu_insert_item ( menu , " Add manually... " , NULL , wifi_manual_args , - 1 ) ;
menu_args_t * wifi_list_args = malloc ( sizeof ( menu_args_t ) ) ;
wifi_list_args - > action = ACTION_WIFI_LIST ;
menu_insert_item ( menu , " List known networks " , NULL , wifi_list_args , - 1 ) ;
menu_args_t * back_args = malloc ( sizeof ( menu_args_t ) ) ;
back_args - > action = ACTION_BACK ;
menu_insert_item ( menu , " < Back " , NULL , back_args , - 1 ) ;
2022-01-24 21:32:33 +00:00
2022-04-15 23:16:36 +00:00
bool render = true ;
menu_args_t * menuArgs = NULL ;
2022-01-05 22:20:01 +00:00
2022-04-15 23:16:36 +00:00
while ( 1 ) {
2022-04-23 02:00:55 +00:00
rp2040_input_message_t buttonMessage = { 0 } ;
2022-04-15 23:16:36 +00:00
if ( xQueueReceive ( buttonQueue , & buttonMessage , 16 / portTICK_PERIOD_MS ) = = pdTRUE ) {
2022-04-23 02:00:55 +00:00
uint8_t pin = buttonMessage . input ;
2022-04-15 23:16:36 +00:00
bool value = buttonMessage . state ;
switch ( pin ) {
2022-04-23 02:00:55 +00:00
case RP2040_INPUT_JOYSTICK_DOWN :
2022-04-15 23:16:36 +00:00
if ( value ) {
menu_navigate_next ( menu ) ;
render = true ;
}
break ;
2022-04-23 02:00:55 +00:00
case RP2040_INPUT_JOYSTICK_UP :
2022-04-15 23:16:36 +00:00
if ( value ) {
menu_navigate_previous ( menu ) ;
render = true ;
}
break ;
2022-04-23 02:00:55 +00:00
case RP2040_INPUT_BUTTON_ACCEPT :
2022-04-15 23:16:36 +00:00
if ( value ) {
menuArgs = menu_get_callback_args ( menu , menu_get_position ( menu ) ) ;
}
break ;
default :
break ;
}
}
2022-01-05 22:20:01 +00:00
2022-04-15 23:16:36 +00:00
if ( render ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , menu , NULL ) ;
render = false ;
}
if ( menuArgs ! = NULL ) {
* menu_action = menuArgs - > action ;
break ;
}
2022-01-06 00:12:28 +00:00
}
2022-01-23 00:27:22 +00:00
2022-04-15 23:16:36 +00:00
for ( size_t index = 0 ; index < menu_get_length ( menu ) ; index + + ) {
free ( menu_get_callback_args ( menu , index ) ) ;
2022-01-06 00:12:28 +00:00
}
2022-04-15 23:16:36 +00:00
menu_free ( menu ) ;
2022-01-05 22:20:01 +00:00
}
2022-05-03 18:44:45 +00:00
void flush_stdin ( ) {
2022-05-03 21:45:50 +00:00
uint8_t * data = malloc ( 2048 ) ;
uart_read_bytes ( 0 , data , 2048 - 1 , 20 / portTICK_PERIOD_MS ) ;
free ( data ) ;
/*while (true) {
2022-05-03 18:44:45 +00:00
char in = getc ( stdin ) ;
if ( in = = 0xFF ) {
break ;
}
2022-05-03 21:45:50 +00:00
} */
2022-05-03 18:44:45 +00:00
}
bool read_stdin ( uint8_t * buffer , uint32_t len , uint32_t timeout ) {
2022-05-03 21:45:50 +00:00
int read = uart_read_bytes ( 0 , buffer , len , timeout / portTICK_PERIOD_MS ) ;
return ( read = = len ) ;
/*uint8_t index = 0;
2022-05-03 18:44:45 +00:00
uint32_t timeout_counter = 0 ;
while ( index < len ) {
char in = getc ( stdin ) ;
if ( in ! = 0xFF ) {
buffer [ index ] = in ;
index + + ;
} else {
vTaskDelay ( 10 / portTICK_PERIOD_MS ) ;
timeout_counter + = 10 ;
if ( timeout_counter > timeout ) {
return false ;
}
}
}
2022-05-03 21:45:50 +00:00
return true ; */
}
bool rp2040_bl_sync ( ) {
flush_stdin ( ) ;
char command [ ] = " SYNC " ;
uart_write_bytes ( 0 , command , 4 ) ;
uint8_t rx_buffer [ 4 * 6 ] ;
read_stdin ( rx_buffer , sizeof ( rx_buffer ) , 1000 ) ;
if ( memcmp ( rx_buffer , " PICO " , 4 ) ! = 0 ) return false ;
2022-05-03 18:44:45 +00:00
return true ;
}
bool rp2040_bl_get_info ( uint32_t * flash_start , uint32_t * flash_size , uint32_t * erase_size , uint32_t * write_size , uint32_t * max_data_len ) {
flush_stdin ( ) ;
2022-05-03 21:45:50 +00:00
char command [ ] = " INFO " ;
uart_write_bytes ( 0 , command , 4 ) ;
/*printf("INFO");*/
2022-05-03 18:44:45 +00:00
uint8_t rx_buffer [ 4 * 6 ] ;
read_stdin ( rx_buffer , sizeof ( rx_buffer ) , 1000 ) ;
if ( memcmp ( rx_buffer , " OKOK " , 4 ) ! = 0 ) return false ;
memcpy ( ( uint8_t * ) flash_start , & rx_buffer [ 4 * 1 ] , 4 ) ;
memcpy ( ( uint8_t * ) flash_size , & rx_buffer [ 4 * 2 ] , 4 ) ;
memcpy ( ( uint8_t * ) erase_size , & rx_buffer [ 4 * 3 ] , 4 ) ;
memcpy ( ( uint8_t * ) write_size , & rx_buffer [ 4 * 4 ] , 4 ) ;
memcpy ( ( uint8_t * ) max_data_len , & rx_buffer [ 4 * 5 ] , 4 ) ;
return true ;
}
bool rp2040_bl_erase ( uint32_t address , uint32_t length ) {
2022-05-03 21:45:50 +00:00
flush_stdin ( ) ;
char command [ 12 ] ;
snprintf ( command , 5 , " ERAS " ) ;
memcpy ( command + 4 , ( char * ) & address , 4 ) ;
memcpy ( command + 8 , ( char * ) & length , 4 ) ;
uart_write_bytes ( 0 , command , sizeof ( command ) ) ;
/*printf("ERAS");
uint8_t * addres_u8 = ( uint8_t * ) & address ;
2022-05-03 18:44:45 +00:00
putc ( addres_u8 [ 0 ] , stdout ) ;
putc ( addres_u8 [ 1 ] , stdout ) ;
putc ( addres_u8 [ 2 ] , stdout ) ;
putc ( addres_u8 [ 3 ] , stdout ) ;
2022-05-03 21:45:50 +00:00
uint8_t * length_u8 = ( uint8_t * ) & length ;
2022-05-03 18:44:45 +00:00
putc ( length_u8 [ 0 ] , stdout ) ;
putc ( length_u8 [ 1 ] , stdout ) ;
putc ( length_u8 [ 2 ] , stdout ) ;
2022-05-03 21:45:50 +00:00
putc ( length_u8 [ 3 ] , stdout ) ; */
2022-05-03 18:44:45 +00:00
uint8_t rx_buffer [ 4 ] ;
read_stdin ( rx_buffer , sizeof ( rx_buffer ) , 10000 ) ;
if ( memcmp ( rx_buffer , " OKOK " , 4 ) ! = 0 ) return false ;
return true ;
}
bool rp2040_bl_write ( uint32_t address , uint32_t length , uint8_t * data , uint32_t * crc ) {
flush_stdin ( ) ;
2022-05-03 21:45:50 +00:00
char command [ 12 ] ;
snprintf ( command , 5 , " WRIT " ) ;
memcpy ( command + 4 , ( char * ) & address , 4 ) ;
memcpy ( command + 8 , ( char * ) & length , 4 ) ;
uart_write_bytes ( 0 , command , sizeof ( command ) ) ;
/*printf("WRIT");
uint8_t * addres_u8 = ( uint8_t * ) & address ;
2022-05-03 18:44:45 +00:00
putc ( addres_u8 [ 0 ] , stdout ) ;
putc ( addres_u8 [ 1 ] , stdout ) ;
putc ( addres_u8 [ 2 ] , stdout ) ;
putc ( addres_u8 [ 3 ] , stdout ) ;
2022-05-03 21:45:50 +00:00
uint8_t * length_u8 = ( uint8_t * ) & length ;
2022-05-03 18:44:45 +00:00
putc ( length_u8 [ 0 ] , stdout ) ;
putc ( length_u8 [ 1 ] , stdout ) ;
putc ( length_u8 [ 2 ] , stdout ) ;
putc ( length_u8 [ 3 ] , stdout ) ;
for ( uint32_t index = 0 ; index < length ; index + + ) {
putc ( data [ index ] , stdout ) ;
2022-05-03 21:45:50 +00:00
} */
2022-05-03 18:44:45 +00:00
2022-05-03 21:45:50 +00:00
uart_write_bytes ( 0 , data , length ) ;
2022-05-03 18:44:45 +00:00
2022-05-03 21:45:50 +00:00
uint8_t rx_buffer [ 8 ] ;
read_stdin ( rx_buffer , sizeof ( rx_buffer ) , 10000 ) ;
if ( memcmp ( rx_buffer , " OKOK " , 4 ) ! = 0 ) return false ;
2022-05-03 18:44:45 +00:00
memcpy ( ( uint8_t * ) crc , & rx_buffer [ 4 * 1 ] , 4 ) ;
return true ;
}
2022-05-03 21:45:50 +00:00
bool rp2040_bl_seal ( uint32_t addr , uint32_t vtor , uint32_t length , uint32_t crc ) {
flush_stdin ( ) ;
char command [ 20 ] ;
snprintf ( command , 5 , " SEAL " ) ;
memcpy ( command + 4 , ( char * ) & addr , 4 ) ;
memcpy ( command + 8 , ( char * ) & vtor , 4 ) ;
memcpy ( command + 12 , ( char * ) & length , 4 ) ;
memcpy ( command + 16 , ( char * ) & crc , 4 ) ;
uart_write_bytes ( 0 , command , sizeof ( command ) ) ;
uint8_t rx_buffer [ 4 ] ;
read_stdin ( rx_buffer , sizeof ( rx_buffer ) , 10000 ) ;
if ( memcmp ( rx_buffer , " OKOK " , 4 ) ! = 0 ) return false ;
return true ;
}
bool rp2040_bl_go ( uint32_t vtor ) {
flush_stdin ( ) ;
char command [ 8 ] ;
snprintf ( command , 5 , " GOGO " ) ;
memcpy ( command + 4 , ( char * ) & vtor , 4 ) ;
uart_write_bytes ( 0 , command , sizeof ( command ) ) ;
return true ;
}
2022-01-05 22:20:01 +00:00
void app_main ( void ) {
2022-05-03 18:44:45 +00:00
flush_stdin ( ) ;
2022-01-05 22:20:01 +00:00
esp_err_t res ;
2022-04-15 23:16:36 +00:00
/* Initialize memory */
uint8_t * framebuffer = heap_caps_malloc ( ILI9341_BUFFER_SIZE , MALLOC_CAP_8BIT ) ;
2022-01-05 22:20:01 +00:00
if ( framebuffer = = NULL ) {
ESP_LOGE ( TAG , " Failed to allocate framebuffer " ) ;
restart ( ) ;
}
memset ( framebuffer , 0 , ILI9341_BUFFER_SIZE ) ;
2022-04-15 23:16:36 +00:00
pax_buf_t * pax_buffer = malloc ( sizeof ( pax_buf_t ) ) ;
2022-02-04 00:04:51 +00:00
if ( framebuffer = = NULL ) {
ESP_LOGE ( TAG , " Failed to allocate pax buffer " ) ;
restart ( ) ;
}
memset ( pax_buffer , 0 , sizeof ( pax_buf_t ) ) ;
pax_buf_init ( pax_buffer , framebuffer , ILI9341_WIDTH , ILI9341_HEIGHT , PAX_BUF_16_565RGB ) ;
2022-01-11 23:53:38 +00:00
driver_framebuffer_init ( framebuffer ) ;
2022-04-15 23:16:36 +00:00
/* Initialize hardware */
2022-04-23 02:00:55 +00:00
bool lcdReady = false ;
res = board_init ( & lcdReady ) ;
2022-01-23 00:27:22 +00:00
if ( res ! = ESP_OK ) {
2022-04-23 02:00:55 +00:00
if ( lcdReady ) {
ILI9341 * ili9341 = get_ili9341 ( ) ;
2022-05-03 18:44:45 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Hardware error! " ) ;
2022-04-23 02:00:55 +00:00
}
2022-01-23 00:27:22 +00:00
printf ( " Failed to initialize hardware! \n " ) ;
restart ( ) ;
}
2022-04-15 23:16:36 +00:00
ILI9341 * ili9341 = get_ili9341 ( ) ;
ICE40 * ice40 = get_ice40 ( ) ;
BNO055 * bno055 = get_bno055 ( ) ;
RP2040 * rp2040 = get_rp2040 ( ) ;
2022-04-08 21:15:57 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " AppFS init... " ) ;
2022-01-06 00:12:28 +00:00
res = appfs_init ( ) ;
if ( res ! = ESP_OK ) {
ESP_LOGE ( TAG , " AppFS init failed: %d " , res ) ;
2022-04-16 00:14:28 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " AppFS init failed! " ) ;
2022-01-06 00:12:28 +00:00
return ;
}
ESP_LOGI ( TAG , " AppFS initialized " ) ;
2022-01-05 22:20:01 +00:00
2022-04-16 00:14:28 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " NVS init... " ) ;
res = nvs_init ( ) ;
if ( res ! = ESP_OK ) {
ESP_LOGE ( TAG , " NVS init failed: %d " , res ) ;
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " NVS init failed! " ) ;
return ;
}
ESP_LOGI ( TAG , " NVS initialized " ) ;
2022-04-08 21:15:57 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Mount SD card... " ) ;
2022-01-06 00:12:28 +00:00
res = mount_sd ( SD_CMD , SD_CLK , SD_D0 , SD_PWR , " /sd " , false , 5 ) ;
bool sdcard_ready = ( res = = ESP_OK ) ;
2022-04-08 21:15:57 +00:00
if ( sdcard_ready ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " SD card mounted " ) ;
}
2022-04-23 02:00:55 +00:00
ws2812_init ( GPIO_LED_DATA ) ;
2022-04-29 03:24:17 +00:00
uint8_t ledBuffer [ 15 ] = { 50 , 0 , 0 , 50 , 0 , 0 , 50 , 0 , 0 , 50 , 0 , 0 , 50 , 0 , 0 } ;
2022-04-23 02:00:55 +00:00
ws2812_send_data ( ledBuffer , sizeof ( ledBuffer ) ) ;
2022-04-29 03:24:17 +00:00
uint8_t fw_version ;
if ( rp2040_get_firmware_version ( rp2040 , & fw_version ) ! = ESP_OK ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " RP2040 FW VERSION READ FAILED " ) ;
restart ( ) ;
}
if ( fw_version = = 0xFF ) {
// RP2040 is in bootloader mode
char buffer [ 255 ] = { 0 } ;
2022-05-03 18:44:45 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Updating RP2040... " ) ;
vTaskDelay ( 1 / portTICK_PERIOD_MS ) ;
2022-04-29 03:24:17 +00:00
uint8_t bl_version ;
if ( rp2040_get_bootloader_version ( rp2040 , & bl_version ) ! = ESP_OK ) {
2022-05-03 18:44:45 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Communication error (1) " ) ;
restart ( ) ;
}
if ( bl_version ! = 0x01 ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Unknown BL version " ) ;
restart ( ) ;
}
2022-05-03 21:45:50 +00:00
ESP_ERROR_CHECK ( uart_driver_install ( 0 , 2048 , 0 , 0 , NULL , 0 ) ) ;
uart_config_t uart_config = {
. baud_rate = 115200 ,
. data_bits = UART_DATA_8_BITS ,
. parity = UART_PARITY_DISABLE ,
. stop_bits = UART_STOP_BITS_1 ,
. flow_ctrl = UART_HW_FLOWCTRL_DISABLE ,
. source_clk = UART_SCLK_APB ,
} ;
ESP_ERROR_CHECK ( uart_param_config ( 0 , & uart_config ) ) ;
2022-05-03 18:44:45 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Waiting for bootloader... " ) ;
while ( true ) {
vTaskDelay ( 1 / portTICK_PERIOD_MS ) ;
uint8_t bl_state ;
if ( rp2040_get_bootloader_state ( rp2040 , & bl_state ) ! = ESP_OK ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Communication error (2) " ) ;
restart ( ) ;
}
if ( bl_state = = 0xB0 ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Bootloader ready " ) ;
break ;
}
if ( bl_state > 0xB0 ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Unknown BL state " ) ;
restart ( ) ;
}
}
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Sync to BL... " ) ;
char rx_buffer [ 16 ] ;
uint8_t rx_buffer_pos = 0 ;
memset ( rx_buffer , 0 , sizeof ( rx_buffer ) ) ;
while ( true ) {
2022-05-03 21:45:50 +00:00
//printf("SYNC");
//uint8_t rx_buffer[4];
//read_stdin(rx_buffer, sizeof(rx_buffer), 1000);
2022-05-03 18:44:45 +00:00
2022-05-03 21:45:50 +00:00
/*char in = 0xFF;
2022-05-03 18:44:45 +00:00
do {
in = getc ( stdin ) ;
if ( in ! = 0xFF ) {
rx_buffer [ rx_buffer_pos ] = in ;
rx_buffer_pos + + ;
}
2022-05-03 21:45:50 +00:00
} while ( ( in ! = 0xFF ) & & ( rx_buffer_pos < sizeof ( rx_buffer ) ) ) ; */
2022-05-03 18:44:45 +00:00
2022-05-03 21:45:50 +00:00
//if (memcmp(rx_buffer, "PICO", 4) == 0) {
// break;
//}
2022-05-03 18:44:45 +00:00
2022-05-03 21:45:50 +00:00
/*if (rx_buffer_pos >= 4) {
2022-05-03 18:44:45 +00:00
for ( uint8_t i = 0 ; i < sizeof ( rx_buffer ) - 1 ; i + + ) {
rx_buffer [ i ] = rx_buffer [ i + 1 ] ;
if ( memcmp ( rx_buffer , " PICO " , 4 ) = = 0 ) {
break ;
}
}
rx_buffer_pos - - ;
2022-05-03 21:45:50 +00:00
} */
flush_stdin ( ) ;
if ( rp2040_bl_sync ( ) ) break ;
2022-05-03 18:44:45 +00:00
vTaskDelay ( 500 / portTICK_PERIOD_MS ) ;
}
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Synced to BL! " ) ;
2022-05-03 21:45:50 +00:00
/*char in = 0xFF;
2022-05-03 18:44:45 +00:00
do {
in = getc ( stdin ) ;
2022-05-03 21:45:50 +00:00
} while ( in ! = 0xFF ) ; */
flush_stdin ( ) ;
2022-05-03 18:44:45 +00:00
uint32_t flash_start = 0 , flash_size = 0 , erase_size = 0 , write_size = 0 , max_data_len = 0 ;
bool success = rp2040_bl_get_info ( & flash_start , & flash_size , & erase_size , & write_size , & max_data_len ) ;
if ( ! success ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " BL INFO FAIL " ) ;
restart ( ) ;
}
pax_noclip ( pax_buffer ) ;
pax_background ( pax_buffer , 0xCCCCCC ) ;
char message [ 64 ] ;
memset ( message , 0 , sizeof ( message ) ) ;
snprintf ( message , sizeof ( message ) - 1 , " Flash start: 0x%08X " , flash_start ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 0 , message ) ;
snprintf ( message , sizeof ( message ) - 1 , " Flash size : 0x%08X " , flash_size ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 1 , message ) ;
snprintf ( message , sizeof ( message ) - 1 , " Erase size : 0x%08X " , erase_size ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 2 , message ) ;
snprintf ( message , sizeof ( message ) - 1 , " Write size : 0x%08X " , write_size ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 3 , message ) ;
snprintf ( message , sizeof ( message ) - 1 , " Max data ln: 0x%08X " , max_data_len ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 4 , message ) ;
ili9341_write ( ili9341 , framebuffer ) ;
bool eraseSuccess = rp2040_bl_erase ( flash_start , flash_size - erase_size ) ;
snprintf ( message , sizeof ( message ) - 1 , " Erase : %s " , eraseSuccess ? " YES " : " NO " ) ;
pax_draw_text ( pax_buffer , eraseSuccess ? 0xFF000000 : 0xFFFF0000 , NULL , 18 , 0 , 20 * 5 , message ) ;
ili9341_write ( ili9341 , framebuffer ) ;
vTaskDelay ( 1000 / portTICK_PERIOD_MS ) ;
if ( ! eraseSuccess ) {
vTaskDelay ( 1000 / portTICK_PERIOD_MS ) ;
vTaskDelay ( 1000 / portTICK_PERIOD_MS ) ;
vTaskDelay ( 1000 / portTICK_PERIOD_MS ) ;
2022-04-29 03:24:17 +00:00
restart ( ) ;
}
2022-05-03 18:44:45 +00:00
2022-05-03 21:45:50 +00:00
uint32_t position = 0 ;
uint32_t txSize = write_size ;
uint8_t * txBuffer = malloc ( write_size ) ;
uint32_t blockCrc = 0 ;
uint32_t totalCrc = 0 ;
uint32_t totalLength = 0 ;
while ( true ) {
if ( ( sizeof ( mch2022_firmware_bin ) - position ) < txSize ) {
txSize = sizeof ( mch2022_firmware_bin ) - position ;
2022-05-03 18:44:45 +00:00
}
2022-05-03 21:45:50 +00:00
if ( txSize = = 0 ) break ;
2022-05-03 18:44:45 +00:00
pax_noclip ( pax_buffer ) ;
pax_background ( pax_buffer , 0xCCCCCC ) ;
memset ( message , 0 , sizeof ( message ) ) ;
2022-05-03 21:45:50 +00:00
snprintf ( message , sizeof ( message ) - 1 , " Write to : 0x%08X " , 0x10010000 + position ) ;
2022-05-03 18:44:45 +00:00
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 0 , message ) ;
2022-05-03 21:45:50 +00:00
snprintf ( message , sizeof ( message ) - 1 , " Write len: 0x%08X " , txSize ) ;
2022-05-03 18:44:45 +00:00
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 1 , message ) ;
ili9341_write ( ili9341 , framebuffer ) ;
2022-05-03 21:45:50 +00:00
uint32_t checkCrc = 0 ;
memset ( txBuffer , 0 , write_size ) ;
memcpy ( txBuffer , & mch2022_firmware_bin [ position ] , txSize ) ;
blockCrc = crc32_le ( 0 , txBuffer , write_size ) ;
totalCrc = crc32_le ( totalCrc , txBuffer , write_size ) ;
totalLength + = write_size ;
bool writeSuccess = rp2040_bl_write ( 0x10010000 + position , write_size , txBuffer , & checkCrc ) ;
snprintf ( message , sizeof ( message ) - 1 , " Write res: %s " , writeSuccess ? " YES " : " NO " ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 2 , message ) ;
snprintf ( message , sizeof ( message ) - 1 , " CRC : %08X " , blockCrc ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 3 , message ) ;
snprintf ( message , sizeof ( message ) - 1 , " CRC CHECK: %08X " , checkCrc ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 4 , message ) ;
snprintf ( message , sizeof ( message ) - 1 , " CRC OK? : %s " , ( blockCrc = = checkCrc ) ? " YES " : " NO " ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 5 , message ) ;
snprintf ( message , sizeof ( message ) - 1 , " CRC TOTAL: %08X " , totalCrc ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 7 , message ) ;
ili9341_write ( ili9341 , framebuffer ) ;
if ( writeSuccess & & ( blockCrc = = checkCrc ) ) {
vTaskDelay ( 10 / portTICK_PERIOD_MS ) ;
position + = txSize ;
} else {
while ( ! rp2040_bl_sync ( ) ) {
flush_stdin ( ) ;
vTaskDelay ( 20 / portTICK_PERIOD_MS ) ;
}
2022-05-03 18:44:45 +00:00
}
2022-05-03 21:45:50 +00:00
}
free ( txBuffer ) ;
pax_noclip ( pax_buffer ) ;
pax_background ( pax_buffer , 0xCCCCCC ) ;
memset ( message , 0 , sizeof ( message ) ) ;
snprintf ( message , sizeof ( message ) - 1 , " Sealing... " ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 0 , message ) ;
ili9341_write ( ili9341 , framebuffer ) ;
bool sealRes = rp2040_bl_seal ( 0x10010000 , 0x10010000 , totalLength , totalCrc ) ;
snprintf ( message , sizeof ( message ) - 1 , " Result: %s " , sealRes ? " OK " : " FAIL " ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 1 , message ) ;
ili9341_write ( ili9341 , framebuffer ) ;
if ( sealRes ) {
vTaskDelay ( 2000 / portTICK_PERIOD_MS ) ;
pax_noclip ( pax_buffer ) ;
pax_background ( pax_buffer , 0xCCCCCC ) ;
memset ( message , 0 , sizeof ( message ) ) ;
snprintf ( message , sizeof ( message ) - 1 , " Waiting for reset... " ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 0 , message ) ;
ili9341_write ( ili9341 , framebuffer ) ;
rp2040_bl_go ( 0x10010000 ) ;
}
2022-05-03 18:44:45 +00:00
2022-04-29 03:24:17 +00:00
while ( true ) {
2022-05-03 18:44:45 +00:00
vTaskDelay ( 1000 / portTICK_PERIOD_MS ) ;
}
2022-04-29 03:24:17 +00:00
}
2022-05-03 18:44:45 +00:00
pax_noclip ( pax_buffer ) ;
pax_background ( pax_buffer , 0xCCCCCC ) ;
char message [ 64 ] ;
memset ( message , 0 , sizeof ( message ) ) ;
snprintf ( message , sizeof ( message ) - 1 , " RP2040 firmware: 0x%02X " , fw_version ) ;
pax_draw_text ( pax_buffer , 0xFF000000 , NULL , 18 , 0 , 20 * 0 , message ) ;
ili9341_write ( ili9341 , framebuffer ) ;
vTaskDelay ( 1000 / portTICK_PERIOD_MS ) ;
2022-04-29 03:24:17 +00:00
/*while (true) {
fpga_test ( ili9341 , ice40 , rp2040 - > queue ) ;
vTaskDelay ( 200 / portTICK_PERIOD_MS ) ;
} */
2022-04-23 02:00:55 +00:00
/*while (true) {
uint16_t state ;
rp2040_read_buttons ( rp2040 , & state ) ;
printf ( " Button state: %04X \n " , state ) ;
vTaskDelay ( 100 / portTICK_PERIOD_MS ) ;
ledBuffer [ 1 ] = 255 ;
ws2812_send_data ( ledBuffer , sizeof ( ledBuffer ) ) ;
vTaskDelay ( 200 / portTICK_PERIOD_MS ) ;
ledBuffer [ 1 ] = 0 ;
ledBuffer [ 0 ] = 255 ;
ws2812_send_data ( ledBuffer , sizeof ( ledBuffer ) ) ;
fpga_test ( ili9341 , ice40 , rp2040 - > queue ) ;
ledBuffer [ 0 ] = 0 ;
ws2812_send_data ( ledBuffer , sizeof ( ledBuffer ) ) ;
} */
2022-01-01 02:06:55 +00:00
2022-04-15 23:16:36 +00:00
while ( true ) {
menu_action_t menu_action ;
appfs_handle_t appfs_fd ;
2022-04-23 02:00:55 +00:00
menu_launcher ( rp2040 - > queue , pax_buffer , ili9341 , framebuffer , & menu_action , & appfs_fd ) ;
2022-04-15 23:16:36 +00:00
if ( menu_action = = ACTION_APPFS ) {
appfs_boot_app ( appfs_fd ) ;
} else if ( menu_action = = ACTION_FPGA ) {
2022-05-03 18:44:45 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Loading... " ) ;
fpga_test ( ili9341 , ice40 , rp2040 - > queue ) ;
} else if ( menu_action = = ACTION_RP2040_BL ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " RP2040 update... " ) ;
2022-04-29 03:24:17 +00:00
rp2040_reboot_to_bootloader ( rp2040 ) ;
2022-05-03 18:44:45 +00:00
esp_restart ( ) ;
2022-04-15 23:16:36 +00:00
} else if ( menu_action = = ACTION_INSTALLER ) {
2022-05-03 18:44:45 +00:00
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Installing... " ) ;
appfs_store_app ( pax_buffer , ili9341 , framebuffer ) ;
} else if ( menu_action = = ACTION_WIFI_CONNECT ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Connecting... " ) ;
2022-04-18 00:10:44 +00:00
nvs_handle_t handle ;
nvs_open ( " system " , NVS_READWRITE , & handle ) ;
char ssid [ 33 ] ;
char password [ 33 ] ;
size_t requiredSize ;
esp_err_t res = nvs_get_str ( handle , " wifi.ssid " , NULL , & requiredSize ) ;
if ( res ! = ESP_OK ) {
strcpy ( ssid , " " ) ;
} else if ( requiredSize < sizeof ( ssid ) ) {
res = nvs_get_str ( handle , " wifi.ssid " , ssid , & requiredSize ) ;
if ( res ! = ESP_OK ) strcpy ( ssid , " " ) ;
res = nvs_get_str ( handle , " wifi.password " , NULL , & requiredSize ) ;
if ( res ! = ESP_OK ) {
strcpy ( password , " " ) ;
} else if ( requiredSize < sizeof ( password ) ) {
res = nvs_get_str ( handle , " wifi.password " , password , & requiredSize ) ;
if ( res ! = ESP_OK ) strcpy ( password , " " ) ;
}
}
nvs_close ( & handle ) ;
wifi_init ( ssid , password , WIFI_AUTH_WPA2_PSK , 3 ) ;
2022-04-16 00:14:28 +00:00
} else if ( menu_action = = ACTION_OTA ) {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Firmware update... " ) ;
} else if ( menu_action = = ACTION_SETTINGS ) {
2022-04-17 18:22:54 +00:00
while ( true ) {
2022-04-23 02:00:55 +00:00
menu_wifi_settings ( rp2040 - > queue , pax_buffer , ili9341 , framebuffer , & menu_action ) ;
2022-04-17 18:22:54 +00:00
if ( menu_action = = ACTION_WIFI_MANUAL ) {
nvs_handle_t handle ;
nvs_open ( " system " , NVS_READWRITE , & handle ) ;
char ssid [ 33 ] ;
char password [ 33 ] ;
size_t requiredSize ;
esp_err_t res = nvs_get_str ( handle , " wifi.ssid " , NULL , & requiredSize ) ;
if ( res ! = ESP_OK ) {
strcpy ( ssid , " " ) ;
strcpy ( password , " " ) ;
} else if ( requiredSize < sizeof ( ssid ) ) {
res = nvs_get_str ( handle , " wifi.ssid " , ssid , & requiredSize ) ;
if ( res ! = ESP_OK ) strcpy ( ssid , " " ) ;
res = nvs_get_str ( handle , " wifi.password " , NULL , & requiredSize ) ;
if ( res ! = ESP_OK ) {
strcpy ( password , " " ) ;
} else if ( requiredSize < sizeof ( password ) ) {
res = nvs_get_str ( handle , " wifi.password " , password , & requiredSize ) ;
if ( res ! = ESP_OK ) strcpy ( password , " " ) ;
}
}
2022-04-23 02:00:55 +00:00
bool accepted = keyboard ( rp2040 - > queue , pax_buffer , ili9341 , framebuffer , 30 , 30 , pax_buffer - > width - 60 , pax_buffer - > height - 60 , " WiFi SSID " , " Press HOME to exit " , ssid , sizeof ( ssid ) ) ;
2022-04-17 18:22:54 +00:00
if ( accepted ) {
2022-04-23 02:00:55 +00:00
accepted = keyboard ( rp2040 - > queue , pax_buffer , ili9341 , framebuffer , 30 , 30 , pax_buffer - > width - 60 , pax_buffer - > height - 60 , " WiFi password " , " Press HOME to exit " , password , sizeof ( password ) ) ;
2022-04-17 18:22:54 +00:00
}
if ( accepted ) {
nvs_set_str ( handle , " wifi.ssid " , ssid ) ;
nvs_set_str ( handle , " wifi.password " , password ) ;
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " WiFi settings stored " ) ;
} else {
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , " Canceled " ) ;
}
nvs_close ( & handle ) ;
} else if ( menu_action = = ACTION_WIFI_LIST ) {
nvs_handle_t handle ;
nvs_open ( " system " , NVS_READWRITE , & handle ) ;
char ssid [ 33 ] ;
char password [ 33 ] ;
size_t requiredSize ;
esp_err_t res = nvs_get_str ( handle , " wifi.ssid " , NULL , & requiredSize ) ;
if ( res ! = ESP_OK ) {
strcpy ( ssid , " " ) ;
} else if ( requiredSize < sizeof ( ssid ) ) {
res = nvs_get_str ( handle , " wifi.ssid " , ssid , & requiredSize ) ;
if ( res ! = ESP_OK ) strcpy ( ssid , " " ) ;
res = nvs_get_str ( handle , " wifi.password " , NULL , & requiredSize ) ;
if ( res ! = ESP_OK ) {
strcpy ( password , " " ) ;
} else if ( requiredSize < sizeof ( password ) ) {
res = nvs_get_str ( handle , " wifi.password " , password , & requiredSize ) ;
if ( res ! = ESP_OK ) strcpy ( password , " " ) ;
}
}
nvs_close ( & handle ) ;
char buffer [ 300 ] ;
snprintf ( buffer , sizeof ( buffer ) , " SSID is %s \n Password is %s " , ssid , password ) ;
graphics_task ( pax_buffer , ili9341 , framebuffer , NULL , buffer ) ;
} else {
break ;
2022-04-16 21:31:18 +00:00
}
2022-04-16 00:14:28 +00:00
}
2022-01-01 06:13:50 +00:00
}
2022-01-01 02:06:55 +00:00
}
2022-04-08 21:15:57 +00:00
2022-01-05 22:20:01 +00:00
free ( framebuffer ) ;
2021-12-29 17:34:55 +00:00
}