mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-21 15:25:29 +03:00
Merge pull request #1831 from martinbudden/inav_osd_single_element
Draw single OSD element per osdUpdate
This commit is contained in:
commit
f4850845df
5 changed files with 124 additions and 59 deletions
|
@ -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];
|
static uint8_t shadowBuffer[VIDEO_BUFFER_CHARS_PAL];
|
||||||
|
|
||||||
//max chars to update in one idle
|
//max chars to update in one idle
|
||||||
#define MAX_CHARS2UPDATE 100
|
#define MAX_CHARS2UPDATE 50
|
||||||
#ifdef MAX7456_DMA_CHANNEL_TX
|
#ifdef MAX7456_DMA_CHANNEL_TX
|
||||||
volatile bool dmaTransactionInProgress = false;
|
volatile bool dmaTransactionInProgress = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -309,7 +309,7 @@ bool max7456DmaInProgres(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void max7456DrawScreen(void)
|
void max7456DrawScreenPartial(void)
|
||||||
{
|
{
|
||||||
uint8_t check;
|
uint8_t check;
|
||||||
static uint16_t pos = 0;
|
static uint16_t pos = 0;
|
||||||
|
|
|
@ -145,7 +145,7 @@ enum VIDEO_TYPES { AUTO = 0, PAL, NTSC };
|
||||||
extern uint16_t maxScreenSize;
|
extern uint16_t maxScreenSize;
|
||||||
|
|
||||||
void max7456Init(uint8_t system);
|
void max7456Init(uint8_t system);
|
||||||
void max7456DrawScreen(void);
|
void max7456DrawScreenPartial(void);
|
||||||
void max7456WriteNvm(uint8_t char_address, const uint8_t *font_data);
|
void max7456WriteNvm(uint8_t char_address, const uint8_t *font_data);
|
||||||
uint8_t max7456GetRowsCount(void);
|
uint8_t max7456GetRowsCount(void);
|
||||||
void max7456Write(uint8_t x, uint8_t y, const char *buff);
|
void max7456Write(uint8_t x, uint8_t y, const char *buff);
|
||||||
|
|
|
@ -505,7 +505,7 @@ cfTask_t cfTasks[TASK_COUNT] = {
|
||||||
[TASK_OSD] = {
|
[TASK_OSD] = {
|
||||||
.taskName = "OSD",
|
.taskName = "OSD",
|
||||||
.taskFunc = taskUpdateOsd,
|
.taskFunc = taskUpdateOsd,
|
||||||
.desiredPeriod = 1000000 / 60, // 60 Hz
|
.desiredPeriod = TASK_PERIOD_HZ(OSD_TASK_FREQUENCY_HZ),
|
||||||
.staticPriority = TASK_PRIORITY_LOW,
|
.staticPriority = TASK_PRIORITY_LOW,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -100,7 +100,7 @@ typedef struct statistic_s {
|
||||||
static statistic_t stats;
|
static statistic_t stats;
|
||||||
|
|
||||||
uint16_t refreshTimeout = 0;
|
uint16_t refreshTimeout = 0;
|
||||||
#define REFRESH_1S 12
|
#define REFRESH_1S OSD_TASK_FREQUENCY_HZ
|
||||||
|
|
||||||
static uint8_t armState;
|
static uint8_t armState;
|
||||||
|
|
||||||
|
@ -138,16 +138,22 @@ static void osdFormatDistanceStr(char* buff, int32_t dist)
|
||||||
|
|
||||||
switch (osdConfig()->units) {
|
switch (osdConfig()->units) {
|
||||||
case OSD_UNIT_IMPERIAL:
|
case OSD_UNIT_IMPERIAL:
|
||||||
if (dist < 0)
|
if (dist < 0) {
|
||||||
tfp_sprintf(buff, "-%d%c ", dist_abs / 100, SYM_FT);
|
tfp_sprintf(buff, "-%d%c ", dist_abs / 100, SYM_FT);
|
||||||
else
|
} else {
|
||||||
tfp_sprintf(buff, "%d%c ", dist_abs / 100, SYM_FT);
|
tfp_sprintf(buff, "%d%c ", dist_abs / 100, SYM_FT);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default: // Metric
|
default: // Metric
|
||||||
if (dist < 0)
|
if (dist < 0) {
|
||||||
tfp_sprintf(buff, "-%d.%01d%c ", dist_abs / 100, (dist_abs % 100) / 10, SYM_M);
|
tfp_sprintf(buff, "-%d.%01d%c ", dist_abs / 100, (dist_abs % 100) / 10, SYM_M);
|
||||||
else
|
} else {
|
||||||
|
if (dist < 10000) { // less than 100m
|
||||||
tfp_sprintf(buff, "%d.%01d%c ", dist_abs / 100, (dist_abs % 100) / 10, SYM_M);
|
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) {
|
switch (osdConfig()->units) {
|
||||||
case OSD_UNIT_IMPERIAL:
|
case OSD_UNIT_IMPERIAL:
|
||||||
tfp_sprintf(buff, "%d%c", osdConvertVelocityToUnit(vel), SYM_MPH);
|
tfp_sprintf(buff, "%2d%c", osdConvertVelocityToUnit(vel), SYM_MPH);
|
||||||
break;
|
break;
|
||||||
default: // Metric
|
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])) {
|
if (!VISIBLE(osdConfig()->item_pos[item]) || BLINK(osdConfig()->item_pos[item])) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t elemPosX = OSD_X(osdConfig()->item_pos[item]);
|
uint8_t elemPosX = OSD_X(osdConfig()->item_pos[item]);
|
||||||
|
@ -198,7 +204,7 @@ static void osdDrawSingleElement(uint8_t item)
|
||||||
osdRssi = 99;
|
osdRssi = 99;
|
||||||
|
|
||||||
buff[0] = SYM_RSSI;
|
buff[0] = SYM_RSSI;
|
||||||
tfp_sprintf(buff + 1, "%d", osdRssi);
|
tfp_sprintf(buff + 1, "%2d", osdRssi);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +231,7 @@ static void osdDrawSingleElement(uint8_t item)
|
||||||
case OSD_GPS_SATS:
|
case OSD_GPS_SATS:
|
||||||
buff[0] = 0x1e;
|
buff[0] = 0x1e;
|
||||||
buff[1] = 0x1f;
|
buff[1] = 0x1f;
|
||||||
tfp_sprintf(buff + 2, "%d", gpsSol.numSat);
|
tfp_sprintf(buff + 2, "%2d", gpsSol.numSat);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OSD_GPS_SPEED:
|
case OSD_GPS_SPEED:
|
||||||
|
@ -278,7 +284,7 @@ static void osdDrawSingleElement(uint8_t item)
|
||||||
if (h < 0) h+=360;
|
if (h < 0) h+=360;
|
||||||
|
|
||||||
buff[0] = 0xA9;
|
buff[0] = 0xA9;
|
||||||
tfp_sprintf(&buff[1], "%d%c", h , 0xA8 );
|
tfp_sprintf(&buff[1], "%3d%c", h , 0xA8 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif // GPS
|
#endif // GPS
|
||||||
|
@ -336,7 +342,7 @@ static void osdDrawSingleElement(uint8_t item)
|
||||||
p = "HOR ";
|
p = "HOR ";
|
||||||
|
|
||||||
max7456Write(elemPosX, elemPosY, p);
|
max7456Write(elemPosX, elemPosY, p);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OSD_CRAFT_NAME:
|
case OSD_CRAFT_NAME:
|
||||||
|
@ -354,12 +360,12 @@ static void osdDrawSingleElement(uint8_t item)
|
||||||
case OSD_THROTTLE_POS:
|
case OSD_THROTTLE_POS:
|
||||||
buff[0] = SYM_THR;
|
buff[0] = SYM_THR;
|
||||||
buff[1] = SYM_THR1;
|
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;
|
break;
|
||||||
|
|
||||||
#ifdef VTX
|
#ifdef VTX
|
||||||
case OSD_VTX_CHANNEL:
|
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;
|
break;
|
||||||
#endif // VTX
|
#endif // VTX
|
||||||
|
|
||||||
|
@ -400,6 +406,10 @@ static void osdDrawSingleElement(uint8_t item)
|
||||||
pitchAngle = (pitchAngle / 8) - 41; // 41 = 4 * 9 + 5
|
pitchAngle = (pitchAngle / 8) - 41; // 41 = 4 * 9 + 5
|
||||||
|
|
||||||
for (int x = -4; x <= 4; x++) {
|
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;
|
int y = (rollAngle * x) / 64;
|
||||||
y -= pitchAngle;
|
y -= pitchAngle;
|
||||||
// y += 41; // == 4 * 9 + 5
|
// y += 41; // == 4 * 9 + 5
|
||||||
|
@ -410,7 +420,7 @@ static void osdDrawSingleElement(uint8_t item)
|
||||||
|
|
||||||
osdDrawSingleElement(OSD_HORIZON_SIDEBARS);
|
osdDrawSingleElement(OSD_HORIZON_SIDEBARS);
|
||||||
|
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OSD_HORIZON_SIDEBARS:
|
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_LEFT);
|
||||||
max7456WriteChar(elemPosX + hudwidth - 1, elemPosY, SYM_AH_RIGHT);
|
max7456WriteChar(elemPosX + hudwidth - 1, elemPosY, SYM_AH_RIGHT);
|
||||||
|
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(BARO) || defined(GPS)
|
||||||
case OSD_VARIO:
|
case OSD_VARIO:
|
||||||
{
|
{
|
||||||
int16_t v = getEstimatedActualVelocity(Z) / 50; //50cm = 1 arrow
|
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+2, vchars[2]);
|
||||||
max7456WriteChar(elemPosX, elemPosY+3, vchars[3]);
|
max7456WriteChar(elemPosX, elemPosY+3, vchars[3]);
|
||||||
max7456WriteChar(elemPosX, elemPosY+4, vchars[4]);
|
max7456WriteChar(elemPosX, elemPosY+4, vchars[4]);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OSD_VARIO_NUM:
|
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);
|
tfp_sprintf(buff, "%c%d.%01d%c", value < 0 ? '-' : ' ', abs(value / 10), abs((value % 10)), 0x9F);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
case OSD_ROLL_PIDS:
|
case OSD_ROLL_PIDS:
|
||||||
{
|
{
|
||||||
|
@ -508,10 +520,49 @@ static void osdDrawSingleElement(uint8_t item)
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
max7456Write(elemPosX, elemPosY, buff);
|
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)
|
void osdDrawElements(void)
|
||||||
|
@ -577,6 +628,7 @@ void osdDrawElements(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
||||||
{
|
{
|
||||||
osdConfig->item_pos[OSD_ALTITUDE] = OSD_POS(1, 0) | VISIBLE_FLAG;
|
osdConfig->item_pos[OSD_ALTITUDE] = OSD_POS(1, 0) | VISIBLE_FLAG;
|
||||||
|
@ -816,7 +868,7 @@ static void osdArmMotors(void)
|
||||||
osdResetStats();
|
osdResetStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void osdRefresh(timeUs_t currentTimeUs)
|
static void osdRefreshStats(timeUs_t currentTimeUs)
|
||||||
{
|
{
|
||||||
static uint8_t lastSec = 0;
|
static uint8_t lastSec = 0;
|
||||||
uint8_t sec;
|
uint8_t sec;
|
||||||
|
@ -840,27 +892,7 @@ static void osdRefresh(timeUs_t currentTimeUs)
|
||||||
lastSec = sec;
|
lastSec = sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refreshTimeout) {
|
|
||||||
if (checkStickPosition(THR_HI) || checkStickPosition(PIT_HI)) // hide statistics
|
|
||||||
refreshTimeout = 1;
|
|
||||||
refreshTimeout--;
|
|
||||||
if (!refreshTimeout)
|
|
||||||
max7456ClearScreen();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
blinkState = (currentTimeUs / 200000) % 2;
|
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)
|
void osdUpdate(timeUs_t currentTimeUs)
|
||||||
{
|
{
|
||||||
static uint32_t counter = 0;
|
static uint8_t iterationCounter = 0;
|
||||||
|
|
||||||
#ifdef MAX7456_DMA_CHANNEL_TX
|
#ifdef MAX7456_DMA_CHANNEL_TX
|
||||||
// don't touch buffers if DMA transaction is in progress
|
// don't touch buffers if DMA transaction is in progress
|
||||||
if (max7456DmaInProgres())
|
if (max7456DmaInProgres()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
#endif // MAX7456_DMA_CHANNEL_TX
|
#endif // MAX7456_DMA_CHANNEL_TX
|
||||||
|
|
||||||
// redraw values in buffer
|
// refresh alarms every 20 iterations
|
||||||
if (counter++ % 5 == 0)
|
if (iterationCounter == 0) {
|
||||||
osdRefresh(currentTimeUs);
|
if (!displayIsGrabbed(osdDisplayPort)) {
|
||||||
else // rest of time redraw screen 10 chars per idle to don't lock the main idle
|
osdUpdateAlarms();
|
||||||
max7456DrawScreen();
|
}
|
||||||
|
}
|
||||||
|
// 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
|
#ifdef CMS
|
||||||
// do not allow ARM if we are in menu
|
// do not allow ARM if we are in menu
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "common/time.h"
|
#include "common/time.h"
|
||||||
#include "config/parameter_group.h"
|
#include "config/parameter_group.h"
|
||||||
|
|
||||||
|
#define OSD_TASK_FREQUENCY_HZ 100
|
||||||
|
|
||||||
#define VISIBLE_FLAG 0x0800
|
#define VISIBLE_FLAG 0x0800
|
||||||
#define BLINK_FLAG 0x0400
|
#define BLINK_FLAG 0x0400
|
||||||
#define VISIBLE(x) (x & VISIBLE_FLAG)
|
#define VISIBLE(x) (x & VISIBLE_FLAG)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue