diff --git a/display_ssd1306.c b/display_ssd1306.c new file mode 100644 index 0000000..8f432cb --- /dev/null +++ b/display_ssd1306.c @@ -0,0 +1,114 @@ + +/** \file + + \brief Code specific to the SSD1306 display. +*/ + +#include "display_ssd1306.h" + +#ifdef DISPLAY_TYPE_SSD1306 + +#include "displaybus.h" +#include "font.h" + + +static const uint8_t PROGMEM init_sequence[] = { + 0x00, // Command marker. + 0xAE, // Display off. + 0xD5, 0x80, // Display clock divider (reset). + 0xA8, 0x1F, // 1/32 duty. + 0x40 | 0x00, // Start line (reset). + 0x20, 0x02, // Page addressing mode (reset). + 0x22, 0x00, 0x03, // Start and end page in horiz./vert. addressing mode[1]. + 0x21, 0x00, 0x7F, // Start and end column in horiz./vert. addressing mode. + 0xA0 | 0x00, // No segment remap (reset). + 0xC0 | 0x00, // Normal com pins mapping (reset). + 0xDA, 0x02, // Sequental without remap com pins. + 0x81, 0x7F, // Contrast (reset). + 0xDB, 0x20, // Vcomh (reset). + 0xD9, 0xF1, // Precharge period. + 0x8D, 0x14, // Charge pump. + 0xA6, // Positive display. + 0xA4, // Resume display. + 0xAF // Display on. +}; +// [1] Do not set this to 0x00..0x07 on a 32 pixel high display, or vertical +// addressing mode will mess up. 32 pixel high displays have only 4 pages +// (0..3), still addressing logic accepts, but can't deal with the 0..7 +// meant for 64 pixel high displays. + +/** + * Initializes the display's controller configuring the way of + * displaying data. + */ +void display_init(void) { + uint8_t i; + + displaybus_init(DISPLAY_I2C_ADDRESS); + + for (i = 0; i < sizeof(init_sequence); i++) { + // Send last byte with 'last_byte' set. + displaybus_write(init_sequence[i], (i == sizeof(init_sequence) - 1)); + } +} + +/** + 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. +*/ +void display_clear(void) { + uint16_t i; + + // 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); +} + +/** + Prints the text at a given position. +*/ +void display_text_P(uint8_t line, uint8_t column, PGM_P message) { + uint8_t i; + + // Enter command mode. + displaybus_write(0x00, 0); + // Set line. + displaybus_write(0xB0 | (line & 0x03), 0); + // Set column. + displaybus_write(0x00 | (column & 0x0F), 0); + displaybus_write(0x10 | ((column >> 4) & 0x0F), 1); + + // Render text to bitmap to display. + displaybus_write(0x40, 0); + while (pgm_read_byte(message)) { + uint8_t index = pgm_read_byte(message) - 0x20; + + // Send the character bitmap. + for (i = 0; i < pgm_read_byte(&font[index].columns); i++) { + 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, 0); + } + + message++; + } + // Send another space for transmission end. + displaybus_write(0x00, 1); +} + +#endif /* DISPLAY_TYPE_SSD1306 */ diff --git a/display_ssd1306.h b/display_ssd1306.h new file mode 100644 index 0000000..26368e6 --- /dev/null +++ b/display_ssd1306.h @@ -0,0 +1,56 @@ + +#ifndef _DISPLAY_SSD1306_H +#define _DISPLAY_SSD1306_H + +#include "config_wrapper.h" + + +#ifdef DISPLAY_TYPE_SSD1306 + +#define DISPLAY +#define DISPLAY_I2C_ADDRESS (0x3C << 1) + + +#define DISPLAY_LINES 4 +#define DISPLAY_SYMBOLS_PER_LINE 16 +#define HOTENDS_COUNT 1 +#define HOTBED_ZONES 1 + +#define DISPLAY_PLACE_HOTEND 0, 0, 8 +#define DISPLAY_PLACE_HOTBED 0, 8, 8 +#define DISPLAY_PLACE_X 1, 0, 5 +#define DISPLAY_PLACE_Y 1, 5, 5 +#define DISPLAY_PLACE_Z 1, 10, 5 +#define DISPLAY_PLACE_FEEDRATE 2, 0, 5 +#define DISPLAY_PLACE_PROGRESS 2, 5, 5 +#define DISPLAY_PLACE_TIMER 2, 10, 6 +#define DISPLAY_PLACE_STATUS 3, 0, 16 + +typedef struct { + uint16_t hotend_temp[HOTENDS_COUNT]; + uint16_t hotbed_temp[HOTBED_ZONES]; + uint16_t x; + uint16_t y; + uint16_t z; + uint16_t feedrate; + uint8_t progress; // in percents + uint32_t timer; // in seconds +} DISPLAY_T; + + +void display_init(void); +void display_on(void); +void display_hotend(uint8_t index); +void display_hotbed(uint8_t index); +void display_point(uint16_t x, uint16_t y, uint16_t z); +void display_feedrate(uint16_t value); +void display_progress(uint8_t value); +void display_timer(uint32_t value); +void display_off(void); + +void display_clear(void); +void display_text_P(uint8_t line, uint8_t column, PGM_P message_P); + +#endif /* DISPLAY_TYPE_SSD1306 */ + +#endif /* _DISPLAY_SSD1306_H */ diff --git a/i2c_test.c b/i2c_test.c index 764f195..fa95ab6 100644 --- a/i2c_test.c +++ b/i2c_test.c @@ -15,99 +15,16 @@ #include #include "config_wrapper.h" -#include "displaybus.h" +#include "display_ssd1306.h" #include "font.h" -#define DISPLAY_I2C_ADDRESS (0x3C << 1) - -const uint8_t PROGMEM display_init[] = { - 0x00, // Command marker. - 0xAE, // Display off. - 0xD5, 0x80, // Display clock divider (reset). - 0xA8, 0x1F, // 1/32 duty. - 0x40 | 0x00, // Start line (reset). - 0x20, 0x02, // Page addressing mode (reset). - 0x22, 0x00, 0x03, // Start and end page in horiz./vert. addressing mode[1]. - 0x21, 0x00, 0x7F, // Start and end column in horiz./vert. addressing mode. - 0xA0 | 0x00, // No segment remap (reset). - 0xC0 | 0x00, // Normal com pins mapping (reset). - 0xDA, 0x02, // Sequental without remap com pins. - 0x81, 0x7F, // Contrast (reset). - 0xDB, 0x20, // Vcomh (reset). - 0xD9, 0xF1, // Precharge period. - 0x8D, 0x14, // Charge pump. - 0xA6, // Positive display. - 0xA4, // Resume display. - 0xAF // Display on. -}; -// [1] Do not set this to 0x00..0x07 on a 32 pixel high display, or vertical -// addressing mode will mess up. 32 pixel high displays have only 4 pages -// (0..3), still addressing logic accepts, but can't deal with the 0..7 -// meant for 64 pixel high displays. - static void i2c_test(void) { - uint16_t i; - const char* message = "Welcome to Teacup"; - - for (i = 0; i < sizeof(display_init); i++) { - // Send last byte with 'last_byte' set. - displaybus_write(pgm_read_byte(&display_init[i]), - (i == sizeof(display_init) - 1)); - } - /** - 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 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); - - /** - Setup cursor on display. - "Welcome to Teacup" is 64 pixel columns wide, entire display is 128 columns, so we offset by 32 columns to get it to the center. */ - displaybus_write(0x00, 0); - // Line 1. - displaybus_write(0xB0 | 1, 0); - // Column 32. - displaybus_write(0x00 | (32 & 0x0F), 0); - displaybus_write(0x10 | ((32 >> 4) & 0x0F), 1); - - // Render text to bitmap to display. - displaybus_write(0x40, 0); - while (*message) { - uint8_t index = (uint8_t)*message - 0x20; - - // Send the character bitmap. - for (i = 0; i < pgm_read_byte(&font[index].columns); i++) { - 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, 0); - } - - message++; - } - // Send another space for transmission end. - displaybus_write(0x00, 1); + display_text_P(1, 32, PSTR("Welcome to Teacup")); } #endif /* I2C_TEST */ diff --git a/mendel.c b/mendel.c index ff73a13..26ccbce 100644 --- a/mendel.c +++ b/mendel.c @@ -32,7 +32,7 @@ #include "config_wrapper.h" #ifdef I2C // This is temporary, until display code is completed. - // It includes static i2c_test(), which is called in main(): + // It includes static i2c_test(), which is called in init(): #define I2C_TEST #include "i2c_test.c" #undef I2C_TEST @@ -51,8 +51,8 @@ #include "clock.h" #include "intercom.h" #include "spi.h" -#include "displaybus.h" #include "sd.h" +#include "display_ssd1306.h" #include "simulator.h" #ifdef SIMINFO @@ -95,10 +95,6 @@ void init(void) { spi_init(); #endif - #ifdef DISPLAY_BUS - displaybus_init(DISPLAY_I2C_ADDRESS); - #endif - // set up timers timer_init(); @@ -127,6 +123,12 @@ void init(void) { // prepare the power supply power_init(); + #ifdef DISPLAY + display_init(); + display_clear(); + i2c_test(); + #endif + // say hi to host serial_writestr_P(PSTR("start\nok\n")); @@ -147,11 +149,6 @@ int main (void) init(); - #ifdef DISPLAY_BUS - // This is temporary, until display code is completed. - i2c_test(); - #endif - // main loop for (;;) {