1 #include <twr_ssd1306.h>
4 #define _TWR_SSD1306_SETCONTRAST 0x81
5 #define _TWR_SSD1306_DISPLAYALLON_RESUME 0xA4
6 #define _TWR_SSD1306_DISPLAYALLON 0xA5
7 #define _TWR_SSD1306_NORMALDISPLAY 0xA6
8 #define _TWR_SSD1306_INVERTDISPLAY 0xA7
9 #define _TWR_SSD1306_DISPLAYOFF 0xAE
10 #define _TWR_SSD1306_DISPLAYON 0xAF
11 #define _TWR_SSD1306_SETDISPLAYOFFSET 0xD3
12 #define _TWR_SSD1306_SETCOMPINS 0xDA
13 #define _TWR_SSD1306_SETVCOMDETECT 0xDB
14 #define _TWR_SSD1306_SETDISPLAYCLOCKDIV 0xD5
15 #define _TWR_SSD1306_SETPRECHARGE 0xD9
16 #define _TWR_SSD1306_SETMULTIPLEX 0xA8
17 #define _TWR_SSD1306_SETLOWCOLUMN 0x00
18 #define _TWR_SSD1306_SETHIGHCOLUMN 0x10
19 #define _TWR_SSD1306_SETSTARTLINE 0x40
20 #define _TWR_SSD1306_MEMORYMODE 0x20
21 #define _TWR_SSD1306_COLUMNADDR 0x21
22 #define _TWR_SSD1306_PAGEADDR 0x22
23 #define _TWR_SSD1306_COMSCANINC 0xC0
24 #define _TWR_SSD1306_COMSCANDEC 0xC8
25 #define _TWR_SSD1306_SEGREMAP 0xA0
26 #define _TWR_SSD1306_CHARGEPUMP 0x8D
27 #define _TWR_SSD1306_EXTERNALVCC 0x1
28 #define _TWR_SSD1306_SWITCHCAPVCC 0x2
30 static bool _twr_ssd1306_command(
twr_ssd1306_t *
self, uint8_t command);
31 static bool _twr_ssd1306_send_data(
twr_ssd1306_t *
self, uint8_t *buffer,
size_t length);
36 memset(
self, 0xff,
sizeof(*
self));
38 self->_i2c_channel = i2c_channel;
40 self->_i2c_address = i2c_address;
42 self->_framebuffer = framebuffer;
46 self->_initialized = _twr_ssd1306_init(
self);
48 return self->_initialized;
53 twr_gfx_caps_t caps = { .width =
self->_framebuffer->width, .height =
self->_framebuffer->height };
60 if (!self->_initialized)
62 self->_initialized = _twr_ssd1306_init(
self);
65 return self->_initialized;
70 memset(self->_framebuffer->buffer, 0x00, self->_framebuffer->length);
76 uint32_t byteIndex = 0;
80 byteIndex += (y / 8) * self->_framebuffer->width;
82 uint8_t bitMask = 1 << (y % 8);
86 self->_framebuffer->buffer[byteIndex] &= ~bitMask;
90 self->_framebuffer->buffer[byteIndex] |= bitMask;
105 if (!self->_initialized)
107 self->_initialized = _twr_ssd1306_init(
self);
110 if (!self->_initialized)
115 if (_twr_ssd1306_command(
self, _TWR_SSD1306_COLUMNADDR) &&
116 _twr_ssd1306_command(
self, 0) &&
117 _twr_ssd1306_command(
self, self->_framebuffer->width - 1) &&
118 _twr_ssd1306_command(
self, _TWR_SSD1306_PAGEADDR) &&
119 _twr_ssd1306_command(
self, 0) &&
120 _twr_ssd1306_command(
self, self->_framebuffer->pages - 1))
122 for (
size_t i = 0; i <
self->_framebuffer->length; i += 8)
124 if (!_twr_ssd1306_send_data(
self, self->_framebuffer->buffer + i, 8))
151 static bool _twr_ssd1306_command(
twr_ssd1306_t *
self, uint8_t command)
156 static bool _twr_ssd1306_send_data(
twr_ssd1306_t *
self, uint8_t *buffer,
size_t length)
170 return _twr_ssd1306_command(
self, _TWR_SSD1306_DISPLAYOFF) &&
171 _twr_ssd1306_command(
self, _TWR_SSD1306_SETDISPLAYCLOCKDIV) &&
172 _twr_ssd1306_command(
self, 0x80) &&
173 _twr_ssd1306_command(
self, _TWR_SSD1306_SETMULTIPLEX) &&
174 _twr_ssd1306_command(
self, self->_framebuffer->height - 1) &&
175 _twr_ssd1306_command(
self, _TWR_SSD1306_SETDISPLAYOFFSET) &&
176 _twr_ssd1306_command(
self, 0x0) &&
177 _twr_ssd1306_command(
self, _TWR_SSD1306_SETSTARTLINE | 0x0) &&
178 _twr_ssd1306_command(
self, _TWR_SSD1306_CHARGEPUMP) &&
179 _twr_ssd1306_command(
self, 0x14) &&
180 _twr_ssd1306_command(
self, _TWR_SSD1306_MEMORYMODE) &&
181 _twr_ssd1306_command(
self, 0x00) &&
182 _twr_ssd1306_command(
self, _TWR_SSD1306_SEGREMAP | 0x1) &&
183 _twr_ssd1306_command(
self, _TWR_SSD1306_COMSCANDEC) &&
184 _twr_ssd1306_command(
self, _TWR_SSD1306_SETCOMPINS) &&
185 _twr_ssd1306_command(
self, self->_framebuffer->height == 64 ? 0x12 : 0x02) &&
186 _twr_ssd1306_command(
self, _TWR_SSD1306_SETCONTRAST) &&
187 _twr_ssd1306_command(
self, 0x8f) &&
188 _twr_ssd1306_command(
self, _TWR_SSD1306_SETPRECHARGE) &&
189 _twr_ssd1306_command(
self, 0xF1) &&
190 _twr_ssd1306_command(
self, _TWR_SSD1306_SETVCOMDETECT) &&
191 _twr_ssd1306_command(
self, 0x40) &&
192 _twr_ssd1306_command(
self, _TWR_SSD1306_DISPLAYALLON_RESUME) &&
193 _twr_ssd1306_command(
self, _TWR_SSD1306_NORMALDISPLAY) &&
194 _twr_ssd1306_command(
self, _TWR_SSD1306_DISPLAYON);
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
bool twr_i2c_memory_write(twr_i2c_channel_t channel, const twr_i2c_memory_transfer_t *transfer)
Memory write to I2C channel.
bool twr_i2c_memory_write_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
twr_i2c_channel_t
I2C channels.
@ TWR_I2C_SPEED_400_KHZ
I2C communication speed is 400 kHz.
bool twr_ssd1306_init(twr_ssd1306_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address, const twr_ssd1306_framebuffer_t *framebuffer)
Initialize lcd driver.
void twr_ssd1306_clear(twr_ssd1306_t *self)
Clear.
bool twr_ssd1306_update(twr_ssd1306_t *self)
Lcd update, send data.
const twr_gfx_driver_t * twr_ssd1306_get_driver(void)
Get Lcd driver.
bool twr_ssd1306_is_ready(twr_ssd1306_t *self)
Check if lcd is ready for commands.
uint32_t twr_ssd1306_get_pixel(twr_ssd1306_t *self, int x, int y)
Lcd get pixel.
twr_gfx_caps_t twr_ssd1306_get_caps(twr_ssd1306_t *self)
Get capabilities.
void twr_ssd1306_draw_pixel(twr_ssd1306_t *self, int x, int y, uint32_t color)
Lcd draw pixel.
Display driver interface.
I2C memory transfer parameters.
uint32_t memory_address
8-bit I2C memory address (it can be extended to 16-bit format if OR-ed with TWR_I2C_MEMORY_ADDRESS_16...
uint8_t device_address
7-bit I2C device address
size_t length
Length of buffer which is being written or read.
void * buffer
Pointer to buffer which is being written or read.