Kiibohd Controller
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

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