diff --git a/src/Makefile b/src/Makefile index 58ddf671f..d9cd86e4a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -71,12 +71,13 @@ HELI = NO # Values = YES, NO TEMPLATES = YES -# Enable navigation with Pots / Rotary encoders +# Enable navigation with Pots / Sticks / Rotary encoders # Values = NO # POT1 (only POT1 available for fields modification), # POT2 (menus scroll), # POT3 (cursor down/up), # POTS (POT1, POT2, POT3), +# STICKS # ROTENC (Rotary encoder) NAVIGATION = NO @@ -710,6 +711,9 @@ endif ifeq ($(NAVIGATION), POTS) CPPDEFS += -DNAVIGATION_POT1 -DNAVIGATION_POT2 -DNAVIGATION_POT3 endif +ifeq ($(NAVIGATION), STICKS) + CPPDEFS += -DNAVIGATION_STICKS +endif ifeq ($(NAVIGATION), ROTENC) CPPDEFS += -DROTARY_ENCODER_NAVIGATION endif diff --git a/src/gtests.cpp b/src/gtests.cpp index c27ff7be0..ec7efd63b 100644 --- a/src/gtests.cpp +++ b/src/gtests.cpp @@ -46,7 +46,10 @@ void doMixerCalculations(); #define MIXER_RESET() \ memset(channelOutputs, 0, sizeof(channelOutputs)); \ - memset(ex_chans, 0, sizeof(ex_chans)) + 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 */ uint16_t anaInValues[NUM_STICKS+NUM_POTS] = { 0 }; uint16_t anaIn(uint8_t chan) @@ -282,8 +285,8 @@ TEST(FrSky, dateNtime) TEST(getSwitch, undefCSW) { MODEL_RESET(); - EXPECT_EQ(getSwitch(MAX_PSWITCH, 0), false); - EXPECT_EQ(getSwitch(-MAX_PSWITCH, 0), true); // no good answer there! + EXPECT_EQ(getSwitch(MAX_PSWITCH), false); + EXPECT_EQ(getSwitch(-MAX_PSWITCH), true); // no good answer there! } TEST(getSwitch, circularCSW) @@ -291,18 +294,16 @@ TEST(getSwitch, circularCSW) MODEL_RESET(); g_model.customSw[0] = { MAX_SWITCH-NUM_CSW, MAX_SWITCH-NUM_CSW, CS_OR }; g_model.customSw[1] = { MAX_SWITCH-NUM_CSW, MAX_SWITCH-NUM_CSW, CS_AND }; - EXPECT_EQ(getSwitch(MAX_SWITCH-NUM_CSW, 0), false); - EXPECT_EQ(getSwitch(-(MAX_SWITCH-NUM_CSW), 0), true); - EXPECT_EQ(getSwitch(1+MAX_SWITCH-NUM_CSW, 0), false); - EXPECT_EQ(getSwitch(-(1+MAX_SWITCH-NUM_CSW), 0), true); + EXPECT_EQ(getSwitch(MAX_SWITCH-NUM_CSW), false); + EXPECT_EQ(getSwitch(-(MAX_SWITCH-NUM_CSW)), true); + EXPECT_EQ(getSwitch(1+MAX_SWITCH-NUM_CSW), false); + EXPECT_EQ(getSwitch(-(1+MAX_SWITCH-NUM_CSW)), true); } TEST(getSwitch, nullSW) { MODEL_RESET(); - EXPECT_EQ(getSwitch(0, 0), false); - EXPECT_EQ(getSwitch(0, true), true); - EXPECT_EQ(getSwitch(0, 0), false); + EXPECT_EQ(getSwitch(0), true); } TEST(FlightModes, nullFadeOut_posFadeIn) @@ -465,6 +466,24 @@ TEST(Mixer, RecursiveAddChannel) EXPECT_EQ(chans[1], 0); } +#define CHECK_SLOW_MOVEMENT(channel, sign, duration) \ + do { \ + for (int i=1; i<=(duration); i++) { \ + perOut(e_perout_mode_normal, 1); \ + lastAct = lastAct + (sign) * (1<<19)/500; /* 100 on ARM */ \ + EXPECT_EQ(chans[(channel)], 256 * (lastAct >> 8)); \ + } \ + } while (0) + +#define CHECK_DELAY(channel, duration) \ + do { \ + int32_t value = chans[(channel)]; \ + for (int i=1; i<=(duration); i++) { \ + perOut(e_perout_mode_normal, 1); \ + EXPECT_EQ(chans[(channel)], value); \ + } \ + } while (0) + TEST(Mixer, SlowOnSwitch) { MODEL_RESET(); @@ -481,19 +500,10 @@ TEST(Mixer, SlowOnSwitch) EXPECT_EQ(chans[0], 0); simuSetSwitch(0, 1); - int32_t lastAct = 0; - for (int i=1; i<=250; i++) { - perOut(e_perout_mode_normal, 1); - lastAct = lastAct + (1<<19)/500; /* 100 on ARM */ - EXPECT_EQ(chans[0], 256 * (lastAct >> 8)); - } + CHECK_SLOW_MOVEMENT(0, +1, 250); simuSetSwitch(0, 0); - for (int i=1; i<=250; i++) { - perOut(e_perout_mode_normal, 1); - lastAct = lastAct - (1<<19)/500; /* 100 on ARM */ - EXPECT_EQ(chans[0], 256 * (lastAct >> 8)); - } + CHECK_SLOW_MOVEMENT(0, -1, 250); } TEST(Mixer, SlowOnPhase) @@ -513,19 +523,10 @@ TEST(Mixer, SlowOnPhase) perOut(e_perout_mode_normal, 0); EXPECT_EQ(chans[0], 0); - int32_t lastAct = 0; - for (int i=1; i<=250; i++) { - perOut(e_perout_mode_normal, 1); - lastAct = lastAct+(1<<19)/500; /* 100 on ARM */ - EXPECT_EQ(chans[0], 256 * (lastAct >> 8)); - } + CHECK_SLOW_MOVEMENT(0, +1, 250); s_perout_flight_phase = 1; - for (int i=1; i<=250; i++) { - perOut(e_perout_mode_normal, 1); - lastAct = lastAct - (1<<19)/500; /* 100 on ARM */ - EXPECT_EQ(chans[0], 256 * (lastAct >> 8)); - } + CHECK_SLOW_MOVEMENT(0, -1, 250); } TEST(Mixer, SlowOnSwitchAndPhase) @@ -547,20 +548,11 @@ TEST(Mixer, SlowOnSwitchAndPhase) simuSetSwitch(0, 1); s_perout_flight_phase = 0; - int32_t lastAct = 0; - for (int i=1; i<=250; i++) { - perOut(e_perout_mode_normal, 1); - lastAct = lastAct+(1<<19)/500; /* 100 on ARM */ - EXPECT_EQ(chans[0], 256 * (lastAct >> 8)); - } + CHECK_SLOW_MOVEMENT(0, +1, 250); simuSetSwitch(0, 0); s_perout_flight_phase = 1; - for (int i=1; i<=250; i++) { - perOut(e_perout_mode_normal, 1); - lastAct = lastAct - (1<<19)/500; /* 100 on ARM */ - EXPECT_EQ(chans[0], 256 * (lastAct >> 8)); - } + CHECK_SLOW_MOVEMENT(0, -1, 250); } TEST(Mixer, SlowOnSwitchSource) @@ -575,21 +567,38 @@ TEST(Mixer, SlowOnSwitchSource) g_model.mixData[0].speedDown = 10; simuSetSwitch(0, 0); - int32_t lastAct = 0; - for (int i=1; i<=250; i++) { - perOut(e_perout_mode_normal, 1); - lastAct = lastAct - (1<<19)/500; /* 100 on ARM */ - EXPECT_EQ(chans[0], 256 * (lastAct >> 8)); - } - + CHECK_SLOW_MOVEMENT(0, -1, 250); EXPECT_EQ(chans[0], -CHANNEL_MAX); simuSetSwitch(0, 1); - for (int i=1; i<=500; i++) { - perOut(e_perout_mode_normal, 1); - lastAct = lastAct + (1<<19)/500; /* 100 on ARM */ - EXPECT_EQ(chans[0], 256 * (lastAct >> 8)); - } + CHECK_SLOW_MOVEMENT(0, +1, 500); +} + +TEST(Mixer, SlowAndDelayOnReplace3POSSource) +{ + MODEL_RESET(); + MIXER_RESET(); + g_model.mixData[0].destCh = 0; + g_model.mixData[0].mltpx = MLTPX_REP; + g_model.mixData[0].srcRaw = MIXSRC_3POS; + g_model.mixData[0].weight = 100; + g_model.mixData[0].delayUp = 10; + g_model.mixData[0].delayUp = 10; + g_model.mixData[0].speedUp = 10; + g_model.mixData[0].speedDown = 10; + + simuSetSwitch(3, -1); + CHECK_SLOW_MOVEMENT(0, -1, 250); + EXPECT_EQ(chans[0], -CHANNEL_MAX); + + simuSetSwitch(3, 0); + CHECK_DELAY(0, 500); + CHECK_SLOW_MOVEMENT(0, +1, 250/*half course*/); + EXPECT_EQ(chans[0], 0); + + simuSetSwitch(3, 1); + CHECK_DELAY(0, 500); + CHECK_SLOW_MOVEMENT(0, +1, 250); } TEST(Curves, LinearIntpol) diff --git a/src/gui/menu_general.cpp b/src/gui/menu_general.cpp index 56be78dc4..14fea6cec 100644 --- a/src/gui/menu_general.cpp +++ b/src/gui/menu_general.cpp @@ -960,6 +960,8 @@ void menuGeneralDiagAna(uint8_t event) SIMPLE_MENU(STR_MENUANA, menuTabDiag, e_Ana, ANAS_ITEMS_COUNT); + STICK_SCROLL_DISABLE(); + for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS) : 0); uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ; + if (active) STICK_SCROLL_DISABLE(); switch(j) { #if defined(PCBTARANIS) @@ -3728,7 +3729,7 @@ void menuModelCustomSwitchOne(uint8_t event) CustomSwData * cs = cswaddress(s_currIdx); uint8_t sw = SWSRC_SW1+s_currIdx; - putsSwitches(14*FW, 0, sw, (getSwitch(sw, 0) ? BOLD : 0)); + putsSwitches(14*FW, 0, sw, (getSwitch(sw) ? BOLD : 0)); SIMPLE_SUBMENU_NOTITLE(CSW_FIELD_COUNT); int8_t sub = m_posVert; @@ -3864,7 +3865,7 @@ void menuModelCustomSwitches(uint8_t event) // CSW name uint8_t sw = SWSRC_SW1+k; - putsSwitches(0, y, sw, (sub==k ? INVERS : 0) | (getSwitch(sw, 0) ? BOLD : 0)); + putsSwitches(0, y, sw, (sub==k ? INVERS : 0) | (getSwitch(sw) ? BOLD : 0)); if (cs->func > 0) { // CSW func @@ -3929,7 +3930,7 @@ void menuModelCustomSwitches(uint8_t event) // CSW name uint8_t sw = SWSRC_SW1+k; - putsSwitches(0, y, sw, (getSwitch(sw, 0) ? BOLD : 0) | ((sub==k && m_posHorz<0) ? INVERS : 0)); + putsSwitches(0, y, sw, (getSwitch(sw) ? BOLD : 0) | ((sub==k && m_posHorz<0) ? INVERS : 0)); // CSW func lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, m_posHorz==0 ? attr : 0); diff --git a/src/gui/view_main.cpp b/src/gui/view_main.cpp index 90c2f314b..1d2e11169 100644 --- a/src/gui/view_main.cpp +++ b/src/gui/view_main.cpp @@ -39,10 +39,9 @@ #if LCD_W >= 212 #define BIGSIZE MIDSIZE #define BOX_WIDTH 31 +#define BOX_CENTERY (LCD_H-BOX_WIDTH/2-10) #define LBOX_CENTERX (BOX_WIDTH/2 + 17) -#define LBOX_CENTERY (LCD_H-BOX_WIDTH/2-10) #define RBOX_CENTERX (LCD_W-LBOX_CENTERX) -#define RBOX_CENTERY LBOX_CENTERY #define MODELNAME_X (15) #define MODELNAME_Y (11) #define VBATT_X (MODELNAME_X+26) @@ -69,10 +68,9 @@ #else #define BIGSIZE DBLSIZE #define BOX_WIDTH 23 +#define BOX_CENTERY (LCD_H-9-BOX_WIDTH/2) #define LBOX_CENTERX (LCD_W/4 + 10) -#define LBOX_CENTERY (LCD_H-9-BOX_WIDTH/2) #define RBOX_CENTERX (3*LCD_W/4 - 10) -#define RBOX_CENTERY LBOX_CENTERY #define MODELNAME_X (2*FW-2) #define MODELNAME_Y (0) #define PHASE_X (6*FW) @@ -128,22 +126,24 @@ void drawPotsBars() } } +void drawStick(uint8_t centrex, int16_t xval, int16_t yval) +{ + lcd_square(centrex-BOX_WIDTH/2, BOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH); + DO_CROSS(centrex, BOX_CENTERY, 3); + lcd_square(centrex + (xval/((2*RESX)/BOX_LIMIT)) - MARKER_WIDTH/2, BOX_CENTERY - (yval/((2*RESX)/BOX_LIMIT)) - MARKER_WIDTH/2, MARKER_WIDTH, ROUND); +} + void doMainScreenGraphics() { - lcd_square(LBOX_CENTERX-BOX_WIDTH/2, LBOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH); - lcd_square(RBOX_CENTERX-BOX_WIDTH/2, RBOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH); - - DO_CROSS(LBOX_CENTERX, LBOX_CENTERY, 3) - DO_CROSS(RBOX_CENTERX, RBOX_CENTERY, 3) - int16_t calibStickVert = calibratedStick[CONVERT_MODE(1+1)-1]; if (g_model.throttleReversed && CONVERT_MODE(1+1)-1 == THR_STICK) calibStickVert = -calibStickVert; - lcd_square(LBOX_CENTERX+(calibratedStick[CONVERT_MODE(0+1)-1]*BOX_LIMIT/(2*RESX))-MARKER_WIDTH/2, LBOX_CENTERY-(calibStickVert*BOX_LIMIT/(2*RESX))-MARKER_WIDTH/2, MARKER_WIDTH, ROUND); + drawStick(LBOX_CENTERX, calibratedStick[CONVERT_MODE(0+1)-1], calibStickVert); + calibStickVert = calibratedStick[CONVERT_MODE(2+1)-1]; if (g_model.throttleReversed && CONVERT_MODE(2+1)-1 == THR_STICK) calibStickVert = -calibStickVert; - lcd_square(RBOX_CENTERX+(calibratedStick[CONVERT_MODE(3+1)-1]*BOX_LIMIT/(2*RESX))-MARKER_WIDTH/2, RBOX_CENTERY-(calibStickVert*BOX_LIMIT/(2*RESX))-MARKER_WIDTH/2, MARKER_WIDTH, ROUND); + drawStick(RBOX_CENTERX, calibratedStick[CONVERT_MODE(3+1)-1], calibStickVert); #if !defined(PCBTARANIS) drawPotsBars(); @@ -451,6 +451,8 @@ void onMainViewMenu(const char *result) void menuMainView(uint8_t event) { + STICK_SCROLL_DISABLE(); + #if !defined(PCBTARANIS) uint8_t view = g_eeGeneral.view; uint8_t view_base = view & 0x0f; @@ -678,7 +680,7 @@ void menuMainView(uint8_t event) uint8_t x = LCD_W/2+7*FW+col*FW; uint8_t y = LCD_H/2-7+line*8; lcd_putcAtt(x, y, sw>=9 ? 'A'+sw-9 : '1'+sw, SMLSIZE); - if (getSwitch(SWSRC_SW1+sw, 0)) + if (getSwitch(SWSRC_SW1+sw)) lcd_filled_rect(x-1, y-1, 6, 8); sw++; } @@ -752,7 +754,7 @@ void menuMainView(uint8_t event) x = 17*FW-1; y -= 3*FH; } - putsSwitches(x, y, sw, getSwitch(i, 0) ? INVERS : 0); + putsSwitches(x, y, sw, getSwitch(i) ? INVERS : 0); } } else { @@ -773,23 +775,23 @@ void menuMainView(uint8_t event) // Custom Switches #if defined(PCBSKY9X) for (uint8_t i=0; i 2 for (uint8_t i=0; i1 ? 3*FW+6 : 0), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i, 0) ? INVERS : 0); + putsSwitches(2*FW-2 + (i/3)*(4*FW-2) + (i/3>1 ? 3*FW+6 : 0), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0); #elif defined(PCBGRUVIN9X) for (uint8_t i=0; i1 ? 3*FW : 0), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i, 0) ? INVERS : 0); + putsSwitches(2*FW-2 + (i/3)*(4*FW-2) + (i/3>1 ? 3*FW : 0), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0); #elif !defined(PCBSTD) for (uint8_t i=0; i=0 && (ed.mode&2))) { #if defined(BOLD_FONT) @@ -897,10 +897,9 @@ getvalue_t getValue(uint8_t i) } #if defined(CPUARM) -#define GETSWITCH_RECURSIVE_TYPE uint32_t -volatile bool s_default_switch_value; + #define GETSWITCH_RECURSIVE_TYPE uint32_t #else -#define GETSWITCH_RECURSIVE_TYPE uint16_t + #define GETSWITCH_RECURSIVE_TYPE uint16_t #endif volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_used; @@ -920,11 +919,7 @@ bool __getSwitch(int8_t swtch) bool result; if (swtch == 0) -#if defined(CPUARM) - return s_default_switch_value; -#else - return s_last_switch_used & ((GETSWITCH_RECURSIVE_TYPE)1<<15); -#endif + return true; uint8_t cs_idx = abs(swtch); @@ -1094,16 +1089,10 @@ bool __getSwitch(int8_t swtch) return swtch > 0 ? result : !result; } -bool getSwitch(int8_t swtch, bool nc) +bool getSwitch(int8_t swtch) { -#if defined(CPUARM) s_last_switch_used = 0; s_last_switch_value = 0; - s_default_switch_value = nc; -#else - s_last_switch_used = ((GETSWITCH_RECURSIVE_TYPE)nc<<15); - s_last_switch_value = 0; -#endif return __getSwitch(swtch); } @@ -1195,7 +1184,7 @@ uint8_t getFlightPhase() { for (uint8_t i=1; iswtch && getSwitch(phase->swtch, 0)) { + if (phase->swtch && getSwitch(phase->swtch)) { return i; } } @@ -1511,9 +1500,9 @@ void checkBacklight() if (tmr10ms != x) { tmr10ms = x; uint16_t tsum = stickMoveValue(); - if (tsum != inacSum) { - inacSum = tsum; - inacCounter = 0; + if (tsum != inactivity.sum) { + inactivity.sum = tsum; + inactivity.counter = 0; if (g_eeGeneral.backlightMode & e_backlight_mode_sticks) backlightOn(); } @@ -2129,10 +2118,8 @@ int16_t rawAnas [NUM_INPUTS] = {0}; int16_t anas [NUM_INPUTS] = {0}; int16_t trims[NUM_STICKS] = {0}; int32_t chans[NUM_CHNOUT] = {0}; -uint8_t inacPrescale; -uint16_t inacCounter = 0; -uint16_t inacSum = 0; BeepANACenter bpanaCenter = 0; +struct t_inactivity inactivity = {0}; int24_t act [MAX_MIXERS] = {0}; SwOn swOn [MAX_MIXERS]; // TODO better name later... @@ -2489,7 +2476,7 @@ void evalFunctions() swtch += MAX_SWITCH+1; } - bool active = getSwitch(swtch, 0); + bool active = getSwitch(swtch); if (active) newActiveSwitches |= switch_mask; if (momentary || short_long) { @@ -2739,8 +2726,7 @@ void perOut(uint8_t mode, uint8_t tick10ms) } #if defined(HELI) - if(g_model.swashR.value) - { + 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 = calc100toRESX(g_model.swashR.value); q *= q; @@ -2755,20 +2741,18 @@ void perOut(uint8_t mode, uint8_t tick10ms) #define REZ_SWASH_X(x) ((x) - (x)/8 - (x)/128 - (x)/512) // 1024*sin(60) ~= 886 #define REZ_SWASH_Y(x) ((x)) // 1024 => 1024 - if(g_model.swashR.type) - { + if (g_model.swashR.type) { getvalue_t vp = anas[ELE_STICK]+trims[ELE_STICK]; getvalue_t vr = anas[AIL_STICK]+trims[AIL_STICK]; getvalue_t vc = 0; if (g_model.swashR.collectiveSource) vc = getValue(g_model.swashR.collectiveSource-1); - if(g_model.swashR.invertELE) vp = -vp; - if(g_model.swashR.invertAIL) vr = -vr; - if(g_model.swashR.invertCOL) vc = -vc; + if (g_model.swashR.invertELE) vp = -vp; + if (g_model.swashR.invertAIL) vr = -vr; + if (g_model.swashR.invertCOL) vc = -vc; - switch (g_model.swashR.type) - { + switch (g_model.swashR.type) { case SWASH_TYPE_120: vp = REZ_SWASH_Y(vp); vr = REZ_SWASH_X(vr); @@ -2834,7 +2818,7 @@ void perOut(uint8_t mode, uint8_t tick10ms) //========== PHASE && SWITCH ===== bool mixCondition = (md->phases != 0 || md->swtch); - int8_t mixEnabled = !(md->phases & (1 << s_perout_flight_phase)) && getSwitch(md->swtch, 1); + int8_t mixEnabled = !(md->phases & (1 << s_perout_flight_phase)) && getSwitch(md->swtch); //========== VALUE =============== getvalue_t v = 0; @@ -2848,7 +2832,7 @@ void perOut(uint8_t mode, uint8_t tick10ms) } else { if (k < NUM_STICKS) { - v = md->noExpo ? rawAnas[k] : anas[k]; //Switch is on. MAX=FULL=512 or value. + v = md->noExpo ? rawAnas[k] : anas[k]; } else { v = getValue(k); @@ -2859,34 +2843,32 @@ void perOut(uint8_t mode, uint8_t tick10ms) if (dirtyChannels & ((bitfield_channels_t)1 << (k-MIXSRC_CH1+1)) & (passDirtyChannels|~(((bitfield_channels_t) 1 << md->destCh)-1))) passDirtyChannels |= (bitfield_channels_t) 1 << md->destCh; if (k-MIXSRC_CH1+1 < md->destCh || pass > 0) - v = chans[k-MIXSRC_CH1+1] >> 8; // remove factor 256 from old mix loop; was 100 before + v = chans[k-MIXSRC_CH1+1] >> 8; } } } bool apply_offset_and_curve = true; - //========== DELAYS =============== + // ========== DELAYS =============== int8_t _swOn = swOn[i].now; int8_t _swPrev = swOn[i].prev; bool swTog = (mixEnabled != _swOn); - // if (i==0) { printf("mixEnabled=%d swOn=%d swPrev=%d sDelay=%d mixCondition=%d\n", mixEnabled, _swOn, _swPrev, sDelay[i], mixCondition); fflush(stdout); } - if (swTog) { + if (mode==e_perout_mode_normal && swTog) { if (!swOn[i].delay) _swPrev = _swOn; swOn[i].delay = (mixEnabled > _swOn ? md->delayUp : md->delayDown) * (100/DELAY_STEP); swOn[i].now = mixEnabled; swOn[i].prev = _swPrev; } - if (swOn[i].delay > 0) { + if (mode==e_perout_mode_normal && swOn[i].delay > 0) { swOn[i].delay = max(0, (int16_t)swOn[i].delay - tick10ms); if (!mixCondition) - v = _swPrev << 10; // TODO optim? + v = _swPrev << 10; else if (mixEnabled) continue; } else if (!mixEnabled) { if (md->speedDown) { - if (md->mltpx == MLTPX_REP) continue; if (mixCondition) { v = 0; apply_offset_and_curve = false; @@ -3039,7 +3021,7 @@ void perOut(uint8_t mode, uint8_t tick10ms) else { if ((tmp.words_t.hi|0x007F)!=0x007F) tmp.words_t.hi=0x0079; // set to max nearly } - *ptr=tmp.dword; + *ptr = tmp.dword; // this implementation saves 18bytes flash /* dv=*ptr>>8; @@ -3143,7 +3125,7 @@ void doMixerCalculations() for (uint8_t p=0; p> 4) * fp_act[p]; weight += fp_act[p]; @@ -3260,7 +3242,7 @@ void doMixerCalculations() if (atm>=(TMR_VAROFS+MAX_SWITCH)){ // toggeled switch if(!(sw_toggled[i] | s_sum[i] | s_cnt[i] | lastSwPos[i])) { lastSwPos[i] = tm < 0; s_sum[i] = 1; } // if initializing then init the lastSwPos - uint8_t swPos = getSwitch(tm>0 ? tm-(TMR_VAROFS+MAX_SWITCH-1) : tm+MAX_SWITCH, 0); + uint8_t swPos = getSwitch(tm>0 ? tm-(TMR_VAROFS+MAX_SWITCH-1) : tm+MAX_SWITCH); if (swPos && !lastSwPos[i]) sw_toggled[i] = !sw_toggled[i]; // if switch is flipped first time -> change counter state lastSwPos[i] = swPos; } @@ -3298,7 +3280,7 @@ void doMixerCalculations() } else { if (atm<(TMR_VAROFS+MAX_SWITCH)) - sw_toggled[i] = tm>0 ? getSwitch(tm-(TMR_VAROFS-1), 0) : !getSwitch(-tm, 0); // normal switch + sw_toggled[i] = tm>0 ? getSwitch(tm-(TMR_VAROFS-1)) : !getSwitch(-tm); // normal switch if (sw_toggled[i]) newTimerVal++; } @@ -3354,8 +3336,11 @@ void doMixerCalculations() s_time_tot += 100; s_timeCumTot += 1; - inacCounter++; - if ((((uint8_t)inacCounter)&0x07)==0x01 && g_eeGeneral.inactivityTimer && g_vbat100mV>50 && inacCounter > ((uint16_t)g_eeGeneral.inactivityTimer*60)) + struct t_inactivity *ptrInactivity = &inactivity; + FORCE_INDIRECT(ptrInactivity) ; + + ptrInactivity->counter++; + if ((((uint8_t)ptrInactivity->counter)&0x07)==0x01 && g_eeGeneral.inactivityTimer && g_vbat100mV>50 && ptrInactivity->counter > ((uint16_t)g_eeGeneral.inactivityTimer*60)) AUDIO_INACTIVITY(); #if defined(AUDIO) @@ -3448,6 +3433,41 @@ void doMixerCalculations() #endif } +#if defined(NAVIGATION_STICKS) +uint8_t StickScrollAllowed; +uint8_t StickScrollTimer; +static const pm_uint8_t rate[] PROGMEM = { 0, 0, 100, 40, 16, 7, 3, 1 } ; + +uint8_t calcStickScroll( uint8_t index ) +{ + uint8_t direction ; + int8_t value ; + + if ( ( g_eeGeneral.stickMode & 1 ) == 0 ) + { + index ^= 3 ; + } + + value = calibratedStick[index] / 128 ; + direction = value > 0 ? 0x80 : 0 ; + if ( value < 0 ) + { + value = -value ; // (abs) + } + if ( value > 7 ) + { + value = 7 ; + } + value = pgm_read_byte(rate+(uint8_t)value) ; + if ( value ) + { + StickScrollTimer = STICK_SCROLL_TIMEOUT ; // Seconds + } + return value | direction ; +} +#endif + + void perMain() { #if defined(SIMU) @@ -3595,6 +3615,70 @@ void perMain() } #endif +#if defined(NAVIGATION_STICKS) + if (StickScrollAllowed) { + if ( StickScrollTimer ) { + static uint8_t repeater; + uint8_t direction; + uint8_t value; + + if ( repeater < 128 ) + { + repeater += 1; + } + value = calcStickScroll( 2 ); + direction = value & 0x80; + value &= 0x7F; + if ( value ) + { + if ( repeater > value ) + { + repeater = 0; + if ( evt == 0 ) + { + if ( direction ) + { + evt = EVT_KEY_FIRST(KEY_UP); + } + else + { + evt = EVT_KEY_FIRST(KEY_DOWN); + } + } + } + } + else + { + value = calcStickScroll( 3 ); + direction = value & 0x80; + value &= 0x7F; + if ( value ) + { + if ( repeater > value ) + { + repeater = 0; + if ( evt == 0 ) + { + if ( direction ) + { + evt = EVT_KEY_FIRST(KEY_RIGHT); + } + else + { + evt = EVT_KEY_FIRST(KEY_LEFT); + } + } + } + } + } + } + } + else { + StickScrollTimer = 0; // Seconds + } + StickScrollAllowed = 1 ; +#endif + lcd_clear(); const char *warn = s_warning; uint8_t menu = s_menu_count; diff --git a/src/opentx.h b/src/opentx.h index 3389fa00d..51049ed57 100644 --- a/src/opentx.h +++ b/src/opentx.h @@ -414,6 +414,15 @@ enum EnumKeys { void watchdogSetTimeout(uint32_t timeout); #endif +#if defined(NAVIGATION_STICKS) + extern uint8_t StickScrollAllowed; + extern uint8_t StickScrollTimer; + #define STICK_SCROLL_TIMEOUT 9 + #define STICK_SCROLL_DISABLE() StickScrollAllowed = 0 +#else + #define STICK_SCROLL_DISABLE() +#endif + #include "eeprom_common.h" #if defined(PCBSKY9X) @@ -688,9 +697,12 @@ void watchdogSetTimeout(uint32_t timeout); #define MAX_ALERT_TIME 60 -extern uint8_t inacPrescale; -extern uint16_t inacCounter; -extern uint16_t inacSum; +struct t_inactivity +{ + uint16_t counter; + uint16_t sum; +}; +extern struct t_inactivity inactivity; #if defined(PXX) extern uint8_t pxxFlag[NUM_MODULES]; @@ -752,7 +764,11 @@ enum PerOutMode { }; // Fiddle to force compiler to use a pointer -#define FORCE_INDIRECT(ptr) __asm__ __volatile__ ("" : "=e" (ptr) : "0" (ptr)) +#if defined(CPUARM) || defined(SIMU) + #define FORCE_INDIRECT(ptr) +#else + #define FORCE_INDIRECT(ptr) __asm__ __volatile__ ("" : "=e" (ptr) : "0" (ptr)) +#endif extern uint8_t s_perout_flight_phase; @@ -767,7 +783,7 @@ void perMain(); NOINLINE void per10ms(); getvalue_t getValue(uint8_t i); -bool getSwitch(int8_t swtch, bool nc); +bool getSwitch(int8_t swtch); extern swstate_t switches_states; int8_t getMovedSwitch(); @@ -1137,6 +1153,7 @@ PACK(typedef struct t_SwOn { int16_t activeExpo:1; }) SwOn; extern SwOn swOn [MAX_MIXERS]; +extern int24_t act [MAX_MIXERS]; #ifdef BOLD_FONT inline bool isExpoActive(uint8_t expo) diff --git a/src/protocols/dsm2_arm.cpp b/src/protocols/dsm2_arm.cpp index 843091513..4d3f4412e 100644 --- a/src/protocols/dsm2_arm.cpp +++ b/src/protocols/dsm2_arm.cpp @@ -113,7 +113,7 @@ void setupPulsesDsm2(uint8_t chns) } if ((dsmDat[0] & BIND_BIT) && (!switchState(SW_TRN))) dsmDat[0] &= ~BIND_BIT; // clear bind bit if trainer not pulled - // TODO find a way to do that, FUNC SWITCH: if ((!(dsmDat[0] & BIND_BIT)) && getSwitch(MAX_DRSWITCH-1, 0, 0)) dsmDat[0] |= RANGECHECK_BIT; // range check function + // TODO find a way to do that, FUNC SWITCH: if ((!(dsmDat[0] & BIND_BIT)) && getSwitch(MAX_DRSWITCH-1)) dsmDat[0] |= RANGECHECK_BIT; // range check function // else dsmDat[0] &= ~RANGECHECK_BIT; dsmDat[1]=g_eeGeneral.currModel+1; //DSM2 Header second byte for model match for(uint8_t i=0; igetKeyState(KEY_##key)) { \ if (!state##key) { \ - state_##swtch = (state_##swtch+1); \ - if (state_##swtch == 2+states) state_##swtch = 2; \ + state_##swtch = (state_##swtch+inc_##swtch); \ + if (state_##swtch == 1+states) inc_##swtch = -1; \ + else if (state_##swtch == 2) inc_##swtch = 1; \ state##key = true; \ } \ } \ diff --git a/src/targets/stock/board_stock.cpp b/src/targets/stock/board_stock.cpp index b9ed2cb04..c597d0cd1 100644 --- a/src/targets/stock/board_stock.cpp +++ b/src/targets/stock/board_stock.cpp @@ -122,17 +122,19 @@ inline void boardInit() #if defined(AUDIO) || defined(VOICE) SET_TIMER_AUDIO_CTRL(); + #if !defined(CPUM2561) + TIMSK |= (1<