void menuModelTelemetry(uint8_t event) { if (s_warning_result) { s_warning_result = 0; for (int i=0; i<MAX_SENSORS; i++) { delTelemetryIndex(i); } } MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX, { TELEMETRY_TYPE_ROWS RSSI_ROWS SENSORS_ROWS VARIO_ROWS LABEL(TopBar), 0, 0, TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), CASE_CPUARM(TELEMETRY_SCREEN_ROWS(2)) CASE_CPUARM(TELEMETRY_SCREEN_ROWS(3)) }); int sub = m_posVert; for (int i=0; i<NUM_BODY_LINES; i++) { coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH; int k = i + s_pgOfs; for (int j=0; j<=k; j++) { if (mstate_tab[j] == HIDDEN_ROW) k++; } LcdFlags blink = ((s_editMode>0) ? BLINK|INVERS : INVERS); LcdFlags attr = (sub == k ? blink : 0); if (k>=ITEM_TELEMETRY_SENSOR1 && k<ITEM_TELEMETRY_SENSOR1+MAX_SENSORS) { int index = k-ITEM_TELEMETRY_SENSOR1; lcd_outdezAtt(INDENT_WIDTH, y, index+1, LEFT|attr); lcd_putcAtt(lcdLastPos, y, ':', attr); lcd_putsnAtt(3*FW, y, g_model.telemetrySensors[index].label, TELEM_LABEL_LEN, ZCHAR); if (telemetryItems[index].isFresh()) { lcd_putc(10*FW, y, '*'); } TelemetryItem & telemetryItem = telemetryItems[index]; if (telemetryItem.isAvailable()) { bool isOld = telemetryItem.isOld(); lcdNextPos = TELEM_COL2; if (isOld) lcd_putc(lcdNextPos, y, '['); putsTelemetryChannelValue(lcdNextPos, y, index, getValue(MIXSRC_FIRST_TELEM+3*index), LEFT); if (isOld) lcd_putc(lcdLastPos, y, ']'); } else { lcd_putsAtt(TELEM_COL2, y, "---", 0); // TODO shortcut } TelemetrySensor * sensor = & g_model.telemetrySensors[index]; if (sensor->type == TELEM_TYPE_CUSTOM && !g_model.ignoreSensorIds) { lcd_outdezAtt(TELEM_COL3, y, sensor->instance, LEFT); } if (attr) { s_editMode = 0; s_currIdx = index; if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); MENU_ADD_ITEM(STR_EDIT); MENU_ADD_ITEM(STR_COPY); MENU_ADD_ITEM(STR_DELETE); menuHandler = onSensorMenu; } else if (event == EVT_KEY_BREAK(KEY_ENTER)) { pushMenu(menuModelSensor); } } } else switch (k) { case ITEM_TELEMETRY_PROTOCOL_TYPE: g_model.telemetryProtocol = selectMenuItem(TELEM_COL2, y, STR_TELEMETRY_TYPE, "\017FrSky S.PORT\0 FrSky D\0 FrSky D (cable)", g_model.telemetryProtocol, PROTOCOL_TELEMETRY_FIRST, g_eeGeneral.serial2Mode==UART_MODE_TELEMETRY ? PROTOCOL_FRSKY_D_SECONDARY : PROTOCOL_FRSKY_D, attr, event); break; case ITEM_TELEMETRY_SENSORS_LABEL: lcd_putsLeft(y, STR_TELEMETRY_SENSORS); lcd_putsAtt(TELEM_COL2, y, STR_VALUE, 0); if (!g_model.ignoreSensorIds) { lcd_putsAtt(TELEM_COL3, y, STR_ID, 0); } break; case ITEM_TELEMETRY_DISCOVER_SENSORS: lcd_putsAtt(0, y, allowNewSensors ? STR_STOP_DISCOVER_SENSORS : STR_DISCOVER_SENSORS, attr); if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) { s_editMode = 0; allowNewSensors = !allowNewSensors; } break; case ITEM_TELEMETRY_NEW_SENSOR: lcd_putsAtt(0, y, STR_TELEMETRY_NEWSENSOR, attr); if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) { s_editMode = 0; int res = availableTelemetryIndex(); if (res >= 0) { s_currIdx = res; pushMenu(menuModelSensor); } else { POPUP_WARNING(STR_TELEMETRYFULL); } } break; case ITEM_TELEMETRY_DELETE_ALL_SENSORS: lcd_putsAtt(0, y, STR_DELETE_ALL_SENSORS, attr); s_editMode = 0; if (attr && event==EVT_KEY_LONG(KEY_ENTER)) { killEvents(KEY_ENTER); POPUP_CONFIRMATION(STR_CONFIRMDELETE); } break; case ITEM_TELEMETRY_IGNORE_SENSOR_INSTANCE: ON_OFF_MENU_ITEM(g_model.ignoreSensorIds, TELEM_COL2, y, STR_IGNORE_INSTANCE, attr, event); break; case ITEM_TELEMETRY_RSSI_LABEL: lcd_putsLeft(y, PSTR("RSSI")); break; case ITEM_TELEMETRY_RSSI_ALARM1: case ITEM_TELEMETRY_RSSI_ALARM2: { uint8_t alarm = k-ITEM_TELEMETRY_RSSI_ALARM1; lcd_putsLeft(y, (alarm==0 ? STR_LOWALARM : STR_CRITICALALARM)); lcd_outdezNAtt(TELEM_COL2, y, getRssiAlarmValue(alarm), LEFT|attr, 3); if (attr && s_editMode>0) { CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[alarm].value, -30, 30); } break; } #if defined(VARIO) case ITEM_TELEMETRY_VARIO_LABEL: lcd_putsLeft(y, STR_VARIO); break; case ITEM_TELEMETRY_VARIO_SOURCE: lcd_putsLeft(y, STR_SOURCE); putsMixerSource(TELEM_COL2, y, g_model.frsky.varioSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.varioSource-1) : 0, attr); if (attr) { g_model.frsky.varioSource = checkIncDec(event, g_model.frsky.varioSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable); } break; case ITEM_TELEMETRY_VARIO_RANGE: lcd_putsLeft(y, STR_RANGE); lcd_outdezAtt(TELEM_COL2, y, -10+g_model.frsky.varioMin, (m_posHorz==0 ? attr : 0)|LEFT); lcd_outdezAtt(TELEM_COL2+7*FW, y, 10+g_model.frsky.varioMax, (m_posHorz==1 ? attr : 0)|LEFT); if (attr && s_editMode>0) { switch (m_posHorz) { case 0: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMin, -7, 7); break; case 1: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); break; } } break; case ITEM_TELEMETRY_VARIO_CENTER: lcd_putsLeft(y, STR_CENTER); lcd_outdezAtt(TELEM_COL2, y, -5+g_model.frsky.varioCenterMin, (m_posHorz==0 ? attr : 0)|PREC1|LEFT); lcd_outdezAtt(TELEM_COL2+7*FW, y, 5+g_model.frsky.varioCenterMax, (m_posHorz==1 ? attr : 0)|PREC1|LEFT); lcd_putsiAtt(TELEM_COL3, y, STR_VVARIOCENTER, g_model.frsky.varioCenterSilent, (m_posHorz==2 ? attr : 0)); if (attr && s_editMode>0) { switch (m_posHorz) { case 0: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMin, -16, 5+min<int8_t>(10, g_model.frsky.varioCenterMax+5)); break; case 1: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -5+max<int8_t>(-10, g_model.frsky.varioCenterMin-5), +15); break; case 2: CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.varioCenterSilent, 1); break; } } break; #endif case ITEM_TELEMETRY_TOP_BAR_LABEL: lcd_putsLeft(y, STR_TOP_BAR); break; case ITEM_TELEMETRY_TOP_BAR_VOLTAGE: lcd_putsLeft(y, STR_VOLTAGE); putsMixerSource(TELEM_COL2, y, g_model.frsky.voltsSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.voltsSource-1) : 0, attr); if (attr) { g_model.frsky.voltsSource = checkIncDec(event, g_model.frsky.voltsSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isVoltsSensor); } break; case ITEM_TELEMETRY_TOP_BAR_ALTITUDE: lcd_putsLeft(y, STR_ALTITUDE); putsMixerSource(TELEM_COL2, y, g_model.frsky.altitudeSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.altitudeSource-1) : 0, attr); if (attr) { g_model.frsky.altitudeSource = checkIncDec(event, g_model.frsky.altitudeSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isAltSensor); } break; case ITEM_TELEMETRY_SCREEN_LABEL1: case ITEM_TELEMETRY_SCREEN_LABEL2: case ITEM_TELEMETRY_SCREEN_LABEL3: case ITEM_TELEMETRY_SCREEN_LABEL4: { uint8_t screenIndex = TELEMETRY_CURRENT_SCREEN(k); putsStrIdx(0*FW, y, STR_SCREEN, screenIndex+1); TelemetryScreenType oldScreenType = TELEMETRY_SCREEN_TYPE(screenIndex); TelemetryScreenType newScreenType = (TelemetryScreenType)selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VTELEMSCREENTYPE, oldScreenType, 0, TELEMETRY_SCREEN_TYPE_MAX, (m_posHorz==0 ? attr : 0), event); if (newScreenType != oldScreenType) { g_model.frsky.screensType = (g_model.frsky.screensType & (~(0x03 << (2*screenIndex)))) | (newScreenType << (2*screenIndex)); memset(&g_model.frsky.screens[screenIndex], 0, sizeof(g_model.frsky.screens[screenIndex])); } #if defined(LUA) if (newScreenType == TELEMETRY_SCREEN_TYPE_SCRIPT) { TelemetryScriptData & scriptData = g_model.frsky.screens[screenIndex].script; // TODO better function name for --- // TODO function for these lines if (ZEXIST(scriptData.file)) lcd_putsnAtt(TELEM_SCRTYPE_COL+7*FW, y, scriptData.file, sizeof(scriptData.file), (m_posHorz==1 ? attr : 0)); else lcd_putsiAtt(TELEM_SCRTYPE_COL+7*FW, y, STR_VCSWFUNC, 0, (m_posHorz==1 ? attr : 0)); if (m_posHorz==1 && attr && event==EVT_KEY_BREAK(KEY_ENTER) && READ_ONLY_UNLOCKED()) { s_editMode = 0; if (listSdFiles(SCRIPTS_TELEM_PATH, SCRIPTS_EXT, sizeof(g_model.frsky.screens[screenIndex].script.file), g_model.frsky.screens[screenIndex].script.file)) { menuHandler = onTelemetryScriptFileSelectionMenu; } else { POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); s_menu_flags = 0; } } } else if (attr) { MOVE_CURSOR_FROM_HERE(); } #endif break; } case ITEM_TELEMETRY_SCREEN_LINE1: case ITEM_TELEMETRY_SCREEN_LINE2: case ITEM_TELEMETRY_SCREEN_LINE3: case ITEM_TELEMETRY_SCREEN_LINE4: case ITEM_TELEMETRY_SCREEN_LINE5: case ITEM_TELEMETRY_SCREEN_LINE6: case ITEM_TELEMETRY_SCREEN_LINE7: case ITEM_TELEMETRY_SCREEN_LINE8: case ITEM_TELEMETRY_SCREEN_LINE9: case ITEM_TELEMETRY_SCREEN_LINE10: case ITEM_TELEMETRY_SCREEN_LINE11: case ITEM_TELEMETRY_SCREEN_LINE12: case ITEM_TELEMETRY_SCREEN_LINE13: case ITEM_TELEMETRY_SCREEN_LINE14: case ITEM_TELEMETRY_SCREEN_LINE15: case ITEM_TELEMETRY_SCREEN_LINE16: { uint8_t screenIndex, lineIndex; if (k < ITEM_TELEMETRY_SCREEN_LABEL2) { screenIndex = 0; lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE1; } else if (k >= ITEM_TELEMETRY_SCREEN_LABEL4) { screenIndex = 3; lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE13; } else if (k >= ITEM_TELEMETRY_SCREEN_LABEL3) { screenIndex = 2; lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE9; } else { screenIndex = 1; lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE5; } #if defined(GAUGES) if (IS_BARS_SCREEN(screenIndex)) { FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex]; source_t barSource = bar.source; putsMixerSource(TELEM_COL1, y, barSource, m_posHorz==0 ? attr : 0); int barMax = getMaximumValue(barSource); int barMin = -barMax; if (barSource) { if (barSource <= MIXSRC_LAST_CH) { putsChannelValue(TELEM_BARS_COLMIN, y, barSource, calc100toRESX(bar.barMin), (m_posHorz==1 ? attr : 0) | LEFT); putsChannelValue(TELEM_BARS_COLMAX, y, barSource, calc100toRESX(bar.barMax), (m_posHorz==2 ? attr : 0) | LEFT); } else { putsChannelValue(TELEM_BARS_COLMIN, y, barSource, bar.barMin, (m_posHorz==1 ? attr : 0) | LEFT); putsChannelValue(TELEM_BARS_COLMAX, y, barSource, bar.barMax, (m_posHorz==2 ? attr : 0) | LEFT); } } else if (attr) { MOVE_CURSOR_FROM_HERE(); } if (attr && s_editMode>0) { switch (m_posHorz) { case 0: bar.source = checkIncDec(event, barSource, 0, MIXSRC_LAST_TELEM, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable); if (checkIncDec_Ret) { if (barSource <= MIXSRC_LAST_CH) { bar.barMin = -100; bar.barMax = 100; } else { bar.barMin = 0; bar.barMax = 0; } } break; case 1: bar.barMin = checkIncDec(event, bar.barMin, barMin, bar.barMax, EE_MODEL|NO_INCDEC_MARKS); break; case 2: bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, barMax, EE_MODEL|NO_INCDEC_MARKS); break; } } } else #endif { for (int c=0; c<NUM_LINE_ITEMS; c++) { LcdFlags cellAttr = (m_posHorz==c ? attr : 0); source_t & value = g_model.frsky.screens[screenIndex].lines[lineIndex].sources[c]; const coord_t pos[] = {TELEM_COL1, TELEM_COL2, TELEM_COL3}; putsMixerSource(pos[c], y, value, cellAttr); if (cellAttr && s_editMode>0) { value = checkIncDec(event, value, 0, MIXSRC_LAST_TELEM, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable); } } if (attr && m_posHorz == NUM_LINE_ITEMS) { REPEAT_LAST_CURSOR_MOVE(); } } break; } } } }
void menuModelTelemetry(uint8_t event) { MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX+1, {0, TELEMETRY_TYPE_ROWS CHANNELS_ROWS RSSI_ROWS SENSORS_ROWS USRDATA_ROWS CASE_VARIO(LABEL(Vario)) CASE_VARIO(0) CASE_VARIO(VARIO_RANGE_ROWS) TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), CASE_CPUARM(TELEMETRY_SCREEN_ROWS(2)) CASE_CPUARM(TELEMETRY_SCREEN_ROWS(3))}); uint8_t sub = m_posVert - 1; switch (event) { case EVT_KEY_BREAK(KEY_DOWN): case EVT_KEY_BREAK(KEY_UP): case EVT_KEY_BREAK(KEY_LEFT): case EVT_KEY_BREAK(KEY_RIGHT): if (s_editMode>0 && sub<=ITEM_TELEMETRY_RSSI_ALARM2) frskySendAlarms(); // update FrSky module when edit mode exited break; } for (uint8_t i=0; i<LCD_LINES-1; i++) { coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH; uint8_t k = i + s_pgOfs; #if defined(CPUARM) for (int j=0; j<=k; j++) { if (mstate_tab[j+1] == HIDDEN_ROW) k++; } #endif uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS); uint8_t attr = (sub == k ? blink : 0); #if !defined(CPUARM) uint8_t ch = TELEMETRY_CURRENT_EDIT_CHANNEL(k); FrSkyChannelData & channel = g_model.frsky.channels[ch]; uint8_t dest = TELEM_A1-1+ch; #endif #if defined(CPUARM) if (k>=ITEM_TELEMETRY_SENSOR1 && k<ITEM_TELEMETRY_SENSOR1+MAX_SENSORS) { int index = k-ITEM_TELEMETRY_SENSOR1; lcd_outdezAtt(INDENT_WIDTH, y, index+1, LEFT|attr); lcd_putcAtt(lcdLastPos, y, ':', attr); lcd_putsnAtt(3*FW, y, g_model.telemetrySensors[index].label, TELEM_LABEL_LEN, ZCHAR); if (telemetryItems[index].isFresh()) { lcd_putc(16*FW, y, '*'); } TelemetryItem & telemetryItem = telemetryItems[index]; if (telemetryItem.isAvailable()) { bool isOld = telemetryItem.isOld(); lcdNextPos = TELEM_COL2; if (isOld) lcd_putc(lcdNextPos, y, '['); putsTelemetryChannelValue(lcdNextPos, y, index, getValue(MIXSRC_FIRST_TELEM+3*index), LEFT); if (isOld) lcd_putc(lcdLastPos, y, ']'); } else { lcd_putsAtt(TELEM_COL2, y, "---", 0); // TODO shortcut } if (attr) { s_editMode = 0; s_currIdx = index; if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); MENU_ADD_ITEM(STR_EDIT); MENU_ADD_ITEM(STR_COPY); MENU_ADD_ITEM(STR_DELETE); menuHandler = onSensorMenu; } else if (event == EVT_KEY_BREAK(KEY_ENTER)) { pushMenu(menuModelSensor); } } } else #endif switch (k) { #if defined(CPUARM) case ITEM_TELEMETRY_PROTOCOL_TYPE: g_model.telemetryProtocol = selectMenuItem(TELEM_COL2, y, STR_TELEMETRY_TYPE, "\017FrSky S.PORT\0 FrSky D\0 FrSky D (cable)", g_model.telemetryProtocol, PROTOCOL_TELEMETRY_FIRST, CASE_PCBSKY9X(PROTOCOL_FRSKY_D_SECONDARY) attr, event); break; #endif #if defined(CPUARM) case ITEM_TELEMETRY_SENSORS_LABEL: lcd_putsLeft(y, STR_TELEMETRY_SENSORS); break; case ITEM_TELEMETRY_NEWSENSOR: lcd_putsAtt(0, y, STR_TELEMETRY_NEWSENSOR, attr); if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) { s_editMode = 0; int res = availableTelemetryIndex(); if (res >= 0) { s_currIdx = res; pushMenu(menuModelSensor); } else { POPUP_WARNING(STR_TELEMETRYFULL); } } break; case ITEM_TELEMETRY_IGNORE_SENSORID: ON_OFF_MENU_ITEM(g_model.ignoreSensorIds, TELEM_COL2, y, STR_IGNOREIDS, attr, event); break; #endif #if !defined(CPUARM) case ITEM_TELEMETRY_A1_LABEL: case ITEM_TELEMETRY_A2_LABEL: lcd_putsLeft(y, STR_ACHANNEL); lcd_outdezAtt(2*FW, y, ch+1, 0); putsTelemetryChannelValue(TELEM_COL2+6*FW, y, dest, frskyData.analog[ch].value, LEFT); break; case ITEM_TELEMETRY_A1_RANGE: case ITEM_TELEMETRY_A2_RANGE: lcd_putsLeft(y, STR_RANGE); putsTelemetryChannelValue(TELEM_COL2, y, dest, 255-channel.offset, (m_posHorz<=0 ? attr : 0)|NO_UNIT|LEFT); lcd_putsiAtt(lcdLastPos, y, STR_VTELEMUNIT, channel.type, m_posHorz!=0 ? attr : 0); if (attr && (s_editMode>0 || p1valdiff)) { if (m_posHorz == 0) { uint16_t ratio = checkIncDec(event, channel.ratio, 0, 256, EE_MODEL); if (checkIncDec_Ret) { if (ratio == 127 && channel.multiplier > 0) { channel.multiplier--; channel.ratio = 255; } else if (ratio == 256) { if (channel.multiplier < FRSKY_MULTIPLIER_MAX) { channel.multiplier++; channel.ratio = 128; } } else { channel.ratio = ratio; } } } else { CHECK_INCDEC_MODELVAR_ZERO(event, channel.type, UNIT_A1A2_MAX); } } break; case ITEM_TELEMETRY_A1_OFFSET: case ITEM_TELEMETRY_A2_OFFSET: lcd_putsLeft(y, STR_OFFSET); putsTelemetryChannelValue(TELEM_COL2, y, dest, 0, LEFT|attr); if (attr) channel.offset = checkIncDec(event, channel.offset, -256, 256, EE_MODEL); break; case ITEM_TELEMETRY_A1_ALARM1: case ITEM_TELEMETRY_A1_ALARM2: case ITEM_TELEMETRY_A2_ALARM1: case ITEM_TELEMETRY_A2_ALARM2: { uint8_t alarm = ((k==ITEM_TELEMETRY_A1_ALARM1 || k==ITEM_TELEMETRY_A2_ALARM1) ? 0 : 1); lcd_putsLeft(y, STR_ALARM); lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ALARM_LEVEL(ch, alarm), m_posHorz<=0 ? attr : 0); lcd_putsiAtt(TELEM_COL2+4*FW, y, STR_VALARMFN, ALARM_GREATER(ch, alarm), (CURSOR_ON_LINE() || m_posHorz==1) ? attr : 0); putsTelemetryChannelValue(TELEM_COL2+6*FW, y, dest, channel.alarms_value[alarm], ((CURSOR_ON_LINE() || m_posHorz==2) ? attr : 0) | LEFT); if (attr && (s_editMode>0 || p1valdiff)) { uint8_t t; switch (m_posHorz) { case 0: t = ALARM_LEVEL(ch, alarm); channel.alarms_level = (channel.alarms_level & ~(3<<(2*alarm))) + (checkIncDecModel(event, t, 0, 3) << (2*alarm)); break; case 1: t = ALARM_GREATER(ch, alarm); if (t != checkIncDecModel(event, t, 0, 1)) { channel.alarms_greater ^= (1 << alarm); frskySendAlarms(); } break; case 2: channel.alarms_value[alarm] = checkIncDec(event, channel.alarms_value[alarm], 0, 255, EE_MODEL); break; } } break; } #endif case ITEM_TELEMETRY_RSSI_LABEL: lcd_putsLeft(y, PSTR("RSSI")); break; case ITEM_TELEMETRY_RSSI_ALARM1: case ITEM_TELEMETRY_RSSI_ALARM2: { uint8_t alarm = k-ITEM_TELEMETRY_RSSI_ALARM1; lcd_putsLeft(y, STR_ALARM); lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ((2+alarm+g_model.frsky.rssiAlarms[alarm].level)%4), m_posHorz<=0 ? attr : 0); lcd_putc(TELEM_COL2+4*FW, y, '<'); lcd_outdezNAtt(TELEM_COL2+6*FW, y, getRssiAlarmValue(alarm), LEFT|(m_posHorz!=0 ? attr : 0), 3); if (attr && (s_editMode>0 || p1valdiff)) { switch (m_posHorz) { case 0: CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[alarm].level, -3, 2); // circular (saves flash) break; case 1: CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[alarm].value, -30, 30); break; } } break; } #if !defined(CPUARM) #if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) case ITEM_TELEMETRY_USR_LABEL: lcd_putsLeft(y, STR_USRDATA); break; case ITEM_TELEMETRY_USR_PROTO: lcd_putsLeft(y, STR_PROTO); lcd_putsiAtt(TELEM_COL2, y, STR_VTELPROTO, g_model.frsky.usrProto, attr); if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.usrProto, USR_PROTO_LAST); break; case ITEM_TELEMETRY_USR_BLADES: lcd_putsLeft(y, STR_BLADES); lcd_outdezAtt(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr); if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, MAX_BLADES); break; #endif case ITEM_TELEMETRY_USR_VOLTAGE_SOURCE: lcd_putsLeft(y, STR_VOLTAGE); lcd_putsiAtt(TELEM_COL2, y, STR_AMPSRC, g_model.frsky.voltsSource+1, attr); if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.voltsSource, FRSKY_VOLTS_SOURCE_LAST); break; case ITEM_TELEMETRY_USR_CURRENT_SOURCE: lcd_putsLeft(y, STR_CURRENT); lcd_putsiAtt(TELEM_COL2, y, STR_AMPSRC, g_model.frsky.currentSource, attr); if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.currentSource, FRSKY_CURRENT_SOURCE_LAST); break; #if defined(FAS_OFFSET) || !defined(CPUM64) case ITEM_TELEMETRY_FAS_OFFSET: lcd_putsLeft(y, STR_FAS_OFFSET); lcd_outdezAtt(TELEM_COL2, y, g_model.frsky.fasOffset, attr|LEFT|PREC1); lcd_outdezAtt(TELEM_COL2+6*FW, y, frskyData.hub.current, LEFT|PREC1); lcd_putc(TELEM_COL2+8*FW, y, 'A'); if (attr) g_model.frsky.fasOffset = checkIncDec(event, g_model.frsky.fasOffset, -120, 120, EE_MODEL); break; #endif #endif #if defined(VARIO) case ITEM_TELEMETRY_VARIO_LABEL: lcd_putsLeft(y, STR_VARIO); break; case ITEM_TELEMETRY_VARIO_SOURCE: lcd_putsLeft(y, STR_SOURCE); #if defined(CPUARM) putsMixerSource(TELEM_COL2, y, g_model.frsky.varioSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.varioSource-1) : 0, attr); if (attr) { g_model.frsky.varioSource = checkIncDec(event, g_model.frsky.varioSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable); } #else lcd_putsiAtt(TELEM_COL2, y, STR_VARIOSRC, g_model.frsky.varioSource, attr); if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioSource, 0, VARIO_SOURCE_LAST); #endif break; case ITEM_TELEMETRY_VARIO_RANGE: lcd_putsLeft(y, STR_LIMIT); #if defined(PCBSTD) lcd_outdezAtt(TELEM_COL2, y, 5+g_model.frsky.varioCenterMax, (m_posHorz==0 ? attr : 0)|PREC1|LEFT); lcd_outdezAtt(TELEM_COL2+8*FW, y, 10+g_model.frsky.varioMax, (m_posHorz==1 ? attr : 0)); if (attr && (s_editMode>0 || p1valdiff)) { switch (m_posHorz) { case 0: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -15, +15); break; case 1: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); break; } } #else lcd_outdezAtt(TELEM_COL2, y, -10+g_model.frsky.varioMin, (m_posHorz<=0 ? attr : 0)|LEFT); lcd_outdezAtt(TELEM_COL2+7*FW-2, y, -5+g_model.frsky.varioCenterMin, ((CURSOR_ON_LINE() || m_posHorz==1) ? attr : 0)|PREC1); lcd_outdezAtt(TELEM_COL2+10*FW, y, 5+g_model.frsky.varioCenterMax, ((CURSOR_ON_LINE() || m_posHorz==2) ? attr : 0)|PREC1); lcd_outdezAtt(TELEM_COL2+13*FW+2, y, 10+g_model.frsky.varioMax, ((CURSOR_ON_LINE() || m_posHorz==3) ? attr : 0)); if (attr && (s_editMode>0 || p1valdiff)) { switch (m_posHorz) { case 0: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMin, -7, 7); break; case 1: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMin, -16, 5+min<int8_t>(10, g_model.frsky.varioCenterMax+5)); break; case 2: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -5+max<int8_t>(-10, g_model.frsky.varioCenterMin-5), +15); break; case 3: CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); break; } } #endif break; #endif case ITEM_TELEMETRY_SCREEN_LABEL1: case ITEM_TELEMETRY_SCREEN_LABEL2: #if defined(CPUARM) case ITEM_TELEMETRY_SCREEN_LABEL3: case ITEM_TELEMETRY_SCREEN_LABEL4: { uint8_t screenIndex = TELEMETRY_CURRENT_EDIT_SCREEN(k); putsStrIdx(0*FW, y, STR_SCREEN, screenIndex+1); TelemetryScreenType oldScreenType = TELEMETRY_SCREEN_TYPE(screenIndex); TelemetryScreenType newScreenType = (TelemetryScreenType)selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VTELEMSCREENTYPE, oldScreenType, 0, TELEMETRY_SCREEN_TYPE_MAX, (m_posHorz==0 ? attr : 0), event); if (newScreenType != oldScreenType) { g_model.frsky.screensType = (g_model.frsky.screensType & (~(0x03 << (2*screenIndex)))) | (newScreenType << (2*screenIndex)); memset(&g_model.frsky.screens[screenIndex], 0, sizeof(g_model.frsky.screens[screenIndex])); } break; } #else { uint8_t screenIndex = (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 1 : 2); putsStrIdx(0*FW, y, STR_SCREEN, screenIndex); #if defined(GAUGES) bool screenType = g_model.frsky.screensType & screenIndex; if (screenType != (bool)selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VTELEMSCREENTYPE, screenType, 0, 1, attr, event)) g_model.frsky.screensType ^= screenIndex; #endif break; } #endif case ITEM_TELEMETRY_SCREEN_LINE1: case ITEM_TELEMETRY_SCREEN_LINE2: case ITEM_TELEMETRY_SCREEN_LINE3: case ITEM_TELEMETRY_SCREEN_LINE4: case ITEM_TELEMETRY_SCREEN_LINE5: case ITEM_TELEMETRY_SCREEN_LINE6: case ITEM_TELEMETRY_SCREEN_LINE7: case ITEM_TELEMETRY_SCREEN_LINE8: #if defined(CPUARM) case ITEM_TELEMETRY_SCREEN_LINE9: case ITEM_TELEMETRY_SCREEN_LINE10: case ITEM_TELEMETRY_SCREEN_LINE11: case ITEM_TELEMETRY_SCREEN_LINE12: case ITEM_TELEMETRY_SCREEN_LINE13: case ITEM_TELEMETRY_SCREEN_LINE14: case ITEM_TELEMETRY_SCREEN_LINE15: case ITEM_TELEMETRY_SCREEN_LINE16: #endif { uint8_t screenIndex, lineIndex; if (k < ITEM_TELEMETRY_SCREEN_LABEL2) { screenIndex = 0; lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE1; } #if defined(CPUARM) else if (k >= ITEM_TELEMETRY_SCREEN_LABEL4) { screenIndex = 3; lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE13; } else if (k >= ITEM_TELEMETRY_SCREEN_LABEL3) { screenIndex = 2; lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE9; } #endif else { screenIndex = 1; lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE5; } #if defined(GAUGES) if (IS_BARS_SCREEN(screenIndex)) { FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex]; source_t barSource = bar.source; #if defined(CPUARM) putsMixerSource(TELEM_COL1, y, barSource, m_posHorz==0 ? attr : 0); if (barSource) { putsChannelValue(TELEM_BARS_COLMIN, y, barSource, bar.barMin, (m_posHorz==1 ? attr : 0) | LEFT); putsChannelValue(TELEM_BARS_COLMAX, y, barSource, bar.barMax, (m_posHorz==2 ? attr : 0) | LEFT); } #else lcd_putsiAtt(TELEM_COL1, y, STR_VTELEMCHNS, barSource, m_posHorz==0 ? attr : 0); if (barSource) { putsTelemetryChannelValue(TELEM_BARS_COLMIN, y, barSource-1, convertBarTelemValue(barSource, bar.barMin), (m_posHorz==1 ? attr : 0) | LEFT); putsTelemetryChannelValue(TELEM_BARS_COLMAX, y, barSource-1, convertBarTelemValue(barSource, 255-bar.barMax), (m_posHorz==2 ? attr : 0) | LEFT); } #endif else if (attr) { MOVE_CURSOR_FROM_HERE(); } if (attr && (s_editMode>0 || p1valdiff)) { switch (m_posHorz) { case 0: #if defined(CPUARM) bar.source = CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, barSource, MIXSRC_LAST_TELEM, isSourceAvailable); #else bar.source = CHECK_INCDEC_MODELVAR_ZERO(event, barSource, TELEM_DISPLAY_MAX); #endif if (checkIncDec_Ret) { bar.barMin = 0; #if defined(CPUARM) bar.barMax = 0; #else bar.barMax = 255 - maxBarTelemValue(bar.source); #endif } break; case 1: #if defined(CPUARM) bar.barMin = checkIncDec(event, bar.barMin, -30000, bar.barMax, EE_MODEL|NO_INCDEC_MARKS); #else bar.barMin = checkIncDec(event, bar.barMin, 0, 254-bar.barMax, EE_MODEL|NO_INCDEC_MARKS); #endif break; case 2: #if defined(CPUARM) bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, 30000, EE_MODEL|NO_INCDEC_MARKS); #else bar.barMax = 255 - checkIncDec(event, 255-bar.barMax, bar.barMin+1, maxBarTelemValue(barSource), EE_MODEL|NO_INCDEC_MARKS); #endif break; } } } else #endif { for (uint8_t c=0; c<NUM_LINE_ITEMS; c++) { uint8_t cellAttr = (m_posHorz==c ? attr : 0); source_t & value = g_model.frsky.screens[screenIndex].lines[lineIndex].sources[c]; uint8_t pos[] = {INDENT_WIDTH, TELEM_COL2}; #if defined(CPUARM) putsMixerSource(pos[c], y, value, cellAttr); if (cellAttr && (s_editMode>0 || p1valdiff)) { CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, value, MIXSRC_LAST_TELEM, isSourceAvailable); } #else lcd_putsiAtt(pos[c], y, STR_VTELEMCHNS, value, cellAttr); if (cellAttr && (s_editMode>0 || p1valdiff)) { CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, value, (lineIndex==3 && c==0) ? TELEM_STATUS_MAX : TELEM_DISPLAY_MAX, isTelemetrySourceAvailable); } #endif } if (attr && m_posHorz == NUM_LINE_ITEMS) { REPEAT_LAST_CURSOR_MOVE(); } } break; } } } }
void menuModelLogicalSwitches(uint8_t event) { INCDEC_DECLARE_VARS(EE_MODEL); MENU(STR_MENULOGICALSWITCHES, menuTabModel, e_LogicalSwitches, NUM_LOGICAL_SWITCH+1, {0, NAVIGATION_LINE_BY_LINE|LS_FIELD_LAST/*repeated...*/}); uint8_t k = 0; int8_t sub = m_posVert - 1; horzpos_t horz = m_posHorz; for (uint8_t i=0; i<LCD_LINES-1; i++) { coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH; k = i+s_pgOfs; uint8_t attr = (sub==k ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); uint8_t attr1 = (horz==1 ? attr : 0); uint8_t attr2 = (horz==2 ? attr : 0); LogicalSwitchData * cs = lswAddress(k); // CSW name uint8_t sw = SWSRC_SW1+k; putsSwitches(0, y, sw, (getSwitch(sw) ? BOLD : 0) | ((sub==k && CURSOR_ON_LINE()) ? INVERS : 0)); // CSW func lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, horz==0 ? attr : 0); // CSW params uint8_t cstate = lswFamily(cs->func); #if defined(CPUARM) int16_t v1_val=cs->v1, v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; int16_t v3_min=-1, v3_max=100; #else int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; #define v1_val cs->v1 #endif if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) { putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1); putsSwitches(CSW_3RD_COLUMN, y, cs->v2, attr2); v1_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v1_max = SWSRC_LAST_IN_LOGICAL_SWITCHES; v2_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v2_max = SWSRC_LAST_IN_LOGICAL_SWITCHES; INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH); INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches); } #if defined(CPUARM) else if (cstate == LS_FAMILY_EDGE) { putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1); putsEdgeDelayParam(CSW_3RD_COLUMN, y, cs, attr2, horz==LS_FIELD_V3 ? attr : 0); v1_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v1_max = SWSRC_LAST_IN_LOGICAL_SWITCHES; v2_min=-129; v2_max = 122; v3_max = 222 - cs->v2; if (horz == 1) { INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH); INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches); } else { INCDEC_SET_FLAG(EE_MODEL); INCDEC_ENABLE_CHECK(NULL); } } #endif else if (cstate == LS_FAMILY_COMP) { #if defined(CPUARM) v1_val = (uint8_t)cs->v1; #endif putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1); putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, attr2); INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); INCDEC_ENABLE_CHECK(isSourceAvailable); } else if (cstate == LS_FAMILY_TIMER) { lcd_outdezAtt(CSW_2ND_COLUMN, y, lswTimerValue(cs->v1), LEFT|PREC1|attr1); lcd_outdezAtt(CSW_3RD_COLUMN, y, lswTimerValue(cs->v2), LEFT|PREC1|attr2); v1_min = v2_min = -128; v1_max = v2_max = 122; INCDEC_SET_FLAG(EE_MODEL); INCDEC_ENABLE_CHECK(NULL); } else { #if defined(CPUARM) v1_val = (uint8_t)cs->v1; #endif putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1); if (horz == 1) { INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); INCDEC_ENABLE_CHECK(isSourceAvailableInCustomSwitches); } else { INCDEC_SET_FLAG(EE_MODEL); INCDEC_ENABLE_CHECK(NULL); } #if defined(CPUARM) putsChannelValue(CSW_3RD_COLUMN, y, v1_val, calc100toRESX(cs->v2), LEFT|attr2); v2_min = -30000; v2_max = 30000; #elif defined(FRSKY) if (v1_val >= MIXSRC_FIRST_TELEM) { putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2); v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1); #if defined(CPUARM) if (cs->func == LS_FUNC_DIFFEGREATER) v2_min = -v2_max; else if (cs->func == LS_FUNC_ADIFFEGREATER) v2_min = 0; else v2_min = minTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1); if (horz == 2 && v2_max-v2_min > 1000) INCDEC_SET_FLAG(EE_MODEL | INCDEC_REP10 | NO_INCDEC_MARKS); if (cs->v2 < v2_min || cs->v2 > v2_max) { cs->v2 = 0; eeDirty(EE_MODEL); } #else if (cstate == LS_FAMILY_OFS) { v2_min = -128; v2_max -= 128; } else { v2_max = min((uint8_t)127, (uint8_t)v2_max); v2_min = -v2_max; } if (cs->v2 > v2_max) { cs->v2 = v2_max; eeDirty(EE_MODEL); } #endif } else { lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); #if defined(CPUARM) && defined(GVARS) if (v1_val >= MIXSRC_GVAR1) { v2_min = -1024; v2_max = +1024; } else #endif { v2_min = -LIMIT_EXT_PERCENT; v2_max = +LIMIT_EXT_PERCENT; } } #else if (v1_val >= MIXSRC_FIRST_TELEM) { putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2); v2_min = -128; v2_max = 127; } else { lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); v2_min = -LIMIT_EXT_PERCENT; v2_max = +LIMIT_EXT_PERCENT; } #endif } // CSW AND switch #if defined(CPUARM) putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, horz==LS_FIELD_ANDSW ? attr : 0); #else uint8_t andsw = cs->andsw; if (andsw > SWSRC_LAST_SWITCH) { andsw += SWSRC_SW1-SWSRC_LAST_SWITCH-1; } putsSwitches(CSW_4TH_COLUMN, y, andsw, horz==LS_FIELD_ANDSW ? attr : 0); #endif #if defined(CPUARM) // CSW duration if (cs->duration > 0) lcd_outdezAtt(CSW_5TH_COLUMN, y, cs->duration, (horz==LS_FIELD_DURATION ? attr : 0)|PREC1|LEFT); else lcd_putsiAtt(CSW_5TH_COLUMN, y, STR_MMMINV, 0, horz==LS_FIELD_DURATION ? attr : 0); // CSW delay if (cstate == LS_FAMILY_EDGE) { lcd_puts(CSW_6TH_COLUMN, y, STR_NA); if (attr && horz == LS_FIELD_DELAY) { REPEAT_LAST_CURSOR_MOVE(); } } else if (cs->delay > 0) { lcd_outdezAtt(CSW_6TH_COLUMN, y, cs->delay, (horz==LS_FIELD_DELAY ? attr : 0)|PREC1|LEFT); } else { lcd_putsiAtt(CSW_6TH_COLUMN, y, STR_MMMINV, 0, horz==LS_FIELD_DELAY ? attr : 0); } if (attr && horz == LS_FIELD_V3 && cstate != LS_FAMILY_EDGE) { REPEAT_LAST_CURSOR_MOVE(); } #endif if ((s_editMode>0 || p1valdiff) && attr) { switch (horz) { case LS_FIELD_FUNCTION: { #if defined(CPUARM) cs->func = checkIncDec(event, cs->func, 0, LS_FUNC_MAX, EE_MODEL, isLogicalSwitchFunctionAvailable); #else CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, LS_FUNC_MAX); #endif uint8_t new_cstate = lswFamily(cs->func); if (cstate != new_cstate) { #if defined(CPUARM) if (new_cstate == LS_FAMILY_TIMER) { cs->v1 = cs->v2 = -119; } else if (new_cstate == LS_FAMILY_EDGE) { cs->v1 = 0; cs->v2 = -129; cs->v3 = 0; } else { cs->v1 = cs->v2 = 0; } #else cs->v1 = cs->v2 = (new_cstate==LS_FAMILY_TIMER ? -119/*1.0*/ : 0); #endif } break; } case LS_FIELD_V1: cs->v1 = CHECK_INCDEC_PARAM(event, v1_val, v1_min, v1_max); break; case LS_FIELD_V2: cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max); if (checkIncDec_Ret) TRACE("v2=%d", cs->v2); break; #if defined(CPUARM) case LS_FIELD_V3: cs->v3 = CHECK_INCDEC_PARAM(event, cs->v3, v3_min, v3_max); break; #endif case LS_FIELD_ANDSW: #if defined(CPUARM) INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH); INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches); cs->andsw = CHECK_INCDEC_PARAM(event, cs->andsw, -MAX_LS_ANDSW, MAX_LS_ANDSW); #else CHECK_INCDEC_MODELVAR_ZERO(event, cs->andsw, MAX_LS_ANDSW); #endif break; #if defined(CPUARM) case LS_FIELD_DURATION: CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_LS_DURATION); break; case LS_FIELD_DELAY: CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_LS_DELAY); break; #endif } } } }