Add camera frame OSD element

Adds an adjustable outline element designed to represent the field of view of the pilot's HD camera for visual framing. The width, height and position of the frame are adjustable.
This commit is contained in:
Bruce Luckcuck 2019-11-01 17:30:02 -04:00
parent ef4da5ab3c
commit 5c3b8c6eb6
5 changed files with 54 additions and 0 deletions

View File

@ -1336,6 +1336,7 @@ const clivalue_t valueTable[] = {
#endif
{ "osd_rcchannels_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_RC_CHANNELS]) },
{ "osd_camera_frame_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_CAMERA_FRAME]) },
// OSD stats enabled flags are stored as bitmapped values inside a 32bit parameter
// It is recommended to keep the settings order the same as the enumeration. This way the settings are displayed in the cli in the same order making it easier on the users
@ -1381,6 +1382,8 @@ const clivalue_t valueTable[] = {
#endif
{ "osd_rcchannels", VAR_INT8 | MASTER_VALUE | MODE_ARRAY, .config.array.length = OSD_RCCHANNELS_COUNT, PG_OSD_CONFIG, offsetof(osdConfig_t, rcChannels) },
{ "osd_camera_frame_width", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { OSD_CAMERA_FRAME_MIN_WIDTH, OSD_CAMERA_FRAME_MAX_WIDTH }, PG_OSD_CONFIG, offsetof(osdConfig_t, camera_frame_width) },
{ "osd_camera_frame_height", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { OSD_CAMERA_FRAME_MIN_HEIGHT, OSD_CAMERA_FRAME_MAX_HEIGHT }, PG_OSD_CONFIG, offsetof(osdConfig_t, camera_frame_height) },
// PG_SYSTEM_CONFIG
#if defined(STM32F4)

View File

@ -878,6 +878,11 @@ static bool mspCommonProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProce
sbufWriteU8(dst, 0);
#endif // USE_OSD_STICK_OVERLAY
// API >= 1.43
// Add the camera frame element width/height
sbufWriteU8(dst, osdConfig()->camera_frame_width);
sbufWriteU8(dst, osdConfig()->camera_frame_height);
#endif // USE_OSD
break;
}
@ -3259,6 +3264,13 @@ static mspResult_e mspCommonProcessInCommand(mspDescriptor_t srcDesc, uint8_t cm
#endif // USE_OSD_STICK_OVERLAY
}
if (sbufBytesRemaining(src) >= 2) {
// API >= 1.43
// OSD camera frame element width/height
osdConfigMutable()->camera_frame_width = sbufReadU8(src);
osdConfigMutable()->camera_frame_height = sbufReadU8(src);
}
#endif
} else if ((int8_t)addr == -2) {
#if defined(USE_OSD)

View File

@ -286,6 +286,7 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
osdConfig->item_pos[OSD_CROSSHAIRS] = OSD_POS(13, 6);
osdConfig->item_pos[OSD_ARTIFICIAL_HORIZON] = OSD_POS(14, 2);
osdConfig->item_pos[OSD_HORIZON_SIDEBARS] = OSD_POS(14, 6);
osdConfig->item_pos[OSD_CAMERA_FRAME] = OSD_POS(3, 1);
// Enable the default stats
osdConfig->enabled_stats = 0; // reset all to off and enable only a few initially
@ -343,6 +344,9 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
osdConfig->distance_alarm = 0;
osdConfig->logo_on_arming = OSD_LOGO_ARMING_OFF;
osdConfig->logo_on_arming_duration = 5; // 0.5 seconds
osdConfig->camera_frame_width = 24;
osdConfig->camera_frame_height = 11;
}
static void osdDrawLogo(int x, int y)

View File

@ -41,6 +41,11 @@ extern const char * const osdTimerSourceNames[OSD_NUM_TIMER_TYPES];
#define OSD_RCCHANNELS_COUNT 4
#define OSD_CAMERA_FRAME_MIN_WIDTH 2
#define OSD_CAMERA_FRAME_MAX_WIDTH 30 // Characters per row supportes by MAX7456
#define OSD_CAMERA_FRAME_MIN_HEIGHT 2
#define OSD_CAMERA_FRAME_MAX_HEIGHT 16 // Rows supported by MAX7456 (PAL)
#define OSD_PROFILE_BITS_POS 11
#define OSD_PROFILE_MASK (((1 << OSD_PROFILE_COUNT) - 1) << OSD_PROFILE_BITS_POS)
#define OSD_POS_MAX 0x3FF
@ -135,6 +140,7 @@ typedef enum {
OSD_PROFILE_NAME,
OSD_RSSI_DBM_VALUE,
OSD_RC_CHANNELS,
OSD_CAMERA_FRAME,
OSD_ITEM_COUNT // MUST BE LAST
} osd_items_e;
@ -274,6 +280,8 @@ typedef struct osdConfig_s {
uint16_t distance_alarm;
uint8_t logo_on_arming; // show the logo on arming
uint8_t logo_on_arming_duration; // display duration in 0.1s units
uint8_t camera_frame_width; // The width of the box for the camera frame element
uint8_t camera_frame_height; // The height of the box for the camera frame element
} osdConfig_t;
PG_DECLARE(osdConfig_t, osdConfig);

View File

@ -596,6 +596,30 @@ static void osdElementCoreTemperature(osdElementParms_t *element)
}
#endif // USE_ADC_INTERNAL
static void osdBackgroundCameraFrame(osdElementParms_t *element)
{
const uint8_t xpos = element->elemPosX;
const uint8_t ypos = element->elemPosY;
const uint8_t width = constrain(osdConfig()->camera_frame_width, OSD_CAMERA_FRAME_MIN_WIDTH, OSD_CAMERA_FRAME_MAX_WIDTH);
const uint8_t height = constrain(osdConfig()->camera_frame_height, OSD_CAMERA_FRAME_MIN_HEIGHT, OSD_CAMERA_FRAME_MAX_HEIGHT);
element->buff[0] = SYM_STICK_OVERLAY_CENTER;
for (int i = 1; i < (width - 1); i++) {
element->buff[i] = SYM_STICK_OVERLAY_HORIZONTAL;
}
element->buff[width - 1] = SYM_STICK_OVERLAY_CENTER;
element->buff[width] = 0; // string terminator
displayWrite(element->osdDisplayPort, xpos, ypos, DISPLAYPORT_ATTR_NONE, element->buff);
for (int i = 1; i < (height - 1); i++) {
displayWriteChar(element->osdDisplayPort, xpos, ypos + i, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_VERTICAL);
displayWriteChar(element->osdDisplayPort, xpos + width - 1, ypos + i, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_VERTICAL);
}
displayWrite(element->osdDisplayPort, xpos, ypos + height - 1, DISPLAYPORT_ATTR_NONE, element->buff);
element->drawElement = false; // element already drawn
}
static void osdBackgroundCraftName(osdElementParms_t *element)
{
if (strlen(pilotConfig()->name) == 0) {
@ -1535,11 +1559,13 @@ static const uint8_t osdElementDisplayOrder[] = {
OSD_PROFILE_NAME,
#endif
OSD_RC_CHANNELS,
OSD_CAMERA_FRAME,
};
// Define the mapping between the OSD element id and the function to draw it
const osdElementDrawFn osdElementDrawFunction[OSD_ITEM_COUNT] = {
[OSD_CAMERA_FRAME] = NULL, // only has background. Added first so it's the lowest "layer" and doesn't cover other elements
[OSD_RSSI_VALUE] = osdElementRssi,
[OSD_MAIN_BATT_VOLTAGE] = osdElementMainBatteryVoltage,
[OSD_CROSSHAIRS] = NULL, // only has background
@ -1647,6 +1673,7 @@ const osdElementDrawFn osdElementDrawFunction[OSD_ITEM_COUNT] = {
// Only necessary to define the entries that actually have a background function
const osdElementDrawFn osdElementBackgroundFunction[OSD_ITEM_COUNT] = {
[OSD_CAMERA_FRAME] = osdBackgroundCameraFrame,
[OSD_CROSSHAIRS] = osdBackgroundCrosshairs,
[OSD_HORIZON_SIDEBARS] = osdBackgroundHorizonSidebars,
[OSD_CRAFT_NAME] = osdBackgroundCraftName,