Hiroh Satoh / keyboard Featured

Dependencies:   BLE_API mbed-dev nRF51822

Committer:
cho45
Date:
Thu Jul 21 00:38:09 2016 +0900
Revision:
5:65d4e94735b6
Parent:
4:54cb552e50c4
Child:
6:f1c3ea8bc850
keyboard controller

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 4:54cb552e50c4 22 #include "mcp23017.h"
cho45 5:65d4e94735b6 23 #include "keymap.h"
cho45 0:be89b5fdea09 24
cho45 0:be89b5fdea09 25 static const char MODEL_NAME[] = "keyboard";
cho45 0:be89b5fdea09 26 static const char SERIAL_NUMBER[] = "X00000";
cho45 0:be89b5fdea09 27 static const char HARDWARE_REVISION[] = "0.1";
cho45 0:be89b5fdea09 28 static const char FIRMWARE_REVISION[] = "0.1";
cho45 0:be89b5fdea09 29 static const char SOFTWARE_REVISION[] = "0.0";
cho45 0:be89b5fdea09 30
cho45 0:be89b5fdea09 31 static const uint8_t DEVICE_NAME[] = "my keyboard";
cho45 0:be89b5fdea09 32 static const uint8_t SHORT_DEVICE_NAME[] = "kbd1";
cho45 0:be89b5fdea09 33
cho45 2:c2e3f240640c 34 static const bool ENABLE_BONDING = true;
cho45 2:c2e3f240640c 35 static const bool REQUIRE_MITM = true;
cho45 2:c2e3f240640c 36 static const uint8_t PASSKEY[6] = {'1','2','3','4','5','6'}; // must be 6-digits number
cho45 2:c2e3f240640c 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 3:266dfa9f8709 48 void updateBatteryLevel() {
cho45 3:266dfa9f8709 49 if (!batteryService) return;
cho45 3:266dfa9f8709 50 static const float BATTERY_MAX = 2.4;
cho45 4:54cb552e50c4 51 static const float REFERNECE = 1.2;
cho45 4:54cb552e50c4 52 static const float PRESCALE = 3;
cho45 3:266dfa9f8709 53
cho45 4:54cb552e50c4 54 NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
cho45 4:54cb552e50c4 55
cho45 4:54cb552e50c4 56 // Use internal 1.2V reference for batteryInput
cho45 4:54cb552e50c4 57 // 1/3 pre-scaled input and 1.2V internal band gap reference
cho45 4:54cb552e50c4 58 // ref. mbed-src/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/analogin_api.c
cho45 4:54cb552e50c4 59 NRF_ADC->CONFIG =
cho45 4:54cb552e50c4 60 (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
cho45 4:54cb552e50c4 61 // Use VDD 1/3 for input
cho45 4:54cb552e50c4 62 (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
cho45 4:54cb552e50c4 63 // Use internal band gap for reference
cho45 4:54cb552e50c4 64 (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
cho45 4:54cb552e50c4 65 (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
cho45 4:54cb552e50c4 66
cho45 4:54cb552e50c4 67 // Start ADC
cho45 4:54cb552e50c4 68 NRF_ADC->TASKS_START = 1;
cho45 4:54cb552e50c4 69 while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) {
cho45 4:54cb552e50c4 70 // busy loop
cho45 4:54cb552e50c4 71 }
cho45 4:54cb552e50c4 72
cho45 4:54cb552e50c4 73 // Read ADC result
cho45 4:54cb552e50c4 74 uint16_t raw10bit = static_cast<uint16_t>(NRF_ADC->RESULT);
cho45 4:54cb552e50c4 75 float ratio = raw10bit / static_cast<float>(1<<10);
cho45 4:54cb552e50c4 76
cho45 4:54cb552e50c4 77 float batteryVoltage = ratio * (REFERNECE * PRESCALE);
cho45 3:266dfa9f8709 78 float percentage = (batteryVoltage / BATTERY_MAX) * 100;
cho45 3:266dfa9f8709 79 if (percentage > 100) {
cho45 3:266dfa9f8709 80 percentage = 100;
cho45 3:266dfa9f8709 81 }
cho45 4:54cb552e50c4 82 printf("updateBatteryLevel %f V : %d/100\r\n", batteryVoltage, static_cast<uint8_t>(percentage));
cho45 3:266dfa9f8709 83 batteryService->updateBatteryLevel(static_cast<uint8_t>(percentage));
cho45 3:266dfa9f8709 84 }
cho45 3:266dfa9f8709 85
cho45 3:266dfa9f8709 86
cho45 0:be89b5fdea09 87 static void onConnect(const Gap::ConnectionCallbackParams_t *params) {
cho45 2:c2e3f240640c 88 printf("onConnect\r\n");
cho45 0:be89b5fdea09 89 }
cho45 0:be89b5fdea09 90
cho45 2:c2e3f240640c 91 static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) {
cho45 2:c2e3f240640c 92 printf("onDisconnect\r\n");
cho45 2:c2e3f240640c 93 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
cho45 2:c2e3f240640c 94 }
cho45 2:c2e3f240640c 95
cho45 2:c2e3f240640c 96 static void onTimeout(const Gap::TimeoutSource_t source) {
cho45 2:c2e3f240640c 97 printf("onTimeout\r\n");
cho45 2:c2e3f240640c 98 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
cho45 2:c2e3f240640c 99 }
cho45 0:be89b5fdea09 100
cho45 0:be89b5fdea09 101 static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) {
cho45 2:c2e3f240640c 102 printf("Input passKey: ");
cho45 2:c2e3f240640c 103 for (unsigned i = 0; i < Gap::ADDR_LEN; i++) {
cho45 2:c2e3f240640c 104 printf("%c", passkey[i]);
cho45 2:c2e3f240640c 105 }
cho45 2:c2e3f240640c 106 printf("\r\n");
cho45 2:c2e3f240640c 107 }
cho45 2:c2e3f240640c 108
cho45 2:c2e3f240640c 109 static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) {
cho45 2:c2e3f240640c 110 if (status == SecurityManager::SEC_STATUS_SUCCESS) {
cho45 2:c2e3f240640c 111 printf("Security success %d\r\n", status);
cho45 2:c2e3f240640c 112 } else {
cho45 2:c2e3f240640c 113 printf("Security failed %d\r\n", status);
cho45 2:c2e3f240640c 114 }
cho45 2:c2e3f240640c 115 }
cho45 2:c2e3f240640c 116
cho45 2:c2e3f240640c 117 static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) {
cho45 2:c2e3f240640c 118 printf("Security setup initiated\r\n");
cho45 0:be89b5fdea09 119 }
cho45 0:be89b5fdea09 120
cho45 2:c2e3f240640c 121 static void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) {
cho45 2:c2e3f240640c 122 // https://developer.mbed.org/compiler/#nav:/keyboard/BLE_API/ble/blecommon.h;
cho45 2:c2e3f240640c 123 ble_error_t error;
cho45 2:c2e3f240640c 124 BLE &ble = params->ble;
cho45 2:c2e3f240640c 125
cho45 2:c2e3f240640c 126 error = params->error;
cho45 2:c2e3f240640c 127 if (error != BLE_ERROR_NONE) {
cho45 2:c2e3f240640c 128 printf("error on ble.init() \r\n");
cho45 2:c2e3f240640c 129 goto return_error;
cho45 2:c2e3f240640c 130 }
cho45 2:c2e3f240640c 131
cho45 2:c2e3f240640c 132 ble.gap().onDisconnection(onDisconnect);
cho45 2:c2e3f240640c 133 ble.gap().onConnection(onConnect);
cho45 2:c2e3f240640c 134 ble.gap().onTimeout(onTimeout);
cho45 2:c2e3f240640c 135
cho45 2:c2e3f240640c 136 printf("setup ble security manager\r\n");
cho45 2:c2e3f240640c 137 ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback);
cho45 2:c2e3f240640c 138 ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback);
cho45 2:c2e3f240640c 139 ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
cho45 2:c2e3f240640c 140 // bonding with hard-coded passkey.
cho45 2:c2e3f240640c 141 error = ble.securityManager().init(ENABLE_BONDING, REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY, PASSKEY);
cho45 2:c2e3f240640c 142 if (error != BLE_ERROR_NONE) {
cho45 2:c2e3f240640c 143 printf("error on ble.securityManager().init()");
cho45 2:c2e3f240640c 144 goto return_error;
cho45 2:c2e3f240640c 145 }
cho45 2:c2e3f240640c 146
cho45 2:c2e3f240640c 147 keyboardService = new KeyboardService(ble);
cho45 2:c2e3f240640c 148 deviceInformationService = new DeviceInformationService(ble, "lowreal.net", MODEL_NAME, SERIAL_NUMBER, HARDWARE_REVISION, FIRMWARE_REVISION, SOFTWARE_REVISION);
cho45 3:266dfa9f8709 149 batteryService = new BatteryService(ble, 100);
cho45 3:266dfa9f8709 150 updateBatteryLevel();
cho45 0:be89b5fdea09 151
cho45 2:c2e3f240640c 152 printf("general setup\r\n");
cho45 2:c2e3f240640c 153 error = ble.gap().accumulateAdvertisingPayload(
cho45 2:c2e3f240640c 154 GapAdvertisingData::BREDR_NOT_SUPPORTED |
cho45 2:c2e3f240640c 155 GapAdvertisingData::LE_GENERAL_DISCOVERABLE
cho45 2:c2e3f240640c 156 );
cho45 2:c2e3f240640c 157 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 158
cho45 2:c2e3f240640c 159 printf("set COMPLETE_LIST_16BIT_SERVICE_IDS\r\n");
cho45 2:c2e3f240640c 160 error = ble.gap().accumulateAdvertisingPayload(
cho45 2:c2e3f240640c 161 GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
cho45 2:c2e3f240640c 162 (uint8_t*)uuid16_list, sizeof(uuid16_list)
cho45 2:c2e3f240640c 163 );
cho45 2:c2e3f240640c 164 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 165
cho45 2:c2e3f240640c 166 printf("set advertising\r\n");
cho45 2:c2e3f240640c 167 // see 5.1.2: HID over GATT Specification (pg. 25)
cho45 2:c2e3f240640c 168 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
cho45 0:be89b5fdea09 169
cho45 2:c2e3f240640c 170 printf("set advertising interval\r\n");
cho45 2:c2e3f240640c 171 ble.gap().setAdvertisingInterval(50);
cho45 2:c2e3f240640c 172 // XXX
cho45 2:c2e3f240640c 173 // ble.gap().setAdvertisingTimeout(0);
cho45 2:c2e3f240640c 174
cho45 2:c2e3f240640c 175 printf("set keyboard\r\n");
cho45 2:c2e3f240640c 176 error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD);
cho45 2:c2e3f240640c 177 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 178
cho45 2:c2e3f240640c 179 printf("set complete local name\r\n");
cho45 2:c2e3f240640c 180 error = ble.gap().accumulateAdvertisingPayload(
cho45 2:c2e3f240640c 181 GapAdvertisingData::COMPLETE_LOCAL_NAME,
cho45 2:c2e3f240640c 182 DEVICE_NAME, sizeof(DEVICE_NAME)
cho45 2:c2e3f240640c 183 );
cho45 2:c2e3f240640c 184 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 185
cho45 2:c2e3f240640c 186 printf("set device name\r\n");
cho45 2:c2e3f240640c 187 error = ble.gap().setDeviceName(DEVICE_NAME);
cho45 2:c2e3f240640c 188 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 189 // ble.gap().setTxPower(-12);
cho45 0:be89b5fdea09 190
cho45 0:be89b5fdea09 191
cho45 2:c2e3f240640c 192 printf("advertising\r\n");
cho45 2:c2e3f240640c 193 error = ble.gap().startAdvertising();
cho45 2:c2e3f240640c 194 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 195 return;
cho45 0:be89b5fdea09 196
cho45 2:c2e3f240640c 197 return_error:
cho45 2:c2e3f240640c 198 printf("error with %d\r\n", error);
cho45 2:c2e3f240640c 199 return;
cho45 0:be89b5fdea09 200 }
cho45 0:be89b5fdea09 201
cho45 5:65d4e94735b6 202 class KeyboardMatrixController {
cho45 5:65d4e94735b6 203 I2C& i2c;
cho45 5:65d4e94735b6 204 MCP23017 gpio1;
cho45 5:65d4e94735b6 205 MCP23017 gpio2;
cho45 5:65d4e94735b6 206
cho45 5:65d4e94735b6 207 static const uint8_t GPIO1_SLAVE_ADDRESS = 0b0100000;
cho45 5:65d4e94735b6 208 static const uint8_t GPIO2_SLAVE_ADDRESS = 0b0100001;
cho45 5:65d4e94735b6 209
cho45 5:65d4e94735b6 210 /**
cho45 5:65d4e94735b6 211 * COL=GPIOA (output normaly positive)
cho45 5:65d4e94735b6 212 * ROW=GPIOB (input pulled-up)
cho45 5:65d4e94735b6 213 */
cho45 5:65d4e94735b6 214
cho45 5:65d4e94735b6 215 int setupGpio(MCP23017& gpio) {
cho45 5:65d4e94735b6 216 int ok;
cho45 5:65d4e94735b6 217 ok = gpio.write8(
cho45 5:65d4e94735b6 218 MCP23017::IOCON,
cho45 5:65d4e94735b6 219 0<<MCP23017::BANK |
cho45 5:65d4e94735b6 220 1<<MCP23017::MIRROR |
cho45 5:65d4e94735b6 221 1<<MCP23017::SEQOP |
cho45 5:65d4e94735b6 222 0<<MCP23017::DISSLW |
cho45 5:65d4e94735b6 223 1<<MCP23017::ODR // int pin is open drain
cho45 5:65d4e94735b6 224 );
cho45 5:65d4e94735b6 225
cho45 5:65d4e94735b6 226 // IODIR
cho45 5:65d4e94735b6 227 // 1: input
cho45 5:65d4e94735b6 228 // 0: output
cho45 5:65d4e94735b6 229 ok = gpio.write16(
cho45 5:65d4e94735b6 230 MCP23017::IODIRA,
cho45 5:65d4e94735b6 231 0b0000000011111111
cho45 5:65d4e94735b6 232 );
cho45 4:54cb552e50c4 233
cho45 5:65d4e94735b6 234 // INPUT POLARITY
cho45 5:65d4e94735b6 235 // 1: inverse polarity
cho45 5:65d4e94735b6 236 // 0: raw
cho45 5:65d4e94735b6 237 ok = gpio.write8(
cho45 5:65d4e94735b6 238 MCP23017::IPOLB,
cho45 5:65d4e94735b6 239 0b11111111
cho45 5:65d4e94735b6 240 );
cho45 5:65d4e94735b6 241
cho45 5:65d4e94735b6 242 // INTERRUPT-ON-CHANGE Enable
cho45 5:65d4e94735b6 243 ok = gpio.write8(
cho45 5:65d4e94735b6 244 MCP23017::GPINTENB,
cho45 5:65d4e94735b6 245 0b11111111
cho45 5:65d4e94735b6 246 );
cho45 5:65d4e94735b6 247 // INTERRUPT-ON-CHANGE Control
cho45 5:65d4e94735b6 248 // 1: compared with DEFVAL
cho45 5:65d4e94735b6 249 // 0: compared to previous value
cho45 5:65d4e94735b6 250 ok = gpio.write8(
cho45 5:65d4e94735b6 251 MCP23017::INTCONB,
cho45 5:65d4e94735b6 252 0b00000000
cho45 5:65d4e94735b6 253 );
cho45 5:65d4e94735b6 254 // PULL-UP (for input pin)
cho45 5:65d4e94735b6 255 // 1: pull-up enabled
cho45 5:65d4e94735b6 256 // 0: pull-up disabled
cho45 5:65d4e94735b6 257 ok = gpio.write8(
cho45 5:65d4e94735b6 258 MCP23017::GPPUB,
cho45 5:65d4e94735b6 259 0b11111111
cho45 5:65d4e94735b6 260 );
cho45 5:65d4e94735b6 261
cho45 5:65d4e94735b6 262 ok = gpio1.write8(
cho45 5:65d4e94735b6 263 MCP23017::GPIOA,
cho45 5:65d4e94735b6 264 0b00000000
cho45 5:65d4e94735b6 265 );
cho45 5:65d4e94735b6 266
cho45 5:65d4e94735b6 267 return ok;
cho45 5:65d4e94735b6 268 }
cho45 5:65d4e94735b6 269
cho45 4:54cb552e50c4 270 public:
cho45 5:65d4e94735b6 271 KeyboardMatrixController(I2C& _i2c) :
cho45 5:65d4e94735b6 272 i2c(_i2c),
cho45 5:65d4e94735b6 273 gpio1(i2c, GPIO1_SLAVE_ADDRESS),
cho45 5:65d4e94735b6 274 gpio2(i2c, GPIO2_SLAVE_ADDRESS)
cho45 4:54cb552e50c4 275 {
cho45 4:54cb552e50c4 276 }
cho45 4:54cb552e50c4 277
cho45 5:65d4e94735b6 278 void init() {
cho45 5:65d4e94735b6 279 setupGpio(gpio1);
cho45 5:65d4e94735b6 280 // setupGpio(gpio2);
cho45 5:65d4e94735b6 281 }
cho45 5:65d4e94735b6 282
cho45 5:65d4e94735b6 283 void scanKeyboard(uint8_t* keys) {
cho45 5:65d4e94735b6 284 int ok;
cho45 5:65d4e94735b6 285
cho45 5:65d4e94735b6 286 // Disable interrupt
cho45 5:65d4e94735b6 287 ok = gpio1.write8(
cho45 5:65d4e94735b6 288 MCP23017::GPINTENB,
cho45 5:65d4e94735b6 289 0b00000000
cho45 5:65d4e94735b6 290 );
cho45 5:65d4e94735b6 291
cho45 5:65d4e94735b6 292 for (int i = 0; i < 8; i++) {
cho45 5:65d4e94735b6 293 ok = gpio1.write8(
cho45 5:65d4e94735b6 294 MCP23017::GPIOA,
cho45 5:65d4e94735b6 295 ~(1<<i)
cho45 5:65d4e94735b6 296 );
cho45 5:65d4e94735b6 297 keys[i] = gpio1.read8(MCP23017::GPIOB, ok);
cho45 4:54cb552e50c4 298 }
cho45 2:c2e3f240640c 299
cho45 5:65d4e94735b6 300 // set all output to negative for interrupt
cho45 5:65d4e94735b6 301 ok = gpio1.write8(
cho45 5:65d4e94735b6 302 MCP23017::GPIOA,
cho45 5:65d4e94735b6 303 0b00000000
cho45 5:65d4e94735b6 304 );
cho45 5:65d4e94735b6 305
cho45 5:65d4e94735b6 306 // Enable interrupt
cho45 5:65d4e94735b6 307 ok = gpio1.write8(
cho45 5:65d4e94735b6 308 MCP23017::GPINTENB,
cho45 5:65d4e94735b6 309 0b11111111
cho45 5:65d4e94735b6 310 );
cho45 5:65d4e94735b6 311
cho45 5:65d4e94735b6 312 // Clear interrupt
cho45 5:65d4e94735b6 313 gpio1.read8(MCP23017::GPIOB, ok);
cho45 5:65d4e94735b6 314
cho45 5:65d4e94735b6 315 // TODO gpio2
cho45 4:54cb552e50c4 316 }
cho45 5:65d4e94735b6 317 };
cho45 4:54cb552e50c4 318
cho45 5:65d4e94735b6 319 I2C i2c(I2C_SDA0, I2C_SCL0);
cho45 5:65d4e94735b6 320 KeyboardMatrixController keyboardMatrixController(i2c);
cho45 5:65d4e94735b6 321 Keymap keymap(keyboardService);
cho45 5:65d4e94735b6 322 InterruptIn buttonInt(P0_5);
cho45 5:65d4e94735b6 323 DigitalIn buttonIntIn(P0_5);
cho45 5:65d4e94735b6 324
cho45 5:65d4e94735b6 325 // ROWS=8
cho45 5:65d4e94735b6 326 // COLS=16
cho45 5:65d4e94735b6 327 // 列ごとに1バイトにパックしてキーの状態を保持する
cho45 5:65d4e94735b6 328 static uint8_t keysA[COLS];
cho45 5:65d4e94735b6 329 static uint8_t keysB[COLS];
cho45 5:65d4e94735b6 330 static bool state = 0;
cho45 5:65d4e94735b6 331
cho45 5:65d4e94735b6 332 void buttonIntCallback() {
cho45 5:65d4e94735b6 333 printf("pinChanged!!!\r\n");
cho45 5:65d4e94735b6 334 uint8_t (&keysCurr)[COLS] = state ? keysA : keysB;
cho45 5:65d4e94735b6 335 uint8_t (&keysPrev)[COLS] = state ? keysB : keysA;
cho45 5:65d4e94735b6 336
cho45 5:65d4e94735b6 337 printf("scanKeyboard\r\n");
cho45 5:65d4e94735b6 338 keyboardMatrixController.scanKeyboard(keysCurr);
cho45 5:65d4e94735b6 339
cho45 5:65d4e94735b6 340 for (int col = 0; col < COLS; col++) {
cho45 5:65d4e94735b6 341 uint8_t changed = keysPrev[col] ^ keysCurr[col];
cho45 5:65d4e94735b6 342 if (changed) printf("changed: %x\r\n", changed);
cho45 5:65d4e94735b6 343 for (int row = 0; row < ROWS; row++) {
cho45 5:65d4e94735b6 344 if (changed & (1<<row)) {
cho45 5:65d4e94735b6 345 bool pressed = keysCurr[col] & (1<<row);
cho45 5:65d4e94735b6 346 printf("changed: col=%d, row=%d / pressed=%d\r\n", col, row, pressed);
cho45 5:65d4e94735b6 347 // keymap.execute(col, row, pressed);
cho45 4:54cb552e50c4 348 }
cho45 4:54cb552e50c4 349 }
cho45 2:c2e3f240640c 350 }
cho45 5:65d4e94735b6 351 state = !state;
cho45 2:c2e3f240640c 352 }
cho45 2:c2e3f240640c 353
cho45 0:be89b5fdea09 354 int main(void) {
cho45 5:65d4e94735b6 355 printf("init\r\n");
cho45 4:54cb552e50c4 356
cho45 4:54cb552e50c4 357 // mbed's Serial of TARGET_RBLAB_BLENANO sucks
cho45 4:54cb552e50c4 358 // DO NOT CONNECT RTS/CTS AUTOMATICALY!
cho45 4:54cb552e50c4 359 NRF_UART0->PSELRTS = 0xFFFFFFFFUL;
cho45 4:54cb552e50c4 360 NRF_UART0->PSELCTS = 0xFFFFFFFFUL;
cho45 4:54cb552e50c4 361
cho45 4:54cb552e50c4 362 int ok;
cho45 4:54cb552e50c4 363
cho45 4:54cb552e50c4 364 // 100kHz
cho45 4:54cb552e50c4 365 i2c.frequency(100000);
cho45 4:54cb552e50c4 366
cho45 5:65d4e94735b6 367 buttonInt.mode(PullUp);
cho45 5:65d4e94735b6 368 buttonInt.fall(buttonIntCallback);
cho45 4:54cb552e50c4 369
cho45 5:65d4e94735b6 370 keyboardMatrixController.init();
cho45 5:65d4e94735b6 371 buttonIntCallback();
cho45 4:54cb552e50c4 372
cho45 5:65d4e94735b6 373 while (1) {
cho45 5:65d4e94735b6 374 wait_ms(1000);
cho45 4:54cb552e50c4 375 }
cho45 4:54cb552e50c4 376
cho45 4:54cb552e50c4 377 return;
cho45 0:be89b5fdea09 378
cho45 2:c2e3f240640c 379 // https://github.com/jpbrucker/BLE_HID/blob/master/examples/examples_common.cpp
cho45 0:be89b5fdea09 380
cho45 2:c2e3f240640c 381 printf("ble.init\r\n");
cho45 2:c2e3f240640c 382 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 2:c2e3f240640c 383 ble.init(bleInitComplete);
cho45 0:be89b5fdea09 384
cho45 2:c2e3f240640c 385 while (!ble.hasInitialized()) { }
cho45 0:be89b5fdea09 386
cho45 2:c2e3f240640c 387 printf("ble.hasIntialized\r\n");
cho45 0:be89b5fdea09 388
cho45 2:c2e3f240640c 389 while (1) {
cho45 2:c2e3f240640c 390 ble.waitForEvent();
cho45 2:c2e3f240640c 391 }
cho45 2:c2e3f240640c 392 }