Compare commits

..
53 Commits
Author SHA1 Message Date
Earle F. Philhower, III 06a1fdac50 Update version 2023-03-01 16:59:38 -08:00
Earle F. Philhower, III 7308ef4117 Update bluetooth.rst 2023-03-01 16:44:35 -08:00
Earle F. Philhower, III 67c1db9957 JoystickBLE actually implements a gamepad, update appearance 2023-03-01 16:30:51 -08:00
Earle F. Philhower, III f5a621935d Add BLE HID libraries and examples (#1240) 2023-03-01 16:29:25 -08:00
Earle F. Philhower, III 354edb30d3 Move pico-sdk to RPI's original version (#1239)
No need to use my own fork, we're using the default upstream code.
2023-03-01 10:24:45 -08:00
Earle F. Philhower, III 96113fe848 Fix BLE enable definition (#1238)
BLE tested working with BTStack BLE hog-keyboard-demo.
2023-03-01 10:08:03 -08:00
Earle F. Philhower, III fd1596b6c9 Update keywords.txt 2023-02-28 12:41:22 -08:00
Earle F. Philhower, III 9760efbca3 Clean up the BT HID libraries a bit (#1236) 2023-02-28 10:10:39 -08:00
Earle F. Philhower, III d92c1025ba Update to SDK 1.5, add alpha-level BT support, use Pico-SDK CYW43 infrastructure (#1167)
* Update to Pico-SDK v1.5
* Hook in pico_rand, use ioctl to set ipv6 allmulti
* Move into PicoSDK LWIP mutex, hack timer sizes
* Utilize much of the PicoSDK infrastructure for WiFi
* Add WiFi::begin(ssid, pass, bssid)
* WiFiMulti to use BSSID, make more robust

WiFiMulti will now be more aggressive and try all matching SSIDs, in order
of RSSI, using the BSSID to identify individual APs in a mesh.

Before, if the highest RSSI AP didn't connect, it would fail immediately.
Now, it will go down the list, ordered by RSSI, to attempt to get a link.

* Add Bluetooth support from Pico-SDK
Able to build and run the HID Keyboard Demo from the Arduino IDE, almost
as-is.

Will probably need to make BT configurable.  Enabling BT on a plain WiFi
sketch uses 50KB of flash and 16KB of RAM even if no BT is used.

* Separate picow libs, BT through menus, example

Build normal Pico.a and 4 different options for PicoW IP/BT configuration.
Use IP=>IP/Bluetooth menu to select between options.

* CMakefile rationalization

* Move BT TLV(pairing) out of last 2 flash sectors

The pairing keys for BT are stored at the end of flash by default, but
we use the last sector of flash for EPROM and the penultimate one for
the filesystem.  Overwriting those in BT could cause some real exciting
crashes down the line.

Move the store to an app-build specific address using a dummy const
array to allocate space in the application image itself.

* PicoBluetoothHID with BT Mouse, Joystick, Keyboard

Add simple Bluetooth Classic HID helper function and port the existing
USB HID devices to it.  Port their examples.

* Protect BT key storage from multicore

* Add short-n-sweet Bluetooth documents

* Add Bluetooth Serial port library

* Turn off BT when the BT libraries exit
2023-02-27 20:09:02 -08:00
Earle F. Philhower, III de55db12f1 Update rp2040.rst 2023-02-26 18:54:32 -08:00
Earle F. Philhower, III 264b9efb36 Return custom USB product and manufacturer (#1223)
Return the pre-existing USB_PRODUCT/MANUFACTURER to the USB host in
the ID stage, allowing for reports like:

[1412958.589070] usb 1-6.3.4.1: New USB device found, idVendor=2e8a, idProduct=f00a, bcdDevice= 1.00
[1412958.589076] usb 1-6.3.4.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1412958.589079] usb 1-6.3.4.1: Product: Pico W
[1412958.589080] usb 1-6.3.4.1: Manufacturer: Raspberry Pi
[1412958.589081] usb 1-6.3.4.1: SerialNumber: E6614C775B6C7F31

or

[1413190.272233] usb 1-6.3.4.1: New USB device found, idVendor=2e8a, idProduct=1037, bcdDevice= 1.00
[1413190.272239] usb 1-6.3.4.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1413190.272242] usb 1-6.3.4.1: Product: HunterCat NFC RP2040
[1413190.272243] usb 1-6.3.4.1: Manufacturer: ElectronicCats
[1413190.272244] usb 1-6.3.4.1: SerialNumber: E6614C775B6C7F31
2023-02-23 17:13:12 -08:00
Earle F. Philhower, III 9fd5cdf1ba Move PicoW auto-reassignment of LED pin to code (#1208)
Many examples require that LED_BUILTIN be defined as a constant, so we
can't use a ternary operator to swap between Pico and PicoW LED pins.

Instead, do the check in the digitalWrite/digitalRead/pinMode calls
to cover most of the uses.
2023-02-22 16:13:24 -08:00
Earle F. Philhower, III 1b33cbe591 Always apply 5M speed to CMSIS_DAP TCL script (#1218)
Still need it on the command line in platform.txt for upload/etc., but make the
debug script in lib/picoprobe_cmsis_dap.tcl include the adapter speed setting.
2023-02-21 12:30:05 -08:00
MisterSilvereagleandEarle F. Philhower, III a97d5eab22 Fix spelling mistake (#1211)
Co-authored-by: Earle F. Philhower, III <earlephilhower@yahoo.com>
2023-02-20 09:58:50 -08:00
crp500 83e790851f Update PlayStereo.ino (#1210)
The PWMAudio lib is expecting an int16_t value but the example passes a sample cast to uint16_t 
So any values from the lookup table that are negative are recast to 0 i think.
So half the sine wave in the case of the example is lost.
2023-02-20 09:58:14 -08:00
Earle F. Philhower, III 11ac5ed33e Update version 2023-02-18 13:04:53 -08:00
Earle F. Philhower, III b7912f182b Add isPicoW call to RP2040 object (#1204)
Use the RPi code to get a best-guess as to whether the board is a Pico or
PicoW.

Fixes #849
2023-02-18 13:00:02 -08:00
Earle F. Philhower, III 6db0ac8471 Add release package fixups for picoprobe-cmsis-dap (#1205) 2023-02-18 12:14:23 -08:00
Ha Thach 060aa52c89 Add picoprobe CMSIS-DAP support (#1198) 2023-02-18 12:09:02 -08:00
Carter Nelson ba413bb7ad Remove extra SPI byte flip (#1202)
Fixes #1201
2023-02-17 12:42:31 -08:00
Earle F. Philhower, III 97e787e48a Reduce unintialized_ram overhead to 0 in most cases (#1200)
Use GNU LD MAX() to ensure the uninitialized RAM portions are after the
OTA region.  For most apps this already happens, so there will be no
overhead added.
2023-02-16 18:23:15 -08:00
Earle F. Philhower, III b473139758 Enable use of uninitialized_ram() macro (#1199)
The uninitted RAM macro would fail because the OTA code would clear out the
first 50KB or so of RAM to copy its code and global values.

Move all global values to the end of RAM in OTA, and then align any uninitted
vars to a 16KB unit to ensure it won't appear in the 1st part of RAM that is
still needed to copy the OTA executable.

In the normal case, without any uninit_ram vars, no additional space is used.
When uninit_ram is used, up to 16KB of space may be lost to get that alignment,
but it will work properly.

Fixes #1188
2023-02-16 17:59:15 -08:00
Earle F. Philhower, III 7afcec8edc Update picotool refs in JSON (#1197) 2023-02-15 18:49:40 -08:00
Earle F. Philhower, III d1a3009447 Upgrade to toolchain 1.5.0-b (#1196)
Includes fixes for ::printf/etc. using stdout/stderr
Fixes #1181
2023-02-15 18:20:18 -08:00
Earle F. Philhower, III 651d596246 Allow FreeRTOS to ::printf (#1195)
The stdin/stdout FILEs have an internal mutex which needs to be initted
to a FreeRTOS one, or any sketch with ::printf will hang.  Automatically
create and acquire/release the shadowed mutex.

Requires new build of pico-quick-toolchain to function properly.  Tested
on preliminary local build.
2023-02-15 15:58:45 -08:00
Earle F. Philhower, III 75bab41e39 Make uf2conf.py flush STDOUT for real-time updates (#1194)
Without flushing STDOUT, the upload script's output aften are buffered
and not displayed until it completes.  Add in flush commands to allow
the IDE to display status as it changes.
2023-02-15 12:13:55 -08:00
Earle F. Philhower, III 36e0b4a908 Unbreak FreeRTOS (#1193)
USB changes caused FreeRTOS to not be able to swap tasks when the Serial port
was connected.  Clear the "stop PendSV" flag after checking for reset signal.
2023-02-15 12:10:52 -08:00
Earle F. Philhower, III 974301eaaf Add rp2040.cpuid() call to get running core (#1190)
Per question received via email.
2023-02-14 16:22:04 -08:00
Earle F. Philhower, III 2acc161ad2 Update contrib.rst 2023-02-14 13:24:02 -08:00
Earle F. Philhower, III 7322bad830 Add docs on adding a new board to the core, too 2023-02-14 08:46:24 -08:00
Earle F. Philhower, III 6afd3260ef Update README.md 2023-02-13 14:56:46 -08:00
Earle F. Philhower, III 76e7cca821 Add contributing docs (#1183) 2023-02-13 14:54:52 -08:00
Earle F. Philhower, III 84206eb237 Fix SD.H FILE_WRITE mapping (#1178)
O_RDWR != O_READ|O_WRITE.  Posix is weird.  Thanks @mcspr
2023-02-12 17:46:50 -08:00
Earle F. Philhower, III 5e576c1a08 Update SD examples with working SPI configs (#1175)
Fixes #1172
2023-02-12 11:01:01 -08:00
Earle F. Philhower, III fc180041aa Implement WiFi::softAPgetStationNum (#1174) 2023-02-12 10:38:37 -08:00
Earle F. Philhower, III 1bfd07c19a Update version 2023-02-11 12:34:40 -08:00
Andrew KrollandEarle F. Philhower, III 5dafbf57e9 Optimize and improve upload experience (#1136)
Stop the IDE from reporting large "Serial port not fount"-type errors after
every upload by delaying a bit before the uploader exits to give the OS/Pico
time to renegotiate.

Fixes flashing problems on certain Linux distros by checking all possible mount
locations instead of only the first one to be found.

Make 1200bps reset tickle more robust

Co-authored-by: Earle F. Philhower, III <earlephilhower@yahoo.com>
2023-02-11 12:33:44 -08:00
Earle F. Philhower, III 09db2e6c37 Apply SD.h fix from ESP8266 (#1171)
Pull in the portion of the change correcting the flag setting from
https://github.com/esp8266/Arduino/pull/8833
2023-02-11 11:57:27 -08:00
Earle F. Philhower, III b6cb2e7edc Avoid race condition in I2S/PWMAudio delete (#1163)
Fixes #1162

Disable DMA interrupts while we're tearing down an AudioBufferManager
and explicitly clear any potential leftover IRQs to avoid hangs.
2023-02-09 13:29:45 -08:00
Earle F. Philhower, III bedcbf57c6 Add ESP8266/32 WiFi.isConnected wrapper (#1166)
Fixes #1165
2023-02-09 08:39:35 -08:00
TomKong666 7df080ee92 PDM library re-port (#1160)
See #1156
2023-02-07 08:10:24 -08:00
Earle F. Philhower, III b400897ca2 Avoid initial glitch on Serial1/2 when RX high (#1154)
Fixes #1153

Set up the GPIO redirects before the UART is pulled from reset to avoid
a possible bad byte at `Serial1/2.begin()`.
2023-02-01 19:15:58 -08:00
uPesy Electronics 7573500e59 Add uPesy Tutorials using Arduino Pico port. (#1151) 2023-02-01 06:52:25 -08:00
Vishnu Mohanan 8a1e03739a Fix SPI transfer16 return value (#1148)
The SPI transfer16() function returned wrongly oriented bytes. Replaced reverseByte() with reverse16Bit().

Fixes #1146
2023-01-31 08:09:53 -08:00
Earle F. Philhower, III a1af9698ac Fix USB VID/PID setting, rationalize boards.txt (#1144)
The USB VID was always being set to the Raspberry Pi foundation code,
causing other brand boards to show up incorrectly.

Remove redundant values from the boards.txt and define a consistent
USB VID/PID and use it in the setup code.

See #1129 for more info
2023-01-28 11:10:39 -08:00
Earle F. Philhower, III af01c3cc77 Add boot2_w25q128jv to generic Pico flash menu (#1142)
Add-on to #1126
2023-01-26 16:35:16 -08:00
Earle F. Philhower, III 4c8bdc2bfc Print useful uf2conv error if executable not found (#1141)
Fixes #1140

````
Converting to uf2, output size: 134144, start address: 0x2000
ERROR: Unable to execute powershell or wmic commands, can't continue.
ERROR: Please make sure either PowerShell or WMIC is installed and in
       your %PATH%.
````
2023-01-26 11:02:07 -08:00
Conor Burns c58f94a9ba Add correct boot source to helios (#1126) 2023-01-25 14:45:51 -08:00
Earle F. Philhower, III ecaa2bd778 Fix SerialUART::overflow reporting race condition (#1133)
Fixes #1132
2023-01-21 01:38:15 -08:00
Earle F. Philhower, III d619bf0bc1 More minor ESP8266 compatibility tweaks (#1131) 2023-01-20 17:06:40 -08:00
Gavin Hurlbut 9a241b0e43 Add Serial UART break reporting (#1130)
Added SerialUART::getBreakReceived()
2023-01-20 16:54:31 -08:00
Earle F. Philhower, III e3f2f87e2d Add more ESP8266 WiFi compatibility wrappers (#1128) 2023-01-19 12:44:05 -08:00
Earle F. Philhower, III a8238cb0d4 Add the YD-RP2040 support files
Oops!
2023-01-19 07:57:26 -08:00
172 changed files with 10855 additions and 1421 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
url = https://github.com/earlephilhower/ArduinoCore-API.git
[submodule "pico-sdk"]
path = pico-sdk
url = https://github.com/earlephilhower/pico-sdk.git
url = https://github.com/raspberrypi/pico-sdk.git
[submodule "system/pyserial"]
path = tools/pyserial
url = https://github.com/pyserial/pyserial.git
+8 -1
View File
@@ -9,6 +9,9 @@ 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
@@ -160,7 +163,8 @@ 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
@@ -191,6 +195,9 @@ Here are some links to coverage and additional tutorials for using `arduino-pico
* 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.
+1004 -452
View File
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
+3
View File
@@ -107,6 +107,9 @@ extern bool __isFreeRTOS;
#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"
+17 -19
View File
@@ -27,6 +27,7 @@
#include <hardware/structs/rosc.h>
#include <hardware/structs/systick.h>
#include <pico/multicore.h>
#include <pico/rand.h>
#include <pico/util/queue.h>
#include "CoreMutex.h"
#include "ccount.pio.h"
@@ -246,6 +247,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() {
@@ -336,28 +342,20 @@ public:
_MFIFO fifo;
// TODO - Not so great HW random generator. 32-bits wide. Cryptographers somewhere are crying
uint32_t hwrand32() {
// Try and whiten the HW ROSC bit
uint32_t r = 0;
for (int k = 0; k < 32; k++) {
unsigned long int b;
do {
b = rosc_hw->randombit & 1;
if (b != (rosc_hw->randombit & 1)) {
break;
}
} while (true);
r <<= 1;
r |= b;
}
// Stir using the cycle count LSBs. In any WiFi use case this will be a random # since the connection time is not cycle-accurate
uint64_t rr = (((uint64_t)~r) << 32LL) | r;
rr >>= rp2040.getCycleCount() & 32LL;
return (uint32_t)rr;
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;
+6 -7
View File
@@ -46,12 +46,11 @@ mutex_t __usb_mutex;
#define USB_TASK_INTERVAL 1000
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
@@ -302,15 +301,15 @@ void __SetupUSBDescriptor() {
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
+4 -4
View File
@@ -1,5 +1,5 @@
#pragma once
#define ARDUINO_PICO_MAJOR 2
#define ARDUINO_PICO_MINOR 7
#define ARDUINO_PICO_REVISION 1
#define ARDUINO_PICO_VERSION_STR "2.7.1"
#define ARDUINO_PICO_MAJOR 3
#define ARDUINO_PICO_MINOR 0
#define ARDUINO_PICO_REVISION 0
#define ARDUINO_PICO_VERSION_STR "3.0.0"
+53 -18
View File
@@ -134,6 +134,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,18 +185,6 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
break;
}
uart_set_format(_uart, bits, stop, parity);
_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_set_hw_flow(_uart, _rts != UART_PIN_NOT_DEFINED, _cts != UART_PIN_NOT_DEFINED);
_writer = 0;
_reader = 0;
@@ -200,6 +202,7 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
} else {
// Polling mode has no IRQs used
}
_break = false;
_running = true;
}
@@ -288,13 +291,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() {
@@ -365,6 +377,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();
@@ -391,8 +422,12 @@ void __not_in_flash_func(SerialUART::_handleIRQ)(bool inIRQ) {
uart_get_hw(_uart)->icr = UART_UARTICR_RTIC_BITS | UART_UARTICR_RXIC_BITS;
while (uart_is_readable(_uart)) {
uint32_t raw = uart_get_hw(_uart)->dr;
if (raw & 0x700) {
// Framing, Parity, or Break. Ignore this bad char
if (raw & 0x400) {
// break!
_break = true;
continue;
} else if (raw & 0x300) {
// Framing, Parity Error. Ignore this bad char
continue;
}
uint8_t val = raw & 0xff;
+10
View File
@@ -63,9 +63,18 @@ 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;
@@ -76,6 +85,7 @@ private:
mutex_t _mutex;
bool _polling = false;
bool _overflow;
bool _break;
// Lockless, IRQ-handled circular queue
uint32_t _writer;
+13 -1
View File
@@ -33,6 +33,7 @@
#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
@@ -174,11 +175,22 @@ SerialUSB::operator bool() {
static bool _dtr = false;
static bool _rts = false;
static int _bps = 115200;
static bool _rebooting = false;
static void CheckSerialReset() {
if ((_bps == 1200) && (!_dtr)) {
__holdUpPendSV = 1; // Ensure we don't get swapped out by FreeRTOS
if (!_rebooting && (_bps == 1200) && (!_dtr)) {
_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.
sleep_ms(3);
reset_usb_boot(0, 0);
while (1); // WDT will fire here
}
__holdUpPendSV = 0;
}
extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
+5
View File
@@ -44,6 +44,11 @@ public:
using Print::write;
operator bool() override;
// ESP8266 compat
void setDebugOutput(bool unused) {
(void) unused;
}
private:
bool _running = false;
};
+7 -2
View File
@@ -28,7 +28,7 @@ typedef struct {
} FMMap;
static FMMap *_map = nullptr;
extern "C" SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m) {
SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive) {
if (!_map) {
_map = (FMMap *)calloc(sizeof(FMMap), 16);
}
@@ -42,7 +42,12 @@ extern "C" SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m) {
for (int i = 0; i < 16; i++) {
if (_map[i].src == nullptr) {
// Make a new mutex
SemaphoreHandle_t fm = __freertos_mutex_create();
SemaphoreHandle_t fm;
if (recursive) {
fm = _freertos_recursive_mutex_create();
} else {
fm = __freertos_mutex_create();
}
if (fm == nullptr) {
return nullptr;
}
+1 -1
View File
@@ -59,8 +59,8 @@ extern "C" {
extern void vTaskPreemptionEnable(TaskHandle_t p) __attribute__((weak));
#endif
extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m);
}
extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive = false);
// Halt the FreeRTOS PendSV task switching magic
extern "C" int __holdUpPendSV;
+104
View File
@@ -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
+6
View File
@@ -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
+16 -4
View File
@@ -80,7 +80,7 @@ static SemaphoreHandle_t __getFreeRTOSMutex(_LOCK_T lock) {
} else if (l == &__lock___arc4random_mutex) {
return __lock___arc4random_mutex_freertos;
}
return nullptr;
return __get_freertos_mutex_for_ptr(l, false);
}
static SemaphoreHandle_t __getFreeRTOSRecursiveMutex(_LOCK_T lock) {
@@ -96,12 +96,18 @@ static SemaphoreHandle_t __getFreeRTOSRecursiveMutex(_LOCK_T lock) {
} else if (l == &__lock___env_recursive_mutex) {
return __lock___env_recursive_mutex_freertos;
}
return nullptr;
return __get_freertos_mutex_for_ptr((mutex_t *)l, true);
}
void __retarget_lock_init(_LOCK_T *lock) {
if (__freeRTOSinitted) {
/* Already done in initFreeRTOSMutexes() */
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);
}
@@ -109,7 +115,13 @@ void __retarget_lock_init(_LOCK_T *lock) {
void __retarget_lock_init_recursive(_LOCK_T *lock) {
if (__freeRTOSinitted) {
/* Already done in initFreeRTOSMutexes() */
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);
}
+17 -32
View File
@@ -18,45 +18,25 @@
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"
// Global indicator that we're inside an LWIP block
extern "C" {
volatile bool __inLWIP = false;
}
auto_init_recursive_mutex(__mtxLWIP);
#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() {
noInterrupts();
recursive_mutex_enter_blocking(&__mtxLWIP);
__inLWIP = true;
_ref++;
interrupts();
cyw43_arch_lwip_begin();
}
~LWIPMutex() {
noInterrupts();
if (0 == --_ref) {
__inLWIP = false;
}
recursive_mutex_exit(&__mtxLWIP);
interrupts();
cyw43_arch_lwip_end();
}
private:
static int _ref;
};
int LWIPMutex::_ref = 0;
extern "C" {
@@ -275,10 +255,15 @@ extern "C" {
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
auto_init_mutex(__sys_check_timeouts_mtx);
extern void __real_sys_check_timeouts(void);
void __wrap_sys_check_timeouts(void) {
LWIPMutex m;
__real_sys_check_timeouts();
uint32_t owner;
if (mutex_try_enter(&__sys_check_timeouts_mtx, &owner)) {
__real_sys_check_timeouts();
mutex_exit(&__sys_check_timeouts_mtx);
}
}
extern err_t __real_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg);
+27
View File
@@ -170,3 +170,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,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
@@ -1,348 +0,0 @@
/*
Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
SPDX-License-Identifier: BSD-3-Clause
*/
// Taken from the Pico-SDK v1.4.0 and hacked by EFP3 to allow overriding the LWIP setup
//#include <stdio.h>
#include "pico/cyw43_arch.h"
#include "pico/mutex.h"
#include "pico/sem.h"
#include "hardware/gpio.h"
#include "hardware/irq.h"
#include "cyw43_stats.h"
#include <lwip/init.h>
#include "lwip/timeouts.h"
#ifndef CYW43_PIN_WL_HOST_WAKE
#define CYW43_PIN_WL_HOST_WAKE 24
#endif
#ifndef CYW43_PIN_WL_REG_ON
#define CYW43_PIN_WL_REG_ON 23
#endif
#ifndef CYW43_WL_GPIO_COUNT
#define CYW43_WL_GPIO_COUNT 3
#endif
#ifndef CYW43_WL_GPIO_LED_PIN
#define CYW43_WL_GPIO_LED_PIN 0
#endif
extern volatile bool __inLWIP;
// note same code
#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND
#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND && CYW43_LWIP && !NO_SYS
#error PICO_CYW43_ARCH_THREADSAFE_BACKGROUND requires lwIP NO_SYS=1
#endif
#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND && CYW43_LWIP && MEM_LIBC_MALLOC
#error MEM_LIBC_MALLOC is incompatible with PICO_CYW43_ARCH_THREADSAFE_BACKGROUND
#endif
// todo right now we are now always doing a cyw43_dispatch along with a lwip one when hopping cores in low_prio_irq_schedule_dispatch
#ifndef CYW43_SLEEP_CHECK_MS
#define CYW43_SLEEP_CHECK_MS 50 // How often to run lwip callback
#endif
static alarm_id_t periodic_alarm = -1;
static inline uint recursive_mutex_enter_count(recursive_mutex_t *mutex) {
return mutex->enter_count;
}
static inline lock_owner_id_t recursive_mutex_owner(recursive_mutex_t *mutex) {
return mutex->owner;
}
#define CYW43_GPIO_IRQ_HANDLER_PRIORITY 0x40
enum {
CYW43_DISPATCH_SLOT_CYW43 = 0,
CYW43_DISPATCH_SLOT_ADAPTER,
CYW43_DISPATCH_SLOT_ENUM_COUNT
};
#ifndef CYW43_DISPATCH_SLOT_COUNT
#define CYW43_DISPATCH_SLOT_COUNT CYW43_DISPATCH_SLOT_ENUM_COUNT
#endif
typedef void (*low_prio_irq_dispatch_t)(void);
static void low_prio_irq_schedule_dispatch(size_t slot, low_prio_irq_dispatch_t f);
static uint8_t cyw43_core_num;
#ifndef NDEBUG
static bool in_low_priority_irq;
#endif
static uint8_t low_priority_irq_num;
static bool low_priority_irq_missed;
static low_prio_irq_dispatch_t low_priority_irq_dispatch_slots[CYW43_DISPATCH_SLOT_COUNT];
static recursive_mutex_t cyw43_mutex;
semaphore_t cyw43_irq_sem;
// Called in low priority pendsv interrupt only to do lwip processing and check cyw43 sleep
static void periodic_worker(void) {
#if CYW43_USE_STATS && LWIP_SYS_CHECK_MS
static uint32_t counter;
if (counter++ % (30000 / LWIP_SYS_CHECK_MS) == 0) {
cyw43_dump_stats();
}
#endif
CYW43_STAT_INC(LWIP_RUN_COUNT);
//#if CYW43_LWIP
if (!__inLWIP) {
sys_check_timeouts();
}
//#endif
if (cyw43_poll) {
if (cyw43_sleep > 0) {
if (--cyw43_sleep == 0) {
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
}
}
}
}
// Regular callback to get lwip to check for timeouts
static int64_t periodic_alarm_handler(__unused alarm_id_t id, __unused void *user_data) {
// Do lwip processing in low priority pendsv interrupt
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_ADAPTER, periodic_worker);
return CYW43_SLEEP_CHECK_MS * 1000;
}
void cyw43_await_background_or_timeout_us(uint32_t timeout_us) {
// if we are called from within an IRQ, then don't wait (we are only ever called in a polling loop)
if (!__get_current_exception()) {
sem_acquire_timeout_us(&cyw43_irq_sem, timeout_us);
}
}
// GPIO interrupt handler to tell us there's cyw43 has work to do
static void gpio_irq_handler(void) {
uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE);
if (events & GPIO_IRQ_LEVEL_HIGH) {
// As we use a high level interrupt, it will go off forever until it's serviced
// So disable the interrupt until this is done. It's re-enabled again by CYW43_POST_POLL_HOOK
// which is called at the end of cyw43_poll_func
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
// also clear the force bit which we use to progratically cause this handler to fire (on the right core)
io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
&iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
hw_clear_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE / 8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7)));
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
CYW43_STAT_INC(IRQ_COUNT);
}
}
// Low priority interrupt handler to perform background processing
static void low_priority_irq_handler(void) {
assert(cyw43_core_num == get_core_num());
if (recursive_mutex_try_enter(&cyw43_mutex, NULL)) {
if (__inLWIP || (recursive_mutex_enter_count(&cyw43_mutex) != 1)) {
low_priority_irq_missed = true;
CYW43_STAT_INC(PENDSV_DISABLED_COUNT);
} else {
CYW43_STAT_INC(PENDSV_RUN_COUNT);
#ifndef NDEBUG
in_low_priority_irq = true;
#endif
for (size_t i = 0; i < count_of(low_priority_irq_dispatch_slots); i++) {
if (low_priority_irq_dispatch_slots[i] != NULL) {
low_prio_irq_dispatch_t f = low_priority_irq_dispatch_slots[i];
low_priority_irq_dispatch_slots[i] = NULL;
f();
}
}
#ifndef NDEBUG
in_low_priority_irq = false;
#endif
}
recursive_mutex_exit(&cyw43_mutex);
} else {
CYW43_STAT_INC(PENDSV_DISABLED_COUNT);
low_priority_irq_missed = true;
}
sem_release(&cyw43_irq_sem);
}
static bool low_prio_irq_init(uint8_t priority) {
assert(get_core_num() == cyw43_core_num);
int irq = user_irq_claim_unused(false);
if (irq < 0) {
return false;
}
low_priority_irq_num = (uint8_t) irq;
irq_set_exclusive_handler(low_priority_irq_num, low_priority_irq_handler);
irq_set_enabled(low_priority_irq_num, true);
irq_set_priority(low_priority_irq_num, priority);
return true;
}
static void low_prio_irq_deinit(void) {
if (low_priority_irq_num > 0) {
irq_set_enabled(low_priority_irq_num, false);
irq_remove_handler(low_priority_irq_num, low_priority_irq_handler);
user_irq_unclaim(low_priority_irq_num);
low_priority_irq_num = 0;
}
}
int cyw43_arch_init(void) {
cyw43_core_num = get_core_num();
recursive_mutex_init(&cyw43_mutex);
cyw43_init(&cyw43_state);
sem_init(&cyw43_irq_sem, 0, 1);
// Start regular lwip callback to handle timeouts
periodic_alarm = add_alarm_in_us(CYW43_SLEEP_CHECK_MS * 1000, periodic_alarm_handler, NULL, true);
if (periodic_alarm < 0) {
return PICO_ERROR_GENERIC;
}
gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_GPIO_IRQ_HANDLER_PRIORITY);
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
irq_set_enabled(IO_IRQ_BANK0, true);
lwip_init();
// start low priority handler (no background work is done before this)
bool ok = low_prio_irq_init(PICO_LOWEST_IRQ_PRIORITY);
if (!ok) {
cyw43_arch_deinit();
return PICO_ERROR_GENERIC;
}
return PICO_OK;
}
void cyw43_arch_deinit(void) {
if (periodic_alarm >= 0) {
cancel_alarm(periodic_alarm);
periodic_alarm = -1;
}
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
gpio_remove_raw_irq_handler(IO_IRQ_BANK0, gpio_irq_handler);
low_prio_irq_deinit();
}
void cyw43_post_poll_hook(void) {
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
}
// This is called in the gpio and low_prio_irq interrupts and on either core
static void low_prio_irq_schedule_dispatch(size_t slot, low_prio_irq_dispatch_t f) {
assert(slot < count_of(low_priority_irq_dispatch_slots));
low_priority_irq_dispatch_slots[slot] = f;
if (cyw43_core_num == get_core_num()) {
//on same core, can dispatch directly
irq_set_pending(low_priority_irq_num);
} else {
// on wrong core, so force via GPIO IRQ which itself calls this method for the CYW43 slot.
// since the CYW43 slot always uses the same function, this is fine with the addition of an
// extra (but harmless) CYW43 slot call when another SLOT is invoked.
// We could do better, but would have to track why the IRQ was called.
io_irq_ctrl_hw_t *irq_ctrl_base = cyw43_core_num ?
&iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
hw_set_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE / 8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7)));
}
}
void cyw43_schedule_internal_poll_dispatch(void (*func)(void)) {
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, func);
}
// Prevent background processing in pensv and access by the other core
// These methods are called in pensv context and on either core
// They can be called recursively
void cyw43_thread_enter(void) {
// Lock the other core and stop low_prio_irq running
recursive_mutex_enter_blocking(&cyw43_mutex);
}
#ifndef NDEBUG
void cyw43_thread_lock_check(void) {
// Lock the other core and stop low_prio_irq running
if (recursive_mutex_enter_count(&cyw43_mutex) < 1 || recursive_mutex_owner(&cyw43_mutex) != lock_get_caller_owner_id()) {
panic("cyw43_thread_lock_check failed");
}
}
#endif
// Re-enable background processing
void cyw43_thread_exit(void) {
// Run low_prio_irq if needed
if (1 == recursive_mutex_enter_count(&cyw43_mutex)) {
// note the outer release of the mutex is not via cyw43_exit in the low_priority_irq case (it is a direct mutex exit)
assert(!in_low_priority_irq);
// if (low_priority_irq_missed) {
// low_priority_irq_missed = false;
if (low_priority_irq_dispatch_slots[CYW43_DISPATCH_SLOT_CYW43]) {
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
}
// }
}
recursive_mutex_exit(&cyw43_mutex);
}
static void cyw43_delay_until(absolute_time_t until) {
// sleep can be called in IRQs, so there's not much we can do there
if (__get_current_exception()) {
busy_wait_until(until);
} else {
sleep_until(until);
}
}
void cyw43_delay_ms(uint32_t ms) {
cyw43_delay_until(make_timeout_time_ms(ms));
}
void cyw43_delay_us(uint32_t us) {
cyw43_delay_until(make_timeout_time_us(us));
}
void cyw43_arch_poll() {
// should not be necessary
// if (cyw43_poll) {
// low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
// }
}
#ifdef ARDUINO_RASPBERRY_PI_PICO_W
void __attribute__((weak)) cyw43_cb_tcpip_init(cyw43_t *self, int itf);
void cyw43_cb_tcpip_init(cyw43_t *self, int itf) {
(void) self;
(void) itf;
}
void __attribute__((weak)) cyw43_cb_tcpip_deinit(cyw43_t *self, int itf);
void cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) {
(void) self;
(void) itf;
}
void __attribute__((weak)) cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf);
void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
(void) self;
(void) itf;
}
void __attribute__((weak)) cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf);
void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
(void) self;
(void) itf;
}
void __attribute__((weak)) cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf);
void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
(void) cb_data;
(void) itf;
(void) len;
(void) buf;
}
#endif
#endif
+1 -1
View File
@@ -47,7 +47,7 @@ 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 wontinue to run at the new frequency). Note
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:
+2 -2
View File
@@ -14,12 +14,12 @@ 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 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
+49
View File
@@ -0,0 +1,49 @@
Bluetooth on PicoW Support
==========================
As of the Pico-SDK version 1.5.0, the PicoW has **BETA** Bluetooth support.
So, since this core builds off the SDK the best that can be suggested it
that we have **ALPHA** Bluetooth support. As such, bug reports are welcome,
but Pull Requests fixing problems you find are seriously appreciated.
Enabling Bluetooth
------------------
To enable Bluetooth (BT), use the ``Tools->IP/Bluetooth Stack`` menu. It
requires around 80KB of flash and 20KB of RAM when enabled.
Both Bluetooth Classic and BluetoothBLE are enabled in ``btstack_config.h``.
Included Bluetooth Libraries
----------------------------
You may use the ``KeyboardBT``, ``MouseBT``, or ``JoystickBT`` to emulate a
Bluetooth Classic HID device using the same API as their USB versions.
You may use the ``KeyboardBLE``, ``MouseBLE``, or ``JoystickBLE`` to emulate a
Bluetooth Low Energy (BLE) HID device using the same API as their USB versions.
The ``SerialBT`` library implements a very simple SPP (Serial Port Profile)
Serial-compatible port.
Writing Custom Bluetooth Applications
-------------------------------------
You may also write full applications using the ``BTStack`` standard callback
method, but please be aware that the Raspberry Pi team has built an
interrupt-driven version of the BT execute loop, so there is no need
to actually call ``btstack_run_loop_execute`` because the ``async_context``
handler will do it for you.
There is no need to call ``cyw43_arch_init`` in your code, either, as that
is part of the PicoW variant booting process.
For many BTStack examples, you simply need call the included
``btstack_main()`` and make sure that ``hci_power_control(HCI_POWER_ON);`` is
called afterwards to start processing (in the background).
You will also need to acquire the BT ``async_context`` system lock before
calling any BTStack APIs. See the ``libraries/PicoBluetoothHID`` helper
class for an example of how to do this.
Note that if you need to modify the system ``btstack_config.h`` file, do so
in the ``tools/libpico`` directory and rebuild the Pico SDK static library.
Otherwise the change will not take effect in the precompiled code, leading
to really bad behavior.
+2 -2
View File
@@ -54,9 +54,9 @@ author = u'Earle F. Philhower, III'
# built documents.
#
# The short X.Y version.
version = u'2.7.1'
version = u'3.0.0'
# The full version, including alpha/beta/rc tags.
release = u'2.7.1'
release = u'3.0.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
+99
View File
@@ -0,0 +1,99 @@
Contributing and Porting to the Core
====================================
First of all, thank you for contributing to the project. It's a lot of work
keeping up with all the different uses of the RP2040, so the more people
working on the code, the better. Your assistance can help the project
succeed.
Contributing to the Core (Pull Requests)
----------------------------------------
We use the standard GitHub Pull Request model. If you're unfamiliar with it,
this `guide <https://www.freecodecamp.org/news/how-to-make-your-first-pull-request-on-github-3/>` gives a simple overview of the process.
All pull requests have to pass a set of Continuous Integration (CI) checks
which help make sure the code compiles under different configurations and has
no spelling or style errors.
Tips for a Good Pull Request (PR)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All code in the core and libraries, except for INO sketches, uses a 4-space
indent with cuddled brackets. When in doubt, copy your formatting from the
surrounding code. You should install ``astyle`` and run ``tests/restyle.sh``
on your machine before committing and pushing any pull requests to ensure
the formatting is correct.
Describe the change you're proposing and why it's important in your
``git commit`` message. If it fixes an open issue, place ``Fixes #xxxx``
(where xxxx is the issue number) in the message to link the two.
Try and only change one thing per pull request. That makes it easier to
review and prioritize. Opening up a separate PR per change also helps keep
track of them when release messages are generated.
Adding a New Board
------------------
Adding a new board requires:
* Updated ``tools/makeboards.py`` script
* Updated ``boards.txt`` file, generated by ``makeboard.py``
* Updated ``package_pico_index.template.json`` file, generated by ``makeboard.py``
* New ``tools/json/BOARD_NAME.json`` board file for Platform.IO
* New ``variants/BOARD_NAME/pins_arduino.h`` header defining the I/O pins
To add a new RP2040 board you will need to update the ``tools/makeboards.py``
script. Do *NOT* manually edit ``boards.txt``, that file is machine generated.
You will need to add a ``MakeBoard`` call at the end of the file. Please be sure
to add your board so that it sorts alphabetically, starting with the company name
and then the board name. Otherwise it is hard to find a specific board in the menu.
Run ``python3 tools/makeboards.py`` to update the ``boards.txt`` file and generate
a Platform.IO JSON file in the ``tools/json`` directory.
Create a folder called ``variants/BOARD_NAME`` and place in a ``pins_arduino.h``
file in it that contains your default pin name mapping (i.e. SPI0/1 pins, UART
pins, LED_DEFAULT, etc.). Copying one of the existing ones as a template can
make this task much simpler.
In your ``git commit`` be sure to add the newly generated ``tools/json/XXX.json``
file as well as the modified ``makeboards`` script and ``boards.txt``, the new
``pins_arduino.h`` header you generated, and the Arduino packaging JSON
``package/package_pico_index.template.json``. You should also add a note in
the ``README.md`` file listing your new board.
Submit the updated commit as a PR and, if all goes well, your board will be in
on the next core release.
Porting Libraries and Applications to the Core
----------------------------------------------
We try and follow Arduino standards so, with luck, porting to this core should
be relatively straightforward. The ``WiFi`` library and associates support
libraries like ``WebServer`` are modeled after the ESP32 and ESP8266 versions
of those libraries, combined with the "standard" Arduino ``WiFi`` one.
Compiler Defines for Porting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are adding RP2040 support to an existing library and need to isolate
code that only runs on this core, use the following define.
.. code:: cpp
#if defined(ARDUINO_ARCH_RP2040)
~~~ your changes ~~~
#endif
Library Architectures
~~~~~~~~~~~~~~~~~~~~~
After adding support in the code, libraries need their ``library.properties``
and ``library.json`` files updated to indicate support, or the IDE will
not know your new code is compatible here.
Add ``rp2040`` to ``architectures`` (in ``library.properties``) and
``"rp2040"`` to ``platforms[]`` (in ``library.json``) to let the tools know.
+2 -2
View File
@@ -1,5 +1,5 @@
Getting Help and Contributing
=============================
Getting Help
============
This is a community supported project and has multiple ways to get assistance.
Posting complete details, in a polite and organized way will get the best
+5 -1
View File
@@ -16,7 +16,9 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
:maxdepth: 2
:caption: Contents:
Getting Help and Contributing <help>
Getting Help <help>
Contributing <contrib>
Installation <install>
IDE Menus <ide>
@@ -41,6 +43,8 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
USB (Arduino and Adafruit_TinyUSB) <usb>
Multicore Processing <multicore>
Bluetooth (Alpha/Beta) <bluetooth>
Single File USB Drive <singlefile>
FreeRTOS SMP (multicore) <freertos>
+18 -2
View File
@@ -13,6 +13,10 @@ Returns the current frequency of the core clock. This is read at runtime,
versus the constant ``F_CPU`` macro that is also available. This is useful
in cases where your code changes the core clock (i.e. low power modes, etc.)
int rp2040.cpuid()
~~~~~~~~~~~~~~~~~~
Returns the current core ID (0 or 1) of the executing task.
uint32_t rp2040.getCycleCount()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Returns a 32-bit cycle count from then the core started running. Because it
@@ -41,13 +45,16 @@ Hardware Watchdog
-----------------
void rp2040.wdt_begin(uint32_t delay_ms)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Enables the hardware watchdog timer with a delay value of delay_ms
milliseconds. Note that on the RP2040, once this function has called, the
hardware watchdog can _not_ be disabled.
The maximum ``delay_ms`` allowed in this call is ``8300``, corresponding
to 8.3 seconds. Any higher values will be truncated by the hardware.
void rp2040.wdt_reset()
~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
Reloads the watchdog's counter with the amount of time set by wdt_begin.
@@ -71,6 +78,15 @@ Returns the total heap that was available to this program at compile time (i.e.
the Pico RAM size minus things like the ``.data`` and ``.bss`` sections and other
overhead).
Hardware Identification
-----------------------
bool isPicoW()
~~~~~~~~~~~~~~
Returns the core's best guess if this code is running on a Raspberry Pi Pico W.
This would let you, possibly, use the same UF2 for Pico and PicoW by simply not
doing any WiFi calls.
Bootloader
----------
+74
View File
@@ -0,0 +1,74 @@
#pragma once
// BTstack features that can be enabled
#define ENABLE_LOG_INFO
#define ENABLE_LOG_ERROR
#define ENABLE_PRINTF_HEXDUMP
#define ENABLE_SCO_OVER_HCI
#ifdef ENABLE_CLASSIC
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
#endif
#ifdef ENABLE_BLE
#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_CENTRAL
#endif
// BTstack configuration. buffers, sizes, ...
#define HCI_OUTGOING_PRE_BUFFER_SIZE 4
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4
#define MAX_NR_AVDTP_CONNECTIONS 1
#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
#define MAX_NR_AVRCP_CONNECTIONS 2
#define MAX_NR_BNEP_CHANNELS 1
#define MAX_NR_BNEP_SERVICES 1
#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
#define MAX_NR_GATT_CLIENTS 1
#define MAX_NR_HCI_CONNECTIONS 2
#define MAX_NR_HID_HOST_CONNECTIONS 1
#define MAX_NR_HIDS_CLIENTS 1
#define MAX_NR_HFP_CONNECTIONS 1
#define MAX_NR_L2CAP_CHANNELS 4
#define MAX_NR_L2CAP_SERVICES 3
#define MAX_NR_RFCOMM_CHANNELS 1
#define MAX_NR_RFCOMM_MULTIPLEXERS 1
#define MAX_NR_RFCOMM_SERVICES 1
#define MAX_NR_SERVICE_RECORD_ITEMS 4
#define MAX_NR_SM_LOOKUP_ENTRIES 3
#define MAX_NR_WHITELIST_ENTRIES 16
#define MAX_NR_LE_DEVICE_DB_ENTRIES 16
// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun
#define MAX_NR_CONTROLLER_ACL_BUFFERS 3
#define MAX_NR_CONTROLLER_SCO_PACKETS 3
// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun
#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
#define HCI_HOST_ACL_PACKET_LEN 1024
#define HCI_HOST_ACL_PACKET_NUM 3
#define HCI_HOST_SCO_PACKET_LEN 120
#define HCI_HOST_SCO_PACKET_NUM 3
// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
#define NVM_NUM_DEVICE_DB_ENTRIES 16
#define NVM_NUM_LINK_KEYS 16
// We don't give btstack a malloc, so use a fixed-size ATT DB.
#define MAX_ATT_DB_SIZE 512
// BTstack HAL configuration
#define HAVE_EMBEDDED_TIME_MS
// map btstack_assert onto Pico SDK assert()
#define HAVE_ASSERT
// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
#define HCI_RESET_RESEND_TIMEOUT_MS 1000
#define ENABLE_SOFTWARE_AES128
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#undef HAVE_BTSTACK_STDIN
+4 -1
View File
@@ -13,6 +13,9 @@ extern void interrupts();
#define SYS_ARCH_PROTECT(lev) noInterrupts
#define SYS_ARCH_UNPROTECT(lev) interrupts
extern unsigned long get_rand_32(void);
#define LWIP_RAND() get_rand_32()
// Common settings used in most of the pico_w examples
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
@@ -25,7 +28,7 @@ extern void interrupts();
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ARP 2
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
+2 -2
View File
@@ -12,8 +12,8 @@
#define _PICO_VERSION_H
#define PICO_SDK_VERSION_MAJOR 1
#define PICO_SDK_VERSION_MINOR 4
#define PICO_SDK_VERSION_MINOR 5
#define PICO_SDK_VERSION_REVISION 0
#define PICO_SDK_VERSION_STRING "1.4.0"
#define PICO_SDK_VERSION_STRING "1.5.0"
#endif
+2
View File
@@ -44,6 +44,8 @@ restartCore1 KEYWORD2
reboot KEYWORD2
restart KEYWORD2
isPicoW KEYWORD2
getChipID KEYWORD2
hwrand32 KEYWORD2
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10 -6
View File
@@ -191,11 +191,6 @@ SECTIONS
__data_end__ = .;
} > RAM AT> FLASH
.uninitialized_data (COPY): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
/* Start and end symbols must be word-aligned */
.scratch_x : {
__scratch_x_start__ = .;
@@ -213,7 +208,7 @@ SECTIONS
} > SCRATCH_Y AT > FLASH
__scratch_y_source__ = LOADADDR(.scratch_y);
.bss : {
.bss : {
. = ALIGN(4);
__bss_start__ = .;
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
@@ -222,6 +217,15 @@ SECTIONS
__bss_end__ = .;
} > RAM
/* At most one of the following two will be engaged, depending on the SDK version */
.uninitialized_ram MAX(0x20003000, .) (NOLOAD) : {
*(.uninitialized_ram*)
} > RAM
.uninitialized_data MAX(0x20003000, .) (NOLOAD) : {
*(.uninitialized_data*)
} > RAM
.heap (COPY):
{
__end__ = .;
BIN
View File
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
source [find interface/cmsis-dap.cfg]
adapter speed 5000
source [find target/rp2040.cfg]
+6
View File
@@ -40,8 +40,11 @@
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_vreg/include
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_watchdog/include
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_xosc/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_async_context/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_bootrom/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_btstack/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_cyw43_arch/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_cyw43_driver/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_double/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_float/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_int64_ops/include
@@ -50,8 +53,11 @@
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_platform/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_printf/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_runtime/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_rand/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio_uart/include
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_unique_id/include
-iwithprefixbefore/pico-sdk/lib/cyw43-driver/src
-iwithprefixbefore/pico-sdk/lib/lwip/src/include
-iwithprefixbefore/pico-sdk/lib/btstack/src
-iwithprefixbefore/pico-sdk/lib/btstack/platform/embedded
+7
View File
@@ -200,3 +200,10 @@
-Wl,--wrap=raw_bind
-Wl,--wrap=raw_sendto
-Wl,--wrap=raw_remove
-Wl,--wrap=cyw43_cb_process_ethernet
-Wl,--wrap=cyw43_cb_tcpip_set_link_up
-Wl,--wrap=cyw43_cb_tcpip_set_link_down
-Wl,--wrap=cyw43_tcpip_link_status
-Wl,--wrap=cyw43_cb_tcpip_init
-Wl,--wrap=cyw43_cb_tcpip_deinit
@@ -69,6 +69,7 @@ AudioBufferManager::AudioBufferManager(size_t bufferCount, size_t bufferWords, i
}
AudioBufferManager::~AudioBufferManager() {
noInterrupts();
if (_running) {
_running = false;
for (auto i = 0; i < 2; i++) {
@@ -76,6 +77,7 @@ AudioBufferManager::~AudioBufferManager() {
__channelMap[_channelDMA[i]] = nullptr;
dma_channel_abort(_channelDMA[i]);
dma_channel_unclaim(_channelDMA[i]);
dma_channel_acknowledge_irq0(_channelDMA[i]);
}
__channelCount--;
if (!__channelCount) {
@@ -84,6 +86,7 @@ AudioBufferManager::~AudioBufferManager() {
irq_remove_handler(DMA_IRQ_0, _irq);
}
}
interrupts();
for (int i = 0; i < 2; i++) {
if (_active[i] != _silence) {
_deleteAudioBuffer(_active[i]);
+29
View File
@@ -0,0 +1,29 @@
/**
simple demo to show sha1 calculation
*/
#include <Arduino.h>
#include <Hash.h>
void setup() {
Serial.begin(115200);
}
void loop() {
// usage as String
// SHA1:a9993e364706816aba3e25717850c26c9cd0d89d
Serial.print("SHA1:");
Serial.println(sha1("abc"));
// usage as ptr
// SHA1:a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
uint8_t hash[20];
sha1("test", &hash[0]);
Serial.print("SHA1:");
for (uint16_t i = 0; i < 20; i++) { Serial.printf("%02x", hash[i]); }
Serial.println();
delay(1000);
}
+23
View File
@@ -0,0 +1,23 @@
#######################################
# Syntax Coloring Map For Hash
#######################################
#######################################
# Library (KEYWORD3)
#######################################
Hash KEYWORD3 RESERVED_WORD
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
sha1 KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
+10
View File
@@ -0,0 +1,10 @@
name=Hash
version=1.0
author=Markus Sattler
maintainer=Markus Sattler
sentence=Generate Hash from data
paragraph=
category=Data Processing
url=
architectures=rp2040
dot_a_linkage=true
+96
View File
@@ -0,0 +1,96 @@
/**
* @file Hash.cpp
* @date 20.05.2015
* @author Markus Sattler
*
* Copyright (c) 2015 Markus Sattler. 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
*
*/
#include <Arduino.h>
#include <bearssl/bearssl_hash.h>
#include "Hash.h"
/**
* create a sha1 hash from data
* @param data uint8_t *
* @param size uint32_t
* @param hash uint8_t[20]
*/
void sha1(const uint8_t* data, uint32_t size, uint8_t hash[20]) {
br_sha1_context ctx;
#ifdef DEBUG_SHA1
os_printf("DATA:");
for(uint16_t i = 0; i < size; i++) {
os_printf("%02X", data[i]);
}
os_printf("\n");
os_printf("DATA:");
for(uint16_t i = 0; i < size; i++) {
os_printf("%c", data[i]);
}
os_printf("\n");
#endif
br_sha1_init(&ctx);
br_sha1_update(&ctx, data, size);
br_sha1_out(&ctx, hash);
#ifdef DEBUG_SHA1
os_printf("SHA1:");
for(uint16_t i = 0; i < 20; i++) {
os_printf("%02X", hash[i]);
}
os_printf("\n\n");
#endif
}
void sha1(const char* data, uint32_t size, uint8_t hash[20]) {
sha1((const uint8_t *) data, size, hash);
}
void sha1(const String& data, uint8_t hash[20]) {
sha1(data.c_str(), data.length(), hash);
}
String sha1(const uint8_t* data, uint32_t size) {
uint8_t hash[20];
String hashStr((const char*)nullptr);
hashStr.reserve(20 * 2 + 1);
sha1(&data[0], size, &hash[0]);
for(uint16_t i = 0; i < 20; i++) {
char hex[3];
snprintf(hex, sizeof(hex), "%02x", hash[i]);
hashStr += hex;
}
return hashStr;
}
String sha1(const char* data, uint32_t size) {
return sha1((const uint8_t*) data, size);
}
String sha1(const String& data) {
return sha1(data.c_str(), data.length());
}
+38
View File
@@ -0,0 +1,38 @@
/**
* @file Hash.h
* @date 20.05.2015
* @author Markus Sattler
*
* Copyright (c) 2015 Markus Sattler. 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 HASH_H_
#define HASH_H_
//#define DEBUG_SHA1
void sha1(const uint8_t* data, uint32_t size, uint8_t hash[20]);
void sha1(const char* data, uint32_t size, uint8_t hash[20]);
void sha1(const String& data, uint8_t hash[20]);
String sha1(const uint8_t* data, uint32_t size);
String sha1(const char* data, uint32_t size);
String sha1(const String& data);
#endif /* HASH_H_ */
+34
View File
@@ -0,0 +1,34 @@
:repository-owner: arduino-libraries
:repository-name: Joystick
= {repository-name} Library for Arduino (RP2040 based boards) =
This library allows an RaspberryPi RP2040 board to act as a Joystick when
Earle F. Philhower`s [arduino-pico](https://github.com/earlephilhower/arduino-pico)
Core is used.
It was forked from the original upstream USB Joystick library by Benjamin Aigner
== Acknowledgements / Credits ==
* [arduino-pico](https://github.com/earlephilhower/arduino-pico) Earle F. Philhower providing the Arduino Core, on which this library is based on, available under LGPL.
* [tinyUSB] (https://github.com/hathach/tinyusb) Ha Thach for providing tinyUSB under MIT license, which covers most of the USB functionality.
== License ==
Copyright (c) Benjamin Aigner <beni@asterics-foundation.org> 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
+435
View File
@@ -0,0 +1,435 @@
# Joystick library
## Methods
### `Joystick.begin()`
Must be called before starting using the Joystick emulation. To end control, use `Joystick.end()`.
#### Syntax
```
Joystick.begin()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
}
void loop() {
// Initialize the Joystick library when button is pressed
if (digitalRead(2) == LOW) {
Joystick.begin();
}
}
```
#### See also
* [Joystick.button()](#joystickbutton)
* [Joystick.end()](#joystickend)
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.position()](#joystickposition)
* [Joystick.X()](#joystickx)
* [Joystick.hat()](#joystickhat)
* [Joystick.use8bit()](#joystickuse8bit)
* [Joystick.useManualSend()](#joystickuseManualSend)
### `Joystick.button()`
Updates a button of the USB joystick.
#### Syntax
```
Joystick.button(1,true);
delay(250);
Joystick.button(1,false);
```
#### Parameters
* `button`: number of Joystick button, which status should be changed
* `val`: state of button, `true` for pressed, `false` for released
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
uint8_t i = 1; //counter for the button number 1-32
if (digitalRead(2) == LOW) { //if button is pressed
Joystick.button(i,true); //"press" the Joystick button
delay(250); //wait for 0.25s
Joystick.button(i,false); //"release" the Joystick button
i = i + 1; //increment & use next Joystick button number
if(i > 32) i = 1; //we have 32 buttons available, wrap-around
}
}
```
#### Notes
* Up to 32 buttons are available, numbered as button 1 to button 32.
* If manual_send is active, call `Joystick.send_now()` to send an update to the host.
#### See also
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.useManualSend()](#joystickuseManualSend)
* [Joystick.X()](#joystickx)
* [Joystick.hat()](#joystickhat)
### `Joystick.end()`
Stops emulating the Joystick connected to a computer. To start control, use `Joystick.begin()`.
#### Syntax
```
Joystick.end()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
// Initiate the Joystick library
Joystick.begin();
}
void loop() {
// If the button is pressed, send a button 1 press / release
if (digitalRead(2) == LOW) {
Joystick.button(1,true);
delay(250);
Joystick.button(1,false);
// Then end the Joystick emulation
Joystick.end();
}
}
```
#### See also
* [Joystick.begin()](#joystickbegin)
### `Joystick.use8bit()`
Switch axis value range between 10bit and 8bit.
* Default: 10bit, range for an axis from 0 to 1023
* 8bit mode: range from -127 to 127.
__Note:__ due to the gamepad descriptor of tinyUSB, the maximum range is -127/127. 10bit mode enables mapping, not a higher resolution.
#### Syntax
```
Joystick.use8bit(true)
```
#### Parameters
* `mode`: true, if values from -127/127 are used. False to use a range from 0 to 1023.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
//send middle position in default 10bit mode
Joystick.position(512,512);
delay(250);
//enable 8bit mode
Joystick.use8bit(true);
//send middle position in 8bit mode
Joystick.position(0,0);
delay(250);
//send maximum left in 10bit mode
Joystick.use8bit(false);
Joystick.position(0,0);
delay(250);
//enable 8bit mode
Joystick.use8bit(true);
//send left position in 8bit mode
Joystick.position(-127,-127);
}
```
#### See also
* [Joystick.position()](#joystickposition)
* [Joystick.X()](#joystickx)
* [Joystick.Y()](#joysticky)
* [Joystick.Z()](#joystickz)
* [Joystick.Zrotate()](#joystickrotate)
* [Joystick.slider()](#joystickslider)
* [Joystick.sliderLeft()](#joysticksliderleft)
* [Joystick.sliderRight()](#joysticksliderright)
### `Joystick.useManualSend()`
To fully control transmitting the USB-HID reports, enable manual sending.
If disabled, each call to a function updating the Joystick status (buttons, all axis, hat)
will send a HID report. If you update in a loop, the time between updates (at least 1ms) is too short and something might be not transmitted correctly.
If enabled, update all your axis values, buttons, hat and then send one report via `Joystick.send_now()`.
#### Syntax
```
Joystick.useManualSend(true)
```
#### Parameters
* `mode`: false is sending report each Joystick update, true enables manual sending via send_now().
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
if (digitalRead(2) == LOW) {
// send data in 4 different reports
Joystick.button(1,true);
Joystick.button(2,true);
Joystick.button(3,true);
Joystick.button(4,true);
//enable manual send
Joystick.useManualSend(true);
//send same data in one report
Joystick.button(1,false);
Joystick.button(2,false);
Joystick.button(3,false);
Joystick.button(4,false);
Joystick.send_now();
}
}
```
#### See also
* [Joystick.send_now()](#joysticksend_now)
### `Joystick.send_now()`
Send a HID report now. Used together with manual sending, see `Joystick.useManualSend()`.
#### Syntax
```
Joystick.send_now()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
//enable manual sending in setup
Joystick.useManualSend(true);
}
void loop() {
if (digitalRead(2) == LOW) {
// update all buttons, but nothing is sent to the host
for(uint8_t i = 1; i<=32; i++) Joystick.button(i,true);
Joystick.X(256);
Joystick.sliderLeft(0);
//now send in one HID report
Joystick.send_now();
}
}
```
#### See also
* [Joystick.useManualSend()](#joystickusemanualsend)
### `Joystick.X()`
Update X axis.
__Note:__ If [manual send](#joystickusemanualsend) is active, the value is sent to the host only after calling [send_now](#joysticksend_now).
__Note:__ If in 10bit mode (default), the parameter is interpreted from 0 to 1023.
In 8bit mode from -127 to 127. The internal resolution is always 8bit. Change setting with [use8bit](#joystickuse8bit).
#### Syntax
```
Joystick.X(0)
```
#### Parameters
* `val`: value from 0 to 1023 (default) or -127 to 127 (8bit mode)
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
if (digitalRead(2) == LOW) {
Joystick.X(256);
delay(500);
Joystick.X(512);
}
}
```
#### See also
* [Joystick.Y()](#joysticky)
* [Joystick.Z()](#joystickz)
* [Joystick.Zrotate()](#joystickrotate)
* [Joystick.slider()](#joystickslider)
* [Joystick.sliderLeft()](#joysticksliderleft)
* [Joystick.sliderRight()](#joysticksliderright)
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.position()](#joystickposition)
* [Joystick.hat()](#joystickhat)
* [Joystick.use8bit()](#joystickuse8bit)
* [Joystick.useManualSend()](#joystickuseManualSend)
### `Joystick.Y()`
Update Y axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.Z()`
Update Z axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.Zrotate()`
Update Z rotate axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.sliderLeft()`
Left slider value. Please refer to [Joystick.X()](#joystickx).
### `Joystick.sliderRight()`
Right slider value. Please refer to [Joystick.X()](#joystickx).
### `Joystick.slider()`
Same as [Joystick.sliderLeft()](#joysticksliderleft).
### `Joystick.position()`
Sets X and Y axis in one call. If autosending is active, one report is generated. Please refer to [Joystick.X()](#joystickx).
#### Syntax
```
Joystick.position(512,512)
```
#### Parameters
* `X`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for X axis
* `Y`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for Y axis
#### See also
* [Joystick.X()](#joystickx)
* [Joystick.Y()](#joysticky)
### `Joystick.hat()`
Set the hat value to selection angle or rest position.
#### Syntax
```
Joystick.hat(-1), // released/rest position
```
#### Parameters
* `angle` Angle value from 0-360 degrees or -1 for released resting position. Mapped to 8 different directions.
+14
View File
@@ -0,0 +1,14 @@
# Joystick library
The Joystick functions enable a RP2040 board to act as a HID game controller.
To use this library:
```
#include <Joystick.h>
```
## Examples
* [Joystick-AllFunctions] Includes example calls for each Joystick function
@@ -0,0 +1,110 @@
/* Benjamin Aigner, 2022 <beni@asterics-foundation.org> */
/* Public domain / CC 0 */
/** example code using all possibilities of the Joystick class
for the RP2040.
*/
#include <JoystickBLE.h>
void setup() {
Serial.begin(115200);
Serial.println("Use BOOTSEL to start the Joystick demo.");
JoystickBLE.begin();
}
void loop() {
if (BOOTSEL) {
Serial.println("Joystick buttons");
for (uint8_t i = 1; i <= 32; i++) {
JoystickBLE.button(i, true);
delay(250);
JoystickBLE.button(i, false);
delay(10); //we need a short delay here, sending packets with less than 1ms leads to packet loss!
}
//alternativ with manual send:
JoystickBLE.useManualSend(true);
Serial.println("Joystick buttons - manual send");
for (uint8_t i = 1; i <= 32; i++) {
JoystickBLE.button(i, true);
JoystickBLE.send_now();
delay(250);
JoystickBLE.button(i, false);
}
JoystickBLE.useManualSend(false);
//iterate all joystick axis
//Note: although you can use 0-1023 here (10bit), internally 8bits are used (-127 to 127)
Serial.println("Joystick X");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBLE.X(i);
delay(2);
} JoystickBLE.X(512);
Serial.println("Joystick Y");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBLE.Y(i);
delay(2);
} JoystickBLE.Y(512);
Serial.println("Joystick Z");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBLE.Z(i);
delay(2);
} JoystickBLE.Z(512);
Serial.println("Joystick Zrotate");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBLE.Zrotate(i);
delay(2);
} JoystickBLE.Zrotate(512);
Serial.println("Joystick sliderLeft");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBLE.sliderLeft(i);
delay(2);
} JoystickBLE.sliderLeft(0);
Serial.println("Joystick sliderRight");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBLE.sliderRight(i);
delay(2);
} JoystickBLE.sliderRight(0);
Serial.println("Joystick hat");
for (uint16_t i = 0; i < 360; i++) {
JoystickBLE.hat(i);
delay(20);
} JoystickBLE.hat(-1);
//use int8 mode for the axis.
//Note: hat is not used differently.
Serial.println("Now all axis in 8bit mode, -127 to 127");
JoystickBLE.use8bit(true);
Serial.println("Joystick X");
for (int16_t i = -127; i < 128; i++) {
JoystickBLE.X(i);
delay(2);
} JoystickBLE.X(0);
Serial.println("Joystick Y");
for (int16_t i = -127; i < 128; i++) {
JoystickBLE.Y(i);
delay(2);
} JoystickBLE.Y(0);
Serial.println("Joystick Z");
for (int16_t i = -127; i < 128; i++) {
JoystickBLE.Z(i);
delay(2);
} JoystickBLE.Z(0);
Serial.println("Joystick Zrotate");
for (int16_t i = -127; i < 128; i++) {
JoystickBLE.Zrotate(i);
delay(2);
} JoystickBLE.Zrotate(0);
Serial.println("Joystick sliderLeft");
for (int16_t i = -127; i < 128; i++) {
JoystickBLE.sliderLeft(i);
delay(2);
} JoystickBLE.sliderLeft(0);
Serial.println("Joystick sliderRight");
for (int16_t i = -127; i < 128; i++) {
JoystickBLE.sliderRight(i);
delay(2);
} JoystickBLE.sliderRight(0);
JoystickBLE.use8bit(false);
}
}
+33
View File
@@ -0,0 +1,33 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
JoystickBLE KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
use8bit KEYWORD2
X KEYWORD2
Y KEYWORD2
button KEYWORD2
position KEYWORD2
Z KEYWORD2
Zrotate KEYWORD2
sliderLeft KEYWORD2
slider KEYWORD2
sliderRight KEYWORD2
hat KEYWORD2
useManualSend KEYWORD2
send_now KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
+9
View File
@@ -0,0 +1,9 @@
name=JoystickBLE
version=1.0.1
author=Benjamin Aigner
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Allows any PicoW board to act as a BLE joystick/gamepad
paragraph=Allows any PicoW board to act as a BLE joystick/gamepad
category=Device Control
url=https://github.com/earlephilhower/arduino-pico
architectures=rp2040
+184
View File
@@ -0,0 +1,184 @@
/*
JoystickBLE.cpp
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
Modified for BLE 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>
Implementation loosely based on:
Mouse library from https://github.com/earlephilhower/arduino-pico
Joystick functions from Teensyduino https://github.com/PaulStoffregen
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 "JoystickBLE.h"
#include <Arduino.h>
#include <PicoBluetoothBLEHID.h>
//================================================================================
//================================================================================
// Joystick/Gamepad
JoystickBLE_::JoystickBLE_(void) {
_use8bit = false;
_autosend = true;
memset(&data, 0, sizeof(data));
//_X_axis = _Y_axis = _Z_axis = _Zrotate = _sliderLeft = _sliderRight = _hat = data.buttons = 0;
}
/** define the mapping of axes values
default: axes methods are accepting values from 0-1023 (compatibility to other Joystick libraries)
and are mapped internally to int8_t
if use8bit(true) is called, -127 to 127 values are used.*/
void JoystickBLE_::use8bit(bool mode) {
_use8bit = mode;
}
//if set, the gamepad report is not automatically sent after an update of axes/buttons; use send_now to update
void JoystickBLE_::useManualSend(bool mode) {
_autosend = !mode;
}
/** Maps values from 8bit signed or 10bit unsigned to report values
Depending on the setting via use8bit(), either values from 0-1023 or -127 - 127
are mapped.
*/
int JoystickBLE_::map8or10bit(int const value) {
if (_use8bit) {
if (value < -127) {
return -127;
} else if (value > 127) {
return 127;
} else {
return value;
}
} else {
if (value < 0) {
return 0;
}
if (value > 1023) {
return 1023;
}
return map(value, 0, 1023, -127, 127);
}
}
#define REPORT_ID 0x01
static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))};
void JoystickBLE_::begin(void) {
PicoBluetoothBLEHID.startHID("PicoW BLE Joystick", "PicoW BLE Joystick", 0x03c4, desc_joystick, sizeof(desc_joystick));
}
void JoystickBLE_::end(void) {
PicoBluetoothBLEHID.end();
}
void JoystickBLE_::button(uint8_t button, bool val) {
//I've no idea why, but without a second dword, it is not possible.
//maybe something with the alignment when using bit set/clear?!?
static uint32_t buttons_local = 0;
if (button >= 1 && button <= 32) {
if (val) {
buttons_local |= (1UL << (button - 1));
} else {
buttons_local &= ~(1UL << (button - 1));
}
data.buttons = buttons_local;
if (_autosend) {
send_now();
}
}
}
void JoystickBLE_::X(int val) {
data.x = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBLE_::Y(int val) {
data.y = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBLE_::Z(int val) {
data.z = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBLE_::Zrotate(int val) {
data.rz = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBLE_::sliderLeft(int val) {
data.rx = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBLE_::sliderRight(int val) {
data.ry = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBLE_::slider(int val) {
data.rx = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBLE_::position(int X, int Y) {
data.x = map8or10bit(X);
data.y = map8or10bit(Y);
if (_autosend) {
send_now();
}
}
//compatibility: there is only one hat implemented, num parameter is ignored
void JoystickBLE_::hat(unsigned int num, int angle) {
(void) num;
hat(angle);
}
//set the hat value, from 0-360. -1 is rest position
void JoystickBLE_::hat(int angle) {
if (angle < 0) {
data.hat = 0;
}
if (angle >= 0 && angle <= 360) {
data.hat = map(angle, 0, 360, 1, 8);
}
if (_autosend) {
send_now();
}
}
//immediately send an HID report
void JoystickBLE_::send_now(void) {
PicoBluetoothBLEHID.send(&data, sizeof(data));
}
JoystickBLE_ JoystickBLE;
+68
View File
@@ -0,0 +1,68 @@
/*
JoystickBLE.h
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
Modified for BT 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <Arduino.h>
#include "class/hid/hid.h"
//======================================================================
class JoystickBLE_ {
private:
bool _autosend;
bool _use8bit;
hid_gamepad_report_t data;
int map8or10bit(int const value);
public:
JoystickBLE_(void);
void begin(void);
void end(void);
//set a selected button to pressed/released
void button(uint8_t button, bool val);
//set axis values
void X(int val);
void Y(int val);
void position(int X, int Y);
void Z(int val);
void Zrotate(int val);
void sliderLeft(int val);
void sliderRight(int val);
//note: not implemented in TinyUSB gamepad, is mapped to sliderLeft.
void slider(int val);
//set the hat value, from 0-360. -1 is rest position
void hat(int angle);
//compatibility: there is only one hat implemented, num parameter is ignored
void hat(unsigned int num, int angle);
//if set, the gamepad report is not automatically sent after an update of axes/buttons; use send_now to update
void useManualSend(bool mode);
//immediately send an HID report
void send_now(void);
//define the mapping of axes values
//default: axes methods are accepting values from 0-1023 (compatibility to other Joystick libraries)
// and are mapped internally to int8_t
//if use8bit(true) is called, -127 to 127 values are used.
void use8bit(bool mode);
};
extern JoystickBLE_ JoystickBLE;
+34
View File
@@ -0,0 +1,34 @@
:repository-owner: arduino-libraries
:repository-name: Joystick
= {repository-name} Library for Arduino (RP2040 based boards) =
This library allows an RaspberryPi RP2040 board to act as a Joystick when
Earle F. Philhower`s [arduino-pico](https://github.com/earlephilhower/arduino-pico)
Core is used.
It was forked from the original upstream USB Joystick library by Benjamin Aigner
== Acknowledgements / Credits ==
* [arduino-pico](https://github.com/earlephilhower/arduino-pico) Earle F. Philhower providing the Arduino Core, on which this library is based on, available under LGPL.
* [tinyUSB] (https://github.com/hathach/tinyusb) Ha Thach for providing tinyUSB under MIT license, which covers most of the USB functionality.
== License ==
Copyright (c) Benjamin Aigner <beni@asterics-foundation.org> 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
+435
View File
@@ -0,0 +1,435 @@
# Joystick library
## Methods
### `Joystick.begin()`
Must be called before starting using the Joystick emulation. To end control, use `Joystick.end()`.
#### Syntax
```
Joystick.begin()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
}
void loop() {
// Initialize the Joystick library when button is pressed
if (digitalRead(2) == LOW) {
Joystick.begin();
}
}
```
#### See also
* [Joystick.button()](#joystickbutton)
* [Joystick.end()](#joystickend)
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.position()](#joystickposition)
* [Joystick.X()](#joystickx)
* [Joystick.hat()](#joystickhat)
* [Joystick.use8bit()](#joystickuse8bit)
* [Joystick.useManualSend()](#joystickuseManualSend)
### `Joystick.button()`
Updates a button of the USB joystick.
#### Syntax
```
Joystick.button(1,true);
delay(250);
Joystick.button(1,false);
```
#### Parameters
* `button`: number of Joystick button, which status should be changed
* `val`: state of button, `true` for pressed, `false` for released
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
uint8_t i = 1; //counter for the button number 1-32
if (digitalRead(2) == LOW) { //if button is pressed
Joystick.button(i,true); //"press" the Joystick button
delay(250); //wait for 0.25s
Joystick.button(i,false); //"release" the Joystick button
i = i + 1; //increment & use next Joystick button number
if(i > 32) i = 1; //we have 32 buttons available, wrap-around
}
}
```
#### Notes
* Up to 32 buttons are available, numbered as button 1 to button 32.
* If manual_send is active, call `Joystick.send_now()` to send an update to the host.
#### See also
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.useManualSend()](#joystickuseManualSend)
* [Joystick.X()](#joystickx)
* [Joystick.hat()](#joystickhat)
### `Joystick.end()`
Stops emulating the Joystick connected to a computer. To start control, use `Joystick.begin()`.
#### Syntax
```
Joystick.end()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
// Initiate the Joystick library
Joystick.begin();
}
void loop() {
// If the button is pressed, send a button 1 press / release
if (digitalRead(2) == LOW) {
Joystick.button(1,true);
delay(250);
Joystick.button(1,false);
// Then end the Joystick emulation
Joystick.end();
}
}
```
#### See also
* [Joystick.begin()](#joystickbegin)
### `Joystick.use8bit()`
Switch axis value range between 10bit and 8bit.
* Default: 10bit, range for an axis from 0 to 1023
* 8bit mode: range from -127 to 127.
__Note:__ due to the gamepad descriptor of tinyUSB, the maximum range is -127/127. 10bit mode enables mapping, not a higher resolution.
#### Syntax
```
Joystick.use8bit(true)
```
#### Parameters
* `mode`: true, if values from -127/127 are used. False to use a range from 0 to 1023.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
//send middle position in default 10bit mode
Joystick.position(512,512);
delay(250);
//enable 8bit mode
Joystick.use8bit(true);
//send middle position in 8bit mode
Joystick.position(0,0);
delay(250);
//send maximum left in 10bit mode
Joystick.use8bit(false);
Joystick.position(0,0);
delay(250);
//enable 8bit mode
Joystick.use8bit(true);
//send left position in 8bit mode
Joystick.position(-127,-127);
}
```
#### See also
* [Joystick.position()](#joystickposition)
* [Joystick.X()](#joystickx)
* [Joystick.Y()](#joysticky)
* [Joystick.Z()](#joystickz)
* [Joystick.Zrotate()](#joystickrotate)
* [Joystick.slider()](#joystickslider)
* [Joystick.sliderLeft()](#joysticksliderleft)
* [Joystick.sliderRight()](#joysticksliderright)
### `Joystick.useManualSend()`
To fully control transmitting the USB-HID reports, enable manual sending.
If disabled, each call to a function updating the Joystick status (buttons, all axis, hat)
will send a HID report. If you update in a loop, the time between updates (at least 1ms) is too short and something might be not transmitted correctly.
If enabled, update all your axis values, buttons, hat and then send one report via `Joystick.send_now()`.
#### Syntax
```
Joystick.useManualSend(true)
```
#### Parameters
* `mode`: false is sending report each Joystick update, true enables manual sending via send_now().
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
if (digitalRead(2) == LOW) {
// send data in 4 different reports
Joystick.button(1,true);
Joystick.button(2,true);
Joystick.button(3,true);
Joystick.button(4,true);
//enable manual send
Joystick.useManualSend(true);
//send same data in one report
Joystick.button(1,false);
Joystick.button(2,false);
Joystick.button(3,false);
Joystick.button(4,false);
Joystick.send_now();
}
}
```
#### See also
* [Joystick.send_now()](#joysticksend_now)
### `Joystick.send_now()`
Send a HID report now. Used together with manual sending, see `Joystick.useManualSend()`.
#### Syntax
```
Joystick.send_now()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
//enable manual sending in setup
Joystick.useManualSend(true);
}
void loop() {
if (digitalRead(2) == LOW) {
// update all buttons, but nothing is sent to the host
for(uint8_t i = 1; i<=32; i++) Joystick.button(i,true);
Joystick.X(256);
Joystick.sliderLeft(0);
//now send in one HID report
Joystick.send_now();
}
}
```
#### See also
* [Joystick.useManualSend()](#joystickusemanualsend)
### `Joystick.X()`
Update X axis.
__Note:__ If [manual send](#joystickusemanualsend) is active, the value is sent to the host only after calling [send_now](#joysticksend_now).
__Note:__ If in 10bit mode (default), the parameter is interpreted from 0 to 1023.
In 8bit mode from -127 to 127. The internal resolution is always 8bit. Change setting with [use8bit](#joystickuse8bit).
#### Syntax
```
Joystick.X(0)
```
#### Parameters
* `val`: value from 0 to 1023 (default) or -127 to 127 (8bit mode)
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
if (digitalRead(2) == LOW) {
Joystick.X(256);
delay(500);
Joystick.X(512);
}
}
```
#### See also
* [Joystick.Y()](#joysticky)
* [Joystick.Z()](#joystickz)
* [Joystick.Zrotate()](#joystickrotate)
* [Joystick.slider()](#joystickslider)
* [Joystick.sliderLeft()](#joysticksliderleft)
* [Joystick.sliderRight()](#joysticksliderright)
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.position()](#joystickposition)
* [Joystick.hat()](#joystickhat)
* [Joystick.use8bit()](#joystickuse8bit)
* [Joystick.useManualSend()](#joystickuseManualSend)
### `Joystick.Y()`
Update Y axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.Z()`
Update Z axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.Zrotate()`
Update Z rotate axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.sliderLeft()`
Left slider value. Please refer to [Joystick.X()](#joystickx).
### `Joystick.sliderRight()`
Right slider value. Please refer to [Joystick.X()](#joystickx).
### `Joystick.slider()`
Same as [Joystick.sliderLeft()](#joysticksliderleft).
### `Joystick.position()`
Sets X and Y axis in one call. If autosending is active, one report is generated. Please refer to [Joystick.X()](#joystickx).
#### Syntax
```
Joystick.position(512,512)
```
#### Parameters
* `X`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for X axis
* `Y`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for Y axis
#### See also
* [Joystick.X()](#joystickx)
* [Joystick.Y()](#joysticky)
### `Joystick.hat()`
Set the hat value to selection angle or rest position.
#### Syntax
```
Joystick.hat(-1), // released/rest position
```
#### Parameters
* `angle` Angle value from 0-360 degrees or -1 for released resting position. Mapped to 8 different directions.
+14
View File
@@ -0,0 +1,14 @@
# Joystick library
The Joystick functions enable a RP2040 board to act as a HID game controller.
To use this library:
```
#include <Joystick.h>
```
## Examples
* [Joystick-AllFunctions] Includes example calls for each Joystick function
@@ -0,0 +1,110 @@
/* Benjamin Aigner, 2022 <beni@asterics-foundation.org> */
/* Public domain / CC 0 */
/** example code using all possibilities of the Joystick class
for the RP2040.
*/
#include <JoystickBT.h>
void setup() {
Serial.begin(115200);
Serial.println("Use BOOTSEL to start the Joystick demo.");
JoystickBT.begin();
}
void loop() {
if (BOOTSEL) {
Serial.println("Joystick buttons");
for (uint8_t i = 1; i <= 32; i++) {
JoystickBT.button(i, true);
delay(250);
JoystickBT.button(i, false);
delay(10); //we need a short delay here, sending packets with less than 1ms leads to packet loss!
}
//alternativ with manual send:
JoystickBT.useManualSend(true);
Serial.println("Joystick buttons - manual send");
for (uint8_t i = 1; i <= 32; i++) {
JoystickBT.button(i, true);
JoystickBT.send_now();
delay(250);
JoystickBT.button(i, false);
}
JoystickBT.useManualSend(false);
//iterate all joystick axis
//Note: although you can use 0-1023 here (10bit), internally 8bits are used (-127 to 127)
Serial.println("Joystick X");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBT.X(i);
delay(2);
} JoystickBT.X(512);
Serial.println("Joystick Y");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBT.Y(i);
delay(2);
} JoystickBT.Y(512);
Serial.println("Joystick Z");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBT.Z(i);
delay(2);
} JoystickBT.Z(512);
Serial.println("Joystick Zrotate");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBT.Zrotate(i);
delay(2);
} JoystickBT.Zrotate(512);
Serial.println("Joystick sliderLeft");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBT.sliderLeft(i);
delay(2);
} JoystickBT.sliderLeft(0);
Serial.println("Joystick sliderRight");
for (uint16_t i = 0; i < 1023; i++) {
JoystickBT.sliderRight(i);
delay(2);
} JoystickBT.sliderRight(0);
Serial.println("Joystick hat");
for (uint16_t i = 0; i < 360; i++) {
JoystickBT.hat(i);
delay(20);
} JoystickBT.hat(-1);
//use int8 mode for the axis.
//Note: hat is not used differently.
Serial.println("Now all axis in 8bit mode, -127 to 127");
JoystickBT.use8bit(true);
Serial.println("Joystick X");
for (int16_t i = -127; i < 128; i++) {
JoystickBT.X(i);
delay(2);
} JoystickBT.X(0);
Serial.println("Joystick Y");
for (int16_t i = -127; i < 128; i++) {
JoystickBT.Y(i);
delay(2);
} JoystickBT.Y(0);
Serial.println("Joystick Z");
for (int16_t i = -127; i < 128; i++) {
JoystickBT.Z(i);
delay(2);
} JoystickBT.Z(0);
Serial.println("Joystick Zrotate");
for (int16_t i = -127; i < 128; i++) {
JoystickBT.Zrotate(i);
delay(2);
} JoystickBT.Zrotate(0);
Serial.println("Joystick sliderLeft");
for (int16_t i = -127; i < 128; i++) {
JoystickBT.sliderLeft(i);
delay(2);
} JoystickBT.sliderLeft(0);
Serial.println("Joystick sliderRight");
for (int16_t i = -127; i < 128; i++) {
JoystickBT.sliderRight(i);
delay(2);
} JoystickBT.sliderRight(0);
JoystickBT.use8bit(false);
}
}
+33
View File
@@ -0,0 +1,33 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
JoystickBT KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
use8bit KEYWORD2
X KEYWORD2
Y KEYWORD2
button KEYWORD2
position KEYWORD2
Z KEYWORD2
Zrotate KEYWORD2
sliderLeft KEYWORD2
slider KEYWORD2
sliderRight KEYWORD2
hat KEYWORD2
useManualSend KEYWORD2
send_now KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
+9
View File
@@ -0,0 +1,9 @@
name=JoystickBT
version=1.0.1
author=Benjamin Aigner
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Allows any PicoW board to act as a BT joystick/gamepad
paragraph=Allows any PicoW board to act as a BT joystick/gamepad
category=Device Control
url=https://github.com/earlephilhower/arduino-pico
architectures=rp2040
+184
View File
@@ -0,0 +1,184 @@
/*
Joystick.cpp
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
Modified for BT 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>
Implementation loosely based on:
Mouse library from https://github.com/earlephilhower/arduino-pico
Joystick functions from Teensyduino https://github.com/PaulStoffregen
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 "JoystickBT.h"
#include <Arduino.h>
#include <PicoBluetoothHID.h>
//================================================================================
//================================================================================
// Joystick/Gamepad
JoystickBT_::JoystickBT_(void) {
_use8bit = false;
_autosend = true;
memset(&data, 0, sizeof(data));
//_X_axis = _Y_axis = _Z_axis = _Zrotate = _sliderLeft = _sliderRight = _hat = data.buttons = 0;
}
/** define the mapping of axes values
default: axes methods are accepting values from 0-1023 (compatibility to other Joystick libraries)
and are mapped internally to int8_t
if use8bit(true) is called, -127 to 127 values are used.*/
void JoystickBT_::use8bit(bool mode) {
_use8bit = mode;
}
//if set, the gamepad report is not automatically sent after an update of axes/buttons; use send_now to update
void JoystickBT_::useManualSend(bool mode) {
_autosend = !mode;
}
/** Maps values from 8bit signed or 10bit unsigned to report values
Depending on the setting via use8bit(), either values from 0-1023 or -127 - 127
are mapped.
*/
int JoystickBT_::map8or10bit(int const value) {
if (_use8bit) {
if (value < -127) {
return -127;
} else if (value > 127) {
return 127;
} else {
return value;
}
} else {
if (value < 0) {
return 0;
}
if (value > 1023) {
return 1023;
}
return map(value, 0, 1023, -127, 127);
}
}
#define REPORT_ID 0x01
static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))};
void JoystickBT_::begin(void) {
PicoBluetoothHID.startHID("PicoW Joystick 00:00:00:00:00:00", "PicoW HID Joystick", 0x2508, 33, desc_joystick, sizeof(desc_joystick));
}
void JoystickBT_::end(void) {
PicoBluetoothHID.end();
}
void JoystickBT_::button(uint8_t button, bool val) {
//I've no idea why, but without a second dword, it is not possible.
//maybe something with the alignment when using bit set/clear?!?
static uint32_t buttons_local = 0;
if (button >= 1 && button <= 32) {
if (val) {
buttons_local |= (1UL << (button - 1));
} else {
buttons_local &= ~(1UL << (button - 1));
}
data.buttons = buttons_local;
if (_autosend) {
send_now();
}
}
}
void JoystickBT_::X(int val) {
data.x = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBT_::Y(int val) {
data.y = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBT_::Z(int val) {
data.z = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBT_::Zrotate(int val) {
data.rz = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBT_::sliderLeft(int val) {
data.rx = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBT_::sliderRight(int val) {
data.ry = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBT_::slider(int val) {
data.rx = map8or10bit(val);
if (_autosend) {
send_now();
}
}
void JoystickBT_::position(int X, int Y) {
data.x = map8or10bit(X);
data.y = map8or10bit(Y);
if (_autosend) {
send_now();
}
}
//compatibility: there is only one hat implemented, num parameter is ignored
void JoystickBT_::hat(unsigned int num, int angle) {
(void) num;
hat(angle);
}
//set the hat value, from 0-360. -1 is rest position
void JoystickBT_::hat(int angle) {
if (angle < 0) {
data.hat = 0;
}
if (angle >= 0 && angle <= 360) {
data.hat = map(angle, 0, 360, 1, 8);
}
if (_autosend) {
send_now();
}
}
//immediately send an HID report
void JoystickBT_::send_now(void) {
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
}
JoystickBT_ JoystickBT;
+68
View File
@@ -0,0 +1,68 @@
/*
JoystickBT.h
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
Modified for BT 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <Arduino.h>
#include "class/hid/hid.h"
//======================================================================
class JoystickBT_ {
private:
bool _autosend;
bool _use8bit;
hid_gamepad_report_t data;
int map8or10bit(int const value);
public:
JoystickBT_(void);
void begin(void);
void end(void);
//set a selected button to pressed/released
void button(uint8_t button, bool val);
//set axis values
void X(int val);
void Y(int val);
void position(int X, int Y);
void Z(int val);
void Zrotate(int val);
void sliderLeft(int val);
void sliderRight(int val);
//note: not implemented in TinyUSB gamepad, is mapped to sliderLeft.
void slider(int val);
//set the hat value, from 0-360. -1 is rest position
void hat(int angle);
//compatibility: there is only one hat implemented, num parameter is ignored
void hat(unsigned int num, int angle);
//if set, the gamepad report is not automatically sent after an update of axes/buttons; use send_now to update
void useManualSend(bool mode);
//immediately send an HID report
void send_now(void);
//define the mapping of axes values
//default: axes methods are accepting values from 0-1023 (compatibility to other Joystick libraries)
// and are mapped internally to int8_t
//if use8bit(true) is called, -127 to 127 values are used.
void use8bit(bool mode);
};
extern JoystickBT_ JoystickBT;
+165
View File
@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+31
View File
@@ -0,0 +1,31 @@
:repository-owner: arduino-libraries
:repository-name: Keyboard
= {repository-name} Library for Arduino =
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"]
This library allows an Arduino board with USB capabilities to act as a keyboard.
For more information about this library please visit us at
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
== License ==
Copyright (c) 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
@@ -0,0 +1,20 @@
/* Released into the public domain */
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
#include <KeyboardBLE.h>
void setup() {
Serial.begin(115200);
KeyboardBLE.begin();
delay(5000);
Serial.printf("Arduino USB Password Typer\n");
Serial.printf("Press BOOTSEL to enter your super-secure(not!) password\n\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("Typing password for you...shhhh....");
KeyboardBLE.print("ThisPasswordIsWeakLikeABaby");
while (BOOTSEL);
}
}
@@ -0,0 +1,39 @@
/*
Keyboard test
For the Arduino Leonardo, Micro or Due
Reads a byte from the serial port, sends a keystroke back.
The sent keystroke is one higher than what's received, e.g. if you send a,
you get b, send A you get B, and so forth.
The circuit:
- none
created 21 Oct 2011
modified 27 Mar 2012
by Tom Igoe
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardSerial
*/
#include <KeyboardBLE.h>
void setup() {
// open the serial port:
Serial.begin(9600);
// initialize control over the keyboard:
KeyboardBLE.begin();
}
void loop() {
// check for incoming serial data:
if (Serial.available() > 0) {
// read incoming serial data:
char inChar = Serial.read();
// Type the next ASCII value from what you received:
KeyboardBLE.write(inChar + 1);
}
}
+24
View File
@@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map For Keyboard
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
KeyboardBLE KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
write KEYWORD2
press KEYWORD2
release KEYWORD2
releaseAll KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
+9
View File
@@ -0,0 +1,9 @@
name=KeyboardBLE
version=1.0.3
author=Arduino and EFP3
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Allows a RP2040 to act as a Keyboard.
paragraph=Port of pure Arduino Keyboard to PicoW BLE
category=Device Control
url=https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
architectures=rp2040
+179
View File
@@ -0,0 +1,179 @@
/*
KeyboardBLE.cpp
Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
Main Arduino Library Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
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 "KeyboardBLE.h"
#include "KeyboardLayout.h"
#include <PicoBluetoothBLEHID.h>
//================================================================================
//================================================================================
// Keyboard
KeyboardBLE_::KeyboardBLE_(void) {
bzero(&_keyReport, sizeof(_keyReport));
_asciimap = KeyboardLayout_en_US;
}
#define REPORT_ID 0x01
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))};
void KeyboardBLE_::begin(const uint8_t *layout) {
_asciimap = layout;
PicoBluetoothBLEHID.startHID("PicoW BLE Keyboard", "PicoW BLE Keyboard", 0x03c1, desc_keyboard, sizeof(desc_keyboard));
}
void KeyboardBLE_::end(void) {
PicoBluetoothBLEHID.end();
}
void KeyboardBLE_::sendReport(KeyReport* keys) {
hid_keyboard_report_t data;
data.modifier = keys->modifiers;
data.reserved = 0;
memcpy(data.keycode, keys->keys, sizeof(data.keycode));
PicoBluetoothBLEHID.send(&data, sizeof(data));
}
// press() adds the specified key (printing, non-printing, or modifier)
// to the persistent key report and sends the report. Because of the way
// USB HID works, the host acts like the key remains pressed until we
// call release(), releaseAll(), or otherwise clear the report and resend.
size_t KeyboardBLE_::press(uint8_t k) {
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers |= (1 << (k - 128));
k = 0;
} else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
setWriteError();
return 0;
}
if ((k & ALT_GR) == ALT_GR) {
_keyReport.modifiers |= 0x40; // AltGr = right Alt
k &= 0x3F;
} else if ((k & SHIFT) == SHIFT) {
_keyReport.modifiers |= 0x02; // the left shift modifier
k &= 0x7F;
}
if (k == ISO_REPLACEMENT) {
k = ISO_KEY;
}
}
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i = 0; i < 6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
setWriteError();
return 0;
}
}
sendReport(&_keyReport);
return 1;
}
// release() takes the specified key out of the persistent key report and
// sends the report. This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t KeyboardBLE_::release(uint8_t k) {
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers &= ~(1 << (k - 128));
k = 0;
} else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
return 0;
}
if ((k & ALT_GR) == ALT_GR) {
_keyReport.modifiers &= ~(0x40); // AltGr = right Alt
k &= 0x3F;
} else if ((k & SHIFT) == SHIFT) {
_keyReport.modifiers &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
if (k == ISO_REPLACEMENT) {
k = ISO_KEY;
}
}
// Test the key report to see if k is present. Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i = 0; i < 6; i++) {
if (0 != k && _keyReport.keys[i] == k) {
_keyReport.keys[i] = 0x00;
}
}
sendReport(&_keyReport);
return 1;
}
void KeyboardBLE_::releaseAll(void) {
_keyReport.keys[0] = 0;
_keyReport.keys[1] = 0;
_keyReport.keys[2] = 0;
_keyReport.keys[3] = 0;
_keyReport.keys[4] = 0;
_keyReport.keys[5] = 0;
_keyReport.modifiers = 0;
sendReport(&_keyReport);
}
size_t KeyboardBLE_::write(uint8_t c) {
uint8_t p = press(c); // Keydown
delay(10);
release(c); // Keyup
delay(10);
return p; // just return the result of press() since release() almost always returns 1
}
size_t KeyboardBLE_::write(const uint8_t *buffer, size_t size) {
size_t n = 0;
while (size--) {
if (*buffer != '\r') {
if (write(*buffer)) {
n++;
} else {
break;
}
}
buffer++;
}
return n;
}
KeyboardBLE_ KeyboardBLE;
+141
View File
@@ -0,0 +1,141 @@
/*
KeyboardBLE.h
Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
Main Arduino Library Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
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 KEYBOARDBLE_h
#define KEYBOARDBLE_h
#include <Arduino.h>
//================================================================================
//================================================================================
// Keyboard
// Modifiers
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
// Misc keys
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_MENU 0xED // "Keyboard Application" in USB standard
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_PRINT_SCREEN 0xCE // Print Screen / SysRq
#define KEY_SCROLL_LOCK 0xCF
#define KEY_PAUSE 0xD0 // Pause / Break
// Numeric keypad
#define KEY_NUM_LOCK 0xDB
#define KEY_KP_SLASH 0xDC
#define KEY_KP_ASTERISK 0xDD
#define KEY_KP_MINUS 0xDE
#define KEY_KP_PLUS 0xDF
#define KEY_KP_ENTER 0xE0
#define KEY_KP_1 0xE1
#define KEY_KP_2 0xE2
#define KEY_KP_3 0xE3
#define KEY_KP_4 0xE4
#define KEY_KP_5 0xE5
#define KEY_KP_6 0xE6
#define KEY_KP_7 0xE7
#define KEY_KP_8 0xE8
#define KEY_KP_9 0xE9
#define KEY_KP_0 0xEA
#define KEY_KP_DOT 0xEB
// Function keys
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
#define KEY_F13 0xF0
#define KEY_F14 0xF1
#define KEY_F15 0xF2
#define KEY_F16 0xF3
#define KEY_F17 0xF4
#define KEY_F18 0xF5
#define KEY_F19 0xF6
#define KEY_F20 0xF7
#define KEY_F21 0xF8
#define KEY_F22 0xF9
#define KEY_F23 0xFA
#define KEY_F24 0xFB
// Supported keyboard layouts
extern const uint8_t KeyboardLayout_de_DE[];
extern const uint8_t KeyboardLayout_en_US[];
extern const uint8_t KeyboardLayout_es_ES[];
extern const uint8_t KeyboardLayout_fr_FR[];
extern const uint8_t KeyboardLayout_it_IT[];
extern const uint8_t KeyboardLayout_sv_SE[];
extern const uint8_t KeyboardLayout_da_DK[];
// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct {
uint8_t modifiers;
uint8_t reserved;
uint8_t keys[6];
} KeyReport;
class KeyboardBLE_ : public Print {
private:
KeyReport _keyReport;
const uint8_t *_asciimap;
void sendReport(KeyReport* keys);
public:
KeyboardBLE_(void);
void begin(const uint8_t *layout = KeyboardLayout_en_US);
void end(void);
size_t write(uint8_t k);
size_t write(const uint8_t *buffer, size_t size);
size_t press(uint8_t k);
size_t release(uint8_t k);
void releaseAll(void);
};
extern KeyboardBLE_ KeyboardBLE;
#endif
@@ -0,0 +1,65 @@
/*
KeyboardLayout.h
This file is not part of the public API. It is meant to be included
only in Keyboard.cpp and the keyboard layout files. Layout files map
ASCII character codes to keyboard scan codes (technically, to USB HID
Usage codes), possibly altered by the SHIFT or ALT_GR modifiers.
== Creating your own layout ==
In order to create your own layout file, copy an existing layout that
is similar to yours, then modify it to use the correct keys. The
layout is an array in ASCII order. Each entry contains a scan code,
possibly modified by "|SHIFT" or "|ALT_GR", as in this excerpt from
the Italian layout:
0x35, // bslash
0x30|ALT_GR, // ]
0x2e|SHIFT, // ^
Do not change the control characters (those before scan code 0x2c,
corresponding to space). Do not attempt to grow the table past DEL. Do
not use both SHIFT and ALT_GR on the same character: this is not
supported. Unsupported characters should have 0x00 as scan code.
For a keyboard with an ISO physical layout, use the scan codes below:
+---+---+---+---+---+---+---+---+---+---+---+---+---+-------+
|35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp |
+---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+
| Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret |
+-----++--++--++--++--++--++--++--++--++--++--++--++--++ |
|CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 | |
+----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+
|Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 | Shift |
+----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+
|Ctrl|Win |Alt | |AlGr|Win |Menu|Ctrl|
+----+----+----+------------------------+----+----+----+----+
The ANSI layout is identical except that key 0x31 is above (rather
than next to) Return, and there is not key 0x32.
Give a unique name to the layout array, then declare it in Keyboard.h
with a line of the form:
extern const uint8_t KeyboardLayout_xx_YY[];
== Encoding details ==
All scan codes are less than 0x80, which makes bit 7 available to
signal that a modifier (Shift or AltGr) is needed to generate the
character. With only one exception, keys that are used with modifiers
have scan codes that are less than 0x40. This makes bit 6 available
to signal whether the modifier is Shift or AltGr. The exception is
0x64, the key next next to Left Shift on the ISO layout (and absent
from the ANSI layout). We handle it by replacing its value by 0x32 in
the layout arrays.
*/
#include <Arduino.h>
#define SHIFT 0x80
#define ALT_GR 0xc0
#define ISO_KEY 0x64
#define ISO_REPLACEMENT 0x32
@@ -0,0 +1,137 @@
/*
Danish keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_da_DK[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x20 | SHIFT, // #
0x21 | ALT_GR, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x31, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x31 | SHIFT, // *
0x2d, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x1f | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x25 | ALT_GR, // [
0x32 | ALT_GR, // bslash
0x26 | ALT_GR, // ]
0x00, // ^ not supported (requires dead key + space)
0x38 | SHIFT, // _
0x00, // ` not supported (requires dead key + space)
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x24 | ALT_GR, // {
0x2e | ALT_GR, // |
0x27 | ALT_GR, // }
0x00, // ~ not supported (requires dead key + space)
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
German keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_de_DE[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x31, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x31 | SHIFT, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x30 | SHIFT, // *
0x30, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x14 | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1d | SHIFT, // Y
0x1c | SHIFT, // Z
0x25 | ALT_GR, // [
0x2d | ALT_GR, // bslash
0x26 | ALT_GR, // ]
0x00, // ^ not supported (requires dead key + space)
0x38 | SHIFT, // _
0x00, // ` not supported (requires dead key + space)
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1d, // y
0x1c, // z
0x24 | ALT_GR, // {
0x32 | ALT_GR, // |
0x27 | ALT_GR, // }
0x30 | ALT_GR, // ~
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Standard US keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_en_US[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x34 | SHIFT, // "
0x20 | SHIFT, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x24 | SHIFT, // &
0x34, // '
0x26 | SHIFT, // (
0x27 | SHIFT, // )
0x25 | SHIFT, // *
0x2e | SHIFT, // +
0x36, // ,
0x2d, // -
0x37, // .
0x38, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x33 | SHIFT, // :
0x33, // ;
0x36 | SHIFT, // <
0x2e, // =
0x37 | SHIFT, // >
0x38 | SHIFT, // ?
0x1f | SHIFT, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f, // [
0x31, // bslash
0x30, // ]
0x23 | SHIFT, // ^
0x2d | SHIFT, // _
0x35, // `
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x2f | SHIFT, // {
0x31 | SHIFT, // |
0x30 | SHIFT, // }
0x35 | SHIFT, // ~
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Spanish keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_es_ES[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x20 | ALT_GR, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x2d, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x30 | SHIFT, // *
0x30, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x1f | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f | ALT_GR, // [
0x35 | ALT_GR, // bslash
0x30 | ALT_GR, // ]
0x00, // ^ not supported (requires dead key + space)
0x38 | SHIFT, // _
0x00, // ` not supported (requires dead key + space)
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x34 | ALT_GR, // {
0x1e | ALT_GR, // |
0x31 | ALT_GR, // }
0x00, // ~ not supported (requires dead key + space)
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Traditional (not AFNOR) French keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_fr_FR[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x38, // !
0x20, // "
0x20 | ALT_GR, // #
0x30, // $
0x34 | SHIFT, // %
0x1E, // &
0x21, // '
0x22, // (
0x2d, // )
0x31, // *
0x2e | SHIFT, // +
0x10, // ,
0x23, // -
0x36 | SHIFT, // .
0x37 | SHIFT, // /
0x27 | SHIFT, // 0
0x1e | SHIFT, // 1
0x1f | SHIFT, // 2
0x20 | SHIFT, // 3
0x21 | SHIFT, // 4
0x22 | SHIFT, // 5
0x23 | SHIFT, // 6
0x24 | SHIFT, // 7
0x25 | SHIFT, // 8
0x26 | SHIFT, // 9
0x37, // :
0x36, // ;
0x32, // <
0x2e, // =
0x32 | SHIFT, // >
0x10 | SHIFT, // ?
0x27 | ALT_GR, // @
0x14 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x33 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x04 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1d | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1a | SHIFT, // Z
0x22 | ALT_GR, // [
0x25 | ALT_GR, // bslash
0x2d | ALT_GR, // ]
0x26 | ALT_GR, // ^
0x25, // _
0x24 | ALT_GR, // `
0x14, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x33, // m
0x11, // n
0x12, // o
0x13, // p
0x04, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1d, // w
0x1b, // x
0x1c, // y
0x1a, // z
0x21 | ALT_GR, // {
0x23 | ALT_GR, // |
0x2e | ALT_GR, // }
0x1f | ALT_GR, // ~
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Italian keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_it_IT[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x34 | ALT_GR, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x2d, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x30 | SHIFT, // *
0x30, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x33 | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f | ALT_GR, // [
0x35, // bslash
0x30 | ALT_GR, // ]
0x2e | SHIFT, // ^
0x38 | SHIFT, // _
0x00, // ` not in this layout
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x00, // { not supported (requires AltGr+Shift)
0x35 | SHIFT, // |
0x00, // } not supported (requires AltGr+Shift)
0x00, // ~ not in this layout
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Swedish keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_sv_SE[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x20 | SHIFT, // #
0x21 | ALT_GR, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x31, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x31 | SHIFT, // *
0x2d, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x1f | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x25 | ALT_GR, // [
0x2d | ALT_GR, // bslash
0x26 | ALT_GR, // ]
0x00, // ^ not supported (requires dead key + space)
0x38 | SHIFT, // _
0x00, // ` not supported (requires dead key + space)
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x24 | ALT_GR, // {
0x32 | ALT_GR, // |
0x27 | ALT_GR, // }
0x00, // ~ not supported (requires dead key + space)
0x00 // DEL
};
@@ -0,0 +1,44 @@
/*
Keyboard_da_DK.h
Copyright (c) 2021, Peter John
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 KEYBOARD_DA_DK_h
#define KEYBOARD_DA_DK_h
#include "HID.h"
#if !defined(_USING_HID)
#warning "Using legacy HID core (non pluggable)"
#else
//================================================================================
//================================================================================
// Keyboard
// DA_DK keys
#define KEY_A_RING (136+0x2f)
#define KEY_SLASHED_O (136+0x34)
#define KEY_ASH (136+0x33)
#define KEY_UMLAUT (136+0x30)
#define KEY_ACUTE_ACC (136+0x2e)
#endif
#endif
@@ -0,0 +1,44 @@
/*
Keyboard_sv_SE.h
Copyright (c) 2021, Peter John
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 KEYBOARD_SV_SE_h
#define KEYBOARD_SV_SE_h
#include "HID.h"
#if !defined(_USING_HID)
#warning "Using legacy HID core (non pluggable)"
#else
//================================================================================
//================================================================================
// Keyboard
// SV_SE keys
#define KEY_A_RING (136+0x2f)
#define KEY_A_UMLAUT (136+0x34)
#define KEY_O_UMLAUT (136+0x33)
#define KEY_UMLAUT (136+0x30)
#define KEY_ACUTE_ACC (136+0x2e)
#endif
#endif
+165
View File
@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+31
View File
@@ -0,0 +1,31 @@
:repository-owner: arduino-libraries
:repository-name: Keyboard
= {repository-name} Library for Arduino =
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"]
This library allows an Arduino board with USB capabilities to act as a keyboard.
For more information about this library please visit us at
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
== License ==
Copyright (c) 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
@@ -0,0 +1,20 @@
/* Released into the public domain */
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
#include <KeyboardBT.h>
void setup() {
Serial.begin(115200);
KeyboardBT.begin();
delay(5000);
Serial.printf("Arduino USB Password Typer\n");
Serial.printf("Press BOOTSEL to enter your super-secure(not!) password\n\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("Typing password for you...shhhh....");
KeyboardBT.print("ThisPasswordIsWeakLikeABaby");
while (BOOTSEL);
}
}
@@ -0,0 +1,39 @@
/*
Keyboard test
For the Arduino Leonardo, Micro or Due
Reads a byte from the serial port, sends a keystroke back.
The sent keystroke is one higher than what's received, e.g. if you send a,
you get b, send A you get B, and so forth.
The circuit:
- none
created 21 Oct 2011
modified 27 Mar 2012
by Tom Igoe
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardSerial
*/
#include <KeyboardBT.h>
void setup() {
// open the serial port:
Serial.begin(9600);
// initialize control over the keyboard:
KeyboardBT.begin();
}
void loop() {
// check for incoming serial data:
if (Serial.available() > 0) {
// read incoming serial data:
char inChar = Serial.read();
// Type the next ASCII value from what you received:
KeyboardBT.write(inChar + 1);
}
}
+24
View File
@@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map For Keyboard
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
KeyboardBT KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
write KEYWORD2
press KEYWORD2
release KEYWORD2
releaseAll KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
+9
View File
@@ -0,0 +1,9 @@
name=KeyboardBT
version=1.0.3
author=Arduino and EFP3
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Allows a RP2040 to act as a Keyboard.
paragraph=Port of pure Arduino Keyboard to PicoW BT
category=Device Control
url=https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
architectures=rp2040
+179
View File
@@ -0,0 +1,179 @@
/*
KeyboardBT.cpp
Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
Main Arduino Library Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
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 "KeyboardBT.h"
#include "KeyboardLayout.h"
#include <PicoBluetoothHID.h>
//================================================================================
//================================================================================
// Keyboard
KeyboardBT_::KeyboardBT_(void) {
bzero(&_keyReport, sizeof(_keyReport));
_asciimap = KeyboardLayout_en_US;
}
#define REPORT_ID 0x01
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))};
void KeyboardBT_::begin(const uint8_t *layout) {
_asciimap = layout;
PicoBluetoothHID.startHID("PicoW Keyboard 00:00:00:00:00:00", "PicoW HID Keyboard", 0x2540, 33, desc_keyboard, sizeof(desc_keyboard));
}
void KeyboardBT_::end(void) {
PicoBluetoothHID.end();
}
void KeyboardBT_::sendReport(KeyReport* keys) {
hid_keyboard_report_t data;
data.modifier = keys->modifiers;
data.reserved = 0;
memcpy(data.keycode, keys->keys, sizeof(data.keycode));
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
}
// press() adds the specified key (printing, non-printing, or modifier)
// to the persistent key report and sends the report. Because of the way
// USB HID works, the host acts like the key remains pressed until we
// call release(), releaseAll(), or otherwise clear the report and resend.
size_t KeyboardBT_::press(uint8_t k) {
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers |= (1 << (k - 128));
k = 0;
} else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
setWriteError();
return 0;
}
if ((k & ALT_GR) == ALT_GR) {
_keyReport.modifiers |= 0x40; // AltGr = right Alt
k &= 0x3F;
} else if ((k & SHIFT) == SHIFT) {
_keyReport.modifiers |= 0x02; // the left shift modifier
k &= 0x7F;
}
if (k == ISO_REPLACEMENT) {
k = ISO_KEY;
}
}
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i = 0; i < 6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
setWriteError();
return 0;
}
}
sendReport(&_keyReport);
return 1;
}
// release() takes the specified key out of the persistent key report and
// sends the report. This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t KeyboardBT_::release(uint8_t k) {
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers &= ~(1 << (k - 128));
k = 0;
} else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
return 0;
}
if ((k & ALT_GR) == ALT_GR) {
_keyReport.modifiers &= ~(0x40); // AltGr = right Alt
k &= 0x3F;
} else if ((k & SHIFT) == SHIFT) {
_keyReport.modifiers &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
if (k == ISO_REPLACEMENT) {
k = ISO_KEY;
}
}
// Test the key report to see if k is present. Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i = 0; i < 6; i++) {
if (0 != k && _keyReport.keys[i] == k) {
_keyReport.keys[i] = 0x00;
}
}
sendReport(&_keyReport);
return 1;
}
void KeyboardBT_::releaseAll(void) {
_keyReport.keys[0] = 0;
_keyReport.keys[1] = 0;
_keyReport.keys[2] = 0;
_keyReport.keys[3] = 0;
_keyReport.keys[4] = 0;
_keyReport.keys[5] = 0;
_keyReport.modifiers = 0;
sendReport(&_keyReport);
}
size_t KeyboardBT_::write(uint8_t c) {
uint8_t p = press(c); // Keydown
delay(10);
release(c); // Keyup
delay(10);
return p; // just return the result of press() since release() almost always returns 1
}
size_t KeyboardBT_::write(const uint8_t *buffer, size_t size) {
size_t n = 0;
while (size--) {
if (*buffer != '\r') {
if (write(*buffer)) {
n++;
} else {
break;
}
}
buffer++;
}
return n;
}
KeyboardBT_ KeyboardBT;
+141
View File
@@ -0,0 +1,141 @@
/*
KeyboardBT.h
Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
Main Arduino Library Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
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 KEYBOARDBT_h
#define KEYBOARDBT_h
#include <Arduino.h>
//================================================================================
//================================================================================
// Keyboard
// Modifiers
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
// Misc keys
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_MENU 0xED // "Keyboard Application" in USB standard
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_PRINT_SCREEN 0xCE // Print Screen / SysRq
#define KEY_SCROLL_LOCK 0xCF
#define KEY_PAUSE 0xD0 // Pause / Break
// Numeric keypad
#define KEY_NUM_LOCK 0xDB
#define KEY_KP_SLASH 0xDC
#define KEY_KP_ASTERISK 0xDD
#define KEY_KP_MINUS 0xDE
#define KEY_KP_PLUS 0xDF
#define KEY_KP_ENTER 0xE0
#define KEY_KP_1 0xE1
#define KEY_KP_2 0xE2
#define KEY_KP_3 0xE3
#define KEY_KP_4 0xE4
#define KEY_KP_5 0xE5
#define KEY_KP_6 0xE6
#define KEY_KP_7 0xE7
#define KEY_KP_8 0xE8
#define KEY_KP_9 0xE9
#define KEY_KP_0 0xEA
#define KEY_KP_DOT 0xEB
// Function keys
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
#define KEY_F13 0xF0
#define KEY_F14 0xF1
#define KEY_F15 0xF2
#define KEY_F16 0xF3
#define KEY_F17 0xF4
#define KEY_F18 0xF5
#define KEY_F19 0xF6
#define KEY_F20 0xF7
#define KEY_F21 0xF8
#define KEY_F22 0xF9
#define KEY_F23 0xFA
#define KEY_F24 0xFB
// Supported keyboard layouts
extern const uint8_t KeyboardLayout_de_DE[];
extern const uint8_t KeyboardLayout_en_US[];
extern const uint8_t KeyboardLayout_es_ES[];
extern const uint8_t KeyboardLayout_fr_FR[];
extern const uint8_t KeyboardLayout_it_IT[];
extern const uint8_t KeyboardLayout_sv_SE[];
extern const uint8_t KeyboardLayout_da_DK[];
// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct {
uint8_t modifiers;
uint8_t reserved;
uint8_t keys[6];
} KeyReport;
class KeyboardBT_ : public Print {
private:
KeyReport _keyReport;
const uint8_t *_asciimap;
void sendReport(KeyReport* keys);
public:
KeyboardBT_(void);
void begin(const uint8_t *layout = KeyboardLayout_en_US);
void end(void);
size_t write(uint8_t k);
size_t write(const uint8_t *buffer, size_t size);
size_t press(uint8_t k);
size_t release(uint8_t k);
void releaseAll(void);
};
extern KeyboardBT_ KeyboardBT;
#endif
+65
View File
@@ -0,0 +1,65 @@
/*
KeyboardLayout.h
This file is not part of the public API. It is meant to be included
only in Keyboard.cpp and the keyboard layout files. Layout files map
ASCII character codes to keyboard scan codes (technically, to USB HID
Usage codes), possibly altered by the SHIFT or ALT_GR modifiers.
== Creating your own layout ==
In order to create your own layout file, copy an existing layout that
is similar to yours, then modify it to use the correct keys. The
layout is an array in ASCII order. Each entry contains a scan code,
possibly modified by "|SHIFT" or "|ALT_GR", as in this excerpt from
the Italian layout:
0x35, // bslash
0x30|ALT_GR, // ]
0x2e|SHIFT, // ^
Do not change the control characters (those before scan code 0x2c,
corresponding to space). Do not attempt to grow the table past DEL. Do
not use both SHIFT and ALT_GR on the same character: this is not
supported. Unsupported characters should have 0x00 as scan code.
For a keyboard with an ISO physical layout, use the scan codes below:
+---+---+---+---+---+---+---+---+---+---+---+---+---+-------+
|35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp |
+---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+
| Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret |
+-----++--++--++--++--++--++--++--++--++--++--++--++--++ |
|CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 | |
+----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+
|Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 | Shift |
+----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+
|Ctrl|Win |Alt | |AlGr|Win |Menu|Ctrl|
+----+----+----+------------------------+----+----+----+----+
The ANSI layout is identical except that key 0x31 is above (rather
than next to) Return, and there is not key 0x32.
Give a unique name to the layout array, then declare it in Keyboard.h
with a line of the form:
extern const uint8_t KeyboardLayout_xx_YY[];
== Encoding details ==
All scan codes are less than 0x80, which makes bit 7 available to
signal that a modifier (Shift or AltGr) is needed to generate the
character. With only one exception, keys that are used with modifiers
have scan codes that are less than 0x40. This makes bit 6 available
to signal whether the modifier is Shift or AltGr. The exception is
0x64, the key next next to Left Shift on the ISO layout (and absent
from the ANSI layout). We handle it by replacing its value by 0x32 in
the layout arrays.
*/
#include <Arduino.h>
#define SHIFT 0x80
#define ALT_GR 0xc0
#define ISO_KEY 0x64
#define ISO_REPLACEMENT 0x32
@@ -0,0 +1,137 @@
/*
Danish keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_da_DK[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x20 | SHIFT, // #
0x21 | ALT_GR, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x31, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x31 | SHIFT, // *
0x2d, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x1f | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x25 | ALT_GR, // [
0x32 | ALT_GR, // bslash
0x26 | ALT_GR, // ]
0x00, // ^ not supported (requires dead key + space)
0x38 | SHIFT, // _
0x00, // ` not supported (requires dead key + space)
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x24 | ALT_GR, // {
0x2e | ALT_GR, // |
0x27 | ALT_GR, // }
0x00, // ~ not supported (requires dead key + space)
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
German keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_de_DE[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x31, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x31 | SHIFT, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x30 | SHIFT, // *
0x30, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x14 | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1d | SHIFT, // Y
0x1c | SHIFT, // Z
0x25 | ALT_GR, // [
0x2d | ALT_GR, // bslash
0x26 | ALT_GR, // ]
0x00, // ^ not supported (requires dead key + space)
0x38 | SHIFT, // _
0x00, // ` not supported (requires dead key + space)
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1d, // y
0x1c, // z
0x24 | ALT_GR, // {
0x32 | ALT_GR, // |
0x27 | ALT_GR, // }
0x30 | ALT_GR, // ~
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Standard US keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_en_US[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x34 | SHIFT, // "
0x20 | SHIFT, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x24 | SHIFT, // &
0x34, // '
0x26 | SHIFT, // (
0x27 | SHIFT, // )
0x25 | SHIFT, // *
0x2e | SHIFT, // +
0x36, // ,
0x2d, // -
0x37, // .
0x38, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x33 | SHIFT, // :
0x33, // ;
0x36 | SHIFT, // <
0x2e, // =
0x37 | SHIFT, // >
0x38 | SHIFT, // ?
0x1f | SHIFT, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f, // [
0x31, // bslash
0x30, // ]
0x23 | SHIFT, // ^
0x2d | SHIFT, // _
0x35, // `
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x2f | SHIFT, // {
0x31 | SHIFT, // |
0x30 | SHIFT, // }
0x35 | SHIFT, // ~
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Spanish keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_es_ES[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x20 | ALT_GR, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x2d, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x30 | SHIFT, // *
0x30, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x1f | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f | ALT_GR, // [
0x35 | ALT_GR, // bslash
0x30 | ALT_GR, // ]
0x00, // ^ not supported (requires dead key + space)
0x38 | SHIFT, // _
0x00, // ` not supported (requires dead key + space)
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x34 | ALT_GR, // {
0x1e | ALT_GR, // |
0x31 | ALT_GR, // }
0x00, // ~ not supported (requires dead key + space)
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Traditional (not AFNOR) French keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_fr_FR[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x38, // !
0x20, // "
0x20 | ALT_GR, // #
0x30, // $
0x34 | SHIFT, // %
0x1E, // &
0x21, // '
0x22, // (
0x2d, // )
0x31, // *
0x2e | SHIFT, // +
0x10, // ,
0x23, // -
0x36 | SHIFT, // .
0x37 | SHIFT, // /
0x27 | SHIFT, // 0
0x1e | SHIFT, // 1
0x1f | SHIFT, // 2
0x20 | SHIFT, // 3
0x21 | SHIFT, // 4
0x22 | SHIFT, // 5
0x23 | SHIFT, // 6
0x24 | SHIFT, // 7
0x25 | SHIFT, // 8
0x26 | SHIFT, // 9
0x37, // :
0x36, // ;
0x32, // <
0x2e, // =
0x32 | SHIFT, // >
0x10 | SHIFT, // ?
0x27 | ALT_GR, // @
0x14 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x33 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x04 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1d | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1a | SHIFT, // Z
0x22 | ALT_GR, // [
0x25 | ALT_GR, // bslash
0x2d | ALT_GR, // ]
0x26 | ALT_GR, // ^
0x25, // _
0x24 | ALT_GR, // `
0x14, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x33, // m
0x11, // n
0x12, // o
0x13, // p
0x04, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1d, // w
0x1b, // x
0x1c, // y
0x1a, // z
0x21 | ALT_GR, // {
0x23 | ALT_GR, // |
0x2e | ALT_GR, // }
0x1f | ALT_GR, // ~
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Italian keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_it_IT[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x34 | ALT_GR, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x2d, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x30 | SHIFT, // *
0x30, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x33 | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f | ALT_GR, // [
0x35, // bslash
0x30 | ALT_GR, // ]
0x2e | SHIFT, // ^
0x38 | SHIFT, // _
0x00, // ` not in this layout
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x00, // { not supported (requires AltGr+Shift)
0x35 | SHIFT, // |
0x00, // } not supported (requires AltGr+Shift)
0x00, // ~ not in this layout
0x00 // DEL
};
@@ -0,0 +1,137 @@
/*
Swedish keyboard layout.
*/
#include "KeyboardLayout.h"
extern const uint8_t KeyboardLayout_sv_SE[128] PROGMEM = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x1f | SHIFT, // "
0x20 | SHIFT, // #
0x21 | ALT_GR, // $
0x22 | SHIFT, // %
0x23 | SHIFT, // &
0x31, // '
0x25 | SHIFT, // (
0x26 | SHIFT, // )
0x31 | SHIFT, // *
0x2d, // +
0x36, // ,
0x38, // -
0x37, // .
0x24 | SHIFT, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x37 | SHIFT, // :
0x36 | SHIFT, // ;
0x32, // <
0x27 | SHIFT, // =
0x32 | SHIFT, // >
0x2d | SHIFT, // ?
0x1f | ALT_GR, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x25 | ALT_GR, // [
0x2d | ALT_GR, // bslash
0x26 | ALT_GR, // ]
0x00, // ^ not supported (requires dead key + space)
0x38 | SHIFT, // _
0x00, // ` not supported (requires dead key + space)
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x24 | ALT_GR, // {
0x32 | ALT_GR, // |
0x27 | ALT_GR, // }
0x00, // ~ not supported (requires dead key + space)
0x00 // DEL
};

Some files were not shown because too many files have changed in this diff Show More