diff --git a/src/eeprom_arm.cpp b/src/eeprom_arm.cpp index 4cef83788..da33df48a 100644 --- a/src/eeprom_arm.cpp +++ b/src/eeprom_arm.cpp @@ -409,7 +409,7 @@ void eeLoadModel(uint8_t id) memclear(lastFunctionTime, sizeof(lastFunctionTime)); for (uint8_t i=0; imode, m_posHorz==0 ? attr : 0); - putsTime(MODEL_SETUP_2ND_COLUMN+5*FW-2, y, timer->start, m_posHorz==1 ? attr : 0, m_posHorz==2 ? attr : 0); -#if defined(CPUARM) || defined(PCBGRUVIN9X) - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW-1, y, g_model.timers[k-ITEM_MODEL_TIMER1].remanent ? 'R' : '-', m_posHorz==3 ? attr : 0); -#endif - if (attr && (editMode>0 || p1valdiff)) { - div_t qr = div(timer->start, 60); - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, timer->mode, -2*(MAX_PSWITCH+NUM_CSW)-1, TMR_VAROFS+2*(MAX_PSWITCH+NUM_CSW)); - break; - case 1: - CHECK_INCDEC_MODELVAR_ZERO(event, qr.quot, 59); - timer->start = qr.rem + qr.quot*60; - break; - case 2: - qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62)-2; - timer->start -= qr.rem ; - if ((int16_t)timer->start < 0) timer->start=0; - break; -#if defined(CPUARM) || defined(PCBGRUVIN9X) - case 3: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.timers[k-ITEM_MODEL_TIMER1].remanent, 1); - break; -#endif + TimerData *timer = &g_model.timers[k>=ITEM_MODEL_TIMER2 ? 1 : 0]; + if (k==ITEM_MODEL_TIMER1_MINUTE_BEEP || k==ITEM_MODEL_TIMER2_MINUTE_BEEP) { + timer->minuteBeep = onoffMenuItem(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); + } + else if (k==ITEM_MODEL_TIMER1_COUNTDOWN_BEEP || k==ITEM_MODEL_TIMER2_COUNTDOWN_BEEP) { + timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event); + } + else { + putsStrIdx(0*FW, y, STR_TIMER, k>=ITEM_MODEL_TIMER2 ? 2 : 1); + putsTmrMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, m_posHorz==0 ? attr : 0); + putsTime(MODEL_SETUP_2ND_COLUMN+5*FW-2, y, timer->start, m_posHorz==1 ? attr : 0, m_posHorz==2 ? attr : 0); + if (attr && (editMode>0 || p1valdiff)) { + div_t qr = div(timer->start, 60); + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, timer->mode, -2*(MAX_PSWITCH+NUM_CSW)-1, TMR_VAROFS+2*(MAX_PSWITCH+NUM_CSW)); + break; + case 1: + CHECK_INCDEC_MODELVAR_ZERO(event, qr.quot, 59); + timer->start = qr.rem + qr.quot*60; + break; + case 2: + qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62)-2; + timer->start -= qr.rem ; + if ((int16_t)timer->start < 0) timer->start=0; + break; + } } } break; } +#if defined(CPUARM) || defined(PCBGRUVIN9X) + case ITEM_MODEL_TIMER1_PERSISTENT: + case ITEM_MODEL_TIMER2_PERSISTENT: + { + TimerData &timer = g_model.timers[k==ITEM_MODEL_TIMER2_PERSISTENT]; + timer.persistent = onoffMenuItem(timer.persistent, MODEL_SETUP_2ND_COLUMN, y, PSTR(INDENT"Persist."), attr, event); + break; + } +#endif + case ITEM_MODEL_EXTENDED_LIMITS: g_model.extendedLimits = onoffMenuItem(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event); break; diff --git a/src/myeeprom.h b/src/myeeprom.h index 194a21228..0c3a91ce8 100644 --- a/src/myeeprom.h +++ b/src/myeeprom.h @@ -173,8 +173,7 @@ PACK(typedef struct t_EEGeneral { uint8_t spare2:1; uint8_t inactivityTimer; uint8_t throttleReversed:1; - uint8_t minuteBeep:1; - uint8_t preBeep:1; + uint8_t spare3:2; SPLASH_MODE; /* 3bits */ int8_t hapticMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all uint8_t blOffBright:4; @@ -992,14 +991,20 @@ enum MixSources { #if defined(PCBGRUVIN9X) || defined(CPUARM) PACK(typedef struct t_TimerData { int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw - uint16_t start; - uint16_t remanent:1; - uint16_t value:15; + uint16_t start:12; + uint16_t countdownBeep:1; + uint16_t minuteBeep:1; + uint16_t persistent:1; + uint16_t spare:1; + uint16_t value; }) TimerData; #else PACK(typedef struct t_TimerData { int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw - uint16_t start; + uint16_t start:12; + uint16_t countdownBeep:1; + uint16_t minuteBeep:1; + uint16_t spare:2; }) TimerData; #endif diff --git a/src/open9x.cpp b/src/open9x.cpp index b35a1648b..47ca40795 100644 --- a/src/open9x.cpp +++ b/src/open9x.cpp @@ -292,7 +292,7 @@ void per10ms() // These moved here from perOut() to improve beep trigger reliability. #if defined(PWM_BACKLIGHT) - if (g_tmr10ms % 4 == 0) + if ((g_tmr10ms&0x03) == 0x00) fadeBacklight(); // increment or decrement brightness until target brightness is reached #endif @@ -338,7 +338,7 @@ CurveInfo curveinfo(uint8_t idx) result.crv = curveaddress(idx); int8_t *next = curveaddress(idx+1); uint8_t size = next - result.crv; - if (size % 2 == 0) { + if ((size & 1) == 0) { result.points = (size / 2) + 1; result.custom = true; } @@ -854,12 +854,15 @@ bool __getSwitch(int8_t swtch) } #endif } + else if (cs->v1 >= MIXSRC_GVAR1) { + y = cs->v2; + } else { y = calc100toRESX(cs->v2); } #else - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - y = cs->v2; // it's a timer + if (cs->v1 >= MIXSRC_GVAR1) { + y = cs->v2; // it's a GVAR or a Timer } else { y = calc100toRESX(cs->v2); @@ -1214,12 +1217,13 @@ void putsTelemetryValue(xcoord_t x, uint8_t y, lcdint_t val, uint8_t unit, uint8 } #endif -#define INAC_DEVISOR 512 // Bypass splash screen with stick movement +#define INAC_DEVISOR 512 // bypass splash screen with stick movement +#define INAC_DEV_SHIFT 9 // shift right value for stick movement uint16_t stickMoveValue() { uint16_t sum = 0; - for (uint8_t i=0; i<4; i++) - sum += anaIn(i)/INAC_DEVISOR; + for (uint8_t i=0; i> INAC_DEV_SHIFT; return sum; } @@ -1586,7 +1590,7 @@ uint8_t checkTrim(uint8_t event) after = TRIM_MAX; if (after < TRIM_MIN) after = TRIM_MIN; - after /= 4; + after >>= 2; after += 60; #endif @@ -1772,7 +1776,6 @@ static uint8_t lastSwPos[2] = {0, 0}; static uint16_t s_cnt[2] = {0, 0}; static uint16_t s_sum[2] = {0, 0}; static uint8_t sw_toggled[2] = {false, false}; -static uint16_t s_time_cum_16[2] = {0, 0}; #if defined(THRTRACE) uint8_t s_traceBuf[MAXTRACE]; @@ -1843,7 +1846,7 @@ BeepANACenter evalSticks(uint8_t mode) if (g_model.swashR.value) { uint32_t v = (int32_t(calibratedStick[ELE_STICK])*calibratedStick[ELE_STICK] + int32_t(calibratedStick[AIL_STICK])*calibratedStick[AIL_STICK]); - uint32_t q = int32_t(RESX)*g_model.swashR.value/100; + uint32_t q = calc100toRESX(g_model.swashR.value); q *= q; if (v>q) d = isqrt32(v); @@ -1923,8 +1926,8 @@ BeepANACenter evalSticks(uint8_t mode) } #ifdef HELI - if(d && (ch==ELE_STICK || ch==AIL_STICK)) - v = int32_t(v)*g_model.swashR.value*RESX/(int32_t(d)*100); + if (d && (ch==ELE_STICK || ch==AIL_STICK)) + v = (int32_t(v)*calc100toRESX(g_model.swashR.value))/int32_t(d); #endif rawAnas[ch] = v; @@ -1963,8 +1966,6 @@ PLAY_FUNCTION(playValue, uint8_t idx) { int16_t val = getValue(idx); - // TODO add the MIXSRC_TELEM_TM1 and so on. - switch (idx) { case MIXSRC_FIRST_TELEM-1+TELEM_TX_VOLTAGE-1: PLAY_NUMBER(val, 1+UNIT_VOLTS, PREC1); @@ -2051,7 +2052,7 @@ PLAY_FUNCTION(playValue, uint8_t idx) default: { uint8_t unit = 1; - if (idx < MIXSRC_FIRST_TELEM-1+TELEM_TM1-1) + if (idx < MIXSRC_GVAR1) val = calcRESXto100(val); if (idx >= MIXSRC_FIRST_TELEM-1+TELEM_ALT-1 && idx <= MIXSRC_FIRST_TELEM-1+TELEM_GPSALT-1) unit = idx - (MIXSRC_FIRST_TELEM-1+TELEM_ALT-1); @@ -2396,13 +2397,13 @@ void perOut(uint8_t mode, uint8_t tick10ms) if(g_model.swashR.value) { uint32_t v = ((int32_t)anas[ELE_STICK]*anas[ELE_STICK] + (int32_t)anas[AIL_STICK]*anas[AIL_STICK]); - uint32_t q = (int32_t)RESX*g_model.swashR.value/100; + uint32_t q = calc100toRESX(g_model.swashR.value); q *= q; - if(v>q) - { + if (v>q) { uint16_t d = isqrt32(v); - anas[ELE_STICK] = (int32_t)anas[ELE_STICK]*g_model.swashR.value*RESX/((int32_t)d*100); - anas[AIL_STICK] = (int32_t)anas[AIL_STICK]*g_model.swashR.value*RESX/((int32_t)d*100); + int16_t tmp = calc100toRESX(g_model.swashR.value); + anas[ELE_STICK] = (int32_t) anas[ELE_STICK]*tmp/d; + anas[AIL_STICK] = (int32_t) anas[AIL_STICK]*tmp/d; } } @@ -2769,7 +2770,7 @@ void doMixerCalculations() s_perout_flight_phase = p; perOut(e_perout_mode_normal, tick10ms); for (uint8_t i=0; i> 4) * fp_act[p]; weight += fp_act[p]; } } @@ -2841,50 +2842,21 @@ void doMixerCalculations() val = RESX + calibratedStick[g_model.thrTraceSrc == 0 ? THR_STICK : g_model.thrTraceSrc+NUM_STICKS-1]; } - val /= (RESX/16); // calibrate it - - static tmr10ms_t s_time_tot; - static uint8_t s_cnt_1s; - static uint16_t s_sum_1s; -#if defined(THRTRACE) - static tmr10ms_t s_time_trace; - static uint16_t s_cnt_10s; - static uint16_t s_sum_10s; +#if !defined(CPUM64) + // code cost is about 16 bytes for higher throttle accuracy for timer + // would not be noticable anyway, because all version up to this change had only 16 steps; + // now it has already 32 steps; this define would increase to 128 steps + #define ACCURAT_THROTTLE_TIMER #endif - s_cnt_1s++; - s_sum_1s += val; - - if ((tmr10ms_t)(tmr10ms - s_time_tot) >= 100) { // 1sec - s_time_tot += 100; - s_timeCumTot += 1; - - val = s_sum_1s / s_cnt_1s; - s_timeCum16ThrP += val / 2; - if (val) s_timeCumThr += 1; - -#if defined(THRTRACE) - s_cnt_10s += s_cnt_1s; - s_sum_10s += s_sum_1s; - - if ((tmr10ms_t)(tmr10ms - s_time_trace) >= 1000) { // 10s - s_time_trace += 1000; - val = s_sum_10s / s_cnt_10s; - s_sum_10s = 0; - s_cnt_10s = 0; - - s_traceBuf[s_traceWr++] = val; - if (s_traceWr >= MAXTRACE) s_traceWr = 0; - if (s_traceCnt >= 0) s_traceCnt++; - } +#if defined(ACCURAT_THROTTLE_TIMER) + val >>= (RESX_SHIFT-6); // calibrate it (resolution increased by factor 4) +#else + val >>= (RESX_SHIFT-4); // calibrate it #endif - s_cnt_1s = 0; - s_sum_1s = 0; - } - // Timers start - for (uint8_t i=0; i<2; i++) { + for (uint8_t i=0; i= 0 ? tm : TMR_VAROFS-tm-1); @@ -2914,73 +2885,127 @@ void doMixerCalculations() if ( (s_timerVal_10ms[i] += tick10ms ) >= 100 ) { s_timerVal_10ms[i] -= 100 ; - - if (tv) s_timerVal[i] = tv - s_timerVal[i]; + int16_t newTimerVal = s_timerVal[i]; + if (tv) newTimerVal = tv - newTimerVal; if (atm==TMRMODE_ABS) { - s_timerVal[i]++; + newTimerVal++; } else if (atm==TMRMODE_THR) { - if (val) s_timerVal[i]++; + if (val) newTimerVal++; } else if (atm==TMRMODE_THR_REL) { - if (s_cnt[i]) { - val = s_sum[i]/s_cnt[i]; - s_sum[i] -= val*s_cnt[i]; //rest - s_cnt[i] = 0; - s_time_cum_16[i] += val/2; - if (s_time_cum_16[i] >= 16) { - s_timerVal[i] ++; - s_time_cum_16[i] -= 16; - } + // @@@ open.20.fsguruh: why so complicated? we have already a s_sum field; use it for the half seconds (not showable) as well + // check for s_cnt[i]==0 is not needed because we are shure it is at least 1 +#if defined(ACCURAT_THROTTLE_TIMER) + if ((s_sum[i]/s_cnt[i])>=128) { // throttle was normalized to 0 to 128 value (throttle/64*2 (because - range is added as well) + newTimerVal++; // add second used of throttle + s_sum[i]-=128*s_cnt[i]; } +#else + if ((s_sum[i]/s_cnt[i])>=32) { // throttle was normalized to 0 to 32 value (throttle/16*2 (because - range is added as well) + newTimerVal++; // add second used of throttle + s_sum[i]-=32*s_cnt[i]; + } +#endif + s_cnt[i]=0; } else if (atm==TMRMODE_THR_TRG) { - if (val || s_timerVal[i] > 0) - s_timerVal[i]++; + if (val || newTimerVal > 0) + newTimerVal++; } else { if (atm<(TMR_VAROFS+MAX_SWITCH)) sw_toggled[i] = tm>0 ? getSwitch(tm-(TMR_VAROFS-1), 0) : !getSwitch(-tm, 0); // normal switch if (sw_toggled[i]) - s_timerVal[i]++; + newTimerVal++; } switch(s_timerState[i]) { case TMR_RUNNING: - if (tv && s_timerVal[i]>=(int16_t)tv) s_timerState[i]=TMR_BEEPING; + if (tv && newTimerVal>=(int16_t)tv) s_timerState[i]=TMR_BEEPING; break; case TMR_BEEPING: - if (s_timerVal[i] >= (int16_t)tv + MAX_ALERT_TIME) s_timerState[i]=TMR_STOPPED; + if (newTimerVal >= (int16_t)tv + MAX_ALERT_TIME) s_timerState[i]=TMR_STOPPED; break; } - if (tv) s_timerVal[i] = tv - s_timerVal[i]; //if counting backwards - display backwards + if (tv) newTimerVal = tv - newTimerVal; //if counting backwards - display backwards + + if (newTimerVal != s_timerVal[i]) { // beep only if seconds advance + s_timerVal[i] = newTimerVal; + if (s_timerState[i] == TMR_RUNNING) { + if (g_model.timers[i].countdownBeep && g_model.timers[i].start) { // beep when 30, 15, 10, 5,4,3,2,1 seconds remaining + if (newTimerVal==30) AUDIO_TIMER_30(); //beep three times + if (newTimerVal==20) AUDIO_TIMER_20(); //beep two times + if (newTimerVal==10) AUDIO_TIMER_10(); + if (newTimerVal<= 3) AUDIO_TIMER_LT3(newTimerVal); + } + + if (g_model.timers[i].minuteBeep && (newTimerVal % 60)==0) { // short beep every minute + AUDIO_TIMER_MINUTE(newTimerVal); + } + } + else if (s_timerState[0] == TMR_BEEPING) { + AUDIO_WARNING1(); + } + } } } }; - static int16_t last_tmr; - if (last_tmr != s_timerVal[0]) { // beep only if seconds advance - if (s_timerState[0] == TMR_RUNNING) { - if (g_eeGeneral.preBeep && g_model.timers[0].start) { // beep when 30, 15, 10, 5,4,3,2,1 seconds remaining - if(s_timerVal[0]==30) AUDIO_TIMER_30(); //beep three times - if(s_timerVal[0]==20) AUDIO_TIMER_20(); //beep two times - if(s_timerVal[0]==10) AUDIO_TIMER_10(); - if(s_timerVal[0]<= 3) AUDIO_TIMER_LT3(s_timerVal[0]); - } + static tmr10ms_t s_time_tot; + static uint8_t s_cnt_1s; + static uint16_t s_sum_1s; +#if defined(THRTRACE) + static tmr10ms_t s_time_trace; + static uint16_t s_cnt_10s; + static uint16_t s_sum_10s; +#endif - if (g_eeGeneral.minuteBeep && (s_timerVal[0] % 60)==0) { // short beep every minute - AUDIO_TIMER_MINUTE(s_timerVal[0]); - } + s_cnt_1s++; + s_sum_1s += val; + + // @@@ open.20.fsguruh: moved code here; at least val variable conflicts with caculations above, safer here? + // even reduced code size about 8 bytes, why ever? + if ((tmr10ms_t)(tmr10ms - s_time_tot) >= 100) { // 1sec + s_time_tot += 100; + s_timeCumTot += 1; + +#if defined(ACCURAT_THROTTLE_TIMER) + val = s_sum_1s / s_cnt_1s; + s_timeCum16ThrP += (val>>3); // s_timeCum16ThrP would overrun if we would store throttle value with higher accuracy; therefore stay with 16 steps + if (val) s_timeCumThr += 1; + s_sum_1s>>=2; // correct better accuracy now, because trace graph can show this information; in case thrtrace is not active, the compile should remove this +#else + val = s_sum_1s / s_cnt_1s; + s_timeCum16ThrP += (val>>1); + if (val) s_timeCumThr += 1; +#endif + +#if defined(THRTRACE) + // throttle trace is done every 10 seconds; Tracebuffer is adjusted to screen size. + // in case buffer runs out, it wraps around + // resolution for y axis is only 32, therefore no higher value makes sense + s_cnt_10s += s_cnt_1s; + s_sum_10s += s_sum_1s; + + if ((tmr10ms_t)(tmr10ms - s_time_trace) >= 1000) { // 10s + s_time_trace += 1000; + val = s_sum_10s / s_cnt_10s; + s_sum_10s = 0; + s_cnt_10s = 0; + + s_traceBuf[s_traceWr++] = val; + if (s_traceWr >= MAXTRACE) s_traceWr = 0; + if (s_traceCnt >= 0) s_traceCnt++; } - else if(s_timerState[0] == TMR_BEEPING) { - AUDIO_WARNING1(); - } - last_tmr = s_timerVal[0]; +#endif + + s_cnt_1s = 0; + s_sum_1s = 0; } - // Timers end if (s_fade_flight_phases) { uint16_t tick_delta = delta * tick10ms; @@ -3031,6 +3056,9 @@ void perMain() } nextMixerEndTime = t0 + MAX_MIXER_DELTA; + // this is a very tricky implementation; lastMixerEndTime is just like a default value not to stop mixcalculations totally; + // the real value for lastMixerEndTime is calculated inside pulses_XXX.cpp which aligns the timestamp to the pulses generated + // nextMixerEndTime is actually defined inside pulses_XXX.h doMixerCalculations(); @@ -3455,7 +3483,7 @@ void moveTrimsToOffsets() // copy state of 3 primary to subtrim void saveTimers() { for (uint8_t i=0; i