Add support for OSD element type variants

Extends the OSD element position setting to include a 2 bit selector for alternate representations of the element. So up to 4 variants of an element can be supported. Meant to be used instead of adding new elements when the request is a mutually exclusive variant of an existing element. If there are no variants of an element then the logic falls back to "type 1" (`OSD_ELEMENT_TYPE_1`) which is the only representation of the element.

As an example, in this PR the "Battery usage" element has been extended to 4 types:
1. The original capacity remaining graphical bar (shrinks as battery is used) - this is the default.
2. Capacity used graphical bar (grows as battery is used).
3. Remaining capacity numerical percentage (goes down as battery is used).
4. Capacity used numerical percentage (goes up as battery is used).

When extending an element it is not necessary to support all 4 types and the element rendering code should default to the original type 1 version for unsupported types.

Will require Configurator support. Since the 2 high bits of the `uint16` were previously unused the setting will default to the "type 1" original variant in all cases where an incompatible Configurator is used.
This commit is contained in:
Bruce Luckcuck 2020-03-26 13:37:58 -04:00
parent 34614231d3
commit 45aad0d379
3 changed files with 55 additions and 14 deletions

View File

@ -56,7 +56,7 @@ extern const char * const osdTimerSourceNames[OSD_NUM_TIMER_TYPES];
#define OSD_PROFILE_BITS_POS 11 #define OSD_PROFILE_BITS_POS 11
#define OSD_PROFILE_MASK (((1 << OSD_PROFILE_COUNT) - 1) << OSD_PROFILE_BITS_POS) #define OSD_PROFILE_MASK (((1 << OSD_PROFILE_COUNT) - 1) << OSD_PROFILE_BITS_POS)
#define OSD_POS_MAX 0x3FF #define OSD_POS_MAX 0x3FF
#define OSD_POSCFG_MAX (OSD_PROFILE_MASK | 0x3FF) // For CLI values #define OSD_POSCFG_MAX UINT16_MAX // element positions now use all 16 bits
#define OSD_PROFILE_FLAG(x) (1 << ((x) - 1 + OSD_PROFILE_BITS_POS)) #define OSD_PROFILE_FLAG(x) (1 << ((x) - 1 + OSD_PROFILE_BITS_POS))
#define OSD_PROFILE_1_FLAG OSD_PROFILE_FLAG(1) #define OSD_PROFILE_1_FLAG OSD_PROFILE_FLAG(1)
@ -73,9 +73,11 @@ extern const char * const osdTimerSourceNames[OSD_NUM_TIMER_TYPES];
// Character coordinate // Character coordinate
#define OSD_POSITION_BITS 5 // 5 bits gives a range 0-31 #define OSD_POSITION_BITS 5 // 5 bits gives a range 0-31
#define OSD_POSITION_XY_MASK ((1 << OSD_POSITION_BITS) - 1) #define OSD_POSITION_XY_MASK ((1 << OSD_POSITION_BITS) - 1)
#define OSD_POSITION_TYPE_MASK 0xC000 // bits 14-15
#define OSD_POS(x,y) ((x & OSD_POSITION_XY_MASK) | ((y & OSD_POSITION_XY_MASK) << OSD_POSITION_BITS)) #define OSD_POS(x,y) ((x & OSD_POSITION_XY_MASK) | ((y & OSD_POSITION_XY_MASK) << OSD_POSITION_BITS))
#define OSD_X(x) (x & OSD_POSITION_XY_MASK) #define OSD_X(x) (x & OSD_POSITION_XY_MASK)
#define OSD_Y(x) ((x >> OSD_POSITION_BITS) & OSD_POSITION_XY_MASK) #define OSD_Y(x) ((x >> OSD_POSITION_BITS) & OSD_POSITION_XY_MASK)
#define OSD_TYPE(x) ((x & OSD_POSITION_TYPE_MASK) >> 14)
// Timer configuration // Timer configuration
// Stored as 15[alarm:8][precision:4][source:4]0 // Stored as 15[alarm:8][precision:4][source:4]0

View File

