예제 #1
0
파일: maths.cpp 프로젝트: 4408/opentx
void varioWakeup()
{
  static tmr10ms_t s_varioTmr;
  tmr10ms_t tmr10ms = get_tmr10ms();
  
  if (isFunctionActive(FUNC_VARIO)) {
#if defined(AUDIO)
    cli();
    int16_t verticalSpeed = frskyData.hub.varioSpeed;
    sei();
    
#if defined(PCBSTD)
    int16_t varioCenterMax = (int16_t)g_model.frsky.varioCenterMax * 10 + 50;
    if (verticalSpeed >= varioCenterMax) {
      verticalSpeed = verticalSpeed - varioCenterMax;
      int16_t varioMax = (10+(int16_t)g_model.frsky.varioMax) * 100;
      if (verticalSpeed > varioMax) verticalSpeed = varioMax;
      verticalSpeed = (verticalSpeed * 10) / ((varioMax-varioCenterMax) / 100);

      if ((int16_t)(s_varioTmr-tmr10ms) < 0) {
        uint8_t SoundVarioBeepTime = (1600 - verticalSpeed) / 100;
        uint8_t SoundVarioBeepFreq = (verticalSpeed * 10 + 16000) >> 8;
        s_varioTmr = tmr10ms + (SoundVarioBeepTime*2);
        AUDIO_VARIO(SoundVarioBeepFreq, SoundVarioBeepTime);
      }
    }
예제 #2
0
파일: pers.cpp 프로젝트: RasmusKS/er9x
void eeDirty(uint8_t msk)
{
	uint8_t lmask = msk & 7 ;
  if(!lmask) return;
  s_eeDirtyMsk      |= lmask;
  s_eeDirtyTime10ms  = get_tmr10ms() ;
	s_eeLongTimer = msk >> 4 ;
}
예제 #3
0
void displayMixLine(coord_t y, MixData *md)
{
  if (md->name[0])
    lcd_putsnAtt(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR);
  if (!md->flightModes || ((md->curve.value || md->swtch) && ((get_tmr10ms() / 200) & 1)))
    displayMixInfos(y, md);
  else
    displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes);
}
예제 #4
0
파일: rotarysw.cpp 프로젝트: neolu/gv9x
void setRotarySwIdx(int8_t idx) {
	if (rotarySwIdx != idx) {
		rotarySwIdx = idx;
		if (rotarySwIdx >= 0) {
			rotarySwChanged = (get_tmr10ms() >> 3) + 3;
#ifdef MAVLINK
			uint8_t send = g_model.rotarySw[rotarySwIdx].typeRotary == ROTARY_TYPE_MAVLINK ? 1 : 0;
			MAVLINK_ReqMode(g_model.rotarySw[rotarySwIdx].numMode, send);
#endif
		}
예제 #5
0
void displayExpoLine(coord_t y, ExpoData *ed)
{
  putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0);

  if (ed->carryTrim != TRIM_ON) {
    lcd_putc(EXPO_LINE_TRIM_POS, y, ed->carryTrim > 0 ? '-' : STR_RETA123[-ed->carryTrim]);
  }

  if (!ed->flightModes || ((ed->curve.value || ed->swtch) && ((get_tmr10ms() / 200) & 1)))
    displayExpoInfos(y, ed);
  else
    displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes);

  if (ed->name[0]) {
    lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR);
  }
}
예제 #6
0
    /* ON / OFF version */
    lcd_putsiAtt(x, y, STR_OFFON, value, attr ? INVERS:0) ;
#endif
}

void displayScreenIndex(uint8_t index, uint8_t count, uint8_t attr)
{
    lcd_outdezAtt(LCD_W, 0, count, attr);
    xcoord_t x = 1+LCD_W-FW*(count>9 ? 3 : 2);
    lcd_putcAtt(x, 0, '/', attr);
    lcd_outdezAtt(x, 0, index+1, attr);
}

#if !defined(CPUM64)
void displayScrollbar(xcoord_t x, uint8_t y, uint8_t h, uint16_t offset, uint16_t count, uint8_t visible)
{
    lcd_vlineStip(x, y, h, SOLID, ERASE);
    lcd_vlineStip(x, y, h, DOTTED);
    uint8_t yofs = (h * offset) / count;
    uint8_t yhgt = (h * visible) / count;
    if (yhgt + yofs > h)
        yhgt = h - yofs;
    lcd_vlineStip(x, y + yofs, yhgt, SOLID, FORCE);
}
#endif

#if defined(NAVIGATION_POT1)
int16_t p1valdiff;
#endif

#if defined(NAVIGATION_POT2)
int8_t p2valdiff;
#endif

uint8_t switchToMix(uint8_t source)
{
#if defined(PCBTARANIS)
    if (source <= 5*3)
        return MIXSRC_FIRST_SWITCH + (source-1) / 3;
    else if (source <= 17)
        return MIXSRC_SF;
    else if (source <= 20)
        return MIXSRC_SG;
    else
        return MIXSRC_SH;
#else
    if (source <= 3)
        return MIXSRC_3POS;
    else
        return MIXSRC_FIRST_SWITCH - 3 + source;
#endif
}

int8_t  checkIncDec_Ret;

#if defined(CPUARM)
int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags, IsValueAvailable isValueAvailable)
#else
int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags)
#endif
{
    int16_t newval = val;

#if defined(DBLKEYS)
    uint8_t in = KEYS_PRESSED();
    if (EVT_KEY_MASK(event)) {
        bool dblkey = true;
        if (DBLKEYS_PRESSED_RGT_LFT(in))
            newval = -val;
        else if (DBLKEYS_PRESSED_RGT_UP(in)) {
            newval = (i_max > 100 ? 100 : i_max);
#if defined(CPUARM)
            if (i_flags & DBLKEYS_1000) newval *= 10;
#endif
        }
        else if (DBLKEYS_PRESSED_LFT_DWN(in)) {
            newval = (i_min < -100 ? -100 : i_min);
#if defined(CPUARM)
            if (i_flags & DBLKEYS_1000) newval *= 10;
#endif
        }
        else if (DBLKEYS_PRESSED_UP_DWN(in))
            newval = 0;
        else
            dblkey = false;

#if defined(CPUARM)

#endif

        if (dblkey) {
            killEvents(KEY_UP);
            killEvents(KEY_DOWN);
            killEvents(KEY_RIGHT);
            killEvents(KEY_LEFT);
#if defined(PCBTARANIS)
            killEvents(KEY_PAGE);
            killEvents(KEY_MENU);
            killEvents(KEY_ENTER);
            killEvents(KEY_EXIT);
#endif
            event = 0;
        }
    }
#endif

#if defined(PCBTARANIS)
    if (s_editMode>0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP))) {
#else
    if (event==EVT_KEY_FIRST(KEY_RIGHT) || event==EVT_KEY_REPT(KEY_RIGHT) || (s_editMode>0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)))) {
#endif
#if defined(CPUARM)
        do {
            if (IS_KEY_REPT(event) && (i_flags & INCDEC_REP10)) {
                newval += min(10, i_max-val);
            }
            else {
                newval++;
            }
        } while (isValueAvailable && !isValueAvailable(newval) && newval<=i_max);
        if (newval > i_max) {
            newval = val;
            killEvents(event);
            AUDIO_WARNING2();
        }
        else
#else
        newval++;
#endif
            AUDIO_KEYPAD_UP();
    }
#if defined(PCBTARANIS)
    else if (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN))) {
#else
    else if (event==EVT_KEY_FIRST(KEY_LEFT) || event==EVT_KEY_REPT(KEY_LEFT) || (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)))) {
#endif
#if defined(CPUARM)
        do {
            if (IS_KEY_REPT(event) && (i_flags & INCDEC_REP10)) {
                newval -= min(10, val-i_min);
            }
            else {
                newval--;
            }
        } while (isValueAvailable && !isValueAvailable(newval) && newval>=i_min);
        if (newval < i_min) {
            newval = val;
            killEvents(event);
            AUDIO_WARNING2();
        }
        else
#else
        newval--;
#endif
            AUDIO_KEYPAD_DOWN();
    }

    if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) {
        s_editMode = 0;
        newval = !val;
    }

#if defined(NAVIGATION_POT1)
    // change values based on P1
    newval -= p1valdiff;
    p1valdiff = 0;
#endif

#if defined(AUTOSWITCH)
    if (i_flags & INCDEC_SWITCH) {
        if (s_editMode>0) {
            int8_t swtch = getMovedSwitch();
            if (swtch) {
#if defined(PCBTARANIS)
                if(swtch == SWSRC_SH2)
                    newval = (newval == SWSRC_SH2 ? SWSRC_SH0 : SWSRC_SH2);
                else if(swtch != SWSRC_SH0)
                    newval = swtch;
#else
                if (IS_MOMENTARY(newval) && IS_MOMENTARY(swtch))
                    newval = -newval;
                else
                    newval = swtch;
#endif
            }
        }
    }
#endif

#if defined(AUTOSOURCE)
    if (i_flags & INCDEC_SOURCE) {
        if (s_editMode>0) {
            int8_t source = GET_MOVED_SOURCE(i_min, i_max);
            if (source) {
                newval = source;
            }
#if defined(AUTOSWITCH)
            else {
                uint8_t swtch = abs(getMovedSwitch());
                if (swtch) {
                    newval = switchToMix(swtch);
                }
            }
#endif
        }
    }
#endif

    if (newval > i_max || newval < i_min) {
        newval = (newval > i_max ? i_max : i_min);
        killEvents(event);
        AUDIO_WARNING2();
    }

    if (newval != val) {
        if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && (newval==0 || newval==-100 || newval==+100) && !IS_ROTARY_EVENT(event)) {
            pauseEvents(event); // delay before auto-repeat continues
            if (newval>val) // without AUDIO it's optimized, because the 2 sounds are the same
                AUDIO_KEYPAD_UP();
            else
                AUDIO_KEYPAD_DOWN();
        }
        eeDirty(i_flags & (EE_GENERAL|EE_MODEL));
        checkIncDec_Ret = (newval > val ? 1 : -1);
    }
    else {
        checkIncDec_Ret = 0;
    }
    return newval;
}

#if defined(CPUM64)
int8_t checkIncDecModel(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max)
{
    return checkIncDec(event, i_val, i_min, i_max, EE_MODEL);
}

int8_t checkIncDecModelZero(uint8_t event, int8_t i_val, int8_t i_max)
{
    return checkIncDecModel(event, i_val, 0, i_max);
}

int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max)
{
    return checkIncDec(event, i_val, i_min, i_max, EE_GENERAL);
}
#endif

bool check_simple(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, vertpos_t maxrow)
{
    return check(event, curr, menuTab, menuTabSize, 0, 0, maxrow);
}

bool check_submenu_simple(check_event_t event, uint8_t maxrow)
{
    return check_simple(event, 0, 0, 0, maxrow);
}

void title(const pm_char * s)
{
    lcd_putsAtt(0, 0, s, INVERS);
}

#define SCROLL_TH      64
#define SCROLL_POT1_TH 32

#if defined(CPUARM)
#define CURSOR_NOT_ALLOWED_IN_ROW(row)   ((int8_t)MAXCOL(row) < 0)
#else
#define CURSOR_NOT_ALLOWED_IN_ROW(row)   (MAXCOL(row) == TITLE_ROW)
#endif

#if defined(PCBTARANIS)
#define MAXCOL_RAW(row) (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0)
#define MAXCOL(row)     (MAXCOL_RAW(row) >= HIDDEN_ROW ? MAXCOL_RAW(row) : (const uint8_t)(MAXCOL_RAW(row) & (~NAVIGATION_LINE_BY_LINE)))
#define COLATTR(row)    (MAXCOL_RAW(row) == (uint8_t)-1 ? (const uint8_t)0 : (const uint8_t)(MAXCOL_RAW(row) & NAVIGATION_LINE_BY_LINE))
#else
#define MAXCOL(row)     (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0)
#endif

#define INC(val, min, max) if (val<max) {val++;} else {val=min;}
#define DEC(val, min, max) if (val>min) {val--;} else {val=max;}

#if LCD_W >= 212
uint8_t scrollbar_X = LCD_W-1;
#endif

#if defined(CPUARM)
bool modelHasNotes()
{
    char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/";
    char *buf = strcat_modelname(&filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel);
    strcpy(buf, TEXT_EXT);

    return isFileAvailable(filename);
}

void pushModelNotes()
{
    char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/";
    char *buf = strcat_modelname(&filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel);
    strcpy(buf, TEXT_EXT);
    pushMenuTextView(filename);
}
#endif

