Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed-dev nRF51822
main.cpp@4:54cb552e50c4, 2016-07-20 (annotated)
- Committer:
- cho45
- Date:
- Wed Jul 20 02:05:45 2016 +0900
- Revision:
- 4:54cb552e50c4
- Parent:
- 3:266dfa9f8709
- Child:
- 5:65d4e94735b6
update
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| cho45 | 0:be89b5fdea09 | 1 | /* mbed Microcontroller Library |
| cho45 | 0:be89b5fdea09 | 2 | * Copyright (c) 2015 ARM Limited |
| cho45 | 0:be89b5fdea09 | 3 | * |
| cho45 | 0:be89b5fdea09 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| cho45 | 0:be89b5fdea09 | 5 | * you may not use this file except in compliance with the License. |
| cho45 | 0:be89b5fdea09 | 6 | * You may obtain a copy of the License at |
| cho45 | 0:be89b5fdea09 | 7 | * |
| cho45 | 0:be89b5fdea09 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| cho45 | 0:be89b5fdea09 | 9 | * |
| cho45 | 0:be89b5fdea09 | 10 | * Unless required by applicable law or agreed to in writing, software |
| cho45 | 0:be89b5fdea09 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| cho45 | 0:be89b5fdea09 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| cho45 | 0:be89b5fdea09 | 13 | * See the License for the specific language governing permissions and |
| cho45 | 0:be89b5fdea09 | 14 | * limitations under the License. |
| cho45 | 0:be89b5fdea09 | 15 | */ |
| cho45 | 0:be89b5fdea09 | 16 | |
| cho45 | 0:be89b5fdea09 | 17 | #include "mbed.h" |
| cho45 | 0:be89b5fdea09 | 18 | #include "BLE.h" |
| cho45 | 0:be89b5fdea09 | 19 | #include "KeyboardService.h" |
| cho45 | 0:be89b5fdea09 | 20 | #include "BatteryService.h" |
| cho45 | 0:be89b5fdea09 | 21 | #include "DeviceInformationService.h" |
| cho45 |
4:54cb552e50c4 | 22 | #include "mcp23017.h" |
| cho45 | 0:be89b5fdea09 | 23 | |
| cho45 | 0:be89b5fdea09 | 24 | static const char MODEL_NAME[] = "keyboard"; |
| cho45 | 0:be89b5fdea09 | 25 | static const char SERIAL_NUMBER[] = "X00000"; |
| cho45 | 0:be89b5fdea09 | 26 | static const char HARDWARE_REVISION[] = "0.1"; |
| cho45 | 0:be89b5fdea09 | 27 | static const char FIRMWARE_REVISION[] = "0.1"; |
| cho45 | 0:be89b5fdea09 | 28 | static const char SOFTWARE_REVISION[] = "0.0"; |
| cho45 | 0:be89b5fdea09 | 29 | |
| cho45 | 0:be89b5fdea09 | 30 | static const uint8_t DEVICE_NAME[] = "my keyboard"; |
| cho45 | 0:be89b5fdea09 | 31 | static const uint8_t SHORT_DEVICE_NAME[] = "kbd1"; |
| cho45 | 0:be89b5fdea09 | 32 | |
| cho45 |
2:c2e3f240640c | 33 | static const bool ENABLE_BONDING = true; |
| cho45 |
2:c2e3f240640c | 34 | static const bool REQUIRE_MITM = true; |
| cho45 |
2:c2e3f240640c | 35 | static const uint8_t PASSKEY[6] = {'1','2','3','4','5','6'}; // must be 6-digits number |
| cho45 |
2:c2e3f240640c | 36 | |
| cho45 | 0:be89b5fdea09 | 37 | static const uint16_t uuid16_list[] = { |
| cho45 |
2:c2e3f240640c | 38 | GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, |
| cho45 |
2:c2e3f240640c | 39 | GattService::UUID_DEVICE_INFORMATION_SERVICE, |
| cho45 |
2:c2e3f240640c | 40 | GattService::UUID_BATTERY_SERVICE |
| cho45 | 0:be89b5fdea09 | 41 | }; |
| cho45 | 0:be89b5fdea09 | 42 | |
| cho45 | 0:be89b5fdea09 | 43 | KeyboardService* keyboardService; |
| cho45 | 0:be89b5fdea09 | 44 | BatteryService* batteryService; |
| cho45 | 0:be89b5fdea09 | 45 | DeviceInformationService* deviceInformationService; |
| cho45 | 0:be89b5fdea09 | 46 | |
| cho45 |
4:54cb552e50c4 | 47 | I2C i2c(I2C_SDA0, I2C_SCL0); |
| cho45 |
4:54cb552e50c4 | 48 | MCP23017 gpio1(i2c, 0b0100000); |
| cho45 |
4:54cb552e50c4 | 49 | InterruptIn buttonInt(P0_5); |
| cho45 | 0:be89b5fdea09 | 50 | |
| cho45 |
3:266dfa9f8709 | 51 | void updateBatteryLevel() { |
| cho45 |
3:266dfa9f8709 | 52 | if (!batteryService) return; |
| cho45 |
3:266dfa9f8709 | 53 | static const float BATTERY_MAX = 2.4; |
| cho45 |
4:54cb552e50c4 | 54 | static const float REFERNECE = 1.2; |
| cho45 |
4:54cb552e50c4 | 55 | static const float PRESCALE = 3; |
| cho45 |
3:266dfa9f8709 | 56 | |
| cho45 |
4:54cb552e50c4 | 57 | NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; |
| cho45 |
4:54cb552e50c4 | 58 | |
| cho45 |
4:54cb552e50c4 | 59 | // Use internal 1.2V reference for batteryInput |
| cho45 |
4:54cb552e50c4 | 60 | // 1/3 pre-scaled input and 1.2V internal band gap reference |
| cho45 |
4:54cb552e50c4 | 61 | // ref. mbed-src/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/analogin_api.c |
| cho45 |
4:54cb552e50c4 | 62 | NRF_ADC->CONFIG = |
| cho45 |
4:54cb552e50c4 | 63 | (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) | |
| cho45 |
4:54cb552e50c4 | 64 | // Use VDD 1/3 for input |
| cho45 |
4:54cb552e50c4 | 65 | (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | |
| cho45 |
4:54cb552e50c4 | 66 | // Use internal band gap for reference |
| cho45 |
4:54cb552e50c4 | 67 | (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) | |
| cho45 |
4:54cb552e50c4 | 68 | (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); |
| cho45 |
4:54cb552e50c4 | 69 | |
| cho45 |
4:54cb552e50c4 | 70 | // Start ADC |
| cho45 |
4:54cb552e50c4 | 71 | NRF_ADC->TASKS_START = 1; |
| cho45 |
4:54cb552e50c4 | 72 | while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) { |
| cho45 |
4:54cb552e50c4 | 73 | // busy loop |
| cho45 |
4:54cb552e50c4 | 74 | } |
| cho45 |
4:54cb552e50c4 | 75 | |
| cho45 |
4:54cb552e50c4 | 76 | // Read ADC result |
| cho45 |
4:54cb552e50c4 | 77 | uint16_t raw10bit = static_cast<uint16_t>(NRF_ADC->RESULT); |
| cho45 |
4:54cb552e50c4 | 78 | float ratio = raw10bit / static_cast<float>(1<<10); |
| cho45 |
4:54cb552e50c4 | 79 | |
| cho45 |
4:54cb552e50c4 | 80 | float batteryVoltage = ratio * (REFERNECE * PRESCALE); |
| cho45 |
3:266dfa9f8709 | 81 | float percentage = (batteryVoltage / BATTERY_MAX) * 100; |
| cho45 |
3:266dfa9f8709 | 82 | if (percentage > 100) { |
| cho45 |
3:266dfa9f8709 | 83 | percentage = 100; |
| cho45 |
3:266dfa9f8709 | 84 | } |
| cho45 |
4:54cb552e50c4 | 85 | printf("updateBatteryLevel %f V : %d/100\r\n", batteryVoltage, static_cast<uint8_t>(percentage)); |
| cho45 |
3:266dfa9f8709 | 86 | batteryService->updateBatteryLevel(static_cast<uint8_t>(percentage)); |
| cho45 |
3:266dfa9f8709 | 87 | } |
| cho45 |
3:266dfa9f8709 | 88 | |
| cho45 |
3:266dfa9f8709 | 89 | |
| cho45 | 0:be89b5fdea09 | 90 | static void onConnect(const Gap::ConnectionCallbackParams_t *params) { |
| cho45 |
2:c2e3f240640c | 91 | printf("onConnect\r\n"); |
| cho45 | 0:be89b5fdea09 | 92 | } |
| cho45 | 0:be89b5fdea09 | 93 | |
| cho45 |
2:c2e3f240640c | 94 | static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) { |
| cho45 |
2:c2e3f240640c | 95 | printf("onDisconnect\r\n"); |
| cho45 |
2:c2e3f240640c | 96 | BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); |
| cho45 |
2:c2e3f240640c | 97 | } |
| cho45 |
2:c2e3f240640c | 98 | |
| cho45 |
2:c2e3f240640c | 99 | static void onTimeout(const Gap::TimeoutSource_t source) { |
| cho45 |
2:c2e3f240640c | 100 | printf("onTimeout\r\n"); |
| cho45 |
2:c2e3f240640c | 101 | BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); |
| cho45 |
2:c2e3f240640c | 102 | } |
| cho45 | 0:be89b5fdea09 | 103 | |
| cho45 | 0:be89b5fdea09 | 104 | static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) { |
| cho45 |
2:c2e3f240640c | 105 | printf("Input passKey: "); |
| cho45 |
2:c2e3f240640c | 106 | for (unsigned i = 0; i < Gap::ADDR_LEN; i++) { |
| cho45 |
2:c2e3f240640c | 107 | printf("%c", passkey[i]); |
| cho45 |
2:c2e3f240640c | 108 | } |
| cho45 |
2:c2e3f240640c | 109 | printf("\r\n"); |
| cho45 |
2:c2e3f240640c | 110 | } |
| cho45 |
2:c2e3f240640c | 111 | |
| cho45 |
2:c2e3f240640c | 112 | static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) { |
| cho45 |
2:c2e3f240640c | 113 | if (status == SecurityManager::SEC_STATUS_SUCCESS) { |
| cho45 |
2:c2e3f240640c | 114 | printf("Security success %d\r\n", status); |
| cho45 |
2:c2e3f240640c | 115 | } else { |
| cho45 |
2:c2e3f240640c | 116 | printf("Security failed %d\r\n", status); |
| cho45 |
2:c2e3f240640c | 117 | } |
| cho45 |
2:c2e3f240640c | 118 | } |
| cho45 |
2:c2e3f240640c | 119 | |
| cho45 |
2:c2e3f240640c | 120 | static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) { |
| cho45 |
2:c2e3f240640c | 121 | printf("Security setup initiated\r\n"); |
| cho45 | 0:be89b5fdea09 | 122 | } |
| cho45 | 0:be89b5fdea09 | 123 | |
| cho45 |
2:c2e3f240640c | 124 | static void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) { |
| cho45 |
2:c2e3f240640c | 125 | // https://developer.mbed.org/compiler/#nav:/keyboard/BLE_API/ble/blecommon.h; |
| cho45 |
2:c2e3f240640c | 126 | ble_error_t error; |
| cho45 |
2:c2e3f240640c | 127 | BLE &ble = params->ble; |
| cho45 |
2:c2e3f240640c | 128 | |
| cho45 |
2:c2e3f240640c | 129 | error = params->error; |
| cho45 |
2:c2e3f240640c | 130 | if (error != BLE_ERROR_NONE) { |
| cho45 |
2:c2e3f240640c | 131 | printf("error on ble.init() \r\n"); |
| cho45 |
2:c2e3f240640c | 132 | goto return_error; |
| cho45 |
2:c2e3f240640c | 133 | } |
| cho45 |
2:c2e3f240640c | 134 | |
| cho45 |
2:c2e3f240640c | 135 | ble.gap().onDisconnection(onDisconnect); |
| cho45 |
2:c2e3f240640c | 136 | ble.gap().onConnection(onConnect); |
| cho45 |
2:c2e3f240640c | 137 | ble.gap().onTimeout(onTimeout); |
| cho45 |
2:c2e3f240640c | 138 | |
| cho45 |
2:c2e3f240640c | 139 | printf("setup ble security manager\r\n"); |
| cho45 |
2:c2e3f240640c | 140 | ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback); |
| cho45 |
2:c2e3f240640c | 141 | ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback); |
| cho45 |
2:c2e3f240640c | 142 | ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); |
| cho45 |
2:c2e3f240640c | 143 | // bonding with hard-coded passkey. |
| cho45 |
2:c2e3f240640c | 144 | error = ble.securityManager().init(ENABLE_BONDING, REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY, PASSKEY); |
| cho45 |
2:c2e3f240640c | 145 | if (error != BLE_ERROR_NONE) { |
| cho45 |
2:c2e3f240640c | 146 | printf("error on ble.securityManager().init()"); |
| cho45 |
2:c2e3f240640c | 147 | goto return_error; |
| cho45 |
2:c2e3f240640c | 148 | } |
| cho45 |
2:c2e3f240640c | 149 | |
| cho45 |
2:c2e3f240640c | 150 | keyboardService = new KeyboardService(ble); |
| cho45 |
2:c2e3f240640c | 151 | deviceInformationService = new DeviceInformationService(ble, "lowreal.net", MODEL_NAME, SERIAL_NUMBER, HARDWARE_REVISION, FIRMWARE_REVISION, SOFTWARE_REVISION); |
| cho45 |
3:266dfa9f8709 | 152 | batteryService = new BatteryService(ble, 100); |
| cho45 |
3:266dfa9f8709 | 153 | updateBatteryLevel(); |
| cho45 | 0:be89b5fdea09 | 154 | |
| cho45 |
2:c2e3f240640c | 155 | printf("general setup\r\n"); |
| cho45 |
2:c2e3f240640c | 156 | error = ble.gap().accumulateAdvertisingPayload( |
| cho45 |
2:c2e3f240640c | 157 | GapAdvertisingData::BREDR_NOT_SUPPORTED | |
| cho45 |
2:c2e3f240640c | 158 | GapAdvertisingData::LE_GENERAL_DISCOVERABLE |
| cho45 |
2:c2e3f240640c | 159 | ); |
| cho45 |
2:c2e3f240640c | 160 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 161 | |
| cho45 |
2:c2e3f240640c | 162 | printf("set COMPLETE_LIST_16BIT_SERVICE_IDS\r\n"); |
| cho45 |
2:c2e3f240640c | 163 | error = ble.gap().accumulateAdvertisingPayload( |
| cho45 |
2:c2e3f240640c | 164 | GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, |
| cho45 |
2:c2e3f240640c | 165 | (uint8_t*)uuid16_list, sizeof(uuid16_list) |
| cho45 |
2:c2e3f240640c | 166 | ); |
| cho45 |
2:c2e3f240640c | 167 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 168 | |
| cho45 |
2:c2e3f240640c | 169 | printf("set advertising\r\n"); |
| cho45 |
2:c2e3f240640c | 170 | // see 5.1.2: HID over GATT Specification (pg. 25) |
| cho45 |
2:c2e3f240640c | 171 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
| cho45 | 0:be89b5fdea09 | 172 | |
| cho45 |
2:c2e3f240640c | 173 | printf("set advertising interval\r\n"); |
| cho45 |
2:c2e3f240640c | 174 | ble.gap().setAdvertisingInterval(50); |
| cho45 |
2:c2e3f240640c | 175 | // XXX |
| cho45 |
2:c2e3f240640c | 176 | // ble.gap().setAdvertisingTimeout(0); |
| cho45 |
2:c2e3f240640c | 177 | |
| cho45 |
2:c2e3f240640c | 178 | printf("set keyboard\r\n"); |
| cho45 |
2:c2e3f240640c | 179 | error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD); |
| cho45 |
2:c2e3f240640c | 180 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 181 | |
| cho45 |
2:c2e3f240640c | 182 | printf("set complete local name\r\n"); |
| cho45 |
2:c2e3f240640c | 183 | error = ble.gap().accumulateAdvertisingPayload( |
| cho45 |
2:c2e3f240640c | 184 | GapAdvertisingData::COMPLETE_LOCAL_NAME, |
| cho45 |
2:c2e3f240640c | 185 | DEVICE_NAME, sizeof(DEVICE_NAME) |
| cho45 |
2:c2e3f240640c | 186 | ); |
| cho45 |
2:c2e3f240640c | 187 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 188 | |
| cho45 |
2:c2e3f240640c | 189 | printf("set device name\r\n"); |
| cho45 |
2:c2e3f240640c | 190 | error = ble.gap().setDeviceName(DEVICE_NAME); |
| cho45 |
2:c2e3f240640c | 191 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 192 | // ble.gap().setTxPower(-12); |
| cho45 | 0:be89b5fdea09 | 193 | |
| cho45 | 0:be89b5fdea09 | 194 | |
| cho45 |
2:c2e3f240640c | 195 | printf("advertising\r\n"); |
| cho45 |
2:c2e3f240640c | 196 | error = ble.gap().startAdvertising(); |
| cho45 |
2:c2e3f240640c | 197 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 198 | return; |
| cho45 | 0:be89b5fdea09 | 199 | |
| cho45 |
2:c2e3f240640c | 200 | return_error: |
| cho45 |
2:c2e3f240640c | 201 | printf("error with %d\r\n", error); |
| cho45 |
2:c2e3f240640c | 202 | return; |
| cho45 | 0:be89b5fdea09 | 203 | } |
| cho45 | 0:be89b5fdea09 | 204 | |
| cho45 |
4:54cb552e50c4 | 205 | class MyKeyboardService : public HIDServiceBase { |
| cho45 |
4:54cb552e50c4 | 206 | union { |
| cho45 |
4:54cb552e50c4 | 207 | uint8_t raw[8]; |
| cho45 |
4:54cb552e50c4 | 208 | struct { |
| cho45 |
4:54cb552e50c4 | 209 | uint8_t modifier; |
| cho45 |
4:54cb552e50c4 | 210 | uint8_t padding; |
| cho45 |
4:54cb552e50c4 | 211 | uint8_t keycode[6]; |
| cho45 |
4:54cb552e50c4 | 212 | } data; |
| cho45 |
4:54cb552e50c4 | 213 | } inputReportData; |
| cho45 |
4:54cb552e50c4 | 214 | |
| cho45 |
4:54cb552e50c4 | 215 | union { |
| cho45 |
4:54cb552e50c4 | 216 | uint8_t raw[1]; |
| cho45 |
4:54cb552e50c4 | 217 | } outputReportData; |
| cho45 |
4:54cb552e50c4 | 218 | public: |
| cho45 |
4:54cb552e50c4 | 219 | MyKeyboardService(BLE& _ble) : |
| cho45 |
4:54cb552e50c4 | 220 | HIDServiceBase( |
| cho45 |
4:54cb552e50c4 | 221 | _ble, |
| cho45 |
4:54cb552e50c4 | 222 | KEYBOARD_REPORT_MAP, |
| cho45 |
4:54cb552e50c4 | 223 | sizeof(KEYBOARD_REPORT_MAP), |
| cho45 |
4:54cb552e50c4 | 224 | inputReport = inputReportData.raw, |
| cho45 |
4:54cb552e50c4 | 225 | outputReport = outputReportData.raw, |
| cho45 |
4:54cb552e50c4 | 226 | featureReport = NULL, |
| cho45 |
4:54cb552e50c4 | 227 | inputReportLength = sizeof(inputReportData), |
| cho45 |
4:54cb552e50c4 | 228 | outputReportLength = sizeof(outputReportData), |
| cho45 |
4:54cb552e50c4 | 229 | featureReportLength = 0, |
| cho45 |
4:54cb552e50c4 | 230 | reportTickerDelay = 24 |
| cho45 |
4:54cb552e50c4 | 231 | ) |
| cho45 |
4:54cb552e50c4 | 232 | { |
| cho45 |
4:54cb552e50c4 | 233 | } |
| cho45 |
4:54cb552e50c4 | 234 | |
| cho45 |
4:54cb552e50c4 | 235 | void appendReportData(uint8_t keycode) { |
| cho45 |
4:54cb552e50c4 | 236 | for (int i = 0; i < 6; i++) { |
| cho45 |
4:54cb552e50c4 | 237 | if (inputReportData.data.keycode[i] == 0) { |
| cho45 |
4:54cb552e50c4 | 238 | inputReportData.data.keycode[i] = keycode; |
| cho45 |
4:54cb552e50c4 | 239 | startReportTicker(); |
| cho45 |
4:54cb552e50c4 | 240 | return; |
| cho45 |
4:54cb552e50c4 | 241 | } |
| cho45 |
4:54cb552e50c4 | 242 | } |
| cho45 |
2:c2e3f240640c | 243 | |
| cho45 |
4:54cb552e50c4 | 244 | // TODO: report data is full |
| cho45 |
4:54cb552e50c4 | 245 | } |
| cho45 |
4:54cb552e50c4 | 246 | |
| cho45 |
4:54cb552e50c4 | 247 | void deleteReportData(uint8_t keycode) { |
| cho45 |
4:54cb552e50c4 | 248 | for (int i = 0; i < 6; i++) { |
| cho45 |
4:54cb552e50c4 | 249 | if (inputReportData.data.keycode[i] == keycode) { |
| cho45 |
4:54cb552e50c4 | 250 | inputReportData.data.keycode[i] = 0; |
| cho45 |
4:54cb552e50c4 | 251 | startReportTicker(); |
| cho45 |
4:54cb552e50c4 | 252 | return; |
| cho45 |
4:54cb552e50c4 | 253 | } |
| cho45 |
4:54cb552e50c4 | 254 | } |
| cho45 |
2:c2e3f240640c | 255 | } |
| cho45 |
4:54cb552e50c4 | 256 | |
| cho45 |
4:54cb552e50c4 | 257 | bool isKeyPressed() { |
| cho45 |
4:54cb552e50c4 | 258 | for (int i = 0; i < 8; i++) { |
| cho45 |
4:54cb552e50c4 | 259 | if (inputReportData.raw[i]) { |
| cho45 |
4:54cb552e50c4 | 260 | return 1; |
| cho45 |
4:54cb552e50c4 | 261 | } |
| cho45 |
4:54cb552e50c4 | 262 | } |
| cho45 |
4:54cb552e50c4 | 263 | return 0; |
| cho45 |
4:54cb552e50c4 | 264 | } |
| cho45 |
2:c2e3f240640c | 265 | |
| cho45 |
4:54cb552e50c4 | 266 | virtual void sendCallback(void) { |
| cho45 |
4:54cb552e50c4 | 267 | ble_error_t error = HIDServiceBase::send(inputReportData.raw); |
| cho45 |
4:54cb552e50c4 | 268 | if (error == BLE_STACK_BUSY) { |
| cho45 |
4:54cb552e50c4 | 269 | // retry after |
| cho45 |
4:54cb552e50c4 | 270 | return; |
| cho45 |
4:54cb552e50c4 | 271 | } |
| cho45 |
4:54cb552e50c4 | 272 | |
| cho45 |
4:54cb552e50c4 | 273 | if (!isKeyPressed()) { |
| cho45 |
4:54cb552e50c4 | 274 | stopReportTicker(); |
| cho45 |
4:54cb552e50c4 | 275 | } |
| cho45 |
4:54cb552e50c4 | 276 | } |
| cho45 |
4:54cb552e50c4 | 277 | }; |
| cho45 |
4:54cb552e50c4 | 278 | |
| cho45 |
4:54cb552e50c4 | 279 | void buttonIntCallback() { |
| cho45 |
4:54cb552e50c4 | 280 | int ok; |
| cho45 |
4:54cb552e50c4 | 281 | printf("buttonInt!!\r\n"); |
| cho45 |
4:54cb552e50c4 | 282 | uint8_t read = gpio1.read8(MCP23017::GPIOA, ok); |
| cho45 |
4:54cb552e50c4 | 283 | printf("read %x\r\n", read); |
| cho45 |
2:c2e3f240640c | 284 | } |
| cho45 |
2:c2e3f240640c | 285 | |
| cho45 | 0:be89b5fdea09 | 286 | int main(void) { |
| cho45 |
4:54cb552e50c4 | 287 | // printf("init\r\n"); |
| cho45 |
4:54cb552e50c4 | 288 | |
| cho45 |
4:54cb552e50c4 | 289 | // mbed's Serial of TARGET_RBLAB_BLENANO sucks |
| cho45 |
4:54cb552e50c4 | 290 | // DO NOT CONNECT RTS/CTS AUTOMATICALY! |
| cho45 |
4:54cb552e50c4 | 291 | NRF_UART0->PSELRTS = 0xFFFFFFFFUL; |
| cho45 |
4:54cb552e50c4 | 292 | NRF_UART0->PSELCTS = 0xFFFFFFFFUL; |
| cho45 |
4:54cb552e50c4 | 293 | |
| cho45 |
4:54cb552e50c4 | 294 | buttonInt.mode(PullUp); |
| cho45 |
4:54cb552e50c4 | 295 | buttonInt.fall(buttonIntCallback); |
| cho45 |
4:54cb552e50c4 | 296 | |
| cho45 |
4:54cb552e50c4 | 297 | int ok; |
| cho45 |
4:54cb552e50c4 | 298 | |
| cho45 |
4:54cb552e50c4 | 299 | // 100kHz |
| cho45 |
4:54cb552e50c4 | 300 | i2c.frequency(100000); |
| cho45 |
4:54cb552e50c4 | 301 | |
| cho45 |
4:54cb552e50c4 | 302 | ok = gpio1.write8( |
| cho45 |
4:54cb552e50c4 | 303 | MCP23017::IOCON, |
| cho45 |
4:54cb552e50c4 | 304 | 0<<MCP23017::BANK | |
| cho45 |
4:54cb552e50c4 | 305 | 1<<MCP23017::MIRROR | |
| cho45 |
4:54cb552e50c4 | 306 | 1<<MCP23017::SEQOP | |
| cho45 |
4:54cb552e50c4 | 307 | 0<<MCP23017::DISSLW | |
| cho45 |
4:54cb552e50c4 | 308 | 1<<MCP23017::ODR |
| cho45 |
4:54cb552e50c4 | 309 | ); |
| cho45 |
4:54cb552e50c4 | 310 | |
| cho45 |
4:54cb552e50c4 | 311 | // IODIR |
| cho45 |
4:54cb552e50c4 | 312 | // 1: input |
| cho45 |
4:54cb552e50c4 | 313 | // 0: output |
| cho45 |
4:54cb552e50c4 | 314 | ok = gpio1.write16( |
| cho45 |
4:54cb552e50c4 | 315 | MCP23017::IODIRA, |
| cho45 |
4:54cb552e50c4 | 316 | 0b1111111100000000 |
| cho45 |
4:54cb552e50c4 | 317 | ); |
| cho45 |
4:54cb552e50c4 | 318 | |
| cho45 |
4:54cb552e50c4 | 319 | // INPUT POLARITY |
| cho45 |
4:54cb552e50c4 | 320 | ok = gpio1.write8( |
| cho45 |
4:54cb552e50c4 | 321 | MCP23017::IPOLA, |
| cho45 |
4:54cb552e50c4 | 322 | 0b00000000 |
| cho45 |
4:54cb552e50c4 | 323 | ); |
| cho45 |
4:54cb552e50c4 | 324 | // INTERRUPT-ON-CHANGE Enable |
| cho45 |
4:54cb552e50c4 | 325 | ok = gpio1.write8( |
| cho45 |
4:54cb552e50c4 | 326 | MCP23017::GPINTENA, |
| cho45 |
4:54cb552e50c4 | 327 | 0b11111111 |
| cho45 |
4:54cb552e50c4 | 328 | ); |
| cho45 |
4:54cb552e50c4 | 329 | // INTERRUPT-ON-CHANGE Control |
| cho45 |
4:54cb552e50c4 | 330 | // 1: compared with DEFVAL |
| cho45 |
4:54cb552e50c4 | 331 | // 0: compared to previous value |
| cho45 |
4:54cb552e50c4 | 332 | ok = gpio1.write8( |
| cho45 |
4:54cb552e50c4 | 333 | MCP23017::INTCONA, |
| cho45 |
4:54cb552e50c4 | 334 | 0b00000000 |
| cho45 |
4:54cb552e50c4 | 335 | ); |
| cho45 |
4:54cb552e50c4 | 336 | // PULL-UP (for input pin) |
| cho45 |
4:54cb552e50c4 | 337 | // 1: pull-up enabled |
| cho45 |
4:54cb552e50c4 | 338 | // 0: pull-up disabled |
| cho45 |
4:54cb552e50c4 | 339 | ok = gpio1.write8( |
| cho45 |
4:54cb552e50c4 | 340 | MCP23017::GPPUA, |
| cho45 |
4:54cb552e50c4 | 341 | 0b11111111 |
| cho45 |
4:54cb552e50c4 | 342 | ); |
| cho45 |
4:54cb552e50c4 | 343 | |
| cho45 |
4:54cb552e50c4 | 344 | if (!ok) { |
| cho45 |
4:54cb552e50c4 | 345 | printf("failed to write to i2c bus\r\n"); |
| cho45 |
4:54cb552e50c4 | 346 | } else { |
| cho45 |
4:54cb552e50c4 | 347 | printf("wrote to i2c bus\r\n"); |
| cho45 |
4:54cb552e50c4 | 348 | } |
| cho45 |
4:54cb552e50c4 | 349 | |
| cho45 |
4:54cb552e50c4 | 350 | uint8_t read = gpio1.read8(MCP23017::GPIOA, ok); |
| cho45 |
4:54cb552e50c4 | 351 | printf("read %x\r\n", read); |
| cho45 |
4:54cb552e50c4 | 352 | |
| cho45 |
4:54cb552e50c4 | 353 | while (1) {} |
| cho45 |
4:54cb552e50c4 | 354 | |
| cho45 |
4:54cb552e50c4 | 355 | return; |
| cho45 | 0:be89b5fdea09 | 356 | |
| cho45 |
2:c2e3f240640c | 357 | // https://github.com/jpbrucker/BLE_HID/blob/master/examples/examples_common.cpp |
| cho45 | 0:be89b5fdea09 | 358 | |
| cho45 |
2:c2e3f240640c | 359 | printf("ble.init\r\n"); |
| cho45 |
2:c2e3f240640c | 360 | BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE); |
| cho45 |
2:c2e3f240640c | 361 | ble.init(bleInitComplete); |
| cho45 | 0:be89b5fdea09 | 362 | |
| cho45 |
2:c2e3f240640c | 363 | while (!ble.hasInitialized()) { } |
| cho45 | 0:be89b5fdea09 | 364 | |
| cho45 |
2:c2e3f240640c | 365 | printf("ble.hasIntialized\r\n"); |
| cho45 | 0:be89b5fdea09 | 366 | |
| cho45 |
2:c2e3f240640c | 367 | while (1) { |
| cho45 |
2:c2e3f240640c | 368 | ble.waitForEvent(); |
| cho45 |
2:c2e3f240640c | 369 | } |
| cho45 |
2:c2e3f240640c | 370 | } |