changeset 153:0f8218554421

Press/Release is working! - Removed 'Zombie' code - Still a bit of iffiness with the averaging algorithm (should be looked at again) - Added more CLI debugging (averaging and press/debounce)
author Jacob Alexander <haata@kiibohd.com>
date Sun, 20 Apr 2014 01:08:02 -0700
parents cddbce3da134
children a2be5e8fc3d7
files README Scan/DPH/scan_loop.c
diffstat 2 files changed, 176 insertions(+), 184 deletions(-) [+]
line wrap: on
line diff
--- a/README	Sat Apr 19 20:17:38 2014 -0700
+++ b/README	Sun Apr 20 01:08:02 2014 -0700
@@ -62,6 +62,7 @@
 You just need the Atmel AVR 8-bit Toolchain. The latest should be fine, as of writing it was 3.4.3.
 
 http://www.atmel.com/tools/atmelavrtoolchainforwindows.aspx
+(Atmel AVR 8-bit Toolchain 3.4.3 - Windows)
 
 Extract the files to a directory, say C:\avr8-gnu-toolchain. Then copy all the folders in that directory to the Cygwin directory.
 Mine is C:\cygwin64.
--- a/Scan/DPH/scan_loop.c	Sat Apr 19 20:17:38 2014 -0700
+++ b/Scan/DPH/scan_loop.c	Sun Apr 20 01:08:02 2014 -0700
@@ -41,9 +41,6 @@
 
 #define STROBE_SETTLE 1
 
-#define TEST_KEY_STROBE (0x05)
-#define TEST_KEY_MASK (1 << 0)
-
 #define ADHSM 7
 
 #define RIGHT_JUSTIFY 0
@@ -85,7 +82,7 @@
 #define MUXES_COUNT 8
 #define MUXES_COUNT_XSHIFT 3
 
-#define WARMUP_LOOPS ( 1024 )
+#define WARMUP_LOOPS ( 2048 )
 #define WARMUP_STOP (WARMUP_LOOPS - 1)
 
 #define SAMPLE_CONTROL 3
@@ -122,10 +119,28 @@
 
 // ----- Function Declarations -----
 
+// CLI Functions
+void cliFunc_avgDebug  ( char* args );
 void cliFunc_echo      ( char* args );
 void cliFunc_keyDebug  ( char* args );
+void cliFunc_pressDebug( char* args );
 void cliFunc_senseDebug( char* args );
 
+// Debug Functions
+void dumpSenseTable();
+
+// High-level Capsense Functions
+void setup_ADC();
+void capsense_scan();
+
+// Capsense Sense Functions
+void testColumn  ( uint8_t strobe );
+void sampleColumn( uint8_t column );
+
+// Low-level Capsense Functions
+void strobe_w( uint8_t strobe_num );
+void recovery( uint8_t on );
+
 
 
 // ----- Variables -----
@@ -139,18 +154,20 @@
 char*       scanCLIDictName = "DPH Module Commands";
 CLIDictItem scanCLIDict[] = {
 	{ "echo",       "Example command, echos the arguments.", cliFunc_echo },
+	{ "avgDebug",   "Enables/Disables averaging results." NL "\t\tDisplays each average, starting from Key 0x00, ignoring 0 valued averages.", cliFunc_avgDebug },
 	{ "keyDebug",   "Enables/Disables long debug for each keypress." NL "\t\tkeycode - [strobe:mux] : sense val : threshold+delta=total : margin", cliFunc_keyDebug },
-	{ "senseDebug", "Prints out the current sense table N times." NL "\t\tsense:threshold:delta.", cliFunc_senseDebug },
+	{ "pressDebug", "Enables/Disables short debug for each keypress.", cliFunc_pressDebug },
+	{ "senseDebug", "Prints out the current sense table N times." NL "\t\tsense:max sense:delta", cliFunc_senseDebug },
 	{ 0, 0, 0 } // Null entry for dictionary end
 };
 
 // CLI Control Variables