#if defined(PCBTARANIS)
void onLongMenuPress(const char *result)
{
    if (result == STR_VIEW_CHANNELS) {
        pushMenu(menuChannelsView);
    }
    else if (result == STR_VIEW_NOTES) {
        pushModelNotes();
    }
}
#endif

#if defined(CPUARM)
tmr10ms_t menuEntryTime;
#endif

#if defined(PCBTARANIS)
bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow, uint8_t flags)
{
    vertpos_t l_posVert = m_posVert;
    horzpos_t l_posHorz = m_posHorz;

    uint8_t maxcol = MAXCOL(l_posVert);

#define scrollUD 0

    if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on

    if (menuTab) {
        uint8_t attr = 0;

        int8_t cc = curr;
        switch (event) {
        case EVT_KEY_LONG(KEY_MENU):
            if (menuTab == menuTabModel) {
                killEvents(event);
                if (modelHasNotes()) {
                    MENU_ADD_SD_ITEM(STR_VIEW_CHANNELS);
                    MENU_ADD_ITEM(STR_VIEW_NOTES);
                    menuHandler = onLongMenuPress;
                }
                else {
                    pushMenu(menuChannelsView);
                    return false;
                }
            }
            break;

        case EVT_KEY_LONG(KEY_PAGE):
            if (curr > 0)
                cc = curr - 1;
            else
                cc = menuTabSize-1;
            killEvents(event);
            break;

        case EVT_KEY_BREAK(KEY_PAGE):
            if (curr < (menuTabSize-1))
                cc = curr + 1;
            else
                cc = 0;
            break;
        }

        if (!calibrationState && cc != curr) {
            chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc]));
            return false;
        }

        if (!(flags&CHECK_FLAG_NO_SCREEN_INDEX)) {
            displayScreenIndex(curr, menuTabSize, attr);
        }

        lcd_filled_rect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
    }

    DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);

    if (s_editMode<=0) {
        if (scrollUD) {
            l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow);
            l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
        }

        if (p2valdiff && l_posVert>0) {
            l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol);
        }
    }

    switch(event)
    {
    case EVT_ENTRY:
        menuEntryTime = get_tmr10ms();
        l_posVert = POS_VERT_INIT;
        l_posHorz = POS_HORZ_INIT(l_posVert);
        SET_SCROLLBAR_X(LCD_W-1);
#if defined(ROTARY_ENCODER_NAVIGATION)
        if (menuTab) {
            s_editMode = EDIT_MODE_INIT;
            break;
        }
        // no break
#else
        s_editMode = EDIT_MODE_INIT;
        break;
#endif

    case EVT_ENTRY_UP:
        menuEntryTime = get_tmr10ms();
        s_editMode = 0;
        l_posHorz = POS_HORZ_INIT(l_posVert);
        SET_SCROLLBAR_X(LCD_W-1);
        break;

    case EVT_ROTARY_BREAK:
        if (s_editMode > 1) break;
        if (m_posHorz < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) {
            l_posHorz = 0;
            break;
        }
        if (!menuTab || l_posVert>0) {
            if (READ_ONLY_UNLOCKED()) {
                s_editMode = (s_editMode<=0);
            }
        }
        break;

#if defined(ROTARY_ENCODER_NAVIGATION)
    case EVT_ROTARY_LONG:
        if (s_editMode > 1) break;
        killEvents(event);
        if (l_posVert != POS_VERT_INIT) {
            l_posVert = POS_VERT_INIT;
            s_editMode = EDIT_MODE_INIT;
            break;
        }
        // no break
#endif
    case EVT_KEY_LONG(KEY_EXIT):
        s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same
        popMenu();
        return false;

    case EVT_KEY_BREAK(KEY_EXIT):
#if defined(ROTARY_ENCODER_NAVIGATION)
        if (s_editMode == 0)
            s_editMode = EDIT_MODE_INIT;
        else
#endif
            if (s_editMode>0) {
                s_editMode = 0;
                break;
            }

        if (l_posHorz >= 0 && (COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            l_posHorz = -1;
        }
        else
        {
            uint8_t posVertInit = POS_VERT_INIT;
            if (s_pgOfs != 0 || l_posVert != posVertInit) {
                s_pgOfs = 0;
                l_posVert = posVertInit;
                l_posHorz = POS_HORZ_INIT(l_posVert);
            }
            else {
                popMenu();
                return false;
            }
        }
        break;

        CASE_EVT_ROTARY_MOVE_RIGHT
        if (s_editMode != 0) break;
        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            if (l_posHorz >= 0) {
                INC(l_posHorz, 0, maxcol);
                break;
            }
        }
        else {
            if (l_posHorz < maxcol) {
                l_posHorz++;
                break;
            }
            else {
                l_posHorz = 0;
                if (!IS_ROTARY_MOVE_RIGHT(event))
                    break;
            }
        }

        do {
            INC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

        s_editMode = 0; // if we go down, we must be in this mode

        l_posHorz = POS_HORZ_INIT(l_posVert);
        break;

        CASE_EVT_ROTARY_MOVE_LEFT
        if (s_editMode != 0) break;
        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            if (l_posHorz >= 0) {
                DEC(l_posHorz, 0, maxcol);
                break;
            }
        }
        else {
            if (l_posHorz > 0) {
                l_posHorz--;
                break;
            }
            else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) {
                l_posHorz = 0xff;
            }
            else {
                l_posHorz = maxcol;
                break;
            }
        }

        do {
            DEC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

        s_editMode = 0; // if we go up, we must be in this mode

        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE))
            l_posHorz = -1;
        else
            l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));

        break;
    }

#if defined(CPUARM)
    if (l_posVert<1) {
        s_pgOfs=0;
    }
    else if (menuTab && horTab) {
        if (maxrow > LCD_LINES-1) {
            while (1) {
                vertpos_t line = s_pgOfs+1;
                for (int numLines=0; line<=maxrow && numLines<LCD_LINES-1; line++) {
                    if (MAXCOL(line) != HIDDEN_ROW) {
                        numLines++;
                    }
                }
                int max = line - s_pgOfs - 1;
                if (l_posVert > max+s_pgOfs) {
                    s_pgOfs++;
                }
                else if (l_posVert < 1+s_pgOfs) {
                    s_pgOfs--;
                }
                else {
                    break;
                }
            }
        }
    }
    else {
        uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
        if (l_posVert>max+s_pgOfs) {
            s_pgOfs = l_posVert-max;
        }
        else if (l_posVert<1+s_pgOfs) {
            s_pgOfs = l_posVert-1;
        }
    }

#if LCD_W >= 212
    if (maxrow > LCD_LINES-1 && scrollbar_X)
        displayScrollbar(scrollbar_X, FH, LCD_H-FH, s_pgOfs, menuTab ? maxrow : maxrow+1, LCD_LINES-1);
#endif

#else
    uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
    if (l_posVert<1) s_pgOfs=0;
    else if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max;
    else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1;
#endif
    m_posVert = l_posVert;
    m_posHorz = l_posHorz;
    if (s_pgOfs > 0) {
        l_posVert--;
        if (l_posVert == s_pgOfs && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)) {
            s_pgOfs = l_posVert-1;
        }
    }
    return true;
}

#else // defined(PCBTARANIS)

bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow)
{
    vertpos_t l_posVert = m_posVert;
    horzpos_t l_posHorz = m_posHorz;

    uint8_t maxcol = MAXCOL(l_posVert);

#if defined(NAVIGATION_POT1)
    // check pot 1 - if changed -> scroll values
    static int16_t p1val;
    static int16_t p1valprev;
    p1valdiff = (p1val-calibratedStick[6]) / SCROLL_POT1_TH;
    if (p1valdiff) {
        p1valdiff = (p1valprev-calibratedStick[6]) / 2;
        p1val = calibratedStick[6];
    }
    p1valprev = calibratedStick[6];
#endif

#if defined(NAVIGATION_POT2)
    // check pot 2 - if changed -> scroll menu
    static int16_t p2valprev;
    p2valdiff = (p2valprev-calibratedStick[4]) / SCROLL_TH;
    if (p2valdiff) p2valprev = calibratedStick[4];
#endif

#if defined(NAVIGATION_POT3)
    // check pot 3 if changed -> cursor down/up
    static int16_t p3valprev;
    int8_t scrollUD = (p3valprev-calibratedStick[5]) / SCROLL_TH;
    if (scrollUD) p3valprev = calibratedStick[5];
#else
#define scrollUD 0
#endif

    if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on

    if (menuTab) {
        uint8_t attr = 0;


        if (l_posVert==0 && !calibrationState) {
            attr = INVERS;

            int8_t cc = curr;

            if (p2valdiff) {
                cc = limit((int8_t)0, (int8_t)(cc - p2valdiff), (int8_t)(menuTabSize-1));
            }

            switch(event) {
#if defined(ROTARY_ENCODER_NAVIGATION)
            case EVT_ROTARY_BREAK:
                if (s_editMode < 0 && maxrow > 0) {
                    s_editMode = 0;
                    // TODO ? l_posVert = (horTab && horTab[1]==0xff) ? 2 : 1;
                    l_posHorz = 0;
                }
                else {
                    s_editMode = -1;
                }
                event = 0;
                break;
#endif

#if defined(ROTARY_ENCODER_NAVIGATION)
            case EVT_ROTARY_LEFT:
                if (s_editMode >= 0)
                    break;
#endif
            case EVT_KEY_FIRST(KEY_LEFT):
                if (curr > 0)
                    cc = curr - 1;
                else
                    cc = menuTabSize-1;
                break;

#if defined(ROTARY_ENCODER_NAVIGATION)
            case EVT_ROTARY_RIGHT:
                if (s_editMode >= 0)
                    break;
#endif
            case EVT_KEY_FIRST(KEY_RIGHT):
                if (curr < (menuTabSize-1))
                    cc = curr + 1;
                else
                    cc = 0;
                break;
            }

            if (cc != curr) {
                chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc]));
                return false;
            }

#if defined(ROTARY_ENCODER_NAVIGATION)
            if (IS_RE_NAVIGATION_ENABLE() && s_editMode < 0)
                attr = INVERS|BLINK;
#endif
        }

        calibrationState = 0;
        displayScreenIndex(curr, menuTabSize, attr);

    }

    DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);

    if (s_editMode<=0) {
        if (scrollUD) {
            l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow);
            l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
        }

        if (p2valdiff && l_posVert>0) {
            l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol);
        }
    }

    switch(event)
    {
    case EVT_ENTRY:
#if defined(CPUARM)
        menuEntryTime = get_tmr10ms();
#endif
        l_posVert = POS_VERT_INIT;
        l_posHorz = POS_HORZ_INIT(l_posVert);
        SET_SCROLLBAR_X(LCD_W-1);
#if defined(ROTARY_ENCODER_NAVIGATION)
        if (menuTab) {
            s_editMode = EDIT_MODE_INIT;
            break;
        }
        // no break
#else
        s_editMode = EDIT_MODE_INIT;
        break;
#endif

#if defined(ROTARY_ENCODER_NAVIGATION)
    case EVT_ENTRY_UP:
        s_editMode = 0;
        SET_SCROLLBAR_X(LCD_W-1);
        break;

    case EVT_ROTARY_BREAK:
        if (s_editMode > 1) break;
#endif

    case EVT_KEY_FIRST(KEY_ENTER):
        if (!menuTab || l_posVert>0) {
            if (READ_ONLY_UNLOCKED()) {
                s_editMode = (s_editMode<=0);
            }
        }
        break;

#if defined(ROTARY_ENCODER_NAVIGATION)
    case EVT_ROTARY_LONG:
        if (s_editMode > 1) break;
        killEvents(event);
        if (l_posVert != POS_VERT_INIT) {
            l_posVert = POS_VERT_INIT;
            s_editMode = EDIT_MODE_INIT;
            break;
        }
        // no break
#endif
    case EVT_KEY_LONG(KEY_EXIT):
        s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same
        popMenu();
        return false;

    case EVT_KEY_BREAK(KEY_EXIT):
#if defined(ROTARY_ENCODER_NAVIGATION)
        if (s_editMode == 0)
            s_editMode = EDIT_MODE_INIT;
        else
#endif
            if (s_editMode>0) {
                s_editMode = 0;
                break;
            }

        if (l_posVert==0 || !menuTab) {
            popMenu();  // beeps itself
            return false;
        }
        else {
            AUDIO_MENUS();
            l_posVert = 0;
            l_posHorz = 0;
        }
        break;

    case EVT_KEY_REPT(KEY_RIGHT):  //inc
        if (l_posHorz==maxcol) break;
    // no break

    case EVT_KEY_FIRST(KEY_RIGHT)://inc
        if (!horTab || s_editMode>0) break;

#if defined(ROTARY_ENCODER_NAVIGATION)
        CASE_EVT_ROTARY_MOVE_RIGHT
        if (s_editMode != 0) break;
        if (l_posHorz < maxcol) {
            l_posHorz++;
            break;
        }
        else {
            l_posHorz = 0;
            if (!IS_ROTARY_MOVE_RIGHT(event))
                break;
        }
#else
        INC(l_posHorz, 0, maxcol);
        break;
#endif

    case EVT_KEY_REPT(KEY_DOWN):  //inc
        if (!IS_ROTARY_RIGHT(event) && l_posVert==maxrow) break;
    // no break

    case EVT_KEY_FIRST(KEY_DOWN): //inc
        if (s_editMode>0) break;
        do {
            INC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

#if defined(ROTARY_ENCODER_NAVIGATION)
        s_editMode = 0; // if we go down, we must be in this mode
#endif

        l_posHorz = min(l_posHorz, MAXCOL(l_posVert));
        break;

    case EVT_KEY_REPT(KEY_LEFT):  //dec
        if (l_posHorz==0) break;
    // no break

    case EVT_KEY_FIRST(KEY_LEFT)://dec
        if (!horTab || s_editMode>0) break;

#if defined(ROTARY_ENCODER_NAVIGATION)
        CASE_EVT_ROTARY_MOVE_LEFT
        if (s_editMode != 0) break;
        if (l_posHorz > 0) {
            l_posHorz--;
            break;
        }
        else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) {
            l_posHorz = 0xff;
        }
        else {
            l_posHorz = maxcol;
            break;
        }
#else
        DEC(l_posHorz, 0, maxcol);
        break;
#endif

    case EVT_KEY_REPT(KEY_UP):  //dec
        if (!IS_ROTARY_LEFT(event) && l_posVert==0) break;
    // no break
    case EVT_KEY_FIRST(KEY_UP): //dec
        if (s_editMode>0) break;

        do {
            DEC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS)
        s_editMode = 0; // if we go up, we must be in this mode
#endif

        l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
        break;
    }

