Hiroh Satoh / keyboard Featured

Dependencies:   BLE_API mbed-dev nRF51822

Revision:
42:2c3be8694896
Parent:
41:2b034f22b98f
Child:
43:4de3870b39cb
--- a/main.cpp	Fri Aug 26 16:12:28 2016 +0000
+++ b/main.cpp	Sat Aug 27 08:43:53 2016 +0000
@@ -1,5 +1,5 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2015 ARM Limited
+/* BLE Keyboard Implementation for mbed
+ * Copyright (c) 2016 cho45 <cho45@lowreal.net>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,206 +18,15 @@
 #include "mbed.h"
 
 #include "HIDController_BLE.h"
-
-#include "mcp23017.h"
-#include "keymap.h"
-
-
-class KeyboardMatrixController {
-	I2C& i2c;
-	MCP23017 gpio1;
-	MCP23017 gpio2;
-	bool gpio1_ready;
-	bool gpio2_ready;
-
-	static const uint8_t GPIO1_SLAVE_ADDRESS = 0b0100000;
-	static const uint8_t GPIO2_SLAVE_ADDRESS = 0b0100100;
-
-	/**
-	 * COL=GPIOA (output normaly positive)
-	 * ROW=GPIOB (input pulled-up)
-	 */
-
-	bool setupGpio(MCP23017& gpio) {
-		int ok;
-		printf("SET IOCON\r\n");
-		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
-		);
-		if (!ok) return false;
-
-		// IODIR
-		//   1: input
-		//   0: output
-		printf("SET IODIRA\r\n");
-		ok = gpio.write16(
-			MCP23017::IODIRA,
-			0b0000000011111111
-		);
-		if (!ok) return false;
-
-		// INPUT POLARITY
-		//   1: inverse polarity
-		//   0: raw
-		printf("SET IPOLB\r\n");
-		ok = gpio.write8(
-			MCP23017::IPOLB,
-			0b11111111
-		);
-		if (!ok) return false;
-
-		// INTERRUPT-ON-CHANGE Enable
-		printf("SET GPINTENB\r\n");
-		ok = gpio.write8(
-			MCP23017::GPINTENB,
-			0b11111111
-		);
-		if (!ok) return false;
-		
-		// INTERRUPT-ON-CHANGE Control
-		//   1: compared with DEFVAL
-		//   0: compared to previous value
-		printf("SET INTCONB\r\n");
-		ok = gpio.write8(
-			MCP23017::INTCONB,
-			0b00000000
-		);
-		if (!ok) return false;
-		
-		// PULL-UP (for input pin)
-		//   1: pull-up enabled
-		//   0: pull-up disabled
-		printf("SET GPPUB\r\n");
-		ok = gpio.write8(
-			MCP23017::GPPUB,
-			0b11111111
-		);
-		if (!ok) return false;
-
-		printf("SET GPIOA\r\n");
-		ok = gpio1.write8(
-			MCP23017::GPIOA,
-			0b00000000
-		);
-		if (!ok) return false;
-
-		return true;
-	}
-
-public:
-	KeyboardMatrixController(I2C& _i2c) :
-		i2c(_i2c),
-		gpio1(i2c, GPIO1_SLAVE_ADDRESS),
-		gpio2(i2c, GPIO2_SLAVE_ADDRESS)
-	{
-	}
+#include "KeyboardMatrixController.h"
+#include "BatteryLevel.h"
+#include "WatchDog.h"
 
