Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fd8e41db1 | ||
|
|
5fd4736d8f | ||
|
|
67a07edccc | ||
|
|
1dc0872818 | ||
|
|
ead0728a57 | ||
|
|
14eb8d3906 | ||
|
|
4c90b295b2 | ||
|
|
43aa0427ea | ||
|
|
cc5d1779a3 | ||
|
|
0f437e4db2 | ||
|
|
3778fbb833 | ||
|
|
4b6f3d05e1 | ||
|
|
9e89dda900 | ||
|
|
91e69e2a1a | ||
|
|
21d1a285dc | ||
|
|
0e579792d1 | ||
|
|
20cabe824f | ||
|
|
0847d3dbb0 | ||
|
|
fa7c287f07 | ||
|
|
9b3032cd58 | ||
|
|
50646b9e70 | ||
|
|
3d6a1c7b41 | ||
|
|
5b76b0668b | ||
|
|
d18f8dce2f | ||
|
|
c64cdc14b6 | ||
|
|
cc800713bd | ||
|
|
c6a0d6ecfe | ||
|
|
c6426ae461 | ||
|
|
7b04a033b3 | ||
|
|
8e4008bf12 | ||
|
|
7eb176c0b4 | ||
|
|
3f475ac68c | ||
|
|
5204dab99b | ||
|
|
273fb84dc5 | ||
|
|
fe3af4d98b | ||
|
|
9aade5bb24 | ||
|
|
3c408dab7c | ||
|
|
2888f4d03d | ||
|
|
f57b5bc762 | ||
|
|
35a4d57360 | ||
|
|
579e366bcf | ||
|
|
db4f79448d | ||
|
|
45bbcca207 | ||
|
|
8e961a5667 | ||
|
|
64ad69c247 | ||
|
|
4def2f219c | ||
|
|
b2b4b2d71d | ||
|
|
e93bd14ef5 | ||
|
|
652f9f9eda | ||
|
|
cac9eb0cd7 | ||
|
|
3b4fb295ea | ||
|
|
a1ae61b5b1 | ||
|
|
355abd8c57 | ||
|
|
b57ac66815 | ||
|
|
a851a928d2 | ||
|
|
16c2e8e454 | ||
|
|
ae908c8e9b | ||
|
|
723c81470a | ||
|
|
a7905fba3e | ||
|
|
6e52b72523 | ||
|
|
ef4ec4185a |
@@ -19,18 +19,18 @@ jobs:
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- name: Cache PlatformIO
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.platformio
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install PlatformIO
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade platformio
|
||||
python-version: '3.x'
|
||||
# - name: Cache PlatformIO
|
||||
# uses: actions/cache@v3
|
||||
# with:
|
||||
# path: ~/.platformio
|
||||
# key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
# - name: Install PlatformIO
|
||||
# run: |
|
||||
# python -m pip install --upgrade pip
|
||||
# pip install --upgrade platformio
|
||||
- name: Deploy updated JSON
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
@@ -43,5 +43,5 @@ jobs:
|
||||
curl -L -o package_rp2040_index.json "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/releases/download/$TAG/package_rp2040_index.json"
|
||||
./package/update_release.py --token ${CI_GITHUB_API_KEY} --repo "$GITHUB_REPOSITORY" --tag global package_rp2040_index.json
|
||||
# Upload to Platform.IO
|
||||
curl -LO $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/releases/download/$TAG/rp2040-$TAG.zip
|
||||
pio package publish rp2040-$TAG.zip --non-interactive
|
||||
# curl -LO $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/releases/download/$TAG/rp2040-$TAG.zip
|
||||
# pio package publish rp2040-$TAG.zip --non-interactive
|
||||
|
||||
@@ -25,6 +25,7 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* Adafruit STEMMA Friend RP2040
|
||||
* Adafruit Trinkey RP2040 QT
|
||||
* Arduino Nano RP2040 Connect
|
||||
* ArtronShop RP2 Nano
|
||||
* BridgeTek IDM2040-7A
|
||||
* Cytron Maker Pi RP2040
|
||||
* Cytron Maker Nano RP2040
|
||||
@@ -35,6 +36,7 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* ExtremeElectronics RC2040
|
||||
* Invector Labs Challenger RP2040 WiFi
|
||||
* Invector Labs Challenger RP2040 WiFi/BLE
|
||||
* Invector Labs Challenger RP2040 WiFi6/BLE
|
||||
* Invector Labs Challenger NB RP2040 WiFi
|
||||
* Invector Labs Challenger RP2040 LTE
|
||||
* Invector Labs Challenger RP2040 LoRa
|
||||
|
||||
+714
-59
File diff suppressed because it is too large
Load Diff
+12
-1
@@ -28,7 +28,7 @@
|
||||
#include "api/ArduinoAPI.h"
|
||||
#include "api/itoa.h" // ARM toolchain doesn't provide itoa etc, provide them
|
||||
#include <pins_arduino.h>
|
||||
#include "hardware/gpio.h" // Required for the port*Register macros
|
||||
#include <hardware/gpio.h> // Required for the port*Register macros
|
||||
#include "debug_internal.h"
|
||||
#include <RP2040.h> // CMSIS
|
||||
|
||||
@@ -129,3 +129,14 @@ constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) {
|
||||
return i < N ? (1L << a[i]) | __bitset(a, i + 1) : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Warn users trying to use Pico SDK's STDIO implementation
|
||||
#include <pico/stdio.h> // Ensure it won't be re-included elsewhere
|
||||
#undef stdio_uart_init
|
||||
#define stdio_uart_init(...) static_assert(0, "stdio_uart_init is not supported or needed. Either use Serial.printf() or set the debug port in the IDE to Serial/1/2 and use printf(). See https://github.com/earlephilhower/arduino-pico/issues/1433#issuecomment-1540354673 and https://github.com/earlephilhower/arduino-pico/issues/1433#issuecomment-1546783109")
|
||||
#undef stdio_init_all
|
||||
#define stdio_init_all(...) static_assert(0, "stdio_init_all is not supported or needed. Either use Serial.printf() or set the debug port in the IDE to Serial/1/2 and use printf(). See https://github.com/earlephilhower/arduino-pico/issues/1433#issuecomment-1540354673 and https://github.com/earlephilhower/arduino-pico/issues/1433#issuecomment-1546783109")
|
||||
#undef stdio_usb_init
|
||||
#define stdio_usb_init(...) static_assert(0, "stdio_usb_init is not supported or needed. Either use Serial.printf() or set the debug port in the IDE to Serial/1/2 and use printf(). See https://github.com/earlephilhower/arduino-pico/issues/1433#issuecomment-1540354673 and https://github.com/earlephilhower/arduino-pico/issues/1433#issuecomment-1546783109")
|
||||
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "hardware/structs/ioqspi.h"
|
||||
#include "hardware/structs/sio.h"
|
||||
#include <pico/stdlib.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/sync.h>
|
||||
#include <hardware/structs/ioqspi.h>
|
||||
#include <hardware/structs/sio.h>
|
||||
|
||||
// This example blinks the Pico LED when the BOOTSEL button is pressed.
|
||||
//
|
||||
|
||||
@@ -28,14 +28,18 @@ CoreMutex::CoreMutex(mutex_t *mutex, uint8_t option) {
|
||||
_mutex = mutex;
|
||||
_acquired = false;
|
||||
_option = option;
|
||||
_pxHigherPriorityTaskWoken = 0; // pdFALSE
|
||||
if (__isFreeRTOS) {
|
||||
auto m = __get_freertos_mutex_for_ptr(mutex);
|
||||
if (_option & FromISR) {
|
||||
__freertos_mutex_take_from_isr(m);
|
||||
} else {
|
||||
if (!__freertos_mutex_try_take(m)) {
|
||||
|
||||
if (__freertos_check_if_in_isr()) {
|
||||
if (!__freertos_mutex_take_from_isr(m, &_pxHigherPriorityTaskWoken)) {
|
||||
return;
|
||||
}
|
||||
// At this point we have the mutex in ISR
|
||||
} else {
|
||||
// Grab the mutex normally, possibly waking other tasks to get it
|
||||
__freertos_mutex_take(m);
|
||||
}
|
||||
} else {
|
||||
uint32_t owner;
|
||||
@@ -56,8 +60,8 @@ CoreMutex::~CoreMutex() {
|
||||
if (_acquired) {
|
||||
if (__isFreeRTOS) {
|
||||
auto m = __get_freertos_mutex_for_ptr(_mutex);
|
||||
if (_option & FromISR) {
|
||||
__freertos_mutex_give_from_isr(m);
|
||||
if (__freertos_check_if_in_isr()) {
|
||||
__freertos_mutex_give_from_isr(m, &_pxHigherPriorityTaskWoken);
|
||||
} else {
|
||||
__freertos_mutex_give(m);
|
||||
}
|
||||
|
||||
@@ -23,12 +23,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pico/mutex.h"
|
||||
#include <pico/mutex.h>
|
||||
#include "_freertos.h"
|
||||
|
||||
enum {
|
||||
DebugEnable = 1,
|
||||
FromISR = 1 << 1,
|
||||
DebugEnable = 1
|
||||
};
|
||||
|
||||
class CoreMutex {
|
||||
@@ -44,4 +43,5 @@ private:
|
||||
mutex_t *_mutex;
|
||||
bool _acquired;
|
||||
uint8_t _option;
|
||||
BaseType_t _pxHigherPriorityTaskWoken;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
RP2040 PIO utility class
|
||||
|
||||
Copyright (c) 2023 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 "PIOProgram.h"
|
||||
#include <map>
|
||||
|
||||
static std::map<const pio_program_t *, int> __pioMap[2];
|
||||
auto_init_mutex(_pioMutex);
|
||||
|
||||
|
||||
PIOProgram::PIOProgram(const pio_program_t *pgm) {
|
||||
_pgm = pgm;
|
||||
_pio = nullptr;
|
||||
_sm = -1;
|
||||
}
|
||||
|
||||
// We leave the INSN loaded in INSN RAM
|
||||
PIOProgram::~PIOProgram() {
|
||||
if (_pio) {
|
||||
pio_sm_unclaim(_pio, _sm);
|
||||
}
|
||||
}
|
||||
|
||||
// Possibly load into a PIO and allocate a SM
|
||||
bool PIOProgram::prepare(PIO *pio, int *sm, int *offset) {
|
||||
CoreMutex m(&_pioMutex);
|
||||
PIO pi[2] = { pio0, pio1 };
|
||||
|
||||
// If it's already loaded into PIO IRAM, try and allocate in that specific PIO
|
||||
for (int o = 0; o < 2; o++) {
|
||||
auto p = __pioMap[o].find(_pgm);
|
||||
if (p != __pioMap[o].end()) {
|
||||
int idx = pio_claim_unused_sm(pi[o], false);
|
||||
if (idx >= 0) {
|
||||
_pio = pi[o];
|
||||
_sm = idx;
|
||||
*pio = pi[o];
|
||||
*sm = idx;
|
||||
*offset = p->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not in any PIO IRAM, so try and add
|
||||
for (int o = 0; o < 2; o++) {
|
||||
if (pio_can_add_program(pi[o], _pgm)) {
|
||||
int idx = pio_claim_unused_sm(pi[o], false);
|
||||
if (idx >= 0) {
|
||||
int off = pio_add_program(pi[o], _pgm);
|
||||
__pioMap[o].insert({_pgm, off});
|
||||
_pio = pi[o];
|
||||
_sm = idx;
|
||||
*pio = pi[o];
|
||||
*sm = idx;
|
||||
*offset = off;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nope, no room either for SMs or INSNs
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
RP2040 PIO utility class
|
||||
|
||||
Copyright (c) 2023 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 <hardware/pio.h>
|
||||
|
||||
// Wrapper class for PIO programs, abstracting common operations out
|
||||
class PIOProgram {
|
||||
public:
|
||||
PIOProgram(const pio_program_t *pgm);
|
||||
~PIOProgram();
|
||||
// Possibly load into a PIO and allocate a SM
|
||||
bool prepare(PIO *pio, int *sm, int *offset);
|
||||
|
||||
private:
|
||||
const pio_program_t *_pgm;
|
||||
PIO _pio;
|
||||
int _sm;
|
||||
};
|
||||
@@ -29,7 +29,9 @@
|
||||
#include <pico/multicore.h>
|
||||
#include <pico/rand.h>
|
||||
#include <pico/util/queue.h>
|
||||
#include <pico/bootrom.h>
|
||||
#include "CoreMutex.h"
|
||||
#include "PIOProgram.h"
|
||||
#include "ccount.pio.h"
|
||||
#include <malloc.h>
|
||||
|
||||
@@ -91,15 +93,14 @@ public:
|
||||
if (!_multicore) {
|
||||
return;
|
||||
}
|
||||
__holdUpPendSV = 1;
|
||||
if (__isFreeRTOS) {
|
||||
vTaskPreemptionDisable(nullptr);
|
||||
vTaskSuspendAll();
|
||||
__freertos_idle_other_core();
|
||||
} else {
|
||||
mutex_enter_blocking(&_idleMutex);
|
||||
__otherCoreIdled = false;
|
||||
multicore_fifo_push_blocking(_GOTOSLEEP);
|
||||
while (!__otherCoreIdled) { /* noop */ }
|
||||
}
|
||||
mutex_enter_blocking(&_idleMutex);
|
||||
__otherCoreIdled = false;
|
||||
multicore_fifo_push_blocking(_GOTOSLEEP);
|
||||
while (!__otherCoreIdled) { /* noop */ }
|
||||
}
|
||||
|
||||
void resumeOtherCore() {
|
||||
@@ -109,10 +110,8 @@ public:
|
||||
mutex_exit(&_idleMutex);
|
||||
__otherCoreIdled = false;
|
||||
if (__isFreeRTOS) {
|
||||
xTaskResumeAll();
|
||||
vTaskPreemptionEnable(nullptr);
|
||||
__freertos_resume_other_core();
|
||||
}
|
||||
__holdUpPendSV = 0;
|
||||
|
||||
// Other core will exit busy-loop and return to operation
|
||||
// once __otherCoreIdled == false.
|
||||
@@ -156,65 +155,9 @@ private:
|
||||
class RP2040;
|
||||
extern RP2040 rp2040;
|
||||
extern "C" void main1();
|
||||
class PIOProgram;
|
||||
|
||||
extern "C" char __StackLimit;
|
||||
extern "C" char __bss_end__;
|
||||
|
||||
// Wrapper class for PIO programs, abstracting common operations out
|
||||
// TODO - Add unload/destructor
|
||||
class PIOProgram {
|
||||
public:
|
||||
PIOProgram(const pio_program_t *pgm) {
|
||||
_pgm = pgm;
|
||||
}
|
||||
|
||||
// Possibly load into a PIO and allocate a SM
|
||||
bool prepare(PIO *pio, int *sm, int *offset) {
|
||||
extern mutex_t _pioMutex;
|
||||
CoreMutex m(&_pioMutex);
|
||||
// Is there an open slot to run in, first?
|
||||
if (!_findFreeSM(pio, sm)) {
|
||||
return false;
|
||||
}
|
||||
// Is it loaded on that PIO?
|
||||
if (_offset[pio_get_index(*pio)] < 0) {
|
||||
// Nope, need to load it
|
||||
if (!pio_can_add_program(*pio, _pgm)) {
|
||||
return false;
|
||||
}
|
||||
_offset[pio_get_index(*pio)] = pio_add_program(*pio, _pgm);
|
||||
}
|
||||
// Here it's guaranteed loaded, return values
|
||||
// PIO and SM already set
|
||||
*offset = _offset[pio_get_index(*pio)];
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Find an unused PIO state machine to grab, returns false when none available
|
||||
static bool _findFreeSM(PIO *pio, int *sm) {
|
||||
int idx = pio_claim_unused_sm(pio0, false);
|
||||
if (idx >= 0) {
|
||||
*pio = pio0;
|
||||
*sm = idx;
|
||||
return true;
|
||||
}
|
||||
idx = pio_claim_unused_sm(pio1, false);
|
||||
if (idx >= 0) {
|
||||
*pio = pio1;
|
||||
*sm = idx;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
int _offset[2] = { -1, -1 };
|
||||
const pio_program_t *_pgm;
|
||||
};
|
||||
|
||||
class RP2040 {
|
||||
public:
|
||||
RP2040() { /* noop */ }
|
||||
@@ -320,6 +263,13 @@ public:
|
||||
reboot();
|
||||
}
|
||||
|
||||
inline void rebootToBootloader() {
|
||||
reset_usb_boot(0, 0);
|
||||
while (1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
static void enableDoubleResetBootloader();
|
||||
|
||||
void wdt_begin(uint32_t delay_ms) {
|
||||
|
||||
+63
-11
@@ -25,17 +25,16 @@
|
||||
#include "CoreMutex.h"
|
||||
#include "RP2040USB.h"
|
||||
|
||||
#include "tusb.h"
|
||||
#include "class/hid/hid_device.h"
|
||||
#include "class/audio/audio.h"
|
||||
#include "class/midi/midi.h"
|
||||
#include "pico/time.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "pico/mutex.h"
|
||||
#include "pico/unique_id.h"
|
||||
#include "pico/usb_reset_interface.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/bootrom.h"
|
||||
#include <tusb.h>
|
||||
#include <class/hid/hid_device.h>
|
||||
#include <class/audio/audio.h>
|
||||
#include <pico/time.h>
|
||||
#include <hardware/irq.h>
|
||||
#include <pico/mutex.h>
|
||||
#include <pico/unique_id.h>
|
||||
#include <pico/usb_reset_interface.h>
|
||||
#include <hardware/watchdog.h>
|
||||
#include <pico/bootrom.h>
|
||||
#include "sdkoverride/tusb_absmouse.h"
|
||||
#include <device/usbd_pvt.h>
|
||||
|
||||
@@ -550,6 +549,59 @@ usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) {
|
||||
*driver_count = 1;
|
||||
return &_resetd_driver;
|
||||
}
|
||||
|
||||
#elif defined NO_USB
|
||||
|
||||
// will ensure backward compatibility with existing code when using pico-debug
|
||||
|
||||
#warning "NO_USB selected. No output to Serial will occur!"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void SerialUSB::begin(unsigned long baud) {
|
||||
}
|
||||
|
||||
void SerialUSB::end() {
|
||||
|
||||
}
|
||||
|
||||
int SerialUSB::peek() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SerialUSB::read() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SerialUSB::available() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SerialUSB::availableForWrite() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SerialUSB::flush() {
|
||||
|
||||
}
|
||||
|
||||
size_t SerialUSB::write(uint8_t c) {
|
||||
(void) c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t SerialUSB::write(const uint8_t *buf, size_t length) {
|
||||
(void) buf;
|
||||
(void) length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SerialUSB::operator bool() {
|
||||
return false;
|
||||
}
|
||||
|
||||
SerialUSB Serial;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "pico/mutex.h"
|
||||
#include <pico/mutex.h>
|
||||
|
||||
// Weak function definitions for each type of endpoint
|
||||
extern void __USBInstallSerial() __attribute__((weak));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define ARDUINO_PICO_MAJOR 3
|
||||
#define ARDUINO_PICO_MINOR 2
|
||||
#define ARDUINO_PICO_REVISION 0
|
||||
#define ARDUINO_PICO_VERSION_STR "3.2.0"
|
||||
#define ARDUINO_PICO_MINOR 3
|
||||
#define ARDUINO_PICO_REVISION 1
|
||||
#define ARDUINO_PICO_VERSION_STR "3.3.1"
|
||||
|
||||
+21
-14
@@ -46,22 +46,24 @@ static pio_program_t *pio_make_uart_prog(int repl, const pio_program_t *pg) {
|
||||
return p;
|
||||
}
|
||||
|
||||
static PIOProgram *_getTxProgram(int bits) {
|
||||
auto f = _txMap.find(bits);
|
||||
static PIOProgram *_getTxProgram(int bits, bool inverted) {
|
||||
int key = inverted ? -bits : bits;
|
||||
auto f = _txMap.find(key);
|
||||
if (f == _txMap.end()) {
|
||||
pio_program_t * p = pio_make_uart_prog(bits, &pio_tx_program);
|
||||
_txMap.insert({bits, new PIOProgram(p)});
|
||||
f = _txMap.find(bits);
|
||||
pio_program_t * p = pio_make_uart_prog(bits, inverted ? &pio_tx_inv_program : &pio_tx_program);
|
||||
_txMap.insert({key, new PIOProgram(p)});
|
||||
f = _txMap.find(key);
|
||||
}
|
||||
return f->second;
|
||||
}
|
||||
|
||||
static PIOProgram *_getRxProgram(int bits) {
|
||||
auto f = _rxMap.find(bits);
|
||||
static PIOProgram *_getRxProgram(int bits, bool inverted) {
|
||||
int key = inverted ? -bits : bits;
|
||||
auto f = _rxMap.find(key);
|
||||
if (f == _rxMap.end()) {
|
||||
pio_program_t * p = pio_make_uart_prog(bits, &pio_rx_program);
|
||||
_rxMap.insert({bits, new PIOProgram(p)});
|
||||
f = _rxMap.find(bits);
|
||||
pio_program_t * p = pio_make_uart_prog(bits, inverted ? &pio_rx_inv_program : &pio_rx_program);
|
||||
_rxMap.insert({key, new PIOProgram(p)});
|
||||
f = _rxMap.find(key);
|
||||
}
|
||||
return f->second;
|
||||
}
|
||||
@@ -96,7 +98,7 @@ void __not_in_flash_func(SerialPIO::_handleIRQ)() {
|
||||
return;
|
||||
}
|
||||
while (!pio_sm_is_rx_fifo_empty(_rxPIO, _rxSM)) {
|
||||
uint32_t decode = _rxPIO->rxf[_rxSM];
|
||||
uint32_t decode = _rxPIO->rxf[_rxSM] ^ (_rxInverted ? 0xffffffff : 0);
|
||||
decode >>= 33 - _rxBits;
|
||||
uint32_t val = 0;
|
||||
for (int b = 0; b < _bits + 1; b++) {
|
||||
@@ -189,7 +191,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
|
||||
|
||||
if (_tx != NOPIN) {
|
||||
_txBits = _bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1/*start bit*/;
|
||||
_txPgm = _getTxProgram(_txBits);
|
||||
_txPgm = _getTxProgram(_txBits, _txInverted);
|
||||
int off;
|
||||
if (!_txPgm->prepare(&_txPIO, &_txSM, &off)) {
|
||||
DEBUGCORE("ERROR: Unable to allocate PIO TX UART, out of PIO resources\n");
|
||||
@@ -216,7 +218,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
|
||||
_reader = 0;
|
||||
|
||||
_rxBits = 2 * (_bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1) - 1;
|
||||
_rxPgm = _getRxProgram(_rxBits);
|
||||
_rxPgm = _getRxProgram(_rxBits, _rxInverted);
|
||||
int off;
|
||||
if (!_rxPgm->prepare(&_rxPIO, &_rxSM, &off)) {
|
||||
DEBUGCORE("ERROR: Unable to allocate PIO RX UART, out of PIO resources\n");
|
||||
@@ -346,6 +348,11 @@ void SerialPIO::flush() {
|
||||
delay((1000 * (_txBits + 1)) / _baud);
|
||||
}
|
||||
|
||||
void SerialPIO::setInverted(bool invTx, bool invRx) {
|
||||
_txInverted = invTx;
|
||||
_rxInverted = invRx;
|
||||
}
|
||||
|
||||
size_t SerialPIO::write(uint8_t c) {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m || (_tx == NOPIN)) {
|
||||
@@ -364,7 +371,7 @@ size_t SerialPIO::write(uint8_t c) {
|
||||
}
|
||||
val <<= 1; // Start bit = low
|
||||
|
||||
pio_sm_put_blocking(_txPIO, _txSM, val);
|
||||
pio_sm_put_blocking(_txPIO, _txSM, _txInverted ? ~val : val);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
void begin(unsigned long baud, uint16_t config) override;
|
||||
void end() override;
|
||||
|
||||
void setInverted(bool invTx = true, bool invRx = true);
|
||||
|
||||
virtual int peek() override;
|
||||
virtual int read() override;
|
||||
virtual int available() override;
|
||||
@@ -63,6 +65,8 @@ protected:
|
||||
int _stop;
|
||||
bool _overflow;
|
||||
mutex_t _mutex;
|
||||
bool _txInverted = false;
|
||||
bool _rxInverted = false;
|
||||
|
||||
PIOProgram *_txPgm;
|
||||
PIO _txPIO;
|
||||
|
||||
+13
-12
@@ -25,15 +25,15 @@
|
||||
#include <Arduino.h>
|
||||
#include "CoreMutex.h"
|
||||
|
||||
#include "tusb.h"
|
||||
#include "pico/time.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "pico/bootrom.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "pico/mutex.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/unique_id.h"
|
||||
#include "hardware/resets.h"
|
||||
#include <tusb.h>
|
||||
#include <pico/time.h>
|
||||
#include <pico/binary_info.h>
|
||||
#include <pico/bootrom.h>
|
||||
#include <hardware/irq.h>
|
||||
#include <pico/mutex.h>
|
||||
#include <hardware/watchdog.h>
|
||||
#include <pico/unique_id.h>
|
||||
#include <hardware/resets.h>
|
||||
|
||||
#ifndef DISABLE_USB_SERIAL
|
||||
// Ensure we are installed in the USB chain
|
||||
@@ -177,8 +177,10 @@ static bool _rts = false;
|
||||
static int _bps = 115200;
|
||||
static bool _rebooting = false;
|
||||
static void CheckSerialReset() {
|
||||
__holdUpPendSV = 1; // Ensure we don't get swapped out by FreeRTOS
|
||||
if (!_rebooting && (_bps == 1200) && (!_dtr)) {
|
||||
if (__isFreeRTOS) {
|
||||
__freertos_idle_other_core();
|
||||
}
|
||||
_rebooting = true;
|
||||
// Disable NVIC IRQ, so that we don't get bothered anymore
|
||||
irq_set_enabled(USBCTRL_IRQ, false);
|
||||
@@ -186,11 +188,10 @@ static void CheckSerialReset() {
|
||||
reset_block(RESETS_RESET_USBCTRL_BITS);
|
||||
unreset_block(RESETS_RESET_USBCTRL_BITS);
|
||||
// Delay a bit, so the PC can figure out that we have disconnected.
|
||||
sleep_ms(3);
|
||||
busy_wait_ms(3);
|
||||
reset_usb_boot(0, 0);
|
||||
while (1); // WDT will fire here
|
||||
}
|
||||
__holdUpPendSV = 0;
|
||||
}
|
||||
|
||||
extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "stdint.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void randomSeed(uint32_t dwSeed) {
|
||||
if (dwSeed != 0) {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "_freertos.h"
|
||||
#include "pico/mutex.h"
|
||||
#include <pico/mutex.h>
|
||||
#include <stdlib.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "pico/mutex.h"
|
||||
#include <pico/mutex.h>
|
||||
|
||||
// Cannot include refs to FreeRTOS's actual semaphore calls because they
|
||||
// are implemented as macros, so we have a wrapper in our variant hook
|
||||
@@ -35,32 +35,26 @@ extern "C" {
|
||||
struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */
|
||||
typedef struct QueueDefinition * QueueHandle_t;
|
||||
typedef QueueHandle_t SemaphoreHandle_t;
|
||||
typedef int32_t BaseType_t;
|
||||
#endif
|
||||
|
||||
extern bool __freertos_check_if_in_isr() __attribute__((weak));
|
||||
|
||||
extern SemaphoreHandle_t __freertos_mutex_create() __attribute__((weak));
|
||||
extern SemaphoreHandle_t _freertos_recursive_mutex_create() __attribute__((weak));
|
||||
|
||||
extern void __freertos_mutex_take(SemaphoreHandle_t mtx) __attribute__((weak));
|
||||
extern void __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx) __attribute__((weak));
|
||||
|
||||
extern int __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx, BaseType_t* pxHigherPriorityTaskWoken) __attribute__((weak));
|
||||
extern int __freertos_mutex_try_take(SemaphoreHandle_t mtx) __attribute__((weak));
|
||||
extern void __freertos_mutex_give(SemaphoreHandle_t mtx) __attribute__((weak));
|
||||
extern void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx) __attribute__((weak));
|
||||
extern void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx, BaseType_t* pxHigherPriorityTaskWoken) __attribute__((weak));
|
||||
|
||||
extern void __freertos_recursive_mutex_take(SemaphoreHandle_t mtx) __attribute__((weak));
|
||||
extern int __freertos_recursive_mutex_try_take(SemaphoreHandle_t mtx) __attribute__((weak));
|
||||
extern void __freertos_recursive_mutex_give(SemaphoreHandle_t mtx) __attribute__((weak));
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
extern void vTaskSuspendAll() __attribute__((weak));
|
||||
extern int32_t xTaskResumeAll() __attribute__((weak));
|
||||
|
||||
typedef struct tskTaskControlBlock * TaskHandle_t;
|
||||
extern void vTaskPreemptionDisable(TaskHandle_t p) __attribute__((weak));
|
||||
extern void vTaskPreemptionEnable(TaskHandle_t p) __attribute__((weak));
|
||||
#endif
|
||||
|
||||
extern void __freertos_idle_other_core() __attribute__((weak));
|
||||
extern void __freertos_resume_other_core() __attribute__((weak));
|
||||
}
|
||||
extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive = false);
|
||||
|
||||
// Halt the FreeRTOS PendSV task switching magic
|
||||
extern "C" int __holdUpPendSV;
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include <lwip/netif.h>
|
||||
extern "C" {
|
||||
#include "cyw43.h"
|
||||
#include "cyw43_stats.h"
|
||||
#include <cyw43.h>
|
||||
#include <cyw43_stats.h>
|
||||
}
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <pico/cyw43_arch.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
// From cyw43_ctrl.c
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
LWIP wrappers to protect against timer-based re-entrancy
|
||||
|
||||
Copyright (c) 202s Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
Copyright (c) 2023 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
|
||||
|
||||
@@ -27,11 +27,8 @@
|
||||
RP2040 rp2040;
|
||||
extern "C" {
|
||||
volatile bool __otherCoreIdled = false;
|
||||
int __holdUpPendSV = 0;
|
||||
};
|
||||
|
||||
mutex_t _pioMutex;
|
||||
|
||||
extern void setup();
|
||||
extern void loop();
|
||||
|
||||
@@ -92,8 +89,6 @@ extern "C" int main() {
|
||||
_REENT_INIT_PTR(_impure_ptr1);
|
||||
}
|
||||
|
||||
mutex_init(&_pioMutex);
|
||||
|
||||
rp2040.begin();
|
||||
|
||||
initVariant();
|
||||
@@ -163,6 +158,7 @@ extern "C" void __register_impure_ptr(struct _reent *p) {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" struct _reent *__wrap___getreent() __attribute__((weak));
|
||||
extern "C" struct _reent *__wrap___getreent() {
|
||||
if (get_core_num() == 0) {
|
||||
return _impure_ptr;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
; We shift out the start and stop bit as part of the FIFO
|
||||
set x, 9
|
||||
|
||||
pull side 1 ; Force stop bit
|
||||
pull side 1 ; Force stop bit high
|
||||
|
||||
; Send the bits
|
||||
bitloop:
|
||||
@@ -41,6 +41,26 @@ wait_bit:
|
||||
|
||||
|
||||
|
||||
; inverted-logic version (inverts the stop bit)
|
||||
|
||||
.program pio_tx_inv
|
||||
.side_set 1 opt
|
||||
|
||||
|
||||
; We shift out the start and stop bit as part of the FIFO
|
||||
set x, 9
|
||||
|
||||
pull side 0 ; Force stop bit low
|
||||
|
||||
; Send the bits
|
||||
bitloop:
|
||||
out pins, 1
|
||||
mov y, isr ; ISR is loaded by the setup routine with the period-1 count
|
||||
wait_bit:
|
||||
jmp y-- wait_bit
|
||||
jmp x-- bitloop
|
||||
|
||||
|
||||
% c-sdk {
|
||||
|
||||
static inline void pio_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx) {
|
||||
@@ -68,7 +88,7 @@ static inline void pio_tx_program_init(PIO pio, uint sm, uint offset, uint pin_t
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
|
||||
|
||||
.program pio_rx
|
||||
|
||||
@@ -91,6 +111,27 @@ wait_half:
|
||||
push ; Stuff it and wait for next start
|
||||
|
||||
|
||||
.program pio_rx_inv
|
||||
|
||||
; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX.
|
||||
|
||||
start:
|
||||
set x, 18 ; Preload bit counter...we'll shift in the start bit and stop bit, and each bit will be double-recorded (to be fixed by RP2040 code)
|
||||
wait 1 pin 0 ; Stall until start bit is asserted
|
||||
|
||||
bitloop:
|
||||
; Delay until 1/2 way into the bit time
|
||||
mov y, osr
|
||||
wait_half:
|
||||
jmp y-- wait_half
|
||||
|
||||
; Read in the bit
|
||||
in pins, 1 ; Shift data bit into ISR
|
||||
jmp x-- bitloop ; Loop all bits
|
||||
|
||||
push ; Stuff it and wait for next start
|
||||
|
||||
|
||||
% c-sdk {
|
||||
static inline void pio_rx_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// This file is autogenerated by pioasm; do not edit! //
|
||||
// -------------------------------------------------- //
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
#include "hardware/pio.h"
|
||||
#endif
|
||||
@@ -37,6 +39,39 @@ static inline pio_sm_config pio_tx_program_get_default_config(uint offset) {
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---------- //
|
||||
// pio_tx_inv //
|
||||
// ---------- //
|
||||
|
||||
#define pio_tx_inv_wrap_target 0
|
||||
#define pio_tx_inv_wrap 5
|
||||
|
||||
static const uint16_t pio_tx_inv_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xe029, // 0: set x, 9
|
||||
0x90a0, // 1: pull block side 0
|
||||
0x6001, // 2: out pins, 1
|
||||
0xa046, // 3: mov y, isr
|
||||
0x0084, // 4: jmp y--, 4
|
||||
0x0042, // 5: jmp x--, 2
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program pio_tx_inv_program = {
|
||||
.instructions = pio_tx_inv_program_instructions,
|
||||
.length = 6,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_tx_inv_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + pio_tx_inv_wrap_target, offset + pio_tx_inv_wrap);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void pio_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx) {
|
||||
// Tell PIO to initially drive output-high on the selected pin, then map PIO
|
||||
@@ -90,6 +125,39 @@ static inline pio_sm_config pio_rx_program_get_default_config(uint offset) {
|
||||
sm_config_set_wrap(&c, offset + pio_rx_wrap_target, offset + pio_rx_wrap);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---------- //
|
||||
// pio_rx_inv //
|
||||
// ---------- //
|
||||
|
||||
#define pio_rx_inv_wrap_target 0
|
||||
#define pio_rx_inv_wrap 6
|
||||
|
||||
static const uint16_t pio_rx_inv_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xe032, // 0: set x, 18
|
||||
0x20a0, // 1: wait 1 pin, 0
|
||||
0xa047, // 2: mov y, osr
|
||||
0x0083, // 3: jmp y--, 3
|
||||
0x4001, // 4: in pins, 1
|
||||
0x0042, // 5: jmp x--, 2
|
||||
0x8020, // 6: push block
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program pio_rx_inv_program = {
|
||||
.instructions = pio_rx_inv_program_instructions,
|
||||
.length = 7,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_rx_inv_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + pio_rx_inv_wrap_target, offset + pio_rx_inv_wrap);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void pio_rx_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "pico.h"
|
||||
#include "pico/time.h"
|
||||
#include "pico/bootrom.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include <pico/time.h>
|
||||
#include <pico/bootrom.h>
|
||||
#include <pico/binary_info.h>
|
||||
|
||||
// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS, Window of opportunity for a second press of a reset button to enter BOOTSEL mode (milliseconds), type=int, default=200, group=pico_bootsel_via_double_reset
|
||||
#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS
|
||||
|
||||
@@ -77,7 +77,7 @@ static std::map<pin_size_t, CBInfo> _map;
|
||||
void _gpioInterruptDispatcher(uint gpio, uint32_t events) {
|
||||
(void) events;
|
||||
// Only need to lock around the std::map check, not the whole IRQ callback
|
||||
CoreMutex m(&_irqMutex, (FromISR | DebugEnable));
|
||||
CoreMutex m(&_irqMutex);
|
||||
if (m) {
|
||||
auto irq = _map.find(gpio);
|
||||
if (irq != _map.end()) {
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ need to be periodically sampled to be read by applications, easily, such as:
|
||||
* Light dependent resistors (LDR), etc.
|
||||
|
||||
|
||||
Up to 4 analog samples can be recorded by the hardware (``A0`` ... ``A4``), and all
|
||||
Up to 4 analog samples can be recorded by the hardware (``A0`` ... ``A3``), and all
|
||||
recording is done at 16-bit levels (but be aware that the ADC in the Pico will only
|
||||
ever return values between 0...4095).
|
||||
|
||||
@@ -29,7 +29,7 @@ ADC Input API
|
||||
ADCInput(pin0 [, pin1, pin2, pin3])
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Creates an ADC input object which will record the pins specified in the code.
|
||||
Only pins ``A0`` ... ``A4`` can be used, and they must be specified in increasing
|
||||
Only pins ``A0`` ... ``A3`` can be used, and they must be specified in increasing
|
||||
order (i.e. ``ADCInput(A0, A1);`` is valid, but ``ADCInput(A1, A0)`` is not.
|
||||
|
||||
bool setBuffers(size_t buffers, size_t bufferWords)
|
||||
|
||||
+2
-2
@@ -54,9 +54,9 @@ author = u'Earle F. Philhower, III'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'3.2.0'
|
||||
version = u'3.3.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'3.2.0'
|
||||
release = u'3.3.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
+3
-2
@@ -10,7 +10,8 @@ Contributing to the Core (Pull Requests)
|
||||
----------------------------------------
|
||||
|
||||
We use the standard GitHub Pull Request model. If you're unfamiliar with it,
|
||||
this `guide <https://www.freecodecamp.org/news/how-to-make-your-first-pull-request-on-github-3/>` gives a simple overview of the process.
|
||||
this `guide <https://www.freecodecamp.org/news/how-to-make-your-first-pull-request-on-github-3/>`__
|
||||
gives a simple overview of the process.
|
||||
|
||||
All pull requests have to pass a set of Continuous Integration (CI) checks
|
||||
which help make sure the code compiles under different configurations and has
|
||||
@@ -84,7 +85,7 @@ code that only runs on this core, use the following define.
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#if defined(ARDUINO_ARCH_RP2040) && !defined(__MBED__)
|
||||
~~~ your changes ~~~
|
||||
#endif
|
||||
|
||||
|
||||
+2
-2
@@ -325,8 +325,8 @@ info64
|
||||
.. code:: cpp
|
||||
|
||||
FSInfo64 fsinfo;
|
||||
SDFS.info(fsinfo);
|
||||
or LittleFS(fsinfo);
|
||||
SDFS.info64(fsinfo);
|
||||
or LittleFS.info64(fsinfo);
|
||||
|
||||
Performs the same operation as ``info`` but allows for reporting greater than
|
||||
4GB for filesystem size/used/etc. Should be used with the SD and SDFS
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
HTTPClient Library
|
||||
==================
|
||||
|
||||
A simple HTTP requestor that can handle both HTTP and HTTP requests is
|
||||
A simple HTTP requester that can handle both HTTP and HTTPS requests is
|
||||
included as the ``HTTPClient`` library.
|
||||
|
||||
Check the examples for use under HTTP and HTTPS configurations. In general,
|
||||
|
||||
+23
-1
@@ -40,6 +40,16 @@ bool setDATA(pin_size_t pin)
|
||||
Sets the DOUT or DIN pin of the I2S device. Any pin may be used.
|
||||
Call before ``I2S::begin()``
|
||||
|
||||
bool setMCLK(pin_size_t pin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the MCLK pin of the I2S device and enables MCLK output. Any pin may be used.
|
||||
Call before ``I2S::begin()``
|
||||
|
||||
bool setMCLKmult(int mult)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the sample rate to MCLK multiplier value. Only multiples of 64 are valid.
|
||||
Call before ``I2S::begin()``
|
||||
|
||||
bool setBitsPerSample(int bits)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Specify how many bits per audio sample to read or write. Note that
|
||||
@@ -58,6 +68,13 @@ Sets the word clock frequency, but does not start the I2S device if not
|
||||
already running. May be called after ``I2S::begin()`` to change the
|
||||
sample rate on-the-fly.
|
||||
|
||||
bool setSysClk(int samplerate)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Changes the PICO system clock to optimise for the desired samplerate.
|
||||
The clock changes to 147.6 MHz for samplerates that are a multiple of 8 kHz, and 135.6 MHz for multiples of 11.025 kHz.
|
||||
Note that using ``setSysClk()`` may affect the timing of other sysclk-dependent functions.
|
||||
Should be called before any I2S functions and any other sysclk dependent initialisations.
|
||||
|
||||
bool setLSBJFormat()
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
Enables LSB-J format for I2S output. In this mode the MSB comes out at the
|
||||
@@ -84,6 +101,11 @@ void flush()
|
||||
~~~~~~~~~~~~
|
||||
Waits until all the I2S buffers have been output.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
@@ -112,7 +134,7 @@ many bytes were actually written.
|
||||
|
||||
int availableForWrite()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns the number of L/R samples that can be written without
|
||||
Returns the amount of bytes that can be written without
|
||||
potentially blocking.
|
||||
|
||||
int read()
|
||||
|
||||
@@ -38,6 +38,22 @@ prevent the Arduino IDE from accessing. For Arduino IDE V2, override the filesys
|
||||
restriction using ``flatpak override --user --filesystem=host cc.arduino.IDE2`` . For
|
||||
For Arduino IDE < V2, use ``flatpak override --user --filesystem=host cc.arduino.arduinoide``.
|
||||
|
||||
Installing via Arduino CLI
|
||||
--------------------------
|
||||
To install using the Arduino command line tool (arduino-cli):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
arduino-cli config add board_manager.additional_urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
arduino-cli core update-index
|
||||
arduino-cli core install rp2040:rp2040
|
||||
|
||||
To list the supported boards:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
arduino-cli board listall | grep rp2040
|
||||
|
||||
Installing via GIT
|
||||
------------------
|
||||
To install via GIT (for latest and greatest versions):
|
||||
|
||||
+12
-12
@@ -90,7 +90,7 @@ Signing requires the generation of an RSA-2048 key (other bit lengths are suppor
|
||||
Automatic Signing
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The simplest way of implementing signing is to use the automatic mode, which presently is only possible on Linux and Mac due to some of the tools not being available for Windows. This mode uses the IDE to configure the source code to enable sigining verification with a given public key, and signs binaries as part of the standard build process using a given public key.
|
||||
The simplest way of implementing signing is to use the automatic mode, which presently is only possible on Linux and Mac due to some of the tools not being available for Windows. This mode uses the IDE to configure the source code to enable signing verification with a given public key, and signs binaries as part of the standard build process using a given public key.
|
||||
|
||||
To enable this mode, just include `private.key` and `public.key` in the sketch `.ino` directory. The IDE will call a helper script (`tools/signing.py`) before the build begins to create a header to enable key validation using the given public key, and to actually do the signing after the build process, generating a `sketch.bin.signed` file. When OTA is enabled (ArduinoOTA, Web, or HTTP), the binary will automatically only accept signed updates.
|
||||
|
||||
@@ -140,11 +140,11 @@ Compile the sketch normally and, once a `.bin` file is available, sign it using
|
||||
Compression
|
||||
-----------
|
||||
|
||||
The eboot bootloader incorporates a GZIP decompressor, built for very low code requirements. For applications, this optional decompression is completely transparent. For uploading compressed filesystems, the application must be built with `ATOMIC_FS_UPDATE` defined because, otherwise, eboot will not be involved in writing the filesystem.
|
||||
The bootloader incorporates a GZIP decompressor, built for very low code requirements. For applications, this optional decompression is completely transparent.
|
||||
|
||||
No changes to the application are required. The `Updater` class and `eboot` bootloader (which performs actual application overwriting on update) automatically search for the `gzip` header in the uploaded binary, and if found, handle it.
|
||||
No changes to the application are required. The `Updater` class and bootloader (which performs actual application overwriting on update) automatically search for the `gzip` header in the uploaded binary, and if found, handle it.
|
||||
|
||||
Compress an application `.bin` file or filesystem package using any `gzip` available, at any desired compression level (`gzip -9` is recommended because it provides the maximum compression and uncompresses as fast as any other compressino level). For example:
|
||||
Compress an application `.bin` file or filesystem package using any `gzip` available, at any desired compression level (`gzip -9` is recommended because it provides the maximum compression and uncompresses as fast as any other compression level). For example:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
@@ -185,11 +185,11 @@ Uploading modules wirelessly from Arduino IDE is intended for the following typi
|
||||
|
||||
- Only if modules are accessible on the same network as the computer with the Arduino IDE.
|
||||
|
||||
- For all IDE uploads,m the Pico W and the computer must be connected to the same network.
|
||||
- For all IDE uploads, the Pico W and the computer must be connected to the same network.
|
||||
|
||||
To upload wirelessly from the IDE:
|
||||
|
||||
1. Build a sketch starts ``WiFi`` and includes the appropriare calls to ``ArduinoOTA`` (see the examples for reference). These include the ``ArduinoOTA.begin()`` call in ``setup()`` and periodically calling ``ArduinoOTA.handle();`` from the ``loop()``
|
||||
1. Build a sketch starts ``WiFi`` and includes the appropriate calls to ``ArduinoOTA`` (see the examples for reference). These include the ``ArduinoOTA.begin()`` call in ``setup()`` and periodically calling ``ArduinoOTA.handle();`` from the ``loop()``
|
||||
|
||||
2. Upload using standard USB connection the first time.
|
||||
|
||||
@@ -200,7 +200,7 @@ To upload wirelessly from the IDE:
|
||||
Password Protection
|
||||
-------------------
|
||||
|
||||
Protecting your OTA uploads with password is really straightforward. All you need to do, is to include the following statement in your code:
|
||||
Protecting your OTA uploads with a password is really straightforward. All you need to do, is to include the following statement in your code:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
@@ -208,11 +208,11 @@ Protecting your OTA uploads with password is really straightforward. All you nee
|
||||
|
||||
Where ``123`` is a sample password that you should replace with your own.
|
||||
|
||||
Before implementing it in your sketch, it is a good idea to check how it works using *BasicOTA.ino* sketch available under *File > Examples > ArduinoOTA*. Go ahead, open *BasicOTA.ino*, uncomment the above statement that is already there, and upload the sketch. To make troubleshooting easier, do not modify example sketch besides what is absolutely required. This is including original simple ``123`` OTA password. Then attempt to upload sketch again (using OTA). After compilation is complete, once upload is about to begin, you should see prompt for password.
|
||||
Before implementing it in your sketch, it is a good idea to check how it works using *BasicOTA.ino* sketch available under *File > Examples > ArduinoOTA*. Go ahead, open *BasicOTA.ino*, uncomment the above statement that is already there, and upload the sketch. To make troubleshooting easier, do not modify example sketch besides what is absolutely required. This includes the original simple ``123`` OTA password. Then attempt to upload a sketch again (using OTA). After compilation is complete, once upload is about to begin, you should see a prompt for password.
|
||||
|
||||
Enter the password and upload should be initiated as usual with the only difference being ``Authenticating...OK`` message visible in upload log.
|
||||
Enter the password and upload should be initiated as usual with the only difference being ``Authenticating...OK`` message visible in the upload log.
|
||||
|
||||
You will not be prompted for a reentering the same password next time. Arduino IDE will remember it for you. You will see prompt for password only after reopening IDE, or if you change it in your sketch, upload the sketch and then try to upload it again.
|
||||
You will not be prompted for a reentering the same password next time. Arduino IDE will remember it for you. You will see a prompt for password only after reopening IDE, or if you change it in your sketch, upload the sketch and then try to upload it again.
|
||||
|
||||
Please note, it is possible to reveal password entered previously in Arduino IDE, if IDE has not been closed since last upload. This can be done by enabling *Show verbose output during: upload* in *File > Preferences* and attempting to upload the module.
|
||||
|
||||
@@ -289,7 +289,7 @@ Simple updater downloads the file every time the function is called.
|
||||
Advanced updater
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Its possible to point the update function to a script on the server. If a version string argument is given, it will be sent to the server. The server side script can use this string to check whether an update should be performed.
|
||||
It's possible to point the update function to a script on the server. If a version string argument is given, it will be sent to the server. The server side script can use this string to check whether an update should be performed.
|
||||
|
||||
The server-side script can respond as follows: - response code 200, and send the firmware image, - or response code 304 to notify Pico that no update is required.
|
||||
|
||||
@@ -305,7 +305,7 @@ The server-side script can respond as follows: - response code 200, and send the
|
||||
Serial.println("[update] Update no Update.");
|
||||
break;
|
||||
case HTTP_UPDATE_OK:
|
||||
Serial.println("[update] Update ok."); // may not be called since we reboot the RP2040
|
||||
Serial.println("[update] Update ok.");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,3 +95,7 @@ void rp2040.enableDoubleResetBootloader()
|
||||
Add a call anywhere in the sketch to ``rp2040.enableDoubleResetBootloader()`` and
|
||||
the core will check for a double-tap on reset, and if found will start the USB
|
||||
bootloader.
|
||||
|
||||
void rp2040.rebootToBootloader()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Will reboot the RP2040 into USB UF2 upload mode.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#define PICO_SDK_VERSION_MAJOR 1
|
||||
#define PICO_SDK_VERSION_MINOR 5
|
||||
#define PICO_SDK_VERSION_REVISION 0
|
||||
#define PICO_SDK_VERSION_STRING "1.5.0"
|
||||
#define PICO_SDK_VERSION_REVISION 1
|
||||
#define PICO_SDK_VERSION_STRING "1.5.1"
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -94,7 +94,9 @@ SECTIONS
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
*(.init)
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
|
||||
/* Some of these excludes required for PicoDVI library, won't affect most code */
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a: *interp.c.obj *divider.S.obj *PicoDVI.cpp.o *dvi.c.o) .text*)
|
||||
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
|
||||
@@ -79,6 +79,10 @@ void ADCInput::onReceive(void(*fn)(void)) {
|
||||
}
|
||||
|
||||
bool ADCInput::begin() {
|
||||
if (_running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
|
||||
_isHolding = 0;
|
||||
@@ -105,7 +109,11 @@ bool ADCInput::begin() {
|
||||
setFrequency(_freq);
|
||||
|
||||
_arb = new AudioBufferManager(_buffers, _bufferWords, 0, INPUT, DMA_SIZE_16);
|
||||
_arb->begin(DREQ_ADC, (volatile void*)&adc_hw->fifo);
|
||||
if (!_arb->begin(DREQ_ADC, (volatile void*)&adc_hw->fifo)) {
|
||||
delete _arb;
|
||||
_arb = nullptr;
|
||||
return false;
|
||||
}
|
||||
_arb->setCallback(_cb);
|
||||
|
||||
adc_fifo_drain();
|
||||
|
||||
Submodule libraries/Adafruit_TinyUSB_Arduino updated: a2bcb19f6c...b17ab37a0e
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/irq.h"
|
||||
#include <hardware/dma.h>
|
||||
#include <hardware/irq.h>
|
||||
#include "AudioBufferManager.h"
|
||||
|
||||
static int __channelCount = 0; // # of channels left. When we hit 0, then remove our handler
|
||||
@@ -78,8 +78,8 @@ AudioBufferManager::~AudioBufferManager() {
|
||||
dma_channel_abort(_channelDMA[i]);
|
||||
dma_channel_unclaim(_channelDMA[i]);
|
||||
dma_channel_acknowledge_irq0(_channelDMA[i]);
|
||||
__channelCount--;
|
||||
}
|
||||
__channelCount--;
|
||||
if (!__channelCount) {
|
||||
irq_set_enabled(DMA_IRQ_0, false);
|
||||
// TODO - how can we know if there are no other parts of the core using DMA0 IRQ??
|
||||
@@ -114,7 +114,7 @@ bool AudioBufferManager::begin(int dreq, volatile void *pioFIFOAddr) {
|
||||
|
||||
// Get ping and pong DMA channels
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
_channelDMA[i] = dma_claim_unused_channel(true);
|
||||
_channelDMA[i] = dma_claim_unused_channel(false);
|
||||
if (_channelDMA[i] == -1) {
|
||||
if (i == 1) {
|
||||
dma_channel_unclaim(_channelDMA[0]);
|
||||
@@ -257,7 +257,7 @@ void __not_in_flash_func(AudioBufferManager::_dmaIRQ)(int channel) {
|
||||
_active[1] = _takeFromList(&_filled);
|
||||
}
|
||||
_overunderflow = _overunderflow | (_active[1] == _silence);
|
||||
dma_channel_set_read_addr(channel, _active[0]->buff, false);
|
||||
dma_channel_set_read_addr(channel, _active[1]->buff, false);
|
||||
} else {
|
||||
if (_empty) {
|
||||
_addToList(&_filled, _active[0]);
|
||||
@@ -266,7 +266,7 @@ void __not_in_flash_func(AudioBufferManager::_dmaIRQ)(int channel) {
|
||||
} else {
|
||||
_overunderflow = true;
|
||||
}
|
||||
dma_channel_set_write_addr(channel, _active[0]->buff, false);
|
||||
dma_channel_set_write_addr(channel, _active[1]->buff, false);
|
||||
}
|
||||
dma_channel_set_trans_count(channel, _wordsPerBuffer * (_dmaSize == DMA_SIZE_16 ? 2 : 1), false);
|
||||
dma_channel_acknowledge_irq0(channel);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "hardware/dma.h"
|
||||
#include <hardware/dma.h>
|
||||
|
||||
class AudioBufferManager {
|
||||
public:
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <BTstackLib.h>
|
||||
#include <SPI.h>
|
||||
|
||||
/*
|
||||
EXAMPLE_START(LEDeviceScanner): LE Device Scanner
|
||||
|
||||
@text The LE Device Scanner monitors BLE device advertisements,
|
||||
keeping track of one or more known devices as they appear.
|
||||
*/
|
||||
|
||||
// Application state
|
||||
int counter[2] = {0, 0};
|
||||
BD_ADDR known_devices[2] = {BD_ADDR("DB:88:B6:70:9E:EB"),
|
||||
BD_ADDR("C9:60:BD:F2:B4:9D")
|
||||
};
|
||||
|
||||
/*
|
||||
@section Setup
|
||||
|
||||
@text After BTstack.setup(), BTstack is configured to call
|
||||
advertisementCallback whenever an Advertisement was received.
|
||||
*/
|
||||
/* LISTING_START(LEDeviceScannerSetup): LE Device Scanner Setup */
|
||||
void setup(void) {
|
||||
Serial.begin(9600);
|
||||
BTstack.setBLEAdvertisementCallback(advertisementCallback);
|
||||
BTstack.setup();
|
||||
BTstack.bleStartScanning();
|
||||
}
|
||||
/* LISTING_END(LEDeviceScannerSetup): LE Device Scanner Setup */
|
||||
|
||||
/*
|
||||
@section Loop
|
||||
|
||||
@text In the standard Arduino loop() function, BTstack's loop() is called.
|
||||
*/
|
||||
/* LISTING_START(LEDeviceScannerLoop): Loop */
|
||||
void loop(void) {
|
||||
BTstack.loop();
|
||||
}
|
||||
/* LISTING_END(LEDeviceScannerLoop): Loop */
|
||||
|
||||
/*
|
||||
@section Advertisement Callback
|
||||
|
||||
@text Whenever an Advertisement is received, isIBeacon() checks if
|
||||
it contains an iBeacon.
|
||||
|
||||
If it's not an iBeacon, the BD_ADDR is compared to the address we are
|
||||
looking for and the counter is incremented.
|
||||
*/
|
||||
/* LISTING_START(LEDeviceScannerAdvertisementCallback): Advertisement Callback
|
||||
*/
|
||||
void advertisementCallback(BLEAdvertisement *bleAdvertisement) {
|
||||
if (!(bleAdvertisement->isIBeacon())) {
|
||||
Serial.print("Device discovered: ");
|
||||
Serial.println(bleAdvertisement->getBdAddr()->getAddressString());
|
||||
for (size_t i = 0; i < sizeof(counter) / sizeof(int); i++) {
|
||||
if (memcmp(bleAdvertisement->getBdAddr()->getAddress(),
|
||||
known_devices[i].getAddress(), sizeof(known_devices[i])) == 0) {
|
||||
counter[i]++;
|
||||
Serial.printf("Known device: %s, has been discovered %d times.\n",
|
||||
known_devices[i].getAddressString(), counter[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* LISTING_END(LEDeviceScannerAdvertisementCallback): Advertisement Callback */
|
||||
@@ -396,9 +396,13 @@ BD_ADDR::BD_ADDR(void) {
|
||||
}
|
||||
|
||||
BD_ADDR::BD_ADDR(const char * address_string, BD_ADDR_TYPE address_type) : address_type(address_type) {
|
||||
(void) address_string;
|
||||
// TODO: implement
|
||||
// log_error("BD_ADDR::BD_ADDR(const char *, BD_ADDR_TYPE) not implemented yet!");
|
||||
int processed = sscanf(address_string, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", address, address + 1,
|
||||
address + 2, address + 3, address + 4, address + 5);
|
||||
if (processed != 6) { // Set address to zeroes if we did not get six bytes back.
|
||||
for (int i = 0; i < 6; i++) {
|
||||
address[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BD_ADDR::BD_ADDR(const uint8_t address[6], BD_ADDR_TYPE address_type) : address_type(address_type) {
|
||||
@@ -774,6 +778,10 @@ static hci_transport_config_uart_t config = {
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
void BTstackManager::setup(void) {
|
||||
setup("BTstack LE Shield");
|
||||
}
|
||||
|
||||
void BTstackManager::setup(const char * name) {
|
||||
|
||||
//#ifdef PIN_LED
|
||||
// pinMode(PIN_LED, OUTPUT);
|
||||
@@ -822,7 +830,6 @@ void BTstackManager::setup(void) {
|
||||
const uint8_t flags[] = { 0x02, 0x01, 0x02 };
|
||||
memcpy(&adv_data[pos], flags, sizeof(flags));
|
||||
pos += sizeof(flags);
|
||||
const char * name = "BTstack LE Shield";
|
||||
adv_data[pos++] = strlen(name) + 1;
|
||||
adv_data[pos++] = 0x09;
|
||||
memcpy(&adv_data[pos], name, strlen(name));
|
||||
|
||||
@@ -135,6 +135,7 @@ extern "C" {
|
||||
public:
|
||||
BTstackManager(void);
|
||||
void setup(void);
|
||||
void setup(const char * name);
|
||||
void loop(void);
|
||||
|
||||
void setPublicBdAddr(bd_addr_t addr);
|
||||
|
||||
@@ -36,6 +36,7 @@ pcTaskGetName KEYWORD2
|
||||
ulTaskNotifyTake KEYWORD2
|
||||
vTaskNotifyGiveFromISR KEYWORD2
|
||||
taskYIELD KEYWORD2
|
||||
vTaskCoreAffinitySet KEYWORD2
|
||||
vTaskSuspend KEYWORD2
|
||||
vTaskResume KEYWORD2
|
||||
xTaskResumeFromISR KEYWORD2
|
||||
@@ -43,6 +44,7 @@ xTaskGetTickCount KEYWORD2
|
||||
xTaskGetTickCountFromISR KEYWORD2
|
||||
uxTaskGetNumberOfTasks KEYWORD2
|
||||
uxTaskGetStackHighWaterMark KEYWORD2
|
||||
uxTaskGetSystemState KEYWORD2
|
||||
|
||||
# Instances (KEYWORD2)
|
||||
|
||||
|
||||
Submodule libraries/FreeRTOS/lib/FreeRTOS-Kernel updated: b5942ddd07...29fdcf092a
@@ -29,10 +29,7 @@
|
||||
#define configUSE_TASK_PREEMPTION_DISABLE 1
|
||||
|
||||
#define configUSE_NEWLIB_REENTRANT 1
|
||||
#define configNEWLIB_REENTRANT_IS_DYNAMIC 0 /* Note that we have a different config option, portSET_IMPURE_PTR */
|
||||
#include <reent.h>
|
||||
extern void __register_impure_ptr(struct _reent *p);
|
||||
#define portSET_IMPURE_PTR(x) __register_impure_ptr(x)
|
||||
#define configNEWLIB_REENTRANT_IS_DYNAMIC 1
|
||||
|
||||
/* Run time stats related definitions. */
|
||||
void vMainConfigureTimerForRunTimeStats(void);
|
||||
|
||||
@@ -1 +1,14 @@
|
||||
#include "../lib/FreeRTOS-Kernel/tasks.c"
|
||||
|
||||
//See https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/496
|
||||
struct _reent* __wrap___getreent(void) {
|
||||
// No lock needed because if this changes, we won't be running anymore.
|
||||
TCB_t *pxCurTask = xTaskGetCurrentTaskHandle();
|
||||
if (pxCurTask == NULL) {
|
||||
// No task running. Return global struct.
|
||||
return _GLOBAL_REENT;
|
||||
} else {
|
||||
// We have a task; return its reentrant struct.
|
||||
return &pxCurTask->xNewLib_reent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,59 @@
|
||||
#include <pico.h>
|
||||
#include <pico/time.h>
|
||||
|
||||
#include "_freertos.h"
|
||||
#include <_freertos.h>
|
||||
|
||||
// Interfaces for the main core to use FreeRTOS mutexes
|
||||
extern "C" {
|
||||
extern volatile bool __otherCoreIdled;
|
||||
|
||||
SemaphoreHandle_t __freertos_mutex_create() {
|
||||
return xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
SemaphoreHandle_t _freertos_recursive_mutex_create() {
|
||||
return xSemaphoreCreateRecursiveMutex();
|
||||
}
|
||||
|
||||
void __freertos_mutex_take(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreTake(mtx, portMAX_DELAY);
|
||||
}
|
||||
|
||||
int __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx, BaseType_t* pxHigherPriorityTaskWoken) {
|
||||
return xSemaphoreTakeFromISR(mtx, pxHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
int __freertos_mutex_try_take(SemaphoreHandle_t mtx) {
|
||||
return xSemaphoreTake(mtx, 0);
|
||||
}
|
||||
|
||||
void __freertos_mutex_give(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreGive(mtx);
|
||||
}
|
||||
|
||||
void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx, BaseType_t* pxHigherPriorityTaskWoken) {
|
||||
BaseType_t hiPrio = pxHigherPriorityTaskWoken ? *pxHigherPriorityTaskWoken : pdFALSE;
|
||||
xSemaphoreGiveFromISR(mtx, &hiPrio);
|
||||
portYIELD_FROM_ISR(hiPrio);
|
||||
}
|
||||
|
||||
void __freertos_recursive_mutex_take(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreTakeRecursive(mtx, portMAX_DELAY);
|
||||
}
|
||||
|
||||
int __freertos_recursive_mutex_try_take(SemaphoreHandle_t mtx) {
|
||||
return xSemaphoreTakeRecursive(mtx, 0);
|
||||
}
|
||||
|
||||
void __freertos_recursive_mutex_give(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreGiveRecursive(mtx);
|
||||
}
|
||||
|
||||
bool __freertos_check_if_in_isr() {
|
||||
return portCHECK_IF_IN_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@@ -108,6 +160,40 @@ extern "C" void yield() {
|
||||
taskYIELD();
|
||||
}
|
||||
|
||||
static TaskHandle_t __idleCoreTask[2];
|
||||
static void __no_inline_not_in_flash_func(IdleThisCore)(void *param) {
|
||||
(void) param;
|
||||
while (true) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
vTaskPreemptionDisable(nullptr);
|
||||
portDISABLE_INTERRUPTS();
|
||||
__otherCoreIdled = true;
|
||||
while (__otherCoreIdled) {
|
||||
/* noop */
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
vTaskPreemptionEnable(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __no_inline_not_in_flash_func(__freertos_idle_other_core)() {
|
||||
vTaskPreemptionDisable(nullptr);
|
||||
xTaskNotifyGive(__idleCoreTask[ 1 ^ sio_hw->cpuid ]);
|
||||
while (!__otherCoreIdled) {
|
||||
/* noop */
|
||||
}
|
||||
portDISABLE_INTERRUPTS();
|
||||
vTaskSuspendAll();
|
||||
}
|
||||
|
||||
extern "C" void __no_inline_not_in_flash_func(__freertos_resume_other_core)() {
|
||||
__otherCoreIdled = false;
|
||||
portENABLE_INTERRUPTS();
|
||||
xTaskResumeAll();
|
||||
vTaskPreemptionEnable(nullptr);
|
||||
}
|
||||
|
||||
|
||||
extern mutex_t __usb_mutex;
|
||||
static TaskHandle_t __usbTask;
|
||||
static void __usb(void *param);
|
||||
@@ -124,6 +210,12 @@ void startFreeRTOS(void) {
|
||||
vTaskCoreAffinitySet(c1, 1 << 1);
|
||||
}
|
||||
|
||||
// Create the idle-other-core tasks (for when flash is being written)
|
||||
xTaskCreate(IdleThisCore, "IdleCore0", 128, 0, configMAX_PRIORITIES - 1, __idleCoreTask + 0);
|
||||
vTaskCoreAffinitySet(__idleCoreTask[0], 1 << 0);
|
||||
xTaskCreate(IdleThisCore, "IdleCore1", 128, 0, configMAX_PRIORITIES - 1, __idleCoreTask + 1);
|
||||
vTaskCoreAffinitySet(__idleCoreTask[1], 1 << 1);
|
||||
|
||||
// Initialise and run the freeRTOS scheduler. Execution should never return here.
|
||||
__freeRTOSinitted = true;
|
||||
vTaskStartScheduler();
|
||||
@@ -398,54 +490,7 @@ void __USBStart() {
|
||||
__SetupDescHIDReport();
|
||||
__SetupUSBDescriptor();
|
||||
|
||||
// Make highest prio and locked to core 0
|
||||
xTaskCreate(__usb, "USB", 256, 0, configMAX_PRIORITIES - 1, &__usbTask);
|
||||
// Make high prio and locked to core 0
|
||||
xTaskCreate(__usb, "USB", 256, 0, configMAX_PRIORITIES - 2, &__usbTask);
|
||||
vTaskCoreAffinitySet(__usbTask, 1 << 0);
|
||||
}
|
||||
|
||||
|
||||
// Interfaces for the main core to use FreeRTOS mutexes
|
||||
extern "C" {
|
||||
|
||||
SemaphoreHandle_t __freertos_mutex_create() {
|
||||
return xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
SemaphoreHandle_t _freertos_recursive_mutex_create() {
|
||||
return xSemaphoreCreateRecursiveMutex();
|
||||
}
|
||||
|
||||
void __freertos_mutex_take(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreTake(mtx, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreTakeFromISR(mtx, NULL);
|
||||
}
|
||||
|
||||
int __freertos_mutex_try_take(SemaphoreHandle_t mtx) {
|
||||
return xSemaphoreTake(mtx, 0);
|
||||
}
|
||||
|
||||
void __freertos_mutex_give(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreGive(mtx);
|
||||
}
|
||||
|
||||
void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreGiveFromISR(mtx, NULL);
|
||||
}
|
||||
|
||||
void __freertos_recursive_mutex_take(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreTakeRecursive(mtx, portMAX_DELAY);
|
||||
}
|
||||
|
||||
int __freertos_recursive_mutex_try_take(SemaphoreHandle_t mtx) {
|
||||
return xSemaphoreTakeRecursive(mtx, 0);
|
||||
}
|
||||
|
||||
void __freertos_recursive_mutex_give(SemaphoreHandle_t mtx) {
|
||||
xSemaphoreGiveRecursive(mtx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -282,11 +282,7 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& curren
|
||||
_cbEnd();
|
||||
}
|
||||
|
||||
#ifdef ATOMIC_FS_UPDATE
|
||||
if (_rebootOnUpdate) {
|
||||
#else
|
||||
if (_rebootOnUpdate && !spiffs) {
|
||||
#endif
|
||||
rp2040.restart();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
This example demonstrates I2S output with the optional MCLK signal.
|
||||
Note: System clock sppeds used here may not be compatible with all other libraries
|
||||
requiring specific sys_clks, particularly Pico PIO USB.
|
||||
|
||||
Original 17 November 2016
|
||||
by Sandeep Mistry
|
||||
modified for RP2040 by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
bool setBCLK(pin_size_t pin);
|
||||
- This assigns two adjacent pins - the pin after this one (one greater)
|
||||
is the WS (word select) signal, which toggles before the sample for
|
||||
each channel is sent
|
||||
|
||||
bool setDATA(pin_size_t pin);
|
||||
- Sets the DOUT pin, can be any valid GPIO pin
|
||||
|
||||
|
||||
modified for MCLK by Richard Palmer June 2023
|
||||
*/
|
||||
|
||||
#include <I2S.h>
|
||||
|
||||
// Create the I2S port using a PIO state machine
|
||||
I2S i2s(OUTPUT);
|
||||
|
||||
// GPIO pin numbers
|
||||
#define pDOUT 19
|
||||
#define pBCLK 20
|
||||
#define pWS (pBCLK+1)
|
||||
#define pMCLK 22 // optional MCLK pin
|
||||
|
||||
const int frequency = 440; // frequency of square wave in Hz
|
||||
const int sampleRate = 16000; // minimum for many i2s DACs
|
||||
const int bitsPerSample = 16;
|
||||
const int amplitude = 1 << (bitsPerSample - 2); // amplitude of square wave = 1/2 of maximum
|
||||
|
||||
#define MCLK_MUL 256 // depends on audio hardware. Suits common hardware.
|
||||
|
||||
const int halfWavelength = sampleRate / (2 * frequency); // half wavelength of square wave
|
||||
|
||||
int16_t sample = amplitude; // current sample value
|
||||
int count = 0;
|
||||
|
||||
void setup() {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, 1);
|
||||
|
||||
// set the system clock to a compatible value to the samplerate
|
||||
i2s.setSysClk(sampleRate); // best to do this before starting anything clock-dependent
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.println("I2S with MCLK - square wave");
|
||||
|
||||
i2s.setBCLK(pBCLK);
|
||||
i2s.setDATA(pDOUT);
|
||||
i2s.setMCLK(pMCLK); // must be run before setFrequency() and i2s.begin()
|
||||
i2s.setMCLKmult(MCLK_MUL); // also before i2s.begin()
|
||||
i2s.setBitsPerSample(16);
|
||||
|
||||
// start I2S at the sample rate with 16-bits per sample
|
||||
if (!i2s.begin(sampleRate)) {
|
||||
Serial.println("Failed to initialize I2S!");
|
||||
while (100); // do nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (count % halfWavelength == 0) {
|
||||
// invert the sample every half wavelength count multiple to generate square wave
|
||||
sample = -1 * sample;
|
||||
}
|
||||
|
||||
// write the same sample twice, once for left and once for the right channel
|
||||
i2s.write(sample);
|
||||
i2s.write(sample);
|
||||
|
||||
// increment the counter for the next sample
|
||||
count++;
|
||||
}
|
||||
@@ -16,11 +16,14 @@ end KEYWORD2
|
||||
|
||||
setBCLK KEYWORD2
|
||||
setDATA KEYWORD2
|
||||
setMCLK KEYWORD2
|
||||
setBitsPerSample KEYWORD2
|
||||
setFrequency KEYWORD2
|
||||
setBuffers KEYWORD2
|
||||
setLSBJFormat KEYWORD2
|
||||
swapClocks KEYWORD2
|
||||
setMCLKmult KEYWORD2
|
||||
setSysClk KEYWORD2
|
||||
|
||||
read8 KEYWORD2
|
||||
read16 KEYWORD2
|
||||
|
||||
+91
-14
@@ -21,6 +21,7 @@
|
||||
#include <Arduino.h>
|
||||
#include "I2S.h"
|
||||
#include "pio_i2s.pio.h"
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
|
||||
I2S::I2S(PinMode direction) {
|
||||
@@ -30,6 +31,8 @@ I2S::I2S(PinMode direction) {
|
||||
_isOutput = direction == OUTPUT;
|
||||
_pinBCLK = 26;
|
||||
_pinDOUT = 28;
|
||||
_pinMCLK = 25;
|
||||
_MCLKenabled = false;
|
||||
#ifdef PIN_I2S_BCLK
|
||||
_pinBCLK = PIN_I2S_BCLK;
|
||||
#endif
|
||||
@@ -48,14 +51,16 @@ I2S::I2S(PinMode direction) {
|
||||
_freq = 48000;
|
||||
_arb = nullptr;
|
||||
_cb = nullptr;
|
||||
_buffers = 8;
|
||||
_buffers = 6;
|
||||
_bufferWords = 0;
|
||||
_silenceSample = 0;
|
||||
_isLSBJ = false;
|
||||
_swapClocks = false;
|
||||
_multMCLK = 256;
|
||||
}
|
||||
|
||||
I2S::~I2S() {
|
||||
end();
|
||||
}
|
||||
|
||||
bool I2S::setBCLK(pin_size_t pin) {
|
||||
@@ -66,6 +71,14 @@ bool I2S::setBCLK(pin_size_t pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool I2S::setMCLK(pin_size_t pin) {
|
||||
if (_running || (pin > 28)) {
|
||||
return false;
|
||||
}
|
||||
_pinMCLK = pin;
|
||||
return true;
|
||||
}
|
||||
bool I2S::setDATA(pin_size_t pin) {
|
||||
if (_running || (pin > 29)) {
|
||||
return false;
|
||||
@@ -95,12 +108,41 @@ bool I2S::setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample)
|
||||
bool I2S::setFrequency(int newFreq) {
|
||||
_freq = newFreq;
|
||||
if (_running) {
|
||||
float bitClk = _freq * _bps * 2.0 /* channels */ * 2.0 /* edges per clock */;
|
||||
pio_sm_set_clkdiv(_pio, _sm, (float)clock_get_hz(clk_sys) / bitClk);
|
||||
if (_MCLKenabled) {
|
||||
int bitClk = _freq * _bps * 2.0 /* channels */ * 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 * 2.0 /* channels */ * 2.0 /* edges per clock */;
|
||||
pio_sm_set_clkdiv(_pio, _sm, (float)clock_get_hz(clk_sys) / bitClk);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2S::setSysClk(int samplerate) { // optimise sys_clk for desired samplerate
|
||||
if (samplerate % 11025 == 0) {
|
||||
set_sys_clock_khz(I2SSYSCLK_44_1, false); // 147.6 unsuccessful - no I2S no USB
|
||||
return true;
|
||||
}
|
||||
if (samplerate % 8000 == 0) {
|
||||
set_sys_clock_khz(I2SSYSCLK_8, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool I2S::setMCLKmult(int mult) {
|
||||
if (_running || !_isOutput) {
|
||||
return false;
|
||||
}
|
||||
if ((mult % 64) == 0) {
|
||||
_MCLKenabled = true;
|
||||
_multMCLK = mult;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool I2S::setLSBJFormat() {
|
||||
if (_running || !_isOutput) {
|
||||
return false;
|
||||
@@ -135,16 +177,32 @@ void I2S::onReceive(void(*fn)(void)) {
|
||||
}
|
||||
}
|
||||
|
||||
void I2S::MCLKbegin() {
|
||||
int off = 0;
|
||||
_i2sMCLK = new PIOProgram(&pio_i2s_mclk_program);
|
||||
_i2sMCLK->prepare(&_pioMCLK, &_smMCLK, &off); // not sure how to use the same PIO
|
||||
pio_i2s_MCLK_program_init(_pioMCLK, _smMCLK, off, _pinMCLK);
|
||||
int mClk = _multMCLK * _freq * 2.0 /* edges per clock */;
|
||||
pio_sm_set_clkdiv_int_frac(_pioMCLK, _smMCLK, clock_get_hz(clk_sys) / mClk, 0);
|
||||
pio_sm_set_enabled(_pioMCLK, _smMCLK, true);
|
||||
}
|
||||
|
||||
bool I2S::begin() {
|
||||
_running = true;
|
||||
_hasPeeked = false;
|
||||
_isHolding = 0;
|
||||
int off = 0;
|
||||
if (!_swapClocks) {
|
||||
_i2s = new PIOProgram(_isOutput ? (_isLSBJ ? &pio_lsbj_out_program : &pio_i2s_out_program) : &pio_i2s_in_program);
|
||||
} else {
|
||||
_i2s = new PIOProgram(_isOutput ? (_isLSBJ ? &pio_lsbj_out_swap_program : &pio_i2s_out_swap_program) : &pio_i2s_in_swap_program);
|
||||
}
|
||||
_i2s->prepare(&_pio, &_sm, &off);
|
||||
if (!_i2s->prepare(&_pio, &_sm, &off)) {
|
||||
_running = false;
|
||||
delete _i2s;
|
||||
_i2s = nullptr;
|
||||
return false;
|
||||
}
|
||||
if (_isOutput) {
|
||||
if (_isLSBJ) {
|
||||
pio_lsbj_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
|
||||
@@ -155,6 +213,9 @@ bool I2S::begin() {
|
||||
pio_i2s_in_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
|
||||
}
|
||||
setFrequency(_freq);
|
||||
if (_MCLKenabled) {
|
||||
MCLKbegin();
|
||||
}
|
||||
if (_bps == 8) {
|
||||
uint8_t a = _silenceSample & 0xff;
|
||||
_silenceSample = (a << 24) | (a << 16) | (a << 8) | a;
|
||||
@@ -163,10 +224,17 @@ bool I2S::begin() {
|
||||
_silenceSample = (a << 16) | a;
|
||||
}
|
||||
if (!_bufferWords) {
|
||||
_bufferWords = 16 * (_bps == 32 ? 2 : 1);
|
||||
_bufferWords = 64 * (_bps == 32 ? 2 : 1);
|
||||
}
|
||||
_arb = new AudioBufferManager(_buffers, _bufferWords, _silenceSample, _isOutput ? OUTPUT : INPUT);
|
||||
_arb->begin(pio_get_dreq(_pio, _sm, _isOutput), _isOutput ? &_pio->txf[_sm] : (volatile void*)&_pio->rxf[_sm]);
|
||||
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;
|
||||
}
|
||||
_arb->setCallback(_cb);
|
||||
pio_sm_set_enabled(_pio, _sm, true);
|
||||
|
||||
@@ -175,6 +243,11 @@ bool I2S::begin() {
|
||||
|
||||
void I2S::end() {
|
||||
if (_running) {
|
||||
if (_MCLKenabled) {
|
||||
pio_sm_set_enabled(_pioMCLK, _smMCLK, false);
|
||||
delete _i2sMCLK;
|
||||
_i2sMCLK = nullptr;
|
||||
}
|
||||
pio_sm_set_enabled(_pio, _sm, false);
|
||||
_running = false;
|
||||
delete _arb;
|
||||
@@ -187,10 +260,13 @@ void I2S::end() {
|
||||
int I2S::available() {
|
||||
if (!_running) {
|
||||
return 0;
|
||||
} else if (_isOutput) {
|
||||
return availableForWrite(); // Do what I mean, not what I say
|
||||
} else {
|
||||
return _arb->available();
|
||||
auto avail = _arb->available();
|
||||
avail *= 4; // 4 samples per 32-bits
|
||||
if (_bps < 24 && !_isOutput) {
|
||||
avail += _isHolding / 8;
|
||||
}
|
||||
return avail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +295,7 @@ int I2S::read() {
|
||||
case 16:
|
||||
ret = _holdWord >> 16;
|
||||
_holdWord <<= 16;
|
||||
_isHolding -= 32;
|
||||
_isHolding -= 16;
|
||||
return ret;
|
||||
case 24:
|
||||
case 32:
|
||||
@@ -376,13 +452,14 @@ bool I2S::read32(int32_t *l, int32_t *r) {
|
||||
|
||||
size_t I2S::write(const uint8_t *buffer, size_t size) {
|
||||
// We can only write 32-bit chunks here
|
||||
if (size & 0x3) {
|
||||
if (size & 0x3 || !_running || !_isOutput) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t writtenSize = 0;
|
||||
int32_t *p = (int32_t *)buffer;
|
||||
uint32_t *p = (uint32_t *)buffer;
|
||||
while (size) {
|
||||
if (!write((int32_t)*p)) {
|
||||
if (!_arb->write(*p, false)) {
|
||||
// Blocked, stop write here
|
||||
return writtenSize;
|
||||
} else {
|
||||
@@ -398,5 +475,5 @@ int I2S::availableForWrite() {
|
||||
if (!_running || !_isOutput) {
|
||||
return 0;
|
||||
}
|
||||
return _arb->available();
|
||||
return available();
|
||||
}
|
||||
|
||||
+22
-2
@@ -30,11 +30,14 @@ public:
|
||||
|
||||
bool setBCLK(pin_size_t pin);
|
||||
bool setDATA(pin_size_t pin);
|
||||
bool setMCLK(pin_size_t pin);
|
||||
bool setBitsPerSample(int bps);
|
||||
bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0);
|
||||
bool setFrequency(int newFreq);
|
||||
bool setLSBJFormat();
|
||||
bool swapClocks();
|
||||
bool setMCLKmult(int mult);
|
||||
bool setSysClk(int samplerate);
|
||||
|
||||
bool begin(long sampleRate) {
|
||||
setFrequency(sampleRate);
|
||||
@@ -54,6 +57,15 @@ public:
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) override;
|
||||
virtual int availableForWrite() override;
|
||||
|
||||
// From the AR
|
||||
bool getOverUnderflow() {
|
||||
if (!_running) {
|
||||
return false;
|
||||
} else {
|
||||
return _arb->getOverUnderflow();
|
||||
}
|
||||
}
|
||||
|
||||
// Try and make I2S::write() do what makes sense, namely write
|
||||
// one sample (L or R) at the I2S configured bit width
|
||||
virtual size_t write(uint8_t s) override {
|
||||
@@ -101,14 +113,17 @@ public:
|
||||
private:
|
||||
pin_size_t _pinBCLK;
|
||||
pin_size_t _pinDOUT;
|
||||
pin_size_t _pinMCLK;
|
||||
int _bps;
|
||||
int _freq;
|
||||
int _multMCLK;
|
||||
size_t _buffers;
|
||||
size_t _bufferWords;
|
||||
int32_t _silenceSample;
|
||||
bool _isLSBJ;
|
||||
bool _isOutput;
|
||||
bool _swapClocks;
|
||||
bool _MCLKenabled;
|
||||
|
||||
bool _running;
|
||||
|
||||
@@ -123,9 +138,14 @@ private:
|
||||
int _isHolding = 0;
|
||||
|
||||
void (*_cb)();
|
||||
void MCLKbegin();
|
||||
|
||||
AudioBufferManager *_arb;
|
||||
PIOProgram *_i2s;
|
||||
PIO _pio;
|
||||
int _sm;
|
||||
PIOProgram *_i2sMCLK;
|
||||
PIO _pio, _pioMCLK;
|
||||
int _sm, _smMCLK;
|
||||
|
||||
static const int I2SSYSCLK_44_1 = 135600; // 44.1, 88.2 kHz sample rates
|
||||
static const int I2SSYSCLK_8 = 147600; // 8k, 16, 32, 48, 96, 192 kHz
|
||||
};
|
||||
|
||||
@@ -19,7 +19,16 @@
|
||||
; License along with this library; if not, write to the Free Software
|
||||
; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
.program pio_i2s_mclk
|
||||
; PIO SM clock is MCLK x 2
|
||||
; MCLK/BCLK sync is maintained by ensuring IN/OUT PIO SM clock dividers
|
||||
; are x128, 384, 256, 512 or 768 multiples of MCLK SM divider as required.
|
||||
|
||||
loop_mclk:
|
||||
set pins, 1 ; toggle mclk
|
||||
set pins, 0
|
||||
; Loop back to beginning...
|
||||
|
||||
.program pio_i2s_out
|
||||
.side_set 2 ; 0 = bclk, 1=wclk
|
||||
|
||||
@@ -157,6 +166,14 @@ right:
|
||||
|
||||
% c-sdk {
|
||||
|
||||
static inline void pio_i2s_MCLK_program_init(PIO pio, uint sm, uint offset, uint MCLK_pin) {
|
||||
pio_gpio_init(pio, MCLK_pin);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, MCLK_pin, 1, true);
|
||||
pio_sm_config sm_config = pio_i2s_mclk_program_get_default_config(offset);
|
||||
sm_config_set_set_pins(&sm_config, MCLK_pin, 1);
|
||||
pio_sm_init(pio, sm, offset, &sm_config);
|
||||
}
|
||||
|
||||
static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) {
|
||||
pio_gpio_init(pio, data_pin);
|
||||
pio_gpio_init(pio, clock_pin_base);
|
||||
|
||||
@@ -8,6 +8,34 @@
|
||||
#include "hardware/pio.h"
|
||||
#endif
|
||||
|
||||
// ------------ //
|
||||
// pio_i2s_mclk //
|
||||
// ------------ //
|
||||
|
||||
#define pio_i2s_mclk_wrap_target 0
|
||||
#define pio_i2s_mclk_wrap 1
|
||||
|
||||
static const uint16_t pio_i2s_mclk_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xe001, // 0: set pins, 1
|
||||
0xe000, // 1: set pins, 0
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program pio_i2s_mclk_program = {
|
||||
.instructions = pio_i2s_mclk_program_instructions,
|
||||
.length = 2,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_i2s_mclk_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + pio_i2s_mclk_wrap_target, offset + pio_i2s_mclk_wrap);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ----------- //
|
||||
// pio_i2s_out //
|
||||
// ----------- //
|
||||
@@ -217,6 +245,13 @@ static inline pio_sm_config pio_i2s_in_swap_program_get_default_config(uint offs
|
||||
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);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, MCLK_pin, 1, true);
|
||||
pio_sm_config sm_config = pio_i2s_mclk_program_get_default_config(offset);
|
||||
sm_config_set_set_pins(&sm_config, MCLK_pin, 1);
|
||||
pio_sm_init(pio, sm, offset, &sm_config);
|
||||
}
|
||||
static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) {
|
||||
pio_gpio_init(pio, data_pin);
|
||||
pio_gpio_init(pio, clock_pin_base);
|
||||
@@ -264,4 +299,3 @@ static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint d
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#include "OpenPDMFilter.h"
|
||||
|
||||
extern "C" {
|
||||
#include "hardware/pio.h"
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include <hardware/pio.h>
|
||||
#include <hardware/dma.h>
|
||||
#include <hardware/clocks.h>
|
||||
}
|
||||
#include "hardware/sync.h"
|
||||
#include <hardware/sync.h>
|
||||
#include "pdm.pio.h"
|
||||
static PIOProgram _pdmPgm(&pdm_pio_program);
|
||||
|
||||
|
||||
@@ -100,6 +100,10 @@ void PWMAudio::onTransmit(void(*fn)(void)) {
|
||||
}
|
||||
|
||||
bool PWMAudio::begin() {
|
||||
if (_running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_stereo && (_pin & 1)) {
|
||||
// Illegal, need to have consecutive pins on the same PWM slice
|
||||
Serial.printf("ERROR: PWMAudio stereo mode requires pin be even\n");
|
||||
@@ -118,7 +122,13 @@ bool PWMAudio::begin() {
|
||||
uint32_t ccAddr = PWM_BASE + PWM_CH0_CC_OFFSET + pwm_gpio_to_slice_num(_pin) * 20;
|
||||
|
||||
_arb = new AudioBufferManager(_buffers, _bufferWords, 0x80008000, OUTPUT, DMA_SIZE_32);
|
||||
_arb->begin(pwm_get_dreq(pwm_gpio_to_slice_num(_pin)), (volatile void*)ccAddr);
|
||||
if (!_arb->begin(pwm_get_dreq(pwm_gpio_to_slice_num(_pin)), (volatile void*)ccAddr)) {
|
||||
_running = false;
|
||||
delete _arb;
|
||||
_arb = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
_arb->setCallback(_cb);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -101,8 +101,8 @@ public:
|
||||
info.blockSize = _fs.vol()->bytesPerCluster();
|
||||
info.pageSize = 0; // TODO ?
|
||||
info.maxPathLength = 255; // TODO ?
|
||||
info.totalBytes = _fs.vol()->clusterCount() * info.blockSize;
|
||||
info.usedBytes = info.totalBytes - (_fs.vol()->freeClusterCount() * _fs.vol()->bytesPerCluster());
|
||||
info.totalBytes = (uint64_t)_fs.vol()->clusterCount() * (uint64_t)info.blockSize;
|
||||
info.usedBytes = info.totalBytes - ((uint64_t)_fs.vol()->freeClusterCount() * (uint64_t)_fs.vol()->bytesPerCluster());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
// 3. Open up COMX: in your favorite terminal application and type away
|
||||
|
||||
// Under Mac to connect to the PicoW
|
||||
// 1. Sorry, you're on your own. If you have a Mac and can update this demo with a Pull Request it would be appreciated!
|
||||
// 1. Open System Preferences and go in the bluetooth section. You should find a bluetooth device called
|
||||
// PicoW Serial XX:XX:... Click Connect button.
|
||||
// 2. A /dev/tty.PicoWSerialXXXX becomes available.
|
||||
// 3. Connect to this device with your favorite terminal application.
|
||||
|
||||
|
||||
#include <SerialBT.h>
|
||||
|
||||
@@ -123,6 +123,7 @@ bool UpdaterClass::begin(size_t size, int command) {
|
||||
|
||||
//initialize
|
||||
_startAddress = updateStartAddress;
|
||||
_currentAddress = _startAddress; // Only used in the FS upload case
|
||||
_size = size;
|
||||
_bufferSize = 4096;
|
||||
_buffer = new uint8_t[_bufferSize];
|
||||
|
||||
@@ -237,73 +237,6 @@ void HTTPServer::serveStatic(const char* uri, FS& fs, const char* path, const ch
|
||||
_addRequestHandler(new StaticRequestHandler(fs, path, uri, cache_header));
|
||||
}
|
||||
|
||||
void HTTPServer::httpHandleClient() {
|
||||
bool keepCurrentClient = false;
|
||||
bool callYield = false;
|
||||
|
||||
if (_currentClient->connected()) {
|
||||
switch (_currentStatus) {
|
||||
case HC_NONE:
|
||||
// No-op to avoid C++ compiler warning
|
||||
break;
|
||||
case HC_WAIT_READ:
|
||||
// Wait for data from client to become available
|
||||
if (_currentClient->available()) {
|
||||
switch (_parseRequest(_currentClient)) {
|
||||
case CLIENT_REQUEST_CAN_CONTINUE:
|
||||
// Because HTTP_MAX_SEND_WAIT is expressed in milliseconds, it must be divided by 1000
|
||||
_currentClient->setTimeout(HTTP_MAX_SEND_WAIT / 1000);
|
||||
_contentLength = CONTENT_LENGTH_NOT_SET;
|
||||
_handleRequest();
|
||||
/* fallthrough */
|
||||
case CLIENT_REQUEST_IS_HANDLED:
|
||||
if (_currentClient->connected() || _currentClient->available()) {
|
||||
_currentStatus = HC_WAIT_CLOSE;
|
||||
_statusChange = millis();
|
||||
keepCurrentClient = true;
|
||||
} else {
|
||||
log_v("webserver: peer has closed after served\n");
|
||||
}
|
||||
break;
|
||||
case CLIENT_MUST_STOP:
|
||||
log_v("Close client\n");
|
||||
_currentClient->stop();
|
||||
break;
|
||||
case CLIENT_IS_GIVEN:
|
||||
// client must not be stopped but must not be handled here anymore
|
||||
// (example: tcp connection given to websocket)
|
||||
log_v("Give client\n");
|
||||
break;
|
||||
} // switch _parseRequest()
|
||||
} else { // !_currentClient->available()
|
||||
if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) {
|
||||
keepCurrentClient = true;
|
||||
}
|
||||
callYield = true;
|
||||
}
|
||||
break;
|
||||
case HC_WAIT_CLOSE:
|
||||
// Wait for client to close the connection
|
||||
if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) {
|
||||
keepCurrentClient = true;
|
||||
callYield = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!keepCurrentClient) {
|
||||
if (_currentClient) {
|
||||
delete _currentClient;
|
||||
_currentClient = nullptr;
|
||||
}
|
||||
_currentStatus = HC_NONE;
|
||||
_currentUpload.reset();
|
||||
}
|
||||
|
||||
if (callYield) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPServer::httpClose() {
|
||||
_currentStatus = HC_NONE;
|
||||
|
||||
@@ -41,6 +41,7 @@ enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH };
|
||||
#endif
|
||||
|
||||
#define HTTP_MAX_DATA_WAIT 5000 //ms to wait for the client to send the request
|
||||
#define HTTP_MAX_DATA_AVAILABLE_WAIT 30 //ms to wait for the client to send the request when there is another client with data available
|
||||
#define HTTP_MAX_POST_WAIT 5000 //ms to wait for POST data to arrive
|
||||
#define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed
|
||||
#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection
|
||||
@@ -74,7 +75,6 @@ public:
|
||||
virtual ~HTTPServer();
|
||||
|
||||
virtual void httpClose();
|
||||
virtual void httpHandleClient();
|
||||
|
||||
bool authenticate(const char * username, const char * password);
|
||||
void requestAuthentication(HTTPAuthMethod mode = BASIC_AUTH, const char* realm = nullptr, const String& authFailMsg = String(""));
|
||||
|
||||
@@ -90,19 +90,93 @@ void WebServerTemplate<ServerType, DefaultPort>::handleClient() {
|
||||
_currentClient = nullptr;
|
||||
}
|
||||
|
||||
ClientType client = _server.available();
|
||||
if (!client) {
|
||||
_currentClient = new ClientType(_server.available());
|
||||
if (!_currentClient) {
|
||||
if (_nullDelay) {
|
||||
delay(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_currentClient = new ClientType(client);
|
||||
_currentStatus = HC_WAIT_READ;
|
||||
_statusChange = millis();
|
||||
}
|
||||
httpHandleClient();
|
||||
bool keepCurrentClient = false;
|
||||
bool callYield = false;
|
||||
|
||||
if (_currentClient->connected()) {
|
||||
switch (_currentStatus) {
|
||||
case HC_NONE:
|
||||
// No-op to avoid C++ compiler warning
|
||||
break;
|
||||
case HC_WAIT_READ:
|
||||
// Wait for data from client to become available
|
||||
if (_currentClient->available()) {
|
||||
switch (_parseRequest(_currentClient)) {
|
||||
case CLIENT_REQUEST_CAN_CONTINUE:
|
||||
// Because HTTP_MAX_SEND_WAIT is expressed in milliseconds, it must be divided by 1000
|
||||
_currentClient->setTimeout(HTTP_MAX_SEND_WAIT / 1000);
|
||||
_contentLength = CONTENT_LENGTH_NOT_SET;
|
||||
_handleRequest();
|
||||
/* fallthrough */
|
||||
case CLIENT_REQUEST_IS_HANDLED:
|
||||
if (_currentClient->connected() || _currentClient->available()) {
|
||||
_currentStatus = HC_WAIT_CLOSE;
|
||||
_statusChange = millis();
|
||||
keepCurrentClient = true;
|
||||
} else {
|
||||
//log_v("webserver: peer has closed after served\n");
|
||||
}
|
||||
break;
|
||||
case CLIENT_MUST_STOP:
|
||||
//log_v("Close client\n");
|
||||
_currentClient->stop();
|
||||
break;
|
||||
case CLIENT_IS_GIVEN:
|
||||
// client must not be stopped but must not be handled here anymore
|
||||
// (example: tcp connection given to websocket)
|
||||
//log_v("Give client\n");
|
||||
break;
|
||||
} // switch _parseRequest()
|
||||
} else {
|
||||
// !_currentClient.available(): waiting for more data
|
||||
unsigned long timeSinceChange = millis() - _statusChange;
|
||||
// Use faster connection drop timeout if any other client has data
|
||||
// or the buffer of pending clients is full
|
||||
if ((_server.hasClientData() || _server.hasMaxPendingClients())
|
||||
&& timeSinceChange > HTTP_MAX_DATA_AVAILABLE_WAIT) {
|
||||
//log_v("webserver: closing since there's another connection to read from\r\n");
|
||||
} else {
|
||||
if (timeSinceChange > HTTP_MAX_DATA_WAIT) {
|
||||
//log_v("webserver: closing after read timeout\r\n");
|
||||
} else {
|
||||
keepCurrentClient = true;
|
||||
}
|
||||
}
|
||||
callYield = true;
|
||||
}
|
||||
break;
|
||||
case HC_WAIT_CLOSE:
|
||||
// Wait for client to close the connection
|
||||
if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) {
|
||||
keepCurrentClient = true;
|
||||
callYield = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!keepCurrentClient) {
|
||||
if (_currentClient) {
|
||||
delete _currentClient;
|
||||
_currentClient = nullptr;
|
||||
}
|
||||
_currentStatus = HC_NONE;
|
||||
_currentUpload.reset();
|
||||
}
|
||||
|
||||
if (callYield) {
|
||||
yield();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename ServerType, int DefaultPort>
|
||||
|
||||
@@ -108,11 +108,27 @@ void TwoWire::begin() {
|
||||
}
|
||||
|
||||
static void _handler0() {
|
||||
#if defined(__WIRE0_DEVICE)
|
||||
if (__WIRE0_DEVICE == i2c0) {
|
||||
Wire.onIRQ();
|
||||
} else {
|
||||
Wire1.onIRQ();
|
||||
}
|
||||
#else
|
||||
Wire.onIRQ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _handler1() {
|
||||
#if defined(__WIRE1_DEVICE)
|
||||
if (__WIRE1_DEVICE == i2c0) {
|
||||
Wire.onIRQ();
|
||||
} else {
|
||||
Wire1.onIRQ();
|
||||
}
|
||||
#else
|
||||
Wire1.onIRQ();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Slave mode
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
#include "CYW43shim.h"
|
||||
extern "C" {
|
||||
#include "cyw43.h"
|
||||
#include "cyw43_stats.h"
|
||||
#include <cyw43.h>
|
||||
#include <cyw43_stats.h>
|
||||
}
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <pico/cyw43_arch.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
// From cyw43_ctrl.c
|
||||
|
||||
@@ -416,10 +416,6 @@ template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::linkoutput_s(netif* netif, struct pbuf* pbuf) {
|
||||
LwipIntfDev* lid = (LwipIntfDev*)netif->state;
|
||||
|
||||
if (pbuf->len != pbuf->tot_len || pbuf->next) {
|
||||
Serial.println("ERRTOT\r\n");
|
||||
}
|
||||
|
||||
uint16_t len = lid->sendFrame((const uint8_t*)pbuf->payload, pbuf->len);
|
||||
|
||||
#if PHY_HAS_CAPTURE
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "framework-arduinopico",
|
||||
"version": "1.30200.0",
|
||||
"version": "1.30301.0",
|
||||
"description": "Arduino Wiring-based Framework (RPi Pico RP2040)",
|
||||
"keywords": [
|
||||
"framework",
|
||||
|
||||
@@ -71,6 +71,9 @@
|
||||
{
|
||||
"name": "Arduino Nano RP2040 Connect"
|
||||
},
|
||||
{
|
||||
"name": "ArtronShop RP2 Nano"
|
||||
},
|
||||
{
|
||||
"name": "BridgeTek IDM2040-7A"
|
||||
},
|
||||
@@ -110,6 +113,9 @@
|
||||
{
|
||||
"name": "iLabs Challenger 2040 WiFi/BLE"
|
||||
},
|
||||
{
|
||||
"name": "iLabs Challenger 2040 WiFi6/BLE"
|
||||
},
|
||||
{
|
||||
"name": "iLabs Challenger NB 2040 WiFi"
|
||||
},
|
||||
@@ -140,6 +146,9 @@
|
||||
{
|
||||
"name": "Pimoroni PGA2040"
|
||||
},
|
||||
{
|
||||
"name": "Pimoroni Plasma2040"
|
||||
},
|
||||
{
|
||||
"name": "Solder Party RP2040 Stamp"
|
||||
},
|
||||
|
||||
+1
-1
Submodule pico-sdk updated: 2ccab115de...6a7db34ff6
+1
-1
@@ -20,7 +20,7 @@
|
||||
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
|
||||
|
||||
name=Raspberry Pi RP2040 Boards
|
||||
version=3.2.0
|
||||
version=3.3.1
|
||||
|
||||
runtime.tools.pqt-gcc.path={runtime.platform.path}/system/arm-none-eabi
|
||||
runtime.tools.pqt-python3.path={runtime.platform.path}/system/python3
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"earlephilhower": {
|
||||
"boot2_source": "boot2_w25q080_2_padded_checksum.S",
|
||||
"usb_vid": "0x2E8A",
|
||||
"usb_pid": "0x000A"
|
||||
}
|
||||
},
|
||||
"core": "earlephilhower",
|
||||
"cpu": "cortex-m0plus",
|
||||
"extra_flags": "-D ARDUINO_ARTRONSHOP_RP2_NANO -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
|
||||
"f_cpu": "133000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x2E8A",
|
||||
"0x00C0"
|
||||
],
|
||||
[
|
||||
"0x2E8A",
|
||||
"0x000A"
|
||||
]
|
||||
],
|
||||
"mcu": "rp2040",
|
||||
"variant": "artronshop_rp2_nano"
|
||||
},
|
||||
"debug": {
|
||||
"jlink_device": "RP2040_M0_0",
|
||||
"openocd_target": "rp2040.cfg",
|
||||
"svd_path": "rp2040.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "RP2 Nano",
|
||||
"upload": {
|
||||
"maximum_ram_size": 270336,
|
||||
"maximum_size": 2097152,
|
||||
"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",
|
||||
"pico-debug"
|
||||
]
|
||||
},
|
||||
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
|
||||
"vendor": "ArtronShop"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"earlephilhower": {
|
||||
"boot2_source": "boot2_w25q080_2_padded_checksum.S",
|
||||
"usb_vid": "0x2E8A",
|
||||
"usb_pid": "0x105F"
|
||||
}
|
||||
},
|
||||
"core": "earlephilhower",
|
||||
"cpu": "cortex-m0plus",
|
||||
"extra_flags": "-D ARDUINO_CHALLENGER_2040_WIFI6_BLE_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500 -DWIFIESPAT2",
|
||||
"f_cpu": "133000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x2E8A",
|
||||
"0x00C0"
|
||||
],
|
||||
[
|
||||
"0x2E8A",
|
||||
"0x105F"
|
||||
]
|
||||
],
|
||||
"mcu": "rp2040",
|
||||
"variant": "challenger_2040_wifi6_ble"
|
||||
},
|
||||
"debug": {
|
||||
"jlink_device": "RP2040_M0_0",
|
||||
"openocd_target": "rp2040.cfg",
|
||||
"svd_path": "rp2040.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "Challenger 2040 WiFi6/BLE",
|
||||
"upload": {
|
||||
"maximum_ram_size": 270336,
|
||||
"maximum_size": 8388608,
|
||||
"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",
|
||||
"pico-debug"
|
||||
]
|
||||
},
|
||||
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
|
||||
"vendor": "iLabs"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"earlephilhower": {
|
||||
"boot2_source": "boot2_w25q080_2_padded_checksum.S",
|
||||
"usb_vid": "0x2E8A",
|
||||
"usb_pid": "0x100A"
|
||||
}
|
||||
},
|
||||
"core": "earlephilhower",
|
||||
"cpu": "cortex-m0plus",
|
||||
"extra_flags": "-D ARDUINO_PIMORONI_PLASMA2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500",
|
||||
"f_cpu": "133000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x2E8A",
|
||||
"0x00C0"
|
||||
],
|
||||
[
|
||||
"0x2E8A",
|
||||
"0x100A"
|
||||
]
|
||||
],
|
||||
"mcu": "rp2040",
|
||||
"variant": "pimoroni_plasma2040"
|
||||
},
|
||||
"debug": {
|
||||
"jlink_device": "RP2040_M0_0",
|
||||
"openocd_target": "rp2040.cfg",
|
||||
"svd_path": "rp2040.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "Plasma2040",
|
||||
"upload": {
|
||||
"maximum_ram_size": 270336,
|
||||
"maximum_size": 2097152,
|
||||
"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",
|
||||
"pico-debug"
|
||||
]
|
||||
},
|
||||
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
|
||||
"vendor": "Pimoroni"
|
||||
}
|
||||
+6
-1
@@ -117,7 +117,7 @@ def BuildIPBTStack(name):
|
||||
print('%s.menu.ipbtstack.ipv4ipv6btcble.build.libpicowdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1 -DENABLE_CLASSIC=1 -DENABLE_BLE=1' % (name))
|
||||
|
||||
def BuildUploadMethodMenu(name):
|
||||
for a, b, c, d, e, f in [ ["default", "Default (UF2)", 256, "picoprobe.tcl", "uf2conv", "uf2conv-network"],
|
||||
for a, b, c, d, e, f in [ ["default", "Default (UF2)", 256, "picoprobe_cmsis_dap.tcl", "uf2conv", "uf2conv-network"],
|
||||
["picotool", "Picotool", 256, "picoprobe.tcl", "picotool", None],
|
||||
["picoprobe", "Picoprobe", 256, "picoprobe.tcl", "picoprobe", None],
|
||||
["picoprobe_cmsis_dap", "Picoprobe (CMSIS-DAP)", 256, "picoprobe_cmsis_dap.tcl", "picoprobe_cmsis_dap", None],
|
||||
@@ -357,6 +357,9 @@ MakeBoard("adafruit_kb2040", "Adafruit", "KB2040", "0x239a", "0x8105", 250, "ADA
|
||||
# Arduino
|
||||
MakeBoard("arduino_nano_connect", "Arduino", "Nano RP2040 Connect", "0x2341", ["0x005e", "0x805e", "0x015e", "0x025e"] , 250, "NANO_RP2040_CONNECT", 16, "boot2_w25q080_2_padded_checksum")
|
||||
|
||||
# ArtronShop
|
||||
MakeBoard("artronshop_rp2_nano", "ArtronShop", "RP2 Nano", "0x2e8a", "0x000a", 250, "ARTRONSHOP_RP2_NANO", 2, "boot2_w25q080_2_padded_checksum")
|
||||
|
||||
# BridgeTek
|
||||
MakeBoard("bridgetek_idm2040-7a", "BridgeTek", "IDM2040-7A", "0x2e8a", "0x1041", 250, "BRIDGETEK_IDM2040-7A", 8, "boot2_w25q080_2_padded_checksum", ["FT8XX_TYPE=BT817", "DISPLAY_RES=WVGA", "PLATFORM_RP2040"])
|
||||
|
||||
@@ -385,6 +388,7 @@ MakeBoard("challenger_2040_lora", "iLabs", "Challenger 2040 LoRa", "0x2e8a", "0x
|
||||
MakeBoard("challenger_2040_subghz", "iLabs", "Challenger 2040 SubGHz", "0x2e8a", "0x1032", 250, "CHALLENGER_2040_SUBGHZ_RP2040", 8, "boot2_w25q080_2_padded_checksum")
|
||||
MakeBoard("challenger_2040_wifi", "iLabs", "Challenger 2040 WiFi", "0x2e8a", "0x1006", 250, "CHALLENGER_2040_WIFI_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
|
||||
MakeBoard("challenger_2040_wifi_ble", "iLabs", "Challenger 2040 WiFi/BLE", "0x2e8a", "0x102C", 500, "CHALLENGER_2040_WIFI_BLE_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
|
||||
MakeBoard("challenger_2040_wifi6_ble", "iLabs", "Challenger 2040 WiFi6/BLE", "0x2e8a", "0x105F", 500, "CHALLENGER_2040_WIFI6_BLE_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
|
||||
MakeBoard("challenger_nb_2040_wifi", "iLabs", "Challenger NB 2040 WiFi", "0x2e8a", "0x100d", 500, "CHALLENGER_NB_2040_WIFI_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
|
||||
MakeBoard("challenger_2040_sdrtc", "iLabs", "Challenger 2040 SD/RTC", "0x2e8a", "0x102d", 250, "CHALLENGER_2040_SDRTC_RP2040", 8, "boot2_w25q080_2_padded_checksum")
|
||||
MakeBoard("challenger_2040_nfc", "iLabs", "Challenger 2040 NFC", "0x2e8a", "0x1036", 250, "CHALLENGER_2040_NFC_RP2040", 8, "boot2_w25q080_2_padded_checksum")
|
||||
@@ -403,6 +407,7 @@ MakeBoard("nullbits_bit_c_pro", "nullbits", "Bit-C PRO", "0x2e8a", "0x6e61", 500
|
||||
|
||||
# Pimoroni
|
||||
MakeBoard("pimoroni_pga2040", "Pimoroni", "PGA2040", "0x2e8a", "0x1008", 250, "PIMORONI_PGA2040", 8, "boot2_w25q64jv_4_padded_checksum")
|
||||
MakeBoard("pimoroni_plasma2040", "Pimoroni", "Plasma2040", "0x2e8a", "0x100a", 500, "PIMORONI_PLASMA2040", 2, "boot2_w25q080_2_padded_checksum")
|
||||
|
||||
# Solder Party
|
||||
MakeBoard("solderparty_rp2040_stamp", "Solder Party", "RP2040 Stamp", "0x1209", "0xa182", 500, "SOLDERPARTY_RP2040_STAMP", 8, "boot2_generic_03h_4_padded_checksum")
|
||||
|
||||
@@ -30,10 +30,12 @@
|
||||
#define PIN_SPI1_SS (31u)
|
||||
|
||||
// Wire
|
||||
#define PIN_WIRE0_SDA (24u)
|
||||
#define PIN_WIRE0_SCL (25u)
|
||||
#define PIN_WIRE1_SDA (2u)
|
||||
#define PIN_WIRE1_SCL (3u)
|
||||
#define __WIRE0_DEVICE i2c1
|
||||
#define PIN_WIRE0_SDA (2u)
|
||||
#define PIN_WIRE0_SCL (3u)
|
||||
#define __WIRE1_DEVICE i2c0
|
||||
#define PIN_WIRE1_SDA (24u)
|
||||
#define PIN_WIRE1_SCL (25u)
|
||||
|
||||
#define SERIAL_HOWMANY (2u)
|
||||
#define SPI_HOWMANY (1u)
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED (13u)
|
||||
|
||||
// Serial
|
||||
#define PIN_SERIAL1_TX (0u)
|
||||
#define PIN_SERIAL1_RX (1u)
|
||||
|
||||
#define PIN_SERIAL2_TX (8u)
|
||||
#define PIN_SERIAL2_RX (9u)
|
||||
|
||||
// SPI
|
||||
#define PIN_SPI0_MISO (4u)
|
||||
#define PIN_SPI0_MOSI (3u)
|
||||
#define PIN_SPI0_SCK (2u)
|
||||
#define PIN_SPI0_SS (5u)
|
||||
|
||||
#define PIN_SPI1_MISO (12u)
|
||||
#define PIN_SPI1_MOSI (11u)
|
||||
#define PIN_SPI1_SCK (10u)
|
||||
#define PIN_SPI1_SS (13u)
|
||||
|
||||
// Wire
|
||||
#define PIN_WIRE0_SDA (16u)
|
||||
#define PIN_WIRE0_SCL (17u)
|
||||
|
||||
#define PIN_WIRE1_SDA (18u)
|
||||
#define PIN_WIRE1_SCL (19u)
|
||||
|
||||
#define SERIAL_HOWMANY (3u)
|
||||
#define SPI_HOWMANY (2u)
|
||||
#define WIRE_HOWMANY (2u)
|
||||
|
||||
// from common.h
|
||||
#define PINS_COUNT (22u)
|
||||
#define NUM_DIGITAL_PINS (16u)
|
||||
#define NUM_ANALOG_INPUTS (4u)
|
||||
#define NUM_ANALOG_OUTPUTS (0u)
|
||||
#define ADC_RESOLUTION (12u)
|
||||
|
||||
#define LED_BUILTIN PIN_LED
|
||||
|
||||
static const uint8_t D0 = (0u);
|
||||
static const uint8_t D1 = (1u);
|
||||
static const uint8_t D2 = (2u);
|
||||
static const uint8_t D3 = (3u);
|
||||
static const uint8_t D4 = (4u);
|
||||
static const uint8_t D5 = (5u);
|
||||
static const uint8_t D6 = (6u);
|
||||
static const uint8_t D7 = (7u);
|
||||
static const uint8_t D8 = (8u);
|
||||
static const uint8_t D9 = (9u);
|
||||
static const uint8_t D10 = (10u);
|
||||
static const uint8_t D11 = (11u);
|
||||
static const uint8_t D12 = (12u);
|
||||
static const uint8_t D13 = (13u);
|
||||
|
||||
static const uint8_t A0 = (26u);
|
||||
static const uint8_t A1 = (27u);
|
||||
static const uint8_t A2 = (28u);
|
||||
static const uint8_t A3 = (29u);
|
||||
|
||||
static const uint8_t SS = PIN_SPI1_SS;
|
||||
static const uint8_t MOSI = PIN_SPI1_MOSI;
|
||||
static const uint8_t MISO = PIN_SPI1_MISO;
|
||||
static const uint8_t SCK = PIN_SPI1_SCK;
|
||||
|
||||
static const uint8_t SDA = PIN_WIRE0_SDA;
|
||||
static const uint8_t SCL = PIN_WIRE0_SCL;
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
ESP8285/ESP32C3 helper class for the Challenger RP2040 WiFi enabled boards
|
||||
|
||||
Copyright (c) 2021,2022 P. Oldberg <pontus@ilabs.se>
|
||||
|
||||
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 <ChallengerWiFi.h>
|
||||
|
||||
Challenger2040WiFiClass::Challenger2040WiFiClass(HardwareSerial* serial) {
|
||||
_serial = serial;
|
||||
|
||||
pinMode(PIN_ESP_RST, OUTPUT);
|
||||
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
|
||||
pinMode(PIN_ESP_MODE, OUTPUT);
|
||||
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
|
||||
|
||||
pinMode(D15, OUTPUT);
|
||||
digitalWrite(D15, HIGH); // This is to correct for the
|
||||
// patched PCB.
|
||||
}
|
||||
|
||||
// Do a HW reset by applying a low pulse to the reset line for 1mSec
|
||||
void Challenger2040WiFiClass::doHWReset() {
|
||||
pinMode(D15, OUTPUT);
|
||||
digitalWrite(D15, HIGH); // This is to correct for the
|
||||
delay(1);
|
||||
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
|
||||
delay(1);
|
||||
digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset
|
||||
}
|
||||
|
||||
// Set the mode flag high to indicate normal run operation and do a HW
|
||||
// reset.
|
||||
void Challenger2040WiFiClass::runReset() { // Prepare ESP for normal op
|
||||
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
|
||||
doHWReset();
|
||||
}
|
||||
|
||||
// Set the mode flag low to indicate flash operation and do a HW
|
||||
// reset.
|
||||
void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
|
||||
digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start
|
||||
doHWReset();
|
||||
}
|
||||
|
||||
// Wait for the modem to reply with a "ready" prompt. This can be done
|
||||
// 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
|
||||
|
||||
_serial->setTimeout(100);
|
||||
String rdy = _serial->readStringUntil('\n');
|
||||
while (!rdy.startsWith("ready") && timeout--) {
|
||||
rdy = _serial->readStringUntil('\n');
|
||||
}
|
||||
_serial->setTimeout(1000); // Reset default timeout to 1000
|
||||
if (timeout) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset the ESP and wait for the "ready" prompt to be returned.
|
||||
bool Challenger2040WiFiClass::reset() {
|
||||
runReset();
|
||||
_serial->begin(DEFAULT_ESP_BAUDRATE);
|
||||
return waitForReady();
|
||||
}
|
||||
|
||||
// Checks to see if the modem responds to the "AT" poll command.
|
||||
bool Challenger2040WiFiClass::isAlive() {
|
||||
int timeout = 100;
|
||||
|
||||
_serial->setTimeout(250);
|
||||
_serial->println(F("AT"));
|
||||
String rdy = _serial->readStringUntil('\n');
|
||||
while (!rdy.startsWith(F("OK")) && timeout--) {
|
||||
_serial->println(F("AT"));
|
||||
rdy = _serial->readStringUntil('\n');
|
||||
}
|
||||
_serial->setTimeout(1000);
|
||||
|
||||
if (timeout) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change the baud rate of the ESP device as well as the local UART.
|
||||
// No checking is done on the input baud rate so the user must know what
|
||||
// baud rates are valid. The function ends by checking if the ESP is
|
||||
// reachable by doing an "AT" poll.
|
||||
bool Challenger2040WiFiClass::changeBaudRate(int baud) {
|
||||
_serial->print(F("AT+UART_CUR="));
|
||||
_serial->print(baud);
|
||||
_serial->println(F(",8,1,0,0"));
|
||||
delay(100);
|
||||
_serial->end();
|
||||
_serial->begin(baud);
|
||||
return isAlive();
|
||||
}
|
||||
|
||||
// This method should be called id the builtin object isn't needed any more
|
||||
// It basically just releases the UART pins for other use.
|
||||
void Challenger2040WiFiClass::release() {
|
||||
_serial->end();
|
||||
}
|
||||
|
||||
// We can assign a new hardware serial port to accommodate the ESP device here.
|
||||
// The function will release the previously used serial port and assign the
|
||||
// new port. The ESP will be left in a reset state ready to start normal
|
||||
// operation when exiting the function.
|
||||
// This function is useful for when using the PIO serial ports to communicate
|
||||
// with the ESP instead of the built in hardware serial port.
|
||||
void Challenger2040WiFiClass::setSerial(HardwareSerial* serial) {
|
||||
|
||||
release();
|
||||
_serial = serial;
|
||||
|
||||
pinMode(PIN_ESP_RST, OUTPUT);
|
||||
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
|
||||
pinMode(PIN_ESP_MODE, OUTPUT);
|
||||
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
|
||||
}
|
||||
|
||||
// Return the current serial object
|
||||
HardwareSerial* Challenger2040WiFiClass::getSerial() {
|
||||
return _serial;
|
||||
}
|
||||
|
||||
Challenger2040WiFiClass Challenger2040WiFi;
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
ESP8285/ESP32C3 helper class for the Challenger RP2040 WiFi enabled boards
|
||||
|
||||
Copyright (c) 2021,2022 P. Oldberg <pontus@ilabs.se>
|
||||
|
||||
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
|
||||
|
||||
#define DEFAULT_ESP32_BAUDRATE 115200
|
||||
#define DEFAULT_ESP_BAUDRATE DEFAULT_ESP32_BAUDRATE
|
||||
|
||||
class Challenger2040WiFiClass {
|
||||
public:
|
||||
Challenger2040WiFiClass(HardwareSerial* = &ESP_SERIAL_PORT);
|
||||
void doHWReset();
|
||||
void runReset();
|
||||
void flashReset();
|
||||
bool waitForReady();
|
||||
bool reset();
|
||||
bool isAlive();
|
||||
bool changeBaudRate(int);
|
||||
void release();
|
||||
void setSerial(HardwareSerial*);
|
||||
HardwareSerial* getSerial();
|
||||
private:
|
||||
HardwareSerial* _serial;
|
||||
};
|
||||
|
||||
extern Challenger2040WiFiClass Challenger2040WiFi;
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
ESP8285/ESP32C3 helper class for the Challenger RP2040 WiFi enabled boards
|
||||
|
||||
Copyright (c) 2021,2022 P. Oldberg <pontus@ilabs.se>
|
||||
|
||||
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 <ChallengerWiFi.h>
|
||||
|
||||
/**
|
||||
Just make sure we try to reset the ESP device before the user starts
|
||||
using the device.
|
||||
*/
|
||||
void initVariant() {
|
||||
Challenger2040WiFi.reset();
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#define PINS_COUNT (24u)
|
||||
#define NUM_DIGITAL_PINS (24u)
|
||||
#define NUM_ANALOG_INPUTS (4u)
|
||||
#define NUM_ANALOG_OUTPUTS (0u)
|
||||
#define ADC_RESOLUTION (12u)
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED (10u)
|
||||
|
||||
// Board serial port (Uart0)
|
||||
#define PIN_SERIAL1_TX (16u)
|
||||
#define PIN_SERIAL1_RX (17u)
|
||||
|
||||
// Uart connected to ESP32C6 (Uart1)
|
||||
#define PIN_SERIAL2_TX (4u)
|
||||
#define PIN_SERIAL2_RX (5u)
|
||||
#define PIN_ESP32_RST (19u)
|
||||
#define PIN_ESP32_MODE (24u)
|
||||
#define ESP32_SERIAL Serial2
|
||||
// Uart define esp serial abstraction pins
|
||||
#define PIN_ESP_TX PIN_SERIAL2_TX
|
||||
#define PIN_ESP_RX PIN_SERIAL2_RX
|
||||
#define PIN_ESP_RST PIN_ESP32_RST
|
||||
#define PIN_ESP_MODE PIN_ESP32_MODE
|
||||
#define ESP_SERIAL_PORT ESP32_SERIAL
|
||||
|
||||
// SPI
|
||||
#define PIN_SPI0_MISO (24u)
|
||||
#define PIN_SPI0_MOSI (23u)
|
||||
#define PIN_SPI0_SCK (22u)
|
||||
#define PIN_SPI0_SS (21u)
|
||||
|
||||
// SPI connected to ESP32C6
|
||||
#define PIN_SPI1_MISO (12u)
|
||||
#define PIN_SPI1_MOSI (15u)
|
||||
#define PIN_SPI1_SCK (14u)
|
||||
#define PIN_SPI1_SS (13u)
|
||||
// Handshake signal from ESP32C6
|
||||
#define ESP32_HS (18u)
|
||||
#define ESP32_SPI SPI1
|
||||
|
||||
// Wire
|
||||
#define PIN_WIRE0_SDA (0u)
|
||||
#define PIN_WIRE0_SCL (1u)
|
||||
|
||||
// Not pinned out
|
||||
#define PIN_WIRE1_SDA (31u)
|
||||
#define PIN_WIRE1_SCL (31u)
|
||||
|
||||
#define SERIAL_HOWMANY (2u)
|
||||
#define SPI_HOWMANY (2u)
|
||||
#define WIRE_HOWMANY (1u)
|
||||
|
||||
#define LED_BUILTIN PIN_LED
|
||||
#define NEOPIXEL (11u)
|
||||
|
||||
static const uint8_t D0 = (16u);
|
||||
static const uint8_t D1 = (17u);
|
||||
static const uint8_t D2 = (20u);
|
||||
static const uint8_t D3 = (23u);
|
||||
static const uint8_t D4 = (22u);
|
||||
static const uint8_t D5 = (2u);
|
||||
static const uint8_t D6 = (3u);
|
||||
static const uint8_t D7 = (0u);
|
||||
static const uint8_t D8 = (1u);
|
||||
static const uint8_t D9 = (6u);
|
||||
static const uint8_t D10 = (7u);
|
||||
static const uint8_t D11 = (8u);
|
||||
static const uint8_t D12 = (9u);
|
||||
static const uint8_t D13 = (10u);
|
||||
static const uint8_t D14 = (11u);
|
||||
static const uint8_t D15 = (12u);
|
||||
static const uint8_t D16 = (13u);
|
||||
static const uint8_t D17 = (14u);
|
||||
static const uint8_t D18 = (15u);
|
||||
static const uint8_t D19 = (18u);
|
||||
static const uint8_t D20 = (19u);
|
||||
static const uint8_t D21 = (24u);
|
||||
|
||||
static const uint8_t A0 = (26u);
|
||||
static const uint8_t A1 = (27u);
|
||||
static const uint8_t A2 = (28u);
|
||||
static const uint8_t A3 = (29u);
|
||||
static const uint8_t A4 = (25u);
|
||||
static const uint8_t A5 = (21u);
|
||||
|
||||
static const uint8_t SS = PIN_SPI0_SS;
|
||||
static const uint8_t MOSI = PIN_SPI0_MOSI;
|
||||
static const uint8_t MISO = PIN_SPI0_MISO;
|
||||
static const uint8_t SCK = PIN_SPI0_SCK;
|
||||
|
||||
static const uint8_t SDA = PIN_WIRE0_SDA;
|
||||
static const uint8_t SCL = PIN_WIRE0_SCL;
|
||||
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
// Pin definitions taken from:
|
||||
// https://github.com/rp-rs/rp-hal-boards/blob/main/boards/pimoroni-plasma-2040/src/lib.rs
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED (16u)
|
||||
#define PIN_LED_R (16u)
|
||||
#define PIN_LED_G (17u)
|
||||
#define PIN_LED_B (18u)
|
||||
#define LED_BUILTIN PIN_LED
|
||||
|
||||
// Digital pins
|
||||
#if 0
|
||||
static const uint8_t D0 = (26u);
|
||||
static const uint8_t D1 = (27u);
|
||||
static const uint8_t D2 = (28u);
|
||||
static const uint8_t D3 = (29u);
|
||||
static const uint8_t D4 = (6u);
|
||||
static const uint8_t D5 = (7u);
|
||||
static const uint8_t D6 = (0u);
|
||||
static const uint8_t D7 = (1u);
|
||||
static const uint8_t D8 = (2u);
|
||||
static const uint8_t D9 = (4u);
|
||||
static const uint8_t D10 = (3u);
|
||||
#endif
|
||||
|
||||
// Analog pins
|
||||
static const uint8_t A0 = (26u);
|
||||
static const uint8_t A1 = (27u);
|
||||
static const uint8_t A2 = (28u);
|
||||
static const uint8_t A3 = (31u);
|
||||
#define ADC_RESOLUTION 12
|
||||
|
||||
// NeoPixel
|
||||
#define PIN_NEOPIXEL (15u)
|
||||
//#define NEOPIXEL_POWER (11u)
|
||||
|
||||
// Serial1
|
||||
#define PIN_SERIAL1_TX (31u)
|
||||
#define PIN_SERIAL1_RX (31u)
|
||||
|
||||
// Serial2 not pinned out
|
||||
#define PIN_SERIAL2_TX (31u)
|
||||
#define PIN_SERIAL2_RX (31u)
|
||||
|
||||
// SPI
|
||||
#define PIN_SPI0_MISO (31u)
|
||||
#define PIN_SPI0_MOSI (31u)
|
||||
#define PIN_SPI0_SCK (31u)
|
||||
#define PIN_SPI0_SS (31u) // not pinned out
|
||||
//static const uint8_t SS = PIN_SPI0_SS; // SPI Slave SS not used. Set here only for reference.
|
||||
//static const uint8_t MOSI = PIN_SPI0_MOSI;
|
||||
//static const uint8_t MISO = PIN_SPI0_MISO;
|
||||
//static const uint8_t SCK = PIN_SPI0_SCK;
|
||||
|
||||
// Not pinned out
|
||||
#define PIN_SPI1_MISO (31u)
|
||||
#define PIN_SPI1_MOSI (31u)
|
||||
#define PIN_SPI1_SCK (31u)
|
||||
#define PIN_SPI1_SS (31u)
|
||||
//#define SPI_MISO (PIN_SPI1_MISO)
|
||||
//#define SPI_MOSI (PIN_SPI1_MOSI)
|
||||
//#define SPI_SCK (PIN_SPI1_SCK)
|
||||
|
||||
// Wire
|
||||
#define __WIRE0_DEVICE (i2c1)
|
||||
#define PIN_WIRE0_SDA (20u)
|
||||
#define PIN_WIRE0_SCL (21u)
|
||||
#define SDA PIN_WIRE0_SDA
|
||||
#define SCL PIN_WIRE0_SCL
|
||||
#define I2C_SDA (SDA)
|
||||
#define I2C_SCL (SCL)
|
||||
|
||||
// Wire1 not pinned out
|
||||
#define __WIRE1_DEVICE (i2c0)
|
||||
#define PIN_WIRE1_SDA (31u)
|
||||
#define PIN_WIRE1_SCL (31u)
|
||||
|
||||
#define SERIAL_HOWMANY (0u)
|
||||
#define SPI_HOWMANY (0u)
|
||||
#define WIRE_HOWMANY (1u)
|
||||
Reference in New Issue
Block a user