-uint8_t enableKeyDebug  = 1; // XXX Debugging on by default for now -HaaTa
-uint8_t senseDebugCount = 0;
+uint8_t enableAvgDebug   = 0;
+uint8_t enableKeyDebug   = 0;
+uint8_t enablePressDebug = 1;
+uint8_t senseDebugCount  = 3; // In order to get boot-time oddities
 
 
-// TODO dfj variables...needs cleaning up and commenting
-
 // Variables used to calculate the starting sense value (averaging)
 uint32_t full_avg = 0;
 uint32_t high_avg = 0;
@@ -160,55 +177,27 @@
 uint8_t   low_count = 0;
 
 
-uint16_t samples[MAX_STROBES][MUXES_COUNT];
+uint16_t samples[MAX_STROBES][MUXES_COUNT];   // Overall table of cap sense ADC values
+uint16_t sampleMax[MAX_STROBES][MUXES_COUNT]; // Records the max seen ADC value
 
-uint8_t cur_keymap[MAX_STROBES];
-
-uint8_t keymap_change;
+uint8_t key_activity = 0; // Increments for each detected key per each full scan of the keyboard, it is reset before each full scan
+uint8_t key_release  = 0; // Indicates if going from key press state to release state (some keys pressed to no keys pressed)
 
 uint16_t threshold = THRESHOLD;
 
-uint8_t column = 0;
-
 uint16_t keys_averages_acc[KEY_COUNT];
 uint16_t keys_averages    [KEY_COUNT];
 uint8_t  keys_debounce    [KEY_COUNT]; // Contains debounce statistics
 uint8_t  keys_problem     [KEY_COUNT]; // Marks keys that should be ignored (determined by averaging at startup)
 
-uint8_t full_samples[KEY_COUNT];
-
 // TODO: change this to 'booting', then count down.
 uint16_t boot_count = 0;
 
-uint16_t idle_count = 0;
-uint8_t idle = 1;
-
-uint8_t error = 0;
-uint16_t error_data = 0;
-
 uint8_t total_strobes = MAX_STROBES;
 uint8_t strobe_map[MAX_STROBES];
 
 
 
-// ----- Function Declarations -----
-
-void dumpSenseTable();
-
-void recovery( uint8_t on );
-
-int sampleColumn( uint8_t column );
-
-void capsense_scan();
-
-void setup_ADC();
-
-void strobe_w( uint8_t strobe_num );
-
-uint8_t testColumn( uint8_t strobe );
-
-
-
 // ----- Functions -----
 
 // Initial setup for cap sense controller
@@ -311,11 +300,6 @@
 	// TODO
 #endif
 
