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 Yuuichi Akagawa

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?

UserRevisionLine numberNew 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 }