From bb7fa975c4a25ffb57cce507dc5fef286806452e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Wed, 21 Jun 2023 09:25:27 +0200 Subject: [PATCH] improvements from testing with real display --- src/cgram.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/cgrom.c | 4 +- src/lcdbuf.c | 61 +++++++++++++++- src/lcdbuf.h | 15 +++- src/main.c | 10 +++ 5 files changed, 288 insertions(+), 4 deletions(-) diff --git a/src/cgram.c b/src/cgram.c index 9a14aea..b8e4831 100644 --- a/src/cgram.c +++ b/src/cgram.c @@ -372,6 +372,208 @@ const struct LcdBuf_CGRAM_Symbol CGRAM_CZ[] = { }, }, + // GUI symbols + + { + .symbol = "๐ŸŒข", // Humidity + .fallback = 'H', + .data = { + 0b00100, + 0b01110, + 0b01110, + 0b11111, + 0b10111, + 0b11111, + 0b01110, + }, + }, + + // Some useful glyphs for GUI with a keypad + + { + .symbol = "๐Ÿ…ฐ", + .fallback = 'A', + .data = { + 0b11111, + 0b11011, + 0b10101, + 0b10001, + 0b10101, + 0b10101, + 0b11111, + }, + }, + { + .symbol = "๐Ÿ…ฑ", + .fallback = 'B', + .data = { + 0b11111, + 0b10011, + 0b10101, + 0b10011, + 0b10101, + 0b10011, + 0b11111, + }, + }, + { + .symbol = "๐Ÿ…ฒ", + .fallback = 'C', + .data = { + 0b11111, + 0b11011, + 0b10101, + 0b10111, + 0b10101, + 0b11011, + 0b11111, + }, + }, + { + .symbol = "๐Ÿ…ณ", + .fallback = 'D', + .data = { + 0b11111, + 0b10011, + 0b10101, + 0b10101, + 0b10101, + 0b10011, + 0b11111, + }, + }, + { + .symbol = "โถ", + .fallback = '1', + .data = { + 0b11111, + 0b11011, + 0b10011, + 0b11011, + 0b11011, + 0b10001, + 0b11111, + }, + }, + { + .symbol = "โท", + .fallback = '2', + .data = { + 0b11111, + 0b11001, + 0b10101, + 0b11101, + 0b11011, + 0b10001, + 0b11111, + }, + }, + { + .symbol = "โธ", + .fallback = '3', + .data = { + 0b11111, + 0b10011, + 0b11101, + 0b10011, + 0b11101, + 0b10011, + 0b11111, + }, + }, + { + .symbol = "โน", + .fallback = '4', + .data = { + 0b11111, + 0b10101, + 0b10101, + 0b10001, + 0b11101, + 0b11101, + 0b11111, + }, + }, + { + .symbol = "โŠ›", + .fallback = '*', + .data = { + 0b11111, + 0b11011, + 0b01010, + 0b10001, + 0b01010, + 0b11011, + 0b11111, + }, + }, + { + .symbol = "ยค", + .fallback = '#', + .data = { + 0b11111, + 0b10101, + 0b00000, + 0b10101, + 0b00000, + 0b10101, + 0b11111, + }, + }, + { + .symbol = "โ–Œ", + .fallback = ' ', + .data = { + 0b11100, + 0b11100, + 0b11100, + 0b11100, + 0b11100, + 0b11100, + 0b11100, + 0b11100, + }, + }, + { + .symbol = "โ†‘", + .fallback = '^', + .data = { + 0b00100, + 0b01110, + 0b10101, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + }, + }, + { + .symbol = "โ†“", + .fallback = 'v', + .data = { + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b10101, + 0b01110, + 0b00100, + }, + }, + { + .symbol = "โœ”", + .fallback = 0xE8, + .data = { + 0b00000, + 0b00000, + 0b00001, + 0b10011, + 0b11110, + 0b01100, + 0b00000, + }, + }, + {}, /* end mark */ }; diff --git a/src/cgrom.c b/src/cgrom.c index 3874cd4..7ff0b4b 100644 --- a/src/cgrom.c +++ b/src/cgrom.c @@ -97,8 +97,8 @@ const struct LcdBuf_CGROM_Entry CGROM_A00[] = { {.address = 123, .symbol = "{"}, {.address = 124, .symbol = "|"}, {.address = 125, .symbol = "}"}, - {.address = 126, .symbol = "โ†"}, - {.address = 127, .symbol = "โ†’"}, + {.address = 126, .symbol = "โ†’"}, + {.address = 127, .symbol = "โ†"}, // lots of japanese symbols - add them yourself if you need them {.address = 0xA2, .symbol = "ใ€Œ"}, diff --git a/src/lcdbuf.c b/src/lcdbuf.c index 751f691..c4e11f0 100644 --- a/src/lcdbuf.c +++ b/src/lcdbuf.c @@ -15,6 +15,7 @@ void LcdBuffer_Init(struct LcdBuffer *self, const struct LcdBuf_CGROM_Entry *cgr assert(cgrom); assert(custom_symbols); + memset(self, 0, sizeof(struct LcdBuffer)); LcdBuffer_Clear(self); self->cgrom = cgrom; self->custom_symbols = custom_symbols; @@ -36,8 +37,37 @@ void LcdBuffer_Clear(struct LcdBuffer *self) /** Write what needs to be written to the HW, clear all dirty marks */ void LcdBuffer_Flush(struct LcdBuffer *self) { + bool any_flush = self->full_repaint_required || self->cursor_dirty; + uint8_t flush_cgram_mask = 0; + + // Check if any flushing is required for (int i = 0; i < LCDBUF_CGRAM_CAPACITY; i++) { if (self->cgram[i].refcount > 0 && self->cgram[i].dirty) { + any_flush = true; + flush_cgram_mask |= 1 << i; + } + } + + if (!any_flush) { + // check if we have dirty areas + for (int e = 0; e < LCDBUF_DIRTY_LIST_LEN; e++) { + struct LcdBuf_DirtyExtent *ext = &self->dirty_extents[e]; + if (ext->count) { + any_flush = true; + break; + } + } + } + + if (!any_flush) { + // really nothing to do + return; + } + + LcdBuffer_IO_SetCursorStyle(0); // hide cursor for the time of this function + + for (int i = 0; i < LCDBUF_CGRAM_CAPACITY; i++) { + if (flush_cgram_mask & (1 << i)) { LcdBuffer_IO_WriteCGRAM(i, self->custom_symbols[self->cgram[i].symbol_index].data); self->cgram[i].dirty = false; } @@ -57,7 +87,7 @@ void LcdBuffer_Flush(struct LcdBuffer *self) if (!any_nonspace) { LcdBuffer_IO_Clear(); - return; + goto done; } for (int r = 0; r < LINE_NUM; r++) { @@ -74,11 +104,21 @@ void LcdBuffer_Flush(struct LcdBuffer *self) ext->count = 0; // mark the slot as free } } + + done: + // Restore the visible cursor + if (self->cursor_style != 0) { + LcdBuffer_IO_SetCursorPos(self->cursor_row, self->cursor_col); + LcdBuffer_IO_SetCursorStyle(self->cursor_style); // hide cursor for the time of this function + } + self->cursor_dirty = false; } /** Fully write everything to the display */ void LcdBuffer_FlushAll(struct LcdBuffer *self) { + LcdBuffer_IO_SetCursorStyle(0); // hide cursor for the time of this function + for (int i = 0; i < LCDBUF_CGRAM_CAPACITY; i++) { if (self->cgram[i].refcount > 0) { LcdBuffer_IO_WriteCGRAM(i, self->custom_symbols[self->cgram[i].symbol_index].data); @@ -92,6 +132,14 @@ void LcdBuffer_FlushAll(struct LcdBuffer *self) memset(self->dirty_extents, 0, sizeof(self->dirty_extents)); self->full_repaint_required = false; + + // Restore the visible cursor + if (self->cursor_style != 0) { + LcdBuffer_IO_SetCursorPos(self->cursor_row, self->cursor_col); + LcdBuffer_IO_SetCursorStyle(self->cursor_style); // hide cursor for the time of this function + } + + self->cursor_dirty = false; } //static void show_dirty_slots(const struct LcdBuffer *self) { @@ -289,3 +337,14 @@ void LcdBuffer_Write(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, col++; } } + + +void LcdBuffer_SetCursor(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, uint8_t cursor_style) +{ + if ((self->cursor_style != cursor_style) || (self->cursor_row != row) || (self->cursor_col != col)) { + self->cursor_style = cursor_style; + self->cursor_row = row; + self->cursor_col = col; + self->cursor_dirty = true; + } +} diff --git a/src/lcdbuf.h b/src/lcdbuf.h index a24b689..239d9be 100644 --- a/src/lcdbuf.h +++ b/src/lcdbuf.h @@ -71,6 +71,12 @@ struct LcdBuffer { /** If the dirty extents array was not sufficient to hold all changes, this flag is set, * indicating the dirty_extents array should be disregarded. */ bool full_repaint_required; + + /* Visible cursor - is restored after flushing */ + uint8_t cursor_style; // two bits - blink 0b01, bar 0b10 + lcdbuf_pos_t cursor_row; + lcdbuf_pos_t cursor_col; + bool cursor_dirty; }; /** Initialize the struct */ @@ -91,6 +97,9 @@ void LcdBuffer_Set(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, s /** Write a UTF8 string at a position */ void LcdBuffer_Write(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, char *utf_string); +/** Set visible cursor position and style. style is 2 bits: blink 0b01, bar 0b10 */ +void LcdBuffer_SetCursor(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, uint8_t cursor_style); + /* Callbacks - need to be implemented by the application! */ /** Clear the entire screen (CGRAM can be left unchanged, but they will be written anew if needed) */ @@ -100,6 +109,10 @@ extern void LcdBuffer_IO_Clear(); extern void LcdBuffer_IO_WriteAt(lcdbuf_pos_t row, lcdbuf_pos_t col, const uint8_t *buf, lcdbuf_count_t len); /** Write CGRAM data. Data is always 8 bytes long. */ -extern void LcdBuffer_IO_WriteCGRAM(uint8_t position, const uint8_t* data); +extern void LcdBuffer_IO_WriteCGRAM(uint8_t position, const uint8_t *data); + +/** Set cursor pos & style */ +extern void LcdBuffer_IO_SetCursorPos(lcdbuf_pos_t cursor_row, lcdbuf_pos_t cursor_col); +extern void LcdBuffer_IO_SetCursorStyle(uint8_t cursor_style); #endif //HD44780UTF_LCDBUF_H diff --git a/src/main.c b/src/main.c index 24285a8..f8837e9 100644 --- a/src/main.c +++ b/src/main.c @@ -46,6 +46,16 @@ void LcdBuffer_IO_WriteAt(lcdbuf_pos_t row, lcdbuf_pos_t col, const uint8_t *buf printf("\"\n"); } +void LcdBuffer_IO_SetCursorPos(lcdbuf_pos_t cursor_row, lcdbuf_pos_t cursor_col) +{ + printf("CURS : %d,%d\n", cursor_row, cursor_col); +} + +void LcdBuffer_IO_SetCursorStyle(uint8_t cursor_style) +{ + printf("CURS: style 0x%02x\n", cursor_style); +} + #define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c" #define BYTE_TO_BINARY(byte) \ ((byte) & 0x80 ? '#' : '.'), \