#if defined(CPUARM)
    if (l_posVert<1) s_pgOfs=0;
    else if (menuTab && horTab) {
        vertpos_t realPosVert = l_posVert;
        vertpos_t realPgOfs = s_pgOfs;
        vertpos_t realMaxrow = maxrow;
        for (vertpos_t i=1; i<=maxrow; i++) {
            if (MAXCOL(i) == HIDDEN_ROW) {
                realMaxrow--;
                if (i < l_posVert)
                    realPosVert--;
                if (i < s_pgOfs)
                    realPgOfs--;
            }
        }
        if (realPosVert>(LCD_LINES-1)+realPgOfs) realPgOfs = realPosVert-(LCD_LINES-1);
        else if (realPosVert<1+realPgOfs) realPgOfs = realPosVert-1;
        s_pgOfs = realPgOfs;
        for (vertpos_t i=1; i<=realPgOfs; i++) {
            if (MAXCOL(i) == HIDDEN_ROW) {
                s_pgOfs++;
            }
        }
        maxrow = realMaxrow;
    }
    else {
        uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
        if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max;
        else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1;
    }

#if LCD_W >= 212
    if (maxrow > LCD_LINES-1 && scrollbar_X)
        displayScrollbar(scrollbar_X, FH, LCD_H-FH, s_pgOfs, menuTab ? maxrow : maxrow+1, LCD_LINES-1);
#endif

#else
    uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
    if (l_posVert<1) s_pgOfs=0;
    else if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max;
    else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1;
#endif
    m_posVert = l_posVert;
    m_posHorz = l_posHorz;
#if !defined(CPUM64)
    // cosmetics on 9x
    if (s_pgOfs > 0) {
        l_posVert--;
        if (l_posVert == s_pgOfs && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert))
            s_pgOfs = l_posVert-1;
    }
#endif
    return true;
}
#endif

MenuFuncP g_menuStack[5];
uint8_t g_menuPos[4];
uint8_t g_menuStackPtr = 0;
vertpos_t m_posVert;
horzpos_t m_posHorz;

void popMenu()
{
    assert(g_menuStackPtr>0);

    g_menuStackPtr = g_menuStackPtr-1;
    AUDIO_KEYPAD_UP();
    m_posHorz = 0;
    m_posVert = g_menuPos[g_menuStackPtr];
    (*g_menuStack[g_menuStackPtr])(EVT_ENTRY_UP);
}

void chainMenu(MenuFuncP newMenu)
{
    g_menuStack[g_menuStackPtr] = newMenu;
    (*newMenu)(EVT_ENTRY);
    AUDIO_MENUS();
}

void pushMenu(MenuFuncP newMenu)
{
    killEvents(KEY_ENTER);

    if (g_menuStackPtr == 0) {
        if (newMenu == menuGeneralSetup)
            g_menuPos[0] = 1;
        if (newMenu == menuModelSelect)
            g_menuPos[0] = 0;
    }
    else {
        g_menuPos[g_menuStackPtr] = m_posVert;
    }

    g_menuStackPtr++;

    assert(g_menuStackPtr < DIM(g_menuStack));

    AUDIO_MENUS();
    g_menuStack[g_menuStackPtr] = newMenu;
    (*newMenu)(EVT_ENTRY);
}

const pm_char * s_warning = NULL;
const pm_char * s_warning_info;
uint8_t         s_warning_info_len;
uint8_t         s_warning_type;
uint8_t         s_warning_result = 0;

#if defined(CPUARM)
uint8_t s_warning_info_flags = ZCHAR;
int16_t s_warning_input_value;
int16_t s_warning_input_min;
int16_t s_warning_input_max;
#endif

void displayBox()
{
    lcd_filled_rect(10, 16, LCD_W-20, 40, SOLID, ERASE);
    lcd_rect(10, 16, LCD_W-20, 40);
#if defined(CPUARM)
    lcd_putsn(WARNING_LINE_X, WARNING_LINE_Y, s_warning, WARNING_LINE_LEN);
#else
    lcd_puts(WARNING_LINE_X, WARNING_LINE_Y, s_warning);
#endif
    // could be a place for a s_warning_info
}

void displayPopup(const pm_char * pstr)
{
    s_warning = pstr;
    displayBox();
    s_warning = NULL;
    lcdRefresh();
}

void displayWarning(uint8_t event)
{
    s_warning_result = false;
    displayBox();
    if (s_warning_info)
        lcd_putsnAtt(16, WARNING_LINE_Y+FH, s_warning_info, s_warning_info_len, WARNING_INFO_FLAGS);
    lcd_puts(16, WARNING_LINE_Y+2*FH, s_warning_type == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS);
    switch (event) {
#if defined(ROTARY_ENCODER_NAVIGATION)
    case EVT_ROTARY_BREAK:
#endif
    case EVT_KEY_BREAK(KEY_ENTER):
        if (s_warning_type == WARNING_TYPE_ASTERISK)
            break;
        s_warning_result = true;
        // no break
#if defined(ROTARY_ENCODER_NAVIGATION)
    case EVT_ROTARY_LONG:
        killEvents(event);
#endif
    case EVT_KEY_BREAK(KEY_EXIT):
        s_warning = NULL;
        s_warning_type = WARNING_TYPE_ASTERISK;
        break;
#if defined(CPUARM)
    default:
        if (s_warning_type != WARNING_TYPE_INPUT) break;
        s_editMode = EDIT_MODIFY_FIELD;
        s_warning_input_value = checkIncDec(event, s_warning_input_value, s_warning_input_min, s_warning_input_max);
        s_editMode = EDIT_SELECT_FIELD;
        break;
#endif
    }
}

select_menu_value_t selectMenuItem(uint8_t x, uint8_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event)
{
    lcd_putsColumnLeft(x, y, label);
    if (values) lcd_putsiAtt(x, y, values, value-min, attr);
    if (attr) value = checkIncDec(event, value, min, max, (g_menuPos[0] == 0) ? EE_MODEL : EE_GENERAL);
    return value;
}

uint8_t onoffMenuItem(uint8_t value, uint8_t x, uint8_t y, const pm_char *label, LcdFlags attr, uint8_t event )
{
#if defined(GRAPHICS)
    menu_lcd_onoff(x, y, value, attr);
    return selectMenuItem(x, y, label, NULL, value, 0, 1, attr, event);
#else
    return selectMenuItem(x, y, label, STR_OFFON, value, 0, 1, attr, event);
#endif
}

int8_t switchMenuItem(uint8_t x, uint8_t y, int8_t value, LcdFlags attr, uint8_t event)
{
    lcd_putsColumnLeft(x, y, STR_SWITCH);
    putsSwitches(x,  y, value, attr);
    if (attr) CHECK_INCDEC_MODELSWITCH(event, value, SWSRC_FIRST_SHORT_LIST, SWSRC_LAST_SHORT_LIST);
    return value;
}

#if !defined(CPUM64)
void displaySlider(uint8_t x, uint8_t y, uint8_t value, uint8_t max, uint8_t attr)
{
    lcd_putc(x+(value*4*FW)/max, y, '$');
    lcd_hline(x, y+3, 5*FW-1, SOLID);
    if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) lcd_filled_rect(x, y, 5*FW-1, FH-1);
}
#elif defined(GRAPHICS)
void display5posSlider(uint8_t x, uint8_t y, uint8_t value, uint8_t attr)
{
    lcd_putc(x+2*FW+(value*FW), y, '$');
    lcd_hline(x, y+3, 5*FW-1, SOLID);
    if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) lcd_filled_rect(x, y, 5*FW-1, FH-1);
}
#endif

#if defined(GVARS)
#if defined(CPUARM)
int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event)
#else
int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event)
#endif
{
    uint16_t delta = GV_GET_GV1_VALUE(max);
    bool invers = (attr & INVERS);

    // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max);

    if (invers && event == EVT_KEY_LONG(KEY_ENTER)) {
        s_editMode = !s_editMode;
#if defined(CPUARM)
        if (attr & PREC1)
            value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode)*10 : delta);
        else
            value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode) : delta);
#else
        value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode) : delta);
#endif
        eeDirty(EE_MODEL);
    }
    if (GV_IS_GV_VALUE(value, min, max)) {
        if (attr & LEFT)
            attr -= LEFT; /* because of ZCHAR */
        else
            x -= 2*FW+FWNUM;

#if defined(CPUARM)
        attr &= ~PREC1;
#endif

        int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta);
        if (invers) {
            CHECK_INCDEC_MODELVAR(event, idx, -MAX_GVARS, MAX_GVARS-1);
        }

        if (idx < 0) {
            value = (int16_t) GV_CALC_VALUE_IDX_NEG(idx, delta);
            idx = -idx;
            lcd_putcAtt(x-6, y, '-', attr);
        }
        else {
            value = (int16_t) GV_CALC_VALUE_IDX_POS(idx, delta);
            idx++;
        }
        putsStrIdx(x, y, STR_GV, idx, attr);
    }
    else {
        lcd_outdezAtt(x, y, value, attr);
#if defined(CPUARM)
        if (invers) value = checkIncDec(event, value, min, max, EE_MODEL | editflags);
#else
        if (invers) value = checkIncDec(event, value, min, max, EE_MODEL);
#endif
    }
    return value;
}
#else
int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event)
{
    lcd_outdezAtt(x, y, value, attr);
    if (attr&INVERS) value = checkIncDec(event, value, min, max, EE_MODEL);
    return value;
}
#endif

void repeatLastCursorMove(uint8_t event)
{
    if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) {
        putEvent(event);
    }
    else {
        m_posHorz = 0;
    }
}

#if LCD_W >= 212
#define MENU_X   30
#define MENU_Y   16
#define MENU_W   LCD_W-60
#else
#define MENU_X   10
#define MENU_Y   16
#define MENU_W   LCD_W-20
#endif

#if defined(CPUARM)
void (*popupFunc)(uint8_t event) = NULL;
#endif

