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

Dependencies:   microbit

Committer:
masakjm
Date:
Sat Jun 08 04:40:57 2019 +0000
Revision:
2:8e2e6c6658be
Parent:
1:9d0e2e5b5d25
Child:
3:d8fd4efb63cc
Improved stability

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