Hiroh Satoh / keyboard Featured

Dependencies:   BLE_API mbed-dev nRF51822

Revision:
4:54cb552e50c4
Parent:
3:266dfa9f8709
Child:
5:65d4e94735b6
--- a/main.cpp	Tue Jul 19 01:06:00 2016 +0900
+++ b/main.cpp	Wed Jul 20 02:05:45 2016 +0900
@@ -19,6 +19,7 @@
 #include "KeyboardService.h"
 #include "BatteryService.h"
 #include "DeviceInformationService.h"
+#include "mcp23017.h"
 
 static const char MODEL_NAME[] = "keyboard";
 static const char SERIAL_NUMBER[] = "X00000";
@@ -33,8 +34,6 @@
 static const bool REQUIRE_MITM = true;
 static const uint8_t PASSKEY[6] = {'1','2','3','4','5','6'}; // must be 6-digits number
 
-InterruptIn button1(D2);
-
 static const uint16_t uuid16_list[] =  {
 	GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE,
 	GattService::UUID_DEVICE_INFORMATION_SERVICE,
@@ -45,19 +44,45 @@
 BatteryService* batteryService;
 DeviceInformationService* deviceInformationService;
 
-// I2C i2c(D2, D3);
-AnalogIn batteryInput(A4);
+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;
+	static const float REFERNECE = 1.2;
+	static const float PRESCALE = 3;
 
-	float batteryVoltage = batteryInput.read() * 1.2 * 3;
+	NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
+
+	// Use internal 1.2V reference for batteryInput
+	//	1/3 pre-scaled input and 1.2V internal band gap reference
+	// ref. mbed-src/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/analogin_api.c
+	NRF_ADC->CONFIG =
+		(ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
+		// Use VDD 1/3 for input
+		(ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
+		// Use internal band gap for reference
+		(ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
+		(ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
+
+	// Start ADC
+	NRF_ADC->TASKS_START = 1;
+	while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) {
+		// busy loop
+	}
+
+	// Read ADC result
+	uint16_t raw10bit = static_cast<uint16_t>(NRF_ADC->RESULT);
+	float ratio = raw10bit / static_cast<float>(1<<10);
+
+	float batteryVoltage = ratio * (REFERNECE * PRESCALE);
 	float percentage = (batteryVoltage / BATTERY_MAX) * 100;
 	if (percentage > 100) {
 		percentage = 100;
 	}
-	printf("updateBatteryLevel %d\r\n",static_cast<uint8_t>(percentage));
+	printf("updateBatteryLevel %f V : %d/100\r\n", batteryVoltage, static_cast<uint8_t>(percentage));
 	batteryService->updateBatteryLevel(static_cast<uint8_t>(percentage));
 }
 
@@ -177,32 +202,157 @@
 	return;
 }
 
-void send_string(const char * c) {
-	if (!keyboardService) return;
+class MyKeyboardService : public HIDServiceBase {
+	union {
+		uint8_t raw[8];
+		struct {
+			uint8_t modifier;
+			uint8_t padding;
+			uint8_t keycode[6];
+		} data;
+	} inputReportData;
+
+	union {
+		uint8_t raw[1];
+	} outputReportData;
+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
+		)
+	{
+	}
+
+	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;
+			}
+		}
 
-	if (!keyboardService->isConnected()) {
-		printf("we haven't connected yet...");
-	} else {
-		int len = strlen(c);
-		keyboardService->printf(c);
-		printf("sending %d chars\r\n", len);
+		// TODO: report data is full
+	}
+
+	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;
+			}
+		}
 	}
-}
+
+	bool isKeyPressed() {
+		for (int i = 0; i < 8; i++) {
+			if (inputReportData.raw[i]) {
+				return 1;
+			}
+		}
+		return 0;
+	}
 
-void send_stuff() {
-	send_string("hello world!\n");
+	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);
 }
 
 int main(void) {
-	// Use internal 1.2V reference for batteryInput
-	//	1/3 pre-scaled input and 1.2V internal band gap reference
-	//	(mbed uses vdd for reference but i want use band gap)
-	// ref. mbed-src/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/analogin_api.c
-	NRF_ADC->CONFIG =
-		(ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
-		(ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
-		(ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
-		(ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
+	// 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
+	);
+
+	// 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
+	);
+
+	if (!ok) {
+		printf("failed to write to i2c bus\r\n");
+	} else {
+		printf("wrote to i2c bus\r\n");
+	}
+
+	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
 
@@ -210,8 +360,6 @@
 	BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
 	ble.init(bleInitComplete);
 
-	button1.rise(send_stuff);
-
 	while (!ble.hasInitialized()) { }
 
 	printf("ble.hasIntialized\r\n");