BetaFlight模块设计之三十四:OSD模块分析

基于BetaFlight开源代码框架简介的框架设计,逐步分析内部模块功能设计。

1. OSD模块

描述:主要是将系统信息叠加到视频流上,以便更加便捷的通过眼镜了解飞控实时状态。

src/main/
 ├── /osd/
 │  ├── osd.c/h
 │  ├── osd_elements.c/h
 │  └── osd_warnings.c/h
 └── /driver/
    └── display.c/h

注:这里主要是VTX上的OSD,而OLED显示设备并非OSD叠加,而是DashBoard显示。

模块之间的依赖关系

1.1 osd状态机子模块

osd.c主要描述了状态机的整体情况,详见:BetaFlight模块设计之十六:OSD更新任务分析

1.2 osd_warnings检查子模块

\src\main\osd\osd_warnings.h

#define OSD_WARNINGS_MAX_SIZE 12
#define OSD_FORMAT_MESSAGE_BUFFER_SIZE (OSD_WARNINGS_MAX_SIZE + 1)

void renderOsdWarning(char *warningText, bool *blinking, uint8_t *displayAttr);

注:OSD检查子模块主要是在osdUpdate中被调用,定期调度执行:
osdUpdate–>osdDrawNextActiveElement–>osdDrawSingleElement–>osdElementDrawFunction[OSD_WARNINGS]–>osdElementWarnings–>renderOsdWarning

1.3 osd_elements子模块

主要用于衔接osd状态机与OSD适配设备的作用。

\src\main\osd\osd_elements.h

//使用适配层进行OSD显示
bool osdDrawNextActiveElement(displayPort_t *osdDisplayPort, timeUs_t currentTimeUs);
void osdDrawActiveElementsBackground(displayPort_t *osdDisplayPort);

//OSD Element参数格式化和状态管理函数
int osdConvertTemperatureToSelectedUnit(int tempInDegreesCelcius);
void osdFormatDistanceString(char *result, int distance, char leadingSymbol);
bool osdFormatRtcDateTime(char *buffer);
void osdFormatTime(char * buff, osd_timer_precision_e precision, timeUs_t time);
void osdFormatTimer(char *buff, bool showSymbol, bool usePrecision, int timerIndex);
float osdGetMetersToSelectedUnit(int32_t meters);
char osdGetMetersToSelectedUnitSymbol(void);
int32_t osdGetSpeedToSelectedUnit(int32_t value);
char osdGetSpeedToSelectedUnitSymbol(void);
char osdGetTemperatureSymbolForSelectedUnit(void);
void osdAddActiveElements(void);
uint8_t osdGetActiveElement();
uint8_t osdGetActiveElementCount();
void osdElementsInit(bool backgroundLayerFlag);
void osdSyncBlink();
void osdResetAlarms(void);
void osdUpdateAlarms(void);
bool osdElementsNeedAccelerometer(void);

2. OSD设备、驱动及适配框架

注:Kakute F7 AIO的板子用的是7456芯片

2.1 OSD设备

主要就是三种OSD设备,其中AUTO只是三种设备自动侦测。详见:void init(void)

\src\main\osd\osd.h
typedef enum {
    OSD_DISPLAYPORT_DEVICE_NONE = 0,
    OSD_DISPLAYPORT_DEVICE_AUTO,
    OSD_DISPLAYPORT_DEVICE_MAX7456,
    OSD_DISPLAYPORT_DEVICE_MSP,
    OSD_DISPLAYPORT_DEVICE_FRSKYOSD,
} osdDisplayPortDevice_e;

2.2 芯片驱动

这里以Kakute F7使用的7456芯片为例。

\src\main\io\displayport_max7456.c

static const displayPortVTable_t max7456VTable = {
    .grab = grab,
    .release = release,
    .clearScreen = clearScreen,
    .drawScreen = drawScreen,
    .screenSize = screenSize,
    .writeString = writeString,
    .writeChar = writeChar,
    .isTransferInProgress = isTransferInProgress,
    .heartbeat = heartbeat,
    .redraw = redraw,
    .isSynced = isSynced,
    .txBytesFree = txBytesFree,
    .layerSupported = layerSupported,
    .layerSelect = layerSelect,
    .layerCopy = layerCopy,
    .writeFontCharacter = writeFontCharacter,
    .checkReady = checkReady,
    .setBackgroundType = setBackgroundType,
};

