Hiroh Satoh / keyboard Featured

Dependencies:   BLE_API mbed-dev nRF51822

Committer:
cho45
Date:
Mon Aug 22 15:24:34 2016 +0000
Revision:
22:a78f0a91280a
Parent:
21:d801c32231b0
Child:
23:b31957ce64e9
RXD ???????????1mA?????

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 6:f1c3ea8bc850 18
cho45 6:f1c3ea8bc850 19 #include "HIDController_BLE.h"
cho45 6:f1c3ea8bc850 20
cho45 4:54cb552e50c4 21 #include "mcp23017.h"
cho45 5:65d4e94735b6 22 #include "keymap.h"
cho45 0:be89b5fdea09 23
cho45 0:be89b5fdea09 24
cho45 5:65d4e94735b6 25 class KeyboardMatrixController {
cho45 5:65d4e94735b6 26 I2C& i2c;
cho45 5:65d4e94735b6 27 MCP23017 gpio1;
cho45 5:65d4e94735b6 28 MCP23017 gpio2;
cho45 13:b0ffdf2012b9 29 bool gpio1_ready;
cho45 13:b0ffdf2012b9 30 bool gpio2_ready;
cho45 5:65d4e94735b6 31
cho45 5:65d4e94735b6 32 static const uint8_t GPIO1_SLAVE_ADDRESS = 0b0100000;
cho45 14:3a8c126b7834 33 static const uint8_t GPIO2_SLAVE_ADDRESS = 0b0100100;
cho45 5:65d4e94735b6 34
cho45 5:65d4e94735b6 35 /**
cho45 5:65d4e94735b6 36 * COL=GPIOA (output normaly positive)
cho45 5:65d4e94735b6 37 * ROW=GPIOB (input pulled-up)
cho45 5:65d4e94735b6 38 */
cho45 5:65d4e94735b6 39
cho45 13:b0ffdf2012b9 40 bool setupGpio(MCP23017& gpio) {
cho45 5:65d4e94735b6 41 int ok;
cho45 13:b0ffdf2012b9 42 printf("SET IOCON\r\n");
cho45 5:65d4e94735b6 43 ok = gpio.write8(
cho45 5:65d4e94735b6 44 MCP23017::IOCON,
cho45 5:65d4e94735b6 45 0<<MCP23017::BANK |
cho45 5:65d4e94735b6 46 1<<MCP23017::MIRROR |
cho45 5:65d4e94735b6 47 1<<MCP23017::SEQOP |
cho45 5:65d4e94735b6 48 0<<MCP23017::DISSLW |
cho45 5:65d4e94735b6 49 1<<MCP23017::ODR // int pin is open drain
cho45 5:65d4e94735b6 50 );
cho45 13:b0ffdf2012b9 51 if (!ok) return false;
cho45 5:65d4e94735b6 52
cho45 5:65d4e94735b6 53 // IODIR
cho45 5:65d4e94735b6 54 // 1: input
cho45 5:65d4e94735b6 55 // 0: output
cho45 13:b0ffdf2012b9 56 printf("SET IODIRA\r\n");
cho45 5:65d4e94735b6 57 ok = gpio.write16(
cho45 5:65d4e94735b6 58 MCP23017::IODIRA,
cho45 5:65d4e94735b6 59 0b0000000011111111
cho45 5:65d4e94735b6 60 );
cho45 13:b0ffdf2012b9 61 if (!ok) return false;
cho45 4:54cb552e50c4 62
cho45 5:65d4e94735b6 63 // INPUT POLARITY
cho45 5:65d4e94735b6 64 // 1: inverse polarity
cho45 5:65d4e94735b6 65 // 0: raw
cho45 13:b0ffdf2012b9 66 printf("SET IPOLB\r\n");
cho45 5:65d4e94735b6 67 ok = gpio.write8(
cho45 5:65d4e94735b6 68 MCP23017::IPOLB,
cho45 5:65d4e94735b6 69 0b11111111
cho45 5:65d4e94735b6 70 );
cho45 13:b0ffdf2012b9 71 if (!ok) return false;
cho45 5:65d4e94735b6 72
cho45 5:65d4e94735b6 73 // INTERRUPT-ON-CHANGE Enable
cho45 13:b0ffdf2012b9 74 printf("SET GPINTENB\r\n");
cho45 5:65d4e94735b6 75 ok = gpio.write8(
cho45 5:65d4e94735b6 76 MCP23017::GPINTENB,
cho45 5:65d4e94735b6 77 0b11111111
cho45 5:65d4e94735b6 78 );
cho45 13:b0ffdf2012b9 79 if (!ok) return false;
cho45 13:b0ffdf2012b9 80
cho45 5:65d4e94735b6 81 // INTERRUPT-ON-CHANGE Control
cho45 5:65d4e94735b6 82 // 1: compared with DEFVAL
cho45 5:65d4e94735b6 83 // 0: compared to previous value
cho45 13:b0ffdf2012b9 84 printf("SET INTCONB\r\n");
cho45 5:65d4e94735b6 85 ok = gpio.write8(
cho45 5:65d4e94735b6 86 MCP23017::INTCONB,
cho45 5:65d4e94735b6 87 0b00000000
cho45 5:65d4e94735b6 88 );
cho45 13:b0ffdf2012b9 89 if (!ok) return false;
cho45 13:b0ffdf2012b9 90
cho45 5:65d4e94735b6 91 // PULL-UP (for input pin)
cho45 5:65d4e94735b6 92 // 1: pull-up enabled
cho45 5:65d4e94735b6 93 // 0: pull-up disabled
cho45 13:b0ffdf2012b9 94 printf("SET GPPUB\r\n");
cho45 5:65d4e94735b6 95 ok = gpio.write8(
cho45 5:65d4e94735b6 96 MCP23017::GPPUB,
cho45 5:65d4e94735b6 97 0b11111111
cho45 5:65d4e94735b6 98 );
cho45 13:b0ffdf2012b9 99 if (!ok) return false;
cho45 5:65d4e94735b6 100
cho45 13:b0ffdf2012b9 101 printf("SET GPIOA\r\n");
cho45 5:65d4e94735b6 102 ok = gpio1.write8(
cho45 5:65d4e94735b6 103 MCP23017::GPIOA,
cho45 5:65d4e94735b6 104 0b00000000
cho45 5:65d4e94735b6 105 );
cho45 13:b0ffdf2012b9 106 if (!ok) return false;
cho45 5:65d4e94735b6 107
cho45 13:b0ffdf2012b9 108 return true;
cho45 5:65d4e94735b6 109 }
cho45 5:65d4e94735b6 110
cho45 4:54cb552e50c4 111 public:
cho45 5:65d4e94735b6 112 KeyboardMatrixController(I2C& _i2c) :
cho45 5:65d4e94735b6 113 i2c(_i2c),
cho45 5:65d4e94735b6 114 gpio1(i2c, GPIO1_SLAVE_ADDRESS),
cho45 5:65d4e94735b6 115 gpio2(i2c, GPIO2_SLAVE_ADDRESS)
cho45 4:54cb552e50c4 116 {
cho45 4:54cb552e50c4 117 }
cho45 4:54cb552e50c4 118
cho45 5:65d4e94735b6 119 void init() {
cho45 13:b0ffdf2012b9 120 printf("init gpio1\r\n");
cho45 13:b0ffdf2012b9 121 gpio1_ready = setupGpio(gpio1);
cho45 13:b0ffdf2012b9 122 printf("gpio1 initialized: %s\r\n", gpio1_ready ? "success" : "failed");
cho45 13:b0ffdf2012b9 123
cho45 13:b0ffdf2012b9 124 printf("init gpio2\r\n");
cho45 13:b0ffdf2012b9 125 gpio2_ready = setupGpio(gpio2);
cho45 13:b0ffdf2012b9 126 printf("gpio2 initialized: %s\r\n", gpio2_ready ? "success" : "failed");
cho45 13:b0ffdf2012b9 127
cho45 5:65d4e94735b6 128 }
cho45 5:65d4e94735b6 129
cho45 5:65d4e94735b6 130 void scanKeyboard(uint8_t* keys) {
cho45 5:65d4e94735b6 131 int ok;
cho45 13:b0ffdf2012b9 132
cho45 13:b0ffdf2012b9 133 disableInterrupt();
cho45 5:65d4e94735b6 134
cho45 13:b0ffdf2012b9 135 if (gpio1_ready) {
cho45 13:b0ffdf2012b9 136 for (int i = 0; i < 8; i++) {
cho45 13:b0ffdf2012b9 137 ok = gpio1.write8(
cho45 13:b0ffdf2012b9 138 MCP23017::GPIOA,
cho45 13:b0ffdf2012b9 139 ~(1<<i)
cho45 13:b0ffdf2012b9 140 );
cho45 13:b0ffdf2012b9 141 keys[i] = gpio1.read8(MCP23017::GPIOB, ok);
cho45 13:b0ffdf2012b9 142 }
cho45 13:b0ffdf2012b9 143
cho45 13:b0ffdf2012b9 144 // set all output to negative for interrupt
cho45 5:65d4e94735b6 145 ok = gpio1.write8(
cho45 5:65d4e94735b6 146 MCP23017::GPIOA,
cho45 13:b0ffdf2012b9 147 0b00000000
cho45 5:65d4e94735b6 148 );
cho45 4:54cb552e50c4 149 }
cho45 2:c2e3f240640c 150
cho45 5:65d4e94735b6 151
cho45 13:b0ffdf2012b9 152 if (gpio2_ready) {
cho45 13:b0ffdf2012b9 153 for (int i = 0; i < 8; i++) {
cho45 13:b0ffdf2012b9 154 ok = gpio2.write8(
cho45 13:b0ffdf2012b9 155 MCP23017::GPIOA,
cho45 13:b0ffdf2012b9 156 ~(1<<i)
cho45 13:b0ffdf2012b9 157 );
cho45 13:b0ffdf2012b9 158 keys[i+8] = gpio2.read8(MCP23017::GPIOB, ok);
cho45 13:b0ffdf2012b9 159 }
cho45 13:b0ffdf2012b9 160
cho45 13:b0ffdf2012b9 161 // set all output to negative for interrupt
cho45 13:b0ffdf2012b9 162 ok = gpio2.write8(
cho45 13:b0ffdf2012b9 163 MCP23017::GPIOA,
cho45 13:b0ffdf2012b9 164 0b00000000
cho45 13:b0ffdf2012b9 165 );
cho45 13:b0ffdf2012b9 166 }
cho45 13:b0ffdf2012b9 167
cho45 13:b0ffdf2012b9 168 enableInterrupt();
cho45 7:b9270a37345b 169 }
cho45 13:b0ffdf2012b9 170
cho45 7:b9270a37345b 171 void disableInterrupt() {
cho45 7:b9270a37345b 172 int ok;
cho45 13:b0ffdf2012b9 173 if (gpio1_ready) {
cho45 13:b0ffdf2012b9 174 // Disable interrupt
cho45 13:b0ffdf2012b9 175 ok = gpio1.write8(
cho45 13:b0ffdf2012b9 176 MCP23017::GPINTENB,
cho45 13:b0ffdf2012b9 177 0b00000000
cho45 13:b0ffdf2012b9 178 );
cho45 13:b0ffdf2012b9 179 }
cho45 13:b0ffdf2012b9 180
cho45 13:b0ffdf2012b9 181 if (gpio2_ready) {
cho45 13:b0ffdf2012b9 182 // Disable interrupt
cho45 13:b0ffdf2012b9 183 ok = gpio2.write8(
cho45 13:b0ffdf2012b9 184 MCP23017::GPINTENB,
cho45 13:b0ffdf2012b9 185 0b00000000
cho45 13:b0ffdf2012b9 186 );
cho45 13:b0ffdf2012b9 187 }
cho45 7:b9270a37345b 188 }
cho45 7:b9270a37345b 189
cho45 7:b9270a37345b 190 void enableInterrupt() {
cho45 7:b9270a37345b 191 int ok;
cho45 13:b0ffdf2012b9 192 if (gpio1_ready) {
cho45 13:b0ffdf2012b9 193 // Enable interrupt
cho45 13:b0ffdf2012b9 194 ok = gpio1.write8(
cho45 13:b0ffdf2012b9 195 MCP23017::GPINTENB,
cho45 13:b0ffdf2012b9 196 0b11111111
cho45 13:b0ffdf2012b9 197 );
cho45 13:b0ffdf2012b9 198 }
cho45 13:b0ffdf2012b9 199
cho45 13:b0ffdf2012b9 200 if (gpio2_ready) {
cho45 13:b0ffdf2012b9 201 // Enable interrupt
cho45 13:b0ffdf2012b9 202 ok = gpio2.write8(
cho45 13:b0ffdf2012b9 203 MCP23017::GPINTENB,
cho45 13:b0ffdf2012b9 204 0b11111111
cho45 13:b0ffdf2012b9 205 );
cho45 13:b0ffdf2012b9 206 }
cho45 5:65d4e94735b6 207
cho45 5:65d4e94735b6 208 // Clear interrupt
cho45 13:b0ffdf2012b9 209 // gpio1.read8(MCP23017::GPIOB, ok);
cho45 4:54cb552e50c4 210 }
cho45 5:65d4e94735b6 211 };
cho45 4:54cb552e50c4 212
cho45 5:65d4e94735b6 213 I2C i2c(I2C_SDA0, I2C_SCL0);
cho45 16:345eebc4f259 214 // Serial serial(USBTX, USBRX);
cho45 5:65d4e94735b6 215 KeyboardMatrixController keyboardMatrixController(i2c);
cho45 6:f1c3ea8bc850 216 Keymap keymap;
cho45 15:70bf079d3ee1 217
cho45 15:70bf079d3ee1 218 // Interrupt from MCP23017
cho45 15:70bf079d3ee1 219 // (pulled-up and two MCP23017 is configured with open drain INT)
cho45 5:65d4e94735b6 220 InterruptIn buttonInt(P0_5);
cho45 5:65d4e94735b6 221
cho45 15:70bf079d3ee1 222 // Unsed pins. Set to output for power consumption
cho45 20:d8840ac38434 223 DigitalIn unused_p0_4(P0_4, PullUp);
cho45 20:d8840ac38434 224 DigitalIn unused_p0_7(P0_7, PullUp);
cho45 20:d8840ac38434 225 DigitalIn unused_p0_6(P0_6, PullUp);
cho45 20:d8840ac38434 226 DigitalIn unused_p0_15(P0_15, PullUp);
cho45 20:d8840ac38434 227 DigitalIn unused_p0_29(P0_29, PullUp);
cho45 20:d8840ac38434 228 DigitalIn unused_p0_28(P0_28, PullUp);
cho45 20:d8840ac38434 229 DigitalIn unused_p0_19(P0_19, PullUp); // This is on board LED which connected to VDD
cho45 22:a78f0a91280a 230 DigitalIn unused_p0_11(P0_11, PullUp); // RXD
cho45 15:70bf079d3ee1 231
cho45 15:70bf079d3ee1 232
cho45 5:65d4e94735b6 233 // ROWS=8
cho45 5:65d4e94735b6 234 // COLS=16
cho45 5:65d4e94735b6 235 // 列ごとに1バイトにパックしてキーの状態を保持する
cho45 5:65d4e94735b6 236 static uint8_t keysA[COLS];
cho45 5:65d4e94735b6 237 static uint8_t keysB[COLS];
cho45 5:65d4e94735b6 238 static bool state = 0;
cho45 9:d1daefbf1fbd 239 // delay for interrupt
cho45 13:b0ffdf2012b9 240 static volatile int8_t pollCount = 0;
cho45 5:65d4e94735b6 241
cho45 5:65d4e94735b6 242 void buttonIntCallback() {
cho45 8:d684faf04c9a 243 // just for wakeup
cho45 9:d1daefbf1fbd 244 pollCount = 100;
cho45 2:c2e3f240640c 245 }
cho45 2:c2e3f240640c 246
cho45 0:be89b5fdea09 247 int main(void) {
cho45 5:65d4e94735b6 248 printf("init\r\n");
cho45 4:54cb552e50c4 249
cho45 4:54cb552e50c4 250 // mbed's Serial of TARGET_RBLAB_BLENANO sucks
cho45 4:54cb552e50c4 251 // DO NOT CONNECT RTS/CTS AUTOMATICALY!
cho45 4:54cb552e50c4 252 NRF_UART0->PSELRTS = 0xFFFFFFFFUL;
cho45 4:54cb552e50c4 253 NRF_UART0->PSELCTS = 0xFFFFFFFFUL;
cho45 4:54cb552e50c4 254
cho45 16:345eebc4f259 255
cho45 4:54cb552e50c4 256 // 100kHz
cho45 4:54cb552e50c4 257 i2c.frequency(100000);
cho45 4:54cb552e50c4 258
cho45 5:65d4e94735b6 259 buttonInt.mode(PullUp);
cho45 5:65d4e94735b6 260 buttonInt.fall(buttonIntCallback);
cho45 4:54cb552e50c4 261
cho45 5:65d4e94735b6 262 keyboardMatrixController.init();
cho45 5:65d4e94735b6 263 buttonIntCallback();
cho45 4:54cb552e50c4 264
cho45 6:f1c3ea8bc850 265 HIDController::init();
cho45 16:345eebc4f259 266
cho45 16:345eebc4f259 267 // STOP UART RX for power consumption
cho45 21:d801c32231b0 268 NRF_UART0->TASKS_STOPRX = 1;
cho45 16:345eebc4f259 269
cho45 16:345eebc4f259 270 NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
cho45 16:345eebc4f259 271
cho45 5:65d4e94735b6 272 while (1) {
cho45 9:d1daefbf1fbd 273 if (pollCount-- > 0) {
cho45 7:b9270a37345b 274 uint8_t (&keysCurr)[COLS] = state ? keysA : keysB;
cho45 7:b9270a37345b 275 uint8_t (&keysPrev)[COLS] = state ? keysB : keysA;
cho45 7:b9270a37345b 276
cho45 16:345eebc4f259 277 NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
cho45 7:b9270a37345b 278 keyboardMatrixController.scanKeyboard(keysCurr);
cho45 16:345eebc4f259 279 NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
cho45 7:b9270a37345b 280
cho45 9:d1daefbf1fbd 281 bool queue = false;
cho45 9:d1daefbf1fbd 282
cho45 7:b9270a37345b 283 for (int col = 0; col < COLS; col++) {
cho45 7:b9270a37345b 284 uint8_t changed = keysPrev[col] ^ keysCurr[col];
cho45 9:d1daefbf1fbd 285 if (changed) queue = true;
cho45 7:b9270a37345b 286 for (int row = 0; row < ROWS; row++) {
cho45 7:b9270a37345b 287 if (changed & (1<<row)) {
cho45 7:b9270a37345b 288 bool pressed = keysCurr[col] & (1<<row);
cho45 8:d684faf04c9a 289 // printf("changed: col=%d, row=%d / pressed=%d\r\n", col, row, pressed);
cho45 7:b9270a37345b 290 keymap.execute(col, row, pressed);
cho45 7:b9270a37345b 291 }
cho45 7:b9270a37345b 292 }
cho45 7:b9270a37345b 293 }
cho45 7:b9270a37345b 294 state = !state;
cho45 16:345eebc4f259 295
cho45 7:b9270a37345b 296
cho45 9:d1daefbf1fbd 297 if (queue) HIDController::queueCurrentReportData();
cho45 7:b9270a37345b 298 wait_ms(5);
cho45 8:d684faf04c9a 299 } else {
cho45 13:b0ffdf2012b9 300 printf("wait for events...\r\n");
cho45 16:345eebc4f259 301
cho45 21:d801c32231b0 302 /*// save 50uA
cho45 16:345eebc4f259 303 while (NRF_UART0->EVENTS_TXDRDY != 1);
cho45 16:345eebc4f259 304
cho45 16:345eebc4f259 305 uint32_t tx = NRF_UART0->PSELTXD;
cho45 16:345eebc4f259 306
cho45 14:3a8c126b7834 307 NRF_UART0->TASKS_STOPTX = 1;
cho45 14:3a8c126b7834 308 NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Disabled << UART_ENABLE_ENABLE_Pos);
cho45 21:d801c32231b0 309 /**/
cho45 16:345eebc4f259 310
cho45 10:1aed2481a743 311 HIDController::waitForEvent();
cho45 16:345eebc4f259 312
cho45 21:d801c32231b0 313 /*/
cho45 14:3a8c126b7834 314 NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
cho45 14:3a8c126b7834 315 NRF_UART0->TASKS_STARTTX = 1;
cho45 16:345eebc4f259 316 NRF_UART0->PSELTXD = 0xFFFFFFFF;
cho45 16:345eebc4f259 317 NRF_UART0->EVENTS_TXDRDY = 0;
cho45 16:345eebc4f259 318 NRF_UART0->TXD = 0;
cho45 16:345eebc4f259 319 while (NRF_UART0->EVENTS_TXDRDY != 1);
cho45 16:345eebc4f259 320 NRF_UART0->PSELTXD = tx;
cho45 21:d801c32231b0 321 /**/
cho45 7:b9270a37345b 322 }
cho45 2:c2e3f240640c 323 }
cho45 2:c2e3f240640c 324 }