Browse Source

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
connect
Jacob Alexander 8 years ago
parent
commit
a8caf6e515

+ 0
- 1
Lib/CMake/kll.cmake View File

string ( REPLACE " " ";" MAP_LIST ${BaseMap} ) # Change spaces to semicolons string ( REPLACE " " ";" MAP_LIST ${BaseMap} ) # Change spaces to semicolons
foreach ( MAP ${MAP_LIST} ) foreach ( MAP ${MAP_LIST} )
# Only check the Scan Module for BaseMap .kll files, default to defaultMap.kll # Only check the Scan Module for BaseMap .kll files, default to defaultMap.kll
message("THIS -> ${pathname} ${MAP}")
if ( NOT EXISTS ${pathname}/${MAP}.kll ) if ( NOT EXISTS ${pathname}/${MAP}.kll )
set ( BaseMap_Args ${BaseMap_Args} ${pathname}/defaultMap.kll ) set ( BaseMap_Args ${BaseMap_Args} ${pathname}/defaultMap.kll )
set ( KLL_DEPENDS ${KLL_DEPENDS} ${pathname}/defaultMap.kll ) set ( KLL_DEPENDS ${KLL_DEPENDS} ${pathname}/defaultMap.kll )

+ 124
- 10
Macro/PartialMap/macro.c View File

uint16_t macroResultMacroPendingList[ ResultMacroNum ] = { 0 }; uint16_t macroResultMacroPendingList[ ResultMacroNum ] = { 0 };
uint16_t macroResultMacroPendingListSize = 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 ----- // ----- Capabilities -----
// Otherwise no defined Trigger Macro // Otherwise no defined Trigger Macro
erro_msg("Scan Code has no defined Trigger Macro: "); erro_msg("Scan Code has no defined Trigger Macro: ");
printHex( scanCode ); printHex( scanCode );
print( NL );
return 0; 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 // Update the scancode key state
// * 0x04 - Unpressed (this is currently ignored) // * 0x04 - Unpressed (this is currently ignored)
inline void Macro_keyState( uint8_t scanCode, uint8_t state ) 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 // Only add to macro trigger list if one of three states
switch ( state ) switch ( state )
{ {
inline void Macro_analogState( uint8_t scanCode, uint8_t state ) inline void Macro_analogState( uint8_t scanCode, uint8_t state )
{ {
// Only add to macro trigger list if non-off // Only add to macro trigger list if non-off
// TODO Handle change for interconnect
if ( state != 0x00 ) if ( state != 0x00 )
{ {
macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode; macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode;
inline void Macro_ledState( uint8_t ledCode, uint8_t state ) inline void Macro_ledState( uint8_t ledCode, uint8_t state )
{ {
// Only add to macro trigger list if non-off // Only add to macro trigger list if non-off
// TODO Handle change for interconnect
if ( state != 0x00 ) if ( state != 0x00 )
{ {
macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = ledCode; macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = ledCode;
// Lookup Trigger List // Lookup Trigger List
nat_ptr_t *triggerList = Macro_layerLookup( &macroTriggerListBuffer[ key ], latch_expire ); 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 // Number of Triggers in list
nat_ptr_t triggerListSize = triggerList[0]; nat_ptr_t triggerListSize = triggerList[0];


{ {
if ( macroTriggerListBufferSize > 0 ) 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; macroTriggerListBufferSize = 0;
} }
return; return;
if ( USBKeys_Sent != 0 ) if ( USBKeys_Sent != 0 )
return; 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 the pause flag is set, only process if the step counter is non-zero
if ( macroPauseMode ) if ( macroPauseMode )
{ {

+ 1
- 1
Macro/PartialMap/macro.h View File

void Macro_analogState( uint8_t scanCode, uint8_t state ); void Macro_analogState( uint8_t scanCode, uint8_t state );
void Macro_keyState( 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_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_process();
void Macro_setup(); void Macro_setup();



+ 1
- 3
Scan/MDErgo1/defaultMap.kll View File

KLL = 0.3c; KLL = 0.3c;


# Modified Date # Modified Date
Date = 2015-08-05;
Date = 2015-08-15;


######## ########
# NOTE # # NOTE #
# #
# Each LED is represented by a single bit # Each LED is represented by a single bit
# See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details # See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details
ISSILedMask1 => ISSILedMask1_define;
ISSILedMask1 = " ISSILedMask1 = "
0xFF, 0x00, /* C1-1 -> C1-16 */ 0xFF, 0x00, /* C1-1 -> C1-16 */
0xFF, 0x00, /* C2-1 -> C2-16 */ 0xFF, 0x00, /* C2-1 -> C2-16 */
# LED Brightness Override # LED Brightness Override
# #
# Each LED channel supports 256 levels (8-bit control) # Each LED channel supports 256 levels (8-bit control)
ISSILedBrightness1 => ISSILedBrightness1_define;
ISSILedBrightness1 = " 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, /* C1-1 -> C1-16 */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* C2-1 -> C2-16 */

+ 222
- 97
Scan/UARTConnect/connect_scan.c View File



// ----- Macros ----- // ----- 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 // Macro for adding to each uart Tx ring buffer
#define uart_addTxBuffer( uartNum ) \ #define uart_addTxBuffer( uartNum ) \
case uartNum: \ case uartNum: \
/* Delay UART copy until there's some space left */ \ /* 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..."); \ warn_msg("Too much data to send on UART0, waiting..."); \
delay( 1 ); \ delay( 1 ); \
printHex( buffer[ c ] ); \ printHex( buffer[ c ] ); \
print( " +" #uartNum NL ); \ 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 break


uint8_t fifoSize = ( ( UART##uartNum##_PFIFO & UART_PFIFO_TXFIFOSIZE ) >> 2 ); \ uint8_t fifoSize = ( ( UART##uartNum##_PFIFO & UART_PFIFO_TXFIFOSIZE ) >> 2 ); \
if ( fifoSize == 0 ) \ if ( fifoSize == 0 ) \
fifoSize = 1; \ 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 ) \ if ( uart##uartNum##_buffer_items == 0 ) \
break; \ break; \
/* Process each byte in the UART buffer */ \ /* Process each byte in the UART buffer */ \
while ( available-- > 0 ) \ 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; \ uint8_t byteRead = UART##uartNum##_D; \
if ( Connect_debug ) \ if ( Connect_debug ) \
{ \ { \
printHex( byteRead ); \ printHex( byteRead ); \
print( "(" ); \
print("("); \
printInt8( available ); \ 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 ) \ switch ( uart##uartNum##_rx_status ) \
{ \ { \
case UARTStatus_Wait: \ case UARTStatus_Wait: \
if ( Connect_debug ) \ if ( Connect_debug ) \
{ \ { \
print(" SYN "); \
print(" Wait "); \
} \ } \
uart##uartNum##_rx_status = byteRead == 0x16 ? UARTStatus_SYN : UARTStatus_Wait; \ uart##uartNum##_rx_status = byteRead == 0x16 ? UARTStatus_SYN : UARTStatus_Wait; \
break; \ break; \
case UARTStatus_SYN: \ case UARTStatus_SYN: \
if ( Connect_debug ) \ if ( Connect_debug ) \
{ \ { \
print(" SOH "); \
print(" SYN "); \
} \ } \
uart##uartNum##_rx_status = byteRead == 0x01 ? UARTStatus_SOH : UARTStatus_Wait; \ uart##uartNum##_rx_status = byteRead == 0x01 ? UARTStatus_SOH : UARTStatus_Wait; \
break; \ break; \
{ \ { \
if ( Connect_debug ) \ 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; \ uint8_t byte = byteRead; \
if ( byte <= Animation ) \
if ( byte < Command_TOP ) \
{ \ { \
uart##uartNum##_rx_status = UARTStatus_Command; \ uart##uartNum##_rx_status = UARTStatus_Command; \
uart##uartNum##_rx_command = byte; \ uart##uartNum##_rx_command = byte; \
default: \ default: \
if ( Connect_debug ) \ if ( Connect_debug ) \
{ \ { \
print("###"); \
print(" ### "); \
printHex( uart##uartNum##_rx_command ); \
} \ } \
break; \ break; \
} \ } \
// Macros for locking/unlock Tx buffers // Macros for locking/unlock Tx buffers
#define uart_lockTx( uartNum ) \ #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 ) \ #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; \
} }






// CLI Functions // CLI Functions
void cliFunc_connectCmd ( char *args ); void cliFunc_connectCmd ( char *args );
void cliFunc_connectDbg ( char *args );
void cliFunc_connectIdl ( char *args ); void cliFunc_connectIdl ( char *args );
void cliFunc_connectLst ( char *args ); void cliFunc_connectLst ( char *args );
void cliFunc_connectMst ( char *args ); void cliFunc_connectMst ( char *args );


// Connect Module command dictionary // 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( 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( 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( connectLst, "Lists available UARTConnect commands and index id" );
CLIDict_Entry( connectMst, "Sets the device as master. Use argument of s to set as slave." ); CLIDict_Entry( connectMst, "Sets the device as master. Use argument of s to set as slave." );
CLIDict_Entry( connectSts, "UARTConnect status." ); CLIDict_Entry( connectSts, "UARTConnect status." );
CLIDict_Def( uartConnectCLIDict, "UARTConnect Module Commands" ) = { CLIDict_Def( uartConnectCLIDict, "UARTConnect Module Commands" ) = {
CLIDict_Item( connectCmd ), CLIDict_Item( connectCmd ),
CLIDict_Item( connectDbg ),
CLIDict_Item( connectIdl ), CLIDict_Item( connectIdl ),
CLIDict_Item( connectLst ), CLIDict_Item( connectLst ),
CLIDict_Item( connectMst ), CLIDict_Item( connectMst ),
// -- Connect Device Id Variables -- // -- Connect Device Id Variables --
uint8_t Connect_id = 255; // Invalid, unset uint8_t Connect_id = 255; // Invalid, unset
uint8_t Connect_master = 0; uint8_t Connect_master = 0;
uint8_t Connect_maxId = 0;




// -- Control Variables -- // -- Control Variables --
uint32_t Connect_lastCheck = 0; // Cable Check scheduler 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 -- // -- Rx Status Variables --
volatile uint16_t uart1_rx_bytes_waiting; volatile uint16_t uart1_rx_bytes_waiting;
volatile Command uart0_rx_command; volatile Command uart0_rx_command;
volatile Command uart1_rx_command; volatile Command uart1_rx_command;
volatile uint8_t uart0_lock;
volatile uint8_t uart1_lock;




// -- Tx Status Variables -- // -- Tx Status Variables --
// Choose the uart // Choose the uart
switch ( uart ) switch ( uart )
{ {
uart_addTxBuffer( 0 );
uart_addTxBuffer( 1 );
uart_addTxBuffer( UART_Master );
uart_addTxBuffer( UART_Slave );
default: default:
erro_msg("Invalid UART to send from..."); erro_msg("Invalid UART to send from...");
break; break;
void Connect_send_CableCheck( uint8_t patternLen ) void Connect_send_CableCheck( uint8_t patternLen )
{ {
// Wait until the Tx buffers are ready, then lock them // Wait until the Tx buffers are ready, then lock them
uart_lockTx( 0 );
uart_lockTx( 1 );
uart_lockBothTx( UART_Master, UART_Slave );


// Prepare header // Prepare header
uint8_t header[] = { 0x16, 0x01, CableCheck, patternLen }; uint8_t header[] = { 0x16, 0x01, CableCheck, patternLen };


// Send header // 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 // Send 0xD2 (11010010) for each argument
uint8_t value = 0xD2; uint8_t value = 0xD2;
for ( uint8_t c = 0; c < patternLen; c++ ) 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 // Release Tx buffers
uart_unlockTx( 0 );
uart_unlockTx( 1 );
uart_unlockTx( UART_Master );
uart_unlockTx( UART_Slave );
} }


void Connect_send_IdRequest() void Connect_send_IdRequest()
{ {
// Lock master bound Tx // Lock master bound Tx
uart_lockTx( 1 );
uart_lockTx( UART_Master );


// Prepare header // Prepare header
uint8_t header[] = { 0x16, 0x01, IdRequest }; uint8_t header[] = { 0x16, 0x01, IdRequest };


// Send header // Send header
Connect_addBytes( header, sizeof( header ), 1 ); // Master
Connect_addBytes( header, sizeof( header ), UART_Master );


// Unlock Tx // Unlock Tx
uart_unlockTx( 1 );
uart_unlockTx( UART_Master );
} }


// id is the value the next slave should enumerate as // id is the value the next slave should enumerate as
void Connect_send_IdEnumeration( uint8_t id ) void Connect_send_IdEnumeration( uint8_t id )
{ {
// Lock slave bound Tx // Lock slave bound Tx
uart_lockTx( 0 );
uart_lockTx( UART_Slave );


// Prepare header // Prepare header
uint8_t header[] = { 0x16, 0x01, IdEnumeration, id }; uint8_t header[] = { 0x16, 0x01, IdEnumeration, id };


// Send header // Send header
Connect_addBytes( header, sizeof( header ), 0 ); // Slave
Connect_addBytes( header, sizeof( header ), UART_Slave );


// Unlock Tx // Unlock Tx
uart_unlockTx( 0 );
uart_unlockTx( UART_Slave );
} }


// id is the currently assigned id to the slave // id is the currently assigned id to the slave
void Connect_send_IdReport( uint8_t id ) void Connect_send_IdReport( uint8_t id )
{ {
// Lock master bound Tx // Lock master bound Tx
uart_lockTx( 1 );
uart_lockTx( UART_Master );


// Prepare header // Prepare header
uint8_t header[] = { 0x16, 0x01, IdReport, id }; uint8_t header[] = { 0x16, 0x01, IdReport, id };


// Send header // Send header
Connect_addBytes( header, sizeof( header ), 1 ); // Master
Connect_addBytes( header, sizeof( header ), UART_Master );


// Unlock Tx // Unlock Tx
uart_unlockTx( 1 );
uart_unlockTx( UART_Master );
} }


// id is the currently assigned id to the slave // id is the currently assigned id to the slave
void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes ) void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes )
{ {
// Lock master bound Tx // Lock master bound Tx
uart_lockTx( 1 );
uart_lockTx( UART_Master );


// Prepare header // Prepare header
uint8_t header[] = { 0x16, 0x01, ScanCode, id, numScanCodes }; uint8_t header[] = { 0x16, 0x01, ScanCode, id, numScanCodes };


// Send header // Send header
Connect_addBytes( header, sizeof( header ), 1 ); // Master
Connect_addBytes( header, sizeof( header ), UART_Master );


// Send each of the scan codes // 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 // Unlock Tx
uart_unlockTx( 1 );
uart_unlockTx( UART_Master );
} }


// id is the currently assigned id to the slave // id is the currently assigned id to the slave
void Connect_send_Animation( uint8_t id, uint8_t *paramList, uint8_t numParams ) void Connect_send_Animation( uint8_t id, uint8_t *paramList, uint8_t numParams )
{ {
// Lock slave bound Tx // Lock slave bound Tx
uart_lockTx( 0 );
uart_lockTx( UART_Slave );


// Prepare header // Prepare header
uint8_t header[] = { 0x16, 0x01, Animation, id, numParams }; uint8_t header[] = { 0x16, 0x01, Animation, id, numParams };


// Send header // Send header
Connect_addBytes( header, sizeof( header ), 0 ); // Slave
Connect_addBytes( header, sizeof( header ), UART_Slave );


// Send each of the scan codes // Send each of the scan codes
Connect_addBytes( paramList, numParams, 0 ); // Slave
Connect_addBytes( paramList, numParams, UART_Slave );


// Unlock Tx // Unlock Tx
uart_unlockTx( 0 );
uart_unlockTx( UART_Slave );
} }


void Connect_send_Idle( uint8_t num ) void Connect_send_Idle( uint8_t num )
{ {
// Wait until the Tx buffers are ready, then lock them // 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) // Send n number of idles to reset link status (if in a bad state)
uint8_t value = 0x16; uint8_t value = 0x16;
for ( uint8_t c = 0; c < num; c++ ) 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 // Release Tx buffers
uart_unlockTx( 0 );
uart_unlockTx( 1 );
uart_unlockTx( UART_Master );
uart_unlockTx( UART_Slave );
} }






// - Cable Check variables - // - Cable Check variables -
uint32_t Connect_cableFaultsMaster = 0; 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_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 // Check if this is the first byte
if ( *pending_bytes == 0xFFFF ) if ( *pending_bytes == 0xFFFF )
warn_print("Cable Fault!"); warn_print("Cable Fault!");


// Check which side of the chain // Check which side of the chain
if ( to_slave )
{
Connect_cableFaultsMaster++;
Connect_cableOkMaster = 0;
print(" Master ");
}
else
if ( uart_num == UART_Slave )
{ {
Connect_cableFaultsSlave++; Connect_cableFaultsSlave++;
Connect_cableOkSlave = 0; Connect_cableOkSlave = 0;
print(" Slave "); print(" Slave ");
} }
else
{
Connect_cableFaultsMaster++;
Connect_cableOkMaster = 0;
print(" Master ");
}
printHex( byte ); printHex( byte );
print( NL ); print( NL );


// Signal that the command should wait for a SYN again // Signal that the command should wait for a SYN again
return 1; 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 cable check was successful, set cable ok
if ( *pending_bytes == 0 ) if ( *pending_bytes == 0 )
{ {
if ( to_slave )
if ( uart_num == UART_Slave )
{ {
Connect_cableOkMaster = 1;
Connect_cableOkSlave = 1;
} }
else else
{ {
Connect_cableOkSlave = 1;
Connect_cableOkMaster = 1;
} }
} }


return *pending_bytes == 0 ? 1 : 0; 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"); dbug_print("IdRequest");
// Check the directionality // Check the directionality
if ( to_slave )
if ( uart_num == UART_Master )
{ {
erro_print("Invalid IdRequest direction..."); erro_print("Invalid IdRequest direction...");
} }
return 1; 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"); dbug_print("IdEnumeration");
// Check the directionality // Check the directionality
if ( !to_slave )
if ( uart_num == UART_Slave )
{ {
erro_print("Invalid IdEnumeration direction..."); erro_print("Invalid IdEnumeration direction...");
} }
return 1; 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"); dbug_print("IdReport");
// Check the directionality // Check the directionality
if ( to_slave )
if ( uart_num == UART_Master )
{ {
erro_print("Invalid IdRequest direction..."); erro_print("Invalid IdRequest direction...");
} }
// Track Id response if master // Track Id response if master
if ( Connect_master ) if ( Connect_master )
{ {
// TODO, setup id's
info_msg("Id Reported: "); info_msg("Id Reported: ");
printHex( id ); printHex( id );
print( NL ); print( NL );

// Check if this is the highest ID
if ( id > Connect_maxId )
Connect_maxId = id;
return 1; return 1;
} }
// Propagate id if yet another slave // Propagate id if yet another slave
uint8_t Connect_receive_ScanCodeBufferPos; uint8_t Connect_receive_ScanCodeBufferPos;
uint8_t Connect_receive_ScanCodeDeviceId; 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 // Check the directionality
if ( to_slave )
if ( uart_num == UART_Master )
{ {
erro_print("Invalid ScanCode direction..."); erro_print("Invalid ScanCode direction...");
} }


// Reset the BufferPos if higher than sizeof TriggerGuide // Reset the BufferPos if higher than sizeof TriggerGuide
// And send the TriggerGuide to the Macro Module // And send the TriggerGuide to the Macro Module
if ( Connect_receive_ScanCodeBufferPos > sizeof( TriggerGuide ) )
if ( Connect_receive_ScanCodeBufferPos >= sizeof( TriggerGuide ) )
{ {
Connect_receive_ScanCodeBufferPos = 0; Connect_receive_ScanCodeBufferPos = 0;


// Adjust ScanCode offset // Adjust ScanCode offset
if ( Connect_receive_ScanCodeDeviceId > 0 ) 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 // This variable is in generatedKeymaps.h
extern uint8_t InterconnectOffsetList[]; extern uint8_t InterconnectOffsetList[];
Connect_receive_ScanCodeBuffer.scanCode = Connect_receive_ScanCodeBuffer.scanCode + InterconnectOffsetList[ Connect_receive_ScanCodeDeviceId - 1 ]; Connect_receive_ScanCodeBuffer.scanCode = Connect_receive_ScanCodeBuffer.scanCode + InterconnectOffsetList[ Connect_receive_ScanCodeDeviceId - 1 ];
} }


// ScanCode receive debug // 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 // Send ScanCode to macro module
// TODO
//Macro_triggerState( &Connect_receive_ScanCodeBuffer, 1 );
Macro_interconnectAdd( &Connect_receive_ScanCodeBuffer );
} }


break; break;
Connect_receive_ScanCodeDeviceId = byte; Connect_receive_ScanCodeDeviceId = byte;


// Lock the master Tx buffer // Lock the master Tx buffer
uart_lockTx( 1 );
uart_lockTx( UART_Master );


// Send header + Id byte // Send header + Id byte
uint8_t header[] = { 0x16, 0x01, ScanCode, byte }; uint8_t header[] = { 0x16, 0x01, ScanCode, byte };
Connect_addBytes( header, sizeof( header ), 1 ); // Master
Connect_addBytes( header, sizeof( header ), UART_Master );
break; break;
} }
case 0xFFFE: // Number of TriggerGuides in bytes case 0xFFFE: // Number of TriggerGuides in bytes
Connect_receive_ScanCodeBufferPos = 0; Connect_receive_ScanCodeBufferPos = 0;


// Pass through byte // Pass through byte
Connect_addBytes( &byte, 1, 1 ); // Master
Connect_addBytes( &byte, 1, UART_Master );
break; break;


default: default:
// Pass through byte // Pass through byte
Connect_addBytes( &byte, 1, 1 ); // Master
Connect_addBytes( &byte, 1, UART_Master );


// Unlock Tx Buffer after sending last byte // Unlock Tx Buffer after sending last byte
if ( *pending_bytes == 0 ) if ( *pending_bytes == 0 )
uart_unlockTx( 1 );
uart_unlockTx( UART_Master );
break; break;
} }


return *pending_bytes == 0 ? 1 : 0; 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"); dbug_print("Animation");
return 1; return 1;
uart1_rx_status = UARTStatus_Wait; uart1_rx_status = UARTStatus_Wait;
uart0_rx_bytes_waiting = 0; uart0_rx_bytes_waiting = 0;
uart1_rx_bytes_waiting = 0; uart1_rx_bytes_waiting = 0;
uart0_lock = 0;
uart1_lock = 0;


// Tx Status Variables // Tx Status Variables
uart0_tx_status = UARTStatus_Ready; uart0_tx_status = UARTStatus_Ready;
UART1_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT; UART1_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;


// Number of bytes in FIFO before TX Interrupt // Number of bytes in FIFO before TX Interrupt
// TODO Set 0
UART0_TWFIFO = 1; UART0_TWFIFO = 1;
UART1_TWFIFO = 1; UART1_TWFIFO = 1;


{ {
// Check if initially configured as a slave and usb comes up // Check if initially configured as a slave and usb comes up
// Then reconfigure as a master // Then reconfigure as a master
if ( !Connect_master && Output_Available )
if ( !Connect_master && Output_Available && !Connect_override )
{ {
Connect_setup( Output_Available ); Connect_setup( Output_Available );
} }
} }
} }


void cliFunc_connectDbg( char* args )
{
print( NL );
info_msg("Connect Debug Mode Toggle");
Connect_debug = !Connect_debug;
}

void cliFunc_connectIdl( char* args ) void cliFunc_connectIdl( char* args )
{ {
// Parse number from argument // Parse number from argument


print( NL ); print( NL );


// Set override
Connect_override = 1;

switch ( arg1Ptr[0] ) switch ( arg1Ptr[0] )
{ {
// Disable override
case 'd':
case 'D':
Connect_override = 0;
case 's': case 's':
case 'S': case 'S':
info_msg("Setting device as slave."); info_msg("Setting device as slave.");
print( Connect_master ? "Master" : "Slave" ); print( Connect_master ? "Master" : "Slave" );
print( NL "Device Id:\t" ); print( NL "Device Id:\t" );
printHex( Connect_id ); printHex( Connect_id );
print( NL "Max Id:\t" );
printHex( Connect_maxId );
print( NL "Master <=" NL "\tStatus:\t"); print( NL "Master <=" NL "\tStatus:\t");
printHex( Connect_cableOkMaster ); printHex( Connect_cableOkMaster );
print( NL "\tFaults:\t"); print( NL "\tFaults:\t");
printHex( Connect_cableFaultsMaster );
printHex32( Connect_cableFaultsMaster );
print("/");
printHex32( Connect_cableChecksMaster );
print( NL "\tRx:\t"); print( NL "\tRx:\t");
printHex( uart1_rx_status ); printHex( uart1_rx_status );
print( NL "\tTx:\t"); print( NL "\tTx:\t");
print( NL "Slave <=" NL "\tStatus:\t"); print( NL "Slave <=" NL "\tStatus:\t");
printHex( Connect_cableOkSlave ); printHex( Connect_cableOkSlave );
print( NL "\tFaults:\t"); print( NL "\tFaults:\t");
printHex( Connect_cableFaultsSlave );
printHex32( Connect_cableFaultsSlave );
print("/");
printHex32( Connect_cableChecksSlave );
print( NL "\tRx:\t"); print( NL "\tRx:\t");
printHex( uart0_rx_status ); printHex( uart0_rx_status );
print( NL "\tTx:\t"); print( NL "\tTx:\t");

+ 1
- 0
Scan/UARTConnect/connect_scan.h View File

RemoteInput, // Remote command to send to a given node's debug cli RemoteInput, // Remote command to send to a given node's debug cli


Command_TOP, // Enum bounds Command_TOP, // Enum bounds
Command_SYN = 0x16, // Reserved for error handling
} Command; } Command;


// UART Rx/Tx Status // UART Rx/Tx Status