logic analyzer v2 firmware initial
This commit is contained in:
commit
f87dbb9aa7
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
build/
|
||||||
|
.vscode/
|
||||||
|
*.uf2
|
||||||
|
*.elf
|
||||||
|
*.bin
|
||||||
|
*.map
|
||||||
|
CMakeFiles/
|
||||||
|
CMakeCache.txt
|
||||||
137
CMakeLists.txt
Normal file
137
CMakeLists.txt
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# Generated Cmake Pico project file
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
# Initialise pico_sdk from installed location
|
||||||
|
# (note this can come from environment, CMake cache etc)
|
||||||
|
|
||||||
|
# == DO NEVER EDIT THE NEXT LINES for Raspberry Pi Pico VS Code Extension to work ==
|
||||||
|
if(WIN32)
|
||||||
|
set(USERHOME $ENV{USERPROFILE})
|
||||||
|
else()
|
||||||
|
set(USERHOME $ENV{HOME})
|
||||||
|
endif()
|
||||||
|
set(sdkVersion 2.0.0)
|
||||||
|
set(toolchainVersion 13_2_Rel1)
|
||||||
|
set(picotoolVersion 2.0.0)
|
||||||
|
include(LogicAnalyzer_Build_Settings.cmake)
|
||||||
|
include(${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
|
||||||
|
|
||||||
|
|
||||||
|
# ====================================================================================
|
||||||
|
if(NOT BOARD_TYPE)
|
||||||
|
message(FATAL_ERROR "Board not set, configure the build on LogicAnalyzer_Build_Settings.cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if((BOARD_TYPE STREQUAL "BOARD_PICO_W") OR (BOARD_TYPE STREQUAL "BOARD_PICO_W_WIFI"))
|
||||||
|
message(STATUS "Setting PICO_BOARD to pico_w")
|
||||||
|
set(PICO_BOARD pico_w CACHE STRING "Board type")
|
||||||
|
message(STATUS "Forcing Debug for W build")
|
||||||
|
set(CMAKE_BUILD_TYPE Debug)
|
||||||
|
if(TURBO_MODE)
|
||||||
|
message(FATAL_ERROR "Cannot enable turbo mode for the Pico W")
|
||||||
|
endif()
|
||||||
|
elseif(BOARD_TYPE STREQUAL "BOARD_PICO_2")
|
||||||
|
message(STATUS "Setting PICO_BOARD to pico2")
|
||||||
|
set(PICO_BOARD pico2 CACHE STRING "Board type")
|
||||||
|
else()
|
||||||
|
message(STATUS "Setting PICO_BOARD to pico")
|
||||||
|
set(PICO_BOARD pico CACHE STRING "Board type")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(TURBO_MODE)
|
||||||
|
message(WARNING "WARNING!! Turbo mode enabled! Device will be extremely overclocked and overvoltaged!")
|
||||||
|
add_compile_definitions(TURBO_MODE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEBUG_BUILD)
|
||||||
|
if((BOARD_TYPE STREQUAL "BOARD_PICO") OR (BOARD_TYPE STREQUAL "BOARD_ZERO") OR (BOARD_TYPE STREQUAL "BOARD_PICO_2"))
|
||||||
|
message(STATUS "Forcing Release for RAM-only build")
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Pull in Raspberry Pi Pico SDK (must be before project)
|
||||||
|
include(pico_sdk_import.cmake)
|
||||||
|
|
||||||
|
project(LogicAnalyzer C CXX ASM)
|
||||||
|
|
||||||
|
# Initialise the Raspberry Pi Pico SDK
|
||||||
|
pico_sdk_init()
|
||||||
|
|
||||||
|
# Add executable. Default name is the project name, version 0.1
|
||||||
|
|
||||||
|
FILE(GLOB CSources *.c)
|
||||||
|
ADD_EXECUTABLE(LogicAnalyzer ${CSources})
|
||||||
|
|
||||||
|
# Enable ram-only build for the base pico and zero, increases timming precission
|
||||||
|
if(NOT DEBUG_BUILD)
|
||||||
|
if((BOARD_TYPE STREQUAL "BOARD_PICO") OR (BOARD_TYPE STREQUAL "BOARD_ZERO") OR (BOARD_TYPE STREQUAL "BOARD_PICO_2"))
|
||||||
|
message(STATUS "Setting RAM-only compilation")
|
||||||
|
pico_set_binary_type(LogicAnalyzer copy_to_ram)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Create C header file with the name <pio program>.pio.h
|
||||||
|
pico_generate_pio_header(${PROJECT_NAME}
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/LogicAnalyzer.pio
|
||||||
|
)
|
||||||
|
|
||||||
|
pico_set_program_name(LogicAnalyzer "LogicAnalyzer")
|
||||||
|
pico_set_program_version(LogicAnalyzer "6.0")
|
||||||
|
add_compile_definitions(FIRMWARE_VERSION="V6_0")
|
||||||
|
|
||||||
|
pico_enable_stdio_uart(LogicAnalyzer 0)
|
||||||
|
pico_enable_stdio_usb(LogicAnalyzer 1)
|
||||||
|
|
||||||
|
if(BOARD_TYPE STREQUAL "BOARD_PICO")
|
||||||
|
message(STATUS "Configuring for Pico")
|
||||||
|
add_compile_definitions(BUILD_PICO)
|
||||||
|
endif()
|
||||||
|
if(BOARD_TYPE STREQUAL "BOARD_PICO_2")
|
||||||
|
message(STATUS "Configuring for Pico 2")
|
||||||
|
add_compile_definitions(BUILD_PICO_2)
|
||||||
|
endif()
|
||||||
|
if(BOARD_TYPE STREQUAL "BOARD_PICO_W")
|
||||||
|
message(STATUS "Configuring for Pico W without WiFi support")
|
||||||
|
set(PICO_BOARD pico_w)
|
||||||
|
add_compile_definitions(BUILD_PICO_W)
|
||||||
|
set (CYW_LIB pico_cyw43_arch_none)
|
||||||
|
endif()
|
||||||
|
if(BOARD_TYPE STREQUAL "BOARD_PICO_W_WIFI")
|
||||||
|
message(STATUS "Configuring for Pico W with WiFi support")
|
||||||
|
add_compile_definitions(BUILD_PICO_W_WIFI)
|
||||||
|
set (CYW_LIB pico_cyw43_arch_lwip_poll)
|
||||||
|
endif()
|
||||||
|
if(BOARD_TYPE STREQUAL "BOARD_ZERO")
|
||||||
|
message(STATUS "Configuring for Zero")
|
||||||
|
add_compile_definitions(BUILD_ZERO)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add any user requested libraries
|
||||||
|
target_link_libraries(LogicAnalyzer
|
||||||
|
pico_stdlib
|
||||||
|
hardware_dma
|
||||||
|
hardware_pio
|
||||||
|
hardware_clocks
|
||||||
|
hardware_flash
|
||||||
|
hardware_adc
|
||||||
|
hardware_exception
|
||||||
|
hardware_vreg
|
||||||
|
pico_multicore
|
||||||
|
pico_base_headers
|
||||||
|
pico_multicore
|
||||||
|
cmsis_core
|
||||||
|
${CYW_LIB}
|
||||||
|
)
|
||||||
|
|
||||||
|
pico_add_extra_outputs(LogicAnalyzer)
|
||||||
|
|
||||||
|
target_include_directories(LogicAnalyzer PRIVATE ${CMAKE_CURRENT_LIST_DIR} )
|
||||||
|
|
||||||
|
target_compile_definitions(LogicAnalyzer PUBLIC USBD_MANUFACTURER="Dr. Gusman" USBD_PRODUCT="LogicAnalyzer" USBD_VID=0x1209 USBD_PID=0x3020)
|
||||||
44
Event_Machine.c
Normal file
44
Event_Machine.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "Event_Machine.h"
|
||||||
|
|
||||||
|
//Initialize the event machine
|
||||||
|
void event_machine_init(EVENT_MACHINE* machine, EVENT_HANDLER handler, uint8_t event_size, uint8_t queue_depth)
|
||||||
|
{
|
||||||
|
queue_init(&machine->queue, event_size, queue_depth);
|
||||||
|
machine->handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool event_has_events(EVENT_MACHINE* machine)
|
||||||
|
{
|
||||||
|
return &machine->queue.wptr != &machine->queue.rptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Adds an event to the machine
|
||||||
|
void event_push(EVENT_MACHINE* machine, void* event)
|
||||||
|
{
|
||||||
|
queue_add_blocking(&machine->queue, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Processes the pending events
|
||||||
|
void event_process_queue(EVENT_MACHINE* machine, void* event_buffer, uint8_t max_events)
|
||||||
|
{
|
||||||
|
uint8_t evt_count = 0;
|
||||||
|
while(!queue_is_empty(&machine->queue) && evt_count++ < max_events)
|
||||||
|
{
|
||||||
|
queue_remove_blocking(&machine->queue, event_buffer);
|
||||||
|
machine->handler(event_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Clears the stored events in the machine
|
||||||
|
void event_clear(EVENT_MACHINE* machine)
|
||||||
|
{
|
||||||
|
machine->queue.wptr = 0;
|
||||||
|
machine->queue.rptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Free an event machine
|
||||||
|
void event_free(EVENT_MACHINE* machine)
|
||||||
|
{
|
||||||
|
queue_free(&machine->queue);
|
||||||
|
machine->handler = NULL;
|
||||||
|
}
|
||||||
27
Event_Machine.h
Normal file
27
Event_Machine.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __EVENTMACHINE__
|
||||||
|
#define __EVENTMACHINE__
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/util/queue.h"
|
||||||
|
|
||||||
|
//Event handler function declaration
|
||||||
|
typedef void(*EVENT_HANDLER)(void*);
|
||||||
|
|
||||||
|
//Event machine struct
|
||||||
|
typedef struct _EVENT_MACHINE
|
||||||
|
{
|
||||||
|
//Queue to store events
|
||||||
|
queue_t queue;
|
||||||
|
//Function to process the events
|
||||||
|
EVENT_HANDLER handler;
|
||||||
|
|
||||||
|
} EVENT_MACHINE;
|
||||||
|
|
||||||
|
void event_machine_init(EVENT_MACHINE* machine, EVENT_HANDLER handler, uint8_t args_size, uint8_t queue_depth);
|
||||||
|
bool event_has_events(EVENT_MACHINE* machine);
|
||||||
|
void event_push(EVENT_MACHINE* machine, void* event);
|
||||||
|
void event_process_queue(EVENT_MACHINE* machine, void* event_buffer, uint8_t max_events);
|
||||||
|
void event_clear(EVENT_MACHINE* machine);
|
||||||
|
void event_free(EVENT_MACHINE* machine);
|
||||||
|
|
||||||
|
#endif
|
||||||
774
LogicAnalyzer.c
Normal file
774
LogicAnalyzer.c
Normal file
@ -0,0 +1,774 @@
|
|||||||
|
#include "LogicAnalyzer_Board_Settings.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/dma.h"
|
||||||
|
#include "hardware/pio.h"
|
||||||
|
#include "hardware/clocks.h"
|
||||||
|
#include "hardware/flash.h"
|
||||||
|
#include "hardware/vreg.h"
|
||||||
|
#include "pico/multicore.h"
|
||||||
|
#include "LogicAnalyzer.pio.h"
|
||||||
|
#include "LogicAnalyzer_Structs.h"
|
||||||
|
#include "LogicAnalyzer_Capture.h"
|
||||||
|
#include "hardware/structs/syscfg.h"
|
||||||
|
#include "hardware/structs/systick.h"
|
||||||
|
#include "tusb.h"
|
||||||
|
#include "pico/unique_id.h"
|
||||||
|
#include "pico/bootrom.h"
|
||||||
|
|
||||||
|
#ifdef WS2812_LED
|
||||||
|
#include "LogicAnalyzer_W2812.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (CYGW_LED) || defined(USE_CYGW_WIFI)
|
||||||
|
|
||||||
|
#include "pico/cyw43_arch.h"
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
#include "Event_Machine.h"
|
||||||
|
#include "Shared_Buffers.h"
|
||||||
|
#include "LogicAnalyzer_WiFi.h"
|
||||||
|
#include "hardware/regs/usb.h"
|
||||||
|
#include "hardware/structs/usb.h"
|
||||||
|
|
||||||
|
bool usbDisabled = false;
|
||||||
|
bool cywReady = false;
|
||||||
|
bool skipWiFiData = false;
|
||||||
|
bool dataFromWiFi = false;
|
||||||
|
EVENT_FROM_WIFI wifiEventBuffer;
|
||||||
|
WIFI_SETTINGS_REQUEST* wReq;
|
||||||
|
|
||||||
|
#define MULTICORE_LOCKOUT_TIMEOUT (uint64_t)10 * 365 * 24 * 60 * 60 * 1000 * 1000
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (GPIO_LED)
|
||||||
|
#define INIT_LED() {\
|
||||||
|
gpio_init(LED_IO); \
|
||||||
|
gpio_set_dir(LED_IO, GPIO_OUT); \
|
||||||
|
}
|
||||||
|
#define LED_ON() gpio_put(LED_IO, 1)
|
||||||
|
#define LED_OFF() gpio_put(LED_IO, 0)
|
||||||
|
#elif defined (CYGW_LED)
|
||||||
|
|
||||||
|
#define INIT_LED() { }
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
#define LED_ON() {\
|
||||||
|
EVENT_FROM_FRONTEND lonEvt;\
|
||||||
|
lonEvt.event = LED_ON;\
|
||||||
|
event_push(&frontendToWifi, &lonEvt);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LED_OFF() {\
|
||||||
|
EVENT_FROM_FRONTEND loffEvt;\
|
||||||
|
loffEvt.event = LED_OFF;\
|
||||||
|
event_push(&frontendToWifi, &loffEvt);\
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#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)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined (WS2812_LED)
|
||||||
|
#define INIT_LED() init_rgb()
|
||||||
|
#define LED_ON() send_rgb(0,32,0)
|
||||||
|
#define LED_OFF() send_rgb(0,0,32)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Buffer used to store received data
|
||||||
|
uint8_t messageBuffer[128];
|
||||||
|
//Position in the buffer
|
||||||
|
uint8_t bufferPos = 0;
|
||||||
|
//Capture status
|
||||||
|
bool capturing = false;
|
||||||
|
|
||||||
|
bool blink = false;
|
||||||
|
uint32_t blinkCount = 0;
|
||||||
|
|
||||||
|
//Capture request pointer
|
||||||
|
CAPTURE_REQUEST* req;
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
/// @brief Stores a new WiFi configuration in the flash of the device
|
||||||
|
/// @param settings Settings to store
|
||||||
|
void storeSettings(WIFI_SETTINGS* settings)
|
||||||
|
{
|
||||||
|
uint8_t buffer[FLASH_PAGE_SIZE];
|
||||||
|
memcpy(buffer, settings, sizeof(WIFI_SETTINGS));
|
||||||
|
//multicore_lockout_start_blocking ();
|
||||||
|
multicore_lockout_start_timeout_us(MULTICORE_LOCKOUT_TIMEOUT);
|
||||||
|
|
||||||
|
uint32_t intStatus = save_and_disable_interrupts();
|
||||||
|
|
||||||
|
flash_range_erase(FLASH_SETTINGS_OFFSET, FLASH_SECTOR_SIZE);
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 1000; buc++)
|
||||||
|
{
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_range_program(FLASH_SETTINGS_OFFSET, buffer, FLASH_PAGE_SIZE);
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 1000; buc++)
|
||||||
|
{
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_interrupts(intStatus);
|
||||||
|
|
||||||
|
bool unlocked = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
unlocked = multicore_lockout_end_timeout_us(MULTICORE_LOCKOUT_TIMEOUT);
|
||||||
|
} while(!unlocked);
|
||||||
|
|
||||||
|
sleep_ms(500);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @brief Sends a response message to the host application in string mode
|
||||||
|
/// @param response The message to be sent (null terminated)
|
||||||
|
/// @param toWiFi If true the message is sent to a WiFi endpoint, else to the USB connection through STDIO
|
||||||
|
void sendResponse(const char* response, bool toWiFi)
|
||||||
|
{
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
if(toWiFi)
|
||||||
|
{
|
||||||
|
EVENT_FROM_FRONTEND evt;
|
||||||
|
evt.event = SEND_DATA;
|
||||||
|
evt.dataLength = strlen(response);
|
||||||
|
memset(evt.data, 0, 32);
|
||||||
|
memcpy(evt.data, response, evt.dataLength);
|
||||||
|
event_push(&frontendToWifi, &evt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
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
|
||||||
|
/// @param fromWiFi If true the message comes from a WiFi connection
|
||||||
|
void processData(uint8_t* data, uint length, bool fromWiFi)
|
||||||
|
{
|
||||||
|
for(uint pos = 0; pos < length; pos++)
|
||||||
|
{
|
||||||
|
//Store char in buffer and increment position
|
||||||
|
messageBuffer[bufferPos++] = data[pos];
|
||||||
|
|
||||||
|
//If we have stored the first byte and it is not 0x55 restart reception
|
||||||
|
if(bufferPos == 1 && messageBuffer[0] != 0x55)
|
||||||
|
bufferPos = 0;
|
||||||
|
else if(bufferPos == 2 && messageBuffer[1] != 0xAA) //If we have stored the second byte and it is not 0xAA restart reception
|
||||||
|
bufferPos = 0;
|
||||||
|
else if(bufferPos >= 256) //Have we overflowed the buffer? then inform to the host and restart reception
|
||||||
|
{
|
||||||
|
sendResponse("ERR_MSG_OVERFLOW\n", fromWiFi);
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
else if(bufferPos > 2) //Try to parse the data
|
||||||
|
{
|
||||||
|
if(messageBuffer[bufferPos - 2] == 0xAA && messageBuffer[bufferPos - 1] == 0x55) //Do we have the stop condition?
|
||||||
|
{
|
||||||
|
|
||||||
|
//Yes, unescape the buffer,
|
||||||
|
int dest = 0;
|
||||||
|
|
||||||
|
for(int src = 0; src < bufferPos; src++)
|
||||||
|
{
|
||||||
|
if(messageBuffer[src] == 0xF0)
|
||||||
|
{
|
||||||
|
messageBuffer[dest] = messageBuffer[src + 1] ^ 0xF0;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
messageBuffer[dest] = messageBuffer[src];
|
||||||
|
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(messageBuffer[2]) //Check the command we received
|
||||||
|
{
|
||||||
|
|
||||||
|
case 0: //ID request
|
||||||
|
|
||||||
|
if(bufferPos != 5) //Malformed message?
|
||||||
|
sendResponse("ERR_UNKNOWN_MSG\n", fromWiFi);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendResponse("LOGIC_ANALYZER_"BOARD_NAME"_"FIRMWARE_VERSION"\n", fromWiFi);
|
||||||
|
|
||||||
|
char msg[64];
|
||||||
|
|
||||||
|
sprintf(msg, "FREQ:%d\n", MAX_FREQ);
|
||||||
|
sendResponse(msg, fromWiFi);
|
||||||
|
sprintf(msg, "BLASTFREQ:%d\n", MAX_BLAST_FREQ);
|
||||||
|
sendResponse(msg, fromWiFi);
|
||||||
|
sprintf(msg, "BUFFER:%d\n", CAPTURE_BUFFER_SIZE);
|
||||||
|
sendResponse(msg, fromWiFi);
|
||||||
|
sprintf(msg, "CHANNELS:%d\n", MAX_CHANNELS);
|
||||||
|
sendResponse(msg, fromWiFi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: //Capture request
|
||||||
|
|
||||||
|
req = (CAPTURE_REQUEST*)&messageBuffer[3]; //Get the request pointer
|
||||||
|
|
||||||
|
bool started = false;
|
||||||
|
|
||||||
|
#ifdef SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
|
||||||
|
if(req->triggerType == 1) //Start complex trigger capture
|
||||||
|
started = StartCaptureComplex(req->frequency, req->preSamples, req->postSamples, (uint8_t*)&req->channels, req->channelCount, req->trigger, req->count, req->triggerValue, req->captureMode);
|
||||||
|
else if(req->triggerType == 2) //start fast trigger capture
|
||||||
|
started = StartCaptureFast(req->frequency, req->preSamples, req->postSamples, (uint8_t*)&req->channels, req->channelCount, req->trigger, req->count, req->triggerValue, req->captureMode);
|
||||||
|
else if(req->triggerType == 3)
|
||||||
|
started = StartCaptureBlast(req->frequency, req->postSamples, (uint8_t*)&req->channels, req->channelCount, req->trigger, req->inverted, req->captureMode);
|
||||||
|
else //Start simple trigger capture
|
||||||
|
started = StartCaptureSimple(req->frequency, req->preSamples, req->postSamples, req->loopCount, req->measure, (uint8_t*)&req->channels, req->channelCount, req->trigger, req->inverted, req->captureMode);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
if(req->triggerType == 1 || req->triggerType == 2)
|
||||||
|
{
|
||||||
|
sendResponse("CAPTURE_ERROR\n", fromWiFi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(req->triggerType == 3)
|
||||||
|
started = StartCaptureBlast(req->frequency, req->postSamples, (uint8_t*)&req->channels, req->channelCount, req->trigger, req->inverted, req->captureMode);
|
||||||
|
else //Start simple trigger capture
|
||||||
|
started = StartCaptureSimple(req->frequency, req->preSamples, req->postSamples, req->loopCount, req->measure, (uint8_t*)&req->channels, req->channelCount, req->trigger, req->inverted, req->captureMode);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(started) //If started successfully inform to the host
|
||||||
|
{
|
||||||
|
sendResponse("CAPTURE_STARTED\n", fromWiFi);
|
||||||
|
capturing = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sendResponse("CAPTURE_ERROR\n", fromWiFi); //Else notify the error
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
case 2: //Update WiFi settings
|
||||||
|
|
||||||
|
wReq = (WIFI_SETTINGS_REQUEST*)&messageBuffer[3];
|
||||||
|
WIFI_SETTINGS settings;
|
||||||
|
memcpy(settings.apName, wReq->apName, 33);
|
||||||
|
memcpy(settings.passwd, wReq->passwd, 64);
|
||||||
|
memcpy(settings.ipAddress, wReq->ipAddress, 16);
|
||||||
|
settings.port = wReq->port;
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 33; buc++)
|
||||||
|
settings.checksum += settings.apName[buc];
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 64; buc++)
|
||||||
|
settings.checksum += settings.passwd[buc];
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 16; buc++)
|
||||||
|
settings.checksum += settings.ipAddress[buc];
|
||||||
|
|
||||||
|
settings.checksum += settings.port;
|
||||||
|
|
||||||
|
settings.checksum += 0x0f0f;
|
||||||
|
|
||||||
|
storeSettings(&settings);
|
||||||
|
|
||||||
|
wifiSettings = settings;
|
||||||
|
|
||||||
|
EVENT_FROM_FRONTEND evt;
|
||||||
|
evt.event = CONFIG_RECEIVED;
|
||||||
|
event_push(&frontendToWifi, &evt);
|
||||||
|
|
||||||
|
sendResponse("SETTINGS_SAVED\n", 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
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
|
||||||
|
sendResponse("RESTARTING_BOOTLOADER\n", fromWiFi);
|
||||||
|
sleep_ms(1000);
|
||||||
|
reset_usb_boot(0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
|
||||||
|
blink = true;
|
||||||
|
blinkCount = 0;
|
||||||
|
sendResponse("BLINKON\n", fromWiFi);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
|
||||||
|
blink = false;
|
||||||
|
blinkCount = 0;
|
||||||
|
sendResponse("BLINKOFF\n", fromWiFi);
|
||||||
|
LED_ON();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
sendResponse("ERR_UNKNOWN_MSG\n", fromWiFi); //Unknown message
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferPos = 0; //Reset buffer position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//PROTOCOL EXPLAINED:
|
||||||
|
//
|
||||||
|
//The protocol is very basic, it receives binary frames and sends strings terminated by a carriage return.
|
||||||
|
//
|
||||||
|
//Each binary frame has a start and an end condition, being these two secuences of two bytes:
|
||||||
|
// start condition: 0x55 0xAA
|
||||||
|
// stop condition: 0xAA 0x55
|
||||||
|
//
|
||||||
|
//This kind of framing can cause problems if the packets contain the frame condition bytes, there needs to be implemented
|
||||||
|
//a scape character to avoid this.The char 0xF0 is used as escape character. Escaping is done by XOR'ing the scape character
|
||||||
|
//with the scaped char. For example, if we need to send 0xAA we would send { 0xF0, 0x5A }, which is 0xAA XOR 0xF0 = 0x5A.
|
||||||
|
//In case of sending the scape char we would send { 0xF0, 0x00 }.
|
||||||
|
//
|
||||||
|
//Inside each frame we have a command byte and additional data. Based on the command a binary struct will be deserialized
|
||||||
|
//from the buffer. Right now the protocol has only two commands: ID request and capture request. ID request does not
|
||||||
|
//have any data, but the capture request has a CAPTURE_REQUEST struct as data.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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
|
||||||
|
bool processUSBInput(bool skipProcessing)
|
||||||
|
{
|
||||||
|
//Try to get char
|
||||||
|
uint data = getchar_timeout_us(0);
|
||||||
|
|
||||||
|
//Timeout? Then leave
|
||||||
|
if(data == PICO_ERROR_TIMEOUT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint8_t filteredData = (uint8_t)data;
|
||||||
|
|
||||||
|
if(!skipProcessing)
|
||||||
|
processData(&filteredData, 1, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
/// @brief Purges any pending data in the USB input
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
EVENT_FROM_WIFI* wEvent = (EVENT_FROM_WIFI*)event;
|
||||||
|
|
||||||
|
switch(wEvent->event)
|
||||||
|
{
|
||||||
|
case CYW_READY:
|
||||||
|
cywReady = true;
|
||||||
|
break;
|
||||||
|
case CONNECTED:
|
||||||
|
usbDisabled = true;
|
||||||
|
//disableUSB();
|
||||||
|
break;
|
||||||
|
case DISCONNECTED:
|
||||||
|
usbDisabled = false;
|
||||||
|
purgeUSBData();
|
||||||
|
//enableUSB();
|
||||||
|
break;
|
||||||
|
case DATA_RECEIVED:
|
||||||
|
if(skipWiFiData)
|
||||||
|
dataFromWiFi = true;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Receives and processes input from the host application (when connected through WiFi)
|
||||||
|
/// @param skipProcessing /// @param skipProcessing If true the received data is not processed (used for cleanup)
|
||||||
|
/// @return True if anything is received, false if not
|
||||||
|
bool processWiFiInput(bool skipProcessing)
|
||||||
|
{
|
||||||
|
bool res = event_has_events(&wifiToFrontend);
|
||||||
|
|
||||||
|
if(skipProcessing)
|
||||||
|
{
|
||||||
|
skipWiFiData = true;
|
||||||
|
dataFromWiFi = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_process_queue(&wifiToFrontend, &wifiEventBuffer, 8);
|
||||||
|
|
||||||
|
skipWiFiData = false;
|
||||||
|
|
||||||
|
return dataFromWiFi;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @brief Process input data from the host application if it is available
|
||||||
|
void processInput()
|
||||||
|
{
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
if(!usbDisabled)
|
||||||
|
processUSBInput(false);
|
||||||
|
|
||||||
|
processWiFiInput(false);
|
||||||
|
#else
|
||||||
|
processUSBInput(false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Processes input data from the host application to check if there is any cancel capture request
|
||||||
|
/// @return True if there was input data
|
||||||
|
bool processCancel()
|
||||||
|
{
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
if(!usbDisabled)
|
||||||
|
if(processUSBInput(true))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return processWiFiInput(true);
|
||||||
|
#else
|
||||||
|
return processUSBInput(true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Main app loop
|
||||||
|
/// @return Exit code
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
#if defined (TURBO_MODE)
|
||||||
|
|
||||||
|
vreg_disable_voltage_limit();
|
||||||
|
vreg_set_voltage(VREG_VOLTAGE_1_30);
|
||||||
|
sleep_ms(1);
|
||||||
|
|
||||||
|
//Overclock Powerrrr!
|
||||||
|
set_sys_clock_khz(400000, true);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
set_sys_clock_khz(200000, true);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Enable systick using CPU clock
|
||||||
|
systick_hw->csr = 0x05;
|
||||||
|
|
||||||
|
pico_unique_board_id_t id;
|
||||||
|
pico_get_unique_board_id(&id);
|
||||||
|
|
||||||
|
uint16_t delay = 0;
|
||||||
|
|
||||||
|
for(int buc = 0; buc < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; buc++)
|
||||||
|
delay += id.id[buc];
|
||||||
|
|
||||||
|
delay = (delay & 0x3ff) + ((delay & 0xFC00) >> 6);
|
||||||
|
|
||||||
|
sleep_ms(delay);
|
||||||
|
|
||||||
|
//Initialize USB stdio
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
#if defined (BUILD_PICO_W)
|
||||||
|
cyw43_arch_init();
|
||||||
|
#elif defined (BUILD_PICO_W_WIFI)
|
||||||
|
event_machine_init(&wifiToFrontend, wifiEvent, sizeof(EVENT_FROM_WIFI), 8);
|
||||||
|
multicore_launch_core1(runWiFiCore);
|
||||||
|
while(!cywReady)
|
||||||
|
event_process_queue(&wifiToFrontend, &wifiEventBuffer, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//A bit of delay, if the program tries to send data before Windows has identified the device it may crash
|
||||||
|
sleep_ms(1000);
|
||||||
|
|
||||||
|
//Clear message buffer
|
||||||
|
memset(messageBuffer, 0, 128);
|
||||||
|
|
||||||
|
//Configure led
|
||||||
|
INIT_LED();
|
||||||
|
LED_ON();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
//Are we capturing?
|
||||||
|
if(capturing)
|
||||||
|
{
|
||||||
|
//Is the PIO units still working?
|
||||||
|
if(!IsCapturing())
|
||||||
|
{
|
||||||
|
//Retrieve the capture buffer and get info about it.
|
||||||
|
uint32_t length, first;
|
||||||
|
CHANNEL_MODE mode;
|
||||||
|
uint8_t* buffer = GetBuffer(&length, &first, &mode);
|
||||||
|
|
||||||
|
uint8_t stampsLength;
|
||||||
|
volatile uint32_t* timestamps = GetTimestamps(&stampsLength);
|
||||||
|
|
||||||
|
//Send the data to the host
|
||||||
|
uint8_t* lengthPointer = (uint8_t*)&length;
|
||||||
|
|
||||||
|
//Send capture length
|
||||||
|
sleep_ms(100);
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
if(usbDisabled)
|
||||||
|
{
|
||||||
|
EVENT_FROM_FRONTEND evt;
|
||||||
|
evt.event = SEND_DATA;
|
||||||
|
evt.dataLength = 4;
|
||||||
|
memcpy(evt.data, lengthPointer, 4);
|
||||||
|
event_push(&frontendToWifi, &evt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cdc_transfer(lengthPointer, 4);
|
||||||
|
|
||||||
|
#else
|
||||||
|
cdc_transfer(lengthPointer, 4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sleep_ms(100);
|
||||||
|
|
||||||
|
//Tanslate sample numbers to byte indexes, makes easier to send data
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case MODE_16_CHANNEL:
|
||||||
|
length *= 2;
|
||||||
|
first *= 2;
|
||||||
|
break;
|
||||||
|
case MODE_24_CHANNEL:
|
||||||
|
length *= 4;
|
||||||
|
first *= 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
//Send the samples
|
||||||
|
if(usbDisabled)
|
||||||
|
{
|
||||||
|
EVENT_FROM_FRONTEND evt;
|
||||||
|
evt.event = SEND_DATA;
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
int filledData;
|
||||||
|
while(pos < length)
|
||||||
|
{
|
||||||
|
filledData = 0;
|
||||||
|
while(pos < length && filledData < 32)
|
||||||
|
{
|
||||||
|
evt.data[filledData] = buffer[first++];
|
||||||
|
|
||||||
|
if(first >= 131072)
|
||||||
|
first = 0;
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
filledData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
evt.dataLength = filledData;
|
||||||
|
event_push(&frontendToWifi, &evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
evt.data[0] = stampsLength;
|
||||||
|
evt.dataLength = 1;
|
||||||
|
event_push(&frontendToWifi, &evt);
|
||||||
|
|
||||||
|
for(int buc = 0; buc < stampsLength; buc++)
|
||||||
|
{
|
||||||
|
*((uint32_t*)evt.data) = timestamps[buc];
|
||||||
|
evt.dataLength = 4;
|
||||||
|
event_push(&frontendToWifi, &evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(first + length > CAPTURE_BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
cdc_transfer(buffer + first, CAPTURE_BUFFER_SIZE - first);
|
||||||
|
cdc_transfer(buffer, (first + length) - CAPTURE_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cdc_transfer(buffer + first, length);
|
||||||
|
|
||||||
|
cdc_transfer(&stampsLength, 1);
|
||||||
|
|
||||||
|
if(stampsLength > 1)
|
||||||
|
cdc_transfer((unsigned char*)timestamps, stampsLength * 4);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
if(first + length > CAPTURE_BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
cdc_transfer(buffer + first, CAPTURE_BUFFER_SIZE - first);
|
||||||
|
cdc_transfer(buffer, (first + length) - CAPTURE_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cdc_transfer(buffer + first, length);
|
||||||
|
|
||||||
|
cdc_transfer(&stampsLength, 1);
|
||||||
|
|
||||||
|
if(stampsLength > 1)
|
||||||
|
cdc_transfer((unsigned char*)timestamps, stampsLength * 4);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
//Done!
|
||||||
|
capturing = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LED_OFF();
|
||||||
|
sleep_ms(1000);
|
||||||
|
|
||||||
|
//Check for cancel request
|
||||||
|
if(processCancel())
|
||||||
|
{
|
||||||
|
//Stop capture
|
||||||
|
StopCapture();
|
||||||
|
capturing = false;
|
||||||
|
LED_ON();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LED_ON();
|
||||||
|
#ifdef SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
check_fast_interrupt();
|
||||||
|
#endif
|
||||||
|
sleep_ms(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(blink)
|
||||||
|
{
|
||||||
|
if(blinkCount++ == 200000)
|
||||||
|
{
|
||||||
|
LED_OFF();
|
||||||
|
}
|
||||||
|
else if(blinkCount == 400000)
|
||||||
|
{
|
||||||
|
LED_ON();
|
||||||
|
blinkCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processInput(); //Read incomming data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
241
LogicAnalyzer.pio
Normal file
241
LogicAnalyzer.pio
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
.program BLAST_CAPTURE
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
|
||||||
|
jmp pin LOOP ;wait for trigger
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
|
||||||
|
in pins 32 ;capture
|
||||||
|
|
||||||
|
.wrap
|
||||||
|
|
||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
.program POSITIVE_CAPTURE
|
||||||
|
|
||||||
|
pull
|
||||||
|
out y 32 ;read loop count
|
||||||
|
pull
|
||||||
|
mov x, osr ;read capture length (use MOV instead of PULL so we can MOV it again on each loop)
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
|
||||||
|
in pins 32 ;read sample
|
||||||
|
jmp pin POST_CAPTURE ;exit wrap if pin is set
|
||||||
|
|
||||||
|
.wrap
|
||||||
|
|
||||||
|
POST_CAPTURE:
|
||||||
|
|
||||||
|
in pins 32 ;read sample
|
||||||
|
jmp x-- POST_CAPTURE ;loop if more samples needed
|
||||||
|
|
||||||
|
jmp y-- LOOP ;jump to loop control
|
||||||
|
|
||||||
|
irq 0 ;notify to the main program that we have finished capturing
|
||||||
|
|
||||||
|
LOCK:
|
||||||
|
|
||||||
|
jmp LOCK ;block the program
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
|
||||||
|
mov x, osr ;read loop count
|
||||||
|
|
||||||
|
INNER_LOOP:
|
||||||
|
|
||||||
|
jmp pin POST_CAPTURE ;wait for trigger
|
||||||
|
jmp INNER_LOOP
|
||||||
|
|
||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
.program NEGATIVE_CAPTURE
|
||||||
|
|
||||||
|
pull
|
||||||
|
out y 32 ;read loop count
|
||||||
|
pull
|
||||||
|
mov x, osr ;read capture length (use MOV instead of PULL so we can MOV it again on each loop)
|
||||||
|
|
||||||
|
PRE_CAPTURE:
|
||||||
|
|
||||||
|
in pins 32 ;read sample
|
||||||
|
jmp pin PRE_CAPTURE ;loop if pin is set
|
||||||
|
|
||||||
|
POST_CAPTURE:
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
|
||||||
|
in pins 32 ;read sample
|
||||||
|
jmp x-- POST_CAPTURE ;loop if more samples needed
|
||||||
|
|
||||||
|
jmp y-- LOOP ;jump to loop control
|
||||||
|
|
||||||
|
irq 0 ;notify to the main program that we have finished capturing
|
||||||
|
|
||||||
|
LOCK:
|
||||||
|
|
||||||
|
jmp LOCK ;block the program
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
|
||||||
|
mov x, osr ;read loop count
|
||||||
|
|
||||||
|
INNER_LOOP:
|
||||||
|
jmp pin INNER_LOOP ;wait for trigger
|
||||||
|
|
||||||
|
.wrap
|
||||||
|
|
||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
.program POSITIVE_CAPTURE_MEASUREBURSTS
|
||||||
|
|
||||||
|
pull
|
||||||
|
out y 32 ;read loop count
|
||||||
|
pull
|
||||||
|
mov x, osr ;read capture length (use MOV instead of PULL so we can MOV it again on each loop)
|
||||||
|
irq wait 1 ;trigger NMI to sync first timestamp
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
|
||||||
|
in pins 32 ;read sample
|
||||||
|
jmp pin POST_CAPTURE ;exit wrap if pin is set
|
||||||
|
|
||||||
|
.wrap
|
||||||
|
|
||||||
|
POST_CAPTURE:
|
||||||
|
|
||||||
|
in pins 32 ;read sample
|
||||||
|
jmp x-- POST_CAPTURE ;loop if more samples needed
|
||||||
|
|
||||||
|
jmp y-- LOOP ;jump to loop control
|
||||||
|
|
||||||
|
irq 1 ;trigger NMI on the CPU to capture burst timestamp
|
||||||
|
irq 0 ;notify to the main program that we have finished capturing
|
||||||
|
|
||||||
|
LOCK:
|
||||||
|
|
||||||
|
jmp LOCK ;block the program
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
|
||||||
|
irq 1 ;trigger NMI on the CPU to capture burst timestamp
|
||||||
|
mov x, osr ;read loop count
|
||||||
|
|
||||||
|
INNER_LOOP:
|
||||||
|
|
||||||
|
jmp pin POST_CAPTURE ;wait for trigger
|
||||||
|
jmp INNER_LOOP
|
||||||
|
|
||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
.program NEGATIVE_CAPTURE_MEASUREBURSTS
|
||||||
|
|
||||||
|
pull
|
||||||
|
out y 32 ;read loop count
|
||||||
|
pull
|
||||||
|
mov x, osr ;read capture length (use MOV instead of PULL so we can MOV it again on each loop)
|
||||||
|
irq wait 1 ;trigger NMI to sync first timestamp
|
||||||
|
|
||||||
|
PRE_CAPTURE:
|
||||||
|
|
||||||
|
in pins 32 ;read sample
|
||||||
|
jmp pin PRE_CAPTURE ;loop if pin is set
|
||||||
|
|
||||||
|
POST_CAPTURE:
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
|
||||||
|
in pins 32 ;read sample
|
||||||
|
jmp x-- POST_CAPTURE ;loop if more samples needed
|
||||||
|
|
||||||
|
jmp y-- LOOP ;jump to loop control
|
||||||
|
|
||||||
|
irq 1 ;trigger NMI on the CPU to capture burst timestamp
|
||||||
|
irq 0 ;notify to the main program that we have finished capturing
|
||||||
|
|
||||||
|
LOCK:
|
||||||
|
|
||||||
|
jmp LOCK ;block the program
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
|
||||||
|
irq 1 ;trigger NMI on the CPU to capture burst timestamp
|
||||||
|
mov x, osr ;read loop count
|
||||||
|
|
||||||
|
INNER_LOOP:
|
||||||
|
jmp pin INNER_LOOP ;wait for trigger
|
||||||
|
|
||||||
|
.wrap
|
||||||
|
|
||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
.program COMPLEX_CAPTURE
|
||||||
|
|
||||||
|
pull
|
||||||
|
out x 32 ;read capture length
|
||||||
|
|
||||||
|
wait irq 7 ;wait for trigger program to be ready
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
|
||||||
|
in pins 29 ;read sample
|
||||||
|
jmp pin POST_CAPTURE ;exit wrap if pin is set
|
||||||
|
|
||||||
|
.wrap
|
||||||
|
|
||||||
|
POST_CAPTURE:
|
||||||
|
|
||||||
|
in pins 29 ;read sample
|
||||||
|
jmp x-- POST_CAPTURE ;loop if more samples needed
|
||||||
|
|
||||||
|
irq 0 ;notify to the main program that we have finished capturing
|
||||||
|
|
||||||
|
LOCK:
|
||||||
|
|
||||||
|
jmp LOCK ;block the program
|
||||||
|
|
||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
.program FAST_CAPTURE
|
||||||
|
|
||||||
|
pull
|
||||||
|
out x 32 ;read capture length
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
|
||||||
|
in pins 29 ;read sample
|
||||||
|
jmp pin POST_CAPTURE ;exit wrap if pin is set
|
||||||
|
|
||||||
|
.wrap
|
||||||
|
|
||||||
|
POST_CAPTURE:
|
||||||
|
|
||||||
|
in pins 29 ;read sample
|
||||||
|
jmp x-- POST_CAPTURE ;loop if more samples needed
|
||||||
|
|
||||||
|
irq 0 ;notify to the main program that we have finished capturing
|
||||||
|
|
||||||
|
LOCK:
|
||||||
|
|
||||||
|
jmp LOCK ;block the program
|
||||||
|
|
||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
;--------Kept only for reference, the program is stored in volatile memory as it must--------
|
||||||
|
;---------be modified for concrete trigger parameters.---------------------------------------
|
||||||
|
;--------------------------------------------------------------------------------------------
|
||||||
|
;.program COMPLEX_TRIGGER
|
||||||
|
|
||||||
|
; pull
|
||||||
|
; out x 32 ;read trigger value
|
||||||
|
|
||||||
|
; set pins 0 ;set trigger pin to low
|
||||||
|
|
||||||
|
; irq 7 ;Release capture program
|
||||||
|
|
||||||
|
;TRIGGER_LOOP:
|
||||||
|
|
||||||
|
; mov osr, pins ;read pin status to output shift register
|
||||||
|
; out y, 4 ;output 4 bits to Y (writes 32 bits)
|
||||||
|
; jmp x!=y TRIGGER_LOOP ;loop if trigger not met
|
||||||
|
|
||||||
|
; set pins 1 ;set trigger pin to high (trigger met)
|
||||||
|
|
||||||
|
;LOCK:
|
||||||
|
|
||||||
|
; jmp LOCK ;block program
|
||||||
122
LogicAnalyzer_Board_Settings.h
Normal file
122
LogicAnalyzer_Board_Settings.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#ifndef __LOGICANALYZER_BOARD_SETTINGS__
|
||||||
|
|
||||||
|
#define __LOGICANALYZER_BOARD_SETTINGS__
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
//#include "LogicAnalyzer_Build_Settings.h"
|
||||||
|
|
||||||
|
//Board definitions
|
||||||
|
|
||||||
|
//This defines the name sent to the software
|
||||||
|
//#define BOARD_NAME "PICO"
|
||||||
|
//If defined the device supports complex, fast and external triggers
|
||||||
|
//#define SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
//Stablishes the channel base GPIO
|
||||||
|
//#define INPUT_PIN_BASE 2
|
||||||
|
//Complex/fast/ext trigger output pin
|
||||||
|
//#define COMPLEX_TRIGGER_OUT_PIN 0
|
||||||
|
//Complex/fast/ext trigger input pin
|
||||||
|
//#define COMPLEX_TRIGGER_IN_PIN 1
|
||||||
|
//If defined, the onboard led is a led connected to a GPIO
|
||||||
|
//#define GPIO_LED
|
||||||
|
//If defined, the onboard led is a led connected to a CYGW module (for the Pico W)
|
||||||
|
//#define CYGW_LED
|
||||||
|
//If defined, the onboard led is a RGB led connected to a GPIO
|
||||||
|
//#define WS2812_LED
|
||||||
|
//Defines the used GPIO used for the GPIO and WS2812 led types
|
||||||
|
//#define LED_IO 25
|
||||||
|
//If defined enables the Pico W WiFi module
|
||||||
|
//#define USE_CYGW_WIFI
|
||||||
|
|
||||||
|
#if defined (BUILD_PICO)
|
||||||
|
|
||||||
|
#define BOARD_NAME "PICO"
|
||||||
|
#define SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
#define INPUT_PIN_BASE 2
|
||||||
|
#define COMPLEX_TRIGGER_OUT_PIN 0
|
||||||
|
#define COMPLEX_TRIGGER_IN_PIN 1
|
||||||
|
#define GPIO_LED
|
||||||
|
#define LED_IO 25
|
||||||
|
|
||||||
|
#ifdef TURBO_MODE
|
||||||
|
#define MAX_FREQ 200000000
|
||||||
|
#define MAX_BLAST_FREQ 400000000
|
||||||
|
#else
|
||||||
|
#define MAX_FREQ 100000000
|
||||||
|
#define MAX_BLAST_FREQ 200000000
|
||||||
|
#endif
|
||||||
|
#define CAPTURE_BUFFER_SIZE (128 * 1024)
|
||||||
|
#define MAX_CHANNELS 24
|
||||||
|
|
||||||
|
#elif defined (BUILD_PICO_2)
|
||||||
|
|
||||||
|
#define BOARD_NAME "PICO_2"
|
||||||
|
#define SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
#define INPUT_PIN_BASE 2
|
||||||
|
#define COMPLEX_TRIGGER_OUT_PIN 0
|
||||||
|
#define COMPLEX_TRIGGER_IN_PIN 1
|
||||||
|
#define GPIO_LED
|
||||||
|
#define LED_IO 25
|
||||||
|
|
||||||
|
#ifdef TURBO_MODE
|
||||||
|
#define MAX_FREQ 200000000
|
||||||
|
#define MAX_BLAST_FREQ 400000000
|
||||||
|
#else
|
||||||
|
#define MAX_FREQ 100000000
|
||||||
|
#define MAX_BLAST_FREQ 200000000
|
||||||
|
#endif
|
||||||
|
#define CAPTURE_BUFFER_SIZE (128 * 3 * 1024)
|
||||||
|
#define MAX_CHANNELS 24
|
||||||
|
|
||||||
|
#elif defined (BUILD_PICO_W)
|
||||||
|
|
||||||
|
#define BOARD_NAME "W"
|
||||||
|
#define SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
#define INPUT_PIN_BASE 2
|
||||||
|
#define COMPLEX_TRIGGER_OUT_PIN 0
|
||||||
|
#define COMPLEX_TRIGGER_IN_PIN 1
|
||||||
|
#define CYGW_LED
|
||||||
|
|
||||||
|
#define MAX_FREQ 100000000
|
||||||
|
#define MAX_BLAST_FREQ 200000000
|
||||||
|
#define CAPTURE_BUFFER_SIZE (128 * 1024)
|
||||||
|
#define MAX_CHANNELS 24
|
||||||
|
|
||||||
|
#elif defined (BUILD_PICO_W_WIFI)
|
||||||
|
|
||||||
|
#define BOARD_NAME "WIFI"
|
||||||
|
#define SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
#define INPUT_PIN_BASE 2
|
||||||
|
#define COMPLEX_TRIGGER_OUT_PIN 0
|
||||||
|
#define COMPLEX_TRIGGER_IN_PIN 1
|
||||||
|
#define CYGW_LED
|
||||||
|
#define USE_CYGW_WIFI
|
||||||
|
|
||||||
|
#define MAX_FREQ 100000000
|
||||||
|
#define MAX_BLAST_FREQ 200000000
|
||||||
|
#define CAPTURE_BUFFER_SIZE (128 * 1024)
|
||||||
|
#define MAX_CHANNELS 24
|
||||||
|
|
||||||
|
#elif defined (BUILD_ZERO)
|
||||||
|
|
||||||
|
#define BOARD_NAME "ZERO"
|
||||||
|
#define SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
#define INPUT_PIN_BASE 0
|
||||||
|
#define COMPLEX_TRIGGER_OUT_PIN 17
|
||||||
|
#define COMPLEX_TRIGGER_IN_PIN 18
|
||||||
|
#define WS2812_LED
|
||||||
|
#define LED_IO 16
|
||||||
|
|
||||||
|
#ifdef TURBO_MODE
|
||||||
|
#define MAX_FREQ 200000000
|
||||||
|
#define MAX_BLAST_FREQ 400000000
|
||||||
|
#else
|
||||||
|
#define MAX_FREQ 100000000
|
||||||
|
#define MAX_BLAST_FREQ 200000000
|
||||||
|
#endif
|
||||||
|
#define CAPTURE_BUFFER_SIZE (128 * 1024)
|
||||||
|
#define MAX_CHANNELS 24
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
10
LogicAnalyzer_Build_Settings.cmake
Normal file
10
LogicAnalyzer_Build_Settings.cmake
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# This file controls the build settings, set your board version
|
||||||
|
# Current versions: "BOARD_PICO", "BOARD_PICO_W", "BOARD_PICO_W_WIFI", "BOARD_ZERO", "BOARD_PICO_2"
|
||||||
|
set(BOARD_TYPE "BOARD_PICO_2")
|
||||||
|
|
||||||
|
# Set to 1 to enable 200Mhz mode (warning! extreme overclock and overvoltage!)
|
||||||
|
# Not available for the Pico W
|
||||||
|
set(TURBO_MODE 1)
|
||||||
|
|
||||||
|
# Uncomment to be able to debug the build
|
||||||
|
# set(DEBUG_BUILD 1)
|
||||||
1375
LogicAnalyzer_Capture.c
Normal file
1375
LogicAnalyzer_Capture.c
Normal file
File diff suppressed because it is too large
Load Diff
29
LogicAnalyzer_Capture.h
Normal file
29
LogicAnalyzer_Capture.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "LogicAnalyzer_Board_Settings.h"
|
||||||
|
#ifndef __ANALYZER_CAPTURE__
|
||||||
|
#define __ANALYZER_CAPTURE__
|
||||||
|
|
||||||
|
#if defined(BUILD_PICO_2)
|
||||||
|
#include <RP2350.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MODE_8_CHANNEL,
|
||||||
|
MODE_16_CHANNEL,
|
||||||
|
MODE_24_CHANNEL
|
||||||
|
|
||||||
|
} CHANNEL_MODE;
|
||||||
|
|
||||||
|
bool StartCaptureSimple(uint32_t freq, uint32_t preLength, uint32_t postLength, uint8_t loopCount, uint8_t measureBursts, const uint8_t* capturePins, uint8_t capturePinCount, uint8_t triggerPin, bool invertTrigger, CHANNEL_MODE captureMode);
|
||||||
|
bool StartCaptureBlast(uint32_t freq, uint32_t length, const uint8_t* capturePins, uint8_t capturePinCount, uint8_t triggerPin, bool invertTrigger, CHANNEL_MODE captureMode);
|
||||||
|
#ifdef SUPPORTS_COMPLEX_TRIGGER
|
||||||
|
bool StartCaptureComplex(uint32_t freq, uint32_t preLength, uint32_t postLength, const uint8_t* capturePins, uint8_t capturePinCount, uint8_t triggerPinBase, uint8_t triggerPinCount, uint16_t triggerValue, CHANNEL_MODE captureMode);
|
||||||
|
bool StartCaptureFast(uint32_t freq, uint32_t preLength, uint32_t postLength, const uint8_t* capturePins, uint8_t capturePinCount, uint8_t triggerPinBase, uint8_t triggerPinCount, uint16_t triggerValue, CHANNEL_MODE captureMode);
|
||||||
|
#endif
|
||||||
|
void StopCapture();
|
||||||
|
bool IsCapturing();
|
||||||
|
uint8_t* GetBuffer(uint32_t* bufferSize, uint32_t* firstSample, CHANNEL_MODE* captureMode);
|
||||||
|
volatile uint32_t* GetTimestamps(uint8_t* length);
|
||||||
|
void check_fast_interrupt();
|
||||||
|
|
||||||
|
#endif
|
||||||
110
LogicAnalyzer_Structs.h
Normal file
110
LogicAnalyzer_Structs.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
|
||||||
|
#ifndef __ANALYZER_STRUCTS__
|
||||||
|
#define __ANALYZER_STRUCTS__
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
|
||||||
|
//Capture request issued by the host computer
|
||||||
|
typedef struct _CAPTURE_REQUEST
|
||||||
|
{
|
||||||
|
//Indicates tthe trigger type: 0 = edge, 1 = pattern (complex), 2 = pattern (fast)
|
||||||
|
uint8_t triggerType;
|
||||||
|
//Trigger channel (or base channel for pattern trigger)
|
||||||
|
uint8_t trigger;
|
||||||
|
|
||||||
|
//Union of the trigger characteristics (inverted or pin count)
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint8_t inverted;
|
||||||
|
uint8_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Trigger value of the pattern trigger
|
||||||
|
uint16_t triggerValue;
|
||||||
|
//Channels to capture
|
||||||
|
uint8_t channels[24];
|
||||||
|
//Channel count
|
||||||
|
uint8_t channelCount;
|
||||||
|
//Sampling frequency
|
||||||
|
uint32_t frequency;
|
||||||
|
//Number of samples stored before the trigger
|
||||||
|
uint32_t preSamples;
|
||||||
|
//Number of samples stored after the trigger
|
||||||
|
uint32_t postSamples;
|
||||||
|
//Number of capture loops
|
||||||
|
uint8_t loopCount;
|
||||||
|
//Measure burst times
|
||||||
|
uint8_t measure;
|
||||||
|
//Capture mode (0 = 8 channel, 1 = 16 channel, 2 = 24 channel)
|
||||||
|
uint8_t captureMode;
|
||||||
|
|
||||||
|
}CAPTURE_REQUEST;
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
typedef struct _WIFI_SETTINGS
|
||||||
|
{
|
||||||
|
char apName[33];
|
||||||
|
char passwd[64];
|
||||||
|
char ipAddress[16];
|
||||||
|
uint16_t port;
|
||||||
|
uint16_t checksum;
|
||||||
|
|
||||||
|
} WIFI_SETTINGS;
|
||||||
|
|
||||||
|
typedef struct _WIFI_SETTINGS_REQUEST
|
||||||
|
{
|
||||||
|
char apName[33];
|
||||||
|
char passwd[64];
|
||||||
|
char ipAddress[16];
|
||||||
|
uint16_t port;
|
||||||
|
|
||||||
|
} WIFI_SETTINGS_REQUEST;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CYW_READY,
|
||||||
|
CONNECTED,
|
||||||
|
DISCONNECTED,
|
||||||
|
DATA_RECEIVED,
|
||||||
|
POWER_STATUS_DATA
|
||||||
|
|
||||||
|
} WIFI_EVENT;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LED_ON,
|
||||||
|
LED_OFF,
|
||||||
|
CONFIG_RECEIVED,
|
||||||
|
SEND_DATA,
|
||||||
|
GET_POWER_STATUS
|
||||||
|
|
||||||
|
} FRONTEND_EVENT;
|
||||||
|
|
||||||
|
typedef struct _EVENT_FROM_WIFI
|
||||||
|
{
|
||||||
|
WIFI_EVENT event;
|
||||||
|
char data[128];
|
||||||
|
uint8_t dataLength;
|
||||||
|
|
||||||
|
} EVENT_FROM_WIFI;
|
||||||
|
|
||||||
|
typedef struct _EVENT_FROM_FRONTEND
|
||||||
|
{
|
||||||
|
FRONTEND_EVENT event;
|
||||||
|
char data[32];
|
||||||
|
uint8_t dataLength;
|
||||||
|
|
||||||
|
} EVENT_FROM_FRONTEND;
|
||||||
|
|
||||||
|
typedef struct _POWER_STATUS
|
||||||
|
{
|
||||||
|
float vsysVoltage;
|
||||||
|
bool vbusConnected;
|
||||||
|
|
||||||
|
} POWER_STATUS;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
70
LogicAnalyzer_W2812.c
Normal file
70
LogicAnalyzer_W2812.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#include "LogicAnalyzer_Board_Settings.h"
|
||||||
|
|
||||||
|
#ifdef WS2812_LED
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "LogicAnalyzer_w2812.h"
|
||||||
|
|
||||||
|
#define LONG_START 52.0 * (MAX_FREQ / 100000000.0)
|
||||||
|
#define SHORT_START 26.0 * (MAX_FREQ / 100000000.0)
|
||||||
|
#define LONG_END 52.0 * (MAX_FREQ / 100000000.0)
|
||||||
|
#define SHORT_END 25.0 * (MAX_FREQ / 100000000.0)
|
||||||
|
|
||||||
|
void __attribute__ ((noinline)) delay_cycles4(uint32_t loops)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"mov r0, %[input_loops]\r\n"
|
||||||
|
"1:\r\n"
|
||||||
|
"sub r0, #1\r\n"
|
||||||
|
"bne 1b\r\n"
|
||||||
|
:
|
||||||
|
: [input_loops] "r" (loops)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char reverse_bits(unsigned char b) {
|
||||||
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||||
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||||
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_rgb(uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
{
|
||||||
|
uint32_t rgb = reverse_bits(g) | (reverse_bits(r) << 8) | (reverse_bits(b) << 16);
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 24; buc++)
|
||||||
|
{
|
||||||
|
if(rgb & (1 << buc))
|
||||||
|
{
|
||||||
|
gpio_put(LED_IO, true);
|
||||||
|
delay_cycles4(LONG_START);
|
||||||
|
gpio_put(LED_IO, false);
|
||||||
|
delay_cycles4(SHORT_END);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpio_put(LED_IO, true);
|
||||||
|
delay_cycles4(SHORT_START);
|
||||||
|
gpio_put(LED_IO, false);
|
||||||
|
delay_cycles4(LONG_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_rgb()
|
||||||
|
{
|
||||||
|
gpio_init(LED_IO);
|
||||||
|
gpio_set_dir(LED_IO, true);
|
||||||
|
gpio_put(LED_IO, true);
|
||||||
|
sleep_us(500);
|
||||||
|
gpio_put(LED_IO, false);
|
||||||
|
sleep_us(500);
|
||||||
|
send_rgb(0, 0, 0);
|
||||||
|
sleep_ms(500);
|
||||||
|
send_rgb(0, 0, 0);
|
||||||
|
sleep_ms(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
14
LogicAnalyzer_W2812.h
Normal file
14
LogicAnalyzer_W2812.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "LogicAnalyzer_Board_Settings.h"
|
||||||
|
|
||||||
|
#ifdef WS2812_LED
|
||||||
|
|
||||||
|
#ifndef __LOGICANALYZER_W2812__
|
||||||
|
|
||||||
|
#define __LOGICANALYZER_W2812__
|
||||||
|
|
||||||
|
void send_rgb(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
void init_rgb();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
308
LogicAnalyzer_WiFi.c
Normal file
308
LogicAnalyzer_WiFi.c
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
#include "LogicAnalyzer_Board_Settings.h"
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
#include "Event_Machine.h"
|
||||||
|
#include "Shared_Buffers.h"
|
||||||
|
#include "LogicAnalyzer_WiFi.h"
|
||||||
|
#include "LogicAnalyzer_Structs.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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"
|
||||||
|
|
||||||
|
EVENT_FROM_FRONTEND frontendEventBuffer;
|
||||||
|
WIFI_STATE_MACHINE currentState = VALIDATE_SETTINGS;
|
||||||
|
ip_addr_t address;
|
||||||
|
struct tcp_pcb* serverPcb;
|
||||||
|
struct tcp_pcb* clientPcb;
|
||||||
|
|
||||||
|
bool apConnected = false;
|
||||||
|
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 = pads_bank0_hw->io[29];
|
||||||
|
uint32_t old_ctrl = io_bank0_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);
|
||||||
|
|
||||||
|
pads_bank0_hw->io[29] = old_pad;
|
||||||
|
io_bank0_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));
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopServer()
|
||||||
|
{
|
||||||
|
if(serverPcb == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tcp_close(serverPcb);
|
||||||
|
serverPcb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void killClient()
|
||||||
|
{
|
||||||
|
if(clientPcb != NULL)
|
||||||
|
{
|
||||||
|
tcp_recv(clientPcb, NULL);
|
||||||
|
tcp_err(clientPcb, NULL);
|
||||||
|
tcp_close(clientPcb);
|
||||||
|
clientPcb = NULL;
|
||||||
|
}
|
||||||
|
currentState = WAITING_TCP_CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendData(uint8_t* data, uint8_t len)
|
||||||
|
{
|
||||||
|
while(clientPcb && tcp_sndbuf(clientPcb) < len)
|
||||||
|
{
|
||||||
|
cyw43_arch_poll();
|
||||||
|
sleep_ms(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tcp_write(clientPcb, data, len, TCP_WRITE_FLAG_COPY))
|
||||||
|
{
|
||||||
|
killClient();
|
||||||
|
EVENT_FROM_WIFI evt;
|
||||||
|
evt.event = DISCONNECTED;
|
||||||
|
event_push(&wifiToFrontend, &evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverError(void *arg, err_t err)
|
||||||
|
{
|
||||||
|
killClient();
|
||||||
|
|
||||||
|
EVENT_FROM_WIFI evt;
|
||||||
|
evt.event = DISCONNECTED;
|
||||||
|
event_push(&wifiToFrontend, &evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t serverReceiveData(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
|
||||||
|
{
|
||||||
|
EVENT_FROM_WIFI evt;
|
||||||
|
|
||||||
|
//Client disconnected
|
||||||
|
if(!p || p->tot_len == 0)
|
||||||
|
{
|
||||||
|
if(p)
|
||||||
|
pbuf_free(p);
|
||||||
|
|
||||||
|
killClient();
|
||||||
|
evt.event = DISCONNECTED;
|
||||||
|
event_push(&wifiToFrontend, &evt);
|
||||||
|
return ERR_ABRT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = p->tot_len;
|
||||||
|
uint16_t pos = 0;
|
||||||
|
|
||||||
|
while(left)
|
||||||
|
{
|
||||||
|
uint8_t copy = left > 128 ? 128 : left;
|
||||||
|
evt.event = DATA_RECEIVED;
|
||||||
|
evt.dataLength = copy;
|
||||||
|
pbuf_copy_partial(p, evt.data, copy, pos);
|
||||||
|
event_push(&wifiToFrontend, &evt);
|
||||||
|
pos += copy;
|
||||||
|
left -= copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbuf_free(p);
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t acceptConnection(void *arg, struct tcp_pcb *client_pcb, err_t err)
|
||||||
|
{
|
||||||
|
if (err != ERR_OK || client_pcb == NULL || clientPcb != NULL || currentState != WAITING_TCP_CLIENT)
|
||||||
|
return ERR_VAL;
|
||||||
|
|
||||||
|
clientPcb = client_pcb;
|
||||||
|
|
||||||
|
tcp_recv(clientPcb, serverReceiveData);
|
||||||
|
tcp_err(clientPcb, serverError);
|
||||||
|
|
||||||
|
currentState = TCP_CLIENT_CONNECTED;
|
||||||
|
|
||||||
|
EVENT_FROM_WIFI evt;
|
||||||
|
evt.event = CONNECTED;
|
||||||
|
event_push(&wifiToFrontend, &evt);
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tryStartServer()
|
||||||
|
{
|
||||||
|
serverPcb = tcp_new_ip_type(IPADDR_TYPE_V4);
|
||||||
|
err_t err = tcp_bind(serverPcb, &address, wifiSettings.port);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
serverPcb = tcp_listen_with_backlog(serverPcb, 1);
|
||||||
|
|
||||||
|
if(!serverPcb)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
tcp_accept(serverPcb, acceptConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tryConnectAP()
|
||||||
|
{
|
||||||
|
if(cyw43_arch_wifi_connect_timeout_ms((const char*)wifiSettings.apName, (const char*)wifiSettings.passwd, CYW43_AUTH_WPA2_AES_PSK, 10000))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ipaddr_aton((const char*)wifiSettings.ipAddress, &address);
|
||||||
|
|
||||||
|
netif_set_ipaddr(netif_list, &address);
|
||||||
|
|
||||||
|
apConnected = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disconnectAP()
|
||||||
|
{
|
||||||
|
if(!apConnected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cyw43_wifi_leave(&cyw43_state, 0);
|
||||||
|
apConnected = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void processWifiMachine()
|
||||||
|
{
|
||||||
|
switch (currentState)
|
||||||
|
{
|
||||||
|
case VALIDATE_SETTINGS:
|
||||||
|
{
|
||||||
|
if(!boot)
|
||||||
|
readSettings();
|
||||||
|
|
||||||
|
boot = true;
|
||||||
|
|
||||||
|
uint16_t checksum = 0;
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 33; buc++)
|
||||||
|
checksum += wifiSettings.apName[buc];
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 64; buc++)
|
||||||
|
checksum += wifiSettings.passwd[buc];
|
||||||
|
|
||||||
|
for(int buc = 0; buc < 16; buc++)
|
||||||
|
checksum += wifiSettings.ipAddress[buc];
|
||||||
|
|
||||||
|
checksum += wifiSettings.port;
|
||||||
|
|
||||||
|
checksum += 0x0f0f;
|
||||||
|
|
||||||
|
if(wifiSettings.checksum == checksum)
|
||||||
|
currentState = CONNECTING_AP;
|
||||||
|
else
|
||||||
|
currentState = WAITING_SETTINGS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONNECTING_AP:
|
||||||
|
if(tryConnectAP())
|
||||||
|
currentState = STARTING_TCP_SERVER;
|
||||||
|
break;
|
||||||
|
case STARTING_TCP_SERVER:
|
||||||
|
if(tryStartServer())
|
||||||
|
currentState = WAITING_TCP_CLIENT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void frontendEvent(void* event)
|
||||||
|
{
|
||||||
|
EVENT_FROM_FRONTEND* evt = (EVENT_FROM_FRONTEND*)event;
|
||||||
|
switch(evt->event)
|
||||||
|
{
|
||||||
|
case LED_ON:
|
||||||
|
LED_ON();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LED_OFF:
|
||||||
|
LED_OFF();
|
||||||
|
break;
|
||||||
|
case CONFIG_RECEIVED:
|
||||||
|
|
||||||
|
killClient();
|
||||||
|
stopServer();
|
||||||
|
disconnectAP();
|
||||||
|
currentState = VALIDATE_SETTINGS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEND_DATA:
|
||||||
|
sendData(evt->data, evt->dataLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GET_POWER_STATUS:
|
||||||
|
getPowerStatus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runWiFiCore()
|
||||||
|
{
|
||||||
|
event_machine_init(&frontendToWifi, frontendEvent, sizeof(EVENT_FROM_FRONTEND), 8);
|
||||||
|
multicore_lockout_victim_init();
|
||||||
|
cyw43_arch_init();
|
||||||
|
cyw43_arch_enable_sta_mode();
|
||||||
|
EVENT_FROM_WIFI evtRdy;
|
||||||
|
evtRdy.event = CYW_READY;
|
||||||
|
event_push(&wifiToFrontend, &evtRdy);
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
event_process_queue(&frontendToWifi, &frontendEventBuffer, 8);
|
||||||
|
processWifiMachine();
|
||||||
|
if(currentState > CONNECTING_AP)
|
||||||
|
cyw43_arch_poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
24
LogicAnalyzer_WiFi.h
Normal file
24
LogicAnalyzer_WiFi.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "LogicAnalyzer_Board_Settings.h"
|
||||||
|
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
|
||||||
|
#ifndef __LOGICANALYZER_WIFI__
|
||||||
|
#define __LOGICANALYZER_WIFI__
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
VALIDATE_SETTINGS,
|
||||||
|
WAITING_SETTINGS,
|
||||||
|
CONNECTING_AP,
|
||||||
|
STARTING_TCP_SERVER,
|
||||||
|
WAITING_TCP_CLIENT,
|
||||||
|
TCP_CLIENT_CONNECTED
|
||||||
|
|
||||||
|
} WIFI_STATE_MACHINE;
|
||||||
|
|
||||||
|
void runWiFiCore();
|
||||||
|
bool getVsysState();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
11
Shared_Buffers.c
Normal file
11
Shared_Buffers.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "LogicAnalyzer_Board_Settings.h"
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
#include "Shared_Buffers.h"
|
||||||
|
#include "LogicAnalyzer_Structs.h"
|
||||||
|
#include "Event_Machine.h"
|
||||||
|
|
||||||
|
|
||||||
|
volatile WIFI_SETTINGS wifiSettings;
|
||||||
|
EVENT_MACHINE wifiToFrontend;
|
||||||
|
EVENT_MACHINE frontendToWifi;
|
||||||
|
#endif
|
||||||
16
Shared_Buffers.h
Normal file
16
Shared_Buffers.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "LogicAnalyzer_Board_Settings.h"
|
||||||
|
#ifdef USE_CYGW_WIFI
|
||||||
|
#ifndef __SHARED_BUFFERS__
|
||||||
|
#define __SHARED_BUFFERS__
|
||||||
|
#include "LogicAnalyzer_Structs.h"
|
||||||
|
#include "Event_Machine.h"
|
||||||
|
#include "hardware/flash.h"
|
||||||
|
|
||||||
|
#define FLASH_SETTINGS_OFFSET ((2048 * 1024) - FLASH_SECTOR_SIZE)
|
||||||
|
#define FLASH_SETTINGS_ADDRESS (XIP_BASE + FLASH_SETTINGS_OFFSET)
|
||||||
|
|
||||||
|
volatile extern WIFI_SETTINGS wifiSettings;
|
||||||
|
extern EVENT_MACHINE wifiToFrontend;
|
||||||
|
extern EVENT_MACHINE frontendToWifi;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
90
lwipopts.h
Normal file
90
lwipopts.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H
|
||||||
|
#define _LWIPOPTS_EXAMPLE_COMMONH_H
|
||||||
|
|
||||||
|
|
||||||
|
// Common settings used in most of the pico_w examples
|
||||||
|
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
|
||||||
|
|
||||||
|
// allow override in some examples
|
||||||
|
#ifndef NO_SYS
|
||||||
|
#define NO_SYS 1
|
||||||
|
#endif
|
||||||
|
// allow override in some examples
|
||||||
|
#ifndef LWIP_SOCKET
|
||||||
|
#define LWIP_SOCKET 0
|
||||||
|
#endif
|
||||||
|
#if PICO_CYW43_ARCH_POLL
|
||||||
|
#define MEM_LIBC_MALLOC 1
|
||||||
|
#else
|
||||||
|
// MEM_LIBC_MALLOC is incompatible with non polling versions
|
||||||
|
#define MEM_LIBC_MALLOC 0
|
||||||
|
#endif
|
||||||
|
#define MEM_ALIGNMENT 4
|
||||||
|
#define MEM_SIZE 4000
|
||||||
|
#define MEMP_NUM_TCP_SEG 32
|
||||||
|
#define MEMP_NUM_ARP_QUEUE 10
|
||||||
|
#define PBUF_POOL_SIZE 24
|
||||||
|
#define LWIP_ARP 1
|
||||||
|
#define LWIP_ETHERNET 1
|
||||||
|
#define LWIP_ICMP 1
|
||||||
|
#define LWIP_RAW 1
|
||||||
|
#define TCP_WND (8 * TCP_MSS)
|
||||||
|
#define TCP_MSS 1460
|
||||||
|
#define TCP_SND_BUF (8 * TCP_MSS)
|
||||||
|
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
|
||||||
|
#define LWIP_NETIF_STATUS_CALLBACK 1
|
||||||
|
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||||
|
#define LWIP_NETIF_HOSTNAME 1
|
||||||
|
#define LWIP_NETCONN 0
|
||||||
|
#define MEM_STATS 0
|
||||||
|
#define SYS_STATS 0
|
||||||
|
#define MEMP_STATS 0
|
||||||
|
#define LINK_STATS 0
|
||||||
|
// #define ETH_PAD_SIZE 2
|
||||||
|
#define LWIP_CHKSUM_ALGORITHM 3
|
||||||
|
#define LWIP_DHCP 1
|
||||||
|
#define LWIP_IPV4 1
|
||||||
|
#define LWIP_TCP 1
|
||||||
|
#define LWIP_UDP 1
|
||||||
|
#define LWIP_DNS 1
|
||||||
|
#define LWIP_TCP_KEEPALIVE 1
|
||||||
|
#define LWIP_NETIF_TX_SINGLE_PBUF 1
|
||||||
|
#define DHCP_DOES_ARP_CHECK 0
|
||||||
|
#define LWIP_DHCP_DOES_ACD_CHECK 0
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define LWIP_DEBUG 1
|
||||||
|
#define LWIP_STATS 1
|
||||||
|
#define LWIP_STATS_DISPLAY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||||
|
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||||
|
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||||
|
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||||
|
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||||
|
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define INET_DEBUG LWIP_DBG_OFF
|
||||||
|
#define IP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||||
|
#define RAW_DEBUG LWIP_DBG_OFF
|
||||||
|
#define MEM_DEBUG LWIP_DBG_OFF
|
||||||
|
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define SYS_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||||
|
#define UDP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define PPP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define SLIP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||||
|
|
||||||
|
#endif /* __LWIPOPTS_H__ */
|
||||||
84
pico_sdk_import.cmake
Normal file
84
pico_sdk_import.cmake
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||||
|
|
||||||
|
# This can be dropped into an external project to help locate this SDK
|
||||||
|
# It should be include()ed prior to project()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||||
|
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||||
|
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
|
||||||
|
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
|
||||||
|
|
||||||
|
if (NOT PICO_SDK_PATH)
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT)
|
||||||
|
include(FetchContent)
|
||||||
|
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||||
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
|
endif ()
|
||||||
|
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||||
|
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_sdk
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||||
|
GIT_SUBMODULES_RECURSE FALSE
|
||||||
|
)
|
||||||
|
else ()
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_sdk
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT pico_sdk)
|
||||||
|
message("Downloading Raspberry Pi Pico SDK")
|
||||||
|
FetchContent_Populate(pico_sdk)
|
||||||
|
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||||
|
endif ()
|
||||||
|
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||||
|
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||||
|
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||||
|
|
||||||
|
include(${PICO_SDK_INIT_CMAKE_FILE})
|
||||||
96
publish.ps1
Normal file
96
publish.ps1
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$packageName = "LogicAnalyzer"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Define board types and turbo mode options
|
||||||
|
$boardTypes = @("BOARD_PICO", "BOARD_PICO_W", "BOARD_PICO_W_WIFI", "BOARD_ZERO", "BOARD_PICO_2")
|
||||||
|
$turboModes = @("0", "1")
|
||||||
|
|
||||||
|
# Path to the build settings file
|
||||||
|
$buildSettingsFile = "LogicAnalyzer_Build_Settings.cmake"
|
||||||
|
|
||||||
|
# Paths from settings.json
|
||||||
|
$cmakePath = "${env:USERPROFILE}/.pico-sdk/cmake/v3.28.6/bin/cmake"
|
||||||
|
$ninjaPath = "${env:USERPROFILE}/.pico-sdk/ninja/v1.12.1/ninja"
|
||||||
|
$picoSdkPath = "${env:USERPROFILE}/.pico-sdk/sdk/2.0.0"
|
||||||
|
$picoToolchainPath = "${env:USERPROFILE}/.pico-sdk/toolchain/13_2_Rel1"
|
||||||
|
|
||||||
|
# Function to update the build settings file
|
||||||
|
function Update-BuildSettings {
|
||||||
|
param (
|
||||||
|
[string]$boardType,
|
||||||
|
[string]$turboMode
|
||||||
|
)
|
||||||
|
$content = Get-Content $buildSettingsFile
|
||||||
|
$content = $content -replace '(set\(BOARD_TYPE ".*"\))', "set(BOARD_TYPE `"$boardType`")"
|
||||||
|
$content = $content -replace '(set\(TURBO_MODE .*\))', "set(TURBO_MODE $turboMode)"
|
||||||
|
Set-Content $buildSettingsFile $content
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the number of processors
|
||||||
|
$processorCount = [Environment]::ProcessorCount
|
||||||
|
|
||||||
|
# Create the publish directory if it doesn't exist
|
||||||
|
$publishDir = ".\publish"
|
||||||
|
if (-Not (Test-Path -Path $publishDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $publishDir
|
||||||
|
} else {
|
||||||
|
# Clear the publish directory
|
||||||
|
Remove-Item -Recurse -Force "$publishDir\*"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Loop through each board type and turbo mode combination
|
||||||
|
foreach ($boardType in $boardTypes) {
|
||||||
|
foreach ($turboMode in $turboModes) {
|
||||||
|
# Skip turbo mode for BOARD_PICO_W variants
|
||||||
|
if ($turboMode -eq "1" -and ($boardType -eq "BOARD_PICO_W" -or $boardType -eq "BOARD_PICO_W_WIFI")) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update the build settings file
|
||||||
|
Update-BuildSettings -boardType $boardType -turboMode $turboMode
|
||||||
|
|
||||||
|
# Clean the build directory
|
||||||
|
Remove-Item -Recurse -Force "build"
|
||||||
|
New-Item -ItemType Directory -Path "build"
|
||||||
|
Set-Location -Path "build"
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
$env:PICO_SDK_PATH = $picoSdkPath
|
||||||
|
$env:PICO_TOOLCHAIN_PATH = $picoToolchainPath
|
||||||
|
$env:Path = "${env:USERPROFILE}/.pico-sdk/toolchain/13_2_Rel1/bin;${env:USERPROFILE}/.pico-sdk/picotool/2.0.0/picotool;${env:USERPROFILE}/.pico-sdk/cmake/v3.28.6/bin;${env:USERPROFILE}/.pico-sdk/ninja/v1.12.1;${env:Path}"
|
||||||
|
|
||||||
|
# Run the CMake configuration command
|
||||||
|
& $cmakePath -G "Ninja" ..
|
||||||
|
|
||||||
|
# Run the CMake build command
|
||||||
|
& $cmakePath --build . --config Release -- -j $processorCount
|
||||||
|
|
||||||
|
# Check if the .uf2 file exists before moving it
|
||||||
|
$uf2File = "LogicAnalyzer.uf2"
|
||||||
|
if (Test-Path -Path $uf2File) {
|
||||||
|
# Determine the final binary name
|
||||||
|
if ($turboMode -eq "1") {
|
||||||
|
$binaryName = "${packageName}_${boardType}_Turbo.uf2"
|
||||||
|
} else {
|
||||||
|
$binaryName = "${packageName}_${boardType}.uf2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Move the generated .uf2 file
|
||||||
|
Move-Item -Path $uf2File -Destination "..\$publishDir\$binaryName"
|
||||||
|
} else {
|
||||||
|
Write-Host "Error: $uf2File not found for $boardType with Turbo $turboMode"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return to the root directory
|
||||||
|
Set-Location -Path ".."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compress the .uf2 files and delete the originals
|
||||||
|
Get-ChildItem -Path $publishDir -Filter *.uf2 | ForEach-Object {
|
||||||
|
$zipFileName = "$($_.BaseName).zip"
|
||||||
|
Compress-Archive -Path $_.FullName -DestinationPath "$publishDir\$zipFileName"
|
||||||
|
Remove-Item -Path $_.FullName
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user