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@3:266dfa9f8709, 2016-07-19 (annotated)
- Committer:
- cho45
- Date:
- Tue Jul 19 01:06:00 2016 +0900
- Revision:
- 3:266dfa9f8709
- Parent:
- 2:c2e3f240640c
- Child:
- 4:54cb552e50c4
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 | 0:be89b5fdea09 | 22 | |
| cho45 | 0:be89b5fdea09 | 23 | static const char MODEL_NAME[] = "keyboard"; |
| cho45 | 0:be89b5fdea09 | 24 | static const char SERIAL_NUMBER[] = "X00000"; |
| cho45 | 0:be89b5fdea09 | 25 | static const char HARDWARE_REVISION[] = "0.1"; |
| cho45 | 0:be89b5fdea09 | 26 | static const char FIRMWARE_REVISION[] = "0.1"; |
| cho45 | 0:be89b5fdea09 | 27 | static const char SOFTWARE_REVISION[] = "0.0"; |
| cho45 | 0:be89b5fdea09 | 28 | |
| cho45 | 0:be89b5fdea09 | 29 | static const uint8_t DEVICE_NAME[] = "my keyboard"; |
| cho45 | 0:be89b5fdea09 | 30 | static const uint8_t SHORT_DEVICE_NAME[] = "kbd1"; |
| cho45 | 0:be89b5fdea09 | 31 | |
| cho45 |
2:c2e3f240640c | 32 | static const bool ENABLE_BONDING = true; |
| cho45 |
2:c2e3f240640c | 33 | static const bool REQUIRE_MITM = true; |
| cho45 |
2:c2e3f240640c | 34 | static const uint8_t PASSKEY[6] = {'1','2','3','4','5','6'}; // must be 6-digits number |
| cho45 |
2:c2e3f240640c | 35 | |
| cho45 | 0:be89b5fdea09 | 36 | InterruptIn button1(D2); |
| cho45 | 0:be89b5fdea09 | 37 | |
| cho45 | 0:be89b5fdea09 | 38 | static const uint16_t uuid16_list[] = { |
| cho45 |
2:c2e3f240640c | 39 | GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, |
| cho45 |
2:c2e3f240640c | 40 | GattService::UUID_DEVICE_INFORMATION_SERVICE, |
| cho45 |
2:c2e3f240640c | 41 | GattService::UUID_BATTERY_SERVICE |
| cho45 | 0:be89b5fdea09 | 42 | }; |
| cho45 | 0:be89b5fdea09 | 43 | |
| cho45 | 0:be89b5fdea09 | 44 | KeyboardService* keyboardService; |
| cho45 | 0:be89b5fdea09 | 45 | BatteryService* batteryService; |
| cho45 | 0:be89b5fdea09 | 46 | DeviceInformationService* deviceInformationService; |
| cho45 | 0:be89b5fdea09 | 47 | |
| cho45 | 0:be89b5fdea09 | 48 | // I2C i2c(D2, D3); |
| cho45 |
2:c2e3f240640c | 49 | AnalogIn batteryInput(A4); |
| 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 |
3:266dfa9f8709 | 54 | |
| cho45 |
3:266dfa9f8709 | 55 | float batteryVoltage = batteryInput.read() * 1.2 * 3; |
| cho45 |
3:266dfa9f8709 | 56 | float percentage = (batteryVoltage / BATTERY_MAX) * 100; |
| cho45 |
3:266dfa9f8709 | 57 | if (percentage > 100) { |
| cho45 |
3:266dfa9f8709 | 58 | percentage = 100; |
| cho45 |
3:266dfa9f8709 | 59 | } |
| cho45 |
3:266dfa9f8709 | 60 | printf("updateBatteryLevel %d\r\n",static_cast<uint8_t>(percentage)); |
| cho45 |
3:266dfa9f8709 | 61 | batteryService->updateBatteryLevel(static_cast<uint8_t>(percentage)); |
| cho45 |
3:266dfa9f8709 | 62 | } |
| cho45 |
3:266dfa9f8709 | 63 | |
| cho45 |
3:266dfa9f8709 | 64 | |
| cho45 | 0:be89b5fdea09 | 65 | static void onConnect(const Gap::ConnectionCallbackParams_t *params) { |
| cho45 |
2:c2e3f240640c | 66 | printf("onConnect\r\n"); |
| cho45 | 0:be89b5fdea09 | 67 | } |
| cho45 | 0:be89b5fdea09 | 68 | |
| cho45 |
2:c2e3f240640c | 69 | static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) { |
| cho45 |
2:c2e3f240640c | 70 | printf("onDisconnect\r\n"); |
| cho45 |
2:c2e3f240640c | 71 | BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); |
| cho45 |
2:c2e3f240640c | 72 | } |
| cho45 |
2:c2e3f240640c | 73 | |
| cho45 |
2:c2e3f240640c | 74 | static void onTimeout(const Gap::TimeoutSource_t source) { |
| cho45 |
2:c2e3f240640c | 75 | printf("onTimeout\r\n"); |
| cho45 |
2:c2e3f240640c | 76 | BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); |
| cho45 |
2:c2e3f240640c | 77 | } |
| cho45 | 0:be89b5fdea09 | 78 | |
| cho45 | 0:be89b5fdea09 | 79 | static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) { |
| cho45 |
2:c2e3f240640c | 80 | printf("Input passKey: "); |
| cho45 |
2:c2e3f240640c | 81 | for (unsigned i = 0; i < Gap::ADDR_LEN; i++) { |
| cho45 |
2:c2e3f240640c | 82 | printf("%c", passkey[i]); |
| cho45 |
2:c2e3f240640c | 83 | } |
| cho45 |
2:c2e3f240640c | 84 | printf("\r\n"); |
| cho45 |
2:c2e3f240640c | 85 | } |
| cho45 |
2:c2e3f240640c | 86 | |
| cho45 |
2:c2e3f240640c | 87 | static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) { |
| cho45 |
2:c2e3f240640c | 88 | if (status == SecurityManager::SEC_STATUS_SUCCESS) { |
| cho45 |
2:c2e3f240640c | 89 | printf("Security success %d\r\n", status); |
| cho45 |
2:c2e3f240640c | 90 | } else { |
| cho45 |
2:c2e3f240640c | 91 | printf("Security failed %d\r\n", status); |
| cho45 |
2:c2e3f240640c | 92 | } |
| cho45 |
2:c2e3f240640c | 93 | } |
| cho45 |
2:c2e3f240640c | 94 | |
| cho45 |
2:c2e3f240640c | 95 | static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) { |
| cho45 |
2:c2e3f240640c | 96 | printf("Security setup initiated\r\n"); |
| cho45 | 0:be89b5fdea09 | 97 | } |
| cho45 | 0:be89b5fdea09 | 98 | |
| cho45 |
2:c2e3f240640c | 99 | static void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) { |
| cho45 |
2:c2e3f240640c | 100 | // https://developer.mbed.org/compiler/#nav:/keyboard/BLE_API/ble/blecommon.h; |
| cho45 |
2:c2e3f240640c | 101 | ble_error_t error; |
| cho45 |
2:c2e3f240640c | 102 | BLE &ble = params->ble; |
| cho45 |
2:c2e3f240640c | 103 | |
| cho45 |
2:c2e3f240640c | 104 | error = params->error; |
| cho45 |
2:c2e3f240640c | 105 | if (error != BLE_ERROR_NONE) { |
| cho45 |
2:c2e3f240640c | 106 | printf("error on ble.init() \r\n"); |
| cho45 |
2:c2e3f240640c | 107 | goto return_error; |
| cho45 |
2:c2e3f240640c | 108 | } |
| cho45 |
2:c2e3f240640c | 109 | |
| cho45 |
2:c2e3f240640c | 110 | ble.gap().onDisconnection(onDisconnect); |
| cho45 |
2:c2e3f240640c | 111 | ble.gap().onConnection(onConnect); |
| cho45 |
2:c2e3f240640c | 112 | ble.gap().onTimeout(onTimeout); |
| cho45 |
2:c2e3f240640c | 113 | |
| cho45 |
2:c2e3f240640c | 114 | printf("setup ble security manager\r\n"); |
| cho45 |
2:c2e3f240640c | 115 | ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback); |
| cho45 |
2:c2e3f240640c | 116 | ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback); |
| cho45 |
2:c2e3f240640c | 117 | ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); |
| cho45 |
2:c2e3f240640c | 118 | // bonding with hard-coded passkey. |
| cho45 |
2:c2e3f240640c | 119 | error = ble.securityManager().init(ENABLE_BONDING, REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY, PASSKEY); |
| cho45 |
2:c2e3f240640c | 120 | if (error != BLE_ERROR_NONE) { |
| cho45 |
2:c2e3f240640c | 121 | printf("error on ble.securityManager().init()"); |
| cho45 |
2:c2e3f240640c | 122 | goto return_error; |
| cho45 |
2:c2e3f240640c | 123 | } |
| cho45 |
2:c2e3f240640c | 124 | |
| cho45 |
2:c2e3f240640c | 125 | keyboardService = new KeyboardService(ble); |
| cho45 |
2:c2e3f240640c | 126 | deviceInformationService = new DeviceInformationService(ble, "lowreal.net", MODEL_NAME, SERIAL_NUMBER, HARDWARE_REVISION, FIRMWARE_REVISION, SOFTWARE_REVISION); |
| cho45 |
3:266dfa9f8709 | 127 | batteryService = new BatteryService(ble, 100); |
| cho45 |
3:266dfa9f8709 | 128 | updateBatteryLevel(); |
| cho45 | 0:be89b5fdea09 | 129 | |
| cho45 |
2:c2e3f240640c | 130 | printf("general setup\r\n"); |
| cho45 |
2:c2e3f240640c | 131 | error = ble.gap().accumulateAdvertisingPayload( |
| cho45 |
2:c2e3f240640c | 132 | GapAdvertisingData::BREDR_NOT_SUPPORTED | |
| cho45 |
2:c2e3f240640c | 133 | GapAdvertisingData::LE_GENERAL_DISCOVERABLE |
| cho45 |
2:c2e3f240640c | 134 | ); |
| cho45 |
2:c2e3f240640c | 135 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 136 | |
| cho45 |
2:c2e3f240640c | 137 | printf("set COMPLETE_LIST_16BIT_SERVICE_IDS\r\n"); |
| cho45 |
2:c2e3f240640c | 138 | error = ble.gap().accumulateAdvertisingPayload( |
| cho45 |
2:c2e3f240640c | 139 | GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, |
| cho45 |
2:c2e3f240640c | 140 | (uint8_t*)uuid16_list, sizeof(uuid16_list) |
| cho45 |
2:c2e3f240640c | 141 | ); |
| cho45 |
2:c2e3f240640c | 142 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 143 | |
| cho45 |
2:c2e3f240640c | 144 | printf("set advertising\r\n"); |
| cho45 |
2:c2e3f240640c | 145 | // see 5.1.2: HID over GATT Specification (pg. 25) |
| cho45 |
2:c2e3f240640c | 146 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
| cho45 | 0:be89b5fdea09 | 147 | |
| cho45 |
2:c2e3f240640c | 148 | printf("set advertising interval\r\n"); |
| cho45 |
2:c2e3f240640c | 149 | ble.gap().setAdvertisingInterval(50); |
| cho45 |
2:c2e3f240640c | 150 | // XXX |
| cho45 |
2:c2e3f240640c | 151 | // ble.gap().setAdvertisingTimeout(0); |
| cho45 |
2:c2e3f240640c | 152 | |
| cho45 |
2:c2e3f240640c | 153 | printf("set keyboard\r\n"); |
| cho45 |
2:c2e3f240640c | 154 | error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD); |
| cho45 |
2:c2e3f240640c | 155 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 156 | |
| cho45 |
2:c2e3f240640c | 157 | printf("set complete local name\r\n"); |
| cho45 |
2:c2e3f240640c | 158 | error = ble.gap().accumulateAdvertisingPayload( |
| cho45 |
2:c2e3f240640c | 159 | GapAdvertisingData::COMPLETE_LOCAL_NAME, |
| cho45 |
2:c2e3f240640c | 160 | DEVICE_NAME, sizeof(DEVICE_NAME) |
| cho45 |
2:c2e3f240640c | 161 | ); |
| cho45 |
2:c2e3f240640c | 162 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 163 | |
| cho45 |
2:c2e3f240640c | 164 | printf("set device name\r\n"); |
| cho45 |
2:c2e3f240640c | 165 | error = ble.gap().setDeviceName(DEVICE_NAME); |
| cho45 |
2:c2e3f240640c | 166 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 167 | // ble.gap().setTxPower(-12); |
| cho45 | 0:be89b5fdea09 | 168 | |
| cho45 | 0:be89b5fdea09 | 169 | |
| cho45 |
2:c2e3f240640c | 170 | printf("advertising\r\n"); |
| cho45 |
2:c2e3f240640c | 171 | error = ble.gap().startAdvertising(); |
| cho45 |
2:c2e3f240640c | 172 | if (error != BLE_ERROR_NONE) goto return_error; |
| cho45 |
2:c2e3f240640c | 173 | return; |
| cho45 | 0:be89b5fdea09 | 174 | |
| cho45 |
2:c2e3f240640c | 175 | return_error: |
| cho45 |
2:c2e3f240640c | 176 | printf("error with %d\r\n", error); |
| cho45 |
2:c2e3f240640c | 177 | return; |
| cho45 | 0:be89b5fdea09 | 178 | } |
| cho45 | 0:be89b5fdea09 | 179 | |
| cho45 | 0:be89b5fdea09 | 180 | void send_string(const char * c) { |
| cho45 |
2:c2e3f240640c | 181 | if (!keyboardService) return; |
| cho45 |
2:c2e3f240640c | 182 | |
| cho45 |
2:c2e3f240640c | 183 | if (!keyboardService->isConnected()) { |
| cho45 |
2:c2e3f240640c | 184 | printf("we haven't connected yet..."); |
| cho45 |
2:c2e3f240640c | 185 | } else { |
| cho45 |
2:c2e3f240640c | 186 | int len = strlen(c); |
| cho45 |
2:c2e3f240640c | 187 | keyboardService->printf(c); |
| cho45 |
2:c2e3f240640c | 188 | printf("sending %d chars\r\n", len); |
| cho45 |
2:c2e3f240640c | 189 | } |
| cho45 | 0:be89b5fdea09 | 190 | } |
| cho45 |
2:c2e3f240640c | 191 | |
| cho45 | 0:be89b5fdea09 | 192 | void send_stuff() { |
| cho45 |
2:c2e3f240640c | 193 | send_string("hello world!\n"); |
| cho45 |
2:c2e3f240640c | 194 | } |
| cho45 |
2:c2e3f240640c | 195 | |
| cho45 | 0:be89b5fdea09 | 196 | int main(void) { |
| cho45 |
2:c2e3f240640c | 197 | // Use internal 1.2V reference for batteryInput |
| cho45 |
2:c2e3f240640c | 198 | // 1/3 pre-scaled input and 1.2V internal band gap reference |
| cho45 |
2:c2e3f240640c | 199 | // (mbed uses vdd for reference but i want use band gap) |
| cho45 |
2:c2e3f240640c | 200 | // ref. mbed-src/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/analogin_api.c |
| cho45 |
2:c2e3f240640c | 201 | NRF_ADC->CONFIG = |
| cho45 |
2:c2e3f240640c | 202 | (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) | |
| cho45 |
2:c2e3f240640c | 203 | (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | |
| cho45 |
2:c2e3f240640c | 204 | (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) | |
| cho45 |
2:c2e3f240640c | 205 | (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); |
| cho45 | 0:be89b5fdea09 | 206 | |
| cho45 |
2:c2e3f240640c | 207 | // https://github.com/jpbrucker/BLE_HID/blob/master/examples/examples_common.cpp |
| cho45 | 0:be89b5fdea09 | 208 | |
| cho45 |
2:c2e3f240640c | 209 | printf("ble.init\r\n"); |
| cho45 |
2:c2e3f240640c | 210 | BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE); |
| cho45 |
2:c2e3f240640c | 211 | ble.init(bleInitComplete); |
| cho45 | 0:be89b5fdea09 | 212 | |
| cho45 |
2:c2e3f240640c | 213 | button1.rise(send_stuff); |
| cho45 | 0:be89b5fdea09 | 214 | |
| cho45 |
2:c2e3f240640c | 215 | while (!ble.hasInitialized()) { } |
| cho45 | 0:be89b5fdea09 | 216 | |
| cho45 |
2:c2e3f240640c | 217 | printf("ble.hasIntialized\r\n"); |
| cho45 | 0:be89b5fdea09 | 218 | |
| cho45 |
2:c2e3f240640c | 219 | while (1) { |
| cho45 |
2:c2e3f240640c | 220 | ble.waitForEvent(); |
| cho45 |
2:c2e3f240640c | 221 | } |
| cho45 |
2:c2e3f240640c | 222 | } |