aboutsummaryrefslogtreecommitdiffstats
path: root/arduino/libraries/Bluefruit52Lib/examples
diff options
context:
space:
mode:
Diffstat (limited to 'arduino/libraries/Bluefruit52Lib/examples')
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart/central_bleuart.ino207
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart_multi/central_bleuart_multi.ino318
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm/central_custom_hrm.ino205
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_hid/central_hid.ino226
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_scan/central_scan.ino73
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_scan_advanced/central_scan_advanced.ino218
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_ti_sensortag_optical/central_ti_sensortag_optical.ino309
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/DualRoles/dual_bleuart/dual_bleuart.ino212
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/Fading/Fading.ino45
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/Serial1_test/Serial1_test.ino46
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/SerialEcho/SerialEcho.ino45
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/adc/adc.ino21
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/adc_vbat/adc_vbat.ino93
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/blinky/blinky.ino30
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/dfu_ota/dfu_ota.ino28
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/dfu_serial/dfu_serial.ino29
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/digital_interrupt_deferred/digital_interrupt_deferred.ino46
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/fwinfo/fwinfo.ino33
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/gpstest_swuart/gpstest_swuart.ino57
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/hw_systick/hw_systick.ino57
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/hwinfo/hwinfo.ino42
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/hwpwm/hwpwm.ino81
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/meminfo/meminfo.ino33
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/nfc_to_gpio/nfc_to_gpio.ino40
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/rtos_scheduler/rtos_scheduler.ino49
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Hardware/software_timer/software_timer.ino58
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/LICENSE.txt458
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/StandardFirmataBLE.ino916
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/adv_advanced/adv_advanced.ino91
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/ancs/ancs.ino217
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/ancs_oled/ancs_oled.ino458
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/beacon/beacon.ino93
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/blemidi/blemidi.ino182
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/bleuart/bleuart.ino142
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/blinky_ota/blinky_ota.ino63
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/clearbonds/clearbonds.ino54
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/client_cts/client_cts.ino176
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/client_cts_oled/client_cts_oled.ino193
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/controller/controller.ino182
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/controller/packetParser.cpp134
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_hrm/custom_hrm.ino224
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.cpp106
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.h89
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/custom_htm.ino219
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/eddystone_url/eddystone_url.ino73
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_camerashutter/hid_camerashutter.ino131
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyboard/hid_keyboard.ino146
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyscan/hid_keyscan.ino194
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_mouse/hid_mouse.ino146
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/neomatrix/neomatrix.ino168
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/neopixel/neopixel.ino350
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Peripheral/throughput/throughput.ino183
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Projects/homekit/homekit_lightbulb/homekit_lightbulb.ino189
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/README.md24
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_central/rssi_proximity_central.ino683
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_peripheral/rssi_proximity_peripheral.ino160
56 files changed, 9045 insertions, 0 deletions
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart/central_bleuart.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart/central_bleuart.ino
new file mode 100755
index 0000000..8c59162
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart/central_bleuart.ino
@@ -0,0 +1,207 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/*
+ * This sketch demonstrate the central API(). A additional bluefruit
+ * that has bleuart as peripheral is required for the demo.
+ */
+#include <bluefruit.h>
+
+BLEClientBas clientBas; // battery client
+BLEClientDis clientDis; // device information client
+BLEClientUart clientUart; // bleuart client
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Central BLEUART Example");
+ Serial.println("-----------------------------------\n");
+
+ // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
+ // SRAM usage required by SoftDevice will increase dramatically with number of connections
+ Bluefruit.begin(0, 1);
+
+ Bluefruit.setName("Bluefruit52 Central");
+
+ // Configure Battyer client
+ clientBas.begin();
+
+ // Configure DIS client
+ clientDis.begin();
+
+ // Init BLE Central Uart Serivce
+ clientUart.begin();
+ clientUart.setRxCallback(bleuart_rx_callback);
+
+ // Increase Blink rate to different from PrPh advertising mode
+ Bluefruit.setConnLedInterval(250);
+
+ // Callbacks for Central
+ Bluefruit.Central.setConnectCallback(connect_callback);
+ Bluefruit.Central.setDisconnectCallback(disconnect_callback);
+
+ /* Start Central Scanning
+ * - Enable auto scan if disconnected
+ * - Interval = 100 ms, window = 80 ms
+ * - Don't use active scan
+ * - Start(timeout) with timeout = 0 will scan forever (until connected)
+ */
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.restartOnDisconnect(true);
+ Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
+ Bluefruit.Scanner.useActiveScan(false);
+ Bluefruit.Scanner.start(0); // // 0 = Don't stop scanning after n seconds
+}
+
+/**
+ * Callback invoked when scanner pick up an advertising data
+ * @param report Structural advertising data
+ */
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ // Check if advertising contain BleUart service
+ if ( Bluefruit.Scanner.checkReportForService(report, clientUart) )
+ {
+ Serial.print("BLE UART service detected. Connecting ... ");
+
+ // Connect to device with bleuart service in advertising
+ Bluefruit.Central.connect(report);
+ }else
+ {
+ // For Softdevice v6: after received a report, scanner will be paused
+ // We need to call Scanner resume() to continue scanning
+ Bluefruit.Scanner.resume();
+ }
+}
+
+/**
+ * Callback invoked when an connection is established
+ * @param conn_handle
+ */
+void connect_callback(uint16_t conn_handle)
+{
+ Serial.println("Connected");
+
+ Serial.print("Dicovering Device Information ... ");
+ if ( clientDis.discover(conn_handle) )
+ {
+ Serial.println("Found it");
+ char buffer[32+1];
+
+ // read and print out Manufacturer
+ memset(buffer, 0, sizeof(buffer));
+ if ( clientDis.getManufacturer(buffer, sizeof(buffer)) )
+ {
+ Serial.print("Manufacturer: ");
+ Serial.println(buffer);
+ }
+
+ // read and print out Model Number
+ memset(buffer, 0, sizeof(buffer));
+ if ( clientDis.getModel(buffer, sizeof(buffer)) )
+ {
+ Serial.print("Model: ");
+ Serial.println(buffer);
+ }
+
+ Serial.println();
+ }else
+ {
+ Serial.println("Found NONE");
+ }
+
+ Serial.print("Dicovering Battery ... ");
+ if ( clientBas.discover(conn_handle) )
+ {
+ Serial.println("Found it");
+ Serial.print("Battery level: ");
+ Serial.print(clientBas.read());
+ Serial.println("%");
+ }else
+ {
+ Serial.println("Found NONE");
+ }
+
+ Serial.print("Discovering BLE Uart Service ... ");
+ if ( clientUart.discover(conn_handle) )
+ {
+ Serial.println("Found it");
+
+ Serial.println("Enable TXD's notify");
+ clientUart.enableTXD();
+
+ Serial.println("Ready to receive from peripheral");
+ }else
+ {
+ Serial.println("Found NONE");
+
+ // disconect since we couldn't find bleuart service
+ Bluefruit.Central.disconnect(conn_handle);
+ }
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println("Disconnected");
+}
+
+/**
+ * Callback invoked when uart received data
+ * @param uart_svc Reference object to the service where the data
+ * arrived. In this example it is clientUart
+ */
+void bleuart_rx_callback(BLEClientUart& uart_svc)
+{
+ Serial.print("[RX]: ");
+
+ while ( uart_svc.available() )
+ {
+ Serial.print( (char) uart_svc.read() );
+ }
+
+ Serial.println();
+}
+
+void loop()
+{
+ if ( Bluefruit.Central.connected() )
+ {
+ // Not discovered yet
+ if ( clientUart.discovered() )
+ {
+ // Discovered means in working state
+ // Get Serial input and send to Peripheral
+ if ( Serial.available() )
+ {
+ delay(2); // delay a bit for all characters to arrive
+
+ char str[20+1] = { 0 };
+ Serial.readBytes(str, 20);
+
+ clientUart.print( str );
+ }
+ }
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart_multi/central_bleuart_multi.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart_multi/central_bleuart_multi.ino
new file mode 100755
index 0000000..4796c4e
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart_multi/central_bleuart_multi.ino
@@ -0,0 +1,318 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch demonstrates the central API() that allows you to connect
+ * to multiple peripherals boards (Bluefruit nRF52 in peripheral mode, or
+ * any Bluefruit nRF51 boards).
+ *
+ * One or more Bluefruit boards, configured as a peripheral with the
+ * bleuart service running are required for this demo.
+ *
+ * This sketch will:
+ * - Read data from the HW serial port (normally USB serial, accessible
+ * via the Serial Monitor for example), and send any incoming data to
+ * all other peripherals connected to the central device.
+ * - Forward any incoming bleuart messages from a peripheral to all of
+ * the other connected devices.
+ *
+ * It is recommended to give each peripheral board a distinct name in order
+ * to more easily distinguish the individual devices.
+ *
+ * Connection Handle Explanation
+ * -----------------------------
+ * The total number of connections is BLE_MAX_CONN = BLE_PRPH_MAX_CONN + BLE_CENTRAL_MAX_CONN.
+ *
+ * The 'connection handle' is an integer number assigned by the SoftDevice
+ * (Nordic's proprietary BLE stack). Each connection will receive it's own
+ * numeric 'handle' starting from 0 to BLE_MAX_CONN-1, depending on the order
+ * of connection(s).
+ *
+ * - E.g If our Central board connects to a mobile phone first (running as a peripheral),
+ * then afterwards connects to another Bluefruit board running in peripheral mode, then
+ * the connection handle of mobile phone is 0, and the handle for the Bluefruit
+ * board is 1, and so on.
+ */
+
+/* LED PATTERNS
+ * ------------
+ * LED_RED - Blinks pattern changes based on the number of connections.
+ * LED_BLUE - Blinks constantly when scanning
+ */
+
+#include <bluefruit.h>
+
+// Struct containing peripheral info
+typedef struct
+{
+ char name[32];
+
+ uint16_t conn_handle;
+
+ // Each prph need its own bleuart client service
+ BLEClientUart bleuart;
+} prph_info_t;
+
+/* Peripheral info array (one per peripheral device)
+ *
+ * There are 'BLE_CENTRAL_MAX_CONN' central connections, but the
+ * the connection handle can be numerically larger (for example if
+ * the peripheral role is also used, such as connecting to a mobile
+ * device). As such, we need to convert connection handles <-> the array
+ * index where appropriate to prevent out of array accesses.
+ *
+ * Note: One can simply declares the array with BLE_MAX_CONN and use connection
+ * handle as index directly with the expense of SRAM.
+ */
+prph_info_t prphs[BLE_CENTRAL_MAX_CONN];
+
+// Software Timer for blinking the RED LED
+SoftwareTimer blinkTimer;
+uint8_t connection_num = 0; // for blink pattern
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ // Initialize blinkTimer for 100 ms and start it
+ blinkTimer.begin(100, blink_timer_callback);
+ blinkTimer.start();
+
+ Serial.println("Bluefruit52 Central Multi BLEUART Example");
+ Serial.println("-----------------------------------------\n");
+
+ // Initialize Bluefruit with max concurrent connections as Peripheral = 1, Central = 1
+ // SRAM usage required by SoftDevice will increase with number of connections
+ Bluefruit.begin(0, 4);
+
+ // Set Name
+ Bluefruit.setName("Bluefruit52 Central");
+
+ // Init peripheral pool
+ for (uint8_t idx=0; idx<BLE_CENTRAL_MAX_CONN; idx++)
+ {
+ // Invalid all connection handle
+ prphs[idx].conn_handle = BLE_CONN_HANDLE_INVALID;
+
+ // All of BLE Central Uart Serivce
+ prphs[idx].bleuart.begin();
+ prphs[idx].bleuart.setRxCallback(bleuart_rx_callback);
+ }
+
+ // Callbacks for Central
+ Bluefruit.Central.setConnectCallback(connect_callback);
+ Bluefruit.Central.setDisconnectCallback(disconnect_callback);
+
+ /* Start Central Scanning
+ * - Enable auto scan if disconnected
+ * - Interval = 100 ms, window = 80 ms
+ * - Filter only accept bleuart service in advertising
+ * - Don't use active scan (used to retrieve the optional scan response adv packet)
+ * - Start(0) = will scan forever since no timeout is given
+ */
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.restartOnDisconnect(true);
+ Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms
+ Bluefruit.Scanner.filterUuid(BLEUART_UUID_SERVICE);
+ Bluefruit.Scanner.useActiveScan(false); // Don't request scan response data
+ Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
+}
+
+/**
+ * Callback invoked when scanner picks up an advertising packet
+ * @param report Structural advertising data
+ */
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ // Since we configure the scanner with filterUuid()
+ // Scan callback only invoked for device with bleuart service advertised
+ // Connect to the device with bleuart service in advertising packet
+ Bluefruit.Central.connect(report);
+}
+
+/**
+ * Callback invoked when an connection is established
+ * @param conn_handle
+ */
+void connect_callback(uint16_t conn_handle)
+{
+ // Find an available ID to use
+ int id = findConnHandle(BLE_CONN_HANDLE_INVALID);
+
+ // Eeek: Exceeded the number of connections !!!
+ if ( id < 0 ) return;
+
+ prph_info_t* peer = &prphs[id];
+ peer->conn_handle = conn_handle;
+
+ Bluefruit.Gap.getPeerName(conn_handle, peer->name, 32);
+
+ Serial.print("Connected to ");
+ Serial.println(peer->name);
+
+ Serial.print("Discovering BLE UART service ... ");
+
+ if ( peer->bleuart.discover(conn_handle) )
+ {
+ Serial.println("Found it");
+ Serial.println("Enabling TXD characteristic's CCCD notify bit");
+ peer->bleuart.enableTXD();
+
+ Serial.println("Continue scanning for more peripherals");
+ Bluefruit.Scanner.start(0);
+
+ Serial.println("Enter some text in the Serial Monitor to send it to all connected peripherals:");
+ } else
+ {
+ Serial.println("Found ... NOTHING!");
+
+ // disconect since we couldn't find bleuart service
+ Bluefruit.Central.disconnect(conn_handle);
+ }
+
+ connection_num++;
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ connection_num--;
+
+ // Mark the ID as invalid
+ int id = findConnHandle(conn_handle);
+
+ // Non-existant connection, something went wrong, DBG !!!
+ if ( id < 0 ) return;
+
+ // Mark conn handle as invalid
+ prphs[id].conn_handle = BLE_CONN_HANDLE_INVALID;
+
+ Serial.print(prphs[id].name);
+ Serial.println(" disconnected!");
+}
+
+/**
+ * Callback invoked when BLE UART data is received
+ * @param uart_svc Reference object to the service where the data
+ * arrived.
+ */
+void bleuart_rx_callback(BLEClientUart& uart_svc)
+{
+ // uart_svc is prphs[conn_handle].bleuart
+ uint16_t conn_handle = uart_svc.connHandle();
+
+ int id = findConnHandle(conn_handle);
+ prph_info_t* peer = &prphs[id];
+
+ // Print sender's name
+ Serial.printf("[From %s]: ", peer->name);
+
+ // Read then forward to all peripherals
+ while ( uart_svc.available() )
+ {
+ // default MTU with an extra byte for string terminator
+ char buf[20+1] = { 0 };
+
+ if ( uart_svc.read(buf,sizeof(buf)-1) )
+ {
+ Serial.println(buf);
+ sendAll(buf);
+ }
+ }
+}
+
+/**
+ * Helper function to send a string to all connected peripherals
+ */
+void sendAll(const char* str)
+{
+ Serial.print("[Send to All]: ");
+ Serial.println(str);
+
+ for(uint8_t id=0; id < BLE_CENTRAL_MAX_CONN; id++)
+ {
+ prph_info_t* peer = &prphs[id];
+
+ if ( peer->bleuart.discovered() )
+ {
+ peer->bleuart.print(str);
+ }
+ }
+}
+
+void loop()
+{
+ // First check if we are connected to any peripherals
+ if ( Bluefruit.Central.connected() )
+ {
+ // default MTU with an extra byte for string terminator
+ char buf[20+1] = { 0 };
+
+ // Read from HW Serial (normally USB Serial) and send to all peripherals
+ if ( Serial.readBytes(buf, sizeof(buf)-1) )
+ {
+ sendAll(buf);
+ }
+ }
+}
+
+/**
+ * Find the connection handle in the peripheral array
+ * @param conn_handle Connection handle
+ * @return array index if found, otherwise -1
+ */
+int findConnHandle(uint16_t conn_handle)
+{
+ for(int id=0; id<BLE_CENTRAL_MAX_CONN; id++)
+ {
+ if (conn_handle == prphs[id].conn_handle)
+ {
+ return id;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Software Timer callback is invoked via a built-in FreeRTOS thread with
+ * minimal stack size. Therefore it should be as simple as possible. If
+ * a periodically heavy task is needed, please use Scheduler.startLoop() to
+ * create a dedicated task for it.
+ *
+ * More information http://www.freertos.org/RTOS-software-timer.html
+ */
+void blink_timer_callback(TimerHandle_t xTimerID)
+{
+ (void) xTimerID;
+
+ // Period of sequence is 10 times (1 second).
+ // RED LED will toggle first 2*n times (on/off) and remain off for the rest of period
+ // Where n = number of connection
+ static uint8_t count = 0;
+
+ if ( count < 2*connection_num ) digitalToggle(LED_RED);
+ if ( count % 2 && digitalRead(LED_RED)) digitalWrite(LED_RED, LOW); // issue #98
+
+ count++;
+ if (count >= 10) count = 0;
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm/central_custom_hrm.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm/central_custom_hrm.ino
new file mode 100755
index 0000000..a0cef0c
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm/central_custom_hrm.ino
@@ -0,0 +1,205 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch show how to use BLEClientService and BLEClientCharacteristic
+ * to implement a custom client that is used to talk with Gatt server on
+ * peripheral.
+ *
+ * Note: you will need another feather52 running peripheral/custom_HRM sketch
+ * to test with.
+ */
+
+#include <bluefruit.h>
+
+/* HRM Service Definitions
+ * Heart Rate Monitor Service: 0x180D
+ * Heart Rate Measurement Char: 0x2A37 (Mandatory)
+ * Body Sensor Location Char: 0x2A38 (Optional)
+ */
+
+BLEClientService hrms(UUID16_SVC_HEART_RATE);
+BLEClientCharacteristic hrmc(UUID16_CHR_HEART_RATE_MEASUREMENT);
+BLEClientCharacteristic bslc(UUID16_CHR_BODY_SENSOR_LOCATION);
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Central Custom HRM Example");
+ Serial.println("--------------------------------------\n");
+
+ // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
+ // SRAM usage required by SoftDevice will increase dramatically with number of connections
+ Bluefruit.begin(0, 1);
+
+ Bluefruit.setName("Bluefruit52 Central");
+
+ // Initialize HRM client
+ hrms.begin();
+
+ // Initialize client characteristics of HRM.
+ // Note: Client Char will be added to the last service that is begin()ed.
+ bslc.begin();
+
+ // set up callback for receiving measurement
+ hrmc.setNotifyCallback(hrm_notify_callback);
+ hrmc.begin();
+
+ // Increase Blink rate to different from PrPh advertising mode
+ Bluefruit.setConnLedInterval(250);
+
+ // Callbacks for Central
+ Bluefruit.Central.setDisconnectCallback(disconnect_callback);
+ Bluefruit.Central.setConnectCallback(connect_callback);
+
+ /* Start Central Scanning
+ * - Enable auto scan if disconnected
+ * - Interval = 100 ms, window = 80 ms
+ * - Don't use active scan
+ * - Filter only accept HRM service
+ * - Start(timeout) with timeout = 0 will scan forever (until connected)
+ */
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.restartOnDisconnect(true);
+ Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
+ Bluefruit.Scanner.filterUuid(hrms.uuid);
+ Bluefruit.Scanner.useActiveScan(false);
+ Bluefruit.Scanner.start(0); // // 0 = Don't stop scanning after n seconds
+}
+
+void loop()
+{
+ // do nothing
+}
+
+/**
+ * Callback invoked when scanner pick up an advertising data
+ * @param report Structural advertising data
+ */
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ // Since we configure the scanner with filterUuid()
+ // Scan callback only invoked for device with hrm service advertised
+ // Connect to device with HRM service in advertising
+ Bluefruit.Central.connect(report);
+}
+
+/**
+ * Callback invoked when an connection is established
+ * @param conn_handle
+ */
+void connect_callback(uint16_t conn_handle)
+{
+ Serial.println("Connected");
+ Serial.print("Discovering HRM Service ... ");
+
+ // If HRM is not found, disconnect and return
+ if ( !hrms.discover(conn_handle) )
+ {
+ Serial.println("Found NONE");
+
+ // disconect since we couldn't find HRM service
+ Bluefruit.Central.disconnect(conn_handle);
+
+ return;
+ }
+
+ // Once HRM service is found, we continue to discover its characteristic
+ Serial.println("Found it");
+
+ Serial.print("Discovering Measurement characteristic ... ");
+ if ( !hrmc.discover() )
+ {
+ // Measurement chr is mandatory, if it is not found (valid), then disconnect
+ Serial.println("not found !!!");
+ Serial.println("Measurement characteristic is mandatory but not found");
+ Bluefruit.Central.disconnect(conn_handle);
+ return;
+ }
+ Serial.println("Found it");
+
+ // Measurement is found, continue to look for option Body Sensor Location
+ // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml
+ // Body Sensor Location is optional, print out the location in text if present
+ Serial.print("Discovering Body Sensor Location characteristic ... ");
+ if ( bslc.discover() )
+ {
+ Serial.println("Found it");
+
+ // Body sensor location value is 8 bit
+ const char* body_str[] = { "Other", "Chest", "Wrist", "Finger", "Hand", "Ear Lobe", "Foot" };
+
+ // Read 8-bit BSLC value from peripheral
+ uint8_t loc_value = bslc.read8();
+
+ Serial.print("Body Location Sensor: ");
+ Serial.println(body_str[loc_value]);
+ }else
+ {
+ Serial.println("Found NONE");
+ }
+
+ // Reaching here means we are ready to go, let's enable notification on measurement chr
+ if ( hrmc.enableNotify() )
+ {
+ Serial.println("Ready to receive HRM Measurement value");
+ }else
+ {
+ Serial.println("Couldn't enable notify for HRM Measurement. Increase DEBUG LEVEL for troubleshooting");
+ }
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println("Disconnected");
+}
+
+
+/**
+ * Hooked callback that triggered when a measurement value is sent from peripheral
+ * @param chr Pointer client characteristic that even occurred,
+ * in this example it should be hrmc
+ * @param data Pointer to received data
+ * @param len Length of received data
+ */
+void hrm_notify_callback(BLEClientCharacteristic* chr, uint8_t* data, uint16_t len)
+{
+ // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml
+ // Measurement contains of control byte0 and measurement (8 or 16 bit) + optional field
+ // if byte0's bit0 is 0 --> measurement is 8 bit, otherwise 16 bit.
+
+ Serial.print("HRM Measurement: ");
+
+ if ( data[0] & bit(0) )
+ {
+ uint16_t value;
+ memcpy(&value, data+1, 2);
+
+ Serial.println(value);
+ }
+ else
+ {
+ Serial.println(data[1]);
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_hid/central_hid.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_hid/central_hid.ino
new file mode 100755
index 0000000..c78d055
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_hid/central_hid.ino
@@ -0,0 +1,226 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/*
+ * This sketch demonstrate the central API(). An additional bluefruit
+ * that has blehid as peripheral is required for the demo.
+ */
+#include <bluefruit.h>
+
+// Polling or callback implementation
+#define POLLING 1
+
+BLEClientHidAdafruit hid;
+
+// Last checked report, to detect if there is changes between reports
+hid_keyboard_report_t last_kbd_report = { 0 };
+hid_mouse_report_t last_mse_report = { 0 };
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Central HID (Keyboard + Mouse) Example");
+ Serial.println("--------------------------------------------------\n");
+
+ // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
+ // SRAM usage required by SoftDevice will increase dramatically with number of connections
+ Bluefruit.begin(0, 1);
+
+ Bluefruit.setName("Bluefruit52 Central");
+
+ // Init BLE Central Uart Serivce
+ hid.begin();
+
+ #if POLLING == 0
+ hid.setKeyboardReportCallback(keyboard_report_callback);
+ #endif
+
+ // Increase Blink rate to different from PrPh advertising mode
+ Bluefruit.setConnLedInterval(250);
+
+ // Callbacks for Central
+ Bluefruit.Central.setConnectCallback(connect_callback);
+ Bluefruit.Central.setDisconnectCallback(disconnect_callback);
+
+ /* Start Central Scanning
+ * - Enable auto scan if disconnected
+ * - Interval = 100 ms, window = 80 ms
+ * - Don't use active scan
+ * - Filter only accept HID service in advertising
+ * - Start(timeout) with timeout = 0 will scan forever (until connected)
+ */
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.restartOnDisconnect(true);
+ Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
+ Bluefruit.Scanner.filterService(hid); // only report HID service
+ Bluefruit.Scanner.useActiveScan(false);
+ Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
+}
+
+/**
+ * Callback invoked when scanner pick up an advertising data
+ * @param report Structural advertising data
+ */
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ // Since we configure the scanner with filterUuid()
+ // Scan callback only invoked for device with hid service advertised
+ // Connect to the device with hid service in advertising packet
+ Bluefruit.Central.connect(report);
+}
+
+/**
+ * Callback invoked when an connection is established
+ * @param conn_handle
+ */
+void connect_callback(uint16_t conn_handle)
+{
+ Serial.println("Connected");
+
+ Serial.print("Discovering HID Service ... ");
+
+ if ( hid.discover(conn_handle) )
+ {
+ Serial.println("Found it");
+
+ // HID device mostly require pairing/bonding
+ if ( !Bluefruit.Gap.requestPairing(conn_handle) )
+ {
+ Serial.print("Failed to paired");
+ return;
+ }
+
+ // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.hid_information.xml
+ uint8_t hidInfo[4];
+ hid.getHidInfo(hidInfo);
+
+ Serial.printf("HID version: %d.%d\n", hidInfo[0], hidInfo[1]);
+ Serial.print("Country code: "); Serial.println(hidInfo[2]);
+ Serial.printf("HID Flags : 0x%02X\n", hidInfo[3]);
+
+ // BLEClientHidAdafruit currently only suports Boot Protocol Mode
+ // for Keyboard and Mouse. Let's set the protocol mode on prph to Boot Mode
+ hid.setProtocolMode(HID_PROTOCOL_MODE_BOOT);
+
+ // Enable Keyboard report notification if present on prph
+ if ( hid.keyboardPresent() ) hid.enableKeyboard();
+
+ // Enable Mouse report notification if present on prph
+ if ( hid.mousePresent() ) hid.enableMouse();
+
+ Serial.println("Ready to receive from peripheral");
+ }else
+ {
+ Serial.println("Found NONE");
+
+ // disconect since we couldn't find bleuart service
+ Bluefruit.Central.disconnect(conn_handle);
+ }
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println("Disconnected");
+}
+
+void loop()
+{
+
+#if POLLING == 1
+ // nothing to do if hid not discovered
+ if ( !hid.discovered() ) return;
+
+ /*------------- Polling Keyboard -------------*/
+ hid_keyboard_report_t kbd_report;
+
+ // Get latest report
+ hid.getKeyboardReport(&kbd_report);
+
+ processKeyboardReport(&kbd_report);
+
+
+ // polling interval is 5 ms
+ delay(5);
+#endif
+
+}
+
+
+void keyboard_report_callback(hid_keyboard_report_t* report)
+{
+ processKeyboardReport(report);
+}
+
+void processKeyboardReport(hid_keyboard_report_t* report)
+{
+ // Check with last report to see if there is any changes
+ if ( memcmp(&last_kbd_report, report, sizeof(hid_keyboard_report_t)) )
+ {
+ bool shifted = false;
+
+ if ( report->modifier )
+ {
+ if ( report->modifier & (KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_RIGHTCTRL) )
+ {
+ Serial.print("Ctrl ");
+ }
+
+ if ( report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT) )
+ {
+ Serial.print("Shift ");
+
+ shifted = true;
+ }
+
+ if ( report->modifier & (KEYBOARD_MODIFIER_LEFTALT | KEYBOARD_MODIFIER_RIGHTALT) )
+ {
+ Serial.print("Alt ");
+ }
+ }
+
+ for(uint8_t i=0; i<6; i++)
+ {
+ uint8_t kc = report->keycode[i];
+ char ch = 0;
+
+ if ( kc < 128 )
+ {
+ ch = shifted ? HID_KEYCODE_TO_ASCII[kc].shifted : HID_KEYCODE_TO_ASCII[kc].ascii;
+ }else
+ {
+ // non-US keyboard !!??
+ }
+
+ // Printable
+ if (ch)
+ {
+ Serial.print(ch);
+ }
+ }
+ }
+
+ // update last report
+ memcpy(&last_kbd_report, report, sizeof(hid_keyboard_report_t));
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan/central_scan.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan/central_scan.ino
new file mode 100755
index 0000000..191f978
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan/central_scan.ino
@@ -0,0 +1,73 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <bluefruit.h>
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Central Scan Example");
+ Serial.println("--------------------------------\n");
+
+ // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
+ // SRAM usage required by SoftDevice will increase dramatically with number of connections
+ Bluefruit.begin(0, 1);
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Start Central Scan
+ Bluefruit.setConnLedInterval(250);
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.start(0);
+
+ Serial.println("Scanning ...");
+}
+
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ Serial.println("Timestamp Addr Rssi Data");
+
+ Serial.printf("%09d ", millis());
+
+ // MAC is in little endian --> print reverse
+ Serial.printBufferReverse(report->peer_addr.addr, 6, ':');
+ Serial.print(" ");
+
+ Serial.print(report->rssi);
+ Serial.print(" ");
+
+ Serial.printBuffer(report->data.p_data, report->data.len, '-');
+ Serial.println();
+
+ // Check if advertising contain BleUart service
+ if ( Bluefruit.Scanner.checkReportForUuid(report, BLEUART_UUID_SERVICE) )
+ {
+ Serial.println(" BLE UART service detected");
+ }
+
+ Serial.println();
+
+ // For Softdevice v6: after received a report, scanner will be paused
+ // We need to call Scanner resume() to continue scanning
+ Bluefruit.Scanner.resume();
+}
+
+void loop()
+{
+ // nothing to do
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan_advanced/central_scan_advanced.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan_advanced/central_scan_advanced.ino
new file mode 100755
index 0000000..3aab152
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan_advanced/central_scan_advanced.ino
@@ -0,0 +1,218 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <bluefruit.h>
+
+/* For a list of EIR data types see:
+ * https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
+ * Matching enum: cores/nRF5/SDK/components/softdevice/s132/headers/ble_gap.h */
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Central ADV Scan Example");
+ Serial.println("------------------------------------\n");
+
+ // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
+ // SRAM usage required by SoftDevice will increase dramatically with number of connections
+ Bluefruit.begin(0, 1);
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+
+ /* Set the device name */
+ Bluefruit.setName("Bluefruit52");
+
+ /* Set the LED interval for blinky pattern on BLUE LED */
+ Bluefruit.setConnLedInterval(250);
+
+ /* Start Central Scanning
+ * - Enable auto scan if disconnected
+ * - Filter out packet with a min rssi
+ * - Interval = 100 ms, window = 50 ms
+ * - Use active scan (used to retrieve the optional scan response adv packet)
+ * - Start(0) = will scan forever since no timeout is given
+ */
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.restartOnDisconnect(true);
+ Bluefruit.Scanner.filterRssi(-80);
+ //Bluefruit.Scanner.filterUuid(BLEUART_UUID_SERVICE); // only invoke callback if detect bleuart service
+ Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms
+ Bluefruit.Scanner.useActiveScan(true); // Request scan response data
+ Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
+
+ Serial.println("Scanning ...");
+}
+
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ PRINT_LOCATION();
+ uint8_t len = 0;
+ uint8_t buffer[32];
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Display the timestamp and device address */
+ if (report->type.scan_response)
+ {
+ Serial.printf("[SR%10d] Packet received from ", millis());
+ }
+ else
+ {
+ Serial.printf("[ADV%9d] Packet received from ", millis());
+ }
+ // MAC is in little endian --> print reverse
+ Serial.printBufferReverse(report->peer_addr.addr, 6, ':');
+ Serial.print("\n");
+
+ /* Raw buffer contents */
+ Serial.printf("%14s %d bytes\n", "PAYLOAD", report->data.len);
+ if (report->data.len)
+ {
+ Serial.printf("%15s", " ");
+ Serial.printBuffer(report->data.p_data, report->data.len, '-');
+ Serial.println();
+ }
+
+ /* RSSI value */
+ Serial.printf("%14s %d dBm\n", "RSSI", report->rssi);
+
+ /* Adv Type */
+ Serial.printf("%14s ", "ADV TYPE");
+ if ( report->type.connectable )
+ {
+ Serial.print("Connectable ");
+ }else
+ {
+ Serial.print("Non-connectable ");
+ }
+
+ if ( report->type.directed )
+ {
+ Serial.println("directed");
+ }else
+ {
+ Serial.println("undirected");
+ }
+
+ /* Shortened Local Name */
+ if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, buffer, sizeof(buffer)))
+ {
+ Serial.printf("%14s %s\n", "SHORT NAME", buffer);
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ /* Complete Local Name */
+ if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, buffer, sizeof(buffer)))
+ {
+ Serial.printf("%14s %s\n", "COMPLETE NAME", buffer);
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ /* TX Power Level */
+ if (Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_TX_POWER_LEVEL, buffer, sizeof(buffer)))
+ {
+ Serial.printf("%14s %i\n", "TX PWR LEVEL", buffer[0]);
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ /* Check for UUID16 Complete List */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, buffer, sizeof(buffer));
+ if ( len )
+ {
+ printUuid16List(buffer, len);
+ }
+
+ /* Check for UUID16 More Available List */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, buffer, sizeof(buffer));
+ if ( len )
+ {
+ printUuid16List(buffer, len);
+ }
+
+ /* Check for UUID128 Complete List */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, buffer, sizeof(buffer));
+ if ( len )
+ {
+ printUuid128List(buffer, len);
+ }
+
+ /* Check for UUID128 More Available List */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, buffer, sizeof(buffer));
+ if ( len )
+ {
+ printUuid128List(buffer, len);
+ }
+
+ /* Check for BLE UART UUID */
+ if ( Bluefruit.Scanner.checkReportForUuid(report, BLEUART_UUID_SERVICE) )
+ {
+ Serial.printf("%14s %s\n", "BLE UART", "UUID Found!");
+ }
+
+ /* Check for DIS UUID */
+ if ( Bluefruit.Scanner.checkReportForUuid(report, UUID16_SVC_DEVICE_INFORMATION) )
+ {
+ Serial.printf("%14s %s\n", "DIS", "UUID Found!");
+ }
+
+ /* Check for Manufacturer Specific Data */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, buffer, sizeof(buffer));
+ if (len)
+ {
+ Serial.printf("%14s ", "MAN SPEC DATA");
+ Serial.printBuffer(buffer, len, '-');
+ Serial.println();
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ Serial.println();
+
+ // For Softdevice v6: after received a report, scanner will be paused
+ // We need to call Scanner resume() to continue scanning
+ Bluefruit.Scanner.resume();
+}
+
+void printUuid16List(uint8_t* buffer, uint8_t len)
+{
+ Serial.printf("%14s %s", "16-Bit UUID");
+ for(int i=0; i<len; i+=2)
+ {
+ uint16_t uuid16;
+ memcpy(&uuid16, buffer+i, 2);
+ Serial.printf("%04X ", uuid16);
+ }
+ Serial.println();
+}
+
+void printUuid128List(uint8_t* buffer, uint8_t len)
+{
+ (void) len;
+ Serial.printf("%14s %s", "128-Bit UUID");
+
+ // Print reversed order
+ for(int i=0; i<16; i++)
+ {
+ const char* fm = (i==4 || i==6 || i==8 || i==10) ? "-%02X" : "%02X";
+ Serial.printf(fm, buffer[15-i]);
+ }
+
+ Serial.println();
+}
+
+void loop()
+{
+ // nothing to do
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_ti_sensortag_optical/central_ti_sensortag_optical.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_ti_sensortag_optical/central_ti_sensortag_optical.ino
new file mode 100755
index 0000000..92d76af
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_ti_sensortag_optical/central_ti_sensortag_optical.ino
@@ -0,0 +1,309 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch shows how to use BLEClientService and BLEClientCharacteristic
+ * to implement a custom client that is used to talk with Gatt server on
+ * the TI SensorTag peripheral device.
+ *
+ * Online uuid/hex converters
+ * https://yupana-engineering.com/online-uuid-to-c-array-converter
+ * https://www.scadacore.com/tools/programming-calculators/online-hex-converter/
+ * https://codebeautify.org/string-hex-converter
+ *
+ * Adafruit Bluefruit Feather nRF52
+ * https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/blescanner
+ *
+ * Sensor Tag
+ * http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User%27s_Guide#Optical_Sensor
+ *
+ * Scan Response (Extended Advertisement data retrieval)
+ * https://devzone.nordicsemi.com/tutorials/b/bluetooth-low-energy/posts/ble-advertising-a-beginners-tutorial
+ *
+ */
+
+ #include <bluefruit.h>
+
+/* TI Sensor Tag UUID Definitions
+ * Base SensorTag UUID pattern: F000-0000-0451-4000-B000-000000000000
+ * Optical Service: 0xA070
+ * Optical Characteristic: 0xAA71
+ * Optical Data Collection Enabler: 0xAA72
+ * Optical Measurement Period: 0xAA73
+ * Local Name: "CC2650 SensorTag"
+ */
+
+ uint8_t SENSORTAG_OPTICAL_SERVICE_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x70,0xAA,0x00,0xF0};
+ uint8_t SENSORTAG_OPTICAL_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x71,0xAA,0x00,0xF0};
+ uint8_t SENSORTAG_OPTICAL_ENABLE_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x72,0xAA,0x00,0xF0};
+ uint8_t SENSORTAG_OPTICAL_PERIOD_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x73,0xAA,0x00,0xF0};
+ uint8_t SENSORTAG_ADV_COMPLETE_LOCAL_NAME[] = {0x43,0x43,0x32,0x36,0x35,0x30,0x20,0x53,0x65,0x6e,0x73,0x6f,0x72,0x54,0x61,0x67};
+
+BLEClientService sensorTagOpticalService(SENSORTAG_OPTICAL_SERVICE_UUID);
+BLEClientCharacteristic sensorTagOpticalCharacteristic(SENSORTAG_OPTICAL_CHARACTERISTIC_UUID);
+BLEClientCharacteristic opticalCharacteristicDataCollectionEnabler(SENSORTAG_OPTICAL_ENABLE_CHARACTERISTIC_UUID);
+BLEClientCharacteristic opticalCharacteristicPeriod(SENSORTAG_OPTICAL_PERIOD_CHARACTERISTIC_UUID);
+
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Central TI Sensor Tag Example");
+ Serial.println("-----------------------------------------\n");
+
+ // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
+ // SRAM usage required by SoftDevice will increase dramatically with number of connections
+ Bluefruit.begin(0, 1);
+
+ Bluefruit.setName("Bluefruit52 TI SensorTag Central");
+
+ // Initialize Service
+ sensorTagOpticalService.begin();
+
+ // set up callback for receiving measurement
+ sensorTagOpticalCharacteristic.setNotifyCallback(sensortag_optical_notify_callback);
+ sensorTagOpticalCharacteristic.begin();
+
+ // set up the characteristic to enable the optical component on the device
+ opticalCharacteristicDataCollectionEnabler.begin();
+
+ // set up the characteristic to adjust the measurement period
+ opticalCharacteristicPeriod.begin();
+
+ // Increase Blink rate to different from PrPh advertising mode
+ Bluefruit.setConnLedInterval(250);
+
+ // Callbacks for Central
+ Bluefruit.Central.setDisconnectCallback(disconnect_callback);
+ Bluefruit.Central.setConnectCallback(connect_callback);
+
+ /* Start Central Scanning
+ * - Enable auto scan if disconnected
+ * - Interval = 100 ms, window = 80 ms
+ * - No UUID Filter
+ * - Use active scan
+ * - Start(timeout) with timeout = 0 will scan forever (until connected)
+ */
+
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.restartOnDisconnect(true);
+ Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
+ // Bluefruit.Scanner.filterUuid(); // do not not set anything here or Scan Response won't work
+ Bluefruit.Scanner.useActiveScan(true); // required for SensorTag to reveal the Local Name in the advertisement.
+ Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
+}
+
+void loop()
+{
+ // do nothing
+}
+
+/**
+ * Callback invoked when scanner pick up an advertising data
+ * @param report Structural advertising data
+ */
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ Serial.println("");
+ Serial.println("Scan Callback");
+ printReport( report );
+
+ /* Choose a peripheral to connect with by searching for an advertisement packet with a
+ Complete Local Name matching our target device*/
+ uint8_t buffer[BLE_GAP_ADV_SET_DATA_SIZE_MAX] = { 0 };
+
+ Serial.print("Parsing report for Local Name ... ");
+ if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, buffer, sizeof(buffer)))
+ {
+ Serial.println("Found Local Name");
+ Serial.printf("%14s %s\n", "Local Name:", buffer);
+
+ Serial.print(" Local Name data: ");
+ printHexList(buffer, BLE_GAP_ADV_SET_DATA_SIZE_MAX );
+
+ Serial.print("Determining Local Name Match ... ");
+ if ( !memcmp( buffer, SENSORTAG_ADV_COMPLETE_LOCAL_NAME, sizeof(SENSORTAG_ADV_COMPLETE_LOCAL_NAME)) )
+ {
+ Serial.println("Local Name Match!");
+
+ Serial.println("Connecting to Peripheral ... ");
+ Bluefruit.Central.connect(report);
+ }
+ else
+ {
+ Serial.println("No Match");
+ Bluefruit.Scanner.resume(); // continue scanning
+ }
+ }
+ else
+ {
+ Serial.println("Failed");
+
+ // For Softdevice v6: after received a report, scanner will be paused
+ // We need to call Scanner resume() to continue scanning
+ Bluefruit.Scanner.resume();
+ }
+}
+
+/**
+ * Callback invoked when an connection is established
+ * @param conn_handle
+ */
+void connect_callback(uint16_t conn_handle)
+{
+ Serial.println("");
+ Serial.print("Connect Callback, conn_handle: ");
+ Serial.println( conn_handle );
+
+ /* Complete Local Name */
+ uint8_t buffer[BLE_GAP_ADV_SET_DATA_SIZE_MAX] = { 0 };
+
+ // If Service is not found, disconnect and return
+ Serial.print("Discovering Optical Service ... ");
+ if ( !sensorTagOpticalService.discover(conn_handle) )
+ {
+ Serial.println("No Service Found");
+
+ // disconect since we couldn't find service
+ Bluefruit.Central.disconnect(conn_handle);
+
+ return;
+ }
+ Serial.println("Service Found");
+
+ // Once service is found, we continue to discover the primary characteristic
+ Serial.print("Discovering Optical Characteristic ... ");
+ if ( !sensorTagOpticalCharacteristic.discover() )
+ {
+ // Measurement chr is mandatory, if it is not found (valid), then disconnect
+ Serial.println("No Characteristic Found. Characteristic is mandatory but not found. ");
+ Bluefruit.Central.disconnect(conn_handle);
+ return;
+ }
+ Serial.println("Characteristic Found");
+
+ // Data Collection Charactistic. Find and enable.
+ // You enable data collection on the Characteristic before the peripheral will start measuring values.
+ // This is different than setting the Notify descriptor, which is handled below.
+ Serial.print("Discovering Data Collection Configuration Characteristic ... ");
+ if ( !opticalCharacteristicDataCollectionEnabler.discover() )
+ {
+ Serial.println("No Characteristic Found. Characteristic is mandatory but not found.");
+ Bluefruit.Central.disconnect(conn_handle);
+ return;
+ }
+ Serial.println("Characteristic Found");
+ // Found it, now write 0x01 to turn on optical data collection
+ Serial.print("Enabling Data Collection, return value: ");
+ Serial.println( opticalCharacteristicDataCollectionEnabler.write8( 0x01 ) );
+
+ // Measurement Period Characteristic. Find and adjust.
+ Serial.print("Measurement Period Characteristic ... ");
+ if ( !opticalCharacteristicPeriod.discover() )
+ {
+ Serial.println("No Characteristic Found, but not mandatory so not disconnecting");
+ }
+ Serial.println("Characteristic Found");
+ // Found it, now adjust it:
+ // Resolution 10 ms. Range 100 ms (0x0A) to 2.55 sec (0xFF). Default is 800 milliseconds (0x50).
+ // 19 is 250
+ Serial.print("Adjusting Measurement Period, return value: ");
+ // Serial.println( opticalCharacteristicPeriod.write8( 0xFF ) ); // Slowest
+ Serial.println( opticalCharacteristicPeriod.write8( 0x0A ) ); // Fastest
+
+ // Reaching here means we are ready to go, let's enable notification on measurement chr
+ Serial.print("Enabling Notify on the Characteristic ... ");
+ if ( sensorTagOpticalCharacteristic.enableNotify() )
+ {
+ Serial.println("enableNotify success, now ready to receive Characteristic values");
+ }else
+ {
+ Serial.println("Couldn't enable notify for Characteristic. Increase DEBUG LEVEL for troubleshooting");
+ }
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println("Disconnected");
+}
+
+/**
+ * Hooked callback that triggered when a measurement value is sent from peripheral
+ * @param chr Pointer client characteristic that even occurred,
+ * in this example it should be sensorTagOpticalCharacteristic
+ * @param data Pointer to received data
+ * @param len Length of received data
+ */
+void sensortag_optical_notify_callback(BLEClientCharacteristic* chr, uint8_t* data, uint16_t len)
+{
+ Serial.print("Optical data: ");
+ uint16_t tData = (uint16_t) ( ( data[0] & 0xFF ) | ( data[1] & 0xFF ) << 8 );
+ Serial.print( sensorOpt3001Convert( tData ) );
+ Serial.println( " Lux" );
+}
+
+/*
+ * Conversion to Lux. Algorithm from the TI Sensor Tag Wiki documentation page
+ */
+float sensorOpt3001Convert(uint16_t rawData)
+{
+ uint16_t e, m;
+
+ m = rawData & 0x0FFF;
+ e = (rawData & 0xF000) >> 12;
+
+ /** e on 4 bits stored in a 16 bit unsigned => it can store 2 << (e - 1) with e < 16 */
+ e = (e == 0) ? 1 : 2 << (e - 1);
+
+ return m * (0.01 * e);
+}
+
+/* Prints a hex list to the Serial Monitor */
+void printHexList(uint8_t* buffer, uint8_t len)
+{
+ // print forward order
+ for(int i=0; i<len; i++)
+ {
+ Serial.printf("%02X-", buffer[i]);
+ }
+ Serial.println();
+}
+
+void printReport( const ble_gap_evt_adv_report_t* report )
+{
+ Serial.print( " rssi: " );
+ Serial.println( report->rssi );
+ Serial.print( " scan_rsp: " );
+ Serial.println( report->type.scan_response );
+// Serial.print( " type: " );
+// Serial.println( report->type );
+ Serial.print( " dlen: " );
+ Serial.println( report->data.len );
+ Serial.print( " data: " );
+ for( int i = 0; i < report->data.len; i+= sizeof(uint8_t) )
+ {
+ Serial.printf( "%02X-", report->data.p_data[ i ] );
+ }
+ Serial.println("");
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/DualRoles/dual_bleuart/dual_bleuart.ino b/arduino/libraries/Bluefruit52Lib/examples/DualRoles/dual_bleuart/dual_bleuart.ino
new file mode 100755
index 0000000..236dd02
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/DualRoles/dual_bleuart/dual_bleuart.ino
@@ -0,0 +1,212 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/*
+ * This sketch demonstrate how to run both Central and Peripheral roles
+ * at the same time. It will act as a relay between an central (mobile)
+ * to another peripheral using bleuart service.
+ *
+ * Mobile <--> DualRole <--> peripheral Ble Uart
+ */
+#include <bluefruit.h>
+
+// Peripheral uart service
+BLEUart bleuart;
+
+// Central uart client
+BLEClientUart clientUart;
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Dual Role BLEUART Example");
+ Serial.println("-------------------------------------\n");
+
+ // Initialize Bluefruit with max concurrent connections as Peripheral = 1, Central = 1
+ // SRAM usage required by SoftDevice will increase with number of connections
+ Bluefruit.begin(1, 1);
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52 duo");
+
+ // Callbacks for Peripheral
+ Bluefruit.setConnectCallback(prph_connect_callback);
+ Bluefruit.setDisconnectCallback(prph_disconnect_callback);
+
+ // Callbacks for Central
+ Bluefruit.Central.setConnectCallback(cent_connect_callback);
+ Bluefruit.Central.setDisconnectCallback(cent_disconnect_callback);
+
+ // Configure and Start BLE Uart Service
+ bleuart.begin();
+ bleuart.setRxCallback(prph_bleuart_rx_callback);
+
+ // Init BLE Central Uart Serivce
+ clientUart.begin();
+ clientUart.setRxCallback(cent_bleuart_rx_callback);
+
+
+ /* Start Central Scanning
+ * - Enable auto scan if disconnected
+ * - Interval = 100 ms, window = 80 ms
+ * - Filter only accept bleuart service
+ * - Don't use active scan
+ * - Start(timeout) with timeout = 0 will scan forever (until connected)
+ */
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.restartOnDisconnect(true);
+ Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
+ Bluefruit.Scanner.filterUuid(bleuart.uuid);
+ Bluefruit.Scanner.useActiveScan(false);
+ Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include bleuart 128-bit uuid
+ Bluefruit.Advertising.addService(bleuart);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // do nothing, all the work is done in callback
+}
+
+/*------------------------------------------------------------------*/
+/* Peripheral
+ *------------------------------------------------------------------*/
+void prph_connect_callback(uint16_t conn_handle)
+{
+ char peer_name[32] = { 0 };
+ Bluefruit.Gap.getPeerName(conn_handle, peer_name, sizeof(peer_name));
+
+ Serial.print("[Prph] Connected to ");
+ Serial.println(peer_name);
+}
+
+void prph_disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println();
+ Serial.println("[Prph] Disconnected");
+}
+
+void prph_bleuart_rx_callback(void)
+{
+ // Forward data from Mobile to our peripheral
+ char str[20+1] = { 0 };
+ bleuart.read(str, 20);
+
+ Serial.print("[Prph] RX: ");
+ Serial.println(str);
+
+ if ( clientUart.discovered() )
+ {
+ clientUart.print(str);
+ }else
+ {
+ bleuart.println("[Prph] Central role not connected");
+ }
+}
+
+/*------------------------------------------------------------------*/
+/* Central
+ *------------------------------------------------------------------*/
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ // Since we configure the scanner with filterUuid()
+ // Scan callback only invoked for device with bleuart service advertised
+ // Connect to the device with bleuart service in advertising packet
+ Bluefruit.Central.connect(report);
+}
+
+void cent_connect_callback(uint16_t conn_handle)
+{
+ char peer_name[32] = { 0 };
+ Bluefruit.Gap.getPeerName(conn_handle, peer_name, sizeof(peer_name));
+
+ Serial.print("[Cent] Connected to ");
+ Serial.println(peer_name);;
+
+ if ( clientUart.discover(conn_handle) )
+ {
+ // Enable TXD's notify
+ clientUart.enableTXD();
+ }else
+ {
+ // disconect since we couldn't find bleuart service
+ Bluefruit.Central.disconnect(conn_handle);
+ }
+}
+
+void cent_disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println("[Cent] Disconnected");
+}
+
+/**
+ * Callback invoked when uart received data
+ * @param cent_uart Reference object to the service where the data
+ * arrived. In this example it is clientUart
+ */
+void cent_bleuart_rx_callback(BLEClientUart& cent_uart)
+{
+ char str[20+1] = { 0 };
+ cent_uart.read(str, 20);
+
+ Serial.print("[Cent] RX: ");
+ Serial.println(str);
+
+ if ( bleuart.notifyEnabled() )
+ {
+ // Forward data from our peripheral to Mobile
+ bleuart.print( str );
+ }else
+ {
+ // response with no prph message
+ clientUart.println("[Cent] Peripheral role not connected");
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/Fading/Fading.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/Fading/Fading.ino
new file mode 100755
index 0000000..d5df3a8
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/Fading/Fading.ino
@@ -0,0 +1,45 @@
+/*
+ Fading
+
+ This example shows how to fade an LED using the analogWrite() function.
+
+ The circuit:
+ * LED attached from digital pin 9 to ground.
+
+ Created 1 Nov 2008
+ By David A. Mellis
+ modified 30 Aug 2011
+ By Tom Igoe
+
+ http://www.arduino.cc/en/Tutorial/Fading
+
+ This example code is in the public domain.
+
+ */
+
+
+int ledPin = LED_RED; // LED connected to digital pin 9
+
+void setup() {
+ // nothing happens in setup
+}
+
+void loop() {
+ // fade in from min to max in increments of 5 points:
+ for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
+ // sets the value (range from 0 to 255):
+ analogWrite(ledPin, fadeValue);
+ // wait for 30 milliseconds to see the dimming effect
+ delay(30);
+ }
+
+ // fade out from max to min in increments of 5 points:
+ for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
+ // sets the value (range from 0 to 255):
+ analogWrite(ledPin, fadeValue);
+ // wait for 30 milliseconds to see the dimming effect
+ delay(30);
+ }
+}
+
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/Serial1_test/Serial1_test.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/Serial1_test/Serial1_test.ino
new file mode 100755
index 0000000..ff5875d
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/Serial1_test/Serial1_test.ino
@@ -0,0 +1,46 @@
+/*********************************************************************
+ This is an example for our Feather Bluefruit modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/*
+ * This sketch demonstrate how to use Hardware Serial1 along with
+ * native USB Serial on Bluefruit nRF52840.
+ * Note: Bluefruit nRF52832 does not support Serial1
+ */
+
+#include "Arduino.h"
+
+void setup()
+{
+ // Open serial communications and wait for port to open:
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Goodnight moon!");
+
+ // set the data rate for the SoftwareSerial port
+ //mySerial.begin(9600);
+ //mySerial.println("Hello, world?");
+
+ Serial1.begin(115200);
+ Serial1.println("Hello, world?");
+}
+
+void loop() // run over and over//
+{
+ if (Serial1.available())
+ Serial.write(Serial1.read());
+
+ if (Serial.available())
+ Serial1.write(Serial.read());
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/SerialEcho/SerialEcho.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/SerialEcho/SerialEcho.ino
new file mode 100755
index 0000000..0daf716
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/SerialEcho/SerialEcho.ino
@@ -0,0 +1,45 @@
+/*********************************************************************
+ This is an example for our Feather Bluefruit modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <Arduino.h>
+
+const int baudrate = 115200;
+
+/**************************************************************************/
+/*!
+ @brief The setup function runs once when reset the board
+*/
+/**************************************************************************/
+void setup()
+{
+ Serial.begin (baudrate);
+
+ Serial.println("Serial Echo demo");
+ Serial.print("Badurate : ");
+ Serial.println(baudrate);
+}
+
+/**************************************************************************/
+/*!
+ @brief The loop function runs over and over again forever
+*/
+/**************************************************************************/
+void loop()
+{
+ // From Serial monitor to All
+ if ( Serial.available() )
+ {
+ Serial.write( Serial.read() );
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/adc/adc.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/adc/adc.ino
new file mode 100755
index 0000000..1133826
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/adc/adc.ino
@@ -0,0 +1,21 @@
+int adcin = A5;
+int adcvalue = 0;
+float mv_per_lsb = 3600.0F/1024.0F; // 10-bit ADC with 3.6V input range
+
+void setup() {
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+}
+
+void loop() {
+ // Get a fresh ADC value
+ adcvalue = analogRead(adcin);
+
+ // Display the results
+ Serial.print(adcvalue);
+ Serial.print(" [");
+ Serial.print((float)adcvalue * mv_per_lsb);
+ Serial.println(" mV]");
+
+ delay(100);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/adc_vbat/adc_vbat.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/adc_vbat/adc_vbat.ino
new file mode 100755
index 0000000..ceaa0a1
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/adc_vbat/adc_vbat.ino
@@ -0,0 +1,93 @@
+#define VBAT_PIN (A7)
+#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
+#define VBAT_DIVIDER (0.71275837F) // 2M + 0.806M voltage divider on VBAT = (2M / (0.806M + 2M))
+#define VBAT_DIVIDER_COMP (1.403F) // Compensation factor for the VBAT divider
+
+int readVBAT(void) {
+ int raw;
+
+ // Set the analog reference to 3.0V (default = 3.6V)
+ analogReference(AR_INTERNAL_3_0);
+
+ // Set the resolution to 12-bit (0..4095)
+ analogReadResolution(12); // Can be 8, 10, 12 or 14
+
+ // Let the ADC settle
+ delay(1);
+
+ // Get the raw 12-bit, 0..3000mV ADC value
+ raw = analogRead(VBAT_PIN);
+
+ // Set the ADC back to the default settings
+ analogReference(AR_DEFAULT);
+ analogReadResolution(10);
+
+ return raw;
+}
+
+uint8_t mvToPercent(float mvolts) {
+ uint8_t battery_level;
+
+ if (mvolts >= 3000)
+ {
+ battery_level = 100;
+ }
+ else if (mvolts > 2900)
+ {
+ battery_level = 100 - ((3000 - mvolts) * 58) / 100;
+ }
+ else if (mvolts > 2740)
+ {
+ battery_level = 42 - ((2900 - mvolts) * 24) / 160;
+ }
+ else if (mvolts > 2440)
+ {
+ battery_level = 18 - ((2740 - mvolts) * 12) / 300;
+ }
+ else if (mvolts > 2100)
+ {
+ battery_level = 6 - ((2440 - mvolts) * 6) / 340;
+ }
+ else
+ {
+ battery_level = 0;
+ }
+
+ return battery_level;
+}
+
+void setup() {
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ // Get a single ADC sample and throw it away
+ readVBAT();
+}
+
+void loop() {
+ // Get a raw ADC reading
+ int vbat_raw = readVBAT();
+
+ // Convert from raw mv to percentage (based on LIPO chemistry)
+ uint8_t vbat_per = mvToPercent(vbat_raw * VBAT_MV_PER_LSB);
+
+ // Convert the raw value to compensated mv, taking the resistor-
+ // divider into account (providing the actual LIPO voltage)
+ // ADC range is 0..3000mV and resolution is 12-bit (0..4095),
+ // VBAT voltage divider is 2M + 0.806M, which needs to be added back
+ float vbat_mv = (float)vbat_raw * VBAT_MV_PER_LSB * VBAT_DIVIDER_COMP;
+
+ // Display the results
+ Serial.print("ADC = ");
+ Serial.print(vbat_raw * VBAT_MV_PER_LSB);
+ Serial.print(" mV (");
+ Serial.print(vbat_raw);
+ Serial.print(") ");
+ Serial.print("LIPO = ");
+ Serial.print(vbat_mv);
+ Serial.print(" mV (");
+ Serial.print(vbat_per);
+ Serial.println("%)");
+
+ delay(1000);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/blinky/blinky.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/blinky/blinky.ino
new file mode 100755
index 0000000..c2f4906
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/blinky/blinky.ino
@@ -0,0 +1,30 @@
+/*
+ Blink
+ Turns on an LED on for one second, then off for one second, repeatedly.
+
+ Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
+ it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care
+ of use the correct LED pin whatever is the board used.
+ If you want to know what pin the on-board LED is connected to on your Arduino model, check
+ the Technical Specs of your board at https://www.arduino.cc/en/Main/Products
+
+ This example code is in the public domain.
+
+ modified 8 May 2014
+ by Scott Fitzgerald
+
+ modified 2 Sep 2016
+ by Arturo Guadalupi
+*/
+
+// the setup function runs once when you press reset or power the board
+void setup() {
+ // initialize digital pin LED_BUILTIN as an output.
+ pinMode(LED_RED, OUTPUT);
+}
+
+// the loop function runs over and over again forever
+void loop() {
+ digitalToggle(LED_RED); // turn the LED on (HIGH is the voltage level)
+ delay(1000); // wait for a second
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/dfu_ota/dfu_ota.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/dfu_ota/dfu_ota.ino
new file mode 100755
index 0000000..4dca371
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/dfu_ota/dfu_ota.ino
@@ -0,0 +1,28 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch invoke API to enter OTA dfu mode */
+
+#include <Arduino.h>
+
+
+void setup()
+{
+ enterOTADfu();
+}
+
+
+void loop()
+{
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/dfu_serial/dfu_serial.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/dfu_serial/dfu_serial.ino
new file mode 100755
index 0000000..65476b8
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/dfu_serial/dfu_serial.ino
@@ -0,0 +1,29 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <Arduino.h>
+
+/*
+ * This sketch will reset the board into Serial DFU mode
+ */
+
+void setup()
+{
+ enterSerialDfu();
+}
+
+
+void loop()
+{
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/digital_interrupt_deferred/digital_interrupt_deferred.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/digital_interrupt_deferred/digital_interrupt_deferred.ino
new file mode 100755
index 0000000..464e31b
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/digital_interrupt_deferred/digital_interrupt_deferred.ino
@@ -0,0 +1,46 @@
+/*********************************************************************
+ This is an example for our Feather Bluefruit modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/*
+ * This sketch demonstrate how to pass ISR_DEFFERED as additional parameter
+ * to defer callback from ISR context with attachInterrupt
+ */
+#include <Arduino.h>
+
+int interruptPin = A0;
+
+void setup()
+{
+ Serial.begin(115200);
+
+ pinMode(interruptPin, INPUT_PULLUP);
+
+ // ISR_DEFERRED flag cause the callback to be deferred from ISR context
+ // and invoked within a callback thread.
+ // It is required to use ISR_DEFERRED if callback function take long time
+ // to run e.g Serial.print() or using any of Bluefruit API() which will
+ // potentially call rtos API
+ attachInterrupt(interruptPin, digital_callback, ISR_DEFERRED | CHANGE);
+}
+
+void loop()
+{
+ // nothing to do
+}
+
+void digital_callback(void)
+{
+ Serial.print("Pin value: ");
+ Serial.println(digitalRead(interruptPin));
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/fwinfo/fwinfo.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/fwinfo/fwinfo.ino
new file mode 100755
index 0000000..538ac31
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/fwinfo/fwinfo.ino
@@ -0,0 +1,33 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <Arduino.h>
+
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Firmware Info Example");
+ Serial.println("---------------------------------\n");
+}
+
+
+void loop()
+{
+ dbgPrintVersion();
+ digitalToggle(LED_RED);
+ delay(5000); // wait for a second
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/gpstest_swuart/gpstest_swuart.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/gpstest_swuart/gpstest_swuart.ino
new file mode 100755
index 0000000..262f079
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/gpstest_swuart/gpstest_swuart.ino
@@ -0,0 +1,57 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This example show how to use Software Serial on Bluefruit nRF52
+ * to interact with GPS FeatherWing https://www.adafruit.com/product/3133
+ *
+ * Hardware Set up
+ * - Connect 3V and GND to GPS wing
+ * -
+ */
+
+#include <SoftwareSerial.h>
+
+#define SW_RXD A0
+#define SW_TXD A1
+
+// Declare an Software Serial instance
+SoftwareSerial mySerial(SW_RXD, SW_TXD);
+
+void setup() {
+
+ // Init hardware UART <-> Serial Monitor
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("GPS echo test");
+
+ // Init Software Uart <-> GPS FeatherWing
+ mySerial.begin(9600); // default NMEA GPS baud
+}
+
+
+void loop() {
+
+ // Pass data from Serial (HW uart) to GPS Wing (SW Uart)
+ if (Serial.available()) {
+ char c = Serial.read();
+ mySerial.write(c);
+ }
+
+ // Pass data from GPS Wing (SW Uart) to Serial (HW uart)
+ if (mySerial.available()) {
+ char c = mySerial.read();
+ Serial.write(c);
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/hw_systick/hw_systick.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/hw_systick/hw_systick.ino
new file mode 100755
index 0000000..72ae8f8
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/hw_systick/hw_systick.ino
@@ -0,0 +1,57 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <Arduino.h>
+
+// Interval between systick event
+#define TICK_INTERVAL_MS 50
+
+// Note: Extern "C" is required since all the IRQ hardware handler is
+// declared as "C function" within the startup (assembly) file.
+// Without it, our SysTick_Handler will be declared as "C++ function"
+// which is not the same as the "C function" in startup even it has
+// the same name.
+extern "C"
+{
+
+/* This is hardware interupt service function exectuing in non-RTOS thread
+ * Function implementation should be quick and short if possible.
+ *
+ * WARNING: This function MUST NOT call any blocking FreeRTOS API
+ * such as delay(), xSemaphoreTake() etc ... for more information
+ * http://www.freertos.org/a00016.html
+ */
+void SysTick_Handler(void)
+{
+ digitalToggle(LED_RED);
+}
+
+} // extern C
+
+void setup()
+{
+ /* Input parameter is number of ticks between interrupts handler i.e SysTick_Handler
+ * 1000 ms --> F_CPU ticks
+ * T ms --> (F_CPU/1000)*T ticks
+ *
+ * Note: Since systick is 24-bit timer, the max tick value is 0xFFFFFF, F_CPU = 64 Mhz
+ * --> our Tmax = 0xFFFFFF/64000 ~ 262 ms
+ */
+
+ SysTick_Config( (F_CPU/1000)*TICK_INTERVAL_MS );
+}
+
+void loop()
+{
+ // do nothing here
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/hwinfo/hwinfo.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/hwinfo/hwinfo.ino
new file mode 100755
index 0000000..23518b5
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/hwinfo/hwinfo.ino
@@ -0,0 +1,42 @@
+#include <Arduino.h>
+
+typedef volatile uint32_t REG32;
+#define pREG32 (REG32 *)
+
+#define DEVICE_ID_HIGH (*(pREG32 (0x10000060)))
+#define DEVICE_ID_LOW (*(pREG32 (0x10000064)))
+#define MAC_ADDRESS_HIGH (*(pREG32 (0x100000a8)))
+#define MAC_ADDRESS_LOW (*(pREG32 (0x100000a4)))
+
+void setup() {
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit 52 HW Info");
+ Serial.println("");
+
+ // MAC Address
+ uint32_t addr_high = ((MAC_ADDRESS_HIGH) & 0x0000ffff) | 0x0000c000;
+ uint32_t addr_low = MAC_ADDRESS_LOW;
+ Serial.print("MAC Address: ");
+ Serial.print((addr_high >> 8) & 0xFF, HEX); Serial.print(":");
+ Serial.print((addr_high) & 0xFF, HEX); Serial.print(":");
+ Serial.print((addr_low >> 24) & 0xFF, HEX); Serial.print(":");
+ Serial.print((addr_low >> 16) & 0xFF, HEX); Serial.print(":");
+ Serial.print((addr_low >> 8) & 0xFF, HEX); Serial.print(":");
+ Serial.print((addr_low) & 0xFF, HEX); Serial.println("");
+
+ // Unique Device ID
+ Serial.print("Device ID : ");
+ Serial.print(DEVICE_ID_HIGH, HEX);
+ Serial.println(DEVICE_ID_LOW, HEX);
+
+ // MCU Variant;
+ Serial.printf("MCU Variant: nRF%X 0x%08X\n",NRF_FICR->INFO.PART, NRF_FICR->INFO.VARIANT);
+ Serial.printf("Memory : Flash = %d KB, RAM = %d KB\n", NRF_FICR->INFO.FLASH, NRF_FICR->INFO.RAM);
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/hwpwm/hwpwm.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/hwpwm/hwpwm.ino
new file mode 100755
index 0000000..93bf6cc
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/hwpwm/hwpwm.ino
@@ -0,0 +1,81 @@
+/*********************************************************************
+ This is an example for our Feather Bluefruit modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/*
+ * This sketch use different Hardware PWMs for LED Blue and Red
+ * running with different frequency
+ * - PWM0 : clock/1 ~ 16Mhz
+ * - PWM1 : clock/16 ~ 1Mhz
+ *
+ * While LED RED looks solid, LED BLUE will blink while fading
+ * (due to its lower freq). Furthermore LED RED is inverted
+ * compared to LED BLUE (PWM2) --> They fade in opposite direction.
+ */
+
+#include <Arduino.h>
+
+/**************************************************************************/
+/*!
+ @brief The setup function runs once when reset the board
+*/
+/**************************************************************************/
+void setup()
+{
+ // Add LED RED to PWM0
+ HwPWM0.addPin( LED_RED );
+
+ // Add LED BLUE to PWM1
+ HwPWM1.addPin( LED_BLUE );
+
+ // Enable PWM modules with 15-bit resolutions(max) but different clock div
+ HwPWM0.begin();
+ HwPWM0.setResolution(15);
+ HwPWM0.setClockDiv(PWM_PRESCALER_PRESCALER_DIV_1); // freq = 16Mhz
+
+ HwPWM1.begin();
+ HwPWM1.setResolution(15);
+ HwPWM1.setClockDiv(PWM_PRESCALER_PRESCALER_DIV_16); // freq = 1Mhz
+}
+
+/**************************************************************************/
+/*!
+ @brief The loop function runs over and over again forever
+*/
+/**************************************************************************/
+void loop()
+{
+ const int maxValue = bit(15) - 1;
+
+ // fade in from min to max
+ for (int fadeValue = 0 ; fadeValue <= maxValue; fadeValue += 1024)
+ {
+ // Write same value but inverted for Led Blue
+ HwPWM0.writePin(LED_RED, fadeValue, false);
+ HwPWM1.writePin(LED_BLUE, fadeValue, true);
+
+ // wait for 30 milliseconds to see the dimming effect
+ delay(30);
+ }
+
+ // fade out from max to min
+ for (int fadeValue = maxValue ; fadeValue >= 0; fadeValue -= 1024)
+ {
+ // Write same value but inverted for Led Blue
+ HwPWM0.writePin(LED_RED, fadeValue, false);
+ HwPWM1.writePin(LED_BLUE, fadeValue, true);
+
+ // wait for 30 milliseconds to see the dimming effect
+ delay(30);
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/meminfo/meminfo.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/meminfo/meminfo.ino
new file mode 100755
index 0000000..9df909c
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/meminfo/meminfo.ino
@@ -0,0 +1,33 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <Arduino.h>
+
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Memory Info Example");
+ Serial.println("-------------------------------\n");
+}
+
+
+void loop()
+{
+ dbgMemInfo();
+ digitalToggle(LED_RED);
+ delay(5000); // wait for a second
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/nfc_to_gpio/nfc_to_gpio.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/nfc_to_gpio/nfc_to_gpio.ino
new file mode 100755
index 0000000..89fa7cb
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/nfc_to_gpio/nfc_to_gpio.ino
@@ -0,0 +1,40 @@
+// This sketch will check if the NFC pins are configured for NFC mode,
+// and if so it will switch them to operate in GPIO mode. A system
+// reset is required before this change takes effect since the CONFIG
+// memory is only read on power up.
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// !!!!! IMPORTANT NOTE ... READ BEFORE RUNNING THIS SKETCH !!!!!
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+// UICR customer registers are meant to be stored with values
+// that are supposed to stay there during the life time of the softdevice.
+// You cannot erase them without erasing everything on chip, so setting the
+// NFC pins to GPIO mode is a ONE WAY OPERATION and you will need a debugger
+// like a Segger J-Link to set them back to NFC mode!
+
+void setup() {
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 NFC to GPIO Pin Config");
+ Serial.println("----------------------------------\n");
+ if ((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)){
+ Serial.println("Fix NFC pins");
+ NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
+ while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
+ NRF_UICR->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk;
+ while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
+ NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
+ while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
+ Serial.println("Done");
+ delay(500);
+ NVIC_SystemReset();
+ }
+
+}
+void loop() {
+ // put your main code here, to run repeatedly:
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/rtos_scheduler/rtos_scheduler.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/rtos_scheduler/rtos_scheduler.ino
new file mode 100755
index 0000000..032b070
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/rtos_scheduler/rtos_scheduler.ino
@@ -0,0 +1,49 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <Arduino.h>
+
+/*
+ * Sketch demonstate mutli-task using Scheduler. Demo create loop2() that
+ * run in 'parallel' with loop().
+ * - loop() toggle LED_RED every 1 second
+ * - loop2() toggle LED_BLUE every half of second
+ */
+
+void setup()
+{
+ // LED_RED & LED_BLUE pin already initialized as an output.
+
+ // Create loop2() using Scheduler to run in 'parallel' with loop()
+ Scheduler.startLoop(loop2);
+}
+
+/**
+ * Toggle led1 every 1 second
+ */
+void loop()
+{
+ digitalToggle(LED_RED); // Toggle LED
+ delay(1000); // wait for a second
+}
+
+/**
+ * Toggle led1 every 0.5 second
+ */
+void loop2()
+{
+ digitalToggle(LED_BLUE); // Toggle LED
+ delay(500); // wait for a half second
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Hardware/software_timer/software_timer.ino b/arduino/libraries/Bluefruit52Lib/examples/Hardware/software_timer/software_timer.ino
new file mode 100755
index 0000000..8a63990
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Hardware/software_timer/software_timer.ino
@@ -0,0 +1,58 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <Arduino.h>
+
+/* SoftwareTimer is a helper class that uses FreeRTOS software timer
+ * to invoke callback. Its periodic timing is flexible as opposed to
+ * hardware timer and cannot be faster than rtos's tick which is configured
+ * at ~1 ms interval.
+ *
+ * If you need an strict interval timing, or faster frequency, check out
+ * the hw_systick sketch example that use hardware systick timer.
+ *
+ * http://www.freertos.org/RTOS-software-timer.html
+ */
+SoftwareTimer blinkTimer;
+
+
+void setup()
+{
+ // Configure the timer with 1000 ms interval, with our callback
+ blinkTimer.begin(1000, blink_timer_callback);
+
+ // Start the timer
+ blinkTimer.start();
+}
+
+void loop()
+{
+ // do nothing here
+}
+
+
+/**
+ * Software Timer callback is invoked via a built-in FreeRTOS thread with
+ * minimal stack size. Therefore it should be as simple as possible. If
+ * a periodically heavy task is needed, please use Scheduler.startLoop() to
+ * create a dedicated task for it.
+ *
+ * More information http://www.freertos.org/RTOS-software-timer.html
+ */
+void blink_timer_callback(TimerHandle_t xTimerID)
+{
+ // freeRTOS timer ID, ignored if not used
+ (void) xTimerID;
+
+ digitalToggle(LED_RED);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/LICENSE.txt b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/LICENSE.txt
new file mode 100755
index 0000000..77cec6d
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/LICENSE.txt
@@ -0,0 +1,458 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/StandardFirmataBLE.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/StandardFirmataBLE.ino
new file mode 100755
index 0000000..5cfa943
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/StandardFirmataBLE.ino
@@ -0,0 +1,916 @@
+/*
+ Firmata is a generic protocol for communicating with microcontrollers
+ from software on a host computer. It is intended to work with
+ any host computer software package.
+
+ To download a host software package, please click on the following link
+ to open the list of Firmata client libraries in your default browser.
+
+ https://github.com/firmata/arduino#firmata-client-libraries
+
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated October 16th, 2016
+*/
+
+// Adafruit nRF52 Boards require Firmata at least 2.5.7
+
+#include <bluefruit.h>
+#include <Servo.h>
+#include <Wire.h>
+#include <Firmata.h>
+
+#define I2C_WRITE B00000000
+#define I2C_READ B00001000
+#define I2C_READ_CONTINUOUSLY B00010000
+#define I2C_STOP_READING B00011000
+#define I2C_READ_WRITE_MODE_MASK B00011000
+#define I2C_10BIT_ADDRESS_MODE_MASK B00100000
+#define I2C_END_TX_MASK B01000000
+#define I2C_STOP_TX 1
+#define I2C_RESTART_TX 0
+#define I2C_MAX_QUERIES 8
+#define I2C_REGISTER_NOT_SPECIFIED -1
+
+// the minimum interval for sampling analog input
+#define MINIMUM_SAMPLING_INTERVAL 1
+
+// Adafruit
+uint8_t ANALOG_TO_PIN(uint8_t n)
+{
+ switch (n)
+ {
+ case 0 : return PIN_A0;
+ case 1 : return PIN_A1;
+ case 2 : return PIN_A2;
+ case 3 : return PIN_A3;
+ case 4 : return PIN_A4;
+ case 5 : return PIN_A5;
+ case 6 : return PIN_A6;
+ case 7 : return PIN_A7;
+ }
+
+ return 127;
+}
+
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+#ifdef FIRMATA_SERIAL_FEATURE
+SerialFirmata serialFeature;
+#endif
+
+BLEUart bleuart;
+
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+
+/* digital input ports */
+byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
+byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
+
+/* pins configuration */
+byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+unsigned int samplingInterval = 19; // how often to run the main loop (in ms)
+
+/* i2c data */
+struct i2c_device_info {
+ byte addr;
+ int reg;
+ byte bytes;
+ byte stopTX;
+};
+
+/* for i2c read continuous more */
+i2c_device_info query[I2C_MAX_QUERIES];
+
+byte i2cRxData[64];
+boolean isI2CEnabled = false;
+signed char queryIndex = -1;
+// default delay time between i2c read request and Wire.requestFrom()
+unsigned int i2cReadDelayTime = 0;
+
+Servo servos[MAX_SERVOS];
+byte servoPinMap[TOTAL_PINS];
+byte detachedServos[MAX_SERVOS];
+byte detachedServoCount = 0;
+byte servoCount = 0;
+
+boolean isResetting = false;
+
+// Forward declare a few functions to avoid compiler errors with older versions
+// of the Arduino IDE.
+void setPinModeCallback(byte, int);
+void reportAnalogCallback(byte analogPin, int value);
+void sysexCallback(byte, byte, byte*);
+
+/* utility functions */
+void wireWrite(byte data)
+{
+#if ARDUINO >= 100
+ Wire.write((byte)data);
+#else
+ Wire.send(data);
+#endif
+}
+
+byte wireRead(void)
+{
+#if ARDUINO >= 100
+ return Wire.read();
+#else
+ return Wire.receive();
+#endif
+}
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void attachServo(byte pin, int minPulse, int maxPulse)
+{
+ if (servoCount < MAX_SERVOS) {
+ // reuse indexes of detached servos until all have been reallocated
+ if (detachedServoCount > 0) {
+ servoPinMap[pin] = detachedServos[detachedServoCount - 1];
+ if (detachedServoCount > 0) detachedServoCount--;
+ } else {
+ servoPinMap[pin] = servoCount;
+ servoCount++;
+ }
+ if (minPulse > 0 && maxPulse > 0) {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
+ } else {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
+ }
+ } else {
+ Firmata.sendString("Max servos attached");
+ }
+}
+
+void detachServo(byte pin)
+{
+ servos[servoPinMap[pin]].detach();
+ // if we're detaching the last servo, decrement the count
+ // otherwise store the index of the detached servo
+ if (servoPinMap[pin] == servoCount && servoCount > 0) {
+ servoCount--;
+ } else if (servoCount > 0) {
+ // keep track of detached servos because we want to reuse their indexes
+ // before incrementing the count of attached servos
+ detachedServoCount++;
+ detachedServos[detachedServoCount - 1] = servoPinMap[pin];
+ }
+
+ servoPinMap[pin] = 255;
+}
+
+void enableI2CPins()
+{
+ byte i;
+ // is there a faster way to do this? would probaby require importing
+ // Arduino.h to get SCL and SDA pins
+ for (i = 0; i < TOTAL_PINS; i++) {
+ if (IS_PIN_I2C(i)) {
+ // mark pins as i2c so they are ignore in non i2c data requests
+ setPinModeCallback(i, PIN_MODE_I2C);
+ }
+ }
+
+ isI2CEnabled = true;
+
+ Wire.begin();
+}
+
+/* disable the i2c pins so they can be used for other functions */
+void disableI2CPins() {
+ isI2CEnabled = false;
+ // disable read continuous mode for all devices
+ queryIndex = -1;
+}
+
+void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
+ // allow I2C requests that don't require a register read
+ // for example, some devices using an interrupt pin to signify new data available
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
+ if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
+ Wire.beginTransmission(address);
+ wireWrite((byte)theRegister);
+ Wire.endTransmission(stopTX); // default = true
+ // do not set a value of 0
+ if (i2cReadDelayTime > 0) {
+ // delay is necessary for some devices such as WiiNunchuck
+ delayMicroseconds(i2cReadDelayTime);
+ }
+ } else {
+ theRegister = 0; // fill the register with a dummy value
+ }
+
+ Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
+
+ // check to be sure correct number of bytes were returned by slave
+ if (numBytes < Wire.available()) {
+ Firmata.sendString("I2C: Too many bytes received");
+ } else if (numBytes > Wire.available()) {
+ Firmata.sendString("I2C: Too few bytes received");
+ }
+
+ i2cRxData[0] = address;
+ i2cRxData[1] = theRegister;
+
+ for (int i = 0; i < numBytes && Wire.available(); i++) {
+ i2cRxData[2 + i] = wireRead();
+ }
+
+ // send slave address, register and received bytes
+ Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
+}
+
+void outputPort(byte portNumber, byte portValue, byte forceSend)
+{
+ // pins not configured as INPUT are cleared to zeros
+ portValue = portValue & portConfigInputs[portNumber];
+ // only send if the value is different than previously sent
+ if (forceSend || previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * check all the active digital inputs for change of state, then add any events
+ * to the Serial output queue using Serial.print() */
+void checkDigitalInputs(void)
+{
+ /* Using non-looping code allows constants to be given to readPort().
+ * The compiler will apply substantial optimizations if the inputs
+ * to readPort() are compile-time constants. */
+ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
+ if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
+ if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
+ if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
+ if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
+ if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
+ if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
+ if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
+ if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
+ if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
+ if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
+ if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
+ if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
+ if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
+ if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
+ if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
+}
+
+// -----------------------------------------------------------------------------
+/* sets the pin mode to the correct state and sets the relevant bits in the
+ * two bit-arrays that track Digital I/O and PWM status
+ */
+void setPinModeCallback(byte pin, int mode)
+{
+ if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
+ return;
+
+ if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
+ // disable i2c so pins can be used for other functions
+ // the following if statements should reconfigure the pins properly
+ disableI2CPins();
+ }
+ if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ if (mode == INPUT || mode == PIN_MODE_PULLUP) {
+ portConfigInputs[pin / 8] |= (1 << (pin & 7));
+ } else {
+ portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
+ }
+ }
+ Firmata.setPinState(pin, 0);
+ switch (mode) {
+ case PIN_MODE_ANALOG:
+ if (IS_PIN_ANALOG(pin)) {
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ }
+ Firmata.setPinMode(pin, PIN_MODE_ANALOG);
+ }
+ break;
+ case INPUT:
+// Adafruit: Input without pull up cause pin state changes randomly --> lots of transmission data
+// if (IS_PIN_DIGITAL(pin)) {
+// pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+//#if ARDUINO <= 100
+// // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+// digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+//#endif
+// Firmata.setPinMode(pin, INPUT);
+// }
+// break;
+ case PIN_MODE_PULLUP:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
+ Firmata.setPinMode(pin, PIN_MODE_PULLUP);
+ Firmata.setPinState(pin, 1);
+ }
+ break;
+ case OUTPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
+ // Disable PWM if pin mode was previously set to PWM.
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW);
+ }
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
+ Firmata.setPinMode(pin, OUTPUT);
+ }
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin)) {
+ pinMode(PIN_TO_PWM(pin), OUTPUT);
+ analogWrite(PIN_TO_PWM(pin), 0);
+ Firmata.setPinMode(pin, PIN_MODE_PWM);
+ }
+ break;
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.setPinMode(pin, PIN_MODE_SERVO);
+ if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
+ // pass -1 for min and max pulse values to use default values set
+ // by Servo library
+ attachServo(pin, -1, -1);
+ }
+ }
+ break;
+ case PIN_MODE_I2C:
+ if (IS_PIN_I2C(pin)) {
+ // mark the pin as i2c
+ // the user must call I2C_CONFIG to enable I2C for a device
+ Firmata.setPinMode(pin, PIN_MODE_I2C);
+ }
+ break;
+ case PIN_MODE_SERIAL:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
+#endif
+ break;
+ default:
+ Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+/*
+ * Sets the value of an individual pin. Useful if you want to set a pin value but
+ * are not tracking the digital port state.
+ * Can only be used on pins configured as OUTPUT.
+ * Cannot be used to enable pull-ups on Digital INPUT pins.
+ */
+void setPinValueCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ Firmata.setPinState(pin, value);
+ digitalWrite(PIN_TO_DIGITAL(pin), value);
+ }
+ }
+}
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS) {
+ switch (Firmata.getPinMode(pin)) {
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin))
+ servos[servoPinMap[pin]].write(value);
+ Firmata.setPinState(pin, value);
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin))
+ analogWrite(PIN_TO_PWM(pin), value);
+ Firmata.setPinState(pin, value);
+ break;
+ }
+ }
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
+
+ if (port < TOTAL_PORTS) {
+ // create a mask of the pins on this port that are writable.
+ lastPin = port * 8 + 8;
+ if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
+ for (pin = port * 8; pin < lastPin; pin++) {
+ // do not disturb non-digital pins (eg, Rx & Tx)
+ if (IS_PIN_DIGITAL(pin)) {
+ // do not touch pins in PWM, ANALOG, SERVO or other modes
+ if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
+ pinValue = ((byte)value & mask) ? 1 : 0;
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ pinWriteMask |= mask;
+ } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
+ // only handle INPUT here for backwards compatibility
+#if ARDUINO > 100
+ pinMode(pin, INPUT_PULLUP);
+#else
+ // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
+ pinWriteMask |= mask;
+#endif
+ }
+ Firmata.setPinState(pin, pinValue);
+ }
+ }
+ mask = mask << 1;
+ }
+ writePort(port, (byte)value, pinWriteMask);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+/* sets bits in a bit array (int) to toggle the reporting of the analogIns
+ */
+//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
+//}
+void reportAnalogCallback(byte analogPin, int value)
+{
+ if (analogPin < TOTAL_ANALOG_PINS) {
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
+ } else {
+ analogInputsToReport = analogInputsToReport | (1 << analogPin);
+ // prevent during system reset or all analog pin values will be reported
+ // which may report noise for unconnected analog pins
+ if (!isResetting) {
+ // Send pin value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ Firmata.sendAnalog(analogPin, analogRead( ANALOG_TO_PIN(analogPin) ) );
+ }
+ }
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+void reportDigitalCallback(byte port, int value)
+{
+ if (port < TOTAL_PORTS) {
+ reportPINs[port] = (byte)value;
+ // Send port value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
+ }
+ // do not disable analog reporting on these 8 pins, to allow some
+ // pins used for digital, others analog. Instead, allow both types
+ // of reporting to be enabled, but check if the pin is configured
+ // as analog when sampling the analog inputs. Likewise, while
+ // scanning digital pins, portConfigInputs will mask off values from any
+ // pins configured as analog
+}
+
+/*==============================================================================
+ * SYSEX-BASED commands
+ *============================================================================*/
+
+void sysexCallback(byte command, byte argc, byte *argv)
+{
+ byte mode;
+ byte stopTX;
+ byte slaveAddress;
+ byte data;
+ int slaveRegister;
+ unsigned int delayTime;
+
+ switch (command) {
+ case I2C_REQUEST:
+ mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
+ if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
+ Firmata.sendString("10-bit addressing not supported");
+ return;
+ }
+ else {
+ slaveAddress = argv[0];
+ }
+
+ // need to invert the logic here since 0 will be default for client
+ // libraries that have not updated to add support for restart tx
+ if (argv[1] & I2C_END_TX_MASK) {
+ stopTX = I2C_RESTART_TX;
+ }
+ else {
+ stopTX = I2C_STOP_TX; // default
+ }
+
+ switch (mode) {
+ case I2C_WRITE:
+ Wire.beginTransmission(slaveAddress);
+ for (byte i = 2; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ wireWrite(data);
+ }
+ Wire.endTransmission();
+ delayMicroseconds(70);
+ break;
+ case I2C_READ:
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
+ break;
+ case I2C_READ_CONTINUOUSLY:
+ if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
+ // too many queries, just ignore
+ Firmata.sendString("too many queries");
+ break;
+ }
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ queryIndex++;
+ query[queryIndex].addr = slaveAddress;
+ query[queryIndex].reg = slaveRegister;
+ query[queryIndex].bytes = data;
+ query[queryIndex].stopTX = stopTX;
+ break;
+ case I2C_STOP_READING:
+ byte queryIndexToSkip;
+ // if read continuous mode is enabled for only 1 i2c device, disable
+ // read continuous reporting for that device
+ if (queryIndex <= 0) {
+ queryIndex = -1;
+ } else {
+ queryIndexToSkip = 0;
+ // if read continuous mode is enabled for multiple devices,
+ // determine which device to stop reading and remove it's data from
+ // the array, shifiting other array data to fill the space
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ if (query[i].addr == slaveAddress) {
+ queryIndexToSkip = i;
+ break;
+ }
+ }
+
+ for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
+ if (i < I2C_MAX_QUERIES) {
+ query[i].addr = query[i + 1].addr;
+ query[i].reg = query[i + 1].reg;
+ query[i].bytes = query[i + 1].bytes;
+ query[i].stopTX = query[i + 1].stopTX;
+ }
+ }
+ queryIndex--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case I2C_CONFIG:
+ delayTime = (argv[0] + (argv[1] << 7));
+
+ if (delayTime > 0) {
+ i2cReadDelayTime = delayTime;
+ }
+
+ if (!isI2CEnabled) {
+ enableI2CPins();
+ }
+
+ break;
+ case SERVO_CONFIG:
+ if (argc > 4) {
+ // these vars are here for clarity, they'll optimized away by the compiler
+ byte pin = argv[0];
+ int minPulse = argv[1] + (argv[2] << 7);
+ int maxPulse = argv[3] + (argv[4] << 7);
+
+ if (IS_PIN_DIGITAL(pin)) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ attachServo(pin, minPulse, maxPulse);
+ setPinModeCallback(pin, PIN_MODE_SERVO);
+ }
+ }
+ break;
+ case SAMPLING_INTERVAL:
+ if (argc > 1) {
+ samplingInterval = argv[0] + (argv[1] << 7);
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL;
+ }
+ } else {
+ //Firmata.sendString("Not enough data");
+ }
+ break;
+ case EXTENDED_ANALOG:
+ if (argc > 1) {
+ int val = argv[1];
+ if (argc > 2) val |= (argv[2] << 7);
+ if (argc > 3) val |= (argv[3] << 14);
+ analogWriteCallback(argv[0], val);
+ }
+ break;
+ case CAPABILITY_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(CAPABILITY_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write((byte)INPUT);
+ Firmata.write(1);
+ Firmata.write((byte)PIN_MODE_PULLUP);
+ Firmata.write(1);
+ Firmata.write((byte)OUTPUT);
+ Firmata.write(1);
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ Firmata.write(PIN_MODE_ANALOG);
+ Firmata.write(10); // 10 = 10-bit resolution
+ }
+ if (IS_PIN_PWM(pin)) {
+ Firmata.write(PIN_MODE_PWM);
+ Firmata.write(DEFAULT_PWM_RESOLUTION);
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write(PIN_MODE_SERVO);
+ Firmata.write(14);
+ }
+ if (IS_PIN_I2C(pin)) {
+ Firmata.write(PIN_MODE_I2C);
+ Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
+ }
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleCapability(pin);
+#endif
+ Firmata.write(127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+ case PIN_STATE_QUERY:
+ if (argc > 0) {
+ byte pin = argv[0];
+ Firmata.write(START_SYSEX);
+ Firmata.write(PIN_STATE_RESPONSE);
+ Firmata.write(pin);
+ if (pin < TOTAL_PINS) {
+ Firmata.write(Firmata.getPinMode(pin));
+ Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
+ }
+ Firmata.write(END_SYSEX);
+ }
+ break;
+ case ANALOG_MAPPING_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(ANALOG_MAPPING_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+
+ case SERIAL_MESSAGE:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleSysex(command, argc, argv);
+#endif
+ break;
+ }
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+
+void systemResetCallback()
+{
+ isResetting = true;
+
+ // initialize a defalt state
+ // TODO: option to load config from EEPROM instead of default
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.reset();
+#endif
+
+ if (isI2CEnabled) {
+ disableI2CPins();
+ }
+
+ for (byte i = 0; i < TOTAL_PORTS; i++) {
+ reportPINs[i] = false; // by default, reporting off
+ portConfigInputs[i] = 0; // until activated
+ previousPINs[i] = 0;
+ }
+
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ // pins with analog capability default to analog input
+ // otherwise, pins default to digital output
+ if (IS_PIN_ANALOG(i)) {
+ // turns off pullup, configures everything
+ setPinModeCallback(i, PIN_MODE_ANALOG);
+ } else if (IS_PIN_DIGITAL(i)) {
+ // sets the output to 0, configures portConfigInputs
+ setPinModeCallback(i, OUTPUT);
+ }
+
+ servoPinMap[i] = 255;
+ }
+ // by default, do not report any analog inputs
+ analogInputsToReport = 0;
+
+ detachedServoCount = 0;
+ servoCount = 0;
+
+ /* send digital inputs to set the initial state on the host computer,
+ * since once in the loop(), this firmware will only send on change */
+ /*
+ TODO: this can never execute, since no pins default to digital input
+ but it will be needed when/if we support EEPROM stored config
+ for (byte i=0; i < TOTAL_PORTS; i++) {
+ outputPort(i, readPort(i, portConfigInputs[i]), true);
+ }
+ */
+ isResetting = false;
+}
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Standard Firmata via BLEUART Example");
+ Serial.println("------------------------------------------------\n");
+
+ // Config the peripheral connection with maximum bandwidth
+ // more SRAM required by SoftDevice
+ // Note: All config***() function must be called before begin()
+ Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+ Bluefruit.setName("Bluefruit52");
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+
+ // try to go as fast as possible, could be rejected by some central, increase it if needed
+ // iOS won't negotitate and will mostly use 30ms
+ Bluefruit.setConnInterval(9, 24); // min = 9*1.25=11.25 ms, max = 23*1.25=30ms
+
+ // Configure and Start BLE Uart Service
+ // Firmata use several small write(1) --> buffering TXD is required to run smoothly
+ // Enable buffering TXD
+ bleuart.begin();
+ bleuart.bufferTXD(true);
+
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+ Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
+ Firmata.attach(START_SYSEX, sysexCallback);
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
+
+ // use bleuart as transportation layer
+ Firmata.begin(bleuart);
+
+ // to use a port other than Serial, such as Serial1 on an Arduino Leonardo or Mega,
+ // Call begin(baud) on the alternate serial port and pass it to Firmata to begin like this:
+ // Serial1.begin(57600);
+ // Firmata.begin(Serial1);
+ // However do not do this if you are using SERIAL_MESSAGE
+
+ //Firmata.begin(57600);
+ //while (!Serial) {
+ // ; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101
+ //}
+
+ systemResetCallback(); // reset to default config
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include bleuart 128-bit uuid
+ Bluefruit.Advertising.addService(bleuart);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ // Skip if not connected and bleuart notification is enabled
+ if ( !(Bluefruit.connected() && bleuart.notifyEnabled()) )
+ {
+ // go to low power mode since there is nothing to do
+ waitForEvent();
+ return;
+ }
+
+ byte pin, analogPin;
+
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
+ * FTDI buffer using Serial.print() */
+ checkDigitalInputs();
+
+ /* STREAMREAD - processing incoming messagse as soon as possible, while still
+ * checking digital inputs. */
+ while (Firmata.available())
+ Firmata.processInput();
+
+ // TODO - ensure that Stream buffer doesn't go over 60 bytes
+
+ currentMillis = millis();
+ if (currentMillis - previousMillis > samplingInterval) {
+ previousMillis += samplingInterval;
+ /* ANALOGREAD - do all analogReads() at the configured sampling interval */
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
+ analogPin = PIN_TO_ANALOG(pin);
+ if (analogInputsToReport & (1 << analogPin)) {
+ Firmata.sendAnalog(analogPin, analogRead( ANALOG_TO_PIN(analogPin) ));
+ }
+ }
+ }
+ // report i2c data for all device with read continuous mode enabled
+ if (queryIndex > -1) {
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
+ }
+ }
+ }
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.update();
+#endif
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/adv_advanced/adv_advanced.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/adv_advanced/adv_advanced.ino
new file mode 100755
index 0000000..7332a2d
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/adv_advanced/adv_advanced.ino
@@ -0,0 +1,91 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketches demontrates the Bluefruit.Advertising API(). When powered up,
+ * the Bluefruit module will start advertising for ADV_TIMEOUT seconds (by
+ * default 30 seconds in fast mode, the remaining time slow mode) and then
+ * stop advertising completely. The module will start advertising again if
+ * PIN_ADV is grounded.
+ */
+#include <bluefruit.h>
+
+#define PIN_ADV A0
+#define ADV_TIMEOUT 60 // seconds
+
+void setup()
+{
+ // configure PIN_ADV as input with a pullup (pin is active low)
+ pinMode(PIN_ADV, INPUT_PULLUP);
+
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Advanced Advertising Example");
+ Serial.println("----------------------------------------\n");
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Set up and start advertising
+ startAdv();
+
+ Serial.println("Advertising is started");
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.setStopCallback(adv_stop_callback);
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in units of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(ADV_TIMEOUT); // Stop advertising entirely after ADV_TIMEOUT seconds
+}
+
+void loop()
+{
+ // Only check pin when advertising has already stopped
+ if ( !Bluefruit.Advertising.isRunning() )
+ {
+ // Check if Pin is grounded
+ if ( digitalRead(PIN_ADV) == 0 )
+ {
+ Bluefruit.Advertising.start(ADV_TIMEOUT);
+ Serial.println("Advertising is started");
+ }
+ }
+}
+
+/**
+ * Callback invoked when advertising is stopped by timeout
+ */
+void adv_stop_callback(void)
+{
+ Serial.println("Advertising time passed, advertising will now stop.");
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/ancs/ancs.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/ancs/ancs.ino
new file mode 100755
index 0000000..5b4e48a
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/ancs/ancs.ino
@@ -0,0 +1,217 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch demonstrate the BLEAncs service. After uploading, go to
+ * iOS setting and connect to Bluefruit, and then press PAIR. Bluefruit
+ * will print out any notification meesages to Serial Monitor
+ */
+
+#include <bluefruit.h>
+
+// BLE Client Service
+BLEClientDis bleClientDis;
+BLEAncs bleancs;
+
+char buffer[128];
+
+// Check BLEAncs.h for AncsNotification_t
+const char* EVENT_STR[] = { "Added", "Modified", "Removed" };
+const char* CAT_STR [] =
+{
+ "Other" , "Incoming Call" , "Missed Call", "Voice Mail" ,
+ "Social" , "Schedule" , "Email" , "News" ,
+ "Health and Fitness", "Business and Finance", "Location" , "Entertainment"
+};
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 BLE ANCS Example");
+ Serial.println("----------------------------\n");
+
+ Serial.println("Go to iOS's Bluetooth settings and connect to Bluefruit52");
+ Serial.println("It may appear up as 'Accessory' depending on your OS version.");
+
+ // Config the peripheral connection with maximum bandwidth
+ // more SRAM required by SoftDevice
+ // Note: All config***() function must be called before begin()
+ Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+ Bluefruit.setConnectCallback(connect_callback);
+ Bluefruit.setDisconnectCallback(disconnect_callback);
+
+ // Configure DIS client
+ bleClientDis.begin();
+
+ // Configure ANCS client
+ bleancs.begin();
+ bleancs.setNotificationCallback(ancs_notification_callback);
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include ANCS 128-bit uuid
+ Bluefruit.Advertising.addService(bleancs);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // Not connected, wait for a connection
+ if ( !Bluefruit.connected() ) return;
+
+ // If service is not yet discovered
+ if ( !bleancs.discovered() ) return;
+
+ // Your code here
+}
+
+void connect_callback(uint16_t conn_handle)
+{
+ Serial.println("Connected");
+
+ Serial.print("Discovering DIS ... ");
+ if ( bleClientDis.discover(conn_handle) )
+ {
+ Serial.println("Discovered");
+
+ // Read and print Manufacturer string
+ memset(buffer, 0, sizeof(buffer));
+ if ( bleClientDis.getManufacturer(buffer, sizeof(buffer)) )
+ {
+ Serial.print("Manufacturer: ");
+ Serial.println(buffer);
+ }
+
+ // Read and print Model Number string
+ memset(buffer, 0, sizeof(buffer));
+ if ( bleClientDis.getModel(buffer, sizeof(buffer)) )
+ {
+ Serial.print("Model: ");
+ Serial.println(buffer);
+ }
+
+ Serial.println();
+ }
+
+ Serial.print("Discovering ANCS ... ");
+ if ( bleancs.discover(conn_handle) )
+ {
+ Serial.println("Discovered");
+
+ // ANCS requires pairing to work, it makes sense to request security here as well
+ Serial.print("Attempting to PAIR with the iOS device, please press PAIR on your phone ... ");
+ if ( Bluefruit.requestPairing() )
+ {
+ Serial.println("Done");
+ Serial.println("Enabling notifications");
+ Serial.println();
+ bleancs.enableNotification();
+
+ Serial.println("| Event | Category (count) | Title | Message | App ID | App Name |");
+ Serial.println("---------------------------------------------------------------------------------------------------------------");
+ }
+ }
+}
+
+void ancs_notification_callback(AncsNotification_t* notif)
+{
+ int n;
+ Serial.printf("| %-8s | ", EVENT_STR[notif->eventID]);
+
+ // Print Category with padding
+ n = Serial.printf("%s (%d)", CAT_STR[notif->categoryID], notif->categoryCount);
+ for (int i=n; i<20; i++) Serial.print(' ');
+ Serial.print(" | ");
+
+ // Get notification Title
+ // iDevice often includes Unicode "Bidirection Text Control" in the Title.
+ // Most strings have U+202D at the beginning and U+202C at the end. You may
+ // want to remove them.
+ // U+202D is E2-80-AD, U+202C is E2-80-AC in UTF-8
+ memset(buffer, 0, sizeof(buffer));
+ bleancs.getAttribute(notif->uid, ANCS_ATTR_TITLE, buffer, sizeof(buffer));
+ Serial.printf("%-14s | ", buffer);
+
+ // Get notification Message
+ memset(buffer, 0, sizeof(buffer));
+ bleancs.getAttribute(notif->uid, ANCS_ATTR_MESSAGE, buffer, sizeof(buffer));
+ Serial.printf("%-15s | ", buffer);
+
+ // Get App ID and store in the app_id variable
+ char app_id[64] = { 0 };
+ memset(buffer, 0, sizeof(buffer));
+ bleancs.getAttribute(notif->uid, ANCS_ATTR_APP_IDENTIFIER, buffer, sizeof(buffer));
+ strcpy(app_id, buffer);
+ Serial.printf("%-20s | ", app_id);
+
+ // Get Application Name
+ memset(buffer, 0, sizeof(buffer));
+ bleancs.getAppAttribute(app_id, ANCS_APP_ATTR_DISPLAY_NAME, buffer, sizeof(buffer));
+ Serial.printf("%-15s | ", buffer);
+
+ Serial.println();
+
+ // Automatically accept incoming calls using 'performAction'
+ if ( notif->categoryID == ANCS_CAT_INCOMING_CALL && notif->eventID == ANCS_EVT_NOTIFICATION_ADDED)
+ {
+ Serial.println("Incoming call accepted");
+ bleancs.performAction(notif->uid, ANCS_ACTION_POSITIVE);
+ }
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) reason;
+
+ Serial.println();
+ Serial.println("Disconnected");
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/ancs_oled/ancs_oled.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/ancs_oled/ancs_oled.ino
new file mode 100755
index 0000000..ce91a31
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/ancs_oled/ancs_oled.ino
@@ -0,0 +1,458 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/*
+ * This sketch is similar to 'ancs', but it also uses a Feather OLED
+ * Wing to display incoming ANCS alerts:
+ * https://www.adafruit.com/product/2900
+ *
+ * BUTTON A: Up or accept call
+ * BUTTON B: Not used since it is hard to press
+ * BUTTON C: Down or decline call
+ */
+#include <Wire.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
+#include <bluefruit.h>
+
+/*------------- OLED and Buttons -------------*/
+#if defined ARDUINO_NRF52_FEATHER
+// Feather nRF52832
+#define BUTTON_A 31
+#define BUTTON_B 30
+#define BUTTON_C 27
+
+#elif defined ARDUINO_NRF52840_FEATHER
+// Feather nRF52840
+#define BUTTON_A 9
+#define BUTTON_B 6
+#define BUTTON_C 5
+
+#else
+#error board not supported
+#endif
+
+
+#define OLED_RESET 4 // TODO remove ?
+Adafruit_SSD1306 oled(OLED_RESET);
+
+
+/*------------- Notification List -------------*/
+#define MAX_COUNT 20
+#define BUFSIZE 64
+
+typedef struct
+{
+ AncsNotification_t ntf;
+ char title[BUFSIZE];
+ char message[BUFSIZE];
+ char app_name[BUFSIZE];
+} MyNotif_t;
+
+MyNotif_t myNotifs[MAX_COUNT] = { 0 };
+
+// Number of notifications
+int notifCount = 0;
+
+/*------------- Display Management -------------*/
+#define ONSCREEN_TIME 5000 // On-screen time for each notification
+
+int activeIndex = 0; // Index of currently displayed notification
+int displayIndex = -1; // Index of notification about to display
+
+uint32_t drawTime = 0; // Last time oled display notification
+
+/*------------- BLE Client Service-------------*/
+BLEAncs bleancs;
+
+void setup()
+{
+ // Button configured
+ pinMode(BUTTON_A, INPUT_PULLUP);
+ pinMode(BUTTON_B, INPUT_PULLUP);
+ pinMode(BUTTON_C, INPUT_PULLUP);
+
+ // init with the I2C addr 0x3C (for the 128x32) and show splashscreen
+ oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
+ oled.display();
+
+ oled.setTextSize(1);// max is 4 line, 21 chars each
+ oled.setTextColor(WHITE);
+
+ // Config the peripheral connection with maximum bandwidth
+ // more SRAM required by SoftDevice
+ // Note: All config***() function must be called before begin()
+ //Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+ Bluefruit.setConnectCallback(connect_callback);
+ Bluefruit.setDisconnectCallback(disconnect_callback);
+
+ // Configure and Start Service
+ bleancs.begin();
+ bleancs.setNotificationCallback(ancs_notification_callback);
+
+ // Set up and start advertising
+ startAdv();
+
+ // splash screen effect
+ delay(100);
+
+ oled.clearDisplay();
+ oled.setCursor(0, 0);
+ oled.println("Not connected");
+ oled.display();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include ANCS 128-bit uuid
+ Bluefruit.Advertising.addService(bleancs);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // If service is not yet discovered
+ if ( !bleancs.discovered() ) return;
+
+ // No notifications, do nothing
+ if ( notifCount == 0 ) return;
+
+ // Check buttons
+ uint32_t presedButtons = readPressedButtons();
+
+ if ( myNotifs[activeIndex].ntf.categoryID == ANCS_CAT_INCOMING_CALL )
+ {
+ /* Incoming call event
+ * - Button A to accept call
+ * - Button C to decline call
+ */
+ if ( presedButtons & bit(BUTTON_A) )
+ {
+ bleancs.actPositive(myNotifs[activeIndex].ntf.uid);
+ }
+
+ if ( presedButtons & bit(BUTTON_C) )
+ {
+ bleancs.actNegative(myNotifs[activeIndex].ntf.uid);
+ }
+ }
+ else
+ {
+ /* Normal events navigation (wrap around)
+ * - Button A to display previous notification
+ * - Button C to display next notification
+ *
+ * When a notification is display ONSCREEN_TIME,
+ * we will display the next one
+ */
+ if ( presedButtons & bit(BUTTON_A) )
+ {
+ displayIndex = (activeIndex != 0) ? (activeIndex-1) : (notifCount-1) ;
+ }
+
+ if ( presedButtons & bit(BUTTON_C) )
+ {
+ displayIndex = (activeIndex != (notifCount-1)) ? (activeIndex + 1) : 0;
+ }
+
+ // Display requested notification
+ if ( displayIndex >= 0 )
+ {
+ activeIndex = displayIndex;
+ displayIndex = -1;
+
+ displayNotification(activeIndex);
+ drawTime = millis(); // Save time we draw
+ }
+ // Display next notification if time is up
+ else if ( drawTime + ONSCREEN_TIME < millis() )
+ {
+ activeIndex = (activeIndex+1)%notifCount;
+
+ displayNotification(activeIndex);
+ drawTime = millis(); // Save time we draw
+ }
+ }
+}
+
+/**
+ * Display notification contents to oled screen
+ * @param index index of notification
+ */
+void displayNotification(int index)
+{
+ // safeguard
+ if ( index < 0 || (index >= notifCount) ) return;
+
+ // let's Turn on and off RED LED when we draw to get attention
+ digitalWrite(LED_RED, HIGH);
+
+ /*------------- Display to OLED -------------*/
+ MyNotif_t* myNtf = &myNotifs[index];
+
+ oled.clearDisplay();
+ oled.setCursor(0, 0);
+
+ // Incoming call event, display a bit differently
+ if ( myNtf->ntf.categoryID == ANCS_CAT_INCOMING_CALL )
+ {
+ oled.println(myNtf->title);
+ oled.println(" is calling");
+ oled.println(" Btn A to ACCEPT");
+ oled.println(" Btn C to DECLINE");
+ }else
+ {
+ // Text size = 1, max char is 21. Text size = 2, max char is 10
+ char tempbuf[22];
+ sprintf(tempbuf, "%-15s %02d/%02d", myNtf->app_name, index+1, notifCount);
+
+ oled.println(tempbuf);
+ oled.println(myNtf->title);
+
+ oled.print(" ");
+ oled.print(myNtf->message);
+ }
+
+ oled.display();
+
+ digitalWrite(LED_RED, LOW);
+}
+
+/**
+ * Connect Callback
+ * Perform ANCS discovering, request Pairing
+ */
+void connect_callback(uint16_t conn_handle)
+{
+ oled.clearDisplay();
+ oled.setCursor(0, 0);
+ oled.println("Connected.");
+ oled.print("Discovering ... ");
+ oled.display();
+
+ if ( bleancs.discover( conn_handle ) )
+ {
+ oled.println("OK");
+
+ // ANCS requires pairing to work
+ oled.print("Paring ... ");
+
+ oled.display();
+
+ if ( Bluefruit.requestPairing() )
+ {
+ oled.println("OK");
+
+ bleancs.enableNotification();
+ oled.println("Receiving ...");
+ }else
+ {
+ oled.println("Failed");
+ }
+ }else
+ {
+ oled.println("Failed");
+ }
+
+ oled.display();
+}
+
+/**
+ * Notification callback
+ * @param notif Notification from iDevice
+ *
+ * Save/Modify notification into myNotifs struct to display later
+ */
+void ancs_notification_callback(AncsNotification_t* notif)
+{
+ if (notif->eventID == ANCS_EVT_NOTIFICATION_ADDED )
+ {
+ myNotifs[ notifCount ].ntf = *notif;
+
+ /*------------- Retrieve Title, Message, App Name -------------*/
+ MyNotif_t* myNtf = &myNotifs[notifCount];
+ uint32_t uid = myNtf->ntf.uid;
+
+ // iDevice often include Unicode "Bidirection Text Control" in the Title.
+ // Mostly are U+202D as beginning and U+202C as ending. Let's remove them
+ if ( bleancs.getTitle (uid, myNtf->title , BUFSIZE) )
+ {
+ char u202D[3] = { 0xE2, 0x80, 0xAD }; // U+202D in UTF-8
+ char u202C[3] = { 0xE2, 0x80, 0xAC }; // U+202C in UTF-8
+
+ int len = strlen(myNtf->title);
+
+ if ( 0 == memcmp(&myNtf->title[len-3], u202C, 3) )
+ {
+ len -= 3;
+ myNtf->title[len] = 0; // chop ending U+202C
+ }
+
+ if ( 0 == memcmp(myNtf->title, u202D, 3) )
+ {
+ memmove(myNtf->title, myNtf->title+3, len-2); // move null-terminator as well
+ }
+ }
+
+ bleancs.getMessage(uid, myNtf->message , BUFSIZE);
+ bleancs.getAppName(uid, myNtf->app_name, BUFSIZE);
+
+ displayIndex = notifCount++; // display new notification
+ }else if (notif->eventID == ANCS_EVT_NOTIFICATION_REMOVED )
+ {
+ for(int i=0; i<notifCount; i++)
+ {
+ if ( notif->uid == myNotifs[i].ntf.uid )
+ {
+ // remove by swapping with the last one
+ notifCount--;
+ myNotifs[i] = myNotifs[notifCount];
+
+ // Invalid removed data
+ memset(&myNotifs[notifCount], 0, sizeof(MyNotif_t));
+
+ if (activeIndex == notifCount)
+ {
+ // If remove the last notification, adjust display index
+ displayIndex = notifCount-1;
+ }else if (activeIndex == i)
+ {
+ // Re-draw if remove currently active one
+ displayIndex = activeIndex;
+ }
+
+ break;
+ }
+ }
+ }else
+ {
+ // Modification
+ for(int i=0; i<notifCount; i++)
+ {
+ if ( notif->uid == myNotifs[i].ntf.uid )
+ {
+ // Display modification
+ displayIndex = i;
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle connection where this event happens
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ // reset notification array
+ notifCount = 0;
+ activeIndex = 0;
+ displayIndex = -1;
+
+ memset(myNotifs, 0, sizeof(myNotifs));
+
+ oled.clearDisplay();
+ oled.setCursor(0, 0);
+ oled.println("Not connected");
+ oled.display();
+}
+
+/**
+ * Check if button A,B,C state are pressed, include some software
+ * debouncing.
+ *
+ * Note: Only set bit when Button is state change from
+ * idle -> pressed. Press and hold only report 1 time, release
+ * won't report as well
+ *
+ * @return Bitmask of pressed buttons e.g If BUTTON_A is pressed
+ * bit 31 will be set.
+ */
+uint32_t readPressedButtons(void)
+{
+ // must be exponent of 2
+ enum { MAX_CHECKS = 8, SAMPLE_TIME = 10 };
+
+ /* Array that maintains bounce status/, which is sampled
+ * 10 ms each. Debounced state is regconized if all the values
+ * of a button has the same value (bit set or clear)
+ */
+ static uint32_t lastReadTime = 0;
+ static uint32_t states[MAX_CHECKS] = { 0 };
+ static uint32_t index = 0;
+
+ // Last Debounced state, used to detect changed
+ static uint32_t lastDebounced = 0;
+
+ // Too soon, nothing to do
+ if (millis() - lastReadTime < SAMPLE_TIME ) return 0;
+
+ lastReadTime = millis();
+
+ // Take current read and masked with BUTTONs
+ // Note: Bitwise inverted since buttons are active (pressed) LOW
+ uint32_t debounced = ~(*portInputRegister( digitalPinToPort(0) ));
+ debounced &= (bit(BUTTON_A) | bit(BUTTON_B) | bit(BUTTON_C));
+
+ // Copy current state into array
+ states[ (index & (MAX_CHECKS-1)) ] = debounced;
+ index++;
+
+ // Bitwise And all the state in the array together to get the result
+ // This means pin must stay at least MAX_CHECKS time to be realized as changed
+ for(int i=0; i<MAX_CHECKS; i++)
+ {
+ debounced &= states[i];
+ }
+
+ // result is button changed and current debounced is set
+ // Mean button is pressed (idle previously)
+ uint32_t result = (debounced ^ lastDebounced) & debounced;
+
+ lastDebounced = debounced;
+
+ return result;
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/beacon/beacon.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/beacon/beacon.ino
new file mode 100755
index 0000000..5897eb8
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/beacon/beacon.ino
@@ -0,0 +1,93 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <bluefruit.h>
+
+// Beacon uses the Manufacturer Specific Data field in the advertising
+// packet, which means you must provide a valid Manufacturer ID. Update
+// the field below to an appropriate value. For a list of valid IDs see:
+// https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
+// 0x004C is Apple (for example)
+#define MANUFACTURER_ID 0x004C
+
+// AirLocate UUID: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
+uint8_t beaconUuid[16] =
+{
+ 0xE2, 0xC5, 0x6D, 0xB5, 0xDF, 0xFB, 0x48, 0xD2,
+ 0xB0, 0x60, 0xD0, 0xF5, 0xA7, 0x10, 0x96, 0xE0,
+};
+
+// A valid Beacon packet consists of the following information:
+// UUID, Major, Minor, RSSI @ 1M
+BLEBeacon beacon(beaconUuid, 0x0000, 0x0000, -54);
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Beacon Example");
+ Serial.println("--------------------------\n");
+
+ Bluefruit.begin();
+
+ // off Blue LED for lowest power consumption
+ Bluefruit.autoConnLed(false);
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(0);
+ Bluefruit.setName("Bluefruit52");
+
+ // Manufacturer ID is required for Manufacturer Specific Data
+ beacon.setManufacturer(MANUFACTURER_ID);
+
+ // Setup the advertising packet
+ startAdv();
+
+ Serial.println("Broadcasting beacon, open your beacon app to test");
+
+ // Suspend Loop() to save power, since we didn't have any code there
+ suspendLoop();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ // Set the beacon payload using the BLEBeacon class populated
+ // earlier in this example
+ Bluefruit.Advertising.setBeacon(beacon);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * Apple Beacon specs
+ * - Type: Non connectable, undirected
+ * - Fixed interval: 100 ms -> fast = slow = 100 ms
+ */
+ //Bluefruit.Advertising.setType(BLE_GAP_ADV_TYPE_ADV_NONCONN_IND);
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(160, 160); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // loop is already suspended, CPU will not run loop() at all
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/blemidi/blemidi.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/blemidi/blemidi.ino
new file mode 100755
index 0000000..9e09bb4
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/blemidi/blemidi.ino
@@ -0,0 +1,182 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* For BLE MIDI Setup
+ * https://learn.adafruit.com/wireless-untztrument-using-ble-midi/overview
+ */
+
+
+#include <bluefruit.h>
+#include <MIDI.h>
+
+BLEDis bledis;
+BLEMidi blemidi;
+
+// Create a new instance of the Arduino MIDI Library,
+// and attach BluefruitLE MIDI as the transport.
+MIDI_CREATE_BLE_INSTANCE(blemidi);
+
+// Variable that holds the current position in the sequence.
+int position = 0;
+
+// Store example melody as an array of note values
+byte note_sequence[] = {
+ 74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78,
+ 74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61,
+ 56,61,64,68,74,78,81,86,90,93,98,102
+};
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Adafruit Bluefruit52 MIDI over Bluetooth LE Example");
+
+ // Config the peripheral connection with maximum bandwidth
+ // more SRAM required by SoftDevice
+ // Note: All config***() function must be called before begin()
+ Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+ Bluefruit.setName("Bluefruit52 MIDI");
+ Bluefruit.setTxPower(4);
+
+ // Setup the on board blue LED to be enabled on CONNECT
+ Bluefruit.autoConnLed(true);
+
+ // Configure and Start Device Information Service
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather52");
+ bledis.begin();
+
+ // Initialize MIDI, and listen to all MIDI channels
+ // This will also call blemidi service's begin()
+ MIDI.begin(MIDI_CHANNEL_OMNI);
+
+ // Attach the handleNoteOn function to the MIDI Library. It will
+ // be called whenever the Bluefruit receives MIDI Note On messages.
+ MIDI.setHandleNoteOn(handleNoteOn);
+
+ // Do the same for MIDI Note Off messages.
+ MIDI.setHandleNoteOff(handleNoteOff);
+
+ // Set up and start advertising
+ startAdv();
+
+ // Start MIDI read loop
+ Scheduler.startLoop(midiRead);
+}
+
+void startAdv(void)
+{
+ // Set General Discoverable Mode flag
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+
+ // Advertise TX Power
+ Bluefruit.Advertising.addTxPower();
+
+ // Advertise BLE MIDI Service
+ Bluefruit.Advertising.addService(blemidi);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void handleNoteOn(byte channel, byte pitch, byte velocity)
+{
+ // Log when a note is pressed.
+ Serial.printf("Note on: channel = %d, pitch = %d, velocity - %d", channel, pitch, velocity);
+ Serial.println();
+}
+
+void handleNoteOff(byte channel, byte pitch, byte velocity)
+{
+ // Log when a note is released.
+ Serial.printf("Note off: channel = %d, pitch = %d, velocity - %d", channel, pitch, velocity);
+ Serial.println();
+}
+
+void loop()
+{
+ // Don't continue if we aren't connected.
+ if (! Bluefruit.connected()) {
+ return;
+ }
+
+ // Don't continue if the connected device isn't ready to receive messages.
+ if (! blemidi.notifyEnabled()) {
+ return;
+ }
+
+ // Setup variables for the current and previous
+ // positions in the note sequence.
+ int current = position;
+ int previous = position - 1;
+
+ // If we currently are at position 0, set the
+ // previous position to the last note in the sequence.
+ if (previous < 0) {
+ previous = sizeof(note_sequence) - 1;
+ }
+
+ // Send Note On for current position at full velocity (127) on channel 1.
+ MIDI.sendNoteOn(note_sequence[current], 127, 1);
+
+ // Send Note Off for previous note.
+ MIDI.sendNoteOff(note_sequence[previous], 0, 1);
+
+ // Increment position
+ position++;
+
+ // If we are at the end of the sequence, start over.
+ if (position >= sizeof(note_sequence)) {
+ position = 0;
+ }
+
+ delay(286);
+
+}
+
+void midiRead()
+{
+ // Don't continue if we aren't connected.
+ if (! Bluefruit.connected()) {
+ return;
+ }
+
+ // Don't continue if the connected device isn't ready to receive messages.
+ if (! blemidi.notifyEnabled()) {
+ return;
+ }
+
+ // read any new MIDI messages
+ MIDI.read();
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/bleuart/bleuart.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/bleuart/bleuart.ino
new file mode 100755
index 0000000..55d2b77
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/bleuart/bleuart.ino
@@ -0,0 +1,142 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <bluefruit.h>
+
+// BLE Service
+BLEDis bledis; // device information
+BLEUart bleuart; // uart over ble
+BLEBas blebas; // battery
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 BLEUART Example");
+ Serial.println("---------------------------\n");
+
+ // Setup the BLE LED to be enabled on CONNECT
+ // Note: This is actually the default behaviour, but provided
+ // here in case you want to control this LED manually via PIN 19
+ Bluefruit.autoConnLed(true);
+
+ // Config the peripheral connection with maximum bandwidth
+ // more SRAM required by SoftDevice
+ // Note: All config***() function must be called before begin()
+ Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+ //Bluefruit.setName(getMcuUniqueID()); // useful testing with multiple central connections
+ Bluefruit.setConnectCallback(connect_callback);
+ Bluefruit.setDisconnectCallback(disconnect_callback);
+
+ // Configure and Start Device Information Service
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather52");
+ bledis.begin();
+
+ // Configure and Start BLE Uart Service
+ bleuart.begin();
+
+ // Start BLE Battery Service
+ blebas.begin();
+ blebas.write(100);
+
+ // Set up and start advertising
+ startAdv();
+
+ Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
+ Serial.println("Once connected, enter character(s) that you wish to send");
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include bleuart 128-bit uuid
+ Bluefruit.Advertising.addService(bleuart);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // Forward data from HW Serial to BLEUART
+ while (Serial.available())
+ {
+ // Delay to wait for enough input, since we have a limited transmission buffer
+ delay(2);
+
+ uint8_t buf[64];
+ int count = Serial.readBytes(buf, sizeof(buf));
+ bleuart.write( buf, count );
+ }
+
+ // Forward from BLEUART to HW Serial
+ while ( bleuart.available() )
+ {
+ uint8_t ch;
+ ch = (uint8_t) bleuart.read();
+ Serial.write(ch);
+ }
+
+ // Request CPU to enter low-power mode until an event/interrupt occurs
+ waitForEvent();
+}
+
+// callback invoked when central connects
+void connect_callback(uint16_t conn_handle)
+{
+ char central_name[32] = { 0 };
+ Bluefruit.Gap.getPeerName(conn_handle, central_name, sizeof(central_name));
+
+ Serial.print("Connected to ");
+ Serial.println(central_name);
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle connection where this event happens
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println();
+ Serial.println("Disconnected");
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/blinky_ota/blinky_ota.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/blinky_ota/blinky_ota.ino
new file mode 100755
index 0000000..85cd5f0
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/blinky_ota/blinky_ota.ino
@@ -0,0 +1,63 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <bluefruit.h>
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Blinky Example");
+ Serial.println("--------------------------\n");
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // Toggle both LEDs every 1 second
+ digitalToggle(LED_RED);
+
+ delay(1000);
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/clearbonds/clearbonds.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/clearbonds/clearbonds.ino
new file mode 100755
index 0000000..d6770d4
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/clearbonds/clearbonds.ino
@@ -0,0 +1,54 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch remove the folder that contains the bonding information
+ * used by Bluefruit which is "/adafruit/bond"
+ */
+
+#include <bluefruit.h>
+#include <utility/bonding.h>
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Clear Bonds Example");
+ Serial.println("-------------------------------\n");
+
+ Bluefruit.begin();
+
+ Serial.println();
+ Serial.println("----- Before -----\n");
+ bond_print_list(BLE_GAP_ROLE_PERIPH);
+ bond_print_list(BLE_GAP_ROLE_CENTRAL);
+
+ Bluefruit.clearBonds();
+ Bluefruit.Central.clearBonds();
+
+ Serial.println();
+ Serial.println("----- After -----\n");
+
+ bond_print_list(BLE_GAP_ROLE_PERIPH);
+ bond_print_list(BLE_GAP_ROLE_CENTRAL);
+}
+
+void loop()
+{
+ // Toggle both LEDs every 1 second
+ digitalToggle(LED_RED);
+
+ delay(1000);
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/client_cts/client_cts.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/client_cts/client_cts.ino
new file mode 100755
index 0000000..ca145b1
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/client_cts/client_cts.ino
@@ -0,0 +1,176 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch demonstrates the client Current Time Service using the
+ * BLEClientCts API(). After uploading, go to iOS setting and connect
+ * to Bluefruit52, and then press PAIR.
+ *
+ * Note: Currently only iOS act as a CTS server, Android does not. The
+ * easiest way to test this sketch is using an iOS device.
+ *
+ * Current Time Service info:
+ * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.current_time.xml
+ * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.current_time.xml
+ * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.local_time_information.xml
+ */
+
+#include <bluefruit.h>
+
+// BLE Client Current Time Service
+BLEClientCts bleCTime;
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 BLE Client Current Time Example");
+ Serial.println("-------------------------------------------\n");
+
+ Serial.println("Go to iOS's Bluetooth settings and connect to Bluefruit52");
+ Serial.println("It may appear up as 'Accessory' depending on your iOS version.");
+
+ // Config the peripheral connection with maximum bandwidth
+ // more SRAM required by SoftDevice
+ // Note: All config***() function must be called before begin()
+ Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+ Bluefruit.setConnectCallback(connect_callback);
+ Bluefruit.setDisconnectCallback(disconnect_callback);
+
+ // Configure CTS client
+ bleCTime.begin();
+
+ // Callback invoked when iOS device time changes
+ // To test this go to Setting -> Date & Time -> Toggle Time Zone "Set Automatically"
+ // Or change the time manually etc ...
+ bleCTime.setAdjustCallback(cts_adjust_callback);
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+ Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_GENERIC_CLOCK);
+
+ // Include CTS client UUID
+ Bluefruit.Advertising.addService(bleCTime);
+
+ // Includes name
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // If service is not yet discovered
+ if ( !bleCTime.discovered() && !Bluefruit.connPaired() ) return;
+
+ // Get Time from iOS once per second
+ // Note it is not advised to update this quickly
+ // Application should use local clock and update time after
+ // a long period (e.g an hour or day)
+ bleCTime.getCurrentTime();
+
+ printTime();
+
+ delay(1000);
+}
+
+void connect_callback(uint16_t conn_handle)
+{
+ Serial.println("Connected");
+
+ Serial.print("Discovering CTS ... ");
+ if ( bleCTime.discover(conn_handle) )
+ {
+ Serial.println("Discovered");
+
+ // iOS requires pairing to work, it makes sense to request security here as well
+ Serial.print("Attempting to PAIR with the iOS device, please press PAIR on your phone ... ");
+ if ( Bluefruit.requestPairing() )
+ {
+ Serial.println("Done");
+ Serial.println("Enabling Time Adjust Notify");
+ bleCTime.enableAdjust();
+
+ Serial.print("Get Current Time chars value");
+ bleCTime.getCurrentTime();
+
+ Serial.print("Get Local Time Info chars value");
+ bleCTime.getLocalTimeInfo();
+
+ Serial.println();
+ }
+
+ Serial.println();
+ }
+}
+
+void cts_adjust_callback(uint8_t reason)
+{
+ const char * reason_str[] = { "Manual", "External Reference", "Change of Time Zone", "Change of DST" };
+
+ Serial.println("iOS Device time changed due to ");
+ Serial.println( reason_str[reason] );
+}
+
+void printTime(void)
+{
+ const char * day_of_week_str[] = { "n/a", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+
+ Serial.printf("%04d-%02d-%02d ", bleCTime.Time.year, bleCTime.Time.month, bleCTime.Time.day);
+ Serial.printf("%02d:%02d:%02d ", bleCTime.Time.hour, bleCTime.Time.minute, bleCTime.Time.second);
+ Serial.print(day_of_week_str[bleCTime.Time.weekday]);
+
+ int utc_offset = bleCTime.LocalInfo.timezone*15; // in 15 minutes unit
+ Serial.printf(" (UTC %+d:%02d, ", utc_offset/60, utc_offset%60);
+ Serial.printf("DST %+.1f)", ((float) bleCTime.LocalInfo.dst_offset*15)/60 );
+ Serial.println();
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle connection where this event happens
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) reason;
+
+ Serial.println();
+ Serial.println("Disconnected");
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/client_cts_oled/client_cts_oled.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/client_cts_oled/client_cts_oled.ino
new file mode 100755
index 0000000..f9a220c
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/client_cts_oled/client_cts_oled.ino
@@ -0,0 +1,193 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch demonstrates the client Current Time Service using the
+ * BLEClientCts API(). After uploading, go to iOS setting and connect
+ * to Bluefruit52, and then press PAIR.
+ *
+ * Note: Currently only iOS act as a CTS server, Android does not. The
+ * easiest way to test this sketch is using an iOS device.
+ *
+ * This sketch is similar to client_cts but also uses a Feather OLED Wing
+ * to display time https://www.adafruit.com/product/2900
+ *
+ * Current Time Service info:
+ * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.current_time.xml
+ * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.current_time.xml
+ * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.local_time_information.xml
+ */
+
+#include <bluefruit.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
+
+#define OLED_RESET 4
+Adafruit_SSD1306 oled(OLED_RESET);
+
+// BLE Client Current Time Service
+BLEClientCts bleCTime;
+
+void setup()
+{
+ // init with the I2C addr 0x3C (for the 128x32) and show splashscreen
+ oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
+ oled.display();
+
+ oled.setTextSize(1);// max is 4 line, 21 chars each
+ oled.setTextColor(WHITE);
+
+ // Config the peripheral connection with maximum bandwidth
+ // more SRAM required by SoftDevice
+ // Note: All config***() function must be called before begin()
+ Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+ Bluefruit.setConnectCallback(connect_callback);
+ Bluefruit.setDisconnectCallback(disconnect_callback);
+
+ // Configure CTS client
+ bleCTime.begin();
+
+ // Set up and start advertising
+ startAdv();
+
+ // splash screen effect
+ delay(100);
+
+ oled.clearDisplay();
+ oled.setCursor(0, 0);
+ oled.println("Waiting to connect");
+ oled.display();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+ Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_GENERIC_CLOCK);
+
+ // Include CTS client UUID
+ Bluefruit.Advertising.addService(bleCTime);
+
+ // Includes name
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // If service is not yet discovered
+ if ( !bleCTime.discovered() && !Bluefruit.connPaired() ) return;
+
+ // Get Time from iOS once per second
+ // Note it is not advised to update this quickly
+ // Application should use local clock and update time after
+ // a long period (e.g an hour or day)
+ bleCTime.getCurrentTime();
+ bleCTime.getLocalTimeInfo();
+
+ printTime();
+
+ delay(1000);
+}
+
+void connect_callback(uint16_t conn_handle)
+{
+ oled.clearDisplay();
+ oled.setCursor(0, 0);
+ oled.println("Connected.");
+ oled.print("Discovering ... ");
+ oled.display();
+
+ if ( bleCTime.discover(conn_handle) )
+ {
+ oled.println("OK");
+
+ // ANCS requires pairing to work
+ oled.print("Paring ... ");
+
+ oled.display();
+
+ if ( Bluefruit.requestPairing() )
+ {
+ oled.println("OK");
+
+ bleCTime.enableAdjust();
+
+ oled.println("Receiving Time...");
+ bleCTime.getCurrentTime();
+ bleCTime.getLocalTimeInfo();
+ }
+ }
+
+ oled.display();
+}
+
+void printTime(void)
+{
+ const char * day_of_week_str[] = { "n/a", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+ const char * month_str[] = { "na", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+ oled.clearDisplay();
+ oled.setCursor(0, 0);
+
+ oled.print(day_of_week_str[bleCTime.Time.weekday]);
+ oled.printf(" %s %02d %04d\n", month_str[bleCTime.Time.month], bleCTime.Time.day, bleCTime.Time.year);
+
+
+ oled.setTextSize(2);
+ oled.printf(" %02d:%02d:%02d\n", bleCTime.Time.hour, bleCTime.Time.minute, bleCTime.Time.second);
+
+ int utc_offset = bleCTime.LocalInfo.timezone*15; // in 15 minutes unit
+
+ oled.setTextSize(1);
+ oled.printf("UTC %+d:%02d, ", utc_offset/60, utc_offset%60);
+ oled.printf("DST %+.1f", ((float) bleCTime.LocalInfo.dst_offset*15)/60 );
+ oled.println();
+
+ oled.display();
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle connection where this event happens
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) reason;
+
+ oled.clearDisplay();
+ oled.setCursor(0, 0);
+ oled.println("Waiting to connect");
+ oled.display();
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/controller/controller.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/controller/controller.ino
new file mode 100755
index 0000000..5db6696
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/controller/controller.ino
@@ -0,0 +1,182 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <bluefruit.h>
+
+BLEUart bleuart;
+
+// Function prototypes for packetparser.cpp
+uint8_t readPacket (BLEUart *ble_uart, uint16_t timeout);
+float parsefloat (uint8_t *buffer);
+void printHex (const uint8_t * data, const uint32_t numBytes);
+
+// Packet buffer
+extern uint8_t packetbuffer[];
+
+void setup(void)
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println(F("Adafruit Bluefruit52 Controller App Example"));
+ Serial.println(F("-------------------------------------------"));
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Configure and start the BLE Uart service
+ bleuart.begin();
+
+ // Set up and start advertising
+ startAdv();
+
+ Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode"));
+ Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!"));
+ Serial.println();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include the BLE UART (AKA 'NUS') 128-bit UUID
+ Bluefruit.Advertising.addService(bleuart);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+/**************************************************************************/
+/*!
+ @brief Constantly poll for new command or response data
+*/
+/**************************************************************************/
+void loop(void)
+{
+ // Wait for new data to arrive
+ uint8_t len = readPacket(&bleuart, 500);
+ if (len == 0) return;
+
+ // Got a packet!
+ // printHex(packetbuffer, len);
+
+ // Color
+ if (packetbuffer[1] == 'C') {
+ uint8_t red = packetbuffer[2];
+ uint8_t green = packetbuffer[3];
+ uint8_t blue = packetbuffer[4];
+ Serial.print ("RGB #");
+ if (red < 0x10) Serial.print("0");
+ Serial.print(red, HEX);
+ if (green < 0x10) Serial.print("0");
+ Serial.print(green, HEX);
+ if (blue < 0x10) Serial.print("0");
+ Serial.println(blue, HEX);
+ }
+
+ // Buttons
+ if (packetbuffer[1] == 'B') {
+ uint8_t buttnum = packetbuffer[2] - '0';
+ boolean pressed = packetbuffer[3] - '0';
+ Serial.print ("Button "); Serial.print(buttnum);
+ if (pressed) {
+ Serial.println(" pressed");
+ } else {
+ Serial.println(" released");
+ }
+ }
+
+ // GPS Location
+ if (packetbuffer[1] == 'L') {
+ float lat, lon, alt;
+ lat = parsefloat(packetbuffer+2);
+ lon = parsefloat(packetbuffer+6);
+ alt = parsefloat(packetbuffer+10);
+ Serial.print("GPS Location\t");
+ Serial.print("Lat: "); Serial.print(lat, 4); // 4 digits of precision!
+ Serial.print('\t');
+ Serial.print("Lon: "); Serial.print(lon, 4); // 4 digits of precision!
+ Serial.print('\t');
+ Serial.print(alt, 4); Serial.println(" meters");
+ }
+
+ // Accelerometer
+ if (packetbuffer[1] == 'A') {
+ float x, y, z;
+ x = parsefloat(packetbuffer+2);
+ y = parsefloat(packetbuffer+6);
+ z = parsefloat(packetbuffer+10);
+ Serial.print("Accel\t");
+ Serial.print(x); Serial.print('\t');
+ Serial.print(y); Serial.print('\t');
+ Serial.print(z); Serial.println();
+ }
+
+ // Magnetometer
+ if (packetbuffer[1] == 'M') {
+ float x, y, z;
+ x = parsefloat(packetbuffer+2);
+ y = parsefloat(packetbuffer+6);
+ z = parsefloat(packetbuffer+10);
+ Serial.print("Mag\t");
+ Serial.print(x); Serial.print('\t');
+ Serial.print(y); Serial.print('\t');
+ Serial.print(z); Serial.println();
+ }
+
+ // Gyroscope
+ if (packetbuffer[1] == 'G') {
+ float x, y, z;
+ x = parsefloat(packetbuffer+2);
+ y = parsefloat(packetbuffer+6);
+ z = parsefloat(packetbuffer+10);
+ Serial.print("Gyro\t");
+ Serial.print(x); Serial.print('\t');
+ Serial.print(y); Serial.print('\t');
+ Serial.print(z); Serial.println();
+ }
+
+ // Quaternions
+ if (packetbuffer[1] == 'Q') {
+ float x, y, z, w;
+ x = parsefloat(packetbuffer+2);
+ y = parsefloat(packetbuffer+6);
+ z = parsefloat(packetbuffer+10);
+ w = parsefloat(packetbuffer+14);
+ Serial.print("Quat\t");
+ Serial.print(x); Serial.print('\t');
+ Serial.print(y); Serial.print('\t');
+ Serial.print(z); Serial.print('\t');
+ Serial.print(w); Serial.println();
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/controller/packetParser.cpp b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/controller/packetParser.cpp
new file mode 100755
index 0000000..8f0194f
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/controller/packetParser.cpp
@@ -0,0 +1,134 @@
+#include <string.h>
+#include <Arduino.h>
+#include <bluefruit.h>
+
+
+#define PACKET_ACC_LEN (15)
+#define PACKET_GYRO_LEN (15)
+#define PACKET_MAG_LEN (15)
+#define PACKET_QUAT_LEN (19)
+#define PACKET_BUTTON_LEN (5)
+#define PACKET_COLOR_LEN (6)
+#define PACKET_LOCATION_LEN (15)
+
+// READ_BUFSIZE Size of the read buffer for incoming packets
+#define READ_BUFSIZE (20)
+
+
+/* Buffer to hold incoming characters */
+uint8_t packetbuffer[READ_BUFSIZE+1];
+
+/**************************************************************************/
+/*!
+ @brief Casts the four bytes at the specified address to a float
+*/
+/**************************************************************************/
+float parsefloat(uint8_t *buffer)
+{
+ float f;
+ memcpy(&f, buffer, 4);
+ return f;
+}
+
+/**************************************************************************/
+/*!
+ @brief Prints a hexadecimal value in plain characters
+ @param data Pointer to the byte data
+ @param numBytes Data length in bytes
+*/
+/**************************************************************************/
+void printHex(const uint8_t * data, const uint32_t numBytes)
+{
+ uint32_t szPos;
+ for (szPos=0; szPos < numBytes; szPos++)
+ {
+ Serial.print(F("0x"));
+ // Append leading 0 for small values
+ if (data[szPos] <= 0xF)
+ {
+ Serial.print(F("0"));
+ Serial.print(data[szPos] & 0xf, HEX);
+ }
+ else
+ {
+ Serial.print(data[szPos] & 0xff, HEX);
+ }
+ // Add a trailing space if appropriate
+ if ((numBytes > 1) && (szPos != numBytes - 1))
+ {
+ Serial.print(F(" "));
+ }
+ }
+ Serial.println();
+}
+
+/**************************************************************************/
+/*!
+ @brief Waits for incoming data and parses it
+*/
+/**************************************************************************/
+uint8_t readPacket(BLEUart *ble_uart, uint16_t timeout)
+{
+ uint16_t origtimeout = timeout, replyidx = 0;
+
+ memset(packetbuffer, 0, READ_BUFSIZE);
+
+ while (timeout--) {
+ if (replyidx >= 20) break;
+ if ((packetbuffer[1] == 'A') && (replyidx == PACKET_ACC_LEN))
+ break;
+ if ((packetbuffer[1] == 'G') && (replyidx == PACKET_GYRO_LEN))
+ break;
+ if ((packetbuffer[1] == 'M') && (replyidx == PACKET_MAG_LEN))
+ break;
+ if ((packetbuffer[1] == 'Q') && (replyidx == PACKET_QUAT_LEN))
+ break;
+ if ((packetbuffer[1] == 'B') && (replyidx == PACKET_BUTTON_LEN))
+ break;
+ if ((packetbuffer[1] == 'C') && (replyidx == PACKET_COLOR_LEN))
+ break;
+ if ((packetbuffer[1] == 'L') && (replyidx == PACKET_LOCATION_LEN))
+ break;
+
+ while (ble_uart->available()) {
+ char c = ble_uart->read();
+ if (c == '!') {
+ replyidx = 0;
+ }
+ packetbuffer[replyidx] = c;
+ replyidx++;
+ timeout = origtimeout;
+ }
+
+ if (timeout == 0) break;
+ delay(1);
+ }
+
+ packetbuffer[replyidx] = 0; // null term
+
+ if (!replyidx) // no data or timeout
+ return 0;
+ if (packetbuffer[0] != '!') // doesn't start with '!' packet beginning
+ return 0;
+
+ // check checksum!
+ uint8_t xsum = 0;
+ uint8_t checksum = packetbuffer[replyidx-1];
+
+ for (uint8_t i=0; i<replyidx-1; i++) {
+ xsum += packetbuffer[i];
+ }
+ xsum = ~xsum;
+
+ // Throw an error message if the checksum's don't match
+ if (xsum != checksum)
+ {
+ Serial.print("Checksum mismatch in packet : ");
+ printHex(packetbuffer, replyidx+1);
+ return 0;
+ }
+
+ // checksum passed!
+ return replyidx;
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_hrm/custom_hrm.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_hrm/custom_hrm.ino
new file mode 100755
index 0000000..ea7f63d
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_hrm/custom_hrm.ino
@@ -0,0 +1,224 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <bluefruit.h>
+
+/* HRM Service Definitions
+ * Heart Rate Monitor Service: 0x180D
+ * Heart Rate Measurement Char: 0x2A37
+ * Body Sensor Location Char: 0x2A38
+ */
+BLEService hrms = BLEService(UUID16_SVC_HEART_RATE);
+BLECharacteristic hrmc = BLECharacteristic(UUID16_CHR_HEART_RATE_MEASUREMENT);
+BLECharacteristic bslc = BLECharacteristic(UUID16_CHR_BODY_SENSOR_LOCATION);
+
+BLEDis bledis; // DIS (Device Information Service) helper class instance
+BLEBas blebas; // BAS (Battery Service) helper class instance
+
+uint8_t bps = 0;
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 HRM Example");
+ Serial.println("-----------------------\n");
+
+ // Initialise the Bluefruit module
+ Serial.println("Initialise the Bluefruit nRF52 module");
+ Bluefruit.begin();
+
+ // Set the advertised device name (keep it short!)
+ Serial.println("Setting Device Name to 'Feather52 HRM'");
+ Bluefruit.setName("Bluefruit52 HRM");
+
+ // Set the connect/disconnect callback handlers
+ Bluefruit.setConnectCallback(connect_callback);
+ Bluefruit.setDisconnectCallback(disconnect_callback);
+
+ // Configure and Start the Device Information Service
+ Serial.println("Configuring the Device Information Service");
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather52");
+ bledis.begin();
+
+ // Start the BLE Battery Service and set it to 100%
+ Serial.println("Configuring the Battery Service");
+ blebas.begin();
+ blebas.write(100);
+
+ // Setup the Heart Rate Monitor service using
+ // BLEService and BLECharacteristic classes
+ Serial.println("Configuring the Heart Rate Monitor Service");
+ setupHRM();
+
+ // Setup the advertising packet(s)
+ Serial.println("Setting up the advertising payload(s)");
+ startAdv();
+
+ Serial.println("Ready Player One!!!");
+ Serial.println("\nAdvertising");
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include HRM Service UUID
+ Bluefruit.Advertising.addService(hrms);
+
+ // Include Name
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void setupHRM(void)
+{
+ // Configure the Heart Rate Monitor service
+ // See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.heart_rate.xml
+ // Supported Characteristics:
+ // Name UUID Requirement Properties
+ // ---------------------------- ------ ----------- ----------
+ // Heart Rate Measurement 0x2A37 Mandatory Notify
+ // Body Sensor Location 0x2A38 Optional Read
+ // Heart Rate Control Point 0x2A39 Conditional Write <-- Not used here
+ hrms.begin();
+
+ // Note: You must call .begin() on the BLEService before calling .begin() on
+ // any characteristic(s) within that service definition.. Calling .begin() on
+ // a BLECharacteristic will cause it to be added to the last BLEService that
+ // was 'begin()'ed!
+
+ // Configure the Heart Rate Measurement characteristic
+ // See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml
+ // Properties = Notify
+ // Min Len = 1
+ // Max Len = 8
+ // B0 = UINT8 - Flag (MANDATORY)
+ // b5:7 = Reserved
+ // b4 = RR-Internal (0 = Not present, 1 = Present)
+ // b3 = Energy expended status (0 = Not present, 1 = Present)
+ // b1:2 = Sensor contact status (0+1 = Not supported, 2 = Supported but contact not detected, 3 = Supported and detected)
+ // b0 = Value format (0 = UINT8, 1 = UINT16)
+ // B1 = UINT8 - 8-bit heart rate measurement value in BPM
+ // B2:3 = UINT16 - 16-bit heart rate measurement value in BPM
+ // B4:5 = UINT16 - Energy expended in joules
+ // B6:7 = UINT16 - RR Internal (1/1024 second resolution)
+ hrmc.setProperties(CHR_PROPS_NOTIFY);
+ hrmc.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
+ hrmc.setFixedLen(2);
+ hrmc.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates
+ hrmc.begin();
+ uint8_t hrmdata[2] = { 0b00000110, 0x40 }; // Set the characteristic to use 8-bit values, with the sensor connected and detected
+ hrmc.notify(hrmdata, 2); // Use .notify instead of .write!
+
+ // Configure the Body Sensor Location characteristic
+ // See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml
+ // Properties = Read
+ // Min Len = 1
+ // Max Len = 1
+ // B0 = UINT8 - Body Sensor Location
+ // 0 = Other
+ // 1 = Chest
+ // 2 = Wrist
+ // 3 = Finger
+ // 4 = Hand
+ // 5 = Ear Lobe
+ // 6 = Foot
+ // 7:255 = Reserved
+ bslc.setProperties(CHR_PROPS_READ);
+ bslc.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
+ bslc.setFixedLen(1);
+ bslc.begin();
+ bslc.write8(2); // Set the characteristic to 'Wrist' (2)
+}
+
+void connect_callback(uint16_t conn_handle)
+{
+ char central_name[32] = { 0 };
+ Bluefruit.Gap.getPeerName(conn_handle, central_name, sizeof(central_name));
+
+ Serial.print("Connected to ");
+ Serial.println(central_name);
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle connection where this event happens
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println("Disconnected");
+ Serial.println("Advertising!");
+}
+
+void cccd_callback(BLECharacteristic& chr, uint16_t cccd_value)
+{
+ // Display the raw request packet
+ Serial.print("CCCD Updated: ");
+ //Serial.printBuffer(request->data, request->len);
+ Serial.print(cccd_value);
+ Serial.println("");
+
+ // Check the characteristic this CCCD update is associated with in case
+ // this handler is used for multiple CCCD records.
+ if (chr.uuid == hrmc.uuid) {
+ if (chr.notifyEnabled()) {
+ Serial.println("Heart Rate Measurement 'Notify' enabled");
+ } else {
+ Serial.println("Heart Rate Measurement 'Notify' disabled");
+ }
+ }
+}
+
+void loop()
+{
+ digitalToggle(LED_RED);
+
+ if ( Bluefruit.connected() ) {
+ uint8_t hrmdata[2] = { 0b00000110, bps++ }; // Sensor connected, increment BPS value
+
+ // Note: We use .notify instead of .write!
+ // If it is connected but CCCD is not enabled
+ // The characteristic's value is still updated although notification is not sent
+ if ( hrmc.notify(hrmdata, sizeof(hrmdata)) ){
+ Serial.print("Heart Rate Measurement updated to: "); Serial.println(bps);
+ }else{
+ Serial.println("ERROR: Notify not set in the CCCD or not connected!");
+ }
+ }
+
+ // Only send update once per second
+ delay(1000);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.cpp b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.cpp
new file mode 100755
index 0000000..6b372bd
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.cpp
@@ -0,0 +1,106 @@
+/**************************************************************************/
+/*!
+ @file IEEE11073float.h
+*/
+/**************************************************************************/
+
+/**
+ * \file bytelib.c
+ * \brief Byte manipulation module implementation.
+ * Copyright (C) 2010 Signove Tecnologia Corporation.
+ * All rights reserved.
+ * Contact: Signove Tecnologia Corporation (contact@signove.com)
+ *
+ * $LICENSE_TEXT:BEGIN$
+ * 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 and appearing
+ * in the file LICENSE included in the packaging of this file; 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * $LICENSE_TEXT:END$
+ *
+ * \author Walter Guerra, Mateus Lima
+ * \date Jun 14, 2010
+ */
+
+#include <Arduino.h>
+#include "IEEE11073float.h"
+
+uint32_t float2IEEE11073(double data, uint8_t output[4])
+{
+ uint32_t result = MDER_NaN;
+
+
+ if (isnan(data)) {
+ goto finally;
+ }/* else if (data > MDER_FLOAT_MAX) {
+ result = MDER_POSITIVE_INFINITY;
+ goto finally;
+ } else if (data < MDER_FLOAT_MIN) {
+ result = MDER_NEGATIVE_INFINITY;
+ goto finally;
+ } else if (data >= -MDER_FLOAT_EPSILON &&
+ data <= MDER_FLOAT_EPSILON) {
+ result = 0;
+ goto finally;
+ }*/
+
+ double sgn; sgn = data > 0 ? +1 : -1;
+ double mantissa; mantissa = fabs(data);
+ int32_t exponent; exponent = 0; // Note: 10**x exponent, not 2**x
+
+ // scale up if number is too big
+ while (mantissa > MDER_FLOAT_MANTISSA_MAX) {
+ mantissa /= 10.0;
+ ++exponent;
+ if (exponent > MDER_FLOAT_EXPONENT_MAX) {
+ // argh, should not happen
+ if (sgn > 0) {
+ result = MDER_POSITIVE_INFINITY;
+ } else {
+ result = MDER_NEGATIVE_INFINITY;
+ }
+ goto finally;
+ }
+ }
+
+ // scale down if number is too small
+ while (mantissa < 1) {
+ mantissa *= 10;
+ --exponent;
+ if (exponent < MDER_FLOAT_EXPONENT_MIN) {
+ // argh, should not happen
+ result = 0;
+ goto finally;
+ }
+ }
+
+ // scale down if number needs more precision
+ double smantissa; smantissa = round(mantissa * MDER_FLOAT_PRECISION);
+ double rmantissa; rmantissa = round(mantissa) * MDER_FLOAT_PRECISION;
+ double mdiff; mdiff = abs(smantissa - rmantissa);
+ while (mdiff > 0.5 && exponent > MDER_FLOAT_EXPONENT_MIN &&
+ (mantissa * 10) <= MDER_FLOAT_MANTISSA_MAX) {
+ mantissa *= 10;
+ --exponent;
+ smantissa = round(mantissa * MDER_FLOAT_PRECISION);
+ rmantissa = round(mantissa) * MDER_FLOAT_PRECISION;
+ mdiff = abs(smantissa - rmantissa);
+ }
+
+ uint32_t int_mantissa; int_mantissa = (int) round(sgn * mantissa);
+ result = (exponent << 24) | (int_mantissa & 0xFFFFFF);
+
+finally:
+ if ( output ) memcpy(output, &result, 4);
+ return result;
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.h b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.h
new file mode 100755
index 0000000..b5dec8f
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.h
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/*!
+ @file IEEE11073float.h
+*/
+/**************************************************************************/
+
+/**
+ * \file bytelib.c
+ * \brief Byte manipulation module implementation.
+ * Copyright (C) 2010 Signove Tecnologia Corporation.
+ * All rights reserved.
+ * Contact: Signove Tecnologia Corporation (contact@signove.com)
+ *
+ * $LICENSE_TEXT:BEGIN$
+ * 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 and appearing
+ * in the file LICENSE included in the packaging of this file; 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * $LICENSE_TEXT:END$
+ *
+ * \author Walter Guerra, Mateus Lima
+ * \date Jun 14, 2010
+ */
+
+#ifndef _IEEE11073FLOAT_H_
+#define _IEEE11073FLOAT_H_
+
+#include <stdint.h>
+
+typedef enum {
+ MDER_POSITIVE_INFINITY = 0x007FFFFE,
+ MDER_NaN = 0x007FFFFF,
+ MDER_NRes = 0x00800000,
+ MDER_RESERVED_VALUE = 0x00800001,
+ MDER_NEGATIVE_INFINITY = 0x00800002
+} ReservedFloatValues;
+static const int32_t FIRST_RESERVED_VALUE = MDER_POSITIVE_INFINITY;
+
+// (2 ** 23 - 3)
+#define MDER_FLOAT_MANTISSA_MAX 0x007FFFFD
+// 2 ** 7 - 1
+#define MDER_FLOAT_EXPONENT_MAX 127
+#define MDER_FLOAT_EXPONENT_MIN -128
+// (2 ** 23 - 3) * 10 ** 127
+#define MDER_FLOAT_MAX 8.388604999999999e+133
+// -(2 ** 23 - 3) * 10 ** 127
+#define MDER_FLOAT_MIN (-MDER_FLOAT_MAX)
+// 10 ** -128
+#define MDER_FLOAT_EPSILON 1e-128
+// 10 ** upper(23 * log(2) / log(10))
+// precision for a number 1.0000xxx
+#define MDER_FLOAT_PRECISION 10000000
+
+typedef enum {
+ MDER_S_POSITIVE_INFINITY = 0x07FE,
+ MDER_S_NaN = 0x07FF,
+ MDER_S_NRes = 0x0800,
+ MDER_S_RESERVED_VALUE = 0x0801,
+ MDER_S_NEGATIVE_INFINITY = 0x0802
+} ReservedSFloatValues;
+static const uint32_t FIRST_S_RESERVED_VALUE = MDER_S_POSITIVE_INFINITY;
+
+// (2 ** 11 - 3)
+#define MDER_SFLOAT_MANTISSA_MAX 0x07FD
+// 2 ** 3 - 1
+#define MDER_SFLOAT_EXPONENT_MAX 7
+#define MDER_SFLOAT_EXPONENT_MIN -8
+// (2 ** 11 - 3) * 10 ** 7
+#define MDER_SFLOAT_MAX 20450000000.0
+// -(2 ** 11 - 3) * 10 ** 7
+#define MDER_SFLOAT_MIN (-MDER_SFLOAT_MAX)
+// 10 ** -8
+#define MDER_SFLOAT_EPSILON 1e-8
+// 10 ** upper(11 * log(2) / log(10))
+#define MDER_SFLOAT_PRECISION 10000
+
+uint32_t float2IEEE11073(double data, uint8_t output[4]);
+
+#endif /* _IEEE11073FLOAT_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/custom_htm.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/custom_htm.ino
new file mode 100755
index 0000000..ba360fc
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/custom_htm.ino
@@ -0,0 +1,219 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <bluefruit.h>
+#include "IEEE11073float.h"
+
+/* Health Thermometer Service Definitions
+ * Health Thermometer Service: 0x1809
+ * Temperature Measurement Char: 0x2A1C
+ */
+BLEService htms = BLEService(UUID16_SVC_HEALTH_THERMOMETER);
+BLECharacteristic htmc = BLECharacteristic(UUID16_CHR_TEMPERATURE_MEASUREMENT);
+
+BLEDis bledis; // DIS (Device Information Service) helper class instance
+
+double tempvalue = 0;
+
+// Advanced function prototypes
+void startAdv(void);
+void setupHTM(void);
+void connect_callback(uint16_t conn_handle);
+void disconnect_callback(uint16_t conn_handle, uint8_t reason);
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Heath Thermometer Example");
+ Serial.println("-------------------------------------\n");
+
+ // Initialise the Bluefruit module
+ Serial.println("Initialise the Bluefruit nRF52 module");
+ Bluefruit.begin();
+ Bluefruit.setName("Bluefruit52");
+
+ // Set the connect/disconnect callback handlers
+ Bluefruit.setConnectCallback(connect_callback);
+ Bluefruit.setDisconnectCallback(disconnect_callback);
+
+ // Configure and Start the Device Information Service
+ Serial.println("Configuring the Device Information Service");
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather52");
+ bledis.begin();;
+
+ // Setup the Heath Thermometer service using
+ // BLEService and BLECharacteristic classes
+ Serial.println("Configuring the Heath Thermometer Service");
+ setupHTM();
+
+ // Setup the advertising packet(s)
+ Serial.println("Setting up the advertising payload(s)");
+ startAdv();
+
+ Serial.println("Ready Player One!!!");
+ Serial.println("\nAdvertising");
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include HTM Service UUID
+ Bluefruit.Advertising.addService(htms);
+
+ // Include Name
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void setupHTM(void)
+{
+ // Configure the Health Thermometer service
+ // See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.health_thermometer.xml
+ // Supported Characteristics:
+ // Name UUID Requirement Properties
+ // ---------------------------- ------ ----------- ----------
+ // Temperature Measurement 0x2A1C Mandatory Indicate
+ //
+ // Temperature Type 0x2A1D Optional Read <-- Not used here
+ // Intermediate Temperature 0x2A1E Optional Read, Notify <-- Not used here
+ // Measurement Interval 0x2A21 Optional Read, Write, Indicate <-- Not used here
+ htms.begin();
+
+ // Note: You must call .begin() on the BLEService before calling .begin() on
+ // any characteristic(s) within that service definition.. Calling .begin() on
+ // a BLECharacteristic will cause it to be added to the last BLEService that
+ // was 'begin()'ed!
+
+ // Configure the Temperature Measurement characteristic
+ // See:https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.temperature_measurement.xml
+ // Properties = Indicte
+ // Min Len = 6
+ // Max Len = 6
+ // B0 = UINT8 - Flag (MANDATORY)
+ // b3:7 = Reserved
+ // b2 = Temperature Type Flag (0 = Not present, 1 = Present)
+ // b1 = Timestamp Flag (0 = Not present, 1 = Present)
+ // b0 = Unit Flag (0 = Celsius, 1 = Fahrenheit)
+ // B4:1 = FLOAT - IEEE-11073 32-bit FLOAT measurement value
+ // B5 = Temperature Type
+ htmc.setProperties(CHR_PROPS_INDICATE);
+ htmc.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
+ htmc.setFixedLen(6);
+ htmc.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates
+ htmc.begin();
+ uint8_t htmdata[6] = { 0b00000101, 0, 0 ,0 ,0, 2 }; // Set the characteristic to use Fahrenheit, with type (body) but no timestamp field
+ htmc.write(htmdata, sizeof(htmdata)); // Use .write for init data
+
+ // Temperature Type Value
+ // See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.temperature_type.xml
+ // B0 = UINT8 - Temperature Type
+ // 0 = Reserved
+ // 1 = Armpit
+ // 2 = Body (general)
+ // 3 = Ear (usually ear lobe)
+ // 4 = Finger
+ // 5 = Gastro-intestinal Tract
+ // 6 = Mouth
+ // 7 = Rectum
+ // 8 = Toe
+ // 9 = Tympanum (ear drum)
+ // 10:255 = Reserved
+}
+
+void connect_callback(uint16_t conn_handle)
+{
+ char central_name[32] = { 0 };
+ Bluefruit.Gap.getPeerName(conn_handle, central_name, sizeof(central_name));
+
+ Serial.print("Connected to ");
+ Serial.println(central_name);
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle connection where this event happens
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println("Disconnected");
+ Serial.println("Advertising!");
+}
+
+void cccd_callback(BLECharacteristic& chr, uint16_t cccd_value)
+{
+ // Display the raw request packet
+ Serial.print("CCCD Updated: ");
+ //Serial.printBuffer(request->data, request->len);
+ Serial.print(cccd_value);
+ Serial.println("");
+
+ // Check the characteristic this CCCD update is associated with in case
+ // this handler is used for multiple CCCD records.
+ if (chr.uuid == htmc.uuid) {
+ if (chr.indicateEnabled()) {
+ Serial.println("Temperature Measurement 'Indicate' enabled");
+ } else {
+ Serial.println("Temperature Measurement 'Indicate' disabled");
+ }
+ }
+}
+
+void loop()
+{
+ digitalToggle(LED_RED);
+
+ if ( Bluefruit.connected() ) {
+ uint8_t htmdata[6] = { 0b00000101, 0,0,0,0, 2 }; // Fahrenheit unit, temperature type = body (2)
+
+ float2IEEE11073(tempvalue, &htmdata[1]);
+
+ // Note: We use .indicate instead of .write!
+ // If it is connected but CCCD is not enabled
+ // The characteristic's value is still updated although notification is not sent
+ if ( htmc.indicate(htmdata, sizeof(htmdata)) ){
+ Serial.print("Temperature Measurement updated to: "); Serial.println(tempvalue);
+ }else{
+ Serial.println("ERROR: Indicate not set in the CCCD or not connected!");
+ }
+
+ tempvalue += 0.5F;
+ }
+
+ // Only send update once per second
+ delay(1000);
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/eddystone_url/eddystone_url.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/eddystone_url/eddystone_url.ino
new file mode 100755
index 0000000..15b068f
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/eddystone_url/eddystone_url.ino
@@ -0,0 +1,73 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <bluefruit.h>
+
+#define URL "https://www.adafruit.com"
+
+// Create an EddyStone URL with rssi at 0m = -40 and URL as defined above
+EddyStoneUrl eddyUrl(-40, URL);
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 EddyStone URL Example");
+ Serial.println("---------------------------------\n");
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Setup the advertising packet
+ startAdv();
+
+ Serial.println("Broadcasting EddyStone URL, open Google Physical Web app to test");
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ // Set the beacon payload using the BLEBeacon class populated
+ // earlier in this example
+ Bluefruit.Advertising.setBeacon(eddyUrl);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * Apple Beacon specs
+ * - Type: Non connectable, undirected
+ * - Fixed interval: 100 ms -> fast = slow = 100 ms
+ */
+ //Bluefruit.Advertising.setType(BLE_GAP_ADV_TYPE_ADV_NONCONN_IND);
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(160, 160); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // Toggle both LEDs every second
+ digitalToggle(LED_RED);
+ delay(1000);
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_camerashutter/hid_camerashutter.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_camerashutter/hid_camerashutter.ino
new file mode 100755
index 0000000..1b056b4
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_camerashutter/hid_camerashutter.ino
@@ -0,0 +1,131 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/*
+ * This sketch uses the HID Consumer Key API to send the Volume Down
+ * key when PIN_SHUTTER is grounded. This will cause your mobile device
+ * to capture a photo when you are in the camera app
+ */
+#include <bluefruit.h>
+
+BLEDis bledis;
+BLEHidAdafruit blehid;
+
+#define PIN_SHUTTER A0
+
+void setup()
+{
+ pinMode(PIN_SHUTTER, INPUT_PULLUP);
+
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 HID Camera Shutter Example");
+ Serial.println("--------------------------------------\n");
+
+ Serial.println();
+ Serial.println("Go to your phone's Bluetooth settings to pair your device");
+ Serial.println("then open the camera application");
+
+ Serial.println();
+ Serial.printf("Set pin %d to GND to capture a photo\n", PIN_SHUTTER);
+ Serial.println();
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Configure and start DIS (Device Information Service)
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather 52");
+ bledis.begin();
+
+ /* Start BLE HID
+ * Note: Apple requires BLE devices to have a min connection interval >= 20m
+ * (The smaller the connection interval the faster we can send data).
+ * However, for HID and MIDI device Apple will accept a min connection
+ * interval as low as 11.25 ms. Therefore BLEHidAdafruit::begin() will try to
+ * set the min and max connection interval to 11.25 ms and 15 ms respectively
+ * for the best performance.
+ */
+ blehid.begin();
+
+ /* Set connection interval (min, max) to your perferred value.
+ * Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
+ * min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms
+ */
+ /* Bluefruit.setConnInterval(9, 12); */
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+ Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);
+
+ // Include BLE HID service
+ Bluefruit.Advertising.addService(blehid);
+
+ // There is enough room for the dev name in the advertising packet
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // Make sure you are connected and bonded/paired
+ if ( Bluefruit.connected() && Bluefruit.connPaired() )
+ {
+ // Check if pin GND'ed
+ if ( digitalRead(PIN_SHUTTER) == 0 )
+ {
+ // Turn on red LED when we start sending data
+ digitalWrite(LED_RED, 1);
+
+ // Send the 'volume down' key press
+ // Check BLEHidGeneric.h for a list of valid consumer usage codes
+ blehid.consumerKeyPress(HID_USAGE_CONSUMER_VOLUME_DECREMENT);
+
+ // Delay a bit between reports
+ delay(10);
+
+ // Send key release
+ blehid.consumerKeyRelease();
+
+ // Turn off the red LED
+ digitalWrite(LED_RED, 0);
+
+ // Delay to avoid constant capturing
+ delay(500);
+ }
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyboard/hid_keyboard.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyboard/hid_keyboard.ino
new file mode 100755
index 0000000..9b44693
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyboard/hid_keyboard.ino
@@ -0,0 +1,146 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <bluefruit.h>
+
+BLEDis bledis;
+BLEHidAdafruit blehid;
+
+bool hasKeyPressed = false;
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 HID Keyboard Example");
+ Serial.println("--------------------------------\n");
+
+ Serial.println();
+ Serial.println("Go to your phone's Bluetooth settings to pair your device");
+ Serial.println("then open an application that accepts keyboard input");
+
+ Serial.println();
+ Serial.println("Enter the character(s) to send:");
+ Serial.println();
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Configure and Start Device Information Service
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather 52");
+ bledis.begin();
+
+ /* Start BLE HID
+ * Note: Apple requires BLE device must have min connection interval >= 20m
+ * ( The smaller the connection interval the faster we could send data).
+ * However for HID and MIDI device, Apple could accept min connection interval
+ * up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
+ * connection interval to 11.25 ms and 15 ms respectively for best performance.
+ */
+ blehid.begin();
+
+ // Set callback for set LED from central
+ blehid.setKeyboardLedCallback(set_keyboard_led);
+
+ /* Set connection interval (min, max) to your perferred value.
+ * Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
+ * min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms
+ */
+ /* Bluefruit.setConnInterval(9, 12); */
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+ Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);
+
+ // Include BLE HID service
+ Bluefruit.Advertising.addService(blehid);
+
+ // There is enough room for the dev name in the advertising packet
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ // Only send KeyRelease if previously pressed to avoid sending
+ // multiple keyRelease reports (that consume memory and bandwidth)
+ if ( hasKeyPressed )
+ {
+ hasKeyPressed = false;
+ blehid.keyRelease();
+
+ // Delay a bit after a report
+ delay(5);
+ }
+
+ if (Serial.available())
+ {
+ char ch = (char) Serial.read();
+
+ // echo
+ Serial.write(ch);
+
+ blehid.keyPress(ch);
+ hasKeyPressed = true;
+
+ // Delay a bit after a report
+ delay(5);
+ }
+
+ // Request CPU to enter low-power mode until an event/interrupt occurs
+ waitForEvent();
+}
+
+/**
+ * Callback invoked when received Set LED from central.
+ * Must be set previously with setKeyboardLedCallback()
+ *
+ * The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
+ * Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
+ */
+void set_keyboard_led(uint8_t led_bitmap)
+{
+ // light up Red Led if any bits is set
+ if ( led_bitmap )
+ {
+ ledOn( LED_RED );
+ }
+ else
+ {
+ ledOff( LED_RED );
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyscan/hid_keyscan.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyscan/hid_keyscan.ino
new file mode 100755
index 0000000..719b876
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyscan/hid_keyscan.ino
@@ -0,0 +1,194 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* This sketch demonstate how to use BLE HID to scan an array of pin
+ * and send its keycode. It is essentially an implementation of hid keyboard,
+ * useful reference if you want to make an BLE keyboard.
+ */
+
+#include <bluefruit.h>
+
+BLEHidAdafruit blehid;
+
+// Array of pins and its keycode
+// For keycode definition see BLEHidGeneric.h
+uint8_t pins[] = { A0, A1, A2, A3, A4, A5 };
+uint8_t hidcode[] = { HID_KEY_A, HID_KEY_B, HID_KEY_C ,HID_KEY_D, HID_KEY_E, HID_KEY_F };
+
+uint8_t pincount = sizeof(pins)/sizeof(pins[0]);
+
+// Modifier keys, only take cares of Shift
+// ATL, CTRL, CMD keys are left for user excersie.
+uint8_t shiftPin = 11;
+
+bool keyPressedPreviously = false;
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 HID Keyscan Example");
+ Serial.println("-------------------------------\n");
+
+ Serial.println();
+ Serial.println("Go to your phone's Bluetooth settings to pair your device");
+ Serial.println("then open an application that accepts keyboard input");
+
+ Serial.println();
+ Serial.println("Wire configured Pin to GND to send key");
+ Serial.println("Wire Shift Keky to GND if you want to send it in upper case");
+ Serial.println();
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // set up pin as input
+ for (uint8_t i=0; i<pincount; i++)
+ {
+ pinMode(pins[i], INPUT_PULLUP);
+ }
+
+ // set up modifier key
+ pinMode(shiftPin, INPUT_PULLUP);
+
+ /* Start BLE HID
+ * Note: Apple requires BLE device must have min connection interval >= 20m
+ * ( The smaller the connection interval the faster we could send data).
+ * However for HID and MIDI device, Apple could accept min connection interval
+ * up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
+ * connection interval to 11.25 ms and 15 ms respectively for best performance.
+ */
+ blehid.begin();
+
+ // Set callback for set LED from central
+ blehid.setKeyboardLedCallback(set_keyboard_led);
+
+ /* Set connection interval (min, max) to your perferred value.
+ * Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
+ * min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms
+ */
+ /* Bluefruit.setConnInterval(9, 12); */
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+ Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);
+
+ // Include BLE HID service
+ Bluefruit.Advertising.addService(blehid);
+
+ // There is enough room for the dev name in the advertising packet
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ /*-------------- Scan Pin Array and send report ---------------------*/
+ bool anyKeyPressed = false;
+
+ uint8_t modifier = 0;
+ uint8_t count=0;
+ uint8_t keycode[6] = { 0 };
+
+ // scan modifier key (only SHIFT), user implement ATL, CTRL, CMD if needed
+ if ( 0 == digitalRead(shiftPin) )
+ {
+ modifier |= KEYBOARD_MODIFIER_LEFTSHIFT;
+ }
+
+ // scan normal key and send report
+ for(uint8_t i=0; i < pincount; i++)
+ {
+ if ( 0 == digitalRead(pins[i]) )
+ {
+ // if pin is active (low), add its hid code to key report
+ keycode[count++] = hidcode[i];
+
+ // 6 is max keycode per report
+ if ( count == 6)
+ {
+ blehid.keyboardReport(modifier, keycode);
+
+ // reset report
+ count = 0;
+ memset(keycode, 0, 6);
+ }
+
+ // used later
+ anyKeyPressed = true;
+ keyPressedPreviously = true;
+ }
+ }
+
+ // Send any remaining keys (not accumulated up to 6)
+ if ( count )
+ {
+ blehid.keyboardReport(modifier, keycode);
+ }
+
+ // Send All-zero report to indicate there is no keys pressed
+ // Most of the time, it is, though we don't need to send zero report
+ // every loop(), only a key is pressed in previous loop()
+ if ( !anyKeyPressed && keyPressedPreviously )
+ {
+ keyPressedPreviously = false;
+ blehid.keyRelease();
+ }
+
+ // Poll interval
+ delay(10);
+}
+
+/**
+ * Callback invoked when received Set LED from central.
+ * Must be set previously with setKeyboardLedCallback()
+ *
+ * The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
+ * Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
+ */
+void set_keyboard_led(uint8_t led_bitmap)
+{
+ // light up Red Led if any bits is set
+ if ( led_bitmap )
+ {
+ ledOn( LED_RED );
+ }
+ else
+ {
+ ledOff( LED_RED );
+ }
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_mouse/hid_mouse.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_mouse/hid_mouse.ino
new file mode 100755
index 0000000..68dbf48
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/hid_mouse/hid_mouse.ino
@@ -0,0 +1,146 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+#include <bluefruit.h>
+
+BLEDis bledis;
+BLEHidAdafruit blehid;
+
+#define MOVE_STEP 10
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 HID Mouse Example");
+ Serial.println("-----------------------------\n");
+ Serial.println("Go to your phone's Bluetooth settings to pair your device");
+ Serial.println("then open an application that accepts mouse input");
+ Serial.println();
+
+ Serial.println("Enter following characters");
+ Serial.println("- 'WASD' to move mouse (up, left, down, right)");
+ Serial.println("- 'LRMBF' to press mouse button(s) (left, right, middle, backward, forward)");
+ Serial.println("- 'X' to release mouse button(s)");
+
+ Bluefruit.begin();
+ // HID Device can have a min connection interval of 9*1.25 = 11.25 ms
+ Bluefruit.setConnInterval(9, 16); // min = 9*1.25=11.25 ms, max = 16*1.25=20ms
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Configure and Start Device Information Service
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather 52");
+ bledis.begin();
+
+ // BLE HID
+ blehid.begin();
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+ Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_MOUSE);
+
+ // Include BLE HID service
+ Bluefruit.Advertising.addService(blehid);
+
+ // There is enough room for 'Name' in the advertising packet
+ Bluefruit.Advertising.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void loop()
+{
+ if (Serial.available())
+ {
+ char ch = (char) Serial.read();
+
+ // convert to upper case
+ ch = (char) toupper(ch);
+
+ // echo
+ Serial.println(ch);
+
+ switch(ch)
+ {
+ // WASD to move the mouse
+ case 'W':
+ blehid.mouseMove(0, -MOVE_STEP);
+ break;
+
+ case 'A':
+ blehid.mouseMove(-MOVE_STEP, 0);
+ break;
+
+ case 'S':
+ blehid.mouseMove(0, MOVE_STEP);
+ break;
+
+ case 'D':
+ blehid.mouseMove(MOVE_STEP, 0);
+ break;
+
+ // LRMBF for mouse button(s)
+ case 'L':
+ blehid.mouseButtonPress(MOUSE_BUTTON_LEFT);
+ break;
+
+ case 'R':
+ blehid.mouseButtonPress(MOUSE_BUTTON_RIGHT);
+ break;
+
+ case 'M':
+ blehid.mouseButtonPress(MOUSE_BUTTON_MIDDLE);
+ break;
+
+ case 'B':
+ blehid.mouseButtonPress(MOUSE_BUTTON_BACKWARD);
+ break;
+
+ case 'F':
+ // This key is not always supported by every OS
+ blehid.mouseButtonPress(MOUSE_BUTTON_FORWARD);
+ break;
+
+ case 'X':
+ // X to release all buttons
+ blehid.mouseButtonRelease();
+ break;
+
+ default: break;
+ }
+ }
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/neomatrix/neomatrix.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/neomatrix/neomatrix.ino
new file mode 100755
index 0000000..6462a29
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/neomatrix/neomatrix.ino
@@ -0,0 +1,168 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+/* How to run this sketch
+ * - Connect the Neopixel FeatherWing and load this sketch to your Bluefruit52
+ * - Connect to the board using the Bluefruit Connect LE app
+ * - Send character(s) using BLEUART
+ * - Bluefruit will render the received character(s) on Neopixel FeatherWing
+ *
+ * Note: due to the font being larger than the 4x8 Neopixel Wing, you can
+ * only see part of the characters in some cases.
+ * Run the sketch with a larger Neopixel Matrix for a complete demo
+ */
+
+/* NOTE: This sketch required at least version 1.1.0 of Adafruit_Neopixel !!! */
+
+#include <Arduino.h>
+#include <Adafruit_NeoPixel.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_NeoMatrix.h>
+#include <bluefruit.h>
+
+#define PIN 30 /* Pin used to drive the NeoPixels */
+
+#define MATRIX_WIDTH 4
+#define MATRIX_HEIGHT 8
+#define MATRIX_LAYOUT (NEO_MATRIX_TOP + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE)
+
+// MATRIX DECLARATION:
+// Parameter 1 = width of NeoPixel matrix
+// Parameter 2 = height of matrix
+// Parameter 3 = pin number (most are valid)
+// Parameter 4 = matrix layout flags, add together as needed:
+// NEO_MATRIX_TOP, NEO_MATRIX_BOTTOM, NEO_MATRIX_LEFT, NEO_MATRIX_RIGHT:
+// Position of the FIRST LED in the matrix; pick two, e.g.
+// NEO_MATRIX_TOP + NEO_MATRIX_LEFT for the top-left corner.
+// NEO_MATRIX_ROWS, NEO_MATRIX_COLUMNS: LEDs are arranged in horizontal
+// rows or in vertical columns, respectively; pick one or the other.
+// NEO_MATRIX_PROGRESSIVE, NEO_MATRIX_ZIGZAG: all rows/columns proceed
+// in the same order, or alternate lines reverse direction; pick one.
+// See example below for these values in action.
+// Parameter 5 = pixel type flags, add together as needed:
+// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
+// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
+// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
+// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
+
+Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(MATRIX_WIDTH, MATRIX_HEIGHT, PIN,
+ MATRIX_LAYOUT,
+ NEO_GRB + NEO_KHZ800);
+
+// BLE Service
+BLEDis bledis;
+BLEUart bleuart;
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Adafruit Bluefruit NeoMatrix");
+ Serial.println("----------------------------");
+
+ Serial.println();
+ Serial.println("Please connect using Bluefruit Connect LE application");
+
+ // Config Neopixels Matrix
+ matrix.begin();
+ matrix.setTextWrap(false);
+ matrix.setBrightness(40);
+ matrix.setTextColor( matrix.Color(0, 0, 255) ); // Blue for Bluefruit
+
+ matrix.print('?'); // print out ?
+ matrix.show();
+
+ // Init Bluefruit
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+ Bluefruit.setConnectCallback(connect_callback);
+
+ // Configure and Start Device Information Service
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather52");
+ bledis.begin();
+
+ // Configure and start BLE UART service
+ bleuart.begin();
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include bleuart 128-bit uuid
+ Bluefruit.Advertising.addService(bleuart);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void connect_callback(uint16_t conn_handle)
+{
+ char central_name[32] = { 0 };
+ Bluefruit.Gap.getPeerName(conn_handle, central_name, sizeof(central_name));
+
+ Serial.print("Connected to ");
+ Serial.println(central_name);
+
+ Serial.println("Please select 'Uart' tab and send any characters");
+}
+
+
+void loop()
+{
+ // Echo received data
+ if ( Bluefruit.connected() && bleuart.notifyEnabled() )
+ {
+ if ( bleuart.available() )
+ {
+ char ch = (char) bleuart.read();
+
+ // skip newline
+ if ( ch != '\r' && ch != '\n' )
+ {
+ matrix.fillScreen(0);
+ matrix.setCursor(0, 0);
+ matrix.print(ch);
+
+ matrix.show();
+ delay(200);
+ }
+ }
+ }
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/neopixel/neopixel.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/neopixel/neopixel.ino
new file mode 100755
index 0000000..f016a29
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/neopixel/neopixel.ino
@@ -0,0 +1,350 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+// This sketch is intended to be used with the NeoPixel control
+// surface in Adafruit's Bluefruit LE Connect mobile application.
+//
+// - Compile and flash this sketch to the nRF52 Feather
+// - Open the Bluefruit LE Connect app
+// - Switch to the NeoPixel utility
+// - Click the 'connect' button to establish a connection and
+// send the meta-data about the pixel layout
+// - Use the NeoPixel utility to update the pixels on your device
+
+/* NOTE: This sketch required at least version 1.1.0 of Adafruit_Neopixel !!! */
+
+#include <Arduino.h>
+#include <Adafruit_NeoPixel.h>
+#include <bluefruit.h>
+
+#define NEOPIXEL_VERSION_STRING "Neopixel v2.0"
+#define PIN 30 /* Pin used to drive the NeoPixels */
+
+#define MAXCOMPONENTS 4
+uint8_t *pixelBuffer = NULL;
+uint8_t width = 0;
+uint8_t height = 0;
+uint8_t stride;
+uint8_t componentsValue;
+bool is400Hz;
+uint8_t components = 3; // only 3 and 4 are valid values
+
+Adafruit_NeoPixel neopixel = Adafruit_NeoPixel();
+
+// BLE Service
+BLEDis bledis;
+BLEUart bleuart;
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Adafruit Bluefruit Neopixel Test");
+ Serial.println("--------------------------------");
+
+ Serial.println();
+ Serial.println("Please connect using the Bluefruit Connect LE application");
+
+ // Config Neopixels
+ neopixel.begin();
+
+ // Init Bluefruit
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+ Bluefruit.setConnectCallback(connect_callback);
+
+ // Configure and Start Device Information Service
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather52");
+ bledis.begin();
+
+ // Configure and start BLE UART service
+ bleuart.begin();
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include bleuart 128-bit uuid
+ Bluefruit.Advertising.addService(bleuart);
+
+ // Secondary Scan Response packet (optional)
+ // Since there is no room for 'Name' in Advertising packet
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void connect_callback(uint16_t conn_handle)
+{
+ char central_name[32] = { 0 };
+ Bluefruit.Gap.getPeerName(conn_handle, central_name, sizeof(central_name));
+
+ Serial.print("Connected to ");
+ Serial.println(central_name);
+
+ Serial.println("Please select the 'Neopixels' tab, click 'Connect' and have fun");
+}
+
+void loop()
+{
+ // Echo received data
+ if ( Bluefruit.connected() && bleuart.notifyEnabled() )
+ {
+ int command = bleuart.read();
+
+ switch (command) {
+ case 'V': { // Get Version
+ commandVersion();
+ break;
+ }
+
+ case 'S': { // Setup dimensions, components, stride...
+ commandSetup();
+ break;
+ }
+
+ case 'C': { // Clear with color
+ commandClearColor();
+ break;
+ }
+
+ case 'B': { // Set Brightness
+ commandSetBrightness();
+ break;
+ }
+
+ case 'P': { // Set Pixel
+ commandSetPixel();
+ break;
+ }
+
+ case 'I': { // Receive new image
+ commandImage();
+ break;
+ }
+
+ }
+ }
+}
+
+void swapBuffers()
+{
+ uint8_t *base_addr = pixelBuffer;
+ int pixelIndex = 0;
+ for (int j = 0; j < height; j++)
+ {
+ for (int i = 0; i < width; i++) {
+ if (components == 3) {
+ neopixel.setPixelColor(pixelIndex, neopixel.Color(*base_addr, *(base_addr+1), *(base_addr+2)));
+ }
+ else {
+ neopixel.setPixelColor(pixelIndex, neopixel.Color(*base_addr, *(base_addr+1), *(base_addr+2), *(base_addr+3) ));
+ }
+ base_addr+=components;
+ pixelIndex++;
+ }
+ pixelIndex += stride - width; // Move pixelIndex to the next row (take into account the stride)
+ }
+ neopixel.show();
+
+}
+
+void commandVersion() {
+ Serial.println(F("Command: Version check"));
+ sendResponse(NEOPIXEL_VERSION_STRING);
+}
+
+void commandSetup() {
+ Serial.println(F("Command: Setup"));
+
+ width = bleuart.read();
+ height = bleuart.read();
+ stride = bleuart.read();
+ componentsValue = bleuart.read();
+ is400Hz = bleuart.read();
+
+ neoPixelType pixelType;
+ pixelType = componentsValue + (is400Hz ? NEO_KHZ400 : NEO_KHZ800);
+
+ components = (componentsValue == NEO_RGB || componentsValue == NEO_RBG || componentsValue == NEO_GRB || componentsValue == NEO_GBR || componentsValue == NEO_BRG || componentsValue == NEO_BGR) ? 3:4;
+
+ Serial.printf("\tsize: %dx%d\n", width, height);
+ Serial.printf("\tstride: %d\n", stride);
+ Serial.printf("\tpixelType %d\n", pixelType);
+ Serial.printf("\tcomponents: %d\n", components);
+
+ if (pixelBuffer != NULL) {
+ delete[] pixelBuffer;
+ }
+
+ uint32_t size = width*height;
+ pixelBuffer = new uint8_t[size*components];
+ neopixel.updateLength(size);
+ neopixel.updateType(pixelType);
+ neopixel.setPin(PIN);
+
+ // Done
+ sendResponse("OK");
+}
+
+void commandSetBrightness() {
+ Serial.println(F("Command: SetBrightness"));
+
+ // Read value
+ uint8_t brightness = bleuart.read();
+
+ // Set brightness
+ neopixel.setBrightness(brightness);
+
+ // Refresh pixels
+ swapBuffers();
+
+ // Done
+ sendResponse("OK");
+}
+
+void commandClearColor() {
+ Serial.println(F("Command: ClearColor"));
+
+ // Read color
+ uint8_t color[MAXCOMPONENTS];
+ for (int j = 0; j < components;) {
+ if (bleuart.available()) {
+ color[j] = bleuart.read();
+ j++;
+ }
+ }
+
+ // Set all leds to color
+ int size = width * height;
+ uint8_t *base_addr = pixelBuffer;
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < components; j++) {
+ *base_addr = color[j];
+ base_addr++;
+ }
+ }
+
+ // Swap buffers
+ Serial.println(F("ClearColor completed"));
+ swapBuffers();
+
+
+ if (components == 3) {
+ Serial.printf("\tclear (%d, %d, %d)\n", color[0], color[1], color[2] );
+ }
+ else {
+ Serial.printf("\tclear (%d, %d, %d, %d)\n", color[0], color[1], color[2], color[3] );
+ }
+
+ // Done
+ sendResponse("OK");
+}
+
+void commandSetPixel() {
+ Serial.println(F("Command: SetPixel"));
+
+ // Read position
+ uint8_t x = bleuart.read();
+ uint8_t y = bleuart.read();
+
+ // Read colors
+ uint32_t pixelOffset = y*width+x;
+ uint32_t pixelDataOffset = pixelOffset*components;
+ uint8_t *base_addr = pixelBuffer+pixelDataOffset;
+ for (int j = 0; j < components;) {
+ if (bleuart.available()) {
+ *base_addr = bleuart.read();
+ base_addr++;
+ j++;
+ }
+ }
+
+ // Set colors
+ uint32_t neopixelIndex = y*stride+x;
+ uint8_t *pixelBufferPointer = pixelBuffer + pixelDataOffset;
+ uint32_t color;
+ if (components == 3) {
+ color = neopixel.Color( *pixelBufferPointer, *(pixelBufferPointer+1), *(pixelBufferPointer+2) );
+ Serial.printf("\tcolor (%d, %d, %d)\n",*pixelBufferPointer, *(pixelBufferPointer+1), *(pixelBufferPointer+2) );
+ }
+ else {
+ color = neopixel.Color( *pixelBufferPointer, *(pixelBufferPointer+1), *(pixelBufferPointer+2), *(pixelBufferPointer+3) );
+ Serial.printf("\tcolor (%d, %d, %d, %d)\n", *pixelBufferPointer, *(pixelBufferPointer+1), *(pixelBufferPointer+2), *(pixelBufferPointer+3) );
+ }
+ neopixel.setPixelColor(neopixelIndex, color);
+ neopixel.show();
+
+ // Done
+ sendResponse("OK");
+}
+
+void commandImage() {
+ Serial.printf("Command: Image %dx%d, %d, %d\n", width, height, components, stride);
+
+ // Receive new pixel buffer
+ int size = width * height;
+ uint8_t *base_addr = pixelBuffer;
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < components;) {
+ if (bleuart.available()) {
+ *base_addr = bleuart.read();
+ base_addr++;
+ j++;
+ }
+ }
+
+/*
+ if (components == 3) {
+ uint32_t index = i*components;
+ Serial.printf("\tp%d (%d, %d, %d)\n", i, pixelBuffer[index], pixelBuffer[index+1], pixelBuffer[index+2] );
+ }
+ */
+ }
+
+ // Swap buffers
+ Serial.println(F("Image received"));
+ swapBuffers();
+
+ // Done
+ sendResponse("OK");
+}
+
+void sendResponse(char const *response) {
+ Serial.printf("Send Response: %s\n", response);
+ bleuart.write(response, strlen(response)*sizeof(char));
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/throughput/throughput.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/throughput/throughput.ino
new file mode 100755
index 0000000..8f88f2a
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/throughput/throughput.ino
@@ -0,0 +1,183 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <bluefruit.h>
+
+// String to send in the throughput test
+#define TEST_STRING "01234567899876543210"
+const int TEST_STRLEN = strlen(TEST_STRING);
+
+// Number of total data sent ( 1024 times the test string)
+#define TOTAL_BYTES (1024 * strlen(TEST_STRING))
+
+BLEDis bledis;
+BLEUart bleuart;
+
+/**************************************************************************/
+/*!
+ @brief Sets up the HW an the BLE module (this function is called
+ automatically on startup)
+*/
+/**************************************************************************/
+void setup(void)
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Throughput Example");
+ Serial.println("------------------------------\n");
+
+ // Setup the BLE LED to be enabled on CONNECT
+ // Note: This is actually the default behaviour, but provided
+ // here in case you want to control this manually via PIN 19
+ Bluefruit.autoConnLed(true);
+
+ Bluefruit.begin();
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+ Bluefruit.setConnectCallback(connect_callback);
+ Bluefruit.setDisconnectCallback(disconnect_callback);
+
+ // Configure and Start Device Information Service
+ bledis.setManufacturer("Adafruit Industries");
+ bledis.setModel("Bluefruit Feather52");
+ bledis.begin();
+
+ // Configure and Start BLE Uart Service
+ bleuart.begin();
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Include bleuart 128-bit uuid
+ Bluefruit.Advertising.addService(bleuart);
+
+ // There is no room for Name in Advertising packet
+ // Use Scan response for Name
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
+}
+
+void connect_callback(uint16_t conn_handle)
+{
+ (void) conn_handle;
+ Serial.println("Connected");
+}
+
+/**
+ * Callback invoked when a connection is dropped
+ * @param conn_handle connection where this event happens
+ * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
+ * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
+ */
+void disconnect_callback(uint16_t conn_handle, uint8_t reason)
+{
+ (void) conn_handle;
+ (void) reason;
+
+ Serial.println();
+ Serial.println("Disconnected");
+}
+
+/**************************************************************************/
+/*!
+ @brief Constantly poll for new command or response data
+*/
+/**************************************************************************/
+void loop(void)
+{
+ uint32_t start, stop, sent;
+ uint32_t remaining = TOTAL_BYTES;
+ start = stop = sent = 0;
+
+ if (Bluefruit.connected() && bleuart.notifyEnabled())
+ {
+ // Wait for user input before trying again
+ Serial.println("Connected. Send a key and press enter to start test");
+ getUserInput();
+
+ Serial.print("Sending ");
+ Serial.print(remaining);
+ Serial.println(" bytes ...");
+
+ start = millis();
+ while ( (remaining > 0) && Bluefruit.connected() && bleuart.notifyEnabled() )
+ {
+ if ( !bleuart.print(TEST_STRING) ) break;
+
+ sent += TEST_STRLEN;
+ remaining -= TEST_STRLEN;
+
+ // Only print every 100th time
+ // if ( (sent % (100*TEST_STRLEN) ) == 0 )
+ // {
+ // Serial.print("Sent: "); Serial.print(sent);
+ // Serial.print(" Remaining: "); Serial.println(remaining);
+ // }
+ }
+ stop = millis() - start;
+
+ Serial.print("Sent ");
+ Serial.print(sent);
+ Serial.print(" bytes in ");
+ Serial.print(stop / 1000.0F, 2);
+ Serial.println(" seconds.");
+
+ Serial.println("Speed ");
+ Serial.print( (sent / 1000.0F) / (stop / 1000.0F), 2);
+ Serial.println(" KB/s.\r\n");
+ }
+}
+
+/**************************************************************************/
+/*!
+ @brief Get user input from Serial
+*/
+/**************************************************************************/
+char* getUserInput(void)
+{
+ static char inputs[64+1];
+ memset(inputs, 0, sizeof(inputs));
+
+ // wait until data is available
+ while( Serial.available() == 0 ) { delay(1); }
+
+ uint8_t count=0;
+ do
+ {
+ count += Serial.readBytes(inputs+count, 64);
+ } while( (count < 64) && Serial.available() );
+
+ return inputs;
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Projects/homekit/homekit_lightbulb/homekit_lightbulb.ino b/arduino/libraries/Bluefruit52Lib/examples/Projects/homekit/homekit_lightbulb/homekit_lightbulb.ino
new file mode 100755
index 0000000..798d98b
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Projects/homekit/homekit_lightbulb/homekit_lightbulb.ino
@@ -0,0 +1,189 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+*********************************************************************/
+
+#include <bluefruit.h>
+#include <BLEHomekit.h>
+
+#include "crypto/crypto.h"
+
+#define CRYPTO_KEYFILE "/adafruit/homekit/key"
+
+BLEHomekit homekit;
+
+uint8_t test_keys[] =
+{
+ 0x55, 0x02, 0x29, 0x6A, 0x41, 0xB0, 0xF5, 0x35, 0x61, 0xFF, 0x82, 0x52, 0x2E, 0x77, 0xF0, 0xC6,
+ 0x1A, 0x2B, 0x6F, 0xD9, 0x4B, 0x48, 0x01, 0xCA, 0x37, 0xAF, 0x90, 0x74, 0x78, 0x07, 0xF8, 0xBE,
+ 0x58, 0xE8, 0xAD, 0x10, 0xB9, 0x69, 0xA3, 0x03, 0x0E, 0x42, 0x93, 0x2F, 0xF6, 0x3F, 0xE6, 0x40,
+ 0x71, 0x3F, 0x12, 0x63, 0x0B, 0x38, 0xEE, 0xF2, 0xDC, 0xCC, 0x1D, 0x24, 0x08, 0x70, 0xA3, 0xAD,
+ 0x8D, 0x16, 0xC0, 0x06, 0x24, 0x31, 0xCD, 0xB5, 0x34, 0xC8, 0x92, 0x3F, 0x3C, 0xF4, 0x43, 0x99,
+ 0xE1, 0x2B, 0x0C, 0x4B, 0xEE, 0xB6, 0xD9, 0xB6, 0xFD, 0x03, 0x43, 0xAD, 0x64, 0xB6, 0x6A, 0x19,
+ 0xDE, 0xA6, 0x34, 0x73, 0xC9, 0xB1, 0xB9, 0xBC, 0x5A, 0x09, 0xEF, 0x33, 0x1F, 0x32, 0xC9, 0xDD,
+ 0x71, 0xD3, 0xB7, 0x68, 0x89, 0xC6, 0x35, 0x36, 0x74, 0x9B, 0xE9, 0x84, 0x16, 0xF5, 0xAB, 0xCB,
+ 0x83, 0xA0, 0x77, 0x0E, 0xE2, 0x9A, 0x10, 0x36, 0xCC, 0xA9, 0xAE, 0xE3, 0x30, 0x8E, 0x24, 0x2F,
+ 0xCA, 0xC5, 0xAC, 0x37, 0x03, 0xF6, 0xEA, 0x1A, 0x22, 0x81, 0x61, 0x98, 0xCC, 0x76, 0x6D, 0x6E,
+ 0x46, 0x27, 0x50, 0x40, 0xD5, 0x15, 0xBB, 0xF3, 0x83, 0x08, 0x83, 0x3D, 0xDF, 0xED, 0x23, 0x20,
+ 0x70, 0x3B, 0xAB, 0xFD, 0x07, 0x0E, 0x92, 0x12, 0x10, 0xB0, 0xAE, 0x5F, 0xE2, 0x9E, 0x82, 0x33,
+ 0xD6, 0xE4, 0xA9, 0x70, 0x44, 0x6B, 0xE7, 0x7E, 0x4E, 0xA7, 0xF3, 0x63, 0xE3, 0x0F, 0xAB, 0x24,
+ 0xD4, 0xF4, 0x6A, 0xFC, 0x32, 0xDC, 0x4E, 0xA2, 0x4F, 0xBE, 0x25, 0x40, 0x49, 0xA7, 0xB1, 0x0F,
+ 0xF6, 0x4F, 0x1F, 0xFF, 0x08, 0x13, 0x46, 0x55, 0x45, 0x90, 0x6E, 0x09, 0xEA, 0x81, 0x60, 0x66,
+ 0x61, 0x49, 0x41, 0xC5, 0x23, 0xC6, 0xCE, 0xD8, 0xF4, 0xCB, 0x3D, 0x3B, 0xAC, 0x6E, 0x28, 0xDD,
+ 0x19, 0x58, 0x96, 0x3B, 0xC9, 0x39, 0x46, 0x46, 0xC4, 0x90, 0xCF, 0xFB, 0xAE, 0xFD, 0x30, 0xFB,
+ 0x36, 0x14, 0x36, 0xF4, 0x5E, 0xDD, 0x04, 0x2E, 0x3F, 0x5E, 0xCD, 0x71, 0x6B, 0x55, 0xD7, 0xF3,
+ 0x59, 0x24, 0x08, 0x58, 0x90, 0x71, 0x1F, 0x88, 0x53, 0xA0, 0xC1, 0xB8, 0x5F, 0x3D, 0x94, 0xF3,
+ 0xDB, 0xFC, 0x3F, 0x59, 0x41, 0xBF, 0x41, 0xC3, 0xC4, 0x70, 0x1A, 0x0C, 0x9C, 0x9A, 0x54, 0x5E,
+ 0xD3, 0xF0, 0x82, 0xD9, 0xF9, 0xCF, 0x0E, 0xC0, 0x53, 0xAD, 0x2E, 0xFA, 0x99, 0x1A, 0x57, 0x41,
+ 0x4F, 0x71, 0x2B, 0x47, 0x31, 0xB3, 0x18, 0xC4, 0xAE, 0xCD, 0xCC, 0xD4, 0x14, 0x75, 0x48, 0xB9,
+ 0x06, 0x81, 0xBA, 0xD9, 0x60, 0x63, 0xD4, 0x3A, 0x26, 0xE0, 0x64, 0xD1, 0xF7, 0xE4, 0x9A, 0xC1,
+ 0xC1, 0x06, 0xBC, 0x51, 0x85, 0xEC, 0x33, 0x63, 0xCD, 0x25, 0x34, 0x13, 0xBF, 0x5B, 0x65, 0x2D,
+ 0x6C, 0xCE, 0x6F, 0x22, 0x77, 0x12, 0x4C, 0x32, 0xFD, 0x72, 0x5C, 0x65, 0x5F, 0x28, 0x38, 0x6B,
+ 0x52, 0x87, 0x6A, 0xCF, 0x8A, 0x7F, 0xC1, 0x66, 0x03, 0x0C, 0x6F, 0x00, 0x82, 0xA7, 0xA8, 0x73,
+ 0x28, 0x17, 0x19, 0xD3, 0x26, 0x90, 0x70, 0xAF, 0x2B, 0x86, 0x34, 0x96, 0x91, 0xD3, 0xB7, 0x65,
+ 0x48, 0xB7, 0xCB, 0xEA, 0xC4, 0xB1, 0x78, 0x1C, 0x76, 0x51, 0x2F, 0x68, 0x89, 0x42, 0xCD, 0x89,
+ 0xA7, 0xE0, 0x8B, 0xD8, 0x8D, 0x1F, 0xDA, 0xA6, 0xCE, 0xD6, 0x71, 0x9E, 0x7D, 0x98, 0x59, 0x66,
+ 0xAD, 0x91, 0x68, 0xF5, 0xE2, 0xA0, 0x78, 0xB3, 0x69, 0x65, 0x00, 0x94, 0xDC, 0x44, 0x09, 0xA2,
+ 0x2B, 0x71, 0x15, 0x9E, 0x33, 0xE7, 0x8F, 0x72, 0x44, 0x83, 0xF6, 0xF4, 0x9C, 0xDE, 0xF0, 0xC1,
+ 0xAC, 0x60, 0x01, 0x79, 0x24, 0x9E, 0xC0, 0x82, 0x68, 0xA4, 0xE8, 0x70, 0xF0, 0xBD, 0x80, 0x99,
+ 0x1E, 0x5A, 0xB5, 0x08, 0x03, 0x62, 0xC7, 0x3D, 0xD1, 0xFE, 0x23, 0xA7, 0xF1, 0x01, 0x1A, 0x37,
+ 0x23, 0x27, 0x6D, 0x39, 0x63, 0x75, 0x35, 0x60, 0x6B, 0xD1, 0xD3, 0x77, 0xB1, 0xA2, 0xE4, 0x6A,
+ 0x0A, 0xD9, 0xD9, 0x42, 0x37, 0x97, 0x0C, 0x73, 0x97, 0x98, 0x55, 0xC2, 0x22, 0x5B, 0x62, 0x4E,
+ 0x1A, 0xBB, 0xFB, 0xAC, 0x91, 0xB0, 0x68, 0xAD, 0x78, 0x48, 0x45, 0x42, 0xEF, 0x80, 0xE7, 0xB0,
+ 0xC2, 0xA0, 0x03, 0x37, 0xBD, 0x12, 0xFD, 0x3A, 0x65, 0x76, 0xE6, 0xBC, 0xE7, 0x98, 0x79, 0x6F,
+ 0x18, 0x10, 0x9E, 0x67, 0x62, 0x3D, 0x1B, 0x41, 0x8E, 0x2D, 0x99, 0x87, 0x7D, 0x75, 0xBE, 0x49,
+ 0x6E, 0x43, 0xE2, 0x9F, 0x71, 0x29, 0x1F, 0x45, 0xB6, 0x2B, 0xAE, 0x3B, 0x78, 0xEF, 0x09, 0x4A,
+ 0xBD, 0x5F, 0xC1, 0x4C, 0xE5, 0x22, 0xD9, 0x17, 0x11, 0xCE, 0x39, 0xD7, 0x11, 0x3B, 0x13, 0xE8,
+ 0x9B, 0x8D, 0xDF, 0x9E, 0xCB, 0x96, 0xDD, 0xD7, 0xA8, 0x0D, 0x0F, 0xBE, 0x6F, 0xF2, 0xAC, 0xEF,
+ 0x0E, 0xA9, 0xFE, 0x0C, 0xC9, 0xF8, 0xC4, 0x55, 0x36, 0x3D, 0xEF, 0x30, 0xA7, 0x33, 0x7B, 0xB8,
+ 0x99, 0x05, 0xDE, 0xEF, 0xAA, 0xDA, 0xCB, 0xD7, 0x15, 0x30, 0xF4, 0xE3, 0xC8, 0x72, 0x25, 0x4A,
+ 0xBE, 0x1B, 0x35, 0x92, 0x92, 0xDD, 0x4B, 0x1C, 0xA0, 0x6F, 0x7C, 0xEF, 0x95, 0x12, 0x38, 0xFB,
+ 0xC8, 0x4E, 0x80, 0xB8, 0x06, 0xC6, 0x6F, 0xFC, 0x3A, 0xB4, 0x54, 0xCA, 0xC9, 0x8F, 0xE7, 0xB1,
+ 0xA3, 0x29, 0xEB, 0x06, 0xD7, 0xE8, 0xFB, 0x25, 0xD4, 0x30, 0x6A, 0x9C, 0xCC, 0x7C, 0xC7, 0x7E,
+ 0x1F, 0xA8, 0xA4, 0x23, 0x11, 0x9B, 0x9A, 0xBD, 0x9D, 0x2E, 0x8D, 0x5C, 0x67, 0x85, 0x5C, 0xBB,
+ 0xF5, 0x55, 0xC0, 0x11, 0x32, 0x67, 0x58, 0x2A, 0x24, 0xC2, 0xAA, 0x8E, 0x46, 0xC3, 0xDB, 0x5A,
+ 0xA7, 0x02, 0xA3, 0x3D, 0x76, 0x41, 0xED, 0xF4, 0x4C, 0x67, 0xC0, 0xB1, 0x8F, 0xDE, 0x27, 0x8A,
+ 0xF6, 0x53, 0x66, 0xA6, 0x7E, 0xF9, 0xB6, 0x8D, 0xAD, 0x63, 0xC8, 0x9C, 0x44, 0xA2, 0xD8, 0x22,
+ 0x26, 0x01, 0xD9, 0x2A, 0x7E, 0xA5, 0xE8, 0x73, 0xDB, 0x6C, 0xC0, 0xB6, 0xAC, 0x8F, 0xAC, 0x4B,
+ 0xC4, 0xD7, 0x98, 0xFF, 0x5A, 0x18, 0x4B, 0xCF, 0x38, 0xD1, 0x7E, 0x2D, 0xDB, 0xDD, 0x9C, 0x94,
+ 0x66, 0x72, 0x1A, 0xBA, 0x9A, 0x98, 0x92, 0x9B, 0x16, 0x32, 0x2E, 0xF1, 0x9A, 0x83, 0x62, 0x3E,
+ 0x2D, 0x17, 0x64, 0xBF, 0xA5, 0x27, 0xA1, 0xE7, 0xAF, 0xB5, 0xD4, 0x68, 0x3E, 0x06, 0x68, 0xDA,
+ 0xF6, 0x7C, 0x5E, 0x47, 0x0E, 0x50, 0x63, 0x70, 0xDE, 0xF4, 0x2F, 0x42, 0x22, 0x32, 0x2A, 0xF6,
+ 0x8A, 0xEE, 0x33, 0x43, 0x37, 0x46, 0x46, 0x39, 0x37, 0x32, 0x2D, 0x30, 0x34, 0x30, 0x45, 0x2D,
+ 0x34, 0x39, 0x31, 0x35, 0x2D, 0x41, 0x38, 0x33, 0x44, 0x2D, 0x41, 0x39, 0x36, 0x34, 0x36, 0x39,
+ 0x30, 0x44, 0x44, 0x43, 0x43, 0x38, 0x4B, 0xB6, 0xEA, 0x1E, 0x22, 0x3A, 0xEE, 0x83, 0x7E, 0xBE,
+ 0xA9, 0xA4, 0x26, 0x8C, 0x37, 0x00, 0xA1, 0x1A, 0xC4, 0xC1, 0xA1, 0x00, 0xF5, 0x8A, 0x7A, 0xFB,
+ 0x2B, 0x45, 0x70, 0xE4, 0xB5, 0x45, 0xAA, 0x00
+};
+
+void test_homekit(void)
+{
+ extern srp_keys_t srp;
+ extern crypto_keys_t crypto_keys;
+
+ return;
+
+ LOG_LV2_BUFFER("Private b", srp.b, 32);
+ LOG_LV2_BUFFER("Salt s", srp.salt, 16);
+ LOG_LV2_BUFFER("Verifier v", srp.v, 384);
+ LOG_LV2_BUFFER("Public B", srp.B, 384);
+
+ LOG_LV2_BUFFER("Sign Secret", crypto_keys.sign.secret, 64);
+
+ LOG_LV2_BUFFER("Client Name", crypto_keys.client.name, 36);
+ LOG_LV2_BUFFER("Client ltpk", crypto_keys.client.ltpk, 32);
+}
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Homekit Light Bulb Example");
+ Serial.println("--------------------------------------\n");
+
+ // Homekit uses a lot of characteristics so that default Attr Table size
+ // is not enough. Therefore we need to incresae the ATTR Table Size
+ // Note: All config***() function must be called before begin()
+ Bluefruit.configAttrTableSize(3000);
+
+ // Config the peripheral connection with maximum bandwidth
+ Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ //InternalFS.remove(CRYPTO_KEYFILE);
+ //File file(CRYPTO_KEYFILE, FILE_WRITE, InternalFS);
+ //file.write(&test_keys, sizeof(test_keys));
+ //file.close();
+
+ homekit.begin();
+
+ test_homekit();
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 30
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.setStopCallback(adv_stop_callback); // callback when adv is stopped
+
+ /* Homekit include advertising interval as part of its adv data
+ * - Therefore setInterval() must be call before setData(homekit).
+ * - Furthermore since Adverting Data (for homekit) changes when adv interval change
+ * from fast to slow. We do either way to stay consistence
+ * 1. Advertise with fixed interval (fast = slow)
+ * 2. Register stop callback for adv stop, then re-set the Advertising data to match
+ * the changed interval. Which is what this sketch does.
+ */
+ Bluefruit.Advertising.setData(homekit);
+
+ // Stop after 30 secconds
+ Bluefruit.Advertising.start(30);
+}
+
+void adv_stop_callback(void)
+{
+ // change interval to only slow since we alredy passed first 30 seconds
+ Bluefruit.Advertising.setInterval(244, 244);
+
+ // Reset advertising data for homekit.
+ Bluefruit.Advertising.clearData();
+ Bluefruit.Advertising.setData(homekit);
+
+ // Advertising indefintely.
+ Bluefruit.Advertising.start(0);
+}
+
+void loop()
+{
+ // Toggle both LEDs every 1 second
+ digitalToggle(LED_RED);
+ delay(1000);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/README.md b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/README.md
new file mode 100755
index 0000000..f6edc00
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/README.md
@@ -0,0 +1,24 @@
+# RSSI Proximity Project
+
+This project demonstrates how you can use a single Bluefruit nRF52 device
+running in Central mode to listen for a specific signature in the advertising
+packets of nearby Bluefruit nRF52 devices running in peripheral mode.
+
+The Central mode device will sort those devices with the matching signature by
+proximity based on their RSSI (relative signal strength) value.
+
+Most of the Central mode advertising API is used in this demo, making it an
+excellent place to start if you want to create your own custom Central based
+project(s).
+
+## Project Files
+
+This project consists of two parts:
+
+- `rssi_proximity_central`: This project should be run on one Bluefruit nRF52
+ board and will configure the board as a Central device, actively scanning
+ for any peripheral devices in listening range.
+- `rssi_proximity_peripheral`: This project should be run on one or more
+ Bluefruit nRF52 boards and will configure the boards as peripheral devices,
+ sending out a specifically formatted advertising packet at a regular
+ interval.
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_central/rssi_proximity_central.ino b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_central/rssi_proximity_central.ino
new file mode 100755
index 0000000..c284268
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_central/rssi_proximity_central.ino
@@ -0,0 +1,683 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+
+ Author: KTOWN (Kevin Townsend)
+ Copyright (C) Adafruit Industries 2017
+*********************************************************************/
+
+/* This example scans for advertising devices (peripherals) in range,
+ * looking for a specific UUID in the advertising packet. When this
+ * UUID is found, it will display an alert, sorting devices detected
+ * in range by their RSSI value, which is an approximate indicator of
+ * proximity (though highly dependent on environmental obstacles, etc.).
+ *
+ * A simple 'bubble sort' algorithm is used, along with a simple
+ * set of decisions about whether and where to insert new records
+ * in the record list.
+ *
+ * This example is intended to be used with multiple peripherals
+ * devices running the *_peripheral.ino version of this application.
+ *
+ * VERBOSE_OUTPUT
+ * --------------
+ * Verbose advertising packet analysis can be enabled for
+ * advertising packet contents to help debug issues with the
+ * advertising payloads, with fully parsed data displayed in the
+ * Serial Monitor.
+ *
+ * ARRAY_SIZE
+ * ----------
+ * The numbers of peripherals tracked and sorted can be set via the
+ * ARRAY_SIZE macro. Must be at least 2.
+ *
+ * TIMEOUT_MS
+ * ----------
+ * This value determines the number of milliseconds before a tracked
+ * peripheral has it's last sample 'invalidated', such as when a device
+ * is tracked and then goes out of range.
+ *
+ * ENABLE_TFT
+ * ----------
+ * An ILI9341 based TFT can optionally be used to display proximity
+ * alerts. The Adafruit TFT Feather Wing is recommended and is the only
+ * device tested with this functionality.
+ *
+ * ENABLE_OLED
+ * -----------
+ * An SSD1306 128x32 based OLED can optionally be used to display
+ * proximity alerts. The Adafruit OLED Feather Wing is recommended and
+ * is the only device tested with this functionality.
+ */
+
+#include <string.h>
+#include <bluefruit.h>
+#include <SPI.h>
+
+#define VERBOSE_OUTPUT (0) // Set this to 1 for verbose adv packet output to the serial monitor
+#define ARRAY_SIZE (4) // The number of RSSI values to store and compare
+#define TIMEOUT_MS (2500) // Number of milliseconds before a record is invalidated in the list
+#define ENABLE_TFT (0) // Set this to 1 to enable ILI9341 TFT display support
+#define ENABLE_OLED (0) // Set this to 1 to enable SSD1306 128x32 OLED display support
+
+#if (ARRAY_SIZE <= 1)
+ #error "ARRAY_SIZE must be at least 2"
+#endif
+#if (ENABLE_TFT) && (ENABLE_OLED)
+ #error "ENABLE_TFT and ENABLE_OLED can not both be set at the same time"
+#endif
+
+// Custom UUID used to differentiate this device.
+// Use any online UUID generator to generate a valid UUID.
+// Note that the byte order is reversed ... CUSTOM_UUID
+// below corresponds to the follow value:
+// df67ff1a-718f-11e7-8cf7-a6006ad3dba0
+const uint8_t CUSTOM_UUID[] =
+{
+ 0xA0, 0xDB, 0xD3, 0x6A, 0x00, 0xA6, 0xF7, 0x8C,
+ 0xE7, 0x11, 0x8F, 0x71, 0x1A, 0xFF, 0x67, 0xDF
+};
+
+BLEUuid uuid = BLEUuid(CUSTOM_UUID);
+
+/* TFT setup if the TFT display is available */
+#if (ENABLE_TFT)
+ #include <Adafruit_GFX.h>
+ #include <Adafruit_ILI9341.h>
+
+ /* Pin setup for the TFT display over SPI */
+ #ifdef ARDUINO_NRF52_FEATHER
+ #define TFT_DC 11
+ #define TFT_CS 31
+ #define STMPE_CS 30
+ #define SD_CS 27
+ #else
+ #error "Unknown target. Please make sure you are using an nRF52 Feather and BSP 0.6.5 or higher!"
+ #endif
+
+ Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
+#endif
+
+/* 128x32 OLED setup if the OLED display is available */
+#if (ENABLE_OLED)
+ #include <Wire.h>
+ #include <Adafruit_GFX.h>
+ #include <Adafruit_SSD1306.h>
+
+ /* Pin setup for the OLED display */
+ #ifdef ARDUINO_NRF52_FEATHER
+ #define BUTTON_A 31
+ #define BUTTON_B 30
+ #define BUTTON_C 27
+ #else
+ #error "Unknown target. Please make sure you are using an nRF52 Feather and BSP 0.6.5 or higher!"
+ #endif
+
+ Adafruit_SSD1306 oled = Adafruit_SSD1306();
+#endif
+
+/* This struct is used to track detected nodes */
+typedef struct node_record_s
+{
+ uint8_t addr[6]; // Six byte device address
+ int8_t rssi; // RSSI value
+ int32_t timestamp; // Timestamp for invalidation purposes
+ int8_t reserved; // Padding for word alignment
+} node_record_t;
+
+node_record_t records[ARRAY_SIZE];
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Central Proximity Example");
+ Serial.println("-------------------------------------\n");
+
+ /* Enable the TFT display if available */
+ #if ENABLE_TFT
+ tft.begin();
+ tft.fillScreen(ILI9341_BLACK);
+ tft.setCursor(40, 0);
+ tft.setTextColor(ILI9341_WHITE);
+ tft.setTextSize(2);
+ tft.println("DUNKIN");
+ #endif
+
+ /* Enable the OLED display if available */
+ #if ENABLE_OLED
+ oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
+ oled.display();
+ #endif
+
+ /* Clear the results list */
+ memset(records, 0, sizeof(records));
+ for (uint8_t i = 0; i<ARRAY_SIZE; i++)
+ {
+ // Set all RSSI values to lowest value for comparison purposes,
+ // since 0 would be higher than any valid RSSI value
+ records[i].rssi = -128;
+ }
+
+ /* Enable both peripheral and central modes */
+ err_t err = Bluefruit.begin(true, true);
+ if (err)
+ {
+ Serial.print("Unable to init Bluefruit (ERROR CODE: ");
+ Serial.print(err);
+ Serial.println(")");
+ while(1)
+ {
+ digitalToggle(LED_RED);
+ delay(100);
+ }
+ }
+ else
+ {
+ Serial.println("Bluefruit initialized (central mode)");
+ }
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+
+ /* Set the device name */
+ Bluefruit.setName("Bluefruit52");
+
+ /* Set the LED interval for blinky pattern on BLUE LED */
+ Bluefruit.setConnLedInterval(250);
+
+ /* Start Central Scanning
+ * - Enable auto scan if disconnected
+ * - Filter out packet with a min rssi
+ * - Interval = 100 ms, window = 50 ms
+ * - Use active scan (used to retrieve the optional scan response adv packet)
+ * - Start(0) = will scan forever since no timeout is given
+ */
+ Bluefruit.Scanner.setRxCallback(scan_callback);
+ Bluefruit.Scanner.restartOnDisconnect(true);
+ Bluefruit.Scanner.filterRssi(-80); // Only invoke callback for devices with RSSI >= -80 dBm
+ Bluefruit.Scanner.filterUuid(uuid); // Only invoke callback if the target UUID was found
+ //Bluefruit.Scanner.filterMSD(0xFFFF); // Only invoke callback when MSD is present with the specified Company ID
+ Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms
+ Bluefruit.Scanner.useActiveScan(true); // Request scan response data
+ Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
+ Serial.println("Scanning ...");
+}
+
+/* This callback handler is fired every time a valid advertising packet is detected */
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ node_record_t record;
+
+ /* Prepare the record to try to insert it into the existing record list */
+ memcpy(record.addr, report->peer_addr.addr, 6); /* Copy the 6-byte device ADDR */
+ record.rssi = report->rssi; /* Copy the RSSI value */
+ record.timestamp = millis(); /* Set the timestamp (approximate) */
+
+ /* Attempt to insert the record into the list */
+ if (insertRecord(&record) == 1) /* Returns 1 if the list was updated */
+ {
+ printRecordList(); /* The list was updated, print the new values */
+ Serial.println("");
+
+ /* Display the device list on the TFT if available */
+ #if ENABLE_TFT
+ renderResultsToTFT();
+ #endif
+
+ /* Display the device list on the OLED if available */
+ #if ENABLE_OLED
+ renderResultsToOLED();
+ #endif
+ }
+
+/* Fully parse and display the advertising packet to the Serial Monitor
+ * if verbose/debug output is requested */
+#if VERBOSE_OUTPUT
+ uint8_t len = 0;
+ uint8_t buffer[32];
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Display the timestamp and device address */
+ if (report->scan_rsp)
+ {
+ Serial.printf("[SR%10d] Packet received from ", millis());
+ }
+ else
+ {
+ Serial.printf("[ADV%9d] Packet received from ", millis());
+ }
+ // MAC is in little endian --> print reverse
+ Serial.printBufferReverse(report->peer_addr.addr, 6, ':');
+ Serial.println("");
+
+ /* Raw buffer contents */
+ Serial.printf("%14s %d bytes\n", "PAYLOAD", report->dlen);
+ if (report->dlen)
+ {
+ Serial.printf("%15s", " ");
+ Serial.printBuffer(report->data, report->dlen, '-');
+ Serial.println();
+ }
+
+ /* RSSI value */
+ Serial.printf("%14s %d dBm\n", "RSSI", report->rssi);
+
+ /* Adv Type */
+ Serial.printf("%14s ", "ADV TYPE");
+ switch (report->type)
+ {
+ case BLE_GAP_ADV_TYPE_ADV_IND:
+ Serial.printf("Connectable undirected\n");
+ break;
+ case BLE_GAP_ADV_TYPE_ADV_DIRECT_IND:
+ Serial.printf("Connectable directed\n");
+ break;
+ case BLE_GAP_ADV_TYPE_ADV_SCAN_IND:
+ Serial.printf("Scannable undirected\n");
+ break;
+ case BLE_GAP_ADV_TYPE_ADV_NONCONN_IND:
+ Serial.printf("Non-connectable undirected\n");
+ break;
+ }
+
+ /* Shortened Local Name */
+ if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, buffer, sizeof(buffer)))
+ {
+ Serial.printf("%14s %s\n", "SHORT NAME", buffer);
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ /* Complete Local Name */
+ if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, buffer, sizeof(buffer)))
+ {
+ Serial.printf("%14s %s\n", "COMPLETE NAME", buffer);
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ /* TX Power Level */
+ if (Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_TX_POWER_LEVEL, buffer, sizeof(buffer)))
+ {
+ Serial.printf("%14s %i\n", "TX PWR LEVEL", buffer[0]);
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ /* Check for UUID16 Complete List */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, buffer, sizeof(buffer));
+ if ( len )
+ {
+ printUuid16List(buffer, len);
+ }
+
+ /* Check for UUID16 More Available List */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, buffer, sizeof(buffer));
+ if ( len )
+ {
+ printUuid16List(buffer, len);
+ }
+
+ /* Check for UUID128 Complete List */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, buffer, sizeof(buffer));
+ if ( len )
+ {
+ printUuid128List(buffer, len);
+ }
+
+ /* Check for UUID128 More Available List */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, buffer, sizeof(buffer));
+ if ( len )
+ {
+ printUuid128List(buffer, len);
+ }
+
+ /* Check for BLE UART UUID */
+ if ( Bluefruit.Scanner.checkReportForUuid(report, BLEUART_UUID_SERVICE) )
+ {
+ Serial.printf("%14s %s\n", "BLE UART", "UUID Found!");
+ }
+
+ /* Check for DIS UUID */
+ if ( Bluefruit.Scanner.checkReportForUuid(report, UUID16_SVC_DEVICE_INFORMATION) )
+ {
+ Serial.printf("%14s %s\n", "DIS", "UUID Found!");
+ }
+
+ /* Check for Manufacturer Specific Data */
+ len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, buffer, sizeof(buffer));
+ if (len)
+ {
+ Serial.printf("%14s ", "MAN SPEC DATA");
+ Serial.printBuffer(buffer, len, '-');
+ Serial.println();
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ Serial.println();
+#endif
+
+ // For Softdevice v6: after received a report, scanner will be paused
+ // We need to call Scanner resume() to continue scanning
+ Bluefruit.Scanner.resume();
+}
+
+#if ENABLE_TFT
+void renderResultsToTFT(void)
+{
+ tft.fillRect(0, 0, 240, ARRAY_SIZE*8, ILI9341_BLACK);
+ tft.setTextSize(1);
+ tft.setCursor(0, 0);
+
+ for (uint8_t i=0; i<ARRAY_SIZE; i++)
+ {
+ if (records[i].addr[0] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[0], HEX);
+ tft.print(":");
+ if (records[i].addr[1] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[1], HEX);
+ tft.print(":");
+ if (records[i].addr[2] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[2], HEX);
+ tft.print(":");
+ if (records[i].addr[3] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[3], HEX);
+ tft.print(":");
+ if (records[i].addr[4] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[4], HEX);
+ tft.print(":");
+ if (records[i].addr[5] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[5], HEX);
+ tft.print(" ");
+ tft.print(records[i].rssi);
+ tft.print(" [");
+ tft.print(records[i].timestamp);
+ tft.println("] ");
+ }
+}
+#endif
+
+#if ENABLE_OLED
+void renderResultsToOLED(void)
+{
+ oled.clearDisplay();
+ oled.setTextSize(1);
+ oled.setTextColor(WHITE);
+
+ for (uint8_t i=0; i<ARRAY_SIZE; i++)
+ {
+ if (i>=4)
+ {
+ /* We can only display four records on a 128x32 pixel display */
+ oled.display();
+ return;
+ }
+ if (records[i].rssi != -128)
+ {
+ oled.setCursor(0, i*8);
+ if (records[i].addr[0] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[0], HEX);
+ oled.print(":");
+ if (records[i].addr[1] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[1], HEX);
+ oled.print(":");
+ if (records[i].addr[2] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[2], HEX);
+ oled.print(":");
+ if (records[i].addr[3] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[3], HEX);
+ oled.print(":");
+ if (records[i].addr[4] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[4], HEX);
+ oled.print(":");
+ if (records[i].addr[5] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[5], HEX);
+ oled.print(" ");
+ oled.println(records[i].rssi);
+ }
+ }
+
+ oled.display();
+}
+#endif
+
+/* Prints a UUID16 list to the Serial Monitor */
+void printUuid16List(uint8_t* buffer, uint8_t len)
+{
+ Serial.printf("%14s %s", "16-Bit UUID");
+ for(int i=0; i<len; i+=2)
+ {
+ uint16_t uuid16;
+ memcpy(&uuid16, buffer+i, 2);
+ Serial.printf("%04X ", uuid16);
+ }
+ Serial.println();
+}
+
+/* Prints a UUID128 list to the Serial Monitor */
+void printUuid128List(uint8_t* buffer, uint8_t len)
+{
+ (void) len;
+ Serial.printf("%14s %s", "128-Bit UUID");
+
+ // Print reversed order
+ for(int i=0; i<16; i++)
+ {
+ const char* fm = (i==4 || i==6 || i==8 || i==10) ? "-%02X" : "%02X";
+ Serial.printf(fm, buffer[15-i]);
+ }
+
+ Serial.println();
+}
+
+/* Prints the current record list to the Serial Monitor */
+void printRecordList(void)
+{
+ for (uint8_t i = 0; i<ARRAY_SIZE; i++)
+ {
+ Serial.printf("[%i] ", i);
+ Serial.printBuffer(records[i].addr, 6, ':');
+ Serial.printf(" %i (%u ms)\n", records[i].rssi, records[i].timestamp);
+ }
+}
+
+/* This function performs a simple bubble sort on the records array */
+/* It's slow, but relatively easy to understand */
+/* Sorts based on RSSI values, where the strongest signal appears highest in the list */
+void bubbleSort(void)
+{
+ int inner, outer;
+ node_record_t temp;
+
+ for(outer=0; outer<ARRAY_SIZE-1; outer++)
+ {
+ for(inner=outer+1; inner<ARRAY_SIZE; inner++)
+ {
+ if(records[outer].rssi < records[inner].rssi)
+ {
+ memcpy((void *)&temp, (void *)&records[outer], sizeof(node_record_t)); // temp=records[outer];
+ memcpy((void *)&records[outer], (void *)&records[inner], sizeof(node_record_t)); // records[outer] = records[inner];
+ memcpy((void *)&records[inner], (void *)&temp, sizeof(node_record_t)); // records[inner] = temp;
+ }
+ }
+ }
+}
+
+/* This function will check if any records in the list
+ * have expired and need to be invalidated, such as when
+ * a device goes out of range.
+ *
+ * Returns the number of invalidated records, or 0 if
+ * nothing was changed.
+ */
+int invalidateRecords(void)
+{
+ uint8_t i;
+ int match = 0;
+
+ /* Not enough time has elapsed to avoid an underflow error */
+ if (millis() <= TIMEOUT_MS)
+ {
+ return 0;
+ }
+
+ /* Check if any records have expired */
+ for (i=0; i<ARRAY_SIZE; i++)
+ {
+ if (records[i].timestamp) // Ignore zero"ed records
+ {
+ if (records[i].timestamp <= millis() - TIMEOUT_MS)
+ {
+ /* Record has expired, zero it out */
+ memset(&records[i], 0, sizeof(node_record_t));
+ records[i].rssi = -128;
+ match++;
+ }
+ }
+ }
+
+ /* Resort the list if something was zero'ed out */
+ if (match)
+ {
+ // Serial.printf("Invalidated %i records!\n", match);
+ bubbleSort();
+ }
+
+ return match;
+}
+
+/* This function attempts to insert the record if it is larger than the smallest valid RSSI entry */
+/* Returns 1 if a change was made, otherwise 0 */
+int insertRecord(node_record_t *record)
+{
+ uint8_t i;
+
+ /* Invalidate results older than n milliseconds */
+ invalidateRecords();
+
+ /* Record Insertion Workflow:
+ *
+ * START
+ * |
+ * \ /
+ * +-------------+
+ * 1. | BUBBLE SORT | // Put list in known state!
+ * +-------------+
+ * |
+ * _____\ /_____
+ * / ENTRY \ YES
+ * 2. < EXISTS W/THIS > ------------------+
+ * \ ADDRESS? / |
+ * ----------- |
+ * | NO |
+ * | |
+ * ______\ /______ |
+ * / IS \ YES |
+ * 3. < THERE A ZERO'ED >------------------+
+ * \ RECORD? / |
+ * ------------- |
+ * | NO |
+ * | |
+ * ______\ /________ |
+ * / IS THE \ YES |
+ * 4.< RECORD'S RSSI >= >----------------|
+ * \ THE LOWEST RSSI? / |
+ * ---------------- |
+ * | NO |
+ * | |
+ * \ / \ /
+ * +---------------+ +----------------+
+ * | IGNORE RECORD | | REPLACE RECORD |
+ * +---------------+ +----------------+
+ * | |
+ * | \ /
+ * \ / +----------------+
+ * EXIT <------------- | BUBBLE SORT |
+ * +----------------+
+ */
+
+ /* 1. Bubble Sort
+ * This puts the lists in a known state where we can make
+ * certain assumptions about the last record in the array. */
+ bubbleSort();
+
+ /* 2. Check for a match on existing device address */
+ /* Replace it if a match is found, then sort */
+ uint8_t match = 0;
+ for (i=0; i<ARRAY_SIZE; i++)
+ {
+ if (memcmp(records[i].addr, record->addr, 6) == 0)
+ {
+ match = 1;
+ }
+ if (match)
+ {
+ memcpy(&records[i], record, sizeof(node_record_t));
+ goto sort_then_exit;
+ }
+ }
+
+ /* 3. Check for zero'ed records */
+ /* Insert if a zero record is found, then sort */
+ for (i=0; i<ARRAY_SIZE; i++)
+ {
+ if (records[i].rssi == -128)
+ {
+ memcpy(&records[i], record, sizeof(node_record_t));
+ goto sort_then_exit;
+ }
+ }
+
+ /* 4. Check RSSI of the lowest record */
+ /* Replace if >=, then sort */
+ if (records[ARRAY_SIZE-1].rssi <= record->rssi)
+ {
+ memcpy(&records[ARRAY_SIZE-1], record, sizeof(node_record_t));
+ goto sort_then_exit;
+ }
+
+ /* Nothing to do ... RSSI is lower than the last value, exit and ignore */
+ return 0;
+
+sort_then_exit:
+ /* Bubble sort */
+ bubbleSort();
+ return 1;
+}
+
+void loop()
+{
+ /* Toggle red LED every second */
+ digitalToggle(LED_RED);
+
+ /* Invalidate old results once per second in addition
+ * to the invalidation in the callback handler. */
+ /* ToDo: Update to use a mutex or semaphore since this
+ * can lead to list corruption as-is if the scann results
+ * callback is fired in the middle of the invalidation
+ * function. */
+ if (invalidateRecords())
+ {
+ /* The list was updated, print the new values */
+ printRecordList();
+ Serial.println("");
+ /* Display the device list on the TFT if available */
+ #if ENABLE_TFT
+ renderResultsToTFT();
+ #endif
+ /* Display the device list on the OLED if available */
+ #if ENABLE_OLED
+ renderResultsToOLED();
+ #endif
+ }
+
+ delay(1000);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_peripheral/rssi_proximity_peripheral.ino b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_peripheral/rssi_proximity_peripheral.ino
new file mode 100755
index 0000000..1a39836
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_peripheral/rssi_proximity_peripheral.ino
@@ -0,0 +1,160 @@
+/*********************************************************************
+ This is an example for our nRF52 based Bluefruit LE modules
+
+ Pick one up today in the adafruit shop!
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ MIT license, check LICENSE for more information
+ All text above, and the splash screen below must be included in
+ any redistribution
+
+ Author: KTOWN (Kevin Townsend)
+ Copyright (C) Adafruit Industries 2017
+*********************************************************************/
+
+/* This example constantly advertises a custom 128-bit UUID, and is
+ * intended to be used in combination with a Central sketch that scans
+ * for this UUID, and then displays an alert message, sorting matching
+ * devices by their RSSI level which is an approximate indication of
+ * distance (although highly subject to environmental obstacles).
+ *
+ * By including a custom UUID in the advertising packet, we can easily
+ * filter the scan results on the Central device, rather than manually
+ * parsing the advertising packet(s) of every device in range.
+ *
+ * This example is intended to be run with the *_central.ino version
+ * of this application.
+ */
+
+#include <bluefruit.h>
+#include <ble_gap.h>
+
+// Software Timer for blinking RED LED
+SoftwareTimer blinkTimer;
+
+// Custom UUID used to differentiate this device.
+// Use any online UUID generator to generate a valid UUID.
+// Note that the byte order is reversed ... CUSTOM_UUID
+// below corresponds to the follow value:
+// df67ff1a-718f-11e7-8cf7-a6006ad3dba0
+const uint8_t CUSTOM_UUID[] =
+{
+ 0xA0, 0xDB, 0xD3, 0x6A, 0x00, 0xA6, 0xF7, 0x8C,
+ 0xE7, 0x11, 0x8F, 0x71, 0x1A, 0xFF, 0x67, 0xDF
+};
+
+BLEUuid uuid = BLEUuid(CUSTOM_UUID);
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Peripheral Proximity Example");
+ Serial.println("----------------------------------------\n");
+
+ // Initialize blinkTimer for 1000 ms and start it
+ blinkTimer.begin(1000, blink_timer_callback);
+ blinkTimer.start();
+
+ err_t err = Bluefruit.begin();
+ if (err)
+ {
+ Serial.print("Unable to init Bluefruit (ERROR CODE: ");
+ Serial.print(err);
+ Serial.println(")");
+ while(1)
+ {
+ digitalToggle(LED_RED);
+ delay(100);
+ }
+ }
+ else
+ {
+ Serial.println("Bluefruit initialized (peripheral mode)");
+ }
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Set up and start advertising
+ startAdv();
+
+ Serial.println("Advertising started");
+}
+
+void startAdv(void)
+{
+ // Note: The entire advertising packet is limited to 31 bytes!
+
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Preferred Solution: Add a custom UUID to the advertising payload, which
+ // we will look for on the Central side via Bluefruit.Scanner.filterUuid(uuid);
+ // A valid 128-bit UUID can be generated online with almost no chance of conflict
+ // with another device or etup
+ Bluefruit.Advertising.addUuid(uuid);
+
+ /*
+ // Alternative Solution: Manufacturer Specific Data (MSD)
+ // You could also send a custom MSD payload and filter for the 'Company ID'
+ // via 'Bluefruit.Scanner.filterMSD(CID);', although this does require a
+ // valid CID, which is why the UUID method above is more appropriate in
+ // most situations. For a complete list of valid company IDs see:
+ // https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
+ // For test purposes, 0xFFFF CAN be used, but according to the Bluetooth SIG:
+ // > "This value may be used in the internal and interoperability tests before a
+ // > Company ID has been assigned. This value shall not be used in shipping end
+ // > products."
+ uint8_t msd_payload[4]; // Two bytes are required for the CID, so we have 2 bytes user data, expand as needed
+ uint16_t msd_cid = 0xFFFF;
+ memset(msd_payload, 0, sizeof(msd_payload));
+ memcpy(msd_payload, (uint8_t*)&msd_cid, sizeof(msd_cid));
+ msd_payload[2] = 0x11;
+ msd_payload[3] = 0x22;
+ Bluefruit.Advertising.addData(BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, msd_payload, sizeof(msd_payload));
+ */
+
+ // Not enough room in the advertising packet for name
+ // so store it in the Scan Response instead
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in units of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start();
+}
+
+void loop()
+{
+}
+
+/**
+ * Software Timer callback is invoked via a built-in FreeRTOS thread with
+ * minimal stack size. Therefore it should be as simple as possible. If
+ * a periodically heavy task is needed, please use Scheduler.startLoop() to
+ * create a dedicated task for it.
+ *
+ * More information http://www.freertos.org/RTOS-software-timer.html
+ */
+void blink_timer_callback(TimerHandle_t xTimerID)
+{
+ (void) xTimerID;
+ digitalToggle(LED_RED);
+}
+