Skip to content

Latest commit

 

History

History
149 lines (123 loc) · 6.41 KB

usage.md

File metadata and controls

149 lines (123 loc) · 6.41 KB

Using the core library

1. Setting up the i2c ports

In order to communicate with the display you need to set up pico's i2c communication

Add hardware_i2c library to CMakeLists.txt

target_link_libraries(project_name
        hardware_i2c)

Add the ssd1306 library to your project

This is explained in readme.md section 1

Set up i2c

Pico has 2 i2c controllers. You can use any of these, just remember to pass according i2c instance in code

for this example pins 12 and 13 are used for sda and scl lines. These are connected to i2c0 controller. You can use any pins capable of i2c communication but if they are connected to i2c1 controller you'll need to change the code when initializing i2c communication and when creating a display object

imports:

you need

#include "hardware/i2c.h"
#include "pico-ssd1306/ssd1306.h"

i2c init and pin init:

    i2c_init(i2c0, 1000000); // Init i2c0 and set baud rate to 1Mhz (max supported speed by pico)
    // lower baud rates make the communication slower, and since this lib uses blocking writing,
    // lower baud rates lower maximal achievable frame rate
    gpio_set_function(12, GPIO_FUNC_I2C); // Set pins 12 and 13 for i2c role
    gpio_set_function(13, GPIO_FUNC_I2C);
    gpio_pull_up(12); // Pull up the pins for proper communication
    gpio_pull_up(13);

2. Create a display object

When creating a display object you need to provide 3 arguments. Witch i2c controller you want to use (the one you initialized above), display address (usually 0x3C or 0x3D with ssd1306) and display size. This library defines 2 available sizes Size::W128xH64 and Size::W128xH32

pico_ssd1306::SSD1306 display = pico_ssd1306::SSD1306(i2c0, 0x3D, pico_ssd1306::Size::W128xH64);

3. A few words on how this works

From now on you can use the display object to draw anything you want to the display. Core of ssd1306 library exposes 2 functions for drawing (documentation of all functions is here doxygen). setPixel() and addBitmapImage() but just calling these won't draw anything on screen. These functions only affect the buffer. To actually display something you need to first draw to buffer (by setPixel() or addBitmapImage()) and then sending it to the display with sendBuffer(). Same is true for clear() function. It just clears the buffer, not the screen. so calling clear() and sendBuffer() will actually clear the display.

4. Turning on a pixel

setPixel() is pretty self-explanatory. It modifies the state of exactly 1 pixel. Just give it the x and y coordinates, optionally change the write mode and done. If you're confused about write mode see doxygen section about write mode. tldr write mode decides whether a pixel is to be set on, off or inverted (on to off and vice versa)

this example set pixel at x = 0 and y = 0 (top left corner) on

//Create a new display object
pico_ssd1306::SSD1306 display = pico_ssd1306::SSD1306(I2C_PORT, 0x3D, pico_ssd1306::Size::W128xH64);

display.setPixel(0, 0);

display.sendBuffer();

5. Displaying an image

How to prepare an image for pico

Well you can't just shove a png file into c++ and expect it to work. We need a bitmap containing data on which pixels to turn on. This library scans bytes in bit map left to right, top to bottom, so :

#define IMAGE_WIDTH 32
#define IMAGE_HEIGHT 32
uint8_t image[128] = {
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00111111, 0b11111111, 0b11111111, 0b11111100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100, 
    0b00100000, 0b00000001, 0b00000000, 0b00000100 
};

contains such an image:

example2

It's best to keep width to a number divisible by 8. Otherwise, errors occur while shifting bytes and rendering fails. Height does not have such a limitation.

Bitmap to display

addBitmapImage() function does pretty much all the work for us. we need to tell it what and where to draw and done. So what do we need? x and y coordinated on where to anchor an image (anchor is top left point of the image), image and width, height.

display.addBitmapImage(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, image);
display.sendBuffer();

Should draw this image to display at point 0, 0

Entire display now should look like this:

example2

Also note that addBitmapImage() in default write mode doesn't turn pixels off, so overlaying images is possible, so:

display.addBitmapImage(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, image);
display.addBitmapImage(8, 0, IMAGE_WIDTH, IMAGE_HEIGHT, image);
display.sendBuffer();

will overlay the same image with 8 pixel to right image, producing:

example2

This function can take an optional argument of write mode, this is same as in setPixel()

6. Additional Settings

Things like setting contrast, flipping the display etc. are all documented here