Compare commits

..
19 Commits
Author SHA1 Message Date
Earle F. Philhower, III c276a36c9b Update version 2023-04-05 13:38:25 -07:00
Earle F. Philhower, III ff0d794c50 Add MacOS Picotool upload help (#1355)
Fixes #1344
2023-04-04 14:24:15 -07:00
Maximilian Gerhardt 369c878711 Add BTC and BLE docs to PlatformIO (#1354) 2023-04-04 14:20:39 -07:00
Pontus Oldberg 5bf570c27d Add support for Challenger UWB board, fix some defines (#1351) 2023-04-03 08:58:26 -07:00
Earle F. Philhower, III 0963611fc7 Add absolute mouse support (#1342)
Fixes #1338

To be revisited when TinyUSB native support is added and picked up in the SDK
2023-03-30 16:09:04 -07:00
Earle F. Philhower, III 00644db9b1 Update to fixed HID_Mouse submodule (#1340) 2023-03-30 12:24:13 -07:00
Paint Your Dragon f8ba72aa15 Add Feather ThinkINK and USB Host (#1334) 2023-03-29 11:18:45 -07:00
Paint Your Dragon 371b2c87b1 Add Feather RP2040 RFM, fix pins in SCORPIO, DVI board defs (#1333) 2023-03-28 12:58:49 -07:00
Earle F. Philhower, III 387655606e Update README.md 2023-03-21 07:17:40 -07:00
Earle F. Philhower, III e1b881a688 Add Win32 Long Path info to P.IO docs (#1321) 2023-03-20 15:31:39 -07:00
Mark Hildreth 869ea4c16b Add flatpak-specific IDE installation instructions (#1317) 2023-03-19 11:43:47 -07:00
Earle F. Philhower, III 71238ccd74 Clean up CoreMutex and __isFreeRTOS definition (#1312)
See #1311 for more info.  __isFreeRTOS is C++ linkage and only used
in the core proper (all C++).
2023-03-16 14:42:28 -07:00
Earle F. Philhower, III 1dfd9ebac7 Add HID consumer (aka media) keys for USB, BT (#1309)
Allow sending thigns like KEY_MUTE or KEY_SCAN_NEXT from the USB and
Bluetooth Classic keyboard libraries.

BLE requires some add'l magic, not yet discovered.

Pull in latest upstream Keyboard library changes
2023-03-15 19:10:31 -07:00
Earle F. Philhower, III 3dbe5cf930 Add I2S::swapClocks() for boards w/reversed pins (#1298)
Allow users of boards like the Pico-Audiom where the LRCLK comes
before the BCLK pin, to swap the BCLK/LRCLK of the I2S interface.

Fixes #1287
2023-03-15 15:23:56 -07:00
Earle F. Philhower, III 8e8fea4b7d Add (unsupported) BTstack Arduino library (#1305)
The BTstack driver includes a basic Arduino library as part of the ports
directory.
2023-03-15 13:02:24 -07:00
Earle F. Philhower, III ebe5bfbc07 Increase UDP PCBs to avoid DNS OOM error (#1304)
Fixes #1285 (or at least works well enough for now)
2023-03-14 07:28:24 -07:00
Limor "Ladyada" Fried d67930eeef Feather DVI peripheral fix (#1301)
* make the main SPI SPI (even tho its on SPI1)

* fix Wire to default pins
2023-03-13 17:07:55 -07:00
Earle F. Philhower, III 084d5b0b87 Add 4 and 8 MB VCC_GND boards via Flash Size menu (#1297)
Thanks to @e-tinkers for the initial PR!
2023-03-11 09:52:33 -08:00
Earle F. Philhower, III 8dc44b5e0d Astyle format variants format (#1295) 2023-03-10 13:00:04 -08:00
111 changed files with 5369 additions and 818 deletions
+28 -1
View File
@@ -40,6 +40,7 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
* Invector Labs Challenger RP2040 LoRa
* Invector Labs Challenger RP2040 SubGHz
* Invector Labs Challenger RP2040 SD/RTC
* Invector Labs Challenger RP2040 UWB
* Invector Labs RPICO32
* Melopero Cookie RP2040
* Melopero Shake RP2040
@@ -64,13 +65,33 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
* Generic (configurable flash, I/O pins)
# Installing via Arduino Boards Manager
**Windows Users**: Please do not use the Windows Store version of the actual Arduino application
## Windows-specific Notes
Please do not use the Windows Store version of the actual Arduino application
because it has issues detecting attached Pico boards. Use the "Windows ZIP" or plain "Windows"
executable (EXE) download direct from https://arduino.cc. and allow it to install any device
drivers it suggests. Otherwise the Pico board may not be detected. Also, if trying out the
2.0 beta Arduino please install the release 1.8 version beforehand to ensure needed device drivers
are present. (See #20 for more details.)
## Linux-specific Notes
Installing Arduino using flatpak (often used by "App Stores" in various Linux
distributions) will mean it has restricted access to the host. This might cause uploads to fail
with error messages such as the following:
```
Scanning for RP2040 devices
...
No drive to deploy.
```
If you encounter this, you will need to either install Arduino in a different manner, or override
the flatpak sandboxing feature using the following command, then restarting Arduino.
```
flatpak override --user --filesystem=host:ro cc.arduino.IDE2
```
## Installation
Open up the Arduino IDE and go to File->Preferences.
In the dialog that pops up, enter the following URL in the "Additional Boards Manager URLs" field:
@@ -88,6 +109,12 @@ Type "pico" in the search box and select "Add":
![image](https://user-images.githubusercontent.com/11875/111917223-12063680-8a3c-11eb-8884-4f32b8f0feb1.png)
# Installing via GIT
**Windows Users:** Before installing via `git` on Windows, please read and follow the directions in
[this link](https://arduino-pico.readthedocs.io/en/latest/platformio.html#important-steps-for-windows-users-before-installing).
If Win32 long paths are not enabled, and `git` not configured to use them then there
may be errors when attempting to clone the submodules.
To install via GIT (for latest and greatest versions):
````
mkdir -p ~/Arduino/hardware/pico
+1082 -110
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -84,13 +84,13 @@ void analogWriteFreq(uint32_t freq);
void analogWriteRange(uint32_t range);
void analogWriteResolution(int res);
// FreeRTOS potential calls
extern bool __isFreeRTOS;
#ifdef __cplusplus
} // extern "C"
#endif
// FreeRTOS potential calls
extern bool __isFreeRTOS;
// Ancient AVR defines
#define HAVE_HWSERIAL0
#define HAVE_HWSERIAL1
+1 -1
View File
@@ -43,5 +43,5 @@ public:
private:
mutex_t *_mutex;
bool _acquired;
u_int8_t _option;
uint8_t _option;
};
+22 -7
View File
@@ -36,6 +36,7 @@
#include "pico/usb_reset_interface.h"
#include "hardware/watchdog.h"
#include "pico/bootrom.h"
#include "sdkoverride/tusb_absmouse.h"
#include <device/usbd_pvt.h>
// Big, global USB mutex, shared with all USB devices to make sure we don't
@@ -100,7 +101,7 @@ const uint8_t *tud_descriptor_device_cb(void) {
.iSerialNumber = USBD_STR_SERIAL,
.bNumConfigurations = 1
};
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallJoystick && !__USBInstallMassStorage) {
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallAbsoluteMouse && !__USBInstallJoystick && !__USBInstallMassStorage) {
// Can use as-is, this is the default USB case
return (const uint8_t *)&usbd_desc_device;
}
@@ -108,7 +109,7 @@ const uint8_t *tud_descriptor_device_cb(void) {
if (__USBInstallKeyboard) {
usbd_desc_device.idProduct |= 0x8000;
}
if (__USBInstallMouse) {
if (__USBInstallMouse || __USBInstallAbsoluteMouse) {
usbd_desc_device.idProduct |= 0x4000;
}
if (__USBInstallJoystick) {
@@ -137,7 +138,7 @@ int __USBGetJoystickReportID() {
if (__USBInstallKeyboard) {
i++;
}
if (__USBInstallMouse) {
if (__USBInstallMouse || __USBInstallAbsoluteMouse) {
i++;
}
return i;
@@ -156,8 +157,9 @@ static uint8_t *GetDescHIDReport(int *len) {
void __SetupDescHIDReport() {
//allocate memory for the HID report descriptors. We don't use them, but need the size here.
uint8_t desc_hid_report_mouse[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_absmouse[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_joystick[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)), TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(2)) };
int size = 0;
//accumulate the size of all used HID report descriptors
@@ -166,6 +168,8 @@ void __SetupDescHIDReport() {
}
if (__USBInstallMouse) {
size += sizeof(desc_hid_report_mouse);
} else if (__USBInstallAbsoluteMouse) {
size += sizeof(desc_hid_report_absmouse);
}
if (__USBInstallJoystick) {
size += sizeof(desc_hid_report_joystick);
@@ -194,11 +198,19 @@ void __SetupDescHIDReport() {
if (__USBInstallMouse) {
//determine if we need an offset (USB keyboard is installed)
if (__USBInstallKeyboard) {
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(2)) };
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(3)) };
memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
} else {
memcpy(__hid_report, desc_hid_report_mouse, sizeof(desc_hid_report_mouse));
}
} else if (__USBInstallAbsoluteMouse) {
//determine if we need an offset (USB keyboard is installed)
if (__USBInstallKeyboard) {
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(3)) };
memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
} else {
memcpy(__hid_report, desc_hid_report_absmouse, sizeof(desc_hid_report_absmouse));
}
}
//3.) joystick descriptor. 2 additional checks are necessary for mouse and/or keyboard
@@ -206,12 +218,15 @@ void __SetupDescHIDReport() {
uint8_t reportid = 1;
int offset = 0;
if (__USBInstallKeyboard) {
reportid++;
reportid += 2;
offset += sizeof(desc_hid_report_keyboard);
}
if (__USBInstallMouse) {
reportid++;
offset += sizeof(desc_hid_report_mouse);
} else if (__USBInstallAbsoluteMouse) {
reportid++;
offset += sizeof(desc_hid_report_absmouse);
}
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(reportid)) };
memcpy(__hid_report + offset, desc_local, sizeof(desc_local));
@@ -235,7 +250,7 @@ const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
void __SetupUSBDescriptor() {
if (!usbd_desc_cfg) {
bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallJoystick;
bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallAbsoluteMouse || __USBInstallJoystick;
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMassStorage ? 1 : 0);
+6
View File
@@ -23,9 +23,15 @@
// Weak function definitions for each type of endpoint
extern void __USBInstallSerial() __attribute__((weak));
extern void __USBInstallKeyboard() __attribute__((weak));
extern void __USBInstallJoystick() __attribute__((weak));
// One or the other allowed, not both
extern void __USBInstallMouse() __attribute__((weak));
extern void __USBInstallAbsoluteMouse() __attribute__((weak));
extern void __USBInstallMassStorage() __attribute__((weak));
// Big, global USB mutex, shared with all USB devices to make sure we don't
+2 -2
View File
@@ -1,5 +1,5 @@
#pragma once
#define ARDUINO_PICO_MAJOR 3
#define ARDUINO_PICO_MINOR 1
#define ARDUINO_PICO_REVISION 0
#define ARDUINO_PICO_VERSION_STR "3.1.0"
#define ARDUINO_PICO_REVISION 1
#define ARDUINO_PICO_VERSION_STR "3.1.1"
+101
View File
@@ -0,0 +1,101 @@
/*
Expost absolute mouse HID descriptor and report
Taken from @tobozo PR https://github.com/hathach/tinyusb/pull/1363
TODO - remove once that PR merged with TinyUSB
Copyright (c) 2023 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "tusb.h"
#include "class/hid/hid_device.h"
// Absolute Mouse: same as the Standard (relative) Mouse Report but
// with int16_t instead of int8_t for X and Y coordinates.
typedef struct TU_ATTR_PACKED {
uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
int16_t x; /**< Current x position of the mouse. */
int16_t y; /**< Current y position of the mouse. */
int8_t wheel; /**< Current delta wheel movement on the mouse. */
int8_t pan; // using AC Pan
} hid_abs_mouse_report_t;
// Absolute Mouse Report Descriptor Template
#define TUD_HID_REPORT_DESC_ABSMOUSE(...) \
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
/* Report ID if any */\
__VA_ARGS__ \
HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
HID_USAGE_MIN ( 1 ) ,\
HID_USAGE_MAX ( 5 ) ,\
HID_LOGICAL_MIN ( 0 ) ,\
HID_LOGICAL_MAX ( 1 ) ,\
/* Left, Right, Middle, Backward, Forward buttons */ \
HID_REPORT_COUNT( 5 ) ,\
HID_REPORT_SIZE ( 1 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
/* 3 bit padding */ \
HID_REPORT_COUNT( 1 ) ,\
HID_REPORT_SIZE ( 3 ) ,\
HID_INPUT ( HID_CONSTANT ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
/* X, Y absolute position [0, 32767] */ \
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
HID_LOGICAL_MIN ( 0x00 ) ,\
HID_LOGICAL_MAX_N( 0x7FFF, 2 ) ,\
HID_REPORT_SIZE ( 16 ) ,\
HID_REPORT_COUNT ( 2 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
/* Vertical wheel scroll [-127, 127] */ \
HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\
HID_LOGICAL_MIN ( 0x81 ) ,\
HID_LOGICAL_MAX ( 0x7f ) ,\
HID_REPORT_COUNT( 1 ) ,\
HID_REPORT_SIZE ( 8 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \
/* Horizontal wheel scroll [-127, 127] */ \
HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \
HID_LOGICAL_MIN ( 0x81 ), \
HID_LOGICAL_MAX ( 0x7f ), \
HID_REPORT_COUNT( 1 ), \
HID_REPORT_SIZE ( 8 ), \
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \
HID_COLLECTION_END , \
HID_COLLECTION_END \
static inline bool tud_hid_abs_mouse_report(uint8_t report_id,
uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
hid_abs_mouse_report_t report = {
.buttons = buttons,
.x = x,
.y = y,
.wheel = vertical,
.pan = horizontal
};
return tud_hid_n_report(0, report_id, &report, sizeof(report));
}
+2 -2
View File
@@ -54,9 +54,9 @@ author = u'Earle F. Philhower, III'
# built documents.
#
# The short X.Y version.
version = u'3.1.0'
version = u'3.1.1'
# The full version, including alpha/beta/rc tags.
release = u'3.1.0'
release = u'3.1.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
+7
View File
@@ -64,6 +64,13 @@ Enables LSB-J format for I2S output. In this mode the MSB comes out at the
same time as the LRCLK changes, and not the normal 1-cycle delay. Useful for
DAC chips like the PT8211.
bool swapClocks()
~~~~~~~~~~~~~~~~~
Certain boards are hardwired with the WCLK before the BCLK, instead of the normal
way around. This call swaps the WCLK and BCLK pins. Note that you still call
``setBCLK(x)`` with ``x`` being the lowest pin ID (i.e. in swapClocks mode the
``setBCLK`` call actually sets LRCLK).
bool begin()/begin(long sampleRate)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Start the I2S device up with the given sample rate, or with the value set
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

+7 -1
View File
@@ -143,7 +143,13 @@ So for the first sketch you will need to rebuild (with the ``Upload Method->Pico
After the initial upload, as long as the running binary was built using the ``Picotool`` upload method, then the normal upload process should work.
Note that for Ubuntu and other Linux operating systems you may need to add the following lines to a new `udev` config file(``99-picotool.rules``) to allow normal users to access the special USB device the Pico exports:
Under MacOS, it may be necessary to install the USB support libraries from a command terminal before the ``Picotool`` upload method can be used:
.. code::
brew install libusb
For Ubuntu and other Linux operating systems you may need to add the following lines to a new `udev` config file(``99-picotool.rules``) to allow normal users to access the special USB device the Pico exports:
.. code::
+51
View File
@@ -23,6 +23,46 @@ Especially useful is the `Getting started with VSCode + PlatformIO <https://docs
Hereafter it is assumed that you have a basic understanding of PlatformIO in regards to project creation, project file structure and building and uploading PlatformIO projects, through reading the above pages.
Important steps for Windows users, before installing
----------------------------------------------------
By default, Windows has a limited path length that is not long enough to fully clone the ``Pico-SDK``'s ``tinyusb`` repository, resulting in error messages like the one below while attempting to fetch the repository.
.. code::
error: unable to create file '.....' : Filename too long
To work around this requires performing two steps and rebooting Windows once. These steps will enable longer file paths at the Windows OS and the ``git`` level.
Step 1: Enabling long paths in git
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Open up a Windows ``cmd`` or ``terminal`` window and execute the following command
.. code::
git config --system core.longpaths true
Step 2: Enabling long paths in the Windows OS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(taken from https://www.microfocus.com/documentation/filr/filr-4/filr-desktop/t47bx2ogpfz7.html)
1. Click Window key and type gpedit.msc, then press the Enter key. This launches the Local Group Policy Editor.
2. Navigate to Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem.
3. Double click Enable NTFS/Win32 long paths and close the dialog.
.. image:: images/longpath.png
Step 3: Reboot the computer
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once the two prior stages are complete, please do a full reboot or power cycle so that the new settings will take effect.
Current state of development
----------------------------
@@ -234,6 +274,17 @@ The lwIP stack can be configured to support only IPv4 (default) or additionally
to the ``platformio.ini``.
Bluetooth Stack
---------------
The Bluetooth Classic (BTC) and Bluetooth Low Energy (BLE) stack can be activated by adding
.. code:: ini
; BTC and BLE
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH
to the ``platformio.ini``.
Selecting a different core version
----------------------------------
+3
View File
@@ -56,6 +56,9 @@ extern unsigned long get_rand_32(void);
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
// See #1285
#define MEMP_NUM_UDP_PCB 6
#if LWIP_IPV6
#define LWIP_IPV6_DHCP6 1
#endif
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
This is the BTstack ports/arduino library, with compile errors fixed only.
+105
View File
@@ -0,0 +1,105 @@
#include <BTstack.h>
#include <stdio.h>
#include "ble/att_server.h"
#include "ble/gatt_client.h"
#include "ble/gatt-service/ancs_client.h"
#include "ble/sm.h"
#include "btstack_event.h"
#include <SPI.h>
/*
EXAMPLE_START(ANCS): ANCS Client
*/
/*
@section Advertisement
@text An ANCS Client needs to include the ANCS UUID in its advertisement to
get recognized by iOS
*/
/* LISTING_START(ANCSAdvertisement): ANCS Advertisement */
const uint8_t adv_data[] = {
// Flags general discoverable
0x02, 0x01, 0x02,
// Name
0x05, 0x09, 'A', 'N', 'C', 'S',
// Service Solicitation, 128-bit UUIDs - ANCS (little endian)
0x11, 0x15, 0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79
};
/* LISTING_END(ANCSAdvertisement): ANCS Advertisement */
/*
@section Setup
@text In the setup, the LE Security Manager is configured to accept pairing requests.
Then, the ANCS Client library is initialized and and ancs_callback registered.
Finally, the Advertisement data is set and Advertisements are started.
*/
/* LISTING_START(ANCSSetup): ANCS Setup */
void setup(void) {
Serial.begin(9600);
Serial.println("BTstack ANCS Client starting up...");
// startup BTstack and configure log_info/log_error
BTstack.setup();
sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
sm_set_authentication_requirements(SM_AUTHREQ_BONDING);
// setup ANCS Client
ancs_client_init();
ancs_client_register_callback(&ancs_callback);
// enable advertisements
BTstack.setAdvData(sizeof(adv_data), adv_data);
BTstack.startAdvertising();
}
/* LISTING_END(ANCSSetup): ANCS Setup */
void loop(void) {
BTstack.loop();
}
/*
@section ANCS Callback
@text In the ANCS Callback, connect and disconnect events are received.
For actual notifications, ancs_client_attribute_name_for_id allows to
look up the name. To get the notification body, e.g., the actual message,
the GATT Client needs to be used directly.
*/
/* LISTING_START(ANCSCallback): ANCS Callback */
void ancs_callback(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
(void) packet_type;
(void) channel;
(void) size;
const char * attribute_name;
if (hci_event_packet_get_type(packet) != HCI_EVENT_ANCS_META) {
return;
}
switch (hci_event_ancs_meta_get_subevent_code(packet)) {
case ANCS_SUBEVENT_CLIENT_CONNECTED:
Serial.println("ANCS Client: Connected");
break;
case ANCS_SUBEVENT_CLIENT_DISCONNECTED:
Serial.println("ANCS Client: Disconnected");
break;
case ANCS_SUBEVENT_CLIENT_NOTIFICATION:
attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet));
if (!attribute_name) {
break;
}
Serial.print("Notification: ");
Serial.print(attribute_name);
Serial.print(" - ");
Serial.println(ancs_subevent_client_notification_get_text(packet));
break;
default:
break;
}
}
/* LISTING_END(ANCSCallback): ANCS Callback */
@@ -0,0 +1,328 @@
#include <BTstack.h>
#include <SPI.h>
/*
EXAMPLE_START(LECentral): LE Central
@text Compared with the other examples, the LE Central is
a bit more complex. This is because it performs multiple
steps in sequence as it is common with GATT Client APIs.
It shows how to first scan for other
devices and then connect to one. When connected, a series of
GATT Client operations are performed: first the list of
GATT Services is queried. If a particular service is found,
the list of its GATT Characteristics is retrieved and a set
of known Characteristics are cached for later access.
*/
/*
@section Characteristic Summary
@text As multiple Characteristics need to be found, a custom
struct is used to collect all information about it. This allows
to define the list of necessary characteristics in the
characteristics[] array
*/
/* LISTING_START(LECentralSummary): Characteristic Summary */
// BLE Shield Service V2 incl. used Characteristics
UUID bleShieldServiceV2UUID("B8E06067-62AD-41BA-9231-206AE80AB550");
typedef struct characteristic_summary {
UUID uuid;
const char * name;
bool found;
BLECharacteristic characteristic;
} characteristic_summary_t;
typedef enum characteristicIDs {
charRX = 0,
charTX,
charBaud,
charBdAddr,
numCharacteristics /* last one */
} characteristicIDs_t;
characteristic_summary characteristics[] = {
{ UUID("f897177b-aee8-4767-8ecc-cc694fd5fcee"), "RX", false, BLECharacteristic() },
{ UUID("bf45e40a-de2a-4bc8-bba0-e5d6065f1b4b"), "TX", false, BLECharacteristic() },
{ UUID("2fbc0f31-726a-4014-b9fe-c8be0652e982"), "Baudrate", false, BLECharacteristic() },
{ UUID("65c228da-bad1-4f41-b55f-3d177f4e2196"), "BD ADDR", false, BLECharacteristic() }
};
/* LISTING_END(LECentralSummary): Characteristic Summary */
// Application state
BLEDevice myBLEDevice;
BLEService myBLEService;
bool serviceFound;
bool sendCounter = false;
int counter = 0;
char counterString[20];
// static btstack_timer_source_t heartbeat;
/*
@section Setup
@text In the setup, various callbacks are registered. After that
we start scanning for other devices
*/
/* LISTING_START(LECentralSetup): LE Central Setup */
void setup(void) {
Serial.begin(9600);
BTstack.setBLEAdvertisementCallback(advertisementCallback);
BTstack.setBLEDeviceConnectedCallback(deviceConnectedCallback);
BTstack.setBLEDeviceDisconnectedCallback(deviceDisconnectedCallback);
BTstack.setGATTServiceDiscoveredCallback(gattServiceDiscovered);
BTstack.setGATTCharacteristicDiscoveredCallback(gattCharacteristicDiscovered);
BTstack.setGATTCharacteristicNotificationCallback(gattCharacteristicNotification);
BTstack.setGATTCharacteristicReadCallback(gattReadCallback);
BTstack.setGATTCharacteristicWrittenCallback(gattWrittenCallback);
BTstack.setGATTCharacteristicSubscribedCallback(gattSubscribedCallback);
BTstack.setup();
BTstack.bleStartScanning();
}
/* LISTING_END(LECentralSetup): LE Central Setup */
/*
@section Loop
@text In the standard Arduino loop() function, BTstack's loop() is called first
If we're connected, we send the string "BTstack" plus a counter as fast as possible.
As the Bluetooth module might be busy, it's important to check the result of the
writeCharacteristicWithoutResponse() call. If it's not ok, we just try again in the
next loop iteration.
*/
/* LISTING_START(LECentralLoop): Loop */
void loop(void) {
BTstack.loop();
// send counter as fast as possible
if (sendCounter) {
sprintf(counterString, "BTstack %u\n", counter);
int result = myBLEDevice.writeCharacteristicWithoutResponse(&characteristics[charTX].characteristic, (uint8_t*) counterString, strlen(counterString));
if (result == 0) {
Serial.print("Wrote without response: ");
Serial.println(counterString);
counter++;
}
}
}
/* LISTING_END(LECentralLoop): Loop */
/*
@section Advertisement Callback
@text When an Advertisement is received, we check if it contains
the UUID of the service we're interested in. Only a single service
with a 128-bit UUID can be contained in and Advertisement and not
all BLE devices provides this. Other options are to match on the
reported device name or the BD ADDR prefix.
If we found an interesting device, we try to connect to it.
*/
/* LISTING_START(LECentralAdvertisementCallback): Advertisement Callback */
void advertisementCallback(BLEAdvertisement *bleAdvertisement) {
Serial.print("Device discovered: ");
Serial.print(bleAdvertisement->getBdAddr()->getAddressString());
Serial.print(", RSSI: ");
Serial.println(bleAdvertisement->getRssi());
if (bleAdvertisement->containsService(&bleShieldServiceV2UUID)) {
Serial.println("\nBLE ShieldService V2 found!\n");
BTstack.bleStopScanning();
BTstack.bleConnect(bleAdvertisement, 10000); // 10 s
}
}
/* LISTING_END(LECentralAdvertisementCallback): Advertisement Callback */
/*
@section Device Connected Callback
@text At the end of bleConnect(), the device connected callback is callec.
The status argument tells if the connection timed out, or if the connection
was established successfully.
On a successful connection, a GATT Service Discovery is started.
*/
/* LISTING_START(LECentralDeviceConnectedCallback): Device Connected Callback */
void deviceConnectedCallback(BLEStatus status, BLEDevice *device) {
switch (status) {
case BLE_STATUS_OK:
Serial.println("Device connected!");
myBLEDevice = *device;
counter = 0;
myBLEDevice.discoverGATTServices();
break;
case BLE_STATUS_CONNECTION_TIMEOUT:
Serial.println("Error while Connecting the Peripheral");
BTstack.bleStartScanning();
break;
default:
break;
}
}
/* LISTING_END(LECentralDeviceConnectedCallback): Device Connected Callback */
/*
@section Device Disconnected Callback
@text If the connection to a device breaks, the device disconnected callback
is called. Here, we start scanning for new devices again.
*/
/* LISTING_START(LECentralDeviceDisconnectedCallback): Device Disconnected Callback */
void deviceDisconnectedCallback(BLEDevice * device) {
(void) device;
Serial.println("Disconnected, starting over..");
sendCounter = false;
BTstack.bleStartScanning();
}
/* LISTING_END(LECentralDeviceDisconnectedCallback): Device Disconnected Callback */
/*
@section Service Discovered Callback
@text The service discovered callback is called for each service and after the
service discovery is complete. The status argument is provided for this.
The main information about a discovered Service is its UUID.
If we find our service, we store the reference to this service.
This allows to discover the Characteristics for our service after
the service discovery is complete.
*/
/* LISTING_START(LECentralServiceDiscoveredCallback): Service Discovered Callback */
void gattServiceDiscovered(BLEStatus status, BLEDevice *device, BLEService *bleService) {
switch (status) {
case BLE_STATUS_OK:
Serial.print("Service Discovered: :");
Serial.println(bleService->getUUID()->getUuidString());
if (bleService->matches(&bleShieldServiceV2UUID)) {
serviceFound = true;
Serial.println("Our service located!");
myBLEService = *bleService;
}
break;
case BLE_STATUS_DONE:
Serial.println("Service discovery finished");
if (serviceFound) {
device->discoverCharacteristicsForService(&myBLEService);
}
break;
default:
Serial.println("Service discovery error");
break;
}
}
/* LISTING_END(LECentralServiceDiscoveredCallback): Service Discovered Callback */
/*
@section Characteristic Discovered Callback
@text Similar to the Service Discovered callback, the Characteristic Discovered
callback is called for each Characteristic found and after the discovery is complete.
The main information is again its UUID. If we find a Characteristic that we're
interested in, it's name is printed and a reference stored for later.
On discovery complete, we subscribe to a particular Characteristic to receive
Characteristic Value updates in the Notificaation Callback.
*/
/* LISTING_START(LECentralCharacteristicDiscoveredCallback): Characteristic Discovered Callback */
void gattCharacteristicDiscovered(BLEStatus status, BLEDevice *device, BLECharacteristic *characteristic) {
switch (status) {
case BLE_STATUS_OK:
Serial.print("Characteristic Discovered: ");
Serial.print(characteristic->getUUID()->getUuidString());
Serial.print(", handle 0x");
Serial.println(characteristic->getCharacteristic()->value_handle, HEX);
int i;
for (i = 0; i < numCharacteristics; i++) {
if (characteristic->matches(&characteristics[i].uuid)) {
Serial.print("Characteristic found: ");
Serial.println(characteristics[i].name);
characteristics[i].found = 1;
characteristics[i].characteristic = *characteristic;
break;
}
}
break;
case BLE_STATUS_DONE:
Serial.print("Characteristic discovery finished, status ");
Serial.println(status, HEX);
if (characteristics[charRX].found) {
device->subscribeForNotifications(&characteristics[charRX].characteristic);
}
break;
default:
Serial.println("Characteristics discovery error");
break;
}
}
/* LISTING_END(LECentralCharacteristicDiscoveredCallback): Characteristic Discovered Callback */
/*
@section Subscribed Callback
@text After the subscribe operation is complete, we get notified if it was
successful. In this example, we read the Characteristic that contains the
BD ADDR of the other device. This isn't strictly necessary as we already
know the device address from the Advertisement, but it's a common pattern
with iOS as the device address is hidden from applications.
*/
/* LISTING_START(LECentralSubscribedCallback): Subscribed Callback */
void gattSubscribedCallback(BLEStatus status, BLEDevice * device) {
(void) status;
device->readCharacteristic(&characteristics[charBdAddr].characteristic);
}
/* LISTING_END(LECentralSubscribedCallback): Subscribed Callback */
/*
@section Read Callback
@text The Read callback is called with the result from a read operation.
Here, we write to the TX Characteristic next.
*/
/* LISTING_START(LECentralReadCallback): Read Callback */
void gattReadCallback(BLEStatus status, BLEDevice *device, uint8_t *value, uint16_t length) {
(void) status;
(void) length;
Serial.print("Read callback: ");
Serial.println((const char *)value);
device->writeCharacteristic(&characteristics[charTX].characteristic, (uint8_t*) "Hello!", 6);
}
/* LISTING_END(LECentralReadCallback): Read Callback */
/*
@section Written Callback
@text After the write operation is complete, the Written Callback is callbed with
the result in the status argument. As we're done with the initial setup of the remote
device, we set the flag to write the test string as fast as possible.
*/
/* LISTING_START(LECentralWrittenCallback): Written Callback */
void gattWrittenCallback(BLEStatus status, BLEDevice *device) {
(void) status;
(void) device;
sendCounter = true;
}
/* LISTING_END(LECentralWrittenCallback): Written Callback */
/*
@section Notification Callback
@text Notifications for Characteristic Value Updates are delivered via the
Notification Callback. When more than one Characteristic is subscribed,
the value handle can be used to distinguish between them. The
BLECharacteristic.isValueHandle(int handle) allows to test if a value handle
belongs to a particular Characteristic.
*/
/* LISTING_START(LECentralNotificationCallback): Notification Callback */
void gattCharacteristicNotification(BLEDevice *device, uint16_t value_handle, uint8_t *value, uint16_t length) {
(void) device;
(void) value_handle;
(void) length;
Serial.print("Notification: ");
Serial.println((const char *)value);
}
/* LISTING_END(LECentralNotificationCallback): Notification Callback */
@@ -0,0 +1,120 @@
// LE Peripheral Example - not working yet
#include <BTstack.h>
#include <SPI.h>
/*
EXAMPLE_START(LEPeripheral): LE Peripheral
@text BTstack allows to setup a GATT Services and Characteristics directly
from the setup function without using other tools outside of the Arduino IDE.
@section Setup
@text First, a number of callbacks are set. Then, a Service with a Read-only
Characteristic and a dynamic Characteristic is added to the GATT database.
In BTstack, a dynamic Characteristic is a Characteristic where reads and writes
are forwarded to the Sketch. In this example, the dynamic Characteristic is
provided by the single byte variable characteristic_data.
*/
/* LISTING_START(LEPeripheralSetup): Setup */
static char characteristic_data = 'H';
void setup(void) {
Serial.begin(9600);
// set callbacks
BTstack.setBLEDeviceConnectedCallback(deviceConnectedCallback);
BTstack.setBLEDeviceDisconnectedCallback(deviceDisconnectedCallback);
BTstack.setGATTCharacteristicRead(gattReadCallback);
BTstack.setGATTCharacteristicWrite(gattWriteCallback);
// setup GATT Database
BTstack.addGATTService(new UUID("B8E06067-62AD-41BA-9231-206AE80AB551"));
BTstack.addGATTCharacteristic(new UUID("f897177b-aee8-4767-8ecc-cc694fd5fcef"), ATT_PROPERTY_READ, "This is a String!");
BTstack.addGATTCharacteristicDynamic(new UUID("f897177b-aee8-4767-8ecc-cc694fd5fce0"), ATT_PROPERTY_READ | ATT_PROPERTY_WRITE | ATT_PROPERTY_NOTIFY, 0);
// startup Bluetooth and activate advertisements
BTstack.setup();
BTstack.startAdvertising();
}
/* LISTING_END(LEPeripheralSetup): Setup */
void loop(void) {
BTstack.loop();
}
/*
@section Device Connected Callback
@text When a remove device connects, device connected callback is callec.
*/
/* LISTING_START(LEPeripheralDeviceConnectedCallback): Device Connected Callback */
void deviceConnectedCallback(BLEStatus status, BLEDevice *device) {
(void) device;
switch (status) {
case BLE_STATUS_OK:
Serial.println("Device connected!");
break;
default:
break;
}
}
/* LISTING_END(LEPeripheralDeviceConnectedCallback): Device Connected Callback */
/*
@section Device Disconnected Callback
@text If the connection to a device breaks, the device disconnected callback
is called.
*/
/* LISTING_START(LEPeripheralDeviceDisconnectedCallback): Device Disconnected Callback */
void deviceDisconnectedCallback(BLEDevice * device) {
(void) device;
Serial.println("Disconnected.");
}
/* LISTING_END(LEPeripheralDeviceDisconnectedCallback): Device Disconnected Callback */
/*
@section Read Callback
@text In BTstack, the Read Callback is first called to query the size of the
Characteristic Value, before it is called to provide the data.
Both times, the size has to be returned. The data is only stored in the provided
buffer, if the buffer argeument is not NULL.
If more than one dynamic Characteristics is used, the value handle is used
to distinguish them.
*/
/* LISTING_START(LEPeripheralReadCallback): Read Callback */
uint16_t gattReadCallback(uint16_t value_handle, uint8_t * buffer, uint16_t buffer_size) {
(void) value_handle;
(void) buffer_size;
if (buffer) {
Serial.print("gattReadCallback, value: ");
Serial.println(characteristic_data, HEX);
buffer[0] = characteristic_data;
}
return 1;
}
/* LISTING_END(LEPeripheralDeviceDisconnectedCallback): Read Callback */
/*
@section Write Callback
@text When the remove device writes a Characteristic Value, the Write callback
is called. The buffer arguments points to the data of size size/
If more than one dynamic Characteristics is used, the value handle is used
to distinguish them.
*/
/* LISTING_START(LEPeripheralWriteCallback): Write Callback */
int gattWriteCallback(uint16_t value_handle, uint8_t *buffer, uint16_t size) {
(void) value_handle;
(void) size;
characteristic_data = buffer[0];
Serial.print("gattWriteCallback , value ");
Serial.println(characteristic_data, HEX);
return 0;
}
/* LISTING_END(LEPeripheralWriteCallback): Write Callback */
@@ -0,0 +1,25 @@
#include <BTstack.h>
#include <stdio.h>
#include <SPI.h>
/* EXAMPLE_START(iBeacon): iBeacon Simulator
@section Setup
@text After BTstack.setup(), iBeaconConfigure() configures BTstack
to send out iBeacons Advertisements with the provided Major ID,
Minor ID and UUID.
*/
/* LISTING_START(iBeaconSetup): iBeacon Setup */
UUID uuid("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0");
void setup(void) {
Serial.begin(9600);
BTstack.setup();
BTstack.iBeaconConfigure(&uuid, 4711, 2);
BTstack.startAdvertising();
}
/* LISTING_END(iBeaconSetup) */
void loop(void) {
BTstack.loop();
}
@@ -0,0 +1,59 @@
#include <BTstack.h>
#include <SPI.h>
/* EXAMPLE_START(iBeaconScanner): iBeacon Scanner
@section Setup
@text After BTstack.setup(), BTstack is configured to call
advertisementCallback whenever an Advertisement was received.
Then, a device discovery is started
*/
/* LISTING_START(iBeaconSetup): iBeacon Scanner Setup */
void setup(void) {
Serial.begin(9600);
BTstack.setup();
BTstack.setBLEAdvertisementCallback(advertisementCallback);
BTstack.bleStartScanning();
}
/* LISTING_END(iBeaconSetup): iBeacon Scanner Setup */
void loop(void) {
BTstack.loop();
}
/*
@section Advertisement Callback
@text Whenever an Advertisement is received, isIBeacon() checks if
it contains an iBeacon. If yes, the Major ID, Minor ID, and UUID
is printed.
If it's not an iBeacon, only the BD_ADDR and the received signal strength
(RSSI) is shown.
*/
/* LISTING_START(iBeaconCallback): iBeacon Scanner Callback */
void advertisementCallback(BLEAdvertisement *adv) {
if (adv->isIBeacon()) {
Serial.print("iBeacon found ");
Serial.print(adv->getBdAddr()->getAddressString());
Serial.print(", RSSI ");
Serial.print(adv->getRssi());
Serial.print(", UUID ");
Serial.print(adv->getIBeaconUUID()->getUuidString());
Serial.print(", MajorID ");
Serial.print(adv->getIBeaconMajorID());
Serial.print(", MinorID ");
Serial.print(adv->getIBecaonMinorID());
Serial.print(", Measured Power ");
Serial.println(adv->getiBeaconMeasuredPower());
} else {
Serial.print("Device discovered: ");
Serial.print(adv->getBdAddr()->getAddressString());
Serial.print(", RSSI ");
Serial.println(adv->getRssi());
}
}
/* LISTING_END(iBeaconCallback): iBeacon Scanner Callback */
+100
View File
@@ -0,0 +1,100 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Library (KEYWORD3)
#######################################
BTstack KEYWORD3 RESERVED_WORD
#######################################
# Datatypes (KEYWORD1)
#######################################
BLEStatus KEYWORD2
UUID KEYWORD2
BD_ADDR_TYPE KEYWORD2
BD_ADDR KEYWORD2
BLEAdvertisement KEYWORD2
BLECharacteristic KEYWORD2
BLEService KEYWORD2
BLEDevice KEYWORD2
BTstackManager KEYWORD2
#######################################
# Methods and Functions (KEYWORD2)
#######################################
getUuidString KEYWORD2
getUuid128String KEYWORD2
getUuid KEYWORD2
matches KEYWORD2
getAddress KEYWORD2
getAddressString KEYWORD2
getAddressType KEYWORD2
getBdAddr KEYWORD2
getBdAddrType KEYWORD2
getRssi KEYWORD2
containsService KEYWORD2
nameHasPrefix KEYWORD2
getAdvData KEYWORD2
isIBeacon KEYWORD2
getIBeaconUUID KEYWORD2
getIBeaconMajorID KEYWORD2
getIBecaonMinorID KEYWORD2
getiBeaconMeasuredPower KEYWORD2
isValueHandle KEYWORD2
getCharacteristic KEYWORD2
getUUID KEYWORD2
getService KEYWORD2
getHandle KEYWORD2
discoverGATTServices KEYWORD2
discoverCharacteristicsForService KEYWORD2
readCharacteristic KEYWORD2
writeCharacteristic KEYWORD2
writeCharacteristicWithoutResponse KEYWORD2
subscribeForNotifications KEYWORD2
unsubscribeFromNotifications KEYWORD2
subscribeForIndications KEYWORD2
unsubscribeFromIndications KEYWORD2
setPublicBdAddr KEYWORD2
enablePacketLogger KEYWORD2
enableDebugLogger KEYWORD2
setAdvData KEYWORD2
iBeaconConfigure KEYWORD2
startAdvertising KEYWORD2
stopAdvertising KEYWORD2
bleStartScanning KEYWORD2
bleStopScanning KEYWORD2
bleConnect KEYWORD2
bleDisconnect KEYWORD2
setBLEAdvertisementCallback KEYWORD2
setBLEDeviceConnectedCallback KEYWORD2
setBLEDeviceDisconnectedCallback KEYWORD2
setGATTServiceDiscoveredCallback KEYWORD2
setGATTCharacteristicDiscoveredCallback KEYWORD2
setGATTCharacteristicReadCallback KEYWORD2
setGATTCharacteristicNotificationCallback KEYWORD2
setGATTCharacteristicIndicationCallback KEYWORD2
setGATTDoneCallback KEYWORD2
setGATTCharacteristicWrittenCallback KEYWORD2
setGATTCharacteristicSubscribedCallback KEYWORD2
setGATTCharacteristicUnsubscribedCallback KEYWORD2
setGATTCharacteristicRead KEYWORD2
setGATTCharacteristicWrite KEYWORD2
addGATTService KEYWORD2
addGATTCharacteristic KEYWORD2
addGATTCharacteristicDynamic KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
BLE_STATUS_OK LITERAL1
BLE_STATUS_DONE LITERAL1
BLE_STATUS_CONNECTION_TIMEOUT LITERAL1
BLE_STATUS_CONNECTION_ERROR LITERAL1
BLE_STATUS_OTHER_ERROR LITERAL1
PUBLIC_ADDRESS LITERAL1
PRIVAT_ADDRESS LITERAL1
+10
View File
@@ -0,0 +1,10 @@
name=BTstack
version=1.0
author=bluekitchen-gmbh
maintainer=Earle Philhower
sentence=BTstack Arduino library distributed with BTstack
paragraph=
category=Data Processing
url=
architectures=rp2040
dot_a_linkage=true
+907
View File
@@ -0,0 +1,907 @@
/**
Arduino Wrapper for BTstack
*/
#include <Arduino.h>
#include <SPI.h>
#ifdef __AVR__
#include <avr/wdt.h>
#endif
#if __arm__
//#include <Reset.h> // also provides NVIC_SystemReset
#endif
#include "BTstack.h"
#include "btstack_memory.h"
#include "hal_tick.h"
#include "hal_cpu.h"
#include "hci_cmd.h"
#include "btstack_util.h"
#include "btstack_run_loop.h"
#include "btstack_event.h"
#include "btstack_run_loop_embedded.h"
#include "hci_transport.h"
#include "hci_transport_h4.h"
#include "ad_parser.h"
//#include "btstack_chipset_em9301.h"
#include "btstack_debug.h"
#include "gap.h"
#include "hci.h"
#include "hci_dump.h"
#include "hci_dump_embedded_stdout.h"
#include "l2cap.h"
#include "ble/att_db.h"
#include "ble/att_server.h"
#include "ble/att_db_util.h"
#include "ble/le_device_db.h"
#include "ble/sm.h"
// Pin 13 has an LED connected on most Arduino boards.
//#define PIN_LED 13
// prototypes
extern "C" void hal_uart_dma_process(void);
enum {
SET_ADVERTISEMENT_PARAMS = 1 << 0,
SET_ADVERTISEMENT_DATA = 1 << 1,
SET_ADVERTISEMENT_ENABLED = 1 << 2,
};
typedef enum gattAction {
gattActionWrite,
gattActionSubscribe,
gattActionUnsubscribe,
gattActionServiceQuery,
gattActionCharacteristicQuery,
gattActionRead,
} gattAction_t;
static gattAction_t gattAction;
// btstack state
static int btstack_state;
static const uint8_t iBeaconAdvertisement01[] = { 0x02, 0x01 };
static const uint8_t iBeaconAdvertisement38[] = { 0x1a, 0xff, 0x4c, 0x00, 0x02, 0x15 };
static uint8_t adv_data[31];
static uint16_t adv_data_len = 0;
//static int gatt_is_characteristics_query;
static uint16_t le_peripheral_todos = 0;
static bool have_custom_addr;
static bd_addr_t public_bd_addr;
static btstack_timer_source_t connection_timer;
static void (*bleAdvertismentCallback)(BLEAdvertisement * bleAdvertisement) = NULL;
static void (*bleDeviceConnectedCallback)(BLEStatus status, BLEDevice * device) = NULL;
static void (*bleDeviceDisconnectedCallback)(BLEDevice * device) = NULL;
static void (*gattServiceDiscoveredCallback)(BLEStatus status, BLEDevice * device, BLEService * bleService) = NULL;
static void (*gattCharacteristicDiscoveredCallback)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic) = NULL;
static void (*gattCharacteristicNotificationCallback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length) = NULL;
static void (*gattCharacteristicIndicationCallback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length) = NULL;
static void (*gattCharacteristicReadCallback)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length) = NULL;
static void (*gattCharacteristicWrittenCallback)(BLEStatus status, BLEDevice * device) = NULL;
static void (*gattCharacteristicSubscribedCallback)(BLEStatus status, BLEDevice * device) = NULL;
static void (*gattCharacteristicUnsubscribedCallback)(BLEStatus status, BLEDevice * device) = NULL;
// retarget printf to Serial
#ifdef ENERGIA
extern "C" int putchar(int c) {
Serial.write((uint8_t)c);
return c;
}
#else
#ifdef __AVR__
static FILE uartout = {0} ;
static int uart_putchar(char c, FILE *stream) {
Serial.write(c);
return 0;
}
#endif
// added for Arduino Zero. Arduino Due already has tis own _write(..) implementation
// in /Users/mringwal/Library/Arduino15/packages/arduino/hardware/sam/1.6.4/cores/arduino/syscalls_sam3.c
#if defined(__SAMD21G18A__)
// #ifdef __arm__
extern "C" int _write(int file, char *ptr, int len) {
int i;
for (i = 0; i < len; i++) {
if (ptr[i] == '\n') {
Serial.write((uint8_t)'\r');
}
Serial.write((uint8_t)ptr[i]);
}
return i;
}
#endif
#endif
// HAL CPU Implementation
extern "C" void hal_cpu_disable_irqs(void) { }
extern "C" void hal_cpu_enable_irqs(void) { }
extern "C" void hal_cpu_enable_irqs_and_sleep(void) { }
//
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
(void) channel;
(void) size;
hci_con_handle_t con_handle;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (packet[0]) {
case BTSTACK_EVENT_STATE:
btstack_state = packet[2];
// bt stack activated, get started
if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING) {
le_peripheral_todos |= SET_ADVERTISEMENT_PARAMS
| SET_ADVERTISEMENT_DATA
| SET_ADVERTISEMENT_ENABLED;
bd_addr_t addr;
gap_local_bd_addr(addr);
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
}
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
if (bleDeviceDisconnectedCallback) {
con_handle = little_endian_read_16(packet, 3);
BLEDevice device(con_handle);
(*bleDeviceDisconnectedCallback)(&device);
}
le_peripheral_todos |= SET_ADVERTISEMENT_ENABLED;
break;
case GAP_EVENT_ADVERTISING_REPORT: {
if (bleAdvertismentCallback) {
BLEAdvertisement advertisement(packet);
(*bleAdvertismentCallback)(&advertisement);
}
break;
}
case HCI_EVENT_LE_META:
switch (packet[2]) {
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
con_handle = little_endian_read_16(packet, 4);
printf("Connection complete, con_handle 0x%04x\n", con_handle);
btstack_run_loop_remove_timer(&connection_timer);
if (!bleDeviceConnectedCallback) {
break;
}
if (packet[3]) {
(*bleDeviceConnectedCallback)(BLE_STATUS_CONNECTION_ERROR, NULL);
} else {
BLEDevice device(con_handle);
(*bleDeviceConnectedCallback)(BLE_STATUS_OK, &device);
}
break;
default:
break;
}
break;
}
}
}
static void extract_service(gatt_client_service_t * service, uint8_t * packet) {
service->start_group_handle = little_endian_read_16(packet, 4);
service->end_group_handle = little_endian_read_16(packet, 6);
service->uuid16 = 0;
reverse_128(&packet[8], service->uuid128);
if (uuid_has_bluetooth_prefix(service->uuid128)) {
service->uuid16 = big_endian_read_32(service->uuid128, 0);
}
}
static void extract_characteristic(gatt_client_characteristic_t * characteristic, uint8_t * packet) {
characteristic->start_handle = little_endian_read_16(packet, 4);
characteristic->value_handle = little_endian_read_16(packet, 6);
characteristic->end_handle = little_endian_read_16(packet, 8);
characteristic->properties = little_endian_read_16(packet, 10);
characteristic->uuid16 = 0;
reverse_128(&packet[12], characteristic->uuid128);
if (uuid_has_bluetooth_prefix(characteristic->uuid128)) {
characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
}
}
static void gatt_client_callback(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size) {
(void) channel;
(void) packet_type;
(void) size;
// if (hci) event is not 4-byte aligned, event->handle causes crash
// workaround: check event type, assuming GATT event types are contagious
if (packet[0] < GATT_EVENT_QUERY_COMPLETE) {
return;
}
if (packet[0] > GATT_EVENT_MTU) {
return;
}
hci_con_handle_t con_handle = little_endian_read_16(packet, 2);
uint8_t status;
uint8_t * value;
uint16_t value_handle;
uint16_t value_length;
BLEDevice device(con_handle);
switch (hci_event_packet_get_type(packet)) {
case GATT_EVENT_SERVICE_QUERY_RESULT:
if (gattServiceDiscoveredCallback) {
gatt_client_service_t service;
extract_service(&service, packet);
BLEService bleService(service);
(*gattServiceDiscoveredCallback)(BLE_STATUS_OK, &device, &bleService);
}
break;
case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
if (gattCharacteristicDiscoveredCallback) {
gatt_client_characteristic_t characteristic;
extract_characteristic(&characteristic, packet);
BLECharacteristic bleCharacteristic(characteristic);
(*gattCharacteristicDiscoveredCallback)(BLE_STATUS_OK, &device, &bleCharacteristic);
}
break;
case GATT_EVENT_QUERY_COMPLETE:
status = little_endian_read_16(packet, 4);
switch (gattAction) {
case gattActionWrite:
if (gattCharacteristicWrittenCallback) {
gattCharacteristicWrittenCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
}
break;
case gattActionSubscribe:
if (gattCharacteristicSubscribedCallback) {
gattCharacteristicSubscribedCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
}
break;
case gattActionUnsubscribe:
if (gattCharacteristicUnsubscribedCallback) {
gattCharacteristicUnsubscribedCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
}
break;
case gattActionServiceQuery:
if (gattServiceDiscoveredCallback) {
gattServiceDiscoveredCallback(BLE_STATUS_DONE, &device, NULL);
}
break;
case gattActionCharacteristicQuery:
if (gattCharacteristicDiscoveredCallback) {
gattCharacteristicDiscoveredCallback(BLE_STATUS_DONE, &device, NULL);
}
break;
default:
break;
};
break;
case GATT_EVENT_NOTIFICATION:
if (gattCharacteristicNotificationCallback) {
value_handle = little_endian_read_16(packet, 4);
value_length = little_endian_read_16(packet, 6);
value = &packet[8];
(*gattCharacteristicNotificationCallback)(&device, value_handle, value, value_length);
}
break;
case GATT_EVENT_INDICATION:
if (gattCharacteristicIndicationCallback) {
value_handle = little_endian_read_16(packet, 4);
value_length = little_endian_read_16(packet, 6);
value = &packet[8];
(*gattCharacteristicIndicationCallback)(&device, value_handle, value, value_length);
}
break;
case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
if (gattCharacteristicReadCallback) {
value_handle = little_endian_read_16(packet, 4);
value_length = little_endian_read_16(packet, 6);
value = &packet[8];
(*gattCharacteristicReadCallback)(BLE_STATUS_OK, &device, value, value_length);
}
break;
default:
break;
}
}
static void connection_timeout_handler(btstack_timer_source_t * timer) {
(void) timer;
// log_info("Cancel outgoing connection");
gap_connect_cancel();
if (!bleDeviceConnectedCallback) {
return;
}
(*bleDeviceConnectedCallback)(BLE_STATUS_CONNECTION_TIMEOUT, NULL); // page timeout 0x04
}
//
/// UUID class
UUID::UUID(void) {
memset(uuid, 0, 16);
}
UUID::UUID(const uint8_t uuid[16]) {
memcpy(this->uuid, uuid, 16);
}
UUID::UUID(const char * uuidStr) {
memset(uuid, 0, 16);
int len = strlen(uuidStr);
if (len <= 4) {
// Handle 4 Bytes HEX
unsigned int uuid16;
int result = sscanf((char *) uuidStr, "%x", &uuid16);
if (result == 1) {
uuid_add_bluetooth_prefix(uuid, uuid16);
}
return;
}
// quick UUID parser, ignoring dashes
int i = 0;
int data = 0;
int have_nibble = 0;
while (*uuidStr && i < 16) {
const char c = *uuidStr++;
if (c == '-') {
continue;
}
data = data << 4 | nibble_for_char(c);
if (!have_nibble) {
have_nibble = 1;
continue;
}
uuid[i++] = data;
data = 0;
have_nibble = 0;
}
}
const uint8_t * UUID::getUuid(void) const {
return uuid;
}
static char uuid16_buffer[5];
const char * UUID::getUuidString() const {
// TODO: fix uuid_has_bluetooth_prefix call to use const
if (uuid_has_bluetooth_prefix((uint8_t*)uuid)) {
sprintf(uuid16_buffer, "%04x", (uint16_t) big_endian_read_32(uuid, 0));
return uuid16_buffer;
} else {
// TODO: fix uuid128_to_str
return uuid128_to_str((uint8_t*)uuid);
}
}
const char * UUID::getUuid128String() const {
return uuid128_to_str((uint8_t*)uuid);
}
bool UUID::matches(UUID *other) const {
return memcmp(this->uuid, other->uuid, 16) == 0;
}
// BD_ADDR class
BD_ADDR::BD_ADDR(void) {
}
BD_ADDR::BD_ADDR(const char * address_string, BD_ADDR_TYPE address_type) : address_type(address_type) {
(void) address_string;
// TODO: implement
// log_error("BD_ADDR::BD_ADDR(const char *, BD_ADDR_TYPE) not implemented yet!");
}
BD_ADDR::BD_ADDR(const uint8_t address[6], BD_ADDR_TYPE address_type) : address_type(address_type) {
memcpy(this->address, address, 6);
}
const uint8_t * BD_ADDR::getAddress(void) {
return address;
}
const char * BD_ADDR::getAddressString(void) {
return bd_addr_to_str(address);
}
BD_ADDR_TYPE BD_ADDR::getAddressType(void) {
return address_type;
}
BLEAdvertisement::BLEAdvertisement(uint8_t * event_packet) :
advertising_event_type(event_packet[2]),
rssi(event_packet[10]),
data_length(event_packet[11]),
iBeacon_UUID(NULL) {
bd_addr_t addr;
reverse_bd_addr(&event_packet[4], addr);
bd_addr = BD_ADDR(addr, (BD_ADDR_TYPE)event_packet[3]);
memcpy(data, &event_packet[12], LE_ADVERTISING_DATA_SIZE);
}
BLEAdvertisement::~BLEAdvertisement() {
if (iBeacon_UUID) {
delete (iBeacon_UUID);
}
}
const uint8_t * BLEAdvertisement::getAdvData(void) {
return data;
}
BD_ADDR * BLEAdvertisement::getBdAddr(void) {
return &bd_addr;
}
int BLEAdvertisement::getRssi(void) {
return rssi > 127 ? rssi - 256 : rssi;
}
bool BLEAdvertisement::containsService(UUID * service) {
return ad_data_contains_uuid128(data_length, data, (uint8_t*) service->getUuid());
}
bool BLEAdvertisement::nameHasPrefix(const char * name_prefix) {
ad_context_t context;
int name_prefix_len = strlen(name_prefix);
for (ad_iterator_init(&context, data_length, data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)) {
uint8_t data_type = ad_iterator_get_data_type(&context);
uint8_t data_len = ad_iterator_get_data_len(&context);
const uint8_t * data = ad_iterator_get_data(&context);
int compare_len = name_prefix_len;
switch (data_type) {
case 8: // shortented local name
case 9: // complete local name
if (compare_len > data_len) {
compare_len = data_len;
}
if (strncmp(name_prefix, (const char*) data, compare_len) == 0) {
return true;
}
break;
default:
break;
}
}
return false;
};
bool BLEAdvertisement::isIBeacon(void) {
return ((memcmp(iBeaconAdvertisement01, data, sizeof(iBeaconAdvertisement01)) == 0)
&& (memcmp(iBeaconAdvertisement38, &data[3], sizeof(iBeaconAdvertisement38)) == 0));
}
const UUID * BLEAdvertisement::getIBeaconUUID(void) {
if (!iBeacon_UUID) {
iBeacon_UUID = new UUID(&data[9]);
}
return iBeacon_UUID;
};
uint16_t BLEAdvertisement::getIBeaconMajorID(void) {
return big_endian_read_16(data, 25);
};
uint16_t BLEAdvertisement::getIBecaonMinorID(void) {
return big_endian_read_16(data, 27);
};
uint8_t BLEAdvertisement::getiBeaconMeasuredPower(void) {
return data[29];
}
BLECharacteristic::BLECharacteristic(void) {
}
BLECharacteristic::BLECharacteristic(gatt_client_characteristic_t characteristic)
: characteristic(characteristic), uuid(characteristic.uuid128) {
}
const UUID * BLECharacteristic::getUUID(void) {
return &uuid;
}
bool BLECharacteristic::matches(UUID * uuid) {
return this->uuid.matches(uuid);
}
bool BLECharacteristic::isValueHandle(uint16_t value_handle) {
return characteristic.value_handle == value_handle;
}
const gatt_client_characteristic_t * BLECharacteristic::getCharacteristic(void) {
return &characteristic;
}
BLEService::BLEService(void) {
}
BLEService::BLEService(gatt_client_service_t service)
: service(service), uuid(service.uuid128) {
}
const UUID * BLEService::getUUID(void) {
return &uuid;
}
bool BLEService::matches(UUID * uuid) {
return this->uuid.matches(uuid);
}
const gatt_client_service_t * BLEService::getService(void) {
return &service;
}
// discovery of services and characteristics
BLEDevice::BLEDevice(void) {
}
BLEDevice::BLEDevice(hci_con_handle_t handle)
: handle(handle) {
}
uint16_t BLEDevice::getHandle(void) {
return handle;
}
int BLEDevice::discoverGATTServices(void) {
return BTstack.discoverGATTServices(this);
}
int BLEDevice::discoverCharacteristicsForService(BLEService * service) {
return BTstack.discoverCharacteristicsForService(this, service);
}
int BLEDevice::readCharacteristic(BLECharacteristic * characteristic) {
return BTstack.readCharacteristic(this, characteristic);
}
int BLEDevice::writeCharacteristic(BLECharacteristic * characteristic, uint8_t * data, uint16_t size) {
return BTstack.writeCharacteristic(this, characteristic, data, size);
}
int BLEDevice::writeCharacteristicWithoutResponse(BLECharacteristic * characteristic, uint8_t * data, uint16_t size) {
return BTstack.writeCharacteristicWithoutResponse(this, characteristic, data, size);
}
int BLEDevice::subscribeForNotifications(BLECharacteristic * characteristic) {
return BTstack.subscribeForNotifications(this, characteristic);
}
int BLEDevice::unsubscribeFromNotifications(BLECharacteristic * characteristic) {
return BTstack.unsubscribeFromNotifications(this, characteristic);
}
int BLEDevice::subscribeForIndications(BLECharacteristic * characteristic) {
return BTstack.subscribeForIndications(this, characteristic);
}
int BLEDevice::unsubscribeFromIndications(BLECharacteristic * characteristic) {
return BTstack.unsubscribeFromIndications(this, characteristic);
}
static uint16_t (*gattReadCallback)(uint16_t characteristic_id, uint8_t * buffer, uint16_t buffer_size);
static int (*gattWriteCallback)(uint16_t characteristic_id, uint8_t *buffer, uint16_t buffer_size);
// ATT Client Read Callback for Dynamic Data
// - if buffer == NULL, don't copy data, just return size of value
// - if buffer != NULL, copy data and return number bytes copied
// @param offset defines start of attribute value
static uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size) {
(void) con_handle;
(void) offset;
if (gattReadCallback) {
return gattReadCallback(att_handle, buffer, buffer_size);
}
return 0;
}
/* LISTING_END */
/*
@section ATT Write
@text The only valid ATT write in this example is to the Client Characteristic Configuration, which configures notification
and indication. If the ATT handle matches the client configuration handle, the new configuration value is stored and used
in the heartbeat handler to decide if a new value should be sent. See Listing attWrite.
*/
/* LISTING_START(attWrite): ATT Write */
static int att_write_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) {
(void) con_handle;
(void) transaction_mode;
(void) offset;
if (gattWriteCallback) {
gattWriteCallback(att_handle, buffer, buffer_size);
}
return 0;
}
BTstackManager::BTstackManager(void) {
// client_packet_handler = NULL;
have_custom_addr = false;
// reset handler
bleAdvertismentCallback = NULL;
bleDeviceConnectedCallback = NULL;
bleDeviceDisconnectedCallback = NULL;
gattServiceDiscoveredCallback = NULL;
gattCharacteristicDiscoveredCallback = NULL;
gattCharacteristicNotificationCallback = NULL;
att_db_util_init();
// disable LOG_INFO messages
hci_dump_enable_log_level(HCI_DUMP_LOG_LEVEL_INFO, 0);
#ifdef __AVR__
// configure stdout to go via Serial
fdev_setup_stream(&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
stdout = &uartout;
#endif
}
void BTstackManager::setBLEAdvertisementCallback(void (*callback)(BLEAdvertisement * bleAdvertisement)) {
bleAdvertismentCallback = callback;
}
void BTstackManager::setBLEDeviceConnectedCallback(void (*callback)(BLEStatus status, BLEDevice * device)) {
bleDeviceConnectedCallback = callback;
}
void BTstackManager::setBLEDeviceDisconnectedCallback(void (*callback)(BLEDevice * device)) {
bleDeviceDisconnectedCallback = callback;
}
void BTstackManager::setGATTServiceDiscoveredCallback(void (*callback)(BLEStatus status, BLEDevice * device, BLEService * bleService)) {
gattServiceDiscoveredCallback = callback;
}
void BTstackManager::setGATTCharacteristicDiscoveredCallback(void (*callback)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic)) {
gattCharacteristicDiscoveredCallback = callback;
}
void BTstackManager::setGATTCharacteristicNotificationCallback(void (*callback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)) {
gattCharacteristicNotificationCallback = callback;
}
void BTstackManager::setGATTCharacteristicIndicationCallback(void (*callback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)) {
gattCharacteristicIndicationCallback = callback;
}
void BTstackManager::setGATTCharacteristicReadCallback(void (*callback)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length)) {
gattCharacteristicReadCallback = callback;
}
void BTstackManager::setGATTCharacteristicWrittenCallback(void (*callback)(BLEStatus status, BLEDevice * device)) {
gattCharacteristicWrittenCallback = callback;
}
void BTstackManager::setGATTCharacteristicSubscribedCallback(void (*callback)(BLEStatus status, BLEDevice * device)) {
gattCharacteristicSubscribedCallback = callback;
}
void BTstackManager::setGATTCharacteristicUnsubscribedCallback(void (*callback)(BLEStatus status, BLEDevice * device)) {
gattCharacteristicUnsubscribedCallback = callback;
}
int BTstackManager::discoverGATTServices(BLEDevice * device) {
gattAction = gattActionServiceQuery;
return gatt_client_discover_primary_services(gatt_client_callback, device->getHandle());
}
int BTstackManager::discoverCharacteristicsForService(BLEDevice * device, BLEService * service) {
gattAction = gattActionCharacteristicQuery;
return gatt_client_discover_characteristics_for_service(gatt_client_callback, device->getHandle(), (gatt_client_service_t*) service->getService());
}
int BTstackManager::readCharacteristic(BLEDevice * device, BLECharacteristic * characteristic) {
return gatt_client_read_value_of_characteristic(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic());
}
int BTstackManager::writeCharacteristic(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size) {
gattAction = gattActionWrite;
return gatt_client_write_value_of_characteristic(gatt_client_callback, device->getHandle(), characteristic->getCharacteristic()->value_handle,
size, data);
}
int BTstackManager::writeCharacteristicWithoutResponse(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size) {
return gatt_client_write_value_of_characteristic_without_response(device->getHandle(), characteristic->getCharacteristic()->value_handle,
size, data);
}
int BTstackManager::subscribeForNotifications(BLEDevice * device, BLECharacteristic * characteristic) {
gattAction = gattActionSubscribe;
return gatt_client_write_client_characteristic_configuration(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(),
GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
}
int BTstackManager::subscribeForIndications(BLEDevice * device, BLECharacteristic * characteristic) {
gattAction = gattActionSubscribe;
return gatt_client_write_client_characteristic_configuration(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(),
GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION);
}
int BTstackManager::unsubscribeFromNotifications(BLEDevice * device, BLECharacteristic * characteristic) {
gattAction = gattActionUnsubscribe;
return gatt_client_write_client_characteristic_configuration(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(),
GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE);
}
int BTstackManager::unsubscribeFromIndications(BLEDevice * device, BLECharacteristic * characteristic) {
gattAction = gattActionUnsubscribe;
return gatt_client_write_client_characteristic_configuration(gatt_client_callback, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(),
GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE);
}
void BTstackManager::bleConnect(BLEAdvertisement * advertisement, int timeout_ms) {
bleConnect(advertisement->getBdAddr(), timeout_ms);
}
void BTstackManager::bleConnect(BD_ADDR * address, int timeout_ms) {
bleConnect(address->getAddressType(), address->getAddress(), timeout_ms);
}
void BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms) {
(void) address_type;
(void) address;
(void) timeout_ms;
// TODO: implement
// log_error("BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms) not implemented");
}
void BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const uint8_t address[6], int timeout_ms) {
gap_connect((uint8_t*)address, (bd_addr_type_t) address_type);
if (!timeout_ms) {
return;
}
btstack_run_loop_set_timer(&connection_timer, timeout_ms);
btstack_run_loop_set_timer_handler(&connection_timer, connection_timeout_handler);
btstack_run_loop_add_timer(&connection_timer);
}
void BTstackManager::bleDisconnect(BLEDevice * device) {
btstack_run_loop_remove_timer(&connection_timer);
gap_disconnect(device->getHandle());
}
void BTstackManager::setPublicBdAddr(bd_addr_t addr) {
have_custom_addr = true;
memcpy(public_bd_addr, addr, 6);
}
void bluetooth_hardware_error(uint8_t error) {
printf("Bluetooth Hardware Error event 0x%02x. Restarting...\n\n\n", error);
#ifdef __AVR__
wdt_enable(WDTO_15MS);
// wait for watchdog to trigger
#endif
#ifdef __arm__
// NVIC_SystemReset();
#endif
while (1);
}
#if 0
static hci_transport_config_uart_t config = {
HCI_TRANSPORT_CONFIG_UART,
115200,
0, // main baudrate
1, // flow control
NULL,
};
#endif
static btstack_packet_callback_registration_t hci_event_callback_registration;
void BTstackManager::setup(void) {
//#ifdef PIN_LED
// pinMode(PIN_LED, OUTPUT);
//#endif
// printf("BTstackManager::setup()\n");
#if 0
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
const hci_transport_t * transport = hci_transport_h4_instance(btstack_uart_block_embedded_instance());
hci_init(transport, (void*) &config);
hci_set_chipset(btstack_chipset_em9301_instance());
if (have_custom_addr) {
hci_set_bd_addr(public_bd_addr);
}
hci_set_hardware_error_callback(&bluetooth_hardware_error);
#endif
// inform about BTstack state
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
l2cap_init();
// setup central device db
le_device_db_init();
sm_init();
att_server_init(att_db_util_get_address(), att_read_callback, att_write_callback);
gatt_client_init();
// setup advertisements params
uint16_t adv_int_min = 0x0030;
uint16_t adv_int_max = 0x0030;
uint8_t adv_type = 0;
bd_addr_t null_addr;
memset(null_addr, 0, 6);
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
// setup advertisements data
int pos = 0;
const uint8_t flags[] = { 0x02, 0x01, 0x02 };
memcpy(&adv_data[pos], flags, sizeof(flags));
pos += sizeof(flags);
const char * name = "BTstack LE Shield";
adv_data[pos++] = strlen(name) + 1;
adv_data[pos++] = 0x09;
memcpy(&adv_data[pos], name, strlen(name));
pos += strlen(name);
adv_data_len = pos;
gap_advertisements_set_data(adv_data_len, adv_data);
// turn on!
btstack_state = 0;
hci_power_control(HCI_POWER_ON);
}
void BTstackManager::enablePacketLogger(void) {
hci_dump_init(hci_dump_embedded_stdout_get_instance());
}
void BTstackManager::enableDebugLogger() {
// enable LOG_INFO messages
hci_dump_enable_log_level(HCI_DUMP_LOG_LEVEL_INFO, 1);
}
void BTstackManager::loop(void) {
// process data from/to Bluetooth module
// hal_uart_dma_process();
// BTstack Run Loop
// btstack_run_loop_embedded_execute_once();
}
void BTstackManager::bleStartScanning(void) {
// printf("Start scanning\n");
gap_start_scan();
}
void BTstackManager::bleStopScanning(void) {
gap_stop_scan();
}
void BTstackManager::setGATTCharacteristicRead(uint16_t (*cb)(uint16_t characteristic_id, uint8_t * buffer, uint16_t buffer_size)) {
gattReadCallback = cb;
}
void BTstackManager::setGATTCharacteristicWrite(int (*cb)(uint16_t characteristic_id, uint8_t *buffer, uint16_t buffer_size)) {
gattWriteCallback = cb;
}
void BTstackManager::addGATTService(UUID * uuid) {
att_db_util_add_service_uuid128((uint8_t*)uuid->getUuid());
}
uint16_t BTstackManager::addGATTCharacteristic(UUID * uuid, uint16_t flags, const char * text) {
return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags, ATT_SECURITY_NONE, ATT_SECURITY_NONE, (uint8_t*)text, strlen(text));
}
uint16_t BTstackManager::addGATTCharacteristic(UUID * uuid, uint16_t flags, uint8_t * data, uint16_t data_len) {
return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags, ATT_SECURITY_NONE, ATT_SECURITY_NONE, data, data_len);
}
uint16_t BTstackManager::addGATTCharacteristicDynamic(UUID * uuid, uint16_t flags, uint16_t characteristic_id) {
(void) characteristic_id;
return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_NONE, ATT_SECURITY_NONE, NULL, 0);
}
void BTstackManager::setAdvData(uint16_t adv_data_len, const uint8_t * adv_data) {
gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
}
void BTstackManager::startAdvertising() {
gap_advertisements_enable(1);
}
void BTstackManager::stopAdvertising() {
gap_advertisements_enable(0);
}
void BTstackManager::iBeaconConfigure(UUID * uuid, uint16_t major_id, uint16_t minor_id, uint8_t measured_power) {
memcpy(adv_data, iBeaconAdvertisement01, sizeof(iBeaconAdvertisement01));
adv_data[2] = 0x06;
memcpy(&adv_data[3], iBeaconAdvertisement38, sizeof(iBeaconAdvertisement38));
memcpy(&adv_data[9], uuid->getUuid(), 16);
big_endian_store_16(adv_data, 25, major_id);
big_endian_store_16(adv_data, 27, minor_id);
adv_data[29] = measured_power;
adv_data_len = 30;
gap_advertisements_set_data(adv_data_len, adv_data);
}
// 02 01 06 1A FF 4C 00 02 15 -- F8 97 17 7B AE E8 47 67 8E CC CC 69 4F D5 FC EE -- 12 67 00 02 00 00
// 02 01 06 1a ff 4c 00 02 15 -- FB 0B 57 A2 82 28 44 CD 91 3A 94 A1 22 BA 12 06 -- 00 01 00 02 D1 00
BTstackManager BTstack;
+201
View File
@@ -0,0 +1,201 @@
/**
Arduino Wrapper for BTstack
*/
#ifndef __ARDUINO_BTSTACK_H
#define __ARDUINO_BTSTACK_H
#if defined __cplusplus
extern "C" {
#endif
#include "ble/att_db.h"
#include "btstack_util.h"
#include "ble/gatt_client.h"
#include "hci.h"
#include <stdint.h>
typedef enum BLEStatus {
BLE_STATUS_OK,
BLE_STATUS_DONE, // e.g. for service or characteristic discovery done
BLE_STATUS_CONNECTION_TIMEOUT,
BLE_STATUS_CONNECTION_ERROR,
BLE_STATUS_OTHER_ERROR
} BLEStatus;
typedef void (*btstack_packet_handler_t)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
class UUID {
private:
uint8_t uuid[16];
public:
UUID();
UUID(const uint8_t uuid[16]);
UUID(const char * uuidStr);
const char * getUuidString() const;
const char * getUuid128String() const;
const uint8_t * getUuid(void) const;
bool matches(UUID *uuid) const;
};
typedef enum BD_ADDR_TYPE {
PUBLIC_ADDRESS = 0,
PRIVAT_ADDRESS
} BD_ADDR_TYPE;
class BD_ADDR {
private:
uint8_t address[6];
BD_ADDR_TYPE address_type;
public:
BD_ADDR();
BD_ADDR(const char * address_string, BD_ADDR_TYPE address_type = PUBLIC_ADDRESS);
BD_ADDR(const uint8_t address[6], BD_ADDR_TYPE address_type = PUBLIC_ADDRESS);
const uint8_t * getAddress();
const char * getAddressString();
BD_ADDR_TYPE getAddressType();
};
class BLEAdvertisement {
private:
uint8_t advertising_event_type;
uint8_t rssi;
uint8_t data_length;
uint8_t data[10 + LE_ADVERTISING_DATA_SIZE];
BD_ADDR bd_addr;
UUID * iBeacon_UUID;
public:
BLEAdvertisement(uint8_t * event_packet);
~BLEAdvertisement();
BD_ADDR * getBdAddr();
BD_ADDR_TYPE getBdAddrType();
int getRssi();
bool containsService(UUID * service);
bool nameHasPrefix(const char * namePrefix);
const uint8_t * getAdvData();
bool isIBeacon();
const UUID * getIBeaconUUID();
uint16_t getIBeaconMajorID();
uint16_t getIBecaonMinorID();
uint8_t getiBeaconMeasuredPower();
};
class BLECharacteristic {
private:
gatt_client_characteristic_t characteristic;
UUID uuid;
public:
BLECharacteristic();
BLECharacteristic(gatt_client_characteristic_t characteristic);
const UUID * getUUID();
bool matches(UUID * uuid);
bool isValueHandle(uint16_t value_handle);
const gatt_client_characteristic_t * getCharacteristic();
};
class BLEService {
private:
gatt_client_service_t service;
UUID uuid;
public:
BLEService();
BLEService(gatt_client_service_t service);
const UUID * getUUID();
bool matches(UUID * uuid);
const gatt_client_service_t * getService();
};
class BLEDevice {
private:
hci_con_handle_t handle;
public:
BLEDevice();
BLEDevice(hci_con_handle_t handle);
hci_con_handle_t getHandle();
// discovery of services and characteristics
int discoverGATTServices();
int discoverCharacteristicsForService(BLEService * service);
// read/write
int readCharacteristic(BLECharacteristic * characteristic);
int writeCharacteristic(BLECharacteristic * characteristic, uint8_t * data, uint16_t size);
int writeCharacteristicWithoutResponse(BLECharacteristic * characteristic, uint8_t * data, uint16_t size);
// subscribe/unsubscribe
int subscribeForNotifications(BLECharacteristic * characteristic);
int unsubscribeFromNotifications(BLECharacteristic * characteristic);
int subscribeForIndications(BLECharacteristic * characteristic);
int unsubscribeFromIndications(BLECharacteristic * characteristic);
};
class BTstackManager {
public:
BTstackManager(void);
void setup(void);
void loop(void);
void setPublicBdAddr(bd_addr_t addr);
void enablePacketLogger();
void enableDebugLogger();
void setAdvData(uint16_t size, const uint8_t * data);
void iBeaconConfigure(UUID * uuid, uint16_t major_id, uint16_t minor_id, uint8_t measured_power = 0xc6);
void startAdvertising();
void stopAdvertising();
void bleStartScanning();
void bleStopScanning();
// connection management
void bleConnect(BD_ADDR_TYPE address_type, const uint8_t address[6], int timeout_ms);
void bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms);
void bleConnect(BD_ADDR * address, int timeout_ms);
void bleConnect(BLEAdvertisement * advertisement, int timeout_ms);
void bleDisconnect(BLEDevice * device);
// discovery of services and characteristics
int discoverGATTServices(BLEDevice * device);
int discoverCharacteristicsForService(BLEDevice * peripheral, BLEService * service);
// read/write
int readCharacteristic(BLEDevice * device, BLECharacteristic * characteristic);
int writeCharacteristic(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size);
int writeCharacteristicWithoutResponse(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size);
// subscribe/unsubscribe notification and indications
int subscribeForNotifications(BLEDevice * device, BLECharacteristic * characteristic);
int unsubscribeFromNotifications(BLEDevice * device, BLECharacteristic * characteristic);
int subscribeForIndications(BLEDevice * device, BLECharacteristic * characteristic);
int unsubscribeFromIndications(BLEDevice * device, BLECharacteristic * characteristic);
// Callbacks
void setBLEAdvertisementCallback(void (*)(BLEAdvertisement * bleAdvertisement));
void setBLEDeviceConnectedCallback(void (*)(BLEStatus status, BLEDevice * device));
void setBLEDeviceDisconnectedCallback(void (*)(BLEDevice * device));
void setGATTServiceDiscoveredCallback(void (*)(BLEStatus status, BLEDevice * device, BLEService * bleService));
void setGATTCharacteristicDiscoveredCallback(void (*)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic));
void setGATTCharacteristicReadCallback(void (*)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length));
void setGATTCharacteristicNotificationCallback(void (*)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length));
void setGATTCharacteristicIndicationCallback(void (*)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length));
void setGATTDoneCallback(void (*)(BLEStatus status, BLEDevice * device));
void setGATTCharacteristicWrittenCallback(void (*)(BLEStatus status, BLEDevice * device));
void setGATTCharacteristicSubscribedCallback(void (*)(BLEStatus status, BLEDevice * device));
void setGATTCharacteristicUnsubscribedCallback(void (*)(BLEStatus status, BLEDevice * device));
void setGATTCharacteristicRead(uint16_t (*)(uint16_t characteristic_id, uint8_t * buffer, uint16_t buffer_size));
void setGATTCharacteristicWrite(int (*)(uint16_t characteristic_id, uint8_t *buffer, uint16_t buffer_size));
void addGATTService(UUID * uuid);
uint16_t addGATTCharacteristic(UUID * uuid, uint16_t flags, const char * text);
uint16_t addGATTCharacteristic(UUID * uuid, uint16_t flags, uint8_t * data, uint16_t data_len);
uint16_t addGATTCharacteristicDynamic(UUID * uuid, uint16_t flags, uint16_t characteristic_id);
};
extern BTstackManager BTstack;
#if defined __cplusplus
}
#endif
#endif // __ARDUINO_BTSTACK_H
+1
View File
@@ -20,6 +20,7 @@ setBitsPerSample KEYWORD2
setFrequency KEYWORD2
setBuffers KEYWORD2
setLSBJFormat KEYWORD2
swapClocks KEYWORD2
read8 KEYWORD2
read16 KEYWORD2
+17 -4
View File
@@ -52,6 +52,7 @@ I2S::I2S(PinMode direction) {
_bufferWords = 0;
_silenceSample = 0;
_isLSBJ = false;
_swapClocks = false;
}
I2S::~I2S() {
@@ -108,6 +109,14 @@ bool I2S::setLSBJFormat() {
return true;
}
bool I2S::swapClocks() {
if (_running || !_isOutput) {
return false;
}
_swapClocks = true;
return true;
}
void I2S::onTransmit(void(*fn)(void)) {
if (_isOutput) {
_cb = fn;
@@ -130,16 +139,20 @@ bool I2S::begin() {
_running = true;
_hasPeeked = false;
int off = 0;
_i2s = new PIOProgram(_isOutput ? (_isLSBJ ? &pio_lsbj_out_program : &pio_i2s_out_program) : &pio_i2s_in_program);
if (!_swapClocks) {
_i2s = new PIOProgram(_isOutput ? (_isLSBJ ? &pio_lsbj_out_program : &pio_i2s_out_program) : &pio_i2s_in_program);
} else {
_i2s = new PIOProgram(_isOutput ? (_isLSBJ ? &pio_lsbj_out_swap_program : &pio_i2s_out_swap_program) : &pio_i2s_in_swap_program);
}
_i2s->prepare(&_pio, &_sm, &off);
if (_isOutput) {
if (_isLSBJ) {
pio_lsbj_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps);
pio_lsbj_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
} else {
pio_i2s_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps);
pio_i2s_out_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
}
} else {
pio_i2s_in_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps);
pio_i2s_in_program_init(_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
}
setFrequency(_freq);
if (_bps == 8) {
+2
View File
@@ -34,6 +34,7 @@ public:
bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0);
bool setFrequency(int newFreq);
bool setLSBJFormat();
bool swapClocks();
bool begin(long sampleRate) {
setFrequency(sampleRate);
@@ -107,6 +108,7 @@ private:
int32_t _silenceSample;
bool _isLSBJ;
bool _isOutput;
bool _swapClocks;
bool _running;
+74 -7
View File
@@ -41,6 +41,28 @@ right:
out pins, 1 side 0b00 ; Last bit of right also has WCLK change
; Loop back to beginning...
.program pio_i2s_out_swap
.side_set 2 ; 0 = wclk, 1=bclk
; The C code should place (number of bits/sample - 2) in Y and
; also update the SHIFTCTRL to be 24 or 32 as appropriate
; +----- BCLK
; |+---- WCLK
mov x, y side 0b10
left:
out pins, 1 side 0b00
jmp x--, left side 0b10
out pins, 1 side 0b01 ; Last bit of left has WCLK change per I2S spec
mov x, y side 0b11
right:
out pins, 1 side 0b01
jmp x--, right side 0b11
out pins, 1 side 0b00 ; Last bit of right also has WCLK change
; Loop back to beginning...
.program pio_lsbj_out
.side_set 2 ; 0 = bclk, 1=wclk
@@ -64,6 +86,28 @@ right:
; Loop back to beginning...
.program pio_lsbj_out_swap
.side_set 2 ; 0 = wclk, 1=bclk
; The C code should place (number of bits/sample - 2) in Y and
; also update the SHIFTCTRL to be 24 or 32 as appropriate
; +----- BCLK
; |+---- WCLK
mov x, y side 0b10
left:
out pins, 1 side 0b01
jmp x--, left side 0b11
out pins, 1 side 0b01
mov x, y side 0b11
right:
out pins, 1 side 0b00
jmp x--, right side 0b10
out pins, 1 side 0b00
; Loop back to beginning...
.program pio_i2s_in ; Note this is the same as _out, just "in" and not "out"
.side_set 2 ; 0 = bclk, 1=wclk
@@ -86,16 +130,39 @@ right:
in pins, 1 side 0b01 ; Last bit of right also has WCLK change
; Loop back to beginning...
.program pio_i2s_in_swap ; Note this is the same as _out, just "in" and not "out"
.side_set 2 ; 0 = wclk, 1=bclk
; The C code should place (number of bits/sample - 2) in Y and
; also update the SHIFTCTRL to be 24 or 32 as appropriate
; +----- BCLK
; |+---- WCLK
mov x, y side 0b00
left:
in pins, 1 side 0b10
jmp x--, left side 0b00
in pins, 1 side 0b11 ; Last bit of left has WCLK change per I2S spec
mov x, y side 0b01
right:
in pins, 1 side 0b11
jmp x--, right side 0b01
in pins, 1 side 0b10 ; Last bit of right also has WCLK change
; Loop back to beginning...
% c-sdk {
static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) {
static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) {
pio_gpio_init(pio, data_pin);
pio_gpio_init(pio, clock_pin_base);
pio_gpio_init(pio, clock_pin_base + 1);
pio_sm_config sm_config = pio_i2s_out_program_get_default_config(offset);
pio_sm_config sm_config = swap ? pio_i2s_out_swap_program_get_default_config(offset) : pio_i2s_out_program_get_default_config(offset);
sm_config_set_out_pins(&sm_config, data_pin, 1);
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
@@ -111,12 +178,12 @@ static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint
pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2));
}
static inline void pio_lsbj_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) {
static inline void pio_lsbj_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) {
pio_gpio_init(pio, data_pin);
pio_gpio_init(pio, clock_pin_base);
pio_gpio_init(pio, clock_pin_base + 1);
pio_sm_config sm_config = pio_lsbj_out_program_get_default_config(offset);
pio_sm_config sm_config = swap ? pio_lsbj_out_swap_program_get_default_config(offset) : pio_lsbj_out_program_get_default_config(offset);
sm_config_set_out_pins(&sm_config, data_pin, 1);
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
@@ -132,12 +199,12 @@ static inline void pio_lsbj_out_program_init(PIO pio, uint sm, uint offset, uint
pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2));
}
static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) {
static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) {
pio_gpio_init(pio, data_pin);
pio_gpio_init(pio, clock_pin_base);
pio_gpio_init(pio, clock_pin_base + 1);
pio_sm_config sm_config = pio_i2s_in_program_get_default_config(offset);
pio_sm_config sm_config = swap ? pio_i2s_in_swap_program_get_default_config(offset) : pio_i2s_in_program_get_default_config(offset);
sm_config_set_in_pins(&sm_config, data_pin);
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
+112 -6
View File
@@ -43,6 +43,41 @@ static inline pio_sm_config pio_i2s_out_program_get_default_config(uint offset)
}
#endif
// ---------------- //
// pio_i2s_out_swap //
// ---------------- //
#define pio_i2s_out_swap_wrap_target 0
#define pio_i2s_out_swap_wrap 7
static const uint16_t pio_i2s_out_swap_program_instructions[] = {
// .wrap_target
0xb022, // 0: mov x, y side 2
0x6001, // 1: out pins, 1 side 0
0x1041, // 2: jmp x--, 1 side 2
0x6801, // 3: out pins, 1 side 1
0xb822, // 4: mov x, y side 3
0x6801, // 5: out pins, 1 side 1
0x1845, // 6: jmp x--, 5 side 3
0x6001, // 7: out pins, 1 side 0
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program pio_i2s_out_swap_program = {
.instructions = pio_i2s_out_swap_program_instructions,
.length = 8,
.origin = -1,
};
static inline pio_sm_config pio_i2s_out_swap_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + pio_i2s_out_swap_wrap_target, offset + pio_i2s_out_swap_wrap);
sm_config_set_sideset(&c, 2, false, false);
return c;
}
#endif
// ------------ //
// pio_lsbj_out //
// ------------ //
@@ -78,6 +113,41 @@ static inline pio_sm_config pio_lsbj_out_program_get_default_config(uint offset)
}
#endif
// ----------------- //
// pio_lsbj_out_swap //
// ----------------- //
#define pio_lsbj_out_swap_wrap_target 0
#define pio_lsbj_out_swap_wrap 7
static const uint16_t pio_lsbj_out_swap_program_instructions[] = {
// .wrap_target
0xb022, // 0: mov x, y side 2
0x6801, // 1: out pins, 1 side 1
0x1841, // 2: jmp x--, 1 side 3
0x6801, // 3: out pins, 1 side 1
0xb822, // 4: mov x, y side 3
0x6001, // 5: out pins, 1 side 0
0x1045, // 6: jmp x--, 5 side 2
0x6001, // 7: out pins, 1 side 0
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program pio_lsbj_out_swap_program = {
.instructions = pio_lsbj_out_swap_program_instructions,
.length = 8,
.origin = -1,
};
static inline pio_sm_config pio_lsbj_out_swap_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + pio_lsbj_out_swap_wrap_target, offset + pio_lsbj_out_swap_wrap);
sm_config_set_sideset(&c, 2, false, false);
return c;
}
#endif
// ---------- //
// pio_i2s_in //
// ---------- //
@@ -111,12 +181,47 @@ static inline pio_sm_config pio_i2s_in_program_get_default_config(uint offset) {
sm_config_set_sideset(&c, 2, false, false);
return c;
}
#endif
static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) {
// --------------- //
// pio_i2s_in_swap //
// --------------- //
#define pio_i2s_in_swap_wrap_target 0
#define pio_i2s_in_swap_wrap 7
static const uint16_t pio_i2s_in_swap_program_instructions[] = {
// .wrap_target
0xa022, // 0: mov x, y side 0
0x5001, // 1: in pins, 1 side 2
0x0041, // 2: jmp x--, 1 side 0
0x5801, // 3: in pins, 1 side 3
0xa822, // 4: mov x, y side 1
0x5801, // 5: in pins, 1 side 3
0x0845, // 6: jmp x--, 5 side 1
0x5001, // 7: in pins, 1 side 2
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program pio_i2s_in_swap_program = {
.instructions = pio_i2s_in_swap_program_instructions,
.length = 8,
.origin = -1,
};
static inline pio_sm_config pio_i2s_in_swap_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + pio_i2s_in_swap_wrap_target, offset + pio_i2s_in_swap_wrap);
sm_config_set_sideset(&c, 2, false, false);
return c;
}
static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) {
pio_gpio_init(pio, data_pin);
pio_gpio_init(pio, clock_pin_base);
pio_gpio_init(pio, clock_pin_base + 1);
pio_sm_config sm_config = pio_i2s_out_program_get_default_config(offset);
pio_sm_config sm_config = swap ? pio_i2s_out_swap_program_get_default_config(offset) : pio_i2s_out_program_get_default_config(offset);
sm_config_set_out_pins(&sm_config, data_pin, 1);
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits);
@@ -127,11 +232,11 @@ static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint
pio_sm_set_pins(pio, sm, 0); // clear pins
pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2));
}
static inline void pio_lsbj_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) {
static inline void pio_lsbj_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) {
pio_gpio_init(pio, data_pin);
pio_gpio_init(pio, clock_pin_base);
pio_gpio_init(pio, clock_pin_base + 1);
pio_sm_config sm_config = pio_lsbj_out_program_get_default_config(offset);
pio_sm_config sm_config = swap ? pio_lsbj_out_swap_program_get_default_config(offset) : pio_lsbj_out_program_get_default_config(offset);
sm_config_set_out_pins(&sm_config, data_pin, 1);
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits);
@@ -142,11 +247,11 @@ static inline void pio_lsbj_out_program_init(PIO pio, uint sm, uint offset, uint
pio_sm_set_pins(pio, sm, 0); // clear pins
pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2));
}
static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) {
static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits, bool swap) {
pio_gpio_init(pio, data_pin);
pio_gpio_init(pio, clock_pin_base);
pio_gpio_init(pio, clock_pin_base + 1);
pio_sm_config sm_config = pio_i2s_in_program_get_default_config(offset);
pio_sm_config sm_config = swap ? pio_i2s_in_swap_program_get_default_config(offset) : pio_i2s_in_program_get_default_config(offset);
sm_config_set_in_pins(&sm_config, data_pin);
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
sm_config_set_in_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits);
@@ -159,3 +264,4 @@ static inline void pio_i2s_in_program_init(PIO pio, uint sm, uint offset, uint d
}
#endif
@@ -26,7 +26,19 @@ void setup() {
void loop() {
if (BOOTSEL) {
Serial.println("Typing password for you...shhhh....");
Serial.println("First, mute the computer to be extra quiet");
Keyboard.consumerPress(KEY_MUTE);
delay(100);
Keyboard.consumerRelease();
Keyboard.print("ThisPasswordIsWeakLikeABaby");
Serial.println("OK, unmute the computer since our secret is done");
Keyboard.consumerPress(KEY_MUTE);
delay(100);
Keyboard.consumerRelease();
while (BOOTSEL);
}
}
+10
View File
@@ -46,6 +46,16 @@ void Keyboard_::sendReport(KeyReport* keys) {
tud_task();
}
void Keyboard_::sendConsumerReport(uint16_t key) {
CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_report(__USBGetKeyboardReportID() + 1, &key, sizeof(key));
}
tud_task();
}
extern "C" void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
(void) report_id;
(void) instance;
+1
View File
@@ -28,6 +28,7 @@
class Keyboard_ : public HID_Keyboard {
protected:
virtual void sendReport(KeyReport* keys) override;
virtual void sendConsumerReport(uint16_t key) override;
public:
Keyboard_(void);
@@ -63,4 +63,9 @@ void KeyboardBLE_::sendReport(KeyReport* keys) {
PicoBluetoothBLEHID.send(&data, sizeof(data));
}
void KeyboardBLE_::sendConsumerReport(uint16_t key) {
(void) key;
// TODO - Need some BLE-specific code to send 2nd report
}
KeyboardBLE_ KeyboardBLE;
+1
View File
@@ -28,6 +28,7 @@
class KeyboardBLE_ : public HID_Keyboard {
private:
virtual void sendReport(KeyReport* keys) override;
virtual void sendConsumerReport(uint16_t key) override;
public:
KeyboardBLE_(void);
void begin(const char *localName = nullptr, const char *hidName = nullptr, const uint8_t *layout = KeyboardLayout_en_US);
+5 -1
View File
@@ -34,7 +34,7 @@ KeyboardBT_::KeyboardBT_(void) {
#define REPORT_ID 0x01
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))};
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID)), TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(REPORT_ID + 1))};
static void _hidReportCB(uint16_t cid, hid_report_type_t report_type, uint16_t report_id, int report_size, uint8_t *report) {
(void) cid;
@@ -71,4 +71,8 @@ void KeyboardBT_::sendReport(KeyReport* keys) {
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
}
void KeyboardBT_::sendConsumerReport(uint16_t key) {
PicoBluetoothHID.send(REPORT_ID + 1, &key, sizeof(key));
}
KeyboardBT_ KeyboardBT;
+1
View File
@@ -28,6 +28,7 @@
class KeyboardBT_ : public HID_Keyboard {
protected:
virtual void sendReport(KeyReport* keys) override;
virtual void sendConsumerReport(uint16_t key) override;
public:
KeyboardBT_(void);
void begin(const char *localName = nullptr, const char *hidName = nullptr, const uint8_t *layout = KeyboardLayout_en_US);
+31
View File
@@ -0,0 +1,31 @@
:repository-owner: arduino-libraries
:repository-name: Mouse
= {repository-name} Library for Arduino =
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"]
This library allows an Arduino board with USB capabilities to act as a Mouse.
For more information about this library please visit us at
https://www.arduino.cc/reference/en/language/functions/usb/mouse/
== License ==
Copyright (c) Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+428
View File
@@ -0,0 +1,428 @@
# Mouse library
## Methods
### `Mouse.begin()`
Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`.
#### Syntax
```
Mouse.begin()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
}
void loop() {
// Initialize the Mouse library when button is pressed
if (digitalRead(2) == HIGH) {
Mouse.begin();
}
}
```
#### See also
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.click()`
Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button.
`Mouse.click()` defaults to the left mouse button.
#### Syntax
```
Mouse.click()
Mouse.click(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
}
}
```
#### Notes and warnings
When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.end()`
Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`.
#### Syntax
```
Mouse.end()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initiate the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
// Then end the Mouse emulation
Mouse.end();
}
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.move()`
Moves the cursor on a connected computer. The motion onscreen is always relative to the cursor’s current location. Before using `Mouse.move()` you must call `Mouse.begin()`.
#### Syntax
```
Mouse.move(xVal, yVal, wheel)
```
#### Parameters
* `xVal`: amount to move along the x-axis. Allowed data types: signed char.
* `yVal`: amount to move along the y-axis. Allowed data types: signed char.
* `wheel`: amount to move scroll wheel. Allowed data types: signed char.
#### Returns
None.
#### Example
```
#include <Mouse.h>
const int xAxis = A1; // Analog sensor for X axis
const int yAxis = A2; // Analog sensor for Y axis
int range = 12; // Output range of X or Y movement
int responseDelay = 2; // Response delay of the mouse, in ms
int threshold = range / 4; // Resting threshold
int center = range / 2; // Resting position value
int minima[] = {1023, 1023}; // Actual analogRead minima for (x, y)
int maxima[] = {0, 0}; // Actual analogRead maxima for (x, y)
int axis[] = {xAxis, yAxis}; // Pin numbers for (x, y)
int mouseReading[2]; // Final mouse readings for (x, y)
void setup() {
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// Read and scale the two axes
int xReading = readAxis(0);
int yReading = readAxis(1);
// Move the mouse
Mouse.move(xReading, yReading, 0);
delay(responseDelay);
}
/*
Reads an axis (0 or 1 for x or y) and scales the
analog input range to a range from 0 to <range>
*/
int readAxis(int axisNumber) {
int distance = 0; // Distance from center of the output range
// Read the analog input
int reading = analogRead(axis[axisNumber]);
// Of the current reading exceeds the max or min for this axis, reset the max or min
if (reading < minima[axisNumber]) {
minima[axisNumber] = reading;
}
if (reading > maxima[axisNumber]) {
maxima[axisNumber] = reading;
}
// Map the reading from the analog input range to the output range
reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range);
// If the output reading is outside from the rest position threshold, use it
if (abs(reading - center) > threshold) {
distance = (reading - center);
}
// The Y axis needs to be inverted in order to map the movement correctly
if (axisNumber == 1) {
distance = -distance;
}
// Return the distance for this axis
return distance;
}
```
#### Notes and warnings
When you use the `Mouse.move()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.press()`
Sends a button press to a connected computer. A press is the equivalent of clicking and continuously holding the mouse button. A press is cancelled with `Mouse.release()`. Before using `Mouse.press()`, you need to start communication with `Mouse.begin()`. `Mouse.press()` defaults to a left button press.
#### Syntax
```
Mouse.press()
Mouse.press(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the switch attached to pin 2 is closed, press and hold the left mouse button
if (digitalRead(2) == HIGH) {
Mouse.press();
}
// If the switch attached to pin 3 is closed, release the left mouse button
if (digitalRead(3) == HIGH) {
Mouse.release();
}
}
```
#### Notes and warnings
When you use the `Mouse.press()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.release()`
Sends a message that a previously pressed button (invoked through `Mouse.press()`) is released. `Mouse.release()` defaults to the left button.
#### Syntax
```
Mouse.press()
Mouse.press(button)
```
#### Parameters
* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the switch attached to pin 2 is closed, press and hold the left mouse button
if (digitalRead(2) == HIGH) {
Mouse.press();
}
// If the switch attached to pin 3 is closed, release the left mouse button
if (digitalRead(3) == HIGH) {
Mouse.release();
}
}
```
#### Notes and warnings
When you use the `Mouse.release()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.isPressed()`
Checks the current status of all mouse buttons, and reports if any are pressed or not. By default, it checks the status of the left mouse button.
#### Syntax
```
Mouse.isPressed();
Mouse.isPressed(button);
```
#### Parameters
* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
1 if a button was pressed, 0 if a not.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Start serial communication with the computer
Serial.begin(9600);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// A variable for checking the button's state
int mouseState = 0;
// If the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variable
if (digitalRead(2) == HIGH) {
Mouse.press();
mouseState = Mouse.isPressed();
}
// If the switch attached to pin 3 is closed, release the left mouse button and save the state in a variable
if (digitalRead(3) == HIGH) {
Mouse.release();
mouseState = Mouse.isPressed();
}
// Print out the current mouse button state
Serial.println(mouseState);
delay(10);
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
+23
View File
@@ -0,0 +1,23 @@
# Mouse library
The mouse functions enable 32u4 or SAMD micro based boards to control cursor movement on a connected computer through their micro’s native USB port. When updating the cursor position, it is always relative to the cursor’s previous location.
To use this library:
```
#include <Mouse.h>
```
## Notes and warnings
These core libraries allow the 32u4 and SAMD based boards (Leonardo, Esplora, Zero, Due and MKR Family) to appear as a native Mouse and/or Keyboard to a connected computer.
**A word of caution on using the Mouse and Keyboard libraries**: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as `Mouse.move()` and `Keyboard.print()` will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control. Refer to the Mouse and Keyboard examples for some ways to handle this.
When using the Mouse or Keyboard library, it may be best to test your output first using `Serial.print()`. This way, you can be sure you know what values are being reported.
## Examples
* [KeyboardAndMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardAndMouseControl): Demonstrates the Mouse and Keyboard commands in one program.
* [ButtonMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ButtonMouseControl): Control cursor movement with 5 pushbuttons.
* [JoystickMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/JoystickMouseControl): Controls a computer’s cursor movement with a Joystick when a button is pressed.
@@ -0,0 +1,32 @@
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
/* Released to the public domain */
#include <MouseAbsolute.h>
void setup() {
Serial.begin(115200);
MouseAbsolute.begin();
delay(5000);
Serial.printf("Press BOOTSEL to move the mouse in a series of circles\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("BARREL ROLLS!!!");
float r = 1000;
for (float cx = 1000; cx <= 16000; cx += 4000) {
for (float cy = 1000; cy <= 16000; cy += 4000) {
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
MouseAbsolute.move(ax + cx, ay + cy, 0);
delay(10);
}
}
}
while (BOOTSEL) {
delay(1);
}
}
}
+24
View File
@@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
MouseAbsolute KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
click KEYWORD2
move KEYWORD2
press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
@@ -0,0 +1,9 @@
name=MouseAbsolute
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
@@ -0,0 +1,45 @@
/*
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 "MouseAbsolute.h"
#include <RP2040USB.h>
#include "tusb.h"
#include "class/hid/hid_device.h"
#include <sdkoverride/tusb_absmouse.h>
// Weak function override to add our descriptor to the TinyUSB list
void __USBInstallAbsoluteMouse() { /* noop */ }
MouseAbsolute_::MouseAbsolute_(void) : HID_Mouse(true) {
/* noop */
}
void MouseAbsolute_::move(int x, int y, signed char wheel) {
CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_abs_mouse_report(__USBGetMouseReportID(), _buttons, limit_xy(x), limit_xy(y), wheel, 0);
}
tud_task();
}
MouseAbsolute_ MouseAbsolute;
@@ -0,0 +1,34 @@
/*
Mouse.h
Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MOUSEABSOLUTE_h
#define MOUSEABSOLUTE_h
#include <HID_Mouse.h>
class MouseAbsolute_ : public HID_Mouse {
public:
MouseAbsolute_(void);
virtual void move(int x, int y, signed char wheel = 0) override;
};
extern MouseAbsolute_ MouseAbsolute;
#endif
@@ -0,0 +1,33 @@
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
/* Released to the public domain */
#include <MouseBLE.h>
void setup() {
Serial.begin(115200);
MouseBLE.setAbsolute(true);
MouseBLE.begin("CircleBLE Mouse");
delay(5000);
Serial.printf("Press BOOTSEL to move the mouse in a circle\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("BARREL ROLLS!!!");
float r = 1000;
for (float cx = 1000; cx <= 16000; cx += 4000) {
for (float cy = 1000; cy <= 16000; cy += 4000) {
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
MouseBLE.move(ax + cx, ay + cy, 0);
delay(10);
}
}
}
MouseBLE.setBattery(random(0, 101)); // Set between 0...100%
while (BOOTSEL) {
delay(1);
}
}
}
+1
View File
@@ -19,6 +19,7 @@ press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
setBattery KEYWORD2
setAbsolute KEYWORD2
#######################################
# Constants (LITERAL1)
+36 -12
View File
@@ -20,14 +20,16 @@
*/
#include "MouseBLE.h"
#include <sdkoverride/tusb_absmouse.h>
#include <PicoBluetoothBLEHID.h>
MouseBLE_::MouseBLE_(void) {
/* noop */
MouseBLE_::MouseBLE_(bool absolute) : HID_Mouse(absolute) {
_running = false;
}
#define REPORT_ID 0x01
const uint8_t desc_mouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID))};
const uint8_t desc_absmouse[] = {TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(REPORT_ID))};
void MouseBLE_::begin(const char *localName, const char *hidName) {
if (!localName) {
localName = "PicoW BLE Mouse";
@@ -35,25 +37,47 @@ void MouseBLE_::begin(const char *localName, const char *hidName) {
if (!hidName) {
hidName = localName;
}
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c2, desc_mouse, sizeof(desc_mouse));
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c2, _absolute ? desc_absmouse : desc_mouse, _absolute ? sizeof(desc_absmouse) : sizeof(desc_mouse));
_running = true;
}
void MouseBLE_::end(void) {
PicoBluetoothBLEHID.end();
if (_running) {
PicoBluetoothBLEHID.end();
}
_running = false;
}
void MouseBLE_::setBattery(int lvl) {
PicoBluetoothBLEHID.setBattery(lvl);
if (_running) {
PicoBluetoothBLEHID.setBattery(lvl);
}
}
void MouseBLE_::setAbsolute(bool absolute) {
if (!_running) {
_absolute = absolute;
}
}
void MouseBLE_::move(int x, int y, signed char wheel) {
hid_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothBLEHID.send(&data, sizeof(data));
if (!_absolute) {
hid_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothBLEHID.send(&data, sizeof(data));
} else {
hid_abs_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothBLEHID.send(&data, sizeof(data));
}
}
MouseBLE_ MouseBLE;
+5 -1
View File
@@ -25,12 +25,16 @@
#include <HID_Mouse.h>
class MouseBLE_ : public HID_Mouse {
private:
bool _running;
public:
MouseBLE_(void);
MouseBLE_(bool absolute = false);
void begin(const char *localName = nullptr, const char *hidName = nullptr);
void end(void);
virtual void move(int x, int y, signed char wheel = 0) override;
void setBattery(int lvl);
void setAbsolute(bool absolute = true);
};
extern MouseBLE_ MouseBLE;
@@ -0,0 +1,32 @@
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
/* Released to the public domain */
#include <MouseBT.h>
void setup() {
Serial.begin(115200);
MouseBT.setAbsolute(true);
MouseBT.begin("CircleBT Mouse");
delay(5000);
Serial.printf("Press BOOTSEL to move the mouse in a circle\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("BARREL ROLLS!!!");
float r = 1000;
for (float cx = 1000; cx <= 16000; cx += 4000) {
for (float cy = 1000; cy <= 16000; cy += 4000) {
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
MouseBT.move(ax + cx, ay + cy, 0);
delay(10);
}
}
}
while (BOOTSEL) {
delay(1);
}
}
}
+2
View File
@@ -18,6 +18,8 @@ move KEYWORD2
press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
setAbsolute KEYWORD2
#######################################
# Constants (LITERAL1)
+33 -11
View File
@@ -20,14 +20,16 @@
*/
#include "MouseBT.h"
#include <sdkoverride/tusb_absmouse.h>
#include <PicoBluetoothHID.h>
MouseBT_::MouseBT_(void) {
/* noop */
MouseBT_::MouseBT_(bool absolute) : HID_Mouse(absolute) {
_running = false;
}
#define REPORT_ID 0x01
const uint8_t desc_mouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID))};
const uint8_t desc_absmouse[] = {TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(REPORT_ID))};
void MouseBT_::begin(const char *localName, const char *hidName) {
if (!localName) {
@@ -36,21 +38,41 @@ void MouseBT_::begin(const char *localName, const char *hidName) {
if (!hidName) {
hidName = localName;
}
PicoBluetoothHID.startHID(localName, hidName, 0x2580, 33, desc_mouse, sizeof(desc_mouse));
PicoBluetoothHID.startHID(localName, hidName, 0x2580, 33, _absolute ? desc_absmouse : desc_mouse, _absolute ? sizeof(desc_absmouse) : sizeof(desc_mouse));
_running = true;
}
void MouseBT_::end(void) {
PicoBluetoothHID.end();
if (_running) {
PicoBluetoothHID.end();
}
_running = false;
}
void MouseBT_::setAbsolute(bool absolute) {
if (!_running) {
_absolute = absolute;
}
}
void MouseBT_::move(int x, int y, signed char wheel) {
hid_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
if (!_absolute) {
hid_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
} else {
hid_abs_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
}
}
MouseBT_ MouseBT;
+5 -1
View File
@@ -25,11 +25,15 @@
#include <HID_Mouse.h>
class MouseBT_ : public HID_Mouse {
private:
bool _running;
public:
MouseBT_(void);
MouseBT_(bool absolute = false);
void begin(const char *localName = nullptr, const char *hidName = nullptr);
void end(void);
virtual void move(int x, int y, signed char wheel = 0) override;
void setAbsolute(bool absolute = true);
};
extern MouseBT_ MouseBT;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "framework-arduinopico",
"version": "1.30100.0",
"version": "1.30101.0",
"description": "Arduino Wiring-based Framework (RPi Pico RP2040)",
"keywords": [
"framework",
+12
View File
@@ -35,6 +35,15 @@
{
"name": "Adafruit Feather RP2040 DVI"
},
{
"name": "Adafruit Feather RP2040 RFM"
},
{
"name": "Adafruit Feather RP2040 ThinkINK"
},
{
"name": "Adafruit Feather RP2040 USB Host"
},
{
"name": "Adafruit ItsyBitsy RP2040"
},
@@ -104,6 +113,9 @@
{
"name": "iLabs Challenger 2040 NFC"
},
{
"name": "iLabs Challenger 2040 UWB"
},
{
"name": "iLabs RPICO32"
},
+1 -1
View File
@@ -20,7 +20,7 @@
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
name=Raspberry Pi RP2040 Boards
version=3.1.0
version=3.1.1
runtime.tools.pqt-gcc.path={runtime.platform.path}/system/arm-none-eabi
runtime.tools.pqt-python3.path={runtime.platform.path}/system/python3
+1 -1
View File
@@ -10,7 +10,7 @@ for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S ./libraries/SingleF
./libraries/Updater ./libraries/HTTPClient ./libraries/HTTPUpdate \
./libraries/WebServer ./libraries/HTTPUpdateServer ./libraries/DNSServer \
./libraries/Joystick ./libraries/Keyboard ./libraries/Mouse \
./libraries/JoystickBT ./libraries/KeyboardBT \
./libraries/JoystickBT ./libraries/KeyboardBT ./variants ./libraries/BTstack \
./libraries/MouseBT ./libraries/SerialBT ./libraries/HID_Bluetooth \
./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 \{\} \;
+54
View File
@@ -0,0 +1,54 @@
{
"build": {
"arduino": {
"earlephilhower": {
"boot2_source": "boot2_w25q080_2_padded_checksum.S",
"usb_vid": "0x239A",
"usb_pid": "0x812D"
}
},
"core": "earlephilhower",
"cpu": "cortex-m0plus",
"extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_RFM -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
"f_cpu": "133000000L",
"hwids": [
[
"0x2E8A",
"0x00C0"
],
[
"0x239A",
"0x812D"
]
],
"mcu": "rp2040",
"variant": "adafruit_feather_rfm"
},
"debug": {
"jlink_device": "RP2040_M0_0",
"openocd_target": "rp2040.cfg",
"svd_path": "rp2040.svd"
},
"frameworks": [
"arduino"
],
"name": "Feather RP2040 RFM",
"upload": {
"maximum_ram_size": 270336,
"maximum_size": 8388608,
"require_upload_port": true,
"native_usb": true,
"use_1200bps_touch": true,
"wait_for_upload_port": false,
"protocol": "picotool",
"protocols": [
"cmsis-dap",
"jlink",
"raspberrypi-swd",
"picotool",
"picoprobe"
]
},
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
"vendor": "Adafruit"
}
+54
View File
@@ -0,0 +1,54 @@
{
"build": {
"arduino": {
"earlephilhower": {
"boot2_source": "boot2_w25q080_2_padded_checksum.S",
"usb_vid": "0x239A",
"usb_pid": "0x812B"
}
},
"core": "earlephilhower",
"cpu": "cortex-m0plus",
"extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_THINKINK -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
"f_cpu": "133000000L",
"hwids": [
[
"0x2E8A",
"0x00C0"
],
[
"0x239A",
"0x812B"
]
],
"mcu": "rp2040",
"variant": "adafruit_feather_thinkink"
},
"debug": {
"jlink_device": "RP2040_M0_0",
"openocd_target": "rp2040.cfg",
"svd_path": "rp2040.svd"
},
"frameworks": [
"arduino"
],
"name": "Feather RP2040 ThinkINK",
"upload": {
"maximum_ram_size": 270336,
"maximum_size": 8388608,
"require_upload_port": true,
"native_usb": true,
"use_1200bps_touch": true,
"wait_for_upload_port": false,
"protocol": "picotool",
"protocols": [
"cmsis-dap",
"jlink",
"raspberrypi-swd",
"picotool",
"picoprobe"
]
},
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
"vendor": "Adafruit"
}
+54
View File
@@ -0,0 +1,54 @@
{
"build": {
"arduino": {
"earlephilhower": {
"boot2_source": "boot2_w25q080_2_padded_checksum.S",
"usb_vid": "0x239A",
"usb_pid": "0x8129"
}
},
"core": "earlephilhower",
"cpu": "cortex-m0plus",
"extra_flags": "-D ARDUINO_ADAFRUIT_FEATHER_RP2040_USB_HOST -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
"f_cpu": "133000000L",
"hwids": [
[
"0x2E8A",
"0x00C0"
],
[
"0x239A",
"0x8129"
]
],
"mcu": "rp2040",
"variant": "adafruit_feather_usb_host"
},
"debug": {
"jlink_device": "RP2040_M0_0",
"openocd_target": "rp2040.cfg",
"svd_path": "rp2040.svd"
},
"frameworks": [
"arduino"
],
"name": "Feather RP2040 USB Host",
"upload": {
"maximum_ram_size": 270336,
"maximum_size": 8388608,
"require_upload_port": true,
"native_usb": true,
"use_1200bps_touch": true,
"wait_for_upload_port": false,
"protocol": "picotool",
"protocols": [
"cmsis-dap",
"jlink",
"raspberrypi-swd",
"picotool",
"picoprobe"
]
},
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
"vendor": "Adafruit"
}
+1 -1
View File
@@ -9,7 +9,7 @@
},
"core": "earlephilhower",
"cpu": "cortex-m0plus",
"extra_flags": "-D ARDUINO_CHALLENGER_NB_2040_NFC_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
"extra_flags": "-D ARDUINO_CHALLENGER_2040_NFC_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
"f_cpu": "133000000L",
"hwids": [
[
+1 -1
View File
@@ -9,7 +9,7 @@
},
"core": "earlephilhower",
"cpu": "cortex-m0plus",
"extra_flags": "-D ARDUINO_CHALLENGER_NB_2040_SDRTC_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
"extra_flags": "-D ARDUINO_CHALLENGER_2040_SDRTC_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
"f_cpu": "133000000L",
"hwids": [
[
+54
View File
@@ -0,0 +1,54 @@
{
"build": {
"arduino": {
"earlephilhower": {
"boot2_source": "boot2_w25q080_2_padded_checksum.S",
"usb_vid": "0x2E8A",
"usb_pid": "0x1052"
}
},
"core": "earlephilhower",
"cpu": "cortex-m0plus",
"extra_flags": "-D ARDUINO_CHALLENGER_2040_UWB_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500",
"f_cpu": "133000000L",
"hwids": [
[
"0x2E8A",
"0x00C0"
],
[
"0x2E8A",
"0x1052"
]
],
"mcu": "rp2040",
"variant": "challenger_2040_uwb"
},
"debug": {
"jlink_device": "RP2040_M0_0",
"openocd_target": "rp2040.cfg",
"svd_path": "rp2040.svd"
},
"frameworks": [
"arduino"
],
"name": "Challenger 2040 UWB",
"upload": {
"maximum_ram_size": 270336,
"maximum_size": 8388608,
"require_upload_port": true,
"native_usb": true,
"use_1200bps_touch": true,
"wait_for_upload_port": false,
"protocol": "picotool",
"protocols": [
"cmsis-dap",
"jlink",
"raspberrypi-swd",
"picotool",
"picoprobe"
]
},
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
"vendor": "iLabs"
}
+3
View File
@@ -56,6 +56,9 @@ extern unsigned long get_rand_32(void);
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
// See #1285
#define MEMP_NUM_UDP_PCB 6
#if LWIP_IPV6
#define LWIP_IPV6_DHCP6 1
#endif
+10 -6
View File
@@ -210,11 +210,11 @@ def MakeBoard(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flash
for i in range(1, flashsizemb):
fssizelist.append(i * 1024 * 1024)
BuildHeader(name, vendor_name, product_name, vid, pid, pwr, boarddefine, name, flashsizemb * 1024 * 1024, boot2, extra)
if name == "generic":
if (name == "generic") or (name == "vccgnd_yd_rp2040"):
BuildFlashMenu(name, 2*1024*1024, [0, 1*1024*1024])
BuildFlashMenu(name, 4*1024*1024, [0, 2*1024*1024])
BuildFlashMenu(name, 8*1024*1024, [0, 4*1024*1024])
BuildFlashMenu(name, 16*1024*1024, [0, 8*1024*1024])
BuildFlashMenu(name, 4*1024*1024, [0, 3*1024*1024, 2*1024*1024])
BuildFlashMenu(name, 8*1024*1024, [0, 7*1024*1024, 4*1024*1024, 2*1024*1024])
BuildFlashMenu(name, 16*1024*1024, [0, 15*1024*1024, 14*1024*1024, 12*1024*1024, 8*1024*1024, 4*1024*1024, 2*1024*1024])
else:
BuildFlashMenu(name, flashsizemb * 1024 * 1024, fssizelist)
BuildFreq(name)
@@ -339,6 +339,9 @@ MakeBoard("0xcb_helios", "0xCB", "Helios", "0x1209", "0xCB74", 500, "0XCB_HELIOS
MakeBoard("adafruit_feather", "Adafruit", "Feather RP2040", "0x239a", "0x80f1", 250, "ADAFRUIT_FEATHER_RP2040", 8, "boot2_w25x10cl_4_padded_checksum")
MakeBoard("adafruit_feather_scorpio", "Adafruit", "Feather RP2040 SCORPIO", "0x239a", "0x8121", 250, "ADAFRUIT_FEATHER_RP2040_SCORPIO", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("adafruit_feather_dvi", "Adafruit", "Feather RP2040 DVI", "0x239a", "0x8127", 250, "ADAFRUIT_FEATHER_RP2040_DVI", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("adafruit_feather_rfm", "Adafruit", "Feather RP2040 RFM", "0x239a", "0x812D", 250, "ADAFRUIT_FEATHER_RP2040_RFM", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("adafruit_feather_thinkink", "Adafruit", "Feather RP2040 ThinkINK", "0x239a", "0x812B", 250, "ADAFRUIT_FEATHER_RP2040_THINKINK", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("adafruit_feather_usb_host", "Adafruit", "Feather RP2040 USB Host", "0x239a", "0x8129", 250, "ADAFRUIT_FEATHER_RP2040_USB_HOST", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("adafruit_itsybitsy", "Adafruit", "ItsyBitsy RP2040", "0x239a", "0x80fd", 250, "ADAFRUIT_ITSYBITSY_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("adafruit_qtpy", "Adafruit", "QT Py RP2040", "0x239a", "0x80f7", 250, "ADAFRUIT_QTPY_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("adafruit_stemmafriend", "Adafruit", "STEMMA Friend RP2040", "0x239a", "0x80e3", 250, "ADAFRUIT_STEMMAFRIEND_RP2040", 8, "boot2_w25q080_2_padded_checksum")
@@ -378,8 +381,9 @@ MakeBoard("challenger_2040_subghz", "iLabs", "Challenger 2040 SubGHz", "0x2e8a",
MakeBoard("challenger_2040_wifi", "iLabs", "Challenger 2040 WiFi", "0x2e8a", "0x1006", 250, "CHALLENGER_2040_WIFI_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
MakeBoard("challenger_2040_wifi_ble", "iLabs", "Challenger 2040 WiFi/BLE", "0x2e8a", "0x102C", 500, "CHALLENGER_2040_WIFI_BLE_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
MakeBoard("challenger_nb_2040_wifi", "iLabs", "Challenger NB 2040 WiFi", "0x2e8a", "0x100d", 500, "CHALLENGER_NB_2040_WIFI_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
MakeBoard("challenger_2040_sdrtc", "iLabs", "Challenger 2040 SD/RTC", "0x2e8a", "0x102d", 250, "CHALLENGER_NB_2040_SDRTC_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("challenger_2040_nfc", "iLabs", "Challenger 2040 NFC", "0x2e8a", "0x1036", 250, "CHALLENGER_NB_2040_NFC_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("challenger_2040_sdrtc", "iLabs", "Challenger 2040 SD/RTC", "0x2e8a", "0x102d", 250, "CHALLENGER_2040_SDRTC_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("challenger_2040_nfc", "iLabs", "Challenger 2040 NFC", "0x2e8a", "0x1036", 250, "CHALLENGER_2040_NFC_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("challenger_2040_uwb", "iLabs", "Challenger 2040 UWB", "0x2e8a", "0x1052", 500, "CHALLENGER_2040_UWB_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("ilabs_rpico32", "iLabs", "RPICO32", "0x2e8a", "0x1010", 250, "ILABS_2040_RPICO32_RP2040", 8, "boot2_w25q080_2_padded_checksum")
# Melopero
@@ -9,6 +9,19 @@
// NeoPixel
#define PIN_NEOPIXEL (4u)
// 'Boot0' button also on GPIO #7
#define PIN_BUTTON (7u)
// DVI connector
#define PIN_CKN (16u)
#define PIN_CKP (17u)
#define PIN_D0N (18u)
#define PIN_D0P (19u)
#define PIN_D1N (20u)
#define PIN_D1P (21u)
#define PIN_D2N (22u)
#define PIN_D2P (23u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
@@ -22,18 +35,23 @@
#define PIN_SPI0_MOSI (15u)
#define PIN_SPI0_SCK (14u)
#define PIN_SPI0_SS (13u)
#define __SPI0_DEVICE spi1
// Not pinned out
#define PIN_SPI1_MISO (31u)
#define PIN_SPI1_MOSI (31u)
#define PIN_SPI1_SCK (31u)
#define PIN_SPI1_SS (31u)
#define __SPI1_DEVICE spi0
// Wire
#define PIN_WIRE0_SDA (2u)
#define PIN_WIRE0_SCL (3u)
#define __WIRE0_DEVICE i2c1
#define PIN_WIRE1_SDA (31u)
#define PIN_WIRE1_SCL (31u)
#define __WIRE1_DEVICE i2c0
#define SERIAL_HOWMANY (2u)
#define SPI_HOWMANY (1u)
@@ -0,0 +1,60 @@
#pragma once
// Pin definitions taken from:
// https://learn.adafruit.com/assets/100337
// LEDs
#define PIN_LED (13u)
// NeoPixel
#define PIN_NEOPIXEL (4u)
// 'Boot0' button also on GPIO #7
#define PIN_BUTTON (7u)
// RFM transceiver module
#define PIN_RFM_CS (16u)
#define PIN_RFM_RST (17u)
#define PIN_RFM_DIO5 (18u)
#define PIN_RFM_DIO3 (19u)
#define PIN_RFM_DIO4 (20u)
#define PIN_RFM_DIO0 (21u)
#define PIN_RFM_DIO1 (22u)
#define PIN_RFM_DIO2 (23u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
// Not pinned out
#define PIN_SERIAL2_TX (31u)
#define PIN_SERIAL2_RX (31u)
// SPI
#define PIN_SPI0_MISO (8u)
#define PIN_SPI0_MOSI (15u)
#define PIN_SPI0_SCK (14u)
#define PIN_SPI0_SS (13u)
#define __SPI0_DEVICE spi1
// Not pinned out
#define PIN_SPI1_MISO (31u)
#define PIN_SPI1_MOSI (31u)
#define PIN_SPI1_SCK (31u)
#define PIN_SPI1_SS (31u)
#define __SPI1_DEVICE spi0
// Wire
#define PIN_WIRE0_SDA (2u)
#define PIN_WIRE0_SCL (3u)
#define __WIRE0_DEVICE i2c1
#define PIN_WIRE1_SDA (31u)
#define PIN_WIRE1_SCL (31u)
#define __WIRE1_DEVICE i2c0
#define SERIAL_HOWMANY (2u)
#define SPI_HOWMANY (1u)
#define WIRE_HOWMANY (1u)
#include "../generic/common.h"
@@ -9,6 +9,19 @@
// NeoPixel
#define PIN_NEOPIXEL (4u)
// 'Boot0' button also on GPIO #7
#define PIN_BUTTON (7u)
// SCORPIO end connector (level-shifted I/O)
#define PIN_NEOPIXEL0 (16u)
#define PIN_NEOPIXEL1 (17u)
#define PIN_NEOPIXEL2 (18u)
#define PIN_NEOPIXEL3 (19u)
#define PIN_NEOPIXEL4 (20u)
#define PIN_NEOPIXEL5 (21u)
#define PIN_NEOPIXEL6 (22u)
#define PIN_NEOPIXEL7 (23u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
@@ -22,18 +35,23 @@
#define PIN_SPI0_MOSI (15u)
#define PIN_SPI0_SCK (14u)
#define PIN_SPI0_SS (13u)
#define __SPI0_DEVICE spi1
// Not pinned out
#define PIN_SPI1_MISO (31u)
#define PIN_SPI1_MOSI (31u)
#define PIN_SPI1_SCK (31u)
#define PIN_SPI1_SS (31u)
#define __SPI1_DEVICE spi0
// Wire
#define PIN_WIRE0_SDA (24u)
#define PIN_WIRE0_SCL (25u)
#define PIN_WIRE1_SDA (2u)
#define PIN_WIRE1_SCL (3u)
#define PIN_WIRE0_SDA (2u)
#define PIN_WIRE0_SCL (3u)
#define __WIRE0_DEVICE i2c1
#define PIN_WIRE1_SDA (31u)
#define PIN_WIRE1_SCL (31u)
#define __WIRE1_DEVICE i2c0
#define SERIAL_HOWMANY (2u)
#define SPI_HOWMANY (1u)
@@ -0,0 +1,59 @@
#pragma once
// Pin definitions taken from:
// https://learn.adafruit.com/assets/100337
// LEDs
#define PIN_LED (13u)
// NeoPixel
#define PIN_NEOPIXEL (21u)
#define NEOPIXEL_POWER (20u)
// 'Boot0' button also on GPIO #7
#define PIN_BUTTON (7u)
// EPD connector
#define PIN_EPD_BUSY (16u)
#define PIN_EPD_RESET (17u)
#define PIN_EPD_DC (18u)
#define PIN_EPD_CS (19u)
#define PIN_EPD_SCK (22u)
#define PIN_EPD_MOSI (23u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
// Not pinned out
#define PIN_SERIAL2_TX (31u)
#define PIN_SERIAL2_RX (31u)
// SPI
#define PIN_SPI0_MISO (8u)
#define PIN_SPI0_MOSI (15u)
#define PIN_SPI0_SCK (14u)
#define PIN_SPI0_SS (13u)
#define __SPI0_DEVICE spi1
// EPD SPI
#define PIN_SPI1_MISO (31u)
#define PIN_SPI1_MOSI (23u)
#define PIN_SPI1_SCK (22u)
#define PIN_SPI1_SS (19u)
#define __SPI1_DEVICE spi0
// Wire
#define PIN_WIRE0_SDA (2u)
#define PIN_WIRE0_SCL (3u)
#define __WIRE0_DEVICE i2c1
#define PIN_WIRE1_SDA (31u)
#define PIN_WIRE1_SCL (31u)
#define __WIRE1_DEVICE i2c0
#define SERIAL_HOWMANY (2u)
#define SPI_HOWMANY (2u)
#define WIRE_HOWMANY (1u)
#include "../generic/common.h"
@@ -0,0 +1,56 @@
#pragma once
// Pin definitions taken from:
// https://learn.adafruit.com/assets/100337
// LEDs
#define PIN_LED (13u)
// NeoPixel
#define PIN_NEOPIXEL (21u)
#define NEOPIXEL_POWER (20u)
// 'Boot0' button also on GPIO #7
#define PIN_BUTTON (7u)
// USB host connector
#define PIN_USB_DP (16u)
#define PIN_USB_DN (17u)
#define PIN_5V_EN (18u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
// Not pinned out
#define PIN_SERIAL2_TX (31u)
#define PIN_SERIAL2_RX (31u)
// SPI
#define PIN_SPI0_MISO (8u)
#define PIN_SPI0_MOSI (15u)
#define PIN_SPI0_SCK (14u)
#define PIN_SPI0_SS (13u)
#define __SPI0_DEVICE spi1
// Not pinned out
#define PIN_SPI1_MISO (31u)
#define PIN_SPI1_MOSI (31u)
#define PIN_SPI1_SCK (31u)
#define PIN_SPI1_SS (31u)
#define __SPI1_DEVICE spi0
// Wire
#define PIN_WIRE0_SDA (2u)
#define PIN_WIRE0_SCL (3u)
#define __WIRE0_DEVICE i2c1
#define PIN_WIRE1_SDA (31u)
#define PIN_WIRE1_SCL (31u)
#define __WIRE1_DEVICE i2c0
#define SERIAL_HOWMANY (2u)
#define SPI_HOWMANY (1u)
#define WIRE_HOWMANY (1u)
#include "../generic/common.h"
+20 -20
View File
@@ -4,33 +4,33 @@
#define _NINA_PINS_
/******************************************************************************
* INCLUDE
INCLUDE
******************************************************************************/
#include "Arduino.h"
/******************************************************************************
* TYPEDEF
TYPEDEF
******************************************************************************/
int getAnalogReadResolution();
class NinaPin {
public:
NinaPin(int _pin) : pin(_pin) {};
int get() {
return pin;
};
int analogReadResolution() {
return getAnalogReadResolution();
};
bool operator== (NinaPin const & other) const {
return pin == other.pin;
}
//operator int() = delete;
__attribute__ ((error("Change me to a #define"))) operator int();
NinaPin(int _pin) : pin(_pin) {};
int get() {
return pin;
};
int analogReadResolution() {
return getAnalogReadResolution();
};
bool operator== (NinaPin const & other) const {
return pin == other.pin;
}
//operator int() = delete;
__attribute__((error("Change me to a #define"))) operator int();
private:
int pin;
int pin;
};
extern NinaPin LEDR;
@@ -44,13 +44,13 @@ extern NinaPin A7;
#define NINA_PINS_AS_CLASS
/******************************************************************************
* FUNCTION DECLARATION
FUNCTION DECLARATION
******************************************************************************/
void pinMode (NinaPin pin, PinMode mode);
PinStatus digitalRead (NinaPin pin);
void pinMode(NinaPin pin, PinMode mode);
PinStatus digitalRead(NinaPin pin);
void digitalWrite(NinaPin pin, PinStatus value);
int analogRead (NinaPin pin);
void analogWrite (NinaPin pin, int value);
int analogRead(NinaPin pin);
void analogWrite(NinaPin pin, int value);
#endif /* _NINA_PINS_ */
+3 -3
View File
@@ -21,9 +21,9 @@ static const uint8_t D13 = (6u);
static const uint8_t D14 = (26u);
static const uint8_t D15 = (27u);
static const uint8_t D16 = (28u);
static const uint8_t D17 = (29u);
static const uint8_t D18 = (12u);
static const uint8_t D19 = (13u);
static const uint8_t D17 = (29u);
static const uint8_t D18 = (12u);
static const uint8_t D19 = (13u);
static const uint8_t D20 = (2u);
static const uint8_t D21 = (24u);
static const uint8_t D22 = (22u);
+14 -14
View File
@@ -47,20 +47,20 @@
#define LED_BUILTIN PIN_LED
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D15 = (14u);
static const uint8_t D16 = (15u);
+74 -66
View File
@@ -22,92 +22,99 @@
#include <ChallengerLTE.h>
Challenger2040LTEClass::Challenger2040LTEClass() {
pinMode(PIN_SARA_ON, OUTPUT);
digitalWrite(PIN_SARA_ON, LOW); // Output register must always be low
pinMode(PIN_SARA_ON, INPUT_PULLUP);
pinMode(PIN_SARA_ON, OUTPUT);
digitalWrite(PIN_SARA_ON, LOW); // Output register must always be low
pinMode(PIN_SARA_ON, INPUT_PULLUP);
pinMode(PIN_SARA_RST, INPUT_PULLUP); // Keep as input for now
pinMode(PIN_SARA_RST, INPUT_PULLUP); // Keep as input for now
pinMode(PIN_SARA_PWR, OUTPUT);
digitalWrite(PIN_SARA_PWR, LOW); // No power to SARA yet
serialPortConfigured = false;
pinMode(PIN_SARA_PWR, OUTPUT);
digitalWrite(PIN_SARA_PWR, LOW); // No power to SARA yet
serialPortConfigured = false;
}
// Do a HW reset by applying a low pulse to the reset line for 1mSec
bool Challenger2040LTEClass::doPowerOn() {
bool ret;
digitalWrite(PIN_SARA_PWR, HIGH); // Make sure LDO is on
delay(100); // let the power stabilize
pinMode(PIN_SARA_ON, OUTPUT); // Pull power on control low
delay(150); // For 150mS
pinMode(PIN_SARA_ON, INPUT_PULLUP); // before releasing it again.
delay(1000); // Now wait for 1 second
SARA_SERIAL_PORT.begin(DEFAULT_SARA_BAUDRATE);
serialPortConfigured = true;
ret = isAlive(); // Makie sure the modem is
// up and running
bool ret;
digitalWrite(PIN_SARA_PWR, HIGH); // Make sure LDO is on
delay(100); // let the power stabilize
pinMode(PIN_SARA_ON, OUTPUT); // Pull power on control low
delay(150); // For 150mS
pinMode(PIN_SARA_ON, INPUT_PULLUP); // before releasing it again.
delay(1000); // Now wait for 1 second
SARA_SERIAL_PORT.begin(DEFAULT_SARA_BAUDRATE);
serialPortConfigured = true;
ret = isAlive(); // Makie sure the modem is
// up and running
delay(250); // Allow for any extra characters
// before flushing the input buffer
while(SARA_SERIAL_PORT.available()) SARA_SERIAL_PORT.read();
delay(250); // Allow for any extra characters
// before flushing the input buffer
while (SARA_SERIAL_PORT.available()) {
SARA_SERIAL_PORT.read();
}
return ret;
return ret;
}
// Checks to see if the modem responds to the "AT" poll command.
bool Challenger2040LTEClass::isAlive(uint32_t timeout) {
SARA_SERIAL_PORT.setTimeout(100);
SARA_SERIAL_PORT.println(F("AT"));
String rdy = SARA_SERIAL_PORT.readStringUntil('\n');
while(!rdy.startsWith(F("OK")) && --timeout) {
SARA_SERIAL_PORT.setTimeout(100);
SARA_SERIAL_PORT.println(F("AT"));
rdy = SARA_SERIAL_PORT.readStringUntil('\n');
//Serial.println(rdy);
}
SARA_SERIAL_PORT.setTimeout(1000); // Restore serial timeout
if (timeout)
return true;
return false;
String rdy = SARA_SERIAL_PORT.readStringUntil('\n');
while (!rdy.startsWith(F("OK")) && --timeout) {
SARA_SERIAL_PORT.println(F("AT"));
rdy = SARA_SERIAL_PORT.readStringUntil('\n');
//Serial.println(rdy);
}
SARA_SERIAL_PORT.setTimeout(1000); // Restore serial timeout
if (timeout) {
return true;
}
return false;
}
// Return the current MNO profile
// Returns -1 if the serial port is not yet setup or the number of the current
// MNO profile setting from the modem.
int Challenger2040LTEClass::getMNOProfile() {
if (!serialPortConfigured)
return -1;
SARA_SERIAL_PORT.println(F("AT+UMNOPROF?"));
String resp = getResponse();
return resp.substring(resp.indexOf("+UMNOPROF: ") + 11).toInt();
if (!serialPortConfigured) {
return -1;
}
SARA_SERIAL_PORT.println(F("AT+UMNOPROF?"));
String resp = getResponse();
return resp.substring(resp.indexOf("+UMNOPROF: ") + 11).toInt();
}
// Set a new MNO profile
// Returns false if the serial port is not yet setup
bool Challenger2040LTEClass::setMNOProfile(int profile) {
if (!serialPortConfigured)
return false;
String cmd = "AT+UMNOPROF=" + String(profile) + ",1";
SARA_SERIAL_PORT.println(cmd);
if (!serialPortConfigured) {
return false;
}
String cmd = "AT+UMNOPROF=" + String(profile) + ",1";
SARA_SERIAL_PORT.println(cmd);
if (!getResponse().endsWith("OK")) {
return false;
}
return true;
if (!getResponse().endsWith("OK")) {
return false;
}
return true;
}
// Disable power save features
bool Challenger2040LTEClass::enablePS(bool enable) {
if (!serialPortConfigured)
return false;
if (enable)
SARA_SERIAL_PORT.println(F("AT+CPSMS=1"));
else
SARA_SERIAL_PORT.println(F("AT+CPSMS=0"));
if (!serialPortConfigured) {
return false;
}
if (enable) {
SARA_SERIAL_PORT.println(F("AT+CPSMS=1"));
} else {
SARA_SERIAL_PORT.println(F("AT+CPSMS=0"));
}
if (!getResponse().endsWith("OK")) {
return false;
}
return true;
if (!getResponse().endsWith("OK")) {
return false;
}
return true;
}
// Get a response from SARA
@@ -116,18 +123,19 @@ bool Challenger2040LTEClass::enablePS(bool enable) {
// from control characters and appended with a tab character as a separator.
//
String Challenger2040LTEClass::getResponse(int timeout) {
SARA_SERIAL_PORT.setTimeout(2000); // allow for really slow responses
SARA_SERIAL_PORT.setTimeout(2000); // allow for really slow responses
String resp = SARA_SERIAL_PORT.readStringUntil('\n');
resp.trim();
String acc = resp;
while(resp.indexOf("OK") == -1 && resp.indexOf("ERROR") == -1 && --timeout) {
resp = SARA_SERIAL_PORT.readStringUntil('\n');
String resp = SARA_SERIAL_PORT.readStringUntil('\n');
resp.trim();
if (resp.length())
acc += "\t" + resp;
}
return acc;
String acc = resp;
while (resp.indexOf("OK") == -1 && resp.indexOf("ERROR") == -1 && --timeout) {
resp = SARA_SERIAL_PORT.readStringUntil('\n');
resp.trim();
if (resp.length()) {
acc += "\t" + resp;
}
}
return acc;
}
Challenger2040LTEClass Challenger2040LTE;
+2 -2
View File
@@ -22,7 +22,7 @@
#define DEFAULT_SARA_BAUDRATE 115200
class Challenger2040LTEClass {
public:
public:
Challenger2040LTEClass();
bool doPowerOn();
bool isAlive(uint32_t timeout = 50);
@@ -31,7 +31,7 @@ class Challenger2040LTEClass {
bool enablePS(bool enable = true);
String getResponse(int timeout = 5);
private:
private:
bool serialPortConfigured;
};
+24 -24
View File
@@ -49,28 +49,28 @@
#define LED_BUILTIN PIN_LED
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (24u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (12u);
static const uint8_t D10 = (11u);
static const uint8_t D11 = (10u);
static const uint8_t D12 = (9u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D15 = (14u);
static const uint8_t D16 = (15u);
static const uint8_t D17 = (19u);
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (24u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (12u);
static const uint8_t D10 = (11u);
static const uint8_t D11 = (10u);
static const uint8_t D12 = (9u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D15 = (14u);
static const uint8_t D16 = (15u);
static const uint8_t D17 = (19u);
static const uint8_t A0 = (29u);
static const uint8_t A1 = (28u);
static const uint8_t A2 = (27u);
static const uint8_t A3 = (26u);
static const uint8_t A4 = (25u);
static const uint8_t A5 = (21u);
static const uint8_t A0 = (29u);
static const uint8_t A1 = (28u);
static const uint8_t A2 = (27u);
static const uint8_t A3 = (26u);
static const uint8_t A4 = (25u);
static const uint8_t A5 = (21u);
+9 -9
View File
@@ -20,15 +20,15 @@
#include <Arduino.h>
/**
* Setup control pins for the NFC chip.
*/
Setup control pins for the NFC chip.
*/
void initVariant() {
// Initialize the interrupt pin to be an input.
// Setting it to an interrupt and connecting a call back is up to the app.
pinMode(PIN_PN7150_IRQ_B, INPUT);
// Initialize the interrupt pin to be an input.
// Setting it to an interrupt and connecting a call back is up to the app.
pinMode(PIN_PN7150_IRQ_B, INPUT);
// Initialize the reset pin to an output and hold the device in reset.
// It is up to the application to release it.
pinMode(PIN_PN7150_RST_B, OUTPUT);
digitalWrite(PIN_PN7150_RST_B, LOW);
// Initialize the reset pin to an output and hold the device in reset.
// It is up to the application to release it.
pinMode(PIN_PN7150_RST_B, OUTPUT);
digitalWrite(PIN_PN7150_RST_B, LOW);
}
+22 -22
View File
@@ -42,26 +42,26 @@
#define LED_BUILTIN PIN_LED
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D18 = (24u);
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D18 = (24u);
static const uint8_t A0 = (26u);
static const uint8_t A1 = (27u);
static const uint8_t A2 = (28u);
static const uint8_t A3 = (29u);
static const uint8_t A4 = (19u);
static const uint8_t A5 = (21u);
static const uint8_t A0 = (26u);
static const uint8_t A1 = (27u);
static const uint8_t A2 = (28u);
static const uint8_t A3 = (29u);
static const uint8_t A4 = (19u);
static const uint8_t A5 = (21u);
+22 -22
View File
@@ -48,26 +48,26 @@
#define LED_BUILTIN PIN_LED
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D18 = (24u);
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D18 = (24u);
static const uint8_t A0 = (26u);
static const uint8_t A1 = (27u);
static const uint8_t A2 = (28u);
static const uint8_t A3 = (29u);
static const uint8_t A4 = (19u);
static const uint8_t A5 = (21u);
static const uint8_t A0 = (26u);
static const uint8_t A1 = (27u);
static const uint8_t A2 = (28u);
static const uint8_t A3 = (29u);
static const uint8_t A4 = (19u);
static const uint8_t A5 = (21u);
+14 -14
View File
@@ -47,20 +47,20 @@
#define LED_BUILTIN PIN_LED
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D15 = (14u);
static const uint8_t D16 = (15u);
@@ -0,0 +1,74 @@
#pragma once
#define PINS_COUNT (25u)
#define NUM_DIGITAL_PINS (25u)
#define NUM_ANALOG_INPUTS (4u)
#define NUM_ANALOG_OUTPUTS (0u)
#define ADC_RESOLUTION (12u)
// LEDs
#define PIN_LED (24u)
// Serial
#define PIN_SERIAL1_TX (16u)
#define PIN_SERIAL1_RX (17u)
// SPI
#define PIN_SPI0_MISO (20u)
#define PIN_SPI0_MOSI (23u)
#define PIN_SPI0_SCK (22u)
#define PIN_SPI0_SS (21u)
// Connected to DWM3000 module
#define PIN_SPI1_MISO (12u)
#define PIN_SPI1_MOSI (11u)
#define PIN_SPI1_SCK (10u)
#define PIN_SPI1_SS (9u)
#define DWM3000_SS PIN_SPI1_SS
#define DWM3000_RST (13u)
#define DWM3000_IRQ (14u)
#define DWM3000_WAKEUP (15u)
#define DWM3000_SPI SPI1
// Wire
#define PIN_WIRE0_SDA (0u)
#define PIN_WIRE0_SCL (1u)
// Not pinned out
#define PIN_WIRE1_SDA (31u)
#define PIN_WIRE1_SCL (31u)
#define PIN_SERIAL2_RX (31u)
#define PIN_SERIAL2_TX (31u)
#define SERIAL_HOWMANY (1u)
#define SPI_HOWMANY (2u)
#define WIRE_HOWMANY (1u)
#define LED_BUILTIN PIN_LED
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (5u);
static const uint8_t D11 = (6u);
static const uint8_t D12 = (7u);
static const uint8_t D13 = (8u);
static const uint8_t D14 = (13u);
static const uint8_t D15 = (14u);
static const uint8_t D16 = (15u);
static const uint8_t D17 = (18u);
static const uint8_t D18 = (24u);
static const uint8_t A0 = (26u);
static const uint8_t A1 = (27u);
static const uint8_t A2 = (28u);
static const uint8_t A3 = (29u);
static const uint8_t A4 = (19u);
static const uint8_t A5 = (21u);
@@ -22,75 +22,77 @@
#include <ChallengerWiFi.h>
Challenger2040WiFiClass::Challenger2040WiFiClass(HardwareSerial* serial) {
_serial = serial;
_serial = serial;
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
}
// Do a HW reset by applying a low pulse to the reset line for 1mSec
void Challenger2040WiFiClass::doHWReset() {
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
delay(1);
digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
delay(1);
digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset
}
// Set the mode flag high to indicate normal run operation and do a HW
// reset.
void Challenger2040WiFiClass::runReset() { // Prepare ESP for normal op
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
doHWReset();
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
doHWReset();
}
// Set the mode flag low to indicate flash operation and do a HW
// reset.
void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start
doHWReset();
digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start
doHWReset();
}
// Wait for the modem to reply with a "ready" prompt. This can be done
// after a sw or hw reset have been performed to ensure that the AT
// interpreter is up and running.
bool Challenger2040WiFiClass::waitForReady() {
int timeout = 20; // Aprox max 2 sec
int timeout = 20; // Aprox max 2 sec
_serial->setTimeout(100);
String rdy = _serial->readStringUntil('\n');
while(!rdy.startsWith("ready") && timeout--) {
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000); // Reset default timeout to 1000
if (timeout)
return true;
return false;
_serial->setTimeout(100);
String rdy = _serial->readStringUntil('\n');
while (!rdy.startsWith("ready") && timeout--) {
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000); // Reset default timeout to 1000
if (timeout) {
return true;
}
return false;
}
// Reset the ESP and wait for the "ready" prompt to be returned.
bool Challenger2040WiFiClass::reset() {
runReset();
_serial->begin(DEFAULT_ESP_BAUDRATE);
return waitForReady();
runReset();
_serial->begin(DEFAULT_ESP_BAUDRATE);
return waitForReady();
}
// Checks to see if the modem responds to the "AT" poll command.
bool Challenger2040WiFiClass::isAlive() {
int timeout = 100;
int timeout = 100;
_serial->setTimeout(250);
_serial->println(F("AT"));
String rdy = _serial->readStringUntil('\n');
while(!rdy.startsWith(F("OK")) && timeout--) {
_serial->setTimeout(250);
_serial->println(F("AT"));
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000);
String rdy = _serial->readStringUntil('\n');
while (!rdy.startsWith(F("OK")) && timeout--) {
_serial->println(F("AT"));
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000);
if (timeout)
return true;
return false;
if (timeout) {
return true;
}
return false;
}
// Change the baud rate of the ESP device as well as the local UART.
@@ -98,19 +100,19 @@ bool Challenger2040WiFiClass::isAlive() {
// baud rates are valid. The function ends by checking if the ESP is
// reachable by doing an "AT" poll.
bool Challenger2040WiFiClass::changeBaudRate(int baud) {
_serial->print(F("AT+UART_CUR="));
_serial->print(baud);
_serial->println(F(",8,1,0,0"));
delay(100);
_serial->end();
_serial->begin(baud);
return isAlive();
_serial->print(F("AT+UART_CUR="));
_serial->print(baud);
_serial->println(F(",8,1,0,0"));
delay(100);
_serial->end();
_serial->begin(baud);
return isAlive();
}
// This method should be called id the builtin object isn't needed any more
// It basically just releases the UART pins for other use.
void Challenger2040WiFiClass::release() {
_serial->end();
_serial->end();
}
// We can assign a new hardware serial port to accommodate the ESP device here.
@@ -121,18 +123,18 @@ void Challenger2040WiFiClass::release() {
// with the ESP instead of the built in hardware serial port.
void Challenger2040WiFiClass::setSerial(HardwareSerial* serial) {
release();
_serial = serial;
release();
_serial = serial;
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
}
// Return the current serial object
HardwareSerial* Challenger2040WiFiClass::getSerial() {
return _serial;
return _serial;
}
Challenger2040WiFiClass Challenger2040WiFi;
@@ -24,7 +24,7 @@
#define DEFAULT_ESP_BAUDRATE DEFAULT_ESP8285_BAUDRATE
class Challenger2040WiFiClass {
public:
public:
Challenger2040WiFiClass(HardwareSerial* = &ESP_SERIAL_PORT);
void doHWReset();
void runReset();
@@ -36,7 +36,7 @@ class Challenger2040WiFiClass {
void release();
void setSerial(HardwareSerial*);
HardwareSerial* getSerial();
private:
private:
HardwareSerial* _serial;
};
+4 -4
View File
@@ -21,9 +21,9 @@
#include <ChallengerWiFi.h>
/**
* Just make sure we try to reset the ESP device before the user starts
* using the device.
*/
Just make sure we try to reset the ESP device before the user starts
using the device.
*/
void initVariant() {
Challenger2040WiFi.reset();
Challenger2040WiFi.reset();
}
+13 -13
View File
@@ -53,19 +53,19 @@
#define LED_BUILTIN PIN_LED
#define NEOPIXEL (11u)
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (24u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (6u);
static const uint8_t D10 = (7u);
static const uint8_t D11 = (8u);
static const uint8_t D12 = (9u);
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (24u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (6u);
static const uint8_t D10 = (7u);
static const uint8_t D11 = (8u);
static const uint8_t D12 = (9u);
static const uint8_t D13 = (10u);
static const uint8_t D14 = (11u);
static const uint8_t D15 = (12u);
@@ -22,75 +22,77 @@
#include <ChallengerWiFi.h>
Challenger2040WiFiClass::Challenger2040WiFiClass(HardwareSerial* serial) {
_serial = serial;
_serial = serial;
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
}
// Do a HW reset by applying a low pulse to the reset line for 1mSec
void Challenger2040WiFiClass::doHWReset() {
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
delay(1);
digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
delay(1);
digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset
}
// Set the mode flag high to indicate normal run operation and do a HW
// reset.
void Challenger2040WiFiClass::runReset() { // Prepare ESP for normal op
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
doHWReset();
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
doHWReset();
}
// Set the mode flag low to indicate flash operation and do a HW
// reset.
void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start
doHWReset();
digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start
doHWReset();
}
// Wait for the modem to reply with a "ready" prompt. This can be done
// after a sw or hw reset have been performed to ensure that the AT
// interpreter is up and running.
bool Challenger2040WiFiClass::waitForReady() {
int timeout = 20; // Aprox max 2 sec
int timeout = 20; // Aprox max 2 sec
_serial->setTimeout(100);
String rdy = _serial->readStringUntil('\n');
while(!rdy.startsWith("ready") && timeout--) {
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000); // Reset default timeout to 1000
if (timeout)
return true;
return false;
_serial->setTimeout(100);
String rdy = _serial->readStringUntil('\n');
while (!rdy.startsWith("ready") && timeout--) {
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000); // Reset default timeout to 1000
if (timeout) {
return true;
}
return false;
}
// Reset the ESP and wait for the "ready" prompt to be returned.
bool Challenger2040WiFiClass::reset() {
runReset();
_serial->begin(DEFAULT_ESP_BAUDRATE);
return waitForReady();
runReset();
_serial->begin(DEFAULT_ESP_BAUDRATE);
return waitForReady();
}
// Checks to see if the modem responds to the "AT" poll command.
bool Challenger2040WiFiClass::isAlive() {
int timeout = 100;
int timeout = 100;
_serial->setTimeout(250);
_serial->println(F("AT"));
String rdy = _serial->readStringUntil('\n');
while(!rdy.startsWith(F("OK")) && timeout--) {
_serial->setTimeout(250);
_serial->println(F("AT"));
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000);
String rdy = _serial->readStringUntil('\n');
while (!rdy.startsWith(F("OK")) && timeout--) {
_serial->println(F("AT"));
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000);
if (timeout)
return true;
return false;
if (timeout) {
return true;
}
return false;
}
// Change the baud rate of the ESP device as well as the local UART.
@@ -98,19 +100,19 @@ bool Challenger2040WiFiClass::isAlive() {
// baud rates are valid. The function ends by checking if the ESP is
// reachable by doing an "AT" poll.
bool Challenger2040WiFiClass::changeBaudRate(int baud) {
_serial->print(F("AT+UART_CUR="));
_serial->print(baud);
_serial->println(F(",8,1,0,0"));
delay(100);
_serial->end();
_serial->begin(baud);
return isAlive();
_serial->print(F("AT+UART_CUR="));
_serial->print(baud);
_serial->println(F(",8,1,0,0"));
delay(100);
_serial->end();
_serial->begin(baud);
return isAlive();
}
// This method should be called id the builtin object isn't needed any more
// It basically just releases the UART pins for other use.
void Challenger2040WiFiClass::release() {
_serial->end();
_serial->end();
}
// We can assign a new hardware serial port to accommodate the ESP device here.
@@ -121,18 +123,18 @@ void Challenger2040WiFiClass::release() {
// with the ESP instead of the built in hardware serial port.
void Challenger2040WiFiClass::setSerial(HardwareSerial* serial) {
release();
_serial = serial;
release();
_serial = serial;
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
}
// Return the current serial object
HardwareSerial* Challenger2040WiFiClass::getSerial() {
return _serial;
return _serial;
}
Challenger2040WiFiClass Challenger2040WiFi;
@@ -24,7 +24,7 @@
#define DEFAULT_ESP_BAUDRATE DEFAULT_ESP32_BAUDRATE
class Challenger2040WiFiClass {
public:
public:
Challenger2040WiFiClass(HardwareSerial* = &ESP_SERIAL_PORT);
void doHWReset();
void runReset();
@@ -36,7 +36,7 @@ class Challenger2040WiFiClass {
void release();
void setSerial(HardwareSerial*);
HardwareSerial* getSerial();
private:
private:
HardwareSerial* _serial;
};
@@ -21,9 +21,9 @@
#include <ChallengerWiFi.h>
/**
* Just make sure we try to reset the ESP device before the user starts
* using the device.
*/
Just make sure we try to reset the ESP device before the user starts
using the device.
*/
void initVariant() {
Challenger2040WiFi.reset();
Challenger2040WiFi.reset();
}
@@ -56,19 +56,19 @@
#define LED_BUILTIN PIN_LED
#define NEOPIXEL (11u)
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (6u);
static const uint8_t D10 = (7u);
static const uint8_t D11 = (8u);
static const uint8_t D12 = (9u);
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (20u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (6u);
static const uint8_t D10 = (7u);
static const uint8_t D11 = (8u);
static const uint8_t D12 = (9u);
static const uint8_t D13 = (10u);
static const uint8_t D14 = (11u);
static const uint8_t D15 = (12u);
@@ -22,75 +22,77 @@
#include <ChallengerWiFi.h>
Challenger2040WiFiClass::Challenger2040WiFiClass(HardwareSerial* serial) {
_serial = serial;
_serial = serial;
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
}
// Do a HW reset by applying a low pulse to the reset line for 1mSec
void Challenger2040WiFiClass::doHWReset() {
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
delay(1);
digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
delay(1);
digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset
}
// Set the mode flag high to indicate normal run operation and do a HW
// reset.
void Challenger2040WiFiClass::runReset() { // Prepare ESP for normal op
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
doHWReset();
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
doHWReset();
}
// Set the mode flag low to indicate flash operation and do a HW
// reset.
void Challenger2040WiFiClass::flashReset() { // Prepare ESP for flashing
digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start
doHWReset();
digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start
doHWReset();
}
// Wait for the modem to reply with a "ready" prompt. This can be done
// after a sw or hw reset have been performed to ensure that the AT
// interpreter is up and running.
bool Challenger2040WiFiClass::waitForReady() {
int timeout = 20; // Aprox max 2 sec
int timeout = 20; // Aprox max 2 sec
_serial->setTimeout(100);
String rdy = _serial->readStringUntil('\n');
while(!rdy.startsWith("ready") && timeout--) {
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000); // Reset default timeout to 1000
if (timeout)
return true;
return false;
_serial->setTimeout(100);
String rdy = _serial->readStringUntil('\n');
while (!rdy.startsWith("ready") && timeout--) {
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000); // Reset default timeout to 1000
if (timeout) {
return true;
}
return false;
}
// Reset the ESP and wait for the "ready" prompt to be returned.
bool Challenger2040WiFiClass::reset() {
runReset();
_serial->begin(DEFAULT_ESP_BAUDRATE);
return waitForReady();
runReset();
_serial->begin(DEFAULT_ESP_BAUDRATE);
return waitForReady();
}
// Checks to see if the modem responds to the "AT" poll command.
bool Challenger2040WiFiClass::isAlive() {
int timeout = 100;
int timeout = 100;
_serial->setTimeout(250);
_serial->println(F("AT"));
String rdy = _serial->readStringUntil('\n');
while(!rdy.startsWith(F("OK")) && timeout--) {
_serial->setTimeout(250);
_serial->println(F("AT"));
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000);
String rdy = _serial->readStringUntil('\n');
while (!rdy.startsWith(F("OK")) && timeout--) {
_serial->println(F("AT"));
rdy = _serial->readStringUntil('\n');
}
_serial->setTimeout(1000);
if (timeout)
return true;
return false;
if (timeout) {
return true;
}
return false;
}
// Change the baud rate of the ESP device as well as the local UART.
@@ -98,19 +100,19 @@ bool Challenger2040WiFiClass::isAlive() {
// baud rates are valid. The function ends by checking if the ESP is
// reachable by doing an "AT" poll.
bool Challenger2040WiFiClass::changeBaudRate(int baud) {
_serial->print(F("AT+UART_CUR="));
_serial->print(baud);
_serial->println(F(",8,1,0,0"));
delay(100);
_serial->end();
_serial->begin(baud);
return isAlive();
_serial->print(F("AT+UART_CUR="));
_serial->print(baud);
_serial->println(F(",8,1,0,0"));
delay(100);
_serial->end();
_serial->begin(baud);
return isAlive();
}
// This method should be called id the builtin object isn't needed any more
// It basically just releases the UART pins for other use.
void Challenger2040WiFiClass::release() {
_serial->end();
_serial->end();
}
// We can assign a new hardware serial port to accommodate the ESP device here.
@@ -121,18 +123,18 @@ void Challenger2040WiFiClass::release() {
// with the ESP instead of the built in hardware serial port.
void Challenger2040WiFiClass::setSerial(HardwareSerial* serial) {
release();
_serial = serial;
release();
_serial = serial;
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
}
// Return the current serial object
HardwareSerial* Challenger2040WiFiClass::getSerial() {
return _serial;
return _serial;
}
Challenger2040WiFiClass Challenger2040WiFi;
@@ -24,7 +24,7 @@
#define DEFAULT_ESP_BAUDRATE DEFAULT_ESP8285_BAUDRATE
class Challenger2040WiFiClass {
public:
public:
Challenger2040WiFiClass(HardwareSerial* = &ESP_SERIAL_PORT);
void doHWReset();
void runReset();
@@ -36,7 +36,7 @@ class Challenger2040WiFiClass {
void release();
void setSerial(HardwareSerial*);
HardwareSerial* getSerial();
private:
private:
HardwareSerial* _serial;
};
@@ -21,9 +21,9 @@
#include <ChallengerWiFi.h>
/**
* Just make sure we try to reset the ESP device before the user starts
* using the device.
*/
Just make sure we try to reset the ESP device before the user starts
using the device.
*/
void initVariant() {
Challenger2040WiFi.reset();
Challenger2040WiFi.reset();
}
+13 -13
View File
@@ -53,19 +53,19 @@
#define LED_BUILTIN PIN_LED
#define NEOPIXEL (11u)
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (24u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (6u);
static const uint8_t D10 = (7u);
static const uint8_t D11 = (8u);
static const uint8_t D12 = (9u);
static const uint8_t D0 = (16u);
static const uint8_t D1 = (17u);
static const uint8_t D2 = (24u);
static const uint8_t D3 = (23u);
static const uint8_t D4 = (22u);
static const uint8_t D5 = (2u);
static const uint8_t D6 = (3u);
static const uint8_t D7 = (0u);
static const uint8_t D8 = (1u);
static const uint8_t D9 = (6u);
static const uint8_t D10 = (7u);
static const uint8_t D11 = (8u);
static const uint8_t D12 = (9u);
static const uint8_t D13 = (10u);
static const uint8_t D14 = (14u);
static const uint8_t D15 = (15u);
@@ -16,7 +16,7 @@
#define PIN_SERIAL2_RX (5u)
// SPI
#define PIN_SPI0_MISO (0u)
#define PIN_SPI0_MISO (0u)
#define PIN_SPI0_MOSI (3u)
#define PIN_SPI0_SCK (2u)
#define PIN_SPI0_SS (1u)
@@ -28,8 +28,8 @@
#define PIN_SPI1_SS (31u)
// Wire
#define PIN_WIRE0_SDA (4u)
#define PIN_WIRE0_SCL (5u)
#define PIN_WIRE0_SDA (4u)
#define PIN_WIRE0_SCL (5u)
#define PIN_WIRE1_SDA (2u)
#define PIN_WIRE1_SCL (3u)

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