Bluetooth BLE HID Keyboard for the AlterErgo device, based on Seeed Studio Tiny BLE.
Dependencies: BLE_API BLE_HID mbed nRF51822
Fork of BLENano_HID by
main.cpp@1:c6659c8882c9, 2018-08-26 (annotated)
- Committer:
- shervinemami
- Date:
- Sun Aug 26 10:19:01 2018 +0000
- Revision:
- 1:c6659c8882c9
- Parent:
- 0:3435302551b3
Initial working version of keyboard-only BLE HID
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
shervinemami | 1:c6659c8882c9 | 1 | /** |
shervinemami | 1:c6659c8882c9 | 2 | * Handheld BLE finger input device based on Seeed Studio Tiny BLE (TinyBLE). |
shervinemami | 1:c6659c8882c9 | 3 | * By Shervin Emami (http://shervinemami.info/), Apr 2018. |
shervinemami | 1:c6659c8882c9 | 4 | * If the analog voltage on a "finger" pin is below a threshold voltage, |
shervinemami | 1:c6659c8882c9 | 5 | * then it sends a rare keypress using Bluetooth, so that any computer or |
shervinemami | 1:c6659c8882c9 | 6 | * smartphone can be configured to perform a desired function due to this input event. |
shervinemami | 1:c6659c8882c9 | 7 | * |
shervinemami | 1:c6659c8882c9 | 8 | * |
shervinemami | 1:c6659c8882c9 | 9 | * This program implements a complete HID-over-Gatt Profile: |
shervinemami | 1:c6659c8882c9 | 10 | * - HID is provided by KeyboardService |
shervinemami | 1:c6659c8882c9 | 11 | * - Battery Service |
shervinemami | 1:c6659c8882c9 | 12 | * - Device Information Service |
shervinemami | 1:c6659c8882c9 | 13 | * |
shervinemami | 1:c6659c8882c9 | 14 | * Complete strings can be sent over BLE using printf. Please note, however, than a 12char string |
shervinemami | 1:c6659c8882c9 | 15 | * will take about 500ms to transmit, principally because of the limited notification rate in BLE. |
shervinemami | 1:c6659c8882c9 | 16 | * KeyboardService uses a circular buffer to store the strings to send, and calls to putc will fail |
shervinemami | 1:c6659c8882c9 | 17 | * once this buffer is full. This will result in partial strings being sent to the client. |
shervinemami | 1:c6659c8882c9 | 18 | |
shervinemami | 1:c6659c8882c9 | 19 | * Tested with mbed libraries for April 2nd, 2018. If you use a newer version of mbed or other |
shervinemami | 1:c6659c8882c9 | 20 | * libs and you have problems, try rolling back to April 2nd, 2018. |
shervinemami | 1:c6659c8882c9 | 21 | */ |
shervinemami | 1:c6659c8882c9 | 22 | |
shervinemami | 1:c6659c8882c9 | 23 | // Configure the settings of my board. |
shervinemami | 1:c6659c8882c9 | 24 | #include "tiny_ble.h" // Seeed Studio Tiny BLE |
shervinemami | 1:c6659c8882c9 | 25 | |
shervinemami | 1:c6659c8882c9 | 26 | |
shervinemami | 1:c6659c8882c9 | 27 | // Define LOG_MESSAGES if you want various debug messages to be sent to the PC via a UART cable. |
shervinemami | 1:c6659c8882c9 | 28 | #define LOG_MESSAGES |
shervinemami | 1:c6659c8882c9 | 29 | |
shervinemami | 1:c6659c8882c9 | 30 | // Various USB Keyboard keycodes that we can send. |
shervinemami | 1:c6659c8882c9 | 31 | #define KEYCODE_F4 131 |
shervinemami | 1:c6659c8882c9 | 32 | #define KEYCODE_F5 132 |
shervinemami | 1:c6659c8882c9 | 33 | #define KEYCODE_F6 133 |
shervinemami | 1:c6659c8882c9 | 34 | #define KEYCODE_F7 134 |
shervinemami | 1:c6659c8882c9 | 35 | #define KEYCODE_F8 135 |
shervinemami | 1:c6659c8882c9 | 36 | #define KEYCODE_F9 136 |
shervinemami | 1:c6659c8882c9 | 37 | #define KEYCODE_F10 137 |
shervinemami | 1:c6659c8882c9 | 38 | #define KEYCODE_F11 138 |
shervinemami | 1:c6659c8882c9 | 39 | #define KEYCODE_F12 139 |
shervinemami | 1:c6659c8882c9 | 40 | #define KEYCODE_HOME 145 |
shervinemami | 1:c6659c8882c9 | 41 | #define KEYCODE_PAGEUP 146 |
shervinemami | 1:c6659c8882c9 | 42 | #define KEYCODE_PAGEDOWN 147 |
shervinemami | 1:c6659c8882c9 | 43 | #define KEYCODE_RIGHT 148 |
shervinemami | 1:c6659c8882c9 | 44 | #define KEYCODE_LEFT 149 |
shervinemami | 1:c6659c8882c9 | 45 | #define KEYCODE_DOWN 150 |
shervinemami | 1:c6659c8882c9 | 46 | #define KEYCODE_UP 151 |
shervinemami | 1:c6659c8882c9 | 47 | #define KEYCODE_ESCAPE 157 |
shervinemami | 1:c6659c8882c9 | 48 | #define KEYCODE_RIGHTCLK 188 |
shervinemami | 1:c6659c8882c9 | 49 | #define KEYCODE_ACCENT 96 |
shervinemami | 1:c6659c8882c9 | 50 | #define KEYCODE_NUMLOCK 193 |
shervinemami | 1:c6659c8882c9 | 51 | |
shervinemami | 1:c6659c8882c9 | 52 | |
shervinemami | 1:c6659c8882c9 | 53 | |
shervinemami | 1:c6659c8882c9 | 54 | |
shervinemami | 1:c6659c8882c9 | 55 | const int FING1_KEYCODE = KEYCODE_F8; // Set the keypress that will be sent over bluetooth. |
shervinemami | 1:c6659c8882c9 | 56 | const int FING2DOWN_KEYCODE = KEYCODE_F4; // |
shervinemami | 1:c6659c8882c9 | 57 | const int FING2UP_KEYCODE = KEYCODE_NUMLOCK; |
shervinemami | 1:c6659c8882c9 | 58 | const int FING3_KEYCODE = KEYCODE_UP; // |
shervinemami | 1:c6659c8882c9 | 59 | const int FING4_KEYCODE = KEYCODE_DOWN; // |
shervinemami | 1:c6659c8882c9 | 60 | |
shervinemami | 1:c6659c8882c9 | 61 | const float FINGER1_PRESS = 0.42f; // Set how much the person needs to press their finger in to trigger a keypress. |
shervinemami | 1:c6659c8882c9 | 62 | const float FINGER2_PRESS = 0.41f; // Note that each finger is slightly different strength, due to the mechanical design. |
shervinemami | 1:c6659c8882c9 | 63 | const float FINGER3_PRESS = 0.38f; // |
shervinemami | 1:c6659c8882c9 | 64 | const float FINGER4_PRESS = 0.37f; // |
shervinemami | 1:c6659c8882c9 | 65 | |
shervinemami | 1:c6659c8882c9 | 66 | const float FINGER1_RELEASE = 0.35f; // Set how much the person needs to release their finger to finish a keypress. |
shervinemami | 1:c6659c8882c9 | 67 | const float FINGER2_RELEASE = 0.35f; // Note that each finger is slightly different strength, due to the mechanical design. |
shervinemami | 1:c6659c8882c9 | 68 | const float FINGER3_RELEASE = 0.34f; // |
shervinemami | 1:c6659c8882c9 | 69 | const float FINGER4_RELEASE = 0.34f; // |
shervinemami | 1:c6659c8882c9 | 70 | |
shervinemami | 1:c6659c8882c9 | 71 | const float BATTERY_NEEDS_CHARGE = 0.198f; // 0.20 means >= 3.4V, 0.19 means >= 2.4V. |
shervinemami | 1:c6659c8882c9 | 72 | |
shervinemami | 1:c6659c8882c9 | 73 | |
YuuichiAkagawa | 0:3435302551b3 | 74 | /* mbed Microcontroller Library |
YuuichiAkagawa | 0:3435302551b3 | 75 | * Copyright (c) 2015 ARM Limited |
YuuichiAkagawa | 0:3435302551b3 | 76 | * |
YuuichiAkagawa | 0:3435302551b3 | 77 | * Licensed under the Apache License, Version 2.0 (the "License"); |
YuuichiAkagawa | 0:3435302551b3 | 78 | * you may not use this file except in compliance with the License. |
YuuichiAkagawa | 0:3435302551b3 | 79 | * You may obtain a copy of the License at |
YuuichiAkagawa | 0:3435302551b3 | 80 | * |
YuuichiAkagawa | 0:3435302551b3 | 81 | * http://www.apache.org/licenses/LICENSE-2.0 |
YuuichiAkagawa | 0:3435302551b3 | 82 | * |
YuuichiAkagawa | 0:3435302551b3 | 83 | * Unless required by applicable law or agreed to in writing, software |
YuuichiAkagawa | 0:3435302551b3 | 84 | * distributed under the License is distributed on an "AS IS" BASIS, |
YuuichiAkagawa | 0:3435302551b3 | 85 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
YuuichiAkagawa | 0:3435302551b3 | 86 | * See the License for the specific language governing permissions and |
YuuichiAkagawa | 0:3435302551b3 | 87 | * limitations under the License. |
YuuichiAkagawa | 0:3435302551b3 | 88 | */ |
YuuichiAkagawa | 0:3435302551b3 | 89 | |
YuuichiAkagawa | 0:3435302551b3 | 90 | #include "mbed.h" |
YuuichiAkagawa | 0:3435302551b3 | 91 | |
YuuichiAkagawa | 0:3435302551b3 | 92 | #include "ble/BLE.h" |
YuuichiAkagawa | 0:3435302551b3 | 93 | #include "KeyboardService.h" |
YuuichiAkagawa | 0:3435302551b3 | 94 | |
YuuichiAkagawa | 0:3435302551b3 | 95 | #include "examples_common.h" |
shervinemami | 1:c6659c8882c9 | 96 | |
shervinemami | 1:c6659c8882c9 | 97 | |
shervinemami | 1:c6659c8882c9 | 98 | |
shervinemami | 1:c6659c8882c9 | 99 | #undef HID_DEBUG |
shervinemami | 1:c6659c8882c9 | 100 | #undef LOG |
shervinemami | 1:c6659c8882c9 | 101 | #ifdef LOG_MESSAGES |
shervinemami | 1:c6659c8882c9 | 102 | #define LOG(...) { pc.printf(__VA_ARGS__); } |
shervinemami | 1:c6659c8882c9 | 103 | Serial pc(UART_TX, UART_RX); |
shervinemami | 1:c6659c8882c9 | 104 | #else |
shervinemami | 1:c6659c8882c9 | 105 | #define LOG(...) |
shervinemami | 1:c6659c8882c9 | 106 | #endif |
shervinemami | 1:c6659c8882c9 | 107 | #define HID_DEBUG LOG |
shervinemami | 1:c6659c8882c9 | 108 | |
shervinemami | 1:c6659c8882c9 | 109 | |
shervinemami | 1:c6659c8882c9 | 110 | AnalogIn battery(BATTERY_PIN); // For measuring the battery level |
shervinemami | 1:c6659c8882c9 | 111 | AnalogIn finger1(FINGER1_PIN); // For measuring a finger level |
shervinemami | 1:c6659c8882c9 | 112 | AnalogIn finger2(FINGER2_PIN); // |
shervinemami | 1:c6659c8882c9 | 113 | AnalogIn finger3(FINGER3_PIN); // |
shervinemami | 1:c6659c8882c9 | 114 | AnalogIn finger4(FINGER4_PIN); // |
shervinemami | 1:c6659c8882c9 | 115 | DigitalOut waiting_led(LED_RED); // For showing BLE is trying to connect |
shervinemami | 1:c6659c8882c9 | 116 | DigitalOut connected_led(LED_GREEN); // For showing BLE is connected |
shervinemami | 1:c6659c8882c9 | 117 | DigitalOut status_led(LED_BLUE); // For showing BLE is busy |
shervinemami | 1:c6659c8882c9 | 118 | DigitalOut enable_out3v3(OUT3V3_PIN); // For using OUT_3V3 pin of TinyBLE |
shervinemami | 1:c6659c8882c9 | 119 | |
shervinemami | 1:c6659c8882c9 | 120 | #define LED_ON 0 // LEDs on Tiny BLE need 0V to light up. |
shervinemami | 1:c6659c8882c9 | 121 | #define LED_OFF 1 // |
shervinemami | 1:c6659c8882c9 | 122 | |
shervinemami | 1:c6659c8882c9 | 123 | |
shervinemami | 1:c6659c8882c9 | 124 | bool haveAskedForRecharge = false; // Only ask for a recharge once per poweron. Requires user to turn device off once per day! |
shervinemami | 1:c6659c8882c9 | 125 | |
shervinemami | 1:c6659c8882c9 | 126 | |
shervinemami | 1:c6659c8882c9 | 127 | InterruptIn button1(BUTTON_PIN); // For sending a BLE command |
YuuichiAkagawa | 0:3435302551b3 | 128 | |
YuuichiAkagawa | 0:3435302551b3 | 129 | BLE ble; |
YuuichiAkagawa | 0:3435302551b3 | 130 | KeyboardService *kbdServicePtr; |
YuuichiAkagawa | 0:3435302551b3 | 131 | |
shervinemami | 1:c6659c8882c9 | 132 | static const char DEVICE_NAME[] = "ShervFingerControl"; |
shervinemami | 1:c6659c8882c9 | 133 | static const char SHORT_DEVICE_NAME[] = "ShFingerCtl"; |
shervinemami | 1:c6659c8882c9 | 134 | |
shervinemami | 1:c6659c8882c9 | 135 | |
shervinemami | 1:c6659c8882c9 | 136 | // Status flags that are updated in ISR callback functions. |
shervinemami | 1:c6659c8882c9 | 137 | volatile bool check_fingers = false; |
shervinemami | 1:c6659c8882c9 | 138 | volatile bool press_keyup[5] = {false}; |
shervinemami | 1:c6659c8882c9 | 139 | |
shervinemami | 1:c6659c8882c9 | 140 | |
shervinemami | 1:c6659c8882c9 | 141 | |
YuuichiAkagawa | 0:3435302551b3 | 142 | static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) |
YuuichiAkagawa | 0:3435302551b3 | 143 | { |
shervinemami | 1:c6659c8882c9 | 144 | HID_DEBUG("discon\n\r"); |
shervinemami | 1:c6659c8882c9 | 145 | waiting_led = LED_ON; |
shervinemami | 1:c6659c8882c9 | 146 | connected_led = LED_OFF; |
YuuichiAkagawa | 0:3435302551b3 | 147 | |
YuuichiAkagawa | 0:3435302551b3 | 148 | ble.gap().startAdvertising(); // restart advertising |
YuuichiAkagawa | 0:3435302551b3 | 149 | } |
YuuichiAkagawa | 0:3435302551b3 | 150 | |
YuuichiAkagawa | 0:3435302551b3 | 151 | static void onConnect(const Gap::ConnectionCallbackParams_t *params) |
YuuichiAkagawa | 0:3435302551b3 | 152 | { |
shervinemami | 1:c6659c8882c9 | 153 | HID_DEBUG("conn\n\r"); |
shervinemami | 1:c6659c8882c9 | 154 | waiting_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 155 | connected_led = LED_ON; |
YuuichiAkagawa | 0:3435302551b3 | 156 | } |
shervinemami | 1:c6659c8882c9 | 157 | |
shervinemami | 1:c6659c8882c9 | 158 | |
shervinemami | 1:c6659c8882c9 | 159 | |
shervinemami | 1:c6659c8882c9 | 160 | void send_keypress(int keycode, int finger) { |
shervinemami | 1:c6659c8882c9 | 161 | if (!kbdServicePtr) |
shervinemami | 1:c6659c8882c9 | 162 | return; |
YuuichiAkagawa | 0:3435302551b3 | 163 | |
shervinemami | 1:c6659c8882c9 | 164 | if (!kbdServicePtr->isConnected()) { |
shervinemami | 1:c6659c8882c9 | 165 | HID_DEBUG("no conn yet\n\r"); |
shervinemami | 1:c6659c8882c9 | 166 | } else { |
shervinemami | 1:c6659c8882c9 | 167 | //LOG("send_keypress(%d, %d)\n\r", keycode, finger); |
shervinemami | 1:c6659c8882c9 | 168 | kbdServicePtr->keyDownCode(keycode, 0); |
shervinemami | 1:c6659c8882c9 | 169 | press_keyup[finger] = true; |
shervinemami | 1:c6659c8882c9 | 170 | |
shervinemami | 1:c6659c8882c9 | 171 | } |
YuuichiAkagawa | 0:3435302551b3 | 172 | } |
shervinemami | 1:c6659c8882c9 | 173 | |
YuuichiAkagawa | 0:3435302551b3 | 174 | void send_string(const char * c) { |
YuuichiAkagawa | 0:3435302551b3 | 175 | if (!kbdServicePtr) |
YuuichiAkagawa | 0:3435302551b3 | 176 | return; |
YuuichiAkagawa | 0:3435302551b3 | 177 | |
YuuichiAkagawa | 0:3435302551b3 | 178 | if (!kbdServicePtr->isConnected()) { |
shervinemami | 1:c6659c8882c9 | 179 | HID_DEBUG("no conn yet\n\r"); |
YuuichiAkagawa | 0:3435302551b3 | 180 | } else { |
YuuichiAkagawa | 0:3435302551b3 | 181 | int len = strlen(c); |
YuuichiAkagawa | 0:3435302551b3 | 182 | kbdServicePtr->printf(c); |
shervinemami | 1:c6659c8882c9 | 183 | HID_DEBUG("sending %d chars\n\r", len); |
YuuichiAkagawa | 0:3435302551b3 | 184 | } |
YuuichiAkagawa | 0:3435302551b3 | 185 | } |
shervinemami | 1:c6659c8882c9 | 186 | |
shervinemami | 1:c6659c8882c9 | 187 | |
shervinemami | 1:c6659c8882c9 | 188 | // Call the button1_ISR function whenever the pushbutton is pressed. |
shervinemami | 1:c6659c8882c9 | 189 | // Make sure there isn't anything slow like printf in this ISR! |
shervinemami | 1:c6659c8882c9 | 190 | void button1_ISR() { |
shervinemami | 1:c6659c8882c9 | 191 | send_string("x\n"); |
shervinemami | 1:c6659c8882c9 | 192 | } |
shervinemami | 1:c6659c8882c9 | 193 | |
shervinemami | 1:c6659c8882c9 | 194 | |
shervinemami | 1:c6659c8882c9 | 195 | // ISR callback function that is automatically called every 0.1 seconds or so. |
shervinemami | 1:c6659c8882c9 | 196 | // Make sure there isn't anything slow like printf in this ISR! |
shervinemami | 1:c6659c8882c9 | 197 | static void heartbeat_ISR() { |
shervinemami | 1:c6659c8882c9 | 198 | if (!kbdServicePtr->isConnected()) |
shervinemami | 1:c6659c8882c9 | 199 | waiting_led = !waiting_led; |
shervinemami | 1:c6659c8882c9 | 200 | else { |
shervinemami | 1:c6659c8882c9 | 201 | //connected_led = !connected_led; |
shervinemami | 1:c6659c8882c9 | 202 | //waiting_led = 0; |
shervinemami | 1:c6659c8882c9 | 203 | } |
shervinemami | 1:c6659c8882c9 | 204 | |
shervinemami | 1:c6659c8882c9 | 205 | // Signal that we should check the finger sensors soon. |
shervinemami | 1:c6659c8882c9 | 206 | check_fingers = true; |
shervinemami | 1:c6659c8882c9 | 207 | } |
YuuichiAkagawa | 0:3435302551b3 | 208 | |
YuuichiAkagawa | 0:3435302551b3 | 209 | |
YuuichiAkagawa | 0:3435302551b3 | 210 | int main() |
YuuichiAkagawa | 0:3435302551b3 | 211 | { |
shervinemami | 1:c6659c8882c9 | 212 | #ifdef LOG_MESSAGES |
shervinemami | 1:c6659c8882c9 | 213 | pc.baud(115200); // Use fast UART for log messages instead of default 9600 bps. |
shervinemami | 1:c6659c8882c9 | 214 | #endif |
shervinemami | 1:c6659c8882c9 | 215 | |
shervinemami | 1:c6659c8882c9 | 216 | waiting_led = LED_OFF; // Set LEDs to blue, until ready. |
shervinemami | 1:c6659c8882c9 | 217 | connected_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 218 | status_led = LED_ON; |
shervinemami | 1:c6659c8882c9 | 219 | |
shervinemami | 1:c6659c8882c9 | 220 | wait(1); |
shervinemami | 1:c6659c8882c9 | 221 | LOG("---- Shervin's Finger Input device, using TinyBLE + BLE HID keyboard service ----\n\r"); |
shervinemami | 1:c6659c8882c9 | 222 | |
shervinemami | 1:c6659c8882c9 | 223 | // Call the button1_ISR function whenever the pushbutton is pressed. |
shervinemami | 1:c6659c8882c9 | 224 | button1.rise(button1_ISR); |
YuuichiAkagawa | 0:3435302551b3 | 225 | |
shervinemami | 1:c6659c8882c9 | 226 | HID_DEBUG("initialising ticker\n\r"); |
shervinemami | 1:c6659c8882c9 | 227 | |
shervinemami | 1:c6659c8882c9 | 228 | // Call the heartbeat_ISR function every 0.1 seconds |
shervinemami | 1:c6659c8882c9 | 229 | Ticker heartbeat; |
shervinemami | 1:c6659c8882c9 | 230 | heartbeat.attach(heartbeat_ISR, 0.1f); |
shervinemami | 1:c6659c8882c9 | 231 | |
shervinemami | 1:c6659c8882c9 | 232 | HID_DEBUG("enabling finger sensors\n\r"); |
shervinemami | 1:c6659c8882c9 | 233 | enable_out3v3 = 1; |
YuuichiAkagawa | 0:3435302551b3 | 234 | |
shervinemami | 1:c6659c8882c9 | 235 | HID_DEBUG("initialising ble\n\r"); |
YuuichiAkagawa | 0:3435302551b3 | 236 | ble.init(); |
YuuichiAkagawa | 0:3435302551b3 | 237 | |
YuuichiAkagawa | 0:3435302551b3 | 238 | ble.gap().onDisconnection(onDisconnect); |
YuuichiAkagawa | 0:3435302551b3 | 239 | ble.gap().onConnection(onConnect); |
YuuichiAkagawa | 0:3435302551b3 | 240 | |
YuuichiAkagawa | 0:3435302551b3 | 241 | initializeSecurity(ble); |
YuuichiAkagawa | 0:3435302551b3 | 242 | |
shervinemami | 1:c6659c8882c9 | 243 | HID_DEBUG("adding hid service\n\r"); |
YuuichiAkagawa | 0:3435302551b3 | 244 | KeyboardService kbdService(ble); |
YuuichiAkagawa | 0:3435302551b3 | 245 | kbdServicePtr = &kbdService; |
YuuichiAkagawa | 0:3435302551b3 | 246 | |
shervinemami | 1:c6659c8882c9 | 247 | HID_DEBUG("adding device info and battery service\n\r"); |
YuuichiAkagawa | 0:3435302551b3 | 248 | initializeHOGP(ble); |
YuuichiAkagawa | 0:3435302551b3 | 249 | |
shervinemami | 1:c6659c8882c9 | 250 | HID_DEBUG("setting up gap\n\r"); |
YuuichiAkagawa | 0:3435302551b3 | 251 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD); |
YuuichiAkagawa | 0:3435302551b3 | 252 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, |
YuuichiAkagawa | 0:3435302551b3 | 253 | (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
YuuichiAkagawa | 0:3435302551b3 | 254 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
YuuichiAkagawa | 0:3435302551b3 | 255 | (uint8_t *)SHORT_DEVICE_NAME, sizeof(SHORT_DEVICE_NAME)); |
YuuichiAkagawa | 0:3435302551b3 | 256 | |
shervinemami | 1:c6659c8882c9 | 257 | HID_DEBUG("advertising\n\r"); |
YuuichiAkagawa | 0:3435302551b3 | 258 | ble.gap().startAdvertising(); |
shervinemami | 1:c6659c8882c9 | 259 | |
shervinemami | 1:c6659c8882c9 | 260 | // Turn LEDs to green connected. |
shervinemami | 1:c6659c8882c9 | 261 | connected_led = LED_ON; |
shervinemami | 1:c6659c8882c9 | 262 | waiting_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 263 | status_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 264 | |
shervinemami | 1:c6659c8882c9 | 265 | // Run forever ... |
shervinemami | 1:c6659c8882c9 | 266 | int counter1 = 0; |
shervinemami | 1:c6659c8882c9 | 267 | int counter2 = 0; |
YuuichiAkagawa | 0:3435302551b3 | 268 | while (true) { |
YuuichiAkagawa | 0:3435302551b3 | 269 | ble.waitForEvent(); |
shervinemami | 1:c6659c8882c9 | 270 | |
shervinemami | 1:c6659c8882c9 | 271 | // Signal that we should check the finger sensors soon. |
shervinemami | 1:c6659c8882c9 | 272 | if (check_fingers) { |
shervinemami | 1:c6659c8882c9 | 273 | check_fingers = false; |
shervinemami | 1:c6659c8882c9 | 274 | |
shervinemami | 1:c6659c8882c9 | 275 | // Measure all the finger sensors and battery level. |
shervinemami | 1:c6659c8882c9 | 276 | float fing1 = finger1.read(); |
shervinemami | 1:c6659c8882c9 | 277 | float fing2 = finger2.read(); |
shervinemami | 1:c6659c8882c9 | 278 | float fing3 = finger3.read(); |
shervinemami | 1:c6659c8882c9 | 279 | float fing4 = finger4.read(); |
shervinemami | 1:c6659c8882c9 | 280 | float batt = battery.read(); |
shervinemami | 1:c6659c8882c9 | 281 | |
shervinemami | 1:c6659c8882c9 | 282 | // If a finger was pressed and now has been released, send the keyUp event soon after. |
shervinemami | 1:c6659c8882c9 | 283 | if (press_keyup[1] && fing1 < FINGER1_RELEASE) { |
shervinemami | 1:c6659c8882c9 | 284 | press_keyup[1] = false; // Clear the flag |
shervinemami | 1:c6659c8882c9 | 285 | kbdServicePtr->keyUpCode(); |
shervinemami | 1:c6659c8882c9 | 286 | HID_DEBUG("sent key up for 1.\n\r"); |
shervinemami | 1:c6659c8882c9 | 287 | } |
shervinemami | 1:c6659c8882c9 | 288 | if (press_keyup[2] && fing2 < FINGER2_RELEASE) { |
shervinemami | 1:c6659c8882c9 | 289 | press_keyup[2] = false; // Clear the flag |
shervinemami | 1:c6659c8882c9 | 290 | send_keypress(FING2UP_KEYCODE, 2); |
shervinemami | 1:c6659c8882c9 | 291 | HID_DEBUG("sent final key down for 2.\n\r"); |
shervinemami | 1:c6659c8882c9 | 292 | ble.waitForEvent(); // Add a slight delay |
shervinemami | 1:c6659c8882c9 | 293 | //wait(0.1); // Add a slight delay |
shervinemami | 1:c6659c8882c9 | 294 | //ble.waitForEvent(); // Add a slight delay |
shervinemami | 1:c6659c8882c9 | 295 | kbdServicePtr->keyUpCode(); |
shervinemami | 1:c6659c8882c9 | 296 | HID_DEBUG("sent final key up for 2.\n\r"); |
shervinemami | 1:c6659c8882c9 | 297 | press_keyup[2] = false; // Clear the flag |
shervinemami | 1:c6659c8882c9 | 298 | } |
shervinemami | 1:c6659c8882c9 | 299 | if (press_keyup[3] && fing3 < FINGER3_RELEASE) { |
shervinemami | 1:c6659c8882c9 | 300 | press_keyup[3] = false; // Clear the flag |
shervinemami | 1:c6659c8882c9 | 301 | kbdServicePtr->keyUpCode(); |
shervinemami | 1:c6659c8882c9 | 302 | HID_DEBUG("sent key up for 3.\n\r"); |
shervinemami | 1:c6659c8882c9 | 303 | } |
shervinemami | 1:c6659c8882c9 | 304 | if (press_keyup[4] && fing4 < FINGER4_RELEASE) { |
shervinemami | 1:c6659c8882c9 | 305 | press_keyup[4] = false; // Clear the flag |
shervinemami | 1:c6659c8882c9 | 306 | kbdServicePtr->keyUpCode(); |
shervinemami | 1:c6659c8882c9 | 307 | HID_DEBUG("sent key up for 4.\n\r"); |
shervinemami | 1:c6659c8882c9 | 308 | } |
shervinemami | 1:c6659c8882c9 | 309 | |
shervinemami | 1:c6659c8882c9 | 310 | |
shervinemami | 1:c6659c8882c9 | 311 | // Very occasionally, show the connected LED |
shervinemami | 1:c6659c8882c9 | 312 | counter1++; |
shervinemami | 1:c6659c8882c9 | 313 | if (counter1 == 1) { |
shervinemami | 1:c6659c8882c9 | 314 | if (kbdServicePtr->isConnected()) { |
shervinemami | 1:c6659c8882c9 | 315 | connected_led = LED_ON; |
shervinemami | 1:c6659c8882c9 | 316 | waiting_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 317 | } |
shervinemami | 1:c6659c8882c9 | 318 | } |
shervinemami | 1:c6659c8882c9 | 319 | if (counter1 == 2) { |
shervinemami | 1:c6659c8882c9 | 320 | //counter2 = 0; |
shervinemami | 1:c6659c8882c9 | 321 | connected_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 322 | waiting_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 323 | } |
shervinemami | 1:c6659c8882c9 | 324 | |
shervinemami | 1:c6659c8882c9 | 325 | |
shervinemami | 1:c6659c8882c9 | 326 | // Occasionally show some debug info |
shervinemami | 1:c6659c8882c9 | 327 | if (counter1 > 15) { |
shervinemami | 1:c6659c8882c9 | 328 | //counter2++; |
shervinemami | 1:c6659c8882c9 | 329 | LOG("%.2f%. F1=%.2f, F2=%.2f, F3=%.2f, F4=%.2f\n\r", batt, fing1, fing2, fing3, fing4); |
shervinemami | 1:c6659c8882c9 | 330 | |
shervinemami | 1:c6659c8882c9 | 331 | // Check for low battery |
shervinemami | 1:c6659c8882c9 | 332 | if (batt < BATTERY_NEEDS_CHARGE) { |
shervinemami | 1:c6659c8882c9 | 333 | // Toggle blue LED |
shervinemami | 1:c6659c8882c9 | 334 | waiting_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 335 | connected_led = LED_OFF; |
shervinemami | 1:c6659c8882c9 | 336 | status_led = !status_led; |
shervinemami | 1:c6659c8882c9 | 337 | if (!haveAskedForRecharge) { |
shervinemami | 1:c6659c8882c9 | 338 | send_string("RECHARGE BATTERY!"); |
shervinemami | 1:c6659c8882c9 | 339 | haveAskedForRecharge = true; |
shervinemami | 1:c6659c8882c9 | 340 | } |
shervinemami | 1:c6659c8882c9 | 341 | LOG("RECHARGE BATTERY!\n\r"); |
shervinemami | 1:c6659c8882c9 | 342 | } |
shervinemami | 1:c6659c8882c9 | 343 | //else { |
shervinemami | 1:c6659c8882c9 | 344 | //} |
shervinemami | 1:c6659c8882c9 | 345 | counter1 = 0; |
shervinemami | 1:c6659c8882c9 | 346 | } |
shervinemami | 1:c6659c8882c9 | 347 | |
shervinemami | 1:c6659c8882c9 | 348 | // Check if a finger was pressed |
shervinemami | 1:c6659c8882c9 | 349 | if (fing1 > FINGER1_PRESS && !press_keyup[1]) { |
shervinemami | 1:c6659c8882c9 | 350 | send_keypress(FING1_KEYCODE, 1); |
shervinemami | 1:c6659c8882c9 | 351 | HID_DEBUG("sent keypress %d for 1.\n\r", FING1_KEYCODE); |
shervinemami | 1:c6659c8882c9 | 352 | //counter2+=20; |
shervinemami | 1:c6659c8882c9 | 353 | //LOG("%d\n\r", counter2); |
shervinemami | 1:c6659c8882c9 | 354 | } |
shervinemami | 1:c6659c8882c9 | 355 | if (fing2 > FINGER2_PRESS && !press_keyup[2]) { |
shervinemami | 1:c6659c8882c9 | 356 | send_keypress(FING2DOWN_KEYCODE, 2); |
shervinemami | 1:c6659c8882c9 | 357 | HID_DEBUG("sent keypress %d for 2.\n\r", FING2DOWN_KEYCODE); |
shervinemami | 1:c6659c8882c9 | 358 | // Finger 2 is treated differently. We want to be able to hold down finger 2 |
shervinemami | 1:c6659c8882c9 | 359 | // Without causing repeated keystrokes, so we will send an up press straight after the down press, |
shervinemami | 1:c6659c8882c9 | 360 | // and a different key down and up when the fingure is released, so the client software can |
shervinemami | 1:c6659c8882c9 | 361 | // figure out the duration that it was held for. |
shervinemami | 1:c6659c8882c9 | 362 | ble.waitForEvent(); // Add a slight delay |
shervinemami | 1:c6659c8882c9 | 363 | //wait(0.1); // Add a slight delay |
shervinemami | 1:c6659c8882c9 | 364 | //ble.waitForEvent(); // Add a slight delay |
shervinemami | 1:c6659c8882c9 | 365 | kbdServicePtr->keyUpCode(); |
shervinemami | 1:c6659c8882c9 | 366 | HID_DEBUG("sent initial key up for 2.\n\r"); |
shervinemami | 1:c6659c8882c9 | 367 | } |
shervinemami | 1:c6659c8882c9 | 368 | if (fing3 > FINGER3_PRESS && !press_keyup[3]) { |
shervinemami | 1:c6659c8882c9 | 369 | send_keypress(FING3_KEYCODE, 3); |
shervinemami | 1:c6659c8882c9 | 370 | HID_DEBUG("sent keypress %d for 3.\n\r", FING3_KEYCODE); |
shervinemami | 1:c6659c8882c9 | 371 | //counter2++; |
shervinemami | 1:c6659c8882c9 | 372 | //send_keypress(counter2, 3); |
shervinemami | 1:c6659c8882c9 | 373 | //LOG("%d\n\r", counter2); |
shervinemami | 1:c6659c8882c9 | 374 | } |
shervinemami | 1:c6659c8882c9 | 375 | if (fing4 > FINGER4_PRESS && !press_keyup[4]) { |
shervinemami | 1:c6659c8882c9 | 376 | send_keypress(FING4_KEYCODE, 4); |
shervinemami | 1:c6659c8882c9 | 377 | HID_DEBUG("sent keypress %d for 4.\n\r", FING4_KEYCODE); |
shervinemami | 1:c6659c8882c9 | 378 | //counter2--; |
shervinemami | 1:c6659c8882c9 | 379 | //send_keypress(counter2, 4); |
shervinemami | 1:c6659c8882c9 | 380 | //LOG("%d\n\r", counter2); |
shervinemami | 1:c6659c8882c9 | 381 | |
shervinemami | 1:c6659c8882c9 | 382 | } |
shervinemami | 1:c6659c8882c9 | 383 | } |
YuuichiAkagawa | 0:3435302551b3 | 384 | } |
shervinemami | 1:c6659c8882c9 | 385 | } |