comparison Scan/UARTConnect/connect_scan.c @ 307:ecd2ae35d25c

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