-	void init() {
-		printf("init gpio1\r\n");
-		gpio1_ready = setupGpio(gpio1);
-		printf("gpio1 initialized: %s\r\n", gpio1_ready ? "success" : "failed");
-		
-		printf("init gpio2\r\n");
-		gpio2_ready = setupGpio(gpio2);
-		printf("gpio2 initialized: %s\r\n", gpio2_ready ? "success" : "failed");
-
-	}
-
-	// __attribute__((used, long_call, section(".data")))
-	void scanKeyboard(uint8_t* keys) {
-		int ok;
-		
-		disableInterrupt();
-
-		if (gpio1_ready) {
-			for (int i = 0; i < 8; i++) {
-				ok = gpio1.write8(
-					MCP23017::GPIOA,
-					~(1<<i)
-				);
-				wait_us(1);
-				keys[i] = gpio1.read8(MCP23017::GPIOB, ok);
-			}
-	
-			// set all output to negative for interrupt
-			ok = gpio1.write8(
-				MCP23017::GPIOA,
-				0b00000000
-			);
-		}
-
+#include "keymap.h"
+#include "config.h"
 
-		if (gpio2_ready) {
-			for (int i = 0; i < 8; i++) {
-				ok = gpio2.write8(
-					MCP23017::GPIOA,
-					~(1<<i)
-				);
-				wait_us(1);
-				keys[i+8] = gpio2.read8(MCP23017::GPIOB, ok);
-			}
-	
-			// set all output to negative for interrupt
-			ok = gpio2.write8(
-				MCP23017::GPIOA,
-				0b00000000
-			);
-		}
-		
-		enableInterrupt();
-	}
-	
-	int disableInterrupt() {
-		int ok;
-		if (gpio1_ready) {
-			// Disable interrupt
-			ok = gpio1.write8(
-				MCP23017::GPINTENB,
-				0b00000000
-			);
-		}
-		
-		if (gpio2_ready) {
-			// Disable interrupt
-			ok = gpio2.write8(
-				MCP23017::GPINTENB,
-				0b00000000
-			);
-		}
-		return ok;
-	}
-
-	int enableInterrupt() {
-		int ok;
-		if (gpio1_ready) {
-			// Enable interrupt
-			ok = gpio1.write8(
-				MCP23017::GPINTENB,
-				0b11111111
-			);
-		}
-		
-		if (gpio2_ready) {
-			// Enable interrupt
-			ok = gpio2.write8(
-				MCP23017::GPINTENB,
-				0b11111111
-			);
-		}
-
-		// Clear interrupt
-		// gpio1.read8(MCP23017::GPIOB, ok);
-		return ok;
-	}
-};
-
+RawSerial serial(USBTX, USBRX);
 I2C i2c(I2C_SDA0, I2C_SCL0);
-// Serial serial(USBTX, USBRX);
 KeyboardMatrixController keyboardMatrixController(i2c);
 Keymap keymap;
 
@@ -228,20 +37,6 @@
 #define PIN_STATUS_LED P0_4
 DigitalOut statusLed(PIN_STATUS_LED, 0);
 
-// Unsed pins. Set to output for power consumption
-
-// Pad pinout
-/*
-DigitalIn unused_p0_7(P0_7, PullUp);
-DigitalIn unused_p0_6(P0_6, PullUp);
-DigitalIn unused_p0_15(P0_15, PullUp);
-DigitalIn unused_p0_29(P0_29, PullUp);
-DigitalIn unused_p0_28(P0_28, PullUp);
-*/
-
-DigitalIn unused_p0_19(P0_19, PullUp); // This is on board LED which connected to VDD
-DigitalIn unused_p0_11(P0_11, PullUp); // RXD
-
 Timeout timeout;
 
 // ROWS=8
@@ -261,7 +56,7 @@
 }
 
 void powerOff() {
-	printf("power off\r\n");
+	DEBUG_PRINTF("power off\r\n");
 	NRF_POWER->SYSTEMOFF = 1;
 }
 
@@ -292,82 +87,17 @@
 	keyIntervalInterrupt = true;
 }
 
