BLE switch interface using micro:bit with 3 tact switches or 3 Makey Makey sensors

Dependencies:   microbit

Committer:
masakjm
Date:
Tue Jun 11 18:08:53 2019 +0000
Revision:
3:d8fd4efb63cc
Parent:
2:8e2e6c6658be
Change the usage of timer.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
masakjm 1:9d0e2e5b5d25 1 //=================================
masakjm 1:9d0e2e5b5d25 2 // microbit_switch_if_3sw
masakjm 1:9d0e2e5b5d25 3 //=================================
masakjm 1:9d0e2e5b5d25 4 // BLE switch interface using micro:bit with 3 tact switches
masakjm 1:9d0e2e5b5d25 5 // It is intended for use with ios devices.
masakjm 1:9d0e2e5b5d25 6 //
masakjm 1:9d0e2e5b5d25 7 // The MIT License (MIT) Copyright (c) 2019 Masatomo Kojima
masakjm 1:9d0e2e5b5d25 8 //---------------------------------
masakjm 1:9d0e2e5b5d25 9
masakjm 3:d8fd4efb63cc 10 #define VERSION "3SW-190612"
masakjm 2:8e2e6c6658be 11 #define NO_DEBUG
masakjm 1:9d0e2e5b5d25 12
masakjm 1:9d0e2e5b5d25 13 #include "microbit_switch_if_3sw.h"
masakjm 1:9d0e2e5b5d25 14 #include "KeyValueInt.h"
masakjm 1:9d0e2e5b5d25 15 #include <queue>
masakjm 1:9d0e2e5b5d25 16
masakjm 1:9d0e2e5b5d25 17 //---------------------------------
masakjm 1:9d0e2e5b5d25 18 // KeyBuff
masakjm 1:9d0e2e5b5d25 19 //---------------------------------
masakjm 1:9d0e2e5b5d25 20 std::queue<int> KeyBuff;
masakjm 1:9d0e2e5b5d25 21
masakjm 1:9d0e2e5b5d25 22 //---------------------------------
masakjm 1:9d0e2e5b5d25 23 // Display
masakjm 1:9d0e2e5b5d25 24 //---------------------------------
masakjm 1:9d0e2e5b5d25 25 MicroBitDisplay display;
masakjm 1:9d0e2e5b5d25 26 int State; // 状態遷移
masakjm 1:9d0e2e5b5d25 27 char DispChar = DISP_NO_MESSAGE; // LEDに表示する文字コード
masakjm 1:9d0e2e5b5d25 28 char DispCharLast = 0; // 最後に表示した文字コード
masakjm 2:8e2e6c6658be 29 int Cnt = 0; // カウンター
masakjm 1:9d0e2e5b5d25 30
masakjm 1:9d0e2e5b5d25 31 /** ----------
masakjm 1:9d0e2e5b5d25 32 * @brief 整数値をLEDに表示する
masakjm 1:9d0e2e5b5d25 33 * @param data 整数値
masakjm 1:9d0e2e5b5d25 34 */
masakjm 1:9d0e2e5b5d25 35 static void displayNumber(int data)
masakjm 1:9d0e2e5b5d25 36 {
masakjm 1:9d0e2e5b5d25 37 if (0<=data && data<=9) { // 1桁はスクロールしない
masakjm 1:9d0e2e5b5d25 38 display.print(data);
masakjm 1:9d0e2e5b5d25 39 } else {
masakjm 1:9d0e2e5b5d25 40 display.scroll(data);
masakjm 1:9d0e2e5b5d25 41 }
masakjm 1:9d0e2e5b5d25 42 }
masakjm 1:9d0e2e5b5d25 43
masakjm 3:d8fd4efb63cc 44 /** ----------
masakjm 3:d8fd4efb63cc 45 * @brief 一定期間後に表示をOFFにする
masakjm 3:d8fd4efb63cc 46 */
masakjm 3:d8fd4efb63cc 47 static void turnOff() {
masakjm 3:d8fd4efb63cc 48 display.disable();
masakjm 3:d8fd4efb63cc 49 }
masakjm 3:d8fd4efb63cc 50
masakjm 1:9d0e2e5b5d25 51 //---------------------------------
masakjm 1:9d0e2e5b5d25 52 // Flash Memory
masakjm 1:9d0e2e5b5d25 53 //---------------------------------
masakjm 1:9d0e2e5b5d25 54 /** ----------
masakjm 1:9d0e2e5b5d25 55 * @brief キー名を指定して不揮発メモリから値を読み出す
masakjm 1:9d0e2e5b5d25 56 * @param key キー名
masakjm 1:9d0e2e5b5d25 57 * @param init データが保存されていなかった時の初期値
masakjm 1:9d0e2e5b5d25 58 * @return int 取得したデータ
masakjm 1:9d0e2e5b5d25 59 */
masakjm 1:9d0e2e5b5d25 60 static int FlashGet(MicroBitStorage storage, const char* key, int init=0)
masakjm 1:9d0e2e5b5d25 61 {
masakjm 1:9d0e2e5b5d25 62 KeyValuePair* kvp = storage.get(key);
masakjm 1:9d0e2e5b5d25 63 if(kvp != NULL) {
masakjm 1:9d0e2e5b5d25 64 int data;
masakjm 1:9d0e2e5b5d25 65 memcpy(&data, kvp->value, sizeof(int));
masakjm 1:9d0e2e5b5d25 66 DEBUG("== FlashGet exist %s = %d\r\n", key, data);
masakjm 1:9d0e2e5b5d25 67 return data;
masakjm 1:9d0e2e5b5d25 68 }
masakjm 1:9d0e2e5b5d25 69 return init;
masakjm 1:9d0e2e5b5d25 70 }
masakjm 1:9d0e2e5b5d25 71
masakjm 1:9d0e2e5b5d25 72 /** ----------
masakjm 1:9d0e2e5b5d25 73 * @brief 不揮発メモリに値を書き込む
masakjm 1:9d0e2e5b5d25 74 * @param storage 不揮発メモリインスタンス
masakjm 1:9d0e2e5b5d25 75 * @param key キー名
masakjm 1:9d0e2e5b5d25 76 * @param data 値
masakjm 1:9d0e2e5b5d25 77 * @return int MICROBIT_OK = 0
masakjm 1:9d0e2e5b5d25 78 * MICROBIT_INVALID_PARAMETER = -1001,
masakjm 1:9d0e2e5b5d25 79 * MICROBIT_NO_RESOURCES = -1005,
masakjm 1:9d0e2e5b5d25 80 */
masakjm 1:9d0e2e5b5d25 81 static int FlashPut(MicroBitStorage storage, const char* key, int data)
masakjm 1:9d0e2e5b5d25 82 {
masakjm 1:9d0e2e5b5d25 83 int ret = storage.put(key, (uint8_t *)&data, sizeof(int));
masakjm 1:9d0e2e5b5d25 84 DEBUG("== FlashPut %s %d %d\r\n", key, data, ret);
masakjm 1:9d0e2e5b5d25 85 return ret;
masakjm 1:9d0e2e5b5d25 86 }
masakjm 1:9d0e2e5b5d25 87
masakjm 1:9d0e2e5b5d25 88 //---------------------------------
masakjm 1:9d0e2e5b5d25 89 // Setting
masakjm 1:9d0e2e5b5d25 90 //---------------------------------
masakjm 2:8e2e6c6658be 91 bool Setting_inc; // 設定値を増加
masakjm 2:8e2e6c6658be 92 bool Setting_enter; // 設定値を入力
masakjm 2:8e2e6c6658be 93 bool Setting_next; // 次の設定値に移動
masakjm 1:9d0e2e5b5d25 94
masakjm 3:d8fd4efb63cc 95 KeyValueInt kviKeyCode1("keycode1",DISP_SETTING_FREQ, 1, 1, NUM_GROUP_3SW, true);
masakjm 1:9d0e2e5b5d25 96
masakjm 1:9d0e2e5b5d25 97 /** ----------
masakjm 1:9d0e2e5b5d25 98 * @brief 1つのパラメータの表示と変更
masakjm 1:9d0e2e5b5d25 99 * @param storage 不揮発メモリインスタンス
masakjm 1:9d0e2e5b5d25 100 * @param para パラメータのキーと値の組
masakjm 3:d8fd4efb63cc 101 * @param change 変更する時 true
masakjm 1:9d0e2e5b5d25 102 * @param disp 今の値を表示する時 true
masakjm 1:9d0e2e5b5d25 103 * @return bool true : Success false : Failed
masakjm 1:9d0e2e5b5d25 104 */
masakjm 1:9d0e2e5b5d25 105 static bool paraSettingOne(MicroBitStorage storage, KeyValueInt* para, bool change, bool disp)
masakjm 1:9d0e2e5b5d25 106 {
masakjm 1:9d0e2e5b5d25 107 if(disp){
masakjm 1:9d0e2e5b5d25 108 display.print(para->disp); // 識別文字をLED表示
masakjm 1:9d0e2e5b5d25 109 wait(SETTING_DISPLAY_WAIT);
masakjm 1:9d0e2e5b5d25 110 displayNumber(para->value); // 値をLED表示
masakjm 1:9d0e2e5b5d25 111 }
masakjm 1:9d0e2e5b5d25 112 if (!change) {
masakjm 1:9d0e2e5b5d25 113 wait(SETTING_DISPLAY_WAIT);
masakjm 1:9d0e2e5b5d25 114 return true;
masakjm 1:9d0e2e5b5d25 115 }
masakjm 1:9d0e2e5b5d25 116
masakjm 1:9d0e2e5b5d25 117 DEBUG("== paraSetting\r\n");
masakjm 2:8e2e6c6658be 118 Setting_inc = false;
masakjm 2:8e2e6c6658be 119 Setting_next = Setting_enter = false;
masakjm 2:8e2e6c6658be 120 while( ! Setting_next) { // Bボタンが離されるまで
masakjm 2:8e2e6c6658be 121 if (Setting_inc) { // Aボタンが押されたら
masakjm 2:8e2e6c6658be 122 Setting_inc = false;
masakjm 1:9d0e2e5b5d25 123 para->inc();
masakjm 1:9d0e2e5b5d25 124 displayNumber(para->value);
masakjm 1:9d0e2e5b5d25 125 }
masakjm 1:9d0e2e5b5d25 126 wait(0.2);
masakjm 1:9d0e2e5b5d25 127 }
masakjm 1:9d0e2e5b5d25 128 int ret = FlashPut(storage, para->key, para->value);
masakjm 1:9d0e2e5b5d25 129 if (ret) DEBUG("(strage)Error %d\r\n",ret);
masakjm 1:9d0e2e5b5d25 130 return (ret == MICROBIT_OK);
masakjm 1:9d0e2e5b5d25 131 }
masakjm 1:9d0e2e5b5d25 132
masakjm 1:9d0e2e5b5d25 133 /** ----------
masakjm 1:9d0e2e5b5d25 134 * @brief よく変更するパラメータの表示と変更
masakjm 1:9d0e2e5b5d25 135 * @param change true:変更する時
masakjm 3:d8fd4efb63cc 136 * @return char 0 : Success DISP_BLE_ERROR_WRITEDDATA : Failed
masakjm 1:9d0e2e5b5d25 137 */
masakjm 1:9d0e2e5b5d25 138 static char paraSettingFreq(bool change=false)
masakjm 1:9d0e2e5b5d25 139 {
masakjm 1:9d0e2e5b5d25 140 MicroBitStorage storage;
masakjm 1:9d0e2e5b5d25 141
masakjm 1:9d0e2e5b5d25 142 kviKeyCode1.set(FlashGet(storage, kviKeyCode1.key, 1));
masakjm 1:9d0e2e5b5d25 143 if (paraSettingOne(storage, &kviKeyCode1, change, true)) return 0;
masakjm 3:d8fd4efb63cc 144 else return DISP_BLE_ERROR_WRITEDDATA;
masakjm 1:9d0e2e5b5d25 145 }
masakjm 1:9d0e2e5b5d25 146
masakjm 1:9d0e2e5b5d25 147 /** ----------
masakjm 1:9d0e2e5b5d25 148 * @brief デバイス固有のパラメータの表示と変更
masakjm 1:9d0e2e5b5d25 149 * @param change true:変更する時
masakjm 3:d8fd4efb63cc 150 * @return char 0 : Success DISP_BLE_ERROR_WRITEDDATA : Failed
masakjm 1:9d0e2e5b5d25 151 */
masakjm 1:9d0e2e5b5d25 152 static char paraSettingSpec(bool change=false)
masakjm 1:9d0e2e5b5d25 153 {
masakjm 1:9d0e2e5b5d25 154 MicroBitStorage storage;
masakjm 1:9d0e2e5b5d25 155
masakjm 1:9d0e2e5b5d25 156 // kviStickDirec.set(FlashGet(storage, kviStickDirec.key, 1));
masakjm 1:9d0e2e5b5d25 157
masakjm 1:9d0e2e5b5d25 158 if(State == STATE_SETTING_DEVICE) {
masakjm 1:9d0e2e5b5d25 159 // if (paraSettingOne(storage, &kviStickDirec, true , true)) return 0;
masakjm 3:d8fd4efb63cc 160 // else return DISP_BLE_ERROR_WRITEDDATA;
masakjm 1:9d0e2e5b5d25 161 } else {
masakjm 1:9d0e2e5b5d25 162 // if (paraSettingOne(storage, &kviStickDirec, false , false)) return 0;
masakjm 3:d8fd4efb63cc 163 // else return DISP_BLE_ERROR_WRITEDDATA;
masakjm 1:9d0e2e5b5d25 164 }
masakjm 1:9d0e2e5b5d25 165 }
masakjm 1:9d0e2e5b5d25 166 //---------------------------------
masakjm 1:9d0e2e5b5d25 167 // BLE & HID
masakjm 1:9d0e2e5b5d25 168 //---------------------------------
masakjm 1:9d0e2e5b5d25 169 BLE ble;
masakjm 2:8e2e6c6658be 170 KeyboardService *KbdServicePtr;
masakjm 2:8e2e6c6658be 171 BLE_MESSAGE BleMessage;
masakjm 1:9d0e2e5b5d25 172
masakjm 1:9d0e2e5b5d25 173 /** ----------
masakjm 1:9d0e2e5b5d25 174 * @brief BLE接続が切断された時のコールバック関数
masakjm 1:9d0e2e5b5d25 175 */
masakjm 1:9d0e2e5b5d25 176 static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params)
masakjm 1:9d0e2e5b5d25 177 {
masakjm 1:9d0e2e5b5d25 178 DEBUG("(BLE)disconnected\r\n");
masakjm 1:9d0e2e5b5d25 179 ble.gap().startAdvertising(); // restart advertising
masakjm 2:8e2e6c6658be 180 BleMessage = BLE_NO_MESSAGE;
masakjm 1:9d0e2e5b5d25 181 }
masakjm 1:9d0e2e5b5d25 182
masakjm 1:9d0e2e5b5d25 183 /** ----------
masakjm 1:9d0e2e5b5d25 184 * @brief BLE接続が接続された時のコールバック関数
masakjm 1:9d0e2e5b5d25 185 */
masakjm 1:9d0e2e5b5d25 186 static void onConnect(const Gap::ConnectionCallbackParams_t *params)
masakjm 1:9d0e2e5b5d25 187 {
masakjm 2:8e2e6c6658be 188 if(KbdServicePtr->isConnected()) {
masakjm 1:9d0e2e5b5d25 189 DEBUG("(BLE)connected\r\n");
masakjm 1:9d0e2e5b5d25 190 ble.gap().stopAdvertising();
masakjm 2:8e2e6c6658be 191 BleMessage = BLE_CONNECTED;
masakjm 1:9d0e2e5b5d25 192 }
masakjm 1:9d0e2e5b5d25 193 }
masakjm 1:9d0e2e5b5d25 194
masakjm 1:9d0e2e5b5d25 195 /** ----------
masakjm 1:9d0e2e5b5d25 196 * @brief パスキー入力を求められた時のコールバック関数
masakjm 1:9d0e2e5b5d25 197 */
masakjm 1:9d0e2e5b5d25 198 static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey)
masakjm 1:9d0e2e5b5d25 199 {
masakjm 2:8e2e6c6658be 200 // printf("(BLE)Input passKey: ");
masakjm 2:8e2e6c6658be 201 // for (unsigned i = 0; i < Gap::ADDR_LEN; i++) {
masakjm 2:8e2e6c6658be 202 // printf("%c", passkey[i]);
masakjm 2:8e2e6c6658be 203 // }
masakjm 2:8e2e6c6658be 204 // printf("\r\n");
masakjm 1:9d0e2e5b5d25 205 }
masakjm 1:9d0e2e5b5d25 206
masakjm 1:9d0e2e5b5d25 207 /** ----------
masakjm 1:9d0e2e5b5d25 208 * @brief セキュリティ設定完了時のコールバック関数
masakjm 1:9d0e2e5b5d25 209 */
masakjm 1:9d0e2e5b5d25 210 static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status)
masakjm 1:9d0e2e5b5d25 211 {
masakjm 1:9d0e2e5b5d25 212 if (status == SecurityManager::SEC_STATUS_SUCCESS) {
masakjm 1:9d0e2e5b5d25 213 // DEBUG("(BLE)Security success %d\r\n", status);
masakjm 2:8e2e6c6658be 214 BleMessage = BLE_PAIRING_SUCCESS;
masakjm 1:9d0e2e5b5d25 215
masakjm 1:9d0e2e5b5d25 216 } else {
masakjm 1:9d0e2e5b5d25 217 // DEBUG("(BLE)Security failed %d\r\n", status);
masakjm 2:8e2e6c6658be 218 BleMessage = BLE_PAIRING_FAILED;
masakjm 1:9d0e2e5b5d25 219 }
masakjm 1:9d0e2e5b5d25 220 }
masakjm 1:9d0e2e5b5d25 221
masakjm 1:9d0e2e5b5d25 222 /** ----------
masakjm 1:9d0e2e5b5d25 223 * @brief セキュリティ初期化
masakjm 1:9d0e2e5b5d25 224 * @para _ble BLEインスタンス
masakjm 1:9d0e2e5b5d25 225 */
masakjm 1:9d0e2e5b5d25 226 static void initializeSecurity(BLE &_ble)
masakjm 1:9d0e2e5b5d25 227 {
masakjm 1:9d0e2e5b5d25 228 bool enableBonding = true;
masakjm 1:9d0e2e5b5d25 229 bool requireMITM = HID_SECURITY_REQUIRE_MITM;
masakjm 1:9d0e2e5b5d25 230
masakjm 1:9d0e2e5b5d25 231 _ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback);
masakjm 1:9d0e2e5b5d25 232 _ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
masakjm 1:9d0e2e5b5d25 233
masakjm 1:9d0e2e5b5d25 234 _ble.securityManager().init(enableBonding, requireMITM, HID_SECURITY_IOCAPS);
masakjm 1:9d0e2e5b5d25 235 }
masakjm 0:e0105c17ebb3 236
masakjm 1:9d0e2e5b5d25 237 /** ----------
masakjm 1:9d0e2e5b5d25 238 * @brief HOGP (HID Over GATT Profile) 初期化
masakjm 1:9d0e2e5b5d25 239 * @para _ble BLEインスタンス
masakjm 1:9d0e2e5b5d25 240 */
masakjm 1:9d0e2e5b5d25 241 static void initializeHOGP(BLE &_ble)
masakjm 1:9d0e2e5b5d25 242 {
masakjm 1:9d0e2e5b5d25 243 static const uint16_t uuid16_list[] = {GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE,
masakjm 1:9d0e2e5b5d25 244 GattService::UUID_DEVICE_INFORMATION_SERVICE,
masakjm 1:9d0e2e5b5d25 245 GattService::UUID_BATTERY_SERVICE
masakjm 1:9d0e2e5b5d25 246 };
masakjm 1:9d0e2e5b5d25 247
masakjm 1:9d0e2e5b5d25 248 PnPID_t pnpID;
masakjm 1:9d0e2e5b5d25 249 pnpID.vendorID_source = 0x2; // from the USB Implementer's Forum
masakjm 1:9d0e2e5b5d25 250 pnpID.vendorID = 0x0D28; // NXP
masakjm 1:9d0e2e5b5d25 251 pnpID.productID = 0x0204; // CMSIS-DAP (well, it's a keyboard but oh well)
masakjm 1:9d0e2e5b5d25 252 pnpID.productVersion = 0x0100; // v1.0
masakjm 1:9d0e2e5b5d25 253 HIDDeviceInformationService deviceInfo(_ble, "ARM", "m1", "abc", "def", "ghi", "jkl", &pnpID);
masakjm 1:9d0e2e5b5d25 254
masakjm 1:9d0e2e5b5d25 255 BatteryService batteryInfo(_ble, 80);
masakjm 1:9d0e2e5b5d25 256
masakjm 1:9d0e2e5b5d25 257 _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED |
masakjm 1:9d0e2e5b5d25 258 GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
masakjm 1:9d0e2e5b5d25 259 _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
masakjm 1:9d0e2e5b5d25 260 (uint8_t *)uuid16_list, sizeof(uuid16_list));
masakjm 1:9d0e2e5b5d25 261
masakjm 1:9d0e2e5b5d25 262 // see 5.1.2: HID over GATT Specification (pg. 25)
masakjm 1:9d0e2e5b5d25 263 _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
masakjm 1:9d0e2e5b5d25 264 // 30ms to 50ms is recommended (5.1.2)
masakjm 1:9d0e2e5b5d25 265 _ble.gap().setAdvertisingInterval(50);
masakjm 1:9d0e2e5b5d25 266 }
masakjm 1:9d0e2e5b5d25 267
masakjm 1:9d0e2e5b5d25 268 /** ----------
masakjm 1:9d0e2e5b5d25 269 * @brief BLE接続のHID(human interface device) の初期化
masakjm 1:9d0e2e5b5d25 270 */
masakjm 1:9d0e2e5b5d25 271 static void initialize_BLE_HID()
masakjm 1:9d0e2e5b5d25 272 {
masakjm 1:9d0e2e5b5d25 273 static const char SHORT_DEVICE_NAME[] = "micro:bit";
masakjm 1:9d0e2e5b5d25 274 static char DeviceName[20];
masakjm 1:9d0e2e5b5d25 275
masakjm 1:9d0e2e5b5d25 276 int id = microbit_serial_number()& 0xfff; // シリアル番号の下12桁を4桁の10進で表示
masakjm 1:9d0e2e5b5d25 277 sprintf(DeviceName, "micro:bit %04d", id);
masakjm 1:9d0e2e5b5d25 278 DEBUG("(BLE)id %s\r\n", DeviceName);
masakjm 1:9d0e2e5b5d25 279
masakjm 1:9d0e2e5b5d25 280 // DEBUG("(BLE)initialising ble\r\n");
masakjm 1:9d0e2e5b5d25 281 ble.init();
masakjm 1:9d0e2e5b5d25 282
masakjm 1:9d0e2e5b5d25 283 ble.gap().onDisconnection(onDisconnect);
masakjm 1:9d0e2e5b5d25 284 ble.gap().onConnection(onConnect);
masakjm 1:9d0e2e5b5d25 285
masakjm 1:9d0e2e5b5d25 286 initializeSecurity(ble);
masakjm 1:9d0e2e5b5d25 287
masakjm 1:9d0e2e5b5d25 288 DEBUG("(BLE)adding hid service\r\n");
masakjm 1:9d0e2e5b5d25 289 KeyboardService kbdService(ble);
masakjm 2:8e2e6c6658be 290 KbdServicePtr = &kbdService;
masakjm 1:9d0e2e5b5d25 291
masakjm 1:9d0e2e5b5d25 292 DEBUG("(BLE)adding device info and battery service\r\n");
masakjm 1:9d0e2e5b5d25 293 initializeHOGP(ble);
masakjm 1:9d0e2e5b5d25 294
masakjm 1:9d0e2e5b5d25 295 DEBUG("(BLE)setting up gap\r\n");
masakjm 1:9d0e2e5b5d25 296 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD);
masakjm 1:9d0e2e5b5d25 297 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME,
masakjm 1:9d0e2e5b5d25 298 (uint8_t *)DeviceName, sizeof(DeviceName));
masakjm 1:9d0e2e5b5d25 299 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
masakjm 1:9d0e2e5b5d25 300 (uint8_t *)SHORT_DEVICE_NAME, sizeof(SHORT_DEVICE_NAME));
masakjm 1:9d0e2e5b5d25 301 ble.gap().setDeviceName((const uint8_t *)DeviceName);
masakjm 1:9d0e2e5b5d25 302
masakjm 1:9d0e2e5b5d25 303 DEBUG("(BLE)advertising\r\n");
masakjm 1:9d0e2e5b5d25 304 ble.gap().startAdvertising();
masakjm 1:9d0e2e5b5d25 305 }
masakjm 1:9d0e2e5b5d25 306
masakjm 1:9d0e2e5b5d25 307 //---------------------------------
masakjm 1:9d0e2e5b5d25 308 // Button
masakjm 1:9d0e2e5b5d25 309 //---------------------------------
masakjm 1:9d0e2e5b5d25 310 MicroBitMessageBus bus;
masakjm 1:9d0e2e5b5d25 311 MicroBitButton buttonA(MICROBIT_PIN_BUTTON_A, MICROBIT_ID_BUTTON_A);
masakjm 1:9d0e2e5b5d25 312 MicroBitButton buttonB(MICROBIT_PIN_BUTTON_B, MICROBIT_ID_BUTTON_B);
masakjm 3:d8fd4efb63cc 313 MicroBitButton P0(MICROBIT_PIN_P0, MICROBIT_ID_IO_P0, MICROBIT_BUTTON_ALL_EVENTS, PullUp);
masakjm 3:d8fd4efb63cc 314 MicroBitButton P1(MICROBIT_PIN_P1, MICROBIT_ID_IO_P1, MICROBIT_BUTTON_ALL_EVENTS, PullUp);
masakjm 3:d8fd4efb63cc 315 MicroBitButton P2(MICROBIT_PIN_P2, MICROBIT_ID_IO_P2, MICROBIT_BUTTON_ALL_EVENTS, PullUp);
masakjm 1:9d0e2e5b5d25 316
masakjm 1:9d0e2e5b5d25 317 /** ----------
masakjm 1:9d0e2e5b5d25 318 * @brief キーコードを送信する
masakjm 1:9d0e2e5b5d25 319 * @para code 上位8bit:修飾キー 下位8bit:キーコード    
masakjm 1:9d0e2e5b5d25 320 */
masakjm 1:9d0e2e5b5d25 321 static void sendKeyCode(int code) {
masakjm 1:9d0e2e5b5d25 322 if (code) {
masakjm 1:9d0e2e5b5d25 323 uint8_t key = code & 0xff;
masakjm 1:9d0e2e5b5d25 324 uint8_t modif = code >> 8;
masakjm 0:e0105c17ebb3 325
masakjm 1:9d0e2e5b5d25 326 if (key > KEYMAP_SIZE ) {
masakjm 1:9d0e2e5b5d25 327 DispChar = DISP_ERROR_INCORRECT_CODE; // キーコード設定間違い
masakjm 1:9d0e2e5b5d25 328 } else {
masakjm 2:8e2e6c6658be 329 printf(" Cnt=%d code=%d modif=%d\r\n",Cnt++, key , modif);
masakjm 2:8e2e6c6658be 330 wait(0.05);
masakjm 2:8e2e6c6658be 331 ble_error_t ret = KbdServicePtr->keyDownCode(key, modif);
masakjm 1:9d0e2e5b5d25 332 if (ret) {
masakjm 1:9d0e2e5b5d25 333 DispChar = DISP_BLE_ERROR_SENDDATA;
masakjm 2:8e2e6c6658be 334 DispCharLast = DISP_NO_MESSAGE;
masakjm 1:9d0e2e5b5d25 335 DEBUG("(BLE)Error %d\r\n",ret);
masakjm 1:9d0e2e5b5d25 336 }
masakjm 1:9d0e2e5b5d25 337 }
masakjm 1:9d0e2e5b5d25 338 }
masakjm 1:9d0e2e5b5d25 339 }
masakjm 1:9d0e2e5b5d25 340 /** ----------
masakjm 1:9d0e2e5b5d25 341 * @brief ボタン保持時イベント
masakjm 1:9d0e2e5b5d25 342 * @para e イベント
masakjm 1:9d0e2e5b5d25 343 */
masakjm 1:9d0e2e5b5d25 344 static void onButtonHold(MicroBitEvent e)
masakjm 1:9d0e2e5b5d25 345 {
masakjm 1:9d0e2e5b5d25 346 if ((e.source == MICROBIT_ID_BUTTON_A && buttonB.isPressed()) ||
masakjm 1:9d0e2e5b5d25 347 (e.source == MICROBIT_ID_BUTTON_B && buttonA.isPressed()) ) {
masakjm 1:9d0e2e5b5d25 348 KeyBuff.push(BUTTON_STATUS_HOLD + BUTTON_NAME_A + BUTTON_NAME_B);
masakjm 1:9d0e2e5b5d25 349 }
masakjm 1:9d0e2e5b5d25 350 }
masakjm 1:9d0e2e5b5d25 351
masakjm 1:9d0e2e5b5d25 352 static void ButtonHoldProcess(int button)
masakjm 1:9d0e2e5b5d25 353 {
masakjm 1:9d0e2e5b5d25 354 int code = 0;
masakjm 1:9d0e2e5b5d25 355 switch(button) {
masakjm 1:9d0e2e5b5d25 356 case BUTTON_NAME_A + BUTTON_NAME_B :
masakjm 1:9d0e2e5b5d25 357 DispChar = DISP_HOLD_BUTTON_AB;
masakjm 1:9d0e2e5b5d25 358 code = keyCodeGroup_AB[2];
masakjm 1:9d0e2e5b5d25 359 break;
masakjm 1:9d0e2e5b5d25 360 }
masakjm 1:9d0e2e5b5d25 361 if (code != 0 ) sendKeyCode(code);
masakjm 1:9d0e2e5b5d25 362 }
masakjm 1:9d0e2e5b5d25 363
masakjm 1:9d0e2e5b5d25 364 /** ----------
masakjm 1:9d0e2e5b5d25 365 * @brief ボタン押下げ時イベント
masakjm 1:9d0e2e5b5d25 366 * @para e イベント
masakjm 1:9d0e2e5b5d25 367 */
masakjm 1:9d0e2e5b5d25 368 static void onButtonDown(MicroBitEvent e)
masakjm 1:9d0e2e5b5d25 369 {
masakjm 1:9d0e2e5b5d25 370 switch (State) {
masakjm 1:9d0e2e5b5d25 371 case STATE_SETTING_FREQ :
masakjm 1:9d0e2e5b5d25 372 case STATE_SETTING_DEVICE :
masakjm 1:9d0e2e5b5d25 373 switch(e.source) {
masakjm 1:9d0e2e5b5d25 374 case MICROBIT_ID_BUTTON_A :
masakjm 2:8e2e6c6658be 375 Setting_inc = true;
masakjm 1:9d0e2e5b5d25 376 break;
masakjm 1:9d0e2e5b5d25 377 case MICROBIT_ID_BUTTON_B :
masakjm 2:8e2e6c6658be 378 Setting_enter = true;
masakjm 1:9d0e2e5b5d25 379 break;
masakjm 1:9d0e2e5b5d25 380 }
masakjm 1:9d0e2e5b5d25 381 break;
masakjm 1:9d0e2e5b5d25 382 case STATE_OPERATING :
masakjm 1:9d0e2e5b5d25 383 switch(e.source) {
masakjm 1:9d0e2e5b5d25 384 case MICROBIT_ID_BUTTON_A :
masakjm 1:9d0e2e5b5d25 385 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_A);
masakjm 1:9d0e2e5b5d25 386 break;
masakjm 1:9d0e2e5b5d25 387 case MICROBIT_ID_BUTTON_B :
masakjm 1:9d0e2e5b5d25 388 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_B);
masakjm 1:9d0e2e5b5d25 389 break;
masakjm 1:9d0e2e5b5d25 390 case MICROBIT_ID_IO_P0 :
masakjm 1:9d0e2e5b5d25 391 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_P0);
masakjm 1:9d0e2e5b5d25 392 break;
masakjm 1:9d0e2e5b5d25 393 case MICROBIT_ID_IO_P1 :
masakjm 1:9d0e2e5b5d25 394 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_P1);
masakjm 1:9d0e2e5b5d25 395 break;
masakjm 1:9d0e2e5b5d25 396 case MICROBIT_ID_IO_P2 :
masakjm 1:9d0e2e5b5d25 397 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_P2);
masakjm 1:9d0e2e5b5d25 398 break;
masakjm 1:9d0e2e5b5d25 399 }
masakjm 1:9d0e2e5b5d25 400 }
masakjm 1:9d0e2e5b5d25 401 }
masakjm 1:9d0e2e5b5d25 402
masakjm 1:9d0e2e5b5d25 403 static void ButtonDownProcess(int button)
masakjm 1:9d0e2e5b5d25 404 {
masakjm 1:9d0e2e5b5d25 405 int code = 0;
masakjm 1:9d0e2e5b5d25 406 switch(button) {
masakjm 1:9d0e2e5b5d25 407 case BUTTON_NAME_A :
masakjm 1:9d0e2e5b5d25 408 DispChar = DISP_PRESS_BUTTON_A;
masakjm 1:9d0e2e5b5d25 409 code = keyCodeGroup_AB[0];
masakjm 1:9d0e2e5b5d25 410 break;
masakjm 1:9d0e2e5b5d25 411 case BUTTON_NAME_B :
masakjm 1:9d0e2e5b5d25 412 DispChar = DISP_PRESS_BUTTON_B;
masakjm 1:9d0e2e5b5d25 413 code = keyCodeGroup_AB[1];
masakjm 1:9d0e2e5b5d25 414 break;
masakjm 1:9d0e2e5b5d25 415 case BUTTON_NAME_P0 :
masakjm 1:9d0e2e5b5d25 416 DispChar = DISP_ACTIVE_IO_P0;
masakjm 1:9d0e2e5b5d25 417 code = keyCodeGroup_3SW[kviKeyCode1.value-1][0];
masakjm 1:9d0e2e5b5d25 418 break;
masakjm 1:9d0e2e5b5d25 419 case BUTTON_NAME_P1 :
masakjm 1:9d0e2e5b5d25 420 DispChar = DISP_ACTIVE_IO_P1;
masakjm 1:9d0e2e5b5d25 421 code = keyCodeGroup_3SW[kviKeyCode1.value-1][1];
masakjm 1:9d0e2e5b5d25 422 break;
masakjm 1:9d0e2e5b5d25 423 case BUTTON_NAME_P2 :
masakjm 1:9d0e2e5b5d25 424 DispChar = DISP_ACTIVE_IO_P2;
masakjm 1:9d0e2e5b5d25 425 code = keyCodeGroup_3SW[kviKeyCode1.value-1][2];
masakjm 1:9d0e2e5b5d25 426 break;
masakjm 1:9d0e2e5b5d25 427 }
masakjm 1:9d0e2e5b5d25 428 if (code != 0 ) sendKeyCode(code);
masakjm 1:9d0e2e5b5d25 429 }
masakjm 1:9d0e2e5b5d25 430
masakjm 1:9d0e2e5b5d25 431 /** ----------
masakjm 1:9d0e2e5b5d25 432 * @brief ボタン離し時イベント
masakjm 1:9d0e2e5b5d25 433 * @para e イベント
masakjm 1:9d0e2e5b5d25 434 */
masakjm 1:9d0e2e5b5d25 435 static void onButtonUp(MicroBitEvent e)
masakjm 1:9d0e2e5b5d25 436 {
masakjm 1:9d0e2e5b5d25 437 switch (State) {
masakjm 1:9d0e2e5b5d25 438 case STATE_SETTING_FREQ :
masakjm 1:9d0e2e5b5d25 439 case STATE_SETTING_DEVICE :
masakjm 2:8e2e6c6658be 440 if(Setting_enter) Setting_next = true; // 決定ボタンを離したら次へ
masakjm 1:9d0e2e5b5d25 441 break;
masakjm 1:9d0e2e5b5d25 442 case STATE_OPERATING :
masakjm 1:9d0e2e5b5d25 443 KeyBuff.push(BUTTON_STATUS_UP);
masakjm 1:9d0e2e5b5d25 444 }
masakjm 1:9d0e2e5b5d25 445 }
masakjm 1:9d0e2e5b5d25 446
masakjm 1:9d0e2e5b5d25 447 static void ButtonUpProcess()
masakjm 1:9d0e2e5b5d25 448 {
masakjm 1:9d0e2e5b5d25 449 DispChar = DISP_NO_MESSAGE;
masakjm 2:8e2e6c6658be 450 wait(0.05);
masakjm 2:8e2e6c6658be 451 ble_error_t ret = KbdServicePtr->keyUpCode();
masakjm 1:9d0e2e5b5d25 452 if (ret) {
masakjm 1:9d0e2e5b5d25 453 DispChar = DISP_BLE_ERROR_SENDDATA;
masakjm 2:8e2e6c6658be 454 DispCharLast = DISP_NO_MESSAGE;
masakjm 1:9d0e2e5b5d25 455 }
masakjm 1:9d0e2e5b5d25 456 }
masakjm 1:9d0e2e5b5d25 457
masakjm 1:9d0e2e5b5d25 458 //---------------------------------
masakjm 1:9d0e2e5b5d25 459 // Main
masakjm 1:9d0e2e5b5d25 460 //---------------------------------
masakjm 0:e0105c17ebb3 461 int main()
masakjm 0:e0105c17ebb3 462 {
masakjm 1:9d0e2e5b5d25 463 State = STATE_DESABLE_INPUT;
masakjm 1:9d0e2e5b5d25 464
masakjm 1:9d0e2e5b5d25 465 wait(0.1); // ボタン状態の更新
masakjm 1:9d0e2e5b5d25 466 bool bA = buttonA.isPressed();
masakjm 1:9d0e2e5b5d25 467 bool bB = buttonB.isPressed();
masakjm 1:9d0e2e5b5d25 468
masakjm 1:9d0e2e5b5d25 469 if (bA && bB) { // ボタンABを押しながら起動
masakjm 1:9d0e2e5b5d25 470 for(int i=0;i<2;i++) {
masakjm 1:9d0e2e5b5d25 471 display.scroll(VERSION);
masakjm 1:9d0e2e5b5d25 472 wait(0.5);
masakjm 1:9d0e2e5b5d25 473 }
masakjm 1:9d0e2e5b5d25 474 } else if(bA) { // ボタンAを押しながら起動
masakjm 1:9d0e2e5b5d25 475 State = STATE_SETTING_FREQ;
masakjm 1:9d0e2e5b5d25 476 } else if(bB) { // ボタンBを押しながら起動
masakjm 1:9d0e2e5b5d25 477 State = STATE_SETTING_DEVICE;
masakjm 1:9d0e2e5b5d25 478 }
masakjm 1:9d0e2e5b5d25 479
masakjm 1:9d0e2e5b5d25 480 //----- Display
masakjm 1:9d0e2e5b5d25 481 display.setDisplayMode(DISPLAY_MODE_BLACK_AND_WHITE);
masakjm 1:9d0e2e5b5d25 482 display.clear();
masakjm 3:d8fd4efb63cc 483 Timeout dispTime;
masakjm 1:9d0e2e5b5d25 484
masakjm 1:9d0e2e5b5d25 485 //----- Button
masakjm 1:9d0e2e5b5d25 486 bus.listen(MICROBIT_ID_ANY, MICROBIT_BUTTON_EVT_DOWN, onButtonDown);
masakjm 1:9d0e2e5b5d25 487 bus.listen(MICROBIT_ID_ANY, MICROBIT_BUTTON_EVT_UP, onButtonUp);
masakjm 1:9d0e2e5b5d25 488 bus.listen(MICROBIT_ID_ANY, MICROBIT_BUTTON_EVT_HOLD, onButtonHold);
masakjm 1:9d0e2e5b5d25 489
masakjm 1:9d0e2e5b5d25 490 //----- Device specific settings
masakjm 1:9d0e2e5b5d25 491 DispChar = paraSettingSpec();
masakjm 1:9d0e2e5b5d25 492 //----- Setting
masakjm 1:9d0e2e5b5d25 493 DispChar = paraSettingFreq(State == STATE_SETTING_FREQ);
masakjm 1:9d0e2e5b5d25 494 //----- BLE & HID
masakjm 1:9d0e2e5b5d25 495 State = STATE_DESABLE_INPUT;
masakjm 1:9d0e2e5b5d25 496 initialize_BLE_HID();
masakjm 1:9d0e2e5b5d25 497 display.clear();
masakjm 1:9d0e2e5b5d25 498
masakjm 1:9d0e2e5b5d25 499 //----- Wait to connect
masakjm 3:d8fd4efb63cc 500 display.printChar(DISP_BLE_WAIT);
masakjm 2:8e2e6c6658be 501 while (BleMessage != BLE_CONNECTED) {
masakjm 1:9d0e2e5b5d25 502 wait(0.15);
masakjm 1:9d0e2e5b5d25 503 ble.waitForEvent(); // BLEイベントを待つ
masakjm 2:8e2e6c6658be 504 if(BleMessage != BLE_NO_MESSAGE) { // BLEの状態を表示する
masakjm 2:8e2e6c6658be 505 display.printChar(bleDispChar[BleMessage] );
masakjm 1:9d0e2e5b5d25 506 }
masakjm 1:9d0e2e5b5d25 507 }
masakjm 1:9d0e2e5b5d25 508 wait(3.0);
masakjm 2:8e2e6c6658be 509 BleMessage = BLE_NO_MESSAGE;
masakjm 1:9d0e2e5b5d25 510 display.clear();
masakjm 1:9d0e2e5b5d25 511 //----- Loop
masakjm 1:9d0e2e5b5d25 512 State = STATE_OPERATING;
masakjm 1:9d0e2e5b5d25 513 while (true) {
masakjm 1:9d0e2e5b5d25 514 ble.waitForEvent(); // BLEイベントを待つ
masakjm 1:9d0e2e5b5d25 515
masakjm 2:8e2e6c6658be 516 if(BleMessage != BLE_NO_MESSAGE) { // BLEの状態を表示する
masakjm 2:8e2e6c6658be 517 DispChar = bleDispChar[BleMessage];
masakjm 2:8e2e6c6658be 518 BleMessage = BLE_NO_MESSAGE;
masakjm 1:9d0e2e5b5d25 519 }
masakjm 1:9d0e2e5b5d25 520
masakjm 1:9d0e2e5b5d25 521 if(! KeyBuff.empty()) { // キーバッファ処理
masakjm 1:9d0e2e5b5d25 522 // DEBUG(" size=%d front=%x\r\n", KeyBuff.size(), KeyBuff.front());
masakjm 1:9d0e2e5b5d25 523
masakjm 1:9d0e2e5b5d25 524 switch (KeyBuff.front() & 0xFF00) {
masakjm 1:9d0e2e5b5d25 525 case BUTTON_STATUS_UP :
masakjm 1:9d0e2e5b5d25 526 ButtonUpProcess();
masakjm 1:9d0e2e5b5d25 527 break;
masakjm 1:9d0e2e5b5d25 528 case BUTTON_STATUS_DOWN :
masakjm 1:9d0e2e5b5d25 529 ButtonDownProcess(KeyBuff.front() & 0xFF);
masakjm 1:9d0e2e5b5d25 530 break;
masakjm 1:9d0e2e5b5d25 531 case BUTTON_STATUS_HOLD :
masakjm 1:9d0e2e5b5d25 532 ButtonHoldProcess(KeyBuff.front() & 0xFF);
masakjm 1:9d0e2e5b5d25 533 break;
masakjm 1:9d0e2e5b5d25 534 }
masakjm 1:9d0e2e5b5d25 535 KeyBuff.pop();
masakjm 1:9d0e2e5b5d25 536 }
masakjm 1:9d0e2e5b5d25 537
masakjm 1:9d0e2e5b5d25 538 if (DispChar != DispCharLast) { // 表示文字が変更
masakjm 1:9d0e2e5b5d25 539 display.enable();
masakjm 1:9d0e2e5b5d25 540 if (DispChar) display.printChar(DispChar);
masakjm 1:9d0e2e5b5d25 541 else display.clear();
masakjm 3:d8fd4efb63cc 542 dispTime.detach();
masakjm 3:d8fd4efb63cc 543 dispTime.attach(&turnOff, TIME_TURN_OFF); // 一定時間後に表示をOFF
masakjm 1:9d0e2e5b5d25 544 }
masakjm 1:9d0e2e5b5d25 545 DispCharLast = DispChar;
masakjm 1:9d0e2e5b5d25 546 }
masakjm 1:9d0e2e5b5d25 547 }
masakjm 3:d8fd4efb63cc 548