Mercurial > louis > kiibohd-controller
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 |