-	for ( int i = 0; i < total_strobes; ++i)
-	{
-		cur_keymap[i] = 0;
-	}
-
 	// Reset debounce table
 	for ( int i = 0; i < KEY_COUNT; ++i )
 	{
@@ -336,33 +320,6 @@
 {
 	capsense_scan();
 
-	// Error case, should not occur in normal operation
-	if ( error )
-	{
-		erro_msg("Problem detected... ");
-
-		// Keymap scan debug
-		for ( uint8_t i = 0; i < total_strobes; ++i )
-		{
-			printHex(cur_keymap[strobe_map[i]]);
-			print(" ");
-		}
-
-		print(" : ");
-		printHex(error);
-		error = 0;
-		print(" : ");
-		printHex(error_data);
-		error_data = 0;
-
-		// Display sense table if warmup completede
-		if ( boot_count >= WARMUP_LOOPS )
-		{
-			dumpSenseTable();
-		}
-	}
-
-
 	// Return non-zero if macro and USB processing should be delayed
 	// Macro processing will always run if returning 0
 	// USB processing only happens once the USB send timer expires, if it has not, Scan_loop will be called
@@ -401,34 +358,21 @@
 
 	high_count = 0;
 
+	// Reset key activity, if there is no key activity, averages will accumulate for sense deltas, otherwise they will be reset
+	key_activity = 0;
+
 	// Scan each of the mapped strobes in the matrix
 	for ( uint8_t strober = 0; strober < total_strobes; ++strober )
 	{
 		uint8_t map_strobe = strobe_map[strober];
 
-		uint8_t tries = 1;
-		while ( tries++ && sampleColumn( map_strobe ) ) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+		// Sample the ADCs for the given column/strobe
+		sampleColumn( map_strobe );
 
 		// Only process sense data if warmup is finished
 		if ( boot_count >= WARMUP_LOOPS )
 		{
-			column = testColumn( map_strobe );
-
-			idle |= column; // if column has any pressed keys, then we are not idle.
-
-			// TODO Is this needed anymore? Really only helps debug -HaaTa
-			if( column != cur_keymap[map_strobe] && ( boot_count >= WARMUP_LOOPS ) )
-			{
-				cur_keymap[map_strobe] = column;
-				keymap_change = 1;
-			}
-
-			idle |= keymap_change; // if any keys have changed inc. released, then we are not idle.
-		}
-
-		if ( error == 0x50 )
-		{
-			error_data |= (((uint16_t)map_strobe) << 12);
+			testColumn( map_strobe );
 		}
 
 		uint8_t strobe_line = map_strobe << MUXES_COUNT_XSHIFT;
@@ -436,7 +380,6 @@
 		{
 			// discard sketchy low bit, and meaningless high bits.
 			uint8_t sample = samples[map_strobe][mux] >> 1;
-			full_samples[strobe_line + mux] = sample;
 			keys_averages_acc[strobe_line + mux] += sample;
 		}
 
@@ -489,23 +432,6 @@
 		}
 	}
 
-#ifdef VERIFY_TEST_PAD
-	// verify test key is not down.
-	if ( ( cur_keymap[TEST_KEY_STROBE] & TEST_KEY_MASK ) )
-	{
-		error = 0x05;
-		error_data = cur_keymap[TEST_KEY_STROBE] << 8;
-		error_data += full_samples[TEST_KEY_STROBE * 8];
-	}
-#endif
-
-	/** aggregate if booting, or if idle;
-	 * else, if not booting, check for dirty USB.
-	 * */
-
-	idle_count++;
-	idle_count &= IDLE_COUNT_MASK;
-
 	// Warm up voltage references
 	if ( boot_count < WARMUP_LOOPS )
 	{
@@ -568,43 +494,60 @@
 	}
 	else
 	{
-		// Reset accumulators and idle flag/counter
-		if ( keymap_change )
-		{
-			for ( uint8_t c = 0; c < KEY_COUNT; ++c ) { keys_averages_acc[c] = 0; }
-			idle_count = 0;
-			idle = 0;
-
-			keymap_change = 0;
-		}
-
-		if ( !idle_count )
+		// No keypress, accumulate averages
+		if( !key_activity )
 		{
-			if( idle )
+			// Average Debugging
+			if ( enableAvgDebug )
+			{
+				print("\033[1mAvg\033[0m: ");
+			}
+
+			// aggregate
+			for ( uint8_t i = 0; i < KEY_COUNT; ++i )
 			{
-				// aggregate
-				for ( uint8_t i = 0; i < KEY_COUNT; ++i )
+				uint16_t acc = keys_averages_acc[i];
+				//uint16_t acc = keys_averages_acc[i] >> IDLE_COUNT_SHIFT; // XXX This fixes things... -HaaTa
+				uint32_t av = keys_averages[i];
+
+				av = (av << KEYS_AVERAGES_MIX_SHIFT) - av + acc;
+				av >>= KEYS_AVERAGES_MIX_SHIFT;
+
+				keys_averages[i] = av;
+				keys_averages_acc[i] = 0;
+
+				// Average Debugging
+				if ( enableAvgDebug && av > 0 )
 				{
-					uint16_t acc = keys_averages_acc[i] >> IDLE_COUNT_SHIFT;
-					uint32_t av = keys_averages[i];
-
-					av = (av << KEYS_AVERAGES_MIX_SHIFT) - av + acc;
-					av >>= KEYS_AVERAGES_MIX_SHIFT;
-
-					keys_averages[i] = av;
-					keys_averages_acc[i] = 0;
+					printHex( av );
+					print(" ");
 				}
 			}
 
-			// If the debugging sense table is non-zero, display
-			if ( senseDebugCount > 0 )
+			// Average Debugging
+			if ( enableAvgDebug )
 			{
-				senseDebugCount--;
 				print( NL );
-				dumpSenseTable();
 			}
+
+			// No key presses detected, set key_release indicator
+			key_release = 1;
+		}
+		// Keypresses, reset accumulators
+		else if ( key_release )
+		{
+			for ( uint8_t c = 0; c < KEY_COUNT; ++c ) { keys_averages_acc[c] = 0; }
+
+			key_release = 0;
 		}
 
+		// If the debugging sense table is non-zero, display
+		if ( senseDebugCount > 0 )
+		{
+			senseDebugCount--;
+			print( NL );
+			dumpSenseTable();
+		}
 	}
 }
 
