Use generic HID classes to minimize code duplic'n (#1254)

Move the Joystick, Keyboard, and Mouse into a base class which handles
the operation/input, and a subclass which will implement the reporting
as a HID device via USB, Bluetooth Classic, or Bluetooth Low Energy (BLE).

Reduce copies of library code and makes maintainability much better.
This commit is contained in:
Earle F. Philhower, III 2023-03-03 11:12:09 -08:00 committed by GitHub
parent 0be1d9c3ea
commit 7aa1c08d17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 1668 additions and 3108 deletions

12
.gitmodules vendored
View file

@ -14,14 +14,14 @@
path = libraries/ESP8266SdFat path = libraries/ESP8266SdFat
url = https://github.com/earlephilhower/ESP8266SdFat.git url = https://github.com/earlephilhower/ESP8266SdFat.git
[submodule "libraries/Keyboard"] [submodule "libraries/Keyboard"]
path = libraries/Keyboard path = libraries/HID_Keyboard
url = https://github.com/earlephilhower/Keyboard url = https://github.com/earlephilhower/Keyboard.git
[submodule "libraries/Mouse"] [submodule "libraries/Mouse"]
path = libraries/Mouse path = libraries/HID_Mouse
url = https://github.com/earlephilhower/Mouse url = https://github.com/earlephilhower/Mouse.git
[submodule "libraries/Joystick"] [submodule "libraries/Joystick"]
path = libraries/Joystick path = libraries/HID_Joystick
url = https://github.com/benjaminaigner/Joystick url = https://github.com/earlephilhower/Joystick.git
[submodule "libraries/Adafruit_TinyUSB_Arduino"] [submodule "libraries/Adafruit_TinyUSB_Arduino"]
path = libraries/Adafruit_TinyUSB_Arduino path = libraries/Adafruit_TinyUSB_Arduino
url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git

View file

@ -6,6 +6,7 @@
# Datatypes (KEYWORD1) # Datatypes (KEYWORD1)
####################################### #######################################
PicoBluetoothHID KEYWORD1
PicoBluetoothBLEHID KEYWORD1 PicoBluetoothBLEHID KEYWORD1
####################################### #######################################
@ -20,8 +21,10 @@ connected KEYWORD2
send KEYWORD2 send KEYWORD2
lockBluetooth KEYWORD2 lockBluetooth KEYWORD2
unlockBluetooth KEYWORD2 unlockBluetooth KEYWORD2
getCID KEYWORD2
setBattery KEYWORD2 setBattery KEYWORD2
####################################### #######################################
# Constants (LITERAL1) # Constants (LITERAL1)
####################################### #######################################

View file

@ -1,9 +1,9 @@
name=PicoBluetoothBLEHID name=HID_Bluetooth
version=1.0.0 version=1.0.0
author=Earle F. Philhower, III <earlephilhower@yahoo.com> author=Earle F. Philhower, III <earlephilhower@yahoo.com>
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com> maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Implements a HID device base class for PicoW Bluetooth BLE sentence=Implements a HID device base class for PicoW Bluetooth
paragraph=Implements a HID device base class for PicoW Bluetooth BLE paragraph=Implements a HID device base class for PicoW Bluetooth
category=Device Control category=Device Control
url=https://github.com/earlephilhower/arduino-pico url=https://github.com/earlephilhower/arduino-pico
architectures=rp2040 architectures=rp2040

View file

@ -0,0 +1,7 @@
#ifdef ENABLE_CLASSIC
#include "PicoBluetoothHID.h"
#endif
#ifdef ENABLE_BLE
#include "PicoBluetoothBLEHID.h"
#endif

@ -0,0 +1 @@
Subproject commit 4eb3e28dc20d44afe676a6c7e0e6264e29f82abb

@ -0,0 +1 @@
Subproject commit 74c3b2fee7da9170a608e7458d4c08c6d8104fa9

1
libraries/HID_Mouse Submodule

@ -0,0 +1 @@
Subproject commit 2aa06d16155c8cb20108e79aaa160a01ea96c0cf

@ -1 +0,0 @@
Subproject commit af745f3e62377de71b7708b15f263dab8773e0c5

View file

