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