#if defined(NAVIGATION_MENUS)
const char *s_menu[MENU_MAX_LINES];
uint8_t s_menu_item = 0;
uint16_t s_menu_count = 0;
uint8_t s_menu_flags = 0;
uint16_t s_menu_offset = 0;
void (*menuHandler)(const char *result);
const char * displayMenu(uint8_t event)
{
    const char * result = NULL;

    uint8_t display_count = min(s_menu_count, (uint16_t)MENU_MAX_LINES);
    uint8_t y = (display_count >= 5 ? MENU_Y - FH - 1 : MENU_Y);
    lcd_filled_rect(MENU_X, y, MENU_W, display_count * (FH+1) + 2, SOLID, ERASE);
    lcd_rect(MENU_X, y, MENU_W, display_count * (FH+1) + 2);

    for (uint8_t i=0; i<display_count; i++) {
        lcd_putsAtt(MENU_X+6, i*(FH+1) + y + 2, s_menu[i], s_menu_flags);
        if (i == s_menu_item) lcd_filled_rect(MENU_X+1, i*(FH+1) + y + 1, MENU_W-2, 9);
    }

    if (s_menu_count > display_count) {
        displayScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_LINES * (FH+1), s_menu_offset, s_menu_count, MENU_MAX_LINES);
    }

    switch(event) {
#if defined(ROTARY_ENCODER_NAVIGATION)
        CASE_EVT_ROTARY_LEFT
#endif
    case EVT_KEY_FIRST(KEY_MOVE_UP):
    case EVT_KEY_REPT(KEY_MOVE_UP):
        if (s_menu_item > 0) {
            s_menu_item--;
        }
#if defined(SDCARD)
        else if (s_menu_offset > 0) {
            s_menu_offset--;
            result = STR_UPDATE_LIST;
        }
#endif
        else {
            s_menu_item = display_count - 1;
#if defined(SDCARD)
            if (s_menu_count > MENU_MAX_LINES) {
                s_menu_offset = s_menu_count - display_count;
                result = STR_UPDATE_LIST;
            }
#endif
        }
        break;

#if defined(ROTARY_ENCODER_NAVIGATION)
        CASE_EVT_ROTARY_RIGHT
#endif
    case EVT_KEY_FIRST(KEY_MOVE_DOWN):
    case EVT_KEY_REPT(KEY_MOVE_DOWN):
        if (s_menu_item < display_count - 1 && s_menu_offset + s_menu_item + 1 < s_menu_count) {
            s_menu_item++;
        }
#if defined(SDCARD)
        else if (s_menu_count > s_menu_offset + display_count) {
            s_menu_offset++;
            result = STR_UPDATE_LIST;
        }
#endif
        else {
            s_menu_item = 0;
#if defined(SDCARD)
            if (s_menu_offset) {
                s_menu_offset = 0;
                result = STR_UPDATE_LIST;
            }
#endif
        }
        break;
        CASE_EVT_ROTARY_BREAK
    case EVT_KEY_BREAK(KEY_ENTER):
        result = s_menu[s_menu_item];
        // no break
#if defined(ROTARY_ENCODER_NAVIGATION)
        CASE_EVT_ROTARY_LONG
        killEvents(event);
#endif
    case EVT_KEY_BREAK(KEY_EXIT):
        s_menu_count = 0;
        s_menu_item = 0;
        s_menu_flags = 0;
        s_menu_offset = 0;
        break;
    }

    return result;
}
#endif

#if defined(SDCARD)
char statusLineMsg[STATUS_LINE_LENGTH];
tmr10ms_t statusLineTime = 0;
uint8_t statusLineHeight = 0;

void showStatusLine()
{
    statusLineTime = get_tmr10ms();
}

#define STATUS_LINE_DELAY (3 * 100) /* 3s */
void drawStatusLine()
{
    if (statusLineTime) {
        if ((tmr10ms_t)(get_tmr10ms() - statusLineTime) <= (tmr10ms_t)STATUS_LINE_DELAY) {
            if (statusLineHeight < FH) statusLineHeight++;
        }
        else if (statusLineHeight) {
            statusLineHeight--;
        }
        else {
            statusLineTime = 0;
        }

        lcd_filled_rect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID, ERASE);
        lcd_putsAtt(5, LCD_H+1-statusLineHeight, statusLineMsg, BSS);
        lcd_filled_rect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID);
    }
}
예제 #7
0
void writeLogs()
{
  static const pm_char * error_displayed = NULL;

  if (isFunctionActive(FUNCTION_LOGS) && logDelay > 0) {
    tmr10ms_t tmr10ms = get_tmr10ms();
    if (lastLogTime == 0 || (tmr10ms_t)(tmr10ms - lastLogTime) >= (tmr10ms_t)logDelay*10) {
      lastLogTime = tmr10ms;

      if (!g_oLogFile.fs) {
        const pm_char * result = openLogs();
        if (result != NULL) {
          if (result != error_displayed) {
            error_displayed = result;
            POPUP_WARNING(result);
          }
          return;
        }
      }

#if defined(RTCLOCK)
      {
        static struct gtm utm;
        static gtime_t lastRtcTime = 0;
        if ( g_rtcTime != lastRtcTime )
        {
          lastRtcTime = g_rtcTime;
          gettime(&utm);
        }
        f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d.%02d0,", utm.tm_year+1900, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec, g_ms100);
      }
#else
      f_printf(&g_oLogFile, "%d,", tmr10ms);
#endif

#if defined(FRSKY)
#if !defined(CPUARM)
      f_printf(&g_oLogFile, "%d,%d,%d,", frskyStreaming, RAW_FRSKY_MINMAX(frskyData.rssi[0]), RAW_FRSKY_MINMAX(frskyData.rssi[1]));
      for (uint8_t i=0; i<MAX_FRSKY_A_CHANNELS; i++) {
        int16_t converted_value = applyChannelRatio(i, RAW_FRSKY_MINMAX(frskyData.analog[i]));
        f_printf(&g_oLogFile, "%d.%02d,", converted_value/100, converted_value%100);
      }

#if defined(FRSKY_HUB)
      TELEMETRY_BARO_ALT_PREPARE();

      if (IS_USR_PROTO_FRSKY_HUB()) {
        f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d,%03d.%04d%c,%03d.%04d%c,%03d.%02d," TELEMETRY_GPS_SPEED_FORMAT TELEMETRY_GPS_ALT_FORMAT TELEMETRY_BARO_ALT_FORMAT TELEMETRY_VSPEED_FORMAT TELEMETRY_ASPEED_FORMAT "%d,%d,%d,%d," TELEMETRY_CELLS_FORMAT TELEMETRY_CURRENT_FORMAT "%d," TELEMETRY_VFAS_FORMAT "%d,%d,%d,",
            frskyData.hub.year+2000,
            frskyData.hub.month,
            frskyData.hub.day,
            frskyData.hub.hour,
            frskyData.hub.min,
            frskyData.hub.sec,
            frskyData.hub.gpsLongitude_bp,
            frskyData.hub.gpsLongitude_ap,
            frskyData.hub.gpsLongitudeEW ? frskyData.hub.gpsLongitudeEW : '-',
            frskyData.hub.gpsLatitude_bp,
            frskyData.hub.gpsLatitude_ap,
            frskyData.hub.gpsLatitudeNS ? frskyData.hub.gpsLatitudeNS : '-',
            frskyData.hub.gpsCourse_bp,
            frskyData.hub.gpsCourse_ap,
            TELEMETRY_GPS_SPEED_ARGS
            TELEMETRY_GPS_ALT_ARGS
            TELEMETRY_BARO_ALT_ARGS
            TELEMETRY_VSPEED_ARGS
            TELEMETRY_ASPEED_ARGS
            frskyData.hub.temperature1,
            frskyData.hub.temperature2,
            frskyData.hub.rpm,
            frskyData.hub.fuelLevel,
            TELEMETRY_CELLS_ARGS
            TELEMETRY_CURRENT_ARGS
            frskyData.hub.currentConsumption,
            TELEMETRY_VFAS_ARGS
            frskyData.hub.accelX,
            frskyData.hub.accelY,
            frskyData.hub.accelZ);
      }
#endif

#if defined(WS_HOW_HIGH)
      if (IS_USR_PROTO_WS_HOW_HIGH()) {
        f_printf(&g_oLogFile, "%d,", TELEMETRY_RELATIVE_BARO_ALT_BP);
      }
#endif
#endif

#if defined(CPUARM)
      for (int i=0; i<MAX_SENSORS; i++) {
        TelemetrySensor & sensor = g_model.telemetrySensors[i];
        TelemetryItem & telemetryItem = telemetryItems[i];
        if (sensor.logs) {
          if (sensor.unit == UNIT_GPS) {
            if (telemetryItem.gps.longitudeEW && telemetryItem.gps.latitudeNS)
              f_printf(&g_oLogFile, "%03d.%04d%c %03d.%04d%c,", telemetryItem.gps.longitude_bp, telemetryItem.gps.longitude_ap, telemetryItem.gps.longitudeEW, telemetryItem.gps.latitude_bp, telemetryItem.gps.latitude_ap, telemetryItem.gps.latitudeNS);
            else
              f_printf(&g_oLogFile, ",");
          }
          else if (sensor.unit == UNIT_DATETIME) {
            if (telemetryItem.datetime.datestate)
              f_printf(&g_oLogFile, "%4d-%02d-%02d %02d:%02d:%02d,", telemetryItem.datetime.year, telemetryItem.datetime.month, telemetryItem.datetime.day, telemetryItem.datetime.hour, telemetryItem.datetime.min, telemetryItem.datetime.sec);
            else
              f_printf(&g_oLogFile, ",");
          }
          else if (sensor.prec == 2) {
            div_t qr = div(telemetryItem.value, 100);
            if (telemetryItem.value < 0) f_printf(&g_oLogFile, "-");
            f_printf(&g_oLogFile, "%d.%02d,", abs(qr.quot), abs(qr.rem));
          }
          else if (sensor.prec == 1) {
            div_t qr = div(telemetryItem.value, 10);
            if (telemetryItem.value < 0) f_printf(&g_oLogFile, "-");
            f_printf(&g_oLogFile, "%d.%d,", abs(qr.quot), abs(qr.rem));
          }
          else {
            f_printf(&g_oLogFile, "%d,", telemetryItem.value);
          }
        }
      }
#endif
#endif

      for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) {
        f_printf(&g_oLogFile, "%d,", calibratedStick[i]);
      }

#if defined(PCBTARANIS)
      int result = f_printf(&g_oLogFile, "%d,%d,%d,%d,%d,%d,%d,%d\n",
          get3PosState(SA),
          get3PosState(SB),
          get3PosState(SC),
          get3PosState(SD),
          get3PosState(SE),
          get2PosState(SF),
          get3PosState(SG),
          get2PosState(SH));
#endif

      if (result<0 && !error_displayed) {
        error_displayed = STR_SDCARD_ERROR;
        POPUP_WARNING(STR_SDCARD_ERROR);
        closeLogs();
      }
    }
  }
  else {
    error_displayed = NULL;
    if (g_oLogFile.fs) {
      closeLogs();
    }
  }
}
예제 #8
0
bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow)
{
    vertpos_t l_posVert = m_posVert;
    horzpos_t l_posHorz = m_posHorz;

    uint8_t maxcol = MAXCOL(l_posVert);

#if defined(NAVIGATION_POT1)
    // check pot 1 - if changed -> scroll values
    static int16_t p1val;
    static int16_t p1valprev;
    p1valdiff = (p1val-calibratedStick[6]) / SCROLL_POT1_TH;
    if (p1valdiff) {
        p1valdiff = (p1valprev-calibratedStick[6]) / 2;
        p1val = calibratedStick[6];
    }
    p1valprev = calibratedStick[6];
#endif

#if defined(NAVIGATION_POT2)
    // check pot 2 - if changed -> scroll menu
    static int16_t p2valprev;
    p2valdiff = (p2valprev-calibratedStick[4]) / SCROLL_TH;
    if (p2valdiff) p2valprev = calibratedStick[4];
#endif

#if defined(NAVIGATION_POT3)
    // check pot 3 if changed -> cursor down/up
    static int16_t p3valprev;
    int8_t scrollUD = (p3valprev-calibratedStick[5]) / SCROLL_TH;
    if (scrollUD) p3valprev = calibratedStick[5];
#else
#define scrollUD 0
#endif

    if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on

    if (menuTab) {
        uint8_t attr = 0;


        if (l_posVert==0 && !calibrationState) {
            attr = INVERS;

            int8_t cc = curr;

            if (p2valdiff) {
                cc = limit((int8_t)0, (int8_t)(cc - p2valdiff), (int8_t)(menuTabSize-1));
            }

            switch(event) {
#if defined(ROTARY_ENCODER_NAVIGATION)
            case EVT_ROTARY_BREAK:
                if (s_editMode < 0 && maxrow > 0) {
                    s_editMode = 0;
                    // TODO ? l_posVert = (horTab && horTab[1]==0xff) ? 2 : 1;
                    l_posHorz = 0;
                }
                else {
                    s_editMode = -1;
                }
                event = 0;
                break;
#endif

#if defined(ROTARY_ENCODER_NAVIGATION)
            case EVT_ROTARY_LEFT:
                if (s_editMode >= 0)
                    break;
#endif
            case EVT_KEY_FIRST(KEY_LEFT):
                if (curr > 0)
                    cc = curr - 1;
                else
                    cc = menuTabSize-1;
                break;

#if defined(ROTARY_ENCODER_NAVIGATION)
            case EVT_ROTARY_RIGHT:
                if (s_editMode >= 0)
                    break;
#endif
            case EVT_KEY_FIRST(KEY_RIGHT):
                if (curr < (menuTabSize-1))
                    cc = curr + 1;
                else
                    cc = 0;
                break;
            }

            if (cc != curr) {
                chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc]));
                return false;
            }