@@ -739,7 +682,7 @@
 }
 
 
-int sampleColumn( uint8_t column )
+void sampleColumn( uint8_t column )
 {
 	// ensure all probe lines are driven low, and chill for recovery delay.
 	ADCSRA |= (1 << ADEN) | (1 << ADSC); // enable and start conversions
@@ -769,7 +712,15 @@
 		SET_FULL_MUX( mux + 1 ); // our *next* sample will use this
 
 		// retrieve current read.
-		samples[column][mux] = getADC();
+		uint16_t readVal = getADC();
+		samples[column][mux] = readVal;
+
+		// Update max sense sample table
+		if ( readVal > sampleMax[column][mux] )
+		{
+			sampleMax[column][mux] = readVal;
+		}
+
 		mux++;
 
 	} while ( mux < 8 );
@@ -788,12 +739,10 @@
 	PORTC &= ~C_MASK;
 	PORTD &= ~D_MASK;
 	PORTE &= ~E_MASK;
-
-	return 0;
 }
 
 
-uint8_t testColumn( uint8_t strobe )
+void testColumn( uint8_t strobe )
 {
 	uint16_t db_delta = 0;
 	uint8_t  db_sample = 0;
@@ -821,11 +770,9 @@
 
 				keys_problem[key] = 0;
 			}
-			// Otherwise, don't waste any more cycles processing the problem key
-			else
-			{
-				continue;
-			}
+
+			// Do not waste any more cycles processing, regardless, a keypress cannot be detected
+			continue;
 		}
 
 		// Keypress detected
@@ -833,6 +780,7 @@
 		if ( (db_sample = samples[strobe][mux] >> 1) > (db_threshold = threshold) + (db_delta = delta) )
 		{
 			column |= bit;
+			key_activity++; // No longer idle, stop averaging ADC data
 
 			// Only register keypresses once the warmup is complete, or not enough debounce info
 			if ( keys_debounce[key] <= DEBOUNCE_THRESHOLD )
@@ -841,13 +789,13 @@
 				// Automatically handles converting to a USB code and sending off to the PC
 				if ( keys_debounce[key] == DEBOUNCE_THRESHOLD )
 				{
-//#define KEYSCAN_DEBOUNCE_DEBUG
-#ifdef KEYSCAN_DEBOUNCE_DEBUG
-					// Debug message
-					print("0x");
-					printHex_op( key, 2 );
-					print(" ");
-#endif
+					// Debug message, pressDebug CLI
+					if ( enablePressDebug )
+					{
+						print("0x");
+						printHex_op( key, 2 );
+						print(" ");
+					}
 
 					// Only add the key to the buffer once
 					// NOTE: Buffer can easily handle multiple adds, just more efficient
@@ -857,29 +805,30 @@
 
 				keys_debounce[key]++;
 
-				// Long form key debugging
-				if ( enableKeyDebug )
-				{
-					// Debug message
-					// <key> [<strobe>:<mux>] : <sense val> : <delta + threshold> : <margin>
-					dbug_msg("0x");
-					printHex_op( key, 2 );
-					print(" [");
-					printInt8( strobe );
-					print(":");
-					printInt8( mux );
-					print("] : ");
-					printHex( db_sample ); // Sense
-					print(" : ");
-					printHex( db_threshold );
-					print("+");
-					printHex( db_delta );
-					print("=");
-					printHex( db_threshold + db_delta ); // Sense compare
-					print(" : ");
-					printHex( db_sample - ( db_threshold + db_delta ) ); // Margin
-					print( NL );
-				}
+			}
+
+			// Long form key debugging
+			if ( enableKeyDebug )
+			{
+				// Debug message
+				// <key> [<strobe>:<mux>] : <sense val> : <delta + threshold> : <margin>
+				dbug_msg("0x");
+				printHex_op( key, 2 );
+				print(" [");
+				printInt8( strobe );
+				print(":");
+				printInt8( mux );
+				print("] : ");
+				printHex( db_sample ); // Sense
+				print(" : ");
+				printHex( db_threshold );
+				print("+");
+				printHex( db_delta );
+				print("=");
+				printHex( db_threshold + db_delta ); // Sense compare
+				print(" : ");
+				printHex( db_sample - ( db_threshold + db_delta ) ); // Margin
+				print( NL );
 			}
 		}
 		// Clear debounce entry if no keypress detected
