diff --git a/src/main/drivers/display.h b/src/main/drivers/display.h index af2d84333d..58b8354838 100644 --- a/src/main/drivers/display.h +++ b/src/main/drivers/display.h @@ -20,6 +20,10 @@ #pragma once +#define VIDEO_COLUMNS_SD 30 +#define VIDEO_LINES_NTSC 13 +#define VIDEO_LINES_PAL 16 + typedef enum { DISPLAYPORT_DEVICE_TYPE_MAX7456 = 0, DISPLAYPORT_DEVICE_TYPE_OLED, diff --git a/src/main/drivers/max7456.h b/src/main/drivers/max7456.h index c6de2c990c..154fa9e206 100644 --- a/src/main/drivers/max7456.h +++ b/src/main/drivers/max7456.h @@ -27,8 +27,6 @@ /** PAL or NTSC, value is number of chars total */ #define VIDEO_BUFFER_CHARS_NTSC 390 #define VIDEO_BUFFER_CHARS_PAL 480 -#define VIDEO_LINES_NTSC 13 -#define VIDEO_LINES_PAL 16 typedef enum { // IO defined and MAX7456 was detected diff --git a/src/main/io/displayport_msp.c b/src/main/io/displayport_msp.c index 02892eabf1..c7901dc96c 100644 --- a/src/main/io/displayport_msp.c +++ b/src/main/io/displayport_msp.c @@ -165,20 +165,14 @@ static bool isSynced(const displayPort_t *displayPort) static void redraw(displayPort_t *displayPort) { -#ifdef USE_OSD if (vcdProfile()->video_system == VIDEO_SYSTEM_HD) { displayPort->rows = osdConfig()->canvas_rows; displayPort->cols = osdConfig()->canvas_cols; } else { - const uint8_t displayRows = (vcdProfile()->video_system == VIDEO_SYSTEM_PAL) ? 16 : 13; + const uint8_t displayRows = (vcdProfile()->video_system == VIDEO_SYSTEM_PAL) ? VIDEO_LINES_PAL : VIDEO_LINES_NTSC; displayPort->rows = displayRows + displayPortProfileMsp()->rowAdjust; - displayPort->cols = 30 + displayPortProfileMsp()->colAdjust; + displayPort->cols = OSD_SD_COLS + displayPortProfileMsp()->colAdjust; } -#else - const uint8_t displayRows = (vcdProfile()->video_system == VIDEO_SYSTEM_PAL) ? 16 : 13; - displayPort->rows = displayRows + displayPortProfileMsp()->rowAdjust; - displayPort->cols = 30 + displayPortProfileMsp()->colAdjust; -#endif // USE_OSD drawScreen(displayPort); } @@ -215,6 +209,17 @@ displayPort_t *displayPortMspInit(void) mspDisplayPort.useDeviceBlink = true; } +#ifndef USE_OSD_SD + if (vcdProfile()->video_system != VIDEO_SYSTEM_HD) { + vcdProfileMutable()->video_system = VIDEO_SYSTEM_HD; + } +#endif +#ifndef USE_OSD_HD + if (vcdProfile()->video_system == VIDEO_SYSTEM_HD) { + vcdProfileMutable()->video_system = VIDEO_SYSTEM_AUTO; + } +#endif + redraw(&mspDisplayPort); return &mspDisplayPort; } diff --git a/src/main/msp/msp.c b/src/main/msp/msp.c index 31be178d4b..72f28b6eb3 100644 --- a/src/main/msp/msp.c +++ b/src/main/msp/msp.c @@ -982,7 +982,7 @@ static bool mspCommonProcessOutCommand(int16_t cmdMSP, sbuf_t *dst, mspPostProce #endif sbufWriteU8(dst, osdFlags); -#ifdef USE_MAX7456 +#ifdef USE_OSD_SD // send video system (AUTO/PAL/NTSC/HD) sbufWriteU8(dst, vcdProfile()->video_system); #else @@ -4081,12 +4081,14 @@ static mspResult_e mspCommonProcessInCommand(mspDescriptor_t srcDesc, int16_t cm if ((int8_t)addr == -1) { /* Set general OSD settings */ -#ifdef USE_MAX7456 - vcdProfileMutable()->video_system = sbufReadU8(src); -#else - sbufReadU8(src); // Skip video system + videoSystem_e video_system = sbufReadU8(src); +#ifndef USE_OSD_HD + if (video_system == VIDEO_SYSTEM_HD) { + video_system = VIDEO_SYSTEM_AUTO; + } #endif -#if defined(USE_OSD) + vcdProfileMutable()->video_system = video_system; + osdConfigMutable()->units = sbufReadU8(src); // Alarms @@ -4134,19 +4136,16 @@ static mspResult_e mspCommonProcessInCommand(mspDescriptor_t srcDesc, int16_t cm osdConfigMutable()->camera_frame_width = sbufReadU8(src); osdConfigMutable()->camera_frame_height = sbufReadU8(src); } -#endif } else if ((int8_t)addr == -2) { -#if defined(USE_OSD) // Timers uint8_t index = sbufReadU8(src); if (index > OSD_TIMER_COUNT) { return MSP_RESULT_ERROR; } osdConfigMutable()->timers[index] = sbufReadU16(src); -#endif + return MSP_RESULT_ERROR; } else { -#if defined(USE_OSD) const uint16_t value = sbufReadU16(src); /* Get screen index, 0 is post flight statistics, 1 and above are in flight OSD screens */ @@ -4162,9 +4161,6 @@ static mspResult_e mspCommonProcessInCommand(mspDescriptor_t srcDesc, int16_t cm } else { return MSP_RESULT_ERROR; } -#else - return MSP_RESULT_ERROR; -#endif } } break; @@ -4207,6 +4203,7 @@ static mspResult_e mspCommonProcessInCommand(mspDescriptor_t srcDesc, int16_t cm } break; +#ifdef USE_OSD_HD case MSP_SET_OSD_CANVAS: { osdConfigMutable()->canvas_cols = sbufReadU8(src); @@ -4216,6 +4213,7 @@ static mspResult_e mspCommonProcessInCommand(mspDescriptor_t srcDesc, int16_t cm vcdProfileMutable()->video_system = VIDEO_SYSTEM_HD; } break; +#endif //USE_OSD_HD #endif // OSD default: diff --git a/src/main/osd/osd.c b/src/main/osd/osd.c index 245b9f7bcc..ebeb5e7e2b 100644 --- a/src/main/osd/osd.c +++ b/src/main/osd/osd.c @@ -402,15 +402,29 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig) osdConfig->aux_scale = 200; osdConfig->aux_symbol = 'A'; + // Make it obvious on the configurator that the FC doesn't support HD +#ifdef USE_OSD_HD osdConfig->canvas_cols = OSD_HD_COLS; osdConfig->canvas_rows = OSD_HD_ROWS; +#else + osdConfig->canvas_cols = OSD_SD_COLS; + osdConfig->canvas_rows = OSD_SD_ROWS; +#endif } void pgResetFn_osdElementConfig(osdElementConfig_t *osdElementConfig) { +#ifdef USE_OSD_SD + uint8_t midRow = 7; + uint8_t midCol = 15; +#else + uint8_t midRow = 10; + uint8_t midCol = 26; +#endif + // Position elements near centre of screen and disabled by default for (int i = 0; i < OSD_ITEM_COUNT; i++) { - osdElementConfig->item_pos[i] = OSD_POS(10, 7); + osdElementConfig->item_pos[i] = OSD_POS((midCol - 5), midRow); } // Always enable warnings elements by default @@ -418,14 +432,14 @@ void pgResetFn_osdElementConfig(osdElementConfig_t *osdElementConfig) for (unsigned i = 1; i <= OSD_PROFILE_COUNT; i++) { profileFlags |= OSD_PROFILE_FLAG(i); } - osdElementConfig->item_pos[OSD_WARNINGS] = OSD_POS(9, 10) | profileFlags; + osdElementConfig->item_pos[OSD_WARNINGS] = OSD_POS((midCol - 6), (midRow + 3)) | profileFlags; // Default to old fixed positions for these elements - osdElementConfig->item_pos[OSD_CROSSHAIRS] = OSD_POS(13, 6); - osdElementConfig->item_pos[OSD_ARTIFICIAL_HORIZON] = OSD_POS(14, 2); - osdElementConfig->item_pos[OSD_HORIZON_SIDEBARS] = OSD_POS(14, 6); - osdElementConfig->item_pos[OSD_CAMERA_FRAME] = OSD_POS(3, 1); - osdElementConfig->item_pos[OSD_UP_DOWN_REFERENCE] = OSD_POS(13, 6); + osdElementConfig->item_pos[OSD_CROSSHAIRS] = OSD_POS((midCol - 2), (midRow - 1)); + osdElementConfig->item_pos[OSD_ARTIFICIAL_HORIZON] = OSD_POS((midCol - 1), (midRow - 5)); + osdElementConfig->item_pos[OSD_HORIZON_SIDEBARS] = OSD_POS((midCol - 1), (midRow - 1)); + osdElementConfig->item_pos[OSD_CAMERA_FRAME] = OSD_POS((midCol - 12), (midRow - 6)); + osdElementConfig->item_pos[OSD_UP_DOWN_REFERENCE] = OSD_POS((midCol - 2), (midRow - 1)); } static void osdDrawLogo(int x, int y) @@ -497,29 +511,30 @@ void osdInit(displayPort_t *osdDisplayPortToUse, osdDisplayPortDevice_e displayP cmsDisplayPortRegister(osdDisplayPort); #endif - // Ensure that all OSD elements are on the canvas - for (int i = 0; i < OSD_ITEM_COUNT; i++) { - uint16_t itemPos = osdElementConfig()->item_pos[i]; - uint8_t elemPosX = OSD_X(itemPos); - uint8_t elemPosY = OSD_Y(itemPos); - uint16_t elemProfileType = itemPos & (OSD_PROFILE_MASK | OSD_TYPE_MASK); - bool pos_reset = false; + if (osdDisplayPort->cols && osdDisplayPort->rows) { + // Ensure that all OSD elements are on the canvas once number of row/columns is known + for (int i = 0; i < OSD_ITEM_COUNT; i++) { + uint16_t itemPos = osdElementConfig()->item_pos[i]; + uint8_t elemPosX = OSD_X(itemPos); + uint8_t elemPosY = OSD_Y(itemPos); + uint16_t elemProfileType = itemPos & (OSD_PROFILE_MASK | OSD_TYPE_MASK); + bool pos_reset = false; - if (elemPosX >= osdDisplayPort->cols) { - elemPosX = osdDisplayPort->cols - 1; - pos_reset = true; - } + if (elemPosX >= osdDisplayPort->cols) { + elemPosX = osdDisplayPort->cols - 1; + pos_reset = true; + } - if (elemPosY >= osdDisplayPort->rows) { - elemPosY = osdDisplayPort->rows - 1; - pos_reset = true; - } + if (elemPosY >= osdDisplayPort->rows) { + elemPosY = osdDisplayPort->rows - 1; + pos_reset = true; + } - if (pos_reset) { - osdElementConfigMutable()->item_pos[i] = elemProfileType | OSD_POS(elemPosX, elemPosY); + if (pos_reset) { + osdElementConfigMutable()->item_pos[i] = elemProfileType | OSD_POS(elemPosX, elemPosY); + } } } - } static void osdResetStats(void) diff --git a/src/main/osd/osd.h b/src/main/osd/osd.h index 1bed95dde2..c7c53f9ced 100644 --- a/src/main/osd/osd.h +++ b/src/main/osd/osd.h @@ -82,6 +82,9 @@ extern const char * const osdTimerSourceNames[OSD_NUM_TIMER_TYPES]; #define OSD_Y(x) ((x >> OSD_POSITION_BITS) & OSD_POSITION_XY_MASK) #define OSD_TYPE(x) ((x & OSD_TYPE_MASK) >> 14) +#define OSD_SD_COLS VIDEO_COLUMNS_SD +#define OSD_SD_ROWS VIDEO_LINES_PAL + // Default HD OSD canvas size to be applied unless the goggles announce otherwise #define OSD_HD_COLS 53 #define OSD_HD_ROWS 20 diff --git a/src/main/target/common_pre.h b/src/main/target/common_pre.h index 9a51ba3b17..35ccffa936 100644 --- a/src/main/target/common_pre.h +++ b/src/main/target/common_pre.h @@ -364,6 +364,8 @@ extern uint8_t _dmaram_end__; #define USE_GPS #define USE_OSD +#define USE_OSD_SD +#define USE_OSD_HD #define USE_LED_STRIP #define USE_BLACKBOX @@ -526,11 +528,25 @@ extern uint8_t _dmaram_end__; #define USE_GPS_RESCUE #endif // USE_GPS -#if defined(USE_OSD) || defined(USE_OSD_HD) || defined(USE_OSD_SD) - +#if defined(USE_OSD_HD) || defined(USE_OSD_SD) +// If either USE_OSD_SD for USE_OSD_HD are defined, ensure that USE_OSD is also defined #ifndef USE_OSD #define USE_OSD #endif +#endif + +#ifdef USE_OSD + +#if !defined(USE_OSD_HD) && !defined(USE_OSD_SD) +// If USE_OSD is defined without specifying SD or HD, then support both +#define USE_OSD_SD +#define USE_OSD_HD +#endif + +#if !defined(USE_OSD_SD) && defined(USE_MAX7456) +// If USE_OSD_SD isn't defined then explicitly exclude MAX7456 support +#undef USE_MAX7456 +#endif #define USE_CMS #define USE_MSP_DISPLAYPORT