Hiroh Satoh / keyboard Featured

Dependencies:   BLE_API mbed-dev nRF51822

Revision:
5:65d4e94735b6
Parent:
4:54cb552e50c4
Child:
6:f1c3ea8bc850
--- a/main.cpp	Wed Jul 20 02:05:45 2016 +0900
+++ b/main.cpp	Thu Jul 21 00:38:09 2016 +0900
@@ -20,6 +20,7 @@
 #include "BatteryService.h"
 #include "DeviceInformationService.h"
 #include "mcp23017.h"
+#include "keymap.h"
 
 static const char MODEL_NAME[] = "keyboard";
 static const char SERIAL_NUMBER[] = "X00000";
@@ -44,10 +45,6 @@
 BatteryService* batteryService;
 DeviceInformationService* deviceInformationService;
 
-I2C i2c(I2C_SDA0, I2C_SCL0);
-MCP23017 gpio1(i2c, 0b0100000);
-InterruptIn buttonInt(P0_5);
-
 void updateBatteryLevel() {
 	if (!batteryService) return;
 	static const float BATTERY_MAX = 2.4;
@@ -202,156 +199,181 @@
 	return;
 }
 
-class MyKeyboardService : public HIDServiceBase {
-	union {
-		uint8_t raw[8];
-		struct {
-			uint8_t modifier;
-			uint8_t padding;
-			uint8_t keycode[6];
-		} data;
-	} inputReportData;
+class KeyboardMatrixController {
+	I2C& i2c;
+	MCP23017 gpio1;
+	MCP23017 gpio2;
+
+	static const uint8_t GPIO1_SLAVE_ADDRESS = 0b0100000;
+	static const uint8_t GPIO2_SLAVE_ADDRESS = 0b0100001;
+
+	/**
+	 * COL=GPIOA (output normaly positive)
+	 * ROW=GPIOB (input pulled-up)
+	 */
+
+	int setupGpio(MCP23017& gpio) {
+		int ok;
+		ok = gpio.write8(
+			MCP23017::IOCON,
+			0<<MCP23017::BANK |
+			1<<MCP23017::MIRROR |
+			1<<MCP23017::SEQOP |
+			0<<MCP23017::DISSLW |
+			1<<MCP23017::ODR // int pin is open drain
+		);
+
+		// IODIR
+		//   1: input
+		//   0: output
+		ok = gpio.write16(
+			MCP23017::IODIRA,
+			0b0000000011111111
+		);
 
-	union {
-		uint8_t raw[1];
-	} outputReportData;
+		// INPUT POLARITY
+		//   1: inverse polarity
+		//   0: raw
+		ok = gpio.write8(
+			MCP23017::IPOLB,
+			0b11111111
+		);
+
+		// INTERRUPT-ON-CHANGE Enable
+		ok = gpio.write8(
+			MCP23017::GPINTENB,
+			0b11111111
+		);
+		// INTERRUPT-ON-CHANGE Control
+		//   1: compared with DEFVAL
+		//   0: compared to previous value
+		ok = gpio.write8(
+			MCP23017::INTCONB,
+			0b00000000
+		);
+		// PULL-UP (for input pin)
+		//   1: pull-up enabled
+		//   0: pull-up disabled
+		ok = gpio.write8(
+			MCP23017::GPPUB,
+			0b11111111
+		);
+
+		ok = gpio1.write8(
+			MCP23017::GPIOA,
+			0b00000000
+		);
+
+		return ok;
+	}
+
 public:
-	MyKeyboardService(BLE& _ble) :
-		HIDServiceBase(
-			_ble,
-			KEYBOARD_REPORT_MAP,
-			sizeof(KEYBOARD_REPORT_MAP),
-			inputReport         = inputReportData.raw,
-			outputReport        = outputReportData.raw,
-			featureReport       = NULL,
-			inputReportLength   = sizeof(inputReportData),
-			outputReportLength  = sizeof(outputReportData),
-			featureReportLength = 0,
-			reportTickerDelay   = 24
-		)
+	KeyboardMatrixController(I2C& _i2c) :
+		i2c(_i2c),
+		gpio1(i2c, GPIO1_SLAVE_ADDRESS),
+		gpio2(i2c, GPIO2_SLAVE_ADDRESS)
 	{
 	}
 
-	void appendReportData(uint8_t keycode) {
-		for (int i = 0; i < 6; i++) {
-			if (inputReportData.data.keycode[i] == 0) {
-				inputReportData.data.keycode[i] = keycode;
-				startReportTicker();
-				return;
-			}
+	void init() {
+		setupGpio(gpio1);
+		// setupGpio(gpio2);
+	}
+
+	void scanKeyboard(uint8_t* keys) {
+		int ok;
+
+		// Disable interrupt
+		ok = gpio1.write8(
+			MCP23017::GPINTENB,
+			0b00000000
+		);
+
+		for (int i = 0; i < 8; i++) {
+			ok = gpio1.write8(
+				MCP23017::GPIOA,
+				~(1<<i)
+			);
+			keys[i] = gpio1.read8(MCP23017::GPIOB, ok);
 		}
 
-		// TODO: report data is full
+		// set all output to negative for interrupt
+		ok = gpio1.write8(
+			MCP23017::GPIOA,
+			0b00000000
+		);
+
+		// Enable interrupt
+		ok = gpio1.write8(
+			MCP23017::GPINTENB,
+			0b11111111
+		);
+
+		// Clear interrupt
+		gpio1.read8(MCP23017::GPIOB, ok);
+
+		// TODO gpio2
 	}
+};
 
-	void deleteReportData(uint8_t keycode) {
-		for (int i = 0; i < 6; i++) {
-			if (inputReportData.data.keycode[i] == keycode) {
-				inputReportData.data.keycode[i] = 0;
-				startReportTicker();
-				return;
+I2C i2c(I2C_SDA0, I2C_SCL0);
+KeyboardMatrixController keyboardMatrixController(i2c);
+Keymap keymap(keyboardService);
+InterruptIn buttonInt(P0_5);
+DigitalIn buttonIntIn(P0_5);
+
+// ROWS=8
+// COLS=16
+// 列ごとに1バイトにパックしてキーの状態を保持する
+static uint8_t keysA[COLS];
+static uint8_t keysB[COLS];
+static bool state = 0;
+
+void buttonIntCallback() {
+	printf("pinChanged!!!\r\n");
+	uint8_t (&keysCurr)[COLS] = state ? keysA : keysB;
+	uint8_t (&keysPrev)[COLS] = state ? keysB : keysA;
+
+	printf("scanKeyboard\r\n");
+	keyboardMatrixController.scanKeyboard(keysCurr);
+
+	for (int col = 0; col < COLS; col++) {
+		uint8_t changed = keysPrev[col] ^ keysCurr[col];
+		if (changed) printf("changed: %x\r\n", changed);
+		for (int row = 0; row < ROWS; row++) {
+			if (changed & (1<<row)) {
+				bool pressed = keysCurr[col] & (1<<row);
+				printf("changed: col=%d, row=%d / pressed=%d\r\n", col, row, pressed);
+				// keymap.execute(col, row, pressed);
 			}
 		}
 	}
-
-	bool isKeyPressed() {
-		for (int i = 0; i < 8; i++) {
-			if (inputReportData.raw[i]) {
-				return 1;
-			}
-		}
-		return 0;
-	}
-
-	virtual void sendCallback(void) {
-		ble_error_t error = HIDServiceBase::send(inputReportData.raw);
-		if (error == BLE_STACK_BUSY) {
-			// retry after
-			return;
-		}
-
-		if (!isKeyPressed()) {
-			stopReportTicker();
-		}
-	}
-};
-
-void buttonIntCallback() {
-	int ok;
-	printf("buttonInt!!\r\n");
-	uint8_t read = gpio1.read8(MCP23017::GPIOA, ok);
-	printf("read %x\r\n", read);
+	state = !state;
 }
 
 int main(void) {
-	// printf("init\r\n");
+	printf("init\r\n");
 
 	// mbed's Serial of TARGET_RBLAB_BLENANO sucks
 	// DO NOT CONNECT RTS/CTS AUTOMATICALY!
 	NRF_UART0->PSELRTS = 0xFFFFFFFFUL;
 	NRF_UART0->PSELCTS = 0xFFFFFFFFUL;
 
-	buttonInt.mode(PullUp);
-	buttonInt.fall(buttonIntCallback);
-
 	int ok;
 
 	// 100kHz
 	i2c.frequency(100000);
 
-	ok = gpio1.write8(
-		MCP23017::IOCON,
-		0<<MCP23017::BANK |
-		1<<MCP23017::MIRROR |
-		1<<MCP23017::SEQOP |
-		0<<MCP23017::DISSLW |
-		1<<MCP23017::ODR
-	);
-
-	// IODIR
-	//   1: input
-	//   0: output
-	ok = gpio1.write16(
-		MCP23017::IODIRA,
-		0b1111111100000000
-	);
+	buttonInt.mode(PullUp);
+	buttonInt.fall(buttonIntCallback);
 
-	// INPUT POLARITY
-	ok = gpio1.write8(
-		MCP23017::IPOLA,
-		0b00000000
-	);
-	// INTERRUPT-ON-CHANGE Enable
-	ok = gpio1.write8(
-		MCP23017::GPINTENA,
-		0b11111111
-	);
-	// INTERRUPT-ON-CHANGE Control
-	//   1: compared with DEFVAL
-	//   0: compared to previous value
-	ok = gpio1.write8(
-		MCP23017::INTCONA,
-		0b00000000
-	);
-	// PULL-UP (for input pin)
-	//   1: pull-up enabled
-	//   0: pull-up disabled
-	ok = gpio1.write8(
-		MCP23017::GPPUA,
-		0b11111111
-	);
+	keyboardMatrixController.init();
+	buttonIntCallback();
 
-	if (!ok) {
-		printf("failed to write to i2c bus\r\n");
-	} else {
-		printf("wrote to i2c bus\r\n");
+	while (1) {
+		wait_ms(1000);
 	}
 
-	uint8_t read = gpio1.read8(MCP23017::GPIOA, ok);
-	printf("read %x\r\n", read);
-
-	while (1) {}
-
 	return;
 
 	// https://github.com/jpbrucker/BLE_HID/blob/master/examples/examples_common.cpp