#if defined(ROTARY_ENCODER_NAVIGATION)
            if (IS_RE_NAVIGATION_ENABLE() && s_editMode < 0)
                attr = INVERS|BLINK;
#endif
        }

        calibrationState = 0;
        displayScreenIndex(curr, menuTabSize, attr);

    }

    DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);

    if (s_editMode<=0) {
        if (scrollUD) {
            l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow);
            l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
        }

        if (p2valdiff && l_posVert>0) {
            l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol);
        }
    }

    switch(event)
    {
    case EVT_ENTRY:
#if defined(CPUARM)
        menuEntryTime = get_tmr10ms();
#endif
        l_posVert = POS_VERT_INIT;
        l_posHorz = POS_HORZ_INIT(l_posVert);
        SET_SCROLLBAR_X(LCD_W-1);
#if defined(ROTARY_ENCODER_NAVIGATION)
        if (menuTab) {
            s_editMode = EDIT_MODE_INIT;
            break;
        }
        // no break
#else
        s_editMode = EDIT_MODE_INIT;
        break;
#endif

#if defined(ROTARY_ENCODER_NAVIGATION)
    case EVT_ENTRY_UP:
        s_editMode = 0;
        SET_SCROLLBAR_X(LCD_W-1);
        break;

    case EVT_ROTARY_BREAK:
        if (s_editMode > 1) break;
#endif

    case EVT_KEY_FIRST(KEY_ENTER):
        if (!menuTab || l_posVert>0) {
            if (READ_ONLY_UNLOCKED()) {
                s_editMode = (s_editMode<=0);
            }
        }
        break;

#if defined(ROTARY_ENCODER_NAVIGATION)
    case EVT_ROTARY_LONG:
        if (s_editMode > 1) break;
        killEvents(event);
        if (l_posVert != POS_VERT_INIT) {
            l_posVert = POS_VERT_INIT;
            s_editMode = EDIT_MODE_INIT;
            break;
        }
        // no break
#endif
    case EVT_KEY_LONG(KEY_EXIT):
        s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same
        popMenu();
        return false;

    case EVT_KEY_BREAK(KEY_EXIT):
#if defined(ROTARY_ENCODER_NAVIGATION)
        if (s_editMode == 0)
            s_editMode = EDIT_MODE_INIT;
        else
#endif
            if (s_editMode>0) {
                s_editMode = 0;
                break;
            }

        if (l_posVert==0 || !menuTab) {
            popMenu();  // beeps itself
            return false;
        }
        else {
            AUDIO_MENUS();
            l_posVert = 0;
            l_posHorz = 0;
        }
        break;

    case EVT_KEY_REPT(KEY_RIGHT):  //inc
        if (l_posHorz==maxcol) break;
    // no break

    case EVT_KEY_FIRST(KEY_RIGHT)://inc
        if (!horTab || s_editMode>0) break;

#if defined(ROTARY_ENCODER_NAVIGATION)
        CASE_EVT_ROTARY_MOVE_RIGHT
        if (s_editMode != 0) break;
        if (l_posHorz < maxcol) {
            l_posHorz++;
            break;
        }
        else {
            l_posHorz = 0;
            if (!IS_ROTARY_MOVE_RIGHT(event))
                break;
        }
#else
        INC(l_posHorz, 0, maxcol);
        break;
#endif

    case EVT_KEY_REPT(KEY_DOWN):  //inc
        if (!IS_ROTARY_RIGHT(event) && l_posVert==maxrow) break;
    // no break

    case EVT_KEY_FIRST(KEY_DOWN): //inc
        if (s_editMode>0) break;
        do {
            INC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

#if defined(ROTARY_ENCODER_NAVIGATION)
        s_editMode = 0; // if we go down, we must be in this mode
#endif

        l_posHorz = min(l_posHorz, MAXCOL(l_posVert));
        break;

    case EVT_KEY_REPT(KEY_LEFT):  //dec
        if (l_posHorz==0) break;
    // no break

    case EVT_KEY_FIRST(KEY_LEFT)://dec
        if (!horTab || s_editMode>0) break;

#if defined(ROTARY_ENCODER_NAVIGATION)
        CASE_EVT_ROTARY_MOVE_LEFT
        if (s_editMode != 0) break;
        if (l_posHorz > 0) {
            l_posHorz--;
            break;
        }
        else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) {
            l_posHorz = 0xff;
        }
        else {
            l_posHorz = maxcol;
            break;
        }
#else
        DEC(l_posHorz, 0, maxcol);
        break;
#endif

    case EVT_KEY_REPT(KEY_UP):  //dec
        if (!IS_ROTARY_LEFT(event) && l_posVert==0) break;
    // no break
    case EVT_KEY_FIRST(KEY_UP): //dec
        if (s_editMode>0) break;

        do {
            DEC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS)
        s_editMode = 0; // if we go up, we must be in this mode
#endif

        l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
        break;
    }

#if defined(CPUARM)
    if (l_posVert<1) s_pgOfs=0;
    else if (menuTab && horTab) {
        vertpos_t realPosVert = l_posVert;
        vertpos_t realPgOfs = s_pgOfs;
        vertpos_t realMaxrow = maxrow;
        for (vertpos_t i=1; i<=maxrow; i++) {
            if (MAXCOL(i) == HIDDEN_ROW) {
                realMaxrow--;
                if (i < l_posVert)
                    realPosVert--;
                if (i < s_pgOfs)
                    realPgOfs--;
            }
        }
        if (realPosVert>(LCD_LINES-1)+realPgOfs) realPgOfs = realPosVert-(LCD_LINES-1);
        else if (realPosVert<1+realPgOfs) realPgOfs = realPosVert-1;
        s_pgOfs = realPgOfs;
        for (vertpos_t i=1; i<=realPgOfs; i++) {
            if (MAXCOL(i) == HIDDEN_ROW) {
                s_pgOfs++;
            }
        }
        maxrow = realMaxrow;
    }
    else {
        uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
        if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max;
        else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1;
    }

#if LCD_W >= 212
    if (maxrow > LCD_LINES-1 && scrollbar_X)
        displayScrollbar(scrollbar_X, FH, LCD_H-FH, s_pgOfs, menuTab ? maxrow : maxrow+1, LCD_LINES-1);
#endif

#else
    uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
    if (l_posVert<1) s_pgOfs=0;
    else if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max;
    else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1;
#endif
    m_posVert = l_posVert;
    m_posHorz = l_posHorz;
#if !defined(CPUM64)
    // cosmetics on 9x
    if (s_pgOfs > 0) {
        l_posVert--;
        if (l_posVert == s_pgOfs && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert))
            s_pgOfs = l_posVert-1;
    }
#endif
    return true;
}
예제 #9
0
bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow, uint8_t flags)
{
    vertpos_t l_posVert = m_posVert;
    horzpos_t l_posHorz = m_posHorz;

    uint8_t maxcol = MAXCOL(l_posVert);

#define scrollUD 0

    if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on

    if (menuTab) {
        uint8_t attr = 0;

        int8_t cc = curr;
        switch (event) {
        case EVT_KEY_LONG(KEY_MENU):
            if (menuTab == menuTabModel) {
                killEvents(event);
                if (modelHasNotes()) {
                    MENU_ADD_SD_ITEM(STR_VIEW_CHANNELS);
                    MENU_ADD_ITEM(STR_VIEW_NOTES);
                    menuHandler = onLongMenuPress;
                }
                else {
                    pushMenu(menuChannelsView);
                    return false;
                }
            }
            break;

        case EVT_KEY_LONG(KEY_PAGE):
            if (curr > 0)
                cc = curr - 1;
            else
                cc = menuTabSize-1;
            killEvents(event);
            break;

        case EVT_KEY_BREAK(KEY_PAGE):
            if (curr < (menuTabSize-1))
                cc = curr + 1;
            else
                cc = 0;
            break;
        }

        if (!calibrationState && cc != curr) {
            chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc]));
            return false;
        }

        if (!(flags&CHECK_FLAG_NO_SCREEN_INDEX)) {
            displayScreenIndex(curr, menuTabSize, attr);
        }

        lcd_filled_rect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
    }

    DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);

    if (s_editMode<=0) {
        if (scrollUD) {
            l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow);
            l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
        }

        if (p2valdiff && l_posVert>0) {
            l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol);
        }
    }

    switch(event)
    {
    case EVT_ENTRY:
        menuEntryTime = get_tmr10ms();
        l_posVert = POS_VERT_INIT;
        l_posHorz = POS_HORZ_INIT(l_posVert);
        SET_SCROLLBAR_X(LCD_W-1);
#if defined(ROTARY_ENCODER_NAVIGATION)
        if (menuTab) {
            s_editMode = EDIT_MODE_INIT;
            break;
        }
        // no break
#else
        s_editMode = EDIT_MODE_INIT;
        break;
#endif

    case EVT_ENTRY_UP:
        menuEntryTime = get_tmr10ms();
        s_editMode = 0;
        l_posHorz = POS_HORZ_INIT(l_posVert);
        SET_SCROLLBAR_X(LCD_W-1);
        break;

    case EVT_ROTARY_BREAK:
        if (s_editMode > 1) break;
        if (m_posHorz < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) {
            l_posHorz = 0;
            break;
        }
        if (!menuTab || l_posVert>0) {
            if (READ_ONLY_UNLOCKED()) {
                s_editMode = (s_editMode<=0);
            }
        }
        break;

#if defined(ROTARY_ENCODER_NAVIGATION)
    case EVT_ROTARY_LONG:
        if (s_editMode > 1) break;
        killEvents(event);
        if (l_posVert != POS_VERT_INIT) {
            l_posVert = POS_VERT_INIT;
            s_editMode = EDIT_MODE_INIT;
            break;
        }
        // no break
#endif
    case EVT_KEY_LONG(KEY_EXIT):
        s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same
        popMenu();
        return false;

    case EVT_KEY_BREAK(KEY_EXIT):
#if defined(ROTARY_ENCODER_NAVIGATION)
        if (s_editMode == 0)
            s_editMode = EDIT_MODE_INIT;
        else
#endif
            if (s_editMode>0) {
                s_editMode = 0;
                break;
            }

        if (l_posHorz >= 0 && (COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            l_posHorz = -1;
        }
        else
        {
            uint8_t posVertInit = POS_VERT_INIT;
            if (s_pgOfs != 0 || l_posVert != posVertInit) {
                s_pgOfs = 0;
                l_posVert = posVertInit;
                l_posHorz = POS_HORZ_INIT(l_posVert);
            }
            else {
                popMenu();
                return false;
            }
        }
        break;

        CASE_EVT_ROTARY_MOVE_RIGHT
        if (s_editMode != 0) break;
        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            if (l_posHorz >= 0) {
                INC(l_posHorz, 0, maxcol);
                break;
            }
        }
        else {
            if (l_posHorz < maxcol) {
                l_posHorz++;
                break;
            }
            else {
                l_posHorz = 0;
                if (!IS_ROTARY_MOVE_RIGHT(event))
                    break;
            }
        }

        do {
            INC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

        s_editMode = 0; // if we go down, we must be in this mode

        l_posHorz = POS_HORZ_INIT(l_posVert);
        break;

        CASE_EVT_ROTARY_MOVE_LEFT
        if (s_editMode != 0) break;
        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            if (l_posHorz >= 0) {
                DEC(l_posHorz, 0, maxcol);
                break;
            }
        }
        else {
            if (l_posHorz > 0) {
                l_posHorz--;
                break;
            }
            else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) {
                l_posHorz = 0xff;
            }
            else {
                l_posHorz = maxcol;
                break;
            }
        }

        do {
            DEC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

        s_editMode = 0; // if we go up, we must be in this mode

        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE))
            l_posHorz = -1;
        else
            l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));

        break;
    }