-class WatchDog {
-	static const uint32_t RELOAD_VALUE = 0x6E524635;
-	static const uint8_t WDT_TIMEOUT = 3; // sec
-public:
-	static void init() {
-		// timeout [s] = (CRV + 1) / 32768;
-		// crv = 32768 * timeout - 1
-		NRF_WDT->CRV = 32768 * WDT_TIMEOUT - 1;
-		NRF_WDT->RREN = WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos;
-		NRF_WDT->CONFIG = WDT_CONFIG_SLEEP_Pause << WDT_CONFIG_SLEEP_Pos;
-		NRF_WDT->TASKS_START = 1;
-	}
-	
-	static void reload() {
-		NRF_WDT->RR[0] = RELOAD_VALUE;
-	}
-	
-};
-
-class Battery {
-
-public:
-	static const float BATTERY_MAX = 2.4;
-	static const float REFERNECE = 1.2;
-	static const float PRESCALE = 3;
-	static const float BATTERY_LOW = 2.0;
-	
-	static uint8_t readBatteryPercentage(float voltage) {
-		uint16_t percentage = (voltage - BATTERY_LOW) / (BATTERY_MAX - BATTERY_LOW) * 100;
-		if (percentage > 100) percentage = 100;
-		return percentage;
-	}
-	
-	static float readBatteryVoltage() {
-		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);
-		
-		NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled;
-		
-		float ratio = raw10bit / static_cast<float>(1<<10);
-	
-		float batteryVoltage = ratio * (REFERNECE * PRESCALE);
-		return batteryVoltage;
-	}
-};
-
 #define is_pressed(keys, row, col) (!!(keys[col] & (1<<row)))
 
 int main(void) {
 	{
 		uint32_t reason = NRF_POWER->RESETREAS;
 		NRF_POWER->RESETREAS = 0xffffffff; // clear reason
-		printf("init [%x]\r\n", reason);
+		serial.printf("init [%x]\r\n", reason);
 	}
 	
-	float battery = Battery::readBatteryVoltage();
-	if (battery < Battery::BATTERY_LOW) {
+	float battery = BatteryLevel::readBatteryVoltage();
+	if (battery < BatteryLevel::BATTERY_LOW) {
 		powerOff();
 	}
 			
@@ -391,9 +121,67 @@
 		(NRF_GPIO->PIN_CNF[PIN_STATUS_LED] & ~GPIO_PIN_CNF_DRIVE_Msk) |
 		(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos);
 
+	// Unsed pins.
+	// Set as PullUp for power consumption
+	// Use GPIO registers directly for saving ram
+	// Pad pinouts
+	/* 
+	DigitalIn unused_p0_7(P0_7, PullUp);
+	DigitalIn unused_p0_6(P0_6, PullUp);
+	DigitalIn unused_p0_15(P0_15, PullUp);
+	DigitalIn unused_p0_29(P0_29, PullUp);
+	DigitalIn unused_p0_28(P0_28, PullUp);
+	*/
+	NRF_GPIO->PIN_CNF[P0_7] =
+		(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) |
+		(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
+		(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
+		(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
+		(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+	NRF_GPIO->PIN_CNF[P0_6] =
+		(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) |
+		(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
+		(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
+		(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
+		(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+	NRF_GPIO->PIN_CNF[P0_15] =
+		(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) |
+		(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
+		(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
+		(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
+		(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+	NRF_GPIO->PIN_CNF[P0_29] =
+		(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) |
+		(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
+		(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
+		(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
+		(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+	NRF_GPIO->PIN_CNF[P0_28] =
+		(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) |
+		(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
+		(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
+		(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
+		(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+	/*
+	DigitalIn unused_p0_19(P0_19, PullUp); // This is on board LED which connected to VDD
+	DigitalIn unused_p0_11(P0_11, PullUp); // RXD
+	*/
+	NRF_GPIO->PIN_CNF[P0_19] = // This is on board LED which connected to VDD
+		(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) |
+		(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
+		(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
+		(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
+		(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+	NRF_GPIO->PIN_CNF[P0_11] = // RXD
+		(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) |
+		(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
+		(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
+		(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
+		(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+
 	WatchDog::init();
-			    		
-	// 100kHz
+
+	// only 100kHz/250khz/400khz
 	i2c.frequency(250000);
 
 	buttonInt.mode(PullUp);
@@ -414,7 +202,7 @@
 		WatchDog::reload();
 		
 		if (pollCount > 0) {
-			printf("scan keys\r\n");
+			DEBUG_PRINTF("scan keys\r\n");
   		    
 			while (pollCount-- > 0) {
 				WatchDog::reload();
@@ -434,7 +222,7 @@
 					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);
+							// DEBUG_KEYEVENT("changed: col=%d, row=%d / pressed=%d\r\n", col, row, pressed);
 							keymap.execute(col, row, pressed);
 						}
 					}
@@ -449,11 +237,11 @@
 				    	is_pressed(keysCurr, 1, 0) && // left top 2
 				    	is_pressed(keysCurr, 0, 15)   // right top
 				    ) {
-				    	printf("re-init connection\r\n");
+				    	DEBUG_PRINTF("re-init connection\r\n");
 				    	HIDController::initializeConnection(true);
 				    } else {
 				    	if (HIDController::status() == TIMEOUT) {
-					    	printf("wakeup\r\n");
+					    	DEBUG_PRINTF("wakeup\r\n");
 					    	HIDController::initializeConnection(false);
 				    	}
 				    }
@@ -470,11 +258,11 @@
 		} else {
 			if (!updateStatudLedEnabled) updateStatusLed();
 			
-			float batteryVoltage = Battery::readBatteryVoltage();
-			uint8_t batteryPercentage = Battery::readBatteryPercentage(batteryVoltage);
-			bool isLowBattery = batteryVoltage < Battery::BATTERY_LOW;
+			float batteryVoltage = BatteryLevel::readBatteryVoltage();
+			uint8_t batteryPercentage = BatteryLevel::readBatteryPercentage(batteryVoltage);
+			bool isLowBattery = batteryVoltage < BatteryLevel::BATTERY_LOW;
 
-			printf("%d%% [%d:%s] %s\r\n",
+			DEBUG_PRINTF("%d%% [%d:%s] %s\r\n",
 				batteryPercentage,
 				HIDController::status(),
 				HIDController::statusString(),
@@ -487,27 +275,30 @@
 				powerOff();
 			}
     
-
-			// disable internal HFCLK RC Clock surely. It consume 1mA constantly
-			// TWI / SPI / UART must be disabled and boot without debug mode
-			while (NRF_UART0->EVENTS_TXDRDY != 1);
 			
-			uint32_t tx = NRF_UART0->PSELTXD;
-			
-			NRF_UART0->TASKS_STOPTX = 1;
-			NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Disabled << UART_ENABLE_ENABLE_Pos);
-
-			HIDController::waitForEvent();
-						
-			NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
-			NRF_UART0->TASKS_STARTTX = 1;
-			// dummy send to wakeup...
-			NRF_UART0->PSELTXD = 0xFFFFFFFF;
-		    NRF_UART0->EVENTS_TXDRDY = 0;
-		    NRF_UART0->TXD = 0;
-		    while (NRF_UART0->EVENTS_TXDRDY != 1);
-			NRF_UART0->PSELTXD = tx;
-
+			if (DEBUG_BLE_INTERRUPT) {
+				HIDController::waitForEvent();
+			} else {
+				// disable internal HFCLK RC Clock surely. It consume 1mA constantly
+				// TWI / SPI / UART must be disabled and boot without debug mode
+				while (NRF_UART0->EVENTS_TXDRDY != 1);
+				
+				uint32_t tx = NRF_UART0->PSELTXD;
+				
+				NRF_UART0->TASKS_STOPTX = 1;
+				NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Disabled << UART_ENABLE_ENABLE_Pos);
+	
+				HIDController::waitForEvent();
+							
+				NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
+				NRF_UART0->TASKS_STARTTX = 1;
+				// dummy send to wakeup...
+				NRF_UART0->PSELTXD = 0xFFFFFFFF;
+			    NRF_UART0->EVENTS_TXDRDY = 0;
+			    NRF_UART0->TXD = 0;
+			    while (NRF_UART0->EVENTS_TXDRDY != 1);
+				NRF_UART0->PSELTXD = tx;
+			}
 		}
 	}
 }
\ No newline at end of file