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