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