Skip to content

Commit

Permalink
fix(radio): Mix delay not working when mix line has a switch (#4364)
Browse files Browse the repository at this point in the history
  • Loading branch information
philmoz authored Dec 21, 2023
1 parent 178fabd commit b53ccfa
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 39 deletions.
6 changes: 2 additions & 4 deletions radio/src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,15 @@ enum MainRequest {

extern uint8_t mainRequestFlags;

#define DELAY_POS_MARGIN 3

PACK(struct SwOn {
PACK(struct MixState {
uint16_t delay:14; // max = 2550
uint8_t activeMix:1;
uint8_t activeExpo:1;
int16_t now; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
int16_t prev;
});

extern SwOn swOn[MAX_MIXERS];
extern MixState mixState[MAX_MIXERS];
extern int32_t act[MAX_MIXERS];

// static variables used in evalFlightModeMixes - moved here so they don't interfere with the stack
Expand Down
83 changes: 52 additions & 31 deletions radio/src/mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "hal/trainer_driver.h"
#include "hal/switch_driver.h"

#define DELAY_POS_MARGIN 3

uint8_t s_mixer_first_run_done = false;

int8_t virtualInputsTrims[MAX_INPUTS];
Expand All @@ -38,8 +40,8 @@ int16_t trims[MAX_TRIMS] = {0};
int32_t chans[MAX_OUTPUT_CHANNELS] = {0};
BeepANACenter bpanaCenter = 0;

int32_t act [MAX_MIXERS] = {0};
SwOn swOn [MAX_MIXERS]; // TODO better name later...
int32_t act [MAX_MIXERS] = {0};
MixState mixState [MAX_MIXERS];

uint8_t mixWarning;

Expand Down Expand Up @@ -158,7 +160,7 @@ void applyExpos(int16_t * anas, uint8_t mode, uint8_t ovwrIdx, int16_t ovwrValue
int8_t cur_chn = -1;

for (uint8_t i=0; i<MAX_EXPOS; i++) {
if (mode == e_perout_mode_normal) swOn[i].activeExpo = false;
if (mode == e_perout_mode_normal) mixState[i].activeExpo = false;
ExpoData * ed = expoAddress(i);
if (!EXPO_VALID(ed)) break; // end of list
if (ed->chn == cur_chn)
Expand All @@ -180,7 +182,7 @@ void applyExpos(int16_t * anas, uint8_t mode, uint8_t ovwrIdx, int16_t ovwrValue
v = limit<int32_t>(-1024, v, 1024);
}
if (EXPO_MODE_ENABLE(ed, v)) {
if (mode == e_perout_mode_normal) swOn[i].activeExpo = true;
if (mode == e_perout_mode_normal) mixState[i].activeExpo = true;
cur_chn = ed->chn;

//========== CURVE=================
Expand Down Expand Up @@ -635,7 +637,7 @@ static inline bitfield_channels_t channel_dirty(bitfield_channels_t mask, uint16

static inline bitfield_channels_t upper_channels_mask(uint16_t ch)
{
// take the 2's complement to generate a bit pattern
// take the 1's complement to generate a bit pattern
// that has all bits of 'ch' order and above set
//
// Examples (mask for max 8 channels):
Expand Down Expand Up @@ -731,12 +733,15 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms)
uint8_t lv_mixWarning = 0;
bitfield_channels_t dirtyChannels = all_channels_dirty;

// Calculate locally and then copy to mixState array - prevent UI seeing phantom values while calculating
bool activeMixes[MAX_MIXERS];

do {
bitfield_channels_t passDirtyChannels = 0;

for (uint8_t i=0; i<MAX_MIXERS; i++) {
if (mode == e_perout_mode_normal && pass == 0)
swOn[i].activeMix = 0;
activeMixes[i] = 0;

MixData * md = mixAddress(i);

Expand All @@ -757,22 +762,26 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms)
chans[md->destCh] = 0;

//========== FLIGHT MODE && SWITCH =====
bool mixCondition = (md->flightModes != 0 || md->swtch);
bool fmEnabled = (md->flightModes & (1 << mixerCurrentFlightMode)) == 0;
bool mixLineActive = fmEnabled && getSwitch(md->swtch);
delayval_t mixEnabled = (mixLineActive) ? DELAY_POS_MARGIN+1 : 0;

if (mixLineActive) {
// disable mixer using trainer channels if not connected
if (md->srcRaw >= MIXSRC_FIRST_TRAINER &&
md->srcRaw <= MIXSRC_LAST_TRAINER && !is_trainer_connected()) {
mixLineActive = false;
mixCondition = true;
mixEnabled = 0;
}

#if defined(LUA_MODEL_SCRIPTS)
// disable mixer if Lua script is used as source and script was killed
if (md->srcRaw >= MIXSRC_FIRST_LUA && md->srcRaw <= MIXSRC_LAST_LUA) {
div_t qr = div(md->srcRaw - MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS);
if (scriptInternalData[qr.quot].state != SCRIPT_OK) {
mixLineActive = false;
mixCondition = true;
mixEnabled = 0;
}
}
#endif
Expand All @@ -782,8 +791,10 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms)
getvalue_t v = 0;

if (mode > e_perout_mode_inactive_flight_mode) {
if (!mixLineActive) continue;
v = getValue(md->srcRaw);
if (mixEnabled)
v = getValue(md->srcRaw);
else
continue;
} else {
mixsrc_t srcRaw = md->srcRaw;
v = getValue(srcRaw);
Expand Down Expand Up @@ -811,43 +822,51 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms)
}
}
}
if (!mixCondition)
mixEnabled = v;
}

bool applyOffsetAndCurve = true;

//========== DELAYS ===============
delayval_t _swOn = swOn[i].now;
delayval_t _swPrev = swOn[i].prev;

delayval_t v_active = mixLineActive ? v : 0;
delayval_t _swOn = mixState[i].now;
delayval_t _swPrev = mixState[i].prev;
bool swTog = (mixEnabled > _swOn+DELAY_POS_MARGIN || mixEnabled < _swOn-DELAY_POS_MARGIN);

bool swTog = (v_active > _swOn + DELAY_POS_MARGIN || v_active < _swOn - DELAY_POS_MARGIN);
if (mode == e_perout_mode_normal && swTog) {
if (!swOn[i].delay) { swOn[i].prev = _swOn; }
swOn[i].now = v_active;
swOn[i].delay = (v_active > _swOn ? md->delayUp : md->delayDown) * 10;
if (!mixState[i].delay)
_swPrev = _swOn;
mixState[i].delay = (mixEnabled > _swOn ? md->delayUp : md->delayDown) * 10;
mixState[i].now = mixEnabled;
mixState[i].prev = _swPrev;
}
if (mode == e_perout_mode_normal && swOn[i].delay > 0) {
swOn[i].delay = max<int16_t>(0, (int16_t)swOn[i].delay - tick10ms);
v = _swPrev;
if (mode == e_perout_mode_normal && mixState[i].delay > 0) {
mixState[i].delay = max<int16_t>(0, (int16_t)mixState[i].delay - tick10ms);
// Freeze value until delay expires
if (!mixCondition)
v = _swPrev;
else if (mixEnabled)
continue;
}
else {
if (mode == e_perout_mode_normal) {
swOn[i].now = swOn[i].prev = v_active;
mixState[i].now = mixState[i].prev = mixEnabled;
}
if (!mixLineActive) {
if (!mixEnabled) {
if ((md->speedDown || md->speedUp) && md->mltpx != MLTPX_REPL) {
v = (md->mltpx == MLTPX_ADD ? 0 : RESX);
applyOffsetAndCurve = false;
} else {
if (mixCondition) {
v = (md->mltpx == MLTPX_ADD ? 0 : RESX);
applyOffsetAndCurve = false;
}
} else if (mixCondition) {
continue;
}
}
}

if (mode == e_perout_mode_normal && (mixLineActive || swOn[i].delay)) {
if (mode == e_perout_mode_normal && (!mixCondition || mixEnabled || mixState[i].delay)) {
if (md->mixWarn) lv_mixWarning |= 1 << (md->mixWarn - 1);
swOn[i].activeMix = true;
activeMixes[i] = true;
}

if (applyOffsetAndCurve) {
Expand Down Expand Up @@ -932,8 +951,8 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms)
case MLTPX_REPL:
*ptr = dv;
if (mode == e_perout_mode_normal) {
for (uint8_t m=i-1; m<MAX_MIXERS && mixAddress(m)->destCh==md->destCh; m--)
swOn[m].activeMix = false;
for (int8_t m = i - 1; m >= 0 && mixAddress(m)->destCh == md->destCh; m--)
activeMixes[m] = false;
}
break;
case MLTPX_MUL:
Expand Down Expand Up @@ -987,14 +1006,16 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms)
// *ptr=limit( int32_t(int32_t(-1)<<23), *ptr, int32_t(int32_t(1)<<23)); // limit code cost 72 bytes
// *ptr=limit( int32_t((-32767+RESXl)<<8), *ptr, int32_t((32767-RESXl)<<8)); // limit code cost 80 bytes
#endif

} //endfor mixers

tick10ms = 0;
dirtyChannels &= passDirtyChannels;

} while (++pass < 5 && dirtyChannels);

for (uint8_t i=0; i<MAX_MIXERS; i++)
mixState[i].activeMix = activeMixes[i];

mixWarning = lv_mixWarning;
}

Expand Down
4 changes: 2 additions & 2 deletions radio/src/opentx.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,12 +461,12 @@ void moveTrimsToOffsets();

inline bool isExpoActive(uint8_t expo)
{
return swOn[expo].activeExpo;
return mixState[expo].activeExpo;
}

inline bool isMixActive(uint8_t mix)
{
return swOn[mix].activeMix;
return mixState[mix].activeMix;
}

enum FunctionsActive {
Expand Down
2 changes: 1 addition & 1 deletion radio/src/tests/gtests.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ inline void MIXER_RESET()
memset(chans, 0, sizeof(chans));
memset(ex_chans, 0, sizeof(ex_chans));
memset(act, 0, sizeof(act));
memset(swOn, 0, sizeof(swOn));
memset(mixState, 0, sizeof(mixState));
mixerCurrentFlightMode = lastFlightMode = 0;
lastAct = 0;
logicalSwitchesReset();
Expand Down
2 changes: 1 addition & 1 deletion radio/src/tests/mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ TEST_F(MixerTest, DelayOnSwitch2)
g_model.mixData[0].mltpx = MLTPX_ADD;
g_model.mixData[0].srcRaw = MIXSRC_FIRST_SWITCH;
g_model.mixData[0].weight = 100;
g_model.mixData[0].swtch = SWSRC_ON;
// g_model.mixData[0].swtch = SWSRC_ON;
g_model.mixData[0].delayUp = 50;
g_model.mixData[0].delayDown = 50;

Expand Down

0 comments on commit b53ccfa

Please sign in to comment.