Compare commits

..
31 Commits
Author SHA1 Message Date
Earle F. Philhower, III 7851dc8cb7 Update version 2023-03-10 09:08:28 -08:00
Philipp Molitor 75c553c391 Fix pin assigment for Waveshare RP2040 1.28 LCD PIN_BAT_ADC (#1292) 2023-03-10 04:31:33 -08:00
Earle F. Philhower, III 6bff270402 Manually add MDNS multicast Ethernet MACs to CYW43 (#1290)
SDK 1.5 changed the behavior of the underlying CYW43 blob, and it seems
to block MDNS multicast by default.  Manually add back the Ethernet MACs
used for MDNS multicast in IPV4 and IPV6.

Fixes #1267
2023-03-09 14:15:14 -08:00
nanoparticle 72f1e53106 Add board definition for Neko Systems BL2040 Mini (#1258) 2023-03-09 10:30:54 -08:00
Earle F. Philhower, III e6c7b97b5e Adjust LWIP intf to avoid hangs/crashes under load (#1286)
It seems possible now for TCP connection _pcbs to disappear while being
processed, due to the new async context configuration.  This would cause
LWIP to panic when a NULL pcb was passed in.

Check for and avoid passing in null PCBs in the ClientContext.

Undo special-casing of sys_check_timeouts wrapper

AdvancedWebServer with heavy F5-refresh and #1274 test both pass.

Fixes #1274
2023-03-08 11:48:23 -08:00
whimsee 54f9d3c414 Reassign I2C pins to correct buses (#1255) 2023-03-05 14:56:53 -08:00
Tim Boldtandtimboldt 9e272733cf Add instructions for making I2S input work with Adafruit microphone (#1272)
Co-authored-by: timboldt <tim.boldt@gmail.com>
2023-03-05 14:24:31 -08:00
Earle F. Philhower, III 51afd3440f Add Bluetooth to the PIO CI (#1269) 2023-03-05 08:48:24 -08:00
Sanjay Govind f67bc43584 Add Bluetooth support to Platform.io (#1259) 2023-03-05 08:23:22 -08:00
Earle F. Philhower, III 79e1af7bde Add Keyboard LED callback for USB and BT (not BLE) (#1265)
BLE seems to require some kind of characteristic callback that is not yeet
implemented here.  USB and BT tested and examples updated.
2023-03-04 14:18:40 -08:00
Earle F. Philhower, III 173c44417c Allow setting names for BT/BLE HID devices (#1260) 2023-03-04 12:38:34 -08:00
Earle F. Philhower, III 7aa1c08d17 Use generic HID classes to minimize code duplic'n (#1254)
Move the Joystick, Keyboard, and Mouse into a base class which handles
the operation/input, and a subclass which will implement the reporting
as a HID device via USB, Bluetooth Classic, or Bluetooth Low Energy (BLE).

Reduce copies of library code and makes maintainability much better.
2023-03-03 11:12:09 -08:00
Rei Vilo 0be1d9c3ea Fix picow default libname in platform.txt (#1250) 2023-03-03 07:40:02 -08:00
Earle F. Philhower, III 305e194993 Add setBattery to BLE HID devices (#1246) 2023-03-02 15:55:18 -08:00
Paint Your Dragon 719ab019a4 Add Adafruit Feather RP2040 DVI (#1245)
Includes option for QSPI/4 flash access on specific Adafruit boards for use when overclocking.
2023-03-02 15:54:19 -08:00
Earle F. Philhower, III e9df18f910 Update PicoBluetoothBLEHID.cpp 2023-03-02 08:18:02 -08:00
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
148 changed files with 8745 additions and 954 deletions
+2
View File
@@ -217,3 +217,5 @@ jobs:
run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino
- name: Build Signed OTA Example
run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/ArduinoOTA/examples/SignedOTA/SignedOTA.ino
- name: Build Bluetooth Example
run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" -O "build_flags=-DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH" libraries/MouseBLE/examples/BLECircle/BLECircle.ino
+7 -7
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
@@ -14,14 +14,14 @@
path = libraries/ESP8266SdFat
url = https://github.com/earlephilhower/ESP8266SdFat.git
[submodule "libraries/Keyboard"]
path = libraries/Keyboard
url = https://github.com/earlephilhower/Keyboard
path = libraries/HID_Keyboard
url = https://github.com/earlephilhower/Keyboard.git
[submodule "libraries/Mouse"]
path = libraries/Mouse
url = https://github.com/earlephilhower/Mouse
path = libraries/HID_Mouse
url = https://github.com/earlephilhower/Mouse.git
[submodule "libraries/Joystick"]
path = libraries/Joystick
url = https://github.com/benjaminaigner/Joystick
path = libraries/HID_Joystick
url = https://github.com/earlephilhower/Joystick.git
[submodule "libraries/Adafruit_TinyUSB_Arduino"]
path = libraries/Adafruit_TinyUSB_Arduino
url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git
+3 -1
View File
@@ -43,6 +43,7 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
* Invector Labs RPICO32
* Melopero Cookie RP2040
* Melopero Shake RP2040
* Neko Systems BL2040 Mini
* nullbits Bit-C PRO
* Pimoroni PGA2040
* Seeed XIAO RP2040
@@ -163,7 +164,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
+1077 -301
View File
File diff suppressed because it is too large Load Diff
+2 -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"
@@ -341,26 +342,8 @@ 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() {
+5 -3
View File
@@ -301,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
@@ -383,6 +383,7 @@ void __USBStart() {
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) __attribute__((weak));
extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
// TODO not implemented
(void) instance;
@@ -396,6 +397,7 @@ extern "C" uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, h
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) __attribute__((weak));
extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
// TODO set LED based on CAPLOCK, NUMLOCK etc...
(void) instance;
+4 -4
View File
@@ -1,5 +1,5 @@
#pragma once
#define ARDUINO_PICO_MAJOR 2
#define ARDUINO_PICO_MINOR 7
#define ARDUINO_PICO_REVISION 3
#define ARDUINO_PICO_VERSION_STR "2.7.3"
#define ARDUINO_PICO_MAJOR 3
#define ARDUINO_PICO_MINOR 1
#define ARDUINO_PICO_REVISION 0
#define ARDUINO_PICO_VERSION_STR "3.1.0"
+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
+12 -31
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,7 +255,8 @@ extern "C" {
return __real_udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
}
extern void __real_sys_check_timeouts(void);
// sys_check_timeouts is special case because the async process will call it. If we're already in a timeout check, just do a noop
extern void __real_sys_check_timeouts();
void __wrap_sys_check_timeouts(void) {
LWIPMutex m;
__real_sys_check_timeouts();
@@ -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:
+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.3'
version = u'3.1.0'
# The full version, including alpha/beta/rc tags.
release = u'2.7.3'
release = u'3.1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
+2
View File
@@ -43,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>
+3
View File
@@ -50,6 +50,9 @@ 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.
+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
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.
+1
View File
@@ -1,2 +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
+30
View File
@@ -0,0 +1,30 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
PicoBluetoothHID KEYWORD1
PicoBluetoothBLEHID KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
setOpenedCB KEYWORD2
setClosedCB KEYWORD2
setCanSendNowCB KEYWORD2
startHID KEYWORD2
connected KEYWORD2
send KEYWORD2
lockBluetooth KEYWORD2
unlockBluetooth KEYWORD2
getCID KEYWORD2
setBattery KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
@@ -0,0 +1,9 @@
name=HID_Bluetooth
version=1.0.0
author=Earle F. Philhower, III <earlephilhower@yahoo.com>
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Implements a HID device base class for PicoW Bluetooth
paragraph=Implements a HID device base class for PicoW Bluetooth
category=Device Control
url=https://github.com/earlephilhower/arduino-pico
architectures=rp2040
@@ -0,0 +1,7 @@
#ifdef ENABLE_CLASSIC
#include "PicoBluetoothHID.h"
#endif
#ifdef ENABLE_BLE
#include "PicoBluetoothBLEHID.h"
#endif
@@ -0,0 +1,23 @@
/*
PicoBluetoothBLEHID.h - Simple wrapper for BT-HID objects like
keyboards, mice, gamepads.
Copyright (c) 2023 Earle F. Philhower, III. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "PicoBluetoothBLEHID.h"
PicoBluetoothBLEHID_ PicoBluetoothBLEHID;
@@ -0,0 +1,484 @@
/*
PicoBluetoothBLEHID.h - Simple wrapper for BT-HID objects like
keyboards, mice, gamepads using Bluetooth LE mode
Based off of the BTStack HID main loop
Copyright (c) 2023 Earle F. Philhower, III. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <Arduino.h>
#include <functional>
#include <pico/cyw43_arch.h>
#include <class/hid/hid_device.h>
// The BTStack has redefinitions of this USB enum (same values, just redefined), so hide it to allow easy compilation
#define HID_REPORT_TYPE_INPUT HID_REPORT_TYPE_INPUT_BT
#define HID_REPORT_TYPE_OUTPUT HID_REPORT_TYPE_OUTPUT_BT
#define HID_REPORT_TYPE_FEATURE HID_REPORT_TYPE_FEATURE_BT
#define hid_report_type_t hid_report_type_t_bt
#include <btstack.h>
#undef hid_report_type_t
#undef HID_REPORT_TYPE_FEATURE
#undef HID_REPORT_TYPE_OUTPUT
#undef HID_REPORT_TYPE_INPUT
#include <ble/sm.h>
#include <ble/att_server.h>
#include <btstack_event.h>
#include <ble/gatt-service/battery_service_server.h>
#include <ble/gatt-service/device_information_service_server.h>
#include <ble/gatt-service/hids_device.h>
class PicoBluetoothBLEHID_;
extern PicoBluetoothBLEHID_ PicoBluetoothBLEHID;
class PicoBluetoothBLEHID_ {
public:
PicoBluetoothBLEHID_() {
}
~PicoBluetoothBLEHID_() {
}
// Optional callback, not used presently
// Usage: PicoBluetoothHID.setCanSendNowCB(std::bind(&kbd::onCanSendNow, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
typedef std::function<void(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size)> BTCallback;
void setOpenedCB(BTCallback cb) {
_onOpened = cb;
}
void setClosedCB(BTCallback cb) {
_onClosed = cb;
}
void setCanSendNowCB(BTCallback cb) {
_onCanSendNow = cb;
}
bool startHID(const char *localName, const char *hidName, uint16_t appearance, const uint8_t *hidDescriptor, uint16_t hidDescriptorSize, int battery = 100) {
if (_running) {
return false;
}
_running = true;
_buildAdvData(localName, appearance);
_buildAttdb(hidName);
_battery = battery;
// Setup L2CAP
l2cap_init();
// Setup SM
sm_init();
sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING);
// Setup ATT server
att_server_init(_attdb, NULL, NULL);
// Setup battery service
battery_service_server_init(battery);
// Setup device information service
device_information_service_server_init();
// Setup HID Device service
hids_device_init(0, hidDescriptor, hidDescriptorSize);
// Setup advertisements
uint16_t adv_int_min = 0x0030;
uint16_t adv_int_max = 0x0030;
uint8_t adv_type = 0;
bd_addr_t null_addr;
memset(null_addr, 0, 6);
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
gap_advertisements_set_data(_advDataLen, _advData);
gap_advertisements_enable(1);
// Register for HCI events
_hci_event_callback_registration.callback = PacketHandlerWrapper;
hci_add_event_handler(&_hci_event_callback_registration);
// Register for SM events
_sm_event_callback_registration.callback = PacketHandlerWrapper;
sm_add_event_handler(&_sm_event_callback_registration);
// Register for HIDS events
hids_device_register_packet_handler(PacketHandlerWrapper);
// GO!
hci_power_control(HCI_POWER_ON);
return true;
}
static void PacketHandlerWrapper(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t packet_size) {
PicoBluetoothBLEHID.packetHandler(packet_type, channel, packet, packet_size);
}
void packetHandler(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size) {
if (type != HCI_EVENT_PACKET) {
return;
}
switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_DISCONNECTION_COMPLETE:
_con_handle = HCI_CON_HANDLE_INVALID;
if (_onClosed) {
_onClosed(type, channel, packet, size);
}
break;
case SM_EVENT_JUST_WORKS_REQUEST:
sm_just_works_confirm(sm_event_just_works_request_get_handle(packet));
break;
case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
// printf("Confirming numeric comparison: %"PRIu32"\n", sm_event_numeric_comparison_request_get_passkey(packet));
sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet));
break;
case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
//printf("Display Passkey: %"PRIu32"\n", sm_event_passkey_display_number_get_passkey(packet));
break;
case HCI_EVENT_HIDS_META:
switch (hci_event_hids_meta_get_subevent_code(packet)) {
case HIDS_SUBEVENT_INPUT_REPORT_ENABLE:
_con_handle = hids_subevent_input_report_enable_get_con_handle(packet);
if (_onOpened) {
_onOpened(type, channel, packet, size);
}
break;
case HIDS_SUBEVENT_BOOT_KEYBOARD_INPUT_REPORT_ENABLE:
_con_handle = hids_subevent_boot_keyboard_input_report_enable_get_con_handle(packet);
if (_onOpened) {
_onOpened(type, channel, packet, size);
}
break;
case HIDS_SUBEVENT_PROTOCOL_MODE:
_protocol_mode = hids_subevent_protocol_mode_get_protocol_mode(packet);
break;
case HIDS_SUBEVENT_CAN_SEND_NOW:
switch (_protocol_mode) {
case 0:
hids_device_send_boot_keyboard_input_report(_con_handle, (const uint8_t *)_sendReport, _sendReportLen);
break;
case 1:
hids_device_send_input_report(_con_handle, (const uint8_t *)_sendReport, _sendReportLen);
break;
default:
break;
}
_needToSend = false;
if (_onCanSendNow) {
_onCanSendNow(type, channel, packet, size);
}
break;
}
break;
default:
break;
}
}
bool end() {
if (_running) {
hci_power_control(HCI_POWER_OFF);
}
_running = false;
_needToSend = false;
return true;
}
bool connected() {
return _con_handle != HCI_CON_HANDLE_INVALID;
}
bool send(void *rpt, int len) {
_needToSend = true;
_sendReport = rpt;
_sendReportLen = len;
lockBluetooth();
hids_device_request_can_send_now_event(_con_handle);
unlockBluetooth();
while (connected() && _needToSend) {
/* noop busy wait */
}
return connected();
}
bool setBattery(int level) {
if (!_running || (level < 0) || (level > 100)) {
return false;
}
battery_service_server_set_battery_value(level);
return true;
}
static void lockBluetooth() {
async_context_acquire_lock_blocking(cyw43_arch_async_context());
}
static void unlockBluetooth() {
async_context_release_lock(cyw43_arch_async_context());
}
private:
bool _running = false;
BTCallback _onOpened = nullptr;
BTCallback _onClosed = nullptr;
BTCallback _onCanSendNow = nullptr;
btstack_packet_callback_registration_t _hci_event_callback_registration;
btstack_packet_callback_registration_t _sm_event_callback_registration;
uint8_t _battery = 100;
hci_con_handle_t _con_handle = HCI_CON_HANDLE_INVALID;
uint8_t _protocol_mode = 1;
void _buildAdvData(const char *completeLocalName, uint16_t appearance) {
free(_advData);
_advDataLen = 13 + strlen(completeLocalName);
_advData = (uint8_t*) malloc(_advDataLen);
int i = 0;
// Flags general discoverable, BR/EDR not supported
// 0x02, BLUETOOTH_DATA_TYPE_FLAGS, 0x06,
_advData[i++] = 0x02;
_advData[i++] = BLUETOOTH_DATA_TYPE_FLAGS;
_advData[i++] = 0x06;
// Name
// 0x0d, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME,
_advData[i++] = 1 + strlen(completeLocalName);
_advData[i++] = BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME;
memcpy(_advData + i, completeLocalName, strlen(completeLocalName));
i += strlen(completeLocalName);
// 16-bit Service UUIDs
// 0x03, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS, ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE & 0xff, ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE >> 8,
_advData[i++] = 0x03;
_advData[i++] = BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS;
_advData[i++] = ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE & 0xff;
_advData[i++] = ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE >> 8;
// Appearance HID - Keyboard (Category 15, Sub-Category 1)
// 0x03, BLUETOOTH_DATA_TYPE_APPEARANCE, 0xC1, 0x03,
_advData[i++] = 0x03;
_advData[i++] = BLUETOOTH_DATA_TYPE_APPEARANCE;
_advData[i++] = appearance & 0xff;
_advData[i++] = appearance >> 8;
}
uint8_t *_advData = nullptr;
uint8_t _advDataLen = 0;
void _buildAttdb(const char *hidName) {
free(_attdb);
_attdbLen = sizeof(_attdb_head) + 8 + strlen(hidName) + sizeof(_attdb_tail);
_attdb = (uint8_t *) malloc(_attdbLen);
memcpy(_attdb, _attdb_head, sizeof(_attdb_head));
// 0x0003 VALUE CHARACTERISTIC-GAP_DEVICE_NAME - READ -'HID Mouse'
// READ_ANYBODY
// 0x11, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x2a, 0x48, 0x49, 0x44, 0x20, 0x4d, 0x6f, 0x75, 0x73, 0x65,
int i = sizeof(_attdb_head);
_attdb[i++] = 8 + strlen(hidName);
_attdb[i++] = 0x00;
_attdb[i++] = 0x02;
_attdb[i++] = 0x00;
_attdb[i++] = 0x03;
_attdb[i++] = 0x00;
_attdb[i++] = 0x00;
_attdb[i++] = 0x2a;
memcpy(_attdb + i, hidName, strlen(hidName));
i += strlen(hidName);
memcpy(_attdb + i, _attdb_tail, sizeof(_attdb_tail));
}
uint8_t *_attdb = nullptr;
int _attdbLen = 0;
static constexpr const uint8_t _attdb_head[] = {
// ATT DB Version
1,
// 0x0001 PRIMARY_SERVICE-GAP_SERVICE
0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18,
// 0x0002 CHARACTERISTIC-GAP_DEVICE_NAME - READ
0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x00, 0x2a,
};
static constexpr const uint8_t _attdb_tail[] = {
// #import <battery_service.gatt> -- BEGIN
// Specification Type org.bluetooth.service.battery_service
// https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.battery_service.xml
// Battery Service 180F
// 0x0004 PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE
0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x0f, 0x18,
// 0x0005 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL - DYNAMIC | READ | NOTIFY
0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x12, 0x06, 0x00, 0x19, 0x2a,
// 0x0006 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL - DYNAMIC | READ | NOTIFY
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x06, 0x00, 0x19, 0x2a,
// 0x0007 CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ANYBODY
0x0a, 0x00, 0x0e, 0x01, 0x07, 0x00, 0x02, 0x29, 0x00, 0x00,
// #import <battery_service.gatt> -- END
// add Device ID Service
// #import <device_information_service.gatt> -- BEGIN
// Specification Type org.bluetooth.service.device_information
// https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.device_information.xml
// Device Information 180A
// 0x0008 PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_DEVICE_INFORMATION
0x0a, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x28, 0x0a, 0x18,
// 0x0009 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x09, 0x00, 0x03, 0x28, 0x02, 0x0a, 0x00, 0x29, 0x2a,
// 0x000a VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x0a, 0x00, 0x29, 0x2a,
// 0x000b CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x28, 0x02, 0x0c, 0x00, 0x24, 0x2a,
// 0x000c VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x0c, 0x00, 0x24, 0x2a,
// 0x000d CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x03, 0x28, 0x02, 0x0e, 0x00, 0x25, 0x2a,
// 0x000e VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x0e, 0x00, 0x25, 0x2a,
// 0x000f CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x0f, 0x00, 0x03, 0x28, 0x02, 0x10, 0x00, 0x27, 0x2a,
// 0x0010 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x10, 0x00, 0x27, 0x2a,
// 0x0011 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x11, 0x00, 0x03, 0x28, 0x02, 0x12, 0x00, 0x26, 0x2a,
// 0x0012 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x12, 0x00, 0x26, 0x2a,
// 0x0013 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x13, 0x00, 0x03, 0x28, 0x02, 0x14, 0x00, 0x28, 0x2a,
// 0x0014 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x14, 0x00, 0x28, 0x2a,
// 0x0015 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x15, 0x00, 0x03, 0x28, 0x02, 0x16, 0x00, 0x23, 0x2a,
// 0x0016 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x16, 0x00, 0x23, 0x2a,
// 0x0017 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x17, 0x00, 0x03, 0x28, 0x02, 0x18, 0x00, 0x2a, 0x2a,
// 0x0018 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x18, 0x00, 0x2a, 0x2a,
// 0x0019 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x19, 0x00, 0x03, 0x28, 0x02, 0x1a, 0x00, 0x50, 0x2a,
// 0x001a VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x1a, 0x00, 0x50, 0x2a,
// #import <device_information_service.gatt> -- END
// #import <hids.gatt> -- BEGIN
// Specification Type org.bluetooth.service.human_interface_device
// https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.human_interface_device.xml
// Human Interface Device 1812
// 0x001b PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE
0x0a, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x28, 0x12, 0x18,
// 0x001c CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE - DYNAMIC | READ | WRITE_WITHOUT_RESPONSE
0x0d, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x03, 0x28, 0x06, 0x1d, 0x00, 0x4e, 0x2a,
// 0x001d VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE - DYNAMIC | READ | WRITE_WITHOUT_RESPONSE
// READ_ANYBODY, WRITE_ANYBODY
0x08, 0x00, 0x06, 0x01, 0x1d, 0x00, 0x4e, 0x2a,
// 0x001e CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16
0x0d, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x03, 0x28, 0x1a, 0x1f, 0x00, 0x4d, 0x2a,
// 0x001f VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16
// READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x08, 0x00, 0x0b, 0xf5, 0x1f, 0x00, 0x4d, 0x2a,
// 0x0020 CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x0a, 0x00, 0x0f, 0xf1, 0x20, 0x00, 0x02, 0x29, 0x00, 0x00,
// fixed report id = 1, type = Input (1)
// 0x0021 REPORT_REFERENCE-READ-1-1
0x0a, 0x00, 0x02, 0x00, 0x21, 0x00, 0x08, 0x29, 0x1, 0x1,
// 0x0022 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16
0x0d, 0x00, 0x02, 0x00, 0x22, 0x00, 0x03, 0x28, 0x1a, 0x23, 0x00, 0x4d, 0x2a,
// 0x0023 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16
// READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x08, 0x00, 0x0b, 0xf5, 0x23, 0x00, 0x4d, 0x2a,
// 0x0024 CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x0a, 0x00, 0x0f, 0xf1, 0x24, 0x00, 0x02, 0x29, 0x00, 0x00,
// fixed report id = 2, type = Output (2)
// 0x0025 REPORT_REFERENCE-READ-2-2
0x0a, 0x00, 0x02, 0x00, 0x25, 0x00, 0x08, 0x29, 0x2, 0x2,
// 0x0026 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16
0x0d, 0x00, 0x02, 0x00, 0x26, 0x00, 0x03, 0x28, 0x1a, 0x27, 0x00, 0x4d, 0x2a,
// 0x0027 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16
// READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x08, 0x00, 0x0b, 0xf5, 0x27, 0x00, 0x4d, 0x2a,
// 0x0028 CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x0a, 0x00, 0x0f, 0xf1, 0x28, 0x00, 0x02, 0x29, 0x00, 0x00,
// fixed report id = 3, type = Feature (3)
// 0x0029 REPORT_REFERENCE-READ-3-3
0x0a, 0x00, 0x02, 0x00, 0x29, 0x00, 0x08, 0x29, 0x3, 0x3,
// 0x002a CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT_MAP - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x03, 0x28, 0x02, 0x2b, 0x00, 0x4b, 0x2a,
// 0x002b VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT_MAP - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x2b, 0x00, 0x4b, 0x2a,
// 0x002c CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY
0x0d, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x03, 0x28, 0x1a, 0x2d, 0x00, 0x22, 0x2a,
// 0x002d VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY
// READ_ANYBODY, WRITE_ANYBODY
0x08, 0x00, 0x0a, 0x01, 0x2d, 0x00, 0x22, 0x2a,
// 0x002e CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ANYBODY
0x0a, 0x00, 0x0e, 0x01, 0x2e, 0x00, 0x02, 0x29, 0x00, 0x00,
// 0x002f CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_OUTPUT_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE
0x0d, 0x00, 0x02, 0x00, 0x2f, 0x00, 0x03, 0x28, 0x0e, 0x30, 0x00, 0x32, 0x2a,
// 0x0030 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_OUTPUT_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE
// READ_ANYBODY, WRITE_ANYBODY
0x08, 0x00, 0x0e, 0x01, 0x30, 0x00, 0x32, 0x2a,
// 0x0031 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY
0x0d, 0x00, 0x02, 0x00, 0x31, 0x00, 0x03, 0x28, 0x1a, 0x32, 0x00, 0x33, 0x2a,
// 0x0032 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY
// READ_ANYBODY, WRITE_ANYBODY
0x08, 0x00, 0x0a, 0x01, 0x32, 0x00, 0x33, 0x2a,
// 0x0033 CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ANYBODY
0x0a, 0x00, 0x0e, 0x01, 0x33, 0x00, 0x02, 0x29, 0x00, 0x00,
// bcdHID = 0x101 (v1.0.1), bCountryCode 0, remote wakeable = 0 | normally connectable 2
// 0x0034 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION - READ
0x0d, 0x00, 0x02, 0x00, 0x34, 0x00, 0x03, 0x28, 0x02, 0x35, 0x00, 0x4a, 0x2a,
// 0x0035 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION - READ -'01 01 00 02'
// READ_ANYBODY
0x0c, 0x00, 0x02, 0x00, 0x35, 0x00, 0x4a, 0x2a, 0x01, 0x01, 0x00, 0x02,
// 0x0036 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT - DYNAMIC | WRITE_WITHOUT_RESPONSE
0x0d, 0x00, 0x02, 0x00, 0x36, 0x00, 0x03, 0x28, 0x04, 0x37, 0x00, 0x4c, 0x2a,
// 0x0037 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT - DYNAMIC | WRITE_WITHOUT_RESPONSE
// WRITE_ANYBODY
0x08, 0x00, 0x04, 0x01, 0x37, 0x00, 0x4c, 0x2a,
// #import <hids.gatt> -- END
// 0x0038 PRIMARY_SERVICE-GATT_SERVICE
0x0a, 0x00, 0x02, 0x00, 0x38, 0x00, 0x00, 0x28, 0x01, 0x18,
// 0x0039 CHARACTERISTIC-GATT_DATABASE_HASH - READ
0x0d, 0x00, 0x02, 0x00, 0x39, 0x00, 0x03, 0x28, 0x02, 0x3a, 0x00, 0x2a, 0x2b,
// 0x003a VALUE CHARACTERISTIC-GATT_DATABASE_HASH - READ -''
// READ_ANYBODY
0x18, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x2a, 0x2b, 0xc2, 0x10, 0xf5, 0x75, 0xf3, 0x9f, 0x50, 0xb6, 0x83, 0xc7, 0xfa, 0xac, 0xa6, 0x1b, 0x7d, 0x32,
// END
0x00, 0x00
};
volatile bool _needToSend = false;
void *_sendReport;
int _sendReportLen;
};
@@ -0,0 +1,23 @@
/*
PicoBluetoothHID.h - Simple wrapper for BT-HID objects like
keyboards, mice, gamepads.
Copyright (c) 2023 Earle F. Philhower, III. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "PicoBluetoothHID.h"
PicoBluetoothHID_ PicoBluetoothHID;
@@ -0,0 +1,255 @@
/*
PicoBluetoothHID.h - Simple wrapper for BT-HID objects like
keyboards, mice, gamepads.
Based off of the BTStack HID main loop
Copyright (c) 2023 Earle F. Philhower, III. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <Arduino.h>
#include <functional>
#include <pico/cyw43_arch.h>
#include <class/hid/hid_device.h>
// The BTStack has redefinitions of this USB enum (same values, just redefined), so hide it to allow easy compilation
#define HID_REPORT_TYPE_INPUT HID_REPORT_TYPE_INPUT_BT
#define HID_REPORT_TYPE_OUTPUT HID_REPORT_TYPE_OUTPUT_BT
#define HID_REPORT_TYPE_FEATURE HID_REPORT_TYPE_FEATURE_BT
#define hid_report_type_t hid_report_type_t_bt
#include <btstack.h>
#undef hid_report_type_t
#undef HID_REPORT_TYPE_FEATURE
#undef HID_REPORT_TYPE_OUTPUT
#undef HID_REPORT_TYPE_INPUT
class PicoBluetoothHID_;
extern PicoBluetoothHID_ PicoBluetoothHID;
class PicoBluetoothHID_ {
public:
PicoBluetoothHID_() {
}
~PicoBluetoothHID_() {
}
// Optional callback, not used presently
// Usage: PicoBluetoothHID.setCanSendNowCB(std::bind(&kbd::onCanSendNow, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
typedef std::function<void(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size)> BTCallback;
void setOpenedCB(BTCallback cb) {
_onOpened = cb;
}
void setClosedCB(BTCallback cb) {
_onClosed = cb;
}
void setCanSendNowCB(BTCallback cb) {
_onCanSendNow = cb;
}
bool startHID(const char *localName, const char *hidName, uint16_t hidClass, uint8_t hidSubclass, const uint8_t *hidDescriptor, uint16_t hidDescriptorSize) {
if (_running) {
return false;
}
_running = true;
// Allow finding via inquiry
gap_discoverable_control(1);
// Use Limited Discoverable Mode; Peripheral; Keyboard as CoD
gap_set_class_of_device(hidClass);
// Set local name to be identified - zeroes will be replaced by actual BD ADDR
gap_set_local_name(localName);
// Allow for role switch in general and sniff mode
gap_set_default_link_policy_settings(LM_LINK_POLICY_ENABLE_ROLE_SWITCH | LM_LINK_POLICY_ENABLE_SNIFF_MODE);
// Allow for role switch on outgoing connections - this allow HID Host to become master when we re-connect to it
gap_set_allow_role_switch(true);
// L2CAP
l2cap_init();
#ifdef ENABLE_BLE
// Initialize LE Security Manager. Needed for cross-transport key derivation
sm_init();
#endif
// SDP Server
sdp_init();
bzero(_hid_service_buffer, sizeof(_hid_service_buffer));
const uint8_t hid_boot_device = 0;
const uint8_t hid_virtual_cable = 0;
const uint8_t hid_remote_wake = 1;
const uint8_t hid_reconnect_initiate = 1;
const uint8_t hid_normally_connectable = 1;
// When not set to 0xffff, sniff and sniff subrating are enabled
const uint16_t host_max_latency = 1600;
const uint16_t host_min_timeout = 3200;
hid_sdp_record_t hid_params = {
hidClass, hidSubclass,
hid_virtual_cable, hid_remote_wake,
hid_reconnect_initiate, (bool)hid_normally_connectable,
(bool)hid_boot_device,
host_max_latency, host_min_timeout,
3200,
hidDescriptor,
hidDescriptorSize,
hidName
};
hid_create_sdp_record(_hid_service_buffer, 0x10001, &hid_params);
sdp_register_service(_hid_service_buffer);
// See https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers if you don't have a USB Vendor ID and need a Bluetooth Vendor ID
// device info: BlueKitchen GmbH, product 1, version 1
device_id_create_sdp_record(_device_id_sdp_service_buffer, 0x10003, DEVICE_ID_VENDOR_ID_SOURCE_BLUETOOTH, BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, 1, 1);
sdp_register_service(_device_id_sdp_service_buffer);
// HID Device
hid_device_init(hid_boot_device, hidDescriptorSize, hidDescriptor);
// register for HCI events
_hci_event_callback_registration.callback = PacketHandlerWrapper;
hci_add_event_handler(&_hci_event_callback_registration);
// register for HID events
hid_device_register_packet_handler(PacketHandlerWrapper);
hci_power_control(HCI_POWER_ON);
return true;
}
static void PacketHandlerWrapper(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t packet_size) {
PicoBluetoothHID.packetHandler(packet_type, channel, packet, packet_size);
}
void packetHandler(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size) {
uint8_t status;
if (type != HCI_EVENT_PACKET) {
return;
}
switch (hci_event_packet_get_type(packet)) {
case BTSTACK_EVENT_STATE:
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) {
return;
}
_appState = APP_NOT_CONNECTED;
break;
case HCI_EVENT_USER_CONFIRMATION_REQUEST:
// ssp: inform about user confirmation request
//log_info("SSP User Confirmation Request with numeric value '%06" PRIu32 "'\n", hci_event_user_confirmation_request_get_numeric_value(packet));
//log_info("SSP User Confirmation Auto accept\n");
break;
case HCI_EVENT_HID_META:
switch (hci_event_hid_meta_get_subevent_code(packet)) {
case HID_SUBEVENT_CONNECTION_OPENED:
status = hid_subevent_connection_opened_get_status(packet);
if (status != ERROR_CODE_SUCCESS) {
// outgoing connection failed
_appState = APP_NOT_CONNECTED;
_hid_cid = 0;
return;
}
_appState = APP_CONNECTED;
_hid_cid = hid_subevent_connection_opened_get_hid_cid(packet);
if (_onOpened) {
_onOpened(type, channel, packet, size);
}
break;
case HID_SUBEVENT_CONNECTION_CLOSED:
_appState = APP_NOT_CONNECTED;
_hid_cid = 0;
if (_onClosed) {
_onClosed(type, channel, packet, size);
}
break;
case HID_SUBEVENT_CAN_SEND_NOW:
uint8_t report[2 + _sendReportLen];
report[0] = 0xa1;
report[1] = _sendReportID;
memcpy(report + 2, _sendReport, _sendReportLen);
hid_device_send_interrupt_message(getCID(), report, sizeof(report));
_needToSend = false;
if (_onCanSendNow) {
_onCanSendNow(type, channel, packet, size);
}
break;
}
}
}
bool end() {
if (_running) {
hci_power_control(HCI_POWER_OFF);
}
_running = false;
_needToSend = false;
return true;
}
bool connected() {
return _appState == APP_CONNECTED;
}
bool send(int id, void *rpt, int len) {
_needToSend = true;
_sendReportID = id;
_sendReport = rpt;
_sendReportLen = len;
lockBluetooth();
hid_device_request_can_send_now_event(getCID());
unlockBluetooth();
while (connected() && _needToSend) {
/* noop busy wait */
}
return connected();
}
static void lockBluetooth() {
async_context_acquire_lock_blocking(cyw43_arch_async_context());
}
static void unlockBluetooth() {
async_context_release_lock(cyw43_arch_async_context());
}
uint16_t getCID() {
return _hid_cid;
}
private:
bool _running = false;
enum {APP_BOOTING, APP_NOT_CONNECTED, APP_CONNECTING, APP_CONNECTED} _appState = APP_BOOTING;
BTCallback _onOpened = nullptr;
BTCallback _onClosed = nullptr;
BTCallback _onCanSendNow = nullptr;
uint8_t _hid_service_buffer[300];
uint8_t _device_id_sdp_service_buffer[100];
btstack_packet_callback_registration_t _hci_event_callback_registration;
uint16_t _hid_cid;
volatile bool _needToSend = false;
int _sendReportID;
void *_sendReport;
int _sendReportLen;
};
Submodule libraries/HID_Mouse added at 2aa06d1615
+21 -2
View File
@@ -10,6 +10,19 @@
+-- ------------------------------------ --+
left RPI | (1) GND (2) DIN (3) BCLK (4) LRCLK (5) 3.3V | AIY right
logo +---------------------------------------------+ logo
For an Adfruit I2S MEMS microphone (https://www.adafruit.com/product/3421),
connect the pins as follows:
DOUT -> GPIO0
BCLK <- GPIO1
LRCL <- GPIO2 # LRCLK = BCLK + 1
GND <-> GND
3V <-> 3V3OUT
The other idiosyncrasy of most modern MEMS microphones is that they
require a minimum clock rate to wake up. For example, the SPH0645
microphone needs at least 1MHz.
*/
#include <I2S.h>
@@ -20,15 +33,21 @@ void setup() {
Serial.begin(115200);
i2s.setDATA(0);
i2s.setBCLK(1); // LRCLK = GP2
i2s.setBCLK(1); // Note: LRCLK = BCLK + 1
i2s.setBitsPerSample(16);
i2s.setFrequency(22050);
// NOTE: The following values are known to work with the Adafruit microphone:
// i2s.setBitsPerSample(32);
// i2s.setFrequency(16000);
i2s.begin();
while (1) {
int16_t l, r;
i2s.read16(&l, &r);
Serial.printf("%d %d\n", l, r);
// NOTE: Adafruit microphone word size needs to match the BPS above.
// int32_t l, r;
// i2s.read32(&l, &r);
Serial.printf("%d %d\r\n", l, r);
}
}
+32
View File
@@ -0,0 +1,32 @@
: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.
== 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 <Joystick.h>
void setup() {
Serial.begin(115200);
Serial.println("Use BOOTSEL to start the Joystick demo.");
Joystick.begin();
}
void loop() {
if (BOOTSEL) {
Serial.println("Joystick buttons");
for (uint8_t i = 1; i <= 32; i++) {
Joystick.button(i, true);
delay(250);
Joystick.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:
Joystick.useManualSend(true);
Serial.println("Joystick buttons - manual send");
for (uint8_t i = 1; i <= 32; i++) {
Joystick.button(i, true);
Joystick.send_now();
delay(250);
Joystick.button(i, false);
}
Joystick.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++) {
Joystick.X(i);
delay(2);
} Joystick.X(512);
Serial.println("Joystick Y");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.Y(i);
delay(2);
} Joystick.Y(512);
Serial.println("Joystick Z");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.Z(i);
delay(2);
} Joystick.Z(512);
Serial.println("Joystick Zrotate");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.Zrotate(i);
delay(2);
} Joystick.Zrotate(512);
Serial.println("Joystick sliderLeft");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.sliderLeft(i);
delay(2);
} Joystick.sliderLeft(0);
Serial.println("Joystick sliderRight");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.sliderRight(i);
delay(2);
} Joystick.sliderRight(0);
Serial.println("Joystick hat");
for (uint16_t i = 0; i < 360; i++) {
Joystick.hat(i);
delay(20);
} Joystick.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");
Joystick.use8bit(true);
Serial.println("Joystick X");
for (int16_t i = -127; i < 128; i++) {
Joystick.X(i);
delay(2);
} Joystick.X(0);
Serial.println("Joystick Y");
for (int16_t i = -127; i < 128; i++) {
Joystick.Y(i);
delay(2);
} Joystick.Y(0);
Serial.println("Joystick Z");
for (int16_t i = -127; i < 128; i++) {
Joystick.Z(i);
delay(2);
} Joystick.Z(0);
Serial.println("Joystick Zrotate");
for (int16_t i = -127; i < 128; i++) {
Joystick.Zrotate(i);
delay(2);
} Joystick.Zrotate(0);
Serial.println("Joystick sliderLeft");
for (int16_t i = -127; i < 128; i++) {
Joystick.sliderLeft(i);
delay(2);
} Joystick.sliderLeft(0);
Serial.println("Joystick sliderRight");
for (int16_t i = -127; i < 128; i++) {
Joystick.sliderRight(i);
delay(2);
} Joystick.sliderRight(0);
Joystick.use8bit(false);
}
}
+33
View File
@@ -0,0 +1,33 @@
#######################################
# Syntax Coloring Map For Joystick
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Joystick 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=Joystick
version=1.0.1
author=Benjamin Aigner
maintainer=Benjamin Aigner <beni@asterics-foundation.org>
sentence=Allows any RP2040 board to act as a joystick/gamepad
paragraph=Allows the RP2040 to emulate a USB Joystick
category=Device Control
url=https://github.com/benjaminaigner/Joystick
architectures=rp2040
+49
View File
@@ -0,0 +1,49 @@
/*
Joystick.cpp
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
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 "Joystick.h"
#include "Arduino.h"
#include <RP2040USB.h>
#include "tusb.h"
#include "class/hid/hid_device.h"
// Weak function override to add our descriptor to the TinyUSB list
void __USBInstallJoystick() { /* noop */ }
Joystick_::Joystick_(void) {
// Everything set up in HID_Joystick constructor
}
//immediately send an HID report
void Joystick_::send_now(void) {
CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_n_report(0, __USBGetJoystickReportID(), &data, sizeof(data));
}
tud_task();
}
Joystick_ Joystick;
+35
View File
@@ -0,0 +1,35 @@
/*
Joystick.h
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
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 _JOYSTICK_h
#define _JOYSTICK_h
#include <HID_Joystick.h>
#include "class/hid/hid.h"
//======================================================================
class Joystick_ : public HID_Joystick {
public:
Joystick_(void);
virtual void send_now(void) override;
};
extern Joystick_ Joystick;
#endif /* _JOYSTICK_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);
}
}
+34
View File
@@ -0,0 +1,34 @@
#######################################
# 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
setBattery 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
+63
View File
@@ -0,0 +1,63 @@
/*
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) {
// Member vars set in base constructor
}
#define REPORT_ID 0x01
static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))};
void JoystickBLE_::begin(const char *localName, const char *hidName) {
if (!localName) {
localName = "PicoW BLE Joystick";
}
if (!hidName) {
hidName = localName;
}
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c4, desc_joystick, sizeof(desc_joystick));
}
void JoystickBLE_::end() {
PicoBluetoothBLEHID.end();
}
void JoystickBLE_::setBattery(int lvl) {
PicoBluetoothBLEHID.setBattery(lvl);
}
void JoystickBLE_::send_now() {
PicoBluetoothBLEHID.send(&data, sizeof(data));
}
JoystickBLE_ JoystickBLE;
+36
View File
@@ -0,0 +1,36 @@
/*
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 <HID_Joystick.h>
#include "class/hid/hid.h"
//======================================================================
class JoystickBLE_ : public HID_Joystick {
public:
JoystickBLE_();
void begin(const char *localName = nullptr, const char *hidName = nullptr);
void end();
virtual void send_now() override;
void setBattery(int lvl);
};
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("PicoJoy Demo");
}
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
+60
View File
@@ -0,0 +1,60 @@
/*
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_() {
// HID_Joystick sets up all the member vars
}
#define REPORT_ID 0x01
static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))};
void JoystickBT_::begin(const char *localName, const char *hidName) {
if (!localName) {
localName = "PicoW BT Joystick";
}
if (!hidName) {
hidName = localName;
}
PicoBluetoothHID.startHID(localName, hidName, 0x2508, 33, desc_joystick, sizeof(desc_joystick));
}
void JoystickBT_::end() {
PicoBluetoothHID.end();
}
//immediately send an HID report
void JoystickBT_::send_now() {
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
}
JoystickBT_ JoystickBT;
+35
View File
@@ -0,0 +1,35 @@
/*
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 <HID_Joystick.h>
#include "class/hid/hid.h"
//======================================================================
class JoystickBT_ : public HID_Joystick {
public:
JoystickBT_();
void begin(const char *localName = nullptr, const char *hidName = nullptr);
void end();
virtual void send_now() override;
};
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,32 @@
/* Released into the public domain */
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
#include <Keyboard.h>
void ledCB(bool numlock, bool capslock, bool scrolllock, bool compose, bool kana, void *cbData) {
(void) numlock;
(void) scrolllock;
(void) compose;
(void) kana;
(void) cbData;
digitalWrite(LED_BUILTIN, capslock ? HIGH : LOW);
}
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Keyboard.onLED(ledCB);
Keyboard.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....");
Keyboard.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 "Keyboard.h"
void setup() {
// open the serial port:
Serial.begin(9600);
// initialize control over the keyboard:
Keyboard.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:
Keyboard.write(inChar + 1);
}
}
+24
View File
@@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map For Keyboard
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Keyboard 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=Keyboard
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
category=Device Control
url=https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
architectures=rp2040
+59
View File
@@ -0,0 +1,59 @@
/*
Keyboard.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 "Keyboard.h"
#include <RP2040USB.h>
#include "tusb.h"
#include "class/hid/hid_device.h"
// Weak function override to add our descriptor to the TinyUSB list
void __USBInstallKeyboard() { /* noop */ }
//================================================================================
//================================================================================
// Keyboard
Keyboard_::Keyboard_(void) {
// Base class clears the members we care about
}
void Keyboard_::sendReport(KeyReport* keys) {
CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_keyboard_report(__USBGetKeyboardReportID(), keys->modifiers, keys->keys);
}
tud_task();
}
extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
(void) report_id;
(void) instance;
if ((report_type == HID_REPORT_TYPE_OUTPUT) && (bufsize > 0) && (Keyboard._ledCB)) {
uint8_t const kbd_leds = buffer[0];
Keyboard._ledCB(kbd_leds & KEYBOARD_LED_NUMLOCK, kbd_leds & KEYBOARD_LED_CAPSLOCK, kbd_leds & KEYBOARD_LED_SCROLLLOCK, kbd_leds & KEYBOARD_LED_COMPOSE, kbd_leds & KEYBOARD_LED_KANA, Keyboard._ledCBdata);
}
}
Keyboard_ Keyboard;
+37
View File
@@ -0,0 +1,37 @@
/*
Keyboard.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 KEYBOARD_h
#define KEYBOARD_h
#include <HID_Keyboard.h>
class Keyboard_ : public HID_Keyboard {
protected:
virtual void sendReport(KeyReport* keys) override;
public:
Keyboard_(void);
};
extern Keyboard_ Keyboard;
#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,21 @@
/* 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");
KeyboardBLE.setBattery(random(0, 101)); // Set between 0...100%
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
setBattery 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
+66
View File
@@ -0,0 +1,66 @@
/*
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) {
// Base class clears the members we care about
}
#define REPORT_ID 0x01
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))};
void KeyboardBLE_::begin(const char *localName, const char *hidName, const uint8_t *layout) {
if (!localName) {
localName = "PicoW BLE Keyboard";
}
if (!hidName) {
hidName = localName;
}
_asciimap = layout;
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c1, desc_keyboard, sizeof(desc_keyboard));
}
void KeyboardBLE_::end(void) {
PicoBluetoothBLEHID.end();
}
void KeyboardBLE_::setBattery(int lvl) {
PicoBluetoothBLEHID.setBattery(lvl);
}
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));
}
KeyboardBLE_ KeyboardBLE;
+39
View File
@@ -0,0 +1,39 @@
/*
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 <HID_Keyboard.h>
class KeyboardBLE_ : public HID_Keyboard {
private:
virtual void sendReport(KeyReport* keys) override;
public:
KeyboardBLE_(void);
void begin(const char *localName = nullptr, const char *hidName = nullptr, const uint8_t *layout = KeyboardLayout_en_US);
void end(void);
void setBattery(int lvl);
};
extern KeyboardBLE_ KeyboardBLE;
#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,33 @@
/* Released into the public domain */
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
#include <KeyboardBT.h>
void ledCB(bool numlock, bool capslock, bool scrolllock, bool compose, bool kana, void *cbData) {
(void) numlock;
(void) scrolllock;
(void) compose;
(void) kana;
(void) cbData;
digitalWrite(LED_BUILTIN, capslock ? HIGH : LOW);
}
void setup() {
Serial.begin(115200);
KeyboardBT.begin("PicoW Password");
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
KeyboardBT.onLED(ledCB);
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
+74
View File
@@ -0,0 +1,74 @@
/*
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) {
// Base class clears the members we care about
}
#define REPORT_ID 0x01
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))};
static void _hidReportCB(uint16_t cid, hid_report_type_t report_type, uint16_t report_id, int report_size, uint8_t *report) {
(void) cid;
(void) report_id;
if ((report_type == HID_REPORT_TYPE_OUTPUT) && (report_size > 0) && (KeyboardBT._ledCB)) {
uint8_t const kbd_leds = report[0];
KeyboardBT._ledCB(kbd_leds & KEYBOARD_LED_NUMLOCK, kbd_leds & KEYBOARD_LED_CAPSLOCK, kbd_leds & KEYBOARD_LED_SCROLLLOCK, kbd_leds & KEYBOARD_LED_COMPOSE, kbd_leds & KEYBOARD_LED_KANA, KeyboardBT._ledCBdata);
}
}
void KeyboardBT_::begin(const char *localName, const char *hidName, const uint8_t *layout) {
if (!localName) {
localName = "PicoW BT Keyboard";
}
if (!hidName) {
hidName = localName;
}
_asciimap = layout;
// Required because the hid_report_type_t overlap in BTStack and TUSB
auto *fcn = (void (*)(short unsigned int, hid_report_type_t_bt, short unsigned int, int, unsigned char*))_hidReportCB;
hid_device_register_report_data_callback(fcn);
PicoBluetoothHID.startHID(localName, hidName, 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));
}
KeyboardBT_ KeyboardBT;
+38
View File
@@ -0,0 +1,38 @@
/*
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 <HID_Keyboard.h>
class KeyboardBT_ : public HID_Keyboard {
protected:
virtual void sendReport(KeyReport* keys) override;
public:
KeyboardBT_(void);
void begin(const char *localName = nullptr, const char *hidName = nullptr, const uint8_t *layout = KeyboardLayout_en_US);
void end(void);
};
extern KeyboardBT_ KeyboardBT;
#endif
Submodule libraries/Mouse deleted from be7395a597
+31
View File
@@ -0,0 +1,31 @@
:repository-owner: arduino-libraries
:repository-name: Mouse
= {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 Mouse.
For more information about this library please visit us at
https://www.arduino.cc/reference/en/language/functions/usb/mouse/
== 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
+428
View File
@@ -0,0 +1,428 @@
# Mouse library
## Methods
### `Mouse.begin()`
Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`.
#### Syntax
```
Mouse.begin()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
}
void loop() {
// Initialize the Mouse library when button is pressed
if (digitalRead(2) == HIGH) {
Mouse.begin();
}
}
```
#### See also
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.click()`
Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button.
`Mouse.click()` defaults to the left mouse button.
#### Syntax
```
Mouse.click()
Mouse.click(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
}
}
```
#### Notes and warnings
When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.end()`
Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`.
#### Syntax
```
Mouse.end()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initiate the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
// Then end the Mouse emulation
Mouse.end();
}
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.move()`
Moves the cursor on a connected computer. The motion onscreen is always relative to the cursor’s current location. Before using `Mouse.move()` you must call `Mouse.begin()`.
#### Syntax
```
Mouse.move(xVal, yVal, wheel)
```
#### Parameters
* `xVal`: amount to move along the x-axis. Allowed data types: signed char.
* `yVal`: amount to move along the y-axis. Allowed data types: signed char.
* `wheel`: amount to move scroll wheel. Allowed data types: signed char.
#### Returns
None.
#### Example
```
#include <Mouse.h>
const int xAxis = A1; // Analog sensor for X axis
const int yAxis = A2; // Analog sensor for Y axis
int range = 12; // Output range of X or Y movement
int responseDelay = 2; // Response delay of the mouse, in ms
int threshold = range / 4; // Resting threshold
int center = range / 2; // Resting position value
int minima[] = {1023, 1023}; // Actual analogRead minima for (x, y)
int maxima[] = {0, 0}; // Actual analogRead maxima for (x, y)
int axis[] = {xAxis, yAxis}; // Pin numbers for (x, y)
int mouseReading[2]; // Final mouse readings for (x, y)
void setup() {
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// Read and scale the two axes
int xReading = readAxis(0);
int yReading = readAxis(1);
// Move the mouse
Mouse.move(xReading, yReading, 0);
delay(responseDelay);
}
/*
Reads an axis (0 or 1 for x or y) and scales the
analog input range to a range from 0 to <range>
*/
int readAxis(int axisNumber) {
int distance = 0; // Distance from center of the output range
// Read the analog input
int reading = analogRead(axis[axisNumber]);
// Of the current reading exceeds the max or min for this axis, reset the max or min
if (reading < minima[axisNumber]) {
minima[axisNumber] = reading;
}
if (reading > maxima[axisNumber]) {
maxima[axisNumber] = reading;
}
// Map the reading from the analog input range to the output range
reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range);
// If the output reading is outside from the rest position threshold, use it
if (abs(reading - center) > threshold) {
distance = (reading - center);
}
// The Y axis needs to be inverted in order to map the movement correctly
if (axisNumber == 1) {
distance = -distance;
}
// Return the distance for this axis
return distance;
}
```
#### Notes and warnings
When you use the `Mouse.move()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.press()`
Sends a button press to a connected computer. A press is the equivalent of clicking and continuously holding the mouse button. A press is cancelled with `Mouse.release()`. Before using `Mouse.press()`, you need to start communication with `Mouse.begin()`. `Mouse.press()` defaults to a left button press.
#### Syntax
```
Mouse.press()
Mouse.press(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the switch attached to pin 2 is closed, press and hold the left mouse button
if (digitalRead(2) == HIGH) {
Mouse.press();
}
// If the switch attached to pin 3 is closed, release the left mouse button
if (digitalRead(3) == HIGH) {
Mouse.release();
}
}
```
#### Notes and warnings
When you use the `Mouse.press()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.release()`
Sends a message that a previously pressed button (invoked through `Mouse.press()`) is released. `Mouse.release()` defaults to the left button.
#### Syntax
```
Mouse.press()
Mouse.press(button)
```
#### Parameters
* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the switch attached to pin 2 is closed, press and hold the left mouse button
if (digitalRead(2) == HIGH) {
Mouse.press();
}
// If the switch attached to pin 3 is closed, release the left mouse button
if (digitalRead(3) == HIGH) {
Mouse.release();
}
}
```
#### Notes and warnings
When you use the `Mouse.release()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.isPressed()`
Checks the current status of all mouse buttons, and reports if any are pressed or not. By default, it checks the status of the left mouse button.
#### Syntax
```
Mouse.isPressed();
Mouse.isPressed(button);
```
#### Parameters
* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
1 if a button was pressed, 0 if a not.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Start serial communication with the computer
Serial.begin(9600);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// A variable for checking the button's state
int mouseState = 0;
// If the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variable
if (digitalRead(2) == HIGH) {
Mouse.press();
mouseState = Mouse.isPressed();
}
// If the switch attached to pin 3 is closed, release the left mouse button and save the state in a variable
if (digitalRead(3) == HIGH) {
Mouse.release();
mouseState = Mouse.isPressed();
}
// Print out the current mouse button state
Serial.println(mouseState);
delay(10);
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
+23
View File
@@ -0,0 +1,23 @@
# Mouse library
The mouse functions enable 32u4 or SAMD micro based boards to control cursor movement on a connected computer through their micro’s native USB port. When updating the cursor position, it is always relative to the cursor’s previous location.
To use this library:
```
#include <Mouse.h>
```
## Notes and warnings
These core libraries allow the 32u4 and SAMD based boards (Leonardo, Esplora, Zero, Due and MKR Family) to appear as a native Mouse and/or Keyboard to a connected computer.
**A word of caution on using the Mouse and Keyboard libraries**: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as `Mouse.move()` and `Keyboard.print()` will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control. Refer to the Mouse and Keyboard examples for some ways to handle this.
When using the Mouse or Keyboard library, it may be best to test your output first using `Serial.print()`. This way, you can be sure you know what values are being reported.
## Examples
* [KeyboardAndMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardAndMouseControl): Demonstrates the Mouse and Keyboard commands in one program.
* [ButtonMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ButtonMouseControl): Control cursor movement with 5 pushbuttons.
* [JoystickMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/JoystickMouseControl): Controls a computer’s cursor movement with a Joystick when a button is pressed.
@@ -0,0 +1,34 @@
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
/* Released to the public domain */
#include <Mouse.h>
void setup() {
Serial.begin(115200);
Mouse.begin();
delay(5000);
Serial.printf("Press BOOTSEL to move the mouse in a circle\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("BARREL ROLL!!!");
float r = 100;
float ox = 0.0;
float oy = 0.0;
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
float dx = ax - ox;
float dy = ay - oy;
Mouse.move(dx, dy, 0);
ox = ax;
oy = ay;
delay(10);
}
while (BOOTSEL) {
delay(1);
}
}
}
+24
View File
@@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map For Mouse
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Mouse KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
click KEYWORD2
move KEYWORD2
press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
+9
View File
@@ -0,0 +1,9 @@
name=Mouse
version=1.0.1
author=Arduino and EFP3
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Allows an Arduino board with USB capabilities to act as a Mouse.
paragraph=Allows the RP2040 to emulate a USB mouse
category=Device Control
url=https://www.arduino.cc/reference/en/language/functions/usb/mouse/
architectures=rp2040
+53
View File
@@ -0,0 +1,53 @@
/*
Mouse.cpp
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 "Mouse.h"
#include <RP2040USB.h>
#include "tusb.h"
#include "class/hid/hid_device.h"
// Weak function override to add our descriptor to the TinyUSB list
void __USBInstallMouse() { /* noop */ }
//================================================================================
//================================================================================
// Mouse
/* This function is for limiting the input value for x and y
axis to -127 <= x/y <= 127 since this is the allowed value
range for a USB HID device.
*/
Mouse_::Mouse_(void) {
/* noop */
}
void Mouse_::move(int x, int y, signed char wheel) {
CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_mouse_report(__USBGetMouseReportID(), _buttons, limit_xy(x), limit_xy(y), wheel, 0);
}
tud_task();
}
Mouse_ Mouse;
+34
View File
@@ -0,0 +1,34 @@
/*
Mouse.h
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 MOUSE_h
#define MOUSE_h
#include <HID_Mouse.h>
class Mouse_ : public HID_Mouse {
public:
Mouse_(void);
virtual void move(int x, int y, signed char wheel = 0) override;
};
extern Mouse_ Mouse;
#endif
+31
View File
@@ -0,0 +1,31 @@
:repository-owner: arduino-libraries
:repository-name: Mouse
= {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 Mouse.
For more information about this library please visit us at
https://www.arduino.cc/reference/en/language/functions/usb/mouse/
== 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
+428
View File
@@ -0,0 +1,428 @@
# Mouse library
## Methods
### `Mouse.begin()`
Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`.
#### Syntax
```
Mouse.begin()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
}
void loop() {
// Initialize the Mouse library when button is pressed
if (digitalRead(2) == HIGH) {
Mouse.begin();
}
}
```
#### See also
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.click()`
Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button.
`Mouse.click()` defaults to the left mouse button.
#### Syntax
```
Mouse.click()
Mouse.click(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
}
}
```
#### Notes and warnings
When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.end()`
Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`.
#### Syntax
```
Mouse.end()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initiate the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
// Then end the Mouse emulation
Mouse.end();
}
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.move()`
Moves the cursor on a connected computer. The motion onscreen is always relative to the cursor’s current location. Before using `Mouse.move()` you must call `Mouse.begin()`.
#### Syntax
```
Mouse.move(xVal, yVal, wheel)
```
#### Parameters
* `xVal`: amount to move along the x-axis. Allowed data types: signed char.
* `yVal`: amount to move along the y-axis. Allowed data types: signed char.
* `wheel`: amount to move scroll wheel. Allowed data types: signed char.
#### Returns
None.
#### Example
```
#include <Mouse.h>
const int xAxis = A1; // Analog sensor for X axis
const int yAxis = A2; // Analog sensor for Y axis
int range = 12; // Output range of X or Y movement
int responseDelay = 2; // Response delay of the mouse, in ms
int threshold = range / 4; // Resting threshold
int center = range / 2; // Resting position value
int minima[] = {1023, 1023}; // Actual analogRead minima for (x, y)
int maxima[] = {0, 0}; // Actual analogRead maxima for (x, y)
int axis[] = {xAxis, yAxis}; // Pin numbers for (x, y)
int mouseReading[2]; // Final mouse readings for (x, y)
void setup() {
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// Read and scale the two axes
int xReading = readAxis(0);
int yReading = readAxis(1);
// Move the mouse
Mouse.move(xReading, yReading, 0);
delay(responseDelay);
}
/*
Reads an axis (0 or 1 for x or y) and scales the
analog input range to a range from 0 to <range>
*/
int readAxis(int axisNumber) {
int distance = 0; // Distance from center of the output range
// Read the analog input
int reading = analogRead(axis[axisNumber]);
// Of the current reading exceeds the max or min for this axis, reset the max or min
if (reading < minima[axisNumber]) {
minima[axisNumber] = reading;
}
if (reading > maxima[axisNumber]) {
maxima[axisNumber] = reading;
}
// Map the reading from the analog input range to the output range
reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range);
// If the output reading is outside from the rest position threshold, use it
if (abs(reading - center) > threshold) {
distance = (reading - center);
}
// The Y axis needs to be inverted in order to map the movement correctly
if (axisNumber == 1) {
distance = -distance;
}
// Return the distance for this axis
return distance;
}
```
#### Notes and warnings
When you use the `Mouse.move()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.press()`
Sends a button press to a connected computer. A press is the equivalent of clicking and continuously holding the mouse button. A press is cancelled with `Mouse.release()`. Before using `Mouse.press()`, you need to start communication with `Mouse.begin()`. `Mouse.press()` defaults to a left button press.
#### Syntax
```
Mouse.press()
Mouse.press(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the switch attached to pin 2 is closed, press and hold the left mouse button
if (digitalRead(2) == HIGH) {
Mouse.press();
}
// If the switch attached to pin 3 is closed, release the left mouse button
if (digitalRead(3) == HIGH) {
Mouse.release();
}
}
```
#### Notes and warnings
When you use the `Mouse.press()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.release()`
Sends a message that a previously pressed button (invoked through `Mouse.press()`) is released. `Mouse.release()` defaults to the left button.
#### Syntax
```
Mouse.press()
Mouse.press(button)
```
#### Parameters
* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the switch attached to pin 2 is closed, press and hold the left mouse button
if (digitalRead(2) == HIGH) {
Mouse.press();
}
// If the switch attached to pin 3 is closed, release the left mouse button
if (digitalRead(3) == HIGH) {
Mouse.release();
}
}
```
#### Notes and warnings
When you use the `Mouse.release()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.isPressed()`
Checks the current status of all mouse buttons, and reports if any are pressed or not. By default, it checks the status of the left mouse button.
#### Syntax
```
Mouse.isPressed();
Mouse.isPressed(button);
```
#### Parameters
* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
1 if a button was pressed, 0 if a not.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Start serial communication with the computer
Serial.begin(9600);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// A variable for checking the button's state
int mouseState = 0;
// If the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variable
if (digitalRead(2) == HIGH) {
Mouse.press();
mouseState = Mouse.isPressed();
}
// If the switch attached to pin 3 is closed, release the left mouse button and save the state in a variable
if (digitalRead(3) == HIGH) {
Mouse.release();
mouseState = Mouse.isPressed();
}
// Print out the current mouse button state
Serial.println(mouseState);
delay(10);
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)

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