diff --git a/radio/src/audio_arm.cpp b/radio/src/audio_arm.cpp index 63543b132..f587cad6c 100644 --- a/radio/src/audio_arm.cpp +++ b/radio/src/audio_arm.cpp @@ -421,9 +421,9 @@ bool isAudioFileReferenced(uint32_t i, char * filename) else if (category == PHASE_AUDIO_CATEGORY) { if (sdAvailablePhaseAudioFiles & MASK_PHASE_AUDIO_FILE(index, event)) { getPhaseAudioFile(filename, index, event); - return true; - } + return true; } + } else if (category == SWITCH_AUDIO_CATEGORY) { if (sdAvailableSwitchAudioFiles & MASK_SWITCH_AUDIO_FILE(index)) { getSwitchAudioFile(filename, index); @@ -433,9 +433,9 @@ bool isAudioFileReferenced(uint32_t i, char * filename) else if (category == LOGICAL_SWITCH_AUDIO_CATEGORY) { if (sdAvailableLogicalSwitchAudioFiles & MASK_LOGICAL_SWITCH_AUDIO_FILE(index, event)) { getLogicalSwitchAudioFile(filename, index, event); - return true; - } + return true; } + } return false; } @@ -445,6 +445,7 @@ tmr10ms_t timeAutomaticPromptsSilence = 0; void playModelEvent(uint8_t category, uint8_t index, uint8_t event) { char filename[AUDIO_FILENAME_MAXLEN+1]; + TRACE("playModelEvent(): cat: %u, idx: %u, evt:%u", (uint32_t)category, (uint32_t)index, (uint32_t)event); if (IS_SILENCE_PERIOD_ELAPSED() && isAudioFileReferenced((category << 24) + (index << 16) + event, filename)) { audioQueue.playFile(filename); } diff --git a/radio/src/gtests.cpp b/radio/src/gtests.cpp index 7a0b4132f..ddfff10ad 100644 --- a/radio/src/gtests.cpp +++ b/radio/src/gtests.cpp @@ -45,16 +45,25 @@ void doMixerCalculations(); #define MODEL_RESET() \ memset(&g_model, 0, sizeof(g_model)); \ extern uint8_t s_mixer_first_run_done; \ - s_mixer_first_run_done = false; + s_mixer_first_run_done = false; \ + s_last_phase = 255; -#define MIXER_RESET() \ - memset(channelOutputs, 0, sizeof(channelOutputs)); \ - memset(ex_chans, 0, sizeof(ex_chans)); \ - memset(act, 0, sizeof(act)); \ - memset(swOn, 0, sizeof(swOn)); \ - int32_t lastAct = 0; lastAct = lastAct; /* to avoid a warning */ \ - s_last_switch_used = 0; \ +int32_t lastAct = 0; +void MIXER_RESET() +{ + memset(channelOutputs, 0, sizeof(channelOutputs)); + memset(ex_chans, 0, sizeof(ex_chans)); + memset(act, 0, sizeof(act)); + memset(swOn, 0, sizeof(swOn)); +#if !defined(CPUARM) + s_last_switch_used = 0; s_last_switch_value = 0; +#endif + s_current_mixer_flight_mode = s_last_phase = 0; + lastAct = 0; + logicalSwitchesReset(); +} + uint16_t anaInValues[NUM_STICKS+NUM_POTS] = { 0 }; uint16_t anaIn(uint8_t chan) @@ -309,6 +318,8 @@ TEST(getSwitch, circularCSW) MIXER_RESET(); g_model.logicalSw[0] = { SWSRC_SW1, SWSRC_SW1, LS_FUNC_OR }; g_model.logicalSw[1] = { SWSRC_SW1, SWSRC_SW1, LS_FUNC_AND }; + + evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(-SWSRC_SW1), true); EXPECT_EQ(getSwitch(SWSRC_SW2), false); @@ -330,19 +341,23 @@ TEST(getSwitch, recursiveSW) g_model.logicalSw[0] = { SWSRC_RUD, -SWSRC_SW2, LS_FUNC_OR }; g_model.logicalSw[1] = { SWSRC_ELE, -SWSRC_SW1, LS_FUNC_OR }; + evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), true); - s_last_switch_used = 0; + LS_RECURSIVE_EVALUATION_RESET(); + evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), true); simuSetSwitch(1, 1); - s_last_switch_used = 0; + LS_RECURSIVE_EVALUATION_RESET(); + evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), true); EXPECT_EQ(getSwitch(SWSRC_SW2), true); - s_last_switch_used = 0; + LS_RECURSIVE_EVALUATION_RESET(); + evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), true); EXPECT_EQ(getSwitch(SWSRC_SW2), false); } diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index f6e4e9e56..d019b5353 100755 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -525,6 +525,8 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) { evalInputs(mode); + evalLogicalSwitches(mode==e_perout_mode_normal); + #if defined(MODULE_ALWAYS_SEND_PULSES) checkStartupWarnings(); #endif @@ -910,6 +912,7 @@ int32_t sum_chans512[NUM_CHNOUT] = {0}; #define MAX_ACT 0xffff +uint8_t s_last_phase = 255; // TODO reinit everything here when the model changes, no??? void evalMixes(uint8_t tick10ms) { @@ -920,10 +923,9 @@ void evalMixes(uint8_t tick10ms) static uint16_t fp_act[MAX_FLIGHT_MODES] = {0}; static uint16_t delta = 0; static ACTIVE_PHASES_TYPE s_fade_flight_phases = 0; - static uint8_t s_last_phase = 255; // TODO reinit everything here when the model changes, no??? - - s_last_switch_used = 0; + LS_RECURSIVE_EVALUATION_RESET(); + uint8_t phase = getFlightPhase(); if (s_last_phase != phase) { @@ -945,6 +947,9 @@ void evalMixes(uint8_t tick10ms) fp_act[s_last_phase] = 0; fp_act[phase] = MAX_ACT; } +#if defined(CPUARM) + logicalSwitchesCopyState(s_last_phase, phase); // push last logical switches state from old to new phase +#endif } s_last_phase = phase; } @@ -953,7 +958,7 @@ void evalMixes(uint8_t tick10ms) if (s_fade_flight_phases) { memclear(sum_chans512, sizeof(sum_chans512)); for (uint8_t p=0; p> 4) * fp_act[p]; weight += fp_act[p]; } - s_last_switch_used = 0; + LS_RECURSIVE_EVALUATION_RESET(); } assert(weight); s_current_mixer_flight_mode = phase; diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 8d994e69f..cb9866428 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1520,9 +1520,12 @@ void flightReset() #if defined(FRSKY) telemetryReset(); #endif - lswReset(); + logicalSwitchesReset(); +#if !defined(CPUARM) s_last_switch_value = 0; +#endif + s_mixer_first_run_done = false; START_SILENCE_PERIOD(); @@ -2221,7 +2224,7 @@ void doMixerCalculations() s_cnt_100ms -= 10; s_cnt_1s += 1; - lswTimerTick(); + logicalSwitchesTimerTick(); if (s_cnt_1s >= 10) { // 1sec s_cnt_1s -= 10; diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 49348366a..2611bd1b0 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -671,6 +671,7 @@ enum StartupWarningStates { #endif extern uint8_t s_current_mixer_flight_mode; +extern uint8_t s_last_phase; #if defined(CPUARM) #define bitfield_channels_t uint32_t @@ -693,8 +694,20 @@ NOINLINE void per10ms(); getvalue_t getValue(uint8_t i); bool getSwitch(int8_t swtch); -void lswTimerTick(); -void lswReset(); +void logicalSwitchesTimerTick(); +void logicalSwitchesReset(); + +#if defined(CPUARM) +void evalLogicalSwitches(bool isCurrentPhase=true); +void logicalSwitchesCopyState(uint8_t src, uint8_t dst); +#define LS_RECURSIVE_EVALUATION_RESET() +#else +#define evalLogicalSwitches(xxx) +#define GETSWITCH_RECURSIVE_TYPE uint16_t +extern volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_used; +extern volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_value; +#define LS_RECURSIVE_EVALUATION_RESET() s_last_switch_used = 0 +#endif #if defined(PCBTARANIS) void getSwitchesPosition(bool startup); @@ -817,15 +830,6 @@ extern int8_t safetyCh[NUM_CHNOUT]; extern uint8_t trimsCheckTimer; -#if defined(CPUARM) - #define GETSWITCH_RECURSIVE_TYPE uint32_t -#else - #define GETSWITCH_RECURSIVE_TYPE uint16_t -#endif - -extern volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_used; -extern volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_value; - #define TMR_OFF 0 #define TMR_RUNNING 1 #define TMR_NEGATIVE 2 diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index 5e4c970b2..091e01d1a 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -36,20 +36,39 @@ #include "opentx.h" -#if defined(CPUARM) - #define GETSWITCH_RECURSIVE_TYPE uint32_t -#else - #define GETSWITCH_RECURSIVE_TYPE uint16_t -#endif - #define CS_LAST_VALUE_INIT -32768 + +#if defined(CPUARM) + +enum LogicalSwitchContextState { + SWITCH_START, + SWITCH_DELAY, + SWITCH_ENABLE +}; + +PACK(typedef struct { + uint8_t state:1; + uint8_t timerState:2; + uint8_t spare:5; + uint8_t timer; + int16_t lastValue; +}) LogicalSwitchContext; + +PACK(typedef struct { + LogicalSwitchContext lsw[NUM_LOGICAL_SWITCH]; +}) LogicalSwitchesFlightModeContext; +LogicalSwitchesFlightModeContext lswFm[MAX_FLIGHT_MODES]; + +#define LS_LAST_VALUE(fm, idx) lswFm[fm].lsw[idx].lastValue + +#else + +int16_t lsLastValue[NUM_LOGICAL_SWITCH]; +#define LS_LAST_VALUE(fm, idx) lsLastValue[idx] + volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_used = 0; volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_value = 0; -#if defined(CPUARM) -uint32_t lswDelays[NUM_LOGICAL_SWITCH]; -uint32_t lswDurations[NUM_LOGICAL_SWITCH]; -uint8_t lswStates[NUM_LOGICAL_SWITCH]; #endif #if defined(PCBTARANIS) @@ -157,10 +176,182 @@ void getSwitchesPosition(bool startup) #define SWITCH_POSITION(idx) switchState((EnumKeys)(SW_BASE+(idx))) #endif -int16_t lsLastValue[NUM_LOGICAL_SWITCH]; -#define CS_LAST_VALUE_INIT -32768 +bool getLogicalSwitch(uint8_t idx) +{ + LogicalSwitchData * ls = lswAddress(idx); + bool result; + +#if defined(CPUARM) + int8_t s = ls->andsw; +#else + uint8_t s = ls->andsw; + if (s > SWSRC_LAST_SWITCH) { + s += SWSRC_SW1-SWSRC_LAST_SWITCH-1; + } +#endif + + if (ls->func == LS_FUNC_NONE || (s && !getSwitch(s))) { + LS_LAST_VALUE(s_current_mixer_flight_mode, idx) = CS_LAST_VALUE_INIT; + result = false; + } + else if ((s=lswFamily(ls->func)) == LS_FAMILY_BOOL) { + bool res1 = getSwitch(ls->v1); + bool res2 = getSwitch(ls->v2); + switch (ls->func) { + case LS_FUNC_AND: + result = (res1 && res2); + break; + case LS_FUNC_OR: + result = (res1 || res2); + break; + // case LS_FUNC_XOR: + default: + result = (res1 ^ res2); + break; + } + } + else if (s == LS_FAMILY_TIMER) { + result = (LS_LAST_VALUE(s_current_mixer_flight_mode, idx) <= 0); + } + else if (s == LS_FAMILY_STICKY) { + result = (LS_LAST_VALUE(s_current_mixer_flight_mode, idx) & (1<<0)); + } +#if defined(CPUARM) + else if (s == LS_FAMILY_STAY) { + result = (LS_LAST_VALUE(s_current_mixer_flight_mode, idx) & (1<<0)); + } +#endif + else { + getvalue_t x = getValue(ls->v1); + getvalue_t y; + if (s == LS_FAMILY_COMP) { + y = getValue(ls->v2); + + switch (ls->func) { + case LS_FUNC_EQUAL: + result = (x==y); + break; + case LS_FUNC_GREATER: + result = (x>y); + break; + default: + result = (xv1; +#if defined(FRSKY) + // Telemetry + if (v1 >= MIXSRC_FIRST_TELEM) { + if ((!TELEMETRY_STREAMING() && v1 >= MIXSRC_FIRST_TELEM+TELEM_FIRST_STREAMED_VALUE-1) || IS_FAI_FORBIDDEN(v1-1)) + return false; + + y = convertLswTelemValue(ls); + +#if defined(FRSKY_HUB) && defined(GAUGES) + if (s == LS_FAMILY_OFS) { + uint8_t idx = v1-MIXSRC_FIRST_TELEM+1-TELEM_ALT; + if (idx < THLD_MAX) { + // Fill the threshold array + barsThresholds[idx] = 128 + ls->v2; + } + } +#endif + } + else if (v1 >= MIXSRC_GVAR1) { + y = ls->v2; + } + else { + y = calc100toRESX(ls->v2); + } +#else + if (v1 >= MIXSRC_FIRST_TELEM) { + y = (int16_t)3 * (128+ls->v2); // it's a Timer + } + else if (v1 >= MIXSRC_GVAR1) { + y = ls->v2; // it's a GVAR + } + else { + y = calc100toRESX(ls->v2); + } +#endif + + switch (ls->func) { +#if defined(CPUARM) + case LS_FUNC_VEQUAL: + result = (x==y); + break; +#endif + case LS_FUNC_VALMOSTEQUAL: +#if defined(GVARS) + if (v1 >= MIXSRC_GVAR1 && v1 <= MIXSRC_LAST_GVAR) + result = (x==y); + else +#endif + result = (abs(x-y) < (1024 / STICK_TOLERANCE)); + break; + case LS_FUNC_VPOS: + result = (x>y); + break; + case LS_FUNC_VNEG: + result = (xy); + break; + case LS_FUNC_ANEG: + result = (abs(x)func == LS_FUNC_DIFFEGREATER) + result = (y >= 0 ? (diff >= y) : (diff <= y)); + else + result = (abs(diff) >= y); + if (result) + LS_LAST_VALUE(s_current_mixer_flight_mode, idx) = x; + break; + } + } + } + } + +#if defined(CPUARM) + if (ls->delay || ls->duration) { + LogicalSwitchContext &context = lswFm[s_current_mixer_flight_mode].lsw[idx]; + if (result) { + if (context.timerState == SWITCH_START) { + // set delay timer + context.timerState = SWITCH_DELAY; + context.timer = ls->delay; + } + if (context.timerState == SWITCH_DELAY) { + if (context.timer) { + result = false; //return false while delay timer running + } + else if (ls->duration) { + // set duration timer + context.timerState = SWITCH_ENABLE; + context.timer = ls->duration; + } + } + else if (context.timerState == SWITCH_ENABLE) { + result = (context.timer > 0); //return false after duration timer runs out + } + } + else { + context.timerState = SWITCH_START; + } + } +#endif + + return result; +} -/* recursive function. stack as of today (16/03/2012) grows by 8bytes at each call, which is ok! */ bool getSwitch(int8_t swtch) { bool result; @@ -221,192 +412,51 @@ bool getSwitch(int8_t swtch) #endif else { cs_idx -= SWSRC_FIRST_LOGICAL_SWITCH; - +#if defined(CPUARM) + result = lswFm[s_current_mixer_flight_mode].lsw[cs_idx].state; +#else GETSWITCH_RECURSIVE_TYPE mask = ((GETSWITCH_RECURSIVE_TYPE)1 << cs_idx); if (s_last_switch_used & mask) { result = (s_last_switch_value & mask); } else { s_last_switch_used |= mask; - - LogicalSwitchData * ls = lswAddress(cs_idx); -#if defined(CPUARM) - int8_t s = ls->andsw; -#else - uint8_t s = ls->andsw; - if (s > SWSRC_LAST_SWITCH) { - s += SWSRC_SW1-SWSRC_LAST_SWITCH-1; - } -#endif - if (ls->func == LS_FUNC_NONE || (s && !getSwitch(s))) { - lsLastValue[cs_idx] = CS_LAST_VALUE_INIT; - result = false; - } - else if ((s=lswFamily(ls->func)) == LS_FAMILY_BOOL) { - bool res1 = getSwitch(ls->v1); - bool res2 = getSwitch(ls->v2); - switch (ls->func) { - case LS_FUNC_AND: - result = (res1 && res2); - break; - case LS_FUNC_OR: - result = (res1 || res2); - break; - // case LS_FUNC_XOR: - default: - result = (res1 ^ res2); - break; - } - } - else if (s == LS_FAMILY_TIMER) { - result = (lsLastValue[cs_idx] <= 0); - } - else if (s == LS_FAMILY_STICKY) { - result = (lsLastValue[cs_idx] & (1<<0)); - } -#if defined(CPUARM) - else if (s == LS_FAMILY_STAY) { - result = (lsLastValue[cs_idx] & (1<<0)); - } -#endif - else { - getvalue_t x = getValue(ls->v1); - getvalue_t y; - if (s == LS_FAMILY_COMP) { - y = getValue(ls->v2); - - switch (ls->func) { - case LS_FUNC_EQUAL: - result = (x==y); - break; - case LS_FUNC_GREATER: - result = (x>y); - break; - default: - result = (xv1; -#if defined(FRSKY) - // Telemetry - if (v1 >= MIXSRC_FIRST_TELEM) { - if ((!TELEMETRY_STREAMING() && v1 >= MIXSRC_FIRST_TELEM+TELEM_FIRST_STREAMED_VALUE-1) || IS_FAI_FORBIDDEN(v1-1)) - return swtch > 0 ? false : true; - - y = convertLswTelemValue(ls); - -#if defined(FRSKY_HUB) && defined(GAUGES) - if (s == LS_FAMILY_OFS) { - uint8_t idx = v1-MIXSRC_FIRST_TELEM+1-TELEM_ALT; - if (idx < THLD_MAX) { - // Fill the threshold array - barsThresholds[idx] = 128 + ls->v2; - } - } -#endif - } - else if (v1 >= MIXSRC_GVAR1) { - y = ls->v2; - } - else { - y = calc100toRESX(ls->v2); - } -#else - if (v1 >= MIXSRC_FIRST_TELEM) { - y = (int16_t)3 * (128+ls->v2); // it's a Timer - } - else if (v1 >= MIXSRC_GVAR1) { - y = ls->v2; // it's a GVAR - } - else { - y = calc100toRESX(ls->v2); - } -#endif - - switch (ls->func) { -#if defined(CPUARM) - case LS_FUNC_VEQUAL: - result = (x==y); - break; -#endif - case LS_FUNC_VALMOSTEQUAL: -#if defined(GVARS) - if (v1 >= MIXSRC_GVAR1 && v1 <= MIXSRC_LAST_GVAR) - result = (x==y); - else -#endif - result = (abs(x-y) < (1024 / STICK_TOLERANCE)); - break; - case LS_FUNC_VPOS: - result = (x>y); - break; - case LS_FUNC_VNEG: - result = (xy); - break; - case LS_FUNC_ANEG: - result = (abs(x)func == LS_FUNC_DIFFEGREATER) - result = (y >= 0 ? (diff >= y) : (diff <= y)); - else - result = (abs(diff) >= y); - if (result) - lsLastValue[cs_idx] = x; - break; - } - } - } - } - -#if defined(CPUARM) - if (ls->delay) { - if (result) { - if (lswDelays[cs_idx] > get_tmr10ms()) - result = false; - } - else { - lswDelays[cs_idx] = get_tmr10ms() + (ls->delay*10); - } - } - - if (ls->duration) { - if (result && !lswStates[cs_idx]) { - lswDurations[cs_idx] = get_tmr10ms() + (ls->duration*10); - } - - lswStates[cs_idx] = result; - result = false; - - if (lswDurations[cs_idx] > get_tmr10ms()) { - result = true; - } - } -#endif - + result = getLogicalSwitch(cs_idx); if (result) { - if (!(s_last_switch_value&mask)) PLAY_LOGICAL_SWITCH_ON(cs_idx); s_last_switch_value |= mask; } else { - if (s_last_switch_value&mask) PLAY_LOGICAL_SWITCH_OFF(cs_idx); s_last_switch_value &= ~mask; } - } + } +#endif } return swtch > 0 ? result : !result; } +#if defined(CPUARM) +/** + @brief Calculates new state of logical switches for s_current_mixer_flight_mode +*/ +void evalLogicalSwitches(bool isCurrentPhase) +{ + for (unsigned int idx=0; idxfunc == LS_FUNC_TIMER) { - int16_t *lastValue = &lsLastValue[i]; - if (*lastValue == 0 || *lastValue == CS_LAST_VALUE_INIT) { - *lastValue = -lswTimerValue(ls->v1); +void logicalSwitchesTimerTick() +{ +#if defined(CPUARM) + for (uint8_t fm=0; fmfunc == LS_FUNC_TIMER) { + int16_t *lastValue = &LS_LAST_VALUE(fm, i); + if (*lastValue == 0 || *lastValue == CS_LAST_VALUE_INIT) { + *lastValue = -lswTimerValue(ls->v1); + } + else if (*lastValue < 0) { + if (++(*lastValue) == 0) + *lastValue = lswTimerValue(ls->v2); + } + else { // if (*lastValue > 0) + *lastValue -= 1; + } } - else if (*lastValue < 0) { - if (++(*lastValue) == 0) - *lastValue = lswTimerValue(ls->v2); - } - else { // if (*lastValue > 0) - *lastValue -= 1; - } - } - else if (ls->func == LS_FUNC_STICKY) { - PACK(typedef struct { - uint8_t state; - uint8_t last; - }) ls_sticky_struct; - ls_sticky_struct & lastValue = (ls_sticky_struct &)lsLastValue[i]; - bool before = lastValue.last & 0x01; - if (lastValue.state) { - bool now = getSwitch(ls->v2); - if (now != before) { - lastValue.last ^= 1; - if (!before) { - lastValue.state = 0; + else if (ls->func == LS_FUNC_STICKY) { + PACK(typedef struct { + uint8_t state; + uint8_t last; + }) ls_sticky_struct; + ls_sticky_struct & lastValue = (ls_sticky_struct &)LS_LAST_VALUE(fm, i); + bool before = lastValue.last & 0x01; + if (lastValue.state) { + bool now = getSwitch(ls->v2); + if (now != before) { + lastValue.last ^= 1; + if (!before) { + lastValue.state = 0; + } + } + } + else { + bool now = getSwitch(ls->v1); + if (before != now) { + lastValue.last ^= 1; + if (!before) { + lastValue.state = 1; + } } } } - else { - bool now = getSwitch(ls->v1); - if (before != now) { - lastValue.last ^= 1; - if (!before) { - lastValue.state = 1; - } +#if defined(CPUARM) + else if (ls->func == LS_FUNC_STAY) { + PACK(typedef struct { + uint16_t state:1; + uint16_t duration:15; + }) ls_stay_struct; + + ls_stay_struct & lastValue = (ls_stay_struct &)LS_LAST_VALUE(fm, i); + lastValue.state = false; + bool state = getSwitch(ls->v1); + if (state) { + if (ls->v3 == 0 && lastValue.duration == lswTimerValue(ls->v2)) + lastValue.state = true; + if (lastValue.duration < 1000) + lastValue.duration++; + } + else { + if (lastValue.duration > lswTimerValue(ls->v2) && lastValue.duration <= lswTimerValue(ls->v2+ls->v3)) + lastValue.state = true; + lastValue.duration = 0; } } + + // decrement delay/duration timer + LogicalSwitchContext &context = lswFm[fm].lsw[i]; + if (context.timer) { + context.timer--; + } +#endif } #if defined(CPUARM) - else if (ls->func == LS_FUNC_STAY) { - PACK(typedef struct { - uint16_t state:1; - uint16_t duration:15; - }) ls_stay_struct; - - ls_stay_struct & lastValue = (ls_stay_struct &)lsLastValue[i]; - lastValue.state = false; - bool state = getSwitch(ls->v1); - if (state) { - if (ls->v3 == 0 && lastValue.duration == lswTimerValue(ls->v2)) - lastValue.state = true; - if (lastValue.duration < 1000) - lastValue.duration++; - } - else { - if (lastValue.duration > lswTimerValue(ls->v2) && lastValue.duration <= lswTimerValue(ls->v2+ls->v3)) - lastValue.state = true; - lastValue.duration = 0; - } - } + } #endif - } } LogicalSwitchData *lswAddress(uint8_t idx) @@ -695,10 +756,17 @@ int16_t lswTimerValue(delayval_t val) return (val < -109 ? 129+val : (val < 7 ? (113+val)*5 : (53+val)*10)); } -void lswReset() { - for (uint8_t i=0; i