Kiibohd Controller
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

connect_scan.c 25KB

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