wii_anal_keys.c 9.0 KB

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