Compare commits
+1
-1
Submodule ArduinoCore-API updated: ece6e68f29...82928635c8
@@ -25,6 +25,7 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* Adafruit KB2040
|
||||
* Adafruit Macropad RP2040
|
||||
* Adafruit Metro RP2040
|
||||
* Adafruit Metro RP2350
|
||||
* Adafruit QTPy RP2040
|
||||
* Adafruit STEMMA Friend RP2040
|
||||
* Adafruit Trinkey RP2040 QT
|
||||
@@ -148,7 +149,7 @@ The RP2040 PIO state machines (SMs) are used to generate jitter-free:
|
||||
* I2S Input
|
||||
* I2S Output
|
||||
* Software UARTs (Serial ports)
|
||||
|
||||
* Software SPIs
|
||||
|
||||
# Installing via Arduino Boards Manager
|
||||
## Windows-specific Notes
|
||||
|
||||
+365
-142
@@ -6221,6 +6221,327 @@ adafruit_floppsy.menu.uploadmethod.picoprobe_cmsis_dap.upload.maximum_data_size=
|
||||
adafruit_floppsy.menu.uploadmethod.picoprobe_cmsis_dap.upload.tool=picoprobe_cmsis_dap
|
||||
adafruit_floppsy.menu.uploadmethod.picoprobe_cmsis_dap.upload.tool.default=picoprobe_cmsis_dap
|
||||
|
||||
# -----------------------------------
|
||||
# Adafruit Metro RP2350
|
||||
# -----------------------------------
|
||||
adafruit_metro_rp2350.name=Adafruit Metro RP2350
|
||||
adafruit_metro_rp2350.vid.0=0x239a
|
||||
adafruit_metro_rp2350.pid.0=0x814d
|
||||
adafruit_metro_rp2350.vid.1=0x239a
|
||||
adafruit_metro_rp2350.pid.1=0xc14d
|
||||
adafruit_metro_rp2350.upload_port.0.vid=0x239a
|
||||
adafruit_metro_rp2350.upload_port.0.pid=0x814d
|
||||
adafruit_metro_rp2350.upload_port.1.vid=0x239a
|
||||
adafruit_metro_rp2350.upload_port.1.pid=0xc14d
|
||||
adafruit_metro_rp2350.build.usbvid=-DUSBD_VID=0x239a
|
||||
adafruit_metro_rp2350.build.usbpid=-DUSBD_PID=0x814d
|
||||
adafruit_metro_rp2350.build.usbpwr=-DUSBD_MAX_POWER_MA=250
|
||||
adafruit_metro_rp2350.build.board=ADAFRUIT_METRO_RP2350
|
||||
adafruit_metro_rp2350.build.variant=adafruit_metro_rp2350
|
||||
adafruit_metro_rp2350.upload.maximum_size=16777216
|
||||
adafruit_metro_rp2350.upload.wait_for_upload_port=true
|
||||
adafruit_metro_rp2350.upload.erase_cmd=
|
||||
adafruit_metro_rp2350.serial.disableDTR=false
|
||||
adafruit_metro_rp2350.serial.disableRTS=false
|
||||
adafruit_metro_rp2350.build.f_cpu=125000000
|
||||
adafruit_metro_rp2350.build.led=
|
||||
adafruit_metro_rp2350.build.core=rp2040
|
||||
adafruit_metro_rp2350.build.ldscript=memmap_default.ld
|
||||
adafruit_metro_rp2350.build.boot2=none
|
||||
adafruit_metro_rp2350.build.usb_manufacturer="Adafruit"
|
||||
adafruit_metro_rp2350.build.usb_product="Metro RP2350"
|
||||
adafruit_metro_rp2350.build.psram_length=0x000000
|
||||
adafruit_metro_rp2350.menu.flash.16777216_0=16MB (no FS)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_0.upload.maximum_size=16769024
|
||||
adafruit_metro_rp2350.menu.flash.16777216_0.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_0.build.flash_length=16769024
|
||||
adafruit_metro_rp2350.menu.flash.16777216_0.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_0.build.fs_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_0.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_65536=16MB (Sketch: 16320KB, FS: 64KB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_65536.upload.maximum_size=16703488
|
||||
adafruit_metro_rp2350.menu.flash.16777216_65536.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_65536.build.flash_length=16703488
|
||||
adafruit_metro_rp2350.menu.flash.16777216_65536.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_65536.build.fs_start=285138944
|
||||
adafruit_metro_rp2350.menu.flash.16777216_65536.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_131072=16MB (Sketch: 16256KB, FS: 128KB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_131072.upload.maximum_size=16637952
|
||||
adafruit_metro_rp2350.menu.flash.16777216_131072.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_131072.build.flash_length=16637952
|
||||
adafruit_metro_rp2350.menu.flash.16777216_131072.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_131072.build.fs_start=285073408
|
||||
adafruit_metro_rp2350.menu.flash.16777216_131072.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_262144=16MB (Sketch: 16128KB, FS: 256KB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_262144.upload.maximum_size=16506880
|
||||
adafruit_metro_rp2350.menu.flash.16777216_262144.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_262144.build.flash_length=16506880
|
||||
adafruit_metro_rp2350.menu.flash.16777216_262144.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_262144.build.fs_start=284942336
|
||||
adafruit_metro_rp2350.menu.flash.16777216_262144.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_524288=16MB (Sketch: 15872KB, FS: 512KB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_524288.upload.maximum_size=16244736
|
||||
adafruit_metro_rp2350.menu.flash.16777216_524288.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_524288.build.flash_length=16244736
|
||||
adafruit_metro_rp2350.menu.flash.16777216_524288.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_524288.build.fs_start=284680192
|
||||
adafruit_metro_rp2350.menu.flash.16777216_524288.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_1048576=16MB (Sketch: 15MB, FS: 1MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_1048576.upload.maximum_size=15720448
|
||||
adafruit_metro_rp2350.menu.flash.16777216_1048576.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_1048576.build.flash_length=15720448
|
||||
adafruit_metro_rp2350.menu.flash.16777216_1048576.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_1048576.build.fs_start=284155904
|
||||
adafruit_metro_rp2350.menu.flash.16777216_1048576.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_2097152=16MB (Sketch: 14MB, FS: 2MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_2097152.upload.maximum_size=14671872
|
||||
adafruit_metro_rp2350.menu.flash.16777216_2097152.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_2097152.build.flash_length=14671872
|
||||
adafruit_metro_rp2350.menu.flash.16777216_2097152.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_2097152.build.fs_start=283107328
|
||||
adafruit_metro_rp2350.menu.flash.16777216_2097152.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_3145728=16MB (Sketch: 13MB, FS: 3MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_3145728.upload.maximum_size=13623296
|
||||
adafruit_metro_rp2350.menu.flash.16777216_3145728.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_3145728.build.flash_length=13623296
|
||||
adafruit_metro_rp2350.menu.flash.16777216_3145728.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_3145728.build.fs_start=282058752
|
||||
adafruit_metro_rp2350.menu.flash.16777216_3145728.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_4194304=16MB (Sketch: 12MB, FS: 4MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_4194304.upload.maximum_size=12574720
|
||||
adafruit_metro_rp2350.menu.flash.16777216_4194304.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_4194304.build.flash_length=12574720
|
||||
adafruit_metro_rp2350.menu.flash.16777216_4194304.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_4194304.build.fs_start=281010176
|
||||
adafruit_metro_rp2350.menu.flash.16777216_4194304.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_5242880=16MB (Sketch: 11MB, FS: 5MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_5242880.upload.maximum_size=11526144
|
||||
adafruit_metro_rp2350.menu.flash.16777216_5242880.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_5242880.build.flash_length=11526144
|
||||
adafruit_metro_rp2350.menu.flash.16777216_5242880.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_5242880.build.fs_start=279961600
|
||||
adafruit_metro_rp2350.menu.flash.16777216_5242880.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_6291456=16MB (Sketch: 10MB, FS: 6MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_6291456.upload.maximum_size=10477568
|
||||
adafruit_metro_rp2350.menu.flash.16777216_6291456.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_6291456.build.flash_length=10477568
|
||||
adafruit_metro_rp2350.menu.flash.16777216_6291456.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_6291456.build.fs_start=278913024
|
||||
adafruit_metro_rp2350.menu.flash.16777216_6291456.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_7340032=16MB (Sketch: 9MB, FS: 7MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_7340032.upload.maximum_size=9428992
|
||||
adafruit_metro_rp2350.menu.flash.16777216_7340032.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_7340032.build.flash_length=9428992
|
||||
adafruit_metro_rp2350.menu.flash.16777216_7340032.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_7340032.build.fs_start=277864448
|
||||
adafruit_metro_rp2350.menu.flash.16777216_7340032.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_8388608=16MB (Sketch: 8MB, FS: 8MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_8388608.upload.maximum_size=8380416
|
||||
adafruit_metro_rp2350.menu.flash.16777216_8388608.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_8388608.build.flash_length=8380416
|
||||
adafruit_metro_rp2350.menu.flash.16777216_8388608.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_8388608.build.fs_start=276815872
|
||||
adafruit_metro_rp2350.menu.flash.16777216_8388608.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_9437184=16MB (Sketch: 7MB, FS: 9MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_9437184.upload.maximum_size=7331840
|
||||
adafruit_metro_rp2350.menu.flash.16777216_9437184.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_9437184.build.flash_length=7331840
|
||||
adafruit_metro_rp2350.menu.flash.16777216_9437184.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_9437184.build.fs_start=275767296
|
||||
adafruit_metro_rp2350.menu.flash.16777216_9437184.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_10485760=16MB (Sketch: 6MB, FS: 10MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_10485760.upload.maximum_size=6283264
|
||||
adafruit_metro_rp2350.menu.flash.16777216_10485760.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_10485760.build.flash_length=6283264
|
||||
adafruit_metro_rp2350.menu.flash.16777216_10485760.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_10485760.build.fs_start=274718720
|
||||
adafruit_metro_rp2350.menu.flash.16777216_10485760.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_11534336=16MB (Sketch: 5MB, FS: 11MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_11534336.upload.maximum_size=5234688
|
||||
adafruit_metro_rp2350.menu.flash.16777216_11534336.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_11534336.build.flash_length=5234688
|
||||
adafruit_metro_rp2350.menu.flash.16777216_11534336.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_11534336.build.fs_start=273670144
|
||||
adafruit_metro_rp2350.menu.flash.16777216_11534336.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_12582912=16MB (Sketch: 4MB, FS: 12MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_12582912.upload.maximum_size=4186112
|
||||
adafruit_metro_rp2350.menu.flash.16777216_12582912.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_12582912.build.flash_length=4186112
|
||||
adafruit_metro_rp2350.menu.flash.16777216_12582912.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_12582912.build.fs_start=272621568
|
||||
adafruit_metro_rp2350.menu.flash.16777216_12582912.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_13631488=16MB (Sketch: 3MB, FS: 13MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_13631488.upload.maximum_size=3137536
|
||||
adafruit_metro_rp2350.menu.flash.16777216_13631488.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_13631488.build.flash_length=3137536
|
||||
adafruit_metro_rp2350.menu.flash.16777216_13631488.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_13631488.build.fs_start=271572992
|
||||
adafruit_metro_rp2350.menu.flash.16777216_13631488.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_14680064=16MB (Sketch: 2MB, FS: 14MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_14680064.upload.maximum_size=2088960
|
||||
adafruit_metro_rp2350.menu.flash.16777216_14680064.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_14680064.build.flash_length=2088960
|
||||
adafruit_metro_rp2350.menu.flash.16777216_14680064.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_14680064.build.fs_start=270524416
|
||||
adafruit_metro_rp2350.menu.flash.16777216_14680064.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_15728640=16MB (Sketch: 1MB, FS: 15MB)
|
||||
adafruit_metro_rp2350.menu.flash.16777216_15728640.upload.maximum_size=1040384
|
||||
adafruit_metro_rp2350.menu.flash.16777216_15728640.build.flash_total=16777216
|
||||
adafruit_metro_rp2350.menu.flash.16777216_15728640.build.flash_length=1040384
|
||||
adafruit_metro_rp2350.menu.flash.16777216_15728640.build.eeprom_start=285204480
|
||||
adafruit_metro_rp2350.menu.flash.16777216_15728640.build.fs_start=269475840
|
||||
adafruit_metro_rp2350.menu.flash.16777216_15728640.build.fs_end=285204480
|
||||
adafruit_metro_rp2350.menu.arch.arm=ARM
|
||||
adafruit_metro_rp2350.menu.arch.arm.build.chip=rp2350
|
||||
adafruit_metro_rp2350.menu.arch.arm.build.toolchain=arm-none-eabi
|
||||
adafruit_metro_rp2350.menu.arch.arm.build.toolchainpkg=pqt-gcc
|
||||
adafruit_metro_rp2350.menu.arch.arm.build.toolchainopts=-mcpu=cortex-m33 -mthumb -march=armv8-m.main+fp+dsp -mfloat-abi=softfp -mcmse
|
||||
adafruit_metro_rp2350.menu.arch.arm.build.uf2family=--family rp2350-arm-s --abs-block
|
||||
adafruit_metro_rp2350.menu.arch.arm.build.mcu=cortex-m33
|
||||
adafruit_metro_rp2350.menu.arch.riscv=RISC-V
|
||||
adafruit_metro_rp2350.menu.arch.riscv.build.chip=rp2350-riscv
|
||||
adafruit_metro_rp2350.menu.arch.riscv.build.toolchain=riscv32-unknown-elf
|
||||
adafruit_metro_rp2350.menu.arch.riscv.build.toolchainpkg=pqt-gcc-riscv
|
||||
adafruit_metro_rp2350.menu.arch.riscv.build.toolchainopts=-march=rv32imac_zicsr_zifencei_zba_zbb_zbs_zbkb -mabi=ilp32
|
||||
adafruit_metro_rp2350.menu.arch.riscv.build.uf2family=--family rp2350-riscv --abs-block
|
||||
adafruit_metro_rp2350.menu.arch.riscv.build.mcu=rv32imac
|
||||
adafruit_metro_rp2350.menu.freq.150=150 MHz
|
||||
adafruit_metro_rp2350.menu.freq.150.build.f_cpu=150000000L
|
||||
adafruit_metro_rp2350.menu.freq.50=50 MHz
|
||||
adafruit_metro_rp2350.menu.freq.50.build.f_cpu=50000000L
|
||||
adafruit_metro_rp2350.menu.freq.100=100 MHz
|
||||
adafruit_metro_rp2350.menu.freq.100.build.f_cpu=100000000L
|
||||
adafruit_metro_rp2350.menu.freq.120=120 MHz
|
||||
adafruit_metro_rp2350.menu.freq.120.build.f_cpu=120000000L
|
||||
adafruit_metro_rp2350.menu.freq.125=125 MHz
|
||||
adafruit_metro_rp2350.menu.freq.125.build.f_cpu=125000000L
|
||||
adafruit_metro_rp2350.menu.freq.128=128 MHz
|
||||
adafruit_metro_rp2350.menu.freq.128.build.f_cpu=128000000L
|
||||
adafruit_metro_rp2350.menu.freq.133=133 MHz
|
||||
adafruit_metro_rp2350.menu.freq.133.build.f_cpu=133000000L
|
||||
adafruit_metro_rp2350.menu.freq.175=175 MHz (Overclock)
|
||||
adafruit_metro_rp2350.menu.freq.175.build.f_cpu=175000000L
|
||||
adafruit_metro_rp2350.menu.freq.200=200 MHz (Overclock)
|
||||
adafruit_metro_rp2350.menu.freq.200.build.f_cpu=200000000L
|
||||
adafruit_metro_rp2350.menu.freq.225=225 MHz (Overclock)
|
||||
adafruit_metro_rp2350.menu.freq.225.build.f_cpu=225000000L
|
||||
adafruit_metro_rp2350.menu.freq.240=240 MHz (Overclock)
|
||||
adafruit_metro_rp2350.menu.freq.240.build.f_cpu=240000000L
|
||||
adafruit_metro_rp2350.menu.freq.250=250 MHz (Overclock)
|
||||
adafruit_metro_rp2350.menu.freq.250.build.f_cpu=250000000L
|
||||
adafruit_metro_rp2350.menu.freq.275=275 MHz (Overclock)
|
||||
adafruit_metro_rp2350.menu.freq.275.build.f_cpu=275000000L
|
||||
adafruit_metro_rp2350.menu.freq.300=300 MHz (Overclock)
|
||||
adafruit_metro_rp2350.menu.freq.300.build.f_cpu=300000000L
|
||||
adafruit_metro_rp2350.menu.opt.Small=Small (-Os) (standard)
|
||||
adafruit_metro_rp2350.menu.opt.Small.build.flags.optimize=-Os
|
||||
adafruit_metro_rp2350.menu.opt.Optimize=Optimize (-O)
|
||||
adafruit_metro_rp2350.menu.opt.Optimize.build.flags.optimize=-O
|
||||
adafruit_metro_rp2350.menu.opt.Optimize2=Optimize More (-O2)
|
||||
adafruit_metro_rp2350.menu.opt.Optimize2.build.flags.optimize=-O2
|
||||
adafruit_metro_rp2350.menu.opt.Optimize3=Optimize Even More (-O3)
|
||||
adafruit_metro_rp2350.menu.opt.Optimize3.build.flags.optimize=-O3
|
||||
adafruit_metro_rp2350.menu.opt.Fast=Fast (-Ofast) (maybe slower)
|
||||
adafruit_metro_rp2350.menu.opt.Fast.build.flags.optimize=-Ofast
|
||||
adafruit_metro_rp2350.menu.opt.Debug=Debug (-Og)
|
||||
adafruit_metro_rp2350.menu.opt.Debug.build.flags.optimize=-Og
|
||||
adafruit_metro_rp2350.menu.opt.Disabled=Disabled (-O0)
|
||||
adafruit_metro_rp2350.menu.opt.Disabled.build.flags.optimize=-O0
|
||||
adafruit_metro_rp2350.menu.profile.Disabled=Disabled
|
||||
adafruit_metro_rp2350.menu.profile.Disabled.build.flags.profile=
|
||||
adafruit_metro_rp2350.menu.profile.Enabled=Enabled
|
||||
adafruit_metro_rp2350.menu.profile.Enabled.build.flags.profile=-pg -D__PROFILE
|
||||
adafruit_metro_rp2350.menu.rtti.Disabled=Disabled
|
||||
adafruit_metro_rp2350.menu.rtti.Disabled.build.flags.rtti=-fno-rtti
|
||||
adafruit_metro_rp2350.menu.rtti.Enabled=Enabled
|
||||
adafruit_metro_rp2350.menu.rtti.Enabled.build.flags.rtti=
|
||||
adafruit_metro_rp2350.menu.stackprotect.Disabled=Disabled
|
||||
adafruit_metro_rp2350.menu.stackprotect.Disabled.build.flags.stackprotect=
|
||||
adafruit_metro_rp2350.menu.stackprotect.Enabled=Enabled
|
||||
adafruit_metro_rp2350.menu.stackprotect.Enabled.build.flags.stackprotect=-fstack-protector
|
||||
adafruit_metro_rp2350.menu.exceptions.Disabled=Disabled
|
||||
adafruit_metro_rp2350.menu.exceptions.Disabled.build.flags.exceptions=-fno-exceptions
|
||||
adafruit_metro_rp2350.menu.exceptions.Disabled.build.flags.libstdcpp=-lstdc++
|
||||
adafruit_metro_rp2350.menu.exceptions.Enabled=Enabled
|
||||
adafruit_metro_rp2350.menu.exceptions.Enabled.build.flags.exceptions=-fexceptions
|
||||
adafruit_metro_rp2350.menu.exceptions.Enabled.build.flags.libstdcpp=-lstdc++-exc
|
||||
adafruit_metro_rp2350.menu.dbgport.Disabled=Disabled
|
||||
adafruit_metro_rp2350.menu.dbgport.Disabled.build.debug_port=
|
||||
adafruit_metro_rp2350.menu.dbgport.Serial=Serial
|
||||
adafruit_metro_rp2350.menu.dbgport.Serial.build.debug_port=-DDEBUG_RP2040_PORT=Serial
|
||||
adafruit_metro_rp2350.menu.dbgport.Serial1=Serial1
|
||||
adafruit_metro_rp2350.menu.dbgport.Serial1.build.debug_port=-DDEBUG_RP2040_PORT=Serial1
|
||||
adafruit_metro_rp2350.menu.dbgport.Serial2=Serial2
|
||||
adafruit_metro_rp2350.menu.dbgport.Serial2.build.debug_port=-DDEBUG_RP2040_PORT=Serial2
|
||||
adafruit_metro_rp2350.menu.dbgport.SerialSemi=SerialSemi
|
||||
adafruit_metro_rp2350.menu.dbgport.SerialSemi.build.debug_port=-DDEBUG_RP2040_PORT=SerialSemi
|
||||
adafruit_metro_rp2350.menu.dbglvl.None=None
|
||||
adafruit_metro_rp2350.menu.dbglvl.None.build.debug_level=
|
||||
adafruit_metro_rp2350.menu.dbglvl.Core=Core
|
||||
adafruit_metro_rp2350.menu.dbglvl.Core.build.debug_level=-DDEBUG_RP2040_CORE
|
||||
adafruit_metro_rp2350.menu.dbglvl.SPI=SPI
|
||||
adafruit_metro_rp2350.menu.dbglvl.SPI.build.debug_level=-DDEBUG_RP2040_SPI
|
||||
adafruit_metro_rp2350.menu.dbglvl.Wire=Wire
|
||||
adafruit_metro_rp2350.menu.dbglvl.Wire.build.debug_level=-DDEBUG_RP2040_WIRE
|
||||
adafruit_metro_rp2350.menu.dbglvl.Bluetooth=Bluetooth
|
||||
adafruit_metro_rp2350.menu.dbglvl.Bluetooth.build.debug_level=-DDEBUG_RP2040_BLUETOOTH
|
||||
adafruit_metro_rp2350.menu.dbglvl.All=All
|
||||
adafruit_metro_rp2350.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI -DDEBUG_RP2040_CORE -DDEBUG_RP2040_BLUETOOTH
|
||||
adafruit_metro_rp2350.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_metro_rp2350.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_metro_rp2350.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_metro_rp2350.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_metro_rp2350.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_metro_rp2350.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
adafruit_metro_rp2350.menu.usbstack.tinyusb_host=Adafruit TinyUSB Host (native)
|
||||
adafruit_metro_rp2350.menu.usbstack.tinyusb_host.build.usbstack_flags=-DUSE_TINYUSB -DUSE_TINYUSB_HOST "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
adafruit_metro_rp2350.menu.usbstack.nousb=No USB
|
||||
adafruit_metro_rp2350.menu.usbstack.nousb.build.usbstack_flags="-DNO_USB -DDISABLE_USB_SERIAL -I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4only=IPv4 Only
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4only.build.libpicow=libipv4.a
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4only.build.libpicowdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6=IPv4 + IPv6
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6.build.libpicow=libipv4-ipv6.a
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6.build.libpicowdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4btcble=IPv4 + Bluetooth
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4btcble.build.libpicow=libipv4-bt.a
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4btcble.build.libpicowdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1 -DENABLE_CLASSIC=1 -DENABLE_BLE=1
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6btcble=IPv4 + IPv6 + Bluetooth
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6btcble.build.libpicow=libipv4-ipv6-bt.a
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6btcble.build.libpicowdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1 -DENABLE_CLASSIC=1 -DENABLE_BLE=1
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4onlybig=IPv4 Only - 32K
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4onlybig.build.libpicow=libipv4-big.a
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4onlybig.build.libpicowdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1 -D__LWIP_MEMMULT=2
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6big=IPv4 + IPv6 - 32K
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6big.build.libpicow=libipv4-ipv6-big.a
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6big.build.libpicowdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1 -D__LWIP_MEMMULT=2
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4btcblebig=IPv4 + Bluetooth - 32K
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4btcblebig.build.libpicow=libipv4-bt-big.a
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4btcblebig.build.libpicowdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1 -DENABLE_CLASSIC=1 -DENABLE_BLE=1 -D__LWIP_MEMMULT=2
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6btcblebig=IPv4 + IPv6 + Bluetooth - 32K
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6btcblebig.build.libpicow=libipv4-ipv6-bt-big.a
|
||||
adafruit_metro_rp2350.menu.ipbtstack.ipv4ipv6btcblebig.build.libpicowdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1 -DENABLE_CLASSIC=1 -DENABLE_BLE=1 -D__LWIP_MEMMULT=2
|
||||
adafruit_metro_rp2350.menu.uploadmethod.default=Default (UF2)
|
||||
adafruit_metro_rp2350.menu.uploadmethod.default.build.ram_length=512k
|
||||
adafruit_metro_rp2350.menu.uploadmethod.default.build.debugscript=picoprobe_cmsis_dap.tcl
|
||||
adafruit_metro_rp2350.menu.uploadmethod.default.upload.maximum_data_size=524288
|
||||
adafruit_metro_rp2350.menu.uploadmethod.default.upload.tool=uf2conv
|
||||
adafruit_metro_rp2350.menu.uploadmethod.default.upload.tool.default=uf2conv
|
||||
adafruit_metro_rp2350.menu.uploadmethod.default.upload.tool.network=uf2conv-network
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picotool=Picotool
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picotool.build.ram_length=512k
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picotool.build.debugscript=picoprobe.tcl
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picotool.build.picodebugflags=-DENABLE_PICOTOOL_USB
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picotool.upload.maximum_data_size=524288
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picotool.upload.tool=picotool
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picotool.upload.tool.default=picotool
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picoprobe_cmsis_dap=Picoprobe/Debugprobe (CMSIS-DAP)
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picoprobe_cmsis_dap.build.ram_length=512k
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picoprobe_cmsis_dap.build.debugscript=picoprobe_cmsis_dap.tcl
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picoprobe_cmsis_dap.upload.maximum_data_size=524288
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picoprobe_cmsis_dap.upload.tool=picoprobe_cmsis_dap
|
||||
adafruit_metro_rp2350.menu.uploadmethod.picoprobe_cmsis_dap.upload.tool.default=picoprobe_cmsis_dap
|
||||
|
||||
# -----------------------------------
|
||||
# Amken BunnyBoard
|
||||
# -----------------------------------
|
||||
@@ -28530,7 +28851,7 @@ seeed_xiao_rp2350.build.usbpid=-DUSBD_PID=0x0058
|
||||
seeed_xiao_rp2350.build.usbpwr=-DUSBD_MAX_POWER_MA=250
|
||||
seeed_xiao_rp2350.build.board=SEEED_XIAO_RP2350
|
||||
seeed_xiao_rp2350.build.variant=seeed_xiao_rp2350
|
||||
seeed_xiao_rp2350.upload.maximum_size=16777216
|
||||
seeed_xiao_rp2350.upload.maximum_size=2097152
|
||||
seeed_xiao_rp2350.upload.wait_for_upload_port=true
|
||||
seeed_xiao_rp2350.upload.erase_cmd=
|
||||
seeed_xiao_rp2350.serial.disableDTR=false
|
||||
@@ -28542,147 +28863,49 @@ seeed_xiao_rp2350.build.ldscript=memmap_default.ld
|
||||
seeed_xiao_rp2350.build.boot2=none
|
||||
seeed_xiao_rp2350.build.usb_manufacturer="Seeed"
|
||||
seeed_xiao_rp2350.build.usb_product="XIAO RP2350"
|
||||
seeed_xiao_rp2350.build.psram_length=0x800000
|
||||
seeed_xiao_rp2350.menu.flash.16777216_0=16MB (no FS)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_0.upload.maximum_size=16769024
|
||||
seeed_xiao_rp2350.menu.flash.16777216_0.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_0.build.flash_length=16769024
|
||||
seeed_xiao_rp2350.menu.flash.16777216_0.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_0.build.fs_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_0.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_65536=16MB (Sketch: 16320KB, FS: 64KB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_65536.upload.maximum_size=16703488
|
||||
seeed_xiao_rp2350.menu.flash.16777216_65536.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_65536.build.flash_length=16703488
|
||||
seeed_xiao_rp2350.menu.flash.16777216_65536.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_65536.build.fs_start=285138944
|
||||
seeed_xiao_rp2350.menu.flash.16777216_65536.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_131072=16MB (Sketch: 16256KB, FS: 128KB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_131072.upload.maximum_size=16637952
|
||||
seeed_xiao_rp2350.menu.flash.16777216_131072.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_131072.build.flash_length=16637952
|
||||
seeed_xiao_rp2350.menu.flash.16777216_131072.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_131072.build.fs_start=285073408
|
||||
seeed_xiao_rp2350.menu.flash.16777216_131072.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_262144=16MB (Sketch: 16128KB, FS: 256KB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_262144.upload.maximum_size=16506880
|
||||
seeed_xiao_rp2350.menu.flash.16777216_262144.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_262144.build.flash_length=16506880
|
||||
seeed_xiao_rp2350.menu.flash.16777216_262144.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_262144.build.fs_start=284942336
|
||||
seeed_xiao_rp2350.menu.flash.16777216_262144.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_524288=16MB (Sketch: 15872KB, FS: 512KB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_524288.upload.maximum_size=16244736
|
||||
seeed_xiao_rp2350.menu.flash.16777216_524288.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_524288.build.flash_length=16244736
|
||||
seeed_xiao_rp2350.menu.flash.16777216_524288.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_524288.build.fs_start=284680192
|
||||
seeed_xiao_rp2350.menu.flash.16777216_524288.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_1048576=16MB (Sketch: 15MB, FS: 1MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_1048576.upload.maximum_size=15720448
|
||||
seeed_xiao_rp2350.menu.flash.16777216_1048576.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_1048576.build.flash_length=15720448
|
||||
seeed_xiao_rp2350.menu.flash.16777216_1048576.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_1048576.build.fs_start=284155904
|
||||
seeed_xiao_rp2350.menu.flash.16777216_1048576.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_2097152=16MB (Sketch: 14MB, FS: 2MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_2097152.upload.maximum_size=14671872
|
||||
seeed_xiao_rp2350.menu.flash.16777216_2097152.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_2097152.build.flash_length=14671872
|
||||
seeed_xiao_rp2350.menu.flash.16777216_2097152.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_2097152.build.fs_start=283107328
|
||||
seeed_xiao_rp2350.menu.flash.16777216_2097152.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_3145728=16MB (Sketch: 13MB, FS: 3MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_3145728.upload.maximum_size=13623296
|
||||
seeed_xiao_rp2350.menu.flash.16777216_3145728.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_3145728.build.flash_length=13623296
|
||||
seeed_xiao_rp2350.menu.flash.16777216_3145728.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_3145728.build.fs_start=282058752
|
||||
seeed_xiao_rp2350.menu.flash.16777216_3145728.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_4194304=16MB (Sketch: 12MB, FS: 4MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_4194304.upload.maximum_size=12574720
|
||||
seeed_xiao_rp2350.menu.flash.16777216_4194304.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_4194304.build.flash_length=12574720
|
||||
seeed_xiao_rp2350.menu.flash.16777216_4194304.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_4194304.build.fs_start=281010176
|
||||
seeed_xiao_rp2350.menu.flash.16777216_4194304.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_5242880=16MB (Sketch: 11MB, FS: 5MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_5242880.upload.maximum_size=11526144
|
||||
seeed_xiao_rp2350.menu.flash.16777216_5242880.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_5242880.build.flash_length=11526144
|
||||
seeed_xiao_rp2350.menu.flash.16777216_5242880.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_5242880.build.fs_start=279961600
|
||||
seeed_xiao_rp2350.menu.flash.16777216_5242880.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_6291456=16MB (Sketch: 10MB, FS: 6MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_6291456.upload.maximum_size=10477568
|
||||
seeed_xiao_rp2350.menu.flash.16777216_6291456.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_6291456.build.flash_length=10477568
|
||||
seeed_xiao_rp2350.menu.flash.16777216_6291456.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_6291456.build.fs_start=278913024
|
||||
seeed_xiao_rp2350.menu.flash.16777216_6291456.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_7340032=16MB (Sketch: 9MB, FS: 7MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_7340032.upload.maximum_size=9428992
|
||||
seeed_xiao_rp2350.menu.flash.16777216_7340032.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_7340032.build.flash_length=9428992
|
||||
seeed_xiao_rp2350.menu.flash.16777216_7340032.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_7340032.build.fs_start=277864448
|
||||
seeed_xiao_rp2350.menu.flash.16777216_7340032.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_8388608=16MB (Sketch: 8MB, FS: 8MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_8388608.upload.maximum_size=8380416
|
||||
seeed_xiao_rp2350.menu.flash.16777216_8388608.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_8388608.build.flash_length=8380416
|
||||
seeed_xiao_rp2350.menu.flash.16777216_8388608.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_8388608.build.fs_start=276815872
|
||||
seeed_xiao_rp2350.menu.flash.16777216_8388608.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_9437184=16MB (Sketch: 7MB, FS: 9MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_9437184.upload.maximum_size=7331840
|
||||
seeed_xiao_rp2350.menu.flash.16777216_9437184.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_9437184.build.flash_length=7331840
|
||||
seeed_xiao_rp2350.menu.flash.16777216_9437184.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_9437184.build.fs_start=275767296
|
||||
seeed_xiao_rp2350.menu.flash.16777216_9437184.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_10485760=16MB (Sketch: 6MB, FS: 10MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_10485760.upload.maximum_size=6283264
|
||||
seeed_xiao_rp2350.menu.flash.16777216_10485760.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_10485760.build.flash_length=6283264
|
||||
seeed_xiao_rp2350.menu.flash.16777216_10485760.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_10485760.build.fs_start=274718720
|
||||
seeed_xiao_rp2350.menu.flash.16777216_10485760.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_11534336=16MB (Sketch: 5MB, FS: 11MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_11534336.upload.maximum_size=5234688
|
||||
seeed_xiao_rp2350.menu.flash.16777216_11534336.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_11534336.build.flash_length=5234688
|
||||
seeed_xiao_rp2350.menu.flash.16777216_11534336.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_11534336.build.fs_start=273670144
|
||||
seeed_xiao_rp2350.menu.flash.16777216_11534336.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_12582912=16MB (Sketch: 4MB, FS: 12MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_12582912.upload.maximum_size=4186112
|
||||
seeed_xiao_rp2350.menu.flash.16777216_12582912.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_12582912.build.flash_length=4186112
|
||||
seeed_xiao_rp2350.menu.flash.16777216_12582912.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_12582912.build.fs_start=272621568
|
||||
seeed_xiao_rp2350.menu.flash.16777216_12582912.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_13631488=16MB (Sketch: 3MB, FS: 13MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_13631488.upload.maximum_size=3137536
|
||||
seeed_xiao_rp2350.menu.flash.16777216_13631488.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_13631488.build.flash_length=3137536
|
||||
seeed_xiao_rp2350.menu.flash.16777216_13631488.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_13631488.build.fs_start=271572992
|
||||
seeed_xiao_rp2350.menu.flash.16777216_13631488.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_14680064=16MB (Sketch: 2MB, FS: 14MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_14680064.upload.maximum_size=2088960
|
||||
seeed_xiao_rp2350.menu.flash.16777216_14680064.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_14680064.build.flash_length=2088960
|
||||
seeed_xiao_rp2350.menu.flash.16777216_14680064.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_14680064.build.fs_start=270524416
|
||||
seeed_xiao_rp2350.menu.flash.16777216_14680064.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_15728640=16MB (Sketch: 1MB, FS: 15MB)
|
||||
seeed_xiao_rp2350.menu.flash.16777216_15728640.upload.maximum_size=1040384
|
||||
seeed_xiao_rp2350.menu.flash.16777216_15728640.build.flash_total=16777216
|
||||
seeed_xiao_rp2350.menu.flash.16777216_15728640.build.flash_length=1040384
|
||||
seeed_xiao_rp2350.menu.flash.16777216_15728640.build.eeprom_start=285204480
|
||||
seeed_xiao_rp2350.menu.flash.16777216_15728640.build.fs_start=269475840
|
||||
seeed_xiao_rp2350.menu.flash.16777216_15728640.build.fs_end=285204480
|
||||
seeed_xiao_rp2350.build.psram_length=0x000000
|
||||
seeed_xiao_rp2350.menu.flash.2097152_0=2MB (no FS)
|
||||
seeed_xiao_rp2350.menu.flash.2097152_0.upload.maximum_size=2088960
|
||||
seeed_xiao_rp2350.menu.flash.2097152_0.build.flash_total=2097152
|
||||
seeed_xiao_rp2350.menu.flash.2097152_0.build.flash_length=2088960
|
||||
seeed_xiao_rp2350.menu.flash.2097152_0.build.eeprom_start=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_0.build.fs_start=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_0.build.fs_end=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_65536=2MB (Sketch: 1984KB, FS: 64KB)
|
||||
seeed_xiao_rp2350.menu.flash.2097152_65536.upload.maximum_size=2023424
|
||||
seeed_xiao_rp2350.menu.flash.2097152_65536.build.flash_total=2097152
|
||||
seeed_xiao_rp2350.menu.flash.2097152_65536.build.flash_length=2023424
|
||||
seeed_xiao_rp2350.menu.flash.2097152_65536.build.eeprom_start=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_65536.build.fs_start=270458880
|
||||
seeed_xiao_rp2350.menu.flash.2097152_65536.build.fs_end=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_131072=2MB (Sketch: 1920KB, FS: 128KB)
|
||||
seeed_xiao_rp2350.menu.flash.2097152_131072.upload.maximum_size=1957888
|
||||
seeed_xiao_rp2350.menu.flash.2097152_131072.build.flash_total=2097152
|
||||
seeed_xiao_rp2350.menu.flash.2097152_131072.build.flash_length=1957888
|
||||
seeed_xiao_rp2350.menu.flash.2097152_131072.build.eeprom_start=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_131072.build.fs_start=270393344
|
||||
seeed_xiao_rp2350.menu.flash.2097152_131072.build.fs_end=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_262144=2MB (Sketch: 1792KB, FS: 256KB)
|
||||
seeed_xiao_rp2350.menu.flash.2097152_262144.upload.maximum_size=1826816
|
||||
seeed_xiao_rp2350.menu.flash.2097152_262144.build.flash_total=2097152
|
||||
seeed_xiao_rp2350.menu.flash.2097152_262144.build.flash_length=1826816
|
||||
seeed_xiao_rp2350.menu.flash.2097152_262144.build.eeprom_start=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_262144.build.fs_start=270262272
|
||||
seeed_xiao_rp2350.menu.flash.2097152_262144.build.fs_end=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_524288=2MB (Sketch: 1536KB, FS: 512KB)
|
||||
seeed_xiao_rp2350.menu.flash.2097152_524288.upload.maximum_size=1564672
|
||||
seeed_xiao_rp2350.menu.flash.2097152_524288.build.flash_total=2097152
|
||||
seeed_xiao_rp2350.menu.flash.2097152_524288.build.flash_length=1564672
|
||||
seeed_xiao_rp2350.menu.flash.2097152_524288.build.eeprom_start=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_524288.build.fs_start=270000128
|
||||
seeed_xiao_rp2350.menu.flash.2097152_524288.build.fs_end=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_1048576=2MB (Sketch: 1MB, FS: 1MB)
|
||||
seeed_xiao_rp2350.menu.flash.2097152_1048576.upload.maximum_size=1040384
|
||||
seeed_xiao_rp2350.menu.flash.2097152_1048576.build.flash_total=2097152
|
||||
seeed_xiao_rp2350.menu.flash.2097152_1048576.build.flash_length=1040384
|
||||
seeed_xiao_rp2350.menu.flash.2097152_1048576.build.eeprom_start=270524416
|
||||
seeed_xiao_rp2350.menu.flash.2097152_1048576.build.fs_start=269475840
|
||||
seeed_xiao_rp2350.menu.flash.2097152_1048576.build.fs_end=270524416
|
||||
seeed_xiao_rp2350.menu.arch.arm=ARM
|
||||
seeed_xiao_rp2350.menu.arch.arm.build.chip=rp2350
|
||||
seeed_xiao_rp2350.menu.arch.arm.build.toolchain=arm-none-eabi
|
||||
|
||||
@@ -110,7 +110,7 @@ extern bool __isFreeRTOS;
|
||||
#endif
|
||||
|
||||
#ifndef PGM_VOID_P
|
||||
#define PGM_VOID_P void *
|
||||
#define PGM_VOID_P const void *
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -159,3 +159,7 @@ constexpr uint64_t __bitset(const int (&a)[N], size_t i = 0U) {
|
||||
#define __GPIOCNT 30
|
||||
#define __FIRSTANALOGGPIO 26
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
using namespace arduino;
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define ARDUINO_PICO_MAJOR 4
|
||||
#define ARDUINO_PICO_MINOR 4
|
||||
#define ARDUINO_PICO_REVISION 2
|
||||
#define ARDUINO_PICO_VERSION_STR "4.4.2"
|
||||
#define ARDUINO_PICO_REVISION 4
|
||||
#define ARDUINO_PICO_VERSION_STR "4.4.4"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
extern "C" typedef struct uart_inst uart_inst_t;
|
||||
|
||||
class SerialPIO : public HardwareSerial {
|
||||
class SerialPIO : public arduino::HardwareSerial {
|
||||
public:
|
||||
static const pin_size_t NOPIN = 0xff; // Use in constructor to disable RX or TX unit
|
||||
SerialPIO(pin_size_t tx, pin_size_t rx, size_t fifoSize = 32);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "Arduino.h"
|
||||
#include "api/HardwareSerial.h"
|
||||
|
||||
class SerialSemiClass : public HardwareSerial {
|
||||
class SerialSemiClass : public arduino::HardwareSerial {
|
||||
public:
|
||||
SerialSemiClass() {
|
||||
/* noop */
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
extern "C" typedef struct uart_inst uart_inst_t;
|
||||
|
||||
#define UART_PIN_NOT_DEFINED (255u)
|
||||
class SerialUART : public HardwareSerial {
|
||||
class SerialUART : public arduino::HardwareSerial {
|
||||
public:
|
||||
SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx, pin_size_t rts = UART_PIN_NOT_DEFINED, pin_size_t cts = UART_PIN_NOT_DEFINED);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "api/HardwareSerial.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
class SerialUSB : public HardwareSerial {
|
||||
class SerialUSB : public arduino::HardwareSerial {
|
||||
public:
|
||||
SerialUSB() { }
|
||||
void begin(unsigned long baud = 115200) override;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <errno.h>
|
||||
#include <_syslist.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
|
||||
|
||||
@@ -56,9 +56,9 @@ extern "C" void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOr
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (bitOrder == LSBFIRST) {
|
||||
digitalWrite(dataPin, !!(val & (1 << i)));
|
||||
digitalWrite(dataPin, !!(val & (1 << i)) ? HIGH : LOW);
|
||||
} else {
|
||||
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
|
||||
digitalWrite(dataPin, !!(val & (1 << (7 - i))) ? HIGH : LOW);
|
||||
}
|
||||
|
||||
digitalWrite(clockPin, HIGH);
|
||||
|
||||
+2
-2
@@ -54,9 +54,9 @@ author = u'Earle F. Philhower, III'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'4.4.2'
|
||||
version = u'4.4.4'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'4.4.2'
|
||||
release = u'4.4.4'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
+34
-2
@@ -30,6 +30,12 @@ I2S(INPUT)
|
||||
Creates an I2S input port. Needs to be connected up to the
|
||||
desired pins (see below) and started before any input can happen.
|
||||
|
||||
I2S(INPUT_PULLUP)
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Creates a bi-directional I2S input and output port. Needs to be
|
||||
connected up to the desired pins (see below) and started before
|
||||
any input or output can happen.
|
||||
|
||||
bool setBCLK(pin_size_t pin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the BCLK pin of the I2S device. The LRCLK/word clock will be ``pin + 1``
|
||||
@@ -37,7 +43,18 @@ due to limitations of the PIO state machines. Call this before ``I2S::begin()``
|
||||
|
||||
bool setDATA(pin_size_t pin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the DOUT or DIN pin of the I2S device. Any pin may be used.
|
||||
Sets the DOUT or DIN pin of the I2S device. Any pin may be used. In bi-directional
|
||||
operation, must use ``I2S::setDOUT()`` and ``I2S::setDIN`` instead.
|
||||
Call before ``I2S::begin()``
|
||||
|
||||
bool setDOUT(pin_size_t pin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the DOUT pin of the I2S device. Any pin may be used.
|
||||
Call before ``I2S::begin()``
|
||||
|
||||
bool setDIN(pin_size_t pin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the DIN pin of the I2S device. Any pin may be used.
|
||||
Call before ``I2S::begin()``
|
||||
|
||||
bool setMCLK(pin_size_t pin)
|
||||
@@ -115,6 +132,14 @@ void getOverUnderflow()
|
||||
Returns a flag indicating if the I2S system ran our of data to send on output,
|
||||
or had to throw away data on input.
|
||||
|
||||
void getOverflow()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns a flag indicating if the I2S system had to throw away data on input.
|
||||
|
||||
void getUnderflow()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns a flag indicating if the I2S system ran our of data to send on output.
|
||||
|
||||
size_t write(uint8_t/int8_t/int16_t/int32_t)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Writes a single sample of ``bitsPerSample`` to the buffer. It is up to the
|
||||
@@ -139,7 +164,7 @@ size_t write(const uint8_t \*buffer, size_t size)
|
||||
Transfers number of bytes from an application buffer to the I2S output buffer.
|
||||
Be aware that ``size`` is in *bytes** and not samples. Size must be a multiple
|
||||
of **4 bytes**. Will not block, so check the return value to find out how
|
||||
many bytes were actually written.
|
||||
many 32-bit words were actually written.
|
||||
|
||||
int availableForWrite()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -156,6 +181,13 @@ int peek()
|
||||
Returns the next sample to be read from the I2S buffer (without actually
|
||||
removing it).
|
||||
|
||||
size_t read(uint8_t \*buffer, size_t size)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Transfers number of bytes from the I2S input buffer to an application buffer.
|
||||
Be aware that ``size`` is in *bytes** and not samples. Size must be a multiple
|
||||
of **4 bytes**. Will not block, so check the return value to find out how
|
||||
many 32-bit words were actually read.
|
||||
|
||||
void onTransmit(void (\*fn)(void))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets a callback to be called when an I2S DMA buffer is fully transmitted.
|
||||
|
||||
@@ -172,6 +172,37 @@ To learn more about PSRAM usage, see: :doc:`RP2350 PSRAM Support <psram>`
|
||||
; PSRAM size: 4MB
|
||||
board_upload.psram_length = 4194304
|
||||
|
||||
PSRAM chip select (CS)
|
||||
----------------------
|
||||
|
||||
For RP2350 based boards, this controls what chip-select (also called: slave-select / SS) pin to use when wanting to talk to the PSRAM chip.
|
||||
|
||||
Note that it's not needed to set this with a board that is known to have a PSRAM chip on-board, such as a "Sparkfun Thing Plus 2350". The ``pins_arduino.h`` of that variant already has the correct definition.
|
||||
|
||||
To learn more about PSRAM usage, see: :doc:`RP2350 PSRAM Support <psram>`
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; PSRAM CS is at GP47
|
||||
build_flags =
|
||||
-DRP2350_PSRAM_CS=47
|
||||
|
||||
|
||||
Boot2 Source
|
||||
------------
|
||||
|
||||
Boot2 is the second stage bootloader and predominantly used on the RP2040.
|
||||
Its main purpose is to configure the communication with the Flash at the highest, safest speed it can.
|
||||
All known boards have their correct value already configured. However, when choosing ``board = generic``,
|
||||
you can freely configure the Boot2 to be for a different flash.
|
||||
|
||||
For possible Boot2 filenames, `please see here <https://github.com/earlephilhower/arduino-pico/tree/master/boot2/rp2040>`__.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; expect an ISSI IS25LP080 flash, SPI frequency = CPU frequency divided by 2
|
||||
board_build.arduino.earlephilhower.boot2_source = boot2_is25lp080_2_padded_checksum.S
|
||||
|
||||
CPU Speed
|
||||
---------
|
||||
|
||||
|
||||
@@ -28,6 +28,19 @@ pin itself, as is the standard way in Arduino.
|
||||
|
||||
* The interrupt calls (``attachInterrupt``, and ``detachInterrpt``) are not implemented.
|
||||
|
||||
Software SPI (Master Only)
|
||||
==========================
|
||||
|
||||
Similar to ``SoftwareSerial``, ``SoftwareSPI`` creates a PIO based SPI interface that
|
||||
can be used in the same manner as the hardware SPI devices. The constructor takes the
|
||||
pins desired, which can be any GPIO pins with the rule that if hardware CS is used then
|
||||
it must be on pin ``SCK + 1``. Construct a ``SoftwareSPI`` object in your code as
|
||||
follows and use it as needed (i.e. pass it into ``SD.begin(_CS, softwareSPI);``
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#include <SoftwareSPI.h>
|
||||
SoftwareSPI softSPI(_sck, _miso, _mosi); // no HW CS support, any selection of pins can be used
|
||||
|
||||
SPI Slave (SPISlave)
|
||||
====================
|
||||
|
||||
@@ -204,7 +204,6 @@ size_t AudioBufferManager::write(const uint32_t *v, size_t words, bool sync) {
|
||||
/* noop busy wait */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
size_t availToWriteThisBuff = _wordsPerBuffer - _userOff;
|
||||
size_t toWrite = std::min(availToWriteThisBuff, words);
|
||||
@@ -245,6 +244,38 @@ bool AudioBufferManager::read(uint32_t *v, bool sync) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t AudioBufferManager::read(uint32_t *v, size_t words, bool sync) {
|
||||
size_t read = 0;
|
||||
|
||||
if (!_running || _isOutput) {
|
||||
return 0;
|
||||
}
|
||||
while (words) {
|
||||
AudioBuffer ** volatile p = (AudioBuffer ** volatile)&_filled;
|
||||
if (!*p) {
|
||||
if (!sync) {
|
||||
return read;
|
||||
} else {
|
||||
while (!*p) {
|
||||
/* noop busy wait */
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t availToReadThisBuff = _wordsPerBuffer - _userOff;
|
||||
size_t toRead = std::min(availToReadThisBuff, words);
|
||||
memcpy((void *)v, &((*p)->buff[_userOff]), toRead * sizeof(uint32_t));
|
||||
v += toRead;
|
||||
read += toRead;
|
||||
_userOff += toRead;
|
||||
words -= toRead;
|
||||
if (_userOff == _wordsPerBuffer) {
|
||||
_addToList(&_empty, _takeFromList(p));
|
||||
_userOff = 0;
|
||||
}
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
bool AudioBufferManager::getOverUnderflow() {
|
||||
bool hold = _overunderflow;
|
||||
_overunderflow = false;
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
bool write(uint32_t v, bool sync = true);
|
||||
size_t write(const uint32_t *v, size_t words, bool sync = true);
|
||||
bool read(uint32_t *v, bool sync = true);
|
||||
size_t read(uint32_t *v, size_t words, bool sync = true);
|
||||
void flush();
|
||||
|
||||
bool getOverUnderflow();
|
||||
|
||||
@@ -82,7 +82,7 @@ void deviceDisconnectedCallback(BLEDevice * device) {
|
||||
@text In BTstack, the Read Callback is first called to query the size of the
|
||||
Characteristic Value, before it is called to provide the data.
|
||||
Both times, the size has to be returned. The data is only stored in the provided
|
||||
buffer, if the buffer argeument is not NULL.
|
||||
buffer, if the buffer argument is not NULL.
|
||||
If more than one dynamic Characteristics is used, the value handle is used
|
||||
to distinguish them.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
I2S bi-directional input and output loopback example
|
||||
Released to the Public Domain by Cooper Dalrymple
|
||||
*/
|
||||
|
||||
#include <I2S.h>
|
||||
|
||||
I2S i2s(INPUT_PULLUP);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
i2s.setDOUT(0);
|
||||
i2s.setDIN(1);
|
||||
i2s.setBCLK(2); // Note: LRCLK = BCLK + 1
|
||||
i2s.setBitsPerSample(16);
|
||||
i2s.setFrequency(22050);
|
||||
// NOTE: The following values are known to work with the Adafruit microphone:
|
||||
// i2s.setBitsPerSample(32);
|
||||
// i2s.setFrequency(16000);
|
||||
i2s.begin();
|
||||
|
||||
while (1) {
|
||||
int16_t l, r;
|
||||
i2s.read16(&l, &r);
|
||||
i2s.write16(l, r);
|
||||
// NOTE: Adafruit microphone word size needs to match the BPS above.
|
||||
// int32_t l, r;
|
||||
// i2s.read32(&l, &r);
|
||||
// i2s.write32(l, r);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
/* Nothing here */
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
I2S bi-directional input and output buffered loopback example
|
||||
Released to the Public Domain by Cooper Dalrymple
|
||||
*/
|
||||
|
||||
#include <I2S.h>
|
||||
|
||||
I2S i2s(INPUT_PULLUP);
|
||||
|
||||
#define SIZE 256
|
||||
int16_t buffer[SIZE];
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
i2s.setDOUT(0);
|
||||
i2s.setDIN(1);
|
||||
i2s.setBCLK(2); // Note: LRCLK = BCLK + 1
|
||||
i2s.setBitsPerSample(16);
|
||||
i2s.setFrequency(22050);
|
||||
i2s.setBuffers(6, SIZE * sizeof(int16_t) / sizeof(uint32_t));
|
||||
i2s.begin();
|
||||
|
||||
size_t count, index;
|
||||
while (1) {
|
||||
count = i2s.read((uint8_t *)&buffer, SIZE * sizeof(int16_t)) * sizeof(uint32_t) / sizeof(int16_t);
|
||||
index = 0;
|
||||
while (index < count) {
|
||||
// Reduce volume by half
|
||||
buffer[index++] >>= 1; // right
|
||||
buffer[index++] >>= 1; // left
|
||||
}
|
||||
i2s.write((const uint8_t *)&buffer, count * sizeof(int16_t));
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
/* Nothing here */
|
||||
}
|
||||
+139
-61
@@ -24,13 +24,15 @@
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
|
||||
I2S::I2S(PinMode direction, pin_size_t bclk, pin_size_t data, pin_size_t mclk) {
|
||||
I2S::I2S(PinMode direction, pin_size_t bclk, pin_size_t data, pin_size_t mclk, pin_size_t data_rx) {
|
||||
_running = false;
|
||||
_bps = 16;
|
||||
_writtenHalf = false;
|
||||
_isOutput = direction == OUTPUT;
|
||||
_isInput = direction == INPUT || direction == INPUT_PULLUP;
|
||||
_isOutput = direction == OUTPUT || direction == INPUT_PULLUP;
|
||||
_pinBCLK = bclk;
|
||||
_pinDOUT = data;
|
||||
_pinDIN = direction == INPUT ? data : data_rx;
|
||||
_pinMCLK = mclk;
|
||||
_MCLKenabled = false;
|
||||
#ifdef PIN_I2S_BCLK
|
||||
@@ -44,14 +46,17 @@ I2S::I2S(PinMode direction, pin_size_t bclk, pin_size_t data, pin_size_t mclk) {
|
||||
#endif
|
||||
|
||||
#ifdef PIN_I2S_DIN
|
||||
if (!_isOutput) {
|
||||
_pinDOUT = PIN_I2S_DIN;
|
||||
if (_isInput) {
|
||||
_pinDIN = PIN_I2S_DIN;
|
||||
}
|
||||
#endif
|
||||
_freq = 48000;
|
||||
_arb = nullptr;
|
||||
_cb = nullptr;
|
||||
_cbd = nullptr;
|
||||
_arbInput = nullptr;
|
||||
_cbInput = nullptr;
|
||||
_cbdInput = nullptr;
|
||||
_arbOutput = nullptr;
|
||||
_cbOutput = nullptr;
|
||||
_cbdOutput = nullptr;
|
||||
_buffers = 6;
|
||||
_bufferWords = 0;
|
||||
_silenceSample = 0;
|
||||
@@ -81,7 +86,20 @@ bool I2S::setMCLK(pin_size_t pin) {
|
||||
_pinMCLK = pin;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2S::setDATA(pin_size_t pin) {
|
||||
if (_running || (pin >= __GPIOCNT) || (_isOutput && _isInput)) {
|
||||
return false;
|
||||
}
|
||||
if (_isOutput) {
|
||||
_pinDOUT = pin;
|
||||
} else {
|
||||
_pinDIN = pin;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2S::setDOUT(pin_size_t pin) {
|
||||
if (_running || (pin >= __GPIOCNT)) {
|
||||
return false;
|
||||
}
|
||||
@@ -89,6 +107,14 @@ bool I2S::setDATA(pin_size_t pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2S::setDIN(pin_size_t pin) {
|
||||
if (_running || (pin >= __GPIOCNT)) {
|
||||
return false;
|
||||
}
|
||||
_pinDIN = pin;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2S::setBitsPerSample(int bps) {
|
||||
if (_running || ((bps != 8) && (bps != 16) && (bps != 24) && (bps != 32))) {
|
||||
return false;
|
||||
@@ -111,10 +137,10 @@ bool I2S::setFrequency(int newFreq) {
|
||||
_freq = newFreq;
|
||||
if (_running) {
|
||||
if (_MCLKenabled) {
|
||||
int bitClk = _freq * _bps * (_isTDM ? (double)_tdmChannels : 2.0) /* channels */ * 2.0 /* edges per clock */;
|
||||
int bitClk = _freq * _bps * (_isTDM ? (double)_tdmChannels : 2.0) /* channels */ * (_isInput && _isOutput ? 4.0 : 2.0) /* edges per clock */;
|
||||
pio_sm_set_clkdiv_int_frac(_pio, _sm, clock_get_hz(clk_sys) / bitClk, 0);
|
||||
} else {
|
||||
float bitClk = _freq * _bps * (_isTDM ? (double)_tdmChannels : 2.0) /* channels */ * 2.0 /* edges per clock */;
|
||||
float bitClk = _freq * _bps * (_isTDM ? (double)_tdmChannels : 2.0) /* channels */ * (_isInput && _isOutput ? 4.0 : 2.0) /* edges per clock */;
|
||||
pio_sm_set_clkdiv(_pio, _sm, (float)clock_get_hz(clk_sys) / bitClk);
|
||||
}
|
||||
}
|
||||
@@ -144,7 +170,7 @@ bool I2S::setMCLKmult(int mult) {
|
||||
}
|
||||
|
||||
bool I2S::setLSBJFormat() {
|
||||
if (_running || !_isOutput) {
|
||||
if (_running || !_isOutput || _isInput) {
|
||||
return false;
|
||||
}
|
||||
_isLSBJ = true;
|
||||
@@ -152,7 +178,7 @@ bool I2S::setLSBJFormat() {
|
||||
}
|
||||
|
||||
bool I2S::setTDMFormat() {
|
||||
if (_running || !_isOutput) {
|
||||
if (_running || !_isOutput || _isInput) {
|
||||
return false;
|
||||
}
|
||||
_isTDM = true;
|
||||
@@ -160,7 +186,7 @@ bool I2S::setTDMFormat() {
|
||||
}
|
||||
|
||||
bool I2S::setTDMChannels(int channels) {
|
||||
if (_running || !_isOutput) {
|
||||
if (_running || !_isOutput || _isInput) {
|
||||
return false;
|
||||
}
|
||||
_tdmChannels = channels;
|
||||
@@ -168,7 +194,7 @@ bool I2S::setTDMChannels(int channels) {
|
||||
}
|
||||
|
||||
bool I2S::swapClocks() {
|
||||
if (_running || !_isOutput) {
|
||||
if (_running) {
|
||||
return false;
|
||||
}
|
||||
_swapClocks = true;
|
||||
@@ -177,38 +203,38 @@ bool I2S::swapClocks() {
|
||||
|
||||
void I2S::onTransmit(void(*fn)(void)) {
|
||||
if (_isOutput) {
|
||||
_cb = fn;
|
||||
_cbOutput = fn;
|
||||
if (_running) {
|
||||
_arb->setCallback(_cb);
|
||||
_arbOutput->setCallback(_cbOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2S::onTransmit(void(*fn)(void *), void *cbData) {
|
||||
if (_isOutput) {
|
||||
_cbd = fn;
|
||||
_cbdata = cbData;
|
||||
_cbdOutput = fn;
|
||||
_cbdataOutput = cbData;
|
||||
if (_running) {
|
||||
_arb->setCallback(_cbd, _cbdata);
|
||||
_arbOutput->setCallback(_cbdOutput, _cbdataOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2S::onReceive(void(*fn)(void)) {
|
||||
if (!_isOutput) {
|
||||
_cb = fn;
|
||||
if (_isInput) {
|
||||
_cbInput = fn;
|
||||
if (_running) {
|
||||
_arb->setCallback(_cb);
|
||||
_arbInput->setCallback(_cbInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2S::onReceive(void(*fn)(void *), void *cbData) {
|
||||
if (!_isOutput) {
|
||||
_cbd = fn;
|
||||
_cbdata = cbData;
|
||||
if (_isInput) {
|
||||
_cbdInput = fn;
|
||||
_cbdataInput = cbData;
|
||||
if (_running) {
|
||||
_arb->setCallback(_cbd, _cbdata);
|
||||
_arbInput->setCallback(_cbdInput, _cbdataInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,12 +255,21 @@ bool I2S::begin() {
|
||||
_isHolding = 0;
|
||||
int off = 0;
|
||||
if (!_swapClocks) {
|
||||
_i2s = new PIOProgram(_isOutput ? (_isTDM ? &pio_tdm_out_program : (_isLSBJ ? &pio_lsbj_out_program : &pio_i2s_out_program)) : &pio_i2s_in_program);
|
||||
_i2s = new PIOProgram(_isOutput ? (_isInput ? &pio_i2s_inout_program : (_isTDM ? &pio_tdm_out_program : (_isLSBJ ? &pio_lsbj_out_program : &pio_i2s_out_program))) : &pio_i2s_in_program);
|
||||
} else {
|
||||
_i2s = new PIOProgram(_isOutput ? (_isTDM ? &pio_tdm_out_swap_program : (_isLSBJ ? &pio_lsbj_out_swap_program : &pio_i2s_out_swap_program)) : &pio_i2s_in_swap_program);
|
||||
_i2s = new PIOProgram(_isOutput ? (_isInput ? &pio_i2s_inout_swap_program : (_isTDM ? &pio_tdm_out_swap_program : (_isLSBJ ? &pio_lsbj_out_swap_program : &pio_i2s_out_swap_program))) : &pio_i2s_in_swap_program);
|
||||
}
|
||||
int minpin, maxpin;
|
||||
if (_isOutput && _isInput) {
|
||||
minpin = std::min(std::min((int)_pinDOUT, (int)_pinDIN), (int)_pinBCLK);
|
||||
maxpin = std::max(std::min((int)_pinDOUT, (int)_pinDIN), (int)_pinBCLK + 1);
|
||||
} else if (_isOutput) {
|
||||
minpin = std::min((int)_pinDOUT, (int)_pinBCLK);
|
||||
maxpin = std::max((int)_pinDOUT, (int)_pinBCLK + 1);
|
||||
} else {
|
||||
minpin = std::min((int)_pinDIN, (int)_pinBCLK);
|
||||
maxpin = std::max((int)_pinDIN, (int)_pinBCLK + 1);
|
||||
}
|
||||
int minpin = std::min((int)_pinDOUT, (int)_pinBCLK);
|
||||
int maxpin = std::max((int)_pinDOUT, (int)_pinBCLK + 1);
|
||||
if (!_i2s->prepare(&_pio, &_sm, &off, minpin, maxpin - minpin + 1)) {
|
||||
_running = false;
|
||||
delete _i2s;
|
||||
@@ -242,7 +277,9 @@ bool I2S::begin() {
|
||||
return false;
|
||||
}
|
||||
if (_isOutput) {
|
||||
if (_isTDM) {
|
||||
if (_isInput) {
|
||||
pio_i2s_inout_program_init(_pio, _sm, off, _pinDIN, _pinDOUT, _pinBCLK, _bps, _swapClocks);
|
||||
} else if (_isTDM) {
|
||||
pio_tdm_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks, _tdmChannels);
|
||||
} else if (_isLSBJ) {
|
||||
pio_lsbj_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
|
||||
@@ -250,7 +287,7 @@ bool I2S::begin() {
|
||||
pio_i2s_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
|
||||
}
|
||||
} else {
|
||||
pio_i2s_in_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
|
||||
pio_i2s_in_program_init(_pio, _sm, off, _pinDIN, _pinBCLK, _bps, _swapClocks);
|
||||
}
|
||||
setFrequency(_freq);
|
||||
if (_MCLKenabled) {
|
||||
@@ -266,19 +303,39 @@ bool I2S::begin() {
|
||||
if (!_bufferWords) {
|
||||
_bufferWords = 64 * (_bps == 32 ? 2 : 1);
|
||||
}
|
||||
_arb = new AudioBufferManager(_buffers, _bufferWords, _silenceSample, _isOutput ? OUTPUT : INPUT);
|
||||
if (!_arb->begin(pio_get_dreq(_pio, _sm, _isOutput), _isOutput ? &_pio->txf[_sm] : (volatile void*)&_pio->rxf[_sm])) {
|
||||
_running = false;
|
||||
delete _arb;
|
||||
_arb = nullptr;
|
||||
delete _i2s;
|
||||
_i2s = nullptr;
|
||||
return false;
|
||||
if (_isInput) {
|
||||
_arbInput = new AudioBufferManager(_buffers, _bufferWords, _silenceSample, INPUT);
|
||||
if (!_arbInput->begin(pio_get_dreq(_pio, _sm, false), (volatile void*)&_pio->rxf[_sm])) {
|
||||
_running = false;
|
||||
delete _arbInput;
|
||||
_arbInput = nullptr;
|
||||
delete _i2s;
|
||||
_i2s = nullptr;
|
||||
return false;
|
||||
}
|
||||
if (_cbdInput) {
|
||||
_arbInput->setCallback(_cbdInput, _cbdataInput);
|
||||
} else {
|
||||
_arbInput->setCallback(_cbInput);
|
||||
}
|
||||
}
|
||||
if (_cbd) {
|
||||
_arb->setCallback(_cbd, _cbdata);
|
||||
} else {
|
||||
_arb->setCallback(_cb);
|
||||
if (_isOutput) {
|
||||
_arbOutput = new AudioBufferManager(_buffers, _bufferWords, _silenceSample, OUTPUT);
|
||||
if (!_arbOutput->begin(pio_get_dreq(_pio, _sm, true), &_pio->txf[_sm])) {
|
||||
_running = false;
|
||||
delete _arbOutput;
|
||||
_arbOutput = nullptr;
|
||||
delete _arbInput;
|
||||
_arbInput = nullptr;
|
||||
delete _i2s;
|
||||
_i2s = nullptr;
|
||||
return false;
|
||||
}
|
||||
if (_cbdOutput) {
|
||||
_arbOutput->setCallback(_cbdOutput, _cbdataOutput);
|
||||
} else {
|
||||
_arbOutput->setCallback(_cbOutput);
|
||||
}
|
||||
}
|
||||
pio_sm_set_enabled(_pio, _sm, true);
|
||||
|
||||
@@ -294,8 +351,10 @@ bool I2S::end() {
|
||||
}
|
||||
pio_sm_set_enabled(_pio, _sm, false);
|
||||
_running = false;
|
||||
delete _arb;
|
||||
_arb = nullptr;
|
||||
delete _arbOutput;
|
||||
_arbOutput = nullptr;
|
||||
delete _arbInput;
|
||||
_arbInput = nullptr;
|
||||
delete _i2s;
|
||||
_i2s = nullptr;
|
||||
}
|
||||
@@ -303,12 +362,12 @@ bool I2S::end() {
|
||||
}
|
||||
|
||||
int I2S::available() {
|
||||
if (!_running) {
|
||||
if (!_running || !_isInput) {
|
||||
return 0;
|
||||
} else {
|
||||
auto avail = _arb->available();
|
||||
avail *= 4; // 4 samples per 32-bits
|
||||
if (_bps < 24 && !_isOutput) {
|
||||
auto avail = _arbInput->available();
|
||||
avail *= 4; // 4 bytes per 32-bits
|
||||
if (_bps < 24) {
|
||||
avail += _isHolding / 8;
|
||||
}
|
||||
return avail;
|
||||
@@ -316,7 +375,7 @@ int I2S::available() {
|
||||
}
|
||||
|
||||
int I2S::read() {
|
||||
if (!_running || _isOutput) {
|
||||
if (!_running || !_isInput) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -352,7 +411,7 @@ int I2S::read() {
|
||||
}
|
||||
|
||||
int I2S::peek() {
|
||||
if (!_running || _isOutput) {
|
||||
if (!_running || !_isInput) {
|
||||
return 0;
|
||||
}
|
||||
if (!_hasPeeked) {
|
||||
@@ -364,7 +423,12 @@ int I2S::peek() {
|
||||
|
||||
void I2S::flush() {
|
||||
if (_running) {
|
||||
_arb->flush();
|
||||
if (_isOutput) {
|
||||
_arbOutput->flush();
|
||||
}
|
||||
if (_isInput) {
|
||||
_arbInput->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,7 +472,7 @@ size_t I2S::write(int32_t val, bool sync) {
|
||||
if (!_running || !_isOutput) {
|
||||
return 0;
|
||||
}
|
||||
return _arb->write(val, sync);
|
||||
return _arbOutput->write(val, sync);
|
||||
}
|
||||
|
||||
size_t I2S::write8(int8_t l, int8_t r) {
|
||||
@@ -441,14 +505,14 @@ size_t I2S::write32(int32_t l, int32_t r) {
|
||||
}
|
||||
|
||||
size_t I2S::read(int32_t *val, bool sync) {
|
||||
if (!_running || _isOutput) {
|
||||
if (!_running || !_isInput) {
|
||||
return 0;
|
||||
}
|
||||
return _arb->read((uint32_t *)val, sync);
|
||||
return _arbInput->read((uint32_t *)val, sync);
|
||||
}
|
||||
|
||||
bool I2S::read8(int8_t *l, int8_t *r) {
|
||||
if (!_running || _isOutput) {
|
||||
if (!_running || !_isInput) {
|
||||
return false;
|
||||
}
|
||||
if (_isHolding) {
|
||||
@@ -465,7 +529,7 @@ bool I2S::read8(int8_t *l, int8_t *r) {
|
||||
}
|
||||
|
||||
bool I2S::read16(int16_t *l, int16_t *r) {
|
||||
if (!_running || _isOutput) {
|
||||
if (!_running || !_isInput) {
|
||||
return false;
|
||||
}
|
||||
int32_t o;
|
||||
@@ -476,7 +540,7 @@ bool I2S::read16(int16_t *l, int16_t *r) {
|
||||
}
|
||||
|
||||
bool I2S::read24(int32_t *l, int32_t *r) {
|
||||
if (!_running || _isOutput) {
|
||||
if (!_running || !_isInput) {
|
||||
return false;
|
||||
}
|
||||
read32(l, r);
|
||||
@@ -487,7 +551,7 @@ bool I2S::read24(int32_t *l, int32_t *r) {
|
||||
}
|
||||
|
||||
bool I2S::read32(int32_t *l, int32_t *r) {
|
||||
if (!_running || _isOutput) {
|
||||
if (!_running || !_isInput) {
|
||||
return false;
|
||||
}
|
||||
read(l, true);
|
||||
@@ -495,17 +559,31 @@ bool I2S::read32(int32_t *l, int32_t *r) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t I2S::read(uint8_t *buffer, size_t size) {
|
||||
// We can only read 32-bit chunks here
|
||||
if (size & 0x3 || !_running || !_isInput) {
|
||||
return 0;
|
||||
}
|
||||
return _arbInput->read((uint32_t *)buffer, size / sizeof(uint32_t), false);
|
||||
}
|
||||
|
||||
size_t I2S::write(const uint8_t *buffer, size_t size) {
|
||||
// We can only write 32-bit chunks here
|
||||
if (size & 0x3 || !_running || !_isOutput) {
|
||||
return 0;
|
||||
}
|
||||
return _arb->write((const uint32_t *)buffer, size / sizeof(uint32_t), false);
|
||||
return _arbOutput->write((const uint32_t *)buffer, size / sizeof(uint32_t), false);
|
||||
}
|
||||
|
||||
int I2S::availableForWrite() {
|
||||
if (!_running || !_isOutput) {
|
||||
return 0;
|
||||
} else {
|
||||
auto avail = _arbOutput->available();
|
||||
avail *= 4; // 4 bytes per 32-bits
|
||||
if (_bps < 24 && _isInput) {
|
||||
avail += _isHolding / 8;
|
||||
}
|
||||
return avail;
|
||||
}
|
||||
return available();
|
||||
}
|
||||
|
||||
+32
-9
@@ -26,11 +26,13 @@
|
||||
|
||||
class I2S : public Stream, public AudioOutputBase {
|
||||
public:
|
||||
I2S(PinMode direction = OUTPUT, pin_size_t bclk = 26, pin_size_t data = 28, pin_size_t mclk = 25);
|
||||
I2S(PinMode direction = OUTPUT, pin_size_t bclk = 26, pin_size_t data = 28, pin_size_t mclk = 25, pin_size_t data_rx = 22);
|
||||
virtual ~I2S();
|
||||
|
||||
bool setBCLK(pin_size_t pin);
|
||||
bool setDATA(pin_size_t pin);
|
||||
bool setDOUT(pin_size_t pin);
|
||||
bool setDIN(pin_size_t pin);
|
||||
bool setMCLK(pin_size_t pin);
|
||||
virtual bool setBitsPerSample(int bps) override;
|
||||
virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) override;
|
||||
@@ -52,9 +54,6 @@ public:
|
||||
|
||||
virtual bool begin() override;
|
||||
virtual bool end() override;
|
||||
virtual bool getUnderflow() override {
|
||||
return getOverUnderflow();
|
||||
}
|
||||
|
||||
// from Stream
|
||||
virtual int available() override;
|
||||
@@ -71,7 +70,21 @@ public:
|
||||
if (!_running) {
|
||||
return false;
|
||||
} else {
|
||||
return _arb->getOverUnderflow();
|
||||
return _isOutput ? _arbOutput->getOverUnderflow() : _arbInput->getOverUnderflow();
|
||||
}
|
||||
}
|
||||
bool getOverflow() {
|
||||
if (!_running || !_isInput) {
|
||||
return false;
|
||||
} else {
|
||||
return _arbInput->getOverUnderflow();
|
||||
}
|
||||
}
|
||||
virtual bool getUnderflow() override {
|
||||
if (!_running || !_isOutput) {
|
||||
return false;
|
||||
} else {
|
||||
return _arbOutput->getOverUnderflow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +127,9 @@ public:
|
||||
bool read24(int32_t *l, int32_t *r); // Note that 24b reads will be left-aligned (see above)
|
||||
bool read32(int32_t *l, int32_t *r);
|
||||
|
||||
// Read samples into buffer
|
||||
size_t read(uint8_t *buffer, size_t size);
|
||||
|
||||
// Note that these callback are called from **INTERRUPT CONTEXT** and hence
|
||||
// should be in RAM, not FLASH, and should be quick to execute.
|
||||
void onTransmit(void(*)(void));
|
||||
@@ -124,6 +140,7 @@ public:
|
||||
private:
|
||||
pin_size_t _pinBCLK;
|
||||
pin_size_t _pinDOUT;
|
||||
pin_size_t _pinDIN;
|
||||
pin_size_t _pinMCLK;
|
||||
int _bps;
|
||||
int _freq;
|
||||
@@ -134,6 +151,7 @@ private:
|
||||
bool _isLSBJ;
|
||||
bool _isTDM;
|
||||
int _tdmChannels;
|
||||
bool _isInput;
|
||||
bool _isOutput;
|
||||
bool _swapClocks;
|
||||
bool _MCLKenabled;
|
||||
@@ -150,13 +168,18 @@ private:
|
||||
int32_t _holdWord = 0;
|
||||
int _isHolding = 0;
|
||||
|
||||
void (*_cb)();
|
||||
void (*_cbd)(void *);
|
||||
void *_cbdata;
|
||||
void (*_cbInput)();
|
||||
void (*_cbdInput)(void *);
|
||||
void *_cbdataInput;
|
||||
|
||||
void (*_cbOutput)();
|
||||
void (*_cbdOutput)(void *);
|
||||
void *_cbdataOutput;
|
||||
|
||||
void MCLKbegin();
|
||||
|
||||
AudioBufferManager *_arb;
|
||||
AudioBufferManager *_arbInput;
|
||||
AudioBufferManager *_arbOutput;
|
||||
PIOProgram *_i2s;
|
||||
PIOProgram *_i2sMCLK;
|
||||
PIO _pio, _pioMCLK;
|
||||
|
||||
@@ -194,6 +194,58 @@ right1:
|
||||
; Loop back to beginning...
|
||||
|
||||
|
||||
|
||||
.program pio_i2s_inout
|
||||
.side_set 2 ; 0 = bclk, 1=wclk
|
||||
|
||||
; The C code should place (number of bits/sample - 2) in Y and
|
||||
; also update the SHIFTCTRL to be 24 or 32 as appropriate
|
||||
|
||||
; +----- WCLK
|
||||
; |+---- BCLK
|
||||
mov x, y side 0b00 [1]
|
||||
left1:
|
||||
out pins, 1 side 0b01
|
||||
in pins, 1 side 0b01
|
||||
jmp x--, left1 side 0b00 [1]
|
||||
out pins, 1 side 0b01
|
||||
in pins, 1 side 0b01 ; 2584 LRCK stays low until BCLK goes low
|
||||
; Last bit of left has WCLK change per I2S spec
|
||||
mov x, y side 0b10 [1]
|
||||
right1:
|
||||
out pins, 1 side 0b11
|
||||
in pins, 1 side 0b11
|
||||
jmp x--, right1 side 0b10 [1]
|
||||
out pins, 1 side 0b11
|
||||
in pins, 1 side 0b11 ; 2584 LRCK stays high until BCLK goes low
|
||||
; Loop back to beginning...
|
||||
|
||||
|
||||
.program pio_i2s_inout_swap ; Note this is the same as _out, just "in" and not "out"
|
||||
.side_set 2 ; 0 = wclk, 1=bclk
|
||||
|
||||
; The C code should place (number of bits/sample - 2) in Y and
|
||||
; also update the SHIFTCTRL to be 24 or 32 as appropriate
|
||||
|
||||
; +----- BCLK
|
||||
; |+---- WCLK
|
||||
mov x, y side 0b00 [1]
|
||||
left1:
|
||||
out pins, 1 side 0b10
|
||||
in pins, 1 side 0b10
|
||||
jmp x--, left1 side 0b00 [1]
|
||||
out pins, 1 side 0b10
|
||||
in pins, 1 side 0b10 ;2584 LRCK stays low until BCLK goes low
|
||||
|
||||
mov x, y side 0b01 [1]
|
||||
right1:
|
||||
out pins, 1 side 0b11
|
||||
in pins, 1 side 0b11
|
||||
jmp x--, right1 side 0b01 [1]
|
||||
out pins, 1 side 0b11
|
||||
in pins, 1 side 0b11 ; 2584 LRCK stays high until BCLK goes low
|
||||
; Loop back to beginning...
|
||||
|
||||
|
||||
|
||||
% c-sdk {
|
||||
@@ -314,4 +366,35 @@ static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint d
|
||||
pio_sm_exec(pio, sm, pio_encode_in(pio_pins, bits - 1)); // Shift in 1st R data modulo one bit, avoiding bit shift from #2037
|
||||
}
|
||||
|
||||
static inline void pio_i2s_inout_program_init(PIO pio, uint sm, uint offset, uint data_in_pin, uint data_out_pin, uint clock_pin_base, uint bits, bool swap) {
|
||||
pio_gpio_init(pio, data_in_pin);
|
||||
pio_gpio_init(pio, data_out_pin);
|
||||
pio_gpio_init(pio, clock_pin_base);
|
||||
pio_gpio_init(pio, clock_pin_base + 1);
|
||||
|
||||
pio_sm_config sm_config = swap ? pio_i2s_inout_swap_program_get_default_config(offset) : pio_i2s_inout_program_get_default_config(offset);
|
||||
|
||||
sm_config_set_in_pins(&sm_config, data_in_pin);
|
||||
sm_config_set_out_pins(&sm_config, data_out_pin, 1);
|
||||
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
|
||||
sm_config_set_in_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits);
|
||||
sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &sm_config);
|
||||
|
||||
//uint pin_mask = (1u << data_out_pin) | (3u << clock_pin_base);
|
||||
//pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask);
|
||||
//pio_sm_set_pins(pio, sm, 0); // clear pins
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, data_in_pin, 1, false);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, data_out_pin, 1, true);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, clock_pin_base, 2, true);
|
||||
pio_sm_set_set_pins(pio, sm, data_out_pin, 1);
|
||||
pio_sm_set_set_pins(pio, sm, clock_pin_base, 2);
|
||||
|
||||
pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2));
|
||||
|
||||
pio_sm_exec(pio, sm, pio_encode_in(pio_pins, bits)); // Shift in 1st L data
|
||||
pio_sm_exec(pio, sm, pio_encode_in(pio_pins, bits - 1)); // Shift in 1st R data modulo one bit, avoiding bit shift from #2037
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
@@ -351,6 +351,94 @@ static inline pio_sm_config pio_i2s_in_swap_program_get_default_config(uint offs
|
||||
sm_config_set_sideset(&c, 2, false, false);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------- //
|
||||
// pio_i2s_inout //
|
||||
// ------------- //
|
||||
|
||||
#define pio_i2s_inout_wrap_target 0
|
||||
#define pio_i2s_inout_wrap 11
|
||||
#define pio_i2s_inout_pio_version 0
|
||||
|
||||
static const uint16_t pio_i2s_inout_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xa122, // 0: mov x, y side 0 [1]
|
||||
0x6801, // 1: out pins, 1 side 1
|
||||
0x4801, // 2: in pins, 1 side 1
|
||||
0x0141, // 3: jmp x--, 1 side 0 [1]
|
||||
0x6801, // 4: out pins, 1 side 1
|
||||
0x4801, // 5: in pins, 1 side 1
|
||||
0xb122, // 6: mov x, y side 2 [1]
|
||||
0x7801, // 7: out pins, 1 side 3
|
||||
0x5801, // 8: in pins, 1 side 3
|
||||
0x1147, // 9: jmp x--, 7 side 2 [1]
|
||||
0x7801, // 10: out pins, 1 side 3
|
||||
0x5801, // 11: in pins, 1 side 3
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program pio_i2s_inout_program = {
|
||||
.instructions = pio_i2s_inout_program_instructions,
|
||||
.length = 12,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_i2s_inout_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + pio_i2s_inout_wrap_target, offset + pio_i2s_inout_wrap);
|
||||
sm_config_set_sideset(&c, 2, false, false);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------ //
|
||||
// pio_i2s_inout_swap //
|
||||
// ------------------ //
|
||||
|
||||
#define pio_i2s_inout_swap_wrap_target 0
|
||||
#define pio_i2s_inout_swap_wrap 11
|
||||
#define pio_i2s_inout_swap_pio_version 0
|
||||
|
||||
static const uint16_t pio_i2s_inout_swap_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xa122, // 0: mov x, y side 0 [1]
|
||||
0x7001, // 1: out pins, 1 side 2
|
||||
0x5001, // 2: in pins, 1 side 2
|
||||
0x0141, // 3: jmp x--, 1 side 0 [1]
|
||||
0x7001, // 4: out pins, 1 side 2
|
||||
0x5001, // 5: in pins, 1 side 2
|
||||
0xa922, // 6: mov x, y side 1 [1]
|
||||
0x7801, // 7: out pins, 1 side 3
|
||||
0x5801, // 8: in pins, 1 side 3
|
||||
0x0947, // 9: jmp x--, 7 side 1 [1]
|
||||
0x7801, // 10: out pins, 1 side 3
|
||||
0x5801, // 11: in pins, 1 side 3
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program pio_i2s_inout_swap_program = {
|
||||
.instructions = pio_i2s_inout_swap_program_instructions,
|
||||
.length = 12,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_i2s_inout_swap_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + pio_i2s_inout_swap_wrap_target, offset + pio_i2s_inout_swap_wrap);
|
||||
sm_config_set_sideset(&c, 2, false, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void pio_i2s_MCLK_program_init(PIO pio, uint sm, uint offset, uint MCLK_pin) {
|
||||
pio_gpio_init(pio, MCLK_pin);
|
||||
@@ -441,6 +529,29 @@ static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint d
|
||||
pio_sm_exec(pio, sm, pio_encode_in(pio_pins, bits)); // Shift in 1st L data
|
||||
pio_sm_exec(pio, sm, pio_encode_in(pio_pins, bits - 1)); // Shift in 1st R data modulo one bit, avoiding bit shift from #2037
|
||||
}
|
||||
static inline void pio_i2s_inout_program_init(PIO pio, uint sm, uint offset, uint data_in_pin, uint data_out_pin, uint clock_pin_base, uint bits, bool swap) {
|
||||
pio_gpio_init(pio, data_in_pin);
|
||||
pio_gpio_init(pio, data_out_pin);
|
||||
pio_gpio_init(pio, clock_pin_base);
|
||||
pio_gpio_init(pio, clock_pin_base + 1);
|
||||
pio_sm_config sm_config = swap ? pio_i2s_inout_swap_program_get_default_config(offset) : pio_i2s_inout_program_get_default_config(offset);
|
||||
sm_config_set_in_pins(&sm_config, data_in_pin);
|
||||
sm_config_set_out_pins(&sm_config, data_out_pin, 1);
|
||||
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
|
||||
sm_config_set_in_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits);
|
||||
sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits);
|
||||
pio_sm_init(pio, sm, offset, &sm_config);
|
||||
//uint pin_mask = (1u << data_out_pin) | (3u << clock_pin_base);
|
||||
//pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask);
|
||||
//pio_sm_set_pins(pio, sm, 0); // clear pins
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, data_in_pin, 1, false);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, data_out_pin, 1, true);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, clock_pin_base, 2, true);
|
||||
pio_sm_set_set_pins(pio, sm, data_out_pin, 1);
|
||||
pio_sm_set_set_pins(pio, sm, clock_pin_base, 2);
|
||||
pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2));
|
||||
pio_sm_exec(pio, sm, pio_encode_in(pio_pins, bits)); // Shift in 1st L data
|
||||
pio_sm_exec(pio, sm, pio_encode_in(pio_pins, bits - 1)); // Shift in 1st R data modulo one bit, avoiding bit shift from #2037
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ bool MDNSResponder::_prepareMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_r
|
||||
// Prepare header; count answers
|
||||
stcMDNS_MsgHeader msgHeader(p_rSendParameter.m_u16ID, p_rSendParameter.m_bResponse, 0,
|
||||
p_rSendParameter.m_bAuthorative);
|
||||
// If this is a response, the answers are anwers,
|
||||
// If this is a response, the answers are answers,
|
||||
// else this is a query or probe and the answers go into auth section
|
||||
uint16_t& ru16Answers
|
||||
= (p_rSendParameter.m_bResponse ? msgHeader.m_u16ANCount : msgHeader.m_u16NSCount);
|
||||
|
||||
+14
-86
@@ -45,47 +45,6 @@ SPIClassRP2040::SPIClassRP2040(spi_inst_t *spi, pin_size_t rx, pin_size_t cs, pi
|
||||
_CS = cs;
|
||||
}
|
||||
|
||||
inline spi_cpol_t SPIClassRP2040::cpol() {
|
||||
switch (_spis.getDataMode()) {
|
||||
case SPI_MODE0:
|
||||
return SPI_CPOL_0;
|
||||
case SPI_MODE1:
|
||||
return SPI_CPOL_0;
|
||||
case SPI_MODE2:
|
||||
return SPI_CPOL_1;
|
||||
case SPI_MODE3:
|
||||
return SPI_CPOL_1;
|
||||
}
|
||||
// Error
|
||||
return SPI_CPOL_0;
|
||||
}
|
||||
|
||||
inline spi_cpha_t SPIClassRP2040::cpha() {
|
||||
switch (_spis.getDataMode()) {
|
||||
case SPI_MODE0:
|
||||
return SPI_CPHA_0;
|
||||
case SPI_MODE1:
|
||||
return SPI_CPHA_1;
|
||||
case SPI_MODE2:
|
||||
return SPI_CPHA_0;
|
||||
case SPI_MODE3:
|
||||
return SPI_CPHA_1;
|
||||
}
|
||||
// Error
|
||||
return SPI_CPHA_0;
|
||||
}
|
||||
|
||||
inline uint8_t SPIClassRP2040::reverseByte(uint8_t b) {
|
||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
inline uint16_t SPIClassRP2040::reverse16Bit(uint16_t w) {
|
||||
return (reverseByte(w & 0xff) << 8) | (reverseByte(w >> 8));
|
||||
}
|
||||
|
||||
// The HW can't do LSB first, only MSB first, so need to bitreverse
|
||||
void SPIClassRP2040::adjustBuffer(const void *s, void *d, size_t cnt, bool by16) {
|
||||
if (_spis.getBitOrder() == MSBFIRST) {
|
||||
@@ -94,13 +53,13 @@ void SPIClassRP2040::adjustBuffer(const void *s, void *d, size_t cnt, bool by16)
|
||||
const uint8_t *src = (const uint8_t *)s;
|
||||
uint8_t *dst = (uint8_t *)d;
|
||||
for (size_t i = 0; i < cnt; i++) {
|
||||
*(dst++) = reverseByte(*(src++));
|
||||
*(dst++) = _helper.reverseByte(*(src++));
|
||||
}
|
||||
} else { /* by16 */
|
||||
const uint16_t *src = (const uint16_t *)s;
|
||||
uint16_t *dst = (uint16_t *)d;
|
||||
for (size_t i = 0; i < cnt; i++) {
|
||||
*(dst++) = reverse16Bit(*(src++));
|
||||
*(dst++) = _helper.reverse16Bit(*(src++));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,11 +69,11 @@ byte SPIClassRP2040::transfer(uint8_t data) {
|
||||
if (!_initted) {
|
||||
return 0;
|
||||
}
|
||||
data = (_spis.getBitOrder() == MSBFIRST) ? data : reverseByte(data);
|
||||
DEBUGSPI("SPI::transfer(%02x), cpol=%d, cpha=%d\n", data, cpol(), cpha());
|
||||
data = (_spis.getBitOrder() == MSBFIRST) ? data : _helper.reverseByte(data);
|
||||
DEBUGSPI("SPI::transfer(%02x), cpol=%d, cpha=%d\n", data, _helper.cpol(_spis), _helper.cpha(_spis));
|
||||
hw_write_masked(&spi_get_hw(_spi)->cr0, (8 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); // Fast set to 8-bits
|
||||
spi_write_read_blocking(_spi, &data, &ret, 1);
|
||||
ret = (_spis.getBitOrder() == MSBFIRST) ? ret : reverseByte(ret);
|
||||
ret = (_spis.getBitOrder() == MSBFIRST) ? ret : _helper.reverseByte(ret);
|
||||
DEBUGSPI("SPI: read back %02x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -124,11 +83,11 @@ uint16_t SPIClassRP2040::transfer16(uint16_t data) {
|
||||
if (!_initted) {
|
||||
return 0;
|
||||
}
|
||||
data = (_spis.getBitOrder() == MSBFIRST) ? data : reverse16Bit(data);
|
||||
DEBUGSPI("SPI::transfer16(%04x), cpol=%d, cpha=%d\n", data, cpol(), cpha());
|
||||
data = (_spis.getBitOrder() == MSBFIRST) ? data : _helper.reverse16Bit(data);
|
||||
DEBUGSPI("SPI::transfer16(%04x), cpol=%d, cpha=%d\n", data, _helper.cpol(_spis), _helper.cpha(_spis));
|
||||
hw_write_masked(&spi_get_hw(_spi)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); // Fast set to 16-bits
|
||||
spi_write16_read16_blocking(_spi, &data, &ret, 1);
|
||||
ret = (_spis.getBitOrder() == MSBFIRST) ? ret : reverse16Bit(ret);
|
||||
ret = (_spis.getBitOrder() == MSBFIRST) ? ret : _helper.reverse16Bit(ret);
|
||||
DEBUGSPI("SPI: read back %02x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -172,21 +131,14 @@ void SPIClassRP2040::transfer(const void *txbuf, void *rxbuf, size_t count) {
|
||||
// If its LSB this isn't nearly as fun, we'll just let transfer(x) do it :(
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
*rxbuff = transfer(*txbuff);
|
||||
*rxbuff = (_spis.getBitOrder() == MSBFIRST) ? *rxbuff : reverseByte(*rxbuff);
|
||||
*rxbuff = (_spis.getBitOrder() == MSBFIRST) ? *rxbuff : _helper.reverseByte(*rxbuff);
|
||||
txbuff++;
|
||||
rxbuff++;
|
||||
}
|
||||
DEBUGSPI("SPI::transfer completed\n");
|
||||
}
|
||||
|
||||
#ifdef PICO_RP2350B
|
||||
#define GPIOIRQREGS 6
|
||||
#else
|
||||
#define GPIOIRQREGS 4
|
||||
#endif
|
||||
|
||||
void SPIClassRP2040::beginTransaction(SPISettings settings) {
|
||||
noInterrupts(); // Avoid possible race conditions if IRQ comes in while main app is in middle of this
|
||||
DEBUGSPI("SPI::beginTransaction(clk=%lu, bo=%s)\n", settings.getClockFreq(), (settings.getBitOrder() == MSBFIRST) ? "MSB" : "LSB");
|
||||
if (_initted && settings == _spis) {
|
||||
DEBUGSPI("SPI: Reusing existing initted SPI\n");
|
||||
@@ -202,39 +154,15 @@ void SPIClassRP2040::beginTransaction(SPISettings settings) {
|
||||
DEBUGSPI("SPI: actual baudrate=%u\n", spi_get_baudrate(_spi));
|
||||
}
|
||||
_spis = settings;
|
||||
spi_set_format(_spi, 8, cpol(), cpha(), SPI_MSB_FIRST);
|
||||
spi_set_format(_spi, 8, _helper.cpol(_spis), _helper.cpha(_spis), SPI_MSB_FIRST);
|
||||
_initted = true;
|
||||
}
|
||||
// Disable any IRQs that are being used for SPI
|
||||
io_bank0_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ? &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
|
||||
DEBUGSPI("SPI: IRQ masks before = %08x %08x %08x %08x %08x %08x\n", (unsigned)irq_ctrl_base->inte[0], (unsigned)irq_ctrl_base->inte[1], (unsigned)irq_ctrl_base->inte[2], (unsigned)irq_ctrl_base->inte[3], (GPIOIRQREGS > 4) ? (unsigned)irq_ctrl_base->inte[4] : 0, (GPIOIRQREGS > 5) ? (unsigned)irq_ctrl_base->inte[5] : 0);
|
||||
for (auto entry : _usingIRQs) {
|
||||
int gpio = entry.first;
|
||||
|
||||
// There is no gpio_get_irq, so manually twiddle the register
|
||||
io_rw_32 *en_reg = &irq_ctrl_base->inte[gpio / 8];
|
||||
uint32_t val = ((*en_reg) >> (4 * (gpio % 8))) & 0xf;
|
||||
_usingIRQs.insert_or_assign(gpio, val);
|
||||
DEBUGSPI("SPI: GPIO %d = %lu\n", gpio, val);
|
||||
(*en_reg) ^= val << (4 * (gpio % 8));
|
||||
}
|
||||
DEBUGSPI("SPI: IRQ masks after = %08x %08x %08x %08x %08x %08x\n", (unsigned)irq_ctrl_base->inte[0], (unsigned)irq_ctrl_base->inte[1], (unsigned)irq_ctrl_base->inte[2], (unsigned)irq_ctrl_base->inte[3], (GPIOIRQREGS > 4) ? (unsigned)irq_ctrl_base->inte[4] : 0, (GPIOIRQREGS > 5) ? (unsigned)irq_ctrl_base->inte[5] : 0);
|
||||
interrupts();
|
||||
_helper.maskInterrupts();
|
||||
}
|
||||
|
||||
void SPIClassRP2040::endTransaction(void) {
|
||||
noInterrupts(); // Avoid race condition so the GPIO IRQs won't come back until all state is restored
|
||||
DEBUGSPI("SPI::endTransaction()\n");
|
||||
// Re-enable IRQs
|
||||
for (auto entry : _usingIRQs) {
|
||||
int gpio = entry.first;
|
||||
int mode = entry.second;
|
||||
gpio_set_irq_enabled(gpio, mode, true);
|
||||
}
|
||||
io_bank0_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ? &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
|
||||
(void) irq_ctrl_base;
|
||||
DEBUGSPI("SPI: IRQ masks = %08x %08x %08x %08x %08x %08x\n", (unsigned)irq_ctrl_base->inte[0], (unsigned)irq_ctrl_base->inte[1], (unsigned)irq_ctrl_base->inte[2], (unsigned)irq_ctrl_base->inte[3], (GPIOIRQREGS > 4) ? (unsigned)irq_ctrl_base->inte[4] : 0, (GPIOIRQREGS > 5) ? (unsigned)irq_ctrl_base->inte[5] : 0);
|
||||
interrupts();
|
||||
_helper.unmaskInterrupts();
|
||||
}
|
||||
|
||||
bool SPIClassRP2040::transferAsync(const void *send, void *recv, size_t bytes) {
|
||||
@@ -265,7 +193,7 @@ bool SPIClassRP2040::transferAsync(const void *send, void *recv, size_t bytes) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < bytes; i++) {
|
||||
_dmaBuffer[i] = reverseByte(txbuff[i]);
|
||||
_dmaBuffer[i] = _helper.reverseByte(txbuff[i]);
|
||||
}
|
||||
}
|
||||
_dmaBytes = bytes;
|
||||
@@ -312,7 +240,7 @@ bool SPIClassRP2040::finishedAsync() {
|
||||
spi_get_hw(_spi)->dmacr = 0;
|
||||
if (_spis.getBitOrder() != MSBFIRST) {
|
||||
for (int i = 0; i < _dmaBytes; i++) {
|
||||
_rxFinalBuffer[i] = reverseByte(_rxFinalBuffer[i]);
|
||||
_rxFinalBuffer[i] = _helper.reverseByte(_rxFinalBuffer[i]);
|
||||
}
|
||||
free(_dmaBuffer);
|
||||
_dmaBuffer = nullptr;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <api/HardwareSPI.h>
|
||||
#include <hardware/spi.h>
|
||||
#include <map>
|
||||
#include "SPIHelper.h"
|
||||
|
||||
class SPIClassRP2040 : public arduino::HardwareSPI {
|
||||
public:
|
||||
@@ -76,19 +76,16 @@ public:
|
||||
|
||||
// List of GPIO IRQs to disable during a transaction
|
||||
virtual void usingInterrupt(int interruptNumber) override {
|
||||
_usingIRQs.insert({interruptNumber, 0});
|
||||
_helper.usingInterrupt(interruptNumber);
|
||||
}
|
||||
|
||||
virtual void notUsingInterrupt(int interruptNumber) override {
|
||||
_usingIRQs.erase(interruptNumber);
|
||||
_helper.notUsingInterrupt(interruptNumber);
|
||||
}
|
||||
virtual void attachInterrupt() override { /* noop */ }
|
||||
virtual void detachInterrupt() override { /* noop */ }
|
||||
|
||||
private:
|
||||
spi_cpol_t cpol();
|
||||
spi_cpha_t cpha();
|
||||
uint8_t reverseByte(uint8_t b);
|
||||
uint16_t reverse16Bit(uint16_t w);
|
||||
void adjustBuffer(const void *s, void *d, size_t cnt, bool by16);
|
||||
|
||||
spi_inst_t *_spi;
|
||||
@@ -98,8 +95,6 @@ private:
|
||||
bool _running; // SPI port active
|
||||
bool _initted; // Transaction begun
|
||||
|
||||
std::map<int, int> _usingIRQs;
|
||||
|
||||
// DMA
|
||||
int _channelDMA;
|
||||
int _channelSendDMA;
|
||||
@@ -107,6 +102,7 @@ private:
|
||||
int _dmaBytes;
|
||||
uint8_t *_rxFinalBuffer;
|
||||
uint32_t _dummy;
|
||||
SPIHelper _helper;
|
||||
};
|
||||
|
||||
extern SPIClassRP2040 SPI;
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
SPI internal helper utils library for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2025 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <map>
|
||||
#include <hardware/spi.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/structs/iobank0.h>
|
||||
#include <hardware/irq.h>
|
||||
|
||||
/**
|
||||
@brief Helper routined shared by SPI and SoftwareSPI
|
||||
*/
|
||||
class SPIHelper {
|
||||
public:
|
||||
SPIHelper() { /* noop */ }
|
||||
~SPIHelper() { /* noop */ }
|
||||
|
||||
/**
|
||||
@brief Returns the SDK CPOL setting for a given SPISettings configuration
|
||||
|
||||
@param _spis SPISettings to parse
|
||||
@returns SDK-defined CPOL value
|
||||
*/
|
||||
inline spi_cpol_t cpol(const SPISettings &_spis) {
|
||||
switch (_spis.getDataMode()) {
|
||||
case SPI_MODE0:
|
||||
return SPI_CPOL_0;
|
||||
case SPI_MODE1:
|
||||
return SPI_CPOL_0;
|
||||
case SPI_MODE2:
|
||||
return SPI_CPOL_1;
|
||||
case SPI_MODE3:
|
||||
return SPI_CPOL_1;
|
||||
}
|
||||
// Error
|
||||
return SPI_CPOL_0;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Returns the SDK CPHA setting for a given SPISettings configuration
|
||||
|
||||
@param _spis SPISettings to parse
|
||||
@returns SDK-defined CPHA value
|
||||
*/
|
||||
inline spi_cpha_t cpha(const SPISettings &_spis) {
|
||||
switch (_spis.getDataMode()) {
|
||||
case SPI_MODE0:
|
||||
return SPI_CPHA_0;
|
||||
case SPI_MODE1:
|
||||
return SPI_CPHA_1;
|
||||
case SPI_MODE2:
|
||||
return SPI_CPHA_0;
|
||||
case SPI_MODE3:
|
||||
return SPI_CPHA_1;
|
||||
}
|
||||
// Error
|
||||
return SPI_CPHA_0;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Reverses bits in a byte for MSB->LSB swapping
|
||||
|
||||
@param b Input byte
|
||||
@returns Bit-reversed byte
|
||||
*/
|
||||
inline uint8_t reverseByte(uint8_t b) {
|
||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief MSB->LSB bit reversal for 16b quantities
|
||||
|
||||
@param w 16-b input value
|
||||
@returns 16-bit reversed value
|
||||
*/
|
||||
inline uint16_t reverse16Bit(uint16_t w) {
|
||||
return (reverseByte(w & 0xff) << 8) | (reverseByte(w >> 8));
|
||||
}
|
||||
|
||||
#ifdef PICO_RP2350B
|
||||
static constexpr int GPIOIRQREGS = 6;
|
||||
#else
|
||||
static constexpr int GPIOIRQREGS = 4;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@brief Disables any GPIO interrupts registered before an SPI transaction begins
|
||||
*/
|
||||
void maskInterrupts() {
|
||||
noInterrupts(); // Avoid possible race conditions if IRQ comes in while main app is in middle of this
|
||||
// Disable any IRQs that are being used for SPI
|
||||
io_bank0_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ? &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
|
||||
DEBUGSPI("SPI: IRQ masks before = %08x %08x %08x %08x %08x %08x\n", (unsigned)irq_ctrl_base->inte[0],
|
||||
(unsigned)irq_ctrl_base->inte[1], (unsigned)irq_ctrl_base->inte[2], (unsigned)irq_ctrl_base->inte[3],
|
||||
(GPIOIRQREGS > 4) ? (unsigned)irq_ctrl_base->inte[4] : 0, (GPIOIRQREGS > 5) ? (unsigned)irq_ctrl_base->inte[5] : 0);
|
||||
for (auto entry : _usingIRQs) {
|
||||
int gpio = entry.first;
|
||||
|
||||
// There is no gpio_get_irq, so manually twiddle the register
|
||||
io_rw_32 *en_reg = &irq_ctrl_base->inte[gpio / 8];
|
||||
uint32_t val = ((*en_reg) >> (4 * (gpio % 8))) & 0xf;
|
||||
_usingIRQs.insert_or_assign(gpio, val);
|
||||
DEBUGSPI("SPI: GPIO %d = %lu\n", gpio, val);
|
||||
(*en_reg) ^= val << (4 * (gpio % 8));
|
||||
}
|
||||
DEBUGSPI("SPI: IRQ masks after = %08x %08x %08x %08x %08x %08x\n", (unsigned)irq_ctrl_base->inte[0],
|
||||
(unsigned)irq_ctrl_base->inte[1], (unsigned)irq_ctrl_base->inte[2], (unsigned)irq_ctrl_base->inte[3],
|
||||
(GPIOIRQREGS > 4) ? (unsigned)irq_ctrl_base->inte[4] : 0, (GPIOIRQREGS > 5) ? (unsigned)irq_ctrl_base->inte[5] : 0);
|
||||
interrupts();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Restores GPIO interrupts masks after an SPI transaction completes
|
||||
*/
|
||||
void unmaskInterrupts() {
|
||||
noInterrupts(); // Avoid race condition so the GPIO IRQs won't come back until all state is restored
|
||||
DEBUGSPI("SPI::endTransaction()\n");
|
||||
// Re-enable IRQs
|
||||
for (auto entry : _usingIRQs) {
|
||||
int gpio = entry.first;
|
||||
int mode = entry.second;
|
||||
gpio_set_irq_enabled(gpio, mode, true);
|
||||
}
|
||||
io_bank0_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ? &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
|
||||
(void) irq_ctrl_base;
|
||||
DEBUGSPI("SPI: IRQ masks = %08x %08x %08x %08x %08x %08x\n", (unsigned)irq_ctrl_base->inte[0], (unsigned)irq_ctrl_base->inte[1],
|
||||
(unsigned)irq_ctrl_base->inte[2], (unsigned)irq_ctrl_base->inte[3], (GPIOIRQREGS > 4) ? (unsigned)irq_ctrl_base->inte[4] : 0,
|
||||
(GPIOIRQREGS > 5) ? (unsigned)irq_ctrl_base->inte[5] : 0);
|
||||
interrupts();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Adds an interrupt to be masked during SPI transactions
|
||||
|
||||
@param interruptNumber GPIO number to mask off
|
||||
*/
|
||||
void usingInterrupt(int interruptNumber) {
|
||||
_usingIRQs.insert({interruptNumber, 0});
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Removes an interrupt from the to-be-masked list for SPI transactions
|
||||
|
||||
@param interruptNumber GPIO number to remove
|
||||
*/
|
||||
void notUsingInterrupt(int interruptNumber) {
|
||||
_usingIRQs.erase(interruptNumber);
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<int, int> _usingIRQs;
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
SD card basic file example with Software SPI
|
||||
|
||||
This example shows how to create and destroy an SD card file
|
||||
The circuit:
|
||||
SD card attached to Pico as follows:
|
||||
** SCK - GPIO0
|
||||
** CS - GPIO1
|
||||
** MISO (AKA RX) - GPIO2
|
||||
** MOSI (AKA TX) - GPIO3
|
||||
|
||||
created Nov 2010
|
||||
by David A. Mellis
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <SoftwareSPI.h>
|
||||
|
||||
const int _SCK = 0;
|
||||
const int _CS = 1; // Must be SCK+1 for HW CS support
|
||||
const int _MISO = 2;
|
||||
const int _MOSI = 3;
|
||||
SoftwareSPI softSPI(_SCK, _MISO, _MOSI, _CS);
|
||||
|
||||
#include <SD.h>
|
||||
|
||||
File myFile;
|
||||
|
||||
void setup() {
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(115200);
|
||||
|
||||
do {
|
||||
delay(100); // wait for serial port to connect. Needed for native USB port only
|
||||
} while (!Serial);
|
||||
|
||||
if (_CS != _SCK + 1) {
|
||||
Serial.printf("Error, CS (%d) must be defined as SCK (%d) + 1 \n", _CS, _SCK);
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("Initializing SD card...");
|
||||
|
||||
bool sdInitialized = false;
|
||||
sdInitialized = SD.begin(_CS, softSPI);
|
||||
if (!sdInitialized) {
|
||||
Serial.println("initialization failed!");
|
||||
return;
|
||||
}
|
||||
Serial.println("initialization done.");
|
||||
|
||||
if (SD.exists("example.txt")) {
|
||||
Serial.println("example.txt exists.");
|
||||
} else {
|
||||
Serial.println("example.txt doesn't exist.");
|
||||
}
|
||||
|
||||
// open a new file and immediately close it:
|
||||
Serial.println("Creating example.txt...");
|
||||
myFile = SD.open("example.txt", FILE_WRITE);
|
||||
myFile.close();
|
||||
|
||||
// Check to see if the file exists:
|
||||
if (SD.exists("example.txt")) {
|
||||
Serial.println("example.txt exists.");
|
||||
} else {
|
||||
Serial.println("example.txt doesn't exist.");
|
||||
}
|
||||
|
||||
// delete the file:
|
||||
Serial.println("Removing example.txt...");
|
||||
SD.remove("example.txt");
|
||||
|
||||
if (SD.exists("example.txt")) {
|
||||
Serial.println("example.txt exists.");
|
||||
} else {
|
||||
Serial.println("example.txt doesn't exist.");
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// nothing happens after setup finishes.
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
This sketch establishes a TCP connection to a "quote of the day" service.
|
||||
It sends a "hello" message, and then prints received data.
|
||||
*/
|
||||
|
||||
#include <W5500lwIP.h>
|
||||
|
||||
const char* host = "djxmmx.net";
|
||||
const uint16_t port = 17;
|
||||
|
||||
#include <SoftwareSPI.h>
|
||||
const int _SCK = 0; // Any pin allowed
|
||||
const int _CS = 1; // Must be SCK+1 for HW CS support
|
||||
const int _MISO = 28; // Note that MOSI and MISO don't need to be contiguous. Any pins allowed
|
||||
const int _MOSI = 3; // Any pin not used elsewhere
|
||||
const int _INT = 4; // W5500 IRQ line
|
||||
|
||||
SoftwareSPI softSPI(_SCK, _MISO, _MOSI, _CS);
|
||||
|
||||
Wiznet5500lwIP eth(_CS, softSPI, _INT);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(5000);
|
||||
if (_CS != _SCK + 1) {
|
||||
Serial.printf("Error, CS (%d) must be defined as SCK (%d) + 1 \n", _CS, _SCK);
|
||||
return;
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.println("Starting Ethernet port");
|
||||
|
||||
// Start the Ethernet port
|
||||
if (!eth.begin()) {
|
||||
Serial.println("No wired Ethernet hardware detected. Check pinouts, wiring.");
|
||||
while (1) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
while (!eth.connected()) {
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("Ethernet connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(eth.localIP());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static bool wait = false;
|
||||
|
||||
Serial.print("connecting to ");
|
||||
Serial.print(host);
|
||||
Serial.print(':');
|
||||
Serial.println(port);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, port)) {
|
||||
Serial.println("connection failed");
|
||||
delay(5000);
|
||||
return;
|
||||
}
|
||||
|
||||
// This will send a string to the server
|
||||
Serial.println("sending data to server");
|
||||
if (client.connected()) {
|
||||
client.println("hello from RP2040");
|
||||
}
|
||||
|
||||
// wait for data to be available
|
||||
unsigned long timeout = millis();
|
||||
while (client.available() == 0) {
|
||||
if (millis() - timeout > 5000) {
|
||||
Serial.println(">>> Client Timeout !");
|
||||
client.stop();
|
||||
delay(60000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
Serial.println("receiving from remote server");
|
||||
// not testing 'client.connected()' since we do not need to send data here
|
||||
while (client.available()) {
|
||||
char ch = static_cast<char>(client.read());
|
||||
Serial.print(ch);
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
Serial.println();
|
||||
Serial.println("closing connection");
|
||||
client.stop();
|
||||
|
||||
if (wait) {
|
||||
delay(300000); // execute once every 5 minutes, don't flood remote service
|
||||
}
|
||||
wait = true;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map SPI
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
SoftwareSPI KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
begin KEYWORD2
|
||||
end KEYWORD2
|
||||
beginTransaction KEYWORD2
|
||||
endTransaction KEYWORD2
|
||||
SPISettings KEYWORD2
|
||||
transfer KEYWORD2
|
||||
transfer16 KEYWORD2
|
||||
setBitOrder KEYWORD2
|
||||
setDataMode KEYWORD2
|
||||
setClockDivider KEYWORD2
|
||||
setSCK KEYWORD2
|
||||
setMOSI KEYWORD2
|
||||
setMISO KEYWORD2
|
||||
setCS KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
SPI_CLOCK_DIV4 LITERAL1
|
||||
SPI_CLOCK_DIV16 LITERAL1
|
||||
SPI_CLOCK_DIV64 LITERAL1
|
||||
SPI_CLOCK_DIV128 LITERAL1
|
||||
SPI_CLOCK_DIV2 LITERAL1
|
||||
SPI_CLOCK_DIV8 LITERAL1
|
||||
SPI_CLOCK_DIV32 LITERAL1
|
||||
SPI_CLOCK_DIV64 LITERAL1
|
||||
SPI_MODE0 LITERAL1
|
||||
SPI_MODE1 LITERAL1
|
||||
SPI_MODE2 LITERAL1
|
||||
SPI_MODE3 LITERAL1
|
||||
@@ -0,0 +1,10 @@
|
||||
name=SoftwareSPI
|
||||
version=1.0
|
||||
author=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
sentence=Uses the PIO to provide an SPI interface on any pin.
|
||||
paragraph=
|
||||
category=Signal Input/Output
|
||||
url=http://arduino.cc/en/Reference/SPI
|
||||
architectures=rp2040
|
||||
dot_a_linkage=true
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
PIO-based SPI Master library for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2025 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "SoftwareSPI.h"
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/structs/iobank0.h>
|
||||
#include <hardware/irq.h>
|
||||
#include "spi.pio.h"
|
||||
|
||||
#ifdef USE_TINYUSB
|
||||
// For Serial when selecting TinyUSB. Can't include in the core because Arduino IDE
|
||||
// will not link in libraries called from the core. Instead, add the header to all
|
||||
// the standard libraries in the hope it will still catch some user cases where they
|
||||
// use these libraries.
|
||||
// See https://github.com/earlephilhower/arduino-pico/issues/167#issuecomment-848622174
|
||||
#include <Adafruit_TinyUSB.h>
|
||||
#endif
|
||||
|
||||
SoftwareSPI::SoftwareSPI(pin_size_t sck, pin_size_t miso, pin_size_t mosi, pin_size_t cs) {
|
||||
_running = false;
|
||||
_initted = false;
|
||||
_spis = SPISettings(1, LSBFIRST, SPI_MODE0); // Ensure spi_init called by setting current freq to 0
|
||||
_sck = sck;
|
||||
_miso = miso;
|
||||
_mosi = mosi;
|
||||
_cs = cs;
|
||||
}
|
||||
|
||||
void SoftwareSPI::_adjustPIO(int bits) {
|
||||
if (_bits == bits) {
|
||||
return; // Nothing to do!
|
||||
}
|
||||
// Manually set the shiftctl and possibly Y for 8 bits
|
||||
pio_sm_set_enabled(_pio, _sm, false);
|
||||
uint32_t v = _pio->sm[_sm].shiftctrl ;
|
||||
v &= ~0x3e000000 | ~0x01f00000;
|
||||
if (bits == 8) {
|
||||
v |= 0x108 << 20; // Hardcode push/pull threshold 0'b0100001000, there is no simple accessor I can find
|
||||
} else {
|
||||
v |= 0x210 << 20; // 0b'1000010000
|
||||
}
|
||||
_pio->sm[_sm].shiftctrl = v;
|
||||
if (_hwCS) {
|
||||
pio_sm_exec(_pio, _sm, pio_encode_set(pio_x, bits - 2));
|
||||
pio_sm_exec(_pio, _sm, pio_encode_set(pio_y, bits - 2));
|
||||
}
|
||||
pio_sm_set_enabled(_pio, _sm, true);
|
||||
_bits = bits;
|
||||
}
|
||||
|
||||
byte SoftwareSPI::transfer(uint8_t data) {
|
||||
uint8_t ret;
|
||||
if (!_initted) {
|
||||
return 0;
|
||||
}
|
||||
data = (_spis.getBitOrder() == MSBFIRST) ? data : _helper.reverseByte(data);
|
||||
DEBUGSPI("SoftwareSPI::transfer(%02x), cpol=%d, cpha=%d\n", data, _helper.cpol(_spis), _helper.cpha(_spis));
|
||||
_adjustPIO(8);
|
||||
io_rw_8 *txfifo = (io_rw_8 *) &_pio->txf[_sm];
|
||||
io_rw_8 *rxfifo = (io_rw_8 *) &_pio->rxf[_sm];
|
||||
while (pio_sm_is_tx_fifo_full(_pio, _sm)) { /* noop wait */ }
|
||||
*txfifo = data;
|
||||
while (pio_sm_is_rx_fifo_empty(_pio, _sm)) { /* noop wait for in data */ }
|
||||
ret = *rxfifo;
|
||||
ret = (_spis.getBitOrder() == MSBFIRST) ? ret : _helper.reverseByte(ret);
|
||||
DEBUGSPI("SoftwareSPI: read back %02x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t SoftwareSPI::transfer16(uint16_t data) {
|
||||
uint16_t ret;
|
||||
if (!_initted) {
|
||||
return 0;
|
||||
}
|
||||
data = (_spis.getBitOrder() == MSBFIRST) ? data : _helper.reverse16Bit(data);
|
||||
DEBUGSPI("SoftwareSPI::transfer16(%04x), cpol=%d, cpha=%d\n", data, _helper.cpol(_spis), _helper.cpha(_spis));
|
||||
_adjustPIO(16);
|
||||
io_rw_16 *txfifo = (io_rw_16 *) &_pio->txf[_sm];
|
||||
io_rw_16 *rxfifo = (io_rw_16 *) &_pio->rxf[_sm];
|
||||
while (pio_sm_is_tx_fifo_full(_pio, _sm)) { /* noop wait */ }
|
||||
*txfifo = data;
|
||||
while (pio_sm_is_rx_fifo_empty(_pio, _sm)) { /* noop wait for in data */ }
|
||||
ret = *rxfifo;
|
||||
ret = (_spis.getBitOrder() == MSBFIRST) ? ret : _helper.reverse16Bit(ret);
|
||||
DEBUGSPI("SoftwareSPI: read back %04x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SoftwareSPI::transfer(void *buf, size_t count) {
|
||||
transfer(buf, buf, count);
|
||||
}
|
||||
|
||||
void SoftwareSPI::transfer(const void *csrc, void *cdest, size_t count) {
|
||||
if (!_initted) {
|
||||
return;
|
||||
}
|
||||
DEBUGSPI("SoftwareSPI::transfer(%p, %p %d)\n", csrc, cdest, count);
|
||||
const uint8_t *src = reinterpret_cast<const uint8_t *>(csrc);
|
||||
uint8_t *dest = reinterpret_cast<uint8_t *>(cdest);
|
||||
_adjustPIO(8);
|
||||
io_rw_8 *txfifo = (io_rw_8 *) &_pio->txf[_sm];
|
||||
io_rw_8 *rxfifo = (io_rw_8 *) &_pio->rxf[_sm];
|
||||
int txleft = count;
|
||||
int rxleft = count;
|
||||
|
||||
if (_spis.getBitOrder() == !MSBFIRST) {
|
||||
// We're going to hack like heck here and reverse the txbuf into the receive buff (because txbuff is const
|
||||
// Then by construction SPI will send before it received, we can use the rx buff to trans and recv
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
dest[i] = _helper.reverseByte(src[i]);
|
||||
}
|
||||
src = dest; // We'll transmit the flipped data...
|
||||
}
|
||||
|
||||
while (txleft || rxleft) {
|
||||
while (txleft && !pio_sm_is_tx_fifo_full(_pio, _sm)) {
|
||||
*txfifo = *src++;
|
||||
txleft--;
|
||||
}
|
||||
while (rxleft && !pio_sm_is_rx_fifo_empty(_pio, _sm)) {
|
||||
*dest++ = *rxfifo;
|
||||
rxleft--;
|
||||
}
|
||||
}
|
||||
|
||||
if (_spis.getBitOrder() == !MSBFIRST) {
|
||||
// Now we have data in recv but also need to flip it before returning to the app
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
dest[i] = _helper.reverseByte(dest[i]);
|
||||
}
|
||||
}
|
||||
DEBUGSPI("SoftwareSPI::transfer completed\n");
|
||||
}
|
||||
|
||||
void SoftwareSPI::beginTransaction(SPISettings settings) {
|
||||
DEBUGSPI("SoftwareSPI::beginTransaction(clk=%lu, bo=%s)\n", settings.getClockFreq(), (settings.getBitOrder() == MSBFIRST) ? "MSB" : "LSB");
|
||||
if (_initted && settings == _spis) {
|
||||
DEBUGSPI("SoftwareSPI: Reusing existing initted SPI\n");
|
||||
} else {
|
||||
/* Only de-init if the clock changes frequency */
|
||||
if (settings.getClockFreq() != _spis.getClockFreq()) {
|
||||
DEBUGSPI("SoftwareSPI: initting SPI\n");
|
||||
float divider = (float)rp2040.f_cpu() / (float)settings.getClockFreq();
|
||||
divider /= _hwCS ? 4.0f : 4.0f;
|
||||
pio_sm_set_clkdiv(_pio, _sm, divider);
|
||||
DEBUGSPI("SoftwareSPI: divider=%f\n", divider);
|
||||
}
|
||||
_spis = settings;
|
||||
// Note we can only change frequency, not CPOL/CPHA (which would be physically not too useful anyway)
|
||||
_initted = true;
|
||||
}
|
||||
_helper.maskInterrupts();
|
||||
}
|
||||
|
||||
void SoftwareSPI::endTransaction(void) {
|
||||
DEBUGSPI("SoftwareSPI::endTransaction()\n");
|
||||
_helper.unmaskInterrupts();
|
||||
}
|
||||
|
||||
bool SoftwareSPI::setCS(pin_size_t pin) {
|
||||
if (pin < 1) {
|
||||
// CS is SCK+1, so has to be at least GPIO1
|
||||
return false;
|
||||
}
|
||||
if (!_running || (_cs == pin)) {
|
||||
_cs = pin;
|
||||
_sck = _cs - 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoftwareSPI::setSCK(pin_size_t pin) {
|
||||
if (!_running || (_sck == pin)) {
|
||||
_sck = pin;
|
||||
_cs = pin + 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoftwareSPI::setMISO(pin_size_t pin) {
|
||||
if (!_running || (_miso == pin)) {
|
||||
_miso = pin;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoftwareSPI::setMOSI(pin_size_t pin) {
|
||||
if (!_running || (_mosi == pin)) {
|
||||
_mosi = pin;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SoftwareSPI::begin(bool hwCS) {
|
||||
DEBUGSPI("SoftwareSPI::begin(%d), rx=%d, cs=%d, sck=%d, tx=%d\n", hwCS, _miso, _cs, _sck, _mosi);
|
||||
float divider = (float)rp2040.f_cpu() / (float)_spis.getClockFreq();
|
||||
DEBUGSPI("SoftwareSPI: divider=%f\n", divider);
|
||||
if (!hwCS) {
|
||||
_spi = new PIOProgram(_helper.cpha(_spis) == SPI_CPHA_0 ? &spi_cpha0_program : &spi_cpha1_program);
|
||||
if (!_spi->prepare(&_pio, &_sm, &_off, _sck, 1)) {
|
||||
_running = false;
|
||||
delete _spi;
|
||||
_spi = nullptr;
|
||||
return;
|
||||
}
|
||||
pio_spi_init(_pio, _sm, _off, 8, divider / 4.0f, _helper.cpha(_spis), _helper.cpol(_spis), _sck, _mosi, _miso);
|
||||
} else {
|
||||
_spi = new PIOProgram(_helper.cpha(_spis) == SPI_CPHA_0 ? &spi_cpha0_cs_program : &spi_cpha1_cs_program);
|
||||
if (!_spi->prepare(&_pio, &_sm, &_off, _sck, 2)) {
|
||||
_running = false;
|
||||
delete _spi;
|
||||
_spi = nullptr;
|
||||
return;
|
||||
}
|
||||
pio_spi_cs_init(_pio, _sm, _off, 8, divider / 4.0f, _helper.cpha(_spis), _helper.cpol(_spis), _sck, _mosi, _miso);
|
||||
}
|
||||
_hwCS = hwCS;
|
||||
_bits = 8;
|
||||
// Give a default config in case user doesn't use beginTransaction
|
||||
beginTransaction(_spis);
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
void SoftwareSPI::end() {
|
||||
DEBUGSPI("SoftwareSPI::end()\n");
|
||||
if (_initted) {
|
||||
DEBUGSPI("SoftwareSPI: deinitting currently active SPI\n");
|
||||
_initted = false;
|
||||
pio_sm_set_enabled(_pio, _sm, false);
|
||||
// TODO - We don't have a good PIOProgram reclamation method so this will possibly leak an SM
|
||||
}
|
||||
_spis = SPISettings(0, LSBFIRST, SPI_MODE0);
|
||||
}
|
||||
|
||||
void SoftwareSPI::setBitOrder(BitOrder order) {
|
||||
_spis = SPISettings(_spis.getClockFreq(), order, _spis.getDataMode());
|
||||
beginTransaction(_spis);
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
void SoftwareSPI::setDataMode(uint8_t uc_mode) {
|
||||
_spis = SPISettings(_spis.getClockFreq(), _spis.getBitOrder(), uc_mode);
|
||||
beginTransaction(_spis);
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
void SoftwareSPI::setClockDivider(uint8_t uc_div) {
|
||||
(void) uc_div; // no-op
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
PIO-based SPI Master library for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2025 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h> // For SPIHelper
|
||||
#include <api/HardwareSPI.h>
|
||||
#include <hardware/spi.h>
|
||||
|
||||
class SoftwareSPI : public arduino::HardwareSPI {
|
||||
public:
|
||||
/**
|
||||
@brief Create a PIO-based SPI instance
|
||||
|
||||
@param [in] sck SCK GPIO
|
||||
@param [in] miso MISO GPIO
|
||||
@param [in] mosi MOSI GPIO
|
||||
@param [in] cs Optional CS pin for HW CS, must be SCK+1
|
||||
*/
|
||||
SoftwareSPI(pin_size_t sck, pin_size_t miso, pin_size_t mosi, pin_size_t cs = -1);
|
||||
|
||||
// Send or receive 8- or 16-bit data. Returns read back value
|
||||
byte transfer(uint8_t data) override;
|
||||
uint16_t transfer16(uint16_t data) override;
|
||||
|
||||
// Sends buffer in 8 bit chunks. Overwrites buffer with read data
|
||||
void transfer(void *buf, size_t count) override;
|
||||
|
||||
// Sends one buffer and receives into another, much faster! can set rx or txbuf to nullptr
|
||||
void transfer(const void *txbuf, void *rxbuf, size_t count) override;
|
||||
|
||||
// Call before/after every complete transaction
|
||||
void beginTransaction(SPISettings settings) override;
|
||||
void endTransaction(void) override;
|
||||
|
||||
// Assign pins, call before begin()
|
||||
bool setMISO(pin_size_t pin);
|
||||
inline bool setRX(pin_size_t pin) {
|
||||
return setMISO(pin);
|
||||
}
|
||||
bool setCS(pin_size_t pin);
|
||||
bool setSCK(pin_size_t pin);
|
||||
bool setMOSI(pin_size_t pin);
|
||||
inline bool setTX(pin_size_t pin) {
|
||||
return setMOSI(pin);
|
||||
}
|
||||
|
||||
// Call once to init/deinit SPI class, select pins, etc.
|
||||
virtual void begin() override {
|
||||
begin(false);
|
||||
}
|
||||
void begin(bool hwCS);
|
||||
void end() override;
|
||||
|
||||
// Deprecated - do not use!
|
||||
void setBitOrder(BitOrder order) __attribute__((deprecated));
|
||||
void setDataMode(uint8_t uc_mode) __attribute__((deprecated));
|
||||
void setClockDivider(uint8_t uc_div) __attribute__((deprecated));
|
||||
|
||||
// List of GPIO IRQs to disable during a transaction
|
||||
virtual void usingInterrupt(int interruptNumber) override {
|
||||
_helper.usingInterrupt(interruptNumber);
|
||||
}
|
||||
virtual void notUsingInterrupt(int interruptNumber) override {
|
||||
_helper.notUsingInterrupt(interruptNumber);
|
||||
}
|
||||
virtual void attachInterrupt() override { /* noop */ }
|
||||
virtual void detachInterrupt() override { /* noop */ }
|
||||
|
||||
private:
|
||||
void _adjustPIO(int bits);
|
||||
|
||||
PIOProgram *_spi;
|
||||
PIO _pio;
|
||||
int _sm;
|
||||
int _off;
|
||||
|
||||
SPISettings _spis;
|
||||
pin_size_t _sck, _miso, _mosi, _cs;
|
||||
bool _hwCS;
|
||||
bool _running; // SPI port active
|
||||
bool _initted; // Transaction begun
|
||||
int _bits;
|
||||
SPIHelper _helper;
|
||||
};
|
||||
@@ -0,0 +1,168 @@
|
||||
;
|
||||
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
;
|
||||
|
||||
; These programs implement full-duplex SPI, with a SCK period of 4 clock
|
||||
; cycles. A different program is provided for each value of CPHA, and CPOL is
|
||||
; achieved using the hardware GPIO inversion available in the IO controls.
|
||||
;
|
||||
; Transmit-only SPI can go twice as fast -- see the ST7789 example!
|
||||
.pio_version 0 // only requires PIO version 0
|
||||
|
||||
.program spi_cpha0
|
||||
.side_set 1
|
||||
|
||||
; Pin assignments:
|
||||
; - SCK is side-set pin 0
|
||||
; - MOSI is OUT pin 0
|
||||
; - MISO is IN pin 0
|
||||
;
|
||||
; Autopush and autopull must be enabled, and the serial frame size is set by
|
||||
; configuring the push/pull threshold. Shift left/right is fine, but you must
|
||||
; justify the data yourself. This is done most conveniently for frame sizes of
|
||||
; 8 or 16 bits by using the narrow store replication and narrow load byte
|
||||
; picking behaviour of RP2040's IO fabric.
|
||||
|
||||
; Clock phase = 0: data is captured on the leading edge of each SCK pulse, and
|
||||
; transitions on the trailing edge, or some time before the first leading edge.
|
||||
|
||||
out pins, 1 side 0 [1] ; Stall here on empty (sideset proceeds even if
|
||||
in pins, 1 side 1 [1] ; instruction stalls, so we stall with SCK low)
|
||||
|
||||
.program spi_cpha1
|
||||
.side_set 1
|
||||
|
||||
; Clock phase = 1: data transitions on the leading edge of each SCK pulse, and
|
||||
; is captured on the trailing edge.
|
||||
|
||||
out x, 1 side 0 ; Stall here on empty (keep SCK deasserted)
|
||||
mov pins, x side 1 [1] ; Output data, assert SCK (mov pins uses OUT mapping)
|
||||
in pins, 1 side 0 ; Input data, deassert SCK
|
||||
|
||||
% c-sdk {
|
||||
#include "hardware/gpio.h"
|
||||
static inline void pio_spi_init(PIO pio, uint sm, uint prog_offs, uint n_bits,
|
||||
float clkdiv, bool cpha, bool cpol, uint pin_sck, uint pin_mosi, uint pin_miso) {
|
||||
pio_sm_config c = cpha ? spi_cpha1_program_get_default_config(prog_offs) : spi_cpha0_program_get_default_config(prog_offs);
|
||||
sm_config_set_out_pins(&c, pin_mosi, 1);
|
||||
sm_config_set_in_pins(&c, pin_miso);
|
||||
sm_config_set_sideset_pins(&c, pin_sck);
|
||||
// Only support MSB-first in this example code (shift to left, auto push/pull, threshold=nbits)
|
||||
sm_config_set_out_shift(&c, false, true, n_bits);
|
||||
sm_config_set_in_shift(&c, false, true, n_bits);
|
||||
sm_config_set_clkdiv(&c, clkdiv);
|
||||
|
||||
// MOSI, SCK output are low, MISO is input
|
||||
pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_sck) | (1u << pin_mosi));
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, (1u << pin_sck) | (1u << pin_mosi), (1u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso));
|
||||
pio_gpio_init(pio, pin_mosi);
|
||||
pio_gpio_init(pio, pin_miso);
|
||||
pio_gpio_init(pio, pin_sck);
|
||||
|
||||
// The pin muxes can be configured to invert the output (among other things
|
||||
// and this is a cheesy way to get CPOL=1
|
||||
gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL);
|
||||
// SPI is synchronous, so bypass input synchroniser to reduce input delay.
|
||||
hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso);
|
||||
|
||||
pio_sm_init(pio, sm, prog_offs, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
%}
|
||||
|
||||
; SPI with Chip Select
|
||||
; -----------------------------------------------------------------------------
|
||||
;
|
||||
; For your amusement, here are some SPI programs with an automatic chip select
|
||||
; (asserted once data appears in TX FIFO, deasserts when FIFO bottoms out, has
|
||||
; a nice front/back porch).
|
||||
;
|
||||
; The number of bits per FIFO entry is configured via the Y register
|
||||
; and the autopush/pull threshold. From 2 to 32 bits.
|
||||
;
|
||||
; Pin assignments:
|
||||
; - SCK is side-set bit 0
|
||||
; - CSn is side-set bit 1
|
||||
; - MOSI is OUT bit 0 (host-to-device)
|
||||
; - MISO is IN bit 0 (device-to-host)
|
||||
;
|
||||
; This program only supports one chip select -- use GPIO if more are needed
|
||||
;
|
||||
; Provide a variation for each possibility of CPHA; for CPOL we can just
|
||||
; invert SCK in the IO muxing controls (downstream from PIO)
|
||||
|
||||
|
||||
; CPHA=0: data is captured on the leading edge of each SCK pulse (including
|
||||
; the first pulse), and transitions on the trailing edge
|
||||
|
||||
.program spi_cpha0_cs
|
||||
.side_set 2
|
||||
|
||||
.wrap_target
|
||||
bitloop:
|
||||
out pins, 1 side 0x0 [1]
|
||||
in pins, 1 side 0x1
|
||||
jmp x-- bitloop side 0x1
|
||||
|
||||
out pins, 1 side 0x0
|
||||
mov x, y side 0x0 ; Reload bit counter from Y
|
||||
in pins, 1 side 0x1
|
||||
jmp !osre bitloop side 0x1 ; Fall-through if TXF empties
|
||||
|
||||
nop side 0x0 [1] ; CSn back porch
|
||||
public entry_point: ; Must set X,Y to n-2 before starting!
|
||||
pull ifempty side 0x2 [1] ; Block with CSn high (minimum 2 cycles)
|
||||
.wrap ; Note ifempty to avoid time-of-check race
|
||||
|
||||
; CPHA=1: data transitions on the leading edge of each SCK pulse, and is
|
||||
; captured on the trailing edge
|
||||
|
||||
.program spi_cpha1_cs
|
||||
.side_set 2
|
||||
|
||||
.wrap_target
|
||||
bitloop:
|
||||
out pins, 1 side 0x1 [1]
|
||||
in pins, 1 side 0x0
|
||||
jmp x-- bitloop side 0x0
|
||||
|
||||
out pins, 1 side 0x1
|
||||
mov x, y side 0x1
|
||||
in pins, 1 side 0x0
|
||||
jmp !osre bitloop side 0x0
|
||||
|
||||
public entry_point: ; Must set X,Y to n-2 before starting!
|
||||
pull ifempty side 0x2 [1] ; Block with CSn high (minimum 2 cycles)
|
||||
nop side 0x0 [1]; CSn front porch
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
#include "hardware/gpio.h"
|
||||
static inline void pio_spi_cs_init(PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, bool cpha, bool cpol,
|
||||
uint pin_sck, uint pin_mosi, uint pin_miso) {
|
||||
pio_sm_config c = cpha ? spi_cpha1_cs_program_get_default_config(prog_offs) : spi_cpha0_cs_program_get_default_config(prog_offs);
|
||||
sm_config_set_out_pins(&c, pin_mosi, 1);
|
||||
sm_config_set_in_pins(&c, pin_miso);
|
||||
sm_config_set_sideset_pins(&c, pin_sck);
|
||||
sm_config_set_out_shift(&c, false, true, n_bits);
|
||||
sm_config_set_in_shift(&c, false, true, n_bits);
|
||||
sm_config_set_clkdiv(&c, clkdiv);
|
||||
|
||||
pio_sm_set_pins_with_mask(pio, sm, (2u << pin_sck), (3u << pin_sck) | (1u << pin_mosi));
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, (3u << pin_sck) | (1u << pin_mosi), (3u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso));
|
||||
pio_gpio_init(pio, pin_mosi);
|
||||
pio_gpio_init(pio, pin_miso);
|
||||
pio_gpio_init(pio, pin_sck);
|
||||
pio_gpio_init(pio, pin_sck + 1);
|
||||
gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL);
|
||||
hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso);
|
||||
|
||||
uint entry_point = prog_offs + (cpha ? spi_cpha1_cs_offset_entry_point : spi_cpha0_cs_offset_entry_point);
|
||||
pio_sm_init(pio, sm, entry_point, &c);
|
||||
pio_sm_exec(pio, sm, pio_encode_set(pio_x, n_bits - 2));
|
||||
pio_sm_exec(pio, sm, pio_encode_set(pio_y, n_bits - 2));
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
%}
|
||||
@@ -0,0 +1,218 @@
|
||||
// -------------------------------------------------- //
|
||||
// This file is autogenerated by pioasm; do not edit! //
|
||||
// -------------------------------------------------- //
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
#include "hardware/pio.h"
|
||||
#endif
|
||||
|
||||
// --------- //
|
||||
// spi_cpha0 //
|
||||
// --------- //
|
||||
|
||||
#define spi_cpha0_wrap_target 0
|
||||
#define spi_cpha0_wrap 1
|
||||
#define spi_cpha0_pio_version 0
|
||||
|
||||
static const uint16_t spi_cpha0_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x6101, // 0: out pins, 1 side 0 [1]
|
||||
0x5101, // 1: in pins, 1 side 1 [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program spi_cpha0_program = {
|
||||
.instructions = spi_cpha0_program_instructions,
|
||||
.length = 2,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config spi_cpha0_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + spi_cpha0_wrap_target, offset + spi_cpha0_wrap);
|
||||
sm_config_set_sideset(&c, 1, false, false);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// --------- //
|
||||
// spi_cpha1 //
|
||||
// --------- //
|
||||
|
||||
#define spi_cpha1_wrap_target 0
|
||||
#define spi_cpha1_wrap 2
|
||||
#define spi_cpha1_pio_version 0
|
||||
|
||||
static const uint16_t spi_cpha1_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x6021, // 0: out x, 1 side 0
|
||||
0xb101, // 1: mov pins, x side 1 [1]
|
||||
0x4001, // 2: in pins, 1 side 0
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program spi_cpha1_program = {
|
||||
.instructions = spi_cpha1_program_instructions,
|
||||
.length = 3,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config spi_cpha1_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + spi_cpha1_wrap_target, offset + spi_cpha1_wrap);
|
||||
sm_config_set_sideset(&c, 1, false, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
static inline void pio_spi_init(PIO pio, uint sm, uint prog_offs, uint n_bits,
|
||||
float clkdiv, bool cpha, bool cpol, uint pin_sck, uint pin_mosi, uint pin_miso) {
|
||||
pio_sm_config c = cpha ? spi_cpha1_program_get_default_config(prog_offs) : spi_cpha0_program_get_default_config(prog_offs);
|
||||
sm_config_set_out_pins(&c, pin_mosi, 1);
|
||||
sm_config_set_in_pins(&c, pin_miso);
|
||||
sm_config_set_sideset_pins(&c, pin_sck);
|
||||
// Only support MSB-first in this example code (shift to left, auto push/pull, threshold=nbits)
|
||||
sm_config_set_out_shift(&c, false, true, n_bits);
|
||||
sm_config_set_in_shift(&c, false, true, n_bits);
|
||||
sm_config_set_clkdiv(&c, clkdiv);
|
||||
// MOSI, SCK output are low, MISO is input
|
||||
pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_sck) | (1u << pin_mosi));
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, (1u << pin_sck) | (1u << pin_mosi), (1u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso));
|
||||
pio_gpio_init(pio, pin_mosi);
|
||||
pio_gpio_init(pio, pin_miso);
|
||||
pio_gpio_init(pio, pin_sck);
|
||||
// The pin muxes can be configured to invert the output (among other things
|
||||
// and this is a cheesy way to get CPOL=1
|
||||
gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL);
|
||||
// SPI is synchronous, so bypass input synchroniser to reduce input delay.
|
||||
hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso);
|
||||
pio_sm_init(pio, sm, prog_offs, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ------------ //
|
||||
// spi_cpha0_cs //
|
||||
// ------------ //
|
||||
|
||||
#define spi_cpha0_cs_wrap_target 0
|
||||
#define spi_cpha0_cs_wrap 8
|
||||
#define spi_cpha0_cs_pio_version 0
|
||||
|
||||
#define spi_cpha0_cs_offset_entry_point 8u
|
||||
|
||||
static const uint16_t spi_cpha0_cs_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x6101, // 0: out pins, 1 side 0 [1]
|
||||
0x4801, // 1: in pins, 1 side 1
|
||||
0x0840, // 2: jmp x--, 0 side 1
|
||||
0x6001, // 3: out pins, 1 side 0
|
||||
0xa022, // 4: mov x, y side 0
|
||||
0x4801, // 5: in pins, 1 side 1
|
||||
0x08e0, // 6: jmp !osre, 0 side 1
|
||||
0xa142, // 7: nop side 0 [1]
|
||||
0x91e0, // 8: pull ifempty block side 2 [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program spi_cpha0_cs_program = {
|
||||
.instructions = spi_cpha0_cs_program_instructions,
|
||||
.length = 9,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config spi_cpha0_cs_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + spi_cpha0_cs_wrap_target, offset + spi_cpha0_cs_wrap);
|
||||
sm_config_set_sideset(&c, 2, false, false);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------ //
|
||||
// spi_cpha1_cs //
|
||||
// ------------ //
|
||||
|
||||
#define spi_cpha1_cs_wrap_target 0
|
||||
#define spi_cpha1_cs_wrap 8
|
||||
#define spi_cpha1_cs_pio_version 0
|
||||
|
||||
#define spi_cpha1_cs_offset_entry_point 7u
|
||||
|
||||
static const uint16_t spi_cpha1_cs_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x6901, // 0: out pins, 1 side 1 [1]
|
||||
0x4001, // 1: in pins, 1 side 0
|
||||
0x0040, // 2: jmp x--, 0 side 0
|
||||
0x6801, // 3: out pins, 1 side 1
|
||||
0xa822, // 4: mov x, y side 1
|
||||
0x4001, // 5: in pins, 1 side 0
|
||||
0x00e0, // 6: jmp !osre, 0 side 0
|
||||
0x91e0, // 7: pull ifempty block side 2 [1]
|
||||
0xa142, // 8: nop side 0 [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program spi_cpha1_cs_program = {
|
||||
.instructions = spi_cpha1_cs_program_instructions,
|
||||
.length = 9,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config spi_cpha1_cs_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + spi_cpha1_cs_wrap_target, offset + spi_cpha1_cs_wrap);
|
||||
sm_config_set_sideset(&c, 2, false, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
static inline void pio_spi_cs_init(PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, bool cpha, bool cpol,
|
||||
uint pin_sck, uint pin_mosi, uint pin_miso) {
|
||||
pio_sm_config c = cpha ? spi_cpha1_cs_program_get_default_config(prog_offs) : spi_cpha0_cs_program_get_default_config(prog_offs);
|
||||
sm_config_set_out_pins(&c, pin_mosi, 1);
|
||||
sm_config_set_in_pins(&c, pin_miso);
|
||||
sm_config_set_sideset_pins(&c, pin_sck);
|
||||
sm_config_set_out_shift(&c, false, true, n_bits);
|
||||
sm_config_set_in_shift(&c, false, true, n_bits);
|
||||
sm_config_set_clkdiv(&c, clkdiv);
|
||||
pio_sm_set_pins_with_mask(pio, sm, (2u << pin_sck), (3u << pin_sck) | (1u << pin_mosi));
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, (3u << pin_sck) | (1u << pin_mosi), (3u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso));
|
||||
pio_gpio_init(pio, pin_mosi);
|
||||
pio_gpio_init(pio, pin_miso);
|
||||
pio_gpio_init(pio, pin_sck);
|
||||
pio_gpio_init(pio, pin_sck + 1);
|
||||
gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL);
|
||||
hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso);
|
||||
uint entry_point = prog_offs + (cpha ? spi_cpha1_cs_offset_entry_point : spi_cpha0_cs_offset_entry_point);
|
||||
pio_sm_init(pio, sm, entry_point, &c);
|
||||
pio_sm_exec(pio, sm, pio_encode_set(pio_x, n_bits - 2));
|
||||
pio_sm_exec(pio, sm, pio_encode_set(pio_y, n_bits - 2));
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -97,12 +97,18 @@ bool UpdaterClass::begin(size_t size, int command) {
|
||||
_md5 = MD5Builder();
|
||||
|
||||
if (command == U_FLASH) {
|
||||
// Basic sanity, if it's larger than entire FS then it can't possibly succeed
|
||||
if (&_FS_start + size > &_FS_end) {
|
||||
_setError(UPDATE_ERROR_SPACE);
|
||||
return false;
|
||||
}
|
||||
LittleFS.begin();
|
||||
_fp = LittleFS.open("firmware.bin", "w+");
|
||||
if (!_fp) {
|
||||
#ifdef DEBUG_UPDATER
|
||||
DEBUG_UPDATER.println(F("[begin] unable to create file"));
|
||||
#endif
|
||||
_setError(UPDATE_ERROR_SPACE);
|
||||
return false;
|
||||
}
|
||||
updateStartAddress = 0; // Not used
|
||||
@@ -288,6 +294,7 @@ bool UpdaterClass::end(bool evenIfRemaining) {
|
||||
bool UpdaterClass::_writeBuffer() {
|
||||
if (_command == U_FLASH) {
|
||||
if (_bufferLen != _fp.write(_buffer, _bufferLen)) {
|
||||
_setError(UPDATE_ERROR_SPACE);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -216,9 +216,9 @@ void handleFileList() {
|
||||
// as an HTTP chunk
|
||||
Serial.println(output);
|
||||
server.sendContent(output);
|
||||
output = ',';
|
||||
output = ",";
|
||||
} else {
|
||||
output = '[';
|
||||
output = "[";
|
||||
}
|
||||
|
||||
output += "{\"type\":\"";
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Udp.h>
|
||||
#include <include/slist.h>
|
||||
|
||||
|
||||
@@ -489,6 +489,14 @@ void TwoWire::flush(void) {
|
||||
// data transfer.
|
||||
}
|
||||
|
||||
bool TwoWire::busIdle() {
|
||||
// Check hardware status
|
||||
uint32_t status = _i2c->hw->status;
|
||||
bool tfe = (status & I2C_IC_STATUS_TFE_BITS);
|
||||
bool mast = (status & I2C_IC_STATUS_MST_ACTIVITY_BITS);
|
||||
return (tfe && !mast);
|
||||
}
|
||||
|
||||
// DMA/asynchronous transfers. Do not combime with synchronous runs or bad stuff will happen
|
||||
// All buffers must be valid for entire DMA and not touched until `finishedAsync()` returns true.
|
||||
bool TwoWire::writeReadAsync(uint8_t address, const void *wbuffer, size_t wbytes, const void *rbuffer, size_t rbytes, bool sendStop) {
|
||||
@@ -496,6 +504,10 @@ bool TwoWire::writeReadAsync(uint8_t address, const void *wbuffer, size_t wbytes
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!busIdle()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_dmaRunning) {
|
||||
beginAsync();
|
||||
if (!_dmaRunning) {
|
||||
@@ -507,7 +519,7 @@ bool TwoWire::writeReadAsync(uint8_t address, const void *wbuffer, size_t wbytes
|
||||
abortAsync();
|
||||
|
||||
// Create or enlarge dma command buffer, we need one entry for every i2c byte we want to write/read
|
||||
const size_t bufLen = (wbytes + rbytes) * 2;
|
||||
const size_t bufLen = (wbytes + rbytes) * sizeof(uint16_t);
|
||||
if (_dmaSendBufferLen < bufLen) {
|
||||
if (_dmaSendBuffer) {
|
||||
free(_dmaSendBuffer);
|
||||
@@ -518,6 +530,7 @@ bool TwoWire::writeReadAsync(uint8_t address, const void *wbuffer, size_t wbytes
|
||||
if (!_dmaSendBuffer) {
|
||||
return false;
|
||||
}
|
||||
_dmaSendBufferLen = bufLen;
|
||||
}
|
||||
|
||||
// Fill the dma command buffer
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
bool writeReadAsync(uint8_t address, const void *wbuffer, size_t wbytes, const void *rbuffer, size_t rbytes, bool sendStop = true);
|
||||
bool writeAsync(uint8_t address, const void *buffer, size_t bytes, bool sendStop = true);
|
||||
bool readAsync(uint8_t address, void *buffer, size_t bytes, bool sendStop = true);
|
||||
bool busIdle();
|
||||
bool finishedAsync(); // Call to check if the async operations is completed and the buffer can be reused/read
|
||||
void abortAsync(); // Cancel an outstanding async I2C operation
|
||||
void onFinishedAsync(void(*function)(void)); // Set callback for async operation
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "framework-arduinopico",
|
||||
"version": "1.40402.0",
|
||||
"version": "1.40404.0",
|
||||
"description": "Arduino Wiring-based Framework (RPi Pico RP2040, RP2350)",
|
||||
"keywords": [
|
||||
"framework",
|
||||
|
||||
@@ -86,6 +86,9 @@
|
||||
{
|
||||
"name": "Adafruit Floppsy"
|
||||
},
|
||||
{
|
||||
"name": "Adafruit Metro RP2350"
|
||||
},
|
||||
{
|
||||
"name": "Amken BunnyBoard"
|
||||
},
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
|
||||
|
||||
name=Raspberry Pi RP2040/RP2350 Boards
|
||||
version=4.4.2
|
||||
version=4.4.4
|
||||
|
||||
# Required discoveries and monitors
|
||||
# ---------------------------------
|
||||
@@ -114,7 +114,7 @@ build.espwifitype=
|
||||
build.debugscript=picoprobe_cmsis_dap.tcl
|
||||
build.picodebugflags=
|
||||
build.variantdefines=
|
||||
build.sdfatdefines=-DFILE_COPY_CONSTRUCTOR_SELECT=FILE_COPY_CONSTRUCTOR_PUBLIC -DUSE_UTF8_LONG_NAMES=1 -DSDFAT_FILE_TYPE=3 -DDISABLE_FS_H_WARNING=1
|
||||
build.sdfatdefines=-DFILE_COPY_CONSTRUCTOR_SELECT=FILE_COPY_CONSTRUCTOR_PUBLIC -DUSE_UTF8_LONG_NAMES=1 -DDISABLE_FS_H_WARNING=1
|
||||
|
||||
# Allow Pico boards to be auto-discovered by the IDE
|
||||
#discovery.rp2040.pattern={runtime.tools.pqt-python3.path}/python3 -I "{runtime.platform.path}/tools/pluggable_discovery.py"
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S ./libraries/SingleF
|
||||
./libraries/SPISlave ./libraries/lwIP_ESPHost ./libraries/FatFS\
|
||||
./libraries/FatFSUSB ./libraries/BluetoothAudio ./libraries/BluetoothHCI \
|
||||
./libraries/BluetoothHIDMaster ./libraries/NetBIOS ./libraries/Ticker \
|
||||
./libraries/VFS ./libraries/rp2350 ./libraries/SimpleMDNS ; do
|
||||
./libraries/VFS ./libraries/rp2350 ./libraries/SimpleMDNS ./libraries/SoftwareSPI ; do
|
||||
find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" \) -a \! -path '*api*' -exec astyle --suffix=none --options=./tests/astyle_core.conf \{\} \;
|
||||
find $dir -type f -name "*.ino" -exec astyle --suffix=none --options=./tests/astyle_examples.conf \{\} \;
|
||||
done
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"earlephilhower": {
|
||||
"boot2_source": "none.S",
|
||||
"usb_vid": "0x239A",
|
||||
"usb_pid": "0x814D"
|
||||
}
|
||||
},
|
||||
"core": "earlephilhower",
|
||||
"cpu": "cortex-m33",
|
||||
"extra_flags": "-DARDUINO_ADAFRUIT_METRO_RP2350 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250 ",
|
||||
"f_cpu": "150000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x2E8A",
|
||||
"0x00C0"
|
||||
],
|
||||
[
|
||||
"0x239A",
|
||||
"0x814D"
|
||||
]
|
||||
],
|
||||
"mcu": "rp2350",
|
||||
"variant": "adafruit_metro_rp2350"
|
||||
},
|
||||
"debug": {
|
||||
"jlink_device": "RP2350_0",
|
||||
"openocd_target": "rp2350.cfg",
|
||||
"svd_path": "rp2350.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "Metro RP2350",
|
||||
"upload": {
|
||||
"maximum_ram_size": 524288,
|
||||
"maximum_size": 16777216,
|
||||
"require_upload_port": true,
|
||||
"native_usb": true,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": false,
|
||||
"protocol": "picotool",
|
||||
"protocols": [
|
||||
"blackmagic",
|
||||
"cmsis-dap",
|
||||
"jlink",
|
||||
"raspberrypi-swd",
|
||||
"picotool",
|
||||
"picoprobe"
|
||||
]
|
||||
},
|
||||
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
|
||||
"vendor": "Adafruit"
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
"name": "XIAO RP2350",
|
||||
"upload": {
|
||||
"maximum_ram_size": 524288,
|
||||
"maximum_size": 16777216,
|
||||
"maximum_size": 2097152,
|
||||
"require_upload_port": true,
|
||||
"native_usb": true,
|
||||
"use_1200bps_touch": true,
|
||||
@@ -48,8 +48,7 @@
|
||||
"raspberrypi-swd",
|
||||
"picotool",
|
||||
"picoprobe"
|
||||
],
|
||||
"psram_length": 8388608
|
||||
]
|
||||
},
|
||||
"url": "https://www.seeedstudio.com/Seeed-XIAO-RP2350-p-5944.html",
|
||||
"vendor": "Seeed"
|
||||
|
||||
+2
-2
@@ -516,7 +516,7 @@ MakeBoard("adafruit_macropad2040", "rp2040", "Adafruit", "MacroPad RP2040", "0x2
|
||||
MakeBoard("adafruit_kb2040", "rp2040", "Adafruit", "KB2040", "0x239a", "0x8105", 250, "ADAFRUIT_KB2040_RP2040", 8, 0, "boot2_w25q080_2_padded_checksum")
|
||||
MakeBoard("adafruit_feather_rp2350_hstx", "rp2350", "Adafruit", "Feather RP2350 HSTX", "0x239a", "0x814f", 250, "ADAFRUIT_FEATHER_RP2350_HSTX", 8, 0, "none")
|
||||
MakeBoard("adafruit_floppsy", "rp2040", "Adafruit", "Floppsy", "0x239a", "0x8151", 250, "ADAFRUIT_FLOPPSY_RP2040", 16, 0, "boot2_w25q080_2_padded_checksum")
|
||||
|
||||
MakeBoard("adafruit_metro_rp2350", "rp2350", "Adafruit", "Metro RP2350", "0x239a", "0x814d", 250, "ADAFRUIT_METRO_RP2350", 16, 0, "none")
|
||||
# Amken
|
||||
MakeBoard("amken_bunny", "rp2040","Amken","BunnyBoard","0x2770",["0x7303"],250,"AMKEN_BB",128,0,"boot2_w25q128jvxq_4_padded_checksum","","https://www.amken3d.com")
|
||||
MakeBoard("amken_revelop", "rp2040","Amken","Revelop","0x2770",["0x7304"],250,"AMKEN_REVELOP",32,0,"boot2_W25Q32JVxQ_4_padded_checksum","","https://www.amken3d.com")
|
||||
@@ -656,7 +656,7 @@ MakeBoard("sparkfun_iotnode_lorawanrp2350", "rp2350", "SparkFun", "IoT Node LoRa
|
||||
# Seeed
|
||||
MakeBoard("seeed_indicator_rp2040", "rp2040", "Seeed", "INDICATOR RP2040", "0x2886", "0x0050", 250, "SEEED_INDICATOR_RP2040", 2, 0, "boot2_w25q080_2_padded_checksum")
|
||||
MakeBoard("seeed_xiao_rp2040", "rp2040", "Seeed", "XIAO RP2040", "0x2e8a", "0x000a", 250, "SEEED_XIAO_RP2040", 2, 0, "boot2_w25q080_2_padded_checksum")
|
||||
MakeBoard("seeed_xiao_rp2350", "rp2350", "Seeed", "XIAO RP2350", "0x2886", "0x0058", 250, "SEEED_XIAO_RP2350", 16, 8, "none", None, "https://www.seeedstudio.com/Seeed-XIAO-RP2350-p-5944.html")
|
||||
MakeBoard("seeed_xiao_rp2350", "rp2350", "Seeed", "XIAO RP2350", "0x2886", "0x0058", 250, "SEEED_XIAO_RP2350", 2, 0, "none", None, "https://www.seeedstudio.com/Seeed-XIAO-RP2350-p-5944.html")
|
||||
|
||||
# Upesy
|
||||
MakeBoard("upesy_rp2040_devkit", "rp2040", "uPesy", "RP2040 DevKit", "0x2e8a", "0x1007", 250, "UPESY_RP2040_DEVKIT", 2, 0, "boot2_w25q080_2_padded_checksum")
|
||||
|
||||
@@ -229,7 +229,6 @@ env.Append(
|
||||
# SdFat definitions required for SDFS
|
||||
("FILE_COPY_CONSTRUCTOR_SELECT", "FILE_COPY_CONSTRUCTOR_PUBLIC"),
|
||||
("USE_UTF8_LONG_NAMES", "1"),
|
||||
("SDFAT_FILE_TYPE", "3"),
|
||||
("DISABLE_FS_H_WARNING", "1")
|
||||
],
|
||||
|
||||
|
||||
@@ -23,8 +23,11 @@
|
||||
#define PIN_SPI1_SS (31u)
|
||||
|
||||
// Wire
|
||||
#define __WIRE0_DEVICE i2c1
|
||||
#define PIN_WIRE0_SDA (2u)
|
||||
#define PIN_WIRE0_SCL (3u)
|
||||
|
||||
#define __WIRE1_DEVICE i2c0
|
||||
#define PIN_WIRE1_SDA (31u) // not pinned out
|
||||
#define PIN_WIRE1_SCL (31u)
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#define PICO_RP2350B 1
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED (23u)
|
||||
|
||||
#define PIN_NEOPIXEL (25)
|
||||
#define NUM_NEOPIXEL (1)
|
||||
|
||||
// 'Boot0' button also on GPIO #24
|
||||
#define PIN_BUTTON (24u)
|
||||
|
||||
// USB host connector
|
||||
#define PIN_USB_HOST_DP (32u)
|
||||
#define PIN_USB_HOST_DM (33u)
|
||||
#define PIN_5V_EN (29u)
|
||||
#define PIN_5V_EN_STATE (1u)
|
||||
|
||||
// SDIO
|
||||
#define PIN_SD_CLK (34u)
|
||||
#define PIN_SD_CMD_MOSI (35u)
|
||||
#define PIN_SD_DAT0_MISO (36u)
|
||||
#define PIN_SD_DAT1 (37u)
|
||||
#define PIN_SD_DAT2 (38u)
|
||||
#define PIN_SD_DAT3_CS (39u)
|
||||
#define PIN_SD_DETECT (40u)
|
||||
|
||||
#define __PIN_A0 (41u)
|
||||
#define __PIN_A1 (42u)
|
||||
#define __PIN_A2 (43u)
|
||||
#define __PIN_A3 (44u)
|
||||
#define __PIN_A4 (45u)
|
||||
#define __PIN_A5 (46u)
|
||||
|
||||
// UARTs
|
||||
#define PIN_SERIAL1_TX (0u)
|
||||
#define PIN_SERIAL1_RX (1u)
|
||||
#define PIN_SERIAL2_TX (99u) // not pinned out
|
||||
#define PIN_SERIAL2_RX (99u)
|
||||
|
||||
// SPI
|
||||
#define __SPI0_DEVICE spi1
|
||||
#define PIN_SPI1_MISO (36u)
|
||||
#define PIN_SPI1_MOSI (35u)
|
||||
#define PIN_SPI1_SCK (34u)
|
||||
#define PIN_SPI1_SS (39u)
|
||||
|
||||
#define __SPI1_DEVICE spi0
|
||||
#define PIN_SPI0_MISO (28u)
|
||||
#define PIN_SPI0_MOSI (31u)
|
||||
#define PIN_SPI0_SCK (30u)
|
||||
#define PIN_SPI0_SS (29u)
|
||||
|
||||
// Wire
|
||||
#define __WIRE0_DEVICE i2c0
|
||||
#define PIN_WIRE0_SDA (20u)
|
||||
#define PIN_WIRE0_SCL (21u)
|
||||
|
||||
#define __WIRE1_DEVICE i2c1
|
||||
#define PIN_WIRE1_SDA (99u) // not pinned out
|
||||
#define PIN_WIRE1_SCL (99u)
|
||||
|
||||
#define SERIAL_HOWMANY (1u)
|
||||
#define SPI_HOWMANY (2u)
|
||||
#define WIRE_HOWMANY (1u)
|
||||
|
||||
// PSRAM
|
||||
#define RP2350_PSRAM_CS (47u)
|
||||
#define RP2350_PSRAM_MAX_SCK_HZ (109*1000*1000)
|
||||
|
||||
#include "../generic/common.h"
|
||||
@@ -55,7 +55,7 @@ void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
|
||||
// after a sw or hw reset have been performed to ensure that the AT
|
||||
// interpreter is up and running.
|
||||
bool Challenger2040WiFiClass::waitForReady() {
|
||||
int timeout = 20; // Aprox max 2 sec
|
||||
int timeout = 20; // Approx max 2 sec
|
||||
|
||||
_serial->setTimeout(100);
|
||||
String rdy = _serial->readStringUntil('\n');
|
||||
|
||||
@@ -62,7 +62,7 @@ void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
|
||||
// after a sw or hw reset have been performed to ensure that the AT
|
||||
// interpreter is up and running.
|
||||
bool Challenger2040WiFiClass::waitForReady() {
|
||||
int timeout = 20; // Aprox max 2 sec
|
||||
int timeout = 20; // Approx max 2 sec
|
||||
|
||||
_serial->setTimeout(100);
|
||||
String rdy = _serial->readStringUntil('\n');
|
||||
|
||||
@@ -55,7 +55,7 @@ void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
|
||||
// after a sw or hw reset have been performed to ensure that the AT
|
||||
// interpreter is up and running.
|
||||
bool Challenger2040WiFiClass::waitForReady() {
|
||||
int timeout = 20; // Aprox max 2 sec
|
||||
int timeout = 20; // Approx max 2 sec
|
||||
|
||||
_serial->setTimeout(100);
|
||||
String rdy = _serial->readStringUntil('\n');
|
||||
|
||||
@@ -55,7 +55,7 @@ void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
|
||||
// after a sw or hw reset have been performed to ensure that the AT
|
||||
// interpreter is up and running.
|
||||
bool Challenger2040WiFiClass::waitForReady() {
|
||||
int timeout = 20; // Aprox max 2 sec
|
||||
int timeout = 20; // Approx max 2 sec
|
||||
|
||||
_serial->setTimeout(100);
|
||||
String rdy = _serial->readStringUntil('\n');
|
||||
|
||||
@@ -55,7 +55,7 @@ void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
|
||||
// after a sw or hw reset have been performed to ensure that the AT
|
||||
// interpreter is up and running.
|
||||
bool Challenger2040WiFiClass::waitForReady() {
|
||||
int timeout = 20; // Aprox max 2 sec
|
||||
int timeout = 20; // Approx max 2 sec
|
||||
|
||||
_serial->setTimeout(100);
|
||||
String rdy = _serial->readStringUntil('\n');
|
||||
|
||||
@@ -195,7 +195,7 @@ void iLabsConnectivityClass::flashEspReset() { // Prepare ESP for flashing
|
||||
// after a sw or hw reset have been performed to ensure that the AT
|
||||
// interpreter is up and running.
|
||||
bool iLabsConnectivityClass::waitForEspReady() {
|
||||
int timeout = 20; // Aprox max 2 sec
|
||||
int timeout = 20; // Approx max 2 sec
|
||||
|
||||
_espSerial->setTimeout(100);
|
||||
String rdy = _espSerial->readStringUntil('\n');
|
||||
|
||||
@@ -53,7 +53,7 @@ void Ilabs2040WiFiClass::flashReset() { // Prepare ESP8285 for flashing
|
||||
// after a sw or hw reset have been performed to ensure that the AT
|
||||
// interpreter is up and running.
|
||||
bool Ilabs2040WiFiClass::waitForReady() {
|
||||
int timeout = 20; // Aprox max 2 sec
|
||||
int timeout = 20; // Approx max 2 sec
|
||||
|
||||
ESP_SERIAL_PORT.begin(DEFAULT_ESP8285_BAUDRATE);
|
||||
ESP_SERIAL_PORT.setTimeout(100);
|
||||
|
||||
@@ -53,8 +53,17 @@ static const uint8_t D18 = (9u);
|
||||
|
||||
|
||||
// Wire
|
||||
#define PIN_WIRE1_SDA (16u)
|
||||
#define PIN_WIRE1_SCL (17u)
|
||||
#define __WIRE0_DEVICE (i2c0)
|
||||
#define PIN_WIRE0_SDA (16u)
|
||||
#define PIN_WIRE0_SCL (17u)
|
||||
#define SDA PIN_WIRE0_SDA
|
||||
#define SCL PIN_WIRE0_SCL
|
||||
#define I2C_SDA (SDA)
|
||||
#define I2C_SCL (SCL)
|
||||
|
||||
#define __WIRE1_DEVICE (i2c1)
|
||||
#define PIN_WIRE1_SDA (6u)
|
||||
#define PIN_WIRE1_SCL (7u)
|
||||
|
||||
#define SERIAL_HOWMANY (3u)
|
||||
#define SPI_HOWMANY (2u)
|
||||
@@ -66,10 +75,3 @@ static const uint8_t MISO = PIN_SPI0_MISO;
|
||||
static const uint8_t SCK = PIN_SPI0_SCK;
|
||||
static const uint8_t SS = PIN_SPI0_SS;
|
||||
|
||||
#define __WIRE0_DEVICE (i2c1)
|
||||
#define PIN_WIRE0_SDA (6u)
|
||||
#define PIN_WIRE0_SCL (7u)
|
||||
#define SDA PIN_WIRE0_SDA
|
||||
#define SCL PIN_WIRE0_SCL
|
||||
#define I2C_SDA (SDA)
|
||||
#define I2C_SCL (SCL)
|
||||
Reference in New Issue
Block a user