mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-25 03:29:58 -07:00
302 lines
9.4 KiB
C
302 lines
9.4 KiB
C
#include <stdbool.h>
|
|
|
|
#include "bc_logging.h"
|
|
|
|
#include "wii_anal.h"
|
|
|
|
//+============================================================================ ========================================
|
|
// Stop Calibration mode
|
|
//
|
|
static void calStop(state_t* const state) {
|
|
state->hold = 0; // stop calibration mode
|
|
state->calib &= ~(CAL_RANGE | CAL_NOTJOY); // ...
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// Change to another scene
|
|
//
|
|
void sceneSet(state_t* const state, const scene_t scene) {
|
|
calStop(state); // Stop software calibration
|
|
state->scenePrev = state->scene; // Remember where we came from
|
|
state->scene = scene; // Go to new scene
|
|
INFO("Scene : %d -> %d", state->scenePrev, state->scene);
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// Change to an easter egg scene
|
|
//
|
|
static void sceneSetEgg(state_t* const state, const scene_t scene) {
|
|
calStop(state); // Stop software calibration
|
|
state->scenePegg = state->scene; // Remember where we came from
|
|
state->scene = scene; // Go to new scene
|
|
INFO("Scene* : %d => %d", state->scenePegg, state->scene);
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// Several EC screens have 'peak-hold' and 'calibration' features
|
|
// Enabling peak-hold on screen with no peak meters will have no effect
|
|
// So, to avoid code duplication...
|
|
//
|
|
bool key_calib(const eventMsg_t* const msg, state_t* const state) {
|
|
int used = false; // assume key is NOT-handled
|
|
|
|
switch(msg->input.type) {
|
|
case InputTypeShort: //# <! After InputTypeRelease within INPUT_LONG_PRESS interval
|
|
switch(msg->input.key) {
|
|
case InputKeyUp: //# <U [ SHORT-UP ]
|
|
state->hold = (state->hold == +1) ? 0 : +1; // toggle peak hold
|
|
used = true;
|
|
break;
|
|
|
|
case InputKeyDown: //# <D [ SHORT-DOWN ]
|
|
state->hold = (state->hold == -1) ? 0 : -1; // toggle trough hold
|
|
used = true;
|
|
break;
|
|
|
|
case InputKeyOk: //# <O [ SHORT-OK ]
|
|
if(state->calib & CAL_RANGE)
|
|
calStop(state); // STOP softare calibration
|
|
else
|
|
ecCalibrate(&state->ec, CAL_CENTRE); // perform centre calibration
|
|
used = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case InputTypeLong: //# >! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease
|
|
switch(msg->input.key) {
|
|
case InputKeyOk: //# >O [ LONG-OK ]
|
|
ecCalibrate(&state->ec, CAL_RESET | CAL_CENTRE); // START software calibration
|
|
state->hold = 0;
|
|
state->calib |= CAL_RANGE;
|
|
state->flash = 8; // start with flash ON
|
|
used = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return used;
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// WAIT screen
|
|
//
|
|
static inline bool wait_key(const eventMsg_t* const msg, state_t* const state) {
|
|
int used = false; // assume key is NOT-handled
|
|
|
|
if(msg->input.type == InputTypeShort) {
|
|
switch(msg->input.key) {
|
|
case InputKeyLeft: //# <L [ SHORT-LEFT ]
|
|
timerEn(state, false); // Stop the timer
|
|
sceneSetEgg(state, SCENE_SPLASH);
|
|
used = true;
|
|
break;
|
|
|
|
case InputKeyUp: //# <U [ SHORT-UP ]
|
|
timerEn(state, false); // Stop the timer
|
|
sceneSetEgg(state, SCENE_RIP);
|
|
used = true;
|
|
break;
|
|
|
|
case InputKeyBack: //# <B [ SHORT-BACK ]
|
|
state->run = false;
|
|
used = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return used;
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// DEBUG screen
|
|
//
|
|
static inline bool debug_key(const eventMsg_t* const msg, state_t* const state) {
|
|
int used = false; // assume key is NOT-handled
|
|
|
|
switch(msg->input.type) {
|
|
case InputTypeShort: //# <! After InputTypeRelease within INPUT_LONG_PRESS interval
|
|
switch(msg->input.key) {
|
|
case InputKeyUp: { //# <U [ SHORT-UP ]
|
|
bool init =
|
|
ecInit(&state->ec, NULL); // Initialise the controller //! NULL = no encryption
|
|
(void)init; // in case INFO is optimised out
|
|
INFO("%s : %s", __func__, (init ? "init OK" : "init fail"));
|
|
used = true;
|
|
break;
|
|
}
|
|
|
|
case InputKeyOk: //# <O [ SHORT-OK ]
|
|
if(ecRead(&state->ec) == 0) { // Read the controller
|
|
INFO(
|
|
"%s : joy: {%02X,%02X,%02X,%02X,%02X,%02X}",
|
|
__func__,
|
|
state->ec.joy[0],
|
|
state->ec.joy[1],
|
|
state->ec.joy[2],
|
|
state->ec.joy[3],
|
|
state->ec.joy[4],
|
|
state->ec.joy[5]);
|
|
}
|
|
used = true;
|
|
break;
|
|
|
|
case InputKeyDown: //# <D [ SHORT-DOWN ]
|
|
timerEn(state, true); // restart the timer
|
|
sceneSet(state, state->scenePrev);
|
|
used = true;
|
|
break;
|
|
|
|
case InputKeyBack: //# <B [ SHORT-BACK ]
|
|
state->run = false;
|
|
used = true;
|
|
break;
|
|
|
|
default:
|
|
break; //# <?
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return used;
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// SPLASH and RIP screen
|
|
//
|
|
static inline bool splash_key(const eventMsg_t* const msg, state_t* const state) {
|
|
// Back key on the initial SPLASH screen (this will catch the InputKeyPress)
|
|
if((msg->input.key == InputKeyBack) && (state->scenePrev == SCENE_NONE)) state->run = false;
|
|
|
|
// ANY-other-KEY press
|
|
if(msg->input.type == InputTypeShort) {
|
|
timerEn(state, true); // Restart the timer
|
|
state->scene = state->scenePegg;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// "_pre" allows the plugin to use the key before the active scene gets a chance
|
|
//
|
|
static inline bool key_pre(const eventMsg_t* const msg, state_t* const state) {
|
|
(void)msg;
|
|
(void)state;
|
|
|
|
return false;
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// "_post" allows the plugin to use a key if it was not used by the active scene
|
|
//
|
|
static inline bool key_post(const eventMsg_t* const msg, state_t* const state) {
|
|
int used = false; // assume key is NOT-handled
|
|
|
|
if(msg->input.key == InputKeyBack) {
|
|
if(msg->input.type == InputTypeShort) { //# <B [SHORT-BACK]
|
|
state->ec.init = false; // reset/disconnect the controller
|
|
sceneSet(state, SCENE_WAIT);
|
|
used = true;
|
|
|
|
} else if(msg->input.type == InputTypeLong) { //# >B [LONG-BACK]
|
|
state->run = false; // Signal the plugin to exit
|
|
used = true;
|
|
}
|
|
}
|
|
|
|
// Easter eggs
|
|
switch(state->scene) {
|
|
case SCENE_SPLASH: // Scenes that do NOT offer Easter eggs
|
|
case SCENE_RIP:
|
|
case SCENE_DEBUG:
|
|
break;
|
|
default:
|
|
if(msg->input.type == InputTypeLong) {
|
|
switch(msg->input.key) {
|
|
case InputKeyDown: //# >D [LONG-DOWN]
|
|
timerEn(state, false); // Stop the timer
|
|
sceneSetEgg(state, SCENE_DEBUG);
|
|
used = true;
|
|
break;
|
|
|
|
case InputKeyLeft: //# >L [ LONG-LEFT ]
|
|
timerEn(state, false); // Stop the timer
|
|
sceneSetEgg(state, SCENE_SPLASH);
|
|
used = true;
|
|
break;
|
|
|
|
case InputKeyUp: //# >U [ LONG-UP ]
|
|
timerEn(state, false); // Stop the timer
|
|
sceneSetEgg(state, SCENE_RIP);
|
|
used = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return used;
|
|
}
|
|
|
|
//+============================================================================ ========================================
|
|
// Handle a key press event
|
|
//
|
|
bool evKey(const eventMsg_t* const msg, state_t* const state) {
|
|
furi_assert(msg);
|
|
furi_assert(state);
|
|
|
|
bool used = key_pre(msg, state);
|
|
|
|
if(!used) switch(state->scene) {
|
|
case SCENE_SPLASH: //...
|
|
case SCENE_RIP:
|
|
used = splash_key(msg, state);
|
|
break;
|
|
|
|
case SCENE_WAIT:
|
|
used = wait_key(msg, state);
|
|
break;
|
|
case SCENE_DEBUG:
|
|
used = debug_key(msg, state);
|
|
break;
|
|
|
|
default:
|
|
if(state->ec.pidx >= PID_ERROR) {
|
|
ERROR("%s : bad PID = %d", __func__, state->ec.pidx);
|
|
} else {
|
|
if((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].keys)
|
|
ecId[PID_UNKNOWN].keys(msg, state);
|
|
else
|
|
ecId[state->ec.pidx].keys(msg, state);
|
|
}
|
|
break;
|
|
|
|
case SCENE_NONE:
|
|
break;
|
|
}
|
|
|
|
if(!used) used = key_post(msg, state);
|
|
|
|
return used;
|
|
}
|