bool max7456DisplayPortInit(const vcdProfile_t *vcdProfile, displayPort_t **displayPort)

2.3 适配层框架

该适配模型在max7456DisplayPortInit里面已经初始化:displayInit(&max7456DisplayPort, &max7456VTable, DISPLAYPORT_DEVICE_TYPE_MAX7456);

\src\main\drivers\display.h

typedef enum {
    DISPLAYPORT_ATTR_NONE = 0,
    DISPLAYPORT_ATTR_INFO,
    DISPLAYPORT_ATTR_WARNING,
    DISPLAYPORT_ATTR_CRITICAL,
} displayPortAttr_e;

typedef struct displayPortVTable_s {
    int (*grab)(displayPort_t *displayPort);
    int (*release)(displayPort_t *displayPort);
    int (*clearScreen)(displayPort_t *displayPort, displayClearOption_e options);
    bool (*drawScreen)(displayPort_t *displayPort);
    int (*screenSize)(const displayPort_t *displayPort);
    int (*writeString)(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, const char *text);
    int (*writeChar)(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, uint8_t c);
    bool (*isTransferInProgress)(const displayPort_t *displayPort);
    int (*heartbeat)(displayPort_t *displayPort);
    void (*redraw)(displayPort_t *displayPort);
    bool (*isSynced)(const displayPort_t *displayPort);
    uint32_t (*txBytesFree)(const displayPort_t *displayPort);
    bool (*layerSupported)(displayPort_t *displayPort, displayPortLayer_e layer);
    bool (*layerSelect)(displayPort_t *displayPort, displayPortLayer_e layer);
    bool (*layerCopy)(displayPort_t *displayPort, displayPortLayer_e destLayer, displayPortLayer_e sourceLayer);
    bool (*writeFontCharacter)(displayPort_t *instance, uint16_t addr, const struct osdCharacter_s *chr);
    bool (*checkReady)(displayPort_t *displayPort, bool rescan);
    void (*beginTransaction)(displayPort_t *displayPort, displayTransactionOption_e opts);
    void (*commitTransaction)(displayPort_t *displayPort);
    bool (*getCanvas)(struct displayCanvas_s *canvas, const displayPort_t *displayPort);
    void (*setBackgroundType)(displayPort_t *displayPort, displayPortBackground_e backgroundType);
} displayPortVTable_t;

void displayGrab(displayPort_t *instance);
void displayRelease(displayPort_t *instance);
void displayReleaseAll(displayPort_t *instance);
bool displayIsGrabbed(const displayPort_t *instance);
void displayClearScreen(displayPort_t *instance, displayClearOption_e options);
bool displayDrawScreen(displayPort_t *instance);
int displayScreenSize(const displayPort_t *instance);
void displaySetXY(displayPort_t *instance, uint8_t x, uint8_t y);
int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t attr, const char *s);
int displayWriteChar(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t attr, uint8_t c);
bool displayIsTransferInProgress(const displayPort_t *instance);
bool displayHeartbeat(displayPort_t *instance);
void displayRedraw(displayPort_t *instance);
bool displayIsSynced(const displayPort_t *instance);
uint16_t displayTxBytesFree(const displayPort_t *instance);
bool displayWriteFontCharacter(displayPort_t *instance, uint16_t addr, const struct osdCharacter_s *chr);
bool displayCheckReady(displayPort_t *instance, bool rescan);
void displayBeginTransaction(displayPort_t *instance, displayTransactionOption_e opts);
void displayCommitTransaction(displayPort_t *instance);
bool displayGetCanvas(struct displayCanvas_s *canvas, const displayPort_t *instance);
void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable, displayPortDeviceType_e deviceType);
bool displayLayerSupported(displayPort_t *instance, displayPortLayer_e layer);
bool displayLayerSelect(displayPort_t *instance, displayPortLayer_e layer);
bool displayLayerCopy(displayPort_t *instance, displayPortLayer_e destLayer, displayPortLayer_e sourceLayer);
void displaySetBackgroundType(displayPort_t *instance, displayPortBackground_e backgroundType);
bool displaySupportsOsdSymbols(displayPort_t *instance);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值