changeset 361:7c6ac7b88cda

Working support for Interconnect - Supports up to 255 slave nodes (you'll run into ScanCode limitations before then) - Requires most recent kll compiler update - Additional debugging output and stats counters - Noise and parity checking - Fixed TxFIFO issue when sending buffers larger than the FIFO - Cleaned up defaultMap.kll - Added ScanCode caching (reduces interconnect traffic significantly) - Interconnect module code is conditionally compiled into PartialMap module if required
author Jacob Alexander <haata@kiibohd.com>
date Sat, 15 Aug 2015 21:53:59 -0700
parents dbefb68411e1
children e4be15c39cce
files Lib/CMake/kll.cmake Macro/PartialMap/macro.c Macro/PartialMap/macro.h Scan/MDErgo1/defaultMap.kll Scan/UARTConnect/connect_scan.c Scan/UARTConnect/connect_scan.h
diffstat 6 files changed, 349 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/Lib/CMake/kll.cmake	Sun Aug 09 00:20:41 2015 -0700
+++ b/Lib/CMake/kll.cmake	Sat Aug 15 21:53:59 2015 -0700
@@ -58,7 +58,6 @@
 string ( REPLACE " " ";" MAP_LIST ${BaseMap} ) # Change spaces to semicolons
 foreach ( MAP ${MAP_LIST} )
 	# Only check the Scan Module for BaseMap .kll files, default to defaultMap.kll
-	message("THIS -> ${pathname} ${MAP}")
 	if ( NOT EXISTS ${pathname}/${MAP}.kll )
 		set ( BaseMap_Args ${BaseMap_Args} ${pathname}/defaultMap.kll )
 		set ( KLL_DEPENDS ${KLL_DEPENDS} ${pathname}/defaultMap.kll )
--- a/Macro/PartialMap/macro.c	Sun Aug 09 00:20:41 2015 -0700
+++ b/Macro/PartialMap/macro.c	Sat Aug 15 21:53:59 2015 -0700
@@ -156,6 +156,13 @@
 uint16_t macroResultMacroPendingList[ ResultMacroNum ] = { 0 };
 uint16_t macroResultMacroPendingListSize = 0;
 
+// Interconnect ScanCode Cache
+#if defined(ConnectEnabled_define)
+// TODO This can be shrunk by the size of the max node 0 ScanCode
+TriggerGuide macroInterconnectCache[ MaxScanCode ];
+uint8_t macroInterconnectCacheSize = 0;
+#endif
+
 
 
 // ----- Capabilities -----
@@ -424,18 +431,73 @@
 	// Otherwise no defined Trigger Macro
 	erro_msg("Scan Code has no defined Trigger Macro: ");
 	printHex( scanCode );
+	print( NL );
 	return 0;
 }
 
 
-// Update the scancode using a list of TriggerGuides
-// TODO Handle led state and analog
-inline void Macro_triggerState( void *triggers, uint8_t num )
+// Add an interconnect ScanCode
+// These are handled differently (less information is sent, hold/off states must be assumed)
+#if defined(ConnectEnabled_define)
+inline void Macro_interconnectAdd( void *trigger_ptr )
 {
-	// Copy each of the TriggerGuides to the TriggerListBuffer
-	for ( uint8_t c = 0; c < num; c++ )
-		macroTriggerListBuffer[ macroTriggerListBufferSize++ ] = ((TriggerGuide*)triggers)[ c ];
+	TriggerGuide *trigger = (TriggerGuide*)trigger_ptr;
+
+	// Error checking
+	uint8_t error = 0;
+	switch ( trigger->type )
+	{
+	case 0x00: // Normal key
+		switch ( trigger->state )
+		{
+		case 0x00:
+		case 0x01:
+		case 0x02:
+		case 0x03:
+			break;
+		default:
+			erro_print("Invalid key state");
+			error = 1;
+			break;
+		}
+		break;
+
+	// Invalid TriggerGuide type
+	default:
+		erro_print("Invalid type");
+		error = 1;
+		break;
+	}
+
+	// Display TriggerGuide
+	if ( error )
+	{
+		printHex( trigger->type );
+		print(" ");
+		printHex( trigger->state );
+		print(" ");
+		printHex( trigger->scanCode );
+		print( NL );
+		return;
+	}
+
+	// Add trigger to the Interconnect Cache
+	// During each processing loop, a scancode may be re-added depending on it's state
+	for ( uint8_t c = 0; c < macroInterconnectCacheSize; c++ )
+	{
+		// Check if the same ScanCode
+		if ( macroInterconnectCache[ c ].scanCode == trigger->scanCode )
+		{
+			// Update the state
+			macroInterconnectCache[ c ].state = trigger->state;
+			return;
+		}
+	}
+
+	// If not in the list, add it
+	macroInterconnectCache[ macroInterconnectCacheSize++ ] = *trigger;
 }
+#endif
 
 
 // Update the scancode key state