#if defined(CPUARM)
    if (l_posVert<1) {
        s_pgOfs=0;
    }
    else if (menuTab && horTab) {
        if (maxrow > LCD_LINES-1) {
            while (1) {
                vertpos_t line = s_pgOfs+1;
                for (int numLines=0; line<=maxrow && numLines<LCD_LINES-1; line++) {
                    if (MAXCOL(line) != HIDDEN_ROW) {
                        numLines++;
                    }
                }
                int max = line - s_pgOfs - 1;
                if (l_posVert > max+s_pgOfs) {
                    s_pgOfs++;
                }
                else if (l_posVert < 1+s_pgOfs) {
                    s_pgOfs--;
                }
                else {
                    break;
                }
            }
        }
    }
    else {
        uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
        if (l_posVert>max+s_pgOfs) {
            s_pgOfs = l_posVert-max;
        }
        else if (l_posVert<1+s_pgOfs) {
            s_pgOfs = l_posVert-1;
        }
    }

#if LCD_W >= 212
    if (maxrow > LCD_LINES-1 && scrollbar_X)
        displayScrollbar(scrollbar_X, FH, LCD_H-FH, s_pgOfs, menuTab ? maxrow : maxrow+1, LCD_LINES-1);
#endif

#else
    uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
    if (l_posVert<1) s_pgOfs=0;
    else if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max;
    else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1;
#endif
    m_posVert = l_posVert;
    m_posHorz = l_posHorz;
    if (s_pgOfs > 0) {
        l_posVert--;
        if (l_posVert == s_pgOfs && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)) {
            s_pgOfs = l_posVert-1;
        }
    }
    return true;
}
예제 #10
0
void showStatusLine()
{
    statusLineTime = get_tmr10ms();
}
예제 #11
0
파일: logs.cpp 프로젝트: Paul-NA8E/opentx
// TODO test when disk full
void writeLogs()
{
  static const pm_char * error_displayed = NULL;

  if (isFunctionActive(FUNCTION_LOGS) && logDelay > 0) {
    tmr10ms_t tmr10ms = get_tmr10ms();
    if (lastLogTime == 0 || (tmr10ms_t)(tmr10ms - lastLogTime) >= (tmr10ms_t)logDelay*10) {
      lastLogTime = tmr10ms;

      if (!g_oLogFile.fs) {
        const pm_char * result = openLogs();
        if (result != NULL) {
          if (result != error_displayed) {
            error_displayed = result;
            POPUP_WARNING(result);
          }
          return;
        }
      }

#if defined(RTCLOCK)
      struct gtm utm;
      gettime(&utm);
      f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d.%02d0,", utm.tm_year+1900, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec, g_ms100);
#else
      f_printf(&g_oLogFile, "%d,", tmr10ms);
#endif

#if defined(FRSKY)
#if defined(PCBTARANIS) && defined(REVPLUS)
      f_printf(&g_oLogFile, "%d,", RAW_FRSKY_MINMAX(frskyData.rssi[0]));
#elif defined(CPUARM)
      f_printf(&g_oLogFile, "%d,%d,", RAW_FRSKY_MINMAX(frskyData.swr), RAW_FRSKY_MINMAX(frskyData.rssi[0]));
#else
      f_printf(&g_oLogFile, "%d,%d,%d,", frskyStreaming, RAW_FRSKY_MINMAX(frskyData.rssi[0]), RAW_FRSKY_MINMAX(frskyData.rssi[1]));
#endif

      for (uint8_t i=0; i<MAX_FRSKY_A_CHANNELS; i++) {
        int16_t converted_value = applyChannelRatio(i, RAW_FRSKY_MINMAX(frskyData.analog[i]));
        f_printf(&g_oLogFile, "%d.%02d,", converted_value/100, converted_value%100);
      }
#endif

#if defined(FRSKY_HUB)
      TELEMETRY_BARO_ALT_PREPARE();

      if (IS_USR_PROTO_FRSKY_HUB()) {
        f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d,%03d.%04d%c,%03d.%04d%c,%03d.%02d," TELEMETRY_GPS_SPEED_FORMAT TELEMETRY_GPS_ALT_FORMAT TELEMETRY_BARO_ALT_FORMAT TELEMETRY_VSPEED_FORMAT TELEMETRY_ASPEED_FORMAT "%d,%d,%d,%d," TELEMETRY_CELLS_FORMAT TELEMETRY_CURRENT_FORMAT "%d," TELEMETRY_VFAS_FORMAT "%d,%d,%d,",
            frskyData.hub.year+2000,
            frskyData.hub.month,
            frskyData.hub.day,
            frskyData.hub.hour,
            frskyData.hub.min,
            frskyData.hub.sec,
            frskyData.hub.gpsLongitude_bp,
            frskyData.hub.gpsLongitude_ap,
            frskyData.hub.gpsLongitudeEW ? frskyData.hub.gpsLongitudeEW : '-',
            frskyData.hub.gpsLatitude_bp,
            frskyData.hub.gpsLatitude_ap,
            frskyData.hub.gpsLatitudeNS ? frskyData.hub.gpsLatitudeNS : '-',
            frskyData.hub.gpsCourse_bp,
            frskyData.hub.gpsCourse_ap,
            TELEMETRY_GPS_SPEED_ARGS
            TELEMETRY_GPS_ALT_ARGS
            TELEMETRY_BARO_ALT_ARGS
            TELEMETRY_VSPEED_ARGS
            TELEMETRY_ASPEED_ARGS
            frskyData.hub.temperature1,
            frskyData.hub.temperature2,
            frskyData.hub.rpm,
            frskyData.hub.fuelLevel,
            TELEMETRY_CELLS_ARGS
            TELEMETRY_CURRENT_ARGS
            frskyData.hub.currentConsumption,
            TELEMETRY_VFAS_ARGS
            frskyData.hub.accelX,
            frskyData.hub.accelY,
            frskyData.hub.accelZ);
      }
#endif

#if defined(WS_HOW_HIGH)
      if (IS_USR_PROTO_WS_HOW_HIGH()) {
        f_printf(&g_oLogFile, "%d,", TELEMETRY_RELATIVE_BARO_ALT_BP);
      }
#endif

      for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) {
        f_printf(&g_oLogFile, "%d,", calibratedStick[i]);
      }

#if defined(PCBTARANIS)
      int result = f_printf(&g_oLogFile, "%d,%d,%d,%d,%d,%d,%d,%d\n",
          get3PosState(SA),
          get3PosState(SB),
          get3PosState(SC),
          get3PosState(SD),
          get3PosState(SE),
          get2PosState(SF),
          get3PosState(SG),
          get2PosState(SH));
#else
      int result = f_printf(&g_oLogFile, "%d,%d,%d,%d,%d,%d,%d\n",
          get2PosState(THR),
          get2PosState(RUD),
          get2PosState(ELE),
          get3PosState(ID),
          get2PosState(AIL),
          get2PosState(GEA),
          get2PosState(TRN));
#endif

      if (result<0 && !error_displayed) {
        error_displayed = STR_SDCARD_ERROR;
        POPUP_WARNING(STR_SDCARD_ERROR);
        closeLogs();
      }
    }
  }
  else {
    error_displayed = NULL;
    if (g_oLogFile.fs) {
      closeLogs();
    }
  }
}
예제 #12
0
void check(const char *name, check_event_t event, uint8_t curr, const menuHandlerFunc *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t rowcount, uint8_t flags)
{
  vertpos_t l_posVert = menuVerticalPosition;
  horzpos_t l_posHorz = menuHorizontalPosition;

  uint8_t maxcol = MAXCOL(l_posVert);

  if (menuTab) {
    int cc = curr;
    switch (event) {
      case EVT_KEY_LONG(KEY_MENU):
        if (menuTab == menuTabModel) {
          killEvents(event);
          if (modelHasNotes()) {
            POPUP_MENU_ADD_SD_ITEM(STR_VIEW_CHANNELS);
            POPUP_MENU_ADD_ITEM(STR_VIEW_NOTES);
            popupMenuHandler = onLongMenuPress;
          }
          else {
            pushMenu(menuChannelsView);
          }
        }
        break;

      case EVT_KEY_LONG(KEY_PAGE):
        if (curr > 0)
          cc = curr - 1;
        else
          cc = menuTabSize-1;
        killEvents(event);
        break;

      case EVT_KEY_BREAK(KEY_PAGE):
        if (curr < (menuTabSize-1))
          cc = curr + 1;
        else
          cc = 0;
        break;
    }

    if (!calibrationState && cc != curr) {
      chainMenu((menuHandlerFunc)pgm_read_adr(&menuTab[cc]));
    }

    if (!(flags&CHECK_FLAG_NO_SCREEN_INDEX)) {
      displayScreenIndex(curr, menuTabSize, 0);
    }

    drawFilledRect(0, 0, LCD_W, MENU_HEADER_HEIGHT, SOLID, FILL_WHITE|GREY_DEFAULT);
  }

  DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);

  switch(event)
  {
    case EVT_ENTRY:
      menuEntryTime = get_tmr10ms();
      l_posVert = POS_VERT_INIT;
      l_posHorz = POS_HORZ_INIT(l_posVert);
      SET_SCROLLBAR_X(LCD_W-1);
      s_editMode = EDIT_MODE_INIT;
      break;

    case EVT_ENTRY_UP:
      menuEntryTime = get_tmr10ms();
      s_editMode = 0;
      l_posHorz = POS_HORZ_INIT(l_posVert);
      SET_SCROLLBAR_X(LCD_W-1);
      break;

    case EVT_ROTARY_BREAK:
      if (s_editMode > 1) break;
      if (menuHorizontalPosition < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) {
        l_posHorz = 0;
        break;
      }
      if (READ_ONLY_UNLOCKED()) {
        s_editMode = (s_editMode<=0);
      }
      break;

    case EVT_KEY_LONG(KEY_EXIT):
      s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same
      popMenu();
      break;

    case EVT_KEY_BREAK(KEY_EXIT):
      if (s_editMode>0) {
        s_editMode = 0;
        break;
      }

      if (l_posHorz >= 0 && (COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
        l_posHorz = -1;
      }
      else
      {
        uint8_t posVertInit = POS_VERT_INIT;
        if (menuVerticalOffset != 0 || l_posVert != posVertInit) {
          menuVerticalOffset = 0;
          l_posVert = posVertInit;
          l_posHorz = POS_HORZ_INIT(l_posVert);
        }
        else {
          popMenu();
        }
      }
      break;

    CASE_EVT_ROTARY_MOVE_RIGHT
      if (s_editMode != 0) break;
      if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
        if (l_posHorz >= 0) {
          INC(l_posHorz, 0, maxcol);
          break;
        }
      }
      else {
        if (l_posHorz < maxcol) {
          l_posHorz++;
          break;
        }
        else {
          l_posHorz = 0;
          if (!IS_ROTARY_MOVE_RIGHT(event))
            break;
        }
      }

      do {
        INC(l_posVert, POS_VERT_INIT, rowcount-1);
      } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

      s_editMode = 0; // if we go down, we must be in this mode

      l_posHorz = POS_HORZ_INIT(l_posVert);
      break;

    CASE_EVT_ROTARY_MOVE_LEFT
      if (s_editMode != 0) break;
      if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
        if (l_posHorz >= 0) {
          DEC(l_posHorz, 0, maxcol);
          break;
        }
      }
      else {
        if (l_posHorz > 0) {
          l_posHorz--;
          break;
        }
        else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) {
          l_posHorz = 0xff;
        }
        else {
          l_posHorz = maxcol;
          break;
        }
      }

      do {
        DEC(l_posVert, POS_VERT_INIT, rowcount-1);
      } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

      s_editMode = 0; // if we go up, we must be in this mode

      if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE))
        l_posHorz = -1;
      else
        l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));

      break;
  }

  int linesCount = rowcount;

  if (l_posVert == 0 || (l_posVert==1 && MAXCOL(vertpos_t(0)) >= HIDDEN_ROW) || (l_posVert==2 && MAXCOL(vertpos_t(0)) >= HIDDEN_ROW && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW)) {
    menuVerticalOffset = 0;
    if (horTab) {
      linesCount = 0;
      for (int i=0; i<rowcount; i++) {
        if (i>horTabMax || horTab[i] != HIDDEN_ROW) {
          linesCount++;
        }
      }
    }
  }
  else if (horTab) {
    if (rowcount > NUM_BODY_LINES) {
      while (1) {
        vertpos_t firstLine = 0;
        for (int numLines=0; firstLine<rowcount && numLines<menuVerticalOffset; firstLine++) {
          if (firstLine>=horTabMax || horTab[firstLine] != HIDDEN_ROW) {
            numLines++;
          }
        }
        if (l_posVert < firstLine) {
          menuVerticalOffset--;
        }
        else {
          vertpos_t lastLine = firstLine;
          for (int numLines=0; lastLine<rowcount && numLines<NUM_BODY_LINES; lastLine++) {
            if (lastLine>=horTabMax || horTab[lastLine] != HIDDEN_ROW) {
              numLines++;
            }
          }
          if (l_posVert >= lastLine) {
            menuVerticalOffset++;
          }
          else {
            linesCount = menuVerticalOffset + NUM_BODY_LINES;
            for (int i=lastLine; i<rowcount; i++) {
              if (i>horTabMax || horTab[i] != HIDDEN_ROW) {
                linesCount++;
              }
            }
            break;
          }
        }
      }
    }
  }
  else {
    if (l_posVert>=NUM_BODY_LINES+menuVerticalOffset) {
      menuVerticalOffset = l_posVert-NUM_BODY_LINES+1;
    }
    else if (l_posVert<menuVerticalOffset) {
      menuVerticalOffset = l_posVert;
    }
  }

  if (scrollbar_X && linesCount > NUM_BODY_LINES) {
    displayScrollbar(scrollbar_X, MENU_HEADER_HEIGHT, LCD_H-MENU_HEADER_HEIGHT, menuVerticalOffset, linesCount, NUM_BODY_LINES);
  }

  if (name) {
    title(name);
  }

  menuVerticalPosition = l_posVert;
  menuHorizontalPosition = l_posHorz;
}
예제 #13
0
void boardInit()
{
  RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | ADC_RCC_AHB1Periph | I2C_RCC_AHB1Periph | SD_RCC_AHB1Periph | HAPTIC_RCC_AHB1Periph | INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph | TELEMETRY_RCC_AHB1Periph | SERIAL_RCC_AHB1Periph | TRAINER_RCC_AHB1Periph | HEARTBEAT_RCC_AHB1Periph, ENABLE);
  RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_5MS_APB1Periph | TIMER_2MHz_APB1Periph | I2C_RCC_APB1Periph | SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph | TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph, ENABLE);
  RCC_APB2PeriphClockCmd(BACKLIGHT_RCC_APB2Periph | ADC_RCC_APB2Periph | HAPTIC_RCC_APB2Periph | INTMODULE_RCC_APB2Periph | EXTMODULE_RCC_APB2Periph | HEARTBEAT_RCC_APB2Periph, ENABLE);

