Project update 4 of 6
The Tinusaur OLED Display has two main components: the ATtiny85 microcontroller and the SSD1306 OLED display controller. The SSD1306 chip is a popular choice for controlling OLED displays, which are readily available online.
Such displays can be used to display any number of things, from basic text and numbers, to complex game animations. Back in 2014, we wrote a small, open source library, called SSD1306xLED, for the ATtiny85 microcontroller to work with SSD1306-powered OLED displays. The Tinusaur OLED Display project is a perfect hardware companion to the library.
The SSD1306xLED library works with OLED display modules that use the I2C protocol. There are similar displays that use the same SSD1306 controller but communicate over the SPI interface. Our library does not work with the SPI version of the controller chip. In most cases, you can tell that a SSD1306 controller uses I2C if it has four pins – GND, VCC, SCL, SDA.
Although using the I2C interface, our SSD1306xLED library does not implement the full I2C protocol, but rather just enough of it to send commands and data to the display. In particular, the library does not support reading state back from the display. This comes with two great advantages: 1) it is super fast, and 2) it is super small. Read on for more details. The library is, of course, open source and all the software is available at https://bitbucket.org/tinusaur/ssd1306xled/.
This is a small sub-library used in SSD1306xLED that implements the subset of the I2C protocol necessary to send commands and data out. As its name implies, the I2CSW library only writes out.
For the purpose of communicating with the SSD1306 controller, writing to it is enough, since the controller does not send any data back. The downside is that the same library cannot be used to receive data from another device, such as I2C sensor modules.
There are two macros to set the SCL and SDA wires to high and to low (1 and 0):
There are also three low-level functions:
void i2csw_start(void); void i2csw_stop(void); void i2csw_byte(uint8_t byte);
i2csw_start function sets the SCL and SDA pins as outputs and
the "start" condition. In other words, it lets the devices connected
to the microcontroller know that we are about to send something out.
i2csw_stop function sets the "stop" condition, which indicates
we have finished sending data. It also sets the SDA pin as input so it
won’t keep the SDA line HIGH all the time.
i2csw_byte function sends one byte of data out. It is used to
send commands and data to the I2C devices – the display in our case.
Note that the I2CSW library does not handle the acknowledgment condition.
There are four core functions in the library at the moment:
void ssd1306_start_command(void); void ssd1306_start_data(void); void ssd1306_data_byte(uint8_t); void ssd1306_stop(void);
ssd1306_start_command function indicates to the connected I2C
devices that we’re about to send commands. This is used to configure
the controller or to set some parameters such as the current position
on the display.
ssd1306_start_data function indicates to the connected I2C
devices that we’re about to send some data. This is used to send some
data to the display controller – like bitmaps or text.
ssd1306_data_byte function sends two bytes of data to the display
controller. This function is used for both commands and data.
ssd1306_stop function indicates that we have finished
These are three convenience functions:
void ssd1306_init(void); void ssd1306_setpos(uint8_t x, uint8_t y); void ssd1306_fill4(uint8_t, uint8_t, uint8_t, uint8_t);
ssd1306_init function sends a sequence of commands that will
initialize the display controller so it will work the way we expect.
ssd1306_setpos function sets the current position on the
display. Sending data after this command will display it at that
position. From the SSD1306 documentation (Solomon Systech Apr 2008 P
42/59 Rev 1.1 SSD1306):
Horizontal addressing mode (A[1:0]=00b)
In horizontal addressing mode, after the display RAM is read/written, the column address pointer is increased automatically by 1. If the column address pointer reaches column end address, the column address pointer is reset to column start address and page address pointer is increased by 1. The sequence of movement of the page and column address point for horizontal addressing mode is shown in Figure 10-3. When both column and page address pointers reach the end address, the pointers are reset to column start address and page start address (Dotted line in Figure 10-3.)
We are using the horizontal addressing mode since it is the most convenient for drawing shapes or printing characters.
ssd1306_fill4 function fills out the screen with the four bytes
specified as parameters. The reason for four bytes is that it is
convenient for filling the screen with patterns.
There are three other functions derived from the
ssd1306_clear()clears the screen, i.e., fills it with zeroes
ssd1306_fill(p)fills the display with the specified byte
ssd1306_fill2(p1, p2)fills the display with the two specified bytes
The testing script in the
demonstrates the purpose and usage of the library.
The first section of this file fills out the screen with random values using a linear congruential generator. The second section fills out the screen with a sequential number that creates some patterns. The next section fills the screen line by line. The last section fills out the screen with various patterns.
There are more functions in the SSD1306xLED library, such as for printing text and numbers on the screen and drawing images, but those will be subject of another update. In the meantime, here are images of the various patterns generated by the tests described above: