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

Dependencies:   microbit

Committer:
masakjm
Date:
Thu Jun 06 19:06:06 2019 +0000
Revision:
1:9d0e2e5b5d25
Parent:
0:e0105c17ebb3
Child:
2:8e2e6c6658be

        

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 // or 3 Makey Makey sensors
masakjm 1:9d0e2e5b5d25 6 // It is intended for use with ios devices.
masakjm 1:9d0e2e5b5d25 7 //
masakjm 1:9d0e2e5b5d25 8 // The MIT License (MIT) Copyright (c) 2019 Masatomo Kojima
masakjm 1:9d0e2e5b5d25 9 //---------------------------------
masakjm 1:9d0e2e5b5d25 10
masakjm 1:9d0e2e5b5d25 11 #define VERSION "3SW-190607"
masakjm 1:9d0e2e5b5d25 12 //#define NO_DEBUG
masakjm 1:9d0e2e5b5d25 13
masakjm 1:9d0e2e5b5d25 14 #include "microbit_switch_if_3sw.h"
masakjm 1:9d0e2e5b5d25 15 #include "KeyValueInt.h"
masakjm 1:9d0e2e5b5d25 16 #include <queue>
masakjm 1:9d0e2e5b5d25 17
masakjm 1:9d0e2e5b5d25 18 //---------------------------------
masakjm 1:9d0e2e5b5d25 19 // KeyBuff
masakjm 1:9d0e2e5b5d25 20 //---------------------------------
masakjm 1:9d0e2e5b5d25 21 std::queue<int> KeyBuff;
masakjm 1:9d0e2e5b5d25 22
masakjm 1:9d0e2e5b5d25 23 //---------------------------------
masakjm 1:9d0e2e5b5d25 24 // Display
masakjm 1:9d0e2e5b5d25 25 //---------------------------------
masakjm 1:9d0e2e5b5d25 26 MicroBitDisplay display;
masakjm 1:9d0e2e5b5d25 27 int State; // 状態遷移
masakjm 1:9d0e2e5b5d25 28 char DispChar = DISP_NO_MESSAGE; // LEDに表示する文字コード
masakjm 1:9d0e2e5b5d25 29 char DispCharLast = 0; // 最後に表示した文字コード
masakjm 1:9d0e2e5b5d25 30 bool TurnOffMode = false; // LED非表示モードのフラグ
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 1:9d0e2e5b5d25 85 bool setting_inc; // 設定値を増加
masakjm 1:9d0e2e5b5d25 86 bool setting_enter; // 設定値を入力
masakjm 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 112 setting_inc = false;
masakjm 1:9d0e2e5b5d25 113 setting_next = setting_enter = false;
masakjm 1:9d0e2e5b5d25 114 while( ! setting_next) { // Bボタンが離されるまで
masakjm 1:9d0e2e5b5d25 115 if (setting_inc) { // Aボタンが押されたら
masakjm 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 164 KeyboardService *kbdServicePtr;
masakjm 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 182 if(kbdServicePtr->isConnected()) {
masakjm 1:9d0e2e5b5d25 183 DEBUG("(BLE)connected\r\n");
masakjm 1:9d0e2e5b5d25 184 ble.gap().stopAdvertising();
masakjm 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 194 printf("(BLE)Input passKey: ");
masakjm 1:9d0e2e5b5d25 195 for (unsigned i = 0; i < Gap::ADDR_LEN; i++) {
masakjm 1:9d0e2e5b5d25 196 printf("%c", passkey[i]);
masakjm 1:9d0e2e5b5d25 197 }
masakjm 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 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 1:9d0e2e5b5d25 307 MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_ALL);
masakjm 1:9d0e2e5b5d25 308 MicroBitPin P1(MICROBIT_ID_IO_P1, MICROBIT_PIN_P1, PIN_CAPABILITY_ALL);
masakjm 1:9d0e2e5b5d25 309 MicroBitPin P2(MICROBIT_ID_IO_P2, MICROBIT_PIN_P2, PIN_CAPABILITY_ALL);
masakjm 1:9d0e2e5b5d25 310
masakjm 1:9d0e2e5b5d25 311 //MicroBitButton button0(MICROBIT_PIN_P0, MICROBIT_ID_IO_P0, MICROBIT_BUTTON_ALL_EVENTS, PullUp);
masakjm 1:9d0e2e5b5d25 312 //MicroBitButton button1(MICROBIT_PIN_P1, MICROBIT_ID_IO_P1, MICROBIT_BUTTON_ALL_EVENTS, PullUp);
masakjm 1:9d0e2e5b5d25 313 //MicroBitButton button2(MICROBIT_PIN_P2, MICROBIT_ID_IO_P2, MICROBIT_BUTTON_ALL_EVENTS, PullUp);
masakjm 1:9d0e2e5b5d25 314 MicroBitButton button15(MICROBIT_PIN_P15, MICROBIT_ID_IO_P15, MICROBIT_BUTTON_ALL_EVENTS, PullUp);
masakjm 1:9d0e2e5b5d25 315 MicroBitButton button16(MICROBIT_PIN_P16, MICROBIT_ID_IO_P16, 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 1:9d0e2e5b5d25 329 ble_error_t ret = kbdServicePtr->keyDownCode(key, modif);
masakjm 1:9d0e2e5b5d25 330 // DEBUG(" code=%d modif=%d\r\n",key , modif);
masakjm 1:9d0e2e5b5d25 331 if (ret) {
masakjm 1:9d0e2e5b5d25 332 DispChar = DISP_BLE_ERROR_SENDDATA;
masakjm 1:9d0e2e5b5d25 333 DispCharLast = DISP_NO_MESSAGE; // E が続く時に表示
masakjm 1:9d0e2e5b5d25 334 DEBUG("(BLE)Error %d\r\n",ret);
masakjm 1:9d0e2e5b5d25 335 }
masakjm 1:9d0e2e5b5d25 336 }
masakjm 1:9d0e2e5b5d25 337 }
masakjm 1:9d0e2e5b5d25 338 }
masakjm 1:9d0e2e5b5d25 339 /** ----------
masakjm 1:9d0e2e5b5d25 340 * @brief ボタン保持時イベント
masakjm 1:9d0e2e5b5d25 341 * @para e イベント
masakjm 1:9d0e2e5b5d25 342 */
masakjm 1:9d0e2e5b5d25 343 static void onButtonHold(MicroBitEvent e)
masakjm 1:9d0e2e5b5d25 344 {
masakjm 1:9d0e2e5b5d25 345 if ((e.source == MICROBIT_ID_BUTTON_A && buttonB.isPressed()) ||
masakjm 1:9d0e2e5b5d25 346 (e.source == MICROBIT_ID_BUTTON_B && buttonA.isPressed()) ) {
masakjm 1:9d0e2e5b5d25 347 KeyBuff.push(BUTTON_STATUS_HOLD + BUTTON_NAME_A + BUTTON_NAME_B);
masakjm 1:9d0e2e5b5d25 348 }
masakjm 1:9d0e2e5b5d25 349 }
masakjm 1:9d0e2e5b5d25 350
masakjm 1:9d0e2e5b5d25 351 static void ButtonHoldProcess(int button)
masakjm 1:9d0e2e5b5d25 352 {
masakjm 1:9d0e2e5b5d25 353 int code = 0;
masakjm 1:9d0e2e5b5d25 354 switch(button) {
masakjm 1:9d0e2e5b5d25 355 case BUTTON_NAME_A + BUTTON_NAME_B :
masakjm 1:9d0e2e5b5d25 356 DispChar = DISP_HOLD_BUTTON_AB;
masakjm 1:9d0e2e5b5d25 357 code = keyCodeGroup_AB[2];
masakjm 1:9d0e2e5b5d25 358 break;
masakjm 1:9d0e2e5b5d25 359 }
masakjm 1:9d0e2e5b5d25 360 if (code != 0 ) sendKeyCode(code);
masakjm 1:9d0e2e5b5d25 361 }
masakjm 1:9d0e2e5b5d25 362
masakjm 1:9d0e2e5b5d25 363 /** ----------
masakjm 1:9d0e2e5b5d25 364 * @brief ボタン押下げ時イベント
masakjm 1:9d0e2e5b5d25 365 * @para e イベント
masakjm 1:9d0e2e5b5d25 366 */
masakjm 1:9d0e2e5b5d25 367 static void onButtonDown(MicroBitEvent e)
masakjm 1:9d0e2e5b5d25 368 {
masakjm 1:9d0e2e5b5d25 369 // DEBUG(" Button Down %d State=%d\r\n", e.source, State);
masakjm 1:9d0e2e5b5d25 370
masakjm 1:9d0e2e5b5d25 371 switch (State) {
masakjm 1:9d0e2e5b5d25 372 case STATE_SETTING_FREQ :
masakjm 1:9d0e2e5b5d25 373 case STATE_SETTING_DEVICE :
masakjm 1:9d0e2e5b5d25 374 switch(e.source) {
masakjm 1:9d0e2e5b5d25 375 case MICROBIT_ID_BUTTON_A :
masakjm 1:9d0e2e5b5d25 376 setting_inc = true;
masakjm 1:9d0e2e5b5d25 377 break;
masakjm 1:9d0e2e5b5d25 378 case MICROBIT_ID_BUTTON_B :
masakjm 1:9d0e2e5b5d25 379 setting_enter = true;
masakjm 1:9d0e2e5b5d25 380 break;
masakjm 1:9d0e2e5b5d25 381 }
masakjm 1:9d0e2e5b5d25 382 break;
masakjm 1:9d0e2e5b5d25 383 case STATE_OPERATING :
masakjm 1:9d0e2e5b5d25 384 switch(e.source) {
masakjm 1:9d0e2e5b5d25 385 case MICROBIT_ID_BUTTON_A :
masakjm 1:9d0e2e5b5d25 386 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_A);
masakjm 1:9d0e2e5b5d25 387 break;
masakjm 1:9d0e2e5b5d25 388 case MICROBIT_ID_BUTTON_B :
masakjm 1:9d0e2e5b5d25 389 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_B);
masakjm 1:9d0e2e5b5d25 390 break;
masakjm 1:9d0e2e5b5d25 391 case MICROBIT_ID_IO_P0 :
masakjm 1:9d0e2e5b5d25 392 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_P0);
masakjm 1:9d0e2e5b5d25 393 break;
masakjm 1:9d0e2e5b5d25 394 case MICROBIT_ID_IO_P1 :
masakjm 1:9d0e2e5b5d25 395 case MICROBIT_ID_IO_P16 :
masakjm 1:9d0e2e5b5d25 396 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_P1);
masakjm 1:9d0e2e5b5d25 397 break;
masakjm 1:9d0e2e5b5d25 398 case MICROBIT_ID_IO_P2 :
masakjm 1:9d0e2e5b5d25 399 case MICROBIT_ID_IO_P15 :
masakjm 1:9d0e2e5b5d25 400 KeyBuff.push(BUTTON_STATUS_DOWN + BUTTON_NAME_P2);
masakjm 1:9d0e2e5b5d25 401 break;
masakjm 1:9d0e2e5b5d25 402 }
masakjm 1:9d0e2e5b5d25 403 }
masakjm 1:9d0e2e5b5d25 404 }
masakjm 1:9d0e2e5b5d25 405
masakjm 1:9d0e2e5b5d25 406 static void ButtonDownProcess(int button)
masakjm 1:9d0e2e5b5d25 407 {
masakjm 1:9d0e2e5b5d25 408 int code = 0;
masakjm 1:9d0e2e5b5d25 409 switch(button) {
masakjm 1:9d0e2e5b5d25 410 case BUTTON_NAME_A :
masakjm 1:9d0e2e5b5d25 411 DispChar = DISP_PRESS_BUTTON_A;
masakjm 1:9d0e2e5b5d25 412 code = keyCodeGroup_AB[0];
masakjm 1:9d0e2e5b5d25 413 break;
masakjm 1:9d0e2e5b5d25 414 case BUTTON_NAME_B :
masakjm 1:9d0e2e5b5d25 415 DispChar = DISP_PRESS_BUTTON_B;
masakjm 1:9d0e2e5b5d25 416 code = keyCodeGroup_AB[1];
masakjm 1:9d0e2e5b5d25 417 break;
masakjm 1:9d0e2e5b5d25 418 case BUTTON_NAME_P0 :
masakjm 1:9d0e2e5b5d25 419 DispChar = DISP_ACTIVE_IO_P0;
masakjm 1:9d0e2e5b5d25 420 code = keyCodeGroup_3SW[kviKeyCode1.value-1][0];
masakjm 1:9d0e2e5b5d25 421 break;
masakjm 1:9d0e2e5b5d25 422 case BUTTON_NAME_P1 :
masakjm 1:9d0e2e5b5d25 423 DispChar = DISP_ACTIVE_IO_P1;
masakjm 1:9d0e2e5b5d25 424 code = keyCodeGroup_3SW[kviKeyCode1.value-1][1];
masakjm 1:9d0e2e5b5d25 425 break;
masakjm 1:9d0e2e5b5d25 426 case BUTTON_NAME_P2 :
masakjm 1:9d0e2e5b5d25 427 DispChar = DISP_ACTIVE_IO_P2;
masakjm 1:9d0e2e5b5d25 428 code = keyCodeGroup_3SW[kviKeyCode1.value-1][2];
masakjm 1:9d0e2e5b5d25 429 break;
masakjm 1:9d0e2e5b5d25 430 }
masakjm 1:9d0e2e5b5d25 431 if (code != 0 ) sendKeyCode(code);
masakjm 1:9d0e2e5b5d25 432 }
masakjm 1:9d0e2e5b5d25 433
masakjm 1:9d0e2e5b5d25 434 /** ----------
masakjm 1:9d0e2e5b5d25 435 * @brief ボタン離し時イベント
masakjm 1:9d0e2e5b5d25 436 * @para e イベント
masakjm 1:9d0e2e5b5d25 437 */
masakjm 1:9d0e2e5b5d25 438 static void onButtonUp(MicroBitEvent e)
masakjm 1:9d0e2e5b5d25 439 {
masakjm 1:9d0e2e5b5d25 440 // DEBUG(" Button up %d\r\n", e.source);
masakjm 1:9d0e2e5b5d25 441 switch (State) {
masakjm 1:9d0e2e5b5d25 442 case STATE_SETTING_FREQ :
masakjm 1:9d0e2e5b5d25 443 case STATE_SETTING_DEVICE :
masakjm 1:9d0e2e5b5d25 444 if(setting_enter) setting_next = true; // 決定ボタンを離したら次へ
masakjm 1:9d0e2e5b5d25 445 break;
masakjm 1:9d0e2e5b5d25 446 case STATE_OPERATING :
masakjm 1:9d0e2e5b5d25 447 KeyBuff.push(BUTTON_STATUS_UP);
masakjm 1:9d0e2e5b5d25 448 }
masakjm 1:9d0e2e5b5d25 449 }
masakjm 1:9d0e2e5b5d25 450
masakjm 1:9d0e2e5b5d25 451 static void ButtonUpProcess()
masakjm 1:9d0e2e5b5d25 452 {
masakjm 1:9d0e2e5b5d25 453 DispChar = DISP_NO_MESSAGE;
masakjm 1:9d0e2e5b5d25 454 ble_error_t ret = kbdServicePtr->keyUpCode();
masakjm 1:9d0e2e5b5d25 455 if (ret) {
masakjm 1:9d0e2e5b5d25 456 DispChar = DISP_BLE_ERROR_SENDDATA;
masakjm 1:9d0e2e5b5d25 457 DispCharLast = DISP_NO_MESSAGE; // E が続く時に表示
masakjm 1:9d0e2e5b5d25 458 }
masakjm 1:9d0e2e5b5d25 459 }
masakjm 1:9d0e2e5b5d25 460
masakjm 1:9d0e2e5b5d25 461 //---------------------------------
masakjm 1:9d0e2e5b5d25 462 // Main
masakjm 1:9d0e2e5b5d25 463 //---------------------------------
masakjm 0:e0105c17ebb3 464 int main()
masakjm 0:e0105c17ebb3 465 {
masakjm 1:9d0e2e5b5d25 466 State = STATE_DESABLE_INPUT;
masakjm 1:9d0e2e5b5d25 467
masakjm 1:9d0e2e5b5d25 468 wait(0.1); // ボタン状態の更新
masakjm 1:9d0e2e5b5d25 469 bool bA = buttonA.isPressed();
masakjm 1:9d0e2e5b5d25 470 bool bB = buttonB.isPressed();
masakjm 1:9d0e2e5b5d25 471
masakjm 1:9d0e2e5b5d25 472 if (bA && bB) { // ボタンABを押しながら起動
masakjm 1:9d0e2e5b5d25 473 for(int i=0;i<2;i++) {
masakjm 1:9d0e2e5b5d25 474 display.scroll(VERSION);
masakjm 1:9d0e2e5b5d25 475 wait(0.5);
masakjm 1:9d0e2e5b5d25 476 }
masakjm 1:9d0e2e5b5d25 477 } else if(bA) { // ボタンAを押しながら起動
masakjm 1:9d0e2e5b5d25 478 State = STATE_SETTING_FREQ;
masakjm 1:9d0e2e5b5d25 479 } else if(bB) { // ボタンBを押しながら起動
masakjm 1:9d0e2e5b5d25 480 State = STATE_SETTING_DEVICE;
masakjm 1:9d0e2e5b5d25 481 }
masakjm 1:9d0e2e5b5d25 482
masakjm 1:9d0e2e5b5d25 483 //----- Display
masakjm 1:9d0e2e5b5d25 484 display.setDisplayMode(DISPLAY_MODE_BLACK_AND_WHITE);
masakjm 1:9d0e2e5b5d25 485 display.clear();
masakjm 1:9d0e2e5b5d25 486 Timer dispTime; // 連続表示タイマー
masakjm 1:9d0e2e5b5d25 487 dispTime.start();
masakjm 1:9d0e2e5b5d25 488
masakjm 1:9d0e2e5b5d25 489 //----- Button
masakjm 1:9d0e2e5b5d25 490 bus.listen(MICROBIT_ID_ANY, MICROBIT_BUTTON_EVT_DOWN, onButtonDown);
masakjm 1:9d0e2e5b5d25 491 bus.listen(MICROBIT_ID_ANY, MICROBIT_BUTTON_EVT_UP, onButtonUp);
masakjm 1:9d0e2e5b5d25 492 bus.listen(MICROBIT_ID_ANY, MICROBIT_BUTTON_EVT_HOLD, onButtonHold);
masakjm 1:9d0e2e5b5d25 493
masakjm 1:9d0e2e5b5d25 494 // Put the P0, P1 and P2 pins into touch sense mode.
masakjm 1:9d0e2e5b5d25 495 P0.isTouched();
masakjm 1:9d0e2e5b5d25 496 P1.isTouched();
masakjm 1:9d0e2e5b5d25 497 P2.isTouched();
masakjm 1:9d0e2e5b5d25 498
masakjm 1:9d0e2e5b5d25 499
masakjm 1:9d0e2e5b5d25 500 //----- Device specific settings
masakjm 1:9d0e2e5b5d25 501 DispChar = paraSettingSpec();
masakjm 1:9d0e2e5b5d25 502 //----- Setting
masakjm 1:9d0e2e5b5d25 503 DispChar = paraSettingFreq(State == STATE_SETTING_FREQ);
masakjm 1:9d0e2e5b5d25 504 //----- BLE & HID
masakjm 1:9d0e2e5b5d25 505 State = STATE_DESABLE_INPUT;
masakjm 1:9d0e2e5b5d25 506 initialize_BLE_HID();
masakjm 1:9d0e2e5b5d25 507 display.clear();
masakjm 1:9d0e2e5b5d25 508
masakjm 1:9d0e2e5b5d25 509 //----- Wait to connect
masakjm 1:9d0e2e5b5d25 510 display.printChar('W');
masakjm 1:9d0e2e5b5d25 511 while (bleMessage != BLE_CONNECTED) {
masakjm 1:9d0e2e5b5d25 512 wait(0.15);
masakjm 1:9d0e2e5b5d25 513 ble.waitForEvent(); // BLEイベントを待つ
masakjm 1:9d0e2e5b5d25 514 if(bleMessage != BLE_NO_MESSAGE) { // BLEの状態を表示する
masakjm 1:9d0e2e5b5d25 515 display.printChar(bleDispChar[bleMessage] );
masakjm 1:9d0e2e5b5d25 516 }
masakjm 1:9d0e2e5b5d25 517 }
masakjm 1:9d0e2e5b5d25 518 wait(3.0);
masakjm 1:9d0e2e5b5d25 519 bleMessage = BLE_NO_MESSAGE;
masakjm 1:9d0e2e5b5d25 520 display.clear();
masakjm 1:9d0e2e5b5d25 521 //----- Loop
masakjm 1:9d0e2e5b5d25 522 State = STATE_OPERATING;
masakjm 1:9d0e2e5b5d25 523 while (true) {
masakjm 1:9d0e2e5b5d25 524 wait(0.02);
masakjm 1:9d0e2e5b5d25 525 ble.waitForEvent(); // BLEイベントを待つ
masakjm 1:9d0e2e5b5d25 526
masakjm 1:9d0e2e5b5d25 527 if(bleMessage != BLE_NO_MESSAGE) { // BLEの状態を表示する
masakjm 1:9d0e2e5b5d25 528 DispChar = bleDispChar[bleMessage];
masakjm 1:9d0e2e5b5d25 529 bleMessage = BLE_NO_MESSAGE;
masakjm 1:9d0e2e5b5d25 530 }
masakjm 1:9d0e2e5b5d25 531
masakjm 1:9d0e2e5b5d25 532 if(! KeyBuff.empty()) { // キーバッファ処理
masakjm 1:9d0e2e5b5d25 533 // DEBUG(" size=%d front=%x\r\n", KeyBuff.size(), KeyBuff.front());
masakjm 1:9d0e2e5b5d25 534
masakjm 1:9d0e2e5b5d25 535 switch (KeyBuff.front() & 0xFF00) {
masakjm 1:9d0e2e5b5d25 536 case BUTTON_STATUS_UP :
masakjm 1:9d0e2e5b5d25 537 ButtonUpProcess();
masakjm 1:9d0e2e5b5d25 538 break;
masakjm 1:9d0e2e5b5d25 539 case BUTTON_STATUS_DOWN :
masakjm 1:9d0e2e5b5d25 540 ButtonDownProcess(KeyBuff.front() & 0xFF);
masakjm 1:9d0e2e5b5d25 541 break;
masakjm 1:9d0e2e5b5d25 542 case BUTTON_STATUS_HOLD :
masakjm 1:9d0e2e5b5d25 543 ButtonHoldProcess(KeyBuff.front() & 0xFF);
masakjm 1:9d0e2e5b5d25 544 break;
masakjm 1:9d0e2e5b5d25 545 }
masakjm 1:9d0e2e5b5d25 546 KeyBuff.pop();
masakjm 1:9d0e2e5b5d25 547 }
masakjm 1:9d0e2e5b5d25 548
masakjm 1:9d0e2e5b5d25 549 if (DispChar != DispCharLast) { // 表示文字が変更
masakjm 1:9d0e2e5b5d25 550 TurnOffMode = false;
masakjm 1:9d0e2e5b5d25 551 dispTime.reset();
masakjm 1:9d0e2e5b5d25 552 display.enable();
masakjm 1:9d0e2e5b5d25 553 if (DispChar) display.printChar(DispChar);
masakjm 1:9d0e2e5b5d25 554 else display.clear();
masakjm 1:9d0e2e5b5d25 555 }
masakjm 1:9d0e2e5b5d25 556 if (!TurnOffMode) {
masakjm 1:9d0e2e5b5d25 557 if (dispTime.read() > TIME_TURN_OFF) { // 長時間表示
masakjm 1:9d0e2e5b5d25 558 TurnOffMode = true;
masakjm 1:9d0e2e5b5d25 559 display.disable();
masakjm 1:9d0e2e5b5d25 560 }
masakjm 1:9d0e2e5b5d25 561 }
masakjm 1:9d0e2e5b5d25 562 DispCharLast = DispChar;
masakjm 1:9d0e2e5b5d25 563 }
masakjm 1:9d0e2e5b5d25 564 }
masakjm 1:9d0e2e5b5d25 565
masakjm 1:9d0e2e5b5d25 566