#if !defined(REV9E)
  // some REV9E boards need that the pwrInit() is moved a little bit later
  pwrInit();
#endif

  keysInit();
  adcInit();
  delaysInit();
  lcdInit();    // delaysInit() must be called before
  audioInit();
  init2MhzTimer();
  init5msTimer();
  __enable_irq();
  i2cInit();
  usbInit();
  
#if defined(HAPTIC)  
  hapticInit();
#endif

#if defined(REV9E)
  bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE);
#endif

#if defined(DEBUG)
  DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP|DBGMCU_TIM1_STOP|DBGMCU_TIM2_STOP|DBGMCU_TIM3_STOP|DBGMCU_TIM6_STOP|DBGMCU_TIM8_STOP|DBGMCU_TIM10_STOP|DBGMCU_TIM13_STOP|DBGMCU_TIM14_STOP, ENABLE);
#endif

#if defined(REV9E)
  if (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
    lcd_clear();
    lcd_bmp(76, 2, bmp_lock, 0, 60);
    lcdRefresh();
    lcdRefreshWait();

    tmr10ms_t start = get_tmr10ms();
    tmr10ms_t duration = 0;
    uint8_t pwr_on = 0;
    while (pwrPressed()) {
      duration = get_tmr10ms() - start;
      if (duration < PWR_PRESS_DURATION_MIN) {
        unsigned index = duration / (PWR_PRESS_DURATION_MIN / 4);
        lcd_clear();
        lcd_bmp(76, 2, bmp_startup, index*60, 60);
      }
      else if (duration >= PWR_PRESS_DURATION_MAX) {
        displaySleepBitmap();
        turnBacklightOff();
      }
      else {
        if (pwr_on != 1) {
          pwr_on = 1;
          pwrInit();
          backlightInit();
          haptic.play(15, 3, PLAY_NOW);
        }
      }
      lcdRefresh();
      lcdRefreshWait();
    }
    if (duration < PWR_PRESS_DURATION_MIN || duration >= PWR_PRESS_DURATION_MAX) {
      boardOff();
    }
  }
  else {
    pwrInit();
    backlightInit();
  }
  topLcdInit();
#else
  backlightInit();
