diff --git a/src/main/cms/cms.c b/src/main/cms/cms.c index 3b9f6791ff..388fd6b037 100644 --- a/src/main/cms/cms.c +++ b/src/main/cms/cms.c @@ -466,7 +466,7 @@ long cmsMenuChange(displayPort_t *pDisplay, const void *ptr) pageTop = currentMenu->entries; pageTopAlt = NULL; - displayClear(pDisplay); + displayClearScreen(pDisplay); cmsUpdateMaxRow(pDisplay); } @@ -481,7 +481,7 @@ STATIC_UNIT_TESTED long cmsMenuBack(displayPort_t *pDisplay) return -1; if (menuStackIdx) { - displayClear(pDisplay); + displayClearScreen(pDisplay); menuStackIdx--; currentMenu = menuStack[menuStackIdx]; cursorRow = menuStackHistory[menuStackIdx]; @@ -544,7 +544,7 @@ static void cmsTraverseGlobalExit(const CMS_Menu *pMenu) long cmsMenuExit(displayPort_t *pDisplay, const void *ptr) { if (ptr) { - displayClear(pDisplay); + displayClearScreen(pDisplay); displayWrite(pDisplay, 5, 3, "REBOOTING..."); displayResync(pDisplay); // Was max7456RefreshAll(); why at this timing? @@ -610,7 +610,7 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key) cursorRow++; } else { if (pageTopAlt) { // we have another page - displayClear(pDisplay); + displayClearScreen(pDisplay); p = pageTopAlt; pageTopAlt = pageTop; pageTop = (OSD_Entry *)p; @@ -628,7 +628,7 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key) if (cursorRow == -1 || (pageTop + cursorRow)->type == OME_Label) { if (pageTopAlt) { - displayClear(pDisplay); + displayClearScreen(pDisplay); p = pageTopAlt; pageTopAlt = pageTop; pageTop = (OSD_Entry *)p; diff --git a/src/main/cms/cms_menu_blackbox.c b/src/main/cms/cms_menu_blackbox.c index 7b65850bad..7ad339ccba 100644 --- a/src/main/cms/cms_menu_blackbox.c +++ b/src/main/cms/cms_menu_blackbox.c @@ -47,7 +47,7 @@ static long cmsx_EraseFlash(displayPort_t *pDisplay, const void *ptr) { UNUSED(ptr); - displayClear(pDisplay); + displayClearScreen(pDisplay); displayWrite(pDisplay, 5, 3, "ERASING FLASH..."); displayResync(pDisplay); // Was max7456RefreshAll(); Why at this timing? @@ -56,7 +56,7 @@ static long cmsx_EraseFlash(displayPort_t *pDisplay, const void *ptr) delay(100); } - displayClear(pDisplay); + displayClearScreen(pDisplay); displayResync(pDisplay); // Was max7456RefreshAll(); wedges during heavy SPI? return 0; diff --git a/src/main/drivers/display.c b/src/main/drivers/display.c index 6589a7e930..8d55c102ac 100644 --- a/src/main/drivers/display.c +++ b/src/main/drivers/display.c @@ -24,30 +24,46 @@ #include "display.h" -void displayClear(displayPort_t *instance) +void displayClearScreen(displayPort_t *instance) { - instance->vTable->clear(instance); + instance->vTable->clearScreen(instance); instance->cleared = true; instance->cursorRow = -1; } +void displayDrawScreen(displayPort_t *instance) +{ + instance->vTable->drawScreen(instance); +} + +int displayScreenSize(const displayPort_t *instance) +{ + return instance->vTable->screenSize(instance); +} + void displayGrab(displayPort_t *instance) { instance->vTable->grab(instance); - instance->vTable->clear(instance); - instance->isGrabbed = true; + instance->vTable->clearScreen(instance); + ++instance->grabCount; } void displayRelease(displayPort_t *instance) { instance->vTable->release(instance); - instance->isGrabbed = false; + --instance->grabCount; +} + +void displayReleaseAll(displayPort_t *instance) +{ + instance->vTable->release(instance); + instance->grabCount = 0; } bool displayIsGrabbed(const displayPort_t *instance) { // can be called before initialised - return (instance && instance->isGrabbed); + return (instance && instance->grabCount > 0); } int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, const char *s) @@ -55,6 +71,16 @@ int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, const char *s) return instance->vTable->write(instance, x, y, s); } +int displayWriteChar(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t c) +{ + return instance->vTable->writeChar(instance, x, y, c); +} + +bool displayIsTransferInProgress(const displayPort_t *instance) +{ + return instance->vTable->isTransferInProgress(instance); +} + void displayHeartbeat(displayPort_t *instance) { instance->vTable->heartbeat(instance); @@ -70,3 +96,12 @@ uint16_t displayTxBytesFree(const displayPort_t *instance) return instance->vTable->txBytesFree(instance); } +void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable) +{ + instance->vTable = vTable; + instance->vTable->clearScreen(instance); + instance->cleared = true; + instance->grabCount = 0; + instance->cursorRow = -1; +} + diff --git a/src/main/drivers/display.h b/src/main/drivers/display.h index 1605237736..038753da74 100644 --- a/src/main/drivers/display.h +++ b/src/main/drivers/display.h @@ -26,14 +26,18 @@ typedef struct displayPort_s { // CMS state bool cleared; int8_t cursorRow; - bool isGrabbed; + int8_t grabCount; } displayPort_t; typedef struct displayPortVTable_s { int (*grab)(displayPort_t *displayPort); int (*release)(displayPort_t *displayPort); - int (*clear)(displayPort_t *displayPort); + int (*clearScreen)(displayPort_t *displayPort); + int (*drawScreen)(displayPort_t *displayPort); + int (*screenSize)(const displayPort_t *displayPort); int (*write)(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *text); + int (*writeChar)(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c); + bool (*isTransferInProgress)(const displayPort_t *displayPort); int (*heartbeat)(displayPort_t *displayPort); void (*resync)(displayPort_t *displayPort); uint32_t (*txBytesFree)(const displayPort_t *displayPort); @@ -41,9 +45,15 @@ typedef struct displayPortVTable_s { void displayGrab(displayPort_t *instance); void displayRelease(displayPort_t *instance); +void displayReleaseAll(displayPort_t *instance); bool displayIsGrabbed(const displayPort_t *instance); -void displayClear(displayPort_t *instance); +void displayClearScreen(displayPort_t *instance); +void displayDrawScreen(displayPort_t *instance); +int displayScreenSize(const displayPort_t *instance); int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, const char *s); +int displayWriteChar(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t c); +bool displayIsTransferInProgress(const displayPort_t *instance); void displayHeartbeat(displayPort_t *instance); void displayResync(displayPort_t *instance); uint16_t displayTxBytesFree(const displayPort_t *instance); +void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable); diff --git a/src/main/drivers/max7456.c b/src/main/drivers/max7456.c index defc800e45..3e4d541d87 100755 --- a/src/main/drivers/max7456.c +++ b/src/main/drivers/max7456.c @@ -37,6 +37,122 @@ #include "max7456.h" #include "max7456_symbols.h" + + +//MAX7456 opcodes +#define DMM_REG 0x04 +#define DMAH_REG 0x05 +#define DMAL_REG 0x06 +#define DMDI_REG 0x07 +#define VM0_REG 0x00 +#define VM1_REG 0x01 + +// video mode register 0 bits +#define VIDEO_BUFFER_DISABLE 0x01 +#define MAX7456_RESET 0x02 +#define VERTICAL_SYNC_NEXT_VSYNC 0x04 +#define OSD_ENABLE 0x08 +#define SYNC_MODE_AUTO 0x00 +#define SYNC_MODE_INTERNAL 0x30 +#define SYNC_MODE_EXTERNAL 0x20 +#define VIDEO_MODE_PAL 0x40 +#define VIDEO_MODE_NTSC 0x00 + +// video mode register 1 bits + + +// duty cycle is on_off +#define BLINK_DUTY_CYCLE_50_50 0x00 +#define BLINK_DUTY_CYCLE_33_66 0x01 +#define BLINK_DUTY_CYCLE_25_75 0x02 +#define BLINK_DUTY_CYCLE_75_25 0x03 + +// blinking time +#define BLINK_TIME_0 0x00 +#define BLINK_TIME_1 0x04 +#define BLINK_TIME_2 0x08 +#define BLINK_TIME_3 0x0C + +// background mode brightness (percent) +#define BACKGROUND_BRIGHTNESS_0 0x00 +#define BACKGROUND_BRIGHTNESS_7 0x01 +#define BACKGROUND_BRIGHTNESS_14 0x02 +#define BACKGROUND_BRIGHTNESS_21 0x03 +#define BACKGROUND_BRIGHTNESS_28 0x04 +#define BACKGROUND_BRIGHTNESS_35 0x05 +#define BACKGROUND_BRIGHTNESS_42 0x06 +#define BACKGROUND_BRIGHTNESS_49 0x07 + +#define BACKGROUND_MODE_GRAY 0x40 + +//MAX7456 commands +#define CLEAR_DISPLAY 0x04 +#define CLEAR_DISPLAY_VERT 0x06 +#define END_STRING 0xff + + +#define MAX7456ADD_VM0 0x00 //0b0011100// 00 // 00 ,0011100 +#define MAX7456ADD_VM1 0x01 +#define MAX7456ADD_HOS 0x02 +#define MAX7456ADD_VOS 0x03 +#define MAX7456ADD_DMM 0x04 +#define MAX7456ADD_DMAH 0x05 +#define MAX7456ADD_DMAL 0x06 +#define MAX7456ADD_DMDI 0x07 +#define MAX7456ADD_CMM 0x08 +#define MAX7456ADD_CMAH 0x09 +#define MAX7456ADD_CMAL 0x0a +#define MAX7456ADD_CMDI 0x0b +#define MAX7456ADD_OSDM 0x0c +#define MAX7456ADD_RB0 0x10 +#define MAX7456ADD_RB1 0x11 +#define MAX7456ADD_RB2 0x12 +#define MAX7456ADD_RB3 0x13 +#define MAX7456ADD_RB4 0x14 +#define MAX7456ADD_RB5 0x15 +#define MAX7456ADD_RB6 0x16 +#define MAX7456ADD_RB7 0x17 +#define MAX7456ADD_RB8 0x18 +#define MAX7456ADD_RB9 0x19 +#define MAX7456ADD_RB10 0x1a +#define MAX7456ADD_RB11 0x1b +#define MAX7456ADD_RB12 0x1c +#define MAX7456ADD_RB13 0x1d +#define MAX7456ADD_RB14 0x1e +#define MAX7456ADD_RB15 0x1f +#define MAX7456ADD_OSDBL 0x6c +#define MAX7456ADD_STAT 0xA0 + +#define NVM_RAM_SIZE 54 +#define WRITE_NVR 0xA0 +#define STATUS_REG_NVR_BUSY 0x20 + +/** Line multiples, for convenience & one less op at runtime **/ +#define LINE 30 +#define LINE01 0 +#define LINE02 30 +#define LINE03 60 +#define LINE04 90 +#define LINE05 120 +#define LINE06 150 +#define LINE07 180 +#define LINE08 210 +#define LINE09 240 +#define LINE10 270 +#define LINE11 300 +#define LINE12 330 +#define LINE13 360 +#define LINE14 390 +#define LINE15 420 +#define LINE16 450 + + + + + + + + //on shared SPI buss we want to change clock for OSD chip and restore for other devices #ifdef MAX7456_SPI_CLK #define ENABLE_MAX7456 {spiSetDivisor(MAX7456_SPI_INSTANCE, MAX7456_SPI_CLK);IOLo(max7456CsPin);} @@ -262,7 +378,7 @@ void max7456ReInit(void) //here we init only CS and try to init MAX for first time -void max7456Init(vcdProfile_t *pVcdProfile) +void max7456Init(const vcdProfile_t *pVcdProfile) { #ifdef MAX7456_SPI_CS_PIN max7456CsPin = IOGetByTag(IO_TAG(MAX7456_SPI_CS_PIN)); diff --git a/src/main/drivers/max7456.h b/src/main/drivers/max7456.h index 03421c20a7..6c91f58ab8 100755 --- a/src/main/drivers/max7456.h +++ b/src/main/drivers/max7456.h @@ -26,114 +26,6 @@ #define BWBRIGHTNESS ((BLACKBRIGHTNESS << 2) | WHITEBRIGHTNESS) -//MAX7456 opcodes -#define DMM_REG 0x04 -#define DMAH_REG 0x05 -#define DMAL_REG 0x06 -#define DMDI_REG 0x07 -#define VM0_REG 0x00 -#define VM1_REG 0x01 - -// video mode register 0 bits -#define VIDEO_BUFFER_DISABLE 0x01 -#define MAX7456_RESET 0x02 -#define VERTICAL_SYNC_NEXT_VSYNC 0x04 -#define OSD_ENABLE 0x08 -#define SYNC_MODE_AUTO 0x00 -#define SYNC_MODE_INTERNAL 0x30 -#define SYNC_MODE_EXTERNAL 0x20 -#define VIDEO_MODE_PAL 0x40 -#define VIDEO_MODE_NTSC 0x00 - -// video mode register 1 bits - - -// duty cycle is on_off -#define BLINK_DUTY_CYCLE_50_50 0x00 -#define BLINK_DUTY_CYCLE_33_66 0x01 -#define BLINK_DUTY_CYCLE_25_75 0x02 -#define BLINK_DUTY_CYCLE_75_25 0x03 - -// blinking time -#define BLINK_TIME_0 0x00 -#define BLINK_TIME_1 0x04 -#define BLINK_TIME_2 0x08 -#define BLINK_TIME_3 0x0C - -// background mode brightness (percent) -#define BACKGROUND_BRIGHTNESS_0 0x00 -#define BACKGROUND_BRIGHTNESS_7 0x01 -#define BACKGROUND_BRIGHTNESS_14 0x02 -#define BACKGROUND_BRIGHTNESS_21 0x03 -#define BACKGROUND_BRIGHTNESS_28 0x04 -#define BACKGROUND_BRIGHTNESS_35 0x05 -#define BACKGROUND_BRIGHTNESS_42 0x06 -#define BACKGROUND_BRIGHTNESS_49 0x07 - -#define BACKGROUND_MODE_GRAY 0x40 - -//MAX7456 commands -#define CLEAR_DISPLAY 0x04 -#define CLEAR_DISPLAY_VERT 0x06 -#define END_STRING 0xff - - -#define MAX7456ADD_VM0 0x00 //0b0011100// 00 // 00 ,0011100 -#define MAX7456ADD_VM1 0x01 -#define MAX7456ADD_HOS 0x02 -#define MAX7456ADD_VOS 0x03 -#define MAX7456ADD_DMM 0x04 -#define MAX7456ADD_DMAH 0x05 -#define MAX7456ADD_DMAL 0x06 -#define MAX7456ADD_DMDI 0x07 -#define MAX7456ADD_CMM 0x08 -#define MAX7456ADD_CMAH 0x09 -#define MAX7456ADD_CMAL 0x0a -#define MAX7456ADD_CMDI 0x0b -#define MAX7456ADD_OSDM 0x0c -#define MAX7456ADD_RB0 0x10 -#define MAX7456ADD_RB1 0x11 -#define MAX7456ADD_RB2 0x12 -#define MAX7456ADD_RB3 0x13 -#define MAX7456ADD_RB4 0x14 -#define MAX7456ADD_RB5 0x15 -#define MAX7456ADD_RB6 0x16 -#define MAX7456ADD_RB7 0x17 -#define MAX7456ADD_RB8 0x18 -#define MAX7456ADD_RB9 0x19 -#define MAX7456ADD_RB10 0x1a -#define MAX7456ADD_RB11 0x1b -#define MAX7456ADD_RB12 0x1c -#define MAX7456ADD_RB13 0x1d -#define MAX7456ADD_RB14 0x1e -#define MAX7456ADD_RB15 0x1f -#define MAX7456ADD_OSDBL 0x6c -#define MAX7456ADD_STAT 0xA0 - -#define NVM_RAM_SIZE 54 -#define WRITE_NVR 0xA0 -#define STATUS_REG_NVR_BUSY 0x20 - -/** Line multiples, for convenience & one less op at runtime **/ -#define LINE 30 -#define LINE01 0 -#define LINE02 30 -#define LINE03 60 -#define LINE04 90 -#define LINE05 120 -#define LINE06 150 -#define LINE07 180 -#define LINE08 210 -#define LINE09 240 -#define LINE10 270 -#define LINE11 300 -#define LINE12 330 -#define LINE13 360 -#define LINE14 390 -#define LINE15 420 -#define LINE16 450 - - /** PAL or NTSC, value is number of chars total */ #define VIDEO_BUFFER_CHARS_NTSC 390 #define VIDEO_BUFFER_CHARS_PAL 480 @@ -142,7 +34,7 @@ extern uint16_t maxScreenSize; -void max7456Init(vcdProfile_t *vcdProfile); +void max7456Init(const vcdProfile_t *vcdProfile); void max7456DrawScreen(void); void max7456WriteNvm(uint8_t char_address, const uint8_t *font_data); uint8_t max7456GetRowsCount(void); diff --git a/src/main/drivers/max7456_symbols.h b/src/main/drivers/max7456_symbols.h index a5db8f22dd..086490c17e 100644 --- a/src/main/drivers/max7456_symbols.h +++ b/src/main/drivers/max7456_symbols.h @@ -21,8 +21,6 @@ #pragma once -#ifdef USE_MAX7456 - // Character Symbols #define SYM_BLANK 0x20 @@ -219,5 +217,3 @@ //sport #define SYM_MIN 0xB3 #define SYM_AVG 0xB4 - -#endif // USE_MAX7456 diff --git a/src/main/fc/fc_msp.c b/src/main/fc/fc_msp.c index ad266bc3d8..0d72aee77a 100755 --- a/src/main/fc/fc_msp.c +++ b/src/main/fc/fc_msp.c @@ -1035,7 +1035,11 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn #ifdef OSD sbufWriteU8(dst, 1); // OSD supported // send video system (AUTO/PAL/NTSC) +#ifdef USE_MAX7456 sbufWriteU8(dst, masterConfig.vcdProfile.video_system); +#else + sbufWriteU8(dst, 0); +#endif sbufWriteU8(dst, masterConfig.osdProfile.units); sbufWriteU8(dst, masterConfig.osdProfile.rssi_alarm); sbufWriteU16(dst, masterConfig.osdProfile.cap_alarm); @@ -1197,9 +1201,6 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src) #ifdef GPS uint8_t wp_no; int32_t lat = 0, lon = 0, alt = 0; -#endif -#ifdef OSD - uint8_t addr, font_data[64]; #endif switch (cmdMSP) { case MSP_SELECT_SETTING: @@ -1532,27 +1533,44 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src) #ifdef OSD case MSP_SET_OSD_CONFIG: - addr = sbufReadU8(src); - // set all the other settings - if ((int8_t)addr == -1) { - masterConfig.vcdProfile.video_system = sbufReadU8(src); - masterConfig.osdProfile.units = sbufReadU8(src); - masterConfig.osdProfile.rssi_alarm = sbufReadU8(src); - masterConfig.osdProfile.cap_alarm = sbufReadU16(src); - masterConfig.osdProfile.time_alarm = sbufReadU16(src); - masterConfig.osdProfile.alt_alarm = sbufReadU16(src); - } - // set a position setting - else { - masterConfig.osdProfile.item_pos[addr] = sbufReadU16(src); + { + const uint8_t addr = sbufReadU8(src); + // set all the other settings + if ((int8_t)addr == -1) { +#ifdef USE_MAX7456 + masterConfig.vcdProfile.video_system = sbufReadU8(src); +#else + sbufReadU8(src); // Skip video system +#endif + masterConfig.osdProfile.units = sbufReadU8(src); + masterConfig.osdProfile.rssi_alarm = sbufReadU8(src); + masterConfig.osdProfile.cap_alarm = sbufReadU16(src); + masterConfig.osdProfile.time_alarm = sbufReadU16(src); + masterConfig.osdProfile.alt_alarm = sbufReadU16(src); + } else { + // set a position setting + masterConfig.osdProfile.item_pos[addr] = sbufReadU16(src); + } } break; case MSP_OSD_CHAR_WRITE: - addr = sbufReadU8(src); - for (int i = 0; i < 54; i++) { - font_data[i] = sbufReadU8(src); +#ifdef USE_MAX7456 + { + uint8_t font_data[64]; + const uint8_t addr = sbufReadU8(src); + for (int i = 0; i < 54; i++) { + font_data[i] = sbufReadU8(src); + } + // !!TODO - replace this with a device independent implementation + max7456WriteNvm(addr, font_data); } - max7456WriteNvm(addr, font_data); +#else + // just discard the data + sbufReadU8(src); + for (int i = 0; i < 54; i++) { + sbufReadU8(src); + } +#endif break; #endif diff --git a/src/main/io/displayport_max7456.c b/src/main/io/displayport_max7456.c index 0bfbb4231c..a241136aca 100644 --- a/src/main/io/displayport_max7456.c +++ b/src/main/io/displayport_max7456.c @@ -37,7 +37,6 @@ static int grab(displayPort_t *displayPort) { UNUSED(displayPort); osdResetAlarms(); - displayPort->isGrabbed = true; refreshTimeout = 0; return 0; @@ -46,7 +45,6 @@ static int grab(displayPort_t *displayPort) static int release(displayPort_t *displayPort) { UNUSED(displayPort); - displayPort->isGrabbed = false; return 0; } @@ -59,6 +57,20 @@ static int clearScreen(displayPort_t *displayPort) return 0; } +static int drawScreen(displayPort_t *displayPort) +{ + UNUSED(displayPort); + max7456DrawScreen(); + + return 0; +} + +static int screenSize(const displayPort_t *displayPort) +{ + UNUSED(displayPort); + return maxScreenSize; +} + static int write(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s) { UNUSED(displayPort); @@ -67,6 +79,24 @@ static int write(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s return 0; } +static int writeChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c) +{ + UNUSED(displayPort); + max7456WriteChar(x, y, c); + + return 0; +} + +static bool isTransferInProgress(const displayPort_t *displayPort) +{ + UNUSED(displayPort); +#ifdef MAX7456_DMA_CHANNEL_TX + return max7456DmaInProgres(); +#else + return false; +#endif +} + static void resync(displayPort_t *displayPort) { UNUSED(displayPort); @@ -87,20 +117,24 @@ static uint32_t txBytesFree(const displayPort_t *displayPort) return UINT32_MAX; } -static displayPortVTable_t max7456VTable = { +static const displayPortVTable_t max7456VTable = { .grab = grab, .release = release, - .clear = clearScreen, + .clearScreen = clearScreen, + .drawScreen = drawScreen, + .screenSize = screenSize, .write = write, + .writeChar = writeChar, + .isTransferInProgress = isTransferInProgress, .heartbeat = heartbeat, .resync = resync, .txBytesFree = txBytesFree, }; -displayPort_t *max7456DisplayPortInit(void) +displayPort_t *max7456DisplayPortInit(const vcdProfile_t *vcdProfile) { - max7456DisplayPort.vTable = &max7456VTable; - max7456DisplayPort.isGrabbed = false; + displayInit(&max7456DisplayPort, &max7456VTable); + max7456Init(vcdProfile); resync(&max7456DisplayPort); return &max7456DisplayPort; } diff --git a/src/main/io/displayport_max7456.h b/src/main/io/displayport_max7456.h index bbb4aced35..2e8b6266b0 100644 --- a/src/main/io/displayport_max7456.h +++ b/src/main/io/displayport_max7456.h @@ -17,4 +17,5 @@ #pragma once -displayPort_t *max7456DisplayPortInit(void); +struct vcdProfile_s; +displayPort_t *max7456DisplayPortInit(const struct vcdProfile_s *vcdProfile); diff --git a/src/main/io/displayport_msp.c b/src/main/io/displayport_msp.c index ff16c04c8f..c80f9641e2 100644 --- a/src/main/io/displayport_msp.c +++ b/src/main/io/displayport_msp.c @@ -42,16 +42,17 @@ static int output(displayPort_t *displayPort, uint8_t cmd, const uint8_t *buf, i return mspSerialPush(cmd, buf, len); } -static int grab(displayPort_t *displayPort) +static int heartbeat(displayPort_t *displayPort) { const uint8_t subcmd[] = { 0 }; + // ensure display is not released by MW OSD software return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd)); } -static int heartbeat(displayPort_t *displayPort) +static int grab(displayPort_t *displayPort) { - return grab(displayPort); // ensure display is not released by MW OSD software + return heartbeat(displayPort); } static int release(displayPort_t *displayPort) @@ -61,13 +62,24 @@ static int release(displayPort_t *displayPort) return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd)); } -static int clear(displayPort_t *displayPort) +static int clearScreen(displayPort_t *displayPort) { const uint8_t subcmd[] = { 2 }; return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd)); } +static int drawScreen(displayPort_t *displayPort) +{ + UNUSED(displayPort); + return 0; +} + +static int screenSize(const displayPort_t *displayPort) +{ + return displayPort->rows * displayPort->cols; +} + static int write(displayPort_t *displayPort, uint8_t col, uint8_t row, const char *string) { #define MSP_OSD_MAX_STRING_LENGTH 30 @@ -87,6 +99,21 @@ static int write(displayPort_t *displayPort, uint8_t col, uint8_t row, const cha return output(displayPort, MSP_DISPLAYPORT, buf, len + 4); } +static int writeChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t c) +{ + char buf[2]; + + buf[0] = c; + buf[1] = 0; + return write(displayPort, col, row, buf); //!!TODO - check if there is a direct MSP command to do this +} + +static bool isTransferInProgress(const displayPort_t *displayPort) +{ + UNUSED(displayPort); + return false; +} + static void resync(displayPort_t *displayPort) { displayPort->rows = 13; // XXX Will reflect NTSC/PAL in the future @@ -102,8 +129,12 @@ static uint32_t txBytesFree(const displayPort_t *displayPort) static const displayPortVTable_t mspDisplayPortVTable = { .grab = grab, .release = release, - .clear = clear, + .clearScreen = clearScreen, + .drawScreen = drawScreen, + .screenSize = screenSize, .write = write, + .writeChar = writeChar, + .isTransferInProgress = isTransferInProgress, .heartbeat = heartbeat, .resync = resync, .txBytesFree = txBytesFree @@ -111,8 +142,7 @@ static const displayPortVTable_t mspDisplayPortVTable = { displayPort_t *displayPortMspInit(void) { - mspDisplayPort.vTable = &mspDisplayPortVTable; - mspDisplayPort.isGrabbed = false; + displayInit(&mspDisplayPort, &mspDisplayPortVTable); resync(&mspDisplayPort); return &mspDisplayPort; } diff --git a/src/main/io/displayport_oled.c b/src/main/io/displayport_oled.c index 8bb20329fc..fc60fed257 100644 --- a/src/main/io/displayport_oled.c +++ b/src/main/io/displayport_oled.c @@ -39,13 +39,24 @@ static int oledRelease(displayPort_t *displayPort) return 0; } -static int oledClear(displayPort_t *displayPort) +static int oledClearScreen(displayPort_t *displayPort) { UNUSED(displayPort); i2c_OLED_clear_display_quick(); return 0; } +static int oledDrawScreen(displayPort_t *displayPort) +{ + UNUSED(displayPort); + return 0; +} + +static int oledScreenSize(const displayPort_t *displayPort) +{ + return displayPort->rows * displayPort->cols; +} + static int oledWrite(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s) { UNUSED(displayPort); @@ -54,6 +65,20 @@ static int oledWrite(displayPort_t *displayPort, uint8_t x, uint8_t y, const cha return 0; } +static int oledWriteChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c) +{ + UNUSED(displayPort); + i2c_OLED_set_xy(x, y); + i2c_OLED_send_char(c); + return 0; +} + +static bool oledIsTransferInProgress(const displayPort_t *displayPort) +{ + UNUSED(displayPort); + return false; +} + static int oledHeartbeat(displayPort_t *displayPort) { UNUSED(displayPort); @@ -74,8 +99,12 @@ static uint32_t oledTxBytesFree(const displayPort_t *displayPort) static const displayPortVTable_t oledVTable = { .grab = oledGrab, .release = oledRelease, - .clear = oledClear, + .clearScreen = oledClearScreen, + .drawScreen = oledDrawScreen, + .screenSize = oledScreenSize, .write = oledWrite, + .writeChar = oledWriteChar, + .isTransferInProgress = oledIsTransferInProgress, .heartbeat = oledHeartbeat, .resync = oledResync, .txBytesFree = oledTxBytesFree @@ -83,9 +112,8 @@ static const displayPortVTable_t oledVTable = { displayPort_t *displayPortOledInit(void) { - oledDisplayPort.vTable = &oledVTable; + displayInit(&oledDisplayPort, &oledVTable); oledDisplayPort.rows = SCREEN_CHARACTER_ROW_COUNT; oledDisplayPort.cols = SCREEN_CHARACTER_COLUMN_COUNT; - oledDisplayPort.isGrabbed = false; return &oledDisplayPort; } diff --git a/src/main/io/osd.c b/src/main/io/osd.c index c8dd3d9b6f..342bb40474 100755 --- a/src/main/io/osd.c +++ b/src/main/io/osd.c @@ -31,10 +31,13 @@ #ifdef OSD +#include "build/debug.h" #include "build/version.h" +#include "common/printf.h" #include "common/utils.h" +#include "drivers/max7456_symbols.h" #include "drivers/display.h" #include "drivers/system.h" @@ -42,7 +45,6 @@ #include "cms/cms_types.h" #include "cms/cms_menu_osd.h" -#include "io/displayport_max7456.h" #include "io/flashfs.h" #include "io/osd.h" @@ -58,12 +60,7 @@ #include "hardware_revision.h" #endif -#include "drivers/max7456.h" -#include "drivers/max7456_symbols.h" - -#include "common/printf.h" - -#include "build/debug.h" +#define VIDEO_BUFFER_CHARS_PAL 480 // Character coordinate and attributes @@ -99,7 +96,7 @@ uint16_t refreshTimeout = 0; static uint8_t armState; -static displayPort_t *osd7456DisplayPort; +static displayPort_t *osdDisplayPort; #define AH_MAX_PITCH 200 // Specify maximum AHI pitch value displayed. Default 200 = 20.0 degrees @@ -227,7 +224,7 @@ static void osdDrawSingleElement(uint8_t item) else if (FLIGHT_MODE(HORIZON_MODE)) p = "HOR"; - max7456Write(elemPosX, elemPosY, p); + displayWrite(osdDisplayPort, elemPosX, elemPosY, p); return; } @@ -265,8 +262,9 @@ static void osdDrawSingleElement(uint8_t item) case OSD_CROSSHAIRS: elemPosX = 14 - 1; // Offset for 1 char to the left elemPosY = 6; - if (maxScreenSize == VIDEO_BUFFER_CHARS_PAL) + if (displayScreenSize(osdDisplayPort) == VIDEO_BUFFER_CHARS_PAL) { ++elemPosY; + } buff[0] = SYM_AH_CENTER_LINE; buff[1] = SYM_AH_CENTER; buff[2] = SYM_AH_CENTER_LINE_RIGHT; @@ -281,8 +279,9 @@ static void osdDrawSingleElement(uint8_t item) int rollAngle = attitude.values.roll; int pitchAngle = attitude.values.pitch; - if (maxScreenSize == VIDEO_BUFFER_CHARS_PAL) + if (displayScreenSize(osdDisplayPort) == VIDEO_BUFFER_CHARS_PAL) { ++elemPosY; + } if (pitchAngle > AH_MAX_PITCH) pitchAngle = AH_MAX_PITCH; @@ -301,7 +300,7 @@ static void osdDrawSingleElement(uint8_t item) y -= pitchAngle; // y += 41; // == 4 * 9 + 5 if (y >= 0 && y <= 81) { - max7456WriteChar(elemPosX + x, elemPosY + (y / 9), (SYM_AH_BAR9_0 + (y % 9))); + displayWriteChar(osdDisplayPort, elemPosX + x, elemPosY + (y / 9), (SYM_AH_BAR9_0 + (y % 9))); } } @@ -315,20 +314,21 @@ static void osdDrawSingleElement(uint8_t item) elemPosX = 14; elemPosY = 6; - if (maxScreenSize == VIDEO_BUFFER_CHARS_PAL) + if (displayScreenSize(osdDisplayPort) == VIDEO_BUFFER_CHARS_PAL) { ++elemPosY; + } // Draw AH sides int8_t hudwidth = AH_SIDEBAR_WIDTH_POS; int8_t hudheight = AH_SIDEBAR_HEIGHT_POS; for (int8_t y = -hudheight; y <= hudheight; y++) { - max7456WriteChar(elemPosX - hudwidth, elemPosY + y, SYM_AH_DECORATION); - max7456WriteChar(elemPosX + hudwidth, elemPosY + y, SYM_AH_DECORATION); + displayWriteChar(osdDisplayPort, elemPosX - hudwidth, elemPosY + y, SYM_AH_DECORATION); + displayWriteChar(osdDisplayPort, elemPosX + hudwidth, elemPosY + y, SYM_AH_DECORATION); } // AH level indicators - max7456WriteChar(elemPosX - hudwidth + 1, elemPosY, SYM_AH_LEFT); - max7456WriteChar(elemPosX + hudwidth - 1, elemPosY, SYM_AH_RIGHT); + displayWriteChar(osdDisplayPort, elemPosX - hudwidth + 1, elemPosY, SYM_AH_LEFT); + displayWriteChar(osdDisplayPort, elemPosX + hudwidth - 1, elemPosY, SYM_AH_RIGHT); return; } @@ -337,12 +337,12 @@ static void osdDrawSingleElement(uint8_t item) return; } - max7456Write(elemPosX, elemPosY, buff); + displayWrite(osdDisplayPort, elemPosX, elemPosY, buff); } void osdDrawElements(void) { - max7456ClearScreen(); + displayClearScreen(osdDisplayPort); #if 0 if (currentElement) @@ -352,7 +352,7 @@ void osdDrawElements(void) ; #endif #ifdef CMS - else if (sensors(SENSOR_ACC) || displayIsGrabbed(osd7456DisplayPort)) + else if (sensors(SENSOR_ACC) || displayIsGrabbed(osdDisplayPort)) #else else if (sensors(SENSOR_ACC)) #endif @@ -375,7 +375,7 @@ void osdDrawElements(void) #ifdef GPS #ifdef CMS - if (sensors(SENSOR_GPS) || displayIsGrabbed(osd7456DisplayPort)) + if (sensors(SENSOR_GPS) || displayIsGrabbed(osdDisplayPort)) #else if (sensors(SENSOR_GPS)) #endif @@ -410,44 +410,38 @@ void osdResetConfig(osd_profile_t *osdProfile) osdProfile->alt_alarm = 100; // meters or feet depend on configuration } -void osdInit(void) +void osdInit(displayPort_t *osdDisplayPortToUse) { - char x, string_buffer[30]; + osdDisplayPort = osdDisplayPortToUse; +#ifdef CMS + cmsDisplayPortRegister(osdDisplayPort); +#endif armState = ARMING_FLAG(ARMED); - // This will eventually go away when moving to a full displayPort - // oriented implementation, or replaced with hal. - - max7456Init(&masterConfig.vcdProfile); - - max7456ClearScreen(); + displayClearScreen(osdDisplayPort); // display logo and help - x = 160; + char x = 160; for (int i = 1; i < 5; i++) { for (int j = 3; j < 27; j++) { if (x != 255) - max7456WriteChar(j, i, x++); + displayWriteChar(osdDisplayPort, j, i, x++); } } + char string_buffer[30]; sprintf(string_buffer, "BF VERSION: %s", FC_VERSION_STRING); - max7456Write(5, 6, string_buffer); + displayWrite(osdDisplayPort, 5, 6, string_buffer); #ifdef CMS - max7456Write(7, 7, CMS_STARTUP_HELP_TEXT1); - max7456Write(11, 8, CMS_STARTUP_HELP_TEXT2); - max7456Write(11, 9, CMS_STARTUP_HELP_TEXT3); + displayWrite(osdDisplayPort, 7, 7, CMS_STARTUP_HELP_TEXT1); + displayWrite(osdDisplayPort, 11, 8, CMS_STARTUP_HELP_TEXT2); + displayWrite(osdDisplayPort, 11, 9, CMS_STARTUP_HELP_TEXT3); #endif - max7456RefreshAll(); + displayResync(osdDisplayPort); refreshTimeout = 4 * REFRESH_1S; - - osd7456DisplayPort = max7456DisplayPortInit(); -#ifdef CMS - cmsDisplayPortRegister(osd7456DisplayPort); -#endif } void osdUpdateAlarms(void) @@ -539,40 +533,40 @@ static void osdShowStats(void) uint8_t top = 2; char buff[10]; - max7456ClearScreen(); - max7456Write(2, top++, " --- STATS ---"); + displayClearScreen(osdDisplayPort); + displayWrite(osdDisplayPort, 2, top++, " --- STATS ---"); if (STATE(GPS_FIX)) { - max7456Write(2, top, "MAX SPEED :"); + displayWrite(osdDisplayPort, 2, top, "MAX SPEED :"); itoa(stats.max_speed, buff, 10); - max7456Write(22, top++, buff); + displayWrite(osdDisplayPort, 22, top++, buff); } - max7456Write(2, top, "MIN BATTERY :"); + displayWrite(osdDisplayPort, 2, top, "MIN BATTERY :"); sprintf(buff, "%d.%1dV", stats.min_voltage / 10, stats.min_voltage % 10); - max7456Write(22, top++, buff); + displayWrite(osdDisplayPort, 22, top++, buff); - max7456Write(2, top, "MIN RSSI :"); + displayWrite(osdDisplayPort, 2, top, "MIN RSSI :"); itoa(stats.min_rssi, buff, 10); strcat(buff, "%"); - max7456Write(22, top++, buff); + displayWrite(osdDisplayPort, 22, top++, buff); if (feature(FEATURE_CURRENT_METER)) { - max7456Write(2, top, "MAX CURRENT :"); + displayWrite(osdDisplayPort, 2, top, "MAX CURRENT :"); itoa(stats.max_current, buff, 10); strcat(buff, "A"); - max7456Write(22, top++, buff); + displayWrite(osdDisplayPort, 22, top++, buff); - max7456Write(2, top, "USED MAH :"); + displayWrite(osdDisplayPort, 2, top, "USED MAH :"); itoa(mAhDrawn, buff, 10); strcat(buff, "\x07"); - max7456Write(22, top++, buff); + displayWrite(osdDisplayPort, 22, top++, buff); } - max7456Write(2, top, "MAX ALTITUDE :"); + displayWrite(osdDisplayPort, 2, top, "MAX ALTITUDE :"); int32_t alt = osdGetAltitude(stats.max_altitude); sprintf(buff, "%c%d.%01d%c", alt < 0 ? '-' : ' ', abs(alt / 100), abs((alt % 100) / 10), osdGetAltitudeSymbol()); - max7456Write(22, top++, buff); + displayWrite(osdDisplayPort, 22, top++, buff); refreshTimeout = 60 * REFRESH_1S; } @@ -580,8 +574,8 @@ static void osdShowStats(void) // called when motors armed static void osdArmMotors(void) { - max7456ClearScreen(); - max7456Write(12, 7, "ARMED"); + displayClearScreen(osdDisplayPort); + displayWrite(osdDisplayPort, 12, 7, "ARMED"); refreshTimeout = REFRESH_1S / 2; osdResetStats(); } @@ -615,16 +609,17 @@ static void osdRefresh(uint32_t currentTime) refreshTimeout = 1; refreshTimeout--; if (!refreshTimeout) - max7456ClearScreen(); + displayClearScreen(osdDisplayPort); return; } blinkState = (currentTime / 200000) % 2; #ifdef CMS - if (!displayIsGrabbed(osd7456DisplayPort)) { + if (!displayIsGrabbed(osdDisplayPort)) { osdUpdateAlarms(); osdDrawElements(); + displayHeartbeat(osdDisplayPort); // heartbeat to stop Minim OSD going back into native mode #ifdef OSD_CALLS_CMS } else { cmsUpdate(currentTime); @@ -641,23 +636,28 @@ void osdUpdate(uint32_t currentTime) static uint32_t counter = 0; #ifdef MAX7456_DMA_CHANNEL_TX // don't touch buffers if DMA transaction is in progress - if (max7456DmaInProgres()) + if (displayIsTransferInProgress(osdDisplayPort)) { return; + } #endif // MAX7456_DMA_CHANNEL_TX // redraw values in buffer - if (counter++ % 5 == 0) +#ifdef USE_MAX7456 +#define DRAW_FREQ_DENOM 5 +#else +#define DRAW_FREQ_DENOM 10 // MWOSD @ 115200 baud +#endif + if (counter++ % DRAW_FREQ_DENOM == 0) { osdRefresh(currentTime); - else // rest of time redraw screen 10 chars per idle to don't lock the main idle - max7456DrawScreen(); + } else { // rest of time redraw screen 10 chars per idle so it doesn't lock the main idle + displayDrawScreen(osdDisplayPort); + } #ifdef CMS // do not allow ARM if we are in menu - if (displayIsGrabbed(osd7456DisplayPort)) { + if (displayIsGrabbed(osdDisplayPort)) { DISABLE_ARMING_FLAG(OK_TO_ARM); } #endif } - - #endif // OSD diff --git a/src/main/io/osd.h b/src/main/io/osd.h index c273f45c86..8bdc878bd8 100755 --- a/src/main/io/osd.h +++ b/src/main/io/osd.h @@ -60,7 +60,8 @@ typedef struct osd_profile_s { osd_unit_e units; } osd_profile_t; -void osdInit(void); +struct displayPort_s; +void osdInit(struct displayPort_s *osdDisplayPort); void osdResetConfig(osd_profile_t *osdProfile); void osdResetAlarms(void); void osdUpdate(uint32_t currentTime); diff --git a/src/main/main.c b/src/main/main.c index 5e7fe5bcca..f57575873e 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -75,6 +75,7 @@ #include "rx/spektrum.h" #include "io/beeper.h" +#include "io/displayport_max7456.h" #include "io/serial.h" #include "io/flashfs.h" #include "io/gps.h" @@ -406,7 +407,13 @@ void init(void) #ifdef OSD if (feature(FEATURE_OSD)) { - osdInit(); +#ifdef USE_MAX7456 + // if there is a max7456 chip for the OSD then use it, otherwise use MSP + displayPort_t *osdDisplayPort = max7456DisplayPortInit(&masterConfig.vcdProfile); +#else + displayPort_t *osdDisplayPort = displayPortMspInit(); +#endif + osdInit(osdDisplayPort); } #endif diff --git a/src/test/unit/cms_unittest.cc b/src/test/unit/cms_unittest.cc index a417e8b7ee..6c8e1c79b3 100644 --- a/src/test/unit/cms_unittest.cc +++ b/src/test/unit/cms_unittest.cc @@ -87,7 +87,7 @@ static uint32_t displayPortTestTxBytesFree(const displayPort_t *displayPort) static const displayPortVTable_t testDisplayPortVTable = { .grab = displayPortTestGrab, .release = displayPortTestRelease, - .clear = displayPortTestClear, + .clearScreen = displayPortTestClear, .write = displayPortTestWrite, .heartbeat = displayPortTestHeartbeat, .resync = displayPortTestResync, @@ -96,10 +96,9 @@ static const displayPortVTable_t testDisplayPortVTable = { displayPort_t *displayPortTestInit(void) { - testDisplayPort.vTable = &testDisplayPortVTable; + displayInit(&testDisplayPort, &testDisplayPortVTable); testDisplayPort.rows = 10; testDisplayPort.cols = 40; - testDisplayPort.isGrabbed = false; return &testDisplayPort; } @@ -204,4 +203,4 @@ void saveConfigAndNotify(void) {} void stopMotors(void) {} void stopPwmAllMotors(void) {} void systemReset(void) {} -} \ No newline at end of file +}