@ -1027,22 +1027,51 @@ static void osdElementMainBatteryUsage(osdElementParms_t *element)
// Set length of indicator bar // Set length of indicator bar
#define MAIN_BATT_USAGE_STEPS 11 // Use an odd number so the bar can be centered. #define MAIN_BATT_USAGE_STEPS 11 // Use an odd number so the bar can be centered.
// Calculate constrained value const int usedCapacity = getMAhDrawn();
const float value = constrain(batteryConfig()->batteryCapacity - getMAhDrawn(), 0, batteryConfig()->batteryCapacity); int displayBasis = usedCapacity;
// Calculate mAh used progress switch (element->type) {
const uint8_t mAhUsedProgress = (batteryConfig()->batteryCapacity) ? ceilf((value / (batteryConfig()->batteryCapacity / MAIN_BATT_USAGE_STEPS))) : 0; case OSD_ELEMENT_TYPE_3: // mAh remaining percentage (counts down as battery is used)
displayBasis = constrain(batteryConfig()->batteryCapacity - usedCapacity, 0, batteryConfig()->batteryCapacity);
FALLTHROUGH;
// Create empty battery indicator bar case OSD_ELEMENT_TYPE_4: // mAh used percentage (counts up as battery is used)
element->buff[0] = SYM_PB_START; {
for (int i = 1; i <= MAIN_BATT_USAGE_STEPS; i++) { int displayPercent = 0;
element->buff[i] = i <= mAhUsedProgress ? SYM_PB_FULL : SYM_PB_EMPTY; if (batteryConfig()->batteryCapacity) {
displayPercent = constrain(lrintf(100.0f * displayBasis / batteryConfig()->batteryCapacity), 0, 100);
}
tfp_sprintf(element->buff, "%c%d%%", SYM_MAH, displayPercent);
break;
}
case OSD_ELEMENT_TYPE_2: // mAh used graphical progress bar (grows as battery is used)
displayBasis = constrain(batteryConfig()->batteryCapacity - usedCapacity, 0, batteryConfig()->batteryCapacity);
FALLTHROUGH;
case OSD_ELEMENT_TYPE_1: // mAh remaining graphical progress bar (shrinks as battery is used)
default:
{
uint8_t remainingCapacityBars = 0;
if (batteryConfig()->batteryCapacity) {
const float batteryRemaining = constrain(batteryConfig()->batteryCapacity - displayBasis, 0, batteryConfig()->batteryCapacity);
remainingCapacityBars = ceilf((batteryRemaining / (batteryConfig()->batteryCapacity / MAIN_BATT_USAGE_STEPS)));
}
// Create empty battery indicator bar
element->buff[0] = SYM_PB_START;
for (int i = 1; i <= MAIN_BATT_USAGE_STEPS; i++) {
element->buff[i] = i <= remainingCapacityBars ? SYM_PB_FULL : SYM_PB_EMPTY;
}
element->buff[MAIN_BATT_USAGE_STEPS + 1] = SYM_PB_CLOSE;
if (remainingCapacityBars > 0 && remainingCapacityBars < MAIN_BATT_USAGE_STEPS) {
element->buff[1 + remainingCapacityBars] = SYM_PB_END;
}
element->buff[MAIN_BATT_USAGE_STEPS+2] = '\0';
break;
}
} }
element->buff[MAIN_BATT_USAGE_STEPS + 1] = SYM_PB_CLOSE;
if (mAhUsedProgress > 0 && mAhUsedProgress < MAIN_BATT_USAGE_STEPS) {
element->buff[1 + mAhUsedProgress] = SYM_PB_END;
}
element->buff[MAIN_BATT_USAGE_STEPS+2] = '\0';
} }
static void osdElementMainBatteryVoltage(osdElementParms_t *element) static void osdElementMainBatteryVoltage(osdElementParms_t *element)
@ -1839,6 +1868,7 @@ static void osdDrawSingleElement(displayPort_t *osdDisplayPort, uint8_t item)
element.item = item; element.item = item;
element.elemPosX = elemPosX; element.elemPosX = elemPosX;
element.elemPosY = elemPosY; element.elemPosY = elemPosY;
element.type = OSD_TYPE(osdElementConfig()->item_pos[item]);
element.buff = (char *)&buff; element.buff = (char *)&buff;
element.osdDisplayPort = osdDisplayPort; element.osdDisplayPort = osdDisplayPort;
element.drawElement = true; element.drawElement = true;
@ -1866,6 +1896,7 @@ static void osdDrawSingleElementBackground(displayPort_t *osdDisplayPort, uint8_
element.item = item; element.item = item;
element.elemPosX = elemPosX; element.elemPosX = elemPosX;
element.elemPosY = elemPosY; element.elemPosY = elemPosY;
element.type = OSD_TYPE(osdElementConfig()->item_pos[item]);
element.buff = (char *)&buff; element.buff = (char *)&buff;
element.osdDisplayPort = osdDisplayPort; element.osdDisplayPort = osdDisplayPort;
element.drawElement = true; element.drawElement = true;

View File

@ -24,10 +24,18 @@
#include "osd/osd.h" #include "osd/osd.h"
typedef enum {
OSD_ELEMENT_TYPE_1 = 0,
OSD_ELEMENT_TYPE_2,
OSD_ELEMENT_TYPE_3,
OSD_ELEMENT_TYPE_4
} osdElementType_e;
typedef struct osdElementParms_s { typedef struct osdElementParms_s {
uint8_t item; uint8_t item;
uint8_t elemPosX; uint8_t elemPosX;
uint8_t elemPosY; uint8_t elemPosY;
osdElementType_e type;
char *buff; char *buff;
displayPort_t *osdDisplayPort; displayPort_t *osdDisplayPort;
bool drawElement; bool drawElement;