The Solomon Systech SSD1306 is a monochrome OLED display, capable of displaying 128 x 64 pixels. The SSD1306 is embedded in many ESP32 development boards, but can also supplied via a module for integration with your projects.
The SSD1306 driver provides support for integrating SSD1306 displays with AtomVM applications running on the ESP32 devices.
Note. Testing has primarily utilized standalone SSD1306 modules.
The SSD1306 supports the 2-pin I2C interface, and the atomvm_lib
SSD1306 driver makes use of this interface to communicate with the SSD1306 modem to display data. Users may select any supported GPIO pins on your device to integrate with the module.
For more information about the ESP32 I2C interface, see the ESP IDF SDK I2C documentation.
The AtomVM SSD1306 driver is implemented as an AtomVM component, which includes some native C code that must be linked into the ESP32 AtomVM image. In order to build and deploy this client code, you must build an AtomVM binary image.
For general instructions about how to build AtomVM and include third-party components into an AtomVM image, see the AtomVM Build Instructions.
Once the AtomVM image including this component has been built, you can flash the image to your ESP32 device. For instructions about how to flash AtomVM images to your ESP32 device, see the AtomVM Getting Started Guide.
Once the AtomVM image including this component has been flashed to your ESP32 device, you can then include this project into your rebar3
project using the atomvm_rebar3_plugin
, which provides targets for building AtomVM packbeam files and flashing them to your device.
The atomvm_lib
SSD1306 driver is designed to provide a simple and easy to use interface for displaying textual or bitmap data for AtomVM applications. This section describes the atomvm_lib
SSD1306 driver API, as encapsulated in the ssd1306
Erlang module.
An instance of the atomvm_lib
SSD1306 driver is created via the ssd1306:start/1
function. This function takes a set of configuration, described in more detail below.
For example, to configure the 2-wire I2C interface to use the specified ESP32 pins, you can use the following configuration:
%% erlang
Config = #{
sda_pin => 21,
scl_pin => 22
},
{ok, Display} = ssd1306:start(Config),
...
The SSD1306
instance can now be used for subsequent operations supported by the ssd1306
module.
Note. For more information about the AtomVM I2C interface, see the AtomVM documentation.
To delete an instance of the driver, use the ssd1306:stop/1
function.
%% erlang
ssd1306:stop(Display),
...
Note. This function is not well tested and its use may result in a memory leak.
The atomvm_lib
SSD1306 driver is initialized with a map containing keys and values used to configure the driver. The keys and values in this map are summarized in the following table:
Key | Type | Required | Default Value | Description |
---|---|---|---|---|
sda_pin |
non_negative_integer() |
yes | ESP32 I2C SDA pin | |
scl_pin |
non_negative_integer() |
yes | ESP32 I2C SCL pin | |
freq_hz |
non_negative_integer |
no | 700000 |
I2C clock frequency |
i2c_num |
i2c_num_0 | i2c_num_1 |
no | i2c_num_0 |
I2C hardware port. Consult the IDF SDK documentation for more details. |
To clear the screen use the ssd1306:clear/1
function:
%% erlang
ok = ssd1306:clear(Display),
...
Clearing the screen will turn off (set to black) all pixels in the display.
To write text to the screen use the ssd1306:set_text/2
function:
%% erlang
Text = io_lib:format(
" !!AtomVM!!~n~nFree heap:~n~p bytes",
[erlang:system_info(esp32_free_heap_size)]
),
ok = ssd1306:clear(Display),
ok = ssd1306:set_text(Display, Text),
...
The SSD1306 driver is designed to support 16 columns and 8 rows of textual data on a standard 168 x 64 pixel OLED display.
Note. Be sure to clear the screen using
ssd1306:clear/1
before writing text to the screen.
The SSD1306 driver can be used to write rectangular "bitmap" data, to display something vaguely image-like, if desired.
For the purposes of the driver, a "bitmap" is a sequence of bits encapsulated in an Erlang binary, representing a monochrome image, where a 1 bit indicating that a pixel should be on, and a 0 bit indicating that a pixel should be off.
The bit sequence represents the image in row-major format, with the high-order bit of the first byte representing the pixel at image position (<x,y>
) <0,0>
, the next bit in the first byte representing the pixel at position <1,0>
, etc. Given a rectangular image of pixel dimension width
times height
, there are therefore width
-many bits in the initial bit sequence, representing the first row of the image, followed by the next row, and so forth, until all rows are represented in the binary.
Note that the sequences of width-many bits representing a row of the image generally may not be aligned on byte boundaries. In addition, the width * height
product may not be aligned on byte boundaries, as well. In such a case, the remaining bits in the last byte of the boundary can be ignored, or padded with 0s, as desired. In general, there will be (width * height) div 8 + 1 if (width * height) rem 8 == 0
many bytes in a bitmap, given an image of size width * height
.
The following illustrates the representation of a bitmap in an Erlang binary:
+--------+--------+--------+-- --+------- --------+--------+
|01101011|00101110|11100110|11 ... 01|1100100 ... 1101001|11|00000|
+--------+--------+--------+-- --+------- ... -------+--------+
^ ^ ^ | | padding
bit 0 bit 8 bit 12 | |
|<---------------------------- ... ---->|<--- ... --------->|
| width-many bits |
|<---------------------------- ... ------------------------>|
| width * height -many bits
|<---------------------------- ... ------------------------------>|
(width * height) div 8 + 1 if (width * height) rem 8 == 0 (num bytes)
To write an image, use the ssd1306:set_bitmap/4
function:
%% erlang
Bitmap = <<...>>,
Width = %% ...
Height = %% ...
ssd1306:set_bitmap(Display, Bitmap, Width, Height),
...
Note that the pixels outside of the image region are cleared when setting an image, so there is no need to use the ssd1306:clear/1
function to clear any pixels already on the screen.
The atomvm_lib
SSD1306 driver includes an example program illustrating use of the driver. See the README for information about how to build, flash, and run this example program.