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"
38 #define uart_lock_m( uartNum ) uart##uartNum##_lock
39 #define uart_buffer_items_m( uartNum ) uart##uartNum##_buffer_items
40 #define uart_buffer_m( uartNum ) uart##uartNum##_buffer
41 #define uart_buffer_head_m( uartNum ) uart##uartNum##_buffer_head
42 #define uart_buffer_tail_m( uartNum ) uart##uartNum##_buffer_tail
43 #define uart_tx_status_m( uartNum ) uart##uartNum##_tx_status
45 // Macro for adding to each uart Tx ring buffer
46 #define uart_addTxBuffer( uartNum ) \
48 /* Delay UART copy until there's some space left */ \
49 while ( uart_buffer_items_m( uartNum ) + count > uart_buffer_size ) \
51 warn_msg("Too much data to send on UART0, waiting..."); \
54 /* Append data to ring buffer */ \
55 for ( uint8_t c = 0; c < count; c++ ) \
57 if ( Connect_debug ) \
59 printHex( buffer[ c ] ); \
60 print( " +" #uartNum NL ); \
62 uart_buffer_m( uartNum )[ uart_buffer_tail_m( uartNum )++ ] = buffer[ c ]; \
63 uart_buffer_items_m( uartNum )++; \
64 if ( uart_buffer_tail_m( uartNum ) >= uart_buffer_size ) \
65 uart_buffer_tail_m( uartNum ) = 0; \
66 if ( uart_buffer_head_m( uartNum ) == uart_buffer_tail_m( uartNum ) ) \
67 uart_buffer_head_m( uartNum )++; \
68 if ( uart_buffer_head_m( uartNum ) >= uart_buffer_size ) \
69 uart_buffer_head_m( uartNum ) = 0; \
73 // Macro for popping from Tx ring buffer
74 #define uart_fillTxFifo( uartNum ) \
76 uint8_t fifoSize = ( ( UART##uartNum##_PFIFO & UART_PFIFO_TXFIFOSIZE ) >> 2 ); \
77 if ( fifoSize == 0 ) \
79 if ( Connect_debug ) \
81 print( "TxFIFO " #uartNum " - " ); \
82 printHex( fifoSize ); \
84 printHex( UART##uartNum##_TCFIFO ); \
86 printHex( uart##uartNum##_buffer_items ); \
89 /* XXX Doesn't work well */ \
90 /* while ( UART##uartNum##_TCFIFO < fifoSize ) */ \
91 /* More reliable, albeit slower */ \
92 fifoSize -= UART##uartNum##_TCFIFO; \
93 while ( fifoSize-- != 0 ) \
95 if ( uart##uartNum##_buffer_items == 0 ) \
97 UART##uartNum##_D = uart##uartNum##_buffer[ uart##uartNum##_buffer_head++ ]; \
98 uart##uartNum##_buffer_items--; \
99 if ( uart##uartNum##_buffer_head >= uart_buffer_size ) \
100 uart##uartNum##_buffer_head = 0; \
104 // Macro for processing UART Rx
105 #define uart_processRx( uartNum ) \
107 if ( !( UART##uartNum##_S1 & UART_S1_RDRF ) ) \
109 uint8_t available = UART##uartNum##_RCFIFO; \
110 if ( available == 0 ) \
112 available = UART##uartNum##_D; \
113 UART##uartNum##_CFIFO = UART_CFIFO_RXFLUSH; \
116 /* Process each byte in the UART buffer */ \
117 while ( available-- > 0 ) \
119 /* First check if there was noise or Parity issues with current byte */ \
120 uint8_t err_status = UART##uartNum##_ED; \
121 /* Read byte from Rx FIFO */ \
122 uint8_t byteRead = UART##uartNum##_D; \
123 if ( Connect_debug ) \
125 printHex( byteRead ); \
127 printInt8( available ); \
130 /* Check error status */ \
131 if ( err_status & 0x80 ) \
135 if ( err_status & 0x40 ) \
137 print(" PARITY ERR "); \
139 /* Ignore current byte if there was an error */ \
142 uart##uartNum##_rx_status = UARTStatus_Wait; \
143 if ( Connect_debug ) \
149 switch ( uart##uartNum##_rx_status ) \
151 case UARTStatus_Wait: \
152 if ( Connect_debug ) \
156 uart##uartNum##_rx_status = byteRead == 0x16 ? UARTStatus_SYN : UARTStatus_Wait; \
158 case UARTStatus_SYN: \
159 if ( Connect_debug ) \
163 uart##uartNum##_rx_status = byteRead == 0x01 ? UARTStatus_SOH : UARTStatus_Wait; \
165 case UARTStatus_SOH: \
167 if ( Connect_debug ) \
171 /* Check if this is actually a reserved CMD 0x16 */ \
172 if ( byteRead == Command_SYN ) \
174 uart##uartNum##_rx_status = UARTStatus_SYN; \
177 /* Otherwise process the command */ \
178 uint8_t byte = byteRead; \
179 if ( byte < Command_TOP ) \
181 uart##uartNum##_rx_status = UARTStatus_Command; \
182 uart##uartNum##_rx_command = byte; \
183 uart##uartNum##_rx_bytes_waiting = 0xFFFF; \
187 uart##uartNum##_rx_status = UARTStatus_Wait; \
189 switch ( uart##uartNum##_rx_command ) \
192 Connect_receive_IdRequest( 0, (uint16_t*)&uart##uartNum##_rx_bytes_waiting, uartNum ); \
193 uart##uartNum##_rx_status = UARTStatus_Wait; \
196 if ( Connect_debug ) \
199 printHex( uart##uartNum##_rx_command ); \
205 case UARTStatus_Command: \
207 if ( Connect_debug ) \
211 /* Call specific UARTConnect command receive function */ \
212 uint8_t (*rcvFunc)(uint8_t, uint16_t(*), uint8_t) = (uint8_t(*)(uint8_t, uint16_t(*), uint8_t))(Connect_receiveFunctions[ uart##uartNum##_rx_command ]); \
213 if ( rcvFunc( byteRead, (uint16_t*)&uart##uartNum##_rx_bytes_waiting, uartNum ) ) \
214 uart##uartNum##_rx_status = UARTStatus_Wait; \
218 erro_msg("Invalid UARTStatus..."); \
219 uart##uartNum##_rx_status = UARTStatus_Wait; \
223 if ( Connect_debug ) \
230 // Macros for locking/unlock Tx buffers
231 #define uart_lockTx( uartNum ) \
233 /* First, secure place in line for the resource */ \
234 while ( uart_lock_m( uartNum ) ); \
235 uart_lock_m( uartNum ) = 1; \
236 /* Next, wait unit the UART is ready */ \
237 while ( uart_tx_status_m( uartNum ) != UARTStatus_Ready ); \
238 uart_tx_status_m( uartNum ) = UARTStatus_Wait; \
241 #define uart_lockBothTx( uartNum1, uartNum2 ) \
243 /* First, secure place in line for the resource */ \
244 while ( uart_lock_m( uartNum1 ) || uart_lock_m( uartNum2 ) ); \
245 uart_lock_m( uartNum1 ) = 1; \
246 uart_lock_m( uartNum2 ) = 1; \
247 /* Next, wait unit the UARTs are ready */ \
248 while ( uart_tx_status_m( uartNum1 ) != UARTStatus_Ready || uart_tx_status_m( uartNum2 ) != UARTStatus_Ready ); \
249 uart_tx_status_m( uartNum1 ) = UARTStatus_Wait; \
250 uart_tx_status_m( uartNum2 ) = UARTStatus_Wait; \
253 #define uart_unlockTx( uartNum ) \
255 /* Ready the UART */ \
256 uart_tx_status_m( uartNum ) = UARTStatus_Ready; \
257 /* Unlock the resource */ \
258 uart_lock_m( uartNum ) = 0; \
263 // ----- Function Declarations -----
266 void cliFunc_connectCmd ( char *args );
267 void cliFunc_connectDbg ( char *args );
268 void cliFunc_connectIdl ( char *args );
269 void cliFunc_connectLst ( char *args );
270 void cliFunc_connectMst ( char *args );
271 void cliFunc_connectRst ( char *args );
272 void cliFunc_connectSts ( char *args );
276 // ----- Variables -----
278 // Connect Module command dictionary
279 CLIDict_Entry( connectCmd, "Sends a command via UART Connect, first arg is which uart, next arg is the command, rest are the arguments." );
280 CLIDict_Entry( connectDbg, "Toggle UARTConnect debug mode." );
281 CLIDict_Entry( connectIdl, "Sends N number of Idle commands, 2 is the default value, and should be sufficient in most cases." );
282 CLIDict_Entry( connectLst, "Lists available UARTConnect commands and index id" );
283 CLIDict_Entry( connectMst, "Sets the device as master. Use argument of s to set as slave." );
284 CLIDict_Entry( connectRst, "Resets both Rx and Tx connect buffers and state variables." );
285 CLIDict_Entry( connectSts, "UARTConnect status." );
286 CLIDict_Def( uartConnectCLIDict, "UARTConnect Module Commands" ) = {
287 CLIDict_Item( connectCmd ),
288 CLIDict_Item( connectDbg ),
289 CLIDict_Item( connectIdl ),
290 CLIDict_Item( connectLst ),
291 CLIDict_Item( connectMst ),
292 CLIDict_Item( connectRst ),
293 CLIDict_Item( connectSts ),
294 { 0, 0, 0 } // Null entry for dictionary end
298 // -- Connect Device Id Variables --
299 uint8_t Connect_id = 255; // Invalid, unset
300 uint8_t Connect_master = 0;
301 uint8_t Connect_maxId = 0;
304 // -- Control Variables --
305 uint32_t Connect_lastCheck = 0; // Cable Check scheduler
306 uint8_t Connect_debug = 0; // Set 1 for debug
307 uint8_t Connect_override = 0; // Prevents master from automatically being set
310 // -- Rx Status Variables --
312 volatile UARTStatus uart0_rx_status;
313 volatile UARTStatus uart1_rx_status;
314 volatile uint16_t uart0_rx_bytes_waiting;
315 volatile uint16_t uart1_rx_bytes_waiting;
316 volatile Command uart0_rx_command;
317 volatile Command uart1_rx_command;
318 volatile uint8_t uart0_lock;
319 volatile uint8_t uart1_lock;
322 // -- Tx Status Variables --
324 volatile UARTStatus uart0_tx_status;
325 volatile UARTStatus uart1_tx_status;
328 // -- Ring Buffer Variables --
330 #define uart_buffer_size UARTConnectBufSize_define
331 volatile uint8_t uart0_buffer_head;
332 volatile uint8_t uart0_buffer_tail;
333 volatile uint8_t uart0_buffer_items;
334 volatile uint8_t uart0_buffer[uart_buffer_size];
335 volatile uint8_t uart1_buffer_head;
336 volatile uint8_t uart1_buffer_tail;
337 volatile uint8_t uart1_buffer_items;
338 volatile uint8_t uart1_buffer[uart_buffer_size];
340 volatile uint8_t uarts_configured = 0;
343 // -- Ring Buffer Convenience Functions --
345 void Connect_addBytes( uint8_t *buffer, uint8_t count, uint8_t uart )
347 // Too big to fit into buffer
348 if ( count > uart_buffer_size )
350 erro_msg("Too big of a command to fit into the buffer...");
357 uart_addTxBuffer( UART_Master );
358 uart_addTxBuffer( UART_Slave );
360 erro_msg("Invalid UART to send from...");
366 // -- Connect send functions --
368 // patternLen defines how many bytes should the incrementing pattern have
369 void Connect_send_CableCheck( uint8_t patternLen )
371 // Wait until the Tx buffers are ready, then lock them
372 uart_lockBothTx( UART_Master, UART_Slave );
375 uint8_t header[] = { 0x16, 0x01, CableCheck, patternLen };
378 Connect_addBytes( header, sizeof( header ), UART_Master );
379 Connect_addBytes( header, sizeof( header ), UART_Slave );
381 // Send 0xD2 (11010010) for each argument
382 uint8_t value = 0xD2;
383 for ( uint8_t c = 0; c < patternLen; c++ )
385 Connect_addBytes( &value, 1, UART_Master );
386 Connect_addBytes( &value, 1, UART_Slave );
389 // Release Tx buffers
390 uart_unlockTx( UART_Master );
391 uart_unlockTx( UART_Slave );
394 void Connect_send_IdRequest()
396 // Lock master bound Tx
397 uart_lockTx( UART_Master );
400 uint8_t header[] = { 0x16, 0x01, IdRequest };
403 Connect_addBytes( header, sizeof( header ), UART_Master );
406 uart_unlockTx( UART_Master );
409 // id is the value the next slave should enumerate as
410 void Connect_send_IdEnumeration( uint8_t id )
412 // Lock slave bound Tx
413 uart_lockTx( UART_Slave );
416 uint8_t header[] = { 0x16, 0x01, IdEnumeration, id };
419 Connect_addBytes( header, sizeof( header ), UART_Slave );
422 uart_unlockTx( UART_Slave );
425 // id is the currently assigned id to the slave
426 void Connect_send_IdReport( uint8_t id )
428 // Lock master bound Tx
429 uart_lockTx( UART_Master );
432 uint8_t header[] = { 0x16, 0x01, IdReport, id };
435 Connect_addBytes( header, sizeof( header ), UART_Master );
438 uart_unlockTx( UART_Master );
441 // id is the currently assigned id to the slave
442 // scanCodeStateList is an array of [scancode, state]'s (8 bit values)
443 // numScanCodes is the number of scan codes to parse from array
444 void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes )
446 // Lock master bound Tx
447 uart_lockTx( UART_Master );
450 uint8_t header[] = { 0x16, 0x01, ScanCode, id, numScanCodes };
453 Connect_addBytes( header, sizeof( header ), UART_Master );
455 // Send each of the scan codes
456 Connect_addBytes( (uint8_t*)scanCodeStateList, numScanCodes * TriggerGuideSize, UART_Master );
459 uart_unlockTx( UART_Master );
462 // id is the currently assigned id to the slave
463 // paramList is an array of [param, value]'s (8 bit values)
464 // numParams is the number of params to parse from the array
465 void Connect_send_Animation( uint8_t id, uint8_t *paramList, uint8_t numParams )
467 // Lock slave bound Tx
468 uart_lockTx( UART_Slave );
471 uint8_t header[] = { 0x16, 0x01, Animation, id, numParams };
474 Connect_addBytes( header, sizeof( header ), UART_Slave );
476 // Send each of the scan codes
477 Connect_addBytes( paramList, numParams, UART_Slave );
480 uart_unlockTx( UART_Slave );
483 void Connect_send_Idle( uint8_t num )
485 // Wait until the Tx buffers are ready, then lock them
486 uart_lockBothTx( UART_Slave, UART_Master );
488 // Send n number of idles to reset link status (if in a bad state)
489 uint8_t value = 0x16;
490 for ( uint8_t c = 0; c < num; c++ )
492 Connect_addBytes( &value, 1, UART_Master );
493 Connect_addBytes( &value, 1, UART_Slave );
496 // Release Tx buffers
497 uart_unlockTx( UART_Master );
498 uart_unlockTx( UART_Slave );
502 // -- Connect receive functions --
504 // - Cable Check variables -
505 uint32_t Connect_cableFaultsMaster = 0;
506 uint32_t Connect_cableFaultsSlave = 0;
507 uint32_t Connect_cableChecksMaster = 0;
508 uint32_t Connect_cableChecksSlave = 0;
509 uint8_t Connect_cableOkMaster = 0;
510 uint8_t Connect_cableOkSlave = 0;
512 uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
514 // Check if this is the first byte
515 if ( *pending_bytes == 0xFFFF )
517 *pending_bytes = byte;
521 dbug_msg("PENDING SET -> ");
524 printHex( *pending_bytes );
533 // The argument bytes are always 0xD2 (11010010)
536 warn_print("Cable Fault!");
538 // Check which side of the chain
539 if ( uart_num == UART_Slave )
541 Connect_cableFaultsSlave++;
542 Connect_cableOkSlave = 0;
547 Connect_cableFaultsMaster++;
548 Connect_cableOkMaster = 0;
554 // Signal that the command should wait for a SYN again
559 // Check which side of the chain
560 if ( uart_num == UART_Slave )
562 Connect_cableChecksSlave++;
566 Connect_cableChecksMaster++;
571 // If cable check was successful, set cable ok
572 if ( *pending_bytes == 0 )
574 if ( uart_num == UART_Slave )
576 Connect_cableOkSlave = 1;
580 Connect_cableOkMaster = 1;
586 dbug_msg("CABLECHECK RECEIVE - ");
589 printHex( *pending_bytes );
593 // Check whether the cable check has finished
594 return *pending_bytes == 0 ? 1 : 0;
597 uint8_t Connect_receive_IdRequest( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
599 dbug_print("IdRequest");
600 // Check the directionality
601 if ( uart_num == UART_Master )
603 erro_print("Invalid IdRequest direction...");
606 // Check if master, begin IdEnumeration
607 if ( Connect_master )
609 // The first device is always id 1
610 // Id 0 is reserved for the master
611 Connect_send_IdEnumeration( 1 );
613 // Propagate IdRequest
616 Connect_send_IdRequest();
622 uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num )
624 dbug_print("IdEnumeration");
625 // Check the directionality
626 if ( uart_num == UART_Slave )
628 erro_print("Invalid IdEnumeration direction...");
634 // Send reponse back to master
635 Connect_send_IdReport( id );
637 // Propogate next Id if the connection is ok
638 if ( Connect_cableOkSlave )
640 Connect_send_IdEnumeration( id + 1 );
646 uint8_t Connect_receive_IdReport( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num )
648 dbug_print("IdReport");
649 // Check the directionality
650 if ( uart_num == UART_Master )
652 erro_print("Invalid IdRequest direction...");
655 // Track Id response if master
656 if ( Connect_master )
658 info_msg("Id Reported: ");
662 // Check if this is the highest ID
663 if ( id > Connect_maxId )
667 // Propagate id if yet another slave
670 Connect_send_IdReport( id );
676 // - Scan Code Variables -
677 TriggerGuide Connect_receive_ScanCodeBuffer;
678 uint8_t Connect_receive_ScanCodeBufferPos;
679 uint8_t Connect_receive_ScanCodeDeviceId;
681 uint8_t Connect_receive_ScanCode( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
683 // Check the directionality
684 if ( uart_num == UART_Master )
686 erro_print("Invalid ScanCode direction...");
689 // Master node, trigger scan codes
690 if ( Connect_master ) switch ( (*pending_bytes)-- )
692 // Byte count always starts at 0xFFFF
693 case 0xFFFF: // Device Id
694 Connect_receive_ScanCodeDeviceId = byte;
697 case 0xFFFE: // Number of TriggerGuides in bytes (byte * 3)
698 *pending_bytes = byte * sizeof( TriggerGuide );
699 Connect_receive_ScanCodeBufferPos = 0;
703 // Set the specific TriggerGuide entry
704 ((uint8_t*)&Connect_receive_ScanCodeBuffer)[ Connect_receive_ScanCodeBufferPos++ ] = byte;
706 // Reset the BufferPos if higher than sizeof TriggerGuide
707 // And send the TriggerGuide to the Macro Module
708 if ( Connect_receive_ScanCodeBufferPos >= sizeof( TriggerGuide ) )
710 Connect_receive_ScanCodeBufferPos = 0;
712 // Adjust ScanCode offset
713 if ( Connect_receive_ScanCodeDeviceId > 0 )
715 // Check if this node is too large
716 if ( Connect_receive_ScanCodeDeviceId >= InterconnectNodeMax )
718 warn_msg("Not enough interconnect layout nodes configured: ");
719 printHex( Connect_receive_ScanCodeDeviceId );
724 // This variable is in generatedKeymaps.h
725 extern uint8_t InterconnectOffsetList[];
726 Connect_receive_ScanCodeBuffer.scanCode = Connect_receive_ScanCodeBuffer.scanCode + InterconnectOffsetList[ Connect_receive_ScanCodeDeviceId - 1 ];
729 // ScanCode receive debug
733 printHex( Connect_receive_ScanCodeBuffer.type );
735 printHex( Connect_receive_ScanCodeBuffer.state );
737 printHex( Connect_receive_ScanCodeBuffer.scanCode );
741 // Send ScanCode to macro module
742 Macro_interconnectAdd( &Connect_receive_ScanCodeBuffer );
747 // Propagate ScanCode packet
748 else switch ( (*pending_bytes)-- )
750 // Byte count always starts at 0xFFFF
751 case 0xFFFF: // Device Id
753 Connect_receive_ScanCodeDeviceId = byte;
755 // Lock the master Tx buffer
756 uart_lockTx( UART_Master );
758 // Send header + Id byte
759 uint8_t header[] = { 0x16, 0x01, ScanCode, byte };
760 Connect_addBytes( header, sizeof( header ), UART_Master );
763 case 0xFFFE: // Number of TriggerGuides in bytes
764 *pending_bytes = byte * sizeof( TriggerGuide );
765 Connect_receive_ScanCodeBufferPos = 0;
768 Connect_addBytes( &byte, 1, UART_Master );
773 Connect_addBytes( &byte, 1, UART_Master );
775 // Unlock Tx Buffer after sending last byte
776 if ( *pending_bytes == 0 )
777 uart_unlockTx( UART_Master );
781 // Check whether the scan codes have finished sending
782 return *pending_bytes == 0 ? 1 : 0;
785 uint8_t Connect_receive_Animation( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
787 dbug_print("Animation");
793 // NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
794 uint16_t Connect_baud = UARTConnectBaud_define; // Max setting of 8191
795 uint16_t Connect_baudFine = UARTConnectBaudFine_define;
797 // Connect receive function lookup
798 void *Connect_receiveFunctions[] = {
799 Connect_receive_CableCheck,
800 Connect_receive_IdRequest,
801 Connect_receive_IdEnumeration,
802 Connect_receive_IdReport,
803 Connect_receive_ScanCode,
804 Connect_receive_Animation,
809 // ----- Interrupt Functions -----
811 // Master / UART0 ISR
812 void uart0_status_isr()
819 void uart1_status_isr()
827 // ----- Functions -----
829 // Resets the state of the UART buffers and state variables
832 // Rx Status Variables
833 uart0_rx_status = UARTStatus_Wait;
834 uart1_rx_status = UARTStatus_Wait;
835 uart0_rx_bytes_waiting = 0;
836 uart1_rx_bytes_waiting = 0;
840 // Tx Status Variables
841 uart0_tx_status = UARTStatus_Ready;
842 uart1_tx_status = UARTStatus_Ready;
844 // Ring Buffer Variables
845 uart0_buffer_head = 0;
846 uart0_buffer_tail = 0;
847 uart0_buffer_items = 0;
848 uart1_buffer_head = 0;
849 uart1_buffer_tail = 0;
850 uart1_buffer_items = 0;
854 // Setup connection to other side
855 // - Only supports a single slave and master
856 // - If USB has been initiallized at this point, this side is the master
857 // - If both sides assert master, flash error leds
858 void Connect_setup( uint8_t master )
860 // Indication that UARTs are not ready
861 uarts_configured = 0;
863 // Register Connect CLI dictionary
864 CLI_registerDictionary( uartConnectCLIDict, uartConnectCLIDictName );
867 Connect_master = master;
868 if ( Connect_master )
869 Connect_id = 0; // 0x00 is always the master Id
871 // Master / UART0 setup
872 // Slave / UART1 setup
873 // Setup the the UART interface for keyboard data input
874 SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
875 SIM_SCGC4 |= SIM_SCGC4_UART1; // Disable clock gating
877 // Pin Setup for UART0 / UART1
878 PORTA_PCR1 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); // RX Pin
879 PORTA_PCR2 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); // TX Pin
880 PORTE_PCR0 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); // RX Pin
881 PORTE_PCR1 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin
884 UART0_BDH = (uint8_t)(Connect_baud >> 8);
885 UART0_BDL = (uint8_t)Connect_baud;
886 UART0_C4 = Connect_baudFine;
887 UART1_BDH = (uint8_t)(Connect_baud >> 8);
888 UART1_BDL = (uint8_t)Connect_baud;
889 UART1_C4 = Connect_baudFine;
891 // 8 bit, Even Parity, Idle Character bit after stop
892 // NOTE: For 8 bit with Parity you must enable 9 bit transmission (pg. 1065)
893 // You only need to use UART0_D for 8 bit reading/writing though
894 // UART_C1_M UART_C1_PE UART_C1_PT UART_C1_ILT
895 UART0_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
896 UART1_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
898 // Number of bytes in FIFO before TX Interrupt
902 // Number of bytes in FIFO before RX Interrupt
906 // Enable TX and RX FIFOs
907 UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
908 UART1_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
910 // Reciever Inversion Disabled, LSBF
911 // UART_S2_RXINV UART_S2_MSBF
915 // Transmit Inversion Disabled
920 // TX Enabled, RX Enabled, RX Interrupt Enabled
921 // UART_C2_TE UART_C2_RE UART_C2_RIE
922 UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
923 UART1_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
925 // Add interrupts to the vector table
926 NVIC_ENABLE_IRQ( IRQ_UART0_STATUS );
927 NVIC_ENABLE_IRQ( IRQ_UART1_STATUS );
929 // UARTs are now ready to go
930 uarts_configured = 1;
932 // Reset the state of the UART variables
937 // Scan for updates in the master/slave
938 // - Interrupts will deal with most input functions
939 // - Used to send queries
940 // - SyncEvent is sent immediately once the current command is sent
941 // - SyncEvent is also blocking until sent
944 // Check if initially configured as a slave and usb comes up
945 // Then reconfigure as a master
946 if ( !Connect_master && Output_Available && !Connect_override )
948 Connect_setup( Output_Available );
951 // Limit how often we do cable checks
952 uint32_t time_compare = 0x7FF; // Must be all 1's, 0x3FF is valid, 0x4FF is not
953 uint32_t current_time = systick_millis_count;
954 if ( Connect_lastCheck != current_time
955 && ( current_time & time_compare ) == time_compare
958 // Make sure we don't double check if the clock speed is too high
959 Connect_lastCheck = current_time;
961 // Send a cable check command of 2 bytes
962 Connect_send_CableCheck( UARTConnectCableCheckLength_define );
964 // If this is a slave, and we don't have an id yeth
965 // Don't bother sending if there are cable issues
966 if ( !Connect_master && Connect_id == 0xFF && Connect_cableOkMaster )
968 Connect_send_IdRequest();
972 // Only process commands if uarts have been configured
973 if ( uarts_configured )
975 // Check if Tx Buffers are empty and the Tx Ring buffers have data to send
976 // This happens if there was previously nothing to send
977 if ( uart0_buffer_items > 0 && UART0_TCFIFO == 0 )
978 uart_fillTxFifo( 0 );
979 if ( uart1_buffer_items > 0 && UART1_TCFIFO == 0 )
980 uart_fillTxFifo( 1 );
986 // ----- CLI Command Functions -----
988 void cliFunc_connectCmd( char* args )
990 // Parse number from argument
991 // NOTE: Only first argument is used
994 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
998 switch ( numToInt( &arg1Ptr[0] ) )
1001 Connect_send_CableCheck( UARTConnectCableCheckLength_define );
1005 Connect_send_IdRequest();
1009 Connect_send_IdEnumeration( 5 );
1013 Connect_send_IdReport( 8 );
1018 TriggerGuide scanCodes[] = { { 0x00, 0x01, 0x05 }, { 0x00, 0x03, 0x16 } };
1019 Connect_send_ScanCode( 10, scanCodes, 2 );
1025 case RemoteCapability:
1042 void cliFunc_connectDbg( char* args )
1045 info_msg("Connect Debug Mode Toggle");
1046 Connect_debug = !Connect_debug;
1049 void cliFunc_connectIdl( char* args )
1051 // Parse number from argument
1052 // NOTE: Only first argument is used
1055 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
1058 info_msg("Sending Sync Idles...");
1060 uint8_t count = numToInt( &arg1Ptr[0] );
1061 // Default to 2 idles
1065 Connect_send_Idle( count );
1068 void cliFunc_connectLst( char* args )
1070 const char *Command_strs[] = {
1083 info_msg("List of UARTConnect commands");
1084 for ( uint8_t cmd = 0; cmd < Command_TOP; cmd++ )
1089 dPrint( (char*)Command_strs[ cmd ] );
1093 void cliFunc_connectMst( char* args )
1095 // Parse number from argument
1096 // NOTE: Only first argument is used
1099 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
1104 Connect_override = 1;
1106 switch ( arg1Ptr[0] )
1111 Connect_override = 0;
1114 info_msg("Setting device as slave.");
1122 info_msg("Setting device as master.");
1129 void cliFunc_connectRst( char* args )
1132 info_msg("Resetting UARTConnect state...");
1139 void cliFunc_connectSts( char* args )
1142 info_msg("UARTConnect Status");
1143 print( NL "Device Type:\t" );
1144 print( Connect_master ? "Master" : "Slave" );
1145 print( NL "Device Id:\t" );
1146 printHex( Connect_id );
1147 print( NL "Max Id:\t" );
1148 printHex( Connect_maxId );
1149 print( NL "Master <=" NL "\tStatus:\t");
1150 printHex( Connect_cableOkMaster );
1151 print( NL "\tFaults:\t");
1152 printHex32( Connect_cableFaultsMaster );
1154 printHex32( Connect_cableChecksMaster );
1155 print( NL "\tRx:\t");
1156 printHex( uart1_rx_status );
1157 print( NL "\tTx:\t");
1158 printHex( uart1_tx_status );
1159 print( NL "Slave <=" NL "\tStatus:\t");
1160 printHex( Connect_cableOkSlave );
1161 print( NL "\tFaults:\t");
1162 printHex32( Connect_cableFaultsSlave );
1164 printHex32( Connect_cableChecksSlave );
1165 print( NL "\tRx:\t");
1166 printHex( uart0_rx_status );
1167 print( NL "\tTx:\t");
1168 printHex( uart0_tx_status );