Hiroh Satoh / keyboard Featured

Dependencies:   BLE_API mbed-dev nRF51822

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?

UserRevisionLine numberNew 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 }