@@ -447,6 +509,20 @@
 //   * 0x04 - Unpressed (this is currently ignored)
 inline void Macro_keyState( uint8_t scanCode, uint8_t state )
 {
+#if defined(ConnectEnabled_define)
+	// Only compile in if a Connect node module is available
+	if ( !Connect_master )
+	{
+		// ScanCodes are only added if there was a state change (on/off)
+		switch ( state )
+		{
+		case 0x00: // Off
+		case 0x02: // Held
+			return;
+		}
+	}
+#endif
+
 	// Only add to macro trigger list if one of three states
 	switch ( state )
 	{
@@ -470,6 +546,7 @@
 inline void Macro_analogState( uint8_t scanCode, uint8_t state )
 {
 	// Only add to macro trigger list if non-off
+	// TODO Handle change for interconnect
 	if ( state != 0x00 )
 	{
 		macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode;
@@ -487,6 +564,7 @@
 inline void Macro_ledState( uint8_t ledCode, uint8_t state )
 {
 	// Only add to macro trigger list if non-off
+	// TODO Handle change for interconnect
 	if ( state != 0x00 )
 	{
 		macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = ledCode;
@@ -907,6 +985,10 @@
 		// Lookup Trigger List
 		nat_ptr_t *triggerList = Macro_layerLookup( &macroTriggerListBuffer[ key ], latch_expire );
 
+		// If there was an error during lookup, skip
+		if ( triggerList == 0 )
+			continue;
+
 		// Number of Triggers in list
 		nat_ptr_t triggerListSize = triggerList[0];
 
@@ -953,10 +1035,7 @@
 	{
 		if ( macroTriggerListBufferSize > 0 )
 		{
-			dbug_msg("Yuh");
-			printHex( macroTriggerListBufferSize );
-			print( NL );
-			//Connect_send_ScanCode( Connect_id, macroTriggerListBuffer, macroTriggerListBufferSize );
+			Connect_send_ScanCode( Connect_id, macroTriggerListBuffer, macroTriggerListBufferSize );
 			macroTriggerListBufferSize = 0;
 		}
 		return;
@@ -967,6 +1046,41 @@
 	if ( USBKeys_Sent != 0 )
 		return;
 
+#if defined(ConnectEnabled_define)
+	// Check if there are any ScanCodes in the interconnect cache to process
+	if ( Connect_master && macroInterconnectCacheSize > 0 )
+	{
+		// Iterate over all the cache ScanCodes
+		uint8_t currentInterconnectCacheSize = macroInterconnectCacheSize;
+		macroInterconnectCacheSize = 0;
+		for ( uint8_t c = 0; c < currentInterconnectCacheSize; c++ )
+		{
+			// Add to the trigger list
+			macroTriggerListBuffer[ macroTriggerListBufferSize++ ] = macroInterconnectCache[ c ];
+
+			// TODO Handle other TriggerGuide types (e.g. analog)
+			switch ( macroInterconnectCache[ c ].type )
+			{
+			// Normal (Press/Hold/Release)
+			case 0x00:
+				// Decide what to do based on the current state
+				switch ( macroInterconnectCache[ c ].state )
+				{
+				// Re-add to interconnect cache in hold state
+				case 0x01: // Press
+				//case 0x02: // Hold // XXX Why does this not work? -HaaTa
+					macroInterconnectCache[ c ].state = 0x02;
+					macroInterconnectCache[ macroInterconnectCacheSize++ ] = macroInterconnectCache[ c ];
+					break;
+				case 0x03: // Remove
+					break;
+				// Otherwise, do not re-add
+				}
+			}
+		}
+	}
+#endif
+
 	// If the pause flag is set, only process if the step counter is non-zero
 	if ( macroPauseMode )
 	{
--- a/Macro/PartialMap/macro.h	Sun Aug 09 00:20:41 2015 -0700
+++ b/Macro/PartialMap/macro.h	Sat Aug 15 21:53:59 2015 -0700
@@ -37,7 +37,7 @@
 void Macro_analogState( uint8_t scanCode, uint8_t state );
 void Macro_keyState( uint8_t scanCode, uint8_t state );
 void Macro_ledState( uint8_t ledCode, uint8_t state );
-void Macro_triggerState( void *triggers, uint8_t num ); // triggers is of type TriggerGuide, void* for circular dependencies
+void Macro_interconnectAdd( void *trigger ); // triggers is of type TriggerGuide, void* for circular dependencies
 void Macro_process();
 void Macro_setup();
 
--- a/Scan/MDErgo1/defaultMap.kll	Sun Aug 09 00:20:41 2015 -0700
+++ b/Scan/MDErgo1/defaultMap.kll	Sat Aug 15 21:53:59 2015 -0700
@@ -4,7 +4,7 @@
 KLL = 0.3c;
 
 # Modified Date
-Date = 2015-08-05;
+Date = 2015-08-15;
 
 ########
 # NOTE #
@@ -30,7 +30,6 @@
 #
 # Each LED is represented by a single bit
 # See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details
-ISSILedMask1 => ISSILedMask1_define;
 ISSILedMask1 = "
 	0xFF, 0x00, /* C1-1 -> C1-16 */
 	0xFF, 0x00, /* C2-1 -> C2-16 */
@@ -46,7 +45,6 @@
 # LED Brightness Override
 #
 # Each LED channel supports 256 levels (8-bit control)
-ISSILedBrightness1 => ISSILedBrightness1_define;
 ISSILedBrightness1 = "
 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C1-1 -> C1-16 */
 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */
--- a/Scan/UARTConnect/connect_scan.c	Sun Aug 09 00:20:41 2015 -0700
+++ b/Scan/UARTConnect/connect_scan.c	Sat Aug 15 21:53:59 2015 -0700
@@ -33,11 +33,20 @@
 
 // ----- Macros -----
 
+#define UART_Master 1
+#define UART_Slave  0
+#define uart_lock_m( uartNum )         uart##uartNum##_lock
+#define uart_buffer_items_m( uartNum ) uart##uartNum##_buffer_items
+#define uart_buffer_m( uartNum )       uart##uartNum##_buffer
+#define uart_buffer_head_m( uartNum )  uart##uartNum##_buffer_head
+#define uart_buffer_tail_m( uartNum )  uart##uartNum##_buffer_tail
+#define uart_tx_status_m( uartNum )    uart##uartNum##_tx_status
+
 // Macro for adding to each uart Tx ring buffer
 #define uart_addTxBuffer( uartNum ) \
 case uartNum: \
 	/* Delay UART copy until there's some space left */ \
-	while ( uart##uartNum##_buffer_items + count > uart_buffer_size ) \
+	while ( uart_buffer_items_m( uartNum ) + count > uart_buffer_size ) \
 	{ \
 		warn_msg("Too much data to send on UART0, waiting..."); \
 		delay( 1 ); \
@@ -50,14 +59,14 @@
 			printHex( buffer[ c ] ); \
 			print( " +" #uartNum NL ); \
 		} \
-		uart##uartNum##_buffer[ uart##uartNum##_buffer_tail++ ] = buffer[ c ]; \
-		uart##uartNum##_buffer_items++; \
-		if ( uart##uartNum##_buffer_tail >= uart_buffer_size ) \
-			uart##uartNum##_buffer_tail = 0; \
-		if ( uart##uartNum##_buffer_head == uart##uartNum##_buffer_tail ) \
-			uart##uartNum##_buffer_head++; \
-		if ( uart##uartNum##_buffer_head >= uart_buffer_size ) \
-			uart##uartNum##_buffer_head = 0; \
+		uart_buffer_m( uartNum )[ uart_buffer_tail_m( uartNum )++ ] = buffer[ c ]; \
+		uart_buffer_items_m( uartNum )++; \
+		if ( uart_buffer_tail_m( uartNum ) >= uart_buffer_size ) \
+			uart_buffer_tail_m( uartNum ) = 0; \
+		if ( uart_buffer_head_m( uartNum ) == uart_buffer_tail_m( uartNum ) ) \
+			uart_buffer_head_m( uartNum )++; \
+		if ( uart_buffer_head_m( uartNum ) >= uart_buffer_size ) \
+			uart_buffer_head_m( uartNum ) = 0; \
 	} \
 	break
 
@@ -67,7 +76,21 @@
 	uint8_t fifoSize = ( ( UART##uartNum##_PFIFO & UART_PFIFO_TXFIFOSIZE ) >> 2 ); \
 	if ( fifoSize == 0 ) \
 		fifoSize = 1; \
-	while ( UART##uartNum##_TCFIFO < fifoSize ) \
+	if ( Connect_debug ) \
+	{ \
+		print( "TxFIFO " #uartNum " - " ); \
+		printHex( fifoSize ); \
+		print("/"); \
+		printHex( UART##uartNum##_TCFIFO ); \
+		print("/"); \
+		printHex( uart##uartNum##_buffer_items ); \
+		print( NL ); \
+	} \
+	/* XXX Doesn't work well */ \
+	/* while ( UART##uartNum##_TCFIFO < fifoSize ) */ \
+	/* More reliable, albeit slower */ \
+	fifoSize -= UART##uartNum##_TCFIFO; \
+	while ( fifoSize-- != 0 ) \
 	{ \
 		if ( uart##uartNum##_buffer_items == 0 ) \
 			break; \
@@ -93,27 +116,49 @@
 	/* Process each byte in the UART buffer */ \
 	while ( available-- > 0 ) \
 	{ \
+		/* First check if there was noise or Parity issues with current byte */ \
+		uint8_t err_status = UART##uartNum##_ED; \
+		/* Read byte from Rx FIFO */ \
 		uint8_t byteRead = UART##uartNum##_D; \
 		if ( Connect_debug ) \
 		{ \
 			printHex( byteRead ); \
-			print( "(" ); \
+			print("("); \
 			printInt8( available ); \
-			print( ") <-" ); \
+			print(") <-"); \
+		} \
+		/* Check error status */ \
+		if ( err_status & 0x80 ) \
+		{ \
+			print(" NOISY "); \
+		} \
+		if ( err_status & 0x40 ) \
+		{ \
+			print(" PARITY ERR "); \
+		} \
+		/* Ignore current byte if there was an error */ \
+		if ( err_status ) \
+		{ \
+			uart##uartNum##_rx_status = UARTStatus_Wait; \
+			if ( Connect_debug ) \
+			{ \
+				print( NL ); \
+			} \
+			continue; \
 		} \
 		switch ( uart##uartNum##_rx_status ) \
 		{ \
 		case UARTStatus_Wait: \
 			if ( Connect_debug ) \
 			{ \
-				print(" SYN "); \
+				print(" Wait "); \
 			} \
 			uart##uartNum##_rx_status = byteRead == 0x16 ? UARTStatus_SYN : UARTStatus_Wait; \
 			break; \
 		case UARTStatus_SYN: \
 			if ( Connect_debug ) \
 			{ \
-				print(" SOH "); \
+				print(" SYN "); \
 			} \
 			uart##uartNum##_rx_status = byteRead == 0x01 ? UARTStatus_SOH : UARTStatus_Wait; \
 			break; \
@@ -121,10 +166,17 @@
 		{ \
 			if ( Connect_debug ) \
 			{ \
-				print(" CMD "); \
+				print(" SOH "); \
 			} \
+			/* Check if this is actually a reserved CMD 0x16 */ \
+			if ( byteRead == Command_SYN ) \
+			{ \
+				uart##uartNum##_rx_status = UARTStatus_SYN; \
+				break; \
+			} \
+			/* Otherwise process the command */ \
 			uint8_t byte = byteRead; \
-			if ( byte <= Animation ) \
+			if ( byte < Command_TOP ) \
 			{ \
 				uart##uartNum##_rx_status = UARTStatus_Command; \
 				uart##uartNum##_rx_command = byte; \
@@ -143,7 +195,8 @@
 			default: \
 				if ( Connect_debug ) \
 				{ \
-					print("###"); \
+					print(" ### "); \
+					printHex( uart##uartNum##_rx_command ); \
 				} \
 				break; \
 			} \
@@ -177,13 +230,32 @@
 // Macros for locking/unlock Tx buffers
 #define uart_lockTx( uartNum ) \
 { \
-	while ( uart##uartNum##_tx_status == UARTStatus_Wait ); \
-	uart##uartNum##_tx_status = UARTStatus_Wait; \
+	/* First, secure place in line for the resource */ \
+	while ( uart_lock_m( uartNum ) ); \
+	uart_lock_m( uartNum ) = 1; \
+	/* Next, wait unit the UART is ready */ \
+	while ( uart_tx_status_m( uartNum ) != UARTStatus_Ready ); \
+	uart_tx_status_m( uartNum ) = UARTStatus_Wait; \
+}
+
+#define uart_lockBothTx( uartNum1, uartNum2 ) \
+{ \
+	/* First, secure place in line for the resource */ \
+	while ( uart_lock_m( uartNum1 ) || uart_lock_m( uartNum2 ) ); \
+	uart_lock_m( uartNum1 ) = 1; \
+	uart_lock_m( uartNum2 ) = 1; \
+	/* Next, wait unit the UARTs are ready */ \
+	while ( uart_tx_status_m( uartNum1 ) != UARTStatus_Ready || uart_tx_status_m( uartNum2 ) != UARTStatus_Ready ); \
+	uart_tx_status_m( uartNum1 ) = UARTStatus_Wait; \
+	uart_tx_status_m( uartNum2 ) = UARTStatus_Wait; \
 }
 
 #define uart_unlockTx( uartNum ) \
 { \
-	uart##uartNum##_tx_status = UARTStatus_Ready; \
+	/* Ready the UART */ \
+	uart_tx_status_m( uartNum ) = UARTStatus_Ready; \
+	/* Unlock the resource */ \
+	uart_lock_m( uartNum ) = 0; \
 }
 
 
@@ -192,6 +264,7 @@
 
 // CLI Functions
 void cliFunc_connectCmd ( char *args );
+void cliFunc_connectDbg ( char *args );
 void cliFunc_connectIdl ( char *args );
 void cliFunc_connectLst ( char *args );
 void cliFunc_connectMst ( char *args );
@@ -204,6 +277,7 @@
 
 // Connect Module command dictionary
 CLIDict_Entry( connectCmd,  "Sends a command via UART Connect, first arg is which uart, next arg is the command, rest are the arguments." );
+CLIDict_Entry( connectDbg,  "Toggle UARTConnect debug mode." );
 CLIDict_Entry( connectIdl,  "Sends N number of Idle commands, 2 is the default value, and should be sufficient in most cases." );
 CLIDict_Entry( connectLst,  "Lists available UARTConnect commands and index id" );
 CLIDict_Entry( connectMst,  "Sets the device as master. Use argument of s to set as slave." );
@@ -211,6 +285,7 @@
 CLIDict_Entry( connectSts,  "UARTConnect status." );
 CLIDict_Def( uartConnectCLIDict, "UARTConnect Module Commands" ) = {
 	CLIDict_Item( connectCmd ),
+	CLIDict_Item( connectDbg ),
 	CLIDict_Item( connectIdl ),
 	CLIDict_Item( connectLst ),
 	CLIDict_Item( connectMst ),
@@ -223,11 +298,13 @@
 // -- Connect Device Id Variables --
 uint8_t Connect_id = 255; // Invalid, unset
 uint8_t Connect_master = 0;
+uint8_t Connect_maxId = 0;
 
 
 // -- Control Variables --
 uint32_t Connect_lastCheck = 0; // Cable Check scheduler
-uint8_t Connect_debug = 0; // Set 1 for debug
+uint8_t Connect_debug = 0;      // Set 1 for debug
+uint8_t Connect_override = 0;   // Prevents master from automatically being set
 
 
 // -- Rx Status Variables --
@@ -238,6 +315,8 @@
 volatile uint16_t uart1_rx_bytes_waiting;
 volatile Command uart0_rx_command;
 volatile Command uart1_rx_command;
+volatile uint8_t uart0_lock;
+volatile uint8_t uart1_lock;
 
 
 // -- Tx Status Variables --
@@ -275,8 +354,8 @@
 	// Choose the uart
 	switch ( uart )
 	{
-	uart_addTxBuffer( 0 );
-	uart_addTxBuffer( 1 );
+	uart_addTxBuffer( UART_Master );
+	uart_addTxBuffer( UART_Slave );
 	default:
 		erro_msg("Invalid UART to send from...");
 		break;
@@ -290,74 +369,73 @@
 void Connect_send_CableCheck( uint8_t patternLen )
 {
 	// Wait until the Tx buffers are ready, then lock them
-	uart_lockTx( 0 );
-	uart_lockTx( 1 );
+	uart_lockBothTx( UART_Master, UART_Slave );
 
 	// Prepare header
 	uint8_t header[] = { 0x16, 0x01, CableCheck, patternLen };
 
 	// Send header
-	Connect_addBytes( header, sizeof( header ), 1 ); // Master
-	Connect_addBytes( header, sizeof( header ), 0 ); // Slave
+	Connect_addBytes( header, sizeof( header ), UART_Master );
+	Connect_addBytes( header, sizeof( header ), UART_Slave );
 
 	// Send 0xD2 (11010010) for each argument
 	uint8_t value = 0xD2;
 	for ( uint8_t c = 0; c < patternLen; c++ )
 	{
-		Connect_addBytes( &value, 1, 1 ); // Master
-		Connect_addBytes( &value, 1, 0 ); // Slave
+		Connect_addBytes( &value, 1, UART_Master );
+		Connect_addBytes( &value, 1, UART_Slave );
 	}
 
 	// Release Tx buffers
-	uart_unlockTx( 0 );
-	uart_unlockTx( 1 );
+	uart_unlockTx( UART_Master );
+	uart_unlockTx( UART_Slave );
 }
 
 void Connect_send_IdRequest()
 {
 	// Lock master bound Tx
-	uart_lockTx( 1 );
+	uart_lockTx( UART_Master );
 
 	// Prepare header
 	uint8_t header[] = { 0x16, 0x01, IdRequest };
 
 	// Send header
-	Connect_addBytes( header, sizeof( header ), 1 ); // Master
+	Connect_addBytes( header, sizeof( header ), UART_Master );
 
 	// Unlock Tx
-	uart_unlockTx( 1 );
+	uart_unlockTx( UART_Master );
 }
 
 // id is the value the next slave should enumerate as
 void Connect_send_IdEnumeration( uint8_t id )
 {
 	// Lock slave bound Tx
-	uart_lockTx( 0 );
+	uart_lockTx( UART_Slave );
 
 	// Prepare header
 	uint8_t header[] = { 0x16, 0x01, IdEnumeration, id };
 
 	// Send header
-	Connect_addBytes( header, sizeof( header ), 0 ); // Slave
+	Connect_addBytes( header, sizeof( header ), UART_Slave );
 
 	// Unlock Tx
-	uart_unlockTx( 0 );
+	uart_unlockTx( UART_Slave );
 }
 
 // id is the currently assigned id to the slave
 void Connect_send_IdReport( uint8_t id )
 {
 	// Lock master bound Tx
-	uart_lockTx( 1 );
+	uart_lockTx( UART_Master );
 
 	// Prepare header
 	uint8_t header[] = { 0x16, 0x01, IdReport, id };
 
 	// Send header
-	Connect_addBytes( header, sizeof( header ), 1 ); // Master
+	Connect_addBytes( header, sizeof( header ), UART_Master );
 
 	// Unlock Tx
-	uart_unlockTx( 1 );
+	uart_unlockTx( UART_Master );
 }
 
 // id is the currently assigned id to the slave
@@ -366,19 +444,19 @@
 void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes )
 {
 	// Lock master bound Tx
-	uart_lockTx( 1 );
+	uart_lockTx( UART_Master );
 
 	// Prepare header
 	uint8_t header[] = { 0x16, 0x01, ScanCode, id, numScanCodes };
 
 	// Send header
-	Connect_addBytes( header, sizeof( header ), 1 ); // Master
+	Connect_addBytes( header, sizeof( header ), UART_Master );
 
 	// Send each of the scan codes
-	Connect_addBytes( (uint8_t*)scanCodeStateList, numScanCodes * TriggerGuideSize, 1 ); // Master
+	Connect_addBytes( (uint8_t*)scanCodeStateList, numScanCodes * TriggerGuideSize, UART_Master );
 
 	// Unlock Tx
-	uart_unlockTx( 1 );
+	uart_unlockTx( UART_Master );
 }
 
 // id is the currently assigned id to the slave
@@ -387,38 +465,37 @@
 void Connect_send_Animation( uint8_t id, uint8_t *paramList, uint8_t numParams )
 {
 	// Lock slave bound Tx
-	uart_lockTx( 0 );
+	uart_lockTx( UART_Slave );
 
 	// Prepare header
 	uint8_t header[] = { 0x16, 0x01, Animation, id, numParams };
 
 	// Send header
-	Connect_addBytes( header, sizeof( header ), 0 ); // Slave
+	Connect_addBytes( header, sizeof( header ), UART_Slave );
 
 	// Send each of the scan codes
-	Connect_addBytes( paramList, numParams, 0 ); // Slave
+	Connect_addBytes( paramList, numParams, UART_Slave );
 
 	// Unlock Tx
-	uart_unlockTx( 0 );
+	uart_unlockTx( UART_Slave );
 }
 
 void Connect_send_Idle( uint8_t num )
 {
 	// Wait until the Tx buffers are ready, then lock them
-	uart_lockTx( 0 );
-	uart_lockTx( 1 );
+	uart_lockBothTx( UART_Slave, UART_Master );
 
 	// Send n number of idles to reset link status (if in a bad state)
 	uint8_t value = 0x16;
 	for ( uint8_t c = 0; c < num; c++ )
 	{
-		Connect_addBytes( &value, 1, 1 ); // Master
-		Connect_addBytes( &value, 1, 0 ); // Slave
+		Connect_addBytes( &value, 1, UART_Master );
+		Connect_addBytes( &value, 1, UART_Slave );
 	}
 
 	// Release Tx buffers
-	uart_unlockTx( 0 );
-	uart_unlockTx( 1 );
+	uart_unlockTx( UART_Master );
+	uart_unlockTx( UART_Slave );
 }
 
 
@@ -426,11 +503,13 @@
 
 // - Cable Check variables -
 uint32_t Connect_cableFaultsMaster = 0;
-uint32_t Connect_cableFaultsSlave = 0;
+uint32_t Connect_cableFaultsSlave  = 0;
+uint32_t Connect_cableChecksMaster = 0;
+uint32_t Connect_cableChecksSlave  = 0;
 uint8_t  Connect_cableOkMaster = 0;
-uint8_t  Connect_cableOkSlave = 0;
+uint8_t  Connect_cableOkSlave  = 0;
 
-uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8_t to_slave )
+uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
 {
 	// Check if this is the first byte
 	if ( *pending_bytes == 0xFFFF )
@@ -457,36 +536,48 @@
 			warn_print("Cable Fault!");
 
 			// Check which side of the chain
-			if ( to_slave )
+			if ( uart_num == UART_Slave )
+			{
+				Connect_cableFaultsSlave++;
+				Connect_cableOkSlave = 0;
+				print(" Slave ");
+			}
+			else
 			{
 				Connect_cableFaultsMaster++;
 				Connect_cableOkMaster = 0;
 				print(" Master ");
 			}
-			else
-			{
-				Connect_cableFaultsSlave++;
-				Connect_cableOkSlave = 0;
-				print(" Slave ");
-			}
 			printHex( byte );
 			print( NL );
 
 			// Signal that the command should wait for a SYN again
 			return 1;
 		}
+		else
+		{
+			// Check which side of the chain
+			if ( uart_num == UART_Slave )
+			{
+				Connect_cableChecksSlave++;
+			}
+			else
+			{
+				Connect_cableChecksMaster++;
+			}
+		}
 	}
 
 	// If cable check was successful, set cable ok
 	if ( *pending_bytes == 0 )
 	{
-		if ( to_slave )
+		if ( uart_num == UART_Slave )
 		{
-			Connect_cableOkMaster = 1;
+			Connect_cableOkSlave = 1;
 		}
 		else
 		{
-			Connect_cableOkSlave = 1;
+			Connect_cableOkMaster = 1;
 		}
 	}
 
@@ -503,11 +594,11 @@
 	return *pending_bytes == 0 ? 1 : 0;
 }
 
-uint8_t Connect_receive_IdRequest( uint8_t byte, uint16_t *pending_bytes, uint8_t to_slave )
+uint8_t Connect_receive_IdRequest( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
 {
 	dbug_print("IdRequest");
 	// Check the directionality
-	if ( to_slave )
+	if ( uart_num == UART_Master )
 	{
 		erro_print("Invalid IdRequest direction...");
 	}
@@ -528,11 +619,11 @@
 	return 1;
 }
 
-uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint8_t to_slave )
+uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num )
 {
 	dbug_print("IdEnumeration");
 	// Check the directionality
-	if ( !to_slave )
+	if ( uart_num == UART_Slave )
 	{
 		erro_print("Invalid IdEnumeration direction...");
 	}
@@ -552,11 +643,11 @@
 	return 1;
 }
 
-uint8_t Connect_receive_IdReport( uint8_t id, uint16_t *pending_bytes, uint8_t to_slave )
+uint8_t Connect_receive_IdReport( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num )
 {
 	dbug_print("IdReport");
 	// Check the directionality
-	if ( to_slave )
+	if ( uart_num == UART_Master )
 	{
 		erro_print("Invalid IdRequest direction...");
 	}
@@ -564,10 +655,13 @@
 	// Track Id response if master
 	if ( Connect_master )
 	{
-		// TODO, setup id's
 		info_msg("Id Reported: ");
 		printHex( id );
 		print( NL );
+
+		// Check if this is the highest ID
+		if ( id > Connect_maxId )
+			Connect_maxId = id;
 		return 1;
 	}
 	// Propagate id if yet another slave
@@ -584,11 +678,10 @@
 uint8_t Connect_receive_ScanCodeBufferPos;
 uint8_t Connect_receive_ScanCodeDeviceId;
 
-uint8_t Connect_receive_ScanCode( uint8_t byte, uint16_t *pending_bytes, uint8_t to_slave )
+uint8_t Connect_receive_ScanCode( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
 {
-	dbug_print("ScanCode");
 	// Check the directionality
-	if ( to_slave )
+	if ( uart_num == UART_Master )
 	{
 		erro_print("Invalid ScanCode direction...");
 	}
@@ -612,30 +705,41 @@
 
 		// Reset the BufferPos if higher than sizeof TriggerGuide
 		// And send the TriggerGuide to the Macro Module
-		if ( Connect_receive_ScanCodeBufferPos > sizeof( TriggerGuide ) )
+		if ( Connect_receive_ScanCodeBufferPos >= sizeof( TriggerGuide ) )
 		{
 			Connect_receive_ScanCodeBufferPos = 0;
 
 			// Adjust ScanCode offset
 			if ( Connect_receive_ScanCodeDeviceId > 0 )
 			{
+				// Check if this node is too large
+				if ( Connect_receive_ScanCodeDeviceId >= InterconnectNodeMax )
+				{
+					warn_msg("Not enough interconnect layout nodes configured: ");
+					printHex( Connect_receive_ScanCodeDeviceId );
+					print( NL );
+					break;
+				}
+
 				// This variable is in generatedKeymaps.h
 				extern uint8_t InterconnectOffsetList[];
 				Connect_receive_ScanCodeBuffer.scanCode = Connect_receive_ScanCodeBuffer.scanCode + InterconnectOffsetList[ Connect_receive_ScanCodeDeviceId - 1 ];
 			}
 
 			// ScanCode receive debug
-			dbug_print("");
-			printHex( Connect_receive_ScanCodeBuffer.type );
-			print(" ");
-			printHex( Connect_receive_ScanCodeBuffer.state );
-			print(" ");
-			printHex( Connect_receive_ScanCodeBuffer.scanCode );
-			print( NL );
+			if ( Connect_debug )
+			{
+				dbug_msg("");
+				printHex( Connect_receive_ScanCodeBuffer.type );
+				print(" ");
+				printHex( Connect_receive_ScanCodeBuffer.state );
+				print(" ");
+				printHex( Connect_receive_ScanCodeBuffer.scanCode );
+				print( NL );
+			}
 
 			// Send ScanCode to macro module
-			// TODO
-			//Macro_triggerState( &Connect_receive_ScanCodeBuffer, 1 );
+			Macro_interconnectAdd( &Connect_receive_ScanCodeBuffer );
 		}
 
 		break;
@@ -649,11 +753,11 @@
 		Connect_receive_ScanCodeDeviceId = byte;
 
 		// Lock the master Tx buffer
-		uart_lockTx( 1 );
+		uart_lockTx( UART_Master );
 
 		// Send header + Id byte
 		uint8_t header[] = { 0x16, 0x01, ScanCode, byte };
-		Connect_addBytes( header, sizeof( header ), 1 ); // Master
+		Connect_addBytes( header, sizeof( header ), UART_Master );
 		break;
 	}
 	case 0xFFFE: // Number of TriggerGuides in bytes
@@ -661,16 +765,16 @@
 		Connect_receive_ScanCodeBufferPos = 0;
 
 		// Pass through byte
-		Connect_addBytes( &byte, 1, 1 ); // Master
+		Connect_addBytes( &byte, 1, UART_Master );
 		break;
 
 	default:
 		// Pass through byte
-		Connect_addBytes( &byte, 1, 1 ); // Master
+		Connect_addBytes( &byte, 1, UART_Master );
 
 		// Unlock Tx Buffer after sending last byte
 		if ( *pending_bytes == 0 )
-			uart_unlockTx( 1 );
+			uart_unlockTx( UART_Master );
 		break;
 	}
 
@@ -678,7 +782,7 @@
 	return *pending_bytes == 0 ? 1 : 0;
 }
 
-uint8_t Connect_receive_Animation( uint8_t byte, uint16_t *pending_bytes, uint8_t to_slave )
+uint8_t Connect_receive_Animation( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
 {
 	dbug_print("Animation");
 	return 1;
@@ -730,6 +834,8 @@
 	uart1_rx_status = UARTStatus_Wait;
 	uart0_rx_bytes_waiting = 0;
 	uart1_rx_bytes_waiting = 0;
+	uart0_lock = 0;
+	uart1_lock = 0;
 
 	// Tx Status Variables
 	uart0_tx_status = UARTStatus_Ready;
@@ -790,7 +896,6 @@
 	UART1_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
 
 	// Number of bytes in FIFO before TX Interrupt
-	// TODO Set 0
 	UART0_TWFIFO = 1;
 	UART1_TWFIFO = 1;
 
@@ -838,7 +943,7 @@
 {
 	// Check if initially configured as a slave and usb comes up
 	// Then reconfigure as a master
-	if ( !Connect_master && Output_Available )
+	if ( !Connect_master && Output_Available && !Connect_override )
 	{
 		Connect_setup( Output_Available );
 	}
@@ -934,6 +1039,13 @@
 	}
 }
 
+void cliFunc_connectDbg( char* args )
+{
+	print( NL );
+	info_msg("Connect Debug Mode Toggle");
+	Connect_debug = !Connect_debug;
+}
+
 void cliFunc_connectIdl( char* args )
 {
 	// Parse number from argument
@@ -988,8 +1100,15 @@
 
 	print( NL );
 
+	// Set override
+	Connect_override = 1;
+
 	switch ( arg1Ptr[0] )
 	{
+	// Disable override
+	case 'd':
+	case 'D':
+		Connect_override = 0;
 	case 's':
 	case 'S':
 		info_msg("Setting device as slave.");
@@ -1025,10 +1144,14 @@
 	print( Connect_master ? "Master" : "Slave" );
 	print( NL "Device Id:\t" );
 	printHex( Connect_id );
+	print( NL "Max Id:\t" );
+	printHex( Connect_maxId );
 	print( NL "Master <=" NL "\tStatus:\t");
 	printHex( Connect_cableOkMaster );
 	print( NL "\tFaults:\t");
-	printHex( Connect_cableFaultsMaster );
+	printHex32( Connect_cableFaultsMaster );
+	print("/");
+	printHex32( Connect_cableChecksMaster );
 	print( NL "\tRx:\t");
 	printHex( uart1_rx_status );
 	print( NL "\tTx:\t");
@@ -1036,7 +1159,9 @@
 	print( NL "Slave <=" NL "\tStatus:\t");
 	printHex( Connect_cableOkSlave );
 	print( NL "\tFaults:\t");
-	printHex( Connect_cableFaultsSlave );
+	printHex32( Connect_cableFaultsSlave );
+	print("/");
+	printHex32( Connect_cableChecksSlave );
 	print( NL "\tRx:\t");
 	printHex( uart0_rx_status );
 	print( NL "\tTx:\t");
--- a/Scan/UARTConnect/connect_scan.h	Sun Aug 09 00:20:41 2015 -0700
+++ b/Scan/UARTConnect/connect_scan.h	Sat Aug 15 21:53:59 2015 -0700
@@ -41,6 +41,7 @@
 	RemoteInput,      // Remote command to send to a given node's debug cli
 
 	Command_TOP,      // Enum bounds
+	Command_SYN = 0x16, // Reserved for error handling
 } Command;
 
 // UART Rx/Tx Status