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