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