wii_anal_keys.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include <stdbool.h>
  2. #include "bc_logging.h"
  3. #include "wii_anal.h"
  4. //+============================================================================ ========================================
  5. // Stop Calibration mode
  6. //
  7. static void calStop(state_t* const state) {
  8. state->hold = 0; // stop calibration mode
  9. state->calib &= ~(CAL_RANGE | CAL_NOTJOY); // ...
  10. }
  11. //+============================================================================ ========================================
  12. // Change to another scene
  13. //
  14. void sceneSet(state_t* const state, const scene_t scene) {
  15. calStop(state); // Stop software calibration
  16. state->scenePrev = state->scene; // Remember where we came from
  17. state->scene = scene; // Go to new scene
  18. INFO("Scene : %d -> %d", state->scenePrev, state->scene);
  19. }
  20. //+============================================================================ ========================================
  21. // Change to an easter egg scene
  22. //
  23. static void sceneSetEgg(state_t* const state, const scene_t scene) {
  24. calStop(state); // Stop software calibration
  25. state->scenePegg = state->scene; // Remember where we came from
  26. state->scene = scene; // Go to new scene
  27. INFO("Scene* : %d => %d", state->scenePegg, state->scene);
  28. }
  29. //+============================================================================ ========================================
  30. // Several EC screens have 'peak-hold' and 'calibration' features
  31. // Enabling peak-hold on screen with no peak meters will have no effect
  32. // So, to avoid code duplication...
  33. //
  34. bool key_calib(const eventMsg_t* const msg, state_t* const state) {
  35. int used = false; // assume key is NOT-handled
  36. switch(msg->input.type) {
  37. case InputTypeShort: //# <! After InputTypeRelease within INPUT_LONG_PRESS interval
  38. switch(msg->input.key) {
  39. case InputKeyUp: //# <U [ SHORT-UP ]
  40. state->hold = (state->hold == +1) ? 0 : +1; // toggle peak hold
  41. used = true;
  42. break;
  43. case InputKeyDown: //# <D [ SHORT-DOWN ]
  44. state->hold = (state->hold == -1) ? 0 : -1; // toggle trough hold
  45. used = true;
  46. break;
  47. case InputKeyOk: //# <O [ SHORT-OK ]
  48. if(state->calib & CAL_RANGE)
  49. calStop(state); // STOP softare calibration
  50. else
  51. ecCalibrate(&state->ec, CAL_CENTRE); // perform centre calibration
  52. used = true;
  53. break;
  54. default:
  55. break;
  56. }
  57. break;
  58. case InputTypeLong: //# >! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease
  59. switch(msg->input.key) {
  60. case InputKeyOk: //# >O [ LONG-OK ]
  61. ecCalibrate(&state->ec, CAL_RESET | CAL_CENTRE); // START software calibration
  62. state->hold = 0;
  63. state->calib |= CAL_RANGE;
  64. state->flash = 8; // start with flash ON
  65. used = true;
  66. break;
  67. default:
  68. break;
  69. }
  70. break;
  71. default:
  72. break;
  73. }
  74. return used;
  75. }
  76. //+============================================================================ ========================================
  77. // WAIT screen
  78. //
  79. static inline bool wait_key(const eventMsg_t* const msg, state_t* const state) {
  80. int used = false; // assume key is NOT-handled
  81. if(msg->input.type == InputTypeShort) {
  82. switch(msg->input.key) {
  83. case InputKeyLeft: //# <L [ SHORT-LEFT ]
  84. timerEn(state, false); // Stop the timer
  85. sceneSetEgg(state, SCENE_SPLASH);
  86. used = true;
  87. break;
  88. case InputKeyUp: //# <U [ SHORT-UP ]
  89. timerEn(state, false); // Stop the timer
  90. sceneSetEgg(state, SCENE_RIP);
  91. used = true;
  92. break;
  93. case InputKeyBack: //# <B [ SHORT-BACK ]
  94. state->run = false;
  95. used = true;
  96. break;
  97. default:
  98. break;
  99. }
  100. }
  101. return used;
  102. }
  103. //+============================================================================ ========================================
  104. // DEBUG screen
  105. //
  106. static inline bool debug_key(const eventMsg_t* const msg, state_t* const state) {
  107. int used = false; // assume key is NOT-handled
  108. switch(msg->input.type) {
  109. case InputTypeShort: //# <! After InputTypeRelease within INPUT_LONG_PRESS interval
  110. switch(msg->input.key) {
  111. case InputKeyUp: { //# <U [ SHORT-UP ]
  112. bool init =
  113. ecInit(&state->ec, NULL); // Initialise the controller //! NULL = no encryption
  114. (void)init; // in case INFO is optimised out
  115. INFO("%s : %s", __func__, (init ? "init OK" : "init fail"));
  116. used = true;
  117. break;
  118. }
  119. case InputKeyOk: //# <O [ SHORT-OK ]
  120. if(ecRead(&state->ec) == 0) { // Read the controller
  121. INFO(
  122. "%s : joy: {%02X,%02X,%02X,%02X,%02X,%02X}",
  123. __func__,
  124. state->ec.joy[0],
  125. state->ec.joy[1],
  126. state->ec.joy[2],
  127. state->ec.joy[3],
  128. state->ec.joy[4],
  129. state->ec.joy[5]);
  130. }
  131. used = true;
  132. break;
  133. case InputKeyDown: //# <D [ SHORT-DOWN ]
  134. timerEn(state, true); // restart the timer
  135. sceneSet(state, state->scenePrev);
  136. used = true;
  137. break;
  138. case InputKeyBack: //# <B [ SHORT-BACK ]
  139. state->run = false;
  140. used = true;
  141. break;
  142. default:
  143. break; //# <?
  144. }
  145. break;
  146. default:
  147. break;
  148. }
  149. return used;
  150. }
  151. //+============================================================================ ========================================
  152. // SPLASH and RIP screen
  153. //
  154. static inline bool splash_key(const eventMsg_t* const msg, state_t* const state) {
  155. // Back key on the initial SPLASH screen (this will catch the InputKeyPress)
  156. if((msg->input.key == InputKeyBack) && (state->scenePrev == SCENE_NONE)) state->run = false;
  157. // ANY-other-KEY press
  158. if(msg->input.type == InputTypeShort) {
  159. timerEn(state, true); // Restart the timer
  160. state->scene = state->scenePegg;
  161. }
  162. return true;
  163. }
  164. //+============================================================================ ========================================
  165. // "_pre" allows the plugin to use the key before the active scene gets a chance
  166. //
  167. static inline bool key_pre(const eventMsg_t* const msg, state_t* const state) {
  168. (void)msg;
  169. (void)state;
  170. return false;
  171. }
  172. //+============================================================================ ========================================
  173. // "_post" allows the plugin to use a key if it was not used by the active scene
  174. //
  175. static inline bool key_post(const eventMsg_t* const msg, state_t* const state) {
  176. int used = false; // assume key is NOT-handled
  177. if(msg->input.key == InputKeyBack) {
  178. if(msg->input.type == InputTypeShort) { //# <B [SHORT-BACK]
  179. state->ec.init = false; // reset/disconnect the controller
  180. sceneSet(state, SCENE_WAIT);
  181. used = true;
  182. } else if(msg->input.type == InputTypeLong) { //# >B [LONG-BACK]
  183. state->run = false; // Signal the plugin to exit
  184. used = true;
  185. }
  186. }
  187. // Easter eggs
  188. switch(state->scene) {
  189. case SCENE_SPLASH: // Scenes that do NOT offer Easter eggs
  190. case SCENE_RIP:
  191. case SCENE_DEBUG:
  192. break;
  193. default:
  194. if(msg->input.type == InputTypeLong) {
  195. switch(msg->input.key) {
  196. case InputKeyDown: //# >D [LONG-DOWN]
  197. timerEn(state, false); // Stop the timer
  198. sceneSetEgg(state, SCENE_DEBUG);
  199. used = true;
  200. break;
  201. case InputKeyLeft: //# >L [ LONG-LEFT ]
  202. timerEn(state, false); // Stop the timer
  203. sceneSetEgg(state, SCENE_SPLASH);
  204. used = true;
  205. break;
  206. case InputKeyUp: //# >U [ LONG-UP ]
  207. timerEn(state, false); // Stop the timer
  208. sceneSetEgg(state, SCENE_RIP);
  209. used = true;
  210. break;
  211. default:
  212. break;
  213. }
  214. }
  215. break;
  216. }
  217. return used;
  218. }
  219. //+============================================================================ ========================================
  220. // Handle a key press event
  221. //
  222. bool evKey(const eventMsg_t* const msg, state_t* const state) {
  223. furi_assert(msg);
  224. furi_assert(state);
  225. bool used = key_pre(msg, state);
  226. if(!used) switch(state->scene) {
  227. case SCENE_SPLASH: //...
  228. case SCENE_RIP:
  229. used = splash_key(msg, state);
  230. break;
  231. case SCENE_WAIT:
  232. used = wait_key(msg, state);
  233. break;
  234. case SCENE_DEBUG:
  235. used = debug_key(msg, state);
  236. break;
  237. default:
  238. if(state->ec.pidx >= PID_ERROR) {
  239. ERROR("%s : bad PID = %d", __func__, state->ec.pidx);
  240. } else {
  241. if((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].keys)
  242. ecId[PID_UNKNOWN].keys(msg, state);
  243. else
  244. ecId[state->ec.pidx].keys(msg, state);
  245. }
  246. break;
  247. case SCENE_NONE:
  248. break;
  249. }
  250. if(!used) used = key_post(msg, state);
  251. return used;
  252. }