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.

macro.c 30KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. /* Copyright (C) 2014 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/MacroLib.h>
  19. // Project Includes
  20. #include <cli.h>
  21. #include <led.h>
  22. #include <print.h>
  23. #include <scan_loop.h>
  24. #include <output_com.h>
  25. // Keymaps
  26. #include "usb_hid.h"
  27. #include <defaultMap.h>
  28. #include "generatedKeymap.h" // TODO Use actual generated version
  29. // Local Includes
  30. #include "macro.h"
  31. // ----- Function Declarations -----
  32. void cliFunc_capList ( char* args );
  33. void cliFunc_capSelect ( char* args );
  34. void cliFunc_keyPress ( char* args );
  35. void cliFunc_keyRelease( char* args );
  36. void cliFunc_layerList ( char* args );
  37. void cliFunc_layerState( char* args );
  38. void cliFunc_macroDebug( char* args );
  39. void cliFunc_macroList ( char* args );
  40. void cliFunc_macroProc ( char* args );
  41. void cliFunc_macroShow ( char* args );
  42. void cliFunc_macroStep ( char* args );
  43. // ----- Enums -----
  44. // Bit positions are important, passes (correct key) always trump incorrect key votes
  45. typedef enum TriggerMacroVote {
  46. TriggerMacroVote_Release = 0x8, // Correct key
  47. TriggerMacroVote_PassRelease = 0xC, // Correct key (both pass and release)
  48. TriggerMacroVote_Pass = 0x4, // Correct key
  49. TriggerMacroVote_DoNothing = 0x2, // Incorrect key
  50. TriggerMacroVote_Fail = 0x1, // Incorrect key
  51. TriggerMacroVote_Invalid = 0x0, // Invalid state
  52. } TriggerMacroVote;
  53. typedef enum TriggerMacroEval {
  54. TriggerMacroEval_DoNothing,
  55. TriggerMacroEval_DoResult,
  56. TriggerMacroEval_DoResultAndRemove,
  57. TriggerMacroEval_Remove,
  58. } TriggerMacroEval;
  59. // ----- Variables -----
  60. // Macro Module command dictionary
  61. char* macroCLIDictName = "Macro Module Commands";
  62. CLIDictItem macroCLIDict[] = {
  63. { "capList", "Prints an indexed list of all non USB keycode capabilities.", cliFunc_capList },
  64. { "capSelect", "Triggers the specified capabilities. First two args are state and stateType." NL "\t\t\033[35mK11\033[0m Keyboard Capability 0x0B", cliFunc_capSelect },
  65. { "keyPress", "Send key-presses to the macro module. Held until released. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A", cliFunc_keyPress },
  66. { "keyRelease", "Release a key-press from the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A", cliFunc_keyRelease },
  67. { "layerList", "List available layers.", cliFunc_layerList },
  68. { "layerState", "Modify specified indexed layer state <layer> <state byte>." NL "\t\t\033[35mL2\033[0m Indexed Layer 0x02" NL "\t\t0 Off, 1 Shift, 2 Latch, 4 Lock States", cliFunc_layerState },
  69. { "macroDebug", "Disables/Enables sending USB keycodes to the Output Module and prints U/K codes.", cliFunc_macroDebug },
  70. { "macroList", "List the defined trigger and result macros.", cliFunc_macroList },
  71. { "macroProc", "Pause/Resume macro processing.", cliFunc_macroProc },
  72. { "macroShow", "Show the macro corresponding to the given index." NL "\t\t\033[35mT16\033[0m Indexed Trigger Macro 0x10, \033[35mR12\033[0m Indexed Result Macro 0x0C", cliFunc_macroShow },
  73. { "macroStep", "Do N macro processing steps. Defaults to 1.", cliFunc_macroStep },
  74. { 0, 0, 0 } // Null entry for dictionary end
  75. };
  76. // Macro debug flag - If set, clears the USB Buffers after signalling processing completion
  77. uint8_t macroDebugMode = 0;
  78. // Macro pause flag - If set, the macro module pauses processing, unless unset, or the step counter is non-zero
  79. uint8_t macroPauseMode = 0;
  80. // Macro step counter - If non-zero, the step counter counts down every time the macro module does one processing loop
  81. unsigned int macroStepCounter = 0;
  82. // Key Trigger List Buffer
  83. TriggerGuide macroTriggerListBuffer[ MaxScanCode ];
  84. uint8_t macroTriggerListBufferSize = 0;
  85. // Pending Trigger Macro Index List
  86. // * Any trigger macros that need processing from a previous macro processing loop
  87. // TODO, figure out a good way to scale this array size without wasting too much memory, but not rejecting macros
  88. // Possibly could be calculated by the KLL compiler
  89. // XXX It may be possible to calculate the worst case using the KLL compiler
  90. unsigned int macroTriggerMacroPendingList[ TriggerMacroNum ] = { 0 };
  91. unsigned int macroTriggerMacroPendingListSize = 0;
  92. // Layer Index Stack
  93. // * When modifying layer state and the state is non-0x0, the stack must be adjusted
  94. unsigned int macroLayerIndexStack[ LayerNum ] = { 0 };
  95. unsigned int macroLayerIndexStackSize = 0;
  96. // Pending Result Macro Index List
  97. // * Any result macro that needs processing from a previous macro processing loop
  98. unsigned int macroResultMacroPendingList[ ResultMacroNum ] = { 0 };
  99. unsigned int macroResultMacroPendingListSize = 0;
  100. // ----- Functions -----
  101. // Looks up the trigger list for the given scan code (from the active layer)
  102. // NOTE: Calling function must handle the NULL pointer case
  103. unsigned int *Macro_layerLookup( uint8_t scanCode )
  104. {
  105. // If no trigger macro is defined at the given layer, fallthrough to the next layer
  106. for ( unsigned int layer = 0; layer < macroLayerIndexStackSize; layer++ )
  107. {
  108. // Lookup layer
  109. unsigned int **map = LayerIndex[ macroLayerIndexStack[ layer ] ].triggerMap;
  110. // Determine if layer has key defined
  111. if ( map != 0 && *map[ scanCode ] != 0 )
  112. return map[ scanCode ];
  113. }
  114. // Do lookup on default layer
  115. unsigned int **map = LayerIndex[0].triggerMap;
  116. // Determine if layer has key defined
  117. if ( map == 0 && *map[ scanCode ] == 0 )
  118. {
  119. erro_msg("Scan Code has no defined Trigger Macro: ");
  120. printHex( scanCode );
  121. return 0;
  122. }
  123. // Return lookup result
  124. return map[ scanCode ];
  125. }
  126. // Update the scancode key state
  127. // States:
  128. // * 0x00 - Off
  129. // * 0x01 - Pressed
  130. // * 0x02 - Held
  131. // * 0x03 - Released
  132. // * 0x04 - Unpressed (this is currently ignored)
  133. inline void Macro_keyState( uint8_t scanCode, uint8_t state )
  134. {
  135. // Only add to macro trigger list if one of three states
  136. switch ( state )
  137. {
  138. case 0x01: // Pressed
  139. case 0x02: // Held
  140. case 0x03: // Released
  141. macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode;
  142. macroTriggerListBuffer[ macroTriggerListBufferSize ].state = state;
  143. macroTriggerListBuffer[ macroTriggerListBufferSize ].type = 0x00; // Normal key
  144. macroTriggerListBufferSize++;
  145. break;
  146. }
  147. }
  148. // Update the scancode analog state
  149. // States:
  150. // * 0x00 - Off
  151. // * 0x01 - Released
  152. // * 0x02-0xFF - Analog value (low to high)
  153. inline void Macro_analogState( uint8_t scanCode, uint8_t state )
  154. {
  155. // Only add to macro trigger list if non-off
  156. if ( state != 0x00 )
  157. {
  158. macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode;
  159. macroTriggerListBuffer[ macroTriggerListBufferSize ].state = state;
  160. macroTriggerListBuffer[ macroTriggerListBufferSize ].type = 0x02; // Analog key
  161. macroTriggerListBufferSize++;
  162. }
  163. }
  164. // Update led state
  165. // States:
  166. // * 0x00 - Off
  167. // * 0x01 - On
  168. inline void Macro_ledState( uint8_t ledCode, uint8_t state )
  169. {
  170. // Only add to macro trigger list if non-off
  171. if ( state != 0x00 )
  172. {
  173. macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = ledCode;
  174. macroTriggerListBuffer[ macroTriggerListBufferSize ].state = state;
  175. macroTriggerListBuffer[ macroTriggerListBufferSize ].type = 0x01; // LED key
  176. macroTriggerListBufferSize++;
  177. }
  178. }
  179. // Append result macro to pending list, checking for duplicates
  180. // Do nothing if duplicate
  181. inline void Macro_appendResultMacroToPendingList( unsigned int resultMacroIndex )
  182. {
  183. // Iterate through result macro pending list, making sure this macro hasn't been added yet
  184. for ( unsigned int macro = 0; macro < macroResultMacroPendingListSize; macro++ )
  185. {
  186. // If duplicate found, do nothing
  187. if ( macroResultMacroPendingList[ macro ] == resultMacroIndex )
  188. return;
  189. }
  190. // No duplicates found, add to pending list
  191. macroResultMacroPendingList[ macroResultMacroPendingListSize++ ] = resultMacroIndex;
  192. }
  193. // Determine if long ResultMacro (more than 1 seqence element)
  194. inline uint8_t Macro_isLongResultMacro( ResultMacro *macro )
  195. {
  196. // Check the second sequence combo length
  197. // If non-zero return 1 (long sequence)
  198. // 0 otherwise (short sequence)
  199. return macro->guide[ macro->guide[0] * ResultGuideSize( ((ResultGuide*)macro->guide) ) ] > 0 ? 1 : 0;
  200. }
  201. // Votes on the given key vs. guide
  202. inline TriggerMacroVote Macro_evalTriggerMacroVote( TriggerGuide *key, TriggerGuide *guide )
  203. {
  204. // Depending on key type
  205. switch ( guide->type )
  206. {
  207. // Normal State Type
  208. case 0x00:
  209. // Depending on the state of the buffered key, make voting decision
  210. // Incorrect key
  211. if ( guide->scanCode != key->scanCode )
  212. {
  213. switch ( key->state )
  214. {
  215. // Wrong key, pressed, fail
  216. case 0x01:
  217. return TriggerMacroVote_Fail;
  218. // Wrong key, held or released, do not pass (no effect)
  219. case 0x02:
  220. case 0x03:
  221. return TriggerMacroVote_DoNothing;
  222. }
  223. }
  224. // Correct key
  225. else
  226. {
  227. switch ( key->state )
  228. {
  229. // Correct key, pressed, possible passing
  230. case 0x01:
  231. return TriggerMacroVote_Pass;
  232. // Correct key, held, possible passing or release
  233. case 0x02:
  234. return TriggerMacroVote_PassRelease;
  235. // Correct key, released, possible release
  236. case 0x03:
  237. return TriggerMacroVote_Release;
  238. }
  239. }
  240. break;
  241. // LED State Type
  242. case 0x01:
  243. erro_print("LED State Type - Not implemented...");
  244. break;
  245. // Analog State Type
  246. case 0x02:
  247. erro_print("Analog State Type - Not implemented...");
  248. break;
  249. // Invalid State Type
  250. default:
  251. erro_print("Invalid State Type. This is a bug.");
  252. break;
  253. }
  254. // XXX Shouldn't reach here
  255. return TriggerMacroVote_Invalid;
  256. }
  257. // Evaluate/Update TriggerMacro
  258. inline TriggerMacroEval Macro_evalTriggerMacro( unsigned int triggerMacroIndex )
  259. {
  260. // Lookup TriggerMacro
  261. TriggerMacro *macro = &TriggerMacroList[ triggerMacroIndex ];
  262. // Check if macro has finished and should be incremented sequence elements
  263. if ( macro->state == TriggerMacro_Release )
  264. {
  265. macro->state = TriggerMacro_Waiting;
  266. macro->pos = macro->pos + macro->guide[ macro->pos ] * TriggerGuideSize;
  267. }
  268. // Current Macro position
  269. unsigned int pos = macro->pos;
  270. // Length of the combo being processed
  271. uint8_t comboLength = macro->guide[ pos ];
  272. // If no combo items are left, remove the TriggerMacro from the pending list
  273. if ( comboLength == 0 )
  274. {
  275. return TriggerMacroEval_Remove;
  276. }
  277. // Iterate through the key buffer, comparing to each key in the combo
  278. // If any of the pressed keys do not match, fail the macro
  279. //
  280. // The macro is waiting for input when in the TriggerMacro_Waiting state
  281. // Once all keys have been pressed/held (only those keys), entered TriggerMacro_Press state (passing)
  282. // Transition to the next combo (if it exists) when a single key is released (TriggerMacro_Release state)
  283. // On scan after position increment, change to TriggerMacro_Waiting state
  284. // TODO Add support for system LED states (NumLock, CapsLock, etc.)
  285. // TODO Add support for analog key states
  286. // TODO Add support for 0x00 Key state (not pressing a key, not all that useful in general)
  287. // TODO Add support for Press/Hold/Release differentiation when evaluating (not sure if useful)
  288. TriggerMacroVote overallVote = TriggerMacroVote_Invalid;
  289. for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
  290. {
  291. // Lookup key information
  292. TriggerGuide *keyInfo = &macroTriggerListBuffer[ key ];
  293. // Iterate through the items in the combo, voting the on the key state
  294. TriggerMacroVote vote = TriggerMacroVote_Invalid;
  295. for ( uint8_t comboItem = pos + 1; comboItem < pos + comboLength + 1; comboItem += TriggerGuideSize )
  296. {
  297. // Assign TriggerGuide element (key type, state and scancode)
  298. TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ comboItem ]);
  299. // If vote is a pass (>= 0x08, no more keys in the combo need to be looked at)
  300. // Also mask all of the non-passing votes
  301. vote |= Macro_evalTriggerMacroVote( keyInfo, guide );
  302. if ( vote >= TriggerMacroVote_Pass )
  303. {
  304. vote &= TriggerMacroVote_Release | TriggerMacroVote_PassRelease | TriggerMacroVote_Pass;
  305. break;
  306. }
  307. }
  308. // After voting, append to overall vote
  309. overallVote |= vote;
  310. }
  311. // Decide new state of macro after voting
  312. // Fail macro, remove from pending list
  313. if ( overallVote & TriggerMacroVote_Fail )
  314. {
  315. return TriggerMacroEval_Remove;
  316. }
  317. // Do nothing, incorrect key is being held or released
  318. else if ( overallVote & TriggerMacroVote_DoNothing )
  319. {
  320. // Just doing nothing :)
  321. }
  322. // If passing and in Waiting state, set macro state to Press
  323. else if ( overallVote & TriggerMacroVote_Pass && macro->state == TriggerMacro_Waiting )
  324. {
  325. macro->state = TriggerMacro_Press;
  326. // If in press state, and this is the final combo, send request for ResultMacro
  327. // Check to see if the result macro only has a single element
  328. // If this result macro has more than 1 key, only send once
  329. // TODO Add option to have macro repeat rate
  330. if ( macro->guide[ pos + comboLength ] == 0 )
  331. {
  332. // Long Macro, only send once (more than 1 sequence item)
  333. // Short Macro (only 1 sequence item)
  334. return Macro_isLongResultMacro( &ResultMacroList[ macro->result ] )
  335. ? TriggerMacroEval_DoResult
  336. : TriggerMacroEval_DoResultAndRemove;
  337. }
  338. }
  339. // If ready for transition and in Press state, set to Waiting and increment combo position
  340. // Position is incremented (and possibly remove the macro from the pending list) on the next iteration
  341. else if ( overallVote & TriggerMacroVote_Release && macro->state == TriggerMacro_Press )
  342. {
  343. macro->state = TriggerMacro_Release;
  344. }
  345. return TriggerMacroEval_DoNothing;
  346. }
  347. // Evaluate/Update ResultMacro
  348. void Macro_evalResultMacro( unsigned int resultMacroIndex )
  349. {
  350. // TODO
  351. }
  352. // Update pending trigger list
  353. void Macro_updateTriggerMacroPendingList()
  354. {
  355. // Iterate over the macroTriggerListBuffer to add any new Trigger Macros to the pending list
  356. for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
  357. {
  358. // Lookup Trigger List
  359. unsigned int *triggerList = Macro_layerLookup( macroTriggerListBuffer[ key ].scanCode );
  360. // Number of Triggers in list
  361. unsigned int triggerListSize = triggerList[0];
  362. // Iterate over triggerList to see if any TriggerMacros need to be added
  363. // First item is the number of items in the TriggerList
  364. for ( unsigned int macro = 1; macro < triggerListSize + 1; macro++ )
  365. {
  366. // Lookup trigger macro index
  367. unsigned int triggerMacroIndex = triggerList[ macro ];
  368. // Iterate over macroTriggerMacroPendingList to see if any macro in the scancode's
  369. // triggerList needs to be added
  370. unsigned int pending = 0;
  371. for ( ; pending < macroTriggerMacroPendingListSize; pending++ )
  372. {
  373. // Stop scanning if the trigger macro index is found in the pending list
  374. if ( macroTriggerMacroPendingList[ pending ] == triggerMacroIndex )
  375. break;
  376. }
  377. // If the triggerMacroIndex (macro) was not found in the macroTriggerMacroPendingList
  378. // Add it to the list
  379. if ( pending == macroTriggerMacroPendingListSize )
  380. {
  381. macroTriggerMacroPendingList[ macroTriggerMacroPendingListSize++ ] = triggerMacroIndex;
  382. }
  383. }
  384. }
  385. }
  386. // Macro Procesing Loop
  387. // Called once per USB buffer send
  388. inline void Macro_process()
  389. {
  390. // Only do one round of macro processing between Output Module timer sends
  391. if ( USBKeys_Sent != 0 )
  392. return;
  393. // If the pause flag is set, only process if the step counter is non-zero
  394. if ( macroPauseMode )
  395. {
  396. if ( macroStepCounter == 0 )
  397. return;
  398. // Proceed, decrementing the step counter
  399. macroStepCounter--;
  400. }
  401. // Update pending trigger list, before processing TriggerMacros
  402. Macro_updateTriggerMacroPendingList();
  403. // Tail pointer for macroTriggerMacroPendingList
  404. // Macros must be explicitly re-added
  405. unsigned int macroTriggerMacroPendingListTail = 0;
  406. // Iterate through the pending TriggerMacros, processing each of them
  407. for ( unsigned int macro = 0; macro < macroTriggerMacroPendingListSize; macro++ )
  408. {
  409. switch ( Macro_evalTriggerMacro( macroTriggerMacroPendingList[ macro ] ) )
  410. {
  411. // Trigger Result Macro (purposely falling through)
  412. case TriggerMacroEval_DoResult:
  413. // Append ResultMacro to PendingList
  414. Macro_appendResultMacroToPendingList( TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ].result );
  415. // Otherwise, just re-add
  416. default:
  417. macroTriggerMacroPendingList[ macroTriggerMacroPendingListTail++ ] = macroTriggerMacroPendingList[ macro ];
  418. break;
  419. // Trigger Result Macro and Remove (purposely falling through)
  420. case TriggerMacroEval_DoResultAndRemove:
  421. // Append ResultMacro to PendingList
  422. Macro_appendResultMacroToPendingList( TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ].result );
  423. // Remove Macro from Pending List, nothing to do, removing by default
  424. case TriggerMacroEval_Remove:
  425. break;
  426. }
  427. }
  428. // Update the macroResultMacroPendingListSize with the tail pointer
  429. macroTriggerMacroPendingListSize = macroTriggerMacroPendingListTail;
  430. // Iterate through the pending ResultMacros, processing each of them
  431. for ( unsigned int macro = 0; macro < macroResultMacroPendingListSize; macro++ )
  432. {
  433. Macro_evalResultMacro( macroResultMacroPendingList[ macro ] );
  434. }
  435. /* TODO
  436. // Loop through input buffer
  437. for ( uint8_t index = 0; index < KeyIndex_BufferUsed && !macroDebugMode; index++ )
  438. {
  439. // Get the keycode from the buffer
  440. uint8_t key = KeyIndex_Buffer[index];
  441. // Set the modifier bit if this key is a modifier
  442. if ( (key & KEY_LCTRL) == KEY_LCTRL ) // AND with 0xE0
  443. {
  444. USBKeys_Modifiers |= 1 << (key ^ KEY_LCTRL); // Left shift 1 by key XOR 0xE0
  445. // Modifier processed, move on to the next key
  446. continue;
  447. }
  448. // Too many keys
  449. if ( USBKeys_Sent >= USBKeys_MaxSize )
  450. {
  451. warn_msg("USB Key limit reached");
  452. errorLED( 1 );
  453. break;
  454. }
  455. USBKeys_Array[USBKeys_Sent++] = key;
  456. }
  457. */
  458. // Signal buffer that we've used it TODO
  459. Scan_finishedWithMacro( 0 );
  460. //Scan_finishedWithBuffer( KeyIndex_BufferUsed );
  461. // If Macro debug mode is set, clear the USB Buffer
  462. if ( macroDebugMode )
  463. {
  464. USBKeys_Modifiers = 0;
  465. USBKeys_Sent = 0;
  466. }
  467. }
  468. inline void Macro_setup()
  469. {
  470. // Register Macro CLI dictionary
  471. CLI_registerDictionary( macroCLIDict, macroCLIDictName );
  472. // Disable Macro debug mode
  473. macroDebugMode = 0;
  474. // Disable Macro pause flag
  475. macroPauseMode = 0;
  476. // Set Macro step counter to zero
  477. macroStepCounter = 0;
  478. // Make sure macro trigger buffer is empty
  479. macroTriggerListBufferSize = 0;
  480. // Initialize TriggerMacro states
  481. for ( unsigned int macro = 0; macro < TriggerMacroNum; macro++ )
  482. {
  483. TriggerMacroList[ macro ].result = 0;
  484. TriggerMacroList[ macro ].pos = 0;
  485. TriggerMacroList[ macro ].state = TriggerMacro_Waiting;
  486. }
  487. // Initialize ResultMacro states
  488. for ( unsigned int macro = 0; macro < ResultMacroNum; macro++ )
  489. {
  490. ResultMacroList[ macro ].pos = 0;
  491. ResultMacroList[ macro ].state = 0;
  492. ResultMacroList[ macro ].stateType = 0;
  493. }
  494. }
  495. // ----- CLI Command Functions -----
  496. void cliFunc_capList( char* args )
  497. {
  498. print( NL );
  499. info_msg("Capabilities List");
  500. // Iterate through all of the capabilities and display them
  501. for ( unsigned int cap = 0; cap < CapabilitiesNum; cap++ )
  502. {
  503. print( NL "\t" );
  504. printHex( cap );
  505. print(" - ");
  506. // Display/Lookup Capability Name (utilize debug mode of capability)
  507. void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ cap ].func);
  508. capability( 0xFF, 0xFF, 0 );
  509. }
  510. }
  511. void cliFunc_capSelect( char* args )
  512. {
  513. // Parse code from argument
  514. char* curArgs;
  515. char* arg1Ptr;
  516. char* arg2Ptr = args;
  517. // Total number of args to scan (must do a lookup if a keyboard capability is selected)
  518. unsigned int totalArgs = 2; // Always at least two args
  519. unsigned int cap = 0;
  520. // Arguments used for keyboard capability function
  521. unsigned int argSetCount = 0;
  522. uint8_t *argSet = (uint8_t*)args;
  523. // Process all args
  524. for ( unsigned int c = 0; argSetCount < totalArgs; c++ )
  525. {
  526. curArgs = arg2Ptr;
  527. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  528. // Stop processing args if no more are found
  529. // Extra arguments are ignored
  530. if ( *arg1Ptr == '\0' )
  531. break;
  532. // For the first argument, choose the capability
  533. if ( c == 0 ) switch ( arg1Ptr[0] )
  534. {
  535. // Keyboard Capability
  536. case 'K':
  537. // Determine capability index
  538. cap = decToInt( &arg1Ptr[1] );
  539. // Lookup the number of args
  540. totalArgs += CapabilitiesList[ cap ].argCount;
  541. continue;
  542. }
  543. // Because allocating memory isn't doable, and the argument count is arbitrary
  544. // The argument pointer is repurposed as the argument list (much smaller anyways)
  545. argSet[ argSetCount++ ] = (uint8_t)decToInt( arg1Ptr );
  546. // Once all the arguments are prepared, call the keyboard capability function
  547. if ( argSetCount == totalArgs )
  548. {
  549. // Indicate that the capability was called
  550. print( NL );
  551. info_msg("K");
  552. printInt8( cap );
  553. print(" - ");
  554. printHex( argSet[0] );
  555. print(" - ");
  556. printHex( argSet[1] );
  557. print(" - ");
  558. printHex( argSet[2] );
  559. print( "..." NL );
  560. void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ cap ].func);
  561. capability( argSet[0], argSet[1], &argSet[2] );
  562. }
  563. }
  564. }
  565. void cliFunc_keyPress( char* args )
  566. {
  567. // Parse codes from arguments
  568. char* curArgs;
  569. char* arg1Ptr;
  570. char* arg2Ptr = args;
  571. // Process all args
  572. for ( ;; )
  573. {
  574. curArgs = arg2Ptr;
  575. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  576. // Stop processing args if no more are found
  577. if ( *arg1Ptr == '\0' )
  578. break;
  579. // Ignore non-Scancode numbers
  580. switch ( arg1Ptr[0] )
  581. {
  582. // Scancode
  583. case 'S':
  584. Macro_keyState( (uint8_t)decToInt( &arg1Ptr[1] ), 0x01 ); // Press scancode
  585. break;
  586. }
  587. }
  588. }
  589. void cliFunc_keyRelease( char* args )
  590. {
  591. // Parse codes from arguments
  592. char* curArgs;
  593. char* arg1Ptr;
  594. char* arg2Ptr = args;
  595. // Process all args
  596. for ( ;; )
  597. {
  598. curArgs = arg2Ptr;
  599. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  600. // Stop processing args if no more are found
  601. if ( *arg1Ptr == '\0' )
  602. break;
  603. // Ignore non-Scancode numbers
  604. switch ( arg1Ptr[0] )
  605. {
  606. // Scancode
  607. case 'S':
  608. Macro_keyState( (uint8_t)decToInt( &arg1Ptr[1] ), 0x03 ); // Release scancode
  609. break;
  610. }
  611. }
  612. }
  613. void cliFunc_layerList( char* args )
  614. {
  615. print( NL );
  616. info_msg("Layer List");
  617. // Iterate through all of the layers and display them
  618. for ( unsigned int layer = 0; layer < LayerNum; layer++ )
  619. {
  620. print( NL "\t" );
  621. printHex( layer );
  622. print(" - ");
  623. // Display layer name
  624. dPrint( LayerIndex[ layer ].name );
  625. // Default map
  626. if ( layer == 0 )
  627. print(" \033[1m(default)\033[0m");
  628. // Layer State
  629. print( NL "\t\t Layer State: " );
  630. printHex( LayerIndex[ layer ].state );
  631. // Max Index
  632. print(" Max Index: ");
  633. printHex( LayerIndex[ layer ].max );
  634. }
  635. }
  636. void cliFunc_layerState( char* args )
  637. {
  638. // Parse codes from arguments
  639. char* curArgs;
  640. char* arg1Ptr;
  641. char* arg2Ptr = args;
  642. uint8_t arg1 = 0;
  643. uint8_t arg2 = 0;
  644. // Process first two args
  645. for ( uint8_t c = 0; c < 2; c++ )
  646. {
  647. curArgs = arg2Ptr;
  648. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  649. // Stop processing args if no more are found
  650. if ( *arg1Ptr == '\0' )
  651. break;
  652. switch ( c )
  653. {
  654. // First argument (e.g. L1)
  655. case 0:
  656. if ( arg1Ptr[0] != 'L' )
  657. return;
  658. arg1 = (uint8_t)decToInt( &arg1Ptr[1] );
  659. break;
  660. // Second argument (e.g. 4)
  661. case 1:
  662. arg2 = (uint8_t)decToInt( arg1Ptr );
  663. // Display operation (to indicate that it worked)
  664. print( NL );
  665. info_msg("Setting Layer L");
  666. printInt8( arg1 );
  667. print(" to - ");
  668. printHex( arg2 );
  669. // Set the layer state
  670. LayerIndex[ arg1 ].state = arg2;
  671. break;
  672. }
  673. }
  674. }
  675. void cliFunc_macroDebug( char* args )
  676. {
  677. // Toggle macro debug mode
  678. macroDebugMode = macroDebugMode ? 0 : 1;
  679. print( NL );
  680. info_msg("Macro Debug Mode: ");
  681. printInt8( macroDebugMode );
  682. }
  683. void cliFunc_macroList( char* args )
  684. {
  685. // Show available trigger macro indices
  686. print( NL );
  687. info_msg("Trigger Macros Range: T0 -> T");
  688. printInt16( (uint16_t)TriggerMacroNum - 1 ); // Hopefully large enough :P (can't assume 32-bit)
  689. // Show available result macro indices
  690. print( NL );
  691. info_msg("Result Macros Range: R0 -> R");
  692. printInt16( (uint16_t)ResultMacroNum - 1 ); // Hopefully large enough :P (can't assume 32-bit)
  693. // Show Trigger to Result Macro Links
  694. print( NL );
  695. info_msg("Trigger : Result Macro Pairs");
  696. for ( unsigned int macro = 0; macro < TriggerMacroNum; macro++ )
  697. {
  698. print( NL );
  699. print("\tT");
  700. printInt16( (uint16_t)macro ); // Hopefully large enough :P (can't assume 32-bit)
  701. print(" : R");
  702. printInt16( (uint16_t)TriggerMacroList[ macro ].result ); // Hopefully large enough :P (can't assume 32-bit)
  703. }
  704. }
  705. void cliFunc_macroProc( char* args )
  706. {
  707. // Toggle macro pause mode
  708. macroPauseMode = macroPauseMode ? 0 : 1;
  709. print( NL );
  710. info_msg("Macro Processing Mode: ");
  711. printInt8( macroPauseMode );
  712. }
  713. void macroDebugShowTrigger( unsigned int index )
  714. {
  715. // Only proceed if the macro exists
  716. if ( index >= TriggerMacroNum )
  717. return;
  718. // Trigger Macro Show
  719. TriggerMacro *macro = &TriggerMacroList[ index ];
  720. print( NL );
  721. info_msg("Trigger Macro Index: ");
  722. printInt16( (uint16_t)index ); // Hopefully large enough :P (can't assume 32-bit)
  723. print( NL );
  724. // Read the comboLength for combo in the sequence (sequence of combos)
  725. unsigned int pos = 0;
  726. uint8_t comboLength = macro->guide[ pos ];
  727. // Iterate through and interpret the guide
  728. while ( comboLength != 0 )
  729. {
  730. // Initial position of the combo
  731. unsigned int comboPos = ++pos;
  732. // Iterate through the combo
  733. while ( pos < comboLength * TriggerGuideSize + comboPos )
  734. {
  735. // Assign TriggerGuide element (key type, state and scancode)
  736. TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ pos ]);
  737. // Display guide information about trigger key
  738. printHex( guide->scanCode );
  739. print("|");
  740. printHex( guide->type );
  741. print("|");
  742. printHex( guide->state );
  743. // Increment position
  744. pos += TriggerGuideSize;
  745. // Only show combo separator if there are combos left in the sequence element
  746. if ( pos < comboLength * TriggerGuideSize + comboPos )
  747. print("+");
  748. }
  749. // Read the next comboLength
  750. comboLength = macro->guide[ pos ];
  751. // Only show sequence separator if there is another combo to process
  752. if ( comboLength != 0 )
  753. print(";");
  754. }
  755. // Display current position
  756. print( NL "Position: " );
  757. printInt16( (uint16_t)macro->pos ); // Hopefully large enough :P (can't assume 32-bit)
  758. // Display result macro index
  759. print( NL "Result Macro Index: " );
  760. printInt16( (uint16_t)macro->result ); // Hopefully large enough :P (can't assume 32-bit)
  761. }
  762. void macroDebugShowResult( unsigned int index )
  763. {
  764. // Only proceed if the macro exists
  765. if ( index >= ResultMacroNum )
  766. return;
  767. // Trigger Macro Show
  768. ResultMacro *macro = &ResultMacroList[ index ];
  769. print( NL );
  770. info_msg("Result Macro Index: ");
  771. printInt16( (uint16_t)index ); // Hopefully large enough :P (can't assume 32-bit)
  772. print( NL );
  773. // Read the comboLength for combo in the sequence (sequence of combos)
  774. unsigned int pos = 0;
  775. uint8_t comboLength = macro->guide[ pos++ ];
  776. // Iterate through and interpret the guide
  777. while ( comboLength != 0 )
  778. {
  779. // Function Counter, used to keep track of the combos processed
  780. unsigned int funcCount = 0;
  781. // Iterate through the combo
  782. while ( funcCount < comboLength )
  783. {
  784. // Assign TriggerGuide element (key type, state and scancode)
  785. ResultGuide *guide = (ResultGuide*)(&macro->guide[ pos ]);
  786. // Display Function Index
  787. printHex( guide->index );
  788. print("|");
  789. // Display Function Ptr Address
  790. printHex( (unsigned int)CapabilitiesList[ guide->index ].func );
  791. print("|");
  792. // Display/Lookup Capability Name (utilize debug mode of capability)
  793. void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ guide->index ].func);
  794. capability( 0xFF, 0xFF, 0 );
  795. // Display Argument(s)
  796. print("(");
  797. for ( unsigned int arg = 0; arg < CapabilitiesList[ guide->index ].argCount; arg++ )
  798. {
  799. // Arguments are only 8 bit values
  800. printHex( (&guide->args)[ arg ] );
  801. // Only show arg separator if there are args left
  802. if ( arg + 1 < CapabilitiesList[ guide->index ].argCount )
  803. print(",");
  804. }
  805. print(")");
  806. // Increment position
  807. pos += ResultGuideSize( guide );
  808. // Increment function count
  809. funcCount++;
  810. // Only show combo separator if there are combos left in the sequence element
  811. if ( funcCount < comboLength )
  812. print("+");
  813. }
  814. // Read the next comboLength
  815. comboLength = macro->guide[ pos++ ];
  816. // Only show sequence separator if there is another combo to process
  817. if ( comboLength != 0 )
  818. print(";");
  819. }
  820. // Display current position
  821. print( NL "Position: " );
  822. printInt16( (uint16_t)macro->pos ); // Hopefully large enough :P (can't assume 32-bit)
  823. // Display final trigger state/type
  824. print( NL "Final Trigger State (State/Type): " );
  825. printHex( macro->state );
  826. print("/");
  827. printHex( macro->stateType );
  828. }
  829. void cliFunc_macroShow( char* args )
  830. {
  831. // Parse codes from arguments
  832. char* curArgs;
  833. char* arg1Ptr;
  834. char* arg2Ptr = args;
  835. // Process all args
  836. for ( ;; )
  837. {
  838. curArgs = arg2Ptr;
  839. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  840. // Stop processing args if no more are found
  841. if ( *arg1Ptr == '\0' )
  842. break;
  843. // Ignore invalid codes
  844. switch ( arg1Ptr[0] )
  845. {
  846. // Indexed Trigger Macro
  847. case 'T':
  848. macroDebugShowTrigger( decToInt( &arg1Ptr[1] ) );
  849. break;
  850. // Indexed Result Macro
  851. case 'R':
  852. macroDebugShowResult( decToInt( &arg1Ptr[1] ) );
  853. break;
  854. }
  855. }
  856. }
  857. void cliFunc_macroStep( char* args )
  858. {
  859. // Parse number from argument
  860. // NOTE: Only first argument is used
  861. char* arg1Ptr;
  862. char* arg2Ptr;
  863. CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
  864. // Set the macro step counter, negative int's are cast to uint
  865. macroStepCounter = (unsigned int)decToInt( arg1Ptr );
  866. }