Compare commits
@@ -6,6 +6,10 @@ name: Arduino-Pico CI
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -20,7 +24,7 @@ jobs:
|
||||
- name: Run codespell
|
||||
uses: codespell-project/actions-codespell@master
|
||||
with:
|
||||
skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS
|
||||
skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS,./tools/libbearssl/bearssl,./include,./libraries/WiFi/examples/BearSSL_Server,./ota/uzlib,./libraries/http-parser/lib,./libraries/WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino,./libraries/HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino,./.git
|
||||
ignore_words_list: ser,dout
|
||||
|
||||
# Consistent style
|
||||
@@ -46,10 +50,6 @@ jobs:
|
||||
./tests/restyle.sh
|
||||
# If anything changed, GIT should return an error and fail the test
|
||||
git diff --exit-code
|
||||
# - name: Check Arduino API copy is clean
|
||||
# run: |
|
||||
# git submodule update --init ./ArduinoCore-API
|
||||
# diff -r ./cores/rp2040/api ./ArduinoCore-API/api
|
||||
|
||||
# Build all examples on linux (core and Arduino IDE)
|
||||
build-linux:
|
||||
@@ -57,26 +57,24 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
chunk: [0, 1, 2, 3]
|
||||
chunk: [0, 1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Linux toolchain
|
||||
id: cache-linux
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketches
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
BUILD_PARITY: custom
|
||||
mod: 4
|
||||
mod: 6
|
||||
rem: ${{ matrix.chunk }}
|
||||
run: |
|
||||
cd pico-sdk
|
||||
@@ -92,19 +90,17 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Linux toolchain
|
||||
id: cache-linux
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketches
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
BUILD_PARITY: custom
|
||||
run: |
|
||||
cd pico-sdk
|
||||
@@ -120,19 +116,17 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Windows toolchain
|
||||
id: cache-windows
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketch
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
WINDOWS: 1
|
||||
BUILD_PARITY: custom
|
||||
mod: 500
|
||||
@@ -150,24 +144,22 @@ jobs:
|
||||
# Single build under macOS to ensure the Mac toolchain is good.
|
||||
build-mac:
|
||||
name: Mac
|
||||
runs-on: macOS-latest
|
||||
runs-on: macOS-12
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Mac toolchain
|
||||
id: cache-mac
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketch
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
MACOSX: 1
|
||||
BUILD_PARITY: custom
|
||||
mod: 500
|
||||
@@ -185,21 +177,30 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
submodules: 'true'
|
||||
- name: Initialize needed submodules
|
||||
run: |
|
||||
cd pico-sdk
|
||||
git submodule update --init
|
||||
cd ../libraries/Adafruit_TinyUSB_Arduino
|
||||
git submodule update --init
|
||||
cd ../..
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- name: Cache PlatformIO
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.platformio
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install PlatformIO
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
@@ -211,4 +212,10 @@ jobs:
|
||||
- name: Build Fade Example
|
||||
run: pio ci --board=rpipico --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/rp2040/examples/Fade/Fade.ino
|
||||
- name: Build TinyUSB Example
|
||||
run: pio ci --board=rpipico --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" -O "build_flags=-DUSE_TINYUSB" libraries/Adafruit_TinyUSB_Arduino/examples/CDC/cdc_multi/cdc_multi.ino
|
||||
run: pio ci --board=rpipico --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" -O "build_flags=-DUSE_TINYUSB" libraries/Adafruit_TinyUSB_Arduino/examples/CDC/cdc_multi/cdc_multi.ino
|
||||
- name: Build WiFi Example
|
||||
run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino
|
||||
- name: Build Signed OTA Example
|
||||
run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/ArduinoOTA/examples/SignedOTA/SignedOTA.ino
|
||||
- name: Build Bluetooth Example
|
||||
run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" -O "build_flags=-DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH" libraries/MouseBLE/examples/BLECircle/BLECircle.ino
|
||||
|
||||
@@ -9,28 +9,28 @@ jobs:
|
||||
name: Update master JSON file
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- name: Cache PlatformIO
|
||||
uses: actions/cache@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
path: ~/.platformio
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
- uses: actions/setup-python@v2
|
||||
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
|
||||
|
||||
@@ -15,11 +15,11 @@ jobs:
|
||||
name: Package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Build package JSON
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
.DS_Store
|
||||
system
|
||||
tools/dist
|
||||
docs/_build
|
||||
ota/build
|
||||
tools/libpico/build
|
||||
platform.local.txt
|
||||
|
||||
+16
-4
@@ -14,14 +14,26 @@
|
||||
path = libraries/ESP8266SdFat
|
||||
url = https://github.com/earlephilhower/ESP8266SdFat.git
|
||||
[submodule "libraries/Keyboard"]
|
||||
path = libraries/Keyboard
|
||||
url = https://github.com/earlephilhower/Keyboard
|
||||
path = libraries/HID_Keyboard
|
||||
url = https://github.com/earlephilhower/Keyboard.git
|
||||
[submodule "libraries/Mouse"]
|
||||
path = libraries/Mouse
|
||||
url = https://github.com/earlephilhower/Mouse
|
||||
path = libraries/HID_Mouse
|
||||
url = https://github.com/earlephilhower/Mouse.git
|
||||
[submodule "libraries/Joystick"]
|
||||
path = libraries/HID_Joystick
|
||||
url = https://github.com/earlephilhower/Joystick.git
|
||||
[submodule "libraries/Adafruit_TinyUSB_Arduino"]
|
||||
path = libraries/Adafruit_TinyUSB_Arduino
|
||||
url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git
|
||||
[submodule "libraries/FreeRTOS/lib/FreeRTOS-Kernel"]
|
||||
path = libraries/FreeRTOS/lib/FreeRTOS-Kernel
|
||||
url = https://github.com/earlephilhower/FreeRTOS-Kernel.git
|
||||
[submodule "tools/libbearssl/bearssl"]
|
||||
path = tools/libbearssl/bearssl
|
||||
url = https://github.com/earlephilhower/bearssl-esp8266.git
|
||||
[submodule "ota/uzlib"]
|
||||
path = ota/uzlib
|
||||
url = https://github.com/pfalcon/uzlib.git
|
||||
[submodule "libraries/http_parser/lib/http-parser"]
|
||||
path = libraries/http-parser/lib/http-parser
|
||||
url = https://github.com/nodejs/http-parser.git
|
||||
|
||||
+1
-1
Submodule ArduinoCore-API updated: ff01bb620e...ece6e68f29
@@ -9,45 +9,97 @@ This is a port of the RP2040 (Raspberry Pi Pico processor) to the Arduino ecosys
|
||||
# Documentation
|
||||
See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for more detailed usage information.
|
||||
|
||||
# Contributing
|
||||
Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blob/master/docs/contrib.rst) for more information on submitting pull requests and porting libraries or sketches to this core.
|
||||
|
||||
# Supported Boards
|
||||
* Raspberry Pi Pico
|
||||
* Raspberry Pi Pico W
|
||||
* 0xCB Helios
|
||||
* Adafruit Feather RP2040
|
||||
* Adafruit Feather RP2040 SCORPIO
|
||||
* Adafruit ItsyBitsy RP2040
|
||||
* Adafruit KB2040
|
||||
* Adafruit Macropad RP2040
|
||||
* Adafruit Metro RP2040
|
||||
* Adafruit QTPy RP2040
|
||||
* 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
|
||||
* DatanoiseTV PicoADK+
|
||||
* DeRuiLab FlyBoard2040 Core
|
||||
* DFRobot Beetle RP2040
|
||||
* ElectronicCats Hunter Cat NFC
|
||||
* 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
|
||||
* Invector Labs Challenger RP2040 SubGHz
|
||||
* Invector Labs Challenger RP2040 SD/RTC
|
||||
* Invector Labs Challenger RP2040 UWB
|
||||
* Invector Labs RPICO32
|
||||
* Melopero Cookie RP2040
|
||||
* Melopero Shake RP2040
|
||||
* Neko Systems BL2040 Mini
|
||||
* nullbits Bit-C PRO
|
||||
* Pimoroni PGA2040
|
||||
* Pimoroni Plasma2040
|
||||
* Pimoroni Tiny2040
|
||||
* Seeed Indicator RP2040
|
||||
* Seeed XIAO RP2040
|
||||
* Silicognition RP2040-Shim
|
||||
* Solder Party RP2040 Stamp
|
||||
* SparkFun ProMicro RP2040
|
||||
* SparkFun Thing Plus RP2040
|
||||
* uPesy RP2040 DevKit
|
||||
* VCC-GND YD-RP2040
|
||||
* Viyalab Mizu RP2040
|
||||
* Waveshare RP2040 Zero
|
||||
* Waveshare RP2040 One
|
||||
* Waveshare RP2040 Plus
|
||||
* Waveshare RP2040 LCD 0.96
|
||||
* Waveshare RP2040 LCD 1.28
|
||||
* WIZnet W5100S-EVB-Pico
|
||||
* WIZnet W5500-EVB-Pico
|
||||
* WIZnet WizFi360-EVB-Pico
|
||||
* Redscorp RP2040-ProMini
|
||||
* Generic (configurable flash, I/O pins)
|
||||
|
||||
# Installing via Arduino Boards Manager
|
||||
**Windows Users**: Please do not use the Windows Store version of the actual Arduino application
|
||||
## Windows-specific Notes
|
||||
Please do not use the Windows Store version of the actual Arduino application
|
||||
because it has issues detecting attached Pico boards. Use the "Windows ZIP" or plain "Windows"
|
||||
executable (EXE) download direct from https://arduino.cc. and allow it to install any device
|
||||
drivers it suggests. Otherwise the Pico board may not be detected. Also, if trying out the
|
||||
2.0 beta Arduino please install the release 1.8 version beforehand to ensure needed device drivers
|
||||
are present. (See #20 for more details.)
|
||||
|
||||
## Linux-specific Notes
|
||||
Installing Arduino using flatpak (often used by "App Stores" in various Linux
|
||||
distributions) will mean it has restricted access to the host. This might cause uploads to fail
|
||||
with error messages such as the following:
|
||||
|
||||
```
|
||||
Scanning for RP2040 devices
|
||||
...
|
||||
No drive to deploy.
|
||||
```
|
||||
|
||||
If you encounter this, you will need to either install Arduino in a different manner, or override
|
||||
the flatpak sandboxing feature using the following command, then restarting Arduino.
|
||||
|
||||
```
|
||||
flatpak override --user --filesystem=host:ro cc.arduino.IDE2
|
||||
```
|
||||
|
||||
## Installation
|
||||
Open up the Arduino IDE and go to File->Preferences.
|
||||
|
||||
In the dialog that pops up, enter the following URL in the "Additional Boards Manager URLs" field:
|
||||
@@ -65,6 +117,12 @@ Type "pico" in the search box and select "Add":
|
||||

|
||||
|
||||
# Installing via GIT
|
||||
|
||||
**Windows Users:** Before installing via `git` on Windows, please read and follow the directions in
|
||||
[this link](https://arduino-pico.readthedocs.io/en/latest/platformio.html#important-steps-for-windows-users-before-installing).
|
||||
If Win32 long paths are not enabled, and `git` not configured to use them then there
|
||||
may be errors when attempting to clone the submodules.
|
||||
|
||||
To install via GIT (for latest and greatest versions):
|
||||
````
|
||||
mkdir -p ~/Arduino/hardware/pico
|
||||
@@ -141,12 +199,20 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory)
|
||||
|
||||
# Features
|
||||
* Adafruit TinyUSB Arduino (USB mouse, keyboard, flash drive, generic HID, CDC Serial, MIDI, WebUSB, others)
|
||||
* Generic Arduino USB Serial, Keyboard, and Mouse emulation
|
||||
* Bluetooth on the PicoW (Classic and BLE) with Keyboard, Mouse, Joystick, and Virtual Serial
|
||||
* Generic Arduino USB Serial, Keyboard, Joystick, and Mouse emulation
|
||||
* WiFi (Pico W)
|
||||
* HTTP client and server (WebServer)
|
||||
* SSL/TLS/HTTPS
|
||||
* Over-the-Air (OTA) upgrades
|
||||
* Filesystems (LittleFS and SD/SDFS)
|
||||
* Multicore support (setup1() and loop1())
|
||||
* FreeRTOS SMP support
|
||||
* Overclocking and underclocking from the menus
|
||||
* digitalWrite/Read, shiftIn/Out, tone, analogWrite(PWM)/Read, temperature
|
||||
* Analog stereo audio in using DMA and the built-in ADC
|
||||
* Analog stereo audio out using PWM hardware
|
||||
* USB drive mode for data loggers (SingleFileDrive)
|
||||
* Peripherals: SPI master, Wire(I2C) master/slave, dual UART, emulated EEPROM, I2S audio input, I2S audio output, Servo
|
||||
* printf (i.e. debug) output over USB serial
|
||||
|
||||
@@ -164,6 +230,10 @@ Here are some links to coverage and additional tutorials for using `arduino-pico
|
||||
* Pre-release Adafruit QT Py RP2040 - https://www.youtube.com/watch?v=sfC1msqXX0I
|
||||
* Adafruit Feather RP2040 running LCD + TMP117 - https://www.youtube.com/watch?v=fKDeqZiIwHg
|
||||
* Demonstration of Servos and I2C in Korean - https://cafe.naver.com/arduinoshield/1201
|
||||
* Home Assistant Pico W integration starter project using Arduino - https://github.com/daniloc/PicoW_HomeAssistant_Starter
|
||||
* Tutorials for the Raspberry Pi Pico / uPesy RP2040 DevKit board
|
||||
- English version: https://www.upesy.com/blogs/tutorials/best-tutorials-for-rpi-pi-pico-with-arduino-code
|
||||
- French version: https://www.upesy.fr/blogs/tutorials/best-tutorials-for-rpi-pi-pico-with-arduino-code
|
||||
|
||||
# Contributing
|
||||
If you want to contribute or have bugfixes, drop me a note at <earlephilhower@yahoo.com> or open an issue/PR here.
|
||||
@@ -175,8 +245,16 @@ If you want to contribute or have bugfixes, drop me a note at <earlephilhower@ya
|
||||
* [Arduino-Pico](https://github.com/earlephilhower/arduino-pico) core files are licensed under the LGPL.
|
||||
* [LittleFS](https://github.com/ARMmbed/littlefs) library written by ARM Limited and released under the [BSD 3-clause license](https://github.com/ARMmbed/littlefs/blob/master/LICENSE.md).
|
||||
* [UF2CONV.PY](https://github.com/microsoft/uf2) is by Microsoft Corporation and licensed under the MIT license.
|
||||
* Some filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
|
||||
* Networking and filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
|
||||
* DHCP server for AP host mode from the [Micropython Project](https://micropython.org), distributed under the MIT License.
|
||||
* [FreeRTOS](https://freertos.org) is Copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
|
||||
* [lwIP](https://savannah.nongnu.org/projects/lwip/) is (c) the Swedish Institute of Computer Science and licenced under the BSD license.
|
||||
* [BearSSL](https://bearssl.org) library written by Thomas Pornin, is distributed under the [MIT License](https://bearssl.org/#legal-details).
|
||||
* [UZLib](https://github.com/pfalcon/uzlib) is copyright (c) 2003 Joergen Ibsen and distributed under the zlib license.
|
||||
* [LEAmDNS](https://github.com/LaborEtArs/ESP8266mDNS) is copyright multiple authors and distributed under the MIT license.
|
||||
* [http-parser](https://github.com/nodejs/http-parser) is copyright Joyent, Inc. and other Node contributors.
|
||||
* WebServer code modified from the [ESP32 WebServer](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer) and is copyright (c) 2015 Ivan Grokhotkov and others
|
||||
|
||||
-Earle F. Philhower, III
|
||||
|
||||
-Earle F. Philhower, III
|
||||
earlephilhower@yahoo.com
|
||||
|
||||
+11054
-10365
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: generated\Winbond\W25Q128JVxQ\boot2.bin by @maxgerhardt
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0xf7, 0xb5, 0x73, 0x46, 0x21, 0x22, 0x02, 0x26, 0x01, 0x93, 0x29, 0x4b, 0xc0, 0x24, 0x5a, 0x60
|
||||
.byte 0x9a, 0x68, 0x00, 0x27, 0xb2, 0x43, 0xda, 0x60, 0x9a, 0x60, 0x1a, 0x61, 0x5a, 0x61, 0x04, 0x23
|
||||
.byte 0x01, 0x25, 0x64, 0x05, 0xa7, 0x60, 0x63, 0x61, 0x22, 0x4b, 0x30, 0x00, 0x1d, 0x60, 0xe0, 0x23
|
||||
.byte 0xdb, 0x02, 0x23, 0x60, 0x35, 0x23, 0xa5, 0x60, 0x23, 0x66, 0x23, 0x66, 0x00, 0xf0, 0x4a, 0xf8
|
||||
.byte 0xc0, 0xb2, 0xb0, 0x42, 0x12, 0xd0, 0x06, 0x23, 0x28, 0x00, 0x23, 0x66, 0x00, 0xf0, 0x42, 0xf8
|
||||
.byte 0x25, 0x66, 0x03, 0x20, 0x27, 0x66, 0x26, 0x66, 0x00, 0xf0, 0x3c, 0xf8, 0x03, 0x36, 0x26, 0x66
|
||||
.byte 0x02, 0x20, 0x26, 0x66, 0x00, 0xf0, 0x36, 0xf8, 0x28, 0x42, 0xf8, 0xd1, 0x00, 0x25, 0x12, 0x4b
|
||||
.byte 0xa5, 0x60, 0x12, 0x4f, 0x23, 0x60, 0x12, 0x4b, 0x65, 0x60, 0x01, 0x26, 0x3b, 0x60, 0xeb, 0x23
|
||||
.byte 0xa6, 0x60, 0x23, 0x66, 0x4b, 0x3b, 0x23, 0x66, 0x02, 0x20, 0x00, 0xf0, 0x23, 0xf8, 0x0d, 0x4b
|
||||
.byte 0xa5, 0x60, 0x3b, 0x60, 0xa6, 0x60, 0x01, 0x9b, 0xab, 0x42, 0x08, 0xd1, 0x0a, 0x4b, 0x0b, 0x4a
|
||||
.byte 0x13, 0x60, 0x1b, 0x68, 0x83, 0xf3, 0x08, 0x88, 0x09, 0x4b, 0x1b, 0x68, 0x18, 0x47, 0xf7, 0xbd
|
||||
.byte 0x00, 0x00, 0x02, 0x40, 0xf0, 0x00, 0x00, 0x18, 0x00, 0x03, 0x5f, 0x00, 0xf4, 0x00, 0x00, 0x18
|
||||
.byte 0x21, 0x22, 0x00, 0x00, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
|
||||
.byte 0x04, 0x01, 0x00, 0x10, 0xc0, 0x22, 0x03, 0x00, 0x04, 0x21, 0x52, 0x05, 0x90, 0x6a, 0x08, 0x42
|
||||
.byte 0xfc, 0xd0, 0x01, 0x21, 0x90, 0x6a, 0x08, 0x42, 0xfc, 0xd1, 0x01, 0x3b, 0xdb, 0xb2, 0x10, 0x6e
|
||||
.byte 0x00, 0x2b, 0xfa, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xa0, 0xf0, 0x2f
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: generated\Winbond\W25Q16JVxQ\boot2.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0xf7, 0xb5, 0x73, 0x46, 0x21, 0x22, 0x02, 0x26, 0x01, 0x93, 0x29, 0x4b, 0xc0, 0x24, 0x5a, 0x60
|
||||
.byte 0x9a, 0x68, 0x00, 0x27, 0xb2, 0x43, 0xda, 0x60, 0x9a, 0x60, 0x1a, 0x61, 0x5a, 0x61, 0x04, 0x23
|
||||
.byte 0x01, 0x25, 0x64, 0x05, 0xa7, 0x60, 0x63, 0x61, 0x22, 0x4b, 0x30, 0x00, 0x1d, 0x60, 0xe0, 0x23
|
||||
.byte 0xdb, 0x02, 0x23, 0x60, 0x35, 0x23, 0xa5, 0x60, 0x23, 0x66, 0x23, 0x66, 0x00, 0xf0, 0x4a, 0xf8
|
||||
.byte 0xc0, 0xb2, 0xb0, 0x42, 0x12, 0xd0, 0x06, 0x23, 0x28, 0x00, 0x23, 0x66, 0x00, 0xf0, 0x42, 0xf8
|
||||
.byte 0x25, 0x66, 0x03, 0x20, 0x27, 0x66, 0x26, 0x66, 0x00, 0xf0, 0x3c, 0xf8, 0x03, 0x36, 0x26, 0x66
|
||||
.byte 0x02, 0x20, 0x26, 0x66, 0x00, 0xf0, 0x36, 0xf8, 0x28, 0x42, 0xf8, 0xd1, 0x00, 0x25, 0x12, 0x4b
|
||||
.byte 0xa5, 0x60, 0x12, 0x4f, 0x23, 0x60, 0x12, 0x4b, 0x65, 0x60, 0x01, 0x26, 0x3b, 0x60, 0xeb, 0x23
|
||||
.byte 0xa6, 0x60, 0x23, 0x66, 0x4b, 0x3b, 0x23, 0x66, 0x02, 0x20, 0x00, 0xf0, 0x23, 0xf8, 0x0d, 0x4b
|
||||
.byte 0xa5, 0x60, 0x3b, 0x60, 0xa6, 0x60, 0x01, 0x9b, 0xab, 0x42, 0x08, 0xd1, 0x0a, 0x4b, 0x0b, 0x4a
|
||||
.byte 0x13, 0x60, 0x1b, 0x68, 0x83, 0xf3, 0x08, 0x88, 0x09, 0x4b, 0x1b, 0x68, 0x18, 0x47, 0xf7, 0xbd
|
||||
.byte 0x00, 0x00, 0x02, 0x40, 0xf0, 0x00, 0x00, 0x18, 0x00, 0x03, 0x5f, 0x00, 0xf4, 0x00, 0x00, 0x18
|
||||
.byte 0x21, 0x22, 0x00, 0x00, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
|
||||
.byte 0x04, 0x01, 0x00, 0x10, 0xc0, 0x22, 0x03, 0x00, 0x04, 0x21, 0x52, 0x05, 0x90, 0x6a, 0x08, 0x42
|
||||
.byte 0xfc, 0xd0, 0x01, 0x21, 0x90, 0x6a, 0x08, 0x42, 0xfc, 0xd1, 0x01, 0x3b, 0xdb, 0xb2, 0x10, 0x6e
|
||||
.byte 0x00, 0x2b, 0xfa, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xa0, 0xf0, 0x2f
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_w25q64jv.4.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0xf7, 0xb5, 0x73, 0x46, 0x21, 0x22, 0x02, 0x25, 0x01, 0x93, 0x29, 0x4b, 0xc0, 0x24, 0x5a, 0x60
|
||||
.byte 0x9a, 0x68, 0x01, 0x26, 0xaa, 0x43, 0xda, 0x60, 0x9a, 0x60, 0x1a, 0x61, 0x5a, 0x61, 0x00, 0x23
|
||||
.byte 0x64, 0x05, 0xa3, 0x60, 0x04, 0x33, 0x63, 0x61, 0x22, 0x4b, 0x28, 0x00, 0x1e, 0x60, 0xe0, 0x23
|
||||
.byte 0xdb, 0x02, 0x23, 0x60, 0x35, 0x23, 0xa6, 0x60, 0x23, 0x66, 0x23, 0x66, 0x00, 0xf0, 0x4a, 0xf8
|
||||
.byte 0xc0, 0xb2, 0xa8, 0x42, 0x12, 0xd0, 0x06, 0x23, 0x30, 0x00, 0x23, 0x66, 0x00, 0xf0, 0x42, 0xf8
|
||||
.byte 0x31, 0x23, 0x28, 0x00, 0x23, 0x66, 0x25, 0x66, 0x00, 0xf0, 0x3c, 0xf8, 0x03, 0x35, 0x25, 0x66
|
||||
.byte 0x02, 0x20, 0x25, 0x66, 0x00, 0xf0, 0x36, 0xf8, 0x30, 0x42, 0xf8, 0xd1, 0x00, 0x25, 0x12, 0x4b
|
||||
.byte 0xa5, 0x60, 0x12, 0x4f, 0x23, 0x60, 0x12, 0x4b, 0x65, 0x60, 0x01, 0x26, 0x3b, 0x60, 0xeb, 0x23
|
||||
.byte 0xa6, 0x60, 0x23, 0x66, 0x4b, 0x3b, 0x23, 0x66, 0x02, 0x20, 0x00, 0xf0, 0x23, 0xf8, 0x0d, 0x4b
|
||||
.byte 0xa5, 0x60, 0x3b, 0x60, 0xa6, 0x60, 0x01, 0x9b, 0xab, 0x42, 0x08, 0xd1, 0x0a, 0x4b, 0x0b, 0x4a
|
||||
.byte 0x13, 0x60, 0x1b, 0x68, 0x83, 0xf3, 0x08, 0x88, 0x09, 0x4b, 0x1b, 0x68, 0x18, 0x47, 0xf7, 0xbd
|
||||
.byte 0x00, 0x00, 0x02, 0x40, 0xf0, 0x00, 0x00, 0x18, 0x00, 0x03, 0x5f, 0x00, 0xf4, 0x00, 0x00, 0x18
|
||||
.byte 0x21, 0x22, 0x00, 0x00, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
|
||||
.byte 0x04, 0x01, 0x00, 0x10, 0xc0, 0x23, 0x02, 0x00, 0x04, 0x21, 0x5b, 0x05, 0x98, 0x6a, 0x08, 0x42
|
||||
.byte 0xfc, 0xd0, 0x01, 0x21, 0x98, 0x6a, 0x08, 0x42, 0xfc, 0xd1, 0x18, 0x6e, 0x01, 0x2a, 0x00, 0xd0
|
||||
.byte 0x18, 0x6e, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x2d, 0x68, 0xca
|
||||
+34
-8
@@ -18,8 +18,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@@ -29,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
|
||||
|
||||
@@ -69,30 +68,48 @@ void noInterrupts();
|
||||
#define portOutputRegister(port) ((volatile uint32_t*) sio_hw->gpio_out)
|
||||
#define portInputRegister(port) ((volatile uint32_t*) sio_hw->gpio_in)
|
||||
#define portModeRegister(port) ((volatile uint32_t*) sio_hw->gpio_oe)
|
||||
#define digitalWriteFast(pin, val) (val ? sio_hw->gpio_set = (1 << pin) : sio_hw->gpio_clr = (1 << pin))
|
||||
#define digitalReadFast(pin) ((1 << pin) & sio_hw->gpio_in)
|
||||
#define sei() interrupts()
|
||||
#define cli() noInterrupts()
|
||||
|
||||
// ADC RP2040-specific calls
|
||||
void analogReadResolution(int bits);
|
||||
float analogReadTemp(); // Returns core temp in Centigrade
|
||||
#ifdef __cplusplus
|
||||
float analogReadTemp(float vref = 3.3); // Returns core temp in Centigrade
|
||||
#endif
|
||||
|
||||
// PWM RP2040-specific calls
|
||||
void analogWriteFreq(uint32_t freq);
|
||||
void analogWriteRange(uint32_t range);
|
||||
void analogWriteResolution(int res);
|
||||
|
||||
// FreeRTOS potential calls
|
||||
extern bool __isFreeRTOS;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// FreeRTOS potential calls
|
||||
extern bool __isFreeRTOS;
|
||||
|
||||
// Ancient AVR defines
|
||||
#define HAVE_HWSERIAL0
|
||||
#define HAVE_HWSERIAL1
|
||||
#define HAVE_HWSERIAL2
|
||||
|
||||
// PSTR/etc.
|
||||
#ifndef FPSTR
|
||||
#define FPSTR (const char *)
|
||||
#endif
|
||||
|
||||
#ifndef PGM_VOID_P
|
||||
#define PGM_VOID_P void *
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
// emptyString is an ESP-ism, a constant string with ""
|
||||
extern const String emptyString;
|
||||
|
||||
#ifdef USE_TINYUSB
|
||||
// Needed for declaring Serial
|
||||
#include "Adafruit_USBD_CDC.h"
|
||||
@@ -113,4 +130,13 @@ constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // Arduino_h
|
||||
// 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.
|
||||
//
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
CoreMutex for the Raspberry Pi Pico RP2040
|
||||
|
||||
Implements a deadlock-safe multicore mutex for sharing things like the
|
||||
USB or UARTs.
|
||||
|
||||
Copyright (c) 2021 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 "CoreMutex.h"
|
||||
|
||||
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 (__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;
|
||||
if (!mutex_try_enter(_mutex, &owner)) {
|
||||
if (owner == get_core_num()) { // Deadlock!
|
||||
if (_option & DebugEnable) {
|
||||
DEBUGCORE("CoreMutex - Deadlock detected!\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
mutex_enter_blocking(_mutex);
|
||||
}
|
||||
}
|
||||
_acquired = true;
|
||||
}
|
||||
|
||||
CoreMutex::~CoreMutex() {
|
||||
if (_acquired) {
|
||||
if (__isFreeRTOS) {
|
||||
auto m = __get_freertos_mutex_for_ptr(_mutex);
|
||||
if (__freertos_check_if_in_isr()) {
|
||||
__freertos_mutex_give_from_isr(m, &_pxHigherPriorityTaskWoken);
|
||||
} else {
|
||||
__freertos_mutex_give(m);
|
||||
}
|
||||
} else {
|
||||
mutex_exit(_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-20
@@ -23,29 +23,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pico/mutex.h"
|
||||
#include <pico/mutex.h>
|
||||
#include "_freertos.h"
|
||||
|
||||
enum {
|
||||
DebugEnable = 1
|
||||
};
|
||||
|
||||
class CoreMutex {
|
||||
public:
|
||||
CoreMutex(mutex_t *mutex) {
|
||||
uint32_t owner;
|
||||
_mutex = mutex;
|
||||
_acquired = false;
|
||||
if (!mutex_try_enter(_mutex, &owner)) {
|
||||
if (owner == get_core_num()) { // Deadlock!
|
||||
DEBUGCORE("CoreMutex - Deadlock detected!\n");
|
||||
return;
|
||||
}
|
||||
mutex_enter_blocking(_mutex);
|
||||
}
|
||||
_acquired = true;
|
||||
}
|
||||
|
||||
~CoreMutex() {
|
||||
if (_acquired) {
|
||||
mutex_exit(_mutex);
|
||||
}
|
||||
}
|
||||
CoreMutex(mutex_t *mutex, uint8_t option = DebugEnable);
|
||||
~CoreMutex();
|
||||
|
||||
operator bool() {
|
||||
return _acquired;
|
||||
@@ -54,4 +42,6 @@ public:
|
||||
private:
|
||||
mutex_t *_mutex;
|
||||
bool _acquired;
|
||||
uint8_t _option;
|
||||
BaseType_t _pxHigherPriorityTaskWoken;
|
||||
};
|
||||
|
||||
+6
-7
@@ -192,13 +192,12 @@ File File::openNextFile() {
|
||||
String File::readString() {
|
||||
String ret;
|
||||
ret.reserve(size() - position());
|
||||
char temp[256 + 1];
|
||||
int countRead = readBytes(temp, sizeof(temp) - 1);
|
||||
while (countRead > 0) {
|
||||
temp[countRead] = 0;
|
||||
ret += temp;
|
||||
countRead = readBytes(temp, sizeof(temp) - 1);
|
||||
}
|
||||
uint8_t temp[256];
|
||||
int countRead;
|
||||
do {
|
||||
countRead = read(temp, sizeof(temp));
|
||||
ret.concat(temp, countRead);
|
||||
} while (countRead > 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+6
-8
@@ -18,8 +18,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FS_H
|
||||
#define FS_H
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <Arduino.h>
|
||||
@@ -51,7 +50,9 @@ enum SeekMode {
|
||||
|
||||
class File : public Stream {
|
||||
public:
|
||||
File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) { }
|
||||
File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) {
|
||||
_startMillis = millis(); /* workaround -O3 spurious warning #768 */
|
||||
}
|
||||
|
||||
// Print methods:
|
||||
size_t write(uint8_t) override;
|
||||
@@ -91,9 +92,8 @@ public:
|
||||
uint8_t obuf[256];
|
||||
size_t doneLen = 0;
|
||||
size_t sentLen;
|
||||
int i;
|
||||
|
||||
while (src.available() > sizeof(obuf)) {
|
||||
while ((size_t)src.available() > sizeof(obuf)) {
|
||||
src.read(obuf, sizeof(obuf));
|
||||
sentLen = write(obuf, sizeof(obuf));
|
||||
doneLen = doneLen + sentLen;
|
||||
@@ -240,7 +240,7 @@ protected:
|
||||
}
|
||||
time_t (*_timeCallback)(void) = nullptr;
|
||||
static time_t _defaultTimeCB(void) {
|
||||
return time(NULL);
|
||||
return time(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -264,5 +264,3 @@ using fs::SeekEnd;
|
||||
using fs::FSInfo;
|
||||
using fs::FSConfig;
|
||||
#endif //FS_NO_GLOBALS
|
||||
|
||||
#endif //FS_H
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef FSIMPL_H
|
||||
#define FSIMPL_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@@ -149,5 +149,3 @@ protected:
|
||||
};
|
||||
|
||||
} // namespace fs
|
||||
|
||||
#endif //FSIMPL_H
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
PolledTimeout.h - Encapsulation of a polled Timeout
|
||||
|
||||
Copyright (c) 2018 Daniel Salazar. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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 <limits> // std::numeric_limits
|
||||
#include <type_traits> // std::is_unsigned
|
||||
|
||||
#define IRAM_ATTR
|
||||
|
||||
namespace esp8266 {
|
||||
|
||||
|
||||
namespace polledTimeout {
|
||||
|
||||
namespace YieldPolicy {
|
||||
|
||||
struct DoNothing {
|
||||
static void execute() {}
|
||||
};
|
||||
|
||||
struct YieldOrSkip {
|
||||
static void execute() {} //{esp_yield();}
|
||||
};
|
||||
|
||||
template <unsigned long delayMs>
|
||||
struct YieldAndDelayMs {
|
||||
static void execute() {
|
||||
delay(delayMs);
|
||||
}
|
||||
};
|
||||
|
||||
} //YieldPolicy
|
||||
|
||||
namespace TimePolicy {
|
||||
|
||||
struct TimeSourceMillis {
|
||||
// time policy in milli-seconds based on millis()
|
||||
|
||||
using timeType = decltype(millis());
|
||||
static timeType time() {
|
||||
return millis();
|
||||
}
|
||||
static constexpr timeType ticksPerSecond = 1000;
|
||||
static constexpr timeType ticksPerSecondMax = 1000;
|
||||
};
|
||||
|
||||
struct TimeSourceCycles {
|
||||
// time policy based on esp_get_cycle_count()
|
||||
// this particular time measurement is intended to be called very often
|
||||
// (every loop, every yield)
|
||||
|
||||
using timeType = decltype(rp2040.getCycleCount());
|
||||
static timeType time() {
|
||||
return rp2040.getCycleCount();
|
||||
}
|
||||
static constexpr timeType ticksPerSecond = F_CPU;
|
||||
static constexpr timeType ticksPerSecondMax = F_CPU;
|
||||
};
|
||||
|
||||
template <typename TimeSourceType, unsigned long long second_th>
|
||||
// "second_th" units of timeType for one second
|
||||
struct TimeUnit {
|
||||
using timeType = typename TimeSourceType::timeType;
|
||||
|
||||
#if __GNUC__ < 5
|
||||
// gcc-4.8 cannot compile the constexpr-only version of this function
|
||||
// using #defines instead luckily works
|
||||
static constexpr timeType computeRangeCompensation() {
|
||||
#define number_of_secondTh_in_one_tick ((1.0 * second_th) / ticksPerSecond)
|
||||
#define fractional (number_of_secondTh_in_one_tick - (long)number_of_secondTh_in_one_tick)
|
||||
|
||||
return ({
|
||||
fractional == 0 ?
|
||||
1 : // no need for compensation
|
||||
(number_of_secondTh_in_one_tick / fractional) + 0.5; // scalar multiplier allowing exact division
|
||||
});
|
||||
|
||||
#undef number_of_secondTh_in_one_tick
|
||||
#undef fractional
|
||||
}
|
||||
#else
|
||||
static constexpr timeType computeRangeCompensation() {
|
||||
return ({
|
||||
constexpr double number_of_secondTh_in_one_tick = (1.0 * second_th) / ticksPerSecond;
|
||||
constexpr double fractional = number_of_secondTh_in_one_tick - (long)number_of_secondTh_in_one_tick;
|
||||
fractional == 0 ?
|
||||
1 : // no need for compensation
|
||||
(number_of_secondTh_in_one_tick / fractional) + 0.5; // scalar multiplier allowing exact division
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
static constexpr timeType ticksPerSecond = TimeSourceType::ticksPerSecond;
|
||||
static constexpr timeType ticksPerSecondMax = TimeSourceType::ticksPerSecondMax;
|
||||
static constexpr timeType rangeCompensate = computeRangeCompensation();
|
||||
static constexpr timeType user2UnitMultiplierMax = (ticksPerSecondMax * rangeCompensate) / second_th;
|
||||
static constexpr timeType user2UnitMultiplier = (ticksPerSecond * rangeCompensate) / second_th;
|
||||
static constexpr timeType user2UnitDivider = rangeCompensate;
|
||||
// std::numeric_limits<timeType>::max() is reserved
|
||||
static constexpr timeType timeMax = (std::numeric_limits<timeType>::max() - 1) / user2UnitMultiplierMax;
|
||||
|
||||
static timeType toTimeTypeUnit(const timeType userUnit) {
|
||||
return (userUnit * user2UnitMultiplier) / user2UnitDivider;
|
||||
}
|
||||
static timeType toUserUnit(const timeType internalUnit) {
|
||||
return (internalUnit * user2UnitDivider) / user2UnitMultiplier;
|
||||
}
|
||||
static timeType time() {
|
||||
return TimeSourceType::time();
|
||||
}
|
||||
};
|
||||
|
||||
using TimeMillis = TimeUnit < TimeSourceMillis, 1'000 >;
|
||||
using TimeFastMillis = TimeUnit < TimeSourceCycles, 1'000 >;
|
||||
using TimeFastMicros = TimeUnit < TimeSourceCycles, 1'000'000 >;
|
||||
using TimeFastNanos = TimeUnit < TimeSourceCycles, 1'000'000'000 >;
|
||||
|
||||
} //TimePolicy
|
||||
|
||||
template <bool PeriodicT, typename YieldPolicyT = YieldPolicy::DoNothing, typename TimePolicyT = TimePolicy::TimeMillis>
|
||||
class timeoutTemplate {
|
||||
public:
|
||||
using timeType = typename TimePolicyT::timeType;
|
||||
static_assert(std::is_unsigned<timeType>::value == true, "timeType must be unsigned");
|
||||
|
||||
static constexpr timeType alwaysExpired = 0;
|
||||
static constexpr timeType neverExpires = std::numeric_limits<timeType>::max();
|
||||
static constexpr timeType rangeCompensate = TimePolicyT::rangeCompensate; //debug
|
||||
|
||||
timeoutTemplate(const timeType userTimeout) {
|
||||
reset(userTimeout);
|
||||
}
|
||||
|
||||
IRAM_ATTR // fast
|
||||
bool expired() {
|
||||
YieldPolicyT::execute(); //in case of DoNothing: gets optimized away
|
||||
if (PeriodicT) { //in case of false: gets optimized away
|
||||
return expiredRetrigger();
|
||||
}
|
||||
return expiredOneShot();
|
||||
}
|
||||
|
||||
IRAM_ATTR // fast
|
||||
operator bool() {
|
||||
return expired();
|
||||
}
|
||||
|
||||
bool canExpire() const {
|
||||
return !_neverExpires;
|
||||
}
|
||||
|
||||
bool canWait() const {
|
||||
return _timeout != alwaysExpired;
|
||||
}
|
||||
|
||||
// Resets, will trigger after this new timeout.
|
||||
IRAM_ATTR // called from ISR
|
||||
void reset(const timeType newUserTimeout) {
|
||||
reset();
|
||||
_timeout = TimePolicyT::toTimeTypeUnit(newUserTimeout);
|
||||
_neverExpires = (newUserTimeout < 0) || (newUserTimeout > timeMax());
|
||||
}
|
||||
|
||||
// Resets, will trigger after the timeout previously set.
|
||||
IRAM_ATTR // called from ISR
|
||||
void reset() {
|
||||
_start = TimePolicyT::time();
|
||||
}
|
||||
|
||||
// Resets to just expired so that on next poll the check will immediately trigger for the user,
|
||||
// also change timeout (after next immediate trigger).
|
||||
IRAM_ATTR // called from ISR
|
||||
void resetAndSetExpired(const timeType newUserTimeout) {
|
||||
reset(newUserTimeout);
|
||||
_start -= _timeout;
|
||||
}
|
||||
|
||||
// Resets to just expired so that on next poll the check will immediately trigger for the user.
|
||||
IRAM_ATTR // called from ISR
|
||||
void resetAndSetExpired() {
|
||||
reset();
|
||||
_start -= _timeout;
|
||||
}
|
||||
|
||||
void resetToNeverExpires() {
|
||||
_timeout = alwaysExpired + 1; // because canWait() has precedence
|
||||
_neverExpires = true;
|
||||
}
|
||||
|
||||
timeType getTimeout() const {
|
||||
return TimePolicyT::toUserUnit(_timeout);
|
||||
}
|
||||
|
||||
static constexpr timeType timeMax() {
|
||||
return TimePolicyT::timeMax;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
IRAM_ATTR // fast
|
||||
bool checkExpired(const timeType internalUnit) const {
|
||||
// canWait() is not checked here
|
||||
// returns "can expire" and "time expired"
|
||||
return (!_neverExpires) && ((internalUnit - _start) >= _timeout);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
IRAM_ATTR // fast
|
||||
bool expiredRetrigger() {
|
||||
if (!canWait()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
timeType current = TimePolicyT::time();
|
||||
if (checkExpired(current)) {
|
||||
unsigned long n = (current - _start) / _timeout; //how many _timeouts periods have elapsed, will usually be 1 (current - _start >= _timeout)
|
||||
_start += n * _timeout;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IRAM_ATTR // fast
|
||||
bool expiredOneShot() const {
|
||||
// returns "always expired" or "has expired"
|
||||
return !canWait() || checkExpired(TimePolicyT::time());
|
||||
}
|
||||
|
||||
timeType _timeout;
|
||||
timeType _start;
|
||||
bool _neverExpires;
|
||||
};
|
||||
|
||||
// legacy type names, deprecated (unit is milliseconds)
|
||||
|
||||
using oneShot = polledTimeout::timeoutTemplate<false> /*__attribute__((deprecated("use oneShotMs")))*/;
|
||||
using periodic = polledTimeout::timeoutTemplate<true> /*__attribute__((deprecated("use periodicMs")))*/;
|
||||
|
||||
// standard versions (based on millis())
|
||||
// timeMax() is 49.7 days ((2^32)-2 ms)
|
||||
|
||||
using oneShotMs = polledTimeout::timeoutTemplate<false>;
|
||||
using periodicMs = polledTimeout::timeoutTemplate<true>;
|
||||
|
||||
// Time policy based on esp_get_cycle_count(), and intended to be called very often:
|
||||
// "Fast" versions sacrifices time range for improved precision and reduced execution time (by 86%)
|
||||
// (cpu cycles for ::expired(): 372 (millis()) vs 52 (esp_get_cycle_count()))
|
||||
// timeMax() values:
|
||||
// Ms: max is 26843 ms (26.8 s)
|
||||
// Us: max is 26843545 us (26.8 s)
|
||||
// Ns: max is 1073741823 ns ( 1.07 s)
|
||||
// (time policy based on esp_get_cycle_count() is intended to be called very often)
|
||||
|
||||
using oneShotFastMs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
|
||||
using periodicFastMs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
|
||||
using oneShotFastUs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMicros>;
|
||||
using periodicFastUs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMicros>;
|
||||
using oneShotFastNs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastNanos>;
|
||||
using periodicFastNs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastNanos>;
|
||||
|
||||
} //polledTimeout
|
||||
|
||||
|
||||
/* A 1-shot timeout that auto-yields when in CONT can be built as follows:
|
||||
using oneShotYieldMs = esp8266::polledTimeout::timeoutTemplate<false, esp8266::polledTimeout::YieldPolicy::YieldOrSkip>;
|
||||
|
||||
Other policies can be implemented by the user, e.g.: simple yield that panics in SYS, and the polledTimeout types built as needed as shown above, without modifying this file.
|
||||
*/
|
||||
|
||||
}//esp8266
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
RP2040 utility class
|
||||
|
||||
Copyright (c) 2021 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 <hardware/structs/psm.h>
|
||||
|
||||
extern "C" void boot_double_tap_check();
|
||||
|
||||
// The following check will never actually execute, but it will cause the boot reset
|
||||
// checker to be linked in as part of the constructors.
|
||||
|
||||
void RP2040::enableDoubleResetBootloader() {
|
||||
if (psm_hw->done == 0) {
|
||||
boot_double_tap_check();
|
||||
}
|
||||
}
|
||||
@@ -21,13 +21,21 @@
|
||||
#include <hardware/clocks.h>
|
||||
#include <hardware/irq.h>
|
||||
#include <hardware/pio.h>
|
||||
#include <pico/unique_id.h>
|
||||
#include <hardware/exception.h>
|
||||
#include <hardware/watchdog.h>
|
||||
#include <hardware/structs/rosc.h>
|
||||
#include <hardware/structs/systick.h>
|
||||
#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>
|
||||
|
||||
#include "_freertos.h"
|
||||
|
||||
extern "C" volatile bool __otherCoreIdled;
|
||||
|
||||
@@ -85,10 +93,14 @@ public:
|
||||
if (!_multicore) {
|
||||
return;
|
||||
}
|
||||
mutex_enter_blocking(&_idleMutex);
|
||||
__otherCoreIdled = false;
|
||||
multicore_fifo_push_blocking(_GOTOSLEEP);
|
||||
while (!__otherCoreIdled) { /* noop */ }
|
||||
if (__isFreeRTOS) {
|
||||
__freertos_idle_other_core();
|
||||
} else {
|
||||
mutex_enter_blocking(&_idleMutex);
|
||||
__otherCoreIdled = false;
|
||||
multicore_fifo_push_blocking(_GOTOSLEEP);
|
||||
while (!__otherCoreIdled) { /* noop */ }
|
||||
}
|
||||
}
|
||||
|
||||
void resumeOtherCore() {
|
||||
@@ -97,6 +109,10 @@ public:
|
||||
}
|
||||
mutex_exit(&_idleMutex);
|
||||
__otherCoreIdled = false;
|
||||
if (__isFreeRTOS) {
|
||||
__freertos_resume_other_core();
|
||||
}
|
||||
|
||||
// Other core will exit busy-loop and return to operation
|
||||
// once __otherCoreIdled == false.
|
||||
}
|
||||
@@ -139,61 +155,8 @@ private:
|
||||
class RP2040;
|
||||
extern RP2040 rp2040;
|
||||
extern "C" void main1();
|
||||
class PIOProgram;
|
||||
|
||||
// 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;
|
||||
};
|
||||
extern "C" char __StackLimit;
|
||||
extern "C" char __bss_end__;
|
||||
|
||||
class RP2040 {
|
||||
public:
|
||||
@@ -219,7 +182,7 @@ public:
|
||||
// Convert from microseconds to PIO clock cycles
|
||||
static int usToPIOCycles(int us) {
|
||||
// Parenthesis needed to guarantee order of operations to avoid 32bit overflow
|
||||
return (us * (clock_get_hz(clk_sys) / 1000000));
|
||||
return (us * (clock_get_hz(clk_sys) / 1'000'000));
|
||||
}
|
||||
|
||||
// Get current clock frequency
|
||||
@@ -227,6 +190,11 @@ public:
|
||||
return clock_get_hz(clk_sys);
|
||||
}
|
||||
|
||||
// Get current CPU core number
|
||||
static int cpuid() {
|
||||
return sio_hw->cpuid;
|
||||
}
|
||||
|
||||
// Get CPU cycle count. Needs to do magic to extens 24b HW to something longer
|
||||
volatile uint64_t _epoch = 0;
|
||||
inline uint32_t getCycleCount() {
|
||||
@@ -257,6 +225,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline int getFreeHeap() {
|
||||
return getTotalHeap() - getUsedHeap();
|
||||
}
|
||||
|
||||
inline int getUsedHeap() {
|
||||
struct mallinfo m = mallinfo();
|
||||
return m.uordblks;
|
||||
}
|
||||
|
||||
inline int getTotalHeap() {
|
||||
return &__StackLimit - &__bss_end__;
|
||||
}
|
||||
|
||||
void idleOtherCore() {
|
||||
fifo.idleOtherCore();
|
||||
}
|
||||
@@ -271,9 +252,60 @@ public:
|
||||
multicore_launch_core1(main1);
|
||||
}
|
||||
|
||||
void reboot() {
|
||||
watchdog_reboot(0, 0, 10);
|
||||
while (1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
inline void restart() {
|
||||
reboot();
|
||||
}
|
||||
|
||||
inline void rebootToBootloader() {
|
||||
reset_usb_boot(0, 0);
|
||||
while (1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
static void enableDoubleResetBootloader();
|
||||
|
||||
void wdt_begin(uint32_t delay_ms) {
|
||||
watchdog_enable(delay_ms, 1);
|
||||
}
|
||||
|
||||
void wdt_reset() {
|
||||
watchdog_update();
|
||||
}
|
||||
|
||||
const char *getChipID() {
|
||||
static char id[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1] = { 0 };
|
||||
if (!id[0]) {
|
||||
pico_get_unique_board_id_string(id, sizeof(id));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
// Multicore comms FIFO
|
||||
_MFIFO fifo;
|
||||
|
||||
|
||||
uint32_t hwrand32() {
|
||||
return get_rand_32();
|
||||
}
|
||||
|
||||
bool isPicoW() {
|
||||
#if !defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
return false;
|
||||
#else
|
||||
extern bool __isPicoW;
|
||||
return __isPicoW;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static void _SystickHandler() {
|
||||
rp2040._epoch += 1LL << 24;
|
||||
|
||||
+349
-67
@@ -25,14 +25,18 @@
|
||||
#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 <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>
|
||||
|
||||
// Big, global USB mutex, shared with all USB devices to make sure we don't
|
||||
// have multiple cores updating the TUSB state in parallel
|
||||
@@ -40,14 +44,13 @@ mutex_t __usb_mutex;
|
||||
|
||||
// USB processing will be a periodic timer task
|
||||
#define USB_TASK_INTERVAL 1000
|
||||
#define USB_TASK_IRQ 31
|
||||
static int __usb_task_irq;
|
||||
|
||||
// USB VID/PID (note that PID can change depending on the add'l interfaces)
|
||||
#ifndef USBD_VID
|
||||
#define USBD_VID (0x2E8A) // Raspberry Pi
|
||||
#endif
|
||||
|
||||
#ifdef SERIALUSB_PID
|
||||
#define USBD_PID (SERIALUSB_PID)
|
||||
#else
|
||||
#ifndef USBD_PID
|
||||
#define USBD_PID (0x000a) // Raspberry Pi Pico SDK CDC
|
||||
#endif
|
||||
|
||||
@@ -67,11 +70,17 @@ mutex_t __usb_mutex;
|
||||
#define USBD_STR_PRODUCT (0x02)
|
||||
#define USBD_STR_SERIAL (0x03)
|
||||
#define USBD_STR_CDC (0x04)
|
||||
|
||||
#define USBD_STR_RPI_RESET (0x05)
|
||||
|
||||
#define EPNUM_HID 0x83
|
||||
|
||||
#define EPNUM_MIDI 0x01
|
||||
#define USBD_MSC_EPOUT 0x03
|
||||
#define USBD_MSC_EPIN 0x84
|
||||
#define USBD_MSC_EPSIZE 64
|
||||
|
||||
#define TUD_RPI_RESET_DESCRIPTOR(_itfnum, _stridx) \
|
||||
/* Interface */\
|
||||
9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_VENDOR_SPECIFIC, RESET_INTERFACE_SUBCLASS, RESET_INTERFACE_PROTOCOL, _stridx,
|
||||
|
||||
|
||||
const uint8_t *tud_descriptor_device_cb(void) {
|
||||
@@ -91,7 +100,7 @@ const uint8_t *tud_descriptor_device_cb(void) {
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1
|
||||
};
|
||||
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallMIDI) {
|
||||
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallAbsoluteMouse && !__USBInstallJoystick && !__USBInstallMassStorage) {
|
||||
// Can use as-is, this is the default USB case
|
||||
return (const uint8_t *)&usbd_desc_device;
|
||||
}
|
||||
@@ -99,11 +108,14 @@ const uint8_t *tud_descriptor_device_cb(void) {
|
||||
if (__USBInstallKeyboard) {
|
||||
usbd_desc_device.idProduct |= 0x8000;
|
||||
}
|
||||
if (__USBInstallMouse) {
|
||||
if (__USBInstallMouse || __USBInstallAbsoluteMouse) {
|
||||
usbd_desc_device.idProduct |= 0x4000;
|
||||
}
|
||||
if (__USBInstallMIDI) {
|
||||
usbd_desc_device.idProduct |= 0x2000;
|
||||
if (__USBInstallJoystick) {
|
||||
usbd_desc_device.idProduct |= 0x0100;
|
||||
}
|
||||
if (__USBInstallMassStorage) {
|
||||
usbd_desc_device.idProduct ^= 0x2000;
|
||||
}
|
||||
// Set the device class to 0 to indicate multiple device classes
|
||||
usbd_desc_device.bDeviceClass = 0;
|
||||
@@ -117,7 +129,18 @@ int __USBGetKeyboardReportID() {
|
||||
}
|
||||
|
||||
int __USBGetMouseReportID() {
|
||||
return __USBInstallKeyboard ? 2 : 1;
|
||||
return __USBInstallKeyboard ? 3 : 1;
|
||||
}
|
||||
|
||||
int __USBGetJoystickReportID() {
|
||||
int i = 1;
|
||||
if (__USBInstallKeyboard) {
|
||||
i += 2;
|
||||
}
|
||||
if (__USBInstallMouse || __USBInstallAbsoluteMouse) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int __hid_report_len = 0;
|
||||
@@ -131,37 +154,82 @@ static uint8_t *GetDescHIDReport(int *len) {
|
||||
}
|
||||
|
||||
void __SetupDescHIDReport() {
|
||||
if (__USBInstallKeyboard && __USBInstallMouse) {
|
||||
uint8_t desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)),
|
||||
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(2))
|
||||
};
|
||||
__hid_report = (uint8_t *)malloc(sizeof(desc_hid_report));
|
||||
if (__hid_report) {
|
||||
__hid_report_len = sizeof(desc_hid_report);
|
||||
memcpy(__hid_report, desc_hid_report, __hid_report_len);
|
||||
}
|
||||
} else if (__USBInstallKeyboard && ! __USBInstallMouse) {
|
||||
uint8_t desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1))
|
||||
};
|
||||
__hid_report = (uint8_t *)malloc(sizeof(desc_hid_report));
|
||||
if (__hid_report) {
|
||||
__hid_report_len = sizeof(desc_hid_report);
|
||||
memcpy(__hid_report, desc_hid_report, __hid_report_len);
|
||||
}
|
||||
} else if (! __USBInstallKeyboard && __USBInstallMouse) {
|
||||
uint8_t desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1))
|
||||
};
|
||||
__hid_report = (uint8_t *)malloc(sizeof(desc_hid_report));
|
||||
if (__hid_report) {
|
||||
__hid_report_len = sizeof(desc_hid_report);
|
||||
memcpy(__hid_report, desc_hid_report, __hid_report_len);
|
||||
}
|
||||
} else {
|
||||
//allocate memory for the HID report descriptors. We don't use them, but need the size here.
|
||||
uint8_t desc_hid_report_mouse[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1)) };
|
||||
uint8_t desc_hid_report_absmouse[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(1)) };
|
||||
uint8_t desc_hid_report_joystick[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(1)) };
|
||||
uint8_t desc_hid_report_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)), TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(2)) };
|
||||
int size = 0;
|
||||
|
||||
//accumulate the size of all used HID report descriptors
|
||||
if (__USBInstallKeyboard) {
|
||||
size += sizeof(desc_hid_report_keyboard);
|
||||
}
|
||||
if (__USBInstallMouse) {
|
||||
size += sizeof(desc_hid_report_mouse);
|
||||
} else if (__USBInstallAbsoluteMouse) {
|
||||
size += sizeof(desc_hid_report_absmouse);
|
||||
}
|
||||
if (__USBInstallJoystick) {
|
||||
size += sizeof(desc_hid_report_joystick);
|
||||
}
|
||||
|
||||
//no HID used at all
|
||||
if (size == 0) {
|
||||
__hid_report = nullptr;
|
||||
__hid_report_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//allocate the "real" HID report descriptor
|
||||
__hid_report = (uint8_t *)malloc(size);
|
||||
if (__hid_report) {
|
||||
__hid_report_len = size;
|
||||
|
||||
//now copy the descriptors
|
||||
|
||||
//1.) keyboard descriptor, if requested
|
||||
if (__USBInstallKeyboard) {
|
||||
memcpy(__hid_report, desc_hid_report_keyboard, sizeof(desc_hid_report_keyboard));
|
||||
}
|
||||
|
||||
//2.) mouse descriptor, if necessary. Additional offset & new array is necessary if there is a keyboard.
|
||||
if (__USBInstallMouse) {
|
||||
//determine if we need an offset (USB keyboard is installed)
|
||||
if (__USBInstallKeyboard) {
|
||||
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(3)) };
|
||||
memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
|
||||
} else {
|
||||
memcpy(__hid_report, desc_hid_report_mouse, sizeof(desc_hid_report_mouse));
|
||||
}
|
||||
} else if (__USBInstallAbsoluteMouse) {
|
||||
//determine if we need an offset (USB keyboard is installed)
|
||||
if (__USBInstallKeyboard) {
|
||||
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(3)) };
|
||||
memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
|
||||
} else {
|
||||
memcpy(__hid_report, desc_hid_report_absmouse, sizeof(desc_hid_report_absmouse));
|
||||
}
|
||||
}
|
||||
|
||||
//3.) joystick descriptor. 2 additional checks are necessary for mouse and/or keyboard
|
||||
if (__USBInstallJoystick) {
|
||||
uint8_t reportid = 1;
|
||||
int offset = 0;
|
||||
if (__USBInstallKeyboard) {
|
||||
reportid += 2;
|
||||
offset += sizeof(desc_hid_report_keyboard);
|
||||
}
|
||||
if (__USBInstallMouse) {
|
||||
reportid++;
|
||||
offset += sizeof(desc_hid_report_mouse);
|
||||
} else if (__USBInstallAbsoluteMouse) {
|
||||
reportid++;
|
||||
offset += sizeof(desc_hid_report_absmouse);
|
||||
}
|
||||
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(reportid)) };
|
||||
memcpy(__hid_report + offset, desc_local, sizeof(desc_local));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,9 +249,9 @@ const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
|
||||
|
||||
void __SetupUSBDescriptor() {
|
||||
if (!usbd_desc_cfg) {
|
||||
bool hasHID = __USBInstallKeyboard || __USBInstallMouse;
|
||||
bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallAbsoluteMouse || __USBInstallJoystick;
|
||||
|
||||
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMIDI ? 2 : 0);
|
||||
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMassStorage ? 1 : 0);
|
||||
|
||||
uint8_t cdc_desc[TUD_CDC_DESC_LEN] = {
|
||||
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
||||
@@ -198,13 +266,20 @@ void __SetupUSBDescriptor() {
|
||||
TUD_HID_DESCRIPTOR(hid_itf, 0, HID_ITF_PROTOCOL_NONE, hid_report_len, EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
|
||||
};
|
||||
|
||||
uint8_t midi_itf = hid_itf + (hasHID ? 1 : 0);
|
||||
uint8_t midi_desc[TUD_MIDI_DESC_LEN] = {
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MIDI_DESCRIPTOR(midi_itf, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64)
|
||||
uint8_t msd_itf = interface_count - 1;
|
||||
uint8_t msd_desc[TUD_MSC_DESC_LEN] = {
|
||||
TUD_MSC_DESCRIPTOR(msd_itf, 0, USBD_MSC_EPOUT, USBD_MSC_EPIN, USBD_MSC_EPSIZE)
|
||||
};
|
||||
|
||||
int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0) + (__USBInstallMIDI ? sizeof(midi_desc) : 0);
|
||||
int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0) + (__USBInstallMassStorage ? sizeof(msd_desc) : 0);
|
||||
|
||||
#ifdef ENABLE_PICOTOOL_USB
|
||||
uint8_t picotool_itf = interface_count++;
|
||||
uint8_t picotool_desc[] = {
|
||||
TUD_RPI_RESET_DESCRIPTOR(picotool_itf, USBD_STR_RPI_RESET)
|
||||
};
|
||||
usbd_desc_len += sizeof(picotool_desc);
|
||||
#endif
|
||||
|
||||
uint8_t tud_cfg_desc[TUD_CONFIG_DESC_LEN] = {
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
@@ -226,26 +301,34 @@ void __SetupUSBDescriptor() {
|
||||
memcpy(ptr, hid_desc, sizeof(hid_desc));
|
||||
ptr += sizeof(hid_desc);
|
||||
}
|
||||
if (__USBInstallMIDI) {
|
||||
memcpy(ptr, midi_desc, sizeof(midi_desc));
|
||||
if (__USBInstallMassStorage) {
|
||||
memcpy(ptr, msd_desc, sizeof(msd_desc));
|
||||
ptr += sizeof(msd_desc);
|
||||
}
|
||||
#ifdef ENABLE_PICOTOOL_USB
|
||||
memcpy(ptr, picotool_desc, sizeof(picotool_desc));
|
||||
ptr += sizeof(picotool_desc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||
(void) langid;
|
||||
#define DESC_STR_MAX (20)
|
||||
#define DESC_STR_MAX (32)
|
||||
static uint16_t desc_str[DESC_STR_MAX];
|
||||
|
||||
static char idString[PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1];
|
||||
|
||||
static const char *const usbd_desc_str[] = {
|
||||
[USBD_STR_0] = "",
|
||||
[USBD_STR_MANUF] = "Raspberry Pi",
|
||||
[USBD_STR_PRODUCT] = "PicoArduino",
|
||||
[USBD_STR_MANUF] = USB_MANUFACTURER,
|
||||
[USBD_STR_PRODUCT] = USB_PRODUCT,
|
||||
[USBD_STR_SERIAL] = idString,
|
||||
[USBD_STR_CDC] = "Board CDC",
|
||||
#ifdef ENABLE_PICOTOOL_USB
|
||||
[USBD_STR_RPI_RESET] = "Reset",
|
||||
#endif
|
||||
};
|
||||
|
||||
if (!idString[0]) {
|
||||
@@ -258,7 +341,7 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||
len = 1;
|
||||
} else {
|
||||
if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
const char *str = usbd_desc_str[index];
|
||||
for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) {
|
||||
@@ -277,14 +360,14 @@ static void usb_irq() {
|
||||
// if the mutex is already owned, then we are in user code
|
||||
// in this file which will do a tud_task itself, so we'll just do nothing
|
||||
// until the next tick; we won't starve
|
||||
if (mutex_try_enter(&__usb_mutex, NULL)) {
|
||||
if (mutex_try_enter(&__usb_mutex, nullptr)) {
|
||||
tud_task();
|
||||
mutex_exit(&__usb_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
|
||||
irq_set_pending(USB_TASK_IRQ);
|
||||
irq_set_pending(__usb_task_irq);
|
||||
return USB_TASK_INTERVAL;
|
||||
}
|
||||
|
||||
@@ -303,16 +386,30 @@ void __USBStart() {
|
||||
|
||||
tusb_init();
|
||||
|
||||
irq_set_exclusive_handler(USB_TASK_IRQ, usb_irq);
|
||||
irq_set_enabled(USB_TASK_IRQ, true);
|
||||
__usb_task_irq = user_irq_claim_unused(true);
|
||||
irq_set_exclusive_handler(__usb_task_irq, usb_irq);
|
||||
irq_set_enabled(__usb_task_irq, true);
|
||||
|
||||
add_alarm_in_us(USB_TASK_INTERVAL, timer_task, NULL, true);
|
||||
add_alarm_in_us(USB_TASK_INTERVAL, timer_task, nullptr, true);
|
||||
}
|
||||
|
||||
|
||||
bool __USBHIDReady() {
|
||||
uint32_t start = millis();
|
||||
const uint32_t timeout = 500;
|
||||
|
||||
while (((millis() - start) < timeout) && tud_ready() && !tud_hid_ready()) {
|
||||
tud_task();
|
||||
delay(1);
|
||||
}
|
||||
return tud_hid_ready();
|
||||
}
|
||||
|
||||
|
||||
// Invoked when received GET_REPORT control request
|
||||
// Application must fill buffer report's content and return its length.
|
||||
// Return zero will cause the stack to STALL request
|
||||
extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) __attribute__((weak));
|
||||
extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
|
||||
// TODO not implemented
|
||||
(void) instance;
|
||||
@@ -326,6 +423,7 @@ extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, h
|
||||
|
||||
// Invoked when received SET_REPORT control request or
|
||||
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
|
||||
extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) __attribute__((weak));
|
||||
extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
|
||||
// TODO set LED based on CAPLOCK, NUMLOCK etc...
|
||||
(void) instance;
|
||||
@@ -335,4 +433,188 @@ extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_r
|
||||
(void) bufsize;
|
||||
}
|
||||
|
||||
extern "C" int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) __attribute__((weak));
|
||||
extern "C" int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
|
||||
(void) lun;
|
||||
(void) lba;
|
||||
(void) offset;
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" bool tud_msc_test_unit_ready_cb(uint8_t lun) __attribute__((weak));
|
||||
extern "C" bool tud_msc_test_unit_ready_cb(uint8_t lun) {
|
||||
(void) lun;
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) __attribute__((weak));
|
||||
extern "C" int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) {
|
||||
(void) lun;
|
||||
(void) lba;
|
||||
(void) offset;
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) __attribute__((weak));
|
||||
extern "C" int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) {
|
||||
(void) lun;
|
||||
(void) scsi_cmd;
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) __attribute__((weak));
|
||||
extern "C" void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) {
|
||||
(void) lun;
|
||||
*block_count = 0;
|
||||
*block_size = 0;
|
||||
}
|
||||
|
||||
extern "C" void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) __attribute__((weak));
|
||||
extern "C" void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
|
||||
(void) lun;
|
||||
vendor_id[0] = 0;
|
||||
product_id[0] = 0;
|
||||
product_rev[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ENABLE_PICOTOOL_USB
|
||||
|
||||
static uint8_t _picotool_itf_num;
|
||||
|
||||
static void resetd_init() {
|
||||
}
|
||||
|
||||
static void resetd_reset(uint8_t rhport) {
|
||||
(void) rhport;
|
||||
_picotool_itf_num = 0;
|
||||
}
|
||||
|
||||
static uint16_t resetd_open(uint8_t rhport,
|
||||
tusb_desc_interface_t const *itf_desc, uint16_t max_len) {
|
||||
(void) rhport;
|
||||
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass &&
|
||||
RESET_INTERFACE_SUBCLASS == itf_desc->bInterfaceSubClass &&
|
||||
RESET_INTERFACE_PROTOCOL == itf_desc->bInterfaceProtocol, 0);
|
||||
|
||||
uint16_t const drv_len = sizeof(tusb_desc_interface_t);
|
||||
TU_VERIFY(max_len >= drv_len, 0);
|
||||
|
||||
_picotool_itf_num = itf_desc->bInterfaceNumber;
|
||||
return drv_len;
|
||||
}
|
||||
|
||||
// Support for parameterized reset via vendor interface control request
|
||||
static bool resetd_control_xfer_cb(uint8_t rhport, uint8_t stage,
|
||||
tusb_control_request_t const *request) {
|
||||
(void) rhport;
|
||||
// nothing to do with DATA & ACK stage
|
||||
if (stage != CONTROL_STAGE_SETUP) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (request->wIndex == _picotool_itf_num) {
|
||||
if (request->bRequest == RESET_REQUEST_BOOTSEL) {
|
||||
reset_usb_boot(0, (request->wValue & 0x7f));
|
||||
// does not return, otherwise we'd return true
|
||||
}
|
||||
|
||||
if (request->bRequest == RESET_REQUEST_FLASH) {
|
||||
watchdog_reboot(0, 0, 100);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool resetd_xfer_cb(uint8_t rhport, uint8_t ep_addr,
|
||||
xfer_result_t result, uint32_t xferred_bytes) {
|
||||
(void) rhport;
|
||||
(void) ep_addr;
|
||||
(void) result;
|
||||
(void) xferred_bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
static usbd_class_driver_t const _resetd_driver = {
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
.name = "RESET",
|
||||
#endif
|
||||
.init = resetd_init,
|
||||
.reset = resetd_reset,
|
||||
.open = resetd_open,
|
||||
.control_xfer_cb = resetd_control_xfer_cb,
|
||||
.xfer_cb = resetd_xfer_cb,
|
||||
.sof = NULL
|
||||
};
|
||||
|
||||
// Implement callback to add our custom driver
|
||||
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
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,13 +19,20 @@
|
||||
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));
|
||||
|
||||
extern void __USBInstallKeyboard() __attribute__((weak));
|
||||
|
||||
extern void __USBInstallJoystick() __attribute__((weak));
|
||||
|
||||
// One or the other allowed, not both
|
||||
extern void __USBInstallMouse() __attribute__((weak));
|
||||
extern void __USBInstallMIDI() __attribute__((weak));
|
||||
extern void __USBInstallAbsoluteMouse() __attribute__((weak));
|
||||
|
||||
extern void __USBInstallMassStorage() __attribute__((weak));
|
||||
|
||||
// Big, global USB mutex, shared with all USB devices to make sure we don't
|
||||
// have multiple cores updating the TUSB state in parallel
|
||||
@@ -34,6 +41,10 @@ extern mutex_t __usb_mutex;
|
||||
// HID report ID inquiry (report ID will vary depending on the number/type of other HID)
|
||||
int __USBGetKeyboardReportID();
|
||||
int __USBGetMouseReportID();
|
||||
int __USBGetJoystickReportID();
|
||||
|
||||
// Called by main() to init the USB HW/SW.
|
||||
void __USBStart();
|
||||
|
||||
// Helper class for HID report sending with wait and timeout
|
||||
bool __USBHIDReady();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define ARDUINO_PICO_MAJOR 2
|
||||
#define ARDUINO_PICO_MINOR 2
|
||||
#define ARDUINO_PICO_REVISION 2
|
||||
#define ARDUINO_PICO_VERSION_STR "2.2.2"
|
||||
#define ARDUINO_PICO_MAJOR 3
|
||||
#define ARDUINO_PICO_MINOR 4
|
||||
#define ARDUINO_PICO_REVISION 1
|
||||
#define ARDUINO_PICO_VERSION_STR "3.4.1"
|
||||
|
||||
+29
-15
@@ -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");
|
||||
@@ -230,7 +232,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
|
||||
pio_sm_clear_fifos(_rxPIO, _rxSM); // Remove any existing data
|
||||
|
||||
// Put phase divider into OSR w/o using add'l program memory
|
||||
pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 5 /* insns in PIO halfbit loop */);
|
||||
pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 7 /* insns in PIO halfbit loop */);
|
||||
pio_sm_exec(_rxPIO, _rxSM, pio_encode_pull(false, false));
|
||||
|
||||
// Join the TX FIFO to the RX one now that we don't need it
|
||||
@@ -259,9 +261,11 @@ void SerialPIO::end() {
|
||||
}
|
||||
if (_tx != NOPIN) {
|
||||
pio_sm_set_enabled(_txPIO, _txSM, false);
|
||||
pio_sm_unclaim(_txPIO, _txSM);
|
||||
}
|
||||
if (_rx != NOPIN) {
|
||||
pio_sm_set_enabled(_rxPIO, _rxSM, false);
|
||||
pio_sm_unclaim(_rxPIO, _rxSM);
|
||||
_pioSP[pio_get_index(_rxPIO)][_rxSM] = nullptr;
|
||||
// If no more active, disable the IRQ
|
||||
auto pioNum = pio_get_index(_rxPIO);
|
||||
@@ -344,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)) {
|
||||
@@ -362,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;
|
||||
}
|
||||
@@ -370,3 +379,8 @@ size_t SerialPIO::write(uint8_t c) {
|
||||
SerialPIO::operator bool() {
|
||||
return _running;
|
||||
}
|
||||
|
||||
#ifdef ARDUINO_NANO_RP2040_CONNECT
|
||||
// NINA updates
|
||||
SerialPIO Serial3(SERIAL3_TX, SERIAL3_RX);
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
@@ -80,3 +84,8 @@ protected:
|
||||
uint32_t _reader;
|
||||
uint8_t *_queue;
|
||||
};
|
||||
|
||||
#ifdef ARDUINO_NANO_RP2040_CONNECT
|
||||
// NINA updates
|
||||
extern SerialPIO Serial3;
|
||||
#endif
|
||||
|
||||
+87
-16
@@ -40,6 +40,10 @@ bool SerialUART::setRX(pin_size_t pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_rx == pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_running) {
|
||||
panic("FATAL: Attempting to set Serial%d.RX while running", uart_get_index(_uart) + 1);
|
||||
} else {
|
||||
@@ -57,6 +61,10 @@ bool SerialUART::setTX(pin_size_t pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_tx == pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_running) {
|
||||
panic("FATAL: Attempting to set Serial%d.TX while running", uart_get_index(_uart) + 1);
|
||||
} else {
|
||||
@@ -69,11 +77,15 @@ bool SerialUART::setRTS(pin_size_t pin) {
|
||||
constexpr uint32_t valid[2] = { __bitset({3, 15, 19}) /* UART0 */,
|
||||
__bitset({7, 11, 23, 27}) /* UART1 */
|
||||
};
|
||||
if ((!_running) && ((1 << pin) & valid[uart_get_index(_uart)])) {
|
||||
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) {
|
||||
_rts = pin;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_rts == pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_running) {
|
||||
panic("FATAL: Attempting to set Serial%d.RTS while running", uart_get_index(_uart) + 1);
|
||||
} else {
|
||||
@@ -86,11 +98,15 @@ bool SerialUART::setCTS(pin_size_t pin) {
|
||||
constexpr uint32_t valid[2] = { __bitset({2, 14, 18}) /* UART0 */,
|
||||
__bitset({6, 10, 22, 26}) /* UART1 */
|
||||
};
|
||||
if ((!_running) && ((1 << pin) & valid[uart_get_index(_uart)])) {
|
||||
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) {
|
||||
_cts = pin;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_cts == pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_running) {
|
||||
panic("FATAL: Attempting to set Serial%d.CTS while running", uart_get_index(_uart) + 1);
|
||||
} else {
|
||||
@@ -134,6 +150,20 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
|
||||
_overflow = false;
|
||||
_queue = new uint8_t[_fifoSize];
|
||||
_baud = baud;
|
||||
|
||||
_fcnTx = gpio_get_function(_tx);
|
||||
_fcnRx = gpio_get_function(_rx);
|
||||
gpio_set_function(_tx, GPIO_FUNC_UART);
|
||||
gpio_set_function(_rx, GPIO_FUNC_UART);
|
||||
if (_rts != UART_PIN_NOT_DEFINED) {
|
||||
_fcnRts = gpio_get_function(_rts);
|
||||
gpio_set_function(_rts, GPIO_FUNC_UART);
|
||||
}
|
||||
if (_cts != UART_PIN_NOT_DEFINED) {
|
||||
_fcnCts = gpio_get_function(_cts);
|
||||
gpio_set_function(_cts, GPIO_FUNC_UART);
|
||||
}
|
||||
|
||||
uart_init(_uart, baud);
|
||||
int bits, stop;
|
||||
uart_parity_t parity;
|
||||
@@ -171,14 +201,6 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
|
||||
break;
|
||||
}
|
||||
uart_set_format(_uart, bits, stop, parity);
|
||||
gpio_set_function(_tx, GPIO_FUNC_UART);
|
||||
gpio_set_function(_rx, GPIO_FUNC_UART);
|
||||
if (_rts != UART_PIN_NOT_DEFINED) {
|
||||
gpio_set_function(_rts, GPIO_FUNC_UART);
|
||||
}
|
||||
if (_cts != UART_PIN_NOT_DEFINED) {
|
||||
gpio_set_function(_cts, GPIO_FUNC_UART);
|
||||
}
|
||||
uart_set_hw_flow(_uart, _rts != UART_PIN_NOT_DEFINED, _cts != UART_PIN_NOT_DEFINED);
|
||||
_writer = 0;
|
||||
_reader = 0;
|
||||
@@ -196,6 +218,7 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
|
||||
} else {
|
||||
// Polling mode has no IRQs used
|
||||
}
|
||||
_break = false;
|
||||
_running = true;
|
||||
}
|
||||
|
||||
@@ -211,6 +234,7 @@ void SerialUART::end() {
|
||||
irq_set_enabled(UART1_IRQ, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Paranoia - ensure nobody else is using anything here at the same time
|
||||
mutex_enter_blocking(&_mutex);
|
||||
mutex_enter_blocking(&_fifoMutex);
|
||||
@@ -219,6 +243,16 @@ void SerialUART::end() {
|
||||
// Reset the mutexes once all is off/cleaned up
|
||||
mutex_exit(&_fifoMutex);
|
||||
mutex_exit(&_mutex);
|
||||
|
||||
// Restore pin functions
|
||||
gpio_set_function(_tx, _fcnTx);
|
||||
gpio_set_function(_rx, _fcnRx);
|
||||
if (_rts != UART_PIN_NOT_DEFINED) {
|
||||
gpio_set_function(_rts, _fcnRts);
|
||||
}
|
||||
if (_cts != UART_PIN_NOT_DEFINED) {
|
||||
gpio_set_function(_cts, _fcnCts);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialUART::_pumpFIFO() {
|
||||
@@ -273,13 +307,22 @@ int SerialUART::read() {
|
||||
}
|
||||
|
||||
bool SerialUART::overflow() {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m) {
|
||||
if (!_running) {
|
||||
return false;
|
||||
}
|
||||
bool hold = _overflow;
|
||||
|
||||
if (_polling) {
|
||||
_handleIRQ(false);
|
||||
} else {
|
||||
_pumpFIFO();
|
||||
}
|
||||
|
||||
mutex_enter_blocking(&_fifoMutex);
|
||||
bool ovf = _overflow;
|
||||
_overflow = false;
|
||||
return hold;
|
||||
mutex_exit(&_fifoMutex);
|
||||
|
||||
return ovf;
|
||||
}
|
||||
|
||||
int SerialUART::available() {
|
||||
@@ -292,7 +335,7 @@ int SerialUART::available() {
|
||||
} else {
|
||||
_pumpFIFO();
|
||||
}
|
||||
return (_writer - _reader) % _fifoSize;
|
||||
return (_fifoSize + _writer - _reader) % _fifoSize;
|
||||
}
|
||||
|
||||
int SerialUART::availableForWrite() {
|
||||
@@ -350,6 +393,25 @@ SerialUART::operator bool() {
|
||||
return _running;
|
||||
}
|
||||
|
||||
bool SerialUART::getBreakReceived() {
|
||||
if (!_running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_polling) {
|
||||
_handleIRQ(false);
|
||||
} else {
|
||||
_pumpFIFO();
|
||||
}
|
||||
|
||||
mutex_enter_blocking(&_fifoMutex);
|
||||
bool break_received = _break;
|
||||
_break = false;
|
||||
mutex_exit(&_fifoMutex);
|
||||
|
||||
return break_received;
|
||||
}
|
||||
|
||||
void arduino::serialEvent1Run(void) {
|
||||
if (serialEvent1 && Serial1.available()) {
|
||||
serialEvent1();
|
||||
@@ -375,7 +437,16 @@ void __not_in_flash_func(SerialUART::_handleIRQ)(bool inIRQ) {
|
||||
// ICR is write-to-clear
|
||||
uart_get_hw(_uart)->icr = UART_UARTICR_RTIC_BITS | UART_UARTICR_RXIC_BITS;
|
||||
while (uart_is_readable(_uart)) {
|
||||
auto val = uart_getc(_uart);
|
||||
uint32_t raw = uart_get_hw(_uart)->dr;
|
||||
if (raw & 0x400) {
|
||||
// break!
|
||||
_break = true;
|
||||
continue;
|
||||
} else if (raw & 0x300) {
|
||||
// Framing, Parity Error. Ignore this bad char
|
||||
continue;
|
||||
}
|
||||
uint8_t val = raw & 0xff;
|
||||
auto next_writer = _writer + 1;
|
||||
if (next_writer == _fifoSize) {
|
||||
next_writer = 0;
|
||||
|
||||
@@ -63,18 +63,29 @@ public:
|
||||
bool overflow();
|
||||
operator bool() override;
|
||||
|
||||
// ESP8266 compat
|
||||
void setDebugOutput(bool unused) {
|
||||
(void) unused;
|
||||
}
|
||||
|
||||
// Not to be called by users, only from the IRQ handler. In public so that the C-language IQR callback can access it
|
||||
void _handleIRQ(bool inIRQ = true);
|
||||
|
||||
// Allows the user to sleep until a break is received (self-clears the flag
|
||||
// on read)
|
||||
bool getBreakReceived();
|
||||
|
||||
private:
|
||||
bool _running = false;
|
||||
uart_inst_t *_uart;
|
||||
pin_size_t _tx, _rx;
|
||||
pin_size_t _rts, _cts;
|
||||
enum gpio_function _fcnTx, _fcnRx, _fcnRts, _fcnCts;
|
||||
int _baud;
|
||||
mutex_t _mutex;
|
||||
bool _polling = false;
|
||||
bool _overflow;
|
||||
bool _break;
|
||||
|
||||
// Lockless, IRQ-handled circular queue
|
||||
uint32_t _writer;
|
||||
|
||||
+41
-19
@@ -25,14 +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 <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
|
||||
@@ -64,52 +65,57 @@ void SerialUSB::end() {
|
||||
}
|
||||
|
||||
int SerialUSB::peek() {
|
||||
CoreMutex m(&__usb_mutex);
|
||||
CoreMutex m(&__usb_mutex, false);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t c;
|
||||
tud_task();
|
||||
return tud_cdc_peek(&c) ? (int) c : -1;
|
||||
}
|
||||
|
||||
int SerialUSB::read() {
|
||||
CoreMutex m(&__usb_mutex);
|
||||
CoreMutex m(&__usb_mutex, false);
|
||||
if (!_running || !m) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tud_cdc_connected() && tud_cdc_available()) {
|
||||
tud_task();
|
||||
if (tud_cdc_available()) {
|
||||
return tud_cdc_read_char();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SerialUSB::available() {
|
||||
CoreMutex m(&__usb_mutex);
|
||||
CoreMutex m(&__usb_mutex, false);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tud_task();
|
||||
return tud_cdc_available();
|
||||
}
|
||||
|
||||
int SerialUSB::availableForWrite() {
|
||||
CoreMutex m(&__usb_mutex);
|
||||
CoreMutex m(&__usb_mutex, false);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tud_task();
|
||||
return tud_cdc_write_available();
|
||||
}
|
||||
|
||||
void SerialUSB::flush() {
|
||||
CoreMutex m(&__usb_mutex);
|
||||
CoreMutex m(&__usb_mutex, false);
|
||||
if (!_running || !m) {
|
||||
return;
|
||||
}
|
||||
|
||||
tud_cdc_write_flush();
|
||||
tud_task();
|
||||
}
|
||||
|
||||
size_t SerialUSB::write(uint8_t c) {
|
||||
@@ -117,14 +123,14 @@ size_t SerialUSB::write(uint8_t c) {
|
||||
}
|
||||
|
||||
size_t SerialUSB::write(const uint8_t *buf, size_t length) {
|
||||
CoreMutex m(&__usb_mutex);
|
||||
CoreMutex m(&__usb_mutex, false);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t last_avail_time;
|
||||
int written = 0;
|
||||
if (tud_cdc_connected()) {
|
||||
if (tud_cdc_connected() || _ignoreFlowControl) {
|
||||
for (size_t i = 0; i < length;) {
|
||||
int n = length - i;
|
||||
int avail = tud_cdc_write_available();
|
||||
@@ -142,7 +148,7 @@ size_t SerialUSB::write(const uint8_t *buf, size_t length) {
|
||||
tud_task();
|
||||
tud_cdc_write_flush();
|
||||
if (!tud_cdc_connected() ||
|
||||
(!tud_cdc_write_available() && time_us_64() > last_avail_time + 1000000 /* 1 second */)) {
|
||||
(!tud_cdc_write_available() && time_us_64() > last_avail_time + 1'000'000 /* 1 second */)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -151,11 +157,12 @@ size_t SerialUSB::write(const uint8_t *buf, size_t length) {
|
||||
// reset our timeout
|
||||
last_avail_time = 0;
|
||||
}
|
||||
tud_task();
|
||||
return written;
|
||||
}
|
||||
|
||||
SerialUSB::operator bool() {
|
||||
CoreMutex m(&__usb_mutex);
|
||||
CoreMutex m(&__usb_mutex, false);
|
||||
if (!_running || !m) {
|
||||
return false;
|
||||
}
|
||||
@@ -164,12 +171,27 @@ SerialUSB::operator bool() {
|
||||
return tud_cdc_connected();
|
||||
}
|
||||
|
||||
void SerialUSB::ignoreFlowControl(bool ignore) {
|
||||
_ignoreFlowControl = ignore;
|
||||
}
|
||||
|
||||
static bool _dtr = false;
|
||||
static bool _rts = false;
|
||||
static int _bps = 115200;
|
||||
static bool _rebooting = false;
|
||||
static void CheckSerialReset() {
|
||||
if ((_bps == 1200) && (!_dtr)) {
|
||||
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);
|
||||
// Reset the whole USB hardware block
|
||||
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.
|
||||
busy_wait_ms(3);
|
||||
reset_usb_boot(0, 0);
|
||||
while (1); // WDT will fire here
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __SERIALUSB_H__
|
||||
#define __SERIALUSB_H__
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "api/HardwareSerial.h"
|
||||
@@ -45,8 +44,16 @@ public:
|
||||
using Print::write;
|
||||
operator bool() override;
|
||||
|
||||
void ignoreFlowControl(bool ignore = true);
|
||||
|
||||
// ESP8266 compat
|
||||
void setDebugOutput(bool unused) {
|
||||
(void) unused;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _running = false;
|
||||
bool _ignoreFlowControl = false;
|
||||
};
|
||||
|
||||
extern SerialUSB Serial;
|
||||
@@ -54,5 +61,3 @@ extern SerialUSB Serial;
|
||||
namespace arduino {
|
||||
extern void serialEventRun(void) __attribute__((weak));
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
StackThunk - Implements a simple 2nd stack for BSSL and others
|
||||
Copyright (c) 2022 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
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 <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "StackThunk.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
uint32_t *stack_thunk_ptr = nullptr;
|
||||
uint32_t *stack_thunk_top = nullptr;
|
||||
uint32_t *stack_thunk_save = nullptr; /* Saved A1 while in BearSSL */
|
||||
uint32_t stack_thunk_refcnt = 0;
|
||||
|
||||
/* Largest stack usage seen in the wild at 6120 */
|
||||
#define _stackSize (6400/4)
|
||||
#define _stackPaint 0xdeadbeef
|
||||
|
||||
/* Add a reference, and allocate the stack if necessary */
|
||||
void stack_thunk_add_ref() {
|
||||
stack_thunk_refcnt++;
|
||||
if (stack_thunk_refcnt == 1) {
|
||||
// The stack must be in DRAM, or an Soft WDT will follow. Not sure why,
|
||||
// maybe too much time is consumed with the non32-bit exception handler.
|
||||
// Also, interrupt handling on an IRAM stack would be very slow.
|
||||
// Strings on the stack would be very slow to access as well.
|
||||
stack_thunk_ptr = (uint32_t *)malloc(_stackSize * sizeof(uint32_t));
|
||||
if (!stack_thunk_ptr) {
|
||||
// This is a fatal error, stop the sketch
|
||||
abort();
|
||||
}
|
||||
stack_thunk_top = stack_thunk_ptr + _stackSize - 1;
|
||||
stack_thunk_save = nullptr;
|
||||
stack_thunk_repaint();
|
||||
}
|
||||
}
|
||||
|
||||
/* Drop a reference, and free stack if no more in use */
|
||||
void stack_thunk_del_ref() {
|
||||
if (stack_thunk_refcnt == 0) {
|
||||
/* Error! */
|
||||
return;
|
||||
}
|
||||
stack_thunk_refcnt--;
|
||||
if (!stack_thunk_refcnt) {
|
||||
free(stack_thunk_ptr);
|
||||
stack_thunk_ptr = nullptr;
|
||||
stack_thunk_top = nullptr;
|
||||
stack_thunk_save = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void stack_thunk_repaint() {
|
||||
for (int i = 0; i < _stackSize; i++) {
|
||||
stack_thunk_ptr[i] = _stackPaint;
|
||||
}
|
||||
}
|
||||
|
||||
/* Simple accessor functions used by postmortem */
|
||||
uint32_t stack_thunk_get_refcnt() {
|
||||
return stack_thunk_refcnt;
|
||||
}
|
||||
|
||||
uint32_t stack_thunk_get_stack_top() {
|
||||
return (uint32_t)stack_thunk_top;
|
||||
}
|
||||
|
||||
uint32_t stack_thunk_get_stack_bot() {
|
||||
return (uint32_t)stack_thunk_ptr;
|
||||
}
|
||||
|
||||
uint32_t stack_thunk_get_cont_sp() {
|
||||
return (uint32_t)stack_thunk_save;
|
||||
}
|
||||
|
||||
/* Return the number of bytes ever used since the stack was created */
|
||||
uint32_t stack_thunk_get_max_usage() {
|
||||
uint32_t cnt = 0;
|
||||
|
||||
/* No stack == no usage by definition! */
|
||||
if (!stack_thunk_ptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (cnt = 0; (cnt < _stackSize) && (stack_thunk_ptr[cnt] == _stackPaint); cnt++) {
|
||||
/* Noop, all work done in for() */
|
||||
}
|
||||
return 4 * (_stackSize - cnt);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
StackThunk - Implements a simple 2nd stack for BSSL and others
|
||||
Copyright (c) 2022 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
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 <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void stack_thunk_add_ref();
|
||||
extern void stack_thunk_del_ref();
|
||||
extern void stack_thunk_repaint();
|
||||
|
||||
extern uint32_t stack_thunk_get_refcnt();
|
||||
extern uint32_t stack_thunk_get_stack_top();
|
||||
extern uint32_t stack_thunk_get_stack_bot();
|
||||
extern uint32_t stack_thunk_get_cont_sp();
|
||||
extern uint32_t stack_thunk_get_max_usage();
|
||||
extern void stack_thunk_dump_stack();
|
||||
extern void stack_thunk_fatal_overflow();
|
||||
|
||||
// Globals required for thunking operation
|
||||
extern uint32_t *stack_thunk_ptr;
|
||||
extern uint32_t *stack_thunk_top;
|
||||
extern uint32_t *stack_thunk_save;
|
||||
extern uint32_t stack_thunk_refcnt;
|
||||
|
||||
#define make_stack_thunk_void(fcnToThunk, proto, params) \
|
||||
extern "C" void thunk_##fcnToThunk proto { \
|
||||
register uint32_t* sp asm("sp"); \
|
||||
stack_thunk_save = sp; \
|
||||
sp = stack_thunk_top; \
|
||||
fcnToThunk params; \
|
||||
sp = stack_thunk_save; \
|
||||
}
|
||||
|
||||
#define make_stack_thunk_unsigned_char_ptr(fcnToThunk, proto, params) \
|
||||
extern "C" unsigned char * thunk_##fcnToThunk proto { \
|
||||
register uint32_t* sp asm("sp"); \
|
||||
stack_thunk_save = sp; \
|
||||
sp = stack_thunk_top; \
|
||||
auto x = fcnToThunk params; \
|
||||
sp = stack_thunk_save; \
|
||||
return x; \
|
||||
}
|
||||
|
||||
#define make_stack_thunk_bool(fcnToThunk, proto, params) \
|
||||
extern "C" bool thunk_##fcnToThunk proto { \
|
||||
register uint32_t* sp asm("sp"); \
|
||||
stack_thunk_save = sp; \
|
||||
sp = stack_thunk_top; \
|
||||
auto x = fcnToThunk params; \
|
||||
sp = stack_thunk_save; \
|
||||
return x; \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,247 @@
|
||||
/**
|
||||
StreamString.h
|
||||
|
||||
Copyright (c) 2020 D. Gauchard. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __STREAMSTRING_H
|
||||
#define __STREAMSTRING_H
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include "Stream.h"
|
||||
#include "api/String.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// S2Stream points to a String and makes it a Stream
|
||||
// (it is also the helper for StreamString)
|
||||
|
||||
class S2Stream: public Stream {
|
||||
public:
|
||||
S2Stream(String& string, int peekPointer = -1) : string(&string), peekPointer(peekPointer) { }
|
||||
|
||||
S2Stream(String* string, int peekPointer = -1) : string(string), peekPointer(peekPointer) { }
|
||||
|
||||
virtual int available() override {
|
||||
return string->length();
|
||||
}
|
||||
|
||||
virtual int availableForWrite() override {
|
||||
return std::numeric_limits<int16_t>::max();
|
||||
}
|
||||
|
||||
virtual int read() override {
|
||||
if (peekPointer < 0) {
|
||||
// consume chars
|
||||
if (string->length()) {
|
||||
char c = string->charAt(0);
|
||||
string->remove(0, 1);
|
||||
return c;
|
||||
}
|
||||
} else if (peekPointer < (int)string->length()) {
|
||||
// return pointed and move pointer
|
||||
return string->charAt(peekPointer++);
|
||||
}
|
||||
|
||||
// everything is read
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t data) override {
|
||||
return string->concat((char)data);
|
||||
}
|
||||
|
||||
// virtual int read(uint8_t* buffer, size_t len) override
|
||||
// {
|
||||
// if (peekPointer < 0)
|
||||
// {
|
||||
// // string will be consumed
|
||||
// size_t l = std::min(len, (size_t)string->length());
|
||||
// memcpy(buffer, string->c_str(), l);
|
||||
// string->remove(0, l);
|
||||
// return l;
|
||||
// }
|
||||
//
|
||||
// if (peekPointer >= (int)string->length())
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// // only the pointer is moved
|
||||
// size_t l = std::min(len, (size_t)(string->length() - peekPointer));
|
||||
// memcpy(buffer, string->c_str() + peekPointer, l);
|
||||
// peekPointer += l;
|
||||
// return l;
|
||||
// }
|
||||
|
||||
virtual size_t write(const uint8_t* buffer, size_t len) override {
|
||||
return string->concat((const char*)buffer, len) ? len : 0;
|
||||
}
|
||||
|
||||
virtual int peek() override {
|
||||
if (peekPointer < 0) {
|
||||
if (string->length()) {
|
||||
return string->charAt(0);
|
||||
}
|
||||
} else if (peekPointer < (int)string->length()) {
|
||||
return string->charAt(peekPointer);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual void flush() override {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
#if 0
|
||||
virtual bool inputCanTimeout() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool outputCanTimeout() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
//// Stream's peekBufferAPI
|
||||
|
||||
virtual bool hasPeekBufferAPI() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual size_t peekAvailable() {
|
||||
if (peekPointer < 0) {
|
||||
return string->length();
|
||||
}
|
||||
return string->length() - peekPointer;
|
||||
}
|
||||
|
||||
virtual const char* peekBuffer() override {
|
||||
if (peekPointer < 0) {
|
||||
return string->c_str();
|
||||
}
|
||||
if (peekPointer < (int)string->length()) {
|
||||
return string->c_str() + peekPointer;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void peekConsume(size_t consume) override {
|
||||
if (peekPointer < 0) {
|
||||
// string is really consumed
|
||||
string->remove(0, consume);
|
||||
} else {
|
||||
// only the pointer is moved
|
||||
peekPointer = std::min((size_t)string->length(), peekPointer + consume);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ssize_t streamRemaining() override {
|
||||
return peekPointer < 0 ? string->length() : string->length() - peekPointer;
|
||||
}
|
||||
|
||||
// calling setConsume() will consume bytes as the stream is read
|
||||
// (enabled by default)
|
||||
void setConsume() {
|
||||
peekPointer = -1;
|
||||
}
|
||||
#endif
|
||||
// Reading this stream will mark the string as read without consuming
|
||||
// (not enabled by default)
|
||||
// Calling resetPointer() resets the read state and allows rereading.
|
||||
void resetPointer(int pointer = 0) {
|
||||
peekPointer = pointer;
|
||||
}
|
||||
|
||||
protected:
|
||||
String* string;
|
||||
int peekPointer; // -1:String is consumed / >=0:resettable pointer
|
||||
};
|
||||
|
||||
// StreamString is a S2Stream holding the String
|
||||
|
||||
class StreamString: public String, public S2Stream {
|
||||
protected:
|
||||
void resetpp() {
|
||||
if (peekPointer > 0) {
|
||||
peekPointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
StreamString(StreamString&& bro) : String(bro), S2Stream(this) { }
|
||||
StreamString(const StreamString& bro) : String(bro), S2Stream(this) { }
|
||||
|
||||
// duplicate String constructors and operator=:
|
||||
|
||||
StreamString(const char* text = nullptr) : String(text), S2Stream(this) { }
|
||||
StreamString(const String& string) : String(string), S2Stream(this) { }
|
||||
StreamString(const __FlashStringHelper* str) : String(str), S2Stream(this) { }
|
||||
StreamString(String&& string) : String(string), S2Stream(this) { }
|
||||
|
||||
explicit StreamString(char c) : String(c), S2Stream(this) { }
|
||||
explicit StreamString(unsigned char c, unsigned char base = 10) :
|
||||
String(c, base), S2Stream(this) {
|
||||
}
|
||||
explicit StreamString(int i, unsigned char base = 10) : String(i, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned int i, unsigned char base = 10) : String(i, base), S2Stream(this) {
|
||||
}
|
||||
explicit StreamString(long l, unsigned char base = 10) : String(l, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned long l, unsigned char base = 10) :
|
||||
String(l, base), S2Stream(this) {
|
||||
}
|
||||
explicit StreamString(float f, unsigned char decimalPlaces = 2) :
|
||||
String(f, decimalPlaces), S2Stream(this) {
|
||||
}
|
||||
explicit StreamString(double d, unsigned char decimalPlaces = 2) :
|
||||
String(d, decimalPlaces), S2Stream(this) {
|
||||
}
|
||||
|
||||
StreamString& operator=(const StreamString& rhs) {
|
||||
String::operator=(rhs);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator=(const String& rhs) {
|
||||
String::operator=(rhs);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator=(const char* cstr) {
|
||||
String::operator=(cstr);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator=(const __FlashStringHelper* str) {
|
||||
String::operator=(str);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator=(String&& rval) {
|
||||
String::operator=(rval);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __STREAMSTRING_H
|
||||
+15
-5
@@ -28,6 +28,7 @@ typedef struct {
|
||||
pin_size_t pin;
|
||||
PIO pio;
|
||||
int sm;
|
||||
int off;
|
||||
alarm_id_t alarm;
|
||||
} Tone;
|
||||
|
||||
@@ -38,10 +39,18 @@ auto_init_mutex(_toneMutex);
|
||||
static PIOProgram _tone2Pgm(&tone2_program);
|
||||
static std::map<pin_size_t, Tone *> _toneMap;
|
||||
|
||||
static inline bool pio_sm_get_enabled(PIO pio, uint sm) {
|
||||
check_pio_param(pio);
|
||||
check_sm_param(sm);
|
||||
return (pio->ctrl & ~(1u << sm)) & (1 << sm);
|
||||
}
|
||||
|
||||
int64_t _stopTonePIO(alarm_id_t id, void *user_data) {
|
||||
(void) id;
|
||||
Tone *tone = (Tone *)user_data;
|
||||
tone->alarm = 0;
|
||||
digitalWrite(tone->pin, LOW);
|
||||
pinMode(tone->pin, OUTPUT);
|
||||
pio_sm_set_enabled(tone->pio, tone->sm, false);
|
||||
return 0;
|
||||
}
|
||||
@@ -62,7 +71,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
return; // Weird deadlock case
|
||||
}
|
||||
|
||||
int us = 1000000 / frequency / 2;
|
||||
int us = 1'000'000 / frequency / 2;
|
||||
if (us < 5) {
|
||||
us = 5;
|
||||
}
|
||||
@@ -72,14 +81,12 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
newTone = new Tone();
|
||||
newTone->pin = pin;
|
||||
pinMode(pin, OUTPUT);
|
||||
int off;
|
||||
if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &off)) {
|
||||
if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &newTone->off)) {
|
||||
DEBUGCORE("ERROR: tone unable to start, out of PIO resources\n");
|
||||
// ERROR, no free slots
|
||||
delete newTone;
|
||||
return;
|
||||
}
|
||||
tone2_program_init(newTone->pio, newTone->sm, off, pin);
|
||||
newTone->alarm = 0;
|
||||
} else {
|
||||
newTone = entry->second;
|
||||
@@ -88,6 +95,9 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
newTone->alarm = 0;
|
||||
}
|
||||
}
|
||||
if (!pio_sm_get_enabled(newTone->pio, newTone->sm)) {
|
||||
tone2_program_init(newTone->pio, newTone->sm, newTone->off, pin);
|
||||
}
|
||||
pio_sm_clear_fifos(newTone->pio, newTone->sm); // Remove any old updates that haven't yet taken effect
|
||||
pio_sm_put_blocking(newTone->pio, newTone->sm, RP2040::usToPIOCycles(us));
|
||||
pio_sm_set_enabled(newTone->pio, newTone->sm, true);
|
||||
@@ -99,7 +109,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
if (ret > 0) {
|
||||
newTone->alarm = ret;
|
||||
} else {
|
||||
DEBUGCORE("ERROR: Unable to allocate timer for tone(%d, %d, %d)\n",
|
||||
DEBUGCORE("ERROR: Unable to allocate timer for tone(%d, %d, %lu)\n",
|
||||
pin, frequency, duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/String.h"
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
_freertos.cpp - Internal core definitions for FreeRTOS
|
||||
|
||||
Copyright (c) 2022 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 "_freertos.h"
|
||||
#include <pico/mutex.h>
|
||||
#include <stdlib.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
typedef struct {
|
||||
mutex_t *src;
|
||||
SemaphoreHandle_t dst;
|
||||
} FMMap;
|
||||
|
||||
static FMMap *_map = nullptr;
|
||||
SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive) {
|
||||
if (!_map) {
|
||||
_map = (FMMap *)calloc(sizeof(FMMap), 16);
|
||||
}
|
||||
// Pre-existing map
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (m == _map[i].src) {
|
||||
return _map[i].dst;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (_map[i].src == nullptr) {
|
||||
// Make a new mutex
|
||||
SemaphoreHandle_t fm;
|
||||
if (recursive) {
|
||||
fm = _freertos_recursive_mutex_create();
|
||||
} else {
|
||||
fm = __freertos_mutex_create();
|
||||
}
|
||||
if (fm == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_map[i].src = m;
|
||||
_map[i].dst = fm;
|
||||
return fm;
|
||||
}
|
||||
}
|
||||
return nullptr; // Need to make space for more mutex maps!
|
||||
}
|
||||
|
||||
|
||||
// The HW Random code needs a precise sleep_until() in order to assure it
|
||||
// grabs the ROSC bit when it wants. Unfortunately, under FreeRTOS the
|
||||
// sleep_until() becomes imprecise and the "did I get the bit when I wanted"
|
||||
// check in the pico_rand code always fails and you get an infinite loop.
|
||||
|
||||
// This block wraps the 2 get_rand calls to set a flag to convert
|
||||
// sleep_until() (which can do a task swap and cause bad timing) into a
|
||||
// busy wait.
|
||||
|
||||
extern "C" {
|
||||
static bool __inRand = false;
|
||||
|
||||
extern uint64_t __real_get_rand_64();
|
||||
uint64_t __wrap_get_rand_64() {
|
||||
if (__isFreeRTOS) {
|
||||
rp2040.idleOtherCore();
|
||||
__inRand = true;
|
||||
auto r = __real_get_rand_64();
|
||||
__inRand = false;
|
||||
rp2040.resumeOtherCore();
|
||||
return r;
|
||||
} else {
|
||||
return __real_get_rand_64();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t __wrap_get_rand_32() {
|
||||
return (uint32_t) __wrap_get_rand_64();
|
||||
}
|
||||
|
||||
extern void __real_sleep_until(absolute_time_t t);
|
||||
void __wrap_sleep_until(absolute_time_t t) {
|
||||
if (__inRand) {
|
||||
busy_wait_until(t);
|
||||
} else {
|
||||
__real_sleep_until(t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
_freertos.h - Internal core definitions for FreeRTOS
|
||||
|
||||
Copyright (c) 2022 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 <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
|
||||
// to handle it.
|
||||
|
||||
extern bool __isFreeRTOS;
|
||||
|
||||
// FreeRTOS has been set up
|
||||
extern volatile bool __freeRTOSinitted;
|
||||
|
||||
extern "C" {
|
||||
#ifndef INC_FREERTOS_H
|
||||
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 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, 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));
|
||||
|
||||
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);
|
||||
@@ -0,0 +1,7 @@
|
||||
// Simple helper header to ensure pico libs support ?BT
|
||||
|
||||
#ifndef ENABLE_CLASSIC
|
||||
#define ENABLE_CLASSIC 0
|
||||
#endif
|
||||
|
||||
static_assert(ENABLE_CLASSIC, "This library needs Bluetooth enabled. Use the 'Tools->IP/Bluetooth Stack' menu in the IDE to enable it.");
|
||||
@@ -1,57 +1,2 @@
|
||||
/*
|
||||
Arduino API main include
|
||||
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef ARDUINO_API_H
|
||||
#define ARDUINO_API_H
|
||||
|
||||
// version 1.2.0
|
||||
#define ARDUINO_API_VERSION 10200
|
||||
|
||||
#include "Binary.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "Interrupts.h"
|
||||
#include "IPAddress.h"
|
||||
#include "Print.h"
|
||||
#include "Printable.h"
|
||||
#include "PluggableUSB.h"
|
||||
#include "Server.h"
|
||||
#include "String.h"
|
||||
#include "Stream.h"
|
||||
#include "Udp.h"
|
||||
#include "USBAPI.h"
|
||||
#include "WCharacter.h"
|
||||
#endif
|
||||
|
||||
/* Standard C library includes */
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
// Misc Arduino core functions
|
||||
#include "Common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
// Compatibility layer for older code
|
||||
#include "Compat.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#include "../../../ArduinoCore-API/api/ArduinoAPI.h"
|
||||
|
||||
+2
-552
@@ -1,552 +1,2 @@
|
||||
/*
|
||||
binary.h - Definitions for binary constants
|
||||
Deprecated -- use 0b binary literals instead
|
||||
Copyright (c) 2006 David A. Mellis. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef Binary_h
|
||||
#define Binary_h
|
||||
|
||||
/* If supported, 0b binary literals are preferable to these constants.
|
||||
* In that case, warn the user about these being deprecated (if possible). */
|
||||
#if __cplusplus >= 201402L
|
||||
/* C++14 introduces binary literals; C++11 introduces [[deprecated()]] */
|
||||
#define DEPRECATED(x) [[deprecated("use " #x " instead")]]
|
||||
#elif __GNUC__ >= 6
|
||||
/* GCC 4.3 supports binary literals; GCC 6 supports __deprecated__ on enums*/
|
||||
#define DEPRECATED(x) __attribute__ ((__deprecated__ ("use " #x " instead")))
|
||||
#else
|
||||
/* binary literals not supported, or "deprecated" warning not displayable */
|
||||
#define DEPRECATED(x)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
B0 DEPRECATED(0b0 ) = 0,
|
||||
B00 DEPRECATED(0b00 ) = 0,
|
||||
B000 DEPRECATED(0b000 ) = 0,
|
||||
B0000 DEPRECATED(0b0000 ) = 0,
|
||||
B00000 DEPRECATED(0b00000 ) = 0,
|
||||
B000000 DEPRECATED(0b000000 ) = 0,
|
||||
B0000000 DEPRECATED(0b0000000 ) = 0,
|
||||
B00000000 DEPRECATED(0b00000000) = 0,
|
||||
B1 DEPRECATED(0b1 ) = 1,
|
||||
B01 DEPRECATED(0b01 ) = 1,
|
||||
B001 DEPRECATED(0b001 ) = 1,
|
||||
B0001 DEPRECATED(0b0001 ) = 1,
|
||||
B00001 DEPRECATED(0b00001 ) = 1,
|
||||
B000001 DEPRECATED(0b000001 ) = 1,
|
||||
B0000001 DEPRECATED(0b0000001 ) = 1,
|
||||
B00000001 DEPRECATED(0b00000001) = 1,
|
||||
B10 DEPRECATED(0b10 ) = 2,
|
||||
B010 DEPRECATED(0b010 ) = 2,
|
||||
B0010 DEPRECATED(0b0010 ) = 2,
|
||||
B00010 DEPRECATED(0b00010 ) = 2,
|
||||
B000010 DEPRECATED(0b000010 ) = 2,
|
||||
B0000010 DEPRECATED(0b0000010 ) = 2,
|
||||
B00000010 DEPRECATED(0b00000010) = 2,
|
||||
B11 DEPRECATED(0b11 ) = 3,
|
||||
B011 DEPRECATED(0b011 ) = 3,
|
||||
B0011 DEPRECATED(0b0011 ) = 3,
|
||||
B00011 DEPRECATED(0b00011 ) = 3,
|
||||
B000011 DEPRECATED(0b000011 ) = 3,
|
||||
B0000011 DEPRECATED(0b0000011 ) = 3,
|
||||
B00000011 DEPRECATED(0b00000011) = 3,
|
||||
B100 DEPRECATED(0b100 ) = 4,
|
||||
B0100 DEPRECATED(0b0100 ) = 4,
|
||||
B00100 DEPRECATED(0b00100 ) = 4,
|
||||
B000100 DEPRECATED(0b000100 ) = 4,
|
||||
B0000100 DEPRECATED(0b0000100 ) = 4,
|
||||
B00000100 DEPRECATED(0b00000100) = 4,
|
||||
B101 DEPRECATED(0b101 ) = 5,
|
||||
B0101 DEPRECATED(0b0101 ) = 5,
|
||||
B00101 DEPRECATED(0b00101 ) = 5,
|
||||
B000101 DEPRECATED(0b000101 ) = 5,
|
||||
B0000101 DEPRECATED(0b0000101 ) = 5,
|
||||
B00000101 DEPRECATED(0b00000101) = 5,
|
||||
B110 DEPRECATED(0b110 ) = 6,
|
||||
B0110 DEPRECATED(0b0110 ) = 6,
|
||||
B00110 DEPRECATED(0b00110 ) = 6,
|
||||
B000110 DEPRECATED(0b000110 ) = 6,
|
||||
B0000110 DEPRECATED(0b0000110 ) = 6,
|
||||
B00000110 DEPRECATED(0b00000110) = 6,
|
||||
B111 DEPRECATED(0b111 ) = 7,
|
||||
B0111 DEPRECATED(0b0111 ) = 7,
|
||||
B00111 DEPRECATED(0b00111 ) = 7,
|
||||
B000111 DEPRECATED(0b000111 ) = 7,
|
||||
B0000111 DEPRECATED(0b0000111 ) = 7,
|
||||
B00000111 DEPRECATED(0b00000111) = 7,
|
||||
B1000 DEPRECATED(0b1000 ) = 8,
|
||||
B01000 DEPRECATED(0b01000 ) = 8,
|
||||
B001000 DEPRECATED(0b001000 ) = 8,
|
||||
B0001000 DEPRECATED(0b0001000 ) = 8,
|
||||
B00001000 DEPRECATED(0b00001000) = 8,
|
||||
B1001 DEPRECATED(0b1001 ) = 9,
|
||||
B01001 DEPRECATED(0b01001 ) = 9,
|
||||
B001001 DEPRECATED(0b001001 ) = 9,
|
||||
B0001001 DEPRECATED(0b0001001 ) = 9,
|
||||
B00001001 DEPRECATED(0b00001001) = 9,
|
||||
B1010 DEPRECATED(0b1010 ) = 10,
|
||||
B01010 DEPRECATED(0b01010 ) = 10,
|
||||
B001010 DEPRECATED(0b001010 ) = 10,
|
||||
B0001010 DEPRECATED(0b0001010 ) = 10,
|
||||
B00001010 DEPRECATED(0b00001010) = 10,
|
||||
B1011 DEPRECATED(0b1011 ) = 11,
|
||||
B01011 DEPRECATED(0b01011 ) = 11,
|
||||
B001011 DEPRECATED(0b001011 ) = 11,
|
||||
B0001011 DEPRECATED(0b0001011 ) = 11,
|
||||
B00001011 DEPRECATED(0b00001011) = 11,
|
||||
B1100 DEPRECATED(0b1100 ) = 12,
|
||||
B01100 DEPRECATED(0b01100 ) = 12,
|
||||
B001100 DEPRECATED(0b001100 ) = 12,
|
||||
B0001100 DEPRECATED(0b0001100 ) = 12,
|
||||
B00001100 DEPRECATED(0b00001100) = 12,
|
||||
B1101 DEPRECATED(0b1101 ) = 13,
|
||||
B01101 DEPRECATED(0b01101 ) = 13,
|
||||
B001101 DEPRECATED(0b001101 ) = 13,
|
||||
B0001101 DEPRECATED(0b0001101 ) = 13,
|
||||
B00001101 DEPRECATED(0b00001101) = 13,
|
||||
B1110 DEPRECATED(0b1110 ) = 14,
|
||||
B01110 DEPRECATED(0b01110 ) = 14,
|
||||
B001110 DEPRECATED(0b001110 ) = 14,
|
||||
B0001110 DEPRECATED(0b0001110 ) = 14,
|
||||
B00001110 DEPRECATED(0b00001110) = 14,
|
||||
B1111 DEPRECATED(0b1111 ) = 15,
|
||||
B01111 DEPRECATED(0b01111 ) = 15,
|
||||
B001111 DEPRECATED(0b001111 ) = 15,
|
||||
B0001111 DEPRECATED(0b0001111 ) = 15,
|
||||
B00001111 DEPRECATED(0b00001111) = 15,
|
||||
B10000 DEPRECATED(0b10000 ) = 16,
|
||||
B010000 DEPRECATED(0b010000 ) = 16,
|
||||
B0010000 DEPRECATED(0b0010000 ) = 16,
|
||||
B00010000 DEPRECATED(0b00010000) = 16,
|
||||
B10001 DEPRECATED(0b10001 ) = 17,
|
||||
B010001 DEPRECATED(0b010001 ) = 17,
|
||||
B0010001 DEPRECATED(0b0010001 ) = 17,
|
||||
B00010001 DEPRECATED(0b00010001) = 17,
|
||||
B10010 DEPRECATED(0b10010 ) = 18,
|
||||
B010010 DEPRECATED(0b010010 ) = 18,
|
||||
B0010010 DEPRECATED(0b0010010 ) = 18,
|
||||
B00010010 DEPRECATED(0b00010010) = 18,
|
||||
B10011 DEPRECATED(0b10011 ) = 19,
|
||||
B010011 DEPRECATED(0b010011 ) = 19,
|
||||
B0010011 DEPRECATED(0b0010011 ) = 19,
|
||||
B00010011 DEPRECATED(0b00010011) = 19,
|
||||
B10100 DEPRECATED(0b10100 ) = 20,
|
||||
B010100 DEPRECATED(0b010100 ) = 20,
|
||||
B0010100 DEPRECATED(0b0010100 ) = 20,
|
||||
B00010100 DEPRECATED(0b00010100) = 20,
|
||||
B10101 DEPRECATED(0b10101 ) = 21,
|
||||
B010101 DEPRECATED(0b010101 ) = 21,
|
||||
B0010101 DEPRECATED(0b0010101 ) = 21,
|
||||
B00010101 DEPRECATED(0b00010101) = 21,
|
||||
B10110 DEPRECATED(0b10110 ) = 22,
|
||||
B010110 DEPRECATED(0b010110 ) = 22,
|
||||
B0010110 DEPRECATED(0b0010110 ) = 22,
|
||||
B00010110 DEPRECATED(0b00010110) = 22,
|
||||
B10111 DEPRECATED(0b10111 ) = 23,
|
||||
B010111 DEPRECATED(0b010111 ) = 23,
|
||||
B0010111 DEPRECATED(0b0010111 ) = 23,
|
||||
B00010111 DEPRECATED(0b00010111) = 23,
|
||||
B11000 DEPRECATED(0b11000 ) = 24,
|
||||
B011000 DEPRECATED(0b011000 ) = 24,
|
||||
B0011000 DEPRECATED(0b0011000 ) = 24,
|
||||
B00011000 DEPRECATED(0b00011000) = 24,
|
||||
B11001 DEPRECATED(0b11001 ) = 25,
|
||||
B011001 DEPRECATED(0b011001 ) = 25,
|
||||
B0011001 DEPRECATED(0b0011001 ) = 25,
|
||||
B00011001 DEPRECATED(0b00011001) = 25,
|
||||
B11010 DEPRECATED(0b11010 ) = 26,
|
||||
B011010 DEPRECATED(0b011010 ) = 26,
|
||||
B0011010 DEPRECATED(0b0011010 ) = 26,
|
||||
B00011010 DEPRECATED(0b00011010) = 26,
|
||||
B11011 DEPRECATED(0b11011 ) = 27,
|
||||
B011011 DEPRECATED(0b011011 ) = 27,
|
||||
B0011011 DEPRECATED(0b0011011 ) = 27,
|
||||
B00011011 DEPRECATED(0b00011011) = 27,
|
||||
B11100 DEPRECATED(0b11100 ) = 28,
|
||||
B011100 DEPRECATED(0b011100 ) = 28,
|
||||
B0011100 DEPRECATED(0b0011100 ) = 28,
|
||||
B00011100 DEPRECATED(0b00011100) = 28,
|
||||
B11101 DEPRECATED(0b11101 ) = 29,
|
||||
B011101 DEPRECATED(0b011101 ) = 29,
|
||||
B0011101 DEPRECATED(0b0011101 ) = 29,
|
||||
B00011101 DEPRECATED(0b00011101) = 29,
|
||||
B11110 DEPRECATED(0b11110 ) = 30,
|
||||
B011110 DEPRECATED(0b011110 ) = 30,
|
||||
B0011110 DEPRECATED(0b0011110 ) = 30,
|
||||
B00011110 DEPRECATED(0b00011110) = 30,
|
||||
B11111 DEPRECATED(0b11111 ) = 31,
|
||||
B011111 DEPRECATED(0b011111 ) = 31,
|
||||
B0011111 DEPRECATED(0b0011111 ) = 31,
|
||||
B00011111 DEPRECATED(0b00011111) = 31,
|
||||
B100000 DEPRECATED(0b100000 ) = 32,
|
||||
B0100000 DEPRECATED(0b0100000 ) = 32,
|
||||
B00100000 DEPRECATED(0b00100000) = 32,
|
||||
B100001 DEPRECATED(0b100001 ) = 33,
|
||||
B0100001 DEPRECATED(0b0100001 ) = 33,
|
||||
B00100001 DEPRECATED(0b00100001) = 33,
|
||||
B100010 DEPRECATED(0b100010 ) = 34,
|
||||
B0100010 DEPRECATED(0b0100010 ) = 34,
|
||||
B00100010 DEPRECATED(0b00100010) = 34,
|
||||
B100011 DEPRECATED(0b100011 ) = 35,
|
||||
B0100011 DEPRECATED(0b0100011 ) = 35,
|
||||
B00100011 DEPRECATED(0b00100011) = 35,
|
||||
B100100 DEPRECATED(0b100100 ) = 36,
|
||||
B0100100 DEPRECATED(0b0100100 ) = 36,
|
||||
B00100100 DEPRECATED(0b00100100) = 36,
|
||||
B100101 DEPRECATED(0b100101 ) = 37,
|
||||
B0100101 DEPRECATED(0b0100101 ) = 37,
|
||||
B00100101 DEPRECATED(0b00100101) = 37,
|
||||
B100110 DEPRECATED(0b100110 ) = 38,
|
||||
B0100110 DEPRECATED(0b0100110 ) = 38,
|
||||
B00100110 DEPRECATED(0b00100110) = 38,
|
||||
B100111 DEPRECATED(0b100111 ) = 39,
|
||||
B0100111 DEPRECATED(0b0100111 ) = 39,
|
||||
B00100111 DEPRECATED(0b00100111) = 39,
|
||||
B101000 DEPRECATED(0b101000 ) = 40,
|
||||
B0101000 DEPRECATED(0b0101000 ) = 40,
|
||||
B00101000 DEPRECATED(0b00101000) = 40,
|
||||
B101001 DEPRECATED(0b101001 ) = 41,
|
||||
B0101001 DEPRECATED(0b0101001 ) = 41,
|
||||
B00101001 DEPRECATED(0b00101001) = 41,
|
||||
B101010 DEPRECATED(0b101010 ) = 42,
|
||||
B0101010 DEPRECATED(0b0101010 ) = 42,
|
||||
B00101010 DEPRECATED(0b00101010) = 42,
|
||||
B101011 DEPRECATED(0b101011 ) = 43,
|
||||
B0101011 DEPRECATED(0b0101011 ) = 43,
|
||||
B00101011 DEPRECATED(0b00101011) = 43,
|
||||
B101100 DEPRECATED(0b101100 ) = 44,
|
||||
B0101100 DEPRECATED(0b0101100 ) = 44,
|
||||
B00101100 DEPRECATED(0b00101100) = 44,
|
||||
B101101 DEPRECATED(0b101101 ) = 45,
|
||||
B0101101 DEPRECATED(0b0101101 ) = 45,
|
||||
B00101101 DEPRECATED(0b00101101) = 45,
|
||||
B101110 DEPRECATED(0b101110 ) = 46,
|
||||
B0101110 DEPRECATED(0b0101110 ) = 46,
|
||||
B00101110 DEPRECATED(0b00101110) = 46,
|
||||
B101111 DEPRECATED(0b101111 ) = 47,
|
||||
B0101111 DEPRECATED(0b0101111 ) = 47,
|
||||
B00101111 DEPRECATED(0b00101111) = 47,
|
||||
B110000 DEPRECATED(0b110000 ) = 48,
|
||||
B0110000 DEPRECATED(0b0110000 ) = 48,
|
||||
B00110000 DEPRECATED(0b00110000) = 48,
|
||||
B110001 DEPRECATED(0b110001 ) = 49,
|
||||
B0110001 DEPRECATED(0b0110001 ) = 49,
|
||||
B00110001 DEPRECATED(0b00110001) = 49,
|
||||
B110010 DEPRECATED(0b110010 ) = 50,
|
||||
B0110010 DEPRECATED(0b0110010 ) = 50,
|
||||
B00110010 DEPRECATED(0b00110010) = 50,
|
||||
B110011 DEPRECATED(0b110011 ) = 51,
|
||||
B0110011 DEPRECATED(0b0110011 ) = 51,
|
||||
B00110011 DEPRECATED(0b00110011) = 51,
|
||||
B110100 DEPRECATED(0b110100 ) = 52,
|
||||
B0110100 DEPRECATED(0b0110100 ) = 52,
|
||||
B00110100 DEPRECATED(0b00110100) = 52,
|
||||
B110101 DEPRECATED(0b110101 ) = 53,
|
||||
B0110101 DEPRECATED(0b0110101 ) = 53,
|
||||
B00110101 DEPRECATED(0b00110101) = 53,
|
||||
B110110 DEPRECATED(0b110110 ) = 54,
|
||||
B0110110 DEPRECATED(0b0110110 ) = 54,
|
||||
B00110110 DEPRECATED(0b00110110) = 54,
|
||||
B110111 DEPRECATED(0b110111 ) = 55,
|
||||
B0110111 DEPRECATED(0b0110111 ) = 55,
|
||||
B00110111 DEPRECATED(0b00110111) = 55,
|
||||
B111000 DEPRECATED(0b111000 ) = 56,
|
||||
B0111000 DEPRECATED(0b0111000 ) = 56,
|
||||
B00111000 DEPRECATED(0b00111000) = 56,
|
||||
B111001 DEPRECATED(0b111001 ) = 57,
|
||||
B0111001 DEPRECATED(0b0111001 ) = 57,
|
||||
B00111001 DEPRECATED(0b00111001) = 57,
|
||||
B111010 DEPRECATED(0b111010 ) = 58,
|
||||
B0111010 DEPRECATED(0b0111010 ) = 58,
|
||||
B00111010 DEPRECATED(0b00111010) = 58,
|
||||
B111011 DEPRECATED(0b111011 ) = 59,
|
||||
B0111011 DEPRECATED(0b0111011 ) = 59,
|
||||
B00111011 DEPRECATED(0b00111011) = 59,
|
||||
B111100 DEPRECATED(0b111100 ) = 60,
|
||||
B0111100 DEPRECATED(0b0111100 ) = 60,
|
||||
B00111100 DEPRECATED(0b00111100) = 60,
|
||||
B111101 DEPRECATED(0b111101 ) = 61,
|
||||
B0111101 DEPRECATED(0b0111101 ) = 61,
|
||||
B00111101 DEPRECATED(0b00111101) = 61,
|
||||
B111110 DEPRECATED(0b111110 ) = 62,
|
||||
B0111110 DEPRECATED(0b0111110 ) = 62,
|
||||
B00111110 DEPRECATED(0b00111110) = 62,
|
||||
B111111 DEPRECATED(0b111111 ) = 63,
|
||||
B0111111 DEPRECATED(0b0111111 ) = 63,
|
||||
B00111111 DEPRECATED(0b00111111) = 63,
|
||||
B1000000 DEPRECATED(0b1000000 ) = 64,
|
||||
B01000000 DEPRECATED(0b01000000) = 64,
|
||||
B1000001 DEPRECATED(0b1000001 ) = 65,
|
||||
B01000001 DEPRECATED(0b01000001) = 65,
|
||||
B1000010 DEPRECATED(0b1000010 ) = 66,
|
||||
B01000010 DEPRECATED(0b01000010) = 66,
|
||||
B1000011 DEPRECATED(0b1000011 ) = 67,
|
||||
B01000011 DEPRECATED(0b01000011) = 67,
|
||||
B1000100 DEPRECATED(0b1000100 ) = 68,
|
||||
B01000100 DEPRECATED(0b01000100) = 68,
|
||||
B1000101 DEPRECATED(0b1000101 ) = 69,
|
||||
B01000101 DEPRECATED(0b01000101) = 69,
|
||||
B1000110 DEPRECATED(0b1000110 ) = 70,
|
||||
B01000110 DEPRECATED(0b01000110) = 70,
|
||||
B1000111 DEPRECATED(0b1000111 ) = 71,
|
||||
B01000111 DEPRECATED(0b01000111) = 71,
|
||||
B1001000 DEPRECATED(0b1001000 ) = 72,
|
||||
B01001000 DEPRECATED(0b01001000) = 72,
|
||||
B1001001 DEPRECATED(0b1001001 ) = 73,
|
||||
B01001001 DEPRECATED(0b01001001) = 73,
|
||||
B1001010 DEPRECATED(0b1001010 ) = 74,
|
||||
B01001010 DEPRECATED(0b01001010) = 74,
|
||||
B1001011 DEPRECATED(0b1001011 ) = 75,
|
||||
B01001011 DEPRECATED(0b01001011) = 75,
|
||||
B1001100 DEPRECATED(0b1001100 ) = 76,
|
||||
B01001100 DEPRECATED(0b01001100) = 76,
|
||||
B1001101 DEPRECATED(0b1001101 ) = 77,
|
||||
B01001101 DEPRECATED(0b01001101) = 77,
|
||||
B1001110 DEPRECATED(0b1001110 ) = 78,
|
||||
B01001110 DEPRECATED(0b01001110) = 78,
|
||||
B1001111 DEPRECATED(0b1001111 ) = 79,
|
||||
B01001111 DEPRECATED(0b01001111) = 79,
|
||||
B1010000 DEPRECATED(0b1010000 ) = 80,
|
||||
B01010000 DEPRECATED(0b01010000) = 80,
|
||||
B1010001 DEPRECATED(0b1010001 ) = 81,
|
||||
B01010001 DEPRECATED(0b01010001) = 81,
|
||||
B1010010 DEPRECATED(0b1010010 ) = 82,
|
||||
B01010010 DEPRECATED(0b01010010) = 82,
|
||||
B1010011 DEPRECATED(0b1010011 ) = 83,
|
||||
B01010011 DEPRECATED(0b01010011) = 83,
|
||||
B1010100 DEPRECATED(0b1010100 ) = 84,
|
||||
B01010100 DEPRECATED(0b01010100) = 84,
|
||||
B1010101 DEPRECATED(0b1010101 ) = 85,
|
||||
B01010101 DEPRECATED(0b01010101) = 85,
|
||||
B1010110 DEPRECATED(0b1010110 ) = 86,
|
||||
B01010110 DEPRECATED(0b01010110) = 86,
|
||||
B1010111 DEPRECATED(0b1010111 ) = 87,
|
||||
B01010111 DEPRECATED(0b01010111) = 87,
|
||||
B1011000 DEPRECATED(0b1011000 ) = 88,
|
||||
B01011000 DEPRECATED(0b01011000) = 88,
|
||||
B1011001 DEPRECATED(0b1011001 ) = 89,
|
||||
B01011001 DEPRECATED(0b01011001) = 89,
|
||||
B1011010 DEPRECATED(0b1011010 ) = 90,
|
||||
B01011010 DEPRECATED(0b01011010) = 90,
|
||||
B1011011 DEPRECATED(0b1011011 ) = 91,
|
||||
B01011011 DEPRECATED(0b01011011) = 91,
|
||||
B1011100 DEPRECATED(0b1011100 ) = 92,
|
||||
B01011100 DEPRECATED(0b01011100) = 92,
|
||||
B1011101 DEPRECATED(0b1011101 ) = 93,
|
||||
B01011101 DEPRECATED(0b01011101) = 93,
|
||||
B1011110 DEPRECATED(0b1011110 ) = 94,
|
||||
B01011110 DEPRECATED(0b01011110) = 94,
|
||||
B1011111 DEPRECATED(0b1011111 ) = 95,
|
||||
B01011111 DEPRECATED(0b01011111) = 95,
|
||||
B1100000 DEPRECATED(0b1100000 ) = 96,
|
||||
B01100000 DEPRECATED(0b01100000) = 96,
|
||||
B1100001 DEPRECATED(0b1100001 ) = 97,
|
||||
B01100001 DEPRECATED(0b01100001) = 97,
|
||||
B1100010 DEPRECATED(0b1100010 ) = 98,
|
||||
B01100010 DEPRECATED(0b01100010) = 98,
|
||||
B1100011 DEPRECATED(0b1100011 ) = 99,
|
||||
B01100011 DEPRECATED(0b01100011) = 99,
|
||||
B1100100 DEPRECATED(0b1100100 ) = 100,
|
||||
B01100100 DEPRECATED(0b01100100) = 100,
|
||||
B1100101 DEPRECATED(0b1100101 ) = 101,
|
||||
B01100101 DEPRECATED(0b01100101) = 101,
|
||||
B1100110 DEPRECATED(0b1100110 ) = 102,
|
||||
B01100110 DEPRECATED(0b01100110) = 102,
|
||||
B1100111 DEPRECATED(0b1100111 ) = 103,
|
||||
B01100111 DEPRECATED(0b01100111) = 103,
|
||||
B1101000 DEPRECATED(0b1101000 ) = 104,
|
||||
B01101000 DEPRECATED(0b01101000) = 104,
|
||||
B1101001 DEPRECATED(0b1101001 ) = 105,
|
||||
B01101001 DEPRECATED(0b01101001) = 105,
|
||||
B1101010 DEPRECATED(0b1101010 ) = 106,
|
||||
B01101010 DEPRECATED(0b01101010) = 106,
|
||||
B1101011 DEPRECATED(0b1101011 ) = 107,
|
||||
B01101011 DEPRECATED(0b01101011) = 107,
|
||||
B1101100 DEPRECATED(0b1101100 ) = 108,
|
||||
B01101100 DEPRECATED(0b01101100) = 108,
|
||||
B1101101 DEPRECATED(0b1101101 ) = 109,
|
||||
B01101101 DEPRECATED(0b01101101) = 109,
|
||||
B1101110 DEPRECATED(0b1101110 ) = 110,
|
||||
B01101110 DEPRECATED(0b01101110) = 110,
|
||||
B1101111 DEPRECATED(0b1101111 ) = 111,
|
||||
B01101111 DEPRECATED(0b01101111) = 111,
|
||||
B1110000 DEPRECATED(0b1110000 ) = 112,
|
||||
B01110000 DEPRECATED(0b01110000) = 112,
|
||||
B1110001 DEPRECATED(0b1110001 ) = 113,
|
||||
B01110001 DEPRECATED(0b01110001) = 113,
|
||||
B1110010 DEPRECATED(0b1110010 ) = 114,
|
||||
B01110010 DEPRECATED(0b01110010) = 114,
|
||||
B1110011 DEPRECATED(0b1110011 ) = 115,
|
||||
B01110011 DEPRECATED(0b01110011) = 115,
|
||||
B1110100 DEPRECATED(0b1110100 ) = 116,
|
||||
B01110100 DEPRECATED(0b01110100) = 116,
|
||||
B1110101 DEPRECATED(0b1110101 ) = 117,
|
||||
B01110101 DEPRECATED(0b01110101) = 117,
|
||||
B1110110 DEPRECATED(0b1110110 ) = 118,
|
||||
B01110110 DEPRECATED(0b01110110) = 118,
|
||||
B1110111 DEPRECATED(0b1110111 ) = 119,
|
||||
B01110111 DEPRECATED(0b01110111) = 119,
|
||||
B1111000 DEPRECATED(0b1111000 ) = 120,
|
||||
B01111000 DEPRECATED(0b01111000) = 120,
|
||||
B1111001 DEPRECATED(0b1111001 ) = 121,
|
||||
B01111001 DEPRECATED(0b01111001) = 121,
|
||||
B1111010 DEPRECATED(0b1111010 ) = 122,
|
||||
B01111010 DEPRECATED(0b01111010) = 122,
|
||||
B1111011 DEPRECATED(0b1111011 ) = 123,
|
||||
B01111011 DEPRECATED(0b01111011) = 123,
|
||||
B1111100 DEPRECATED(0b1111100 ) = 124,
|
||||
B01111100 DEPRECATED(0b01111100) = 124,
|
||||
B1111101 DEPRECATED(0b1111101 ) = 125,
|
||||
B01111101 DEPRECATED(0b01111101) = 125,
|
||||
B1111110 DEPRECATED(0b1111110 ) = 126,
|
||||
B01111110 DEPRECATED(0b01111110) = 126,
|
||||
B1111111 DEPRECATED(0b1111111 ) = 127,
|
||||
B01111111 DEPRECATED(0b01111111) = 127,
|
||||
B10000000 DEPRECATED(0b10000000) = 128,
|
||||
B10000001 DEPRECATED(0b10000001) = 129,
|
||||
B10000010 DEPRECATED(0b10000010) = 130,
|
||||
B10000011 DEPRECATED(0b10000011) = 131,
|
||||
B10000100 DEPRECATED(0b10000100) = 132,
|
||||
B10000101 DEPRECATED(0b10000101) = 133,
|
||||
B10000110 DEPRECATED(0b10000110) = 134,
|
||||
B10000111 DEPRECATED(0b10000111) = 135,
|
||||
B10001000 DEPRECATED(0b10001000) = 136,
|
||||
B10001001 DEPRECATED(0b10001001) = 137,
|
||||
B10001010 DEPRECATED(0b10001010) = 138,
|
||||
B10001011 DEPRECATED(0b10001011) = 139,
|
||||
B10001100 DEPRECATED(0b10001100) = 140,
|
||||
B10001101 DEPRECATED(0b10001101) = 141,
|
||||
B10001110 DEPRECATED(0b10001110) = 142,
|
||||
B10001111 DEPRECATED(0b10001111) = 143,
|
||||
B10010000 DEPRECATED(0b10010000) = 144,
|
||||
B10010001 DEPRECATED(0b10010001) = 145,
|
||||
B10010010 DEPRECATED(0b10010010) = 146,
|
||||
B10010011 DEPRECATED(0b10010011) = 147,
|
||||
B10010100 DEPRECATED(0b10010100) = 148,
|
||||
B10010101 DEPRECATED(0b10010101) = 149,
|
||||
B10010110 DEPRECATED(0b10010110) = 150,
|
||||
B10010111 DEPRECATED(0b10010111) = 151,
|
||||
B10011000 DEPRECATED(0b10011000) = 152,
|
||||
B10011001 DEPRECATED(0b10011001) = 153,
|
||||
B10011010 DEPRECATED(0b10011010) = 154,
|
||||
B10011011 DEPRECATED(0b10011011) = 155,
|
||||
B10011100 DEPRECATED(0b10011100) = 156,
|
||||
B10011101 DEPRECATED(0b10011101) = 157,
|
||||
B10011110 DEPRECATED(0b10011110) = 158,
|
||||
B10011111 DEPRECATED(0b10011111) = 159,
|
||||
B10100000 DEPRECATED(0b10100000) = 160,
|
||||
B10100001 DEPRECATED(0b10100001) = 161,
|
||||
B10100010 DEPRECATED(0b10100010) = 162,
|
||||
B10100011 DEPRECATED(0b10100011) = 163,
|
||||
B10100100 DEPRECATED(0b10100100) = 164,
|
||||
B10100101 DEPRECATED(0b10100101) = 165,
|
||||
B10100110 DEPRECATED(0b10100110) = 166,
|
||||
B10100111 DEPRECATED(0b10100111) = 167,
|
||||
B10101000 DEPRECATED(0b10101000) = 168,
|
||||
B10101001 DEPRECATED(0b10101001) = 169,
|
||||
B10101010 DEPRECATED(0b10101010) = 170,
|
||||
B10101011 DEPRECATED(0b10101011) = 171,
|
||||
B10101100 DEPRECATED(0b10101100) = 172,
|
||||
B10101101 DEPRECATED(0b10101101) = 173,
|
||||
B10101110 DEPRECATED(0b10101110) = 174,
|
||||
B10101111 DEPRECATED(0b10101111) = 175,
|
||||
B10110000 DEPRECATED(0b10110000) = 176,
|
||||
B10110001 DEPRECATED(0b10110001) = 177,
|
||||
B10110010 DEPRECATED(0b10110010) = 178,
|
||||
B10110011 DEPRECATED(0b10110011) = 179,
|
||||
B10110100 DEPRECATED(0b10110100) = 180,
|
||||
B10110101 DEPRECATED(0b10110101) = 181,
|
||||
B10110110 DEPRECATED(0b10110110) = 182,
|
||||
B10110111 DEPRECATED(0b10110111) = 183,
|
||||
B10111000 DEPRECATED(0b10111000) = 184,
|
||||
B10111001 DEPRECATED(0b10111001) = 185,
|
||||
B10111010 DEPRECATED(0b10111010) = 186,
|
||||
B10111011 DEPRECATED(0b10111011) = 187,
|
||||
B10111100 DEPRECATED(0b10111100) = 188,
|
||||
B10111101 DEPRECATED(0b10111101) = 189,
|
||||
B10111110 DEPRECATED(0b10111110) = 190,
|
||||
B10111111 DEPRECATED(0b10111111) = 191,
|
||||
B11000000 DEPRECATED(0b11000000) = 192,
|
||||
B11000001 DEPRECATED(0b11000001) = 193,
|
||||
B11000010 DEPRECATED(0b11000010) = 194,
|
||||
B11000011 DEPRECATED(0b11000011) = 195,
|
||||
B11000100 DEPRECATED(0b11000100) = 196,
|
||||
B11000101 DEPRECATED(0b11000101) = 197,
|
||||
B11000110 DEPRECATED(0b11000110) = 198,
|
||||
B11000111 DEPRECATED(0b11000111) = 199,
|
||||
B11001000 DEPRECATED(0b11001000) = 200,
|
||||
B11001001 DEPRECATED(0b11001001) = 201,
|
||||
B11001010 DEPRECATED(0b11001010) = 202,
|
||||
B11001011 DEPRECATED(0b11001011) = 203,
|
||||
B11001100 DEPRECATED(0b11001100) = 204,
|
||||
B11001101 DEPRECATED(0b11001101) = 205,
|
||||
B11001110 DEPRECATED(0b11001110) = 206,
|
||||
B11001111 DEPRECATED(0b11001111) = 207,
|
||||
B11010000 DEPRECATED(0b11010000) = 208,
|
||||
B11010001 DEPRECATED(0b11010001) = 209,
|
||||
B11010010 DEPRECATED(0b11010010) = 210,
|
||||
B11010011 DEPRECATED(0b11010011) = 211,
|
||||
B11010100 DEPRECATED(0b11010100) = 212,
|
||||
B11010101 DEPRECATED(0b11010101) = 213,
|
||||
B11010110 DEPRECATED(0b11010110) = 214,
|
||||
B11010111 DEPRECATED(0b11010111) = 215,
|
||||
B11011000 DEPRECATED(0b11011000) = 216,
|
||||
B11011001 DEPRECATED(0b11011001) = 217,
|
||||
B11011010 DEPRECATED(0b11011010) = 218,
|
||||
B11011011 DEPRECATED(0b11011011) = 219,
|
||||
B11011100 DEPRECATED(0b11011100) = 220,
|
||||
B11011101 DEPRECATED(0b11011101) = 221,
|
||||
B11011110 DEPRECATED(0b11011110) = 222,
|
||||
B11011111 DEPRECATED(0b11011111) = 223,
|
||||
B11100000 DEPRECATED(0b11100000) = 224,
|
||||
B11100001 DEPRECATED(0b11100001) = 225,
|
||||
B11100010 DEPRECATED(0b11100010) = 226,
|
||||
B11100011 DEPRECATED(0b11100011) = 227,
|
||||
B11100100 DEPRECATED(0b11100100) = 228,
|
||||
B11100101 DEPRECATED(0b11100101) = 229,
|
||||
B11100110 DEPRECATED(0b11100110) = 230,
|
||||
B11100111 DEPRECATED(0b11100111) = 231,
|
||||
B11101000 DEPRECATED(0b11101000) = 232,
|
||||
B11101001 DEPRECATED(0b11101001) = 233,
|
||||
B11101010 DEPRECATED(0b11101010) = 234,
|
||||
B11101011 DEPRECATED(0b11101011) = 235,
|
||||
B11101100 DEPRECATED(0b11101100) = 236,
|
||||
B11101101 DEPRECATED(0b11101101) = 237,
|
||||
B11101110 DEPRECATED(0b11101110) = 238,
|
||||
B11101111 DEPRECATED(0b11101111) = 239,
|
||||
B11110000 DEPRECATED(0b11110000) = 240,
|
||||
B11110001 DEPRECATED(0b11110001) = 241,
|
||||
B11110010 DEPRECATED(0b11110010) = 242,
|
||||
B11110011 DEPRECATED(0b11110011) = 243,
|
||||
B11110100 DEPRECATED(0b11110100) = 244,
|
||||
B11110101 DEPRECATED(0b11110101) = 245,
|
||||
B11110110 DEPRECATED(0b11110110) = 246,
|
||||
B11110111 DEPRECATED(0b11110111) = 247,
|
||||
B11111000 DEPRECATED(0b11111000) = 248,
|
||||
B11111001 DEPRECATED(0b11111001) = 249,
|
||||
B11111010 DEPRECATED(0b11111010) = 250,
|
||||
B11111011 DEPRECATED(0b11111011) = 251,
|
||||
B11111100 DEPRECATED(0b11111100) = 252,
|
||||
B11111101 DEPRECATED(0b11111101) = 253,
|
||||
B11111110 DEPRECATED(0b11111110) = 254,
|
||||
B11111111 DEPRECATED(0b11111111) = 255
|
||||
};
|
||||
|
||||
#undef DEPRECATED
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#include "../../../ArduinoCore-API/api/Binary.h"
|
||||
|
||||
@@ -1,46 +1,2 @@
|
||||
/*
|
||||
Client.h - Base class that provides Client
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
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 "Stream.h"
|
||||
#include "IPAddress.h"
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class Client : public Stream {
|
||||
|
||||
public:
|
||||
virtual int connect(IPAddress ip, uint16_t port) =0;
|
||||
virtual int connect(const char *host, uint16_t port) =0;
|
||||
virtual size_t write(uint8_t) =0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual uint8_t connected() = 0;
|
||||
virtual operator bool() = 0;
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
|
||||
};
|
||||
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/Client.h"
|
||||
|
||||
@@ -1,10 +1 @@
|
||||
#include "Common.h"
|
||||
|
||||
/* C++ prototypes */
|
||||
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||
{
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
uint16_t makeWord(uint16_t w) { return w; }
|
||||
uint16_t makeWord(uint8_t h, uint8_t l) { return (h << 8) | l; }
|
||||
#include "../../../ArduinoCore-API/api/Common.cpp"
|
||||
|
||||
+1
-172
@@ -1,173 +1,2 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
void yield(void);
|
||||
|
||||
typedef enum {
|
||||
LOW = 0,
|
||||
HIGH = 1,
|
||||
CHANGE = 2,
|
||||
FALLING = 3,
|
||||
RISING = 4,
|
||||
} PinStatus;
|
||||
|
||||
typedef enum {
|
||||
INPUT = 0x0,
|
||||
OUTPUT = 0x1,
|
||||
INPUT_PULLUP = 0x2,
|
||||
INPUT_PULLDOWN = 0x3,
|
||||
OUTPUT_2MA = 0x4,
|
||||
OUTPUT_4MA = 0x5,
|
||||
OUTPUT_8MA = 0x6,
|
||||
OUTPUT_12MA = 0x7,
|
||||
} PinMode;
|
||||
|
||||
typedef enum {
|
||||
LSBFIRST = 0,
|
||||
MSBFIRST = 1,
|
||||
} BitOrder;
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define HALF_PI 1.5707963267948966192313216916398
|
||||
#define TWO_PI 6.283185307179586476925286766559
|
||||
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||
#define EULER 2.718281828459045235360287471352
|
||||
|
||||
#define SERIAL 0x0
|
||||
#define DISPLAY 0x1
|
||||
|
||||
#ifndef constrain
|
||||
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||
#endif
|
||||
|
||||
#ifndef radians
|
||||
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||
#endif
|
||||
|
||||
#ifndef degrees
|
||||
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||
#endif
|
||||
|
||||
#ifndef sq
|
||||
#define sq(x) ((x)*(x))
|
||||
#endif
|
||||
|
||||
typedef void (*voidFuncPtr)(void);
|
||||
typedef void (*voidFuncPtrParam)(void*);
|
||||
|
||||
// interrupts() / noInterrupts() must be defined by the core
|
||||
|
||||
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||
|
||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
|
||||
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
|
||||
|
||||
#ifndef bit
|
||||
#define bit(b) (1UL << (b))
|
||||
#endif
|
||||
|
||||
/* TODO: request for removal */
|
||||
typedef bool boolean;
|
||||
typedef uint8_t byte;
|
||||
typedef uint16_t word;
|
||||
|
||||
void init(void);
|
||||
void initVariant(void);
|
||||
|
||||
#ifndef HOST
|
||||
int atexit(void (*func)()) __attribute__((weak));
|
||||
#endif
|
||||
int main() __attribute__((weak));
|
||||
|
||||
#ifdef EXTENDED_PIN_MODE
|
||||
// Platforms who wnat to declare more than 256 pins need to define EXTENDED_PIN_MODE globally
|
||||
typedef uint32_t pin_size_t;
|
||||
#else
|
||||
typedef uint8_t pin_size_t;
|
||||
#endif
|
||||
|
||||
void pinMode(pin_size_t pinNumber, PinMode pinMode);
|
||||
void digitalWrite(pin_size_t pinNumber, PinStatus status);
|
||||
PinStatus digitalRead(pin_size_t pinNumber);
|
||||
int analogRead(pin_size_t pinNumber);
|
||||
void analogReference(uint8_t mode);
|
||||
void analogWrite(pin_size_t pinNumber, int value);
|
||||
|
||||
unsigned long millis(void);
|
||||
unsigned long micros(void);
|
||||
void delay(unsigned long);
|
||||
void delayMicroseconds(unsigned int us);
|
||||
unsigned long pulseIn(pin_size_t pin, uint8_t state, unsigned long timeout);
|
||||
unsigned long pulseInLong(pin_size_t pin, uint8_t state, unsigned long timeout);
|
||||
|
||||
void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val);
|
||||
uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder);
|
||||
|
||||
void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode);
|
||||
void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void* param);
|
||||
void detachInterrupt(pin_size_t interruptNumber);
|
||||
|
||||
void setup(void);
|
||||
void loop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
template<class T, class L>
|
||||
auto min(const T& a, const L& b) -> decltype((b < a) ? b : a)
|
||||
{
|
||||
return (b < a) ? b : a;
|
||||
}
|
||||
|
||||
template<class T, class L>
|
||||
auto max(const T& a, const L& b) -> decltype((b < a) ? b : a)
|
||||
{
|
||||
return (a < b) ? b : a;
|
||||
}
|
||||
#else
|
||||
#ifndef min
|
||||
#define min(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* C++ prototypes */
|
||||
uint16_t makeWord(uint16_t w);
|
||||
uint16_t makeWord(byte h, byte l);
|
||||
|
||||
#define word(...) makeWord(__VA_ARGS__)
|
||||
|
||||
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||
|
||||
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
|
||||
void noTone(uint8_t _pin);
|
||||
|
||||
// WMath prototypes
|
||||
long random(long);
|
||||
long random(long, long);
|
||||
void randomSeed(unsigned long);
|
||||
long map(long, long, long, long, long);
|
||||
|
||||
#endif // __cplusplus
|
||||
#include "../../../ArduinoCore-API/api/Common.h"
|
||||
|
||||
@@ -1,16 +1,2 @@
|
||||
#ifndef __COMPAT_H__
|
||||
#define __COMPAT_H__
|
||||
|
||||
namespace arduino {
|
||||
|
||||
inline void pinMode(pin_size_t pinNumber, int mode) {
|
||||
pinMode(pinNumber, (PinMode)mode);
|
||||
};
|
||||
|
||||
inline void digitalWrite(pin_size_t pinNumber, int status) {
|
||||
digitalWrite(pinNumber, (PinStatus)status);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#include "../../../ArduinoCore-API/api/Compat.h"
|
||||
|
||||
@@ -1,47 +1,2 @@
|
||||
/*
|
||||
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||
|
||||
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 <inttypes.h>
|
||||
#include "Stream.h"
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class HardwareI2C : public Stream
|
||||
{
|
||||
public:
|
||||
virtual void begin() = 0;
|
||||
virtual void begin(uint8_t address) = 0;
|
||||
virtual void end() = 0;
|
||||
|
||||
virtual void setClock(uint32_t freq) = 0;
|
||||
|
||||
virtual void beginTransmission(uint8_t address) = 0;
|
||||
virtual uint8_t endTransmission(bool stopBit) = 0;
|
||||
virtual uint8_t endTransmission(void) = 0;
|
||||
|
||||
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
|
||||
virtual size_t requestFrom(uint8_t address, size_t len) = 0;
|
||||
|
||||
virtual void onReceive(void(*)(int)) = 0;
|
||||
virtual void onRequest(void(*)(void)) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include "../../../ArduinoCore-API/api/HardwareI2C.h"
|
||||
|
||||
@@ -1,130 +1,2 @@
|
||||
/*
|
||||
Copyright (c) 2018 Arduino LLC. All right reserved.
|
||||
|
||||
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 "Common.h"
|
||||
#include <inttypes.h>
|
||||
#include "Stream.h"
|
||||
|
||||
#define SPI_HAS_TRANSACTION
|
||||
|
||||
namespace arduino {
|
||||
|
||||
typedef enum {
|
||||
SPI_MODE0 = 0,
|
||||
SPI_MODE1 = 1,
|
||||
SPI_MODE2 = 2,
|
||||
SPI_MODE3 = 3,
|
||||
} SPIMode;
|
||||
|
||||
|
||||
class SPISettings {
|
||||
public:
|
||||
SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) {
|
||||
if (__builtin_constant_p(clock)) {
|
||||
init_AlwaysInline(clock, bitOrder, dataMode);
|
||||
} else {
|
||||
init_MightInline(clock, bitOrder, dataMode);
|
||||
}
|
||||
}
|
||||
|
||||
SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode) {
|
||||
if (__builtin_constant_p(clock)) {
|
||||
init_AlwaysInline(clock, bitOrder, (SPIMode)dataMode);
|
||||
} else {
|
||||
init_MightInline(clock, bitOrder, (SPIMode)dataMode);
|
||||
}
|
||||
}
|
||||
|
||||
// Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first.
|
||||
SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); }
|
||||
|
||||
bool operator==(const SPISettings& rhs) const
|
||||
{
|
||||
if ((this->clockFreq == rhs.clockFreq) &&
|
||||
(this->bitOrder == rhs.bitOrder) &&
|
||||
(this->dataMode == rhs.dataMode)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator!=(const SPISettings& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
uint32_t getClockFreq() const {
|
||||
return clockFreq;
|
||||
}
|
||||
SPIMode getDataMode() const {
|
||||
return dataMode;
|
||||
}
|
||||
BitOrder getBitOrder() const {
|
||||
return (bitOrder);
|
||||
}
|
||||
|
||||
private:
|
||||
void init_MightInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) {
|
||||
init_AlwaysInline(clock, bitOrder, dataMode);
|
||||
}
|
||||
|
||||
// Core developer MUST use an helper function in beginTransaction() to use this data
|
||||
void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) __attribute__((__always_inline__)) {
|
||||
this->clockFreq = clock;
|
||||
this->dataMode = dataMode;
|
||||
this->bitOrder = bitOrder;
|
||||
}
|
||||
|
||||
uint32_t clockFreq;
|
||||
SPIMode dataMode;
|
||||
BitOrder bitOrder;
|
||||
|
||||
friend class HardwareSPI;
|
||||
};
|
||||
|
||||
const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
|
||||
|
||||
class HardwareSPI
|
||||
{
|
||||
public:
|
||||
virtual ~HardwareSPI() { }
|
||||
|
||||
virtual uint8_t transfer(uint8_t data) = 0;
|
||||
virtual uint16_t transfer16(uint16_t data) = 0;
|
||||
virtual void transfer(void *buf, size_t count) = 0;
|
||||
|
||||
// Transaction Functions
|
||||
virtual void usingInterrupt(int interruptNumber) = 0;
|
||||
virtual void notUsingInterrupt(int interruptNumber) = 0;
|
||||
virtual void beginTransaction(SPISettings settings) = 0;
|
||||
virtual void endTransaction(void) = 0;
|
||||
|
||||
// SPI Configuration methods
|
||||
virtual void attachInterrupt() = 0;
|
||||
virtual void detachInterrupt() = 0;
|
||||
|
||||
virtual void begin() = 0;
|
||||
virtual void end() = 0;
|
||||
};
|
||||
|
||||
// Alias SPIClass to HardwareSPI since it's already the defacto standard for SPI classe name
|
||||
typedef HardwareSPI SPIClass;
|
||||
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/HardwareSPI.h"
|
||||
|
||||
@@ -1,105 +1,2 @@
|
||||
/*
|
||||
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||
|
||||
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 <inttypes.h>
|
||||
#include "Stream.h"
|
||||
|
||||
namespace arduino {
|
||||
|
||||
// XXX: Those constants should be defined as const int / enums?
|
||||
// XXX: shall we use namespaces too?
|
||||
#define SERIAL_PARITY_EVEN (0x1ul)
|
||||
#define SERIAL_PARITY_ODD (0x2ul)
|
||||
#define SERIAL_PARITY_NONE (0x3ul)
|
||||
#define SERIAL_PARITY_MARK (0x4ul)
|
||||
#define SERIAL_PARITY_SPACE (0x5ul)
|
||||
#define SERIAL_PARITY_MASK (0xFul)
|
||||
|
||||
#define SERIAL_STOP_BIT_1 (0x10ul)
|
||||
#define SERIAL_STOP_BIT_1_5 (0x20ul)
|
||||
#define SERIAL_STOP_BIT_2 (0x30ul)
|
||||
#define SERIAL_STOP_BIT_MASK (0xF0ul)
|
||||
|
||||
#define SERIAL_DATA_5 (0x100ul)
|
||||
#define SERIAL_DATA_6 (0x200ul)
|
||||
#define SERIAL_DATA_7 (0x300ul)
|
||||
#define SERIAL_DATA_8 (0x400ul)
|
||||
#define SERIAL_DATA_MASK (0xF00ul)
|
||||
|
||||
#define SERIAL_5N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_5)
|
||||
#define SERIAL_6N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_6)
|
||||
#define SERIAL_7N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_7)
|
||||
#define SERIAL_8N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_8)
|
||||
#define SERIAL_5N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_5)
|
||||
#define SERIAL_6N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_6)
|
||||
#define SERIAL_7N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_7)
|
||||
#define SERIAL_8N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_8)
|
||||
#define SERIAL_5E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_5)
|
||||
#define SERIAL_6E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_6)
|
||||
#define SERIAL_7E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_7)
|
||||
#define SERIAL_8E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_8)
|
||||
#define SERIAL_5E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_5)
|
||||
#define SERIAL_6E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_6)
|
||||
#define SERIAL_7E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_7)
|
||||
#define SERIAL_8E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_8)
|
||||
#define SERIAL_5O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_5)
|
||||
#define SERIAL_6O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_6)
|
||||
#define SERIAL_7O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_7)
|
||||
#define SERIAL_8O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_8)
|
||||
#define SERIAL_5O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_5)
|
||||
#define SERIAL_6O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_6)
|
||||
#define SERIAL_7O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_7)
|
||||
#define SERIAL_8O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_8)
|
||||
#define SERIAL_5M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_5)
|
||||
#define SERIAL_6M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_6)
|
||||
#define SERIAL_7M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_7)
|
||||
#define SERIAL_8M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_8)
|
||||
#define SERIAL_5M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_5)
|
||||
#define SERIAL_6M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_6)
|
||||
#define SERIAL_7M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_7)
|
||||
#define SERIAL_8M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_8)
|
||||
#define SERIAL_5S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_5)
|
||||
#define SERIAL_6S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_6)
|
||||
#define SERIAL_7S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_7)
|
||||
#define SERIAL_8S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_8)
|
||||
#define SERIAL_5S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_5)
|
||||
#define SERIAL_6S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_6)
|
||||
#define SERIAL_7S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_7)
|
||||
#define SERIAL_8S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_8)
|
||||
|
||||
class HardwareSerial : public Stream
|
||||
{
|
||||
public:
|
||||
virtual void begin(unsigned long) = 0;
|
||||
virtual void begin(unsigned long baudrate, uint16_t config) = 0;
|
||||
virtual void end() = 0;
|
||||
virtual int available(void) = 0;
|
||||
virtual int peek(void) = 0;
|
||||
virtual int read(void) = 0;
|
||||
virtual void flush(void) = 0;
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||
virtual operator bool() = 0;
|
||||
};
|
||||
|
||||
// XXX: Are we keeping the serialEvent API?
|
||||
extern void serialEventRun(void) __attribute__((weak));
|
||||
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/HardwareSerial.h"
|
||||
|
||||
@@ -1,127 +1 @@
|
||||
/*
|
||||
IPAddress.cpp - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
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 "IPAddress.h"
|
||||
#include "Print.h"
|
||||
|
||||
using namespace arduino;
|
||||
|
||||
IPAddress::IPAddress()
|
||||
{
|
||||
_address.dword = 0;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
|
||||
{
|
||||
_address.bytes[0] = first_octet;
|
||||
_address.bytes[1] = second_octet;
|
||||
_address.bytes[2] = third_octet;
|
||||
_address.bytes[3] = fourth_octet;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint32_t address)
|
||||
{
|
||||
_address.dword = address;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
bool IPAddress::fromString(const char *address)
|
||||
{
|
||||
// TODO: add support for "a", "a.b", "a.b.c" formats
|
||||
|
||||
int16_t acc = -1; // Accumulator
|
||||
uint8_t dots = 0;
|
||||
|
||||
while (*address)
|
||||
{
|
||||
char c = *address++;
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0');
|
||||
if (acc > 255) {
|
||||
// Value out of [0..255] range
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
if (dots == 3) {
|
||||
// Too much dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
if (acc < 0) {
|
||||
/* No value between dots, e.g. '1..' */
|
||||
return false;
|
||||
}
|
||||
_address.bytes[dots++] = acc;
|
||||
acc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid char
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dots != 3) {
|
||||
// Too few dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
if (acc < 0) {
|
||||
/* No value between dots, e.g. '1..' */
|
||||
return false;
|
||||
}
|
||||
_address.bytes[3] = acc;
|
||||
return true;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
return *this;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(uint32_t address)
|
||||
{
|
||||
_address.dword = address;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IPAddress::operator==(const uint8_t* addr) const
|
||||
{
|
||||
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||
}
|
||||
|
||||
size_t IPAddress::printTo(Print& p) const
|
||||
{
|
||||
size_t n = 0;
|
||||
for (int i =0; i < 3; i++)
|
||||
{
|
||||
n += p.print(_address.bytes[i], DEC);
|
||||
n += p.print('.');
|
||||
}
|
||||
n += p.print(_address.bytes[3], DEC);
|
||||
return n;
|
||||
}
|
||||
|
||||
const IPAddress arduino::INADDR_NONE(0,0,0,0);
|
||||
#include "../../../ArduinoCore-API/api/IPAddress.cpp"
|
||||
|
||||
@@ -1,85 +1,2 @@
|
||||
/*
|
||||
IPAddress.h - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
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 <stdint.h>
|
||||
#include "Printable.h"
|
||||
#include "String.h"
|
||||
|
||||
// forward declartions of global name space friend classes
|
||||
class EthernetClass;
|
||||
class DhcpClass;
|
||||
class DNSClient;
|
||||
|
||||
namespace arduino {
|
||||
|
||||
// A class to make it easier to handle and pass around IP addresses
|
||||
|
||||
class IPAddress : public Printable {
|
||||
private:
|
||||
union {
|
||||
uint8_t bytes[4]; // IPv4 address
|
||||
uint32_t dword;
|
||||
} _address;
|
||||
|
||||
// Access the raw byte array containing the address. Because this returns a pointer
|
||||
// to the internal structure rather than a copy of the address this function should only
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t* raw_address() { return _address.bytes; };
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPAddress();
|
||||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||
IPAddress(uint32_t address);
|
||||
IPAddress(const uint8_t *address);
|
||||
|
||||
bool fromString(const char *address);
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
|
||||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||
// to a four-byte uint8_t array is expected
|
||||
operator uint32_t() const { return _address.dword; };
|
||||
bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; };
|
||||
bool operator!=(const IPAddress& addr) const { return _address.dword != addr._address.dword; };
|
||||
bool operator==(const uint8_t* addr) const;
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const { return _address.bytes[index]; };
|
||||
uint8_t& operator[](int index) { return _address.bytes[index]; };
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||
IPAddress& operator=(const uint8_t *address);
|
||||
IPAddress& operator=(uint32_t address);
|
||||
|
||||
virtual size_t printTo(Print& p) const;
|
||||
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
|
||||
friend ::EthernetClass;
|
||||
friend ::DhcpClass;
|
||||
friend ::DNSClient;
|
||||
};
|
||||
|
||||
extern const IPAddress INADDR_NONE;
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/IPAddress.h"
|
||||
|
||||
@@ -1,44 +1,2 @@
|
||||
#ifndef W_INTERRUPTS_CPP
|
||||
#define W_INTERRUPTS_CPP
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "Common.h"
|
||||
|
||||
namespace arduino {
|
||||
|
||||
template <typename T>
|
||||
using voidTemplateFuncPtrParam = void (*)(T param);
|
||||
|
||||
template<typename T> struct __container__ {
|
||||
void* param;
|
||||
voidTemplateFuncPtrParam<T> function;
|
||||
};
|
||||
|
||||
// C++ only overloaded version of attachInterrupt function
|
||||
template<typename T> void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam<T> userFunc, PinStatus mode, T& param) {
|
||||
|
||||
struct __container__<T> *cont = new __container__<T>();
|
||||
cont->param = ¶m;
|
||||
cont->function = userFunc;
|
||||
|
||||
// TODO: check lambda scope
|
||||
// TODO: add structure to delete(__container__) when detachInterrupt() is called
|
||||
auto f = [](void* a) -> void
|
||||
{
|
||||
T param = *(T*)((struct __container__<T>*)a)->param;
|
||||
(((struct __container__<T>*)a)->function)(param);
|
||||
};
|
||||
|
||||
attachInterruptParam(interruptNum, f, mode, cont);
|
||||
}
|
||||
|
||||
template<typename T> void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam<T*> userFunc, PinStatus mode, T* param) {
|
||||
attachInterruptParam(interruptNum, (voidFuncPtrParam)userFunc, mode, (void*)param);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#pragma once
|
||||
#include "../../../ArduinoCore-API/api/Interrupts.h"
|
||||
|
||||
@@ -1,101 +1 @@
|
||||
/*
|
||||
PluggableUSB.cpp
|
||||
Copyright (c) 2015 Arduino LLC
|
||||
|
||||
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 "USBAPI.h"
|
||||
#include "PluggableUSB.h"
|
||||
|
||||
using namespace arduino;
|
||||
|
||||
int PluggableUSB_::getInterface(uint8_t* interfaceCount)
|
||||
{
|
||||
int sent = 0;
|
||||
PluggableUSBModule* node;
|
||||
for (node = rootNode; node; node = node->next) {
|
||||
int res = node->getInterface(interfaceCount);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
sent += res;
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
int PluggableUSB_::getDescriptor(USBSetup& setup)
|
||||
{
|
||||
PluggableUSBModule* node;
|
||||
for (node = rootNode; node; node = node->next) {
|
||||
int ret = node->getDescriptor(setup);
|
||||
// ret!=0 -> request has been processed
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PluggableUSB_::getShortName(char *iSerialNum)
|
||||
{
|
||||
PluggableUSBModule* node;
|
||||
for (node = rootNode; node; node = node->next) {
|
||||
iSerialNum += node->getShortName(iSerialNum);
|
||||
}
|
||||
*iSerialNum = 0;
|
||||
}
|
||||
|
||||
bool PluggableUSB_::setup(USBSetup& setup)
|
||||
{
|
||||
PluggableUSBModule* node;
|
||||
for (node = rootNode; node; node = node->next) {
|
||||
if (node->setup(setup)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PluggableUSB_::plug(PluggableUSBModule *node)
|
||||
{
|
||||
if ((lastEp + node->numEndpoints) > totalEP) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rootNode) {
|
||||
rootNode = node;
|
||||
} else {
|
||||
PluggableUSBModule *current = rootNode;
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
current->next = node;
|
||||
}
|
||||
|
||||
node->pluggedInterface = lastIf;
|
||||
node->pluggedEndpoint = lastEp;
|
||||
lastIf += node->numInterfaces;
|
||||
for (uint8_t i = 0; i < node->numEndpoints; i++) {
|
||||
*(unsigned int*)(epBuffer(lastEp)) = node->endpointType[i];
|
||||
lastEp++;
|
||||
}
|
||||
return true;
|
||||
// restart USB layer???
|
||||
}
|
||||
|
||||
PluggableUSB_& PluggableUSB()
|
||||
{
|
||||
static PluggableUSB_ obj;
|
||||
return obj;
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/PluggableUSB.cpp"
|
||||
|
||||
@@ -1,78 +1,2 @@
|
||||
/*
|
||||
PluggableUSB.h
|
||||
Copyright (c) 2015 Arduino LLC
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef PUSB_h
|
||||
#define PUSB_h
|
||||
|
||||
#include "USBAPI.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class PluggableUSBModule {
|
||||
public:
|
||||
PluggableUSBModule(uint8_t numEps, uint8_t numIfs, unsigned int *epType) :
|
||||
numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual bool setup(USBSetup& setup) = 0;
|
||||
virtual int getInterface(uint8_t* interfaceCount) = 0;
|
||||
virtual int getDescriptor(USBSetup& setup) = 0;
|
||||
virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; }
|
||||
|
||||
uint8_t pluggedInterface;
|
||||
uint8_t pluggedEndpoint;
|
||||
|
||||
const uint8_t numEndpoints;
|
||||
const uint8_t numInterfaces;
|
||||
const unsigned int *endpointType;
|
||||
|
||||
PluggableUSBModule *next = NULL;
|
||||
|
||||
friend class PluggableUSB_;
|
||||
};
|
||||
|
||||
class PluggableUSB_ {
|
||||
public:
|
||||
PluggableUSB_();
|
||||
bool plug(PluggableUSBModule *node);
|
||||
int getInterface(uint8_t* interfaceCount);
|
||||
int getDescriptor(USBSetup& setup);
|
||||
bool setup(USBSetup& setup);
|
||||
void getShortName(char *iSerialNum);
|
||||
|
||||
private:
|
||||
uint8_t lastIf;
|
||||
uint8_t lastEp;
|
||||
PluggableUSBModule* rootNode;
|
||||
uint8_t totalEP;
|
||||
};
|
||||
}
|
||||
|
||||
// core need to define
|
||||
void* epBuffer(unsigned int n); // -> returns a pointer to the Nth element of the EP buffer structure
|
||||
|
||||
// Replacement for global singleton.
|
||||
// This function prevents static-initialization-order-fiasco
|
||||
// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
|
||||
arduino::PluggableUSB_& PluggableUSB();
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#include "../../../ArduinoCore-API/api/PluggableUSB.h"
|
||||
|
||||
+1
-429
@@ -1,429 +1 @@
|
||||
/*
|
||||
Copyright (c) 2014 Arduino. All right reserved.
|
||||
|
||||
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 <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
using namespace arduino;
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
/* default implementation: may be overridden */
|
||||
size_t Print::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
size_t n = 0;
|
||||
while (size--) {
|
||||
if (write(*buffer++)) n++;
|
||||
else break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
#if defined(__AVR__)
|
||||
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
|
||||
size_t n = 0;
|
||||
while (1) {
|
||||
unsigned char c = pgm_read_byte(p++);
|
||||
if (c == 0) break;
|
||||
if (write(c)) n++;
|
||||
else break;
|
||||
}
|
||||
return n;
|
||||
#else
|
||||
return print(reinterpret_cast<const char *>(ifsh));
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t Print::print(const String &s)
|
||||
{
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t Print::print(const char str[])
|
||||
{
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::print(char c)
|
||||
{
|
||||
return write(c);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned char b, int base)
|
||||
{
|
||||
return print((unsigned long) b, base);
|
||||
}
|
||||
|
||||
size_t Print::print(int n, int base)
|
||||
{
|
||||
return print((long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned int n, int base)
|
||||
{
|
||||
return print((unsigned long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long n, int base)
|
||||
{
|
||||
if (base == 0) {
|
||||
return write(n);
|
||||
} else if (base == 10) {
|
||||
if (n < 0) {
|
||||
int t = print('-');
|
||||
n = -n;
|
||||
return printNumber(n, 10) + t;
|
||||
}
|
||||
return printNumber(n, 10);
|
||||
} else {
|
||||
return printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long n, int base)
|
||||
{
|
||||
if (base == 0) return write(n);
|
||||
else return printNumber(n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long long n, int base)
|
||||
{
|
||||
if (base == 0) {
|
||||
return write(n);
|
||||
} else if (base == 10) {
|
||||
if (n < 0) {
|
||||
int t = print('-');
|
||||
n = -n;
|
||||
return printULLNumber(n, 10) + t;
|
||||
}
|
||||
return printULLNumber(n, 10);
|
||||
} else {
|
||||
return printULLNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long long n, int base)
|
||||
{
|
||||
if (base == 0) return write(n);
|
||||
else return printULLNumber(n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(double n, int digits)
|
||||
{
|
||||
return printFloat(n, digits);
|
||||
}
|
||||
|
||||
size_t Print::println(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
size_t n = print(ifsh);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(const Printable& x)
|
||||
{
|
||||
return x.printTo(*this);
|
||||
}
|
||||
|
||||
size_t Print::println(void)
|
||||
{
|
||||
return write("\r\n");
|
||||
}
|
||||
|
||||
size_t Print::println(const String &s)
|
||||
{
|
||||
size_t n = print(s);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const char c[])
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(char c)
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned char b, int base)
|
||||
{
|
||||
size_t n = print(b, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(long long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(double num, int digits)
|
||||
{
|
||||
size_t n = print(num, digits);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const Printable& x)
|
||||
{
|
||||
size_t n = print(x);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::printf(const char *format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
char temp[64];
|
||||
char* buffer = temp;
|
||||
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
|
||||
va_end(arg);
|
||||
if (len > sizeof(temp) - 1) {
|
||||
buffer = new char[len + 1];
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
va_start(arg, format);
|
||||
vsnprintf(buffer, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
len = write((const uint8_t*) buffer, len);
|
||||
if (buffer != temp) {
|
||||
delete[] buffer;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// TODO - must be better way than cut-n-paste!
|
||||
size_t Print::printf_P(const char *format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
char temp[64];
|
||||
char* buffer = temp;
|
||||
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
|
||||
va_end(arg);
|
||||
if (len > sizeof(temp) - 1) {
|
||||
buffer = new char[len + 1];
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
va_start(arg, format);
|
||||
vsnprintf(buffer, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
len = write((const uint8_t*) buffer, len);
|
||||
if (buffer != temp) {
|
||||
delete[] buffer;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// Private Methods /////////////////////////////////////////////////////////////
|
||||
|
||||
size_t Print::printNumber(unsigned long n, uint8_t base)
|
||||
{
|
||||
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||
char *str = &buf[sizeof(buf) - 1];
|
||||
|
||||
*str = '\0';
|
||||
|
||||
// prevent crash if called with base == 1
|
||||
if (base < 2) base = 10;
|
||||
|
||||
do {
|
||||
char c = n % base;
|
||||
n /= base;
|
||||
|
||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while(n);
|
||||
|
||||
return write(str);
|
||||
}
|
||||
|
||||
// REFERENCE IMPLEMENTATION FOR ULL
|
||||
// size_t Print::printULLNumber(unsigned long long n, uint8_t base)
|
||||
// {
|
||||
// // if limited to base 10 and 16 the bufsize can be smaller
|
||||
// char buf[65];
|
||||
// char *str = &buf[64];
|
||||
|
||||
// *str = '\0';
|
||||
|
||||
// // prevent crash if called with base == 1
|
||||
// if (base < 2) base = 10;
|
||||
|
||||
// do {
|
||||
// unsigned long long t = n / base;
|
||||
// char c = n - t * base; // faster than c = n%base;
|
||||
// n = t;
|
||||
// *--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
// } while(n);
|
||||
|
||||
// return write(str);
|
||||
// }
|
||||
|
||||
// FAST IMPLEMENTATION FOR ULL
|
||||
size_t Print::printULLNumber(unsigned long long n64, uint8_t base)
|
||||
{
|
||||
// if limited to base 10 and 16 the bufsize can be 20
|
||||
char buf[64];
|
||||
uint8_t i = 0;
|
||||
uint8_t innerLoops = 0;
|
||||
|
||||
// prevent crash if called with base == 1
|
||||
if (base < 2) base = 10;
|
||||
|
||||
// process chunks that fit in "16 bit math".
|
||||
uint16_t top = 0xFFFF / base;
|
||||
uint16_t th16 = 1;
|
||||
while (th16 < top)
|
||||
{
|
||||
th16 *= base;
|
||||
innerLoops++;
|
||||
}
|
||||
|
||||
while (n64 > th16)
|
||||
{
|
||||
// 64 bit math part
|
||||
uint64_t q = n64 / th16;
|
||||
uint16_t r = n64 - q*th16;
|
||||
n64 = q;
|
||||
|
||||
// 16 bit math loop to do remainder. (note buffer is filled reverse)
|
||||
for (uint8_t j=0; j < innerLoops; j++)
|
||||
{
|
||||
uint16_t qq = r/base;
|
||||
buf[i++] = r - qq*base;
|
||||
r = qq;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t n16 = n64;
|
||||
while (n16 > 0)
|
||||
{
|
||||
uint16_t qq = n16/base;
|
||||
buf[i++] = n16 - qq*base;
|
||||
n16 = qq;
|
||||
}
|
||||
|
||||
size_t bytes = i;
|
||||
for (; i > 0; i--)
|
||||
write((char) (buf[i - 1] < 10 ?
|
||||
'0' + buf[i - 1] :
|
||||
'A' + buf[i - 1] - 10));
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
size_t Print::printFloat(double number, int digits)
|
||||
{
|
||||
if (digits < 0)
|
||||
digits = 2;
|
||||
|
||||
size_t n = 0;
|
||||
|
||||
if (isnan(number)) return print("nan");
|
||||
if (isinf(number)) return print("inf");
|
||||
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
|
||||
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
|
||||
|
||||
// Handle negative numbers
|
||||
if (number < 0.0)
|
||||
{
|
||||
n += print('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for (uint8_t i=0; i<digits; ++i)
|
||||
rounding /= 10.0;
|
||||
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
unsigned long int_part = (unsigned long)number;
|
||||
double remainder = number - (double)int_part;
|
||||
n += print(int_part);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if (digits > 0) {
|
||||
n += print(".");
|
||||
}
|
||||
|
||||
// Extract digits from the remainder one at a time
|
||||
while (digits-- > 0)
|
||||
{
|
||||
remainder *= 10.0;
|
||||
unsigned int toPrint = (unsigned int)remainder;
|
||||
n += print(toPrint);
|
||||
remainder -= toPrint;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/Print.cpp"
|
||||
|
||||
@@ -1,100 +1,2 @@
|
||||
/*
|
||||
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||
|
||||
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 <inttypes.h>
|
||||
#include <stdio.h> // for size_t
|
||||
|
||||
#include "String.h"
|
||||
#include "Printable.h"
|
||||
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class Print
|
||||
{
|
||||
private:
|
||||
int write_error;
|
||||
size_t printNumber(unsigned long, uint8_t);
|
||||
size_t printULLNumber(unsigned long long, uint8_t);
|
||||
size_t printFloat(double, int);
|
||||
protected:
|
||||
void setWriteError(int err = 1) { write_error = err; }
|
||||
public:
|
||||
Print() : write_error(0) {}
|
||||
|
||||
int getWriteError() { return write_error; }
|
||||
void clearWriteError() { setWriteError(0); }
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write((const uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
// default to zero, meaning "a single write may block"
|
||||
// should be overriden by subclasses with buffering
|
||||
virtual int availableForWrite() { return 0; }
|
||||
|
||||
size_t print(const __FlashStringHelper *);
|
||||
size_t print(const String &);
|
||||
size_t print(const char[]);
|
||||
size_t print(char);
|
||||
size_t print(unsigned char, int = DEC);
|
||||
size_t print(int, int = DEC);
|
||||
size_t print(unsigned int, int = DEC);
|
||||
size_t print(long, int = DEC);
|
||||
size_t print(unsigned long, int = DEC);
|
||||
size_t print(long long, int = DEC);
|
||||
size_t print(unsigned long long, int = DEC);
|
||||
size_t print(double, int = 2);
|
||||
size_t print(const Printable&);
|
||||
|
||||
size_t println(const __FlashStringHelper *);
|
||||
size_t println(const String &s);
|
||||
size_t println(const char[]);
|
||||
size_t println(char);
|
||||
size_t println(unsigned char, int = DEC);
|
||||
size_t println(int, int = DEC);
|
||||
size_t println(unsigned int, int = DEC);
|
||||
size_t println(long, int = DEC);
|
||||
size_t println(unsigned long, int = DEC);
|
||||
size_t println(long long, int = DEC);
|
||||
size_t println(unsigned long long, int = DEC);
|
||||
size_t println(double, int = 2);
|
||||
size_t println(const Printable&);
|
||||
size_t println(void);
|
||||
|
||||
// EFP3 - Add printf() to make life so much easier...
|
||||
size_t printf(const char *format, ...);
|
||||
size_t printf_P(const char *format, ...);
|
||||
|
||||
virtual void flush() { /* Empty implementation for backward compatibility */ }
|
||||
};
|
||||
|
||||
}
|
||||
using namespace arduino;
|
||||
#include "../../../ArduinoCore-API/api/Print.h"
|
||||
|
||||
@@ -1,39 +1,2 @@
|
||||
/*
|
||||
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||
|
||||
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 <stdlib.h>
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class Print;
|
||||
|
||||
/** The Printable class provides a way for new classes to allow themselves to be printed.
|
||||
By deriving from Printable and implementing the printTo method, it will then be possible
|
||||
for users to print out instances of this class by passing them into the usual
|
||||
Print::print and Print::println methods.
|
||||
*/
|
||||
|
||||
class Printable
|
||||
{
|
||||
public:
|
||||
virtual size_t printTo(Print& p) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/Printable.h"
|
||||
|
||||
@@ -1,141 +1 @@
|
||||
/*
|
||||
Copyright (c) 2014 Arduino. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifndef _RING_BUFFER_
|
||||
#define _RING_BUFFER_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace arduino {
|
||||
|
||||
// Define constants and variables for buffering incoming serial data. We're
|
||||
// using a ring buffer (I think), in which head is the index of the location
|
||||
// to which to write the next incoming character and tail is the index of the
|
||||
// location from which to read.
|
||||
#define SERIAL_BUFFER_SIZE 64
|
||||
|
||||
template <int N>
|
||||
class RingBufferN
|
||||
{
|
||||
public:
|
||||
uint8_t _aucBuffer[N] ;
|
||||
volatile int _iHead ;
|
||||
volatile int _iTail ;
|
||||
volatile int _numElems;
|
||||
|
||||
public:
|
||||
RingBufferN( void ) ;
|
||||
void store_char( uint8_t c ) ;
|
||||
void clear();
|
||||
int read_char();
|
||||
int available();
|
||||
int availableForStore();
|
||||
int peek();
|
||||
bool isFull();
|
||||
|
||||
private:
|
||||
int nextIndex(int index);
|
||||
inline bool isEmpty() const { return (_numElems == 0); }
|
||||
};
|
||||
|
||||
typedef RingBufferN<SERIAL_BUFFER_SIZE> RingBuffer;
|
||||
|
||||
|
||||
template <int N>
|
||||
RingBufferN<N>::RingBufferN( void )
|
||||
{
|
||||
memset( _aucBuffer, 0, N ) ;
|
||||
clear();
|
||||
}
|
||||
|
||||
template <int N>
|
||||
void RingBufferN<N>::store_char( uint8_t c )
|
||||
{
|
||||
// if we should be storing the received character into the location
|
||||
// just before the tail (meaning that the head would advance to the
|
||||
// current location of the tail), we're about to overflow the buffer
|
||||
// and so we don't write the character or advance the head.
|
||||
if (!isFull())
|
||||
{
|
||||
_aucBuffer[_iHead] = c ;
|
||||
_iHead = nextIndex(_iHead);
|
||||
_numElems++;
|
||||
}
|
||||
}
|
||||
|
||||
template <int N>
|
||||
void RingBufferN<N>::clear()
|
||||
{
|
||||
_iHead = 0;
|
||||
_iTail = 0;
|
||||
_numElems = 0;
|
||||
}
|
||||
|
||||
template <int N>
|
||||
int RingBufferN<N>::read_char()
|
||||
{
|
||||
if (isEmpty())
|
||||
return -1;
|
||||
|
||||
uint8_t value = _aucBuffer[_iTail];
|
||||
_iTail = nextIndex(_iTail);
|
||||
_numElems--;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template <int N>
|
||||
int RingBufferN<N>::available()
|
||||
{
|
||||
return _numElems;
|
||||
}
|
||||
|
||||
template <int N>
|
||||
int RingBufferN<N>::availableForStore()
|
||||
{
|
||||
return (N - _numElems);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
int RingBufferN<N>::peek()
|
||||
{
|
||||
if (isEmpty())
|
||||
return -1;
|
||||
|
||||
return _aucBuffer[_iTail];
|
||||
}
|
||||
|
||||
template <int N>
|
||||
int RingBufferN<N>::nextIndex(int index)
|
||||
{
|
||||
return (uint32_t)(index + 1) % N;
|
||||
}
|
||||
|
||||
template <int N>
|
||||
bool RingBufferN<N>::isFull()
|
||||
{
|
||||
return (_numElems == N);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* _RING_BUFFER_ */
|
||||
#endif /* __cplusplus */
|
||||
#include "../../../ArduinoCore-API/api/RingBuffer.h"
|
||||
|
||||
@@ -1,31 +1,2 @@
|
||||
/*
|
||||
Server.h - Base class that provides Server
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
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 "Print.h"
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class Server : public Print {
|
||||
public:
|
||||
virtual void begin() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/Server.h"
|
||||
|
||||
+1
-321
@@ -1,321 +1 @@
|
||||
/*
|
||||
Stream.cpp - adds parsing methods to Stream class
|
||||
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
|
||||
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
|
||||
|
||||
Created July 2011
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
|
||||
findMulti/findUntil routines written by Jim Leonard/Xuth
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
|
||||
|
||||
using namespace arduino;
|
||||
|
||||
// private method to read stream with timeout
|
||||
int Stream::timedRead()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = read();
|
||||
if (c >= 0) return c;
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// private method to peek stream with timeout
|
||||
int Stream::timedPeek()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = peek();
|
||||
if (c >= 0) return c;
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// returns peek of the next digit in the stream or -1 if timeout
|
||||
// discards non-numeric characters
|
||||
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal)
|
||||
{
|
||||
int c;
|
||||
while (1) {
|
||||
c = timedPeek();
|
||||
|
||||
if( c < 0 ||
|
||||
c == '-' ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
(detectDecimal && c == '.')) return c;
|
||||
|
||||
switch( lookahead ){
|
||||
case SKIP_NONE: return -1; // Fail code.
|
||||
case SKIP_WHITESPACE:
|
||||
switch( c ){
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n': break;
|
||||
default: return -1; // Fail code.
|
||||
}
|
||||
case SKIP_ALL:
|
||||
break;
|
||||
}
|
||||
read(); // discard non-numeric
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
// find returns true if the target string is found
|
||||
bool Stream::find(const char *target)
|
||||
{
|
||||
return findUntil(target, strlen(target), NULL, 0);
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of given length is found
|
||||
// returns true if target string is found, false if timed out
|
||||
bool Stream::find(const char *target, size_t length)
|
||||
{
|
||||
return findUntil(target, length, NULL, 0);
|
||||
}
|
||||
|
||||
// as find but search ends if the terminator string is found
|
||||
bool Stream::findUntil(const char *target, const char *terminator)
|
||||
{
|
||||
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of the given length is found
|
||||
// search terminated if the terminator string is found
|
||||
// returns true if target string is found, false if terminated or timed out
|
||||
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
|
||||
{
|
||||
if (terminator == NULL) {
|
||||
MultiTarget t[1] = {{target, targetLen, 0}};
|
||||
return findMulti(t, 1) == 0;
|
||||
} else {
|
||||
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
|
||||
return findMulti(t, 2) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// lookahead determines how parseInt looks ahead in the stream.
|
||||
// See LookaheadMode enumeration at the top of the file.
|
||||
// Lookahead is terminated by the first character that is not a valid part of an integer.
|
||||
// Once parsing commences, 'ignore' will be skipped in the stream.
|
||||
long Stream::parseInt(LookaheadMode lookahead, char ignore)
|
||||
{
|
||||
bool isNegative = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
|
||||
c = peekNextDigit(lookahead, false);
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do{
|
||||
if((char)c == ignore)
|
||||
; // ignore this character
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if(c >= '0' && c <= '9') // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
}
|
||||
while( (c >= '0' && c <= '9') || (char)c == ignore );
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
return value;
|
||||
}
|
||||
|
||||
// as parseInt but returns a floating point value
|
||||
float Stream::parseFloat(LookaheadMode lookahead, char ignore)
|
||||
{
|
||||
bool isNegative = false;
|
||||
bool isFraction = false;
|
||||
double value = 0.0;
|
||||
int c;
|
||||
double fraction = 1.0;
|
||||
|
||||
c = peekNextDigit(lookahead, true);
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do{
|
||||
if((char)c == ignore)
|
||||
; // ignore
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if (c == '.')
|
||||
isFraction = true;
|
||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
if(isFraction) {
|
||||
fraction *= 0.1;
|
||||
value = value + fraction * (c - '0');
|
||||
} else {
|
||||
value = value * 10 + c - '0';
|
||||
}
|
||||
}
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
}
|
||||
while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || (char)c == ignore );
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// read characters from stream into buffer
|
||||
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer
|
||||
// the buffer is NOT null terminated.
|
||||
//
|
||||
size_t Stream::readBytes(char *buffer, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
while (count < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0) break;
|
||||
*buffer++ = (char)c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// as readBytes with terminator character
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
||||
{
|
||||
size_t index = 0;
|
||||
while (index < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0 || (char)c == terminator) break;
|
||||
*buffer++ = (char)c;
|
||||
index++;
|
||||
}
|
||||
return index; // return number of characters, not including null terminator
|
||||
}
|
||||
|
||||
String Stream::readString()
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Stream::readStringUntil(char terminator)
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0 && (char)c != terminator)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
|
||||
// any zero length target string automatically matches and would make
|
||||
// a mess of the rest of the algorithm.
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
if (t->len <= 0)
|
||||
return t - targets;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int c = timedRead();
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
// the simple case is if we match, deal with that first.
|
||||
if ((char)c == t->str[t->index]) {
|
||||
if (++t->index == t->len)
|
||||
return t - targets;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
// if not we need to walk back and see if we could have matched further
|
||||
// down the stream (ie '1112' doesn't match the first position in '11112'
|
||||
// but it will match the second position so we can't just reset the current
|
||||
// index to 0 when we find a mismatch.
|
||||
if (t->index == 0)
|
||||
continue;
|
||||
|
||||
int origIndex = t->index;
|
||||
do {
|
||||
--t->index;
|
||||
// first check if current char works against the new current index
|
||||
if ((char)c != t->str[t->index])
|
||||
continue;
|
||||
|
||||
// if it's the only char then we're good, nothing more to check
|
||||
if (t->index == 0) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we need to check the rest of the found string
|
||||
int diff = origIndex - t->index;
|
||||
size_t i;
|
||||
for (i = 0; i < t->index; ++i) {
|
||||
if (t->str[i] != t->str[i + diff])
|
||||
break;
|
||||
}
|
||||
|
||||
// if we successfully got through the previous loop then our current
|
||||
// index is good.
|
||||
if (i == t->index) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we just try the next index
|
||||
} while (t->index);
|
||||
}
|
||||
}
|
||||
// unreachable
|
||||
return -1;
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/Stream.cpp"
|
||||
|
||||
+1
-130
@@ -1,131 +1,2 @@
|
||||
/*
|
||||
Stream.h - base class for character-based streams.
|
||||
Copyright (c) 2010 David A. Mellis. All right reserved.
|
||||
|
||||
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
|
||||
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Print.h"
|
||||
|
||||
// compatability macros for testing
|
||||
/*
|
||||
#define getInt() parseInt()
|
||||
#define getInt(ignore) parseInt(ignore)
|
||||
#define getFloat() parseFloat()
|
||||
#define getFloat(ignore) parseFloat(ignore)
|
||||
#define getString( pre_string, post_string, buffer, length)
|
||||
readBytesBetween( pre_string, terminator, buffer, length)
|
||||
*/
|
||||
|
||||
namespace arduino {
|
||||
|
||||
// This enumeration provides the lookahead options for parseInt(), parseFloat()
|
||||
// The rules set out here are used until either the first valid character is found
|
||||
// or a time out occurs due to lack of input.
|
||||
enum LookaheadMode{
|
||||
SKIP_ALL, // All invalid characters are ignored.
|
||||
SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid.
|
||||
SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped.
|
||||
};
|
||||
|
||||
#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field
|
||||
|
||||
class Stream : public Print
|
||||
{
|
||||
protected:
|
||||
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||
unsigned long _startMillis; // used for timeout measurement
|
||||
int timedRead(); // private method to read stream with timeout
|
||||
int timedPeek(); // private method to peek stream with timeout
|
||||
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout
|
||||
|
||||
public:
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
|
||||
Stream() {_timeout=1000;}
|
||||
|
||||
// parsing methods
|
||||
|
||||
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
unsigned long getTimeout(void) { return _timeout; }
|
||||
|
||||
bool find(const char *target); // reads data from the stream until the target string is found
|
||||
bool find(const uint8_t *target) { return find ((const char *)target); }
|
||||
// returns true if target string is found, false if timed out (see setTimeout)
|
||||
|
||||
bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found
|
||||
bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); }
|
||||
// returns true if target string is found, false if timed out
|
||||
|
||||
bool find(char target) { return find (&target, 1); }
|
||||
|
||||
bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found
|
||||
bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); }
|
||||
|
||||
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found
|
||||
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); }
|
||||
|
||||
long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// lookahead determines how parseInt looks ahead in the stream.
|
||||
// See LookaheadMode enumeration at the top of the file.
|
||||
// Lookahead is terminated by the first character that is not a valid part of an integer.
|
||||
// Once parsing commences, 'ignore' will be skipped in the stream.
|
||||
|
||||
float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
|
||||
// float version of parseInt
|
||||
|
||||
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
|
||||
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
|
||||
// terminates if length characters have been read or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||
size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
// Arduino String functions to be added here
|
||||
String readString();
|
||||
String readStringUntil(char terminator);
|
||||
|
||||
protected:
|
||||
long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); }
|
||||
float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); }
|
||||
// These overload exists for compatibility with any class that has derived
|
||||
// Stream and used parseFloat/Int with a custom ignore character. To keep
|
||||
// the public API simple, these overload remains protected.
|
||||
|
||||
struct MultiTarget {
|
||||
const char *str; // string you're searching for
|
||||
size_t len; // length of string you're searching for
|
||||
size_t index; // index used by the search routine.
|
||||
};
|
||||
|
||||
// This allows you to search for an arbitrary number of strings.
|
||||
// Returns index of the target that is found first or -1 if timeout occurs.
|
||||
int findMulti(struct MultiTarget *targets, int tCount);
|
||||
};
|
||||
|
||||
#undef NO_IGNORE_CHAR
|
||||
|
||||
}
|
||||
#include "../../../ArduinoCore-API/api/Stream.h"
|
||||
|
||||
+1
-768
@@ -1,768 +1 @@
|
||||
/*
|
||||
String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.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 "String.h"
|
||||
#include "Common.h"
|
||||
#include "itoa.h"
|
||||
#include "deprecated-avr-comp/avr/dtostrf.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
namespace arduino {
|
||||
|
||||
/*********************************************/
|
||||
/* Static Member Initialisation */
|
||||
/*********************************************/
|
||||
|
||||
size_t const String::FLT_MAX_DECIMAL_PLACES;
|
||||
size_t const String::DBL_MAX_DECIMAL_PLACES;
|
||||
|
||||
/*********************************************/
|
||||
/* Constructors */
|
||||
/*********************************************/
|
||||
|
||||
String::String(const char *cstr)
|
||||
{
|
||||
init();
|
||||
if (cstr) copy(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
String::String(const char *cstr, unsigned int length)
|
||||
{
|
||||
init();
|
||||
if (cstr) copy(cstr, length);
|
||||
}
|
||||
|
||||
String::String(const String &value)
|
||||
{
|
||||
init();
|
||||
*this = value;
|
||||
}
|
||||
|
||||
String::String(const __FlashStringHelper *pstr)
|
||||
{
|
||||
init();
|
||||
*this = pstr;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String::String(String &&rval)
|
||||
{
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
String::String(StringSumHelper &&rval)
|
||||
{
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
#endif
|
||||
|
||||
String::String(char c)
|
||||
{
|
||||
init();
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned char value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned char)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(int value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(int)];
|
||||
itoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned int value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned int)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(long value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(long)];
|
||||
ltoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned long value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned long)];
|
||||
ultoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(float value, unsigned char decimalPlaces)
|
||||
{
|
||||
static size_t const FLOAT_BUF_SIZE = FLT_MAX_10_EXP + FLT_MAX_DECIMAL_PLACES + 1 /* '-' */ + 1 /* '.' */ + 1 /* '\0' */;
|
||||
init();
|
||||
char buf[FLOAT_BUF_SIZE];
|
||||
decimalPlaces = min(decimalPlaces, FLT_MAX_DECIMAL_PLACES);
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::String(double value, unsigned char decimalPlaces)
|
||||
{
|
||||
static size_t const DOUBLE_BUF_SIZE = DBL_MAX_10_EXP + DBL_MAX_DECIMAL_PLACES + 1 /* '-' */ + 1 /* '.' */ + 1 /* '\0' */;
|
||||
init();
|
||||
char buf[DOUBLE_BUF_SIZE];
|
||||
decimalPlaces = min(decimalPlaces, DBL_MAX_DECIMAL_PLACES);
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
if (buffer) free(buffer);
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Memory Management */
|
||||
/*********************************************/
|
||||
|
||||
inline void String::init(void)
|
||||
{
|
||||
buffer = NULL;
|
||||
capacity = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
void String::invalidate(void)
|
||||
{
|
||||
if (buffer) free(buffer);
|
||||
buffer = NULL;
|
||||
capacity = len = 0;
|
||||
}
|
||||
|
||||
unsigned char String::reserve(unsigned int size)
|
||||
{
|
||||
if (buffer && capacity >= size) return 1;
|
||||
if (changeBuffer(size)) {
|
||||
if (len == 0) buffer[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char String::changeBuffer(unsigned int maxStrLen)
|
||||
{
|
||||
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
|
||||
if (newbuffer) {
|
||||
buffer = newbuffer;
|
||||
capacity = maxStrLen;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Copy and Move */
|
||||
/*********************************************/
|
||||
|
||||
String & String::copy(const char *cstr, unsigned int length)
|
||||
{
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
len = length;
|
||||
memcpy(buffer, cstr, length);
|
||||
buffer[len] = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
|
||||
{
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
len = length;
|
||||
strcpy_P(buffer, (PGM_P)pstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
void String::move(String &rhs)
|
||||
{
|
||||
if (buffer) {
|
||||
if (rhs && capacity >= rhs.len) {
|
||||
memcpy(buffer, rhs.buffer, rhs.len);
|
||||
len = rhs.len;
|
||||
buffer[len] = '\0';
|
||||
rhs.len = 0;
|
||||
return;
|
||||
} else {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
buffer = rhs.buffer;
|
||||
capacity = rhs.capacity;
|
||||
len = rhs.len;
|
||||
rhs.buffer = NULL;
|
||||
rhs.capacity = 0;
|
||||
rhs.len = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator = (const String &rhs)
|
||||
{
|
||||
if (this == &rhs) return *this;
|
||||
|
||||
if (rhs.buffer) copy(rhs.buffer, rhs.len);
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String & String::operator = (String &&rval)
|
||||
{
|
||||
if (this != &rval) move(rval);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator = (StringSumHelper &&rval)
|
||||
{
|
||||
if (this != &rval) move(rval);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator = (const char *cstr)
|
||||
{
|
||||
if (cstr) copy(cstr, strlen(cstr));
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator = (const __FlashStringHelper *pstr)
|
||||
{
|
||||
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* concat */
|
||||
/*********************************************/
|
||||
|
||||
unsigned char String::concat(const String &s)
|
||||
{
|
||||
return concat(s.buffer, s.len);
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr, unsigned int length)
|
||||
{
|
||||
unsigned int newlen = len + length;
|
||||
if (!cstr) return 0;
|
||||
if (length == 0) return 1;
|
||||
if (!reserve(newlen)) return 0;
|
||||
memcpy(buffer + len, cstr, length);
|
||||
len = newlen;
|
||||
buffer[len] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr)
|
||||
{
|
||||
if (!cstr) return 0;
|
||||
return concat(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
unsigned char String::concat(char c)
|
||||
{
|
||||
return concat(&c, 1);
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned char num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned char)];
|
||||
itoa(num, buf, 10);
|
||||
return concat(buf);
|
||||
}
|
||||
|
||||
unsigned char String::concat(int num)
|
||||
{
|
||||
char buf[2 + 3 * sizeof(int)];
|
||||
itoa(num, buf, 10);
|
||||
return concat(buf);
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned int num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned int)];
|
||||
utoa(num, buf, 10);
|
||||
return concat(buf);
|
||||
}
|
||||
|
||||
unsigned char String::concat(long num)
|
||||
{
|
||||
char buf[2 + 3 * sizeof(long)];
|
||||
ltoa(num, buf, 10);
|
||||
return concat(buf);
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned long num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned long)];
|
||||
ultoa(num, buf, 10);
|
||||
return concat(buf);
|
||||
}
|
||||
|
||||
unsigned char String::concat(float num)
|
||||
{
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string);
|
||||
}
|
||||
|
||||
unsigned char String::concat(double num)
|
||||
{
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string);
|
||||
}
|
||||
|
||||
unsigned char String::concat(const __FlashStringHelper * str)
|
||||
{
|
||||
if (!str) return 0;
|
||||
int length = strlen_P((const char *) str);
|
||||
if (length == 0) return 1;
|
||||
unsigned int newlen = len + length;
|
||||
if (!reserve(newlen)) return 0;
|
||||
strcpy_P(buffer + len, (const char *) str);
|
||||
len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Concatenate */
|
||||
/*********************************************/
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!cstr || !a.concat(cstr)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(c)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Comparison */
|
||||
/*********************************************/
|
||||
|
||||
int String::compareTo(const String &s) const
|
||||
{
|
||||
if (!buffer || !s.buffer) {
|
||||
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
|
||||
if (buffer && len > 0) return *(unsigned char *)buffer;
|
||||
return 0;
|
||||
}
|
||||
return strcmp(buffer, s.buffer);
|
||||
}
|
||||
|
||||
int String::compareTo(const char *cstr) const
|
||||
{
|
||||
if (!buffer || !cstr) {
|
||||
if (cstr && *cstr) return 0 - *(unsigned char *)cstr;
|
||||
if (buffer && len > 0) return *(unsigned char *)buffer;
|
||||
return 0;
|
||||
}
|
||||
return strcmp(buffer, cstr);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const String &s2) const
|
||||
{
|
||||
return (len == s2.len && compareTo(s2) == 0);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const char *cstr) const
|
||||
{
|
||||
if (len == 0) return (cstr == NULL || *cstr == 0);
|
||||
if (cstr == NULL) return buffer[0] == 0;
|
||||
return strcmp(buffer, cstr) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::equalsIgnoreCase( const String &s2 ) const
|
||||
{
|
||||
if (this == &s2) return 1;
|
||||
if (len != s2.len) return 0;
|
||||
if (len == 0) return 1;
|
||||
const char *p1 = buffer;
|
||||
const char *p2 = s2.buffer;
|
||||
while (*p1) {
|
||||
if (tolower(*p1++) != tolower(*p2++)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::startsWith( const String &s2 ) const
|
||||
{
|
||||
if (len < s2.len) return 0;
|
||||
return startsWith(s2, 0);
|
||||
}
|
||||
|
||||
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
|
||||
{
|
||||
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
|
||||
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::endsWith( const String &s2 ) const
|
||||
{
|
||||
if ( len < s2.len || !buffer || !s2.buffer) return 0;
|
||||
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Character Access */
|
||||
/*********************************************/
|
||||
|
||||
char String::charAt(unsigned int loc) const
|
||||
{
|
||||
return operator[](loc);
|
||||
}
|
||||
|
||||
void String::setCharAt(unsigned int loc, char c)
|
||||
{
|
||||
if (loc < len) buffer[loc] = c;
|
||||
}
|
||||
|
||||
char & String::operator[](unsigned int index)
|
||||
{
|
||||
static char dummy_writable_char;
|
||||
if (index >= len || !buffer) {
|
||||
dummy_writable_char = 0;
|
||||
return dummy_writable_char;
|
||||
}
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
char String::operator[]( unsigned int index ) const
|
||||
{
|
||||
if (index >= len || !buffer) return 0;
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
|
||||
{
|
||||
if (!bufsize || !buf) return;
|
||||
if (index >= len) {
|
||||
buf[0] = 0;
|
||||
return;
|
||||
}
|
||||
unsigned int n = bufsize - 1;
|
||||
if (n > len - index) n = len - index;
|
||||
strncpy((char *)buf, buffer + index, n);
|
||||
buf[n] = 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Search */
|
||||
/*********************************************/
|
||||
|
||||
int String::indexOf(char c) const
|
||||
{
|
||||
return indexOf(c, 0);
|
||||
}
|
||||
|
||||
int String::indexOf( char ch, unsigned int fromIndex ) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
const char* temp = strchr(buffer + fromIndex, ch);
|
||||
if (temp == NULL) return -1;
|
||||
return temp - buffer;
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2) const
|
||||
{
|
||||
return indexOf(s2, 0);
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2, unsigned int fromIndex) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
const char *found = strstr(buffer + fromIndex, s2.buffer);
|
||||
if (found == NULL) return -1;
|
||||
return found - buffer;
|
||||
}
|
||||
|
||||
int String::lastIndexOf( char theChar ) const
|
||||
{
|
||||
return lastIndexOf(theChar, len - 1);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(char ch, unsigned int fromIndex) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
char tempchar = buffer[fromIndex + 1];
|
||||
buffer[fromIndex + 1] = '\0';
|
||||
char* temp = strrchr( buffer, ch );
|
||||
buffer[fromIndex + 1] = tempchar;
|
||||
if (temp == NULL) return -1;
|
||||
return temp - buffer;
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2) const
|
||||
{
|
||||
return lastIndexOf(s2, len - s2.len);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
|
||||
{
|
||||
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
|
||||
if (fromIndex >= len) fromIndex = len - 1;
|
||||
int found = -1;
|
||||
for (char *p = buffer; p <= buffer + fromIndex; p++) {
|
||||
p = strstr(p, s2.buffer);
|
||||
if (!p) break;
|
||||
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
String String::substring(unsigned int left, unsigned int right) const
|
||||
{
|
||||
if (left > right) {
|
||||
unsigned int temp = right;
|
||||
right = left;
|
||||
left = temp;
|
||||
}
|
||||
String out;
|
||||
if (left >= len) return out;
|
||||
if (right > len) right = len;
|
||||
out.copy(buffer + left, right - left);
|
||||
return out;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Modification */
|
||||
/*********************************************/
|
||||
|
||||
void String::replace(char find, char replace)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
if (*p == find) *p = replace;
|
||||
}
|
||||
}
|
||||
|
||||
void String::replace(const String& find, const String& replace)
|
||||
{
|
||||
if (len == 0 || find.len == 0) return;
|
||||
int diff = replace.len - find.len;
|
||||
char *readFrom = buffer;
|
||||
char *foundAt;
|
||||
if (diff == 0) {
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
memcpy(foundAt, replace.buffer, replace.len);
|
||||
readFrom = foundAt + replace.len;
|
||||
}
|
||||
} else if (diff < 0) {
|
||||
unsigned int size = len; // compute size needed for result
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
readFrom = foundAt + find.len;
|
||||
diff = 0 - diff;
|
||||
size -= diff;
|
||||
}
|
||||
if (size == len) return;
|
||||
int index = len - 1;
|
||||
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||
readFrom = buffer + index + find.len;
|
||||
memmove(readFrom - diff, readFrom, len - (readFrom - buffer));
|
||||
len -= diff;
|
||||
buffer[len] = 0;
|
||||
memcpy(buffer + index, replace.buffer, replace.len);
|
||||
index--;
|
||||
}
|
||||
} else {
|
||||
unsigned int size = len; // compute size needed for result
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
readFrom = foundAt + find.len;
|
||||
size += diff;
|
||||
}
|
||||
if (size == len) return;
|
||||
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
|
||||
int index = len - 1;
|
||||
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||
readFrom = buffer + index + find.len;
|
||||
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
|
||||
len += diff;
|
||||
buffer[len] = 0;
|
||||
memcpy(buffer + index, replace.buffer, replace.len);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index){
|
||||
// Pass the biggest integer as the count. The remove method
|
||||
// below will take care of truncating it at the end of the
|
||||
// string.
|
||||
remove(index, (unsigned int)-1);
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index, unsigned int count){
|
||||
if (index >= len) { return; }
|
||||
if (count <= 0) { return; }
|
||||
if (count > len - index) { count = len - index; }
|
||||
char *writeTo = buffer + index;
|
||||
len = len - count;
|
||||
memmove(writeTo, buffer + index + count,len - index);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
void String::toLowerCase(void)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::toUpperCase(void)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
*p = toupper(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::trim(void)
|
||||
{
|
||||
if (!buffer || len == 0) return;
|
||||
char *begin = buffer;
|
||||
while (isspace(*begin)) begin++;
|
||||
char *end = buffer + len - 1;
|
||||
while (isspace(*end) && end >= begin) end--;
|
||||
len = end + 1 - begin;
|
||||
if (begin > buffer) memmove(buffer, begin, len);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Parsing / Conversion */
|
||||
/*********************************************/
|
||||
|
||||
long String::toInt(void) const
|
||||
{
|
||||
if (buffer) return atol(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float String::toFloat(void) const
|
||||
{
|
||||
return float(toDouble());
|
||||
}
|
||||
|
||||
double String::toDouble(void) const
|
||||
{
|
||||
if (buffer) return atof(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace arduino
|
||||
#include "../../../ArduinoCore-API/api/String.cpp"
|
||||
|
||||
+2
-259
@@ -1,259 +1,2 @@
|
||||
/*
|
||||
String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.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
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifndef __ARDUINO_STRINGS__
|
||||
#define __ARDUINO_STRINGS__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#if defined(__AVR__)
|
||||
#include "avr/pgmspace.h"
|
||||
#else
|
||||
#include "deprecated-avr-comp/avr/pgmspace.h"
|
||||
#endif
|
||||
|
||||
namespace arduino {
|
||||
|
||||
// When compiling programs with this class, the following gcc parameters
|
||||
// dramatically increase performance and memory (RAM) efficiency, typically
|
||||
// with little or no increase in code size.
|
||||
// -felide-constructors
|
||||
// -std=c++0x
|
||||
|
||||
class __FlashStringHelper;
|
||||
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||
|
||||
// An inherited class for holding the result of a concatenation. These
|
||||
// result objects are assumed to be writable by subsequent concatenations.
|
||||
class StringSumHelper;
|
||||
|
||||
// The string class
|
||||
class String
|
||||
{
|
||||
friend class StringSumHelper;
|
||||
// use a function pointer to allow for "if (s)" without the
|
||||
// complications of an operator bool(). for more information, see:
|
||||
// http://www.artima.com/cppsource/safebool.html
|
||||
typedef void (String::*StringIfHelperType)() const;
|
||||
void StringIfHelper() const {}
|
||||
|
||||
static size_t const FLT_MAX_DECIMAL_PLACES = 10;
|
||||
static size_t const DBL_MAX_DECIMAL_PLACES = FLT_MAX_DECIMAL_PLACES;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
// creates a copy of the initial value.
|
||||
// if the initial value is null or invalid, or if memory allocation
|
||||
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||
// be false).
|
||||
String(const char *cstr = "");
|
||||
String(const char *cstr, unsigned int length);
|
||||
String(const uint8_t *cstr, unsigned int length) : String((const char*)cstr, length) {}
|
||||
String(const String &str);
|
||||
String(const __FlashStringHelper *str);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String(String &&rval);
|
||||
String(StringSumHelper &&rval);
|
||||
#endif
|
||||
explicit String(char c);
|
||||
explicit String(unsigned char, unsigned char base=10);
|
||||
explicit String(int, unsigned char base=10);
|
||||
explicit String(unsigned int, unsigned char base=10);
|
||||
explicit String(long, unsigned char base=10);
|
||||
explicit String(unsigned long, unsigned char base=10);
|
||||
explicit String(float, unsigned char decimalPlaces=2);
|
||||
explicit String(double, unsigned char decimalPlaces=2);
|
||||
~String(void);
|
||||
|
||||
// memory management
|
||||
// return true on success, false on failure (in which case, the string
|
||||
// is left unchanged). reserve(0), if successful, will validate an
|
||||
// invalid string (i.e., "if (s)" will be true afterwards)
|
||||
unsigned char reserve(unsigned int size);
|
||||
inline unsigned int length(void) const {return len;}
|
||||
|
||||
// creates a copy of the assigned value. if the value is null or
|
||||
// invalid, or if the memory allocation fails, the string will be
|
||||
// marked as invalid ("if (s)" will be false).
|
||||
String & operator = (const String &rhs);
|
||||
String & operator = (const char *cstr);
|
||||
String & operator = (const __FlashStringHelper *str);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String & operator = (String &&rval);
|
||||
String & operator = (StringSumHelper &&rval);
|
||||
#endif
|
||||
|
||||
// concatenate (works w/ built-in types)
|
||||
|
||||
// returns true on success, false on failure (in which case, the string
|
||||
// is left unchanged). if the argument is null or invalid, the
|
||||
// concatenation is considered unsucessful.
|
||||
unsigned char concat(const String &str);
|
||||
unsigned char concat(const char *cstr);
|
||||
unsigned char concat(const char *cstr, unsigned int length);
|
||||
unsigned char concat(const uint8_t *cstr, unsigned int length) {return concat((const char*)cstr, length);}
|
||||
unsigned char concat(char c);
|
||||
unsigned char concat(unsigned char num);
|
||||
unsigned char concat(int num);
|
||||
unsigned char concat(unsigned int num);
|
||||
unsigned char concat(long num);
|
||||
unsigned char concat(unsigned long num);
|
||||
unsigned char concat(float num);
|
||||
unsigned char concat(double num);
|
||||
unsigned char concat(const __FlashStringHelper * str);
|
||||
|
||||
// if there's not enough memory for the concatenated value, the string
|
||||
// will be left unchanged (but this isn't signalled in any way)
|
||||
String & operator += (const String &rhs) {concat(rhs); return (*this);}
|
||||
String & operator += (const char *cstr) {concat(cstr); return (*this);}
|
||||
String & operator += (char c) {concat(c); return (*this);}
|
||||
String & operator += (unsigned char num) {concat(num); return (*this);}
|
||||
String & operator += (int num) {concat(num); return (*this);}
|
||||
String & operator += (unsigned int num) {concat(num); return (*this);}
|
||||
String & operator += (long num) {concat(num); return (*this);}
|
||||
String & operator += (unsigned long num) {concat(num); return (*this);}
|
||||
String & operator += (float num) {concat(num); return (*this);}
|
||||
String & operator += (double num) {concat(num); return (*this);}
|
||||
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
|
||||
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||
|
||||
// comparison (only works w/ Strings and "strings")
|
||||
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
|
||||
int compareTo(const String &s) const;
|
||||
int compareTo(const char *cstr) const;
|
||||
unsigned char equals(const String &s) const;
|
||||
unsigned char equals(const char *cstr) const;
|
||||
|
||||
friend unsigned char operator == (const String &a, const String &b) { return a.equals(b); }
|
||||
friend unsigned char operator == (const String &a, const char *b) { return a.equals(b); }
|
||||
friend unsigned char operator == (const char *a, const String &b) { return b == a; }
|
||||
friend unsigned char operator < (const String &a, const String &b) { return a.compareTo(b) < 0; }
|
||||
friend unsigned char operator < (const String &a, const char *b) { return a.compareTo(b) < 0; }
|
||||
friend unsigned char operator < (const char *a, const String &b) { return b.compareTo(a) > 0; }
|
||||
|
||||
friend unsigned char operator != (const String &a, const String &b) { return !(a == b); }
|
||||
friend unsigned char operator != (const String &a, const char *b) { return !(a == b); }
|
||||
friend unsigned char operator != (const char *a, const String &b) { return !(a == b); }
|
||||
friend unsigned char operator > (const String &a, const String &b) { return b < a; }
|
||||
friend unsigned char operator > (const String &a, const char *b) { return b < a; }
|
||||
friend unsigned char operator > (const char *a, const String &b) { return b < a; }
|
||||
friend unsigned char operator <= (const String &a, const String &b) { return !(b < a); }
|
||||
friend unsigned char operator <= (const String &a, const char *b) { return !(b < a); }
|
||||
friend unsigned char operator <= (const char *a, const String &b) { return !(b < a); }
|
||||
friend unsigned char operator >= (const String &a, const String &b) { return !(a < b); }
|
||||
friend unsigned char operator >= (const String &a, const char *b) { return !(a < b); }
|
||||
friend unsigned char operator >= (const char *a, const String &b) { return !(a < b); }
|
||||
|
||||
unsigned char equalsIgnoreCase(const String &s) const;
|
||||
unsigned char startsWith( const String &prefix) const;
|
||||
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||
unsigned char endsWith(const String &suffix) const;
|
||||
|
||||
// character acccess
|
||||
char charAt(unsigned int index) const;
|
||||
void setCharAt(unsigned int index, char c);
|
||||
char operator [] (unsigned int index) const;
|
||||
char& operator [] (unsigned int index);
|
||||
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
|
||||
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
|
||||
{ getBytes((unsigned char *)buf, bufsize, index); }
|
||||
const char* c_str() const { return buffer; }
|
||||
char* begin() { return buffer; }
|
||||
char* end() { return buffer + length(); }
|
||||
const char* begin() const { return c_str(); }
|
||||
const char* end() const { return c_str() + length(); }
|
||||
|
||||
// search
|
||||
int indexOf( char ch ) const;
|
||||
int indexOf( char ch, unsigned int fromIndex ) const;
|
||||
int indexOf( const String &str ) const;
|
||||
int indexOf( const String &str, unsigned int fromIndex ) const;
|
||||
int lastIndexOf( char ch ) const;
|
||||
int lastIndexOf( char ch, unsigned int fromIndex ) const;
|
||||
int lastIndexOf( const String &str ) const;
|
||||
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
|
||||
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
|
||||
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
|
||||
|
||||
// modification
|
||||
void replace(char find, char replace);
|
||||
void replace(const String& find, const String& replace);
|
||||
void remove(unsigned int index);
|
||||
void remove(unsigned int index, unsigned int count);
|
||||
void toLowerCase(void);
|
||||
void toUpperCase(void);
|
||||
void trim(void);
|
||||
|
||||
// parsing/conversion
|
||||
long toInt(void) const;
|
||||
float toFloat(void) const;
|
||||
double toDouble(void) const;
|
||||
|
||||
protected:
|
||||
char *buffer; // the actual char array
|
||||
unsigned int capacity; // the array length minus one (for the '\0')
|
||||
unsigned int len; // the String length (not counting the '\0')
|
||||
protected:
|
||||
void init(void);
|
||||
void invalidate(void);
|
||||
unsigned char changeBuffer(unsigned int maxStrLen);
|
||||
|
||||
// copy and move
|
||||
String & copy(const char *cstr, unsigned int length);
|
||||
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
void move(String &rhs);
|
||||
#endif
|
||||
};
|
||||
|
||||
class StringSumHelper : public String
|
||||
{
|
||||
public:
|
||||
StringSumHelper(const String &s) : String(s) {}
|
||||
StringSumHelper(const char *p) : String(p) {}
|
||||
StringSumHelper(char c) : String(c) {}
|
||||
StringSumHelper(unsigned char num) : String(num) {}
|
||||
StringSumHelper(int num) : String(num) {}
|
||||
StringSumHelper(unsigned int num) : String(num) {}
|
||||
StringSumHelper(long num) : String(num) {}
|
||||
StringSumHelper(unsigned long num) : String(num) {}
|
||||
StringSumHelper(float num) : String(num) {}
|
||||
StringSumHelper(double num) : String(num) {}
|
||||
};
|
||||
|
||||
} // namespace arduino
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // __ARDUINO_STRINGS__
|
||||
#pragma once
|
||||
#include "../../../ArduinoCore-API/api/String.h"
|
||||
|
||||
@@ -1,64 +1,2 @@
|
||||
/*
|
||||
USBAPI.h
|
||||
Copyright (c) 2005-2014 Arduino. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef __USBAPI__
|
||||
#define __USBAPI__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace arduino {
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Low level API
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
union {
|
||||
uint8_t bmRequestType;
|
||||
struct {
|
||||
uint8_t direction : 5;
|
||||
uint8_t type : 2;
|
||||
uint8_t transferDirection : 1;
|
||||
};
|
||||
};
|
||||
uint8_t bRequest;
|
||||
uint8_t wValueL;
|
||||
uint8_t wValueH;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} USBSetup;
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// USB APIs (C scope)
|
||||
//================================================================================
|
||||
|
||||
int USB_SendControl(uint8_t flags, const void* d, int len);
|
||||
int USB_RecvControl(void* d, int len);
|
||||
int USB_RecvControlLong(void* d, int len);
|
||||
|
||||
uint8_t USB_Available(uint8_t ep);
|
||||
uint8_t USB_SendSpace(uint8_t ep);
|
||||
int USB_Send(uint8_t ep, const void* data, int len); // blocking
|
||||
int USB_Recv(uint8_t ep, void* data, int len); // non-blocking
|
||||
int USB_Recv(uint8_t ep); // non-blocking
|
||||
void USB_Flush(uint8_t ep);
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#include "../../../ArduinoCore-API/api/USBAPI.h"
|
||||
|
||||
+1
-91
@@ -1,92 +1,2 @@
|
||||
/*
|
||||
* Udp.cpp: Library to send/receive UDP packets.
|
||||
*
|
||||
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
|
||||
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
|
||||
* might not happen often in practice, but in larger network topologies, a UDP
|
||||
* packet can be received out of sequence.
|
||||
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
|
||||
* aware of it. Again, this may not be a concern in practice on small local networks.
|
||||
* For more information, see http://www.cafeaulait.org/course/week12/35.html
|
||||
*
|
||||
* MIT License:
|
||||
* Copyright (c) 2008 Bjoern Hartmann
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* bjoern@cs.stanford.edu 12/30/2008
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
#include "IPAddress.h"
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class UDP : public Stream {
|
||||
|
||||
public:
|
||||
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||
virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure
|
||||
virtual void stop() =0; // Finish with the UDP socket
|
||||
|
||||
// Sending UDP packets
|
||||
|
||||
// Start building up a packet to send to the remote host specific in ip and port
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
virtual int beginPacket(IPAddress ip, uint16_t port) =0;
|
||||
// Start building up a packet to send to the remote host specific in host and port
|
||||
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||
virtual int beginPacket(const char *host, uint16_t port) =0;
|
||||
// Finish off this packet and send it
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
virtual int endPacket() =0;
|
||||
// Write a single byte into the packet
|
||||
virtual size_t write(uint8_t) =0;
|
||||
// Write size bytes from buffer into the packet
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) =0;
|
||||
|
||||
// Start processing the next available incoming packet
|
||||
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||
virtual int parsePacket() =0;
|
||||
// Number of bytes remaining in the current packet
|
||||
virtual int available() =0;
|
||||
// Read a single byte from the current packet
|
||||
virtual int read() =0;
|
||||
// Read up to len bytes from the current packet and place them into buffer
|
||||
// Returns the number of bytes read, or 0 if none are available
|
||||
virtual int read(unsigned char* buffer, size_t len) =0;
|
||||
// Read up to len characters from the current packet and place them into buffer
|
||||
// Returns the number of characters read, or 0 if none are available
|
||||
virtual int read(char* buffer, size_t len) =0;
|
||||
// Return the next byte from the current packet without moving on to the next byte
|
||||
virtual int peek() =0;
|
||||
virtual void flush() =0; // Finish reading the current packet
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
virtual IPAddress remoteIP() =0;
|
||||
// Return the port of the host who sent the current incoming packet
|
||||
virtual uint16_t remotePort() =0;
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using namespace arduino;
|
||||
#include "../../../ArduinoCore-API/api/Udp.h"
|
||||
|
||||
@@ -1,171 +1,2 @@
|
||||
/*
|
||||
WCharacter.h - Character utility functions for Wiring & Arduino
|
||||
Copyright (c) 2010 Hernando Barragan. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef Character_h
|
||||
#define Character_h
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
namespace arduino {
|
||||
|
||||
// WCharacter.h prototypes
|
||||
inline bool isAlphaNumeric(int c) __attribute__((always_inline));
|
||||
inline bool isAlpha(int c) __attribute__((always_inline));
|
||||
inline bool isAscii(int c) __attribute__((always_inline));
|
||||
inline bool isWhitespace(int c) __attribute__((always_inline));
|
||||
inline bool isControl(int c) __attribute__((always_inline));
|
||||
inline bool isDigit(int c) __attribute__((always_inline));
|
||||
inline bool isGraph(int c) __attribute__((always_inline));
|
||||
inline bool isLowerCase(int c) __attribute__((always_inline));
|
||||
inline bool isPrintable(int c) __attribute__((always_inline));
|
||||
inline bool isPunct(int c) __attribute__((always_inline));
|
||||
inline bool isSpace(int c) __attribute__((always_inline));
|
||||
inline bool isUpperCase(int c) __attribute__((always_inline));
|
||||
inline bool isHexadecimalDigit(int c) __attribute__((always_inline));
|
||||
inline int toAscii(int c) __attribute__((always_inline));
|
||||
inline int toLowerCase(int c) __attribute__((always_inline));
|
||||
inline int toUpperCase(int c)__attribute__((always_inline));
|
||||
|
||||
|
||||
// Checks for an alphanumeric character.
|
||||
// It is equivalent to (isalpha(c) || isdigit(c)).
|
||||
inline bool isAlphaNumeric(int c)
|
||||
{
|
||||
return ( isalnum(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for an alphabetic character.
|
||||
// It is equivalent to (isupper(c) || islower(c)).
|
||||
inline bool isAlpha(int c)
|
||||
{
|
||||
return ( isalpha(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks whether c is a 7-bit unsigned char value
|
||||
// that fits into the ASCII character set.
|
||||
inline bool isAscii(int c)
|
||||
{
|
||||
return ( isascii (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a blank character, that is, a space or a tab.
|
||||
inline bool isWhitespace(int c)
|
||||
{
|
||||
return ( isblank (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a control character.
|
||||
inline bool isControl(int c)
|
||||
{
|
||||
return ( iscntrl (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a digit (0 through 9).
|
||||
inline bool isDigit(int c)
|
||||
{
|
||||
return ( isdigit (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character except space.
|
||||
inline bool isGraph(int c)
|
||||
{
|
||||
return ( isgraph (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a lower-case character.
|
||||
inline bool isLowerCase(int c)
|
||||
{
|
||||
return (islower (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character including space.
|
||||
inline bool isPrintable(int c)
|
||||
{
|
||||
return ( isprint (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character which is not a space
|
||||
// or an alphanumeric character.
|
||||
inline bool isPunct(int c)
|
||||
{
|
||||
return ( ispunct (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for white-space characters. For the avr-libc library,
|
||||
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
||||
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
||||
inline bool isSpace(int c)
|
||||
{
|
||||
return ( isspace (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for an uppercase letter.
|
||||
inline bool isUpperCase(int c)
|
||||
{
|
||||
return ( isupper (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
||||
// 8 9 a b c d e f A B C D E F.
|
||||
inline bool isHexadecimalDigit(int c)
|
||||
{
|
||||
return ( isxdigit (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Converts c to a 7-bit unsigned char value that fits into the
|
||||
// ASCII character set, by clearing the high-order bits.
|
||||
inline int toAscii(int c)
|
||||
{
|
||||
return toascii (c);
|
||||
}
|
||||
|
||||
|
||||
// Warning:
|
||||
// Many people will be unhappy if you use this function.
|
||||
// This function will convert accented letters into random
|
||||
// characters.
|
||||
|
||||
// Converts the letter c to lower case, if possible.
|
||||
inline int toLowerCase(int c)
|
||||
{
|
||||
return tolower (c);
|
||||
}
|
||||
|
||||
|
||||
// Converts the letter c to upper case, if possible.
|
||||
inline int toUpperCase(int c)
|
||||
{
|
||||
return toupper (c);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#pragma once
|
||||
#include "../../../ArduinoCore-API/api/WCharacter.h"
|
||||
|
||||
@@ -1,37 +1 @@
|
||||
/*
|
||||
dtostrf - Emulation for dtostrf function from avr-libc
|
||||
Copyright (c) 2016 Arduino LLC. All rights reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
// This is a default implementation for dtostrf function.
|
||||
// This file should be used if the standard lib doesn't provide an
|
||||
// implementation of dtostrf.
|
||||
|
||||
// Create a file called "dtostrf.c" with the following include:
|
||||
// #include "api/deprecated-avr-comp/avr/dtostrf.c.impl"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
|
||||
asm(".global _printf_float");
|
||||
|
||||
char fmt[20];
|
||||
sprintf(fmt, "%%%d.%df", width, prec);
|
||||
sprintf(sout, fmt, val);
|
||||
return sout;
|
||||
}
|
||||
|
||||
#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/dtostrf.c.impl"
|
||||
|
||||
@@ -1,34 +1,2 @@
|
||||
/*
|
||||
dtostrf - Emulation for dtostrf function from avr-libc
|
||||
Copyright (c) 2015 Arduino LLC. All rights reserved.
|
||||
|
||||
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
|
||||
|
||||
#if !defined(ARDUINO_ARCH_AVR)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *dtostrf(double val, signed char width, unsigned char prec, char *sout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/dtostrf.h"
|
||||
|
||||
@@ -1,23 +1,2 @@
|
||||
/*
|
||||
Copyright (c) 2015 Arduino LCC. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
/*
|
||||
Empty file.
|
||||
This file is here to allow compatibility with sketches (made for AVR)
|
||||
that includes <AVR/interrupt.h>
|
||||
*/
|
||||
#pragma once
|
||||
#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/interrupt.h"
|
||||
|
||||
@@ -1,158 +1,2 @@
|
||||
/*
|
||||
pgmspace.h - Definitions for compatibility with AVR pgmspace macros
|
||||
|
||||
Copyright (c) 2015 Arduino LLC
|
||||
|
||||
Based on work of Paul Stoffregen on Teensy 3 (http://pjrc.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE
|
||||
*/
|
||||
|
||||
#ifndef __PGMSPACE_H_
|
||||
#define __PGMSPACE_H_ 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define PROGMEM
|
||||
#define PGM_P const char *
|
||||
#define PSTR(str) (str)
|
||||
|
||||
#define _SFR_BYTE(n) (n)
|
||||
|
||||
typedef void prog_void;
|
||||
typedef char prog_char;
|
||||
typedef unsigned char prog_uchar;
|
||||
typedef int8_t prog_int8_t;
|
||||
typedef uint8_t prog_uint8_t;
|
||||
typedef int16_t prog_int16_t;
|
||||
typedef uint16_t prog_uint16_t;
|
||||
typedef int32_t prog_int32_t;
|
||||
typedef uint32_t prog_uint32_t;
|
||||
typedef int64_t prog_int64_t;
|
||||
typedef uint64_t prog_uint64_t;
|
||||
|
||||
typedef const void* int_farptr_t;
|
||||
typedef const void* uint_farptr_t;
|
||||
|
||||
#define memchr_P(s, c, n) memchr((s), (c), (n))
|
||||
#define memcmp_P(s1, s2, n) memcmp((s1), (s2), (n))
|
||||
#define memccpy_P(dest, src, c, n) memccpy((dest), (src), (c), (n))
|
||||
#define memcpy_P(dest, src, n) memcpy((dest), (src), (n))
|
||||
#define memmem_P(haystack, haystacklen, needle, needlelen) memmem((haystack), (haystacklen), (needle), (needlelen))
|
||||
#define memrchr_P(s, c, n) memrchr((s), (c), (n))
|
||||
#define strcat_P(dest, src) strcat((dest), (src))
|
||||
#define strchr_P(s, c) strchr((s), (c))
|
||||
#define strchrnul_P(s, c) strchrnul((s), (c))
|
||||
#define strcmp_P(a, b) strcmp((a), (b))
|
||||
#define strcpy_P(dest, src) strcpy((dest), (src))
|
||||
#define strcasecmp_P(s1, s2) strcasecmp((s1), (s2))
|
||||
#define strcasestr_P(haystack, needle) strcasestr((haystack), (needle))
|
||||
#define strcspn_P(s, accept) strcspn((s), (accept))
|
||||
#define strlcat_P(s1, s2, n) strlcat((s1), (s2), (n))
|
||||
#define strlcpy_P(s1, s2, n) strlcpy((s1), (s2), (n))
|
||||
#define strlen_P(a) strlen((a))
|
||||
#define strnlen_P(s, n) strnlen((s), (n))
|
||||
#define strncmp_P(s1, s2, n) strncmp((s1), (s2), (n))
|
||||
#define strncasecmp_P(s1, s2, n) strncasecmp((s1), (s2), (n))
|
||||
#define strncat_P(s1, s2, n) strncat((s1), (s2), (n))
|
||||
#define strncpy_P(s1, s2, n) strncpy((s1), (s2), (n))
|
||||
#define strpbrk_P(s, accept) strpbrk((s), (accept))
|
||||
#define strrchr_P(s, c) strrchr((s), (c))
|
||||
#define strsep_P(sp, delim) strsep((sp), (delim))
|
||||
#define strspn_P(s, accept) strspn((s), (accept))
|
||||
#define strstr_P(a, b) strstr((a), (b))
|
||||
#define strtok_P(s, delim) strtok((s), (delim))
|
||||
#define strtok_rP(s, delim, last) strtok((s), (delim), (last))
|
||||
|
||||
#define strlen_PF(a) strlen((a))
|
||||
#define strnlen_PF(src, len) strnlen((src), (len))
|
||||
#define memcpy_PF(dest, src, len) memcpy((dest), (src), (len))
|
||||
#define strcpy_PF(dest, src) strcpy((dest), (src))
|
||||
#define strncpy_PF(dest, src, len) strncpy((dest), (src), (len))
|
||||
#define strcat_PF(dest, src) strcat((dest), (src))
|
||||
#define strlcat_PF(dest, src, len) strlcat((dest), (src), (len))
|
||||
#define strncat_PF(dest, src, len) strncat((dest), (src), (len))
|
||||
#define strcmp_PF(s1, s2) strcmp((s1), (s2))
|
||||
#define strncmp_PF(s1, s2, n) strncmp((s1), (s2), (n))
|
||||
#define strcasecmp_PF(s1, s2) strcasecmp((s1), (s2))
|
||||
#define strncasecmp_PF(s1, s2, n) strncasecmp((s1), (s2), (n))
|
||||
#define strstr_PF(s1, s2) strstr((s1), (s2))
|
||||
#define strlcpy_PF(dest, src, n) strlcpy((dest), (src), (n))
|
||||
#define memcmp_PF(s1, s2, n) memcmp((s1), (s2), (n))
|
||||
|
||||
#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__)
|
||||
#define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__)
|
||||
#define vsprintf_P(s, f, ...) vsprintf((s), (f), __VA_ARGS__)
|
||||
#define vsnprintf_P(s, f, ...) vsnprintf((s), (f), __VA_ARGS__)
|
||||
|
||||
#if 0
|
||||
// Requires natural aligned addresses
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
|
||||
#define pgm_read_float(addr) (*(const float *)(addr))
|
||||
#define pgm_read_ptr(addr) (*(void *const *)(addr))
|
||||
#else
|
||||
// Supports misaligned addresses
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
static inline unsigned char pgm_read_byte(const void *addr) {
|
||||
return *(const unsigned char *)(addr);
|
||||
}
|
||||
static inline unsigned short pgm_read_word(const void *addr) {
|
||||
const unsigned char *a = (const unsigned char *)addr;
|
||||
return pgm_read_byte(a) | ( pgm_read_byte(a + 1) << 8 );
|
||||
}
|
||||
static inline unsigned long pgm_read_dword(const void *addr) {
|
||||
const unsigned char *a = (const unsigned char *)addr;
|
||||
return pgm_read_byte(a) | ( pgm_read_byte(a + 1) << 8 ) | ( pgm_read_byte(a + 2) << 16 ) | ( pgm_read_byte(a + 3) << 24 );
|
||||
}
|
||||
static inline void *pgm_read_ptr(const void *addr) {
|
||||
return (void*) pgm_read_dword(addr);
|
||||
}
|
||||
static inline float pgm_read_float(const void *addr) {
|
||||
union {
|
||||
void *p;
|
||||
float f;
|
||||
} x;
|
||||
x.p = pgm_read_ptr(addr);
|
||||
return x.f;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_near(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_near(addr) pgm_read_float(addr)
|
||||
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
|
||||
|
||||
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_far(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_far(addr) pgm_read_float(addr)
|
||||
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
|
||||
|
||||
#define pgm_get_far_address(addr) (&(addr))
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/pgmspace.h"
|
||||
|
||||
+1
-36
@@ -1,37 +1,2 @@
|
||||
/*
|
||||
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||
|
||||
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
|
||||
|
||||
// Standard C functions required in Arduino API
|
||||
// If these functions are not provided by the standard library, the
|
||||
// core should supply an implementation of them.
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern char* itoa(int value, char *string, int radix);
|
||||
extern char* ltoa(long value, char *string, int radix);
|
||||
extern char* utoa(unsigned value, char *string, int radix);
|
||||
extern char* ultoa(unsigned long value, char *string, int radix);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#include "../../../ArduinoCore-API/api/itoa.h"
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
CYW43 TCP/Ethernet wrappers
|
||||
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
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
|
||||
#include <lwip/netif.h>
|
||||
extern "C" {
|
||||
#include <cyw43.h>
|
||||
#include <cyw43_stats.h>
|
||||
}
|
||||
#include <pico/cyw43_arch.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
// From cyw43_ctrl.c
|
||||
#define WIFI_JOIN_STATE_KIND_MASK (0x000f)
|
||||
#define WIFI_JOIN_STATE_ACTIVE (0x0001)
|
||||
#define WIFI_JOIN_STATE_FAIL (0x0002)
|
||||
#define WIFI_JOIN_STATE_NONET (0x0003)
|
||||
#define WIFI_JOIN_STATE_BADAUTH (0x0004)
|
||||
#define WIFI_JOIN_STATE_AUTH (0x0200)
|
||||
#define WIFI_JOIN_STATE_LINK (0x0400)
|
||||
#define WIFI_JOIN_STATE_KEYED (0x0800)
|
||||
#define WIFI_JOIN_STATE_ALL (0x0e01)
|
||||
|
||||
// The core can't directly call a library, so put in a dummy weak one to be overridden by one in lwip_cyw43 library
|
||||
extern struct netif *__getCYW43Netif() __attribute__((weak));
|
||||
struct netif *__getCYW43Netif() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// CB from the cyw43 driver
|
||||
extern "C" void __wrap_cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
|
||||
(void) cb_data;
|
||||
(void) itf;
|
||||
struct netif *netif = __getCYW43Netif();
|
||||
if (netif && (netif->flags & NETIF_FLAG_LINK_UP)) {
|
||||
struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
if (p != nullptr) {
|
||||
pbuf_take(p, buf, len);
|
||||
if ((netif->input(p, netif) != ERR_OK)) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
CYW43_STAT_INC(PACKET_IN_COUNT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __wrap_cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
|
||||
(void) self;
|
||||
(void) itf;
|
||||
struct netif *netif = __getCYW43Netif();
|
||||
if (netif) {
|
||||
netif_set_link_up(netif);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __wrap_cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
|
||||
(void) self;
|
||||
(void) itf;
|
||||
struct netif *netif = __getCYW43Netif();
|
||||
if (netif) {
|
||||
netif_set_link_down(netif);
|
||||
}
|
||||
self->wifi_join_state &= ~WIFI_JOIN_STATE_ACTIVE;
|
||||
}
|
||||
|
||||
extern "C" int __wrap_cyw43_tcpip_link_status(cyw43_t *self, int itf) {
|
||||
struct netif *netif = __getCYW43Netif();
|
||||
//if ((CYW43::_netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP))
|
||||
// Fake this since it's only used in the SDK
|
||||
if (netif && ((netif->flags & (NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_LINK_UP))) {
|
||||
return CYW43_LINK_UP;
|
||||
} else {
|
||||
return cyw43_wifi_link_status(self, itf);
|
||||
}
|
||||
}
|
||||
|
||||
// CBs from the SDK, not needed here as we do TCP later in the game
|
||||
extern "C" void __wrap_cyw43_cb_tcpip_init(cyw43_t *self, int itf) {
|
||||
(void) self;
|
||||
(void) itf;
|
||||
}
|
||||
extern "C" void __wrap_cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) {
|
||||
(void) self;
|
||||
(void) itf;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,6 +18,8 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(DEBUG_RP2040_PORT)
|
||||
#define DEBUGV(...) do { } while(0)
|
||||
#define DEBUGCORE(...) do { } while(0)
|
||||
@@ -44,3 +46,7 @@
|
||||
#define DEBUGSPI(...) do { } while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern void hexdump(const void* mem, uint32_t len, uint8_t cols = 16);
|
||||
#endif
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
libb64: Base64 Encoding/Decoding Routines
|
||||
======================================
|
||||
|
||||
Authors:
|
||||
-------
|
||||
|
||||
Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
Copyright-Only Dedication (based on United States law)
|
||||
or Public Domain Certification
|
||||
|
||||
The person or persons who have associated work with this document (the
|
||||
"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
|
||||
his knowledge, the work of authorship identified is in the public domain of the
|
||||
country from which the work is published, or (b) hereby dedicates whatever
|
||||
copyright the dedicators holds in the work of authorship identified below (the
|
||||
"Work") to the public domain. A certifier, moreover, dedicates any copyright
|
||||
interest he may have in the associated work, and for these purposes, is
|
||||
described as a "dedicator" below.
|
||||
|
||||
A certifier has taken reasonable steps to verify the copyright status of this
|
||||
work. Certifier recognizes that his good faith efforts may not shield him from
|
||||
liability if in fact the work certified is not in the public domain.
|
||||
|
||||
Dedicator makes this dedication for the benefit of the public at large and to
|
||||
the detriment of the Dedicator's heirs and successors. Dedicator intends this
|
||||
dedication to be an overt act of relinquishment in perpetuity of all present
|
||||
and future rights under copyright law, whether vested or contingent, in the
|
||||
Work. Dedicator understands that such relinquishment of all rights includes
|
||||
the relinquishment of all rights to enforce (by lawsuit or otherwise) those
|
||||
copyrights in the Work.
|
||||
|
||||
Dedicator recognizes that, once placed in the public domain, the Work may be
|
||||
freely reproduced, distributed, transmitted, used, modified, built upon, or
|
||||
otherwise exploited by anyone for any purpose, commercial or non-commercial,
|
||||
and in any way, including by methods that have not yet been invented or
|
||||
conceived.
|
||||
Executable
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
cdecoder.c - c source to a base64 decoding algorithm implementation
|
||||
|
||||
This is part of the libb64 project, and has been placed in the public domain.
|
||||
For details, see http://sourceforge.net/projects/libb64
|
||||
*/
|
||||
|
||||
#include <pgmspace.h>
|
||||
#include <stdint.h>
|
||||
#include "cdecode.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
static int base64_decode_value_signed(int8_t value_in) {
|
||||
static const int8_t decoding[] PROGMEM = {62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
|
||||
static const int8_t decoding_size = sizeof(decoding);
|
||||
value_in -= 43;
|
||||
if (value_in < 0 || value_in > decoding_size) {
|
||||
return -1;
|
||||
}
|
||||
return pgm_read_byte(&decoding[(int)value_in]);
|
||||
}
|
||||
|
||||
void base64_init_decodestate(base64_decodestate* state_in) {
|
||||
state_in->step = step_a;
|
||||
state_in->plainchar = 0;
|
||||
}
|
||||
|
||||
static int base64_decode_block_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out, base64_decodestate* state_in) {
|
||||
const int8_t* codechar = code_in;
|
||||
int8_t* plainchar = plaintext_out;
|
||||
int8_t fragment;
|
||||
|
||||
*plainchar = state_in->plainchar;
|
||||
|
||||
switch (state_in->step) {
|
||||
while (1) {
|
||||
case step_a:
|
||||
do {
|
||||
if (codechar == code_in + length_in) {
|
||||
state_in->step = step_a;
|
||||
state_in->plainchar = *plainchar;
|
||||
return plainchar - plaintext_out;
|
||||
}
|
||||
fragment = (int8_t)base64_decode_value_signed(*codechar++);
|
||||
} while (fragment < 0);
|
||||
*plainchar = (fragment & 0x03f) << 2;
|
||||
// falls through
|
||||
case step_b:
|
||||
do {
|
||||
if (codechar == code_in + length_in) {
|
||||
state_in->step = step_b;
|
||||
state_in->plainchar = *plainchar;
|
||||
return plainchar - plaintext_out;
|
||||
}
|
||||
fragment = (int8_t)base64_decode_value_signed(*codechar++);
|
||||
} while (fragment < 0);
|
||||
*plainchar++ |= (fragment & 0x030) >> 4;
|
||||
*plainchar = (fragment & 0x00f) << 4;
|
||||
// falls through
|
||||
case step_c:
|
||||
do {
|
||||
if (codechar == code_in + length_in) {
|
||||
state_in->step = step_c;
|
||||
state_in->plainchar = *plainchar;
|
||||
return plainchar - plaintext_out;
|
||||
}
|
||||
fragment = (int8_t)base64_decode_value_signed(*codechar++);
|
||||
} while (fragment < 0);
|
||||
*plainchar++ |= (fragment & 0x03c) >> 2;
|
||||
*plainchar = (fragment & 0x003) << 6;
|
||||
// falls through
|
||||
case step_d:
|
||||
do {
|
||||
if (codechar == code_in + length_in) {
|
||||
state_in->step = step_d;
|
||||
state_in->plainchar = *plainchar;
|
||||
return plainchar - plaintext_out;
|
||||
}
|
||||
fragment = (int8_t)base64_decode_value_signed(*codechar++);
|
||||
} while (fragment < 0);
|
||||
*plainchar++ |= (fragment & 0x03f);
|
||||
}
|
||||
}
|
||||
/* control should not reach here */
|
||||
return plainchar - plaintext_out;
|
||||
}
|
||||
|
||||
static int base64_decode_chars_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out) {
|
||||
base64_decodestate _state;
|
||||
base64_init_decodestate(&_state);
|
||||
int len = base64_decode_block_signed(code_in, length_in, plaintext_out, &_state);
|
||||
if (len > 0) {
|
||||
plaintext_out[len] = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int base64_decode_value(char value_in) {
|
||||
return base64_decode_value_signed(*((int8_t *) &value_in));
|
||||
}
|
||||
|
||||
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) {
|
||||
return base64_decode_block_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out, state_in);
|
||||
}
|
||||
|
||||
int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out) {
|
||||
return base64_decode_chars_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out);
|
||||
}
|
||||
|
||||
};
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
cdecode.h - c header for a base64 decoding algorithm
|
||||
|
||||
This is part of the libb64 project, and has been placed in the public domain.
|
||||
For details, see http://sourceforge.net/projects/libb64
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define base64_decode_expected_len(n) ((n * 3) / 4)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
step_a, step_b, step_c, step_d
|
||||
} base64_decodestep;
|
||||
|
||||
typedef struct {
|
||||
base64_decodestep step;
|
||||
char plainchar;
|
||||
} base64_decodestate;
|
||||
|
||||
void base64_init_decodestate(base64_decodestate* state_in);
|
||||
|
||||
int base64_decode_value(char value_in);
|
||||
|
||||
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
|
||||
|
||||
int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
Executable
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
cencoder.c - c source to a base64 encoding algorithm implementation
|
||||
|
||||
This is part of the libb64 project, and has been placed in the public domain.
|
||||
For details, see http://sourceforge.net/projects/libb64
|
||||
*/
|
||||
|
||||
#include "cencode.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void base64_init_encodestate(base64_encodestate* state_in) {
|
||||
state_in->step = step_A;
|
||||
state_in->result = 0;
|
||||
state_in->stepcount = 0;
|
||||
state_in->stepsnewline = BASE64_CHARS_PER_LINE;
|
||||
}
|
||||
|
||||
|
||||
void base64_init_encodestate_nonewlines(base64_encodestate* state_in) {
|
||||
base64_init_encodestate(state_in);
|
||||
state_in->stepsnewline = -1;
|
||||
}
|
||||
|
||||
char base64_encode_value(const char n) {
|
||||
char r;
|
||||
|
||||
if (n < 26) {
|
||||
r = n + 'A';
|
||||
} else if (n < 26 + 26) {
|
||||
r = n - 26 + 'a';
|
||||
} else if (n < 26 + 26 + 10) {
|
||||
r = n - 26 - 26 + '0';
|
||||
} else if (n == 62) {
|
||||
r = '+';
|
||||
} else {
|
||||
r = '/';
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) {
|
||||
const char* plainchar = plaintext_in;
|
||||
const char* const plaintextend = plaintext_in + length_in;
|
||||
char* codechar = code_out;
|
||||
char result;
|
||||
char fragment;
|
||||
|
||||
result = state_in->result;
|
||||
|
||||
switch (state_in->step) {
|
||||
while (1) {
|
||||
case step_A:
|
||||
if (plainchar == plaintextend) {
|
||||
state_in->result = result;
|
||||
state_in->step = step_A;
|
||||
return codechar - code_out;
|
||||
}
|
||||
fragment = *plainchar++;
|
||||
result = (fragment & 0x0fc) >> 2;
|
||||
*codechar++ = base64_encode_value(result);
|
||||
result = (fragment & 0x003) << 4;
|
||||
// falls through
|
||||
case step_B:
|
||||
if (plainchar == plaintextend) {
|
||||
state_in->result = result;
|
||||
state_in->step = step_B;
|
||||
return codechar - code_out;
|
||||
}
|
||||
fragment = *plainchar++;
|
||||
result |= (fragment & 0x0f0) >> 4;
|
||||
*codechar++ = base64_encode_value(result);
|
||||
result = (fragment & 0x00f) << 2;
|
||||
// falls through
|
||||
case step_C:
|
||||
if (plainchar == plaintextend) {
|
||||
state_in->result = result;
|
||||
state_in->step = step_C;
|
||||
return codechar - code_out;
|
||||
}
|
||||
fragment = *plainchar++;
|
||||
result |= (fragment & 0x0c0) >> 6;
|
||||
*codechar++ = base64_encode_value(result);
|
||||
result = (fragment & 0x03f) >> 0;
|
||||
*codechar++ = base64_encode_value(result);
|
||||
|
||||
++(state_in->stepcount);
|
||||
if ((state_in->stepcount == BASE64_CHARS_PER_LINE / 4) && (state_in->stepsnewline > 0)) {
|
||||
*codechar++ = '\n';
|
||||
state_in->stepcount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* control should not reach here */
|
||||
return codechar - code_out;
|
||||
}
|
||||
|
||||
int base64_encode_blockend(char* code_out, base64_encodestate* state_in) {
|
||||
char* codechar = code_out;
|
||||
|
||||
switch (state_in->step) {
|
||||
case step_B:
|
||||
*codechar++ = base64_encode_value(state_in->result);
|
||||
*codechar++ = '=';
|
||||
*codechar++ = '=';
|
||||
break;
|
||||
case step_C:
|
||||
*codechar++ = base64_encode_value(state_in->result);
|
||||
*codechar++ = '=';
|
||||
break;
|
||||
case step_A:
|
||||
break;
|
||||
}
|
||||
*codechar = 0x00;
|
||||
|
||||
return codechar - code_out;
|
||||
}
|
||||
|
||||
int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out) {
|
||||
base64_encodestate _state;
|
||||
base64_init_encodestate(&_state);
|
||||
int len = base64_encode_block(plaintext_in, length_in, code_out, &_state);
|
||||
return len + base64_encode_blockend((code_out + len), &_state);
|
||||
}
|
||||
|
||||
};
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
cencode.h - c header for a base64 encoding algorithm
|
||||
|
||||
This is part of the libb64 project, and has been placed in the public domain.
|
||||
For details, see http://sourceforge.net/projects/libb64
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define BASE64_CHARS_PER_LINE 72
|
||||
|
||||
#define base64_encode_expected_len_nonewlines(n) ((((4 * (n)) / 3) + 3) & ~3)
|
||||
#define base64_encode_expected_len(n) \
|
||||
(base64_encode_expected_len_nonewlines(n) + ((n / ((BASE64_CHARS_PER_LINE * 3) / 4)) + 1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
step_A, step_B, step_C
|
||||
} base64_encodestep;
|
||||
|
||||
typedef struct {
|
||||
base64_encodestep step;
|
||||
char result;
|
||||
int stepcount;
|
||||
int stepsnewline;
|
||||
} base64_encodestate;
|
||||
|
||||
void base64_init_encodestate(base64_encodestate* state_in);
|
||||
void base64_init_encodestate_nonewlines(base64_encodestate* state_in);
|
||||
|
||||
char base64_encode_value(char value_in);
|
||||
|
||||
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
|
||||
|
||||
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
|
||||
|
||||
int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
+119
-8
@@ -25,6 +25,8 @@
|
||||
#include <pico/mutex.h>
|
||||
#include <sys/lock.h>
|
||||
|
||||
#include "_freertos.h"
|
||||
|
||||
// HACK ALERT
|
||||
// Pico-SDK defines mutex which can be at global scope, but when the auto_init_
|
||||
// macros are used they are defined as static. Newlib needs global access to
|
||||
@@ -42,12 +44,87 @@ auto_init_mutex(__lock___dd_hash_mutex);
|
||||
auto_init_mutex(__lock___arc4random_mutex);
|
||||
#undef static
|
||||
|
||||
// FreeRTOS hack - Allow Newlib to use FreeRTOS mutexes which preserve TASKID which
|
||||
// is needed to support multithread
|
||||
|
||||
SemaphoreHandle_t __lock___sinit_recursive_mutex_freertos;
|
||||
SemaphoreHandle_t __lock___sfp_recursive_mutex_freertos;
|
||||
SemaphoreHandle_t __lock___atexit_recursive_mutex_freertos;
|
||||
SemaphoreHandle_t __lock___at_quick_exit_mutex_freertos;
|
||||
SemaphoreHandle_t __lock___malloc_recursive_mutex_freertos;
|
||||
SemaphoreHandle_t __lock___env_recursive_mutex_freertos;
|
||||
SemaphoreHandle_t __lock___tz_mutex_freertos;
|
||||
SemaphoreHandle_t __lock___dd_hash_mutex_freertos;
|
||||
SemaphoreHandle_t __lock___arc4random_mutex_freertos;
|
||||
|
||||
void __initFreeRTOSMutexes() {
|
||||
__lock___sinit_recursive_mutex_freertos = _freertos_recursive_mutex_create();
|
||||
__lock___sfp_recursive_mutex_freertos = _freertos_recursive_mutex_create();
|
||||
__lock___atexit_recursive_mutex_freertos = _freertos_recursive_mutex_create();
|
||||
__lock___at_quick_exit_mutex_freertos = __freertos_mutex_create();
|
||||
__lock___malloc_recursive_mutex_freertos = _freertos_recursive_mutex_create();
|
||||
__lock___env_recursive_mutex_freertos = _freertos_recursive_mutex_create();
|
||||
__lock___tz_mutex_freertos = __freertos_mutex_create();
|
||||
__lock___dd_hash_mutex_freertos = __freertos_mutex_create();
|
||||
__lock___arc4random_mutex_freertos = __freertos_mutex_create();
|
||||
}
|
||||
|
||||
static SemaphoreHandle_t __getFreeRTOSMutex(_LOCK_T lock) {
|
||||
mutex_t *l = (mutex_t *)lock;
|
||||
if (l == &__lock___at_quick_exit_mutex) {
|
||||
return __lock___at_quick_exit_mutex_freertos;
|
||||
} else if (l == &__lock___tz_mutex) {
|
||||
return __lock___tz_mutex_freertos;
|
||||
} else if (l == &__lock___dd_hash_mutex) {
|
||||
return __lock___dd_hash_mutex_freertos;
|
||||
} else if (l == &__lock___arc4random_mutex) {
|
||||
return __lock___arc4random_mutex_freertos;
|
||||
}
|
||||
return __get_freertos_mutex_for_ptr(l, false);
|
||||
}
|
||||
|
||||
static SemaphoreHandle_t __getFreeRTOSRecursiveMutex(_LOCK_T lock) {
|
||||
recursive_mutex_t *l = (recursive_mutex_t *)lock;
|
||||
if (l == &__lock___sinit_recursive_mutex) {
|
||||
return __lock___sinit_recursive_mutex_freertos;
|
||||
} else if (l == &__lock___sfp_recursive_mutex) {
|
||||
return __lock___sfp_recursive_mutex_freertos;
|
||||
} else if (l == &__lock___atexit_recursive_mutex) {
|
||||
return __lock___atexit_recursive_mutex_freertos;
|
||||
} else if (l == &__lock___malloc_recursive_mutex) {
|
||||
return __lock___malloc_recursive_mutex_freertos;
|
||||
} else if (l == &__lock___env_recursive_mutex) {
|
||||
return __lock___env_recursive_mutex_freertos;
|
||||
}
|
||||
return __get_freertos_mutex_for_ptr((mutex_t *)l, true);
|
||||
}
|
||||
|
||||
void __retarget_lock_init(_LOCK_T *lock) {
|
||||
mutex_init((mutex_t*) lock);
|
||||
if (__freeRTOSinitted) {
|
||||
mutex_t *l = (mutex_t *)lock;
|
||||
if ((l == &__lock___at_quick_exit_mutex) || (l == &__lock___tz_mutex) || (l == &__lock___dd_hash_mutex) || (l == &__lock___arc4random_mutex)) {
|
||||
/* Already done in initFreeRTOSMutexes() */
|
||||
} else {
|
||||
// Will init the mutex as well
|
||||
__get_freertos_mutex_for_ptr(l, false);
|
||||
}
|
||||
} else {
|
||||
mutex_init((mutex_t*) lock);
|
||||
}
|
||||
}
|
||||
|
||||
void __retarget_lock_init_recursive(_LOCK_T *lock) {
|
||||
recursive_mutex_init((recursive_mutex_t*) lock);
|
||||
if (__freeRTOSinitted) {
|
||||
recursive_mutex_t *l = (recursive_mutex_t *)lock;
|
||||
if ((l == &__lock___sinit_recursive_mutex) || (l == &__lock___sfp_recursive_mutex) || (l == &__lock___atexit_recursive_mutex) || (l == &__lock___malloc_recursive_mutex) || (l == &__lock___env_recursive_mutex)) {
|
||||
/* Already done in initFreeRTOSMutexes() */
|
||||
} else {
|
||||
// Will init the mutex as well
|
||||
__get_freertos_mutex_for_ptr((mutex_t *)l, true);
|
||||
}
|
||||
} else {
|
||||
recursive_mutex_init((recursive_mutex_t*) lock);
|
||||
}
|
||||
}
|
||||
|
||||
void __retarget_lock_close(_LOCK_T lock) {
|
||||
@@ -59,25 +136,59 @@ void __retarget_lock_close_recursive(_LOCK_T lock) {
|
||||
}
|
||||
|
||||
void __retarget_lock_acquire(_LOCK_T lock) {
|
||||
mutex_enter_blocking((mutex_t*)lock);
|
||||
if (__freeRTOSinitted) {
|
||||
auto mtx = __getFreeRTOSMutex(lock);
|
||||
__freertos_mutex_take(mtx);
|
||||
} else {
|
||||
mutex_enter_blocking((mutex_t*)lock);
|
||||
}
|
||||
}
|
||||
|
||||
void __retarget_lock_acquire_recursive(_LOCK_T lock) {
|
||||
recursive_mutex_enter_blocking((recursive_mutex_t*)lock);
|
||||
if (__freeRTOSinitted) {
|
||||
auto mtx = __getFreeRTOSRecursiveMutex(lock);
|
||||
__freertos_recursive_mutex_take(mtx);
|
||||
} else {
|
||||
recursive_mutex_enter_blocking((recursive_mutex_t*)lock);
|
||||
}
|
||||
}
|
||||
|
||||
int __retarget_lock_try_acquire(_LOCK_T lock) {
|
||||
return mutex_try_enter((mutex_t *)lock, NULL);
|
||||
int ret;
|
||||
if (__freeRTOSinitted) {
|
||||
auto mtx = __getFreeRTOSMutex(lock);
|
||||
ret = __freertos_mutex_try_take(mtx);
|
||||
} else {
|
||||
ret = mutex_try_enter((mutex_t *)lock, nullptr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __retarget_lock_try_acquire_recursive(_LOCK_T lock) {
|
||||
return recursive_mutex_try_enter((recursive_mutex_t*)lock, NULL);
|
||||
int ret;
|
||||
if (__freeRTOSinitted) {
|
||||
auto mtx = __getFreeRTOSRecursiveMutex(lock);
|
||||
ret = __freertos_recursive_mutex_try_take(mtx);
|
||||
} else {
|
||||
ret = recursive_mutex_try_enter((recursive_mutex_t*)lock, nullptr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __retarget_lock_release(_LOCK_T lock) {
|
||||
mutex_exit((mutex_t*)lock);
|
||||
if (__freeRTOSinitted) {
|
||||
auto mtx = __getFreeRTOSMutex(lock);
|
||||
__freertos_mutex_give(mtx);
|
||||
} else {
|
||||
mutex_exit((mutex_t*)lock);
|
||||
}
|
||||
}
|
||||
|
||||
void __retarget_lock_release_recursive(_LOCK_T lock) {
|
||||
recursive_mutex_exit((recursive_mutex_t*)lock);
|
||||
if (__freeRTOSinitted) {
|
||||
auto mtx = __getFreeRTOSRecursiveMutex(lock);
|
||||
__freertos_recursive_mutex_give(mtx);
|
||||
} else {
|
||||
recursive_mutex_exit((recursive_mutex_t*)lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
LWIP wrappers to protect against timer-based re-entrancy
|
||||
|
||||
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 <pico/mutex.h>
|
||||
#include <lwip/pbuf.h>
|
||||
#include <lwip/udp.h>
|
||||
#include <lwip/tcp.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/raw.h>
|
||||
#include <lwip/timeouts.h>
|
||||
#include <pico/cyw43_arch.h>
|
||||
|
||||
class LWIPMutex {
|
||||
public:
|
||||
LWIPMutex() {
|
||||
cyw43_arch_lwip_begin();
|
||||
}
|
||||
|
||||
~LWIPMutex() {
|
||||
cyw43_arch_lwip_end();
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern u8_t __real_pbuf_header(struct pbuf *p, s16_t header_size);
|
||||
u8_t __wrap_pbuf_header(struct pbuf *p, s16_t header_size) {
|
||||
LWIPMutex m;
|
||||
return __real_pbuf_header(p, header_size);
|
||||
}
|
||||
|
||||
extern u8_t __real_pbuf_free(struct pbuf *p);
|
||||
u8_t __wrap_pbuf_free(struct pbuf *p) {
|
||||
LWIPMutex m;
|
||||
return __real_pbuf_free(p);
|
||||
}
|
||||
|
||||
extern struct pbuf *__real_pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type);
|
||||
struct pbuf *__wrap_pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) {
|
||||
LWIPMutex m;
|
||||
return __real_pbuf_alloc(l, length, type);
|
||||
}
|
||||
|
||||
extern err_t __real_pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
|
||||
err_t __wrap_pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) {
|
||||
LWIPMutex m;
|
||||
return __real_pbuf_take(buf, dataptr, len);
|
||||
}
|
||||
|
||||
extern u16_t __real_pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
|
||||
u16_t __wrap_pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset) {
|
||||
LWIPMutex m;
|
||||
return __real_pbuf_copy_partial(p, dataptr, len, offset);
|
||||
}
|
||||
|
||||
extern void __real_pbuf_ref(struct pbuf *p);
|
||||
void __wrap_pbuf_ref(struct pbuf *p) {
|
||||
LWIPMutex m;
|
||||
__real_pbuf_ref(p);
|
||||
}
|
||||
|
||||
extern u8_t __real_pbuf_get_at(const struct pbuf* p, u16_t offset);
|
||||
u8_t __wrap_pbuf_get_at(const struct pbuf* p, u16_t offset) {
|
||||
LWIPMutex m;
|
||||
return __real_pbuf_get_at(p, offset);
|
||||
}
|
||||
|
||||
extern void *__real_pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset);
|
||||
void *__wrap_pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset) {
|
||||
LWIPMutex m;
|
||||
return __real_pbuf_get_contiguous(p, buffer, bufsize, len, offset);
|
||||
}
|
||||
|
||||
extern void __real_pbuf_cat(struct pbuf *head, struct pbuf *tail);
|
||||
void __wrap_pbuf_cat(struct pbuf *head, struct pbuf *tail) {
|
||||
LWIPMutex m;
|
||||
__real_pbuf_cat(head, tail);
|
||||
}
|
||||
|
||||
extern void __real_tcp_arg(struct tcp_pcb *pcb, void *arg);
|
||||
void __wrap_tcp_arg(struct tcp_pcb *pcb, void *arg) {
|
||||
LWIPMutex m;
|
||||
__real_tcp_arg(pcb, arg);
|
||||
}
|
||||
|
||||
extern struct tcp_pcb *__real_tcp_new(void);
|
||||
struct tcp_pcb *__wrap_tcp_new(void) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_new();
|
||||
}
|
||||
|
||||
extern err_t __real_tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
|
||||
err_t __wrap_tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_bind(pcb, ipaddr, port);
|
||||
}
|
||||
|
||||
extern struct tcp_pcb *__real_tcp_listen(struct tcp_pcb *pcb);
|
||||
struct tcp_pcb *__wrap_tcp_listen(struct tcp_pcb *pcb) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_listen(pcb);
|
||||
}
|
||||
|
||||
extern struct tcp_pcb *__real_tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
|
||||
struct tcp_pcb *__wrap_tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_listen_with_backlog(pcb, backlog);
|
||||
}
|
||||
|
||||
extern void __real_tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err));
|
||||
void __wrap_tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) {
|
||||
LWIPMutex m;
|
||||
__real_tcp_accept(pcb, accept);
|
||||
}
|
||||
|
||||
extern err_t __real_tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err));
|
||||
err_t __wrap_tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_connect(pcb, ipaddr, port, connected);
|
||||
}
|
||||
|
||||
extern err_t __real_tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, u8_t apiflags);
|
||||
err_t __wrap_tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, u8_t apiflags) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_write(pcb, dataptr, len, apiflags);
|
||||
}
|
||||
|
||||
extern void __real_tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len));
|
||||
void __wrap_tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)) {
|
||||
LWIPMutex m;
|
||||
__real_tcp_sent(pcb, sent);
|
||||
}
|
||||
|
||||
extern void __real_tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err));
|
||||
void __wrap_tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) {
|
||||
LWIPMutex m;
|
||||
__real_tcp_recv(pcb, recv);
|
||||
}
|
||||
|
||||
extern void __real_tcp_recved(struct tcp_pcb *pcb, u16_t len);
|
||||
void __wrap_tcp_recved(struct tcp_pcb *pcb, u16_t len) {
|
||||
LWIPMutex m;
|
||||
__real_tcp_recved(pcb, len);
|
||||
}
|
||||
|
||||
extern void __real_tcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval);
|
||||
void __wrap_tcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval) {
|
||||
LWIPMutex m;
|
||||
__real_tcp_poll(pcb, poll, interval);
|
||||
}
|
||||
|
||||
extern err_t __real_tcp_close(struct tcp_pcb *pcb);
|
||||
err_t __wrap_tcp_close(struct tcp_pcb *pcb) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_close(pcb);
|
||||
}
|
||||
|
||||
extern void __real_tcp_abort(struct tcp_pcb *pcb);
|
||||
void __wrap_tcp_abort(struct tcp_pcb *pcb) {
|
||||
LWIPMutex m;
|
||||
__real_tcp_abort(pcb);
|
||||
}
|
||||
|
||||
extern void __real_tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, err_t err));
|
||||
void __wrap_tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, err_t err)) {
|
||||
LWIPMutex m;
|
||||
__real_tcp_err(pcb, err);
|
||||
}
|
||||
|
||||
extern err_t __real_tcp_output(struct tcp_pcb *pcb);
|
||||
err_t __wrap_tcp_output(struct tcp_pcb *pcb) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_output(pcb);
|
||||
}
|
||||
|
||||
extern void __real_tcp_setprio(struct tcp_pcb *pcb, u8_t prio);
|
||||
void __wrap_tcp_setprio(struct tcp_pcb *pcb, u8_t prio) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_setprio(pcb, prio);
|
||||
}
|
||||
|
||||
extern void __real_tcp_backlog_delayed(struct tcp_pcb* pcb);
|
||||
void __wrap_tcp_backlog_delayed(struct tcp_pcb* pcb) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_backlog_delayed(pcb);
|
||||
}
|
||||
|
||||
extern void __real_tcp_backlog_accepted(struct tcp_pcb* pcb);
|
||||
void __wrap_tcp_backlog_accepted(struct tcp_pcb* pcb) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_backlog_accepted(pcb);
|
||||
}
|
||||
extern struct udp_pcb *__real_udp_new(void);
|
||||
struct udp_pcb *__wrap_udp_new(void) {
|
||||
LWIPMutex m;
|
||||
return __real_udp_new();
|
||||
}
|
||||
|
||||
extern void __real_udp_remove(struct udp_pcb *pcb);
|
||||
void __wrap_udp_remove(struct udp_pcb *pcb) {
|
||||
LWIPMutex m;
|
||||
__real_udp_remove(pcb);
|
||||
}
|
||||
|
||||
extern err_t __real_udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
|
||||
err_t __wrap_udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) {
|
||||
LWIPMutex m;
|
||||
return __real_udp_bind(pcb, ipaddr, port);
|
||||
}
|
||||
|
||||
extern err_t __real_udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
|
||||
err_t __wrap_udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) {
|
||||
LWIPMutex m;
|
||||
return __real_udp_connect(pcb, ipaddr, port);
|
||||
}
|
||||
|
||||
extern err_t __real_udp_disconnect(struct udp_pcb *pcb);
|
||||
err_t __wrap_udp_disconnect(struct udp_pcb *pcb) {
|
||||
LWIPMutex m;
|
||||
return __real_udp_disconnect(pcb);
|
||||
}
|
||||
|
||||
extern err_t __real_udp_send(struct udp_pcb *pcb, struct pbuf *p);
|
||||
err_t __wrap_udp_send(struct udp_pcb *pcb, struct pbuf *p) {
|
||||
LWIPMutex m;
|
||||
return __real_udp_send(pcb, p);
|
||||
}
|
||||
|
||||
extern void __real_udp_recv(struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port), void *recv_arg);
|
||||
void __wrap_udp_recv(struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port), void *recv_arg) {
|
||||
LWIPMutex m;
|
||||
__real_udp_recv(pcb, recv, recv_arg);
|
||||
}
|
||||
|
||||
extern err_t __real_udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif);
|
||||
err_t __wrap_udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) {
|
||||
LWIPMutex m;
|
||||
return __real_udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
|
||||
}
|
||||
|
||||
// sys_check_timeouts is special case because the async process will call it. If we're already in a timeout check, just do a noop
|
||||
extern void __real_sys_check_timeouts();
|
||||
void __wrap_sys_check_timeouts(void) {
|
||||
LWIPMutex m;
|
||||
__real_sys_check_timeouts();
|
||||
}
|
||||
|
||||
extern err_t __real_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg);
|
||||
err_t __wrap_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg) {
|
||||
LWIPMutex m;
|
||||
return __real_dns_gethostbyname(hostname, addr, found, callback_arg);
|
||||
}
|
||||
|
||||
extern err_t __real_dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg, u8_t dns_addrtype);
|
||||
err_t __wrap_dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg, u8_t dns_addrtype) {
|
||||
LWIPMutex m;
|
||||
return __real_dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, dns_addrtype);
|
||||
}
|
||||
|
||||
extern struct raw_pcb *__real_raw_new(u8_t proto);
|
||||
struct raw_pcb *__wrap_raw_new(u8_t proto) {
|
||||
LWIPMutex m;
|
||||
return __real_raw_new(proto);
|
||||
}
|
||||
|
||||
extern void __real_raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg);
|
||||
void __wrap_raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) {
|
||||
LWIPMutex m;
|
||||
__real_raw_recv(pcb, recv, recv_arg);
|
||||
}
|
||||
|
||||
extern err_t __real_raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr);
|
||||
err_t __wrap_raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) {
|
||||
LWIPMutex m;
|
||||
return __real_raw_bind(pcb, ipaddr);
|
||||
}
|
||||
|
||||
extern err_t __real_raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr);
|
||||
err_t __wrap_raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) {
|
||||
LWIPMutex m;
|
||||
return __real_raw_sendto(pcb, p, ipaddr);
|
||||
}
|
||||
|
||||
extern void __real_raw_remove(struct raw_pcb *pcb);
|
||||
void __wrap_raw_remove(struct raw_pcb *pcb) {
|
||||
LWIPMutex m;
|
||||
__real_raw_remove(pcb);
|
||||
}
|
||||
|
||||
}; // extern "C"
|
||||
+34
-9
@@ -29,8 +29,6 @@ extern "C" {
|
||||
volatile bool __otherCoreIdled = false;
|
||||
};
|
||||
|
||||
mutex_t _pioMutex;
|
||||
|
||||
extern void setup();
|
||||
extern void loop();
|
||||
|
||||
@@ -38,6 +36,8 @@ extern void loop();
|
||||
extern void initFreeRTOS() __attribute__((weak));
|
||||
extern void startFreeRTOS() __attribute__((weak));
|
||||
bool __isFreeRTOS;
|
||||
volatile bool __freeRTOSinitted;
|
||||
|
||||
|
||||
// Weak empty variant initialization. May be redefined by variant files.
|
||||
void initVariant() __attribute__((weak));
|
||||
@@ -89,8 +89,6 @@ extern "C" int main() {
|
||||
_REENT_INIT_PTR(_impure_ptr1);
|
||||
}
|
||||
|
||||
mutex_init(&_pioMutex);
|
||||
|
||||
rp2040.begin();
|
||||
|
||||
initVariant();
|
||||
@@ -122,19 +120,20 @@ extern "C" int main() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_USB
|
||||
if (!__isFreeRTOS) {
|
||||
if (setup1 || loop1) {
|
||||
rp2040.fifo.begin(2);
|
||||
multicore_launch_core1(main1);
|
||||
} else {
|
||||
rp2040.fifo.begin(1);
|
||||
}
|
||||
rp2040.fifo.registerCore();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!__isFreeRTOS) {
|
||||
if (setup1 || loop1) {
|
||||
delay(1); // Needed to make Picoprobe upload start 2nd core
|
||||
multicore_launch_core1(main1);
|
||||
}
|
||||
setup();
|
||||
while (true) {
|
||||
loop();
|
||||
@@ -159,8 +158,7 @@ extern "C" void __register_impure_ptr(struct _reent *p) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: FreeRTOS should implement this based on thread ID (and each thread should have its own struct _reent
|
||||
extern "C" struct _reent *__wrap___getreent() __attribute__((weak));
|
||||
extern "C" struct _reent *__wrap___getreent() {
|
||||
if (get_core_num() == 0) {
|
||||
return _impure_ptr;
|
||||
@@ -168,3 +166,30 @@ extern "C" struct _reent *__wrap___getreent() {
|
||||
return _impure_ptr1;
|
||||
}
|
||||
}
|
||||
|
||||
// ESP8266 internal debug routine
|
||||
extern void hexdump(const void* mem, uint32_t len, uint8_t cols) __attribute__((weak));
|
||||
void hexdump(const void* mem, uint32_t len, uint8_t cols) {
|
||||
const char* src = (const char*)mem;
|
||||
printf("\n[HEXDUMP] Address: %p len: 0x%lX (%ld)", src, len, len);
|
||||
while (len > 0) {
|
||||
uint32_t linesize = cols > len ? len : cols;
|
||||
printf("\n[%p] 0x%04x: ", src, (int)(src - (const char*)mem));
|
||||
for (uint32_t i = 0; i < linesize; i++) {
|
||||
printf("%02x ", *(src + i));
|
||||
}
|
||||
printf(" ");
|
||||
for (uint32_t i = linesize; i < cols; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
for (uint32_t i = 0; i < linesize; i++) {
|
||||
unsigned char c = *(src + i);
|
||||
putc(isprint(c) ? c : '.', stdout);
|
||||
}
|
||||
src += linesize;
|
||||
len -= linesize;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
const String emptyString = "";
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Malloc/etc. interrupt locking wrappers
|
||||
|
||||
Copyright (c) 2022 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>
|
||||
|
||||
extern "C" void *__real_malloc(size_t size);
|
||||
extern "C" void *__real_calloc(size_t count, size_t size);
|
||||
extern "C" void *__real_realloc(void *mem, size_t size);
|
||||
extern "C" void __real_free(void *mem);
|
||||
|
||||
extern "C" void *__wrap_malloc(size_t size) {
|
||||
noInterrupts();
|
||||
void *rc = __real_malloc(size);
|
||||
interrupts();
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern "C" void *__wrap_calloc(size_t count, size_t size) {
|
||||
noInterrupts();
|
||||
void *rc = __real_calloc(count, size);
|
||||
interrupts();
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern "C" void *__wrap_realloc(void *mem, size_t size) {
|
||||
noInterrupts();
|
||||
void *rc = __real_realloc(mem, size);
|
||||
interrupts();
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern "C" void __wrap_free(void *mem) {
|
||||
noInterrupts();
|
||||
__real_free(mem);
|
||||
interrupts();
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
+10
-3
@@ -90,8 +90,8 @@ extern "C" int _gettimeofday(struct timeval *tv, void *tz) {
|
||||
(void) tz;
|
||||
uint64_t now_us = to_us_since_boot(get_absolute_time()) + __timedelta_us;
|
||||
if (tv) {
|
||||
tv->tv_sec = now_us / 1000000L;
|
||||
tv->tv_usec = now_us % 1000000L;
|
||||
tv->tv_sec = now_us / 1'000'000L;
|
||||
tv->tv_usec = now_us % 1'000'000L;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -101,13 +101,20 @@ extern "C" int settimeofday(const struct timeval *tv, const struct timezone *tz)
|
||||
uint64_t now_us = to_us_since_boot(get_absolute_time());
|
||||
if (tv) {
|
||||
uint64_t newnow_us;
|
||||
newnow_us = tv->tv_sec * 1000000L;
|
||||
newnow_us = tv->tv_sec * 1'000'000L;
|
||||
newnow_us += tv->tv_usec;
|
||||
__timedelta_us = newnow_us - now_us;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For NTP
|
||||
extern "C" void __setSystemTime(unsigned long long sec, unsigned long usec) {
|
||||
uint64_t now_us = to_us_since_boot(get_absolute_time());
|
||||
uint64_t newnow_us = sec * 1'000'000LL + usec;
|
||||
__timedelta_us = newnow_us - now_us;
|
||||
}
|
||||
|
||||
extern "C" int _isatty(int file) {
|
||||
(void) file;
|
||||
errno = ENOSYS;
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
#include <btstack.h>
|
||||
#include <pico/btstack_flash_bank.h>
|
||||
#include <hardware/flash.h>
|
||||
#include <hardware/sync.h>
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
const uint8_t __bluetooth_tlv[8192] __attribute__((aligned(4096))) = { 0 };
|
||||
extern const uint8_t __flash_binary_start;
|
||||
|
||||
#undef PICO_FLASH_BANK_TOTAL_SIZE
|
||||
#undef PICO_FLASH_BANK_STORAGE_OFFSET
|
||||
#define PICO_FLASH_BANK_TOTAL_SIZE sizeof(__bluetooth_tlv)
|
||||
#define PICO_FLASH_BANK_STORAGE_OFFSET ((unsigned int)(__bluetooth_tlv - &__flash_binary_start))
|
||||
|
||||
#if 0
|
||||
// Check sizes
|
||||
static_assert(PICO_FLASH_BANK_TOTAL_SIZE % (FLASH_SECTOR_SIZE * 2) == 0, "PICO_FLASH_BANK_TOTAL_SIZE invalid");
|
||||
static_assert(PICO_FLASH_BANK_TOTAL_SIZE <= PICO_FLASH_SIZE_BYTES, "PICO_FLASH_BANK_TOTAL_SIZE too big");
|
||||
static_assert(PICO_FLASH_BANK_STORAGE_OFFSET + PICO_FLASH_BANK_TOTAL_SIZE <= PICO_FLASH_SIZE_BYTES, "PICO_FLASH_BANK_TOTAL_SIZE too big");
|
||||
#endif
|
||||
|
||||
// Size of one bank
|
||||
#define PICO_FLASH_BANK_SIZE (PICO_FLASH_BANK_TOTAL_SIZE / 2)
|
||||
|
||||
#if 0
|
||||
#define DEBUG_PRINT(format,args...) printf(format, ## args)
|
||||
#else
|
||||
#define DEBUG_PRINT(...)
|
||||
#endif
|
||||
|
||||
static uint32_t pico_flash_bank_get_size(void * context) {
|
||||
(void)(context);
|
||||
return PICO_FLASH_BANK_SIZE;
|
||||
}
|
||||
|
||||
static uint32_t pico_flash_bank_get_alignment(void * context) {
|
||||
(void)(context);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pico_flash_bank_erase(void * context, int bank) {
|
||||
(void)(context);
|
||||
DEBUG_PRINT("erase: bank %d\n", bank);
|
||||
noInterrupts();
|
||||
rp2040.idleOtherCore();
|
||||
flash_range_erase(PICO_FLASH_BANK_STORAGE_OFFSET + (PICO_FLASH_BANK_SIZE * bank), PICO_FLASH_BANK_SIZE);
|
||||
rp2040.resumeOtherCore();
|
||||
interrupts();
|
||||
}
|
||||
|
||||
static void pico_flash_bank_read(void *context, int bank, uint32_t offset, uint8_t *buffer, uint32_t size) {
|
||||
(void)(context);
|
||||
DEBUG_PRINT("read: bank %d offset %u size %u\n", bank, offset, size);
|
||||
|
||||
assert(bank <= 1);
|
||||
if (bank > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(offset < PICO_FLASH_BANK_SIZE);
|
||||
if (offset >= PICO_FLASH_BANK_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert((offset + size) <= PICO_FLASH_BANK_SIZE);
|
||||
if ((offset + size) > PICO_FLASH_BANK_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Flash is xip
|
||||
memcpy(buffer, (void *)(XIP_BASE + PICO_FLASH_BANK_STORAGE_OFFSET + (PICO_FLASH_BANK_SIZE * bank) + offset), size);
|
||||
}
|
||||
|
||||
static void pico_flash_bank_write(void * context, int bank, uint32_t offset, const uint8_t *data, uint32_t size) {
|
||||
(void)(context);
|
||||
DEBUG_PRINT("write: bank %d offset %u size %u\n", bank, offset, size);
|
||||
|
||||
assert(bank <= 1);
|
||||
if (bank > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(offset < PICO_FLASH_BANK_SIZE);
|
||||
if (offset >= PICO_FLASH_BANK_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert((offset + size) <= PICO_FLASH_BANK_SIZE);
|
||||
if ((offset + size) > PICO_FLASH_BANK_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calc bank start position
|
||||
const uint32_t bank_start_pos = PICO_FLASH_BANK_STORAGE_OFFSET + (PICO_FLASH_BANK_SIZE * bank);
|
||||
|
||||
// Calculate first and last page in the bank
|
||||
const uint32_t first_page = offset / FLASH_PAGE_SIZE;
|
||||
const uint32_t last_page = (offset + size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE;
|
||||
|
||||
// Now we only care about the offset in the first page
|
||||
offset %= FLASH_PAGE_SIZE;
|
||||
|
||||
// Amount of data we've copied
|
||||
uint32_t data_pos = 0;
|
||||
uint32_t size_left = size;
|
||||
|
||||
// Write all the pages required
|
||||
for (uint32_t page = first_page; page < last_page; page++) {
|
||||
uint8_t page_data[FLASH_PAGE_SIZE];
|
||||
|
||||
assert(data_pos < size && size_left <= size);
|
||||
|
||||
// Copy data we're not going to overwrite in the first page
|
||||
if (page == first_page && offset > 0) {
|
||||
memcpy(page_data,
|
||||
(void *)(XIP_BASE + bank_start_pos + (page * FLASH_PAGE_SIZE)),
|
||||
offset);
|
||||
}
|
||||
|
||||
// Copy the data we're not going to overwrite in the last page
|
||||
if (page == last_page - 1 && (offset + size_left) < FLASH_PAGE_SIZE) {
|
||||
memcpy(page_data + offset + size_left,
|
||||
(void *)(XIP_BASE + bank_start_pos + (page * FLASH_PAGE_SIZE) + offset + size_left),
|
||||
FLASH_PAGE_SIZE - offset - size_left);
|
||||
}
|
||||
|
||||
// Now copy the new data into the page
|
||||
const uint32_t size_to_copy = MIN(size_left, FLASH_PAGE_SIZE - offset);
|
||||
memcpy(page_data + offset, data + data_pos, size_to_copy);
|
||||
|
||||
data_pos += size_to_copy;
|
||||
size_left -= size_to_copy;
|
||||
|
||||
// zero offset for the following pages
|
||||
offset = 0;
|
||||
|
||||
// Now program the entire page
|
||||
noInterrupts();
|
||||
rp2040.idleOtherCore();
|
||||
flash_range_program(bank_start_pos + (page * FLASH_PAGE_SIZE), page_data, FLASH_PAGE_SIZE);
|
||||
rp2040.resumeOtherCore();
|
||||
interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
static const hal_flash_bank_t pico_flash_bank_instance_obj = {
|
||||
/* uint32_t (*get_size)(..) */ &pico_flash_bank_get_size,
|
||||
/* uint32_t (*get_alignment)(..); */ &pico_flash_bank_get_alignment,
|
||||
/* void (*erase)(..); */ &pico_flash_bank_erase,
|
||||
/* void (*read)(..); */ &pico_flash_bank_read,
|
||||
/* void (*write)(..); */ &pico_flash_bank_write,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
const hal_flash_bank_t *pico_flash_bank_instance(void) {
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Check we're not overlapping the binary in flash
|
||||
//extern char __flash_binary_end;
|
||||
// assert((uintptr_t)&__flash_binary_end - XIP_BASE <= PICO_FLASH_BANK_STORAGE_OFFSET);
|
||||
#endif
|
||||
|
||||
return &pico_flash_bank_instance_obj;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
||||
|
||||
Hacked by EFP3 to allow disabling unless requested
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#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
|
||||
#define PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS 350
|
||||
#endif
|
||||
|
||||
// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via reset double tap, type=int, min=0, max=29, group=pico_bootsel_via_double_reset
|
||||
|
||||
// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK, Optionally disable either the mass storage interface (bit 0) or the PICOBOOT interface (bit 1) when entering BOOTSEL mode via double reset, type=int, min=0, max=3, default=0, group=pico_bootsel_via_double_reset
|
||||
#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK
|
||||
#define PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK 0u
|
||||
#endif
|
||||
|
||||
/** \defgroup pico_bootsel_via_double_reset pico_bootsel_via_double_reset
|
||||
|
||||
When the 'pico_bootsel_via_double_reset' library is linked, a function is
|
||||
injected before main() which will detect when the system has been reset
|
||||
twice in quick succession, and enter the USB ROM bootloader (BOOTSEL mode)
|
||||
when this happens. This allows a double tap of a reset button on a
|
||||
development board to be used to enter the ROM bootloader, provided this
|
||||
library is always linked.
|
||||
*/
|
||||
|
||||
#if !PICO_NO_BI_BOOTSEL_VIA_DOUBLE_RESET
|
||||
bi_decl(bi_program_feature("double reset -> BOOTSEL"));
|
||||
#endif
|
||||
|
||||
// Doesn't make any sense for a RAM only binary
|
||||
#if !PICO_NO_FLASH
|
||||
static const uint32_t magic_token[] = {
|
||||
0xf01681de, 0xbd729b29, 0xd359be7a,
|
||||
};
|
||||
|
||||
// Place our marker on the 2nd core's stack...which will not have been touched when this code is executing
|
||||
static uint32_t *magic_location = (uint32_t*)0x20040000;
|
||||
//static uint32_t __uninitialized_ram(magic_location)[count_of(magic_token)];
|
||||
|
||||
/* Check for double reset and enter BOOTSEL mode if detected
|
||||
|
||||
This function is registered to run automatically before main(). The
|
||||
algorithm is:
|
||||
|
||||
1. Check for magic token in memory; enter BOOTSEL mode if found.
|
||||
2. Initialise that memory with that magic token.
|
||||
3. Do nothing for a short while (few hundred ms).
|
||||
4. Clear the magic token.
|
||||
5. Continue with normal boot.
|
||||
|
||||
Resetting the device twice quickly will interrupt step 3, leaving the token
|
||||
in place so that the second boot will go to the bootloader.
|
||||
*/
|
||||
|
||||
/*static*/ void __attribute__((constructor)) boot_double_tap_check(void) {
|
||||
for (uint i = 0; i < count_of(magic_token); i++) {
|
||||
if (magic_location[i] != magic_token[i]) {
|
||||
// Arm, wait, then disarm and continue booting
|
||||
for (i = 0; i < count_of(magic_token); i++) {
|
||||
magic_location[i] = magic_token[i];
|
||||
}
|
||||
busy_wait_us(PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS * 1000);
|
||||
magic_location[0] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Detected a double reset, so enter USB bootloader
|
||||
magic_location[0] = 0;
|
||||
#ifdef PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED
|
||||
const uint32_t led_mask = 1u << PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED;
|
||||
#else
|
||||
const uint32_t led_mask = 0u;
|
||||
#endif
|
||||
reset_usb_boot(
|
||||
led_mask,
|
||||
PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Expost absolute mouse HID descriptor and report
|
||||
Taken from @tobozo PR https://github.com/hathach/tinyusb/pull/1363
|
||||
TODO - remove once that PR merged with TinyUSB
|
||||
|
||||
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 "tusb.h"
|
||||
#include "class/hid/hid_device.h"
|
||||
|
||||
// Absolute Mouse: same as the Standard (relative) Mouse Report but
|
||||
// with int16_t instead of int8_t for X and Y coordinates.
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
|
||||
int16_t x; /**< Current x position of the mouse. */
|
||||
int16_t y; /**< Current y position of the mouse. */
|
||||
int8_t wheel; /**< Current delta wheel movement on the mouse. */
|
||||
int8_t pan; // using AC Pan
|
||||
} hid_abs_mouse_report_t;
|
||||
|
||||
|
||||
// Absolute Mouse Report Descriptor Template
|
||||
#define TUD_HID_REPORT_DESC_ABSMOUSE(...) \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\
|
||||
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
|
||||
/* Report ID if any */\
|
||||
__VA_ARGS__ \
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\
|
||||
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
|
||||
HID_USAGE_MIN ( 1 ) ,\
|
||||
HID_USAGE_MAX ( 5 ) ,\
|
||||
HID_LOGICAL_MIN ( 0 ) ,\
|
||||
HID_LOGICAL_MAX ( 1 ) ,\
|
||||
/* Left, Right, Middle, Backward, Forward buttons */ \
|
||||
HID_REPORT_COUNT( 5 ) ,\
|
||||
HID_REPORT_SIZE ( 1 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* 3 bit padding */ \
|
||||
HID_REPORT_COUNT( 1 ) ,\
|
||||
HID_REPORT_SIZE ( 3 ) ,\
|
||||
HID_INPUT ( HID_CONSTANT ) ,\
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
/* X, Y absolute position [0, 32767] */ \
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
|
||||
HID_LOGICAL_MIN ( 0x00 ) ,\
|
||||
HID_LOGICAL_MAX_N( 0x7FFF, 2 ) ,\
|
||||
HID_REPORT_SIZE ( 16 ) ,\
|
||||
HID_REPORT_COUNT ( 2 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* Vertical wheel scroll [-127, 127] */ \
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\
|
||||
HID_LOGICAL_MIN ( 0x81 ) ,\
|
||||
HID_LOGICAL_MAX ( 0x7f ) ,\
|
||||
HID_REPORT_COUNT( 1 ) ,\
|
||||
HID_REPORT_SIZE ( 8 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \
|
||||
/* Horizontal wheel scroll [-127, 127] */ \
|
||||
HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \
|
||||
HID_LOGICAL_MIN ( 0x81 ), \
|
||||
HID_LOGICAL_MAX ( 0x7f ), \
|
||||
HID_REPORT_COUNT( 1 ), \
|
||||
HID_REPORT_SIZE ( 8 ), \
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \
|
||||
HID_COLLECTION_END , \
|
||||
HID_COLLECTION_END \
|
||||
|
||||
|
||||
static inline bool tud_hid_abs_mouse_report(uint8_t report_id,
|
||||
uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
|
||||
hid_abs_mouse_report_t report = {
|
||||
.buttons = buttons,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.wheel = vertical,
|
||||
.pan = horizontal
|
||||
};
|
||||
|
||||
return tud_hid_n_report(0, report_id, &report, sizeof(report));
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef STDLIB_NONISO_H
|
||||
#define STDLIB_NONISO_H
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -54,6 +53,3 @@ const char* strrstr(const char*__restrict p_pcString,
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,9 +26,12 @@
|
||||
#include <hardware/pll.h>
|
||||
#include <hardware/adc.h>
|
||||
|
||||
void __clearADCPin(pin_size_t p);
|
||||
|
||||
static uint32_t analogScale = 255;
|
||||
static uint32_t analogFreq = 1000;
|
||||
static bool pwmInitted = false;
|
||||
static uint32_t pwmInitted = 0;
|
||||
static bool scaleInitted = false;
|
||||
static bool adcInitted = false;
|
||||
static uint16_t analogWritePseudoScale = 1;
|
||||
static uint16_t analogWriteSlowScale = 1;
|
||||
@@ -40,31 +43,33 @@ extern "C" void analogWriteFreq(uint32_t freq) {
|
||||
return;
|
||||
}
|
||||
if (freq < 100) {
|
||||
DEBUGCORE("ERROR: analogWriteFreq too low (%d)\n", freq);
|
||||
DEBUGCORE("ERROR: analogWriteFreq too low (%lu)\n", freq);
|
||||
analogFreq = 100;
|
||||
} else if (freq > 1000000) {
|
||||
DEBUGCORE("ERROR: analogWriteFreq too high (%d)\n", freq);
|
||||
analogFreq = 1000000;
|
||||
} else if (freq > 10'000'000) {
|
||||
DEBUGCORE("ERROR: analogWriteFreq too high (%lu)\n", freq);
|
||||
analogFreq = 10'000'000;
|
||||
} else {
|
||||
analogFreq = freq;
|
||||
}
|
||||
pwmInitted = false;
|
||||
pwmInitted = 0;
|
||||
scaleInitted = false;
|
||||
}
|
||||
|
||||
extern "C" void analogWriteRange(uint32_t range) {
|
||||
if (range == analogScale) {
|
||||
return;
|
||||
}
|
||||
if ((range >= 15) && (range <= 65535)) {
|
||||
if ((range >= 3) && (range <= 65535)) {
|
||||
analogScale = range;
|
||||
pwmInitted = false;
|
||||
pwmInitted = 0;
|
||||
scaleInitted = false;
|
||||
} else {
|
||||
DEBUGCORE("ERROR: analogWriteRange out of range (%d)\n", range);
|
||||
DEBUGCORE("ERROR: analogWriteRange out of range (%lu)\n", range);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void analogWriteResolution(int res) {
|
||||
if ((res >= 4) && (res <= 16)) {
|
||||
if ((res >= 2) && (res <= 16)) {
|
||||
analogWriteRange((1 << res) - 1);
|
||||
} else {
|
||||
DEBUGCORE("ERROR: analogWriteResolution out of range (%d)\n", res);
|
||||
@@ -78,29 +83,30 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
|
||||
DEBUGCORE("ERROR: Illegal analogWrite pin (%d)\n", pin);
|
||||
return;
|
||||
}
|
||||
if (!pwmInitted) {
|
||||
__clearADCPin(pin);
|
||||
if (!scaleInitted) {
|
||||
// For low frequencies, we need to scale the output max value up to achieve lower periods
|
||||
analogWritePseudoScale = 1;
|
||||
while (((clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) {
|
||||
while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) {
|
||||
analogWritePseudoScale++;
|
||||
analogScale *= 2;
|
||||
DEBUGCORE("Adjusting analogWrite values PS=%d, scale=%d\n", analogWritePseudoScale, analogScale);
|
||||
DEBUGCORE("Adjusting analogWrite values PS=%d, scale=%lu\n", analogWritePseudoScale, analogScale);
|
||||
}
|
||||
// For high frequencies, we need to scale the output max value down to actually hit the frequency target
|
||||
analogWriteSlowScale = 1;
|
||||
while (((clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)) < 2.0) && (analogScale > 32)) {
|
||||
while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) < 1.0) && (analogScale >= 6)) {
|
||||
analogWriteSlowScale++;
|
||||
analogScale /= 2;
|
||||
DEBUGCORE("Adjusting analogWrite values SS=%d, scale=%d\n", analogWriteSlowScale, analogScale);
|
||||
DEBUGCORE("Adjusting analogWrite values SS=%d, scale=%lu\n", analogWriteSlowScale, analogScale);
|
||||
}
|
||||
|
||||
scaleInitted = true;
|
||||
}
|
||||
if (!(pwmInitted & (1 << pwm_gpio_to_slice_num(pin)))) {
|
||||
pwm_config c = pwm_get_default_config();
|
||||
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / (float)(analogScale * analogFreq));
|
||||
pwm_config_set_wrap(&c, analogScale);
|
||||
for (int i = 0; i < 30; i++) {
|
||||
pwm_init(pwm_gpio_to_slice_num(i), &c, true);
|
||||
}
|
||||
pwmInitted = true;
|
||||
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / ((float)analogScale * analogFreq));
|
||||
pwm_config_set_wrap(&c, analogScale - 1);
|
||||
pwm_init(pwm_gpio_to_slice_num(pin), &c, true);
|
||||
pwmInitted |= 1 << pwm_gpio_to_slice_num(pin);
|
||||
}
|
||||
|
||||
val <<= analogWritePseudoScale;
|
||||
@@ -117,7 +123,13 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
|
||||
}
|
||||
|
||||
auto_init_mutex(_adcMutex);
|
||||
static int _readBits = 10;
|
||||
static uint8_t _readBits = 10;
|
||||
static uint8_t _lastADCMux = 0;
|
||||
static uint32_t _adcGPIOInit = 0;
|
||||
|
||||
void __clearADCPin(pin_size_t p) {
|
||||
_adcGPIOInit &= ~(1 << p);
|
||||
}
|
||||
|
||||
extern "C" int analogRead(pin_size_t pin) {
|
||||
CoreMutex m(&_adcMutex);
|
||||
@@ -131,13 +143,20 @@ extern "C" int analogRead(pin_size_t pin) {
|
||||
}
|
||||
if (!adcInitted) {
|
||||
adc_init();
|
||||
adcInitted = true;
|
||||
}
|
||||
if (!(_adcGPIOInit & (1 << pin))) {
|
||||
adc_gpio_init(pin);
|
||||
_adcGPIOInit |= 1 << pin;
|
||||
}
|
||||
if (_lastADCMux != pin) {
|
||||
adc_select_input(pin - minPin);
|
||||
_lastADCMux = pin;
|
||||
}
|
||||
adc_gpio_init(pin);
|
||||
adc_select_input(pin - minPin);
|
||||
return (_readBits < 12) ? adc_read() >> (12 - _readBits) : adc_read() << (_readBits - 12);
|
||||
}
|
||||
|
||||
extern "C" float analogReadTemp() {
|
||||
extern "C" float analogReadTemp(float vref) {
|
||||
CoreMutex m(&_adcMutex);
|
||||
|
||||
if (!m) {
|
||||
@@ -145,13 +164,15 @@ extern "C" float analogReadTemp() {
|
||||
}
|
||||
if (!adcInitted) {
|
||||
adc_init();
|
||||
adcInitted = true;
|
||||
}
|
||||
_lastADCMux = 0;
|
||||
adc_set_temp_sensor_enabled(true);
|
||||
delay(1); // Allow things to settle. Without this, readings can be erratic
|
||||
adc_select_input(4); // Temperature sensor
|
||||
int v = adc_read();
|
||||
adc_set_temp_sensor_enabled(false);
|
||||
float t = 27.0f - ((v * 3.3f / 4096.0f) - 0.706f) / 0.001721f; // From the datasheet
|
||||
float t = 27.0f - ((v * vref / 4096.0f) - 0.706f) / 0.001721f; // From the datasheet
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
#include "Arduino.h"
|
||||
#include <hardware/gpio.h>
|
||||
|
||||
extern void __clearADCPin(pin_size_t p);
|
||||
|
||||
static PinMode _pm[30];
|
||||
|
||||
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
|
||||
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) __attribute__((weak, alias("__pinMode")));
|
||||
extern "C" void __pinMode(pin_size_t ulPin, PinMode ulMode) {
|
||||
switch (ulMode) {
|
||||
case INPUT:
|
||||
gpio_init(ulPin);
|
||||
@@ -74,9 +77,14 @@ extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
|
||||
return;
|
||||
}
|
||||
_pm[ulPin] = ulMode;
|
||||
|
||||
if ((ulPin >= std::min(A0, A3)) && (ulPin <= std::max(A0, A3))) {
|
||||
__clearADCPin(ulPin);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
||||
extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) __attribute__((weak, alias("__digitalWrite")));
|
||||
extern "C" void __digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
||||
if (ulPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
|
||||
return;
|
||||
@@ -99,7 +107,8 @@ extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" PinStatus digitalRead(pin_size_t ulPin) {
|
||||
extern "C" PinStatus digitalRead(pin_size_t ulPin) __attribute__((weak, alias("__digitalRead")));
|
||||
extern "C" PinStatus __digitalRead(pin_size_t ulPin) {
|
||||
if (ulPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in digitalRead (%d)\n", ulPin);
|
||||
return LOW;
|
||||
|
||||
@@ -22,24 +22,30 @@
|
||||
#include <CoreMutex.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/sync.h>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
// Support nested IRQ disable/re-enable
|
||||
static std::stack<uint32_t> _irqStack[2];
|
||||
#define maxIRQs 15
|
||||
static uint32_t _irqStackTop[2] = { 0, 0 };
|
||||
static uint32_t _irqStack[2][maxIRQs];
|
||||
|
||||
extern "C" void interrupts() {
|
||||
if (_irqStack[get_core_num()].empty()) {
|
||||
auto core = get_core_num();
|
||||
if (!_irqStackTop[core]) {
|
||||
// ERROR
|
||||
return;
|
||||
}
|
||||
auto oldIrqs = _irqStack[get_core_num()].top();
|
||||
_irqStack[get_core_num()].pop();
|
||||
restore_interrupts(oldIrqs);
|
||||
restore_interrupts(_irqStack[core][--_irqStackTop[core]]);
|
||||
}
|
||||
|
||||
extern "C" void noInterrupts() {
|
||||
_irqStack[get_core_num()].push(save_and_disable_interrupts());
|
||||
auto core = get_core_num();
|
||||
if (_irqStackTop[core] == maxIRQs) {
|
||||
// ERROR
|
||||
panic("IRQ stack overflow");
|
||||
}
|
||||
|
||||
_irqStack[core][_irqStackTop[core]++] = save_and_disable_interrupts();
|
||||
}
|
||||
|
||||
// Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and
|
||||
@@ -81,6 +87,15 @@ void _gpioInterruptDispatcher(uint gpio, uint32_t events) {
|
||||
}
|
||||
}
|
||||
|
||||
// To be called when appropriately protected w/IRQ and mutex protects
|
||||
static void _detachInterruptInternal(pin_size_t pin) {
|
||||
auto irq = _map.find(pin);
|
||||
if (irq != _map.end()) {
|
||||
gpio_set_irq_enabled(pin, 0x0f /* all */, false);
|
||||
_map.erase(pin);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus mode) {
|
||||
CoreMutex m(&_irqMutex);
|
||||
if (!m) {
|
||||
@@ -97,7 +112,7 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
|
||||
default: return; // ERROR
|
||||
}
|
||||
noInterrupts();
|
||||
detachInterrupt(pin);
|
||||
_detachInterruptInternal(pin);
|
||||
CBInfo cb(callback);
|
||||
_map.insert({pin, cb});
|
||||
gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher);
|
||||
@@ -120,7 +135,7 @@ void attachInterruptParam(pin_size_t pin, voidFuncPtrParam callback, PinStatus m
|
||||
default: return; // ERROR
|
||||
}
|
||||
noInterrupts();
|
||||
detachInterrupt(pin);
|
||||
_detachInterruptInternal(pin);
|
||||
CBInfo cb(callback, param);
|
||||
_map.insert({pin, cb});
|
||||
gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher);
|
||||
@@ -134,10 +149,6 @@ extern "C" void detachInterrupt(pin_size_t pin) {
|
||||
}
|
||||
|
||||
noInterrupts();
|
||||
auto irq = _map.find(pin);
|
||||
if (irq != _map.end()) {
|
||||
gpio_set_irq_enabled(pin, 0x0f /* all */, false);
|
||||
_map.erase(pin);
|
||||
}
|
||||
_detachInterruptInternal(pin);
|
||||
interrupts();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
wl_definitions.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
/*
|
||||
wl_definitions.h
|
||||
|
||||
Created on: Mar 6, 2011
|
||||
Author: dlafauci
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// Maximum size of a SSID
|
||||
#define WL_SSID_MAX_LENGTH 32
|
||||
// Length of passphrase. Valid lengths are 8-63.
|
||||
#define WL_WPA_KEY_MAX_LENGTH 63
|
||||
// Length of key in bytes. Valid values are 5 and 13.
|
||||
#define WL_WEP_KEY_MAX_LENGTH 13
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_MAC_ADDR_LENGTH 6
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_IPV4_LENGTH 4
|
||||
// Maximum size of a SSID list
|
||||
#define WL_NETWORKS_LIST_MAXNUM 10
|
||||
// Maximum number of socket
|
||||
#define WIFI_MAX_SOCK_NUM 10
|
||||
// Socket not available constant
|
||||
#define SOCK_NOT_AVAIL 255
|
||||
// Default state value for WiFi state field
|
||||
#define NA_STATE -1
|
||||
|
||||
typedef enum {
|
||||
WL_NO_SHIELD = 255,
|
||||
WL_NO_MODULE = WL_NO_SHIELD,
|
||||
WL_IDLE_STATUS = 0,
|
||||
WL_NO_SSID_AVAIL,
|
||||
WL_SCAN_COMPLETED,
|
||||
WL_CONNECTED,
|
||||
WL_CONNECT_FAILED,
|
||||
WL_CONNECTION_LOST,
|
||||
WL_DISCONNECTED,
|
||||
WL_AP_LISTENING,
|
||||
WL_AP_CONNECTED,
|
||||
WL_AP_FAILED
|
||||
} wl_status_t;
|
||||
|
||||
/* Encryption modes */
|
||||
enum wl_enc_type { /* Values map to 802.11 encryption suites... */
|
||||
ENC_TYPE_WEP = 5,
|
||||
ENC_TYPE_TKIP = 2,
|
||||
ENC_TYPE_CCMP = 4,
|
||||
/* ... except these two, 7 and 8 are reserved in 802.11-2007 */
|
||||
ENC_TYPE_NONE = 7,
|
||||
ENC_TYPE_AUTO = 8,
|
||||
|
||||
ENC_TYPE_UNKNOWN = 255
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
wl_types.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
/*
|
||||
wl_types.h
|
||||
|
||||
Created on: Jul 30, 2010
|
||||
Author: dlafauci
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
WL_FAILURE = -1,
|
||||
WL_SUCCESS = 1,
|
||||
} wl_error_code_t;
|
||||
|
||||
/* Authentication modes */
|
||||
enum wl_auth_mode {
|
||||
AUTH_MODE_INVALID,
|
||||
AUTH_MODE_AUTO,
|
||||
AUTH_MODE_OPEN_SYSTEM,
|
||||
AUTH_MODE_SHARED_KEY,
|
||||
AUTH_MODE_WPA,
|
||||
AUTH_MODE_WPA2,
|
||||
AUTH_MODE_WPA_PSK,
|
||||
AUTH_MODE_WPA2_PSK
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
WL_PING_DEST_UNREACHABLE = -1,
|
||||
WL_PING_TIMEOUT = -2,
|
||||
WL_PING_UNKNOWN_HOST = -3,
|
||||
WL_PING_ERROR = -4
|
||||
} wl_ping_result_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
ADC Input Library
|
||||
=================
|
||||
|
||||
The ADC pins can be sampled and recorded by an application using the same
|
||||
interface as the I2S or PWM Audio libraries. This allows analog devices which
|
||||
need to be periodically sampled to be read by applications, easily, such as:
|
||||
|
||||
* Analog electret microphones
|
||||
|
||||
* Potentiometers
|
||||
|
||||
* Light dependent resistors (LDR), etc.
|
||||
|
||||
|
||||
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).
|
||||
|
||||
The interface for the ``ADCInput`` device is very similar to the ``I2S`` input
|
||||
device, and most code can be ported simply by instantiating a ``ADCInput``
|
||||
object in lieu of an ``I2S`` input object and choosing the pins to record.
|
||||
|
||||
Since this uses the ADC hardware, no ``analogRead`` or ``analogReadTemp`` calls are
|
||||
allowed while in use.
|
||||
|
||||
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`` ... ``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)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Set the number of DMA buffers and their size in 32-bit words. Call before
|
||||
``ADCInput::begin()``.
|
||||
|
||||
When running at high sample rates, it is recommended to increase the
|
||||
``bufferWords`` to 32 or higher (i.e. ``adcinput.setBuffers(4, 32);`` ).
|
||||
|
||||
bool setPins(pin_size_t pin [, pin1, pin2, pin3])
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Adjusts the pin to record. Only legal before ``ADCInput::begin()``.
|
||||
|
||||
bool setFrequency(long sampleRate)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the ADC sampling frequency, but does not start recording (however if the
|
||||
device was already running, it will continue to run at the new frequency). Note
|
||||
that every pin requested will be sampled at this frequency, one after the other.
|
||||
That is, if you have code like this:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
ADCInput adc(A0, A1);
|
||||
adc.setFrequency(1000);
|
||||
|
||||
``A0`` will be sampled at 0ms, 1ms, 2ms, etc. and ``A1`` will be sampled at 0.5ms
|
||||
1.5ms, 2.5ms, etc. Each input is sampled at the proper frequency but offset in time
|
||||
since there is only one active ADC at a time.
|
||||
|
||||
bool begin()/begin(long sampleRate)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Start the ADC input up with the given sample rate, or with the value set
|
||||
using the prior ``setFrequency`` call.
|
||||
|
||||
void end()
|
||||
~~~~~~~~~~
|
||||
Stops the ADC Input device.
|
||||
|
||||
int read()
|
||||
~~~~~~~~~~
|
||||
Reads a single sample of recorded ADC data, as a 16-bit value. When multiple pins are
|
||||
recorded the first read will be pin 0, the second will be pin 1, etc. Applications need
|
||||
to keep track of which pin is being returned (normally by always reading out all pins
|
||||
at once). Will not return until data is available.
|
||||
|
||||
int available()
|
||||
~~~~~~~~~~~~~~~
|
||||
Returns the number of samples that can be read without potentially blocking.
|
||||
|
||||
void onReceive(void (\*fn)(void))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets a callback to be called when a ADC input DMA buffer is fully filled.
|
||||
Will be in an interrupt context so the specified function must operate
|
||||
quickly and not use blocking calls like delay().
|
||||
+4
-3
@@ -14,13 +14,14 @@ Returns a value from 0...4095 correspionding to the ADC reading
|
||||
of the specific pin.
|
||||
|
||||
void analogReadResolution(int bits)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Determines the resolution (in bits) of the value returned by the analogRead() function.
|
||||
Default resolution is 10bit.
|
||||
|
||||
float analogReadTemp()
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
float analogReadTemp(float vref = 3.3f)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns the temperature, in Celsius, of the onboard thermal sensor.
|
||||
If you have a custom Vref for the ADC on your RP2040 board, you can pass it in as a parameter. Calling with no parameters assumes the normal, 3.3V Vref.
|
||||
This reading is not exceedingly accurate and of relatively low
|
||||
resolution, so it is not a replacement for an external temperature
|
||||
sensor in many cases.
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
:orphan:
|
||||
|
||||
WiFiClientSecure Class
|
||||
======================
|
||||
|
||||
`BearSSL::WiFiClientSecure` is the object which actually handles TLS encrypted WiFi connections to a remote server or client. It extends `WiFiClient` and so can be used with minimal changes to code that does unsecured communications.
|
||||
|
||||
Validating X509 Certificates (Am I talking to the server I think I'm talking to?)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Prior to connecting to a server, the `BearSSL::WiFiClientSecure` needs to be told how to verify the identity of the other machine. **By default BearSSL will not validate any connections and will refuse to connect to any server.**
|
||||
|
||||
There are multiple modes to tell BearSSL how to verify the identity of the remote server. See the `BearSSL_Validation` example for real uses of the following methods:
|
||||
|
||||
setInsecure()
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Don't verify any X509 certificates. There is no guarantee that the server connected to is the one you think it is in this case.
|
||||
|
||||
setKnownKey(const BearSSL::PublicKey \*pk)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Assume the server is using the specific public key. This does not verify the identity of the server or the X509 certificate it sends, it simply assumes that its public key is the one given. If the server updates its public key at a later point then connections will fail.
|
||||
|
||||
setFingerprint(const uint8_t fp[20]) / setFingerprint(const char \*fpStr)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Verify the SHA1 fingerprint of the certificate returned matches this one. If the server certificate changes, it will fail. If an array of 20 bytes are sent in, it is assumed they are the binary SHA1 values. If a `char*` string is passed in, it is parsed as a series of human-readable hex values separated by spaces or colons (e.g. `setFingerprint("00:01:02:03:...:1f");`)
|
||||
|
||||
This fingerprint is calculated on the raw X509 certificate served by the server. In very rare cases, these certificates have certain encodings which should be normalized before taking a fingerprint (but in order to preserve memory BearSSL does not do this normalization since it would need RAM for an entire copy of the cert), and the fingerprint BearSSL calculates will not match the fingerprint OpenSSL calculates. In this case, you can enable SSL debugging and get a dump of BearSSL's calculated fingerprint and use that one in your code, or use full certificate validation. See the `original issue and debug here <https://github.com/esp8266/Arduino/issues/6209>`__.
|
||||
|
||||
setTrustAnchors(BearSSL::X509List \*ta)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Use the passed-in certificate(s) as a trust anchor, accepting remote certificates signed by any of these. If you have many trust anchors it may make sense to use a `BearSSL::CertStore` because it will only require RAM for a single trust anchor (while the `setTrustAnchors` call requires memory for all certificates in the list).
|
||||
|
||||
setX509Time(time_t now)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For `setTrustAnchors` and `CertStore` , the current time (set via SNTP) is used to verify the certificate against the list, so SNTP must be enabled and functioning before the connection is attempted. If you cannot use SNTP for some reason, you can manually set the "present time" that BearSSL will use to validate a certificate with this call where `now` is standard UNIX time.
|
||||
|
||||
Client Certificates (Proving I'm who I say I am to the server)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
TLS servers can request that a client identify themselves with an X509 certificate signed by a trust anchor it honors (i.e. a global TA or a private CA). This is commonly done for applications like MQTT. By default the client doesn't send a certificate, and in cases where a certificate is required the server will disconnect and no connection will be possible.
|
||||
|
||||
setClientRSACert / setClientECCert
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Sets a client certificate to send to a TLS server that requests one. It should be called before `connect()` to add a certificate to the client in case the server requests it. Note that certificates include both a certificate and a private key. Both should be provided to you by your certificate generator. Elliptic Curve (EC) keys require additional information, as shown in the prototype.
|
||||
|
||||
MFLN or Maximum Fragment Length Negotiation (Saving RAM)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Because TLS was developed on systems with many megabytes of memory, they require by default a 16KB buffer for receive and transmit. That's enormous for the ESP8266, which has only around 40KB total heap available.
|
||||
|
||||
We can (and do) minimize the transmission buffer down to slightly more than 512 bytes to save memory, since BearSSL can internally ensure transmissions larger than that are broken up into smaller chunks that do fit. But that still leaves the 16KB receive buffer requirement since we cannot in general guarantee the TLS peer will send in smaller chunks.
|
||||
|
||||
TLS 1.2 added MFLN, which lets a client negotiate smaller buffers with a server and reduce the memory requirements on the ESP8266. Unfortunately, BearSSL needs to know the buffer sizes before it begins connection, so applications that want to use smaller buffers need to check the remote server's support before `connect()` .
|
||||
|
||||
probeMaxFragmentLength(host, port, len)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Use one of these calls **before** connection to determine if a specific fragment length is supported (len must be a power of two from 512 to 4096, per the specification). This does **not** initiate a SSL connection, it simply opens a TCP port and performs a trial handshake to check support.
|
||||
|
||||
setBufferSizes(int recv, int xmit)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once you have verified (or know beforehand) that MFLN is supported you can use this call to set the size of memory buffers allocated by the connection object. This must be called **before** `connect()` or it will be ignored.
|
||||
|
||||
In certain applications where the TLS server does not support MFLN (not many do as of this writing as it is relatively new to OpenSSL), but you control both the ESP8266 and the server to which it is communicating, you may still be able to `setBufferSizes()` smaller if you guarantee no chunk of data will overflow those buffers.
|
||||
|
||||
bool getMFLNStatus()
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
After a successful connection, this method returns whether or not MFLN negotiation succeeded or not. If it did not succeed, and you reduced the receive buffer with `setBufferSizes` then you may experience reception errors if the server attempts to send messages larger than your receive buffer.
|
||||
|
||||
Sessions (Resuming connections fast)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
setSession(BearSSL::Session &sess)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you are connecting to a server repeatedly in a fixed time period (usually 30 or 60 minutes, but normally configurable at the server), a TLS session can be used to cache crypto settings and speed up connections significantly.
|
||||
|
||||
Errors
|
||||
~~~~~~
|
||||
|
||||
BearSSL can fail in many more unique and interesting ways. Use these calls to get more information when something fails.
|
||||
|
||||
getLastSSLError(char \*dest = NULL, size_t len = 0)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Returns the last BearSSL error code encountered and optionally set a user-allocated buffer to a human-readable form of the error. To only get the last error integer code, just call without any parameters (`int errCode = getLastSSLError();`).
|
||||
|
||||
Limiting Ciphers (New connections faster)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There is very rarely reason to use these calls, but they are available.
|
||||
|
||||
setCiphers()
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Takes an array (in PROGMEM is valid) or a std::vector of 16-bit BearSSL cipher identifiers and restricts BearSSL to only use them. If the server requires a different cipher, then connection will fail. Generally this is not useful except in cases where you want to connect to servers using a specific cipher. See the BearSSL headers for more information on the supported ciphers.
|
||||
|
||||
setCiphersLessSecure()
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Helper function which essentially limits BearSSL to less secure ciphers than it would natively choose, but they may be helpful and faster if your server depended on specific crypto options.
|
||||
|
||||
Limiting TLS(SSL) Versions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, BearSSL will connect with TLS 1.0, TLS 1.1, or TLS 1.2 protocols (depending on the request of the remote side). If you want to limit to a subset, use the following call:
|
||||
|
||||
setSSLVersion(uint32_t min, uint32_t max)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Valid values for min and max are `BR_TLS10`, `BR_TLS11`, `BR_TLS12`. Min and max may be set to the same value if only a single TLS version is desired.
|
||||
|
||||
|
||||
ESP32 Compatibility
|
||||
===================
|
||||
Simple ESP32 ``WiFiClientSecure`` compatibility is built-in, allow for some sketches to run without any modification.
|
||||
The following methods are implemented:
|
||||
|
||||
.. code :: cpp
|
||||
|
||||
void setCACert(const char *rootCA);
|
||||
void setCertificate(const char *client_ca);
|
||||
void setPrivateKey(const char *private_key);
|
||||
bool loadCACert(Stream& stream, size_t size);
|
||||
bool loadCertificate(Stream& stream, size_t size);
|
||||
bool loadPrivateKey(Stream& stream, size_t size);
|
||||
int connect(IPAddress ip, uint16_t port, int32_t timeout);
|
||||
int connect(const char *host, uint16_t port, int32_t timeout);
|
||||
int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
|
||||
Note that the SSL backend is very different between Arduino-Pico and ESP32-Arduino (BearSSL vs. mbedTLS). This means
|
||||
that, for instance, the SSL connection will check valid dates of certificates (and hence require system time to be
|
||||
set on the Pico, which is automatically done in this case).
|
||||
|
||||
TLS-Pre Shared Keys (PSK) is not supported by BearSSL, and hence not implemented here. Neither is ALPN.
|
||||
|
||||
For more advanced control, it is recommended to port to the native Pico calls which allows much more flexibility and control.
|
||||
@@ -0,0 +1,64 @@
|
||||
:orphan:
|
||||
|
||||
WiFiServerSecure Class
|
||||
----------------------
|
||||
|
||||
Implements a TLS encrypted server with optional client certificate validation. See `Server Class <server-class.rst>`__ for general information and `BearSSL Secure Client Class <bearssl-client-secure-class.rst>`__ for basic server and BearSSL concepts.
|
||||
|
||||
setBufferSizes(int recv, int xmit)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Similar to the `BearSSL::WiFiClientSecure` method, sets the receive and transmit buffer sizes. Note that servers cannot request a buffer size from the client, so if these are shrunk and the client tries to send a chunk larger than the receive buffer, it will always fail. Needs to be called before `begin()`
|
||||
|
||||
Setting Server Certificates
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
TLS servers require a certificate identifying itself and containing its public key, and a private key they will use to encrypt information with. The application author is responsible for generating this certificate and key, either using a self-signed generator or using a commercial certification authority. **Do not re-use the certificates included in the examples provided.**
|
||||
|
||||
This example command will generate a RSA 2048-bit key and certificate:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
openssl req -x509 -nodes -newkey rsa:2048 -keyout key.pem -out cert.pem -days 4096
|
||||
|
||||
Again, it is up to the application author to generate this certificate and key and keep the private key safe and **private.**
|
||||
|
||||
setRSACert(const BearSSL::X509List \*chain, const BearSSL::PrivateKey \*sk)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Sets a RSA certificate and key to be used by the server when connections are received. Needs to be called before `begin()`
|
||||
|
||||
setECCert(const BearSSL::X509List \*chain, unsigned cert_issuer_key_type, const BearSSL::PrivateKey \*sk)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Sets an elliptic curve certificate and key for the server. Needs to be called before `begin()`.
|
||||
|
||||
Client sessions (Resuming connections fast)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The TLS handshake process takes a long time because of all the back and forth between the client and the server. You can shorten it by caching the clients' sessions which will skip a few steps in the TLS handshake. In order for this to work, your client also needs to cache the session. `BearSSL::WiFiClientSecure <bearssl-client-secure-class.rst#sessions-resuming-connections-fast>`__ can do that as well as modern web browsers.
|
||||
|
||||
Here are the kind of performance improvements that you'll be able to see for TLS handshakes with an ESP8266 with it's clock set at 160MHz on a network with fairly low latency:
|
||||
|
||||
* With an EC key of 256 bits, a request taking ~360ms without caching takes ~60ms with caching.
|
||||
* With an RSA key of 2048 bits, a request taking ~1850ms without caching takes ~70ms with caching.
|
||||
|
||||
setCache(BearSSL::ServerSessions \*cache)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Sets the cache for the server's sessions. When choosing the size of the cache, remember that each client session takes 100 bytes. If you setup a cache for 10 sessions, it will take 1000 bytes. Needs to be called before `begin()`
|
||||
|
||||
When creating the cache, you can use any of the 2 available constructors:
|
||||
|
||||
* `BearSSL::ServerSessions(ServerSession *sessions, uint32_t size)`: Creates a cache with the given buffer and number of sessions.
|
||||
* `BearSSL::ServerSessions(uint32_t size)`: Dynamically allocates a cache for the given number of sessions.
|
||||
|
||||
Requiring Client Certificates
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
TLS servers can request the client to identify itself by transmitting a certificate during handshake. If the client cannot transmit the certificate, the connection will be dropped by the server.
|
||||
|
||||
setClientTrustAnchor(const BearSSL::X509List \*client_CA_ta)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Sets the trust anchor (normally a self-signing CA) that all received certificates will be verified against. Needs to be called before `begin()`.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user