From c13c6fcbd372c0f051e7f9e1c14d2b4077f070e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Gimenez?= Date: Sun, 5 May 2024 13:17:44 +0200 Subject: [PATCH] Update to V5.1 --- Firmware/LogicAnalyzer/.vscode/launch.json | 5 +- Firmware/LogicAnalyzer/.vscode/settings.json | 4 +- Firmware/LogicAnalyzer/CMakeLists.txt | 5 +- Firmware/LogicAnalyzer/LogicAnalyzer.c | 117 ++++++++++++------ Firmware/LogicAnalyzer/LogicAnalyzer.pio | 29 ++++- .../LogicAnalyzer_Build_Settings.h | 2 +- .../LogicAnalyzer/LogicAnalyzer_Structs.h | 13 +- Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.c | 45 ++++++- Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.h | 1 + .../SharedDriver/LogicAnalyzerDriver.cs | 19 ++- 10 files changed, 182 insertions(+), 58 deletions(-) diff --git a/Firmware/LogicAnalyzer/.vscode/launch.json b/Firmware/LogicAnalyzer/.vscode/launch.json index f78a08e..df858a0 100644 --- a/Firmware/LogicAnalyzer/.vscode/launch.json +++ b/Firmware/LogicAnalyzer/.vscode/launch.json @@ -13,13 +13,14 @@ "type": "cortex-debug", "servertype": "openocd", "gdbPath": "arm-none-eabi-gdb", + "openOCDLaunchCommands": ["adapter speed 5000"], "device": "RP2040", "configFiles": [ - "interface/picoprobe.cfg", + "interface/cmsis-dap.cfg", "target/rp2040.cfg" ], "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd", - "runToMain": true, + "runToEntryPoint": "main", // Give restart the same functionality as runToMain "postRestartCommands": [ "break main", diff --git a/Firmware/LogicAnalyzer/.vscode/settings.json b/Firmware/LogicAnalyzer/.vscode/settings.json index 756e668..5b92403 100644 --- a/Firmware/LogicAnalyzer/.vscode/settings.json +++ b/Firmware/LogicAnalyzer/.vscode/settings.json @@ -61,8 +61,6 @@ "cyw43_arch.h": "c", "logicanalyzer_build_settings.h": "c", "sync.h": "c", - "flash.h": "c", - "shared_buffers.h": "c", - "logicanalyzer_wifi.h": "c" + "flash.h": "c" }, } diff --git a/Firmware/LogicAnalyzer/CMakeLists.txt b/Firmware/LogicAnalyzer/CMakeLists.txt index c511b53..caa1a0a 100644 --- a/Firmware/LogicAnalyzer/CMakeLists.txt +++ b/Firmware/LogicAnalyzer/CMakeLists.txt @@ -5,6 +5,8 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) +# set(PICO_BOARD pico_w) + # Initialise pico_sdk from installed location # (note this can come from environment, CMake cache etc) set(PICO_SDK_PATH "F:/PicoSDK/Pico/pico-sdk") @@ -30,7 +32,7 @@ pico_generate_pio_header(${PROJECT_NAME} ) pico_set_program_name(LogicAnalyzer "LogicAnalyzer") -pico_set_program_version(LogicAnalyzer "4.5") +pico_set_program_version(LogicAnalyzer "5.1") pico_enable_stdio_uart(LogicAnalyzer 0) @@ -50,6 +52,7 @@ target_link_libraries(LogicAnalyzer hardware_pio hardware_clocks hardware_flash + hardware_adc pico_multicore pico_base_headers pico_multicore diff --git a/Firmware/LogicAnalyzer/LogicAnalyzer.c b/Firmware/LogicAnalyzer/LogicAnalyzer.c index e565d47..f376605 100644 --- a/Firmware/LogicAnalyzer/LogicAnalyzer.c +++ b/Firmware/LogicAnalyzer/LogicAnalyzer.c @@ -153,6 +153,41 @@ void sendResponse(const char* response, bool toWiFi) printf(response); } +/// @brief Transfer a buffer of data through USB using the TinyUSB CDC functions +/// @param data Buffer of data to transfer +/// @param len Length of the buffer +void cdc_transfer(unsigned char* data, int len) +{ + + int left = len; + int pos = 0; + + while(left > 0) + { + int avail = (int) tud_cdc_write_available(); + + if(avail > left) + avail = left; + + if(avail) + { + int transferred = (int) tud_cdc_write(data + pos, avail); + tud_task(); + tud_cdc_write_flush(); + + pos += transferred; + left -= transferred; + } + else + { + tud_task(); + tud_cdc_write_flush(); + if (!tud_cdc_connected()) + break; + } + } +} + /// @brief Processes data received from the host application /// @param data The received data /// @param length Length of the data @@ -229,7 +264,7 @@ void processData(uint8_t* data, uint length, bool fromWiFi) break; } else - started = startCaptureSimple(req->frequency, req->preSamples, req->postSamples, (uint8_t*)&req->channels, req->channelCount, req->trigger, req->inverted, req->captureMode); + started = startCaptureSimple(req->frequency, req->preSamples, req->postSamples, req->loopCount, (uint8_t*)&req->channels, req->channelCount, req->trigger, req->inverted, req->captureMode); #endif @@ -245,7 +280,7 @@ void processData(uint8_t* data, uint length, bool fromWiFi) #ifdef USE_CYGW_WIFI - case 2: + case 2: //Update WiFi settings wReq = (WIFI_SETTINGS_REQUEST*)&messageBuffer[3]; WIFI_SETTINGS settings; @@ -279,6 +314,27 @@ void processData(uint8_t* data, uint length, bool fromWiFi) break; + case 3: //Read power status + + if(!fromWiFi) + sendResponse("ERR_UNSUPPORTED\n", fromWiFi); + else + { + EVENT_FROM_FRONTEND powerEvent; + powerEvent.event = GET_POWER_STATUS; + event_push(&frontendToWifi, &powerEvent); + } + + break; + + #else + + case 2: + case 3: + + sendResponse("ERR_UNSUPPORTED\n", fromWiFi); + break; + #endif default: @@ -312,41 +368,6 @@ void processData(uint8_t* data, uint length, bool fromWiFi) //have any data, but the capture request has a CAPTURE_REQUEST struct as data. } -/// @brief Transfer a buffer of data through USB using the TinyUSB CDC functions -/// @param data Buffer of data to transfer -/// @param len Length of the buffer -void cdc_transfer(unsigned char* data, int len) -{ - - int left = len; - int pos = 0; - - while(left > 0) - { - int avail = (int) tud_cdc_write_available(); - - if(avail > left) - avail = left; - - if(avail) - { - int transferred = (int) tud_cdc_write(data + pos, avail); - tud_task(); - tud_cdc_write_flush(); - - pos += transferred; - left -= transferred; - } - else - { - tud_task(); - tud_cdc_write_flush(); - if (!tud_cdc_connected()) - break; - } - } -} - /// @brief Receive and process USB data from the host application /// @param skipProcessing If true the received data is not processed (used for cleanup) /// @return True if anything is received, false if not @@ -376,6 +397,19 @@ void purgeUSBData() while(getchar_timeout_us(0) != PICO_ERROR_TIMEOUT); } +/// @brief Send a string response with the power status +/// @param status Status received from the WiFi core +void sendPowerStatus(POWER_STATUS* status) +{ + char buffer[32]; + memset(buffer, 0, 32); + int len = sprintf(buffer, "%.2f", status->vsysVoltage); + buffer[len++] = '_'; + buffer[len++] = status->vbusConnected ? '1' : '0'; + buffer[len] = '\n'; + sendResponse(buffer, true); +} + /// @brief Callback for the WiFi event queue /// @param event Received event void wifiEvent(void* event) @@ -402,6 +436,13 @@ void wifiEvent(void* event) else processData(wEvent->data, wEvent->dataLength, true); break; + case POWER_STATUS_DATA: + { + POWER_STATUS status; + memcpy(&status, wEvent->data, sizeof(POWER_STATUS)); + sendPowerStatus(&status); + } + break; } } @@ -603,7 +644,9 @@ int main() else { LED_ON(); + #ifdef SUPPORTS_COMPLEX_TRIGGER check_fast_interrupt(); + #endif sleep_ms(1000); } } diff --git a/Firmware/LogicAnalyzer/LogicAnalyzer.pio b/Firmware/LogicAnalyzer/LogicAnalyzer.pio index 60e5e04..8f94fb3 100644 --- a/Firmware/LogicAnalyzer/LogicAnalyzer.pio +++ b/Firmware/LogicAnalyzer/LogicAnalyzer.pio @@ -199,6 +199,7 @@ static bool captureFinished; static bool captureProcessed; //Pin mapping, used to map the channels to the PIO program +//COMPLEX_TRIGGER_IN_PIN is added at the end of the array to support the chained mode #if defined (BUILD_PICO) const uint8_t pinMap[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,26,27,28,COMPLEX_TRIGGER_IN_PIN}; #elif defined (BUILD_PICO_W) @@ -212,16 +213,18 @@ static bool captureProcessed; //Main capture buffer, aligned at a 32k boundary, to use the maxixmum ring size supported by DMA channels static uint8_t captureBuffer[CAPTURE_BUFFER_SIZE] __attribute__((aligned(32768))); -//----------------------------------------------------------------------------- -//--------------Complex trigger PIO program------------------------------------ -//----------------------------------------------------------------------------- -#define COMPLEX_TRIGGER_wrap_target 0 -#define COMPLEX_TRIGGER_wrap 8 - #define CAPTURE_TYPE_SIMPLE 0 #define CAPTURE_TYPE_COMPLEX 1 #define CAPTURE_TYPE_FAST 2 +//----------------------------------------------------------------------------- +//--------------Complex trigger PIO program------------------------------------ +//----------------------------------------------------------------------------- +#ifdef SUPPORTS_COMPLEX_TRIGGER + +#define COMPLEX_TRIGGER_wrap_target 0 +#define COMPLEX_TRIGGER_wrap 8 + uint16_t COMPLEX_TRIGGER_program_instructions[] = { // .wrap_target 0x80a0, // 0: pull block @@ -247,6 +250,7 @@ static inline pio_sm_config COMPLEX_TRIGGER_program_get_default_config(uint offs sm_config_set_wrap(&c, offset + COMPLEX_TRIGGER_wrap_target, offset + COMPLEX_TRIGGER_wrap); return c; } +#endif //----------------------------------------------------------------------------- //--------------Complex trigger PIO program END-------------------------------- //----------------------------------------------------------------------------- @@ -254,6 +258,8 @@ static inline pio_sm_config COMPLEX_TRIGGER_program_get_default_config(uint offs //----------------------------------------------------------------------------- //--------------Fast trigger PIO program--------------------------------------- //----------------------------------------------------------------------------- +#ifdef SUPPORTS_COMPLEX_TRIGGER + #define FAST_TRIGGER_wrap_target 0 #define FAST_TRIGGER_wrap 31 @@ -295,6 +301,7 @@ uint8_t create_fast_trigger_program(uint8_t pattern, uint8_t length) return first; } +#endif //----------------------------------------------------------------------------- //--------------Fast trigger PIO program END----------------------------------- //----------------------------------------------------------------------------- @@ -370,8 +377,10 @@ uint32_t find_capture_tail() //Disable the trigger GPIOs to avoid triggering again a chained device void disable_gpios() { + #ifdef SUPPORTS_COMPLEX_TRIGGER gpio_deinit(COMPLEX_TRIGGER_OUT_PIN); gpio_deinit(COMPLEX_TRIGGER_IN_PIN); + #endif for(uint8_t i = 0; i < lastCapturePinCount; i++) gpio_deinit(lastCapturePins[i]); @@ -590,6 +599,8 @@ void stopCapture() { uint32_t int_status = save_and_disable_interrupts(); + #ifdef SUPPORTS_COMPLEX_TRIGGER + if(lastCaptureType == CAPTURE_TYPE_SIMPLE) simple_capture_completed(); else if(lastCaptureType == CAPTURE_TYPE_COMPLEX) @@ -597,6 +608,12 @@ void stopCapture() else if(lastCaptureType == CAPTURE_TYPE_FAST) fast_capture_completed(); + #else + + simple_capture_completed(); + + #endif + restore_interrupts(int_status); } } diff --git a/Firmware/LogicAnalyzer/LogicAnalyzer_Build_Settings.h b/Firmware/LogicAnalyzer/LogicAnalyzer_Build_Settings.h index fa79bdb..18b410f 100644 --- a/Firmware/LogicAnalyzer/LogicAnalyzer_Build_Settings.h +++ b/Firmware/LogicAnalyzer/LogicAnalyzer_Build_Settings.h @@ -1,7 +1,7 @@ #ifndef __BUILD_SETTINGS__ #define __BUILD_SETTINGS__ - #define FIRMWARE_VERSION "V5_0" + #define FIRMWARE_VERSION "V5_1" //Select the board type to build the firmware for #define BUILD_PICO diff --git a/Firmware/LogicAnalyzer/LogicAnalyzer_Structs.h b/Firmware/LogicAnalyzer/LogicAnalyzer_Structs.h index 572018f..41fe357 100644 --- a/Firmware/LogicAnalyzer/LogicAnalyzer_Structs.h +++ b/Firmware/LogicAnalyzer/LogicAnalyzer_Structs.h @@ -66,7 +66,8 @@ CYW_READY, CONNECTED, DISCONNECTED, - DATA_RECEIVED + DATA_RECEIVED, + POWER_STATUS_DATA } WIFI_EVENT; @@ -75,7 +76,8 @@ LED_ON, LED_OFF, CONFIG_RECEIVED, - SEND_DATA + SEND_DATA, + GET_POWER_STATUS } FRONTEND_EVENT; @@ -95,6 +97,13 @@ } EVENT_FROM_FRONTEND; + typedef struct _POWER_STATUS + { + float vsysVoltage; + bool vbusConnected; + + } POWER_STATUS; + #endif #endif \ No newline at end of file diff --git a/Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.c b/Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.c index 4d0d9d9..f4ad30a 100644 --- a/Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.c +++ b/Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.c @@ -11,6 +11,8 @@ #include "pico/stdlib.h" #include "pico/cyw43_arch.h" #include "pico/multicore.h" +#include "hardware/adc.h" +#include "hardware/gpio.h" #include "hardware/flash.h" #include "lwip/pbuf.h" #include "lwip/tcp.h" @@ -27,6 +29,39 @@ bool boot = false; #define LED_ON() cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1) #define LED_OFF() cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0) +void getPowerStatus() +{ + EVENT_FROM_WIFI evtPower; + evtPower.event = POWER_STATUS_DATA; + evtPower.dataLength = sizeof(POWER_STATUS); + POWER_STATUS* status = (POWER_STATUS*)&evtPower.data; + + adc_init(); + + uint32_t oldInt = save_and_disable_interrupts(); + uint32_t old_pad = padsbank0_hw->io[29]; + uint32_t old_ctrl = iobank0_hw->io[29].ctrl; + + adc_gpio_init(29); + adc_select_input(3); + + sleep_ms(100); + + const float conversion_factor = 3.3f / (1 << 12); + status->vsysVoltage = adc_read() * conversion_factor * 3; + + gpio_init(29); + + padsbank0_hw->io[29] = old_pad; + iobank0_hw->io[29].ctrl = old_ctrl; + restore_interrupts(oldInt); + + status->vbusConnected = cyw43_arch_gpio_get(2); + + event_push(&wifiToFrontend, &evtPower); + +} + void readSettings() { wifiSettings = *((volatile WIFI_SETTINGS*)(FLASH_SETTINGS_ADDRESS)); @@ -87,7 +122,9 @@ err_t serverReceiveData(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t e //Client disconnected if(!p || p->tot_len == 0) { - pbuf_free(p); + if(p) + pbuf_free(p); + killClient(); evt.event = DISCONNECTED; event_push(&wifiToFrontend, &evt); @@ -227,6 +264,7 @@ void frontendEvent(void* event) case LED_ON: LED_ON(); break; + case LED_OFF: LED_OFF(); break; @@ -241,6 +279,10 @@ void frontendEvent(void* event) case SEND_DATA: sendData(evt->data, evt->dataLength); break; + + case GET_POWER_STATUS: + getPowerStatus(); + break; } } @@ -262,4 +304,5 @@ void runWiFiCore() cyw43_arch_poll(); } } + #endif \ No newline at end of file diff --git a/Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.h b/Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.h index 8a384e1..d689e25 100644 --- a/Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.h +++ b/Firmware/LogicAnalyzer/LogicAnalyzer_WiFi.h @@ -18,6 +18,7 @@ } WIFI_STATE_MACHINE; void runWiFiCore(); + bool getVsysState(); #endif #endif \ No newline at end of file diff --git a/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs b/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs index 5575c0e..3de4df7 100644 --- a/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs +++ b/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs @@ -11,6 +11,10 @@ namespace SharedDriver { public class LogicAnalyzerDriver : IDisposable, IAnalizerDriver { + const int MAJOR_VERSION = 5; + const int MINOR_VERSION = 1; + + Regex regVersion = new Regex(".*?(V([0-9]+)_([0-9]+))$"); Regex regAddressPort = new Regex("([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)\\:([0-9]+)"); StreamReader readResponse; @@ -85,15 +89,22 @@ namespace SharedDriver if (verMatch == null || !verMatch.Success || !verMatch.Groups[2].Success) { Dispose(); - throw new DeviceConnectionException($"Invalid device version V{ (string.IsNullOrWhiteSpace(verMatch?.Value) ? "(unknown)" : verMatch?.Value) }, minimum supported version: V5_0"); + throw new DeviceConnectionException($"Invalid device version V{ (string.IsNullOrWhiteSpace(verMatch?.Value) ? "(unknown)" : verMatch?.Value) }, minimum supported version: V{MAJOR_VERSION}_{MINOR_VERSION}"); } int majorVer = int.Parse(verMatch.Groups[2].Value); + int minorVer = int.Parse(verMatch.Groups[3].Value); - if (majorVer < 5) + if (majorVer < MAJOR_VERSION) { Dispose(); - throw new DeviceConnectionException($"Invalid device version V{verMatch.Value}, minimum supported version: V5_0"); + throw new DeviceConnectionException($"Invalid device version V{verMatch.Value}, minimum supported version: V{MAJOR_VERSION}_{MINOR_VERSION}"); + } + + if (majorVer == MAJOR_VERSION && minorVer < MINOR_VERSION) + { + Dispose(); + throw new DeviceConnectionException($"Invalid device version V{verMatch.Value}, minimum supported version: V{MAJOR_VERSION}_{MINOR_VERSION}"); } baseStream.ReadTimeout = Timeout.Infinite; @@ -456,8 +467,6 @@ namespace SharedDriver public string? GetVoltageStatus() { - return "UNSUPPORTED"; - if (!isNetwork) return "UNSUPPORTED";