diff --git a/src/main/cms/cms.c b/src/main/cms/cms.c index b4abfd7ea9..11f453e60e 100644 --- a/src/main/cms/cms.c +++ b/src/main/cms/cms.c @@ -85,6 +85,9 @@ displayPort_t *pCurrentDisplay; static displayPort_t *cmsDisplayPorts[CMS_MAX_DEVICE]; static int cmsDeviceCount; static int cmsCurrentDevice = -1; +#ifdef USE_OSD +static unsigned int osdProfileCursor = 1; +#endif bool cmsDisplayPortRegister(displayPort_t *pDisplay) { @@ -161,6 +164,7 @@ static uint8_t rightMenuColumn; static uint8_t maxMenuItems; static uint8_t linesPerMenuItem; static cms_key_e externKey = CMS_KEY_NONE; +static bool osdElementEditing = false; bool cmsInMenu = false; @@ -344,14 +348,19 @@ static int cmsDrawMenuItemValue(displayPort_t *pDisplay, char *buff, uint8_t row return cnt; } -static int cmsDrawMenuEntry(displayPort_t *pDisplay, OSD_Entry *p, uint8_t row) +static int cmsDrawMenuEntry(displayPort_t *pDisplay, OSD_Entry *p, uint8_t row, bool selectedRow) { #define CMS_DRAW_BUFFER_LEN 12 #define CMS_NUM_FIELD_LEN 5 + #define CMS_CURSOR_BLINK_DELAY_MS 500 char buff[CMS_DRAW_BUFFER_LEN +1]; // Make room for null terminator. int cnt = 0; +#ifndef USE_OSD + UNUSED(selectedRow); +#endif + if (smallScreen) { row++; } @@ -413,11 +422,21 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, OSD_Entry *p, uint8_t row) case OME_VISIBLE: if (IS_PRINTVALUE(p) && p->data) { uint16_t *val = (uint16_t *)p->data; - - if (VISIBLE(*val)) { - strcpy(buff, "YES"); - } else { - strcpy(buff, "NO "); + bool cursorBlink = millis() % (2 * CMS_CURSOR_BLINK_DELAY_MS) < CMS_CURSOR_BLINK_DELAY_MS; + for (unsigned x = 1; x < OSD_PROFILE_COUNT + 1; x++) { + if (VISIBLE_IN_OSD_PROFILE(*val, x)) { + if (osdElementEditing && cursorBlink && selectedRow && (x == osdProfileCursor)) { + strcpy(buff + x - 1, " "); + } else { + strcpy(buff + x - 1, "X"); + } + } else { + if (osdElementEditing && cursorBlink && selectedRow && (x == osdProfileCursor)) { + strcpy(buff + x - 1, " "); + } else { + strcpy(buff + x - 1, "-"); + } + } } cnt = cmsDrawMenuItemValue(pDisplay, buff, row, 3); CLR_PRINTVALUE(p); @@ -573,7 +592,8 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs) // XXX printed if not enough room in the middle of the list. if (IS_PRINTVALUE(p)) { - room -= cmsDrawMenuEntry(pDisplay, p, top + i * linesPerMenuItem); + bool selectedRow = i == currentCtx.cursorRow; + room -= cmsDrawMenuEntry(pDisplay, p, top + i * linesPerMenuItem, selectedRow); if (room < 30) return; } @@ -782,11 +802,15 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, cms_key_e key) } if (key == CMS_KEY_ESC) { - cmsMenuBack(pDisplay); + if (osdElementEditing) { + osdElementEditing = false; + } else { + cmsMenuBack(pDisplay); + } return BUTTON_PAUSE; } - if (key == CMS_KEY_DOWN) { + if ((key == CMS_KEY_DOWN) && (!osdElementEditing)) { if (currentCtx.cursorRow < pageMaxRow) { currentCtx.cursorRow++; } else { @@ -795,7 +819,7 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, cms_key_e key) } } - if (key == CMS_KEY_UP) { + if ((key == CMS_KEY_UP) && (!osdElementEditing)) { currentCtx.cursorRow--; // Skip non-title labels @@ -809,7 +833,7 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, cms_key_e key) } } - if (key == CMS_KEY_DOWN || key == CMS_KEY_UP) + if ((key == CMS_KEY_DOWN || key == CMS_KEY_UP) && (!osdElementEditing)) return res; p = pageTop + currentCtx.cursorRow; @@ -842,6 +866,7 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, cms_key_e key) case OME_Back: cmsMenuBack(pDisplay); res = BUTTON_PAUSE; + osdElementEditing = false; break; case OME_Bool: @@ -859,11 +884,29 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, cms_key_e key) case OME_VISIBLE: if (p->data) { uint16_t *val = (uint16_t *)p->data; - - if (key == CMS_KEY_RIGHT) - *val |= OSD_PROFILE_1_FLAG; - else - *val &= ~OSD_PROFILE_1_FLAG; + if ((key == CMS_KEY_RIGHT) && (!osdElementEditing)) { + osdElementEditing = true; + osdProfileCursor = 1; + } else if (osdElementEditing) { +#ifdef USE_OSD_PROFILES + if (key == CMS_KEY_RIGHT) { + if (osdProfileCursor < OSD_PROFILE_COUNT) { + osdProfileCursor++; + } + } + if (key == CMS_KEY_LEFT) { + if (osdProfileCursor > 1) { + osdProfileCursor--; + } + } +#endif + if (key == CMS_KEY_UP) { + *val |= OSD_PROFILE_FLAG(osdProfileCursor); + } + if (key == CMS_KEY_DOWN) { + *val &= ~OSD_PROFILE_FLAG(osdProfileCursor); + } + } SET_PRINTVALUE(p); } break; diff --git a/src/main/cms/cms.h b/src/main/cms/cms.h index 18d73b4cd6..99d4b8b547 100644 --- a/src/main/cms/cms.h +++ b/src/main/cms/cms.h @@ -31,7 +31,7 @@ typedef enum { CMS_KEY_LEFT, CMS_KEY_RIGHT, CMS_KEY_ESC, - CMS_KEY_MENU + CMS_KEY_MENU, } cms_key_e; extern bool cmsInMenu; diff --git a/src/main/cms/cms_menu_osd.c b/src/main/cms/cms_menu_osd.c index f27af3f7d8..485a542077 100644 --- a/src/main/cms/cms_menu_osd.c +++ b/src/main/cms/cms_menu_osd.c @@ -62,51 +62,51 @@ static long menuOsdActiveElemsOnExit(const OSD_Entry *self) OSD_Entry menuOsdActiveElemsEntries[] = { {"--- ACTIV ELEM ---", OME_Label, NULL, NULL, 0}, - {"RSSI", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_RSSI_VALUE], 0}, - {"BATTERY VOLTAGE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_MAIN_BATT_VOLTAGE], 0}, - {"BATTERY USAGE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_MAIN_BATT_USAGE], 0}, - {"AVG CELL VOLTAGE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_AVG_CELL_VOLTAGE], 0}, - {"CROSSHAIRS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_CROSSHAIRS], 0}, - {"HORIZON", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ARTIFICIAL_HORIZON], 0}, - {"HORIZON SIDEBARS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_HORIZON_SIDEBARS], 0}, - {"TIMER 1", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ITEM_TIMER_1], 0}, - {"TIMER 2", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ITEM_TIMER_2], 0}, - {"REMAINING TIME ESTIMATE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_REMAINING_TIME_ESTIMATE], 0}, - {"FLY MODE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_FLYMODE], 0}, - {"NAME", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_CRAFT_NAME], 0}, - {"THROTTLE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_THROTTLE_POS], 0}, + {"RSSI", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_RSSI_VALUE], DYNAMIC}, + {"BATTERY VOLTAGE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_MAIN_BATT_VOLTAGE], DYNAMIC}, + {"BATTERY USAGE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_MAIN_BATT_USAGE], DYNAMIC}, + {"AVG CELL VOLTAGE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_AVG_CELL_VOLTAGE], DYNAMIC}, + {"CROSSHAIRS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_CROSSHAIRS], DYNAMIC}, + {"HORIZON", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ARTIFICIAL_HORIZON], DYNAMIC}, + {"HORIZON SIDEBARS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_HORIZON_SIDEBARS], DYNAMIC}, + {"TIMER 1", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ITEM_TIMER_1], DYNAMIC}, + {"TIMER 2", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ITEM_TIMER_2], DYNAMIC}, + {"REMAINING TIME ESTIMATE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_REMAINING_TIME_ESTIMATE], DYNAMIC}, + {"FLY MODE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_FLYMODE], DYNAMIC}, + {"NAME", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_CRAFT_NAME], DYNAMIC}, + {"THROTTLE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_THROTTLE_POS], DYNAMIC}, #ifdef USE_VTX_CONTROL - {"VTX CHAN", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_VTX_CHANNEL], 0}, + {"VTX CHAN", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_VTX_CHANNEL], DYNAMIC}, #endif // VTX - {"CURRENT (A)", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_CURRENT_DRAW], 0}, - {"USED MAH", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_MAH_DRAWN], 0}, + {"CURRENT (A)", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_CURRENT_DRAW], DYNAMIC}, + {"USED MAH", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_MAH_DRAWN], DYNAMIC}, #ifdef USE_GPS - {"GPS SPEED", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_GPS_SPEED], 0}, - {"GPS SATS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_GPS_SATS], 0}, - {"GPS LAT", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_GPS_LAT], 0}, - {"GPS LON", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_GPS_LON], 0}, - {"HOME DIR", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_HOME_DIR], 0}, - {"HOME DIST", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_HOME_DIST], 0}, - {"FLIGHT DIST", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_FLIGHT_DIST], 0}, + {"GPS SPEED", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_GPS_SPEED], DYNAMIC}, + {"GPS SATS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_GPS_SATS], DYNAMIC}, + {"GPS LAT", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_GPS_LAT], DYNAMIC}, + {"GPS LON", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_GPS_LON], DYNAMIC}, + {"HOME DIR", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_HOME_DIR], DYNAMIC}, + {"HOME DIST", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_HOME_DIST], DYNAMIC}, + {"FLIGHT DIST", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_FLIGHT_DIST], DYNAMIC}, #endif // GPS - {"COMPASS BAR", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_COMPASS_BAR], 0}, - {"ALTITUDE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ALTITUDE], 0}, - {"POWER", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_POWER], 0}, - {"ROLL PID", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ROLL_PIDS], 0}, - {"PITCH PID", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_PITCH_PIDS], 0}, - {"YAW PID", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_YAW_PIDS], 0}, - {"PROFILES", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_PIDRATE_PROFILE], 0}, - {"DEBUG", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_DEBUG], 0}, - {"WARNINGS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_WARNINGS], 0}, - {"DISARMED", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_DISARMED], 0}, - {"PIT ANG", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_PITCH_ANGLE], 0}, - {"ROL ANG", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ROLL_ANGLE], 0}, - {"HEADING", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_NUMERICAL_HEADING], 0}, + {"COMPASS BAR", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_COMPASS_BAR], DYNAMIC}, + {"ALTITUDE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ALTITUDE], DYNAMIC}, + {"POWER", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_POWER], DYNAMIC}, + {"ROLL PID", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ROLL_PIDS], DYNAMIC}, + {"PITCH PID", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_PITCH_PIDS], DYNAMIC}, + {"YAW PID", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_YAW_PIDS], DYNAMIC}, + {"PROFILES", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_PIDRATE_PROFILE], DYNAMIC}, + {"DEBUG", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_DEBUG], DYNAMIC}, + {"WARNINGS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_WARNINGS], DYNAMIC}, + {"DISARMED", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_DISARMED], DYNAMIC}, + {"PIT ANG", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_PITCH_ANGLE], DYNAMIC}, + {"ROL ANG", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ROLL_ANGLE], DYNAMIC}, + {"HEADING", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_NUMERICAL_HEADING], DYNAMIC}, #ifdef USE_VARIO - {"VARIO", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_NUMERICAL_VARIO], 0}, + {"VARIO", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_NUMERICAL_VARIO], DYNAMIC}, #endif - {"G-FORCE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_G_FORCE], 0}, - {"FLIP ARROW", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_FLIP_ARROW], 0}, + {"G-FORCE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_G_FORCE], DYNAMIC}, + {"FLIP ARROW", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_FLIP_ARROW], DYNAMIC}, {"BACK", OME_Back, NULL, NULL, 0}, {NULL, OME_END, NULL, NULL, 0} }; diff --git a/src/main/io/osd.h b/src/main/io/osd.h index aaf3c41af6..bc5b1fac1e 100644 --- a/src/main/io/osd.h +++ b/src/main/io/osd.h @@ -28,17 +28,26 @@ extern const char * const osdTimerSourceNames[OSD_NUM_TIMER_TYPES]; #define OSD_ELEMENT_BUFFER_LENGTH 32 +#ifdef USE_OSD_PROFILES #define OSD_PROFILE_COUNT 3 +#else +#define OSD_PROFILE_COUNT 1 +#endif #define OSD_PROFILE_BITS_POS 11 -#define OSD_PROFILE_1_FLAG (1 << OSD_PROFILE_BITS_POS) #define OSD_PROFILE_MASK (((1 << OSD_PROFILE_COUNT) - 1) << OSD_PROFILE_BITS_POS) #define OSD_POS_MAX 0x3FF #define OSD_POSCFG_MAX (OSD_PROFILE_MASK | 0x3FF) // For CLI values +#define OSD_PROFILE_FLAG(x) (1 << ((x) - 1 + OSD_PROFILE_BITS_POS)) +#define OSD_PROFILE_1_FLAG OSD_PROFILE_FLAG(1) + + #ifdef USE_OSD_PROFILES #define VISIBLE(x) osdElementVisible(x) +#define VISIBLE_IN_OSD_PROFILE(item, profile) ((item) & ((OSD_PROFILE_1_FLAG) << ((profile)-1))) #else #define VISIBLE(x) ((x) & OSD_PROFILE_MASK) +#define VISIBLE_IN_OSD_PROFILE(item, profile) VISIBLE(item) #endif