]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Scan/UARTConnect/connect_scan.c
UARTConnect enumeration working!
[kiibohd-controller.git] / Scan / UARTConnect / connect_scan.c
1 /* Copyright (C) 2014-2015 by Jacob Alexander
2  *
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.
7  *
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.
12  *
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/>.
15  */
16
17 // ----- Includes -----
18
19 // Compiler Includes
20 #include <Lib/ScanLib.h>
21
22 // Project Includes
23 #include <cli.h>
24 #include <led.h>
25 #include <print.h>
26 #include <macro.h>
27
28 // Local Includes
29 #include "connect_scan.h"
30
31
32
33 // ----- Macros -----
34
35 // Macro for adding to each uart Tx ring buffer
36 #define uart_addTxBuffer( uartNum ) \
37 case uartNum: \
38         while ( uart##uartNum##_buffer_items + count > uart_buffer_size ) \
39         { \
40                 warn_msg("Too much data to send on UART0, waiting..."); \
41                 delay( 1 ); \
42         } \
43         for ( uint8_t c = 0; c < count; c++ ) \
44         { \
45                 if ( Connect_debug ) \
46                 { \
47                         printHex( buffer[ c ] ); \
48                         print( " +" #uartNum NL ); \
49                 } \
50                 uart##uartNum##_buffer[ uart##uartNum##_buffer_tail++ ] = buffer[ c ]; \
51                 uart##uartNum##_buffer_items++; \
52                 if ( uart##uartNum##_buffer_tail >= uart_buffer_size ) \
53                         uart##uartNum##_buffer_tail = 0; \
54                 if ( uart##uartNum##_buffer_head == uart##uartNum##_buffer_tail ) \
55                         uart##uartNum##_buffer_head++; \
56                 if ( uart##uartNum##_buffer_head >= uart_buffer_size ) \
57                         uart##uartNum##_buffer_head = 0; \
58         } \
59         break
60
61 // Macro for popping from Tx ring buffer
62 #define uart_fillTxFifo( uartNum ) \
63 { \
64         uint8_t fifoSize = ( ( UART##uartNum##_PFIFO & UART_PFIFO_TXFIFOSIZE ) >> 2 ); \
65         if ( fifoSize == 0 ) \
66                 fifoSize = 1; \
67         while ( UART##uartNum##_TCFIFO < fifoSize ) \
68         { \
69                 if ( uart##uartNum##_buffer_items == 0 ) \
70                         break; \
71                 UART##uartNum##_D = uart##uartNum##_buffer[ uart##uartNum##_buffer_head++ ]; \
72                 uart##uartNum##_buffer_items--; \
73                 if ( uart##uartNum##_buffer_head >= uart_buffer_size ) \
74                         uart##uartNum##_buffer_head = 0; \
75         } \
76 }
77
78 // Macro for processing UART Rx
79 #define uart_processRx( uartNum ) \
80 { \
81         if ( !( UART##uartNum##_S1 & UART_S1_RDRF ) ) \
82                 return; \
83         uint8_t available = UART##uartNum##_RCFIFO; \
84         if ( available == 0 ) \
85         { \
86                 available = UART##uartNum##_D; \
87                 UART##uartNum##_CFIFO = UART_CFIFO_RXFLUSH; \
88                 return; \
89         } \
90         while ( available-- > 0 ) \
91         { \
92                 uint8_t byteRead = UART##uartNum##_D; \
93                 if ( Connect_debug ) \
94                 { \
95                         printHex( byteRead ); \
96                         print( "(" ); \
97                         printInt8( available ); \
98                         print( ") <-" ); \
99                 } \
100                 switch ( uart##uartNum##_rx_status ) \
101                 { \
102                 case UARTStatus_Wait: \
103                         if ( Connect_debug ) \
104                         { \
105                                 print(" SYN "); \
106                         } \
107                         uart##uartNum##_rx_status = byteRead == 0x16 ? UARTStatus_SYN : UARTStatus_Wait; \
108                         break; \
109                 case UARTStatus_SYN: \
110                         if ( Connect_debug ) \
111                         { \
112                                 print(" SOH "); \
113                         } \
114                         uart##uartNum##_rx_status = byteRead == 0x01 ? UARTStatus_SOH : UARTStatus_Wait; \
115                         break; \
116                 case UARTStatus_SOH: \
117                 { \
118                         if ( Connect_debug ) \
119                         { \
120                                 print(" CMD "); \
121                         } \
122                         uint8_t byte = byteRead; \
123                         if ( byte <= Animation ) \
124                         { \
125                                 uart##uartNum##_rx_status = UARTStatus_Command; \
126                                 uart##uartNum##_rx_command = byte; \
127                                 uart##uartNum##_rx_bytes_waiting = 0xFFFF; \
128                         } \
129                         else \
130                         { \
131                                 uart##uartNum##_rx_status = UARTStatus_Wait; \
132                         } \
133                         switch ( uart##uartNum##_rx_command ) \
134                         { \
135                         case IdRequest: \
136                                 Connect_receive_IdRequest( 0, (uint16_t*)&uart##uartNum##_rx_bytes_waiting, uartNum ); \
137                                 uart##uartNum##_rx_status = UARTStatus_Wait; \
138                                 break; \
139                         default: \
140                                 if ( Connect_debug ) \
141                                 { \
142                                         print("###"); \
143                                 } \
144                                 break; \
145                         } \
146                         break; \
147                 } \
148                 case UARTStatus_Command: \
149                 { \
150                         if ( Connect_debug ) \
151                         { \
152                                 print(" CMD "); \
153                         } \
154                         uint8_t (*rcvFunc)(uint8_t, uint16_t(*), uint8_t) = (uint8_t(*)(uint8_t, uint16_t(*), uint8_t))(Connect_receiveFunctions[ uart##uartNum##_rx_command ]); \
155                         if ( rcvFunc( byteRead, (uint16_t*)&uart##uartNum##_rx_bytes_waiting, uartNum ) ) \
156                                 uart##uartNum##_rx_status = UARTStatus_Wait; \
157                         break; \
158                 } \
159                 default: \
160                         erro_msg("Invalid UARTStatus..."); \
161                         uart##uartNum##_rx_status = UARTStatus_Wait; \
162                         available++; \
163                         continue; \
164                 } \
165                 if ( Connect_debug ) \
166                 { \
167                         print( NL ); \
168                 } \
169         } \
170 }
171
172 // Macros for locking/unlock Tx buffers
173 #define uart_lockTx( uartNum ) \
174 { \
175         while ( uart##uartNum##_tx_status == UARTStatus_Wait ); \
176         uart##uartNum##_tx_status = UARTStatus_Wait; \
177 }
178
179 #define uart_unlockTx( uartNum ) \
180 { \
181         uart##uartNum##_tx_status = UARTStatus_Ready; \
182 }
183
184
185
186 // ----- Function Declarations -----
187
188 // CLI Functions
189 void cliFunc_connectCmd ( char *args );
190 void cliFunc_connectIdl ( char *args );
191 void cliFunc_connectMst ( char *args );
192 void cliFunc_connectRst ( char *args );
193 void cliFunc_connectSts ( char *args );
194
195
196
197 // ----- Variables -----
198
199 // Connect Module command dictionary
200 CLIDict_Entry( connectCmd,  "Sends a command via UART Connect, first arg is which uart, next arg is the command, rest are the arguments." );
201 CLIDict_Entry( connectIdl,  "Sends N number of Idle commands, 2 is the default value, and should be sufficient in most cases." );
202 CLIDict_Entry( connectMst,  "Sets the device as master. Use argument of s to set as slave." );
203 CLIDict_Entry( connectRst,  "Resets both Rx and Tx connect buffers and state variables." );
204 CLIDict_Entry( connectSts,  "UARTConnect status." );
205 CLIDict_Def( uartConnectCLIDict, "UARTConnect Module Commands" ) = {
206         CLIDict_Item( connectCmd ),
207         CLIDict_Item( connectIdl ),
208         CLIDict_Item( connectMst ),
209         CLIDict_Item( connectRst ),
210         CLIDict_Item( connectSts ),
211         { 0, 0, 0 } // Null entry for dictionary end
212 };
213
214
215 // -- Connect Device Id Variables --
216 uint8_t Connect_id = 255; // Invalid, unset
217 uint8_t Connect_master = 0;
218
219
220 // -- Control Variables --
221 uint32_t Connect_lastCheck = 0; // Cable Check scheduler
222 uint8_t Connect_debug = 0; // Set 1 for debug
223
224
225 // -- Rx Status Variables --
226
227 volatile UARTStatus uart0_rx_status;
228 volatile UARTStatus uart1_rx_status;
229 volatile uint16_t uart0_rx_bytes_waiting;
230 volatile uint16_t uart1_rx_bytes_waiting;
231 volatile Command uart0_rx_command;
232 volatile Command uart1_rx_command;
233
234
235 // -- Tx Status Variables --
236
237 volatile UARTStatus uart0_tx_status;
238 volatile UARTStatus uart1_tx_status;
239
240
241 // -- Ring Buffer Variables --
242
243 #define uart_buffer_size UARTConnectBufSize_define
244 volatile uint8_t uart0_buffer_head;
245 volatile uint8_t uart0_buffer_tail;
246 volatile uint8_t uart0_buffer_items;
247 volatile uint8_t uart0_buffer[uart_buffer_size];
248 volatile uint8_t uart1_buffer_head;
249 volatile uint8_t uart1_buffer_tail;
250 volatile uint8_t uart1_buffer_items;
251 volatile uint8_t uart1_buffer[uart_buffer_size];
252
253 volatile uint8_t uarts_configured = 0;
254
255
256 // -- Ring Buffer Convenience Functions --
257
258 void Connect_addBytes( uint8_t *buffer, uint8_t count, uint8_t uart )
259 {
260         // Too big to fit into buffer
261         if ( count > uart_buffer_size )
262         {
263                 erro_msg("Too big of a command to fit into the buffer...");
264                 return;
265         }
266
267         // Choose the uart
268         switch ( uart )
269         {
270         uart_addTxBuffer( 0 );
271         uart_addTxBuffer( 1 );
272         default:
273                 erro_msg("Invalid UART to send from...");
274                 break;
275         }
276 }
277
278
279 // -- Connect send functions --
280
281 // patternLen defines how many bytes should the incrementing pattern have
282 void Connect_send_CableCheck( uint8_t patternLen )
283 {
284         // Wait until the Tx buffers are ready, then lock them
285         uart_lockTx( 0 );
286         uart_lockTx( 1 );
287
288         // Prepare header
289         uint8_t header[] = { 0x16, 0x01, CableCheck, patternLen };
290
291         // Send header
292         Connect_addBytes( header, sizeof( header ), 1 ); // Master
293         Connect_addBytes( header, sizeof( header ), 0 ); // Slave
294
295         // Send 0xD2 (11010010) for each argument
296         uint8_t value = 0xD2;
297         for ( uint8_t c = 0; c < patternLen; c++ )
298         {
299                 Connect_addBytes( &value, 1, 1 ); // Master
300                 Connect_addBytes( &value, 1, 0 ); // Slave
301         }
302
303         // Release Tx buffers
304         uart_unlockTx( 0 );
305         uart_unlockTx( 1 );
306 }
307
308 void Connect_send_IdRequest()
309 {
310         // Lock master bound Tx
311         uart_lockTx( 1 );
312
313         // Prepare header
314         uint8_t header[] = { 0x16, 0x01, IdRequest };
315
316         // Send header
317         Connect_addBytes( header, sizeof( header ), 1 ); // Master
318
319         // Unlock Tx
320         uart_unlockTx( 1 );
321 }
322
323 // id is the value the next slave should enumerate as
324 void Connect_send_IdEnumeration( uint8_t id )
325 {
326         // Lock slave bound Tx
327         uart_lockTx( 0 );
328
329         // Prepare header
330         uint8_t header[] = { 0x16, 0x01, IdEnumeration, id };
331
332         // Send header
333         Connect_addBytes( header, sizeof( header ), 0 ); // Slave
334
335         // Unlock Tx
336         uart_unlockTx( 0 );
337 }
338
339 // id is the currently assigned id to the slave
340 void Connect_send_IdReport( uint8_t id )
341 {
342         // Lock master bound Tx
343         uart_lockTx( 1 );
344
345         // Prepare header
346         uint8_t header[] = { 0x16, 0x01, IdReport, id };
347
348         // Send header
349         Connect_addBytes( header, sizeof( header ), 1 ); // Master
350
351         // Unlock Tx
352         uart_unlockTx( 1 );
353 }
354
355 // id is the currently assigned id to the slave
356 // scanCodeStateList is an array of [scancode, state]'s (8 bit values)
357 // numScanCodes is the number of scan codes to parse from array
358 void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes )
359 {
360         // Lock master bound Tx
361         uart_lockTx( 1 );
362
363         // Prepare header
364         uint8_t header[] = { 0x16, 0x01, ScanCode, id, numScanCodes };
365
366         // Send header
367         Connect_addBytes( header, sizeof( header ), 1 ); // Master
368
369         // Send each of the scan codes
370         Connect_addBytes( (uint8_t*)scanCodeStateList, numScanCodes * TriggerGuideSize, 1 ); // Master
371
372         // Unlock Tx
373         uart_unlockTx( 1 );
374 }
375
376 // id is the currently assigned id to the slave
377 // paramList is an array of [param, value]'s (8 bit values)
378 // numParams is the number of params to parse from the array
379 void Connect_send_Animation( uint8_t id, uint8_t *paramList, uint8_t numParams )
380 {
381         // Lock slave bound Tx
382         uart_lockTx( 0 );
383
384         // Prepare header
385         uint8_t header[] = { 0x16, 0x01, Animation, id, numParams };
386
387         // Send header
388         Connect_addBytes( header, sizeof( header ), 0 ); // Slave
389
390         // Send each of the scan codes
391         Connect_addBytes( paramList, numParams, 0 ); // Slave
392
393         // Unlock Tx
394         uart_unlockTx( 0 );
395 }
396
397 void Connect_send_Idle( uint8_t num )
398 {
399         // Wait until the Tx buffers are ready, then lock them
400         uart_lockTx( 0 );
401         uart_lockTx( 1 );
402
403         // Send n number of idles to reset link status (if in a bad state)
404         uint8_t value = 0x16;
405         for ( uint8_t c = 0; c < num; c++ )
406         {
407                 Connect_addBytes( &value, 1, 1 ); // Master
408                 Connect_addBytes( &value, 1, 0 ); // Slave
409         }
410
411         // Release Tx buffers
412         uart_unlockTx( 0 );
413         uart_unlockTx( 1 );
414 }
415
416
417 // -- Connect receive functions --
418
419 // - Cable Check variables -
420 uint32_t Connect_cableFaultsMaster = 0;
421 uint32_t Connect_cableFaultsSlave = 0;
422 uint8_t  Connect_cableOkMaster = 0;
423 uint8_t  Connect_cableOkSlave = 0;
424
425 uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8_t to_master )
426 {
427         // Check if this is the first byte
428         if ( *pending_bytes == 0xFFFF )
429         {
430                 *pending_bytes = byte;
431
432                 if ( Connect_debug )
433                 {
434                         dbug_msg("PENDING SET -> ");
435                         printHex( byte );
436                         print(" ");
437                         printHex( *pending_bytes );
438                         print( NL );
439                 }
440         }
441         // Verify byte
442         else
443         {
444                 (*pending_bytes)--;
445
446                 // The argument bytes are always 0xD2 (11010010)
447                 if ( byte != 0xD2 )
448                 {
449                         warn_print("Cable Fault!");
450
451                         // Check which side of the chain
452                         if ( to_master )
453                         {
454                                 Connect_cableFaultsMaster++;
455                                 Connect_cableOkMaster = 0;
456                                 print(" Master ");
457                         }
458                         else
459                         {
460                                 Connect_cableFaultsSlave++;
461                                 Connect_cableOkSlave = 0;
462                                 print(" Slave ");
463                         }
464                         printHex( byte );
465                         print( NL );
466
467                         // Signal that the command should wait for a SYN again
468                         return 1;
469                 }
470         }
471
472         // If cable check was successful, set cable ok
473         if ( *pending_bytes == 0 )
474         {
475                 if ( to_master )
476                 {
477                         Connect_cableOkMaster = 1;
478                 }
479                 else
480                 {
481                         Connect_cableOkSlave = 1;
482                 }
483         }
484
485         if ( Connect_debug )
486         {
487                 dbug_msg("CABLECHECK RECEIVE - ");
488                 printHex( byte );
489                 print(" ");
490                 printHex( *pending_bytes );
491                 print( NL );
492         }
493
494         // Check whether the cable check has finished
495         return *pending_bytes == 0 ? 1 : 0;
496 }
497
498 uint8_t Connect_receive_IdRequest( uint8_t byte, uint16_t *pending_bytes, uint8_t to_master )
499 {
500         dbug_print("IdRequest");
501         // Check the directionality
502         if ( to_master )
503         {
504                 erro_print("Invalid IdRequest direction...");
505         }
506
507         // Check if master, begin IdEnumeration
508         if ( Connect_master )
509         {
510                 // The first device is always id 1
511                 // Id 0 is reserved for the master
512                 Connect_send_IdEnumeration( 1 );
513         }
514         // Propagate IdRequest
515         else
516         {
517                 Connect_send_IdRequest();
518         }
519
520         return 1;
521 }
522
523 uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint8_t to_master )
524 {
525         dbug_print("IdEnumeration");
526         // Check the directionality
527         if ( !to_master )
528         {
529                 erro_print("Invalid IdEnumeration direction...");
530         }
531
532         // Set the device id
533         Connect_id = id;
534
535         // Send reponse back to master
536         Connect_send_IdReport( id );
537
538         // Propogate next Id if the connection is ok
539         if ( Connect_cableOkSlave )
540         {
541                 Connect_send_IdEnumeration( id + 1 );
542         }
543
544         return 1;
545 }
546
547 uint8_t Connect_receive_IdReport( uint8_t id, uint16_t *pending_bytes, uint8_t to_master )
548 {
549         dbug_print("IdReport");
550         // Check the directionality
551         if ( to_master )
552         {
553                 erro_print("Invalid IdRequest direction...");
554         }
555
556         // Track Id response if master
557         if ( Connect_master )
558         {
559                 // TODO, setup id's
560                 info_msg("Id Reported: ");
561                 printHex( id );
562                 print( NL );
563                 return 1;
564         }
565         // Propagate id if yet another slave
566         else
567         {
568                 Connect_send_IdReport( id );
569         }
570
571         return 1;
572 }
573
574 // - Scan Code Variables -
575 TriggerGuide Connect_receive_ScanCodeBuffer;
576 uint8_t Connect_receive_ScanCodeBufferPos;
577 uint8_t Connect_receive_ScanCodeDeviceId;
578
579 uint8_t Connect_receive_ScanCode( uint8_t byte, uint16_t *pending_bytes, uint8_t to_master )
580 {
581         dbug_print("ScanCode");
582         // Check the directionality
583         if ( !to_master )
584         {
585                 erro_print("Invalid ScanCode direction...");
586         }
587
588         // Master node, trigger scan codes
589         if ( Connect_master ) switch ( (*pending_bytes)-- )
590         {
591         case 0xFFFF: // Device Id
592                 Connect_receive_ScanCodeDeviceId = byte;
593                 break;
594
595         case 0xFFFE: // Number of TriggerGuides in bytes (byte * 3)
596                 *pending_bytes = byte * 3;
597                 Connect_receive_ScanCodeBufferPos = 0;
598                 break;
599
600         default:
601                 // Set the specific TriggerGuide entry
602                 ((uint8_t*)&Connect_receive_ScanCodeBuffer)[ Connect_receive_ScanCodeBufferPos++ ] = byte;
603
604                 // Reset the BufferPos if higher than 3
605                 // And send the TriggerGuide to the Macro Module
606                 if ( Connect_receive_ScanCodeBufferPos > 3 )
607                 {
608                         Connect_receive_ScanCodeBufferPos = 0;
609                         Macro_triggerState( &Connect_receive_ScanCodeBuffer, 1 );
610                 }
611
612                 break;
613         }
614         // Propagate ScanCode packet
615         else switch ( (*pending_bytes)-- )
616         {
617         case 0xFFFF: // Device Id
618         {
619                 Connect_receive_ScanCodeDeviceId = byte;
620
621                 // Lock the master Tx buffer
622                 uart_lockTx( 1 );
623
624                 // Send header + Id byte
625                 uint8_t header[] = { 0x16, 0x01, ScanCode, byte };
626                 Connect_addBytes( header, sizeof( header ), 1 ); // Master
627                 break;
628         }
629         case 0xFFFE: // Number of TriggerGuides in bytes (byte * 3)
630                 *pending_bytes = byte * 3;
631                 Connect_receive_ScanCodeBufferPos = 0;
632
633                 // Pass through byte
634                 Connect_addBytes( &byte, 1, 1 ); // Master
635                 break;
636
637         default:
638                 // Pass through byte
639                 Connect_addBytes( &byte, 1, 1 ); // Master
640
641                 // Unlock Tx Buffer after sending last byte
642                 if ( *pending_bytes == 0 )
643                         uart_unlockTx( 1 );
644                 break;
645         }
646
647         // Check whether the scan codes have finished sending
648         return *pending_bytes == 0 ? 1 : 0;
649 }
650
651 uint8_t Connect_receive_Animation( uint8_t byte, uint16_t *pending_bytes, uint8_t to_master )
652 {
653         dbug_print("Animation");
654         return 1;
655 }
656
657
658 // Baud Rate
659 // NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
660 uint16_t Connect_baud = UARTConnectBaud_define; // Max setting of 8191
661 uint16_t Connect_baudFine = UARTConnectBaudFine_define;
662
663 // Connect receive function lookup
664 void *Connect_receiveFunctions[] = {
665         Connect_receive_CableCheck,
666         Connect_receive_IdRequest,
667         Connect_receive_IdEnumeration,
668         Connect_receive_IdReport,
669         Connect_receive_ScanCode,
670         Connect_receive_Animation,
671 };
672
673
674
675 // ----- Interrupt Functions -----
676
677 // Master / UART0 ISR
678 void uart0_status_isr()
679 {
680         // Process Rx buffer
681         uart_processRx( 0 );
682 }
683
684 // Slave / UART1 ISR
685 void uart1_status_isr()
686 {
687         // Process Rx buffer
688         uart_processRx( 1 );
689 }
690
691
692
693 // ----- Functions -----
694
695 // Resets the state of the UART buffers and state variables
696 void Connect_reset()
697 {
698         // Rx Status Variables
699         uart0_rx_status = UARTStatus_Wait;
700         uart1_rx_status = UARTStatus_Wait;
701         uart0_rx_bytes_waiting = 0;
702         uart1_rx_bytes_waiting = 0;
703
704         // Tx Status Variables
705         uart0_tx_status = UARTStatus_Ready;
706         uart1_tx_status = UARTStatus_Ready;
707
708         // Ring Buffer Variables
709         uart0_buffer_head = 0;
710         uart0_buffer_tail = 0;
711         uart0_buffer_items = 0;
712         uart1_buffer_head = 0;
713         uart1_buffer_tail = 0;
714         uart1_buffer_items = 0;
715 }
716
717
718 // Setup connection to other side
719 // - Only supports a single slave and master
720 // - If USB has been initiallized at this point, this side is the master
721 // - If both sides assert master, flash error leds
722 void Connect_setup( uint8_t master )
723 {
724         // Indication that UARTs are not ready
725         uarts_configured = 0;
726
727         // Register Connect CLI dictionary
728         CLI_registerDictionary( uartConnectCLIDict, uartConnectCLIDictName );
729
730         // Check if master
731         Connect_master = master;
732         if ( Connect_master )
733                 Connect_id = 0; // 0x00 is always the master Id
734
735         // Master / UART0 setup
736         // Slave  / UART1 setup
737         // Setup the the UART interface for keyboard data input
738         SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
739         SIM_SCGC4 |= SIM_SCGC4_UART1; // Disable clock gating
740
741         // Pin Setup for UART0 / UART1
742         PORTA_PCR1 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); // RX Pin
743         PORTA_PCR2 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); // TX Pin
744         PORTE_PCR0 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); // RX Pin
745         PORTE_PCR1 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin
746
747         // Baud Rate setting
748         UART0_BDH = (uint8_t)(Connect_baud >> 8);
749         UART0_BDL = (uint8_t)Connect_baud;
750         UART0_C4  = Connect_baudFine;
751         UART1_BDH = (uint8_t)(Connect_baud >> 8);
752         UART1_BDL = (uint8_t)Connect_baud;
753         UART1_C4  = Connect_baudFine;
754
755         // 8 bit, Even Parity, Idle Character bit after stop
756         // NOTE: For 8 bit with Parity you must enable 9 bit transmission (pg. 1065)
757         //       You only need to use UART0_D for 8 bit reading/writing though
758         // UART_C1_M UART_C1_PE UART_C1_PT UART_C1_ILT
759         UART0_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
760         UART1_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
761
762         // Number of bytes in FIFO before TX Interrupt
763         // TODO Set 0
764         UART0_TWFIFO = 1;
765         UART1_TWFIFO = 1;
766
767         // Number of bytes in FIFO before RX Interrupt
768         UART0_RWFIFO = 1;
769         UART1_RWFIFO = 1;
770
771         // Enable TX and RX FIFOs
772         UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
773         UART1_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
774
775         // Reciever Inversion Disabled, LSBF
776         // UART_S2_RXINV UART_S2_MSBF
777         UART0_S2 |= 0x00;
778         UART1_S2 |= 0x00;
779
780         // Transmit Inversion Disabled
781         // UART_C3_TXINV
782         UART0_C3 |= 0x00;
783         UART1_C3 |= 0x00;
784
785         // TX Enabled, RX Enabled, RX Interrupt Enabled
786         // UART_C2_TE UART_C2_RE UART_C2_RIE
787         UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
788         UART1_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
789
790         // Add interrupts to the vector table
791         NVIC_ENABLE_IRQ( IRQ_UART0_STATUS );
792         NVIC_ENABLE_IRQ( IRQ_UART1_STATUS );
793
794         // UARTs are now ready to go
795         uarts_configured = 1;
796
797         // Reset the state of the UART variables
798         Connect_reset();
799 }
800
801
802 // Scan for updates in the master/slave
803 // - Interrupts will deal with most input functions
804 // - Used to send queries
805 // - SyncEvent is sent immediately once the current command is sent
806 // - SyncEvent is also blocking until sent
807 void Connect_scan()
808 {
809         // Check if initially configured as a slave and usb comes up
810         // Then reconfigure as a master
811         if ( !Connect_master && Output_Available )
812         {
813                 Connect_setup( Output_Available );
814         }
815
816         // Limit how often we do cable checks
817         uint32_t time_compare = 0x7FF; // Must be all 1's, 0x3FF is valid, 0x4FF is not
818         uint32_t current_time = systick_millis_count;
819         if ( Connect_lastCheck != current_time
820                 && ( current_time & time_compare ) == time_compare
821         )
822         {
823                 // Make sure we don't double check if the clock speed is too high
824                 Connect_lastCheck = current_time;
825
826                 // Send a cable check command of 2 bytes
827                 Connect_send_CableCheck( UARTConnectCableCheckLength_define );
828
829                 // If this is a slave, and we don't have an id yeth
830                 // Don't bother sending if there are cable issues
831                 if ( !Connect_master && Connect_id == 0xFF && Connect_cableOkMaster )
832                 {
833                         Connect_send_IdRequest();
834                 }
835         }
836
837         // Only process commands if uarts have been configured
838         if ( uarts_configured )
839         {
840                 // Check if Tx Buffers are empty and the Tx Ring buffers have data to send
841                 // This happens if there was previously nothing to send
842                 if ( uart0_buffer_items > 0 && UART0_TCFIFO == 0 )
843                         uart_fillTxFifo( 0 );
844                 if ( uart1_buffer_items > 0 && UART1_TCFIFO == 0 )
845                         uart_fillTxFifo( 1 );
846         }
847 }
848
849
850
851 // ----- CLI Command Functions -----
852
853 void cliFunc_connectCmd( char* args )
854 {
855         // Parse number from argument
856         //  NOTE: Only first argument is used
857         char* arg1Ptr;
858         char* arg2Ptr;
859         CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
860
861         print( NL );
862
863         switch ( numToInt( &arg1Ptr[0] ) )
864         {
865         case CableCheck:
866                 Connect_send_CableCheck( UARTConnectCableCheckLength_define );
867                 break;
868
869         case IdRequest:
870                 Connect_send_IdRequest();
871                 break;
872
873         case IdEnumeration:
874                 Connect_send_IdEnumeration( 5 );
875                 break;
876
877         case IdReport:
878                 Connect_send_IdReport( 8 );
879                 break;
880
881         case ScanCode:
882         {
883                 TriggerGuide scanCodes[] = { { 0x00, 0x01, 0x05 }, { 0x00, 0x03, 0x16 } };
884                 Connect_send_ScanCode( 10, scanCodes, 2 );
885                 break;
886         }
887         case Animation:
888         default:
889                 break;
890         }
891 }
892
893 void cliFunc_connectIdl( char* args )
894 {
895         // Parse number from argument
896         //  NOTE: Only first argument is used
897         char* arg1Ptr;
898         char* arg2Ptr;
899         CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
900
901         print( NL );
902         info_msg("Sending Sync Idles...");
903
904         uint8_t count = numToInt( &arg1Ptr[0] );
905         // Default to 2 idles
906         if ( count == 0 )
907                 count = 2;
908
909         Connect_send_Idle( count );
910 }
911
912 void cliFunc_connectMst( char* args )
913 {
914         // Parse number from argument
915         //  NOTE: Only first argument is used
916         char* arg1Ptr;
917         char* arg2Ptr;
918         CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
919
920         print( NL );
921
922         switch ( arg1Ptr[0] )
923         {
924         case 's':
925         case 'S':
926                 info_msg("Setting device as slave.");
927                 Connect_master = 0;
928                 Connect_id = 0xFF;
929                 break;
930
931         case 'm':
932         case 'M':
933         default:
934                 info_msg("Setting device as master.");
935                 Connect_master = 1;
936                 Connect_id = 0;
937                 break;
938         }
939 }
940
941 void cliFunc_connectRst( char* args )
942 {
943         print( NL );
944         info_msg("Resetting UARTConnect state...");
945         Connect_reset();
946
947         // TODO - Argument for re-sync
948 }
949
950 void cliFunc_connectSts( char* args )
951 {
952         print( NL );
953         info_msg("UARTConnect Status");
954         print( NL "Device Type:\t" );
955         print( Connect_master ? "Master" : "Slave" );
956         print( NL "Device Id:\t" );
957         printHex( Connect_id );
958         print( NL "Master <=" NL "\tStatus:\t");
959         printHex( Connect_cableOkMaster );
960         print( NL "\tFaults:\t");
961         printHex( Connect_cableFaultsMaster );
962         print( NL "\tRx:\t");
963         printHex( uart1_rx_status );
964         print( NL "\tTx:\t");
965         printHex( uart1_tx_status );
966         print( NL "Slave <=" NL "\tStatus:\t");
967         printHex( Connect_cableOkSlave );
968         print( NL "\tFaults:\t");
969         printHex( Connect_cableFaultsSlave );
970         print( NL "\tRx:\t");
971         printHex( uart0_rx_status );
972         print( NL "\tTx:\t");
973         printHex( uart0_tx_status );
974 }
975