#endif
}
예제 #14
0
파일: pers.cpp 프로젝트: RasmusKS/er9x
void eeCheck(bool immediately)
{
	EepromActive = 0 ;
  uint8_t msk  = s_eeDirtyMsk;
  if(!msk) return;
	EepromActive = '1' + s_eeLongTimer ;
  if( !immediately )
	{
		if ( ( get_tmr10ms() - s_eeDirtyTime10ms) < WRITE_DELAY_10MS) return ;
		if ( s_eeLongTimer )
		{
			if ( --s_eeLongTimer )
			{
  			s_eeDirtyTime10ms  = get_tmr10ms() ;
				return ;
			}
		}
	}
	s_eeLongTimer = 0 ;
  if ( Ee_lock ) return ;
  Ee_lock = EE_LOCK ;      	// Lock eeprom writing from recursion
  if ( msk & EE_TRIM )
  {
    Ee_lock |= EE_TRIM_LOCK ;    // So the lower levels know what is happening
  }
  

  if(msk & EE_GENERAL)
	{
		EepromActive = '2' ;
		
  	s_eeDirtyMsk &= ~EE_GENERAL ;
    if(theWriteFile.writeRlc(FILE_TMP, FILE_TYP_GENERAL, (uint8_t*)&g_eeGeneral,
                        sizeof(EEGeneral),20) == sizeof(EEGeneral))
    {
      EFile::swap(FILE_GENERAL,FILE_TMP);
    }else{
      if(theWriteFile.write_errno()==ERR_TMO){
        s_eeDirtyMsk |= EE_GENERAL; //try again
        s_eeDirtyTime10ms = get_tmr10ms() - WRITE_DELAY_10MS;
    		if(heartbeat == 0x3)
    		{
    		    wdt_reset();
    		    heartbeat = 0;
    		}

      }else{
        alert(Str_EEPROM_Overflow);
      }
    }
    //first finish GENERAL, then MODEL !!avoid Toggle effect
  }
  else if(msk & EE_MODEL)
	{
		EepromActive = '3' ;
  	s_eeDirtyMsk &= ~(EE_MODEL | EE_TRIM) ;
    if(theWriteFile.writeRlc(FILE_TMP, FILE_TYP_MODEL, (uint8_t*)&g_model,
                        sizeof(g_model),20) == sizeof(g_model))
    {
      EFile::swap(FILE_MODEL(g_eeGeneral.currModel),FILE_TMP);
    }else{
      if(theWriteFile.write_errno()==ERR_TMO){
        s_eeDirtyMsk |= EE_MODEL; //try again
        if ( msk & EE_TRIM )
        {
          s_eeDirtyMsk |= EE_TRIM; //try again
        }
        s_eeDirtyTime10ms = get_tmr10ms() - WRITE_DELAY_10MS;
    		if(heartbeat == 0x3)
    		{
    		    wdt_reset();
    		    heartbeat = 0;
    		}
      }else{
        if ( ( msk & EE_TRIM ) == 0 )		// Don't stop if trim adjust
        {
          alert(Str_EEPROM_Overflow);
        }
      }
    }
  }
  Ee_lock = 0 ;				// UnLock eeprom writing


}
예제 #15
0
/*luadoc
@function getTime()

Return the time since the radio was started in multiple of 10ms

@retval number Number of 10ms ticks since the radio was started Example: 
run time: 12.54 seconds, return value: 1254

@status current Introduced in 2.0.0
*/
static int luaGetTime(lua_State *L)
{
  lua_pushunsigned(L, get_tmr10ms());
  return 1;
}
예제 #16
0
void perMain()
{
#if defined(PCBSKY9X) && !defined(REVA)
  calcConsumption();
#endif
  checkSpeakerVolume();
  checkEeprom();
  sdMountPoll();
  writeLogs();
  handleUsbConnection();
  checkTrainerSettings();
  checkBattery();

  uint8_t evt = getEvent(false);
  if (evt && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) backlightOn(); // on keypress turn the light on
  checkBacklight();
#if defined(NAVIGATION_STICKS)
  uint8_t sticks_evt = getSticksNavigationEvent();
  if (sticks_evt) evt = sticks_evt;
#endif

#if defined(USB_MASS_STORAGE)
  if (usbPlugged()) {
    // disable access to menus
    lcd_clear();
    menuMainView(0);
    lcdRefresh();
    return;
  }
#endif

#if defined(LUA)
  uint32_t t0 = get_tmr10ms();
  static uint32_t lastLuaTime = 0;
  uint16_t interval = (lastLuaTime == 0 ? 0 : (t0 - lastLuaTime));
  lastLuaTime = t0;
  if (interval > maxLuaInterval) {
    maxLuaInterval = interval;
  }

  // run Lua scripts that don't use LCD (to use CPU time while LCD DMA is running)
  luaTask(0, RUN_MIX_SCRIPT | RUN_FUNC_SCRIPT | RUN_TELEM_BG_SCRIPT, false);

  // wait for LCD DMA to finish before continuing, because code from this point 
  // is allowed to change the contents of LCD buffer
  // 
  // WARNING: make sure no code above this line does any change to the LCD display buffer!
  //
  lcdRefreshWait();

  // draw LCD from menus or from Lua script
  // run Lua scripts that use LCD

  bool standaloneScriptWasRun = luaTask(evt, RUN_STNDAL_SCRIPT, true);
  bool refreshScreen = true;
  if (!standaloneScriptWasRun) {
    refreshScreen = !luaTask(evt, RUN_TELEM_FG_SCRIPT, true);
  }

  t0 = get_tmr10ms() - t0;
  if (t0 > maxLuaDuration) {
    maxLuaDuration = t0;
  }

  if (!standaloneScriptWasRun)
#else
  lcdRefreshWait();   // WARNING: make sure no code above this line does any change to the LCD display buffer!
  const bool refreshScreen = true;
#endif
  {
    // normal GUI from menus
    const char *warn = s_warning;
    uint8_t menu = s_menu_count;
    if (refreshScreen) {
      lcd_clear();
    }
    if (menuEvent) {
      m_posVert = menuEvent == EVT_ENTRY_UP ? g_menuPos[g_menuStackPtr] : 0;
      m_posHorz = 0;
      evt = menuEvent;
      menuEvent = 0;
      AUDIO_MENUS();
    }
    g_menuStack[g_menuStackPtr]((warn || menu) ? 0 : evt);
    if (warn) DISPLAY_WARNING(evt);
    if (menu) {
      const char * result = displayMenu(evt);
      if (result) {
        menuHandler(result);
        putEvent(EVT_MENU_UP);
      }
    }
    drawStatusLine();
  }

  lcdRefresh();

#if defined(REV9E) && !defined(SIMU)
  topLcdRefreshStart();
  setTopFirstTimer(getValue(MIXSRC_FIRST_TIMER+g_model.topLcdTimer));
  setTopSecondTimer(g_eeGeneral.globalTimer + sessionTimer);
  setTopRssi(TELEMETRY_RSSI());
  setTopBatteryValue(g_vbat100mV);
  setTopBatteryState(GET_TXBATT_BARS(), IS_TXBATT_WARNING());
  topLcdRefreshEnd();
#endif

#if defined(REV9E) && !defined(SIMU)
  bluetoothWakeup();
#endif

#if defined(PCBTARANIS)
  if (requestScreenshot) {
    requestScreenshot = false;
    writeScreenshot();
  }
#endif

}
예제 #17
0
void evalFunctions()
#endif
{
  MASK_FUNC_TYPE newActiveFunctions  = 0;
  MASK_CFN_TYPE  newActiveSwitches = 0;

#if defined(ROTARY_ENCODERS) && defined(GVARS)
  static rotenc_t rePreviousValues[ROTARY_ENCODERS];
#endif

#if defined(OVERRIDE_CHANNEL_FUNCTION)
  for (uint8_t i=0; i<NUM_CHNOUT; i++) {
    safetyCh[i] = OVERRIDE_CHANNEL_UNDEFINED;
  }
#endif

#if defined(GVARS)
  for (uint8_t i=0; i<NUM_STICKS; i++) {
    trimGvar[i] = -1;
  }
#endif

  for (uint8_t i=0; i<NUM_CFN; i++) {
    const CustomFunctionData *cfn = &functions[i];
    int8_t swtch = CFN_SWITCH(cfn);
    if (swtch) {
      MASK_CFN_TYPE  switch_mask = ((MASK_CFN_TYPE)1 << i);

#if defined(CPUARM)
      bool active = getSwitch(swtch, IS_PLAY_FUNC(CFN_FUNC(cfn)) ? GETSWITCH_MIDPOS_DELAY : 0);
#else
      bool active = getSwitch(swtch);
#endif

      if (HAS_ENABLE_PARAM(CFN_FUNC(cfn))) {
        active &= (bool)CFN_ACTIVE(cfn);
      }

      if (active || IS_PLAY_BOTH_FUNC(CFN_FUNC(cfn))) {

        switch (CFN_FUNC(cfn)) {

#if defined(OVERRIDE_CHANNEL_FUNCTION)
          case FUNC_OVERRIDE_CHANNEL:
            safetyCh[CFN_CH_INDEX(cfn)] = CFN_PARAM(cfn);
            break;
#endif

          case FUNC_TRAINER:
          {
            uint8_t mask = 0x0f;
            if (CFN_CH_INDEX(cfn) > 0) {
              mask = (1<<(CFN_CH_INDEX(cfn)-1));
            }
            newActiveFunctions |= mask;
            break;
          }

          case FUNC_INSTANT_TRIM:
            newActiveFunctions |= (1 << FUNCTION_INSTANT_TRIM);
            if (!isFunctionActive(FUNCTION_INSTANT_TRIM)) {
#if defined(GUI)
              if (g_menuStack[0] == menuMainView
#if defined(FRSKY)
                || g_menuStack[0] == menuTelemetryFrsky
#endif
#if defined(PCBTARANIS)
                || g_menuStack[0] == menuMainViewChannelsMonitor
                || g_menuStack[0] == menuChannelsView
#endif
              )
#endif
              {
                instantTrim();
              }
            }
            break;

          case FUNC_RESET:
            switch (CFN_PARAM(cfn)) {
              case FUNC_RESET_TIMER1:
              case FUNC_RESET_TIMER2:
#if defined(CPUARM)
              case FUNC_RESET_TIMER3:
#endif
                timerReset(CFN_PARAM(cfn));
                break;
              case FUNC_RESET_FLIGHT:
                flightReset();
                break;
#if defined(FRSKY)
              case FUNC_RESET_TELEMETRY:
                telemetryReset();
                break;
#endif
#if ROTARY_ENCODERS > 0
              case FUNC_RESET_ROTENC1:
#if ROTARY_ENCODERS > 1
              case FUNC_RESET_ROTENC2:
#endif
                g_rotenc[CFN_PARAM(cfn)-FUNC_RESET_ROTENC1] = 0;
                break;
#endif
            }
#if defined(CPUARM)
            if (CFN_PARAM(cfn)>=FUNC_RESET_PARAM_FIRST_TELEM) {
              TelemetryItem * telemetryItem = & telemetryItems[CFN_PARAM(cfn)-FUNC_RESET_PARAM_FIRST_TELEM];
              telemetryItem->clear();
            }
#endif
            break;

#if defined(CPUARM)
          case FUNC_SET_TIMER:
          {
            timerSet(CFN_TIMER_INDEX(cfn), CFN_PARAM(cfn));
            break;
          }
#endif

#if 0 //defined(DANGEROUS_MODULE_FUNCTIONS)
          case FUNC_RANGECHECK:
          case FUNC_BIND:
          case FUNC_MODULE_OFF:
          {
            unsigned int moduleIndex = CFN_PARAM(cfn);
            if (moduleIndex < NUM_MODULES) {
              moduleFlag[moduleIndex] = 1 + CFN_FUNC(cfn) - FUNC_RANGECHECK;
            }
            break;
          }
#endif

#if defined(GVARS)
          case FUNC_ADJUST_GVAR:
            if (CFN_GVAR_MODE(cfn) == 0) {
              SET_GVAR(CFN_GVAR_INDEX(cfn), CFN_PARAM(cfn), mixerCurrentFlightMode);
            }
            else if (CFN_GVAR_MODE(cfn) == 2) {
              SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_PARAM(cfn), mixerCurrentFlightMode), mixerCurrentFlightMode);
            }
            else if (CFN_GVAR_MODE(cfn) == 3) {
              if (!(functionsContext.activeSwitches & switch_mask)) {
                SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightPhase(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + (CFN_PARAM(cfn) ? +1 : -1), mixerCurrentFlightMode);
              }
            }
            else if (CFN_PARAM(cfn) >= MIXSRC_TrimRud && CFN_PARAM(cfn) <= MIXSRC_TrimAil) {
              trimGvar[CFN_PARAM(cfn)-MIXSRC_TrimRud] = CFN_GVAR_INDEX(cfn);
            }
#if defined(ROTARY_ENCODERS)
            else if (CFN_PARAM(cfn) >= MIXSRC_REa && CFN_PARAM(cfn) < MIXSRC_TrimRud) {
              int8_t scroll = rePreviousValues[CFN_PARAM(cfn)-MIXSRC_REa] - (g_rotenc[CFN_PARAM(cfn)-MIXSRC_REa] / ROTARY_ENCODER_GRANULARITY);
              if (scroll) {
                SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightPhase(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + scroll, mixerCurrentFlightMode);
              }
            }
#endif
            else {
              SET_GVAR(CFN_GVAR_INDEX(cfn), calcRESXto100(getValue(CFN_PARAM(cfn))), mixerCurrentFlightMode);
            }
            break;
#endif

#if defined(CPUARM) && defined(SDCARD)
          case FUNC_VOLUME:
          {
            getvalue_t raw = getValue(CFN_PARAM(cfn));
            //only set volume if input changed more than hysteresis
            if (abs(requiredSpeakerVolumeRawLast - raw) > VOLUME_HYSTERESIS) {
              requiredSpeakerVolumeRawLast = raw;
            }
            requiredSpeakerVolume = ((1024 + requiredSpeakerVolumeRawLast) * VOLUME_LEVEL_MAX) / 2048;
            break;
          }
#endif

#if defined(CPUARM) && defined(SDCARD)
          case FUNC_PLAY_SOUND:
          case FUNC_PLAY_TRACK:
          case FUNC_PLAY_VALUE:
#if defined(HAPTIC)
          case FUNC_HAPTIC:
#endif
          {
            tmr10ms_t tmr10ms = get_tmr10ms();
            uint8_t repeatParam = CFN_PLAY_REPEAT(cfn);
            if (!IS_SILENCE_PERIOD_ELAPSED() && repeatParam == CFN_PLAY_REPEAT_NOSTART) {
              functionsContext.lastFunctionTime[i] = tmr10ms;
            }
            if (!functionsContext.lastFunctionTime[i] || (repeatParam && repeatParam!=CFN_PLAY_REPEAT_NOSTART && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=100*repeatParam)) {
              if (!IS_PLAYING(i+1)) {
                functionsContext.lastFunctionTime[i] = tmr10ms;
                if (CFN_FUNC(cfn) == FUNC_PLAY_SOUND) {
                  AUDIO_PLAY(AU_FRSKY_FIRST+CFN_PARAM(cfn));
                }
                else if (CFN_FUNC(cfn) == FUNC_PLAY_VALUE) {
                  PLAY_VALUE(CFN_PARAM(cfn), i+1);
                }
#if defined(HAPTIC)
                else if (CFN_FUNC(cfn) == FUNC_HAPTIC) {
                  haptic.event(AU_FRSKY_LAST+CFN_PARAM(cfn));
                }
#endif
                else {
                  playCustomFunctionFile(cfn, i+1);
                }
              }
            }
            break;
          }

          case FUNC_BACKGND_MUSIC:
            newActiveFunctions |= (1 << FUNCTION_BACKGND_MUSIC);
            if (!IS_PLAYING(i+1)) {
              playCustomFunctionFile(cfn, i+1);
            }
            break;

          case FUNC_BACKGND_MUSIC_PAUSE:
            newActiveFunctions |= (1 << FUNCTION_BACKGND_MUSIC_PAUSE);
            break;

#elif defined(VOICE)
          case FUNC_PLAY_SOUND:
          case FUNC_PLAY_TRACK:
          case FUNC_PLAY_BOTH:
          case FUNC_PLAY_VALUE:
          {
            tmr10ms_t tmr10ms = get_tmr10ms();
            uint8_t repeatParam = CFN_PLAY_REPEAT(cfn);
            if (!functionsContext.lastFunctionTime[i] || (CFN_FUNC(cfn)==FUNC_PLAY_BOTH && active!=(bool)(functionsContext.activeSwitches&switch_mask)) || (repeatParam && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=1000*repeatParam)) {
              functionsContext.lastFunctionTime[i] = tmr10ms;
              uint8_t param = CFN_PARAM(cfn);
              if (CFN_FUNC(cfn) == FUNC_PLAY_SOUND) {
                AUDIO_PLAY(AU_FRSKY_FIRST+param);
              }
              else if (CFN_FUNC(cfn) == FUNC_PLAY_VALUE) {
                PLAY_VALUE(param, i+1);
              }
              else {
#if defined(GVARS)
                if (CFN_FUNC(cfn) == FUNC_PLAY_TRACK && param > 250)
                  param = GVAR_VALUE(param-251, getGVarFlightPhase(mixerCurrentFlightMode, param-251));
#endif
                PUSH_CUSTOM_PROMPT(active ? param : param+1, i+1);
              }
            }
            if (!active) {
              // PLAY_BOTH would change activeFnSwitches otherwise
              switch_mask = 0;
            }
            break;
          }
#else
          case FUNC_PLAY_SOUND:
          {
            tmr10ms_t tmr10ms = get_tmr10ms();
            uint8_t repeatParam = CFN_PLAY_REPEAT(cfn);
            if (!functionsContext.lastFunctionTime[i] || (repeatParam && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=1000*repeatParam)) {
              functionsContext.lastFunctionTime[i] = tmr10ms;
              AUDIO_PLAY(AU_FRSKY_FIRST+CFN_PARAM(cfn));
            }
            break;
          }
#endif

#if defined(FRSKY) && defined(VARIO)
          case FUNC_VARIO:
            newActiveFunctions |= (1 << FUNCTION_VARIO);
            break;
#endif

#if defined(HAPTIC) && !defined(CPUARM)
          case FUNC_HAPTIC:
          {
            tmr10ms_t tmr10ms = get_tmr10ms();
            uint8_t repeatParam = CFN_PLAY_REPEAT(cfn);
            if (!functionsContext.lastFunctionTime[i] || (repeatParam && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=1000*repeatParam)) {
              functionsContext.lastFunctionTime[i] = tmr10ms;
              haptic.event(AU_FRSKY_LAST+CFN_PARAM(cfn));
            }
            break;
          }
#endif

#if defined(SDCARD)
          case FUNC_LOGS:
            if (CFN_PARAM(cfn)) {
              newActiveFunctions |= (1 << FUNCTION_LOGS);
              logDelay = CFN_PARAM(cfn);
            }
            break;
#endif

          case FUNC_BACKLIGHT:
            newActiveFunctions |= (1 << FUNCTION_BACKLIGHT);
            break;

#if defined(PCBTARANIS)
          case FUNC_SCREENSHOT:
            if (!(functionsContext.activeSwitches & switch_mask)) {
              requestScreenshot = true;
            }
            break;
#endif

#if defined(DEBUG)
          case FUNC_TEST:
            testFunc();
            break;
#endif
        }

        newActiveSwitches |= switch_mask;
      }
      else {
        functionsContext.lastFunctionTime[i] = 0;
      }
    }
  }

  functionsContext.activeSwitches   = newActiveSwitches;
  functionsContext.activeFunctions  = newActiveFunctions;

#if defined(ROTARY_ENCODERS) && defined(GVARS)
  for (uint8_t i=0; i<ROTARY_ENCODERS; i++) {
    rePreviousValues[i] = (g_rotenc[i] / ROTARY_ENCODER_GRANULARITY);
  }
#endif
}