From: Martin Mares Date: Sun, 17 Jun 2018 13:21:25 +0000 (+0200) Subject: SSD1306 display X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=2aaaf8436b9a503974a8abd1310c50241cd16ded;p=home-hw.git SSD1306 display --- diff --git a/Src/test.c b/Src/test.c index 57d9753..e28a02f 100644 --- a/Src/test.c +++ b/Src/test.c @@ -5,6 +5,7 @@ #include typedef unsigned int uint; +typedef uint8_t byte; typedef uint16_t u16; typedef int16_t s16; @@ -134,6 +135,8 @@ void debug_printf(const char *fmt, ...) va_end(args); } +#if 0 + static uint bmp_read(uint reg, uint bytes) { LL_I2C_ClearFlag_STOP(I2C1); @@ -249,3 +252,123 @@ void run_test(void) LL_mDelay(1000); } } + +#else + +// Based on https://github.com/adafruit/Adafruit_SSD1306 + +#define SSD1306_SETLOWCOLUMN 0x00 +#define SSD1306_SETHIGHCOLUMN 0x10 +#define SSD1306_MEMORYMODE 0x20 +#define SSD1306_SETSTARTLINE 0x40 +#define SSD1306_SETCONTRAST 0x81 +#define SSD1306_CHARGEPUMP 0x8D +#define SSD1306_SEGREMAP 0xA0 +#define SSD1306_DISPLAYALLON_RESUME 0xA4 +#define SSD1306_DISPLAYALLON 0xA5 +#define SSD1306_NORMALDISPLAY 0xA6 +#define SSD1306_INVERTDISPLAY 0xA7 +#define SSD1306_SETMULTIPLEX 0xA8 +#define SSD1306_DISPLAYOFF 0xAE +#define SSD1306_DISPLAYON 0xAF +#define SSD1306_SETSTARTPAGE 0xB0 +#define SSD1306_COMSCANINC 0xC0 +#define SSD1306_COMSCANDEC 0xC8 +#define SSD1306_SETDISPLAYOFFSET 0xD3 +#define SSD1306_SETCOMPINS 0xDA +#define SSD1306_SETVCOMDETECT 0xDB +#define SSD1306_SETDISPLAYCLOCKDIV 0xD5 +#define SSD1306_SETPRECHARGE 0xD9 +#define SSD1306_NOP 0xE3 + +static const byte display_init_cmds[] = { + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80 + SSD1306_SETMULTIPLEX, 0x1F, // ratio 32 + SSD1306_SETDISPLAYOFFSET,0x0, // no offset + SSD1306_SETSTARTLINE | 0x0, // line #0 + SSD1306_CHARGEPUMP, 0x14, // internal vcc + SSD1306_MEMORYMODE, 0x02, // page mode + SSD1306_SEGREMAP | 0x0, // column 0 mapped to SEG0 + SSD1306_COMSCANDEC, // column scan direction reversed + SSD1306_SETCOMPINS, 0x02, // sequential COM pins, disable remap + SSD1306_SETCONTRAST, 0x7F, // contrast level 127 + SSD1306_SETPRECHARGE, 0xF1, // pre-charge period (1, 15) + SSD1306_SETVCOMDETECT, 0x40, // vcomh regulator level- + SSD1306_DISPLAYALLON_RESUME, + SSD1306_NORMALDISPLAY, + SSD1306_DISPLAYON, +}; + +static void display_cmd(byte cmd) +{ + LL_I2C_ClearFlag_STOP(I2C1); + LL_I2C_HandleTransfer(I2C1, 0x79, LL_I2C_ADDRSLAVE_7BIT, 2, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); + while (!LL_I2C_IsActiveFlag_TXE(I2C1)) + ; + LL_I2C_TransmitData8(I2C1, 0x00); // Will send a command + while (!LL_I2C_IsActiveFlag_TXE(I2C1)) + ; + LL_I2C_TransmitData8(I2C1, cmd); + while (!LL_I2C_IsActiveFlag_STOP(I2C1)) + ; +} + +static void display_data_start(uint cnt) +{ + LL_I2C_ClearFlag_STOP(I2C1); + LL_I2C_HandleTransfer(I2C1, 0x79, LL_I2C_ADDRSLAVE_7BIT, cnt + 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); + while (!LL_I2C_IsActiveFlag_TXE(I2C1)) + ; + LL_I2C_TransmitData8(I2C1, 0x40); // Will send data +} + +static void display_data(byte d) +{ + while (!LL_I2C_IsActiveFlag_TXE(I2C1)) + ; + LL_I2C_TransmitData8(I2C1, d); +} + +static void display_data_end(void) +{ + while (!LL_I2C_IsActiveFlag_STOP(I2C1)) + ; +} + +static void display_init(void) +{ + for (uint i=0; i < sizeof(display_init_cmds); i++) + display_cmd(display_init_cmds[i]); + + for (uint p=0; p<4; p++) + { + display_cmd(SSD1306_SETSTARTPAGE + p); + display_cmd(SSD1306_SETHIGHCOLUMN); + display_cmd(SSD1306_SETLOWCOLUMN); + display_data_start(128); + for (uint i=0; i<128; i++) + display_data(p == 0 ? 0x80 | i : 0); + display_data_end(); + } +} + +void run_test(void) +{ + uint cnt = 0; + + debug_puts("Init\r\n"); + display_init(); + + for (;;) + { + LL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); + + debug_printf("Tick tock: %d\r\n", cnt); + + LL_mDelay(1000); + cnt++; + } +} + +#endif