From 57a9b0c32e3ff7dba891e0518af24afd2f6034c7 Mon Sep 17 00:00:00 2001 From: Renze Nicolai Date: Mon, 6 Jun 2022 01:07:58 +0200 Subject: [PATCH] Add webusb mode --- main/CMakeLists.txt | 1 + main/include/webusb.h | 8 +++ main/main.c | 11 ++-- main/webusb.c | 117 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 main/include/webusb.h create mode 100644 main/webusb.c diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index a381bbb..fd2f49b 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -25,6 +25,7 @@ idf_component_register( "animation.c" "button_test.c" "adc_test.c" + "webusb.c" INCLUDE_DIRS "." "include" "menus" diff --git a/main/include/webusb.h b/main/include/webusb.h new file mode 100644 index 0000000..2cd234c --- /dev/null +++ b/main/include/webusb.h @@ -0,0 +1,8 @@ +#pragma once + +#include "ice40.h" +#include "pax_gfx.h" +#include "ili9341.h" +#include + +void webusb_main(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341); diff --git a/main/main.c b/main/main.c index 83e3cf5..51c9644 100644 --- a/main/main.c +++ b/main/main.c @@ -50,6 +50,7 @@ #include "factory_test.h" #include "fpga_download.h" +#include "webusb.h" extern const uint8_t wallpaper_png_start[] asm("_binary_wallpaper_png_start"); extern const uint8_t wallpaper_png_end[] asm("_binary_wallpaper_png_end"); @@ -73,6 +74,8 @@ void display_fatal_error(pax_buf_t* pax_buffer, ILI9341* ili9341, const char* li void app_main(void) { esp_err_t res; + audio_init(); + 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); @@ -116,8 +119,6 @@ void app_main(void) { display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "NVS failed to initialize", "Flash may be corrupted", NULL); esp_restart(); } - - audio_init(); display_boot_screen(pax_buffer, ili9341, "Starting..."); @@ -258,9 +259,9 @@ void app_main(void) { } } else if (webusb_mode == 0x01) { display_boot_screen(pax_buffer, ili9341, "WebUSB mode"); - /*while (true) { - - }*/ + while (true) { + webusb_main(rp2040->queue, pax_buffer, ili9341); + } } else if (webusb_mode == 0x02) { display_boot_screen(pax_buffer, ili9341, "FPGA download mode"); while (true) { diff --git a/main/webusb.c b/main/webusb.c new file mode 100644 index 0000000..995fe11 --- /dev/null +++ b/main/webusb.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "driver/uart.h" +#include "hardware.h" +#include "managed_i2c.h" +#include "pax_gfx.h" +#include "ice40.h" +#include "system_wrapper.h" +#include "graphics_wrapper.h" +#include "esp32/rom/crc.h" + +void webusb_install_uart() { + fflush(stdout); + ESP_ERROR_CHECK(uart_driver_install(0, 2048, 0, 0, NULL, 0)); + uart_config_t uart_config = { + .baud_rate = 921600, + .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)); +} + +void webusb_uninstall_uart() { + uart_driver_delete(0); +} + +bool webusb_read_stdin(uint8_t* buffer, uint32_t len, uint32_t timeout) { + int read = uart_read_bytes(0, buffer, len, timeout / portTICK_PERIOD_MS); + return (read == len); +} + +bool webusb_uart_sync(uint32_t* length, uint32_t* crc) { + uint8_t rx_buffer[4*3]; + webusb_read_stdin(rx_buffer, sizeof(rx_buffer), 100); + if (memcmp(rx_buffer, "WUSB", 4) != 0) return false; + memcpy((uint8_t*) length, &rx_buffer[4 * 1], 4); + memcpy((uint8_t*) crc, &rx_buffer[4 * 2], 4); + return true; +} + +bool webusb_uart_load(uint8_t* buffer, uint32_t length) { + return webusb_read_stdin(buffer, length, 3000); +} + +void webusb_uart_mess(const char *mess) { + uart_write_bytes(0, mess, strlen(mess)); +} + +void webusb_print_status(pax_buf_t* pax_buffer, ILI9341* ili9341, char* message) { + pax_noclip(pax_buffer); + pax_background(pax_buffer, 0x325aa8); + pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*0, "WebUSB mode"); + pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*1, message); + ili9341_write(ili9341, pax_buffer->buf); +} + +void webusb_main(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) { + webusb_install_uart(); + + while (true) { + webusb_print_status(pax_buffer, ili9341, "Waiting..."); + + // 1) Wait for WUSB followed by data length as uint32 and CRC32 of the data as uint32 + uint32_t length, crc; + while (!webusb_uart_sync(&length, &crc)) { + webusb_uart_mess("WUSB"); + } + + webusb_print_status(pax_buffer, ili9341, "Receiving..."); + + // 2) Allocate RAM for the data to be received + uint8_t* buffer = malloc(length); + if (buffer == NULL) { + webusb_uart_mess("EMEM"); + webusb_print_status(pax_buffer, ili9341, "Error: malloc failed"); + vTaskDelay(100 / portTICK_PERIOD_MS); + continue; + } + + // 3) Receive data into the buffer + if (!webusb_uart_load(buffer, length)) { + free(buffer); + webusb_uart_mess("ERCV"); + webusb_print_status(pax_buffer, ili9341, "Error: receive failed"); + vTaskDelay(100 / portTICK_PERIOD_MS); + continue; + } + + // 4) Check CRC + uint32_t checkCrc = crc32_le(0, buffer, length); + + if (checkCrc != crc) { + free(buffer); + webusb_uart_mess("ECRC"); + webusb_print_status(pax_buffer, ili9341, "Error: CRC invalid"); + vTaskDelay(100 / portTICK_PERIOD_MS); + continue; + } + + webusb_uart_mess("OKOK"); + webusb_print_status(pax_buffer, ili9341, "Packet received"); + + // To-do: parse packet + } + + webusb_uninstall_uart(); +}