diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml
index b5a9243..a511106 100644
--- a/.github/workflows/push-master.yml
+++ b/.github/workflows/push-master.yml
@@ -9,7 +9,7 @@ jobs:
###########################
HyperSerialPico:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6.0.2
@@ -19,7 +19,7 @@ jobs:
- name: Install GNU Arm Embedded Toolchain
uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
- release: '12.2.Rel1'
+ release: '14.2.Rel1'
- name: Build packages
shell: bash
@@ -30,101 +30,129 @@ jobs:
cmake --build . --config Release
- uses: actions/upload-artifact@v7.0.1
- name: Upload artifacts (commit)
- if: (startsWith(github.event.ref, 'refs/tags') != true)
+ name: Upload artifacts (release)
with:
+ name: firmware-release-generic-RP2040
path: |
firmware/*.uf2
+ - name: Build packages for generic RP2350
+ shell: bash
+ run: |
+ cd build
+ rm -rf *
+ rm -rf ../firmware/*
+ cmake -DTARGET_BOARD=pico2 -DCMAKE_BUILD_TYPE=Release ..
+ cmake --build .
+ zip -j ../firmware/firmware_generic_RP2350.zip ../firmware/*
+
- uses: actions/upload-artifact@v7.0.1
- name: Upload artifacts (release)
- if: startsWith(github.ref, 'refs/tags/')
+ name: Upload artifacts (release generic RP2350)
with:
- name: firmware-release-generic
+ name: firmware-release-generic-RP2350
+ archive: false
path: |
- firmware/*.uf2
+ firmware/*.zip
- - name: Build packages for Adafruit Feather RP2040 Scorpio (release-only)
- if: startsWith(github.ref, 'refs/tags/')
+ - name: Build packages for Adafruit Feather RP2040 Scorpio
shell: bash
run: |
cd build
- rm *.*
- rm ../firmware/*
- echo "Neopixel is using GPIO16(OUTPUT_DATA_PIN) on output 0." > ../firmware/Firmwares_for_Adafruit_Feather_RP2040_Scorpio.txt
- echo "SPI is using spi0 interface pins: GPIO19(OUTPUT_SPI_DATA_PIN) and GPIO18(OUTPUT_SPI_CLOCK_PIN) on output 3 and 2 respectively." >> ../firmware/Firmwares_for_Adafruit_Feather_RP2040_Scorpio.txt
+ rm -rf *
+ rm -rf ../firmware/*
+ echo "Neopixel is using GPIO16(OUTPUT_DATA_PIN) on output 0." > ../firmware/Pinout_for_Adafruit_Feather_RP2040_Scorpio.txt
+ echo "SPI is using spi0 interface pins: GPIO19(OUTPUT_SPI_DATA_PIN) and GPIO18(OUTPUT_SPI_CLOCK_PIN) on output 3 and 2 respectively." >> ../firmware/Pinout_for_Adafruit_Feather_RP2040_Scorpio.txt
cmake -DOVERRIDE_BOOT_WORKAROUND=ON -DOVERRIDE_DATA_PIN=16 -DOVERRIDE_SPI_DATA_PIN=19 -DOVERRIDE_SPI_CLOCK_PIN=18 -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
zip -j ../firmware/Adafruit_Feather_RP2040_Scorpio.zip ../firmware/*
- uses: actions/upload-artifact@v7.0.1
- name: Upload artifacts (release Adafruit_Feather)
- if: startsWith(github.ref, 'refs/tags/')
+ name: Upload artifacts (release for Adafruit_Feather_RP2040)
with:
- name: firmware-release-adafruit-scorpio
+ name: firmware-release-adafruit-scorpio-RP2040
+ archive: false
path: |
firmware/*.zip
- - name: Build packages for Adafruit ItsyBitsy RP2040 (release-only)
- if: startsWith(github.ref, 'refs/tags/')
+ - name: Build packages for Adafruit ItsyBitsy RP2040
shell: bash
run: |
cd build
- rm *.*
- rm ../firmware/*
- echo "Neopixel is using GPIO14(OUTPUT_DATA_PIN) on output 5." > ../firmware/Firmwares_for_Adafruit_ItsyBitsy_2040.txt
+ rm -rf *
+ rm -rf ../firmware/*
+ echo "Neopixel is using GPIO14(OUTPUT_DATA_PIN) on output 5." > ../firmware/Pinout_for_Adafruit_ItsyBitsy_RP2040.txt
cmake -DOVERRIDE_BOOT_WORKAROUND=ON -DOVERRIDE_DATA_PIN=14 -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
rm ../firmware/*_Spi.uf2
- zip -j ../firmware/Adafruit_ItsyBitsy_2040.zip ../firmware/*
+ rm ../firmware/*_ws2801.uf2
+ zip -j ../firmware/Adafruit_ItsyBitsy_RP2040.zip ../firmware/*
- uses: actions/upload-artifact@v7.0.1
- name: Upload artifacts (release Adafruit_ItsyBitsy)
- if: startsWith(github.ref, 'refs/tags/')
+ name: Upload artifacts (release for Adafruit_ItsyBitsy_RP2040)
with:
- name: firmware-release-adafruit-itsybitsy
+ name: firmware-release-adafruit-itsybitsy-RP2040
+ archive: false
path: |
firmware/*.zip
- - name: Build packages for Pimoroni Plasma Stick 2040 W (release-only)
- if: startsWith(github.ref, 'refs/tags/')
+ - name: Build packages for Pimoroni Plasma Stick RP2040 W
shell: bash
run: |
cd build
- rm *.*
- rm ../firmware/*
- echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output PIXELS." > ../firmware/Firmwares_for_Pimoroni_Plasma_Stick_2040_W.txt
+ rm -rf *
+ rm -rf ../firmware/*
+ echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output PIXELS." > ../firmware/Pinout_for_Pimoroni_Plasma_Stick_RP2040_W.txt
cmake -DOVERRIDE_DATA_PIN=15 -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
rm ../firmware/*_Spi.uf2
- zip -j ../firmware/Pimoroni_Plasma_Stick_2040_W.zip ../firmware/*
+ rm ../firmware/*_ws2801.uf2
+ zip -j ../firmware/Pimoroni_Plasma_Stick_RP2040_W.zip ../firmware/*
- uses: actions/upload-artifact@v7.0.1
- name: Upload artifacts (release Pimoroni_Plasma_Stick_W)
- if: startsWith(github.ref, 'refs/tags/')
+ name: Upload artifacts (release for Pimoroni_Plasma_Stick_RP2040_W)
with:
- name: firmware-release-pimoroni-plasma-stick
+ name: firmware-release-pimoroni-plasma-stick-RP2040-W
+ archive: false
path: |
firmware/*.zip
- - name: Build packages for Pimoroni Plasma 2040 (release-only)
- if: startsWith(github.ref, 'refs/tags/')
+ - name: Build packages for Pimoroni Plasma 2040
shell: bash
run: |
cd build
- rm *.*
- rm ../firmware/*
- echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Firmwares_for_Pimoroni_Plasma_2040.txt
- echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Firmwares_for_Pimoroni_Plasma_2040.txt
+ rm -rf *
+ rm -rf ../firmware/*
+ echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Pinout_for_Pimoroni_Plasma_RP2040.txt
+ echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Pinout_for_Pimoroni_Plasma_RP2040.txt
cmake -DOVERRIDE_DATA_PIN=15 -DOVERRIDE_SPI_INTERFACE=spi1 -DOVERRIDE_SPI_DATA_PIN=15 -DOVERRIDE_SPI_CLOCK_PIN=14 -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
- zip -j ../firmware/Pimoroni_Plasma_2040.zip ../firmware/*
+ zip -j ../firmware/Pimoroni_Plasma_RP2040.zip ../firmware/*
+
+ - uses: actions/upload-artifact@v7.0.1
+ name: Upload artifacts (release for Pimoroni_Plasma_RP2040)
+ with:
+ name: firmware-release-pimoroni-plasma-RP2040
+ archive: false
+ path: |
+ firmware/*.zip
+
+ - name: Build packages for Pimoroni Plasma RP2350
+ shell: bash
+ run: |
+ cd build
+ rm -rf *
+ rm -rf ../firmware/*
+ echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Pinout_for_Pimoroni_Plasma_RP2350.txt
+ echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Pinout_for_Pimoroni_Plasma_RP2350.txt
+ cmake -DTARGET_BOARD=pimoroni_plasma2350 -DOVERRIDE_DATA_PIN=15 -DOVERRIDE_SPI_INTERFACE=spi1 -DOVERRIDE_SPI_DATA_PIN=15 -DOVERRIDE_SPI_CLOCK_PIN=14 -DCMAKE_BUILD_TYPE=Release ..
+ cmake --build .
+ zip -j ../firmware/Pimoroni_Plasma_RP2350.zip ../firmware/*
- uses: actions/upload-artifact@v7.0.1
- name: Upload artifacts (release Pimoroni_Plasma)
- if: startsWith(github.ref, 'refs/tags/')
+ name: Upload artifacts (release for Pimoroni_Plasma_RP2350)
with:
- name: firmware-release-pimoroni-plasma
+ name: firmware-release-pimoroni-plasma-RP2350
+ archive: false
path: |
firmware/*.zip
@@ -136,7 +164,7 @@ jobs:
name: Publish Releases
if: startsWith(github.event.ref, 'refs/tags')
needs: [HyperSerialPico]
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
permissions:
contents: write
steps:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6e0ad2..2c5c6e8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,12 +33,26 @@ add_definitions ( -DPICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE=0 )
# initialize the SDK based on PICO_SDK_PATH
# note: this must happen before project()
set(PICO_SDK_PATH ${CMAKE_CURRENT_SOURCE_DIR}/sdk/pico)
-set(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/sdk/freertos)
+# FreeRTOS config
+add_library(freertos_config INTERFACE)
+target_include_directories(freertos_config INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/sdk/config )
+set(FREERTOS_KERNEL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/sdk/freertos")
+
+# Target: 'pico' (RP2040) or 'pico2' (RP2350)
+set(TARGET_BOARD "pico" CACHE STRING "Target board: pico or pico2")
+set(PICO_BOARD ${TARGET_BOARD})
include(${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
+
+if (PICO_RP2350)
+ set(FREERTOS_PORT "GCC_ARM_CM33_NTZ" CACHE STRING "")
+else()
+ set(FREERTOS_PORT "GCC_ARM_CM0" CACHE STRING "")
+endif()
+
include(${FREERTOS_KERNEL_PATH}/portable/ThirdParty/GCC/RP2040/FreeRTOS_Kernel_import.cmake)
-project(HyperSerialPico C CXX ASM)
+project("HyperSerialPico_${PICO_CHIP}" C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
@@ -53,8 +67,8 @@ ENDIF(CMAKE_COMPILER_IS_GNUCC)
pico_sdk_init()
# generic HyperSerialPico settings
-set(HyperSerialPicoCompanionLibs FreeRTOS-Kernel FreeRTOS-Kernel-Heap1 pico_stdlib pico_multicore hardware_pio hardware_dma hardware_spi)
-set(HyperSerialPicoCompanionIncludes ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/sdk/config)
+set(HyperSerialPicoCompanionIncludes ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/sdk/config ${PICO_SDK_PATH}/src/rp2_common/pico_stdio_usb/include ${PICO_SDK_PATH}/src/common/pico_usb_reset_interface_headers/include)
+set(HyperSerialPicoCompanionLibs FreeRTOS-Kernel freertos_config FreeRTOS-Kernel-Heap1 tinyusb_board tinyusb_device pico_stdlib pico_multicore hardware_pio hardware_dma hardware_spi)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/generated)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/firmware)
@@ -114,10 +128,14 @@ macro(HyperSerialPicoTarget HyperSerialPicoTargetName)
if (BOOT_WORKAROUND)
target_compile_definitions(${HyperSerialPicoTargetName} PUBLIC -DBOOT_WORKAROUND -DPICO_XOSC_STARTUP_DELAY_MULTIPLIER=64)
endif()
+
+ target_compile_definitions(${HyperSerialPicoTargetName} PRIVATE -DPICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS=1)
+ target_sources(${HyperSerialPicoTargetName} PRIVATE ${PICO_SDK_PATH}/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c)
+
target_include_directories(${HyperSerialPicoTargetName} PRIVATE ${HyperSerialPicoCompanionIncludes})
target_link_libraries(${HyperSerialPicoTargetName} ${HyperSerialPicoCompanionLibs})
pico_add_extra_outputs(${HyperSerialPicoTargetName})
- pico_enable_stdio_usb(${HyperSerialPicoTargetName} 1)
+ pico_enable_stdio_usb(${HyperSerialPicoTargetName} 0)
pico_enable_stdio_uart(${HyperSerialPicoTargetName} 0)
pico_generate_pio_header(${HyperSerialPicoTargetName} ${CMAKE_CURRENT_SOURCE_DIR}/pio/neopixel.pio OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/generated)
pico_generate_pio_header(${HyperSerialPicoTargetName} ${CMAKE_CURRENT_SOURCE_DIR}/pio/neopixel_ws2812b.pio OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/generated)
diff --git a/README.md b/README.md
index 2c2e952..5d07289 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
# HyperSerialPico
-Adalight serial port LED driver implementation for Raspberry Pi Pico RP2040.
+Adalight serial port LED driver implementation for Raspberry Pi Pico RP2040/RP2350.
-# Example of supported boards using Rp2040
+# Example of supported boards using rp2040/rp2350


# Recommended boards with a built-in level shifter
-To ensure the LEDs will work properly with the Pico board, a 3.3V to 5V level shifter is needed. You can use an external one e.g. SN74AHCT125N or just buy a model of rp2040 that already has it built-in: Adafruit Feather RP2040 Scorpio (output: GPIO16-23), Adafruit ItsyBitsy RP2040 (output: GPIO14), Pimoroni Plasma 2040 (GPIO14-15) or Pimoroni Plasma Stick 2040 W (GPIO15).
+To ensure the LEDs will work properly with the Pico board, a 3.3V to 5V level shifter is needed. You can use an external one e.g. SN74AHCT125N or just buy a model of rp2040/rp2350 that already has it built-in: Adafruit Feather RP2040 Scorpio (output: GPIO16-23), Adafruit ItsyBitsy RP2040 (output: GPIO14), Pimoroni Plasma 2040 (GPIO14-15), Pimoroni Plasma Stick 2040 W (GPIO15) or Pimoroni Plasma RP2350 (GPIO14-15).
-



+




# Supported LED strips
| LED strip / Device | Single lane | Multi-segment |
diff --git a/include/base.h b/include/base.h
index 9857b64..e48b41e 100644
--- a/include/base.h
+++ b/include/base.h
@@ -45,9 +45,6 @@ class Base
// handle to tasks
TaskHandle_t processDataHandle = nullptr;
TaskHandle_t processSerialHandle = nullptr;
- // semaphore to synchronize them
- semaphore_t serialSemaphore;
- semaphore_t receiverSemaphore;
// current queue position
volatile int queueCurrent = 0;
// queue end position
diff --git a/include/calibration.h b/include/calibration.h
index cd7cf50..5d334c7 100644
--- a/include/calibration.h
+++ b/include/calibration.h
@@ -125,11 +125,11 @@ class CalibrationConfig
* @brief print RGBW calibration parameters when no data is received
*
*/
- void printCalibration()
+ template
+ void printCalibration(char (&output)[N])
{
- char output[128];
- snprintf(output, sizeof(output),"RGBW => Gain: %i/255, red: %i, green: %i, blue: %i\r\n", gain, red, green, blue);
- printf(output);
+ snprintf(output, N, "RGBW => Gain: %i/255, red: %i, green: %i, blue: %i\r\n", gain, red, green, blue);
+ tud_cdc_write_str(output);
}
} calibrationConfig;
diff --git a/include/leds.h b/include/leds.h
index bb58f32..3e92162 100644
--- a/include/leds.h
+++ b/include/leds.h
@@ -77,7 +77,7 @@
#include
#include
-struct ColorGrb32
+struct __attribute__((packed)) ColorGrb32
{
uint8_t notUsed;
uint8_t B;
@@ -99,7 +99,7 @@ struct ColorGrb32
};
};
-struct ColorGrb
+struct __attribute__((packed)) ColorGrb
{
uint8_t B;
uint8_t R;
@@ -116,7 +116,7 @@ struct ColorGrb
};
};
-struct ColorGrbw
+struct __attribute__((packed)) ColorGrbw
{
uint8_t W;
uint8_t B;
@@ -138,7 +138,7 @@ struct ColorGrbw
};
};
-struct ColorDotstartBgr
+struct __attribute__((packed)) ColorDotstartBgr
{
uint8_t Brightness;
uint8_t B;
@@ -155,7 +155,7 @@ struct ColorDotstartBgr
};
};
-struct ColorRgb
+struct __attribute__((packed)) ColorRgb
{
uint8_t R;
uint8_t G;
@@ -202,7 +202,7 @@ class LedDriver
dma = reinterpret_cast(calloc(dmaSize, 1));
}
- ~LedDriver()
+ virtual ~LedDriver()
{
free(buffer);
free(dma);
@@ -234,22 +234,27 @@ class DmaClient
lastRenderTime = 0;
};
- ~DmaClient()
+ virtual ~DmaClient()
{
- for(int i = 0; i < 10 && isDmaBusy; i++)
+ for(int i = 0; i < 100 && isDmaBusy; i++)
busy_wait_us(500);
dma_channel_abort(PICO_DMA_CHANNEL);
dma_channel_set_irq0_enabled(PICO_DMA_CHANNEL, false);
- irq_set_enabled(DMA_IRQ_0, false);
+ irq_remove_handler(DMA_IRQ_0, dmaFinishReceiver);
dma_channel_unclaim(PICO_DMA_CHANNEL);
};
- void dmaConfigure(PIO _selectedPIO, uint _sm)
+ void dmaConfigure()
{
- selectedPIO = _selectedPIO;
- stateIndex = _sm;
+ selectedPIO = pio0;
+ int sm = pio_claim_unused_sm(selectedPIO, false);
+ if (sm < 0) {
+ selectedPIO = pio1;
+ sm = pio_claim_unused_sm(selectedPIO, true);
+ }
+ stateIndex = (uint)sm;
};
void initDmaPio(uint dataLenDword32)
@@ -275,7 +280,7 @@ class DmaClient
void assignDmaIrq()
{
- irq_set_exclusive_handler(DMA_IRQ_0, dmaFinishReceiver);
+ irq_add_shared_handler(DMA_IRQ_0, dmaFinishReceiver, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
dma_channel_set_irq0_enabled(PICO_DMA_CHANNEL, true);
irq_set_enabled(DMA_IRQ_0, true);
};
@@ -284,7 +289,7 @@ class DmaClient
bool isReadyBlocking()
{
- int wait = 200;
+ int wait = 2000;
while(isDmaBusy && wait-- > 0)
busy_wait_us(50);
@@ -315,6 +320,9 @@ class Neopixel : public LedDriver, public DmaClient
uint64_t resetTime;
+ uint programAddress;
+ const pio_program_t* pioProgram;
+
friend class NeopixelParallel;
public:
@@ -322,15 +330,14 @@ class Neopixel : public LedDriver, public DmaClient
LedDriver(_ledsNumber, _pin, _dmaSize)
{
pio_sm_config smConfig;
- uint programAddress;
- dmaConfigure(pio0, 0);
+ dmaConfigure();
resetTime = _resetTime;
if (lanes >= 1)
{
- programAddress = (timingType == NeopixelSubtype::ws2812b) ?
- pio_add_program(selectedPIO, &neopixel_ws2812b_parallel_program) : pio_add_program(selectedPIO, &neopixel_parallel_program);
+ pioProgram = (timingType == NeopixelSubtype::ws2812b) ? &neopixel_ws2812b_parallel_program : &neopixel_parallel_program;
+ programAddress = pio_add_program(selectedPIO, pioProgram);
for(uint i=_pin; i<_pin + lanes; i++){
pio_gpio_init(selectedPIO, i);
@@ -340,12 +347,11 @@ class Neopixel : public LedDriver, public DmaClient
neopixel_ws2812b_parallel_program_get_default_config(programAddress) : neopixel_parallel_program_get_default_config(programAddress);
sm_config_set_out_pins(&smConfig, _pin, lanes);
- sm_config_set_set_pins(&smConfig, _pin, lanes);
}
else
{
- programAddress = (timingType == NeopixelSubtype::ws2812b) ?
- pio_add_program(selectedPIO, &neopixel_ws2812b_program) : pio_add_program(selectedPIO, &neopixel_program);
+ pioProgram = (timingType == NeopixelSubtype::ws2812b) ? &neopixel_ws2812b_program : &neopixel_program;
+ programAddress = pio_add_program(selectedPIO, pioProgram);
pio_gpio_init(selectedPIO, _pin);
@@ -366,6 +372,15 @@ class Neopixel : public LedDriver, public DmaClient
initDmaPio(dmaSize / 4);
}
+ virtual ~Neopixel()
+ {
+ pio_sm_set_enabled(selectedPIO, stateIndex, false);
+ pio_sm_clear_fifos(selectedPIO, stateIndex);
+ pio_sm_unclaim(selectedPIO, stateIndex);
+
+ pio_remove_program(selectedPIO, pioProgram, programAddress);
+ }
+
uint8_t* getBufferMemory()
{
return buffer;
@@ -440,7 +455,7 @@ class NeopixelParallel
buffer = muxer->getBufferMemory();
}
- ~NeopixelParallel()
+ virtual ~NeopixelParallel()
{
if (instances > 0)
instances--;
@@ -514,7 +529,7 @@ class Dotstar : public LedDriver, public DmaClient
Dotstar(uint64_t _resetTime, int _ledsNumber, spi_inst_t* _spi, uint32_t _datapin, uint32_t _clockpin, int _dmaSize):
LedDriver(_ledsNumber, _datapin, _clockpin, _dmaSize)
{
- dmaConfigure(pio0, 0);
+ dmaConfigure();
resetTime = _resetTime;
spi_init(_spi, 10000000);
@@ -583,7 +598,7 @@ class Ws2801 : public LedDriver, public DmaClient
Ws2801(uint64_t _resetTime, int _ledsNumber, spi_inst_t* _spi, uint32_t _datapin, uint32_t _clockpin, int _dmaSize):
LedDriver(_ledsNumber, _datapin, _clockpin, _dmaSize)
{
- dmaConfigure(pio0, 0);
+ dmaConfigure();
resetTime = _resetTime;
spi_init(_spi, 1000000);
diff --git a/include/main.h b/include/main.h
index 3f0fca6..c18bf73 100644
--- a/include/main.h
+++ b/include/main.h
@@ -73,7 +73,6 @@ void processData()
if (base.queueCurrent >= MAX_BUFFER)
{
base.queueCurrent = 0;
- yield();
}
switch (frameState.getState())
@@ -151,17 +150,20 @@ void processData()
}
else if (frameState.getCount() == 0x2aa2 && (input == 0x15 || input == 0x35))
{
- statistics.print(currentTime, base.processDataHandle, base.processSerialHandle);
-
- if (input == 0x15)
- printf(HELLO_MESSAGE);
+ statistics.print(currentTime, input == 0x15);
frameState.setRegroup(true);
- delay(10);
-
currentTime = millis();
- statistics.reset(currentTime);
+ if (input == 0x15)
+ {
+ statistics.reset(currentTime);
+ }
+ else
+ {
+ statistics.lightReset(currentTime, true);
+ }
+
frameState.setState(AwaProtocol::HEADER_A);
}
else
@@ -297,8 +299,6 @@ void processData()
currentTime = millis();
deltaTime = currentTime - statistics.getStartTime();
updateMainStatistics(currentTime, deltaTime, true);
-
- yield();
}
frameState.setState(AwaProtocol::HEADER_A);
diff --git a/include/statistics.h b/include/statistics.h
index 8629179..8d756f2 100644
--- a/include/statistics.h
+++ b/include/statistics.h
@@ -28,6 +28,8 @@
#ifndef STATISTICS_H
#define STATISTICS_H
+#include
+
// statistics (stats sent only when there is no communication)
class
{
@@ -35,11 +37,17 @@ class
uint16_t goodFrames = 0;
uint16_t showFrames = 0;
uint16_t totalFrames = 0;
- uint16_t finalGoodFrames = 0;
- uint16_t finalShowFrames = 0;
- uint16_t finalTotalFrames = 0;
+
+ volatile struct {
+ uint16_t finalGoodFrames = 0;
+ uint16_t finalShowFrames = 0;
+ uint16_t finalTotalFrames = 0;
+ bool welcomeMessage = false;
+ } outputStatistics;
public:
+ std::atomic printLogs = false;
+
/**
* @brief Get the start time of the current period
*
@@ -96,9 +104,9 @@ class
{
if (totalFrames > 0)
{
- finalShowFrames = showFrames;
- finalGoodFrames = std::min(goodFrames, totalFrames);
- finalTotalFrames = totalFrames;
+ outputStatistics.finalShowFrames = showFrames;
+ outputStatistics.finalGoodFrames = std::min(goodFrames, totalFrames);
+ outputStatistics.finalTotalFrames = totalFrames;
}
startTime = currentTime;
@@ -113,25 +121,37 @@ class
* @param curTime
* @param taskHandle
*/
- void print(unsigned long curTime, TaskHandle_t taskHandle1, TaskHandle_t taskHandle2)
+ void print(unsigned long curTime, bool isWelcome)
{
- char output[128];
-
startTime = curTime;
goodFrames = 0;
totalFrames = 0;
showFrames = 0;
+
+ outputStatistics.welcomeMessage = isWelcome;
+
+ printLogs.store(true);
+ }
- snprintf(output, sizeof(output), "HyperHDR frames: %u (FPS), receiv.: %u, good: %u, incompl.: %u, mem1: %i, mem2: %i, heap: %zu\r\n",
- finalShowFrames, finalTotalFrames,finalGoodFrames,(finalTotalFrames - finalGoodFrames),
- (taskHandle1 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandle1) : 0,
- (taskHandle2 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandle2) : 0,
+ void printToSerial(TaskHandle_t taskHandleCore0)
+ {
+ char output[128];
+
+ snprintf(output, sizeof(output), "HyperHDR frames: %u (FPS), receiv.: %u, good: %u, incompl.: %u, core0: %i, heap: %zu\r\n",
+ outputStatistics.finalShowFrames, outputStatistics.finalTotalFrames, outputStatistics.finalGoodFrames,
+ (outputStatistics.finalTotalFrames - outputStatistics.finalGoodFrames),
+ (taskHandleCore0 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandleCore0) : 0,
xPortGetFreeHeapSize());
- printf(output);
+ tud_cdc_write_str(output);
#if defined(NEOPIXEL_RGBW)
- calibrationConfig.printCalibration();
+ calibrationConfig.printCalibration(output);
#endif
+
+ if (outputStatistics.welcomeMessage)
+ {
+ tud_cdc_write_str(HELLO_MESSAGE);
+ }
}
/**
@@ -142,9 +162,9 @@ class
{
startTime = currentTime;
- finalShowFrames = 0;
- finalGoodFrames = 0;
- finalTotalFrames = 0;
+ outputStatistics.finalShowFrames = 0;
+ outputStatistics.finalGoodFrames = 0;
+ outputStatistics.finalTotalFrames = 0;
goodFrames = 0;
totalFrames = 0;
diff --git a/sdk/config/FreeRTOSConfig.h b/sdk/config/FreeRTOSConfig.h
index 64902fc..9c7eaab 100644
--- a/sdk/config/FreeRTOSConfig.h
+++ b/sdk/config/FreeRTOSConfig.h
@@ -47,7 +47,20 @@
#define configUSE_TICK_HOOK 0
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES 32
-#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 256
+#ifdef __ARM_ARCH_8M_MAIN__
+ #define configMINIMAL_STACK_SIZE ( ( configSTACK_DEPTH_TYPE ) 2048 )
+ #define configENABLE_FPU 0
+ #define configENABLE_MPU 0
+ #define configENABLE_TRUSTZONE 0
+ #define configRUN_FREERTOS_SECURE_ONLY 1
+ #define configPRIO_BITS 3
+ #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07
+ #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x05
+ #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) )
+ #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) )
+#else
+ #define configMINIMAL_STACK_SIZE ( ( configSTACK_DEPTH_TYPE ) 512 )
+#endif
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
@@ -103,7 +116,7 @@
/* SMP port only */
#define configNUM_CORES 1
-#define configTICK_CORE 1
+#define configTICK_CORE 0
#define configRUN_MULTIPLE_PRIORITIES 1
/* RP2040 specific */
diff --git a/sdk/config/tusb_config.h b/sdk/config/tusb_config.h
new file mode 100644
index 0000000..643553b
--- /dev/null
+++ b/sdk/config/tusb_config.h
@@ -0,0 +1,47 @@
+#ifndef _TUSB_CONFIG_H_
+#define _TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// -----------------------------------------------------------------------------
+// COMMON CONFIGURATION
+// -----------------------------------------------------------------------------
+#define CFG_TUSB_MCU OPT_MCU_RP2040
+
+#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED)
+#ifndef BOARD_TUD_RHPORT
+ #define BOARD_TUD_RHPORT 0
+#endif
+
+#define CFG_TUD_ENDPOINT0_SIZE 64
+
+// -----------------------------------------------------------------------------
+// DEVICE CLASSES CONFIGURATION
+// -----------------------------------------------------------------------------
+#define CFG_TUD_ENABLED 1
+#define CFG_TUD_CDC 1
+#define CFG_TUD_MSC 0
+#define CFG_TUD_HID 0
+#define CFG_TUD_MIDI 0
+#define CFG_TUD_VENDOR 0
+
+// -----------------------------------------------------------------------------
+// CDC CONFIGURATION
+// -----------------------------------------------------------------------------
+#ifndef CFG_TUD_CDC_RX_BUFSIZE
+ #define CFG_TUD_CDC_RX_BUFSIZE 8192
+#endif
+#ifndef CFG_TUD_CDC_EP_BUFSIZE
+ #define CFG_TUD_CDC_EP_BUFSIZE 4096
+#endif
+#ifndef CFG_TUD_CDC_TX_BUFSIZE
+ #define CFG_TUD_CDC_TX_BUFSIZE 768
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
\ No newline at end of file
diff --git a/sdk/freertos b/sdk/freertos
index 570ade4..9b777ae 160000
--- a/sdk/freertos
+++ b/sdk/freertos
@@ -1 +1 @@
-Subproject commit 570ade4001e50adbf06a074582ea993af562e0e1
+Subproject commit 9b777ae5c5b8e9e456065a00294d1e5f5f9facf5
diff --git a/sdk/pico b/sdk/pico
index f396d05..a1438df 160000
--- a/sdk/pico
+++ b/sdk/pico
@@ -1 +1 @@
-Subproject commit f396d05f8252d4670d4ea05c8b7ac938ef0cd381
+Subproject commit a1438dff1d38bd9c65dbd693f0e5db4b9ae91779
diff --git a/source/main.cpp b/source/main.cpp
index ada0f73..516d98b 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -25,17 +25,18 @@
* SOFTWARE.
*/
-#define TUD_OPT_HIGH_SPEED
-
-
#include "FreeRTOS.h"
#include "task.h"
+#include "tusb_config.h"
+#include "tusb.h"
+#include "pico/multicore.h"
+#include "hardware/irq.h"
+#include "semphr.h"
#include
#include
#include "pico/stdio/driver.h"
#include "pico/stdlib.h"
#include "pico/stdio.h"
-#include "pico/stdio_usb.h"
#include "pico/multicore.h"
#include "pico/sem.h"
#include "leds.h"
@@ -129,52 +130,49 @@ static void core1()
{
for( ;; )
{
- if (sem_acquire_timeout_us(&base.serialSemaphore, portMAX_DELAY))
- {
- processData();
- }
+ [[maybe_unused]] auto val = multicore_fifo_pop_blocking();
+ processData();
}
}
-static void core0( void *pvParameters )
-{
- for( ;; )
- {
- if (sem_acquire_timeout_us(&base.receiverSemaphore, portMAX_DELAY))
+void core0(void *pvParameters) {
+ tusb_init();
+ while (1) {
+ tud_task();
+ if (tud_cdc_connected())
{
- int wanted, received;
- do
- {
- wanted = std::min(MAX_BUFFER - base.queueEnd, MAX_BUFFER - 1);
- received = stdio_usb.in_chars((char*)(&(base.buffer[base.queueEnd])), wanted);
- if (received > 0)
+ // receive
+ if (tud_cdc_available()) {
+ int wanted, received;
+ do
{
- base.queueEnd = (base.queueEnd + received) % (MAX_BUFFER);
- }
- }while(wanted == received);
-
- sem_release(&base.serialSemaphore);
- }
+ wanted = std::min(MAX_BUFFER - base.queueEnd, MAX_BUFFER - 1);
+
+ if (tud_cdc_connected() && tud_cdc_available()) {
+ received = (int)tud_cdc_read(const_cast(&(base.buffer[base.queueEnd])), (uint32_t)wanted);
+ }
+
+ if (received > 0)
+ {
+ base.queueEnd = (base.queueEnd + received) % (MAX_BUFFER);
+ }
+ }while(wanted == received);
+
+ multicore_fifo_push_blocking(0xAA);
+ }
+ // send
+ else if (statistics.printLogs.exchange(false)) {
+ statistics.printToSerial(base.processSerialHandle);
+ tud_cdc_write_flush();
+ }
+ }
}
}
-static void serialEvent(void *)
-{
- sem_release(&base.receiverSemaphore);
-}
-
int main(void)
{
- stdio_init_all();
-
- sem_init(&base.serialSemaphore, 0, 1);
-
- sem_init(&base.receiverSemaphore, 0, 1);
-
multicore_launch_core1(core1);
- stdio_set_chars_available_callback(serialEvent, nullptr);
-
xTaskCreate(core0,
"HyperSerialPico:core0",
configMINIMAL_STACK_SIZE * 2,