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 44KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536
  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. // Keymaps
  25. #include "usb_hid.h"
  26. #include <generatedKeymap.h> // Generated using kll at compile time, in build directory
  27. // Local Includes
  28. #include "macro.h"
  29. // ----- Function Declarations -----
  30. void cliFunc_capList ( char* args );
  31. void cliFunc_capSelect ( char* args );
  32. void cliFunc_keyHold ( char* args );
  33. void cliFunc_keyPress ( char* args );
  34. void cliFunc_keyRelease( char* args );
  35. void cliFunc_layerList ( char* args );
  36. void cliFunc_layerState( char* args );
  37. void cliFunc_macroDebug( char* args );
  38. void cliFunc_macroList ( char* args );
  39. void cliFunc_macroProc ( char* args );
  40. void cliFunc_macroShow ( char* args );
  41. void cliFunc_macroStep ( char* args );
  42. // ----- Enums -----
  43. // Bit positions are important, passes (correct key) always trump incorrect key votes
  44. typedef enum TriggerMacroVote {
  45. TriggerMacroVote_Release = 0x10, // Correct key
  46. TriggerMacroVote_PassRelease = 0x18, // Correct key (both pass and release)
  47. TriggerMacroVote_Pass = 0x8, // Correct key
  48. TriggerMacroVote_DoNothingRelease = 0x4, // Incorrect 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. typedef enum ResultMacroEval {
  60. ResultMacroEval_DoNothing,
  61. ResultMacroEval_Remove,
  62. } ResultMacroEval;
  63. // ----- Variables -----
  64. // Macro Module command dictionary
  65. CLIDict_Entry( capList, "Prints an indexed list of all non USB keycode capabilities." );
  66. CLIDict_Entry( capSelect, "Triggers the specified capabilities. First two args are state and stateType." NL "\t\t\033[35mK11\033[0m Keyboard Capability 0x0B" );
  67. CLIDict_Entry( keyHold, "Send key-hold events to the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" );
  68. CLIDict_Entry( keyPress, "Send key-press events to the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" );
  69. CLIDict_Entry( keyRelease, "Send key-release event to macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" );
  70. CLIDict_Entry( layerList, "List available layers." );
  71. CLIDict_Entry( 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" );
  72. CLIDict_Entry( macroDebug, "Disables/Enables sending USB keycodes to the Output Module and prints U/K codes." );
  73. CLIDict_Entry( macroList, "List the defined trigger and result macros." );
  74. CLIDict_Entry( macroProc, "Pause/Resume macro processing." );
  75. CLIDict_Entry( 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" );
  76. CLIDict_Entry( macroStep, "Do N macro processing steps. Defaults to 1." );
  77. CLIDict_Def( macroCLIDict, "Macro Module Commands" ) = {
  78. CLIDict_Item( capList ),
  79. CLIDict_Item( capSelect ),
  80. CLIDict_Item( keyHold ),
  81. CLIDict_Item( keyPress ),
  82. CLIDict_Item( keyRelease ),
  83. CLIDict_Item( layerList ),
  84. CLIDict_Item( layerState ),
  85. CLIDict_Item( macroDebug ),
  86. CLIDict_Item( macroList ),
  87. CLIDict_Item( macroProc ),
  88. CLIDict_Item( macroShow ),
  89. CLIDict_Item( macroStep ),
  90. { 0, 0, 0 } // Null entry for dictionary end
  91. };
  92. // Macro debug flag - If set, clears the USB Buffers after signalling processing completion
  93. uint8_t macroDebugMode = 0;
  94. // Macro pause flag - If set, the macro module pauses processing, unless unset, or the step counter is non-zero
  95. uint8_t macroPauseMode = 0;
  96. // Macro step counter - If non-zero, the step counter counts down every time the macro module does one processing loop
  97. uint16_t macroStepCounter = 0;
  98. // Key Trigger List Buffer
  99. TriggerGuide macroTriggerListBuffer[ MaxScanCode ];
  100. uint8_t macroTriggerListBufferSize = 0;
  101. // Pending Trigger Macro Index List
  102. // * Any trigger macros that need processing from a previous macro processing loop
  103. // TODO, figure out a good way to scale this array size without wasting too much memory, but not rejecting macros
  104. // Possibly could be calculated by the KLL compiler
  105. // XXX It may be possible to calculate the worst case using the KLL compiler
  106. uint16_t macroTriggerMacroPendingList[ TriggerMacroNum ] = { 0 };
  107. uint16_t macroTriggerMacroPendingListSize = 0;
  108. // Layer Index Stack
  109. // * When modifying layer state and the state is non-0x0, the stack must be adjusted
  110. uint16_t macroLayerIndexStack[ LayerNum + 1 ] = { 0 };
  111. uint16_t macroLayerIndexStackSize = 0;
  112. // Pending Result Macro Index List
  113. // * Any result macro that needs processing from a previous macro processing loop
  114. uint16_t macroResultMacroPendingList[ ResultMacroNum ] = { 0 };
  115. uint16_t macroResultMacroPendingListSize = 0;
  116. // ----- Capabilities -----
  117. // Sets the given layer with the specified layerState
  118. void Macro_layerState( uint8_t state, uint8_t stateType, uint16_t layer, uint8_t layerState )
  119. {
  120. // Ignore if layer does not exist
  121. if ( layer >= LayerNum )
  122. return;
  123. // Is layer in the LayerIndexStack?
  124. uint8_t inLayerIndexStack = 0;
  125. uint16_t stackItem = 0;
  126. while ( stackItem < macroLayerIndexStackSize )
  127. {
  128. // Flag if layer is already in the LayerIndexStack
  129. if ( macroLayerIndexStack[ stackItem ] == layer )
  130. {
  131. inLayerIndexStack = 1;
  132. break;
  133. }
  134. // Increment to next item
  135. stackItem++;
  136. }
  137. // Toggle Layer State Byte
  138. if ( LayerState[ layer ] & layerState )
  139. {
  140. // Unset
  141. LayerState[ layer ] &= ~layerState;
  142. }
  143. else
  144. {
  145. // Set
  146. LayerState[ layer ] |= layerState;
  147. }
  148. // If the layer was not in the LayerIndexStack add it
  149. if ( !inLayerIndexStack )
  150. {
  151. macroLayerIndexStack[ macroLayerIndexStackSize++ ] = layer;
  152. }
  153. // If the layer is in the LayerIndexStack and the state is 0x00, remove
  154. if ( LayerState[ layer ] == 0x00 && inLayerIndexStack )
  155. {
  156. // Remove the layer from the LayerIndexStack
  157. // Using the already positioned stackItem variable from the loop above
  158. while ( stackItem < macroLayerIndexStackSize )
  159. {
  160. macroLayerIndexStack[ stackItem ] = macroLayerIndexStack[ stackItem + 1 ];
  161. stackItem++;
  162. }
  163. // Reduce LayerIndexStack size
  164. macroLayerIndexStackSize--;
  165. }
  166. }
  167. // Modifies the specified Layer control byte
  168. // Argument #1: Layer Index -> uint16_t
  169. // Argument #2: Layer State -> uint8_t
  170. void Macro_layerState_capability( uint8_t state, uint8_t stateType, uint8_t *args )
  171. {
  172. // Display capability name
  173. if ( stateType == 0xFF && state == 0xFF )
  174. {
  175. print("Macro_layerState(layerIndex,layerState)");
  176. return;
  177. }
  178. // Only use capability on press or release
  179. // TODO Analog
  180. // XXX This may cause issues, might be better to implement state table here to decide -HaaTa
  181. if ( stateType == 0x00 && state == 0x02 ) // Hold condition
  182. return;
  183. // Get layer index from arguments
  184. // Cast pointer to uint8_t to uint16_t then access that memory location
  185. uint16_t layer = *(uint16_t*)(&args[0]);
  186. // Get layer toggle byte
  187. uint8_t layerState = args[ sizeof(uint16_t) ];
  188. Macro_layerState( state, stateType, layer, layerState );
  189. }
  190. // Latches given layer
  191. // Argument #1: Layer Index -> uint16_t
  192. void Macro_layerLatch_capability( uint8_t state, uint8_t stateType, uint8_t *args )
  193. {
  194. // Display capability name
  195. if ( stateType == 0xFF && state == 0xFF )
  196. {
  197. print("Macro_layerLatch(layerIndex)");
  198. return;
  199. }
  200. // Only use capability on press
  201. // TODO Analog
  202. if ( stateType == 0x00 && state != 0x03 ) // Only on release
  203. return;
  204. // Get layer index from arguments
  205. // Cast pointer to uint8_t to uint16_t then access that memory location
  206. uint16_t layer = *(uint16_t*)(&args[0]);
  207. Macro_layerState( state, stateType, layer, 0x02 );
  208. }
  209. // Locks given layer
  210. // Argument #1: Layer Index -> uint16_t
  211. void Macro_layerLock_capability( uint8_t state, uint8_t stateType, uint8_t *args )
  212. {
  213. // Display capability name
  214. if ( stateType == 0xFF && state == 0xFF )
  215. {
  216. print("Macro_layerLock(layerIndex)");
  217. return;
  218. }
  219. // Only use capability on press
  220. // TODO Analog
  221. // XXX Could also be on release, but that's sorta dumb -HaaTa
  222. if ( stateType == 0x00 && state != 0x01 ) // All normal key conditions except press
  223. return;
  224. // Get layer index from arguments
  225. // Cast pointer to uint8_t to uint16_t then access that memory location
  226. uint16_t layer = *(uint16_t*)(&args[0]);
  227. Macro_layerState( state, stateType, layer, 0x04 );
  228. }
  229. // Shifts given layer
  230. // Argument #1: Layer Index -> uint16_t
  231. void Macro_layerShift_capability( uint8_t state, uint8_t stateType, uint8_t *args )
  232. {
  233. // Display capability name
  234. if ( stateType == 0xFF && state == 0xFF )
  235. {
  236. print("Macro_layerShift(layerIndex)");
  237. return;
  238. }
  239. // Only use capability on press or release
  240. // TODO Analog
  241. if ( stateType == 0x00 && ( state == 0x00 || state == 0x02 ) ) // Only pass press or release conditions
  242. return;
  243. // Get layer index from arguments
  244. // Cast pointer to uint8_t to uint16_t then access that memory location
  245. uint16_t layer = *(uint16_t*)(&args[0]);
  246. Macro_layerState( state, stateType, layer, 0x01 );
  247. }
  248. // ----- Functions -----
  249. // Looks up the trigger list for the given scan code (from the active layer)
  250. // NOTE: Calling function must handle the NULL pointer case
  251. nat_ptr_t *Macro_layerLookup( uint8_t scanCode, uint8_t latch_expire )
  252. {
  253. // If no trigger macro is defined at the given layer, fallthrough to the next layer
  254. for ( uint16_t layerIndex = 0; layerIndex < macroLayerIndexStackSize; layerIndex++ )
  255. {
  256. // Lookup Layer
  257. const Layer *layer = &LayerIndex[ macroLayerIndexStack[ layerIndex ] ];
  258. // Check if latch has been pressed for this layer
  259. // XXX Regardless of whether a key is found, the latch is removed on first lookup
  260. uint8_t latch = LayerState[ macroLayerIndexStack[ layerIndex ] ] & 0x02;
  261. if ( latch && latch_expire )
  262. {
  263. Macro_layerState( 0, 0, macroLayerIndexStack[ layerIndex ], 0x02 );
  264. }
  265. // Only use layer, if state is valid
  266. // XOR each of the state bits
  267. // If only two are enabled, do not use this state
  268. if ( (LayerState[ macroLayerIndexStack[ layerIndex ] ] & 0x01) ^ (latch>>1) ^ ((LayerState[ macroLayerIndexStack[ layerIndex ] ] & 0x04)>>2) )
  269. {
  270. // Lookup layer
  271. nat_ptr_t **map = (nat_ptr_t**)layer->triggerMap;
  272. // Determine if layer has key defined
  273. // Make sure scanCode is between layer first and last scancodes
  274. if ( map != 0
  275. && scanCode <= layer->last
  276. && scanCode >= layer->first
  277. && *map[ scanCode - layer->first ] != 0 )
  278. {
  279. return map[ scanCode - layer->first ];
  280. }
  281. }
  282. }
  283. // Do lookup on default layer
  284. nat_ptr_t **map = (nat_ptr_t**)LayerIndex[0].triggerMap;
  285. // Lookup default layer
  286. const Layer *layer = &LayerIndex[0];
  287. // Make sure scanCode is between layer first and last scancodes
  288. if ( map != 0
  289. && scanCode <= layer->last
  290. && scanCode >= layer->first
  291. && *map[ scanCode - layer->first ] != 0 )
  292. {
  293. return map[ scanCode - layer->first ];
  294. }
  295. // Otherwise no defined Trigger Macro
  296. erro_msg("Scan Code has no defined Trigger Macro: ");
  297. printHex( scanCode );
  298. return 0;
  299. }
  300. // Update the scancode key state
  301. // States:
  302. // * 0x00 - Off
  303. // * 0x01 - Pressed
  304. // * 0x02 - Held
  305. // * 0x03 - Released
  306. // * 0x04 - Unpressed (this is currently ignored)
  307. inline void Macro_keyState( uint8_t scanCode, uint8_t state )
  308. {
  309. // Only add to macro trigger list if one of three states
  310. switch ( state )
  311. {
  312. case 0x01: // Pressed
  313. case 0x02: // Held
  314. case 0x03: // Released
  315. macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode;
  316. macroTriggerListBuffer[ macroTriggerListBufferSize ].state = state;
  317. macroTriggerListBuffer[ macroTriggerListBufferSize ].type = 0x00; // Normal key
  318. macroTriggerListBufferSize++;
  319. break;
  320. }
  321. }
  322. // Update the scancode analog state
  323. // States:
  324. // * 0x00 - Off
  325. // * 0x01 - Released
  326. // * 0x02-0xFF - Analog value (low to high)
  327. inline void Macro_analogState( uint8_t scanCode, uint8_t state )
  328. {
  329. // Only add to macro trigger list if non-off
  330. if ( state != 0x00 )
  331. {
  332. macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode;
  333. macroTriggerListBuffer[ macroTriggerListBufferSize ].state = state;
  334. macroTriggerListBuffer[ macroTriggerListBufferSize ].type = 0x02; // Analog key
  335. macroTriggerListBufferSize++;
  336. }
  337. }
  338. // Update led state
  339. // States:
  340. // * 0x00 - Off
  341. // * 0x01 - On
  342. inline void Macro_ledState( uint8_t ledCode, uint8_t state )
  343. {
  344. // Only add to macro trigger list if non-off
  345. if ( state != 0x00 )
  346. {
  347. macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = ledCode;
  348. macroTriggerListBuffer[ macroTriggerListBufferSize ].state = state;
  349. macroTriggerListBuffer[ macroTriggerListBufferSize ].type = 0x01; // LED key
  350. macroTriggerListBufferSize++;
  351. }
  352. }
  353. // Append result macro to pending list, checking for duplicates
  354. // Do nothing if duplicate
  355. inline void Macro_appendResultMacroToPendingList( const TriggerMacro *triggerMacro )
  356. {
  357. // Lookup result macro index
  358. var_uint_t resultMacroIndex = triggerMacro->result;
  359. // Iterate through result macro pending list, making sure this macro hasn't been added yet
  360. for ( var_uint_t macro = 0; macro < macroResultMacroPendingListSize; macro++ )
  361. {
  362. // If duplicate found, do nothing
  363. if ( macroResultMacroPendingList[ macro ] == resultMacroIndex )
  364. return;
  365. }
  366. // No duplicates found, add to pending list
  367. macroResultMacroPendingList[ macroResultMacroPendingListSize++ ] = resultMacroIndex;
  368. // Lookup scanCode of the last key in the last combo
  369. var_uint_t pos = 0;
  370. for ( uint8_t comboLength = triggerMacro->guide[0]; comboLength > 0; )
  371. {
  372. pos += TriggerGuideSize * comboLength + 1;
  373. comboLength = triggerMacro->guide[ pos ];
  374. }
  375. uint8_t scanCode = ((TriggerGuide*)&triggerMacro->guide[ pos - TriggerGuideSize ])->scanCode;
  376. // Lookup scanCode in buffer list for the current state and stateType
  377. for ( uint8_t keyIndex = 0; keyIndex < macroTriggerListBufferSize; keyIndex++ )
  378. {
  379. if ( macroTriggerListBuffer[ keyIndex ].scanCode == scanCode )
  380. {
  381. ResultMacroRecordList[ resultMacroIndex ].state = macroTriggerListBuffer[ keyIndex ].state;
  382. ResultMacroRecordList[ resultMacroIndex ].stateType = macroTriggerListBuffer[ keyIndex ].type;
  383. }
  384. }
  385. // Reset the macro position
  386. ResultMacroRecordList[ resultMacroIndex ].pos = 0;
  387. }
  388. // Determine if long ResultMacro (more than 1 seqence element)
  389. inline uint8_t Macro_isLongResultMacro( const ResultMacro *macro )
  390. {
  391. // Check the second sequence combo length
  392. // If non-zero return non-zero (long sequence)
  393. // 0 otherwise (short sequence)
  394. var_uint_t position = 1;
  395. for ( var_uint_t result = 0; result < macro->guide[0]; result++ )
  396. position += ResultGuideSize( (ResultGuide*)&macro->guide[ position ] );
  397. return macro->guide[ position ];
  398. }
  399. // Determine if long TriggerMacro (more than 1 sequence element)
  400. inline uint8_t Macro_isLongTriggerMacro( const TriggerMacro *macro )
  401. {
  402. // Check the second sequence combo length
  403. // If non-zero return non-zero (long sequence)
  404. // 0 otherwise (short sequence)
  405. return macro->guide[ macro->guide[0] * TriggerGuideSize + 1 ];
  406. }
  407. // Votes on the given key vs. guide, short macros
  408. inline TriggerMacroVote Macro_evalShortTriggerMacroVote( TriggerGuide *key, TriggerGuide *guide )
  409. {
  410. // Depending on key type
  411. switch ( guide->type )
  412. {
  413. // Normal State Type
  414. case 0x00:
  415. // For short TriggerMacros completely ignore incorrect keys
  416. if ( guide->scanCode == key->scanCode )
  417. {
  418. switch ( key->state )
  419. {
  420. // Correct key, pressed, possible passing
  421. case 0x01:
  422. return TriggerMacroVote_Pass;
  423. // Correct key, held, possible passing or release
  424. case 0x02:
  425. return TriggerMacroVote_PassRelease;
  426. // Correct key, released, possible release
  427. case 0x03:
  428. return TriggerMacroVote_Release;
  429. }
  430. }
  431. return TriggerMacroVote_DoNothing;
  432. // LED State Type
  433. case 0x01:
  434. erro_print("LED State Type - Not implemented...");
  435. break;
  436. // Analog State Type
  437. case 0x02:
  438. erro_print("Analog State Type - Not implemented...");
  439. break;
  440. // Invalid State Type
  441. default:
  442. erro_print("Invalid State Type. This is a bug.");
  443. break;
  444. }
  445. // XXX Shouldn't reach here
  446. return TriggerMacroVote_Invalid;
  447. }
  448. // Votes on the given key vs. guide, long macros
  449. // A long macro is defined as a guide with more than 1 combo
  450. inline TriggerMacroVote Macro_evalLongTriggerMacroVote( TriggerGuide *key, TriggerGuide *guide )
  451. {
  452. // Depending on key type
  453. switch ( guide->type )
  454. {
  455. // Normal State Type
  456. case 0x00:
  457. // Depending on the state of the buffered key, make voting decision
  458. // Incorrect key
  459. if ( guide->scanCode != key->scanCode )
  460. {
  461. switch ( key->state )
  462. {
  463. // Wrong key, pressed, fail
  464. case 0x01:
  465. return TriggerMacroVote_Fail;
  466. // Wrong key, held, do not pass (no effect)
  467. case 0x02:
  468. return TriggerMacroVote_DoNothing;
  469. // Wrong key released, fail out if pos == 0
  470. case 0x03:
  471. return TriggerMacroVote_DoNothing | TriggerMacroVote_DoNothingRelease;
  472. }
  473. }
  474. // Correct key
  475. else
  476. {
  477. switch ( key->state )
  478. {
  479. // Correct key, pressed, possible passing
  480. case 0x01:
  481. return TriggerMacroVote_Pass;
  482. // Correct key, held, possible passing or release
  483. case 0x02:
  484. return TriggerMacroVote_PassRelease;
  485. // Correct key, released, possible release
  486. case 0x03:
  487. return TriggerMacroVote_Release;
  488. }
  489. }
  490. break;
  491. // LED State Type
  492. case 0x01:
  493. erro_print("LED State Type - Not implemented...");
  494. break;
  495. // Analog State Type
  496. case 0x02:
  497. erro_print("Analog State Type - Not implemented...");
  498. break;
  499. // Invalid State Type
  500. default:
  501. erro_print("Invalid State Type. This is a bug.");
  502. break;
  503. }
  504. // XXX Shouldn't reach here
  505. return TriggerMacroVote_Invalid;
  506. }
  507. // Evaluate/Update TriggerMacro
  508. TriggerMacroEval Macro_evalTriggerMacro( var_uint_t triggerMacroIndex )
  509. {
  510. // Lookup TriggerMacro
  511. const TriggerMacro *macro = &TriggerMacroList[ triggerMacroIndex ];
  512. TriggerMacroRecord *record = &TriggerMacroRecordList[ triggerMacroIndex ];
  513. // Check if macro has finished and should be incremented sequence elements
  514. if ( record->state == TriggerMacro_Release )
  515. {
  516. record->state = TriggerMacro_Waiting;
  517. record->pos = record->pos + macro->guide[ record->pos ] * TriggerGuideSize + 1;
  518. }
  519. // Current Macro position
  520. var_uint_t pos = record->pos;
  521. // Length of the combo being processed
  522. uint8_t comboLength = macro->guide[ pos ] * TriggerGuideSize;
  523. // If no combo items are left, remove the TriggerMacro from the pending list
  524. if ( comboLength == 0 )
  525. {
  526. return TriggerMacroEval_Remove;
  527. }
  528. // Check if this is a long Trigger Macro
  529. uint8_t longMacro = Macro_isLongTriggerMacro( macro );
  530. // Iterate through the items in the combo, voting the on the key state
  531. // If any of the pressed keys do not match, fail the macro
  532. //
  533. // The macro is waiting for input when in the TriggerMacro_Waiting state
  534. // Once all keys have been pressed/held (only those keys), entered TriggerMacro_Press state (passing)
  535. // Transition to the next combo (if it exists) when a single key is released (TriggerMacro_Release state)
  536. // On scan after position increment, change to TriggerMacro_Waiting state
  537. // TODO Add support for system LED states (NumLock, CapsLock, etc.)
  538. // TODO Add support for analog key states
  539. // TODO Add support for 0x00 Key state (not pressing a key, not all that useful in general)
  540. // TODO Add support for Press/Hold/Release differentiation when evaluating (not sure if useful)
  541. TriggerMacroVote overallVote = TriggerMacroVote_Invalid;
  542. for ( uint8_t comboItem = pos + 1; comboItem < pos + comboLength + 1; comboItem += TriggerGuideSize )
  543. {
  544. // Assign TriggerGuide element (key type, state and scancode)
  545. TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ comboItem ]);
  546. TriggerMacroVote vote = TriggerMacroVote_Invalid;
  547. // Iterate through the key buffer, comparing to each key in the combo
  548. for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
  549. {
  550. // Lookup key information
  551. TriggerGuide *keyInfo = &macroTriggerListBuffer[ key ];
  552. // If vote is a pass (>= 0x08, no more keys in the combo need to be looked at)
  553. // Also mask all of the non-passing votes
  554. vote |= longMacro
  555. ? Macro_evalLongTriggerMacroVote( keyInfo, guide )
  556. : Macro_evalShortTriggerMacroVote( keyInfo, guide );
  557. if ( vote >= TriggerMacroVote_Pass )
  558. {
  559. vote &= TriggerMacroVote_Release | TriggerMacroVote_PassRelease | TriggerMacroVote_Pass;
  560. break;
  561. }
  562. }
  563. // If no pass vote was found after scanning all of the keys
  564. // Fail the combo, if this is a short macro (long macros already will have a fail vote)
  565. if ( !longMacro && vote < TriggerMacroVote_Pass )
  566. vote |= TriggerMacroVote_Fail;
  567. // After voting, append to overall vote
  568. overallVote |= vote;
  569. }
  570. // If no pass vote was found after scanning the entire combo
  571. // And this is the first position in the combo, just remove it (nothing important happened)
  572. if ( longMacro && overallVote & TriggerMacroVote_DoNothingRelease && pos == 0 )
  573. overallVote |= TriggerMacroVote_Fail;
  574. // Decide new state of macro after voting
  575. // Fail macro, remove from pending list
  576. if ( overallVote & TriggerMacroVote_Fail )
  577. {
  578. return TriggerMacroEval_Remove;
  579. }
  580. // Do nothing, incorrect key is being held or released
  581. else if ( overallVote & TriggerMacroVote_DoNothing && longMacro )
  582. {
  583. // Just doing nothing :)
  584. }
  585. // If ready for transition and in Press state, set to Waiting and increment combo position
  586. // Position is incremented (and possibly remove the macro from the pending list) on the next iteration
  587. else if ( overallVote & TriggerMacroVote_Release && record->state == TriggerMacro_Press )
  588. {
  589. record->state = TriggerMacro_Release;
  590. // If this is the last combo in the sequence, remove from the pending list
  591. if ( macro->guide[ record->pos + macro->guide[ record->pos ] * TriggerGuideSize + 1 ] == 0 )
  592. return TriggerMacroEval_DoResultAndRemove;
  593. }
  594. // If passing and in Waiting state, set macro state to Press
  595. else if ( overallVote & TriggerMacroVote_Pass
  596. && ( record->state == TriggerMacro_Waiting || record->state == TriggerMacro_Press ) )
  597. {
  598. record->state = TriggerMacro_Press;
  599. // If in press state, and this is the final combo, send request for ResultMacro
  600. // Check to see if the result macro only has a single element
  601. // If this result macro has more than 1 key, only send once
  602. // TODO Add option to have long macro repeat rate
  603. if ( macro->guide[ pos + comboLength + 1 ] == 0 )
  604. {
  605. // Long result macro (more than 1 combo)
  606. if ( Macro_isLongResultMacro( &ResultMacroList[ macro->result ] ) )
  607. {
  608. // Only ever trigger result once, on press
  609. if ( overallVote == TriggerMacroVote_Pass )
  610. {
  611. return TriggerMacroEval_DoResultAndRemove;
  612. }
  613. }
  614. // Short result macro
  615. else
  616. {
  617. // Only trigger result once, on press, if long trigger (more than 1 combo)
  618. if ( Macro_isLongTriggerMacro( macro ) )
  619. {
  620. return TriggerMacroEval_DoResultAndRemove;
  621. }
  622. // Otherwise, trigger result continuously
  623. else
  624. {
  625. return TriggerMacroEval_DoResult;
  626. }
  627. }
  628. }
  629. }
  630. // Otherwise, just remove the macro on key release
  631. // One more result has to be called to indicate to the ResultMacro that the key transitioned to the release state
  632. else if ( overallVote & TriggerMacroVote_Release )
  633. {
  634. return TriggerMacroEval_DoResultAndRemove;
  635. }
  636. // If this is a short macro, just remove it
  637. // The state can be rebuilt on the next iteration
  638. if ( !longMacro )
  639. return TriggerMacroEval_Remove;
  640. return TriggerMacroEval_DoNothing;
  641. }
  642. // Evaluate/Update ResultMacro
  643. inline ResultMacroEval Macro_evalResultMacro( var_uint_t resultMacroIndex )
  644. {
  645. // Lookup ResultMacro
  646. const ResultMacro *macro = &ResultMacroList[ resultMacroIndex ];
  647. ResultMacroRecord *record = &ResultMacroRecordList[ resultMacroIndex ];
  648. // Current Macro position
  649. var_uint_t pos = record->pos;
  650. // Length of combo being processed
  651. uint8_t comboLength = macro->guide[ pos ];
  652. // Function Counter, used to keep track of the combo items processed
  653. var_uint_t funcCount = 0;
  654. // Combo Item Position within the guide
  655. var_uint_t comboItem = pos + 1;
  656. // Iterate through the Result Combo
  657. while ( funcCount < comboLength )
  658. {
  659. // Assign TriggerGuide element (key type, state and scancode)
  660. ResultGuide *guide = (ResultGuide*)(&macro->guide[ comboItem ]);
  661. // Do lookup on capability function
  662. void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ guide->index ].func);
  663. // Call capability
  664. capability( record->state, record->stateType, &guide->args );
  665. // Increment counters
  666. funcCount++;
  667. comboItem += ResultGuideSize( (ResultGuide*)(&macro->guide[ comboItem ]) );
  668. }
  669. // Move to next item in the sequence
  670. record->pos = comboItem;
  671. // If the ResultMacro is finished, remove
  672. if ( macro->guide[ comboItem ] == 0 )
  673. {
  674. record->pos = 0;
  675. return ResultMacroEval_Remove;
  676. }
  677. // Otherwise leave the macro in the list
  678. return ResultMacroEval_DoNothing;
  679. }
  680. // Update pending trigger list
  681. inline void Macro_updateTriggerMacroPendingList()
  682. {
  683. // Iterate over the macroTriggerListBuffer to add any new Trigger Macros to the pending list
  684. for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
  685. {
  686. // TODO LED States
  687. // TODO Analog Switches
  688. // Only add TriggerMacro to pending list if key was pressed (not held, released or off)
  689. if ( macroTriggerListBuffer[ key ].state == 0x00 && macroTriggerListBuffer[ key ].state != 0x01 )
  690. continue;
  691. // TODO Analog
  692. // If this is a release case, indicate to layer lookup for possible latch expiry
  693. uint8_t latch_expire = macroTriggerListBuffer[ key ].state == 0x03;
  694. // Lookup Trigger List
  695. nat_ptr_t *triggerList = Macro_layerLookup( macroTriggerListBuffer[ key ].scanCode, latch_expire );
  696. // Number of Triggers in list
  697. nat_ptr_t triggerListSize = triggerList[0];
  698. // Iterate over triggerList to see if any TriggerMacros need to be added
  699. // First item is the number of items in the TriggerList
  700. for ( var_uint_t macro = 1; macro < triggerListSize + 1; macro++ )
  701. {
  702. // Lookup trigger macro index
  703. var_uint_t triggerMacroIndex = triggerList[ macro ];
  704. // Iterate over macroTriggerMacroPendingList to see if any macro in the scancode's
  705. // triggerList needs to be added
  706. var_uint_t pending = 0;
  707. for ( ; pending < macroTriggerMacroPendingListSize; pending++ )
  708. {
  709. // Stop scanning if the trigger macro index is found in the pending list
  710. if ( macroTriggerMacroPendingList[ pending ] == triggerMacroIndex )
  711. break;
  712. }
  713. // If the triggerMacroIndex (macro) was not found in the macroTriggerMacroPendingList
  714. // Add it to the list
  715. if ( pending == macroTriggerMacroPendingListSize )
  716. {
  717. macroTriggerMacroPendingList[ macroTriggerMacroPendingListSize++ ] = triggerMacroIndex;
  718. // Reset macro position
  719. TriggerMacroRecordList[ triggerMacroIndex ].pos = 0;
  720. TriggerMacroRecordList[ triggerMacroIndex ].state = TriggerMacro_Waiting;
  721. }
  722. }
  723. }
  724. }
  725. // Macro Procesing Loop
  726. // Called once per USB buffer send
  727. inline void Macro_process()
  728. {
  729. // Only do one round of macro processing between Output Module timer sends
  730. if ( USBKeys_Sent != 0 )
  731. return;
  732. // If the pause flag is set, only process if the step counter is non-zero
  733. if ( macroPauseMode )
  734. {
  735. if ( macroStepCounter == 0 )
  736. return;
  737. // Proceed, decrementing the step counter
  738. macroStepCounter--;
  739. dbug_print("Macro Step");
  740. }
  741. // Update pending trigger list, before processing TriggerMacros
  742. Macro_updateTriggerMacroPendingList();
  743. // Tail pointer for macroTriggerMacroPendingList
  744. // Macros must be explicitly re-added
  745. var_uint_t macroTriggerMacroPendingListTail = 0;
  746. // Iterate through the pending TriggerMacros, processing each of them
  747. for ( var_uint_t macro = 0; macro < macroTriggerMacroPendingListSize; macro++ )
  748. {
  749. switch ( Macro_evalTriggerMacro( macroTriggerMacroPendingList[ macro ] ) )
  750. {
  751. // Trigger Result Macro (purposely falling through)
  752. case TriggerMacroEval_DoResult:
  753. // Append ResultMacro to PendingList
  754. Macro_appendResultMacroToPendingList( &TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ] );
  755. default:
  756. macroTriggerMacroPendingList[ macroTriggerMacroPendingListTail++ ] = macroTriggerMacroPendingList[ macro ];
  757. break;
  758. // Trigger Result Macro and Remove (purposely falling through)
  759. case TriggerMacroEval_DoResultAndRemove:
  760. // Append ResultMacro to PendingList
  761. Macro_appendResultMacroToPendingList( &TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ] );
  762. // Remove Macro from Pending List, nothing to do, removing by default
  763. case TriggerMacroEval_Remove:
  764. break;
  765. }
  766. }
  767. // Update the macroTriggerMacroPendingListSize with the tail pointer
  768. macroTriggerMacroPendingListSize = macroTriggerMacroPendingListTail;
  769. // Tail pointer for macroResultMacroPendingList
  770. // Macros must be explicitly re-added
  771. var_uint_t macroResultMacroPendingListTail = 0;
  772. // Iterate through the pending ResultMacros, processing each of them
  773. for ( var_uint_t macro = 0; macro < macroResultMacroPendingListSize; macro++ )
  774. {
  775. switch ( Macro_evalResultMacro( macroResultMacroPendingList[ macro ] ) )
  776. {
  777. // Re-add macros to pending list
  778. case ResultMacroEval_DoNothing:
  779. default:
  780. macroResultMacroPendingList[ macroResultMacroPendingListTail++ ] = macroResultMacroPendingList[ macro ];
  781. break;
  782. // Remove Macro from Pending List, nothing to do, removing by default
  783. case ResultMacroEval_Remove:
  784. break;
  785. }
  786. }
  787. // Update the macroResultMacroPendingListSize with the tail pointer
  788. macroResultMacroPendingListSize = macroResultMacroPendingListTail;
  789. // Signal buffer that we've used it
  790. Scan_finishedWithMacro( macroTriggerListBufferSize );
  791. // Reset TriggerList buffer
  792. macroTriggerListBufferSize = 0;
  793. // If Macro debug mode is set, clear the USB Buffer
  794. if ( macroDebugMode )
  795. {
  796. USBKeys_Modifiers = 0;
  797. USBKeys_Sent = 0;
  798. }
  799. }
  800. inline void Macro_setup()
  801. {
  802. // Register Macro CLI dictionary
  803. CLI_registerDictionary( macroCLIDict, macroCLIDictName );
  804. // Disable Macro debug mode
  805. macroDebugMode = 0;
  806. // Disable Macro pause flag
  807. macroPauseMode = 0;
  808. // Set Macro step counter to zero
  809. macroStepCounter = 0;
  810. // Make sure macro trigger buffer is empty
  811. macroTriggerListBufferSize = 0;
  812. // Initialize TriggerMacro states
  813. for ( var_uint_t macro = 0; macro < TriggerMacroNum; macro++ )
  814. {
  815. TriggerMacroRecordList[ macro ].pos = 0;
  816. TriggerMacroRecordList[ macro ].state = TriggerMacro_Waiting;
  817. }
  818. // Initialize ResultMacro states
  819. for ( var_uint_t macro = 0; macro < ResultMacroNum; macro++ )
  820. {
  821. ResultMacroRecordList[ macro ].pos = 0;
  822. ResultMacroRecordList[ macro ].state = 0;
  823. ResultMacroRecordList[ macro ].stateType = 0;
  824. }
  825. }
  826. // ----- CLI Command Functions -----
  827. void cliFunc_capList( char* args )
  828. {
  829. print( NL );
  830. info_msg("Capabilities List");
  831. printHex( CapabilitiesNum );
  832. // Iterate through all of the capabilities and display them
  833. for ( var_uint_t cap = 0; cap < CapabilitiesNum; cap++ )
  834. {
  835. print( NL "\t" );
  836. printHex( cap );
  837. print(" - ");
  838. // Display/Lookup Capability Name (utilize debug mode of capability)
  839. void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ cap ].func);
  840. capability( 0xFF, 0xFF, 0 );
  841. }
  842. }
  843. void cliFunc_capSelect( char* args )
  844. {
  845. // Parse code from argument
  846. char* curArgs;
  847. char* arg1Ptr;
  848. char* arg2Ptr = args;
  849. // Total number of args to scan (must do a lookup if a keyboard capability is selected)
  850. var_uint_t totalArgs = 2; // Always at least two args
  851. var_uint_t cap = 0;
  852. // Arguments used for keyboard capability function
  853. var_uint_t argSetCount = 0;
  854. uint8_t *argSet = (uint8_t*)args;
  855. // Process all args
  856. for ( var_uint_t c = 0; argSetCount < totalArgs; c++ )
  857. {
  858. curArgs = arg2Ptr;
  859. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  860. // Stop processing args if no more are found
  861. // Extra arguments are ignored
  862. if ( *arg1Ptr == '\0' )
  863. break;
  864. // For the first argument, choose the capability
  865. if ( c == 0 ) switch ( arg1Ptr[0] )
  866. {
  867. // Keyboard Capability
  868. case 'K':
  869. // Determine capability index
  870. cap = numToInt( &arg1Ptr[1] );
  871. // Lookup the number of args
  872. totalArgs += CapabilitiesList[ cap ].argCount;
  873. continue;
  874. }
  875. // Because allocating memory isn't doable, and the argument count is arbitrary
  876. // The argument pointer is repurposed as the argument list (much smaller anyways)
  877. argSet[ argSetCount++ ] = (uint8_t)numToInt( arg1Ptr );
  878. // Once all the arguments are prepared, call the keyboard capability function
  879. if ( argSetCount == totalArgs )
  880. {
  881. // Indicate that the capability was called
  882. print( NL );
  883. info_msg("K");
  884. printInt8( cap );
  885. print(" - ");
  886. printHex( argSet[0] );
  887. print(" - ");
  888. printHex( argSet[1] );
  889. print(" - ");
  890. printHex( argSet[2] );
  891. print( "..." NL );
  892. void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ cap ].func);
  893. capability( argSet[0], argSet[1], &argSet[2] );
  894. }
  895. }
  896. }
  897. void cliFunc_keyHold( char* args )
  898. {
  899. // Parse codes from arguments
  900. char* curArgs;
  901. char* arg1Ptr;
  902. char* arg2Ptr = args;
  903. // Process all args
  904. for ( ;; )
  905. {
  906. curArgs = arg2Ptr;
  907. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  908. // Stop processing args if no more are found
  909. if ( *arg1Ptr == '\0' )
  910. break;
  911. // Ignore non-Scancode numbers
  912. switch ( arg1Ptr[0] )
  913. {
  914. // Scancode
  915. case 'S':
  916. Macro_keyState( (uint8_t)numToInt( &arg1Ptr[1] ), 0x02 ); // Hold scancode
  917. break;
  918. }
  919. }
  920. }
  921. void cliFunc_keyPress( char* args )
  922. {
  923. // Parse codes from arguments
  924. char* curArgs;
  925. char* arg1Ptr;
  926. char* arg2Ptr = args;
  927. // Process all args
  928. for ( ;; )
  929. {
  930. curArgs = arg2Ptr;
  931. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  932. // Stop processing args if no more are found
  933. if ( *arg1Ptr == '\0' )
  934. break;
  935. // Ignore non-Scancode numbers
  936. switch ( arg1Ptr[0] )
  937. {
  938. // Scancode
  939. case 'S':
  940. Macro_keyState( (uint8_t)numToInt( &arg1Ptr[1] ), 0x01 ); // Press scancode
  941. break;
  942. }
  943. }
  944. }
  945. void cliFunc_keyRelease( char* args )
  946. {
  947. // Parse codes from arguments
  948. char* curArgs;
  949. char* arg1Ptr;
  950. char* arg2Ptr = args;
  951. // Process all args
  952. for ( ;; )
  953. {
  954. curArgs = arg2Ptr;
  955. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  956. // Stop processing args if no more are found
  957. if ( *arg1Ptr == '\0' )
  958. break;
  959. // Ignore non-Scancode numbers
  960. switch ( arg1Ptr[0] )
  961. {
  962. // Scancode
  963. case 'S':
  964. Macro_keyState( (uint8_t)numToInt( &arg1Ptr[1] ), 0x03 ); // Release scancode
  965. break;
  966. }
  967. }
  968. }
  969. void cliFunc_layerList( char* args )
  970. {
  971. print( NL );
  972. info_msg("Layer List");
  973. // Iterate through all of the layers and display them
  974. for ( uint16_t layer = 0; layer < LayerNum; layer++ )
  975. {
  976. print( NL "\t" );
  977. printHex( layer );
  978. print(" - ");
  979. // Display layer name
  980. dPrint( (char*)LayerIndex[ layer ].name );
  981. // Default map
  982. if ( layer == 0 )
  983. print(" \033[1m(default)\033[0m");
  984. // Layer State
  985. print( NL "\t\t Layer State: " );
  986. printHex( LayerState[ layer ] );
  987. // First -> Last Indices
  988. print(" First -> Last Indices: ");
  989. printHex( LayerIndex[ layer ].first );
  990. print(" -> ");
  991. printHex( LayerIndex[ layer ].last );
  992. }
  993. }
  994. void cliFunc_layerState( char* args )
  995. {
  996. // Parse codes from arguments
  997. char* curArgs;
  998. char* arg1Ptr;
  999. char* arg2Ptr = args;
  1000. uint8_t arg1 = 0;
  1001. uint8_t arg2 = 0;
  1002. // Process first two args
  1003. for ( uint8_t c = 0; c < 2; c++ )
  1004. {
  1005. curArgs = arg2Ptr;
  1006. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  1007. // Stop processing args if no more are found
  1008. if ( *arg1Ptr == '\0' )
  1009. break;
  1010. switch ( c )
  1011. {
  1012. // First argument (e.g. L1)
  1013. case 0:
  1014. if ( arg1Ptr[0] != 'L' )
  1015. return;
  1016. arg1 = (uint8_t)numToInt( &arg1Ptr[1] );
  1017. break;
  1018. // Second argument (e.g. 4)
  1019. case 1:
  1020. arg2 = (uint8_t)numToInt( arg1Ptr );
  1021. // Display operation (to indicate that it worked)
  1022. print( NL );
  1023. info_msg("Setting Layer L");
  1024. printInt8( arg1 );
  1025. print(" to - ");
  1026. printHex( arg2 );
  1027. // Set the layer state
  1028. LayerState[ arg1 ] = arg2;
  1029. break;
  1030. }
  1031. }
  1032. }
  1033. void cliFunc_macroDebug( char* args )
  1034. {
  1035. // Toggle macro debug mode
  1036. macroDebugMode = macroDebugMode ? 0 : 1;
  1037. print( NL );
  1038. info_msg("Macro Debug Mode: ");
  1039. printInt8( macroDebugMode );
  1040. }
  1041. void cliFunc_macroList( char* args )
  1042. {
  1043. // Show pending key events
  1044. print( NL );
  1045. info_msg("Pending Key Events: ");
  1046. printInt16( (uint16_t)macroTriggerListBufferSize );
  1047. print(" : ");
  1048. for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
  1049. {
  1050. printHex( macroTriggerListBuffer[ key ].scanCode );
  1051. print(" ");
  1052. }
  1053. // Show pending trigger macros
  1054. print( NL );
  1055. info_msg("Pending Trigger Macros: ");
  1056. printInt16( (uint16_t)macroTriggerMacroPendingListSize );
  1057. print(" : ");
  1058. for ( var_uint_t macro = 0; macro < macroTriggerMacroPendingListSize; macro++ )
  1059. {
  1060. printHex( macroTriggerMacroPendingList[ macro ] );
  1061. print(" ");
  1062. }
  1063. // Show pending result macros
  1064. print( NL );
  1065. info_msg("Pending Result Macros: ");
  1066. printInt16( (uint16_t)macroResultMacroPendingListSize );
  1067. print(" : ");
  1068. for ( var_uint_t macro = 0; macro < macroResultMacroPendingListSize; macro++ )
  1069. {
  1070. printHex( macroResultMacroPendingList[ macro ] );
  1071. print(" ");
  1072. }
  1073. // Show available trigger macro indices
  1074. print( NL );
  1075. info_msg("Trigger Macros Range: T0 -> T");
  1076. printInt16( (uint16_t)TriggerMacroNum - 1 ); // Hopefully large enough :P (can't assume 32-bit)
  1077. // Show available result macro indices
  1078. print( NL );
  1079. info_msg("Result Macros Range: R0 -> R");
  1080. printInt16( (uint16_t)ResultMacroNum - 1 ); // Hopefully large enough :P (can't assume 32-bit)
  1081. // Show Trigger to Result Macro Links
  1082. print( NL );
  1083. info_msg("Trigger : Result Macro Pairs");
  1084. for ( var_uint_t macro = 0; macro < TriggerMacroNum; macro++ )
  1085. {
  1086. print( NL );
  1087. print("\tT");
  1088. printInt16( (uint16_t)macro ); // Hopefully large enough :P (can't assume 32-bit)
  1089. print(" : R");
  1090. printInt16( (uint16_t)TriggerMacroList[ macro ].result ); // Hopefully large enough :P (can't assume 32-bit)
  1091. }
  1092. }
  1093. void cliFunc_macroProc( char* args )
  1094. {
  1095. // Toggle macro pause mode
  1096. macroPauseMode = macroPauseMode ? 0 : 1;
  1097. print( NL );
  1098. info_msg("Macro Processing Mode: ");
  1099. printInt8( macroPauseMode );
  1100. }
  1101. void macroDebugShowTrigger( var_uint_t index )
  1102. {
  1103. // Only proceed if the macro exists
  1104. if ( index >= TriggerMacroNum )
  1105. return;
  1106. // Trigger Macro Show
  1107. const TriggerMacro *macro = &TriggerMacroList[ index ];
  1108. TriggerMacroRecord *record = &TriggerMacroRecordList[ index ];
  1109. print( NL );
  1110. info_msg("Trigger Macro Index: ");
  1111. printInt16( (uint16_t)index ); // Hopefully large enough :P (can't assume 32-bit)
  1112. print( NL );
  1113. // Read the comboLength for combo in the sequence (sequence of combos)
  1114. var_uint_t pos = 0;
  1115. uint8_t comboLength = macro->guide[ pos ];
  1116. // Iterate through and interpret the guide
  1117. while ( comboLength != 0 )
  1118. {
  1119. // Initial position of the combo
  1120. var_uint_t comboPos = ++pos;
  1121. // Iterate through the combo
  1122. while ( pos < comboLength * TriggerGuideSize + comboPos )
  1123. {
  1124. // Assign TriggerGuide element (key type, state and scancode)
  1125. TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ pos ]);
  1126. // Display guide information about trigger key
  1127. printHex( guide->scanCode );
  1128. print("|");
  1129. printHex( guide->type );
  1130. print("|");
  1131. printHex( guide->state );
  1132. // Increment position
  1133. pos += TriggerGuideSize;
  1134. // Only show combo separator if there are combos left in the sequence element
  1135. if ( pos < comboLength * TriggerGuideSize + comboPos )
  1136. print("+");
  1137. }
  1138. // Read the next comboLength
  1139. comboLength = macro->guide[ pos ];
  1140. // Only show sequence separator if there is another combo to process
  1141. if ( comboLength != 0 )
  1142. print(";");
  1143. }
  1144. // Display current position
  1145. print( NL "Position: " );
  1146. printInt16( (uint16_t)record->pos ); // Hopefully large enough :P (can't assume 32-bit)
  1147. // Display result macro index
  1148. print( NL "Result Macro Index: " );
  1149. printInt16( (uint16_t)macro->result ); // Hopefully large enough :P (can't assume 32-bit)
  1150. // Display trigger macro state
  1151. print( NL "Trigger Macro State: " );
  1152. switch ( record->state )
  1153. {
  1154. case TriggerMacro_Press: print("Press"); break;
  1155. case TriggerMacro_Release: print("Release"); break;
  1156. case TriggerMacro_Waiting: print("Waiting"); break;
  1157. }
  1158. }
  1159. void macroDebugShowResult( var_uint_t index )
  1160. {
  1161. // Only proceed if the macro exists
  1162. if ( index >= ResultMacroNum )
  1163. return;
  1164. // Trigger Macro Show
  1165. const ResultMacro *macro = &ResultMacroList[ index ];
  1166. ResultMacroRecord *record = &ResultMacroRecordList[ index ];
  1167. print( NL );
  1168. info_msg("Result Macro Index: ");
  1169. printInt16( (uint16_t)index ); // Hopefully large enough :P (can't assume 32-bit)
  1170. print( NL );
  1171. // Read the comboLength for combo in the sequence (sequence of combos)
  1172. var_uint_t pos = 0;
  1173. uint8_t comboLength = macro->guide[ pos++ ];
  1174. // Iterate through and interpret the guide
  1175. while ( comboLength != 0 )
  1176. {
  1177. // Function Counter, used to keep track of the combos processed
  1178. var_uint_t funcCount = 0;
  1179. // Iterate through the combo
  1180. while ( funcCount < comboLength )
  1181. {
  1182. // Assign TriggerGuide element (key type, state and scancode)
  1183. ResultGuide *guide = (ResultGuide*)(&macro->guide[ pos ]);
  1184. // Display Function Index
  1185. printHex( guide->index );
  1186. print("|");
  1187. // Display Function Ptr Address
  1188. printHex( (nat_ptr_t)CapabilitiesList[ guide->index ].func );
  1189. print("|");
  1190. // Display/Lookup Capability Name (utilize debug mode of capability)
  1191. void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ guide->index ].func);
  1192. capability( 0xFF, 0xFF, 0 );
  1193. // Display Argument(s)
  1194. print("(");
  1195. for ( var_uint_t arg = 0; arg < CapabilitiesList[ guide->index ].argCount; arg++ )
  1196. {
  1197. // Arguments are only 8 bit values
  1198. printHex( (&guide->args)[ arg ] );
  1199. // Only show arg separator if there are args left
  1200. if ( arg + 1 < CapabilitiesList[ guide->index ].argCount )
  1201. print(",");
  1202. }
  1203. print(")");
  1204. // Increment position
  1205. pos += ResultGuideSize( guide );
  1206. // Increment function count
  1207. funcCount++;
  1208. // Only show combo separator if there are combos left in the sequence element
  1209. if ( funcCount < comboLength )
  1210. print("+");
  1211. }
  1212. // Read the next comboLength
  1213. comboLength = macro->guide[ pos++ ];
  1214. // Only show sequence separator if there is another combo to process
  1215. if ( comboLength != 0 )
  1216. print(";");
  1217. }
  1218. // Display current position
  1219. print( NL "Position: " );
  1220. printInt16( (uint16_t)record->pos ); // Hopefully large enough :P (can't assume 32-bit)
  1221. // Display final trigger state/type
  1222. print( NL "Final Trigger State (State/Type): " );
  1223. printHex( record->state );
  1224. print("/");
  1225. printHex( record->stateType );
  1226. }
  1227. void cliFunc_macroShow( char* args )
  1228. {
  1229. // Parse codes from arguments
  1230. char* curArgs;
  1231. char* arg1Ptr;
  1232. char* arg2Ptr = args;
  1233. // Process all args
  1234. for ( ;; )
  1235. {
  1236. curArgs = arg2Ptr;
  1237. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  1238. // Stop processing args if no more are found
  1239. if ( *arg1Ptr == '\0' )
  1240. break;
  1241. // Ignore invalid codes
  1242. switch ( arg1Ptr[0] )
  1243. {
  1244. // Indexed Trigger Macro
  1245. case 'T':
  1246. macroDebugShowTrigger( numToInt( &arg1Ptr[1] ) );
  1247. break;
  1248. // Indexed Result Macro
  1249. case 'R':
  1250. macroDebugShowResult( numToInt( &arg1Ptr[1] ) );
  1251. break;
  1252. }
  1253. }
  1254. }
  1255. void cliFunc_macroStep( char* args )
  1256. {
  1257. // Parse number from argument
  1258. // NOTE: Only first argument is used
  1259. char* arg1Ptr;
  1260. char* arg2Ptr;
  1261. CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
  1262. // Default to 1, if no argument given
  1263. var_uint_t count = (var_uint_t)numToInt( arg1Ptr );
  1264. if ( count == 0 )
  1265. count = 1;
  1266. // Set the macro step counter, negative int's are cast to uint
  1267. macroStepCounter = count;
  1268. }