diff --git a/clock.c b/clock.c index f0ca122..ef0ef1b 100644 --- a/clock.c +++ b/clock.c @@ -127,17 +127,23 @@ static void clock_10ms(void) { } } -/*! do reoccuring stuff +/** + Do reoccuring stuff. Call it occasionally in busy loops. - call it occasionally in busy loops + Other than clock_tick() above, which is called at a constant interval, this + is called from the main loop. So it can be called very often on an idle + printer, but rather rarely on one running full speed. */ void clock() { ifclock(clock_flag_10ms) { clock_10ms(); } + + #ifdef DISPLAY + display_tick(); + #endif + #ifdef SIMULATOR sim_time_warp(); #endif } - - diff --git a/display.c b/display.c index 0cca508..b98b271 100644 --- a/display.c +++ b/display.c @@ -9,12 +9,47 @@ #include "display.h" +#ifdef DISPLAY + +// Ringbuffer logic for buffer 'display'. +#define BUFSIZE DISPLAY_BUFFER_SIZE + +volatile uint8_t displayhead = 0; +volatile uint8_t displaytail = 0; +volatile uint8_t displaybuf[BUFSIZE]; + +#include "ringbuffer.h" + + #define TEACUP_C_INCLUDE #include "display_ssd1306.c" #undef TEACUP_C_INCLUDE -#ifdef DISPLAY +#include "delay.h" + +/** + Prints a character at the current cursor position. + + \param data The character to be displayed. + + This code is identical for all display buses and display types, because it + just queues up the character. + + In case the buffer is full already it waits for a millisecond to allow + data to be sent to the display, then it tries again. If it still fails then, + it drops the character. This way we're fairly protected against data loss, + still we guarantee to not hang forever. +*/ +void display_writechar(uint8_t data) { + + if ( ! buf_canwrite(display)) { + delay_ms(1); + } + if (buf_canwrite(display)) { + buf_push(display, data); + } +} void display_writestr_P(PGM_P data_P) { uint8_t r, i = 0; diff --git a/display.h b/display.h index 0680b92..25b5951 100644 --- a/display.h +++ b/display.h @@ -32,7 +32,11 @@ #endif /* DISPLAY_BUS */ +#define DISPLAY_BUFFER_SIZE 128 + + void display_init(void); +void display_tick(void); void display_clear(void); void display_clock(void); diff --git a/display_ssd1306.c b/display_ssd1306.c index 3472ce3..3b4f62d 100644 --- a/display_ssd1306.c +++ b/display_ssd1306.c @@ -116,31 +116,34 @@ void display_clock(void) { } /** - Prints a character at the current cursor position. - - \param data The character to be displayed. + Forwards a character from the display queue to the I2C queue. */ -void display_writechar(uint8_t data) { - uint8_t i, index = data - 0x20; +void display_tick() { + uint8_t i, data, index; - // 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); + if (displaybus_busy()) { + return; } - // Send space between characters. - for (i = 0; i < FONT_SYMBOL_SPACE; i++) { - // TODO: we finalise a I2C (or other) bus message after each character - // here because we have no idea on how many more are following. This - // is highly inefficient and makes the displaybus buffer almost - // pointless. - displaybus_write(0x00, (i == FONT_SYMBOL_SPACE - 1)); + + if (buf_canread(display)) { + buf_pop(display, data); + index = data - 0x20; + + // 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)); + } } } diff --git a/i2c.h b/i2c.h index 8bb6960..f363cd1 100644 --- a/i2c.h +++ b/i2c.h @@ -65,11 +65,15 @@ Size of send buffer. MUST be a \f$2^n\f$ value, maximum is 512. - A larger buffer allows to store more display data immediately, so it can - speed operations up. An exhaused buffer doesn't mean data gets lost, writing - to the buffer then waits until sufficient previous data is sent. + This buffer can be rather small, because there is another queue on the + display level. Transmissions can be large, e.g. 514 bytes when clearing the + display, but typically it's only some 3 to 10 bytes ( = sending one + character). + + An exhausted buffer doesn't mean data loss, writing to the buffer then waits + until sufficient previous data is sent. */ -#define I2C_BUFFER_SIZE 128 +#define I2C_BUFFER_SIZE 16 #ifdef I2C_SLAVE_MODE #define I2C_SLAVE_RX_BUFFER_SIZE 1