From 785cf293cde16b9f0d98f86985aace283f6134e2 Mon Sep 17 00:00:00 2001 From: Alexander Malishev Date: Thu, 12 Jul 2018 02:13:44 +0400 Subject: [PATCH] AP_OSD: use software blink This should fix blink issue with some hardware --- libraries/AP_OSD/AP_OSD.cpp | 4 +- libraries/AP_OSD/AP_OSD.h | 2 +- libraries/AP_OSD/AP_OSD_Backend.cpp | 8 +++- libraries/AP_OSD/AP_OSD_Backend.h | 23 ++++++++---- libraries/AP_OSD/AP_OSD_MAX7456.cpp | 57 ++++++++++++++++------------- libraries/AP_OSD/AP_OSD_MAX7456.h | 8 ++-- libraries/AP_OSD/AP_OSD_SITL.cpp | 13 +------ libraries/AP_OSD/AP_OSD_SITL.h | 3 +- libraries/AP_OSD/AP_OSD_Screen.cpp | 2 +- 9 files changed, 64 insertions(+), 56 deletions(-) diff --git a/libraries/AP_OSD/AP_OSD.cpp b/libraries/AP_OSD/AP_OSD.cpp index a3de2c4676..31410d8660 100644 --- a/libraries/AP_OSD/AP_OSD.cpp +++ b/libraries/AP_OSD/AP_OSD.cpp @@ -83,7 +83,7 @@ const AP_Param::GroupInfo AP_OSD::var_info[] = { // @User: Standard // @RebootRequired: True AP_GROUPINFO("_FONT", 9, AP_OSD, font_num, 0), - + // @Param: _V_OFFSET // @DisplayName: OSD vertical offset // @Description: Sets vertical offset of the osd inside image @@ -127,7 +127,7 @@ const AP_Param::GroupInfo AP_OSD::var_info[] = { // @Values: 0:Metric,1:Imperial,2:SI,3:Aviation // @User: Standard AP_GROUPINFO("_UNITS", 15, AP_OSD, units, 0), - + AP_GROUPEND }; diff --git a/libraries/AP_OSD/AP_OSD.h b/libraries/AP_OSD/AP_OSD.h index c3ccb0ac2e..e82e080e3b 100644 --- a/libraries/AP_OSD/AP_OSD.h +++ b/libraries/AP_OSD/AP_OSD.h @@ -114,7 +114,7 @@ private: TEMPERATURE=5, UNIT_TYPE_LAST=6, }; - + char u_icon(enum unit_type unit); float u_scale(enum unit_type unit, float value); diff --git a/libraries/AP_OSD/AP_OSD_Backend.cpp b/libraries/AP_OSD/AP_OSD_Backend.cpp index 89a8522e1a..208c7f4dcb 100644 --- a/libraries/AP_OSD/AP_OSD_Backend.cpp +++ b/libraries/AP_OSD/AP_OSD_Backend.cpp @@ -25,12 +25,16 @@ extern const AP_HAL::HAL& hal; void AP_OSD_Backend::write(uint8_t x, uint8_t y, bool blink, const char *fmt, ...) { + if (blink && (blink_phase < 2)) { + return; + } char buff[32]; va_list ap; va_start(ap, fmt); int res = hal.util->vsnprintf(buff, sizeof(buff), fmt, ap); - if (res > 0 && _osd.options.get() & AP_OSD::OPTION_DECIMAL_PACK) { + if (res > 0 && check_option(AP_OSD::OPTION_DECIMAL_PACK)) { // automatically use packed decimal characters + // based on fiam idea implemented in inav osd char *p = strchr(&buff[1],'.'); if (p && isdigit(p[1]) && isdigit(p[-1])) { p[-1] += SYM_DIG_OFS_1; @@ -40,7 +44,7 @@ void AP_OSD_Backend::write(uint8_t x, uint8_t y, bool blink, const char *fmt, .. } } if (res < int(sizeof(buff))) { - write(x, y, buff, blink? AP_OSD_Backend::BLINK : 0); + write(x, y, buff); } va_end(ap); } diff --git a/libraries/AP_OSD/AP_OSD_Backend.h b/libraries/AP_OSD/AP_OSD_Backend.h index 67f13b7a5e..ce212cc53d 100644 --- a/libraries/AP_OSD/AP_OSD_Backend.h +++ b/libraries/AP_OSD/AP_OSD_Backend.h @@ -30,7 +30,7 @@ public: virtual ~AP_OSD_Backend(void) {} //draw given text to framebuffer - virtual void write(uint8_t x, uint8_t y, const char* text, uint8_t char_attr = 0) = 0; + virtual void write(uint8_t x, uint8_t y, const char* text) = 0; //draw formatted text to framebuffer virtual void write(uint8_t x, uint8_t y, bool blink, const char *fmt, ...); @@ -42,11 +42,10 @@ public: virtual void flush() = 0; //clear screen - virtual void clear() = 0; - - enum character_attribute_t { - BLINK = (1 << 4), - INVERT = (1 << 3), + //should match hw blink + virtual void clear() + { + blink_phase = (blink_phase+1)%4; }; AP_OSD * get_osd() @@ -58,8 +57,18 @@ protected: AP_OSD& _osd; // get font choice - uint8_t get_font_num(void) const { return (uint8_t)_osd.font_num.get(); } + uint8_t get_font_num(void) const + { + return (uint8_t)_osd.font_num.get(); + } + //check option + bool check_option(uint32_t option) + { + return (_osd.options & option) != 0; + } + + int8_t blink_phase; }; diff --git a/libraries/AP_OSD/AP_OSD_MAX7456.cpp b/libraries/AP_OSD/AP_OSD_MAX7456.cpp index 58741bb787..28c7e2c77b 100644 --- a/libraries/AP_OSD/AP_OSD_MAX7456.cpp +++ b/libraries/AP_OSD/AP_OSD_MAX7456.cpp @@ -347,7 +347,6 @@ void AP_OSD_MAX7456::reinit() // force redrawing all screen memset(shadow_frame, 0xFF, sizeof(shadow_frame)); - memset(shadow_attr, 0xFF, sizeof(shadow_attr)); initialized = true; } @@ -357,7 +356,7 @@ void AP_OSD_MAX7456::flush() if (last_font != get_font_num()) { update_font(); } - + // check for offset changes if (last_v_offset != _osd.v_offset) { int8_t vos = constrain_int16(_osd.v_offset, 0, 31); @@ -373,15 +372,15 @@ void AP_OSD_MAX7456::flush() _dev->get_semaphore()->give(); last_h_offset = _osd.h_offset; } - + check_reinit(); transfer_frame(); } void AP_OSD_MAX7456::transfer_frame() { - uint8_t last_attribute = 0xFF; uint16_t previous_pos = UINT16_MAX - 1; + bool autoincrement = false; if (!initialized) { return; } @@ -389,8 +388,7 @@ void AP_OSD_MAX7456::transfer_frame() buffer_offset = 0; for (uint8_t y=0; y> 8); buffer_add_cmd(MAX7456ADD_DMAL, pos & 0xFF); } - //update character attributes and (re)enter autoincrement mode - if (position_changed || attribute_changed) { - buffer_add_cmd(MAX7456ADD_DMM, attribute | DMM_AUTOINCREMENT); - last_attribute = attribute; + if (!autoincrement && is_dirty(x+1, y)) { + //(re)enter autoincrement mode + buffer_add_cmd(MAX7456ADD_DMM, DMM_AUTOINCREMENT); + autoincrement = true; } buffer_add_cmd(MAX7456ADD_DMDI, chr); previous_pos = pos; } } - - if (buffer_offset > 0) { + if (autoincrement) { buffer_add_cmd(MAX7456ADD_DMDI, 0xFF); buffer_add_cmd(MAX7456ADD_DMM, 0); + autoincrement = false; + } + + if (buffer_offset > 0) { _dev->get_semaphore()->take_blocking(); _dev->transfer(buffer, buffer_offset, nullptr, 0); _dev->get_semaphore()->give(); } } -void AP_OSD_MAX7456::clear() +bool AP_OSD_MAX7456::is_dirty(uint8_t x, uint8_t y) { - memset(frame, ' ', sizeof(frame)); - memset(attr, 0, sizeof(attr)); + if (y>=video_lines || x>=video_columns) { + return false; + } + return frame[y][x] != shadow_frame[y][x]; } -void AP_OSD_MAX7456::write(uint8_t x, uint8_t y, const char* text, uint8_t char_attr) +void AP_OSD_MAX7456::clear() +{ + AP_OSD_Backend::clear(); + memset(frame, ' ', sizeof(frame)); +} + +void AP_OSD_MAX7456::write(uint8_t x, uint8_t y, const char* text) { if (y >= video_lines_pal || text == nullptr) { return; } while ((x < VIDEO_COLUMNS) && (*text != 0)) { frame[y][x] = *text; - attr[y][x] = char_attr; ++text; ++x; } diff --git a/libraries/AP_OSD/AP_OSD_MAX7456.h b/libraries/AP_OSD/AP_OSD_MAX7456.h index ed5bb42a4b..921c40b5dd 100644 --- a/libraries/AP_OSD/AP_OSD_MAX7456.h +++ b/libraries/AP_OSD/AP_OSD_MAX7456.h @@ -25,7 +25,7 @@ public: static AP_OSD_Backend *probe(AP_OSD &osd, AP_HAL::OwnPtr dev); //draw given text to framebuffer - void write(uint8_t x, uint8_t y, const char* text, uint8_t char_attr) override; + void write(uint8_t x, uint8_t y, const char* text) override; //initilize display port and underlying hardware bool init() override; @@ -55,6 +55,8 @@ private: void transfer_frame(); + bool is_dirty(uint8_t x, uint8_t y); + AP_HAL::OwnPtr _dev; uint8_t video_signal_reg; @@ -74,10 +76,6 @@ private: //used to optimize number of characters updated uint8_t shadow_frame[video_lines_pal][video_columns]; - // this assumes at most 32 columns - uint8_t attr[video_lines_pal][video_columns]; - uint8_t shadow_attr[video_lines_pal][video_columns]; - uint8_t buffer[spi_buffer_size]; int buffer_offset; diff --git a/libraries/AP_OSD/AP_OSD_SITL.cpp b/libraries/AP_OSD/AP_OSD_SITL.cpp index 6c6f6bf9d2..eac2a34067 100644 --- a/libraries/AP_OSD/AP_OSD_SITL.cpp +++ b/libraries/AP_OSD/AP_OSD_SITL.cpp @@ -98,7 +98,7 @@ void AP_OSD_SITL::load_font(void) free(font_data); } -void AP_OSD_SITL::write(uint8_t x, uint8_t y, const char* text, uint8_t char_attr) +void AP_OSD_SITL::write(uint8_t x, uint8_t y, const char* text) { if (y >= video_lines || text == nullptr) { return; @@ -106,7 +106,6 @@ void AP_OSD_SITL::write(uint8_t x, uint8_t y, const char* text, uint8_t char_att mutex->take_blocking(); while ((x < video_cols) && (*text != 0)) { buffer[y][x] = *text; - attr[y][x] = char_attr; ++text; ++x; } @@ -115,6 +114,7 @@ void AP_OSD_SITL::write(uint8_t x, uint8_t y, const char* text, uint8_t char_att void AP_OSD_SITL::clear(void) { + AP_OSD_Backend::clear(); mutex->take_blocking(); memset(buffer, 0, sizeof(buffer)); mutex->give(); @@ -136,7 +136,6 @@ void AP_OSD_SITL::update_thread(void) AP_HAL::panic("Unable to create OSD window"); } - uint8_t blink = 0; while (w->isOpen()) { sf::Event event; while (w->pollEvent(event)) { @@ -151,10 +150,8 @@ void AP_OSD_SITL::update_thread(void) last_counter = counter; uint8_t buffer2[video_lines][video_cols]; - uint8_t attr2[video_lines][video_cols]; mutex->take_blocking(); memcpy(buffer2, buffer, sizeof(buffer2)); - memcpy(attr2, attr, sizeof(attr2)); mutex->give(); w->clear(); @@ -164,11 +161,6 @@ void AP_OSD_SITL::update_thread(void) uint16_t py = y * (char_height+char_spacing) * char_scale; sf::Sprite s; uint8_t c = buffer2[y][x]; - if (attr2[y][x] & BLINK) { - if (blink >= 2) { - c = ' '; - } - } s.setTexture(font[c]); s.setPosition(sf::Vector2f(px, py)); s.scale(sf::Vector2f(char_scale,char_scale)); @@ -176,7 +168,6 @@ void AP_OSD_SITL::update_thread(void) } } - blink = (blink+1) % 4; w->display(); if (last_font != get_font_num()) { load_font(); diff --git a/libraries/AP_OSD/AP_OSD_SITL.h b/libraries/AP_OSD/AP_OSD_SITL.h index 01227b6f0d..c15b038331 100644 --- a/libraries/AP_OSD/AP_OSD_SITL.h +++ b/libraries/AP_OSD/AP_OSD_SITL.h @@ -31,7 +31,7 @@ public: static AP_OSD_Backend *probe(AP_OSD &osd); //draw given text to framebuffer - void write(uint8_t x, uint8_t y, const char* text, uint8_t char_attr) override; + void write(uint8_t x, uint8_t y, const char* text) override; //initilize display port and underlying hardware bool init() override; @@ -62,7 +62,6 @@ private: static const uint8_t char_scale = 2; uint8_t buffer[video_lines][video_cols]; - uint8_t attr[video_lines][video_cols]; void update_thread(); static void *update_thread_start(void *obj); diff --git a/libraries/AP_OSD/AP_OSD_Screen.cpp b/libraries/AP_OSD/AP_OSD_Screen.cpp index 2d8b735c7a..ce4e563ee0 100644 --- a/libraries/AP_OSD/AP_OSD_Screen.cpp +++ b/libraries/AP_OSD/AP_OSD_Screen.cpp @@ -144,7 +144,7 @@ const AP_Param::GroupInfo AP_OSD_Screen::var_info[] = { // @Group: GPSLONG // @Path: AP_OSD_Setting.cpp AP_SUBGROUPINFO(gps_longitude, "GPSLONG", 25, AP_OSD_Screen, AP_OSD_Setting), - + // @Group: ROLL // @Path: AP_OSD_Setting.cpp AP_SUBGROUPINFO(roll_angle, "ROLL", 26, AP_OSD_Screen, AP_OSD_Setting),