BLE switch interface with GROVE joystic for micro:bit http://mahoro-ba.net/e2073.html

Dependencies:   microbit

Committer:
masakjm
Date:
Fri Feb 22 21:17:13 2019 +0000
Revision:
11:8e0b379efcb3
Parent:
7:e2779d2fef9c
Child:
12:7fb193872bec

        

Who changed what in which revision?

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