@@ -909,14 +858,15 @@
 
 		bit <<= 1;
 	}
-	return column;
 }
 
 
 void dumpSenseTable()
 {
-	// Initial table alignment
-	print("           ");
+	// Initial table alignment, with base threshold used for every key
+	print("\033[1m");
+	printHex( threshold );
+	print("\033[0m       ");
 
 	// Print out headers first
 	for ( uint8_t mux = 0; mux < MUXES_COUNT; ++mux )
@@ -942,14 +892,21 @@
 		for ( uint8_t mux = 0; mux < MUXES_COUNT; ++mux )
 		{
 			uint8_t delta = keys_averages[(strobe << MUXES_COUNT_XSHIFT) + mux];
-			uint8_t sample = samples[strobe][mux] >> 1; // TODO Make larger samples array (2d)
+			uint8_t sample = samples[strobe][mux] >> 1;
+			uint8_t max = sampleMax[strobe][mux] >> 1;
+
+			// Indicate if the key is being pressed by displaying green
+			if ( sample > delta + threshold )
+			{
+				print("\033[1;32m");
+			}
 
 			printHex_op( sample, 2 );
 			print(":");
-			printHex_op( threshold, 2 );
+			printHex_op( max, 2 );
 			print(":");
 			printHex_op( delta, 2 );
-			print(" ");
+			print("\033[0m ");
 		}
 
 		// New line for each strobe
@@ -984,6 +941,23 @@
 	}
 }
 
+void cliFunc_avgDebug( char* args )
+{
+	print( NL );
+
+	// Args ignored, just toggling
+	if ( enableAvgDebug )
+	{
+		info_print("Cap Sense averaging debug disabled.");
+		enableAvgDebug = 0;
+	}
+	else
+	{
+		info_print("Cap Sense averaging debug enabled.");
+		enableAvgDebug = 1;
+	}
+}
+
 void cliFunc_keyDebug( char* args )
 {
 	print( NL );
@@ -991,16 +965,33 @@
 	// Args ignored, just toggling
 	if ( enableKeyDebug )
 	{
-		info_print("Cap Sense key debug disabled.");
+		info_print("Cap Sense key long debug disabled - pre debounce.");
 		enableKeyDebug = 0;
 	}
 	else
 	{
-		info_print("Cap Sense key debug enabled.");
+		info_print("Cap Sense key long debug enabled - pre debounce.");
 		enableKeyDebug = 1;
 	}
 }
 
+void cliFunc_pressDebug( char* args )
+{
+	print( NL );
+
+	// Args ignored, just toggling
+	if ( enablePressDebug )
+	{
+		info_print("Cap Sense key debug disabled - post debounce.");
+		enablePressDebug = 0;
+	}
+	else
+	{
+		info_print("Cap Sense key debug enabled - post debounce.");
+		enablePressDebug = 1;
+	}
+}
+
 void cliFunc_senseDebug( char* args )
 {
 	// Parse code from argument