Display: queue up display clear commands.

This commit is contained in:
Markus Hitter 2016-05-28 14:34:57 +02:00
parent da0d5aec2c
commit 5b9e123e0e
3 changed files with 80 additions and 67 deletions

View File

@ -41,6 +41,22 @@
#define DISPLAY_BUFFER_SIZE 128 #define DISPLAY_BUFFER_SIZE 128
/**
Printable ASCII characters and our embedded fonts start at 0x20, so we can
use 0x00..0x1F for storing control commands in the character queue. That's
what genuine ASCII does, too, we just use our own code set.
Queueing up actions together with actual characters not only postpones
these actions to idle time, it's also necessary to keep them in the right
order. Without it, writing a few characters, moving the cursor elsewhere and
writing even more characters would result in all characters being written to
the second position, because characters would wait in the queue while cursor
movements were executed immediately.
*/
enum display_low_code {
low_code_clear = 0x01,
low_code_set_cursor
};
void display_init(void); void display_init(void);
void display_tick(void); void display_tick(void);

View File

@ -7,19 +7,7 @@
/** /**
TODO list: TODO list:
- Procedures like display_clear() and display_set_cursor() should be queued - Implement display_set_cursor().
up, too. Just like characters. Fonts start at 0x20, so 0x00..0x1F are
available for command sequences. For example, setting the cursor could
queue up 0x04 0x01 0x20 (3 bytes) to set the cursor to line 1, column 32.
0x04 is the "command", bytes are queued up with display_writechar().
This is necessary to enforce characters and cursor commands to happen in
the right order. Currently, writing a few characters, moving the cursor
elsewhere and writing even more characters results in all characters
being written to the second position, because characters wait in the
queue, while cursor movements are executed immediately.
Code currently in display_set_cursor() would move to display_tick(), then.
*/ */
#include "display.h" #include "display.h"
@ -50,10 +38,10 @@ void display_init(void) {
} }
/** /**
Clear the screen. This display has a dedicated command for doing it. Queue up a clear screen command. Cheap operation on this display.
*/ */
void display_clear(void) { void display_clear(void) {
displaybus_write(0x01, parallel_4bit_instruction); display_writechar((uint8_t)low_code_clear);
} }
/** /**
@ -105,8 +93,8 @@ void display_clock(void) {
} }
/** /**
Forwards a character from the display queue to display bus. As this is a Forwards a character or a control command from the display queue to display
character based display it's easy. bus. As this is a character based display it's easy.
*/ */
void display_tick() { void display_tick() {
uint8_t data; uint8_t data;
@ -117,7 +105,16 @@ void display_tick() {
if (buf_canread(display)) { if (buf_canread(display)) {
buf_pop(display, data); buf_pop(display, data);
displaybus_write(data, parallel_4bit_data); switch (data) {
case low_code_clear:
displaybus_write(0x01, parallel_4bit_instruction);
break;
default:
// Should be a printable character.
displaybus_write(data, parallel_4bit_data);
break;
}
} }
} }

View File

@ -35,19 +35,7 @@
TODO list: TODO list:
- Procedures like display_clear() and display_set_cursor() should be queued - Move code in display_set_cursor() would to display_tick().
up, too. Just like characters. Fonts start at 0x20, so 0x00..0x1F are
available for command sequences. For example, setting the cursor could
queue up 0x04 0x01 0x20 (3 bytes) to set the cursor to line 1, column 32.
0x04 is the "command", bytes are queued up with display_writechar().
This is necessary to enforce characters and cursor commands to happen in
the right order. Currently, writing a few characters, moving the cursor
elsewhere and writing even more characters results in all characters
being written to the second position, because characters wait in the
queue, while cursor movements are executed immediately.
Code currently in display_set_cursor() would move to display_tick(), then.
- Lot's of prettification. Like a nice background picture with the Teacup - Lot's of prettification. Like a nice background picture with the Teacup
logo, like "Welcome to Teacup" as a greeting screen, like writing numbers logo, like "Welcome to Teacup" as a greeting screen, like writing numbers
@ -127,28 +115,11 @@ void display_init(void) {
} }
/** /**
Clear the screen. As this display supports many sophisticated commands, Queue up a clear screen command. Be careful, this is an expensive operation
but not a simple 'clear', we have to overwrite the entire memory with on this display.
zeros, byte by byte.
*/ */
void display_clear(void) { void display_clear(void) {
uint16_t i; display_writechar((uint8_t)low_code_clear);
// Set horizontal adressing mode.
displaybus_write(0x00, 0);
displaybus_write(0x20, 0);
displaybus_write(0x00, 1);
// Write 512 zeros.
displaybus_write(0x40, 0);
for (i = 0; i < 512; i++) {
displaybus_write(0x00, (i == 511));
}
// Return to page adressing mode.
displaybus_write(0x00, 0);
displaybus_write(0x20, 0);
displaybus_write(0x02, 1);
} }
/** /**
@ -212,10 +183,11 @@ void display_clock(void) {
} }
/** /**
Forwards a character from the display queue to the I2C queue. Forwards a character or a control command from the display queue to the I2C
queue.
*/ */
void display_tick() { void display_tick() {
uint8_t i, data, index; uint16_t i, data, index;
if (displaybus_busy()) { if (displaybus_busy()) {
return; return;
@ -232,22 +204,50 @@ void display_tick() {
if (buf_canread(display)) { if (buf_canread(display)) {
buf_pop(display, data); buf_pop(display, data);
index = data - 0x20; switch (data) {
case low_code_clear:
/**
Clear the screen. As this display supports many sophisticated
commands, but not a simple 'clear', we have to overwrite the entire
memory with zeros, byte by byte.
*/
// Set horizontal adressing mode.
displaybus_write(0x00, 0);
displaybus_write(0x20, 0);
displaybus_write(0x00, 1);
// Write pixels command. // Write 512 zeros.
displaybus_write(0x40, 0); displaybus_write(0x40, 0);
for (i = 0; i < 512; i++) {
displaybus_write(0x00, (i == 511));
}
// Send the character bitmap. // Return to page adressing mode.
#ifdef FONT_IS_PROPORTIONAL displaybus_write(0x00, 0);
for (i = 0; i < pgm_read_byte(&font[index].columns); i++) { displaybus_write(0x20, 0);
#else displaybus_write(0x02, 1);
for (i = 0; i < FONT_COLUMNS; i++) { break;
#endif
displaybus_write(pgm_read_byte(&font[index].data[i]), 0); default:
} // Should be a printable character.
// Send space between characters. index = data - 0x20;
for (i = 0; i < FONT_SYMBOL_SPACE; i++) {
displaybus_write(0x00, (i == FONT_SYMBOL_SPACE - 1)); // Write pixels command.
displaybus_write(0x40, 0);
// Send the character bitmap.
#ifdef FONT_IS_PROPORTIONAL
for (i = 0; i < pgm_read_byte(&font[index].columns); i++) {
#else
for (i = 0; i < FONT_COLUMNS; i++) {
#endif
displaybus_write(pgm_read_byte(&font[index].data[i]), 0);
}
// Send space between characters.
for (i = 0; i < FONT_SYMBOL_SPACE; i++) {
displaybus_write(0x00, (i == FONT_SYMBOL_SPACE - 1));
}
break;
} }
} }
} }