Display: first text on OLED.
Note by Traumflug: this code was written by Ruslan Popov a lot earlier already. I picked it to i2c_test.c to get "something" visible running. This is the commit finally adjusted to the new display infrastructure.
This commit is contained in:
parent
5f95784c0b
commit
e3fd9eaea7
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
87
i2c_test.c
87
i2c_test.c
|
|
@ -15,99 +15,16 @@
|
|||
|
||||
#include <string.h>
|
||||
#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 */
|
||||
|
|
|
|||
19
mendel.c
19
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 (;;)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue