1 /* Copyright (C) 2014-2015 by Jacob Alexander
3 * This file is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This file is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this file. If not, see <http://www.gnu.org/licenses/>.
17 // ----- Includes -----
20 #include <Lib/ScanLib.h>
30 #include "connect_scan.h"
34 // ----- Defines -----
36 #define UART_Num_Interfaces 2
39 #define UART_Buffer_Size UARTConnectBufSize_define
45 // Macro for popping from Tx ring buffer
46 #define uart_fillTxFifo( uartNum ) \
48 uint8_t fifoSize = ( ( UART##uartNum##_PFIFO & UART_PFIFO_TXFIFOSIZE ) >> 2 ); \
49 if ( fifoSize == 0 ) \
51 if ( Connect_debug ) \
53 print( "TxFIFO " #uartNum " - " ); \
54 printHex( fifoSize ); \
56 printHex( UART##uartNum##_TCFIFO ); \
58 printHex( uart_tx_buf[ uartNum ].items ); \
61 /* XXX Doesn't work well */ \
62 /* while ( UART##uartNum##_TCFIFO < fifoSize ) */ \
63 /* More reliable, albeit slower */ \
64 fifoSize -= UART##uartNum##_TCFIFO; \
65 while ( fifoSize-- != 0 ) \
67 if ( uart_tx_buf[ uartNum ].items == 0 ) \
69 UART##uartNum##_D = uart_tx_buf[ uartNum ].buffer[ uart_tx_buf[ uartNum ].head++ ]; \
70 uart_tx_buf[ uartNum ].items--; \
71 if ( uart_tx_buf[ uartNum ].head >= UART_Buffer_Size ) \
72 uart_tx_buf[ uartNum ].head = 0; \
76 // Macros for locking/unlock Tx buffers
77 #define uart_lockTx( uartNum ) \
79 /* First, secure place in line for the resource */ \
80 while ( uart_tx_status[ uartNum ].lock ); \
81 uart_tx_status[ uartNum ].lock = 1; \
82 /* Next, wait unit the UART is ready */ \
83 while ( uart_tx_status[ uartNum ].status != UARTStatus_Ready ); \
84 uart_tx_status[ uartNum ].status = UARTStatus_Wait; \
87 #define uart_lockBothTx( uartNum1, uartNum2 ) \
89 /* First, secure place in line for the resource */ \
90 while ( uart_tx_status[ uartNum1 ].lock || uart_tx_status[ uartNum2 ].lock ); \
91 uart_tx_status[ uartNum1 ].lock = 1; \
92 uart_tx_status[ uartNum2 ].lock = 1; \
93 /* Next, wait unit the UARTs are ready */ \
94 while ( uart_tx_status[ uartNum1 ].status != UARTStatus_Ready || uart_tx_status[ uartNum2 ].status != UARTStatus_Ready ); \
95 uart_tx_status[ uartNum1 ].status = UARTStatus_Wait; \
96 uart_tx_status[ uartNum2 ].status = UARTStatus_Wait; \
99 #define uart_unlockTx( uartNum ) \
101 /* Ready the UART */ \
102 uart_tx_status[ uartNum ].status = UARTStatus_Ready; \
103 /* Unlock the resource */ \
104 uart_tx_status[ uartNum ].lock = 0; \
109 // ----- Function Declarations -----
112 void cliFunc_connectCmd ( char *args );
113 void cliFunc_connectDbg ( char *args );
114 void cliFunc_connectIdl ( char *args );
115 void cliFunc_connectLst ( char *args );
116 void cliFunc_connectMst ( char *args );
117 void cliFunc_connectRst ( char *args );
118 void cliFunc_connectSts ( char *args );
122 // ----- Structs -----
124 typedef struct UARTRingBuf {
128 uint8_t buffer[UART_Buffer_Size];
131 typedef struct UARTDMABuf {
132 uint8_t buffer[UART_Buffer_Size];
136 typedef struct UARTStatusRx {
139 uint16_t bytes_waiting;
142 typedef struct UARTStatusTx {
149 // ----- Variables -----
151 // Connect Module command dictionary
152 CLIDict_Entry( connectCmd, "Sends a command via UART Connect, first arg is which uart, next arg is the command, rest are the arguments." );
153 CLIDict_Entry( connectDbg, "Toggle UARTConnect debug mode." );
154 CLIDict_Entry( connectIdl, "Sends N number of Idle commands, 2 is the default value, and should be sufficient in most cases." );
155 CLIDict_Entry( connectLst, "Lists available UARTConnect commands and index id" );
156 CLIDict_Entry( connectMst, "Sets the device as master. Use argument of s to set as slave." );
157 CLIDict_Entry( connectRst, "Resets both Rx and Tx connect buffers and state variables." );
158 CLIDict_Entry( connectSts, "UARTConnect status." );
159 CLIDict_Def( uartConnectCLIDict, "UARTConnect Module Commands" ) = {
160 CLIDict_Item( connectCmd ),
161 CLIDict_Item( connectDbg ),
162 CLIDict_Item( connectIdl ),
163 CLIDict_Item( connectLst ),
164 CLIDict_Item( connectMst ),
165 CLIDict_Item( connectRst ),
166 CLIDict_Item( connectSts ),
167 { 0, 0, 0 } // Null entry for dictionary end
171 // -- Connect Device Id Variables --
172 uint8_t Connect_id = 255; // Invalid, unset
173 uint8_t Connect_master = 0;
174 uint8_t Connect_maxId = 0;
177 // -- Control Variables --
178 uint32_t Connect_lastCheck = 0; // Cable Check scheduler
179 uint8_t Connect_debug = 0; // Set 1 for debug
180 uint8_t Connect_override = 0; // Prevents master from automatically being set
182 volatile uint8_t uarts_configured = 0;
185 // -- Rx Variables --
187 volatile UARTDMABuf uart_rx_buf[UART_Num_Interfaces];
188 volatile UARTStatusRx uart_rx_status[UART_Num_Interfaces];
191 // -- Tx Variables --
193 UARTRingBuf uart_tx_buf [UART_Num_Interfaces];
194 UARTStatusTx uart_tx_status[UART_Num_Interfaces];
197 // -- Ring Buffer Convenience Functions --
199 void Connect_addBytes( uint8_t *buffer, uint8_t count, uint8_t uart )
201 // Too big to fit into buffer
202 if ( count > UART_Buffer_Size )
204 erro_msg("Too big of a command to fit into the buffer...");
209 if ( uart >= UART_Num_Interfaces )
211 erro_print("Invalid UART to send from...");
215 // Delay UART copy until there's some space left
216 while ( uart_tx_buf[ uart ].items + count > UART_Buffer_Size )
218 warn_msg("Too much data to send on UART");
220 print( ", waiting..." NL );
224 // Append data to ring buffer
225 for ( uint8_t c = 0; c < count; c++ )
229 printHex( buffer[ c ] );
235 uart_tx_buf[ uart ].buffer[ uart_tx_buf[ uart ].tail++ ] = buffer[ c ];
236 uart_tx_buf[ uart ].items++;
237 if ( uart_tx_buf[ uart ].tail >= UART_Buffer_Size )
238 uart_tx_buf[ uart ].tail = 0;
239 if ( uart_tx_buf[ uart ].head == uart_tx_buf[ uart ].tail )
240 uart_tx_buf[ uart ].head++;
241 if ( uart_tx_buf[ uart ].head >= UART_Buffer_Size )
242 uart_tx_buf[ uart ].head = 0;
247 // -- Connect send functions --
249 // patternLen defines how many bytes should the incrementing pattern have
250 void Connect_send_CableCheck( uint8_t patternLen )
252 // Wait until the Tx buffers are ready, then lock them
253 uart_lockBothTx( UART_Master, UART_Slave );
256 uint8_t header[] = { 0x16, 0x01, CableCheck, patternLen };
259 Connect_addBytes( header, sizeof( header ), UART_Master );
260 Connect_addBytes( header, sizeof( header ), UART_Slave );
262 // Send 0xD2 (11010010) for each argument
263 uint8_t value = 0xD2;
264 for ( uint8_t c = 0; c < patternLen; c++ )
266 Connect_addBytes( &value, 1, UART_Master );
267 Connect_addBytes( &value, 1, UART_Slave );
270 // Release Tx buffers
271 uart_unlockTx( UART_Master );
272 uart_unlockTx( UART_Slave );
275 void Connect_send_IdRequest()
277 // Lock master bound Tx
278 uart_lockTx( UART_Master );
281 uint8_t header[] = { 0x16, 0x01, IdRequest };
284 Connect_addBytes( header, sizeof( header ), UART_Master );
287 uart_unlockTx( UART_Master );
290 // id is the value the next slave should enumerate as
291 void Connect_send_IdEnumeration( uint8_t id )
293 // Lock slave bound Tx
294 uart_lockTx( UART_Slave );
297 uint8_t header[] = { 0x16, 0x01, IdEnumeration, id };
300 Connect_addBytes( header, sizeof( header ), UART_Slave );
303 uart_unlockTx( UART_Slave );
306 // id is the currently assigned id to the slave
307 void Connect_send_IdReport( uint8_t id )
309 // Lock master bound Tx
310 uart_lockTx( UART_Master );
313 uint8_t header[] = { 0x16, 0x01, IdReport, id };
316 Connect_addBytes( header, sizeof( header ), UART_Master );
319 uart_unlockTx( UART_Master );
322 // id is the currently assigned id to the slave
323 // scanCodeStateList is an array of [scancode, state]'s (8 bit values)
324 // numScanCodes is the number of scan codes to parse from array
325 void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes )
327 // Lock master bound Tx
328 uart_lockTx( UART_Master );
331 uint8_t header[] = { 0x16, 0x01, ScanCode, id, numScanCodes };
334 Connect_addBytes( header, sizeof( header ), UART_Master );
336 // Send each of the scan codes
337 Connect_addBytes( (uint8_t*)scanCodeStateList, numScanCodes * TriggerGuideSize, UART_Master );
340 uart_unlockTx( UART_Master );
343 // id is the currently assigned id to the slave
344 // paramList is an array of [param, value]'s (8 bit values)
345 // numParams is the number of params to parse from the array
346 void Connect_send_Animation( uint8_t id, uint8_t *paramList, uint8_t numParams )
348 // Lock slave bound Tx
349 uart_lockTx( UART_Slave );
352 uint8_t header[] = { 0x16, 0x01, Animation, id, numParams };
355 Connect_addBytes( header, sizeof( header ), UART_Slave );
357 // Send each of the scan codes
358 Connect_addBytes( paramList, numParams, UART_Slave );
361 uart_unlockTx( UART_Slave );
364 // Send a remote capability command using capability index
365 // This may not be what's expected (especially if the firmware is not the same on each node)
366 // To broadcast to all slave nodes, set id to 255 instead of a specific id
367 void Connect_send_RemoteCapability( uint8_t id, uint8_t capabilityIndex, uint8_t state, uint8_t stateType, uint8_t numArgs, uint8_t *args )
370 uint8_t header[] = { 0x16, 0x01, RemoteCapability, id, capabilityIndex, state, stateType, numArgs };
373 if ( id == Connect_id )
376 // Send towards slave node
377 if ( id > Connect_id )
379 // Lock slave bound Tx
380 uart_lockTx( UART_Slave );
383 Connect_addBytes( header, sizeof( header ), UART_Slave );
386 Connect_addBytes( args, numArgs, UART_Slave );
389 uart_unlockTx( UART_Slave );
392 // Send towards master node
393 if ( id < Connect_id || id == 255 )
395 // Lock slave bound Tx
396 uart_lockTx( UART_Master );
399 Connect_addBytes( header, sizeof( header ), UART_Master );
402 Connect_addBytes( args, numArgs, UART_Master );
405 uart_unlockTx( UART_Master );
409 void Connect_send_Idle( uint8_t num )
411 // Wait until the Tx buffers are ready, then lock them
412 uart_lockBothTx( UART_Slave, UART_Master );
414 // Send n number of idles to reset link status (if in a bad state)
415 uint8_t value = 0x16;
416 for ( uint8_t c = 0; c < num; c++ )
418 Connect_addBytes( &value, 1, UART_Master );
419 Connect_addBytes( &value, 1, UART_Slave );
422 // Release Tx buffers
423 uart_unlockTx( UART_Master );
424 uart_unlockTx( UART_Slave );
428 // -- Connect receive functions --
430 // - Cable Check variables -
431 uint32_t Connect_cableFaultsMaster = 0;
432 uint32_t Connect_cableFaultsSlave = 0;
433 uint32_t Connect_cableChecksMaster = 0;
434 uint32_t Connect_cableChecksSlave = 0;
435 uint8_t Connect_cableOkMaster = 0;
436 uint8_t Connect_cableOkSlave = 0;
438 uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
440 // Check if this is the first byte
441 if ( *pending_bytes == 0xFFFF )
443 *pending_bytes = byte;
447 dbug_msg("PENDING SET -> ");
450 printHex( *pending_bytes );
459 // The argument bytes are always 0xD2 (11010010)
462 warn_print("Cable Fault!");
464 // Check which side of the chain
465 if ( uart_num == UART_Slave )
467 Connect_cableFaultsSlave++;
468 Connect_cableOkSlave = 0;
473 Connect_cableFaultsMaster++;
474 Connect_cableOkMaster = 0;
480 // Signal that the command should wait for a SYN again
485 // Check which side of the chain
486 if ( uart_num == UART_Slave )
488 Connect_cableChecksSlave++;
492 Connect_cableChecksMaster++;
497 // If cable check was successful, set cable ok
498 if ( *pending_bytes == 0 )
500 if ( uart_num == UART_Slave )
502 Connect_cableOkSlave = 1;
506 Connect_cableOkMaster = 1;
512 dbug_msg("CABLECHECK RECEIVE - ");
515 printHex( *pending_bytes );
519 // Check whether the cable check has finished
520 return *pending_bytes == 0 ? 1 : 0;
523 uint8_t Connect_receive_IdRequest( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
525 dbug_print("IdRequest");
526 // Check the directionality
527 if ( uart_num == UART_Master )
529 erro_print("Invalid IdRequest direction...");
532 // Check if master, begin IdEnumeration
533 if ( Connect_master )
535 // The first device is always id 1
536 // Id 0 is reserved for the master
537 Connect_send_IdEnumeration( 1 );
539 // Propagate IdRequest
542 Connect_send_IdRequest();
548 uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num )
550 dbug_print("IdEnumeration");
551 // Check the directionality
552 if ( uart_num == UART_Slave )
554 erro_print("Invalid IdEnumeration direction...");
560 // Send reponse back to master
561 Connect_send_IdReport( id );
563 // Propogate next Id if the connection is ok
564 if ( Connect_cableOkSlave )
566 Connect_send_IdEnumeration( id + 1 );
572 uint8_t Connect_receive_IdReport( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num )
574 dbug_print("IdReport");
575 // Check the directionality
576 if ( uart_num == UART_Master )
578 erro_print("Invalid IdRequest direction...");
581 // Track Id response if master
582 if ( Connect_master )
584 info_msg("Id Reported: ");
588 // Check if this is the highest ID
589 if ( id > Connect_maxId )
593 // Propagate id if yet another slave
596 Connect_send_IdReport( id );
602 // - Scan Code Variables -
603 TriggerGuide Connect_receive_ScanCodeBuffer;
604 uint8_t Connect_receive_ScanCodeBufferPos;
605 uint8_t Connect_receive_ScanCodeDeviceId;
607 uint8_t Connect_receive_ScanCode( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
609 // Check the directionality
610 if ( uart_num == UART_Master )
612 erro_print("Invalid ScanCode direction...");
615 // Master node, trigger scan codes
616 if ( Connect_master ) switch ( (*pending_bytes)-- )
618 // Byte count always starts at 0xFFFF
619 case 0xFFFF: // Device Id
620 Connect_receive_ScanCodeDeviceId = byte;
623 case 0xFFFE: // Number of TriggerGuides in bytes (byte * 3)
624 *pending_bytes = byte * sizeof( TriggerGuide );
625 Connect_receive_ScanCodeBufferPos = 0;
629 // Set the specific TriggerGuide entry
630 ((uint8_t*)&Connect_receive_ScanCodeBuffer)[ Connect_receive_ScanCodeBufferPos++ ] = byte;
632 // Reset the BufferPos if higher than sizeof TriggerGuide
633 // And send the TriggerGuide to the Macro Module
634 if ( Connect_receive_ScanCodeBufferPos >= sizeof( TriggerGuide ) )
636 Connect_receive_ScanCodeBufferPos = 0;
638 // Adjust ScanCode offset
639 if ( Connect_receive_ScanCodeDeviceId > 0 )
641 // Check if this node is too large
642 if ( Connect_receive_ScanCodeDeviceId >= InterconnectNodeMax )
644 warn_msg("Not enough interconnect layout nodes configured: ");
645 printHex( Connect_receive_ScanCodeDeviceId );
650 // This variable is in generatedKeymaps.h
651 extern uint8_t InterconnectOffsetList[];
652 Connect_receive_ScanCodeBuffer.scanCode = Connect_receive_ScanCodeBuffer.scanCode + InterconnectOffsetList[ Connect_receive_ScanCodeDeviceId - 1 ];
655 // ScanCode receive debug
659 printHex( Connect_receive_ScanCodeBuffer.type );
661 printHex( Connect_receive_ScanCodeBuffer.state );
663 printHex( Connect_receive_ScanCodeBuffer.scanCode );
667 // Send ScanCode to macro module
668 Macro_interconnectAdd( &Connect_receive_ScanCodeBuffer );
673 // Propagate ScanCode packet
674 // XXX It would be safer to buffer the scancodes first, before transmitting the packet -Jacob
675 // The current method is the more efficient/aggressive, but could cause issues if there were errors during transmission
676 else switch ( (*pending_bytes)-- )
678 // Byte count always starts at 0xFFFF
679 case 0xFFFF: // Device Id
681 Connect_receive_ScanCodeDeviceId = byte;
683 // Lock the master Tx buffer
684 uart_lockTx( UART_Master );
686 // Send header + Id byte
687 uint8_t header[] = { 0x16, 0x01, ScanCode, byte };
688 Connect_addBytes( header, sizeof( header ), UART_Master );
691 case 0xFFFE: // Number of TriggerGuides in bytes
692 *pending_bytes = byte * sizeof( TriggerGuide );
693 Connect_receive_ScanCodeBufferPos = 0;
696 Connect_addBytes( &byte, 1, UART_Master );
701 Connect_addBytes( &byte, 1, UART_Master );
703 // Unlock Tx Buffer after sending last byte
704 if ( *pending_bytes == 0 )
705 uart_unlockTx( UART_Master );
709 // Check whether the scan codes have finished sending
710 return *pending_bytes == 0 ? 1 : 0;
713 uint8_t Connect_receive_Animation( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
715 dbug_print("Animation");
719 // - Remote Capability Variables -
720 #define Connect_receive_RemoteCapabilityMaxArgs 25 // XXX Calculate the max using kll
721 RemoteCapabilityCommand Connect_receive_RemoteCapabilityBuffer;
722 uint8_t Connect_receive_RemoteCapabilityArgs[Connect_receive_RemoteCapabilityMaxArgs];
724 uint8_t Connect_receive_RemoteCapability( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
726 // Check which byte in the packet we are at
727 switch ( (*pending_bytes)-- )
729 // Byte count always starts at 0xFFFF
730 case 0xFFFF: // Device Id
731 Connect_receive_RemoteCapabilityBuffer.id = byte;
734 case 0xFFFE: // Capability Index
735 Connect_receive_RemoteCapabilityBuffer.capabilityIndex = byte;
738 case 0xFFFD: // State
739 Connect_receive_RemoteCapabilityBuffer.state = byte;
742 case 0xFFFC: // StateType
743 Connect_receive_RemoteCapabilityBuffer.stateType = byte;
746 case 0xFFFB: // Number of args
747 Connect_receive_RemoteCapabilityBuffer.numArgs = byte;
748 *pending_bytes = byte;
751 default: // Args (# defined by previous byte)
752 Connect_receive_RemoteCapabilityArgs[
753 Connect_receive_RemoteCapabilityBuffer.numArgs - *pending_bytes + 1
756 // If entire packet has been fully received
757 if ( *pending_bytes == 0 )
759 // Determine if this is the node to run the capability on
760 // Conditions: Matches or broadcast (0xFF)
761 if ( Connect_receive_RemoteCapabilityBuffer.id == 0xFF
762 || Connect_receive_RemoteCapabilityBuffer.id == Connect_id )
764 extern const Capability CapabilitiesList[]; // See generatedKeymap.h
765 void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(
766 CapabilitiesList[ Connect_receive_RemoteCapabilityBuffer.capabilityIndex ].func
769 Connect_receive_RemoteCapabilityBuffer.state,
770 Connect_receive_RemoteCapabilityBuffer.stateType,
771 &Connect_receive_RemoteCapabilityArgs[2]
775 // If this is not the correct node, keep sending it in the same direction (doesn't matter if more nodes exist)
776 // or if this is a broadcast
777 if ( Connect_receive_RemoteCapabilityBuffer.id == 0xFF
778 || Connect_receive_RemoteCapabilityBuffer.id != Connect_id )
780 // Prepare outgoing packet
781 Connect_receive_RemoteCapabilityBuffer.command = RemoteCapability;
783 // Send to the other UART (not the one receiving the packet from
784 uint8_t uart_direction = uart_num == UART_Master ? UART_Slave : UART_Master;
787 switch ( uart_direction )
789 case UART_Master: uart_lockTx( UART_Master ); break;
790 case UART_Slave: uart_lockTx( UART_Slave ); break;
794 uint8_t header[] = { 0x16, 0x01 };
795 Connect_addBytes( header, sizeof( header ), uart_direction );
797 // Send Remote Capability and arguments
798 Connect_addBytes( (uint8_t*)&Connect_receive_RemoteCapabilityBuffer, sizeof( RemoteCapabilityCommand ), uart_direction );
799 Connect_addBytes( Connect_receive_RemoteCapabilityArgs, Connect_receive_RemoteCapabilityBuffer.numArgs, uart_direction );
802 switch ( uart_direction )
804 case UART_Master: uart_unlockTx( UART_Master ); break;
805 case UART_Slave: uart_unlockTx( UART_Slave ); break;
812 // Check whether the scan codes have finished sending
813 return *pending_bytes == 0 ? 1 : 0;
818 // NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
819 uint16_t Connect_baud = UARTConnectBaud_define; // Max setting of 8191
820 uint16_t Connect_baudFine = UARTConnectBaudFine_define;
822 // Connect receive function lookup
823 void *Connect_receiveFunctions[] = {
824 Connect_receive_CableCheck,
825 Connect_receive_IdRequest,
826 Connect_receive_IdEnumeration,
827 Connect_receive_IdReport,
828 Connect_receive_ScanCode,
829 Connect_receive_Animation,
830 Connect_receive_RemoteCapability,
835 // ----- Functions -----
837 // Resets the state of the UART buffers and state variables
841 memset( (void*)uart_rx_status, 0, sizeof( UARTStatusRx ) * UART_Num_Interfaces );
844 memset( (void*)uart_tx_buf, 0, sizeof( UARTRingBuf ) * UART_Num_Interfaces );
845 memset( (void*)uart_tx_status, 0, sizeof( UARTStatusTx ) * UART_Num_Interfaces );
847 // Set Rx/Tx buffers as ready
848 for ( uint8_t inter = 0; inter < UART_Num_Interfaces; inter++ )
850 uart_tx_status[ inter ].status = UARTStatus_Ready;
851 uart_rx_buf[ inter ].last_read = UART_Buffer_Size;
856 // Setup connection to other side
857 // - Only supports a single slave and master
858 // - If USB has been initiallized at this point, this side is the master
859 // - If both sides assert master, flash error leds
860 void Connect_setup( uint8_t master )
862 // Indication that UARTs are not ready
863 uarts_configured = 0;
865 // Register Connect CLI dictionary
866 CLI_registerDictionary( uartConnectCLIDict, uartConnectCLIDictName );
869 Connect_master = master;
870 if ( Connect_master )
871 Connect_id = 0; // 0x00 is always the master Id
875 // Setup the the UART interface for keyboard data input
876 SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
877 SIM_SCGC4 |= SIM_SCGC4_UART1; // Disable clock gating
879 // Pin Setup for UART0 / UART1
880 PORTA_PCR1 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); // RX Pin
881 PORTA_PCR2 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); // TX Pin
882 PORTE_PCR0 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); // RX Pin
883 PORTE_PCR1 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin
886 UART0_BDH = (uint8_t)(Connect_baud >> 8);
887 UART0_BDL = (uint8_t)Connect_baud;
888 UART0_C4 = Connect_baudFine;
889 UART1_BDH = (uint8_t)(Connect_baud >> 8);
890 UART1_BDL = (uint8_t)Connect_baud;
891 UART1_C4 = Connect_baudFine;
893 // 8 bit, Even Parity, Idle Character bit after stop
894 // NOTE: For 8 bit with Parity you must enable 9 bit transmission (pg. 1065)
895 // You only need to use UART0_D for 8 bit reading/writing though
896 // UART_C1_M UART_C1_PE UART_C1_PT UART_C1_ILT
897 UART0_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
898 UART1_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
900 // Only using Tx Fifos
901 UART0_PFIFO = UART_PFIFO_TXFE;
902 UART1_PFIFO = UART_PFIFO_TXFE;
905 SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
906 SIM_SCGC7 |= SIM_SCGC7_DMA;
908 // Start with channels disabled first
912 // Configure DMA channels
913 //DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK; // TODO What's this?
917 // Default control register
921 DMA_DCHPRI0 = 0; // Ch 0, priority 0
922 DMA_DCHPRI1 = 1; // ch 1, priority 1
924 // Clear error interrupts
928 DMA_TCD0_SADDR = (uint32_t*)&UART0_D;
929 DMA_TCD1_SADDR = (uint32_t*)&UART1_D;
933 // No modulo, 8-bit transfer size
934 DMA_TCD0_ATTR = DMA_TCD_ATTR_SMOD(0) | DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DMOD(0) | DMA_TCD_ATTR_DSIZE(0);
935 DMA_TCD1_ATTR = DMA_TCD_ATTR_SMOD(0) | DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DMOD(0) | DMA_TCD_ATTR_DSIZE(0);
937 // One byte transferred at a time
938 DMA_TCD0_NBYTES_MLNO = 1;
939 DMA_TCD1_NBYTES_MLNO = 1;
941 // Source address does not change
945 // Destination buffer
946 DMA_TCD0_DADDR = (uint32_t*)uart_rx_buf[0].buffer;
947 DMA_TCD1_DADDR = (uint32_t*)uart_rx_buf[1].buffer;
949 // Incoming byte, increment by 1 in the rx buffer
953 // Single major loop, must be the same value
954 DMA_TCD0_CITER_ELINKNO = UART_Buffer_Size;
955 DMA_TCD1_CITER_ELINKNO = UART_Buffer_Size;
956 DMA_TCD0_BITER_ELINKNO = UART_Buffer_Size;
957 DMA_TCD1_BITER_ELINKNO = UART_Buffer_Size;
959 // Reset buffer when full
960 DMA_TCD0_DLASTSGA = -( UART_Buffer_Size );
961 DMA_TCD1_DLASTSGA = -( UART_Buffer_Size );
963 // Enable DMA channels
964 DMA_ERQ |= DMA_ERQ_ERQ0 | DMA_ERQ_ERQ1;
966 // Setup DMA channel routing
967 DMAMUX0_CHCFG0 = DMAMUX_ENABLE | DMAMUX_SOURCE_UART0_RX;
968 DMAMUX0_CHCFG1 = DMAMUX_ENABLE | DMAMUX_SOURCE_UART1_RX;
970 // Enable DMA requests (requires Rx interrupts)
971 UART0_C5 = UART_C5_RDMAS;
972 UART1_C5 = UART_C5_RDMAS;
974 // TX Enabled, RX Enabled, RX Interrupt Enabled
975 UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
976 UART1_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
978 // Add interrupts to the vector table
979 NVIC_ENABLE_IRQ( IRQ_UART0_STATUS );
980 NVIC_ENABLE_IRQ( IRQ_UART1_STATUS );
982 // UARTs are now ready to go
983 uarts_configured = 1;
985 // Reset the state of the UART variables
990 #define DMA_BUF_POS( x, pos ) \
992 pos = DMA_TCD##x##_CITER_ELINKNO; \
994 void Connect_rx_process( uint8_t uartNum )
996 // Determine current position to read until
1000 DMA_BUF_POS( 0, bufpos );
1001 DMA_BUF_POS( 1, bufpos );
1004 // Process each of the new bytes
1005 // Even if we receive more bytes during processing, wait until the next check so we don't starve other tasks
1006 while ( bufpos != uart_rx_buf[ uartNum ].last_read )
1008 // If the last_read byte is at the buffer edge, roll back to beginning
1009 if ( uart_rx_buf[ uartNum ].last_read == 0 )
1011 uart_rx_buf[ uartNum ].last_read = UART_Buffer_Size;
1013 // Check to see if we're at the boundary
1014 if ( bufpos == UART_Buffer_Size )
1018 // Read the byte out of Rx DMA buffer
1019 uint8_t byte = uart_rx_buf[ uartNum ].buffer[ UART_Buffer_Size - uart_rx_buf[ uartNum ].last_read-- ];
1021 if ( Connect_debug )
1027 // Process UART byte
1028 switch ( uart_rx_status[ uartNum ].status )
1030 // Every packet must start with a SYN / 0x16
1031 case UARTStatus_Wait:
1032 if ( Connect_debug )
1036 uart_rx_status[ uartNum ].status = byte == 0x16 ? UARTStatus_SYN : UARTStatus_Wait;
1039 // After a SYN, there must be a SOH / 0x01
1040 case UARTStatus_SYN:
1041 if ( Connect_debug )
1045 uart_rx_status[ uartNum ].status = byte == 0x01 ? UARTStatus_SOH : UARTStatus_Wait;
1048 // After a SOH the packet structure may diverge a bit
1049 // This is the packet type field (refer to the Command enum)
1050 // For very small packets (e.g. IdRequest) this is all that's required to take action
1051 case UARTStatus_SOH:
1053 if ( Connect_debug )
1058 // Check if this is actually a reserved CMD 0x16 (Error condition)
1059 if ( byte == Command_SYN )
1061 uart_rx_status[ uartNum ].status = UARTStatus_SYN;
1065 // Otherwise process the command
1066 if ( byte < Command_TOP )
1068 uart_rx_status[ uartNum ].status = UARTStatus_Command;
1069 uart_rx_status[ uartNum ].command = byte;
1070 uart_rx_status[ uartNum ].bytes_waiting = 0xFFFF;
1072 // Invalid packet type, ignore
1075 uart_rx_status[ uartNum ].status = UARTStatus_Wait;
1078 // Check if this is a very short packet
1079 switch ( uart_rx_status[ uartNum ].command )
1082 Connect_receive_IdRequest( 0, (uint16_t*)&uart_rx_status[ uartNum ].bytes_waiting, uartNum );
1083 uart_rx_status[ uartNum ].status = UARTStatus_Wait;
1087 if ( Connect_debug )
1090 printHex( uart_rx_status[ uartNum ].command );
1097 // After the packet type has been deciphered do Command specific processing
1098 // Until the Command has received all the bytes it requires the UART buffer stays in this state
1099 case UARTStatus_Command:
1101 if ( Connect_debug )
1105 /* Call specific UARTConnect command receive function */
1106 uint8_t (*rcvFunc)(uint8_t, uint16_t(*), uint8_t) = (uint8_t(*)(uint8_t, uint16_t(*), uint8_t))(Connect_receiveFunctions[ uart_rx_status[ uartNum ].command ]);
1107 if ( rcvFunc( byte, (uint16_t*)&uart_rx_status[ uartNum ].bytes_waiting, uartNum ) )
1108 uart_rx_status[ uartNum ].status = UARTStatus_Wait;
1112 // Unknown status, should never get here
1114 erro_msg("Invalid UARTStatus...");
1115 uart_rx_status[ uartNum ].status = UARTStatus_Wait;
1119 if ( Connect_debug )
1127 // Scan for updates in the master/slave
1128 // - Interrupts will deal with most input functions
1129 // - Used to send queries
1130 // - SyncEvent is sent immediately once the current command is sent
1131 // - SyncEvent is also blocking until sent
1134 // Check if initially configured as a slave and usb comes up
1135 // Then reconfigure as a master
1136 if ( !Connect_master && Output_Available && !Connect_override )
1138 Connect_setup( Output_Available );
1141 // Limit how often we do cable checks
1142 uint32_t time_compare = 0x7FF; // Must be all 1's, 0x3FF is valid, 0x4FF is not
1143 uint32_t current_time = systick_millis_count;
1144 if ( Connect_lastCheck != current_time
1145 && ( current_time & time_compare ) == time_compare
1148 // Make sure we don't double check if the clock speed is too high
1149 Connect_lastCheck = current_time;
1151 // Send a cable check command of 2 bytes
1152 Connect_send_CableCheck( UARTConnectCableCheckLength_define );
1154 // If this is a slave, and we don't have an id yeth
1155 // Don't bother sending if there are cable issues
1156 if ( !Connect_master && Connect_id == 0xFF && Connect_cableOkMaster )
1158 Connect_send_IdRequest();
1162 // Only process commands if uarts have been configured
1163 if ( uarts_configured )
1165 // Check if Tx Buffers are empty and the Tx Ring buffers have data to send
1166 // This happens if there was previously nothing to send
1167 if ( uart_tx_buf[ 0 ].items > 0 && UART0_TCFIFO == 0 )
1168 uart_fillTxFifo( 0 );
1169 if ( uart_tx_buf[ 1 ].items > 0 && UART1_TCFIFO == 0 )
1170 uart_fillTxFifo( 1 );
1172 // Process Rx Buffers
1173 Connect_rx_process( 0 );
1174 Connect_rx_process( 1 );
1180 // ----- CLI Command Functions -----
1182 void cliFunc_connectCmd( char* args )
1184 // Parse number from argument
1185 // NOTE: Only first argument is used
1188 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
1192 switch ( numToInt( &arg1Ptr[0] ) )
1195 Connect_send_CableCheck( UARTConnectCableCheckLength_define );
1199 Connect_send_IdRequest();
1203 Connect_send_IdEnumeration( 5 );
1207 Connect_send_IdReport( 8 );
1212 TriggerGuide scanCodes[] = { { 0x00, 0x01, 0x05 }, { 0x00, 0x03, 0x16 } };
1213 Connect_send_ScanCode( 10, scanCodes, 2 );
1219 case RemoteCapability:
1236 void cliFunc_connectDbg( char* args )
1239 info_msg("Connect Debug Mode Toggle");
1240 Connect_debug = !Connect_debug;
1243 void cliFunc_connectIdl( char* args )
1245 // Parse number from argument
1246 // NOTE: Only first argument is used
1249 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
1252 info_msg("Sending Sync Idles...");
1254 uint8_t count = numToInt( &arg1Ptr[0] );
1255 // Default to 2 idles
1259 Connect_send_Idle( count );
1262 void cliFunc_connectLst( char* args )
1264 const char *Command_strs[] = {
1277 info_msg("List of UARTConnect commands");
1278 for ( uint8_t cmd = 0; cmd < Command_TOP; cmd++ )
1283 dPrint( (char*)Command_strs[ cmd ] );
1287 void cliFunc_connectMst( char* args )
1289 // Parse number from argument
1290 // NOTE: Only first argument is used
1293 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
1298 Connect_override = 1;
1300 switch ( arg1Ptr[0] )
1305 Connect_override = 0;
1308 info_msg("Setting device as slave.");
1316 info_msg("Setting device as master.");
1323 void cliFunc_connectRst( char* args )
1326 info_msg("Resetting UARTConnect state...");
1333 void cliFunc_connectSts( char* args )
1336 info_msg("UARTConnect Status");
1337 print( NL "Device Type:\t" );
1338 print( Connect_master ? "Master" : "Slave" );
1339 print( NL "Device Id:\t" );
1340 printHex( Connect_id );
1341 print( NL "Max Id:\t" );
1342 printHex( Connect_maxId );
1343 print( NL "Master <=" NL "\tStatus:\t");
1344 printHex( Connect_cableOkMaster );
1345 print( NL "\tFaults:\t");
1346 printHex32( Connect_cableFaultsMaster );
1348 printHex32( Connect_cableChecksMaster );
1349 print( NL "\tRx:\t");
1350 printHex( uart_rx_status[UART_Master].status );
1351 print( NL "\tTx:\t");
1352 printHex( uart_tx_status[UART_Master].status );
1353 print( NL "Slave <=" NL "\tStatus:\t");
1354 printHex( Connect_cableOkSlave );
1355 print( NL "\tFaults:\t");
1356 printHex32( Connect_cableFaultsSlave );
1358 printHex32( Connect_cableChecksSlave );
1359 print( NL "\tRx:\t");
1360 printHex( uart_rx_status[UART_Slave].status );
1361 print( NL "\tTx:\t");
1362 printHex( uart_tx_status[UART_Slave].status );