Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -4842,6 +4842,16 @@ Force OSD to work in grid mode even if the OSD device supports pixel level acces

---

### osd_framerate_hz

Target refresh rate for OSD elements in Hz. Each element is redrawn at approximately this rate. Values above 10 Hz provide no visible improvement for typical flight data but increase CPU load. Artificial horizon and telemetry are always updated every cycle regardless of this setting. Set to -1 for legacy behavior (one element per frame).

| Default | Min | Max |
| --- | --- | --- |
| -1 | -1 | 15 |

---

### osd_gforce_alarm

Value above which the OSD g force indicator will blink (g)
Expand Down
1 change: 1 addition & 0 deletions src/main/build/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ typedef enum {
DEBUG_GPS,
DEBUG_LULU,
DEBUG_SBUS2,
DEBUG_OSD_REFRESH,
DEBUG_COUNT // also update debugModeNames in cli.c
} debugType_e;

Expand Down
3 changes: 2 additions & 1 deletion src/main/fc/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ static const char *debugModeNames[DEBUG_COUNT] = {
"HEADTRACKER",
"GPS",
"LULU",
"SBUS2"
"SBUS2",
"OSD_REFRESH"
};

/* Sensor names (used in lookup tables for *_hardware settings and in status
Expand Down
9 changes: 8 additions & 1 deletion src/main/fc/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ tables:
"VIBE", "CRUISE", "REM_FLIGHT_TIME", "SMARTAUDIO", "ACC",
"NAV_YAW", "PCF8574", "DYN_GYRO_LPF", "AUTOLEVEL", "ALTITUDE",
"AUTOTRIM", "AUTOTUNE", "RATE_DYNAMICS", "LANDING", "POS_EST",
"ADAPTIVE_FILTER", "HEADTRACKER", "GPS", "LULU", "SBUS2"]
"ADAPTIVE_FILTER", "HEADTRACKER", "GPS", "LULU", "SBUS2", "OSD_REFRESH"]
- name: aux_operator
values: ["OR", "AND"]
enum: modeActivationOperator_e
Expand Down Expand Up @@ -3329,6 +3329,13 @@ groups:
max: 600
type: int16_t
field: msp_displayport_fullframe_interval
- name: osd_framerate_hz
description: "Target refresh rate for OSD elements in Hz. Each element is redrawn at approximately this rate. Values above 10 Hz provide no visible improvement for typical flight data but increase CPU load. Artificial horizon and telemetry are always updated every cycle regardless of this setting. Set to -1 for legacy behavior (one element per frame)."
default_value: -1
min: -1
max: 15
type: int8_t
field: osd_framerate_hz
- name: osd_units
description: "IMPERIAL, METRIC, UK"
default_value: "METRIC"
Expand Down
47 changes: 41 additions & 6 deletions src/main/io/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <ctype.h>
#include <math.h>
#include <inttypes.h>
#include <limits.h>

#include "platform.h"

Expand Down Expand Up @@ -4245,15 +4246,48 @@ uint8_t osdIncElementIndex(uint8_t elementIndex)
void osdDrawNextElement(void)
{
static uint8_t elementIndex = 0;
// Flag for end of loop, also prevents infinite loop when no elements are enabled
uint8_t index = elementIndex;
do {
elementIndex = osdIncElementIndex(elementIndex);
} while (!osdDrawSingleElement(elementIndex) && index != elementIndex);
static uint8_t activeElements = 0;
static unsigned lastLayout = UINT_MAX;

// Recount visible elements on layout change
if (currentLayout != lastLayout) {
lastLayout = currentLayout;
activeElements = 0;
uint8_t idx = 0;
do {
idx = osdIncElementIndex(idx);
if (OSD_VISIBLE(osdLayoutsConfig()->item_pos[currentLayout][idx])) {
activeElements++;
}
} while (idx > 0);
}

int8_t framerate_hz = osdConfig()->osd_framerate_hz;

uint8_t elementsPerCycle;
if (framerate_hz <= 0 || activeElements == 0) {
elementsPerCycle = 1; // legacy: one element per cycle
} else {
elementsPerCycle = ((uint16_t)activeElements * framerate_hz * 2 + 124) / 125;
if (elementsPerCycle < 1) elementsPerCycle = 1;
if (elementsPerCycle > activeElements) elementsPerCycle = activeElements;
}

DEBUG_SET(DEBUG_OSD_REFRESH, 0, elementsPerCycle);
DEBUG_SET(DEBUG_OSD_REFRESH, 1, activeElements);
DEBUG_SET(DEBUG_OSD_REFRESH, 2, elementIndex);
DEBUG_SET(DEBUG_OSD_REFRESH, 3, framerate_hz);

for (uint8_t i = 0; i < elementsPerCycle; i++) {
uint8_t index = elementIndex;
do {
elementIndex = osdIncElementIndex(elementIndex);
} while (!osdDrawSingleElement(elementIndex) && index != elementIndex);
}

// Draw artificial horizon + tracking telemetry last
osdDrawSingleElement(OSD_ARTIFICIAL_HORIZON);
if (osdConfig()->telemetry>0){
if (osdConfig()->telemetry > 0) {
osdDisplayTelemetry();
}
}
Expand Down Expand Up @@ -4304,6 +4338,7 @@ PG_RESET_TEMPLATE(osdConfig_t, osdConfig,
.video_system = SETTING_OSD_VIDEO_SYSTEM_DEFAULT,
.row_shiftdown = SETTING_OSD_ROW_SHIFTDOWN_DEFAULT,
.msp_displayport_fullframe_interval = SETTING_OSD_MSP_DISPLAYPORT_FULLFRAME_INTERVAL_DEFAULT,
.osd_framerate_hz = SETTING_OSD_FRAMERATE_HZ_DEFAULT,

.ahi_reverse_roll = SETTING_OSD_AHI_REVERSE_ROLL_DEFAULT,
.ahi_max_pitch = SETTING_OSD_AHI_MAX_PITCH_DEFAULT,
Expand Down
1 change: 1 addition & 0 deletions src/main/io/osd.h
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ typedef struct osdConfig_s {
videoSystem_e video_system;
uint8_t row_shiftdown;
int16_t msp_displayport_fullframe_interval;
int8_t osd_framerate_hz;

// Preferences
uint8_t main_voltage_decimals;
Expand Down
Loading