BLE switch interface with GROVE joystic for micro:bit http://mahoro-ba.net/e2073.html
main.cpp@0:28fb3e9ef81a, 2018-09-17 (annotated)
- Committer:
- masakjm
- Date:
- Mon Sep 17 02:48:51 2018 +0000
- Revision:
- 0:28fb3e9ef81a
- Child:
- 1:3b9ae1dbcdcf
first release
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
masakjm | 0:28fb3e9ef81a | 1 | //================================= |
masakjm | 0:28fb3e9ef81a | 2 | // microbit_switch_if_3sw |
masakjm | 0:28fb3e9ef81a | 3 | //================================= |
masakjm | 0:28fb3e9ef81a | 4 | // BLE switch interface with 3 tact switches for micro:bit |
masakjm | 0:28fb3e9ef81a | 5 | // It is intended for use with ios devices. |
masakjm | 0:28fb3e9ef81a | 6 | // |
masakjm | 0:28fb3e9ef81a | 7 | // The MIT License (MIT) Copyright (c) 2018 Masatomo Kojima |
masakjm | 0:28fb3e9ef81a | 8 | // |
masakjm | 0:28fb3e9ef81a | 9 | // LED message |
masakjm | 0:28fb3e9ef81a | 10 | // S key code setting sw1,2 |
masakjm | 0:28fb3e9ef81a | 11 | // T key code setting sw3 |
masakjm | 0:28fb3e9ef81a | 12 | // W Waiting |
masakjm | 0:28fb3e9ef81a | 13 | // C Conected |
masakjm | 0:28fb3e9ef81a | 14 | // P success Pearing |
masakjm | 0:28fb3e9ef81a | 15 | // F Fail pearing |
masakjm | 0:28fb3e9ef81a | 16 | // E Error at sending data by ble |
masakjm | 0:28fb3e9ef81a | 17 | // e Error at writting data to flash memory |
masakjm | 0:28fb3e9ef81a | 18 | // I Error by Incorrect cording |
masakjm | 0:28fb3e9ef81a | 19 | // |
masakjm | 0:28fb3e9ef81a | 20 | // Please refer to the following site. (Japanese only) |
masakjm | 0:28fb3e9ef81a | 21 | // http://mahoro-ba.net/e2036.html |
masakjm | 0:28fb3e9ef81a | 22 | // http://mahoro-ba.net/e2038.html |
masakjm | 0:28fb3e9ef81a | 23 | // |
masakjm | 0:28fb3e9ef81a | 24 | // I refer to information written on the following sites. |
masakjm | 0:28fb3e9ef81a | 25 | // (1)https://os.mbed.com/teams/microbit/code/microbit_presenter/ |
masakjm | 0:28fb3e9ef81a | 26 | // Licensed under the Apache License, Version 2.0 |
masakjm | 0:28fb3e9ef81a | 27 | // |
masakjm | 0:28fb3e9ef81a | 28 | // (2)https://lancaster-university.github.io/microbit-docs/ |
masakjm | 0:28fb3e9ef81a | 29 | // The MIT License (MIT) |
masakjm | 0:28fb3e9ef81a | 30 | // Copyright (c) 2016 British Broadcasting Corporation. |
masakjm | 0:28fb3e9ef81a | 31 | // |
masakjm | 0:28fb3e9ef81a | 32 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 33 | |
masakjm | 0:28fb3e9ef81a | 34 | #define VERSION "3SW-180917" |
masakjm | 0:28fb3e9ef81a | 35 | //#define NO_DEBUG |
masakjm | 0:28fb3e9ef81a | 36 | |
masakjm | 0:28fb3e9ef81a | 37 | #include "microbit_switch_if.h" |
masakjm | 0:28fb3e9ef81a | 38 | #include "KeyValueInt.h" |
masakjm | 0:28fb3e9ef81a | 39 | |
masakjm | 0:28fb3e9ef81a | 40 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 41 | // Display |
masakjm | 0:28fb3e9ef81a | 42 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 43 | MicroBitDisplay display; |
masakjm | 0:28fb3e9ef81a | 44 | int state; // 状態遷移 |
masakjm | 0:28fb3e9ef81a | 45 | char dispChar = 0; // LEDに表示する文字コード |
masakjm | 0:28fb3e9ef81a | 46 | char dispCharLast = 0; // 最後に表示した文字コード |
masakjm | 0:28fb3e9ef81a | 47 | bool turnOffMode = false; // LED非表示モードのフラグ |
masakjm | 0:28fb3e9ef81a | 48 | |
masakjm | 0:28fb3e9ef81a | 49 | //----- 数値の表示 |
masakjm | 0:28fb3e9ef81a | 50 | static void displayNumber(int data) |
masakjm | 0:28fb3e9ef81a | 51 | { |
masakjm | 0:28fb3e9ef81a | 52 | if (0<=data && data<=9) { // 1桁はスクロールしない |
masakjm | 0:28fb3e9ef81a | 53 | display.print(data); |
masakjm | 0:28fb3e9ef81a | 54 | } else { |
masakjm | 0:28fb3e9ef81a | 55 | display.scroll(data); |
masakjm | 0:28fb3e9ef81a | 56 | } |
masakjm | 0:28fb3e9ef81a | 57 | } |
masakjm | 0:28fb3e9ef81a | 58 | |
masakjm | 0:28fb3e9ef81a | 59 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 60 | // Flash Memory |
masakjm | 0:28fb3e9ef81a | 61 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 62 | |
masakjm | 0:28fb3e9ef81a | 63 | //----- 不揮発メモリの読み出し |
masakjm | 0:28fb3e9ef81a | 64 | static int FlashGet(MicroBitStorage storage, const char* key, int init=0) |
masakjm | 0:28fb3e9ef81a | 65 | { |
masakjm | 0:28fb3e9ef81a | 66 | KeyValuePair* kvp = storage.get(key); |
masakjm | 0:28fb3e9ef81a | 67 | if(kvp != NULL) { |
masakjm | 0:28fb3e9ef81a | 68 | int data; |
masakjm | 0:28fb3e9ef81a | 69 | memcpy(&data, kvp->value, sizeof(int)); |
masakjm | 0:28fb3e9ef81a | 70 | DEBUG("== FlashGet exist %s = %d\r\n", key, data); |
masakjm | 0:28fb3e9ef81a | 71 | return data; |
masakjm | 0:28fb3e9ef81a | 72 | } |
masakjm | 0:28fb3e9ef81a | 73 | return init; |
masakjm | 0:28fb3e9ef81a | 74 | } |
masakjm | 0:28fb3e9ef81a | 75 | |
masakjm | 0:28fb3e9ef81a | 76 | //----- 不揮発メモリの書き込み |
masakjm | 0:28fb3e9ef81a | 77 | // MICROBIT_OK = 0 |
masakjm | 0:28fb3e9ef81a | 78 | // MICROBIT_INVALID_PARAMETER = -1001, |
masakjm | 0:28fb3e9ef81a | 79 | // MICROBIT_NO_RESOURCES = -1005, |
masakjm | 0:28fb3e9ef81a | 80 | static int FlashPut(MicroBitStorage storage, const char* key, int data) |
masakjm | 0:28fb3e9ef81a | 81 | { |
masakjm | 0:28fb3e9ef81a | 82 | int ret = storage.put(key, (uint8_t *)&data, sizeof(int)); |
masakjm | 0:28fb3e9ef81a | 83 | DEBUG("== FlashPut %s %d %d\r\n", key, data, ret); |
masakjm | 0:28fb3e9ef81a | 84 | return ret; |
masakjm | 0:28fb3e9ef81a | 85 | } |
masakjm | 0:28fb3e9ef81a | 86 | |
masakjm | 0:28fb3e9ef81a | 87 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 88 | // Setting |
masakjm | 0:28fb3e9ef81a | 89 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 90 | bool setting_inc; // 設定値を増加 |
masakjm | 0:28fb3e9ef81a | 91 | bool setting_enter; // 設定値を入力 |
masakjm | 0:28fb3e9ef81a | 92 | bool setting_next; // 次の設定値に移動 |
masakjm | 0:28fb3e9ef81a | 93 | |
masakjm | 0:28fb3e9ef81a | 94 | KeyValueInt kviKeyCode1("keycode1",'S', 1, 1, NUM_GROUP1, true); |
masakjm | 0:28fb3e9ef81a | 95 | KeyValueInt kviKeyCode2("keycode2",'T', 1, 1, NUM_GROUP2, true); |
masakjm | 0:28fb3e9ef81a | 96 | |
masakjm | 0:28fb3e9ef81a | 97 | //----- パラメータ設定 |
masakjm | 0:28fb3e9ef81a | 98 | |
masakjm | 0:28fb3e9ef81a | 99 | static int paraSettingOne(MicroBitStorage storage, KeyValueInt* para, bool change) |
masakjm | 0:28fb3e9ef81a | 100 | { |
masakjm | 0:28fb3e9ef81a | 101 | display.print(para->disp); // 識別文字をLED表示 |
masakjm | 0:28fb3e9ef81a | 102 | wait(SETTING_DISPLAY_WAIT); |
masakjm | 0:28fb3e9ef81a | 103 | displayNumber(para->value); // 値をLED表示 |
masakjm | 0:28fb3e9ef81a | 104 | if (!change) { |
masakjm | 0:28fb3e9ef81a | 105 | wait(SETTING_DISPLAY_WAIT); |
masakjm | 0:28fb3e9ef81a | 106 | return 0; |
masakjm | 0:28fb3e9ef81a | 107 | } |
masakjm | 0:28fb3e9ef81a | 108 | |
masakjm | 0:28fb3e9ef81a | 109 | DEBUG("== paraSetting\r\n"); |
masakjm | 0:28fb3e9ef81a | 110 | setting_inc = false; |
masakjm | 0:28fb3e9ef81a | 111 | setting_next = setting_enter = false; |
masakjm | 0:28fb3e9ef81a | 112 | while( ! setting_next) { // Bボタンが離されるまで |
masakjm | 0:28fb3e9ef81a | 113 | if (setting_inc) { // Aボタンが押されたら |
masakjm | 0:28fb3e9ef81a | 114 | setting_inc = false; |
masakjm | 0:28fb3e9ef81a | 115 | para->inc(); |
masakjm | 0:28fb3e9ef81a | 116 | displayNumber(para->value); |
masakjm | 0:28fb3e9ef81a | 117 | } |
masakjm | 0:28fb3e9ef81a | 118 | wait(0.2); |
masakjm | 0:28fb3e9ef81a | 119 | } |
masakjm | 0:28fb3e9ef81a | 120 | if (FlashPut(storage, para->key, para->value)) { |
masakjm | 0:28fb3e9ef81a | 121 | dispChar = 'e'; |
masakjm | 0:28fb3e9ef81a | 122 | return -1; |
masakjm | 0:28fb3e9ef81a | 123 | } else { |
masakjm | 0:28fb3e9ef81a | 124 | dispChar = 0; |
masakjm | 0:28fb3e9ef81a | 125 | return 0; |
masakjm | 0:28fb3e9ef81a | 126 | } |
masakjm | 0:28fb3e9ef81a | 127 | } |
masakjm | 0:28fb3e9ef81a | 128 | |
masakjm | 0:28fb3e9ef81a | 129 | static void paraSetting(bool change) |
masakjm | 0:28fb3e9ef81a | 130 | { |
masakjm | 0:28fb3e9ef81a | 131 | MicroBitStorage storage; |
masakjm | 0:28fb3e9ef81a | 132 | |
masakjm | 0:28fb3e9ef81a | 133 | kviKeyCode1.set(FlashGet(storage, kviKeyCode1.key, 1)); |
masakjm | 0:28fb3e9ef81a | 134 | kviKeyCode2.set(FlashGet(storage, kviKeyCode2.key, 1)); |
masakjm | 0:28fb3e9ef81a | 135 | int err = paraSettingOne(storage, &kviKeyCode1, change); |
masakjm | 0:28fb3e9ef81a | 136 | if (err) return; |
masakjm | 0:28fb3e9ef81a | 137 | paraSettingOne(storage, &kviKeyCode2, change); |
masakjm | 0:28fb3e9ef81a | 138 | } |
masakjm | 0:28fb3e9ef81a | 139 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 140 | // BLE & HID |
masakjm | 0:28fb3e9ef81a | 141 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 142 | BLE ble; |
masakjm | 0:28fb3e9ef81a | 143 | KeyboardService *kbdServicePtr; |
masakjm | 0:28fb3e9ef81a | 144 | |
masakjm | 0:28fb3e9ef81a | 145 | //----- BLE接続が切断された |
masakjm | 0:28fb3e9ef81a | 146 | static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) |
masakjm | 0:28fb3e9ef81a | 147 | { |
masakjm | 0:28fb3e9ef81a | 148 | DEBUG("(BLE)disconnected\r\n"); |
masakjm | 0:28fb3e9ef81a | 149 | ble.gap().startAdvertising(); // restart advertising |
masakjm | 0:28fb3e9ef81a | 150 | dispChar = 0; |
masakjm | 0:28fb3e9ef81a | 151 | } |
masakjm | 0:28fb3e9ef81a | 152 | |
masakjm | 0:28fb3e9ef81a | 153 | //----- BLE接続された |
masakjm | 0:28fb3e9ef81a | 154 | static void onConnect(const Gap::ConnectionCallbackParams_t *params) |
masakjm | 0:28fb3e9ef81a | 155 | { |
masakjm | 0:28fb3e9ef81a | 156 | if(kbdServicePtr->isConnected()) { |
masakjm | 0:28fb3e9ef81a | 157 | DEBUG("(BLE)connected\r\n"); |
masakjm | 0:28fb3e9ef81a | 158 | dispChar = 'C'; |
masakjm | 0:28fb3e9ef81a | 159 | } |
masakjm | 0:28fb3e9ef81a | 160 | } |
masakjm | 0:28fb3e9ef81a | 161 | |
masakjm | 0:28fb3e9ef81a | 162 | //----- BLE接続待ち状態 |
masakjm | 0:28fb3e9ef81a | 163 | static void waiting() |
masakjm | 0:28fb3e9ef81a | 164 | { |
masakjm | 0:28fb3e9ef81a | 165 | if (!kbdServicePtr->isConnected()) { |
masakjm | 0:28fb3e9ef81a | 166 | dispChar ='W'; |
masakjm | 0:28fb3e9ef81a | 167 | } |
masakjm | 0:28fb3e9ef81a | 168 | } |
masakjm | 0:28fb3e9ef81a | 169 | |
masakjm | 0:28fb3e9ef81a | 170 | //----- パスキー表示 |
masakjm | 0:28fb3e9ef81a | 171 | static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) |
masakjm | 0:28fb3e9ef81a | 172 | { |
masakjm | 0:28fb3e9ef81a | 173 | printf("(BLE)Input passKey: "); |
masakjm | 0:28fb3e9ef81a | 174 | for (unsigned i = 0; i < Gap::ADDR_LEN; i++) { |
masakjm | 0:28fb3e9ef81a | 175 | printf("%c", passkey[i]); |
masakjm | 0:28fb3e9ef81a | 176 | } |
masakjm | 0:28fb3e9ef81a | 177 | printf("\r\n"); |
masakjm | 0:28fb3e9ef81a | 178 | } |
masakjm | 0:28fb3e9ef81a | 179 | |
masakjm | 0:28fb3e9ef81a | 180 | //----- セキュリティ設定完了 |
masakjm | 0:28fb3e9ef81a | 181 | static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) |
masakjm | 0:28fb3e9ef81a | 182 | { |
masakjm | 0:28fb3e9ef81a | 183 | if (status == SecurityManager::SEC_STATUS_SUCCESS) { |
masakjm | 0:28fb3e9ef81a | 184 | // DEBUG("(BLE)Security success %d\r\n", status); |
masakjm | 0:28fb3e9ef81a | 185 | dispChar = 'P'; |
masakjm | 0:28fb3e9ef81a | 186 | |
masakjm | 0:28fb3e9ef81a | 187 | } else { |
masakjm | 0:28fb3e9ef81a | 188 | // DEBUG("(BLE)Security failed %d\r\n", status); |
masakjm | 0:28fb3e9ef81a | 189 | dispChar = 'F'; |
masakjm | 0:28fb3e9ef81a | 190 | } |
masakjm | 0:28fb3e9ef81a | 191 | } |
masakjm | 0:28fb3e9ef81a | 192 | |
masakjm | 0:28fb3e9ef81a | 193 | //----- セキュリティ初期設定 |
masakjm | 0:28fb3e9ef81a | 194 | static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) |
masakjm | 0:28fb3e9ef81a | 195 | { |
masakjm | 0:28fb3e9ef81a | 196 | DEBUG("(BLE)Security setup initiated\r\n"); |
masakjm | 0:28fb3e9ef81a | 197 | } |
masakjm | 0:28fb3e9ef81a | 198 | |
masakjm | 0:28fb3e9ef81a | 199 | //----- セキュリティ初期設定 |
masakjm | 0:28fb3e9ef81a | 200 | static void initializeSecurity(BLE &ble) |
masakjm | 0:28fb3e9ef81a | 201 | { |
masakjm | 0:28fb3e9ef81a | 202 | bool enableBonding = true; |
masakjm | 0:28fb3e9ef81a | 203 | bool requireMITM = HID_SECURITY_REQUIRE_MITM; |
masakjm | 0:28fb3e9ef81a | 204 | |
masakjm | 0:28fb3e9ef81a | 205 | ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback); |
masakjm | 0:28fb3e9ef81a | 206 | ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback); |
masakjm | 0:28fb3e9ef81a | 207 | ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); |
masakjm | 0:28fb3e9ef81a | 208 | |
masakjm | 0:28fb3e9ef81a | 209 | ble.securityManager().init(enableBonding, requireMITM, HID_SECURITY_IOCAPS); |
masakjm | 0:28fb3e9ef81a | 210 | } |
masakjm | 0:28fb3e9ef81a | 211 | |
masakjm | 0:28fb3e9ef81a | 212 | //----- HOGP (HID Over GATT Profile) 初期化 |
masakjm | 0:28fb3e9ef81a | 213 | static void initializeHOGP(BLE &ble) |
masakjm | 0:28fb3e9ef81a | 214 | { |
masakjm | 0:28fb3e9ef81a | 215 | static const uint16_t uuid16_list[] = {GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, |
masakjm | 0:28fb3e9ef81a | 216 | GattService::UUID_DEVICE_INFORMATION_SERVICE, |
masakjm | 0:28fb3e9ef81a | 217 | GattService::UUID_BATTERY_SERVICE |
masakjm | 0:28fb3e9ef81a | 218 | }; |
masakjm | 0:28fb3e9ef81a | 219 | |
masakjm | 0:28fb3e9ef81a | 220 | PnPID_t pnpID; |
masakjm | 0:28fb3e9ef81a | 221 | pnpID.vendorID_source = 0x2; // from the USB Implementer's Forum |
masakjm | 0:28fb3e9ef81a | 222 | pnpID.vendorID = 0x0D28; // NXP |
masakjm | 0:28fb3e9ef81a | 223 | pnpID.productID = 0x0204; // CMSIS-DAP (well, it's a keyboard but oh well) |
masakjm | 0:28fb3e9ef81a | 224 | pnpID.productVersion = 0x0100; // v1.0 |
masakjm | 0:28fb3e9ef81a | 225 | HIDDeviceInformationService deviceInfo(ble, "ARM", "m1", "abc", "def", "ghi", "jkl", &pnpID); |
masakjm | 0:28fb3e9ef81a | 226 | |
masakjm | 0:28fb3e9ef81a | 227 | BatteryService batteryInfo(ble, 80); |
masakjm | 0:28fb3e9ef81a | 228 | |
masakjm | 0:28fb3e9ef81a | 229 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | |
masakjm | 0:28fb3e9ef81a | 230 | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
masakjm | 0:28fb3e9ef81a | 231 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, |
masakjm | 0:28fb3e9ef81a | 232 | (uint8_t *)uuid16_list, sizeof(uuid16_list)); |
masakjm | 0:28fb3e9ef81a | 233 | |
masakjm | 0:28fb3e9ef81a | 234 | // see 5.1.2: HID over GATT Specification (pg. 25) |
masakjm | 0:28fb3e9ef81a | 235 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
masakjm | 0:28fb3e9ef81a | 236 | // 30ms to 50ms is recommended (5.1.2) |
masakjm | 0:28fb3e9ef81a | 237 | ble.gap().setAdvertisingInterval(50); |
masakjm | 0:28fb3e9ef81a | 238 | } |
masakjm | 0:28fb3e9ef81a | 239 | |
masakjm | 0:28fb3e9ef81a | 240 | //----- BLE接続のHID(human interface device) の初期化 |
masakjm | 0:28fb3e9ef81a | 241 | static void initialize_BLE_HID() |
masakjm | 0:28fb3e9ef81a | 242 | { |
masakjm | 0:28fb3e9ef81a | 243 | static const char SHORT_DEVICE_NAME[] = "micro:bit"; |
masakjm | 0:28fb3e9ef81a | 244 | static char DeviceName[20]; |
masakjm | 0:28fb3e9ef81a | 245 | |
masakjm | 0:28fb3e9ef81a | 246 | int id = microbit_serial_number()& 0xfff; // シリアル番号の下12桁を4桁の10進で表示 |
masakjm | 0:28fb3e9ef81a | 247 | sprintf(DeviceName, "micro:bit %04d", id); |
masakjm | 0:28fb3e9ef81a | 248 | DEBUG("(BLE)id %s\r\n", DeviceName); |
masakjm | 0:28fb3e9ef81a | 249 | |
masakjm | 0:28fb3e9ef81a | 250 | // DEBUG("(BLE)initialising ble\r\n"); |
masakjm | 0:28fb3e9ef81a | 251 | ble.init(); |
masakjm | 0:28fb3e9ef81a | 252 | |
masakjm | 0:28fb3e9ef81a | 253 | ble.gap().onDisconnection(onDisconnect); |
masakjm | 0:28fb3e9ef81a | 254 | ble.gap().onConnection(onConnect); |
masakjm | 0:28fb3e9ef81a | 255 | |
masakjm | 0:28fb3e9ef81a | 256 | initializeSecurity(ble); |
masakjm | 0:28fb3e9ef81a | 257 | |
masakjm | 0:28fb3e9ef81a | 258 | DEBUG("(BLE)adding hid service\r\n"); |
masakjm | 0:28fb3e9ef81a | 259 | KeyboardService kbdService(ble); |
masakjm | 0:28fb3e9ef81a | 260 | kbdServicePtr = &kbdService; |
masakjm | 0:28fb3e9ef81a | 261 | |
masakjm | 0:28fb3e9ef81a | 262 | DEBUG("(BLE)adding device info and battery service\r\n"); |
masakjm | 0:28fb3e9ef81a | 263 | initializeHOGP(ble); |
masakjm | 0:28fb3e9ef81a | 264 | |
masakjm | 0:28fb3e9ef81a | 265 | DEBUG("(BLE)setting up gap\r\n"); |
masakjm | 0:28fb3e9ef81a | 266 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD); |
masakjm | 0:28fb3e9ef81a | 267 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, |
masakjm | 0:28fb3e9ef81a | 268 | (uint8_t *)DeviceName, sizeof(DeviceName)); |
masakjm | 0:28fb3e9ef81a | 269 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
masakjm | 0:28fb3e9ef81a | 270 | (uint8_t *)SHORT_DEVICE_NAME, sizeof(SHORT_DEVICE_NAME)); |
masakjm | 0:28fb3e9ef81a | 271 | ble.gap().setDeviceName((const uint8_t *)DeviceName); |
masakjm | 0:28fb3e9ef81a | 272 | |
masakjm | 0:28fb3e9ef81a | 273 | DEBUG("(BLE)advertising\r\n"); |
masakjm | 0:28fb3e9ef81a | 274 | ble.gap().startAdvertising(); |
masakjm | 0:28fb3e9ef81a | 275 | } |
masakjm | 0:28fb3e9ef81a | 276 | |
masakjm | 0:28fb3e9ef81a | 277 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 278 | // Button |
masakjm | 0:28fb3e9ef81a | 279 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 280 | MicroBitMessageBus bus; |
masakjm | 0:28fb3e9ef81a | 281 | MicroBitButton buttonA(MICROBIT_PIN_BUTTON_A, MICROBIT_ID_BUTTON_A); |
masakjm | 0:28fb3e9ef81a | 282 | MicroBitButton buttonB(MICROBIT_PIN_BUTTON_B, MICROBIT_ID_BUTTON_B); |
masakjm | 0:28fb3e9ef81a | 283 | MicroBitButton button0(MICROBIT_PIN_P0, MICROBIT_ID_IO_P0, MICROBIT_BUTTON_ALL_EVENTS, PullUp); |
masakjm | 0:28fb3e9ef81a | 284 | MicroBitButton button1(MICROBIT_PIN_P1, MICROBIT_ID_IO_P1, MICROBIT_BUTTON_ALL_EVENTS, PullUp); |
masakjm | 0:28fb3e9ef81a | 285 | MicroBitButton button2(MICROBIT_PIN_P2, MICROBIT_ID_IO_P2, MICROBIT_BUTTON_ALL_EVENTS, PullUp); |
masakjm | 0:28fb3e9ef81a | 286 | |
masakjm | 0:28fb3e9ef81a | 287 | //----- ボタン押下げ時イベント |
masakjm | 0:28fb3e9ef81a | 288 | static void onButtonDown(MicroBitEvent e) |
masakjm | 0:28fb3e9ef81a | 289 | { |
masakjm | 0:28fb3e9ef81a | 290 | // DEBUG(" Button Down %d state=%d\r\n", e.source, state); |
masakjm | 0:28fb3e9ef81a | 291 | int code = 0; |
masakjm | 0:28fb3e9ef81a | 292 | |
masakjm | 0:28fb3e9ef81a | 293 | switch (state) { |
masakjm | 0:28fb3e9ef81a | 294 | case STATE_SETTING : |
masakjm | 0:28fb3e9ef81a | 295 | switch(e.source) { |
masakjm | 0:28fb3e9ef81a | 296 | case MICROBIT_ID_BUTTON_A : |
masakjm | 0:28fb3e9ef81a | 297 | setting_inc = true; |
masakjm | 0:28fb3e9ef81a | 298 | break; |
masakjm | 0:28fb3e9ef81a | 299 | case MICROBIT_ID_BUTTON_B : |
masakjm | 0:28fb3e9ef81a | 300 | setting_enter = true; |
masakjm | 0:28fb3e9ef81a | 301 | break; |
masakjm | 0:28fb3e9ef81a | 302 | } |
masakjm | 0:28fb3e9ef81a | 303 | break; |
masakjm | 0:28fb3e9ef81a | 304 | case STATE_OPERATING : |
masakjm | 0:28fb3e9ef81a | 305 | switch(e.source) { |
masakjm | 0:28fb3e9ef81a | 306 | case MICROBIT_ID_BUTTON_A : |
masakjm | 0:28fb3e9ef81a | 307 | dispChar = 'A'; |
masakjm | 0:28fb3e9ef81a | 308 | code = keyCodeGroup0[0]; |
masakjm | 0:28fb3e9ef81a | 309 | break; |
masakjm | 0:28fb3e9ef81a | 310 | case MICROBIT_ID_BUTTON_B : |
masakjm | 0:28fb3e9ef81a | 311 | dispChar = 'B'; |
masakjm | 0:28fb3e9ef81a | 312 | code = keyCodeGroup0[1]; |
masakjm | 0:28fb3e9ef81a | 313 | break; |
masakjm | 0:28fb3e9ef81a | 314 | case MICROBIT_ID_IO_P0 : |
masakjm | 0:28fb3e9ef81a | 315 | dispChar = '1'; |
masakjm | 0:28fb3e9ef81a | 316 | code = keyCodeGroup1[kviKeyCode1.value-1][0]; |
masakjm | 0:28fb3e9ef81a | 317 | break; |
masakjm | 0:28fb3e9ef81a | 318 | case MICROBIT_ID_IO_P1 : |
masakjm | 0:28fb3e9ef81a | 319 | dispChar = '2'; |
masakjm | 0:28fb3e9ef81a | 320 | code = keyCodeGroup1[kviKeyCode1.value-1][1]; |
masakjm | 0:28fb3e9ef81a | 321 | break; |
masakjm | 0:28fb3e9ef81a | 322 | case MICROBIT_ID_IO_P2 : |
masakjm | 0:28fb3e9ef81a | 323 | dispChar = '3'; |
masakjm | 0:28fb3e9ef81a | 324 | code = keyCodeGroup2[kviKeyCode2.value-1]; |
masakjm | 0:28fb3e9ef81a | 325 | break; |
masakjm | 0:28fb3e9ef81a | 326 | } |
masakjm | 0:28fb3e9ef81a | 327 | |
masakjm | 0:28fb3e9ef81a | 328 | if (code) { |
masakjm | 0:28fb3e9ef81a | 329 | uint8_t key = code & 0xff; |
masakjm | 0:28fb3e9ef81a | 330 | uint8_t modif = code >> 8; |
masakjm | 0:28fb3e9ef81a | 331 | |
masakjm | 0:28fb3e9ef81a | 332 | if (key > KEYMAP_SIZE ) { |
masakjm | 0:28fb3e9ef81a | 333 | dispChar ='I'; // キーコード設定間違い |
masakjm | 0:28fb3e9ef81a | 334 | } else { |
masakjm | 0:28fb3e9ef81a | 335 | ble_error_t ret = kbdServicePtr->keyDownCode(key, modif); |
masakjm | 0:28fb3e9ef81a | 336 | // DEBUG(" code=%d modif=%d\r\n",key , modif); |
masakjm | 0:28fb3e9ef81a | 337 | if (ret) { |
masakjm | 0:28fb3e9ef81a | 338 | dispChar ='E'; |
masakjm | 0:28fb3e9ef81a | 339 | dispCharLast =0; // E が続く時に表示 |
masakjm | 0:28fb3e9ef81a | 340 | DEBUG("(BLE)Error %d\r\n",ret); |
masakjm | 0:28fb3e9ef81a | 341 | } |
masakjm | 0:28fb3e9ef81a | 342 | } |
masakjm | 0:28fb3e9ef81a | 343 | } |
masakjm | 0:28fb3e9ef81a | 344 | } |
masakjm | 0:28fb3e9ef81a | 345 | } |
masakjm | 0:28fb3e9ef81a | 346 | |
masakjm | 0:28fb3e9ef81a | 347 | //----- ボタン離し時イベント |
masakjm | 0:28fb3e9ef81a | 348 | static void onButtonUp(MicroBitEvent e) |
masakjm | 0:28fb3e9ef81a | 349 | { |
masakjm | 0:28fb3e9ef81a | 350 | // DEBUG(" Button up %d\r\n", e.source); |
masakjm | 0:28fb3e9ef81a | 351 | switch (state) { |
masakjm | 0:28fb3e9ef81a | 352 | case STATE_SETTING : |
masakjm | 0:28fb3e9ef81a | 353 | if(setting_enter) setting_next = true; // 決定ボタンを離したら次へ |
masakjm | 0:28fb3e9ef81a | 354 | break; |
masakjm | 0:28fb3e9ef81a | 355 | case STATE_OPERATING : |
masakjm | 0:28fb3e9ef81a | 356 | dispChar = 0; |
masakjm | 0:28fb3e9ef81a | 357 | ble_error_t ret = kbdServicePtr->keyUpCode(); |
masakjm | 0:28fb3e9ef81a | 358 | if (ret) { |
masakjm | 0:28fb3e9ef81a | 359 | dispChar ='E'; |
masakjm | 0:28fb3e9ef81a | 360 | dispCharLast =0; // E が続く時に表示 |
masakjm | 0:28fb3e9ef81a | 361 | } |
masakjm | 0:28fb3e9ef81a | 362 | } |
masakjm | 0:28fb3e9ef81a | 363 | } |
masakjm | 0:28fb3e9ef81a | 364 | |
masakjm | 0:28fb3e9ef81a | 365 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 366 | // Main |
masakjm | 0:28fb3e9ef81a | 367 | //--------------------------------- |
masakjm | 0:28fb3e9ef81a | 368 | int main() |
masakjm | 0:28fb3e9ef81a | 369 | { |
masakjm | 0:28fb3e9ef81a | 370 | state = STATE_NORMAL; |
masakjm | 0:28fb3e9ef81a | 371 | |
masakjm | 0:28fb3e9ef81a | 372 | wait(0.1); // ボタン状態の更新 |
masakjm | 0:28fb3e9ef81a | 373 | bool bA = buttonA.isPressed(); |
masakjm | 0:28fb3e9ef81a | 374 | bool bB = buttonB.isPressed(); |
masakjm | 0:28fb3e9ef81a | 375 | |
masakjm | 0:28fb3e9ef81a | 376 | if (bA && bB) { // ボタンABを押しながら起動 |
masakjm | 0:28fb3e9ef81a | 377 | while(1) { |
masakjm | 0:28fb3e9ef81a | 378 | display.scroll(VERSION); |
masakjm | 0:28fb3e9ef81a | 379 | wait(0.5); |
masakjm | 0:28fb3e9ef81a | 380 | } |
masakjm | 0:28fb3e9ef81a | 381 | } else if(bA) // ボタンAを押しながら起動 |
masakjm | 0:28fb3e9ef81a | 382 | state = STATE_SETTING; |
masakjm | 0:28fb3e9ef81a | 383 | |
masakjm | 0:28fb3e9ef81a | 384 | //----- Display |
masakjm | 0:28fb3e9ef81a | 385 | display.setDisplayMode(DISPLAY_MODE_BLACK_AND_WHITE); |
masakjm | 0:28fb3e9ef81a | 386 | display.clear(); |
masakjm | 0:28fb3e9ef81a | 387 | Timer dispTime; // 連続表示タイマー |
masakjm | 0:28fb3e9ef81a | 388 | dispTime.start(); |
masakjm | 0:28fb3e9ef81a | 389 | |
masakjm | 0:28fb3e9ef81a | 390 | //----- Button |
masakjm | 0:28fb3e9ef81a | 391 | bus.listen(MICROBIT_ID_ANY, MICROBIT_BUTTON_EVT_DOWN, onButtonDown); |
masakjm | 0:28fb3e9ef81a | 392 | bus.listen(MICROBIT_ID_ANY, MICROBIT_BUTTON_EVT_UP, onButtonUp); |
masakjm | 0:28fb3e9ef81a | 393 | |
masakjm | 0:28fb3e9ef81a | 394 | //----- Setting |
masakjm | 0:28fb3e9ef81a | 395 | paraSetting(state == STATE_SETTING); |
masakjm | 0:28fb3e9ef81a | 396 | state = STATE_OPERATING; |
masakjm | 0:28fb3e9ef81a | 397 | |
masakjm | 0:28fb3e9ef81a | 398 | //----- BLE & HID |
masakjm | 0:28fb3e9ef81a | 399 | Ticker heartbeat; |
masakjm | 0:28fb3e9ef81a | 400 | heartbeat.attach(waiting, 1); // 1秒毎に関数waiting を呼び出す |
masakjm | 0:28fb3e9ef81a | 401 | initialize_BLE_HID(); |
masakjm | 0:28fb3e9ef81a | 402 | display.clear(); |
masakjm | 0:28fb3e9ef81a | 403 | |
masakjm | 0:28fb3e9ef81a | 404 | //----- Loop |
masakjm | 0:28fb3e9ef81a | 405 | while (true) { |
masakjm | 0:28fb3e9ef81a | 406 | ble.waitForEvent(); // BLEイベントを待つ |
masakjm | 0:28fb3e9ef81a | 407 | |
masakjm | 0:28fb3e9ef81a | 408 | if (dispChar != dispCharLast) { // 表示文字が変更 |
masakjm | 0:28fb3e9ef81a | 409 | turnOffMode = false; |
masakjm | 0:28fb3e9ef81a | 410 | dispTime.reset(); |
masakjm | 0:28fb3e9ef81a | 411 | display.enable(); |
masakjm | 0:28fb3e9ef81a | 412 | if (dispChar) display.printChar(dispChar); |
masakjm | 0:28fb3e9ef81a | 413 | else display.clear(); |
masakjm | 0:28fb3e9ef81a | 414 | } |
masakjm | 0:28fb3e9ef81a | 415 | if (!turnOffMode) { |
masakjm | 0:28fb3e9ef81a | 416 | if (dispTime.read() > TIME_TURN_OFF) { // 長時間表示 |
masakjm | 0:28fb3e9ef81a | 417 | turnOffMode = true; |
masakjm | 0:28fb3e9ef81a | 418 | display.disable(); |
masakjm | 0:28fb3e9ef81a | 419 | } |
masakjm | 0:28fb3e9ef81a | 420 | } |
masakjm | 0:28fb3e9ef81a | 421 | dispCharLast = dispChar; |
masakjm | 0:28fb3e9ef81a | 422 | } |
masakjm | 0:28fb3e9ef81a | 423 | } |