2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
28 #if defined(USE_OSD) && defined(USE_CMS)
30 #include "build/version.h"
32 #include "cli/settings.h"
35 #include "cms/cms_types.h"
36 #include "cms/cms_menu_osd.h"
38 #include "common/utils.h"
40 #include "config/feature.h"
42 #include "drivers/display.h"
44 #include "io/displayport_max7456.h"
47 #include "osd/osd_elements.h"
50 #include "pg/pg_ids.h"
54 #include "sensors/battery.h"
56 #ifdef USE_EXTENDED_CMS_MENUS
57 static uint16_t osdConfig_item_pos
[OSD_ITEM_COUNT
];
59 static const void *menuOsdActiveElemsOnEnter(displayPort_t
*pDisp
)
63 memcpy(&osdConfig_item_pos
[0], &osdElementConfig()->item_pos
[0], sizeof(uint16_t) * OSD_ITEM_COUNT
);
67 static const void *menuOsdActiveElemsOnExit(displayPort_t
*pDisp
, const OSD_Entry
*self
)
72 memcpy(&osdElementConfigMutable()->item_pos
[0], &osdConfig_item_pos
[0], sizeof(uint16_t) * OSD_ITEM_COUNT
);
73 osdAnalyzeActiveElements();
77 const OSD_Entry menuOsdActiveElemsEntries
[] =
79 {"--- ACTIV ELEM ---", OME_Label
, NULL
, NULL
},
80 {"RSSI", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_RSSI_VALUE
]},
81 #ifdef USE_RX_RSSI_DBM
82 {"RSSI DBM", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_RSSI_DBM_VALUE
]},
85 {"RSNR", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_RSNR_VALUE
]},
87 {"BATTERY VOLTAGE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_MAIN_BATT_VOLTAGE
]},
88 {"BATTERY USAGE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_MAIN_BATT_USAGE
]},
89 {"AVG CELL VOLTAGE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_AVG_CELL_VOLTAGE
]},
91 {"BATTERY EFFICIENCY", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_EFFICIENCY
]},
93 {"CROSSHAIRS", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_CROSSHAIRS
]},
94 {"HORIZON", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ARTIFICIAL_HORIZON
]},
95 {"HORIZON SIDEBARS", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_HORIZON_SIDEBARS
]},
96 {"UP/DOWN REFERENCE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_UP_DOWN_REFERENCE
]},
97 {"TIMER 1", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ITEM_TIMER_1
]},
98 {"TIMER 2", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ITEM_TIMER_2
]},
99 {"REMAINING TIME ESTIMATE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_REMAINING_TIME_ESTIMATE
]},
101 {"RTC DATETIME", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_RTC_DATETIME
]},
103 #ifdef USE_OSD_ADJUSTMENTS
104 {"ADJUSTMENT RANGE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ADJUSTMENT_RANGE
]},
106 #ifdef USE_ADC_INTERNAL
107 {"CORE TEMPERATURE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_CORE_TEMPERATURE
]},
109 {"ANTI GRAVITY", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ANTI_GRAVITY
]},
110 {"FLY MODE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_FLYMODE
]},
111 {"CRAFT NAME", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_CRAFT_NAME
]},
112 {"THROTTLE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_THROTTLE_POS
]},
113 #ifdef USE_VTX_CONTROL
114 {"VTX CHAN", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_VTX_CHANNEL
]},
116 {"CURRENT (A)", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_CURRENT_DRAW
]},
117 {"USED MAH", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_MAH_DRAWN
]},
119 {"GPS SPEED", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_GPS_SPEED
]},
120 {"GPS SATS", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_GPS_SATS
]},
121 {"GPS LAT", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_GPS_LAT
]},
122 {"GPS LON", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_GPS_LON
]},
123 {"HOME DIR", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_HOME_DIR
]},
124 {"HOME DIST", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_HOME_DIST
]},
125 {"FLIGHT DIST", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_FLIGHT_DIST
]},
127 {"COMPASS BAR", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_COMPASS_BAR
]},
128 #ifdef USE_ESC_SENSOR
129 {"ESC TEMPERATURE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ESC_TMP
]},
130 {"ESC RPM", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ESC_RPM
]},
132 {"ALTITUDE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ALTITUDE
]},
133 {"POWER", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_POWER
]},
134 {"ROLL PID", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ROLL_PIDS
]},
135 {"PITCH PID", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_PITCH_PIDS
]},
136 {"YAW PID", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_YAW_PIDS
]},
137 {"PROFILES", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_PIDRATE_PROFILE
]},
138 #ifdef USE_PROFILE_NAMES
139 {"PID PROFILE NAME", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_PID_PROFILE_NAME
]},
140 {"RATE PROFILE NAME", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_RATE_PROFILE_NAME
]},
142 #ifdef USE_OSD_PROFILES
143 {"OSD PROFILE NAME", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_PROFILE_NAME
]},
145 {"DEBUG", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_DEBUG
]},
146 {"WARNINGS", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_WARNINGS
]},
147 {"DISARMED", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_DISARMED
]},
148 {"PIT ANG", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_PITCH_ANGLE
]},
149 {"ROL ANG", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_ROLL_ANGLE
]},
150 {"HEADING", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_NUMERICAL_HEADING
]},
152 {"VARIO", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_NUMERICAL_VARIO
]},
154 {"G-FORCE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_G_FORCE
]},
155 {"MOTOR DIAGNOSTIC", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_MOTOR_DIAG
]},
157 {"LOG STATUS", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_LOG_STATUS
]},
159 {"FLIP ARROW", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_FLIP_ARROW
]},
160 #ifdef USE_RX_LINK_QUALITY_INFO
161 {"LINK QUALITY", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_LINK_QUALITY
]},
163 #ifdef USE_OSD_STICK_OVERLAY
164 {"STICK OVERLAY LEFT", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_STICK_OVERLAY_LEFT
]},
165 {"STICK OVERLAY RIGHT",OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_STICK_OVERLAY_RIGHT
]},
167 {"PILOT NAME", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_PILOT_NAME
]},
168 {"RC CHANNELS", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_RC_CHANNELS
]},
169 {"CAMERA FRAME", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_CAMERA_FRAME
]},
170 {"TOTAL FLIGHTS", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_TOTAL_FLIGHTS
]},
171 {"AUX VALUE", OME_VISIBLE
| DYNAMIC
, NULL
, &osdConfig_item_pos
[OSD_AUX_VALUE
]},
172 {"BACK", OME_Back
, NULL
, NULL
},
173 {NULL
, OME_END
, NULL
, NULL
}
176 static CMS_Menu menuOsdActiveElems
= {
177 #ifdef CMS_MENU_DEBUG
178 .GUARD_text
= "MENUOSDACT",
179 .GUARD_type
= OME_MENU
,
181 .onEnter
= menuOsdActiveElemsOnEnter
,
182 .onExit
= menuOsdActiveElemsOnExit
,
183 .onDisplayUpdate
= NULL
,
184 .entries
= menuOsdActiveElemsEntries
187 static uint8_t osdConfig_rssi_alarm
;
188 static uint16_t osdConfig_link_quality_alarm
;
189 static int16_t osdConfig_rssi_dbm_alarm
;
190 static int16_t osdConfig_rsnr_alarm
;
191 static uint16_t osdConfig_cap_alarm
;
192 static uint16_t osdConfig_alt_alarm
;
193 static uint16_t osdConfig_distance_alarm
;
194 static uint8_t batteryConfig_vbatDurationForWarning
;
195 static uint8_t batteryConfig_vbatDurationForCritical
;
197 static const void *menuAlarmsOnEnter(displayPort_t
*pDisp
)
201 osdConfig_rssi_alarm
= osdConfig()->rssi_alarm
;
202 osdConfig_link_quality_alarm
= osdConfig()->link_quality_alarm
;
203 osdConfig_rssi_dbm_alarm
= osdConfig()->rssi_dbm_alarm
;
204 osdConfig_rsnr_alarm
= osdConfig()->rsnr_alarm
;
205 osdConfig_cap_alarm
= osdConfig()->cap_alarm
;
206 osdConfig_alt_alarm
= osdConfig()->alt_alarm
;
207 osdConfig_distance_alarm
= osdConfig()->distance_alarm
;
208 batteryConfig_vbatDurationForWarning
= batteryConfig()->vbatDurationForWarning
;
209 batteryConfig_vbatDurationForCritical
= batteryConfig()->vbatDurationForCritical
;
214 static const void *menuAlarmsOnExit(displayPort_t
*pDisp
, const OSD_Entry
*self
)
219 osdConfigMutable()->rssi_alarm
= osdConfig_rssi_alarm
;
220 osdConfigMutable()->link_quality_alarm
= osdConfig_link_quality_alarm
;
221 osdConfigMutable()->rssi_dbm_alarm
= osdConfig_rssi_dbm_alarm
;
222 osdConfigMutable()->rsnr_alarm
= osdConfig_rsnr_alarm
;
223 osdConfigMutable()->cap_alarm
= osdConfig_cap_alarm
;
224 osdConfigMutable()->alt_alarm
= osdConfig_alt_alarm
;
225 osdConfigMutable()->distance_alarm
= osdConfig_distance_alarm
;
226 batteryConfigMutable()->vbatDurationForWarning
= batteryConfig_vbatDurationForWarning
;
227 batteryConfigMutable()->vbatDurationForCritical
= batteryConfig_vbatDurationForCritical
;
232 const OSD_Entry menuAlarmsEntries
[] =
234 {"--- ALARMS ---", OME_Label
, NULL
, NULL
},
235 {"RSSI", OME_UINT8
, NULL
, &(OSD_UINT8_t
){&osdConfig_rssi_alarm
, 5, 90, 5}},
236 {"LINK QUALITY", OME_UINT16
, NULL
, &(OSD_UINT16_t
){&osdConfig_link_quality_alarm
, 5, 300, 5}},
237 {"RSSI DBM", OME_INT16
, NULL
, &(OSD_INT16_t
){&osdConfig_rssi_dbm_alarm
, CRSF_RSSI_MIN
, CRSF_SNR_MAX
, 5}},
238 {"RSNR", OME_INT16
, NULL
, &(OSD_INT16_t
){&osdConfig_rsnr_alarm
, CRSF_SNR_MIN
, CRSF_SNR_MAX
, 5}},
239 {"MAIN BAT", OME_UINT16
, NULL
, &(OSD_UINT16_t
){&osdConfig_cap_alarm
, 50, 30000, 50}},
240 {"MAX ALT", OME_UINT16
, NULL
, &(OSD_UINT16_t
){&osdConfig_alt_alarm
, 1, 200, 1}},
241 {"MAX DISTANCE", OME_UINT16
, NULL
, &(OSD_UINT16_t
){&osdConfig_distance_alarm
, 0, UINT16_MAX
, 10}},
242 {"VBAT WARN DUR", OME_UINT8
, NULL
, &(OSD_UINT8_t
){ &batteryConfig_vbatDurationForWarning
, 0, 200, 1 } },
243 {"VBAT CRIT DUR", OME_UINT8
, NULL
, &(OSD_UINT8_t
){ &batteryConfig_vbatDurationForCritical
, 0, 200, 1 } },
244 {"BACK", OME_Back
, NULL
, NULL
},
245 {NULL
, OME_END
, NULL
, NULL
,}
248 static CMS_Menu menuAlarms
= {
249 #ifdef CMS_MENU_DEBUG
250 .GUARD_text
= "MENUALARMS",
251 .GUARD_type
= OME_MENU
,
253 .onEnter
= menuAlarmsOnEnter
,
254 .onExit
= menuAlarmsOnExit
,
255 .onDisplayUpdate
= NULL
,
256 .entries
= menuAlarmsEntries
,
259 osd_timer_source_e timerSource
[OSD_TIMER_COUNT
];
260 osd_timer_precision_e timerPrecision
[OSD_TIMER_COUNT
];
261 uint8_t timerAlarm
[OSD_TIMER_COUNT
];
263 static const void *menuTimersOnEnter(displayPort_t
*pDisp
)
267 for (int i
= 0; i
< OSD_TIMER_COUNT
; i
++) {
268 const uint16_t timer
= osdConfig()->timers
[i
];
269 timerSource
[i
] = OSD_TIMER_SRC(timer
);
270 timerPrecision
[i
] = OSD_TIMER_PRECISION(timer
);
271 timerAlarm
[i
] = OSD_TIMER_ALARM(timer
);
277 static const void *menuTimersOnExit(displayPort_t
*pDisp
, const OSD_Entry
*self
)
282 for (int i
= 0; i
< OSD_TIMER_COUNT
; i
++) {
283 osdConfigMutable()->timers
[i
] = OSD_TIMER(timerSource
[i
], timerPrecision
[i
], timerAlarm
[i
]);
289 static const char * osdTimerPrecisionNames
[] = {"SCND", "HDTH"};
291 const OSD_Entry menuTimersEntries
[] =
293 {"--- TIMERS ---", OME_Label
, NULL
, NULL
},
294 {"1 SRC", OME_TAB
, NULL
, &(OSD_TAB_t
){&timerSource
[OSD_TIMER_1
], OSD_TIMER_SRC_COUNT
- 1, osdTimerSourceNames
} },
295 {"1 PREC", OME_TAB
, NULL
, &(OSD_TAB_t
){&timerPrecision
[OSD_TIMER_1
], OSD_TIMER_PREC_COUNT
- 1, osdTimerPrecisionNames
}},
296 {"1 ALARM", OME_UINT8
, NULL
, &(OSD_UINT8_t
){&timerAlarm
[OSD_TIMER_1
], 0, 0xFF, 1}},
297 {"2 SRC", OME_TAB
, NULL
, &(OSD_TAB_t
){&timerSource
[OSD_TIMER_2
], OSD_TIMER_SRC_COUNT
- 1, osdTimerSourceNames
} },
298 {"2 PREC", OME_TAB
, NULL
, &(OSD_TAB_t
){&timerPrecision
[OSD_TIMER_2
], OSD_TIMER_PREC_COUNT
- 1, osdTimerPrecisionNames
}},
299 {"2 ALARM", OME_UINT8
, NULL
, &(OSD_UINT8_t
){&timerAlarm
[OSD_TIMER_2
], 0, 0xFF, 1}},
300 {"BACK", OME_Back
, NULL
, NULL
},
301 {NULL
, OME_END
, NULL
, NULL
}
304 static CMS_Menu menuTimers
= {
305 #ifdef CMS_MENU_DEBUG
306 .GUARD_text
= "MENUTIMERS",
307 .GUARD_type
= OME_MENU
,
309 .onEnter
= menuTimersOnEnter
,
310 .onExit
= menuTimersOnExit
,
311 .onDisplayUpdate
= NULL
,
312 .entries
= menuTimersEntries
,
314 #endif /* USE_EXTENDED_CMS_MENUS */
317 static bool displayPortProfileMax7456_invert
;
318 static uint8_t displayPortProfileMax7456_blackBrightness
;
319 static uint8_t displayPortProfileMax7456_whiteBrightness
;
322 #ifdef USE_OSD_PROFILES
323 static uint8_t osdConfig_osdProfileIndex
;
326 static displayPortBackground_e osdMenuBackgroundType
;
328 static const void *cmsx_menuOsdOnEnter(displayPort_t
*pDisp
)
332 #ifdef USE_OSD_PROFILES
333 osdConfig_osdProfileIndex
= osdConfig()->osdProfileIndex
;
337 displayPortProfileMax7456_invert
= displayPortProfileMax7456()->invert
;
338 displayPortProfileMax7456_blackBrightness
= displayPortProfileMax7456()->blackBrightness
;
339 displayPortProfileMax7456_whiteBrightness
= displayPortProfileMax7456()->whiteBrightness
;
340 osdMenuBackgroundType
= osdConfig()->cms_background_type
;
346 static const void *cmsx_menuOsdOnExit(displayPort_t
*pDisp
, const OSD_Entry
*self
)
351 #ifdef USE_OSD_PROFILES
352 changeOsdProfileIndex(osdConfig_osdProfileIndex
);
359 static const void *cmsx_max7456Update(displayPort_t
*pDisp
, const void *self
)
363 displayPortProfileMax7456Mutable()->invert
= displayPortProfileMax7456_invert
;
364 displayPortProfileMax7456Mutable()->blackBrightness
= displayPortProfileMax7456_blackBrightness
;
365 displayPortProfileMax7456Mutable()->whiteBrightness
= displayPortProfileMax7456_whiteBrightness
;
367 displayClearScreen(pDisp
, DISPLAY_CLEAR_WAIT
);
371 #endif // USE_MAX7456
373 static const void *cmsx_osdBackgroundUpdate(displayPort_t
*pDisp
, const void *self
)
376 osdConfigMutable()->cms_background_type
= osdMenuBackgroundType
;
377 displaySetBackgroundType(pDisp
, osdMenuBackgroundType
);
381 const OSD_Entry cmsx_menuOsdEntries
[] =
383 {"---OSD---", OME_Label
, NULL
, NULL
},
384 #ifdef USE_OSD_PROFILES
385 {"OSD PROFILE", OME_UINT8
, NULL
, &(OSD_UINT8_t
){&osdConfig_osdProfileIndex
, 1, 3, 1}},
387 #ifdef USE_EXTENDED_CMS_MENUS
388 {"ACTIVE ELEM", OME_Submenu
, cmsMenuChange
, &menuOsdActiveElems
},
389 {"TIMERS", OME_Submenu
, cmsMenuChange
, &menuTimers
},
390 {"ALARMS", OME_Submenu
, cmsMenuChange
, &menuAlarms
},
393 {"INVERT", OME_Bool
, cmsx_max7456Update
, &displayPortProfileMax7456_invert
},
394 {"BRT BLACK", OME_UINT8
, cmsx_max7456Update
, &(OSD_UINT8_t
){&displayPortProfileMax7456_blackBrightness
, 0, 3, 1}},
395 {"BRT WHITE", OME_UINT8
, cmsx_max7456Update
, &(OSD_UINT8_t
){&displayPortProfileMax7456_whiteBrightness
, 0, 3, 1}},
397 {"BACKGROUND",OME_TAB
, cmsx_osdBackgroundUpdate
, &(OSD_TAB_t
){&osdMenuBackgroundType
, DISPLAY_BACKGROUND_COUNT
- 1, lookupTableCMSMenuBackgroundType
}},
398 {"BACK", OME_Back
, NULL
, NULL
},
399 {NULL
, OME_END
, NULL
, NULL
}
402 CMS_Menu cmsx_menuOsd
= {
403 #ifdef CMS_MENU_DEBUG
404 .GUARD_text
= "MENUOSD",
405 .GUARD_type
= OME_MENU
,
407 .onEnter
= cmsx_menuOsdOnEnter
,
408 .onExit
= cmsx_menuOsdOnExit
,
409 .onDisplayUpdate
= NULL
,
410 .entries
= cmsx_menuOsdEntries