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