diff --git a/src/main/drivers/max7456.c b/src/main/drivers/max7456.c index 89a5b4ac16..0f5225d24c 100644 --- a/src/main/drivers/max7456.c +++ b/src/main/drivers/max7456.c @@ -59,7 +59,7 @@ static uint8_t screenBuffer[VIDEO_BUFFER_CHARS_PAL+40]; //for faster writes we u static uint8_t shadowBuffer[VIDEO_BUFFER_CHARS_PAL]; //max chars to update in one idle -#define MAX_CHARS2UPDATE 100 +#define MAX_CHARS2UPDATE 50 #ifdef MAX7456_DMA_CHANNEL_TX volatile bool dmaTransactionInProgress = false; #endif @@ -309,7 +309,7 @@ bool max7456DmaInProgres(void) } #endif -void max7456DrawScreen(void) +void max7456DrawScreenPartial(void) { uint8_t check; static uint16_t pos = 0; diff --git a/src/main/drivers/max7456.h b/src/main/drivers/max7456.h index a4ebe0ab4e..e3fd9b4166 100644 --- a/src/main/drivers/max7456.h +++ b/src/main/drivers/max7456.h @@ -145,7 +145,7 @@ enum VIDEO_TYPES { AUTO = 0, PAL, NTSC }; extern uint16_t maxScreenSize; void max7456Init(uint8_t system); -void max7456DrawScreen(void); +void max7456DrawScreenPartial(void); void max7456WriteNvm(uint8_t char_address, const uint8_t *font_data); uint8_t max7456GetRowsCount(void); void max7456Write(uint8_t x, uint8_t y, const char *buff); diff --git a/src/main/fc/fc_tasks.c b/src/main/fc/fc_tasks.c index 05cbec554b..5d6becb94a 100755 --- a/src/main/fc/fc_tasks.c +++ b/src/main/fc/fc_tasks.c @@ -505,7 +505,7 @@ cfTask_t cfTasks[TASK_COUNT] = { [TASK_OSD] = { .taskName = "OSD", .taskFunc = taskUpdateOsd, - .desiredPeriod = 1000000 / 60, // 60 Hz + .desiredPeriod = TASK_PERIOD_HZ(OSD_TASK_FREQUENCY_HZ), .staticPriority = TASK_PRIORITY_LOW, }, #endif diff --git a/src/main/io/osd.c b/src/main/io/osd.c index 244146c38d..7523f25545 100755 --- a/src/main/io/osd.c +++ b/src/main/io/osd.c @@ -100,7 +100,7 @@ typedef struct statistic_s { static statistic_t stats; uint16_t refreshTimeout = 0; -#define REFRESH_1S 12 +#define REFRESH_1S OSD_TASK_FREQUENCY_HZ static uint8_t armState; @@ -138,16 +138,22 @@ static void osdFormatDistanceStr(char* buff, int32_t dist) switch (osdConfig()->units) { case OSD_UNIT_IMPERIAL: - if (dist < 0) - tfp_sprintf(buff, "-%d%c", dist_abs / 100, SYM_FT); - else - tfp_sprintf(buff, "%d%c", dist_abs / 100, SYM_FT); + if (dist < 0) { + tfp_sprintf(buff, "-%d%c ", dist_abs / 100, SYM_FT); + } else { + tfp_sprintf(buff, "%d%c ", dist_abs / 100, SYM_FT); + } break; default: // Metric - if (dist < 0) - tfp_sprintf(buff, "-%d.%01d%c", dist_abs / 100, (dist_abs % 100) / 10, SYM_M); - else - tfp_sprintf(buff, "%d.%01d%c", dist_abs / 100, (dist_abs % 100) / 10, SYM_M); + if (dist < 0) { + tfp_sprintf(buff, "-%d.%01d%c ", dist_abs / 100, (dist_abs % 100) / 10, SYM_M); + } else { + if (dist < 10000) { // less than 100m + tfp_sprintf(buff, "%d.%01d%c ", dist_abs / 100, (dist_abs % 100) / 10, SYM_M); + } else { + tfp_sprintf(buff, "%d%c ", dist_abs / 100, SYM_M); + } + } } } @@ -173,17 +179,17 @@ static void osdFormatVelocityStr(char* buff, int32_t vel) { switch (osdConfig()->units) { case OSD_UNIT_IMPERIAL: - tfp_sprintf(buff, "%d%c", osdConvertVelocityToUnit(vel), SYM_MPH); + tfp_sprintf(buff, "%2d%c", osdConvertVelocityToUnit(vel), SYM_MPH); break; default: // Metric - tfp_sprintf(buff, "%d%c", osdConvertVelocityToUnit(vel), SYM_KMH); + tfp_sprintf(buff, "%3d%c", osdConvertVelocityToUnit(vel), SYM_KMH); } } -static void osdDrawSingleElement(uint8_t item) +static bool osdDrawSingleElement(uint8_t item) { if (!VISIBLE(osdConfig()->item_pos[item]) || BLINK(osdConfig()->item_pos[item])) { - return; + return false; } uint8_t elemPosX = OSD_X(osdConfig()->item_pos[item]); @@ -198,7 +204,7 @@ static void osdDrawSingleElement(uint8_t item) osdRssi = 99; buff[0] = SYM_RSSI; - tfp_sprintf(buff + 1, "%d", osdRssi); + tfp_sprintf(buff + 1, "%2d", osdRssi); break; } @@ -207,13 +213,13 @@ static void osdDrawSingleElement(uint8_t item) uint8_t p = calculateBatteryPercentage(); p = (100 - p) / 16.6; buff[0] = SYM_BATT_FULL + p; - tfp_sprintf(buff + 1, "%d.%1dV", vbat / 10, vbat % 10); + tfp_sprintf(buff + 1, "%d.%1dV ", vbat / 10, vbat % 10); break; } case OSD_CURRENT_DRAW: buff[0] = SYM_AMP; - tfp_sprintf(buff + 1, "%d.%02d", abs(amperage) / 100, abs(amperage) % 100); + tfp_sprintf(buff + 1, "%d.%02d ", abs(amperage) / 100, abs(amperage) % 100); break; case OSD_MAH_DRAWN: @@ -225,7 +231,7 @@ static void osdDrawSingleElement(uint8_t item) case OSD_GPS_SATS: buff[0] = 0x1e; buff[1] = 0x1f; - tfp_sprintf(buff + 2, "%d", gpsSol.numSat); + tfp_sprintf(buff + 2, "%2d", gpsSol.numSat); break; case OSD_GPS_SPEED: @@ -278,7 +284,7 @@ static void osdDrawSingleElement(uint8_t item) if (h < 0) h+=360; buff[0] = 0xA9; - tfp_sprintf(&buff[1], "%d%c", h , 0xA8 ); + tfp_sprintf(&buff[1], "%3d%c", h , 0xA8 ); break; } #endif // GPS @@ -313,7 +319,7 @@ static void osdDrawSingleElement(uint8_t item) #if 0 if (isAirmodeActive()) - p = "AIR"; + p = "AIR "; #endif if (FLIGHT_MODE(PASSTHRU_MODE)) @@ -333,10 +339,10 @@ static void osdDrawSingleElement(uint8_t item) else if (FLIGHT_MODE(ANGLE_MODE)) p = "STAB"; else if (FLIGHT_MODE(HORIZON_MODE)) - p = "HOR"; + p = "HOR "; max7456Write(elemPosX, elemPosY, p); - return; + return true; } case OSD_CRAFT_NAME: @@ -354,12 +360,12 @@ static void osdDrawSingleElement(uint8_t item) case OSD_THROTTLE_POS: buff[0] = SYM_THR; buff[1] = SYM_THR1; - tfp_sprintf(buff + 2, "%d", (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN)); + tfp_sprintf(buff + 2, "%3d", (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN)); break; #ifdef VTX case OSD_VTX_CHANNEL: - tfp_sprintf(buff, "CH:%d", current_vtx_channel % CHANNELS_PER_BAND + 1); + tfp_sprintf(buff, "CH:%2d", current_vtx_channel % CHANNELS_PER_BAND + 1); break; #endif // VTX @@ -400,6 +406,10 @@ static void osdDrawSingleElement(uint8_t item) pitchAngle = (pitchAngle / 8) - 41; // 41 = 4 * 9 + 5 for (int x = -4; x <= 4; x++) { + // clear the y area before writing the new horizon character + for (int y = 0; y <= 7; y++) { + max7456WriteChar(elemPosX + x, elemPosY + y, 0x20); + } int y = (rollAngle * x) / 64; y -= pitchAngle; // y += 41; // == 4 * 9 + 5 @@ -410,7 +420,7 @@ static void osdDrawSingleElement(uint8_t item) osdDrawSingleElement(OSD_HORIZON_SIDEBARS); - return; + return true; } case OSD_HORIZON_SIDEBARS: @@ -434,9 +444,10 @@ static void osdDrawSingleElement(uint8_t item) max7456WriteChar(elemPosX - hudwidth + 1, elemPosY, SYM_AH_LEFT); max7456WriteChar(elemPosX + hudwidth - 1, elemPosY, SYM_AH_RIGHT); - return; + return true; } +#if defined(BARO) || defined(GPS) case OSD_VARIO: { int16_t v = getEstimatedActualVelocity(Z) / 50; //50cm = 1 arrow @@ -472,7 +483,7 @@ static void osdDrawSingleElement(uint8_t item) max7456WriteChar(elemPosX, elemPosY+2, vchars[2]); max7456WriteChar(elemPosX, elemPosY+3, vchars[3]); max7456WriteChar(elemPosX, elemPosY+4, vchars[4]); - return; + return true; } case OSD_VARIO_NUM: @@ -482,6 +493,7 @@ static void osdDrawSingleElement(uint8_t item) tfp_sprintf(buff, "%c%d.%01d%c", value < 0 ? '-' : ' ', abs(value / 10), abs((value % 10)), 0x9F); break; } +#endif case OSD_ROLL_PIDS: { @@ -508,10 +520,49 @@ static void osdDrawSingleElement(uint8_t item) } default: - return; + return false; } max7456Write(elemPosX, elemPosY, buff); + return true; +} + +static uint8_t osdIncElementIndex(uint8_t elementIndex) +{ + ++elementIndex; + if (!sensors(SENSOR_ACC)) { + if (elementIndex == OSD_CROSSHAIRS) { + elementIndex = OSD_ONTIME; + } + } + if (!feature(FEATURE_CURRENT_METER)) { + if (elementIndex == OSD_CURRENT_DRAW) { + elementIndex = OSD_GPS_SPEED; + } + + } + if (!sensors(SENSOR_GPS)) { + if (elementIndex == OSD_GPS_SPEED) { + elementIndex = OSD_ALTITUDE; + } + if (elementIndex == OSD_GPS_LON) { + elementIndex = OSD_VARIO; + } + } + + if (elementIndex == OSD_ITEM_COUNT) { + elementIndex = 0; + } + return elementIndex; +} + +void osdDrawNextElement(void) +{ + static uint8_t elementIndex = 0; + while (osdDrawSingleElement(elementIndex) == false) { + elementIndex = osdIncElementIndex(elementIndex); + } + elementIndex = osdIncElementIndex(elementIndex); } void osdDrawElements(void) @@ -577,6 +628,7 @@ void osdDrawElements(void) } + void pgResetFn_osdConfig(osdConfig_t *osdConfig) { osdConfig->item_pos[OSD_ALTITUDE] = OSD_POS(1, 0) | VISIBLE_FLAG; @@ -816,7 +868,7 @@ static void osdArmMotors(void) osdResetStats(); } -static void osdRefresh(timeUs_t currentTimeUs) +static void osdRefreshStats(timeUs_t currentTimeUs) { static uint8_t lastSec = 0; uint8_t sec; @@ -840,27 +892,7 @@ static void osdRefresh(timeUs_t currentTimeUs) lastSec = sec; } - if (refreshTimeout) { - if (checkStickPosition(THR_HI) || checkStickPosition(PIT_HI)) // hide statistics - refreshTimeout = 1; - refreshTimeout--; - if (!refreshTimeout) - max7456ClearScreen(); - return; - } - blinkState = (currentTimeUs / 200000) % 2; - -#ifdef CMS - if (!displayIsGrabbed(osdDisplayPort)) { - osdUpdateAlarms(); - osdDrawElements(); -#ifdef OSD_CALLS_CMS - } else { - cmsUpdate(currentTimeUs); -#endif - } -#endif } /* @@ -868,18 +900,49 @@ static void osdRefresh(timeUs_t currentTimeUs) */ void osdUpdate(timeUs_t currentTimeUs) { - static uint32_t counter = 0; + static uint8_t iterationCounter = 0; + #ifdef MAX7456_DMA_CHANNEL_TX // don't touch buffers if DMA transaction is in progress - if (max7456DmaInProgres()) + if (max7456DmaInProgres()) { return; + } #endif // MAX7456_DMA_CHANNEL_TX - // redraw values in buffer - if (counter++ % 5 == 0) - osdRefresh(currentTimeUs); - else // rest of time redraw screen 10 chars per idle to don't lock the main idle - max7456DrawScreen(); + // refresh alarms every 20 iterations + if (iterationCounter == 0) { + if (!displayIsGrabbed(osdDisplayPort)) { + osdUpdateAlarms(); + } + } + // refresh statistics every 20 iterations + if (iterationCounter++ >= 20) { + iterationCounter = 0; + osdRefreshStats(currentTimeUs); + } + if (refreshTimeout) { + if (checkStickPosition(THR_HI) || checkStickPosition(PIT_HI)) { // hide statistics + refreshTimeout = 1; + } + refreshTimeout--; + if (!refreshTimeout) { + max7456ClearScreen(); + } + max7456DrawScreenPartial(); + return; + } + +#ifdef CMS + if (!displayIsGrabbed(osdDisplayPort)) { + osdDrawNextElement(); +#ifdef OSD_CALLS_CMS + } else { + cmsUpdate(currentTimeUs); +#endif + } +#endif + // draw part of screen 10 chars per idle to don't lock the main idle + max7456DrawScreenPartial(); #ifdef CMS // do not allow ARM if we are in menu diff --git a/src/main/io/osd.h b/src/main/io/osd.h index 258c4095ba..32961e25f5 100755 --- a/src/main/io/osd.h +++ b/src/main/io/osd.h @@ -20,6 +20,8 @@ #include "common/time.h" #include "config/parameter_group.h" +#define OSD_TASK_FREQUENCY_HZ 100 + #define VISIBLE_FLAG 0x0800 #define BLINK_FLAG 0x0400 #define VISIBLE(x) (x & VISIBLE_FLAG)