#oled #embedded-hal-driver #no-std #16-bit

no-std ssd1331

I2C/SPI driver for the SSD1331 OLED display controller

11 releases

0.3.0 Jul 11, 2021
0.2.3 Apr 6, 2021
0.2.2 Mar 21, 2020
0.2.0-alpha.2 Jan 13, 2020
0.1.3 Mar 3, 2019

#1535 in Embedded development

Download history 32/week @ 2024-02-26 113/week @ 2024-04-01

113 downloads per month

MIT/Apache

1.5MB
434 lines

SSD1331 driver

Build Status Crates.io Docs.rs

SSD1331 display showing Ferris

SPI (4 wire) driver for the SSD1331 OLED display.

The display is configured by this driver to use a 16 bit, R5 G6 B5 pixel definition. You can convert images into the correct BMP format with the following commands:

convert my_image.png \
    -flip \
    -type truecolor \
    -define bmp:subtype=RGB565 \
    -depth 16 \
    -strip \
    my_image.bmp

You can also export images directly from The GIMP by saving as .bmp and choosing the following option:

The GIMP RGB565 export option.

Documentation

Examples

This crate uses probe-run to run the examples. Once set up, it should be as simple as cargo run --example <example name> --release. --release will be required for some examples to reduce FLASH usage.

Load a BMP image of the Rust logo and display it in the center of the display. From examples/bmp.rs:

#![no_std]
#![no_main]

use cortex_m_rt::{entry, exception, ExceptionFrame};
use embedded_graphics::{geometry::Point, image::Image, pixelcolor::Rgb565, prelude::*};
use panic_semihosting as _;
use ssd1331::{DisplayRotation, Ssd1331};
use stm32f1xx_hal::{
    delay::Delay,
    prelude::*,
    spi::{Mode, Phase, Polarity, Spi},
    stm32,
};
use tinybmp::Bmp;

#[entry]
fn main() -> ! {
    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = stm32::Peripherals::take().unwrap();
    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.freeze(&mut flash.acr);
    let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
    let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
    let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);

    // SPI1
    let sck = gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl);
    let miso = gpioa.pa6;
    let mosi = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl);
    let mut delay = Delay::new(cp.SYST, clocks);
    let mut rst = gpiob.pb0.into_push_pull_output(&mut gpiob.crl);
    let dc = gpiob.pb1.into_push_pull_output(&mut gpiob.crl);

    let spi = Spi::spi1(
        dp.SPI1,
        (sck, miso, mosi),
        &mut afio.mapr,
        Mode {
            polarity: Polarity::IdleLow,
            phase: Phase::CaptureOnFirstTransition,
        },
        8.mhz(),
        clocks,
        &mut rcc.apb2,
    );

    let mut disp = Ssd1331::new(spi, dc, DisplayRotation::Rotate0);

    disp.reset(&mut rst, &mut delay).unwrap();
    disp.init().unwrap();
    disp.flush().unwrap();

    let (w, h) = disp.dimensions();

    let bmp =
        Bmp::from_slice(include_bytes!("./rust-pride.bmp")).expect("Failed to load BMP image");

    let im: Image<Bmp<Rgb565>> = Image::new(&bmp, Point::zero());

    // Position image in the center of the display
    let moved = im.translate(Point::new(
        (w as u32 - bmp.size().width) as i32 / 2,
        (h as u32 - bmp.size().height) as i32 / 2,
    ));

    moved.draw(&mut disp).unwrap();

    disp.flush().unwrap();

    loop {}
}

#[exception]
fn HardFault(ef: &ExceptionFrame) -> ! {
    panic!("{:#?}", ef);
}

Rust rainbow demo image.

Migrating from 0.1 to 0.2

The full changelog can be found here. A tl;dr version is shown below.

Version 0.1.x

use ssd1331::{prelude::*, Builder};

let mut disp: GraphicsMode<_> = Builder::new().connect_spi(spi, dc).into();

disp.reset(&mut rst, &mut delay);
disp.init().unwrap();
disp.flush().unwrap();

disp.get_dimensions();
disp.get_rotation();

Version 0.2.x

use ssd1331::{Ssd1331, DisplayRotation};

let mut disp = Ssd1331::new(spi, dc, DisplayRotation::Rotate0);

disp.reset(&mut rst, &mut delay).unwrap();
disp.init().unwrap();
disp.flush().unwrap();

disp.dimensions();
disp.rotation();

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies