Compare commits
+1
-1
@@ -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
|
||||
|
||||
@@ -9,6 +9,9 @@ This is a port of the RP2040 (Raspberry Pi Pico processor) to the Arduino ecosys
|
||||
# Documentation
|
||||
See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for more detailed usage information.
|
||||
|
||||
# Contributing
|
||||
Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blob/master/docs/contrib.rst) for more information on submitting pull requests and porting libraries or sketches to this core.
|
||||
|
||||
# Supported Boards
|
||||
* Raspberry Pi Pico
|
||||
* Raspberry Pi Pico W
|
||||
@@ -160,7 +163,8 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory)
|
||||
|
||||
# Features
|
||||
* Adafruit TinyUSB Arduino (USB mouse, keyboard, flash drive, generic HID, CDC Serial, MIDI, WebUSB, others)
|
||||
* Generic Arduino USB Serial, Keyboard, and Mouse emulation
|
||||
* Bluetooth on the PicoW (Classic and BLE) with Keyboard, Mouse, Joystick, and Virtual Serial
|
||||
* Generic Arduino USB Serial, Keyboard, Joystick, and Mouse emulation
|
||||
* WiFi (Pico W)
|
||||
* HTTP client and server (WebServer)
|
||||
* SSL/TLS/HTTPS
|
||||
|
||||
+901
-301
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@
|
||||
#include <hardware/structs/rosc.h>
|
||||
#include <hardware/structs/systick.h>
|
||||
#include <pico/multicore.h>
|
||||
#include <pico/rand.h>
|
||||
#include <pico/util/queue.h>
|
||||
#include "CoreMutex.h"
|
||||
#include "ccount.pio.h"
|
||||
@@ -246,6 +247,11 @@ public:
|
||||
return clock_get_hz(clk_sys);
|
||||
}
|
||||
|
||||
// Get current CPU core number
|
||||
static int cpuid() {
|
||||
return sio_hw->cpuid;
|
||||
}
|
||||
|
||||
// Get CPU cycle count. Needs to do magic to extens 24b HW to something longer
|
||||
volatile uint64_t _epoch = 0;
|
||||
inline uint32_t getCycleCount() {
|
||||
@@ -336,28 +342,20 @@ public:
|
||||
_MFIFO fifo;
|
||||
|
||||
|
||||
// TODO - Not so great HW random generator. 32-bits wide. Cryptographers somewhere are crying
|
||||
uint32_t hwrand32() {
|
||||
// Try and whiten the HW ROSC bit
|
||||
uint32_t r = 0;
|
||||
for (int k = 0; k < 32; k++) {
|
||||
unsigned long int b;
|
||||
do {
|
||||
b = rosc_hw->randombit & 1;
|
||||
if (b != (rosc_hw->randombit & 1)) {
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
r <<= 1;
|
||||
r |= b;
|
||||
}
|
||||
// Stir using the cycle count LSBs. In any WiFi use case this will be a random # since the connection time is not cycle-accurate
|
||||
uint64_t rr = (((uint64_t)~r) << 32LL) | r;
|
||||
rr >>= rp2040.getCycleCount() & 32LL;
|
||||
|
||||
return (uint32_t)rr;
|
||||
return get_rand_32();
|
||||
}
|
||||
|
||||
bool isPicoW() {
|
||||
#if !defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
return false;
|
||||
#else
|
||||
extern bool __isPicoW;
|
||||
return __isPicoW;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static void _SystickHandler() {
|
||||
rp2040._epoch += 1LL << 24;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define ARDUINO_PICO_MAJOR 2
|
||||
#define ARDUINO_PICO_MINOR 7
|
||||
#define ARDUINO_PICO_REVISION 2
|
||||
#define ARDUINO_PICO_VERSION_STR "2.7.2"
|
||||
#define ARDUINO_PICO_MAJOR 3
|
||||
#define ARDUINO_PICO_MINOR 0
|
||||
#define ARDUINO_PICO_REVISION 0
|
||||
#define ARDUINO_PICO_VERSION_STR "3.0.0"
|
||||
|
||||
@@ -190,6 +190,7 @@ static void CheckSerialReset() {
|
||||
reset_usb_boot(0, 0);
|
||||
while (1); // WDT will fire here
|
||||
}
|
||||
__holdUpPendSV = 0;
|
||||
}
|
||||
|
||||
extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef struct {
|
||||
} FMMap;
|
||||
|
||||
static FMMap *_map = nullptr;
|
||||
extern "C" SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m) {
|
||||
SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive) {
|
||||
if (!_map) {
|
||||
_map = (FMMap *)calloc(sizeof(FMMap), 16);
|
||||
}
|
||||
@@ -42,7 +42,12 @@ extern "C" SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (_map[i].src == nullptr) {
|
||||
// Make a new mutex
|
||||
SemaphoreHandle_t fm = __freertos_mutex_create();
|
||||
SemaphoreHandle_t fm;
|
||||
if (recursive) {
|
||||
fm = _freertos_recursive_mutex_create();
|
||||
} else {
|
||||
fm = __freertos_mutex_create();
|
||||
}
|
||||
if (fm == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ extern "C" {
|
||||
extern void vTaskPreemptionEnable(TaskHandle_t p) __attribute__((weak));
|
||||
#endif
|
||||
|
||||
extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m);
|
||||
}
|
||||
extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive = false);
|
||||
|
||||
// Halt the FreeRTOS PendSV task switching magic
|
||||
extern "C" int __holdUpPendSV;
|
||||
|
||||
@@ -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
|
||||
+16
-4
@@ -80,7 +80,7 @@ static SemaphoreHandle_t __getFreeRTOSMutex(_LOCK_T lock) {
|
||||
} else if (l == &__lock___arc4random_mutex) {
|
||||
return __lock___arc4random_mutex_freertos;
|
||||
}
|
||||
return nullptr;
|
||||
return __get_freertos_mutex_for_ptr(l, false);
|
||||
}
|
||||
|
||||
static SemaphoreHandle_t __getFreeRTOSRecursiveMutex(_LOCK_T lock) {
|
||||
@@ -96,12 +96,18 @@ static SemaphoreHandle_t __getFreeRTOSRecursiveMutex(_LOCK_T lock) {
|
||||
} else if (l == &__lock___env_recursive_mutex) {
|
||||
return __lock___env_recursive_mutex_freertos;
|
||||
}
|
||||
return nullptr;
|
||||
return __get_freertos_mutex_for_ptr((mutex_t *)l, true);
|
||||
}
|
||||
|
||||
void __retarget_lock_init(_LOCK_T *lock) {
|
||||
if (__freeRTOSinitted) {
|
||||
/* Already done in initFreeRTOSMutexes() */
|
||||
mutex_t *l = (mutex_t *)lock;
|
||||
if ((l == &__lock___at_quick_exit_mutex) || (l == &__lock___tz_mutex) || (l == &__lock___dd_hash_mutex) || (l == &__lock___arc4random_mutex)) {
|
||||
/* Already done in initFreeRTOSMutexes() */
|
||||
} else {
|
||||
// Will init the mutex as well
|
||||
__get_freertos_mutex_for_ptr(l, false);
|
||||
}
|
||||
} else {
|
||||
mutex_init((mutex_t*) lock);
|
||||
}
|
||||
@@ -109,7 +115,13 @@ void __retarget_lock_init(_LOCK_T *lock) {
|
||||
|
||||
void __retarget_lock_init_recursive(_LOCK_T *lock) {
|
||||
if (__freeRTOSinitted) {
|
||||
/* Already done in initFreeRTOSMutexes() */
|
||||
recursive_mutex_t *l = (recursive_mutex_t *)lock;
|
||||
if ((l == &__lock___sinit_recursive_mutex) || (l == &__lock___sfp_recursive_mutex) || (l == &__lock___atexit_recursive_mutex) || (l == &__lock___malloc_recursive_mutex) || (l == &__lock___env_recursive_mutex)) {
|
||||
/* Already done in initFreeRTOSMutexes() */
|
||||
} else {
|
||||
// Will init the mutex as well
|
||||
__get_freertos_mutex_for_ptr((mutex_t *)l, true);
|
||||
}
|
||||
} else {
|
||||
recursive_mutex_init((recursive_mutex_t*) lock);
|
||||
}
|
||||
|
||||
+17
-32
@@ -18,45 +18,25 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "pico/mutex.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/timeouts.h"
|
||||
|
||||
// Global indicator that we're inside an LWIP block
|
||||
extern "C" {
|
||||
volatile bool __inLWIP = false;
|
||||
}
|
||||
|
||||
auto_init_recursive_mutex(__mtxLWIP);
|
||||
#include <pico/mutex.h>
|
||||
#include <lwip/pbuf.h>
|
||||
#include <lwip/udp.h>
|
||||
#include <lwip/tcp.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/raw.h>
|
||||
#include <lwip/timeouts.h>
|
||||
#include <pico/cyw43_arch.h>
|
||||
|
||||
class LWIPMutex {
|
||||
public:
|
||||
LWIPMutex() {
|
||||
noInterrupts();
|
||||
recursive_mutex_enter_blocking(&__mtxLWIP);
|
||||
__inLWIP = true;
|
||||
_ref++;
|
||||
interrupts();
|
||||
cyw43_arch_lwip_begin();
|
||||
}
|
||||
|
||||
~LWIPMutex() {
|
||||
noInterrupts();
|
||||
if (0 == --_ref) {
|
||||
__inLWIP = false;
|
||||
}
|
||||
recursive_mutex_exit(&__mtxLWIP);
|
||||
interrupts();
|
||||
cyw43_arch_lwip_end();
|
||||
}
|
||||
|
||||
private:
|
||||
static int _ref;
|
||||
};
|
||||
int LWIPMutex::_ref = 0;
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -275,10 +255,15 @@ extern "C" {
|
||||
return __real_udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
|
||||
}
|
||||
|
||||
// sys_check_timeouts is special case because the async process will call it. If we're already in a timeout check, just do a noop
|
||||
auto_init_mutex(__sys_check_timeouts_mtx);
|
||||
extern void __real_sys_check_timeouts(void);
|
||||
void __wrap_sys_check_timeouts(void) {
|
||||
LWIPMutex m;
|
||||
__real_sys_check_timeouts();
|
||||
uint32_t owner;
|
||||
if (mutex_try_enter(&__sys_check_timeouts_mtx, &owner)) {
|
||||
__real_sys_check_timeouts();
|
||||
mutex_exit(&__sys_check_timeouts_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
extern err_t __real_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg);
|
||||
|
||||
@@ -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
@@ -47,7 +47,7 @@ Adjusts the pin to record. Only legal before ``ADCInput::begin()``.
|
||||
bool setFrequency(long sampleRate)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the ADC sampling frequency, but does not start recording (however if the
|
||||
device was already running, it will wontinue to run at the new frequency). Note
|
||||
device was already running, it will continue to run at the new frequency). Note
|
||||
that every pin requested will be sampled at this frequency, one after the other.
|
||||
That is, if you have code like this:
|
||||
|
||||
|
||||
+2
-2
@@ -14,12 +14,12 @@ Returns a value from 0...4095 correspionding to the ADC reading
|
||||
of the specific pin.
|
||||
|
||||
void analogReadResolution(int bits)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Determines the resolution (in bits) of the value returned by the analogRead() function.
|
||||
Default resolution is 10bit.
|
||||
|
||||
float analogReadTemp(float vref = 3.3f)
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns the temperature, in Celsius, of the onboard thermal sensor.
|
||||
If you have a custom Vref for the ADC on your RP2040 board, you can pass it in as a parameter. Calling with no parameters assumes the normal, 3.3V Vref.
|
||||
This reading is not exceedingly accurate and of relatively low
|
||||
|
||||
@@ -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
@@ -54,9 +54,9 @@ author = u'Earle F. Philhower, III'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'2.7.2'
|
||||
version = u'3.0.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'2.7.2'
|
||||
release = u'3.0.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
Contributing and Porting to the Core
|
||||
====================================
|
||||
|
||||
First of all, thank you for contributing to the project. It's a lot of work
|
||||
keeping up with all the different uses of the RP2040, so the more people
|
||||
working on the code, the better. Your assistance can help the project
|
||||
succeed.
|
||||
|
||||
Contributing to the Core (Pull Requests)
|
||||
----------------------------------------
|
||||
|
||||
We use the standard GitHub Pull Request model. If you're unfamiliar with it,
|
||||
this `guide <https://www.freecodecamp.org/news/how-to-make-your-first-pull-request-on-github-3/>` gives a simple overview of the process.
|
||||
|
||||
All pull requests have to pass a set of Continuous Integration (CI) checks
|
||||
which help make sure the code compiles under different configurations and has
|
||||
no spelling or style errors.
|
||||
|
||||
Tips for a Good Pull Request (PR)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All code in the core and libraries, except for INO sketches, uses a 4-space
|
||||
indent with cuddled brackets. When in doubt, copy your formatting from the
|
||||
surrounding code. You should install ``astyle`` and run ``tests/restyle.sh``
|
||||
on your machine before committing and pushing any pull requests to ensure
|
||||
the formatting is correct.
|
||||
|
||||
Describe the change you're proposing and why it's important in your
|
||||
``git commit`` message. If it fixes an open issue, place ``Fixes #xxxx``
|
||||
(where xxxx is the issue number) in the message to link the two.
|
||||
|
||||
Try and only change one thing per pull request. That makes it easier to
|
||||
review and prioritize. Opening up a separate PR per change also helps keep
|
||||
track of them when release messages are generated.
|
||||
|
||||
Adding a New Board
|
||||
------------------
|
||||
|
||||
Adding a new board requires:
|
||||
|
||||
* Updated ``tools/makeboards.py`` script
|
||||
* Updated ``boards.txt`` file, generated by ``makeboard.py``
|
||||
* Updated ``package_pico_index.template.json`` file, generated by ``makeboard.py``
|
||||
* New ``tools/json/BOARD_NAME.json`` board file for Platform.IO
|
||||
* New ``variants/BOARD_NAME/pins_arduino.h`` header defining the I/O pins
|
||||
|
||||
To add a new RP2040 board you will need to update the ``tools/makeboards.py``
|
||||
script. Do *NOT* manually edit ``boards.txt``, that file is machine generated.
|
||||
You will need to add a ``MakeBoard`` call at the end of the file. Please be sure
|
||||
to add your board so that it sorts alphabetically, starting with the company name
|
||||
and then the board name. Otherwise it is hard to find a specific board in the menu.
|
||||
|
||||
Run ``python3 tools/makeboards.py`` to update the ``boards.txt`` file and generate
|
||||
a Platform.IO JSON file in the ``tools/json`` directory.
|
||||
|
||||
Create a folder called ``variants/BOARD_NAME`` and place in a ``pins_arduino.h``
|
||||
file in it that contains your default pin name mapping (i.e. SPI0/1 pins, UART
|
||||
pins, LED_DEFAULT, etc.). Copying one of the existing ones as a template can
|
||||
make this task much simpler.
|
||||
|
||||
In your ``git commit`` be sure to add the newly generated ``tools/json/XXX.json``
|
||||
file as well as the modified ``makeboards`` script and ``boards.txt``, the new
|
||||
``pins_arduino.h`` header you generated, and the Arduino packaging JSON
|
||||
``package/package_pico_index.template.json``. You should also add a note in
|
||||
the ``README.md`` file listing your new board.
|
||||
|
||||
Submit the updated commit as a PR and, if all goes well, your board will be in
|
||||
on the next core release.
|
||||
|
||||
|
||||
Porting Libraries and Applications to the Core
|
||||
----------------------------------------------
|
||||
|
||||
We try and follow Arduino standards so, with luck, porting to this core should
|
||||
be relatively straightforward. The ``WiFi`` library and associates support
|
||||
libraries like ``WebServer`` are modeled after the ESP32 and ESP8266 versions
|
||||
of those libraries, combined with the "standard" Arduino ``WiFi`` one.
|
||||
|
||||
Compiler Defines for Porting
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you are adding RP2040 support to an existing library and need to isolate
|
||||
code that only runs on this core, use the following define.
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
~~~ your changes ~~~
|
||||
#endif
|
||||
|
||||
Library Architectures
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After adding support in the code, libraries need their ``library.properties``
|
||||
and ``library.json`` files updated to indicate support, or the IDE will
|
||||
not know your new code is compatible here.
|
||||
|
||||
Add ``rp2040`` to ``architectures`` (in ``library.properties``) and
|
||||
``"rp2040"`` to ``platforms[]`` (in ``library.json``) to let the tools know.
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
Getting Help and Contributing
|
||||
=============================
|
||||
Getting Help
|
||||
============
|
||||
|
||||
This is a community supported project and has multiple ways to get assistance.
|
||||
Posting complete details, in a polite and organized way will get the best
|
||||
|
||||
+5
-1
@@ -16,7 +16,9 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
Getting Help and Contributing <help>
|
||||
Getting Help <help>
|
||||
Contributing <contrib>
|
||||
|
||||
Installation <install>
|
||||
IDE Menus <ide>
|
||||
|
||||
@@ -41,6 +43,8 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
|
||||
USB (Arduino and Adafruit_TinyUSB) <usb>
|
||||
Multicore Processing <multicore>
|
||||
|
||||
Bluetooth (Alpha/Beta) <bluetooth>
|
||||
|
||||
Single File USB Drive <singlefile>
|
||||
|
||||
FreeRTOS SMP (multicore) <freertos>
|
||||
|
||||
+18
-2
@@ -13,6 +13,10 @@ Returns the current frequency of the core clock. This is read at runtime,
|
||||
versus the constant ``F_CPU`` macro that is also available. This is useful
|
||||
in cases where your code changes the core clock (i.e. low power modes, etc.)
|
||||
|
||||
int rp2040.cpuid()
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Returns the current core ID (0 or 1) of the executing task.
|
||||
|
||||
uint32_t rp2040.getCycleCount()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns a 32-bit cycle count from then the core started running. Because it
|
||||
@@ -41,13 +45,16 @@ Hardware Watchdog
|
||||
-----------------
|
||||
|
||||
void rp2040.wdt_begin(uint32_t delay_ms)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Enables the hardware watchdog timer with a delay value of delay_ms
|
||||
milliseconds. Note that on the RP2040, once this function has called, the
|
||||
hardware watchdog can _not_ be disabled.
|
||||
|
||||
The maximum ``delay_ms`` allowed in this call is ``8300``, corresponding
|
||||
to 8.3 seconds. Any higher values will be truncated by the hardware.
|
||||
|
||||
void rp2040.wdt_reset()
|
||||
~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Reloads the watchdog's counter with the amount of time set by wdt_begin.
|
||||
|
||||
|
||||
@@ -71,6 +78,15 @@ Returns the total heap that was available to this program at compile time (i.e.
|
||||
the Pico RAM size minus things like the ``.data`` and ``.bss`` sections and other
|
||||
overhead).
|
||||
|
||||
Hardware Identification
|
||||
-----------------------
|
||||
|
||||
bool isPicoW()
|
||||
~~~~~~~~~~~~~~
|
||||
Returns the core's best guess if this code is running on a Raspberry Pi Pico W.
|
||||
This would let you, possibly, use the same UF2 for Pico and PicoW by simply not
|
||||
doing any WiFi calls.
|
||||
|
||||
Bootloader
|
||||
----------
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -44,6 +44,8 @@ restartCore1 KEYWORD2
|
||||
reboot KEYWORD2
|
||||
restart KEYWORD2
|
||||
|
||||
isPicoW KEYWORD2
|
||||
|
||||
getChipID KEYWORD2
|
||||
|
||||
hwrand32 KEYWORD2
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10
-6
@@ -191,11 +191,6 @@ SECTIONS
|
||||
__data_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.uninitialized_data (COPY): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
@@ -213,7 +208,7 @@ SECTIONS
|
||||
} > SCRATCH_Y AT > FLASH
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
.bss : {
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
@@ -222,6 +217,15 @@ SECTIONS
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
/* At most one of the following two will be engaged, depending on the SDK version */
|
||||
.uninitialized_ram MAX(0x20003000, .) (NOLOAD) : {
|
||||
*(.uninitialized_ram*)
|
||||
} > RAM
|
||||
|
||||
.uninitialized_data MAX(0x20003000, .) (NOLOAD) : {
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
source [find interface/cmsis-dap.cfg]
|
||||
adapter speed 5000
|
||||
source [find target/rp2040.cfg]
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
JoystickBLE KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
end KEYWORD2
|
||||
use8bit KEYWORD2
|
||||
X KEYWORD2
|
||||
Y KEYWORD2
|
||||
button KEYWORD2
|
||||
position KEYWORD2
|
||||
Z KEYWORD2
|
||||
Zrotate KEYWORD2
|
||||
sliderLeft KEYWORD2
|
||||
slider KEYWORD2
|
||||
sliderRight KEYWORD2
|
||||
hat KEYWORD2
|
||||
useManualSend KEYWORD2
|
||||
send_now KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
@@ -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
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
JoystickBLE.cpp
|
||||
|
||||
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
|
||||
Modified for BLE 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
Implementation loosely based on:
|
||||
Mouse library from https://github.com/earlephilhower/arduino-pico
|
||||
Joystick functions from Teensyduino https://github.com/PaulStoffregen
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "JoystickBLE.h"
|
||||
#include <Arduino.h>
|
||||
#include <PicoBluetoothBLEHID.h>
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Joystick/Gamepad
|
||||
|
||||
JoystickBLE_::JoystickBLE_(void) {
|
||||
_use8bit = false;
|
||||
_autosend = true;
|
||||
memset(&data, 0, sizeof(data));
|
||||
//_X_axis = _Y_axis = _Z_axis = _Zrotate = _sliderLeft = _sliderRight = _hat = data.buttons = 0;
|
||||
}
|
||||
|
||||
/** define the mapping of axes values
|
||||
default: axes methods are accepting values from 0-1023 (compatibility to other Joystick libraries)
|
||||
and are mapped internally to int8_t
|
||||
if use8bit(true) is called, -127 to 127 values are used.*/
|
||||
void JoystickBLE_::use8bit(bool mode) {
|
||||
_use8bit = mode;
|
||||
}
|
||||
|
||||
//if set, the gamepad report is not automatically sent after an update of axes/buttons; use send_now to update
|
||||
void JoystickBLE_::useManualSend(bool mode) {
|
||||
_autosend = !mode;
|
||||
}
|
||||
|
||||
/** Maps values from 8bit signed or 10bit unsigned to report values
|
||||
|
||||
Depending on the setting via use8bit(), either values from 0-1023 or -127 - 127
|
||||
are mapped.
|
||||
*/
|
||||
int JoystickBLE_::map8or10bit(int const value) {
|
||||
if (_use8bit) {
|
||||
if (value < -127) {
|
||||
return -127;
|
||||
} else if (value > 127) {
|
||||
return 127;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
if (value < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (value > 1023) {
|
||||
return 1023;
|
||||
}
|
||||
return map(value, 0, 1023, -127, 127);
|
||||
}
|
||||
}
|
||||
|
||||
#define REPORT_ID 0x01
|
||||
static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))};
|
||||
void JoystickBLE_::begin(void) {
|
||||
PicoBluetoothBLEHID.startHID("PicoW BLE Joystick", "PicoW BLE Joystick", 0x03c4, desc_joystick, sizeof(desc_joystick));
|
||||
}
|
||||
|
||||
void JoystickBLE_::end(void) {
|
||||
PicoBluetoothBLEHID.end();
|
||||
}
|
||||
|
||||
void JoystickBLE_::button(uint8_t button, bool val) {
|
||||
//I've no idea why, but without a second dword, it is not possible.
|
||||
//maybe something with the alignment when using bit set/clear?!?
|
||||
static uint32_t buttons_local = 0;
|
||||
|
||||
if (button >= 1 && button <= 32) {
|
||||
if (val) {
|
||||
buttons_local |= (1UL << (button - 1));
|
||||
} else {
|
||||
buttons_local &= ~(1UL << (button - 1));
|
||||
}
|
||||
|
||||
data.buttons = buttons_local;
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickBLE_::X(int val) {
|
||||
data.x = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBLE_::Y(int val) {
|
||||
data.y = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBLE_::Z(int val) {
|
||||
data.z = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBLE_::Zrotate(int val) {
|
||||
data.rz = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBLE_::sliderLeft(int val) {
|
||||
data.rx = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBLE_::sliderRight(int val) {
|
||||
data.ry = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickBLE_::slider(int val) {
|
||||
data.rx = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickBLE_::position(int X, int Y) {
|
||||
data.x = map8or10bit(X);
|
||||
data.y = map8or10bit(Y);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
|
||||
//compatibility: there is only one hat implemented, num parameter is ignored
|
||||
void JoystickBLE_::hat(unsigned int num, int angle) {
|
||||
(void) num;
|
||||
hat(angle);
|
||||
}
|
||||
|
||||
//set the hat value, from 0-360. -1 is rest position
|
||||
void JoystickBLE_::hat(int angle) {
|
||||
if (angle < 0) {
|
||||
data.hat = 0;
|
||||
}
|
||||
if (angle >= 0 && angle <= 360) {
|
||||
data.hat = map(angle, 0, 360, 1, 8);
|
||||
}
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
|
||||
//immediately send an HID report
|
||||
void JoystickBLE_::send_now(void) {
|
||||
PicoBluetoothBLEHID.send(&data, sizeof(data));
|
||||
}
|
||||
|
||||
JoystickBLE_ JoystickBLE;
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
JoystickBLE.h
|
||||
|
||||
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
|
||||
Modified for BT 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "class/hid/hid.h"
|
||||
|
||||
//======================================================================
|
||||
class JoystickBLE_ {
|
||||
private:
|
||||
bool _autosend;
|
||||
bool _use8bit;
|
||||
hid_gamepad_report_t data;
|
||||
int map8or10bit(int const value);
|
||||
public:
|
||||
JoystickBLE_(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
|
||||
//set a selected button to pressed/released
|
||||
void button(uint8_t button, bool val);
|
||||
//set axis values
|
||||
void X(int val);
|
||||
void Y(int val);
|
||||
void position(int X, int Y);
|
||||
void Z(int val);
|
||||
void Zrotate(int val);
|
||||
void sliderLeft(int val);
|
||||
void sliderRight(int val);
|
||||
//note: not implemented in TinyUSB gamepad, is mapped to sliderLeft.
|
||||
void slider(int val);
|
||||
|
||||
//set the hat value, from 0-360. -1 is rest position
|
||||
void hat(int angle);
|
||||
//compatibility: there is only one hat implemented, num parameter is ignored
|
||||
void hat(unsigned int num, int angle);
|
||||
|
||||
|
||||
//if set, the gamepad report is not automatically sent after an update of axes/buttons; use send_now to update
|
||||
void useManualSend(bool mode);
|
||||
//immediately send an HID report
|
||||
void send_now(void);
|
||||
//define the mapping of axes values
|
||||
//default: axes methods are accepting values from 0-1023 (compatibility to other Joystick libraries)
|
||||
// and are mapped internally to int8_t
|
||||
//if use8bit(true) is called, -127 to 127 values are used.
|
||||
void use8bit(bool mode);
|
||||
};
|
||||
extern JoystickBLE_ JoystickBLE;
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Joystick library
|
||||
|
||||
The Joystick functions enable a RP2040 board to act as a HID game controller.
|
||||
|
||||
To use this library:
|
||||
|
||||
```
|
||||
#include <Joystick.h>
|
||||
```
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
* [Joystick-AllFunctions] Includes example calls for each Joystick function
|
||||
@@ -0,0 +1,110 @@
|
||||
/* Benjamin Aigner, 2022 <beni@asterics-foundation.org> */
|
||||
/* Public domain / CC 0 */
|
||||
|
||||
/** example code using all possibilities of the Joystick class
|
||||
for the RP2040.
|
||||
*/
|
||||
|
||||
#include <JoystickBT.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Use BOOTSEL to start the Joystick demo.");
|
||||
JoystickBT.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (BOOTSEL) {
|
||||
Serial.println("Joystick buttons");
|
||||
for (uint8_t i = 1; i <= 32; i++) {
|
||||
JoystickBT.button(i, true);
|
||||
delay(250);
|
||||
JoystickBT.button(i, false);
|
||||
delay(10); //we need a short delay here, sending packets with less than 1ms leads to packet loss!
|
||||
}
|
||||
//alternativ with manual send:
|
||||
JoystickBT.useManualSend(true);
|
||||
Serial.println("Joystick buttons - manual send");
|
||||
for (uint8_t i = 1; i <= 32; i++) {
|
||||
JoystickBT.button(i, true);
|
||||
JoystickBT.send_now();
|
||||
delay(250);
|
||||
JoystickBT.button(i, false);
|
||||
}
|
||||
JoystickBT.useManualSend(false);
|
||||
|
||||
//iterate all joystick axis
|
||||
//Note: although you can use 0-1023 here (10bit), internally 8bits are used (-127 to 127)
|
||||
Serial.println("Joystick X");
|
||||
for (uint16_t i = 0; i < 1023; i++) {
|
||||
JoystickBT.X(i);
|
||||
delay(2);
|
||||
} JoystickBT.X(512);
|
||||
Serial.println("Joystick Y");
|
||||
for (uint16_t i = 0; i < 1023; i++) {
|
||||
JoystickBT.Y(i);
|
||||
delay(2);
|
||||
} JoystickBT.Y(512);
|
||||
Serial.println("Joystick Z");
|
||||
for (uint16_t i = 0; i < 1023; i++) {
|
||||
JoystickBT.Z(i);
|
||||
delay(2);
|
||||
} JoystickBT.Z(512);
|
||||
Serial.println("Joystick Zrotate");
|
||||
for (uint16_t i = 0; i < 1023; i++) {
|
||||
JoystickBT.Zrotate(i);
|
||||
delay(2);
|
||||
} JoystickBT.Zrotate(512);
|
||||
Serial.println("Joystick sliderLeft");
|
||||
for (uint16_t i = 0; i < 1023; i++) {
|
||||
JoystickBT.sliderLeft(i);
|
||||
delay(2);
|
||||
} JoystickBT.sliderLeft(0);
|
||||
Serial.println("Joystick sliderRight");
|
||||
for (uint16_t i = 0; i < 1023; i++) {
|
||||
JoystickBT.sliderRight(i);
|
||||
delay(2);
|
||||
} JoystickBT.sliderRight(0);
|
||||
Serial.println("Joystick hat");
|
||||
for (uint16_t i = 0; i < 360; i++) {
|
||||
JoystickBT.hat(i);
|
||||
delay(20);
|
||||
} JoystickBT.hat(-1);
|
||||
|
||||
//use int8 mode for the axis.
|
||||
//Note: hat is not used differently.
|
||||
Serial.println("Now all axis in 8bit mode, -127 to 127");
|
||||
JoystickBT.use8bit(true);
|
||||
Serial.println("Joystick X");
|
||||
for (int16_t i = -127; i < 128; i++) {
|
||||
JoystickBT.X(i);
|
||||
delay(2);
|
||||
} JoystickBT.X(0);
|
||||
Serial.println("Joystick Y");
|
||||
for (int16_t i = -127; i < 128; i++) {
|
||||
JoystickBT.Y(i);
|
||||
delay(2);
|
||||
} JoystickBT.Y(0);
|
||||
Serial.println("Joystick Z");
|
||||
for (int16_t i = -127; i < 128; i++) {
|
||||
JoystickBT.Z(i);
|
||||
delay(2);
|
||||
} JoystickBT.Z(0);
|
||||
Serial.println("Joystick Zrotate");
|
||||
for (int16_t i = -127; i < 128; i++) {
|
||||
JoystickBT.Zrotate(i);
|
||||
delay(2);
|
||||
} JoystickBT.Zrotate(0);
|
||||
Serial.println("Joystick sliderLeft");
|
||||
for (int16_t i = -127; i < 128; i++) {
|
||||
JoystickBT.sliderLeft(i);
|
||||
delay(2);
|
||||
} JoystickBT.sliderLeft(0);
|
||||
Serial.println("Joystick sliderRight");
|
||||
for (int16_t i = -127; i < 128; i++) {
|
||||
JoystickBT.sliderRight(i);
|
||||
delay(2);
|
||||
} JoystickBT.sliderRight(0);
|
||||
JoystickBT.use8bit(false);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
#######################################
|
||||
@@ -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
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
Joystick.cpp
|
||||
|
||||
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
|
||||
Modified for BT 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
Implementation loosely based on:
|
||||
Mouse library from https://github.com/earlephilhower/arduino-pico
|
||||
Joystick functions from Teensyduino https://github.com/PaulStoffregen
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "JoystickBT.h"
|
||||
#include <Arduino.h>
|
||||
#include <PicoBluetoothHID.h>
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Joystick/Gamepad
|
||||
|
||||
JoystickBT_::JoystickBT_(void) {
|
||||
_use8bit = false;
|
||||
_autosend = true;
|
||||
memset(&data, 0, sizeof(data));
|
||||
//_X_axis = _Y_axis = _Z_axis = _Zrotate = _sliderLeft = _sliderRight = _hat = data.buttons = 0;
|
||||
}
|
||||
|
||||
/** define the mapping of axes values
|
||||
default: axes methods are accepting values from 0-1023 (compatibility to other Joystick libraries)
|
||||
and are mapped internally to int8_t
|
||||
if use8bit(true) is called, -127 to 127 values are used.*/
|
||||
void JoystickBT_::use8bit(bool mode) {
|
||||
_use8bit = mode;
|
||||
}
|
||||
|
||||
//if set, the gamepad report is not automatically sent after an update of axes/buttons; use send_now to update
|
||||
void JoystickBT_::useManualSend(bool mode) {
|
||||
_autosend = !mode;
|
||||
}
|
||||
|
||||
/** Maps values from 8bit signed or 10bit unsigned to report values
|
||||
|
||||
Depending on the setting via use8bit(), either values from 0-1023 or -127 - 127
|
||||
are mapped.
|
||||
*/
|
||||
int JoystickBT_::map8or10bit(int const value) {
|
||||
if (_use8bit) {
|
||||
if (value < -127) {
|
||||
return -127;
|
||||
} else if (value > 127) {
|
||||
return 127;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
if (value < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (value > 1023) {
|
||||
return 1023;
|
||||
}
|
||||
return map(value, 0, 1023, -127, 127);
|
||||
}
|
||||
}
|
||||
|
||||
#define REPORT_ID 0x01
|
||||
static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))};
|
||||
void JoystickBT_::begin(void) {
|
||||
PicoBluetoothHID.startHID("PicoW Joystick 00:00:00:00:00:00", "PicoW HID Joystick", 0x2508, 33, desc_joystick, sizeof(desc_joystick));
|
||||
}
|
||||
|
||||
void JoystickBT_::end(void) {
|
||||
PicoBluetoothHID.end();
|
||||
}
|
||||
|
||||
void JoystickBT_::button(uint8_t button, bool val) {
|
||||
//I've no idea why, but without a second dword, it is not possible.
|
||||
//maybe something with the alignment when using bit set/clear?!?
|
||||
static uint32_t buttons_local = 0;
|
||||
|
||||
if (button >= 1 && button <= 32) {
|
||||
if (val) {
|
||||
buttons_local |= (1UL << (button - 1));
|
||||
} else {
|
||||
buttons_local &= ~(1UL << (button - 1));
|
||||
}
|
||||
|
||||
data.buttons = buttons_local;
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickBT_::X(int val) {
|
||||
data.x = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBT_::Y(int val) {
|
||||
data.y = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBT_::Z(int val) {
|
||||
data.z = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBT_::Zrotate(int val) {
|
||||
data.rz = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBT_::sliderLeft(int val) {
|
||||
data.rx = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
void JoystickBT_::sliderRight(int val) {
|
||||
data.ry = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickBT_::slider(int val) {
|
||||
data.rx = map8or10bit(val);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickBT_::position(int X, int Y) {
|
||||
data.x = map8or10bit(X);
|
||||
data.y = map8or10bit(Y);
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
|
||||
//compatibility: there is only one hat implemented, num parameter is ignored
|
||||
void JoystickBT_::hat(unsigned int num, int angle) {
|
||||
(void) num;
|
||||
hat(angle);
|
||||
}
|
||||
|
||||
//set the hat value, from 0-360. -1 is rest position
|
||||
void JoystickBT_::hat(int angle) {
|
||||
if (angle < 0) {
|
||||
data.hat = 0;
|
||||
}
|
||||
if (angle >= 0 && angle <= 360) {
|
||||
data.hat = map(angle, 0, 360, 1, 8);
|
||||
}
|
||||
if (_autosend) {
|
||||
send_now();
|
||||
}
|
||||
}
|
||||
|
||||
//immediately send an HID report
|
||||
void JoystickBT_::send_now(void) {
|
||||
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
|
||||
}
|
||||
|
||||
JoystickBT_ JoystickBT;
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
JoystickBT.h
|
||||
|
||||
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
|
||||
Modified for BT 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "class/hid/hid.h"
|
||||
|
||||
//======================================================================
|
||||
class JoystickBT_ {
|
||||
private:
|
||||
bool _autosend;
|
||||
bool _use8bit;
|
||||
hid_gamepad_report_t data;
|
||||
int map8or10bit(int const value);
|
||||
public:
|
||||
JoystickBT_(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
|
||||
//set a selected button to pressed/released
|
||||
void button(uint8_t button, bool val);
|
||||
//set axis values
|
||||
void X(int val);
|
||||
void Y(int val);
|
||||
void position(int X, int Y);
|
||||
void Z(int val);
|
||||
void Zrotate(int val);
|
||||
void sliderLeft(int val);
|
||||
void sliderRight(int val);
|
||||
//note: not implemented in TinyUSB gamepad, is mapped to sliderLeft.
|
||||
void slider(int val);
|
||||
|
||||
//set the hat value, from 0-360. -1 is rest position
|
||||
void hat(int angle);
|
||||
//compatibility: there is only one hat implemented, num parameter is ignored
|
||||
void hat(unsigned int num, int angle);
|
||||
|
||||
|
||||
//if set, the gamepad report is not automatically sent after an update of axes/buttons; use send_now to update
|
||||
void useManualSend(bool mode);
|
||||
//immediately send an HID report
|
||||
void send_now(void);
|
||||
//define the mapping of axes values
|
||||
//default: axes methods are accepting values from 0-1023 (compatibility to other Joystick libraries)
|
||||
// and are mapped internally to int8_t
|
||||
//if use8bit(true) is called, -127 to 127 values are used.
|
||||
void use8bit(bool mode);
|
||||
};
|
||||
extern JoystickBT_ JoystickBT;
|
||||
@@ -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.
|
||||
@@ -0,0 +1,31 @@
|
||||
:repository-owner: arduino-libraries
|
||||
:repository-name: Keyboard
|
||||
|
||||
= {repository-name} Library for Arduino =
|
||||
|
||||
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"]
|
||||
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"]
|
||||
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"]
|
||||
|
||||
This library allows an Arduino board with USB capabilities to act as a keyboard.
|
||||
|
||||
For more information about this library please visit us at
|
||||
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
|
||||
|
||||
== License ==
|
||||
|
||||
Copyright (c) Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
@@ -0,0 +1,20 @@
|
||||
/* Released into the public domain */
|
||||
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
|
||||
|
||||
#include <KeyboardBLE.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
KeyboardBLE.begin();
|
||||
delay(5000);
|
||||
Serial.printf("Arduino USB Password Typer\n");
|
||||
Serial.printf("Press BOOTSEL to enter your super-secure(not!) password\n\n");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (BOOTSEL) {
|
||||
Serial.println("Typing password for you...shhhh....");
|
||||
KeyboardBLE.print("ThisPasswordIsWeakLikeABaby");
|
||||
while (BOOTSEL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Keyboard test
|
||||
|
||||
For the Arduino Leonardo, Micro or Due
|
||||
|
||||
Reads a byte from the serial port, sends a keystroke back.
|
||||
The sent keystroke is one higher than what's received, e.g. if you send a,
|
||||
you get b, send A you get B, and so forth.
|
||||
|
||||
The circuit:
|
||||
- none
|
||||
|
||||
created 21 Oct 2011
|
||||
modified 27 Mar 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardSerial
|
||||
*/
|
||||
|
||||
#include <KeyboardBLE.h>
|
||||
|
||||
void setup() {
|
||||
// open the serial port:
|
||||
Serial.begin(9600);
|
||||
// initialize control over the keyboard:
|
||||
KeyboardBLE.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check for incoming serial data:
|
||||
if (Serial.available() > 0) {
|
||||
// read incoming serial data:
|
||||
char inChar = Serial.read();
|
||||
// Type the next ASCII value from what you received:
|
||||
KeyboardBLE.write(inChar + 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Keyboard
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
KeyboardBLE KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
write KEYWORD2
|
||||
press KEYWORD2
|
||||
release KEYWORD2
|
||||
releaseAll KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
KeyboardBLE.cpp
|
||||
|
||||
Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
Main Arduino Library Copyright (c) 2015, Arduino LLC
|
||||
Original code (pre-library): Copyright (c) 2011, Peter Barrett
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "KeyboardBLE.h"
|
||||
#include "KeyboardLayout.h"
|
||||
#include <PicoBluetoothBLEHID.h>
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
KeyboardBLE_::KeyboardBLE_(void) {
|
||||
bzero(&_keyReport, sizeof(_keyReport));
|
||||
_asciimap = KeyboardLayout_en_US;
|
||||
}
|
||||
|
||||
#define REPORT_ID 0x01
|
||||
|
||||
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))};
|
||||
void KeyboardBLE_::begin(const uint8_t *layout) {
|
||||
_asciimap = layout;
|
||||
PicoBluetoothBLEHID.startHID("PicoW BLE Keyboard", "PicoW BLE Keyboard", 0x03c1, desc_keyboard, sizeof(desc_keyboard));
|
||||
}
|
||||
|
||||
void KeyboardBLE_::end(void) {
|
||||
PicoBluetoothBLEHID.end();
|
||||
}
|
||||
|
||||
void KeyboardBLE_::sendReport(KeyReport* keys) {
|
||||
hid_keyboard_report_t data;
|
||||
data.modifier = keys->modifiers;
|
||||
data.reserved = 0;
|
||||
memcpy(data.keycode, keys->keys, sizeof(data.keycode));
|
||||
PicoBluetoothBLEHID.send(&data, sizeof(data));
|
||||
}
|
||||
|
||||
// press() adds the specified key (printing, non-printing, or modifier)
|
||||
// to the persistent key report and sends the report. Because of the way
|
||||
// USB HID works, the host acts like the key remains pressed until we
|
||||
// call release(), releaseAll(), or otherwise clear the report and resend.
|
||||
size_t KeyboardBLE_::press(uint8_t k) {
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers |= (1 << (k - 128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = pgm_read_byte(_asciimap + k);
|
||||
if (!k) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
if ((k & ALT_GR) == ALT_GR) {
|
||||
_keyReport.modifiers |= 0x40; // AltGr = right Alt
|
||||
k &= 0x3F;
|
||||
} else if ((k & SHIFT) == SHIFT) {
|
||||
_keyReport.modifiers |= 0x02; // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
if (k == ISO_REPLACEMENT) {
|
||||
k = ISO_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
// Add k to the key report only if it's not already present
|
||||
// and if there is an empty slot.
|
||||
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
|
||||
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
|
||||
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (_keyReport.keys[i] == 0x00) {
|
||||
_keyReport.keys[i] = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 6) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// release() takes the specified key out of the persistent key report and
|
||||
// sends the report. This tells the OS the key is no longer pressed and that
|
||||
// it shouldn't be repeated any more.
|
||||
size_t KeyboardBLE_::release(uint8_t k) {
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers &= ~(1 << (k - 128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = pgm_read_byte(_asciimap + k);
|
||||
if (!k) {
|
||||
return 0;
|
||||
}
|
||||
if ((k & ALT_GR) == ALT_GR) {
|
||||
_keyReport.modifiers &= ~(0x40); // AltGr = right Alt
|
||||
k &= 0x3F;
|
||||
} else if ((k & SHIFT) == SHIFT) {
|
||||
_keyReport.modifiers &= ~(0x02); // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
if (k == ISO_REPLACEMENT) {
|
||||
k = ISO_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the key report to see if k is present. Clear it if it exists.
|
||||
// Check all positions in case the key is present more than once (which it shouldn't be)
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (0 != k && _keyReport.keys[i] == k) {
|
||||
_keyReport.keys[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void KeyboardBLE_::releaseAll(void) {
|
||||
_keyReport.keys[0] = 0;
|
||||
_keyReport.keys[1] = 0;
|
||||
_keyReport.keys[2] = 0;
|
||||
_keyReport.keys[3] = 0;
|
||||
_keyReport.keys[4] = 0;
|
||||
_keyReport.keys[5] = 0;
|
||||
_keyReport.modifiers = 0;
|
||||
sendReport(&_keyReport);
|
||||
}
|
||||
|
||||
size_t KeyboardBLE_::write(uint8_t c) {
|
||||
uint8_t p = press(c); // Keydown
|
||||
delay(10);
|
||||
release(c); // Keyup
|
||||
delay(10);
|
||||
return p; // just return the result of press() since release() almost always returns 1
|
||||
}
|
||||
|
||||
size_t KeyboardBLE_::write(const uint8_t *buffer, size_t size) {
|
||||
size_t n = 0;
|
||||
while (size--) {
|
||||
if (*buffer != '\r') {
|
||||
if (write(*buffer)) {
|
||||
n++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
KeyboardBLE_ KeyboardBLE;
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
KeyboardBLE.h
|
||||
|
||||
Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
Main Arduino Library Copyright (c) 2015, Arduino LLC
|
||||
Original code (pre-library): Copyright (c) 2011, Peter Barrett
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef KEYBOARDBLE_h
|
||||
#define KEYBOARDBLE_h
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
// Modifiers
|
||||
#define KEY_LEFT_CTRL 0x80
|
||||
#define KEY_LEFT_SHIFT 0x81
|
||||
#define KEY_LEFT_ALT 0x82
|
||||
#define KEY_LEFT_GUI 0x83
|
||||
#define KEY_RIGHT_CTRL 0x84
|
||||
#define KEY_RIGHT_SHIFT 0x85
|
||||
#define KEY_RIGHT_ALT 0x86
|
||||
#define KEY_RIGHT_GUI 0x87
|
||||
|
||||
// Misc keys
|
||||
#define KEY_UP_ARROW 0xDA
|
||||
#define KEY_DOWN_ARROW 0xD9
|
||||
#define KEY_LEFT_ARROW 0xD8
|
||||
#define KEY_RIGHT_ARROW 0xD7
|
||||
#define KEY_BACKSPACE 0xB2
|
||||
#define KEY_TAB 0xB3
|
||||
#define KEY_RETURN 0xB0
|
||||
#define KEY_MENU 0xED // "Keyboard Application" in USB standard
|
||||
#define KEY_ESC 0xB1
|
||||
#define KEY_INSERT 0xD1
|
||||
#define KEY_DELETE 0xD4
|
||||
#define KEY_PAGE_UP 0xD3
|
||||
#define KEY_PAGE_DOWN 0xD6
|
||||
#define KEY_HOME 0xD2
|
||||
#define KEY_END 0xD5
|
||||
#define KEY_CAPS_LOCK 0xC1
|
||||
#define KEY_PRINT_SCREEN 0xCE // Print Screen / SysRq
|
||||
#define KEY_SCROLL_LOCK 0xCF
|
||||
#define KEY_PAUSE 0xD0 // Pause / Break
|
||||
|
||||
// Numeric keypad
|
||||
#define KEY_NUM_LOCK 0xDB
|
||||
#define KEY_KP_SLASH 0xDC
|
||||
#define KEY_KP_ASTERISK 0xDD
|
||||
#define KEY_KP_MINUS 0xDE
|
||||
#define KEY_KP_PLUS 0xDF
|
||||
#define KEY_KP_ENTER 0xE0
|
||||
#define KEY_KP_1 0xE1
|
||||
#define KEY_KP_2 0xE2
|
||||
#define KEY_KP_3 0xE3
|
||||
#define KEY_KP_4 0xE4
|
||||
#define KEY_KP_5 0xE5
|
||||
#define KEY_KP_6 0xE6
|
||||
#define KEY_KP_7 0xE7
|
||||
#define KEY_KP_8 0xE8
|
||||
#define KEY_KP_9 0xE9
|
||||
#define KEY_KP_0 0xEA
|
||||
#define KEY_KP_DOT 0xEB
|
||||
|
||||
// Function keys
|
||||
#define KEY_F1 0xC2
|
||||
#define KEY_F2 0xC3
|
||||
#define KEY_F3 0xC4
|
||||
#define KEY_F4 0xC5
|
||||
#define KEY_F5 0xC6
|
||||
#define KEY_F6 0xC7
|
||||
#define KEY_F7 0xC8
|
||||
#define KEY_F8 0xC9
|
||||
#define KEY_F9 0xCA
|
||||
#define KEY_F10 0xCB
|
||||
#define KEY_F11 0xCC
|
||||
#define KEY_F12 0xCD
|
||||
#define KEY_F13 0xF0
|
||||
#define KEY_F14 0xF1
|
||||
#define KEY_F15 0xF2
|
||||
#define KEY_F16 0xF3
|
||||
#define KEY_F17 0xF4
|
||||
#define KEY_F18 0xF5
|
||||
#define KEY_F19 0xF6
|
||||
#define KEY_F20 0xF7
|
||||
#define KEY_F21 0xF8
|
||||
#define KEY_F22 0xF9
|
||||
#define KEY_F23 0xFA
|
||||
#define KEY_F24 0xFB
|
||||
|
||||
// Supported keyboard layouts
|
||||
extern const uint8_t KeyboardLayout_de_DE[];
|
||||
extern const uint8_t KeyboardLayout_en_US[];
|
||||
extern const uint8_t KeyboardLayout_es_ES[];
|
||||
extern const uint8_t KeyboardLayout_fr_FR[];
|
||||
extern const uint8_t KeyboardLayout_it_IT[];
|
||||
extern const uint8_t KeyboardLayout_sv_SE[];
|
||||
extern const uint8_t KeyboardLayout_da_DK[];
|
||||
|
||||
// Low level key report: up to 6 keys and shift, ctrl etc at once
|
||||
typedef struct {
|
||||
uint8_t modifiers;
|
||||
uint8_t reserved;
|
||||
uint8_t keys[6];
|
||||
} KeyReport;
|
||||
|
||||
class KeyboardBLE_ : public Print {
|
||||
private:
|
||||
KeyReport _keyReport;
|
||||
const uint8_t *_asciimap;
|
||||
void sendReport(KeyReport* keys);
|
||||
public:
|
||||
KeyboardBLE_(void);
|
||||
void begin(const uint8_t *layout = KeyboardLayout_en_US);
|
||||
void end(void);
|
||||
size_t write(uint8_t k);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t press(uint8_t k);
|
||||
size_t release(uint8_t k);
|
||||
void releaseAll(void);
|
||||
};
|
||||
extern KeyboardBLE_ KeyboardBLE;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
KeyboardLayout.h
|
||||
|
||||
This file is not part of the public API. It is meant to be included
|
||||
only in Keyboard.cpp and the keyboard layout files. Layout files map
|
||||
ASCII character codes to keyboard scan codes (technically, to USB HID
|
||||
Usage codes), possibly altered by the SHIFT or ALT_GR modifiers.
|
||||
|
||||
== Creating your own layout ==
|
||||
|
||||
In order to create your own layout file, copy an existing layout that
|
||||
is similar to yours, then modify it to use the correct keys. The
|
||||
layout is an array in ASCII order. Each entry contains a scan code,
|
||||
possibly modified by "|SHIFT" or "|ALT_GR", as in this excerpt from
|
||||
the Italian layout:
|
||||
|
||||
0x35, // bslash
|
||||
0x30|ALT_GR, // ]
|
||||
0x2e|SHIFT, // ^
|
||||
|
||||
Do not change the control characters (those before scan code 0x2c,
|
||||
corresponding to space). Do not attempt to grow the table past DEL. Do
|
||||
not use both SHIFT and ALT_GR on the same character: this is not
|
||||
supported. Unsupported characters should have 0x00 as scan code.
|
||||
|
||||
For a keyboard with an ISO physical layout, use the scan codes below:
|
||||
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+-------+
|
||||
|35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp |
|
||||
+---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+
|
||||
| Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret |
|
||||
+-----++--++--++--++--++--++--++--++--++--++--++--++--++ |
|
||||
|CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 | |
|
||||
+----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+
|
||||
|Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 | Shift |
|
||||
+----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+
|
||||
|Ctrl|Win |Alt | |AlGr|Win |Menu|Ctrl|
|
||||
+----+----+----+------------------------+----+----+----+----+
|
||||
|
||||
The ANSI layout is identical except that key 0x31 is above (rather
|
||||
than next to) Return, and there is not key 0x32.
|
||||
|
||||
Give a unique name to the layout array, then declare it in Keyboard.h
|
||||
with a line of the form:
|
||||
|
||||
extern const uint8_t KeyboardLayout_xx_YY[];
|
||||
|
||||
== Encoding details ==
|
||||
|
||||
All scan codes are less than 0x80, which makes bit 7 available to
|
||||
signal that a modifier (Shift or AltGr) is needed to generate the
|
||||
character. With only one exception, keys that are used with modifiers
|
||||
have scan codes that are less than 0x40. This makes bit 6 available
|
||||
to signal whether the modifier is Shift or AltGr. The exception is
|
||||
0x64, the key next next to Left Shift on the ISO layout (and absent
|
||||
from the ANSI layout). We handle it by replacing its value by 0x32 in
|
||||
the layout arrays.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define SHIFT 0x80
|
||||
#define ALT_GR 0xc0
|
||||
#define ISO_KEY 0x64
|
||||
#define ISO_REPLACEMENT 0x32
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Danish keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_da_DK[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x20 | SHIFT, // #
|
||||
0x21 | ALT_GR, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x31, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x31 | SHIFT, // *
|
||||
0x2d, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x1f | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x25 | ALT_GR, // [
|
||||
0x32 | ALT_GR, // bslash
|
||||
0x26 | ALT_GR, // ]
|
||||
0x00, // ^ not supported (requires dead key + space)
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not supported (requires dead key + space)
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x24 | ALT_GR, // {
|
||||
0x2e | ALT_GR, // |
|
||||
0x27 | ALT_GR, // }
|
||||
0x00, // ~ not supported (requires dead key + space)
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
German keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_de_DE[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x31, // #
|
||||
0x21 | SHIFT, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x31 | SHIFT, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x30 | SHIFT, // *
|
||||
0x30, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x14 | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1d | SHIFT, // Y
|
||||
0x1c | SHIFT, // Z
|
||||
0x25 | ALT_GR, // [
|
||||
0x2d | ALT_GR, // bslash
|
||||
0x26 | ALT_GR, // ]
|
||||
0x00, // ^ not supported (requires dead key + space)
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not supported (requires dead key + space)
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1d, // y
|
||||
0x1c, // z
|
||||
0x24 | ALT_GR, // {
|
||||
0x32 | ALT_GR, // |
|
||||
0x27 | ALT_GR, // }
|
||||
0x30 | ALT_GR, // ~
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Standard US keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_en_US[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x34 | SHIFT, // "
|
||||
0x20 | SHIFT, // #
|
||||
0x21 | SHIFT, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x24 | SHIFT, // &
|
||||
0x34, // '
|
||||
0x26 | SHIFT, // (
|
||||
0x27 | SHIFT, // )
|
||||
0x25 | SHIFT, // *
|
||||
0x2e | SHIFT, // +
|
||||
0x36, // ,
|
||||
0x2d, // -
|
||||
0x37, // .
|
||||
0x38, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x33 | SHIFT, // :
|
||||
0x33, // ;
|
||||
0x36 | SHIFT, // <
|
||||
0x2e, // =
|
||||
0x37 | SHIFT, // >
|
||||
0x38 | SHIFT, // ?
|
||||
0x1f | SHIFT, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x2f, // [
|
||||
0x31, // bslash
|
||||
0x30, // ]
|
||||
0x23 | SHIFT, // ^
|
||||
0x2d | SHIFT, // _
|
||||
0x35, // `
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x2f | SHIFT, // {
|
||||
0x31 | SHIFT, // |
|
||||
0x30 | SHIFT, // }
|
||||
0x35 | SHIFT, // ~
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Spanish keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_es_ES[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x20 | ALT_GR, // #
|
||||
0x21 | SHIFT, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x2d, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x30 | SHIFT, // *
|
||||
0x30, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x1f | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x2f | ALT_GR, // [
|
||||
0x35 | ALT_GR, // bslash
|
||||
0x30 | ALT_GR, // ]
|
||||
0x00, // ^ not supported (requires dead key + space)
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not supported (requires dead key + space)
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x34 | ALT_GR, // {
|
||||
0x1e | ALT_GR, // |
|
||||
0x31 | ALT_GR, // }
|
||||
0x00, // ~ not supported (requires dead key + space)
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Traditional (not AFNOR) French keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_fr_FR[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x38, // !
|
||||
0x20, // "
|
||||
0x20 | ALT_GR, // #
|
||||
0x30, // $
|
||||
0x34 | SHIFT, // %
|
||||
0x1E, // &
|
||||
0x21, // '
|
||||
0x22, // (
|
||||
0x2d, // )
|
||||
0x31, // *
|
||||
0x2e | SHIFT, // +
|
||||
0x10, // ,
|
||||
0x23, // -
|
||||
0x36 | SHIFT, // .
|
||||
0x37 | SHIFT, // /
|
||||
0x27 | SHIFT, // 0
|
||||
0x1e | SHIFT, // 1
|
||||
0x1f | SHIFT, // 2
|
||||
0x20 | SHIFT, // 3
|
||||
0x21 | SHIFT, // 4
|
||||
0x22 | SHIFT, // 5
|
||||
0x23 | SHIFT, // 6
|
||||
0x24 | SHIFT, // 7
|
||||
0x25 | SHIFT, // 8
|
||||
0x26 | SHIFT, // 9
|
||||
0x37, // :
|
||||
0x36, // ;
|
||||
0x32, // <
|
||||
0x2e, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x10 | SHIFT, // ?
|
||||
0x27 | ALT_GR, // @
|
||||
0x14 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x33 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x04 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1d | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1a | SHIFT, // Z
|
||||
0x22 | ALT_GR, // [
|
||||
0x25 | ALT_GR, // bslash
|
||||
0x2d | ALT_GR, // ]
|
||||
0x26 | ALT_GR, // ^
|
||||
0x25, // _
|
||||
0x24 | ALT_GR, // `
|
||||
0x14, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x33, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x04, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1d, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1a, // z
|
||||
0x21 | ALT_GR, // {
|
||||
0x23 | ALT_GR, // |
|
||||
0x2e | ALT_GR, // }
|
||||
0x1f | ALT_GR, // ~
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Italian keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_it_IT[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x34 | ALT_GR, // #
|
||||
0x21 | SHIFT, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x2d, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x30 | SHIFT, // *
|
||||
0x30, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x33 | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x2f | ALT_GR, // [
|
||||
0x35, // bslash
|
||||
0x30 | ALT_GR, // ]
|
||||
0x2e | SHIFT, // ^
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not in this layout
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x00, // { not supported (requires AltGr+Shift)
|
||||
0x35 | SHIFT, // |
|
||||
0x00, // } not supported (requires AltGr+Shift)
|
||||
0x00, // ~ not in this layout
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Swedish keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_sv_SE[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x20 | SHIFT, // #
|
||||
0x21 | ALT_GR, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x31, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x31 | SHIFT, // *
|
||||
0x2d, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x1f | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x25 | ALT_GR, // [
|
||||
0x2d | ALT_GR, // bslash
|
||||
0x26 | ALT_GR, // ]
|
||||
0x00, // ^ not supported (requires dead key + space)
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not supported (requires dead key + space)
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x24 | ALT_GR, // {
|
||||
0x32 | ALT_GR, // |
|
||||
0x27 | ALT_GR, // }
|
||||
0x00, // ~ not supported (requires dead key + space)
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Keyboard_da_DK.h
|
||||
|
||||
Copyright (c) 2021, Peter John
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef KEYBOARD_DA_DK_h
|
||||
#define KEYBOARD_DA_DK_h
|
||||
|
||||
#include "HID.h"
|
||||
|
||||
#if !defined(_USING_HID)
|
||||
|
||||
#warning "Using legacy HID core (non pluggable)"
|
||||
|
||||
#else
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
// DA_DK keys
|
||||
#define KEY_A_RING (136+0x2f)
|
||||
#define KEY_SLASHED_O (136+0x34)
|
||||
#define KEY_ASH (136+0x33)
|
||||
#define KEY_UMLAUT (136+0x30)
|
||||
#define KEY_ACUTE_ACC (136+0x2e)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Keyboard_sv_SE.h
|
||||
|
||||
Copyright (c) 2021, Peter John
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef KEYBOARD_SV_SE_h
|
||||
#define KEYBOARD_SV_SE_h
|
||||
|
||||
#include "HID.h"
|
||||
|
||||
#if !defined(_USING_HID)
|
||||
|
||||
#warning "Using legacy HID core (non pluggable)"
|
||||
|
||||
#else
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
// SV_SE keys
|
||||
#define KEY_A_RING (136+0x2f)
|
||||
#define KEY_A_UMLAUT (136+0x34)
|
||||
#define KEY_O_UMLAUT (136+0x33)
|
||||
#define KEY_UMLAUT (136+0x30)
|
||||
#define KEY_ACUTE_ACC (136+0x2e)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -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.
|
||||
@@ -0,0 +1,31 @@
|
||||
:repository-owner: arduino-libraries
|
||||
:repository-name: Keyboard
|
||||
|
||||
= {repository-name} Library for Arduino =
|
||||
|
||||
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"]
|
||||
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"]
|
||||
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"]
|
||||
|
||||
This library allows an Arduino board with USB capabilities to act as a keyboard.
|
||||
|
||||
For more information about this library please visit us at
|
||||
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
|
||||
|
||||
== License ==
|
||||
|
||||
Copyright (c) Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
@@ -0,0 +1,20 @@
|
||||
/* Released into the public domain */
|
||||
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
|
||||
|
||||
#include <KeyboardBT.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
KeyboardBT.begin();
|
||||
delay(5000);
|
||||
Serial.printf("Arduino USB Password Typer\n");
|
||||
Serial.printf("Press BOOTSEL to enter your super-secure(not!) password\n\n");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (BOOTSEL) {
|
||||
Serial.println("Typing password for you...shhhh....");
|
||||
KeyboardBT.print("ThisPasswordIsWeakLikeABaby");
|
||||
while (BOOTSEL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Keyboard test
|
||||
|
||||
For the Arduino Leonardo, Micro or Due
|
||||
|
||||
Reads a byte from the serial port, sends a keystroke back.
|
||||
The sent keystroke is one higher than what's received, e.g. if you send a,
|
||||
you get b, send A you get B, and so forth.
|
||||
|
||||
The circuit:
|
||||
- none
|
||||
|
||||
created 21 Oct 2011
|
||||
modified 27 Mar 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardSerial
|
||||
*/
|
||||
|
||||
#include <KeyboardBT.h>
|
||||
|
||||
void setup() {
|
||||
// open the serial port:
|
||||
Serial.begin(9600);
|
||||
// initialize control over the keyboard:
|
||||
KeyboardBT.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check for incoming serial data:
|
||||
if (Serial.available() > 0) {
|
||||
// read incoming serial data:
|
||||
char inChar = Serial.read();
|
||||
// Type the next ASCII value from what you received:
|
||||
KeyboardBT.write(inChar + 1);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
#######################################
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
KeyboardBT.cpp
|
||||
|
||||
Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
Main Arduino Library Copyright (c) 2015, Arduino LLC
|
||||
Original code (pre-library): Copyright (c) 2011, Peter Barrett
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "KeyboardBT.h"
|
||||
#include "KeyboardLayout.h"
|
||||
#include <PicoBluetoothHID.h>
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
KeyboardBT_::KeyboardBT_(void) {
|
||||
bzero(&_keyReport, sizeof(_keyReport));
|
||||
_asciimap = KeyboardLayout_en_US;
|
||||
}
|
||||
|
||||
#define REPORT_ID 0x01
|
||||
|
||||
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))};
|
||||
void KeyboardBT_::begin(const uint8_t *layout) {
|
||||
_asciimap = layout;
|
||||
PicoBluetoothHID.startHID("PicoW Keyboard 00:00:00:00:00:00", "PicoW HID Keyboard", 0x2540, 33, desc_keyboard, sizeof(desc_keyboard));
|
||||
}
|
||||
|
||||
void KeyboardBT_::end(void) {
|
||||
PicoBluetoothHID.end();
|
||||
}
|
||||
|
||||
void KeyboardBT_::sendReport(KeyReport* keys) {
|
||||
hid_keyboard_report_t data;
|
||||
data.modifier = keys->modifiers;
|
||||
data.reserved = 0;
|
||||
memcpy(data.keycode, keys->keys, sizeof(data.keycode));
|
||||
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// press() adds the specified key (printing, non-printing, or modifier)
|
||||
// to the persistent key report and sends the report. Because of the way
|
||||
// USB HID works, the host acts like the key remains pressed until we
|
||||
// call release(), releaseAll(), or otherwise clear the report and resend.
|
||||
size_t KeyboardBT_::press(uint8_t k) {
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers |= (1 << (k - 128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = pgm_read_byte(_asciimap + k);
|
||||
if (!k) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
if ((k & ALT_GR) == ALT_GR) {
|
||||
_keyReport.modifiers |= 0x40; // AltGr = right Alt
|
||||
k &= 0x3F;
|
||||
} else if ((k & SHIFT) == SHIFT) {
|
||||
_keyReport.modifiers |= 0x02; // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
if (k == ISO_REPLACEMENT) {
|
||||
k = ISO_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
// Add k to the key report only if it's not already present
|
||||
// and if there is an empty slot.
|
||||
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
|
||||
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
|
||||
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (_keyReport.keys[i] == 0x00) {
|
||||
_keyReport.keys[i] = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 6) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// release() takes the specified key out of the persistent key report and
|
||||
// sends the report. This tells the OS the key is no longer pressed and that
|
||||
// it shouldn't be repeated any more.
|
||||
size_t KeyboardBT_::release(uint8_t k) {
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers &= ~(1 << (k - 128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = pgm_read_byte(_asciimap + k);
|
||||
if (!k) {
|
||||
return 0;
|
||||
}
|
||||
if ((k & ALT_GR) == ALT_GR) {
|
||||
_keyReport.modifiers &= ~(0x40); // AltGr = right Alt
|
||||
k &= 0x3F;
|
||||
} else if ((k & SHIFT) == SHIFT) {
|
||||
_keyReport.modifiers &= ~(0x02); // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
if (k == ISO_REPLACEMENT) {
|
||||
k = ISO_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the key report to see if k is present. Clear it if it exists.
|
||||
// Check all positions in case the key is present more than once (which it shouldn't be)
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (0 != k && _keyReport.keys[i] == k) {
|
||||
_keyReport.keys[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void KeyboardBT_::releaseAll(void) {
|
||||
_keyReport.keys[0] = 0;
|
||||
_keyReport.keys[1] = 0;
|
||||
_keyReport.keys[2] = 0;
|
||||
_keyReport.keys[3] = 0;
|
||||
_keyReport.keys[4] = 0;
|
||||
_keyReport.keys[5] = 0;
|
||||
_keyReport.modifiers = 0;
|
||||
sendReport(&_keyReport);
|
||||
}
|
||||
|
||||
size_t KeyboardBT_::write(uint8_t c) {
|
||||
uint8_t p = press(c); // Keydown
|
||||
delay(10);
|
||||
release(c); // Keyup
|
||||
delay(10);
|
||||
return p; // just return the result of press() since release() almost always returns 1
|
||||
}
|
||||
|
||||
size_t KeyboardBT_::write(const uint8_t *buffer, size_t size) {
|
||||
size_t n = 0;
|
||||
while (size--) {
|
||||
if (*buffer != '\r') {
|
||||
if (write(*buffer)) {
|
||||
n++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
KeyboardBT_ KeyboardBT;
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
KeyboardBT.h
|
||||
|
||||
Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
Main Arduino Library Copyright (c) 2015, Arduino LLC
|
||||
Original code (pre-library): Copyright (c) 2011, Peter Barrett
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef KEYBOARDBT_h
|
||||
#define KEYBOARDBT_h
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
// Modifiers
|
||||
#define KEY_LEFT_CTRL 0x80
|
||||
#define KEY_LEFT_SHIFT 0x81
|
||||
#define KEY_LEFT_ALT 0x82
|
||||
#define KEY_LEFT_GUI 0x83
|
||||
#define KEY_RIGHT_CTRL 0x84
|
||||
#define KEY_RIGHT_SHIFT 0x85
|
||||
#define KEY_RIGHT_ALT 0x86
|
||||
#define KEY_RIGHT_GUI 0x87
|
||||
|
||||
// Misc keys
|
||||
#define KEY_UP_ARROW 0xDA
|
||||
#define KEY_DOWN_ARROW 0xD9
|
||||
#define KEY_LEFT_ARROW 0xD8
|
||||
#define KEY_RIGHT_ARROW 0xD7
|
||||
#define KEY_BACKSPACE 0xB2
|
||||
#define KEY_TAB 0xB3
|
||||
#define KEY_RETURN 0xB0
|
||||
#define KEY_MENU 0xED // "Keyboard Application" in USB standard
|
||||
#define KEY_ESC 0xB1
|
||||
#define KEY_INSERT 0xD1
|
||||
#define KEY_DELETE 0xD4
|
||||
#define KEY_PAGE_UP 0xD3
|
||||
#define KEY_PAGE_DOWN 0xD6
|
||||
#define KEY_HOME 0xD2
|
||||
#define KEY_END 0xD5
|
||||
#define KEY_CAPS_LOCK 0xC1
|
||||
#define KEY_PRINT_SCREEN 0xCE // Print Screen / SysRq
|
||||
#define KEY_SCROLL_LOCK 0xCF
|
||||
#define KEY_PAUSE 0xD0 // Pause / Break
|
||||
|
||||
// Numeric keypad
|
||||
#define KEY_NUM_LOCK 0xDB
|
||||
#define KEY_KP_SLASH 0xDC
|
||||
#define KEY_KP_ASTERISK 0xDD
|
||||
#define KEY_KP_MINUS 0xDE
|
||||
#define KEY_KP_PLUS 0xDF
|
||||
#define KEY_KP_ENTER 0xE0
|
||||
#define KEY_KP_1 0xE1
|
||||
#define KEY_KP_2 0xE2
|
||||
#define KEY_KP_3 0xE3
|
||||
#define KEY_KP_4 0xE4
|
||||
#define KEY_KP_5 0xE5
|
||||
#define KEY_KP_6 0xE6
|
||||
#define KEY_KP_7 0xE7
|
||||
#define KEY_KP_8 0xE8
|
||||
#define KEY_KP_9 0xE9
|
||||
#define KEY_KP_0 0xEA
|
||||
#define KEY_KP_DOT 0xEB
|
||||
|
||||
// Function keys
|
||||
#define KEY_F1 0xC2
|
||||
#define KEY_F2 0xC3
|
||||
#define KEY_F3 0xC4
|
||||
#define KEY_F4 0xC5
|
||||
#define KEY_F5 0xC6
|
||||
#define KEY_F6 0xC7
|
||||
#define KEY_F7 0xC8
|
||||
#define KEY_F8 0xC9
|
||||
#define KEY_F9 0xCA
|
||||
#define KEY_F10 0xCB
|
||||
#define KEY_F11 0xCC
|
||||
#define KEY_F12 0xCD
|
||||
#define KEY_F13 0xF0
|
||||
#define KEY_F14 0xF1
|
||||
#define KEY_F15 0xF2
|
||||
#define KEY_F16 0xF3
|
||||
#define KEY_F17 0xF4
|
||||
#define KEY_F18 0xF5
|
||||
#define KEY_F19 0xF6
|
||||
#define KEY_F20 0xF7
|
||||
#define KEY_F21 0xF8
|
||||
#define KEY_F22 0xF9
|
||||
#define KEY_F23 0xFA
|
||||
#define KEY_F24 0xFB
|
||||
|
||||
// Supported keyboard layouts
|
||||
extern const uint8_t KeyboardLayout_de_DE[];
|
||||
extern const uint8_t KeyboardLayout_en_US[];
|
||||
extern const uint8_t KeyboardLayout_es_ES[];
|
||||
extern const uint8_t KeyboardLayout_fr_FR[];
|
||||
extern const uint8_t KeyboardLayout_it_IT[];
|
||||
extern const uint8_t KeyboardLayout_sv_SE[];
|
||||
extern const uint8_t KeyboardLayout_da_DK[];
|
||||
|
||||
// Low level key report: up to 6 keys and shift, ctrl etc at once
|
||||
typedef struct {
|
||||
uint8_t modifiers;
|
||||
uint8_t reserved;
|
||||
uint8_t keys[6];
|
||||
} KeyReport;
|
||||
|
||||
class KeyboardBT_ : public Print {
|
||||
private:
|
||||
KeyReport _keyReport;
|
||||
const uint8_t *_asciimap;
|
||||
void sendReport(KeyReport* keys);
|
||||
public:
|
||||
KeyboardBT_(void);
|
||||
void begin(const uint8_t *layout = KeyboardLayout_en_US);
|
||||
void end(void);
|
||||
size_t write(uint8_t k);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t press(uint8_t k);
|
||||
size_t release(uint8_t k);
|
||||
void releaseAll(void);
|
||||
};
|
||||
extern KeyboardBT_ KeyboardBT;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
KeyboardLayout.h
|
||||
|
||||
This file is not part of the public API. It is meant to be included
|
||||
only in Keyboard.cpp and the keyboard layout files. Layout files map
|
||||
ASCII character codes to keyboard scan codes (technically, to USB HID
|
||||
Usage codes), possibly altered by the SHIFT or ALT_GR modifiers.
|
||||
|
||||
== Creating your own layout ==
|
||||
|
||||
In order to create your own layout file, copy an existing layout that
|
||||
is similar to yours, then modify it to use the correct keys. The
|
||||
layout is an array in ASCII order. Each entry contains a scan code,
|
||||
possibly modified by "|SHIFT" or "|ALT_GR", as in this excerpt from
|
||||
the Italian layout:
|
||||
|
||||
0x35, // bslash
|
||||
0x30|ALT_GR, // ]
|
||||
0x2e|SHIFT, // ^
|
||||
|
||||
Do not change the control characters (those before scan code 0x2c,
|
||||
corresponding to space). Do not attempt to grow the table past DEL. Do
|
||||
not use both SHIFT and ALT_GR on the same character: this is not
|
||||
supported. Unsupported characters should have 0x00 as scan code.
|
||||
|
||||
For a keyboard with an ISO physical layout, use the scan codes below:
|
||||
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+-------+
|
||||
|35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp |
|
||||
+---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+
|
||||
| Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret |
|
||||
+-----++--++--++--++--++--++--++--++--++--++--++--++--++ |
|
||||
|CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 | |
|
||||
+----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+
|
||||
|Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 | Shift |
|
||||
+----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+
|
||||
|Ctrl|Win |Alt | |AlGr|Win |Menu|Ctrl|
|
||||
+----+----+----+------------------------+----+----+----+----+
|
||||
|
||||
The ANSI layout is identical except that key 0x31 is above (rather
|
||||
than next to) Return, and there is not key 0x32.
|
||||
|
||||
Give a unique name to the layout array, then declare it in Keyboard.h
|
||||
with a line of the form:
|
||||
|
||||
extern const uint8_t KeyboardLayout_xx_YY[];
|
||||
|
||||
== Encoding details ==
|
||||
|
||||
All scan codes are less than 0x80, which makes bit 7 available to
|
||||
signal that a modifier (Shift or AltGr) is needed to generate the
|
||||
character. With only one exception, keys that are used with modifiers
|
||||
have scan codes that are less than 0x40. This makes bit 6 available
|
||||
to signal whether the modifier is Shift or AltGr. The exception is
|
||||
0x64, the key next next to Left Shift on the ISO layout (and absent
|
||||
from the ANSI layout). We handle it by replacing its value by 0x32 in
|
||||
the layout arrays.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define SHIFT 0x80
|
||||
#define ALT_GR 0xc0
|
||||
#define ISO_KEY 0x64
|
||||
#define ISO_REPLACEMENT 0x32
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Danish keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_da_DK[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x20 | SHIFT, // #
|
||||
0x21 | ALT_GR, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x31, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x31 | SHIFT, // *
|
||||
0x2d, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x1f | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x25 | ALT_GR, // [
|
||||
0x32 | ALT_GR, // bslash
|
||||
0x26 | ALT_GR, // ]
|
||||
0x00, // ^ not supported (requires dead key + space)
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not supported (requires dead key + space)
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x24 | ALT_GR, // {
|
||||
0x2e | ALT_GR, // |
|
||||
0x27 | ALT_GR, // }
|
||||
0x00, // ~ not supported (requires dead key + space)
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
German keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_de_DE[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x31, // #
|
||||
0x21 | SHIFT, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x31 | SHIFT, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x30 | SHIFT, // *
|
||||
0x30, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x14 | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1d | SHIFT, // Y
|
||||
0x1c | SHIFT, // Z
|
||||
0x25 | ALT_GR, // [
|
||||
0x2d | ALT_GR, // bslash
|
||||
0x26 | ALT_GR, // ]
|
||||
0x00, // ^ not supported (requires dead key + space)
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not supported (requires dead key + space)
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1d, // y
|
||||
0x1c, // z
|
||||
0x24 | ALT_GR, // {
|
||||
0x32 | ALT_GR, // |
|
||||
0x27 | ALT_GR, // }
|
||||
0x30 | ALT_GR, // ~
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Standard US keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_en_US[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x34 | SHIFT, // "
|
||||
0x20 | SHIFT, // #
|
||||
0x21 | SHIFT, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x24 | SHIFT, // &
|
||||
0x34, // '
|
||||
0x26 | SHIFT, // (
|
||||
0x27 | SHIFT, // )
|
||||
0x25 | SHIFT, // *
|
||||
0x2e | SHIFT, // +
|
||||
0x36, // ,
|
||||
0x2d, // -
|
||||
0x37, // .
|
||||
0x38, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x33 | SHIFT, // :
|
||||
0x33, // ;
|
||||
0x36 | SHIFT, // <
|
||||
0x2e, // =
|
||||
0x37 | SHIFT, // >
|
||||
0x38 | SHIFT, // ?
|
||||
0x1f | SHIFT, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x2f, // [
|
||||
0x31, // bslash
|
||||
0x30, // ]
|
||||
0x23 | SHIFT, // ^
|
||||
0x2d | SHIFT, // _
|
||||
0x35, // `
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x2f | SHIFT, // {
|
||||
0x31 | SHIFT, // |
|
||||
0x30 | SHIFT, // }
|
||||
0x35 | SHIFT, // ~
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Spanish keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_es_ES[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x20 | ALT_GR, // #
|
||||
0x21 | SHIFT, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x2d, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x30 | SHIFT, // *
|
||||
0x30, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x1f | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x2f | ALT_GR, // [
|
||||
0x35 | ALT_GR, // bslash
|
||||
0x30 | ALT_GR, // ]
|
||||
0x00, // ^ not supported (requires dead key + space)
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not supported (requires dead key + space)
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x34 | ALT_GR, // {
|
||||
0x1e | ALT_GR, // |
|
||||
0x31 | ALT_GR, // }
|
||||
0x00, // ~ not supported (requires dead key + space)
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Traditional (not AFNOR) French keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_fr_FR[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x38, // !
|
||||
0x20, // "
|
||||
0x20 | ALT_GR, // #
|
||||
0x30, // $
|
||||
0x34 | SHIFT, // %
|
||||
0x1E, // &
|
||||
0x21, // '
|
||||
0x22, // (
|
||||
0x2d, // )
|
||||
0x31, // *
|
||||
0x2e | SHIFT, // +
|
||||
0x10, // ,
|
||||
0x23, // -
|
||||
0x36 | SHIFT, // .
|
||||
0x37 | SHIFT, // /
|
||||
0x27 | SHIFT, // 0
|
||||
0x1e | SHIFT, // 1
|
||||
0x1f | SHIFT, // 2
|
||||
0x20 | SHIFT, // 3
|
||||
0x21 | SHIFT, // 4
|
||||
0x22 | SHIFT, // 5
|
||||
0x23 | SHIFT, // 6
|
||||
0x24 | SHIFT, // 7
|
||||
0x25 | SHIFT, // 8
|
||||
0x26 | SHIFT, // 9
|
||||
0x37, // :
|
||||
0x36, // ;
|
||||
0x32, // <
|
||||
0x2e, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x10 | SHIFT, // ?
|
||||
0x27 | ALT_GR, // @
|
||||
0x14 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x33 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x04 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1d | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1a | SHIFT, // Z
|
||||
0x22 | ALT_GR, // [
|
||||
0x25 | ALT_GR, // bslash
|
||||
0x2d | ALT_GR, // ]
|
||||
0x26 | ALT_GR, // ^
|
||||
0x25, // _
|
||||
0x24 | ALT_GR, // `
|
||||
0x14, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x33, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x04, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1d, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1a, // z
|
||||
0x21 | ALT_GR, // {
|
||||
0x23 | ALT_GR, // |
|
||||
0x2e | ALT_GR, // }
|
||||
0x1f | ALT_GR, // ~
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Italian keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_it_IT[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x34 | ALT_GR, // #
|
||||
0x21 | SHIFT, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x2d, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x30 | SHIFT, // *
|
||||
0x30, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x33 | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x2f | ALT_GR, // [
|
||||
0x35, // bslash
|
||||
0x30 | ALT_GR, // ]
|
||||
0x2e | SHIFT, // ^
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not in this layout
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x00, // { not supported (requires AltGr+Shift)
|
||||
0x35 | SHIFT, // |
|
||||
0x00, // } not supported (requires AltGr+Shift)
|
||||
0x00, // ~ not in this layout
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Swedish keyboard layout.
|
||||
*/
|
||||
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
extern const uint8_t KeyboardLayout_sv_SE[128] PROGMEM = {
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e | SHIFT, // !
|
||||
0x1f | SHIFT, // "
|
||||
0x20 | SHIFT, // #
|
||||
0x21 | ALT_GR, // $
|
||||
0x22 | SHIFT, // %
|
||||
0x23 | SHIFT, // &
|
||||
0x31, // '
|
||||
0x25 | SHIFT, // (
|
||||
0x26 | SHIFT, // )
|
||||
0x31 | SHIFT, // *
|
||||
0x2d, // +
|
||||
0x36, // ,
|
||||
0x38, // -
|
||||
0x37, // .
|
||||
0x24 | SHIFT, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x37 | SHIFT, // :
|
||||
0x36 | SHIFT, // ;
|
||||
0x32, // <
|
||||
0x27 | SHIFT, // =
|
||||
0x32 | SHIFT, // >
|
||||
0x2d | SHIFT, // ?
|
||||
0x1f | ALT_GR, // @
|
||||
0x04 | SHIFT, // A
|
||||
0x05 | SHIFT, // B
|
||||
0x06 | SHIFT, // C
|
||||
0x07 | SHIFT, // D
|
||||
0x08 | SHIFT, // E
|
||||
0x09 | SHIFT, // F
|
||||
0x0a | SHIFT, // G
|
||||
0x0b | SHIFT, // H
|
||||
0x0c | SHIFT, // I
|
||||
0x0d | SHIFT, // J
|
||||
0x0e | SHIFT, // K
|
||||
0x0f | SHIFT, // L
|
||||
0x10 | SHIFT, // M
|
||||
0x11 | SHIFT, // N
|
||||
0x12 | SHIFT, // O
|
||||
0x13 | SHIFT, // P
|
||||
0x14 | SHIFT, // Q
|
||||
0x15 | SHIFT, // R
|
||||
0x16 | SHIFT, // S
|
||||
0x17 | SHIFT, // T
|
||||
0x18 | SHIFT, // U
|
||||
0x19 | SHIFT, // V
|
||||
0x1a | SHIFT, // W
|
||||
0x1b | SHIFT, // X
|
||||
0x1c | SHIFT, // Y
|
||||
0x1d | SHIFT, // Z
|
||||
0x25 | ALT_GR, // [
|
||||
0x2d | ALT_GR, // bslash
|
||||
0x26 | ALT_GR, // ]
|
||||
0x00, // ^ not supported (requires dead key + space)
|
||||
0x38 | SHIFT, // _
|
||||
0x00, // ` not supported (requires dead key + space)
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x24 | ALT_GR, // {
|
||||
0x32 | ALT_GR, // |
|
||||
0x27 | ALT_GR, // }
|
||||
0x00, // ~ not supported (requires dead key + space)
|
||||
0x00 // DEL
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Keyboard_da_DK.h
|
||||
|
||||
Copyright (c) 2021, Peter John
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef KEYBOARD_DA_DK_h
|
||||
#define KEYBOARD_DA_DK_h
|
||||
|
||||
#include "HID.h"
|
||||
|
||||
#if !defined(_USING_HID)
|
||||
|
||||
#warning "Using legacy HID core (non pluggable)"
|
||||
|
||||
#else
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
// DA_DK keys
|
||||
#define KEY_A_RING (136+0x2f)
|
||||
#define KEY_SLASHED_O (136+0x34)
|
||||
#define KEY_ASH (136+0x33)
|
||||
#define KEY_UMLAUT (136+0x30)
|
||||
#define KEY_ACUTE_ACC (136+0x2e)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Keyboard_sv_SE.h
|
||||
|
||||
Copyright (c) 2021, Peter John
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef KEYBOARD_SV_SE_h
|
||||
#define KEYBOARD_SV_SE_h
|
||||
|
||||
#include "HID.h"
|
||||
|
||||
#if !defined(_USING_HID)
|
||||
|
||||
#warning "Using legacy HID core (non pluggable)"
|
||||
|
||||
#else
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
// SV_SE keys
|
||||
#define KEY_A_RING (136+0x2f)
|
||||
#define KEY_A_UMLAUT (136+0x34)
|
||||
#define KEY_O_UMLAUT (136+0x33)
|
||||
#define KEY_UMLAUT (136+0x30)
|
||||
#define KEY_ACUTE_ACC (136+0x2e)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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,33 @@
|
||||
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
|
||||
/* Released to the public domain */
|
||||
|
||||
#include <MouseBLE.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
MouseBLE.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;
|
||||
MouseBLE.move(dx, dy, 0);
|
||||
ox = ax;
|
||||
oy = ay;
|
||||
delay(10);
|
||||
}
|
||||
while (BOOTSEL) {
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
MouseBLE KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
click KEYWORD2
|
||||
move KEYWORD2
|
||||
press KEYWORD2
|
||||
release KEYWORD2
|
||||
isPressed KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
@@ -0,0 +1,9 @@
|
||||
name=MouseBLE
|
||||
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 over BLE
|
||||
category=Device Control
|
||||
url=https://www.arduino.cc/reference/en/language/functions/usb/mouse/
|
||||
architectures=rp2040
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
MouseBLE.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 "MouseBLE.h"
|
||||
#include <PicoBluetoothBLEHID.h>
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// 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.
|
||||
*/
|
||||
static signed char limit_xy(int const xy) {
|
||||
if (xy < -127) {
|
||||
return -127;
|
||||
} else if (xy > 127) {
|
||||
return 127;
|
||||
} else {
|
||||
return xy;
|
||||
}
|
||||
}
|
||||
|
||||
MouseBLE_::MouseBLE_(void) : _buttons(0) {
|
||||
/* noop */
|
||||
}
|
||||
|
||||
#define REPORT_ID 0x01
|
||||
const uint8_t desc_mouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID))};
|
||||
void MouseBLE_::begin(void) {
|
||||
PicoBluetoothBLEHID.startHID("PicoW BLE Mouse", "PicoW BLE Mouse", 0x03c2, desc_mouse, sizeof(desc_mouse));
|
||||
}
|
||||
|
||||
void MouseBLE_::end(void) {
|
||||
PicoBluetoothBLEHID.end();
|
||||
}
|
||||
|
||||
void MouseBLE_::click(uint8_t b) {
|
||||
_buttons = b;
|
||||
move(0, 0, 0);
|
||||
delay(10);
|
||||
_buttons = 0;
|
||||
move(0, 0, 0);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void MouseBLE_::move(int x, int y, signed char wheel) {
|
||||
hid_mouse_report_t data;
|
||||
data.buttons = _buttons;
|
||||
data.x = limit_xy(x);
|
||||
data.y = limit_xy(y);
|
||||
data.wheel = wheel;
|
||||
data.pan = 0;
|
||||
PicoBluetoothBLEHID.send(&data, sizeof(data));
|
||||
}
|
||||
|
||||
void MouseBLE_::buttons(uint8_t b) {
|
||||
if (b != _buttons) {
|
||||
_buttons = b;
|
||||
move(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void MouseBLE_::press(uint8_t b) {
|
||||
buttons(_buttons | b);
|
||||
}
|
||||
|
||||
void MouseBLE_::release(uint8_t b) {
|
||||
buttons(_buttons & ~b);
|
||||
}
|
||||
|
||||
bool MouseBLE_::isPressed(uint8_t b) {
|
||||
if ((b & _buttons) > 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MouseBLE_ MouseBLE;
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
MouseBLE.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 MOUSEBLE_h
|
||||
#define MOUSEBLE_h
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Mouse
|
||||
|
||||
#define MOUSE_LEFT 1
|
||||
#define MOUSE_RIGHT 2
|
||||
#define MOUSE_MIDDLE 4
|
||||
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
|
||||
|
||||
class MouseBLE_ {
|
||||
private:
|
||||
uint8_t _buttons;
|
||||
void buttons(uint8_t b);
|
||||
public:
|
||||
MouseBLE_(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
void click(uint8_t b = MOUSE_LEFT);
|
||||
void move(int x, int y, signed char wheel = 0);
|
||||
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
|
||||
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
|
||||
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
|
||||
};
|
||||
extern MouseBLE_ MouseBLE;
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user