@ -0,0 +1,32 @@
:repository-owner: arduino-libraries
:repository-name: Joystick
= {repository-name} Library for Arduino (RP2040 based boards) =
This library allows an RaspberryPi RP2040 board to act as a Joystick when
Earle F. Philhower`s [arduino-pico](https://github.com/earlephilhower/arduino-pico)
Core is used.
== Acknowledgements / Credits ==
* [arduino-pico](https://github.com/earlephilhower/arduino-pico) Earle F. Philhower providing the Arduino Core, on which this library is based on, available under LGPL.
* [tinyUSB] (https://github.com/hathach/tinyusb) Ha Thach for providing tinyUSB under MIT license, which covers most of the USB functionality.
== License ==
Copyright (c) Benjamin Aigner <beni@asterics-foundation.org> All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

View file

@ -0,0 +1,435 @@
# Joystick library
## Methods
### `Joystick.begin()`
Must be called before starting using the Joystick emulation. To end control, use `Joystick.end()`.
#### Syntax
```
Joystick.begin()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
}
void loop() {
// Initialize the Joystick library when button is pressed
if (digitalRead(2) == LOW) {
Joystick.begin();
}
}
```
#### See also
* [Joystick.button()](#joystickbutton)
* [Joystick.end()](#joystickend)
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.position()](#joystickposition)
* [Joystick.X()](#joystickx)
* [Joystick.hat()](#joystickhat)
* [Joystick.use8bit()](#joystickuse8bit)
* [Joystick.useManualSend()](#joystickuseManualSend)
### `Joystick.button()`
Updates a button of the USB joystick.
#### Syntax
```
Joystick.button(1,true);
delay(250);
Joystick.button(1,false);
```
#### Parameters
* `button`: number of Joystick button, which status should be changed
* `val`: state of button, `true` for pressed, `false` for released
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
uint8_t i = 1; //counter for the button number 1-32
if (digitalRead(2) == LOW) { //if button is pressed
Joystick.button(i,true); //"press" the Joystick button
delay(250); //wait for 0.25s
Joystick.button(i,false); //"release" the Joystick button
i = i + 1; //increment & use next Joystick button number
if(i > 32) i = 1; //we have 32 buttons available, wrap-around
}
}
```
#### Notes
* Up to 32 buttons are available, numbered as button 1 to button 32.
* If manual_send is active, call `Joystick.send_now()` to send an update to the host.
#### See also
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.useManualSend()](#joystickuseManualSend)
* [Joystick.X()](#joystickx)
* [Joystick.hat()](#joystickhat)
### `Joystick.end()`
Stops emulating the Joystick connected to a computer. To start control, use `Joystick.begin()`.
#### Syntax
```
Joystick.end()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
// Initiate the Joystick library
Joystick.begin();
}
void loop() {
// If the button is pressed, send a button 1 press / release
if (digitalRead(2) == LOW) {
Joystick.button(1,true);
delay(250);
Joystick.button(1,false);
// Then end the Joystick emulation
Joystick.end();
}
}
```
#### See also
* [Joystick.begin()](#joystickbegin)
### `Joystick.use8bit()`
Switch axis value range between 10bit and 8bit.
* Default: 10bit, range for an axis from 0 to 1023
* 8bit mode: range from -127 to 127.
__Note:__ due to the gamepad descriptor of tinyUSB, the maximum range is -127/127. 10bit mode enables mapping, not a higher resolution.
#### Syntax
```
Joystick.use8bit(true)
```
#### Parameters
* `mode`: true, if values from -127/127 are used. False to use a range from 0 to 1023.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
//send middle position in default 10bit mode
Joystick.position(512,512);
delay(250);
//enable 8bit mode
Joystick.use8bit(true);
//send middle position in 8bit mode
Joystick.position(0,0);
delay(250);
//send maximum left in 10bit mode
Joystick.use8bit(false);
Joystick.position(0,0);
delay(250);
//enable 8bit mode
Joystick.use8bit(true);
//send left position in 8bit mode
Joystick.position(-127,-127);
}
```
#### See also
* [Joystick.position()](#joystickposition)
* [Joystick.X()](#joystickx)
* [Joystick.Y()](#joysticky)
* [Joystick.Z()](#joystickz)
* [Joystick.Zrotate()](#joystickrotate)
* [Joystick.slider()](#joystickslider)
* [Joystick.sliderLeft()](#joysticksliderleft)
* [Joystick.sliderRight()](#joysticksliderright)
### `Joystick.useManualSend()`
To fully control transmitting the USB-HID reports, enable manual sending.
If disabled, each call to a function updating the Joystick status (buttons, all axis, hat)
will send a HID report. If you update in a loop, the time between updates (at least 1ms) is too short and something might be not transmitted correctly.
If enabled, update all your axis values, buttons, hat and then send one report via `Joystick.send_now()`.
#### Syntax
```
Joystick.useManualSend(true)
```
#### Parameters
* `mode`: false is sending report each Joystick update, true enables manual sending via send_now().
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
if (digitalRead(2) == LOW) {
// send data in 4 different reports
Joystick.button(1,true);
Joystick.button(2,true);
Joystick.button(3,true);
Joystick.button(4,true);
//enable manual send
Joystick.useManualSend(true);
//send same data in one report
Joystick.button(1,false);
Joystick.button(2,false);
Joystick.button(3,false);
Joystick.button(4,false);
Joystick.send_now();
}
}
```
#### See also
* [Joystick.send_now()](#joysticksend_now)
### `Joystick.send_now()`
Send a HID report now. Used together with manual sending, see `Joystick.useManualSend()`.
#### Syntax
```
Joystick.send_now()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
//enable manual sending in setup
Joystick.useManualSend(true);
}
void loop() {
if (digitalRead(2) == LOW) {
// update all buttons, but nothing is sent to the host
for(uint8_t i = 1; i<=32; i++) Joystick.button(i,true);
Joystick.X(256);
Joystick.sliderLeft(0);
//now send in one HID report
Joystick.send_now();
}
}
```
#### See also
* [Joystick.useManualSend()](#joystickusemanualsend)
### `Joystick.X()`
Update X axis.
__Note:__ If [manual send](#joystickusemanualsend) is active, the value is sent to the host only after calling [send_now](#joysticksend_now).
__Note:__ If in 10bit mode (default), the parameter is interpreted from 0 to 1023.
In 8bit mode from -127 to 127. The internal resolution is always 8bit. Change setting with [use8bit](#joystickuse8bit).
#### Syntax
```
Joystick.X(0)
```
#### Parameters
* `val`: value from 0 to 1023 (default) or -127 to 127 (8bit mode)
#### Returns
None.
#### Example
```
#include <Joystick.h>
void setup() {
pinMode(2, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
if (digitalRead(2) == LOW) {
Joystick.X(256);
delay(500);
Joystick.X(512);
}
}
```
#### See also
* [Joystick.Y()](#joysticky)
* [Joystick.Z()](#joystickz)
* [Joystick.Zrotate()](#joystickrotate)
* [Joystick.slider()](#joystickslider)
* [Joystick.sliderLeft()](#joysticksliderleft)
* [Joystick.sliderRight()](#joysticksliderright)
* [Joystick.send_now()](#joysticksend_now)
* [Joystick.position()](#joystickposition)
* [Joystick.hat()](#joystickhat)
* [Joystick.use8bit()](#joystickuse8bit)
* [Joystick.useManualSend()](#joystickuseManualSend)
### `Joystick.Y()`
Update Y axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.Z()`
Update Z axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.Zrotate()`
Update Z rotate axis. Please refer to [Joystick.X()](#joystickx).
### `Joystick.sliderLeft()`
Left slider value. Please refer to [Joystick.X()](#joystickx).
### `Joystick.sliderRight()`
Right slider value. Please refer to [Joystick.X()](#joystickx).
### `Joystick.slider()`
Same as [Joystick.sliderLeft()](#joysticksliderleft).
### `Joystick.position()`
Sets X and Y axis in one call. If autosending is active, one report is generated. Please refer to [Joystick.X()](#joystickx).
#### Syntax
```
Joystick.position(512,512)
```
#### Parameters
* `X`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for X axis
* `Y`: value from 0 to 1023 (default) or -127 to 127 (8bit mode); for Y axis
#### See also
* [Joystick.X()](#joystickx)
* [Joystick.Y()](#joysticky)
### `Joystick.hat()`
Set the hat value to selection angle or rest position.
#### Syntax
```
Joystick.hat(-1), // released/rest position
```
#### Parameters
* `angle` Angle value from 0-360 degrees or -1 for released resting position. Mapped to 8 different directions.

View file

@ -0,0 +1,14 @@
# Joystick library
The Joystick functions enable a RP2040 board to act as a HID game controller.
To use this library:
```
#include <Joystick.h>
```
## Examples
* [Joystick-AllFunctions] Includes example calls for each Joystick function

View file

@ -0,0 +1,110 @@
/* Benjamin Aigner, 2022 <beni@asterics-foundation.org> */
/* Public domain / CC 0 */
/** example code using all possibilities of the Joystick class
for the RP2040.
*/
#include <Joystick.h>
void setup() {
Serial.begin(115200);
Serial.println("Use BOOTSEL to start the Joystick demo.");
Joystick.begin();
}
void loop() {
if (BOOTSEL) {
Serial.println("Joystick buttons");
for (uint8_t i = 1; i <= 32; i++) {
Joystick.button(i, true);
delay(250);
Joystick.button(i, false);
delay(10); //we need a short delay here, sending packets with less than 1ms leads to packet loss!
}
//alternativ with manual send:
Joystick.useManualSend(true);
Serial.println("Joystick buttons - manual send");
for (uint8_t i = 1; i <= 32; i++) {
Joystick.button(i, true);
Joystick.send_now();
delay(250);
Joystick.button(i, false);
}
Joystick.useManualSend(false);
//iterate all joystick axis
//Note: although you can use 0-1023 here (10bit), internally 8bits are used (-127 to 127)
Serial.println("Joystick X");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.X(i);
delay(2);
} Joystick.X(512);
Serial.println("Joystick Y");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.Y(i);
delay(2);
} Joystick.Y(512);
Serial.println("Joystick Z");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.Z(i);
delay(2);
} Joystick.Z(512);
Serial.println("Joystick Zrotate");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.Zrotate(i);
delay(2);
} Joystick.Zrotate(512);
Serial.println("Joystick sliderLeft");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.sliderLeft(i);
delay(2);
} Joystick.sliderLeft(0);
Serial.println("Joystick sliderRight");
for (uint16_t i = 0; i < 1023; i++) {
Joystick.sliderRight(i);
delay(2);
} Joystick.sliderRight(0);
Serial.println("Joystick hat");
for (uint16_t i = 0; i < 360; i++) {
Joystick.hat(i);
delay(20);
} Joystick.hat(-1);
//use int8 mode for the axis.
//Note: hat is not used differently.
Serial.println("Now all axis in 8bit mode, -127 to 127");
Joystick.use8bit(true);
Serial.println("Joystick X");
for (int16_t i = -127; i < 128; i++) {
Joystick.X(i);
delay(2);
} Joystick.X(0);
Serial.println("Joystick Y");
for (int16_t i = -127; i < 128; i++) {
Joystick.Y(i);
delay(2);
} Joystick.Y(0);
Serial.println("Joystick Z");
for (int16_t i = -127; i < 128; i++) {
Joystick.Z(i);
delay(2);
} Joystick.Z(0);
Serial.println("Joystick Zrotate");
for (int16_t i = -127; i < 128; i++) {
Joystick.Zrotate(i);
delay(2);
} Joystick.Zrotate(0);
Serial.println("Joystick sliderLeft");
for (int16_t i = -127; i < 128; i++) {
Joystick.sliderLeft(i);
delay(2);
} Joystick.sliderLeft(0);
Serial.println("Joystick sliderRight");
for (int16_t i = -127; i < 128; i++) {
Joystick.sliderRight(i);
delay(2);
} Joystick.sliderRight(0);
Joystick.use8bit(false);
}
}

View file

@ -0,0 +1,33 @@
#######################################
# Syntax Coloring Map For Joystick
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Joystick KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
use8bit KEYWORD2
X KEYWORD2
Y KEYWORD2
button KEYWORD2
position KEYWORD2
Z KEYWORD2
Zrotate KEYWORD2
sliderLeft KEYWORD2
slider KEYWORD2
sliderRight KEYWORD2
hat KEYWORD2
useManualSend KEYWORD2
send_now KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View file

@ -0,0 +1,9 @@
name=Joystick
version=1.0.1
author=Benjamin Aigner
maintainer=Benjamin Aigner <beni@asterics-foundation.org>
sentence=Allows any RP2040 board to act as a joystick/gamepad
paragraph=Allows the RP2040 to emulate a USB Joystick
category=Device Control
url=https://github.com/benjaminaigner/Joystick
architectures=rp2040

View file

@ -0,0 +1,49 @@
/*
Joystick.cpp
Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
Implementation loosely based on:
Mouse library from https://github.com/earlephilhower/arduino-pico
Joystick functions from Teensyduino https://github.com/PaulStoffregen
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Joystick.h"
#include "Arduino.h"
#include <RP2040USB.h>
#include "tusb.h"
#include "class/hid/hid_device.h"
// Weak function override to add our descriptor to the TinyUSB list
void __USBInstallJoystick() { /* noop */ }
Joystick_::Joystick_(void) {
// Everything set up in HID_Joystick constructor
}
//immediately send an HID report
void Joystick_::send_now(void) {
CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_n_report(0, __USBGetJoystickReportID(), &data, sizeof(data));
}
tud_task();
}
Joystick_ Joystick;

View file

@ -1,7 +1,7 @@
/* /*
Keyboard_da_DK.h Joystick.h
Copyright (c) 2021, Peter John Copyright (c) 2022, Benjamin Aigner <beni@asterics-foundation.org>
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -18,27 +18,18 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef KEYBOARD_DA_DK_h #ifndef _JOYSTICK_h
#define KEYBOARD_DA_DK_h #define _JOYSTICK_h
#include "HID.h" #include <HID_Joystick.h>
#include "class/hid/hid.h"
#if !defined(_USING_HID) //======================================================================
class Joystick_ : public HID_Joystick {
public:
Joystick_(void);
virtual void send_now(void) override;
};
extern Joystick_ Joystick;
#warning "Using legacy HID core (non pluggable)" #endif /* _JOYSTICK_h */
#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

View file

@ -32,48 +32,7 @@
// Joystick/Gamepad // Joystick/Gamepad
JoystickBLE_::JoystickBLE_(void) { JoystickBLE_::JoystickBLE_(void) {
_use8bit = false; // Member vars set in base constructor
_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 #define REPORT_ID 0x01
@ -90,97 +49,6 @@ void JoystickBLE_::setBattery(int lvl) {
PicoBluetoothBLEHID.setBattery(lvl); PicoBluetoothBLEHID.setBattery(lvl);
} }
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) { void JoystickBLE_::send_now(void) {
PicoBluetoothBLEHID.send(&data, sizeof(data)); PicoBluetoothBLEHID.send(&data, sizeof(data));
} }

View file

@ -21,50 +21,16 @@
#pragma once #pragma once
#include <Arduino.h> #include <HID_Joystick.h>
#include "class/hid/hid.h" #include "class/hid/hid.h"
//====================================================================== //======================================================================
class JoystickBLE_ { class JoystickBLE_ : public HID_Joystick {
private:
bool _autosend;
bool _use8bit;
hid_gamepad_report_t data;
int map8or10bit(int const value);
public: public:
JoystickBLE_(void); JoystickBLE_(void);
void begin(void); void begin(void);
void end(void); void end(void);
virtual void send_now(void) override;
//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);
void setBattery(int lvl); void setBattery(int lvl);
}; };
extern JoystickBLE_ JoystickBLE; extern JoystickBLE_ JoystickBLE;

View file

@ -32,48 +32,7 @@
// Joystick/Gamepad // Joystick/Gamepad
JoystickBT_::JoystickBT_(void) { JoystickBT_::JoystickBT_(void) {
_use8bit = false; // HID_Joystick sets up all the member vars
_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 #define REPORT_ID 0x01
@ -86,96 +45,6 @@ void JoystickBT_::end(void) {
PicoBluetoothHID.end(); 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 //immediately send an HID report
void JoystickBT_::send_now(void) { void JoystickBT_::send_now(void) {
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data)); PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));

View file

@ -21,48 +21,15 @@
#pragma once #pragma once
#include <Arduino.h> #include <HID_Joystick.h>
#include "class/hid/hid.h" #include "class/hid/hid.h"
//====================================================================== //======================================================================
class JoystickBT_ { class JoystickBT_ : public HID_Joystick {
private:
bool _autosend;
bool _use8bit;
hid_gamepad_report_t data;
int map8or10bit(int const value);
public: public:
JoystickBT_(void); JoystickBT_(void);
void begin(void); void begin(void);
void end(void); void end(void);
virtual void send_now(void) override;
//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; extern JoystickBT_ JoystickBT;

@ -1 +0,0 @@
Subproject commit a6498d6228347ff8337a91b9c1ce934350214dd6

165
libraries/Keyboard/LICENSE Normal file
View file

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View file

@ -0,0 +1,31 @@
:repository-owner: arduino-libraries
:repository-name: Keyboard
= {repository-name} Library for Arduino =
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"]
This library allows an Arduino board with USB capabilities to act as a keyboard.
For more information about this library please visit us at
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
== License ==
Copyright (c) Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

View file

@ -0,0 +1,20 @@
/* Released into the public domain */
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
#include <Keyboard.h>
void setup() {
Serial.begin(115200);
Keyboard.begin();
delay(5000);
Serial.printf("Arduino USB Password Typer\n");
Serial.printf("Press BOOTSEL to enter your super-secure(not!) password\n\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("Typing password for you...shhhh....");
Keyboard.print("ThisPasswordIsWeakLikeABaby");
while (BOOTSEL);
}
}

View file

@ -0,0 +1,39 @@
/*
Keyboard test
For the Arduino Leonardo, Micro or Due
Reads a byte from the serial port, sends a keystroke back.
The sent keystroke is one higher than what's received, e.g. if you send a,
you get b, send A you get B, and so forth.
The circuit:
- none
created 21 Oct 2011
modified 27 Mar 2012
by Tom Igoe
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardSerial
*/
#include "Keyboard.h"
void setup() {
// open the serial port:
Serial.begin(9600);
// initialize control over the keyboard:
Keyboard.begin();
}
void loop() {
// check for incoming serial data:
if (Serial.available() > 0) {
// read incoming serial data:
char inChar = Serial.read();
// Type the next ASCII value from what you received:
Keyboard.write(inChar + 1);
}
}

View file

@ -1,26 +1,22 @@
####################################### #######################################
# Syntax Coloring Map # Syntax Coloring Map For Keyboard
####################################### #######################################
####################################### #######################################
# Datatypes (KEYWORD1) # Datatypes (KEYWORD1)
####################################### #######################################
PicoBluetoothHID KEYWORD1 Keyboard KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
####################################### #######################################
setOpenedCB KEYWORD2 begin KEYWORD2
setClosedCB KEYWORD2 write KEYWORD2
setCanSendNowCB KEYWORD2 press KEYWORD2
startHID KEYWORD2 release KEYWORD2
connected KEYWORD2 releaseAll KEYWORD2
send KEYWORD2
lockBluetooth KEYWORD2
unlockBluetooth KEYWORD2
getCID KEYWORD2
####################################### #######################################
# Constants (LITERAL1) # Constants (LITERAL1)

View file

@ -0,0 +1,9 @@
name=Keyboard
version=1.0.3
author=Arduino and EFP3
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Allows a RP2040 to act as a Keyboard.
paragraph=Port of pure Arduino Keyboard
category=Device Control
url=https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
architectures=rp2040

View file

@ -1,7 +1,9 @@
/* /*
Keyboard_sv_SE.h Keyboard.cpp
Copyright (c) 2021, Peter John 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -18,27 +20,30 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef KEYBOARD_SV_SE_h #include "Keyboard.h"
#define KEYBOARD_SV_SE_h #include <RP2040USB.h>
#include "HID.h" #include "tusb.h"
#include "class/hid/hid_device.h"
#if !defined(_USING_HID) // Weak function override to add our descriptor to the TinyUSB list
void __USBInstallKeyboard() { /* noop */ }
#warning "Using legacy HID core (non pluggable)"
#else
//================================================================================ //================================================================================
//================================================================================ //================================================================================
// Keyboard // Keyboard
// SV_SE keys Keyboard_::Keyboard_(void) {
#define KEY_A_RING (136+0x2f) // Base class clears the members we care about
#define KEY_A_UMLAUT (136+0x34) }
#define KEY_O_UMLAUT (136+0x33)
#define KEY_UMLAUT (136+0x30)
#define KEY_ACUTE_ACC (136+0x2e)
#endif void Keyboard_::sendReport(KeyReport* keys) {
#endif CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_keyboard_report(__USBGetKeyboardReportID(), keys->modifiers, keys->keys);
}
tud_task();
}
Keyboard_ Keyboard;

View file

@ -1,7 +1,9 @@
/* /*
Keyboard_sv_SE.h Keyboard.h
Copyright (c) 2021, Peter John 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -18,27 +20,17 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef KEYBOARD_SV_SE_h #ifndef KEYBOARD_h
#define KEYBOARD_SV_SE_h #define KEYBOARD_h
#include "HID.h" #include <HID_Keyboard.h>
#if !defined(_USING_HID) class Keyboard_ : public HID_Keyboard {
protected:
#warning "Using legacy HID core (non pluggable)" virtual void sendReport(KeyReport* keys) override;
public:
#else Keyboard_(void);
};
//================================================================================ extern Keyboard_ Keyboard;
//================================================================================
// 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
#endif

View file

@ -29,8 +29,7 @@
// Keyboard // Keyboard
KeyboardBLE_::KeyboardBLE_(void) { KeyboardBLE_::KeyboardBLE_(void) {
bzero(&_keyReport, sizeof(_keyReport)); // Base class clears the members we care about
_asciimap = KeyboardLayout_en_US;
} }
#define REPORT_ID 0x01 #define REPORT_ID 0x01
@ -57,127 +56,4 @@ void KeyboardBLE_::sendReport(KeyReport* keys) {
PicoBluetoothBLEHID.send(&data, sizeof(data)); 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; KeyboardBLE_ KeyboardBLE;

View file

@ -23,118 +23,15 @@
#ifndef KEYBOARDBLE_h #ifndef KEYBOARDBLE_h
#define KEYBOARDBLE_h #define KEYBOARDBLE_h
#include <Arduino.h> #include <HID_Keyboard.h>
//================================================================================ class KeyboardBLE_ : public HID_Keyboard {
//================================================================================
// 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: private:
KeyReport _keyReport; virtual void sendReport(KeyReport* keys) override;
const uint8_t *_asciimap;
void sendReport(KeyReport* keys);
public: public:
KeyboardBLE_(void); KeyboardBLE_(void);
void begin(const uint8_t *layout = KeyboardLayout_en_US); void begin(const uint8_t *layout = KeyboardLayout_en_US);
void end(void); 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);
void setBattery(int lvl); void setBattery(int lvl);
}; };
extern KeyboardBLE_ KeyboardBLE; extern KeyboardBLE_ KeyboardBLE;

View file

@ -1,65 +0,0 @@
/*
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

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -29,8 +29,7 @@
// Keyboard // Keyboard
KeyboardBT_::KeyboardBT_(void) { KeyboardBT_::KeyboardBT_(void) {
bzero(&_keyReport, sizeof(_keyReport)); // Base class clears the members we care about
_asciimap = KeyboardLayout_en_US;
} }
#define REPORT_ID 0x01 #define REPORT_ID 0x01
@ -53,127 +52,4 @@ void KeyboardBT_::sendReport(KeyReport* keys) {
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data)); 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; KeyboardBT_ KeyboardBT;

View file

@ -23,118 +23,15 @@
#ifndef KEYBOARDBT_h #ifndef KEYBOARDBT_h
#define KEYBOARDBT_h #define KEYBOARDBT_h
#include <Arduino.h> #include <HID_Keyboard.h>
//================================================================================ class KeyboardBT_ : public HID_Keyboard {
//================================================================================ protected:
// Keyboard virtual void sendReport(KeyReport* keys) override;
// 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: public:
KeyboardBT_(void); KeyboardBT_(void);
void begin(const uint8_t *layout = KeyboardLayout_en_US); void begin(const uint8_t *layout = KeyboardLayout_en_US);
void end(void); 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; extern KeyboardBT_ KeyboardBT;

View file

@ -1,65 +0,0 @@
/*
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

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

View file

@ -1,137 +0,0 @@
/*
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
};

@ -1 +0,0 @@
Subproject commit be7395a597c748eda75ea40821637a63e596f09d

View file

@ -0,0 +1,31 @@
:repository-owner: arduino-libraries
:repository-name: Mouse
= {repository-name} Library for Arduino =
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"]
This library allows an Arduino board with USB capabilities to act as a Mouse.
For more information about this library please visit us at
https://www.arduino.cc/reference/en/language/functions/usb/mouse/
== License ==
Copyright (c) Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

428
libraries/Mouse/docs/api.md Normal file
View file

@ -0,0 +1,428 @@
# Mouse library
## Methods
### `Mouse.begin()`
Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`.
#### Syntax
```
Mouse.begin()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
}
void loop() {
// Initialize the Mouse library when button is pressed
if (digitalRead(2) == HIGH) {
Mouse.begin();
}
}
```
#### See also
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.click()`
Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button.
`Mouse.click()` defaults to the left mouse button.
#### Syntax
```
Mouse.click()
Mouse.click(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
}
}
```
#### Notes and warnings
When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.end()`
Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`.
#### Syntax
```
Mouse.end()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initiate the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
// Then end the Mouse emulation
Mouse.end();
}
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.move()`
Moves the cursor on a connected computer. The motion onscreen is always relative to the cursors 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)

View file

@ -0,0 +1,23 @@
# Mouse library
The mouse functions enable 32u4 or SAMD micro based boards to control cursor movement on a connected computer through their micros native USB port. When updating the cursor position, it is always relative to the cursors 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 computers cursor movement with a Joystick when a button is pressed.

View file

@ -0,0 +1,34 @@
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
/* Released to the public domain */
#include <Mouse.h>
void setup() {
Serial.begin(115200);
Mouse.begin();
delay(5000);
Serial.printf("Press BOOTSEL to move the mouse in a circle\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("BARREL ROLL!!!");
float r = 100;
float ox = 0.0;
float oy = 0.0;
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
float dx = ax - ox;
float dy = ay - oy;
Mouse.move(dx, dy, 0);
ox = ax;
oy = ay;
delay(10);
}
while (BOOTSEL) {
delay(1);
}
}
}

View file

@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map For Mouse
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Mouse KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
click KEYWORD2
move KEYWORD2
press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View file

@ -0,0 +1,9 @@
name=Mouse
version=1.0.1
author=Arduino and EFP3
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Allows an Arduino board with USB capabilities to act as a Mouse.
paragraph=Allows the RP2040 to emulate a USB mouse
category=Device Control
url=https://www.arduino.cc/reference/en/language/functions/usb/mouse/
architectures=rp2040

View file

@ -0,0 +1,53 @@
/*
Mouse.cpp
Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Mouse.h"
#include <RP2040USB.h>
#include "tusb.h"
#include "class/hid/hid_device.h"
// Weak function override to add our descriptor to the TinyUSB list
void __USBInstallMouse() { /* noop */ }
//================================================================================
//================================================================================
// Mouse
/* This function is for limiting the input value for x and y
axis to -127 <= x/y <= 127 since this is the allowed value
range for a USB HID device.
*/
Mouse_::Mouse_(void) {
/* noop */
}
void Mouse_::move(int x, int y, signed char wheel) {
CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_mouse_report(__USBGetMouseReportID(), _buttons, limit_xy(x), limit_xy(y), wheel, 0);
}
tud_task();
}
Mouse_ Mouse;

View file

@ -1,7 +1,8 @@
/* /*
Keyboard_da_DK.h Mouse.h
Copyright (c) 2021, Peter John 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -18,27 +19,16 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef KEYBOARD_DA_DK_h #ifndef MOUSE_h
#define KEYBOARD_DA_DK_h #define MOUSE_h
#include "HID.h" #include <HID_Mouse.h>
#if !defined(_USING_HID) class Mouse_ : public HID_Mouse {
public:
#warning "Using legacy HID core (non pluggable)" Mouse_(void);
virtual void move(int x, int y, signed char wheel = 0) override;
#else };
extern Mouse_ Mouse;
//================================================================================
//================================================================================
// 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
#endif

View file

@ -22,25 +22,7 @@
#include "MouseBLE.h" #include "MouseBLE.h"
#include <PicoBluetoothBLEHID.h> #include <PicoBluetoothBLEHID.h>
//================================================================================ MouseBLE_::MouseBLE_(void) {
//================================================================================
// 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 */ /* noop */
} }
@ -58,15 +40,6 @@ void MouseBLE_::setBattery(int lvl) {
PicoBluetoothBLEHID.setBattery(lvl); PicoBluetoothBLEHID.setBattery(lvl);
} }
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) { void MouseBLE_::move(int x, int y, signed char wheel) {
hid_mouse_report_t data; hid_mouse_report_t data;
data.buttons = _buttons; data.buttons = _buttons;
@ -77,27 +50,4 @@ void MouseBLE_::move(int x, int y, signed char wheel) {
PicoBluetoothBLEHID.send(&data, sizeof(data)); 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; MouseBLE_ MouseBLE;

View file

@ -22,30 +22,14 @@
#ifndef MOUSEBLE_h #ifndef MOUSEBLE_h
#define MOUSEBLE_h #define MOUSEBLE_h
#include <Arduino.h> #include <HID_Mouse.h>
//================================================================================ class MouseBLE_ : public HID_Mouse {
//================================================================================
// 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: public:
MouseBLE_(void); MouseBLE_(void);
void begin(void); void begin(void);
void end(void); void end(void);
void click(uint8_t b = MOUSE_LEFT); virtual void move(int x, int y, signed char wheel = 0) override;
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
void setBattery(int lvl); void setBattery(int lvl);
}; };
extern MouseBLE_ MouseBLE; extern MouseBLE_ MouseBLE;

View file

@ -22,25 +22,7 @@
#include "MouseBT.h" #include "MouseBT.h"
#include <PicoBluetoothHID.h> #include <PicoBluetoothHID.h>
//================================================================================ MouseBT_::MouseBT_(void) {
//================================================================================
// 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;
}
}
MouseBT_::MouseBT_(void) : _buttons(0) {
/* noop */ /* noop */
} }
@ -54,15 +36,6 @@ void MouseBT_::end(void) {
PicoBluetoothHID.end(); PicoBluetoothHID.end();
} }
void MouseBT_::click(uint8_t b) {
_buttons = b;
move(0, 0, 0);
delay(10);
_buttons = 0;
move(0, 0, 0);
delay(10);
}
void MouseBT_::move(int x, int y, signed char wheel) { void MouseBT_::move(int x, int y, signed char wheel) {
hid_mouse_report_t data; hid_mouse_report_t data;
data.buttons = _buttons; data.buttons = _buttons;
@ -73,27 +46,4 @@ void MouseBT_::move(int x, int y, signed char wheel) {
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data)); PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
} }
void MouseBT_::buttons(uint8_t b) {
if (b != _buttons) {
_buttons = b;
move(0, 0, 0);
}
}
void MouseBT_::press(uint8_t b) {
buttons(_buttons | b);
}
void MouseBT_::release(uint8_t b) {
buttons(_buttons & ~b);
}
bool MouseBT_::isPressed(uint8_t b) {
if ((b & _buttons) > 0) {
return true;
} else {
return false;
}
}
MouseBT_ MouseBT; MouseBT_ MouseBT;

View file

@ -22,30 +22,14 @@
#ifndef MOUSEBT_h #ifndef MOUSEBT_h
#define MOUSEBT_h #define MOUSEBT_h
#include <Arduino.h> #include <HID_Mouse.h>
//================================================================================ class MouseBT_ : public HID_Mouse {
//================================================================================
// Mouse
#define MOUSE_LEFT 1
#define MOUSE_RIGHT 2
#define MOUSE_MIDDLE 4
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
class MouseBT_ {
private:
uint8_t _buttons;
void buttons(uint8_t b);
public: public:
MouseBT_(void); MouseBT_(void);
void begin(void); void begin(void);
void end(void); void end(void);
void click(uint8_t b = MOUSE_LEFT); virtual void move(int x, int y, signed char wheel = 0) override;
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 MouseBT_ MouseBT; extern MouseBT_ MouseBT;

View file

@ -1,9 +0,0 @@
name=PicoBluetoothHID
version=1.0.0
author=Earle F. Philhower, III <earlephilhower@yahoo.com>
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Implements a HID device base class for PicoW Bluetooth Classic
paragraph=Implements a HID device base class for PicoW Bluetooth Classic
category=Device Control
url=https://github.com/earlephilhower/arduino-pico
architectures=rp2040

View file

@ -9,8 +9,9 @@ for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S ./libraries/SingleF
./libraries/PicoOTA ./libraries/SDFS ./libraries/ArduinoOTA \ ./libraries/PicoOTA ./libraries/SDFS ./libraries/ArduinoOTA \
./libraries/Updater ./libraries/HTTPClient ./libraries/HTTPUpdate \ ./libraries/Updater ./libraries/HTTPClient ./libraries/HTTPUpdate \
./libraries/WebServer ./libraries/HTTPUpdateServer ./libraries/DNSServer \ ./libraries/WebServer ./libraries/HTTPUpdateServer ./libraries/DNSServer \
./libraries/PicoBluetoothHID ./libraries/JoystickBT ./libraries/KeyboardBT \ ./libraries/Joystick ./libraries/Keyboard ./libraries/Mouse \
./libraries/MouseBT ./libraries/SerialBT ./libraries/PicoBluetoothBLEHID \ ./libraries/JoystickBT ./libraries/KeyboardBT \
./libraries/MouseBT ./libraries/SerialBT ./libraries/HID_Bluetooth \
./libraries/JoystickBLE ./libraries/KeyboardBLE ./libraries/MouseBLE ; do ./libraries/JoystickBLE ./libraries/KeyboardBLE ./libraries/MouseBLE ; do
find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" \) -a \! -path '*api*' -exec astyle --suffix=none --options=./tests/astyle_core.conf \{\} \; find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" \) -a \! -path '*api*' -exec astyle --suffix=none --options=./tests/astyle_core.conf \{\} \;
find $dir -type f -name "*.ino" -exec astyle --suffix=none --options=./tests/astyle_examples.conf \{\} \; find $dir -type f -name "*.ino" -exec astyle --suffix=none --options=./tests/astyle_examples.conf \{\} \;