ssd1315 0.3.0

SSD1315 OLED driver.
Documentation
//! # SSD1315
//!
//! The SSD1315 device driver serves for both SSD1315 and SSD1306. Supports both I2C and SPI interface.
//!
//! ## Usage
//!
//! Here is an example of how to use `ssd1315`:
//!
//! ```rust,ignore
//! use ssd1315::*;
//! use embedded_graphics::{
//!     pixelcolor::BinaryColor,
//!     prelude::*,
//!     primitives::{Circle, PrimitiveStyle},
//! };
//!
//! // let i2c = ...; // Initialize your I2C peripheral here
//! let interface = interface::I2cDisplayInterface::new_interface(i2c);
//! // let interface = interface::SpiDisplayInterface::new_interface(spi, dc);
//!
//! let mut display = Ssd1315::new(interface);
//!
//! Circle::new(Point::new(0, 0), 40)
//!         .into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
//!         .draw(&mut display)
//!         .unwrap();
//!
//! display.init_screen();
//! display.flush_screen();
//! ```
//!
//! Congratulations! Now you can see a small circle displayed on your OLED screen!
//!
//! If you want to apply your own configuration to the SSD1315 (e.g. changing the contrast),
//! follow this example:
//!
//! ```rust,ignore
//! use ssd1315::*;
//! use embedded_graphics::{
//!     pixelcolor::BinaryColor,
//!     prelude::*,
//!     primitives::{Circle, PrimitiveStyle},
//! };
//!
//! // let i2c = ...; // Initialize your I2C peripheral here
//! let interface = interface::I2cDisplayInterface::new_interface(i2c);
//! // let interface = interface::SpiDisplayInterface::new_interface(spi, dc);
//!
//! let mut config = config::Ssd1315DisplayConfig::default();
//! config.contrast = 0xff;
//!
//! let mut display = Ssd1315::new(interface);
//! display.set_custom_config(config);
//!
//! Circle::new(Point::new(0, 0), 40)
//!         .into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
//!         .draw(&mut display)
//!         .unwrap();
//!
//! display.init_screen();
//! display.flush_screen();
//! ```
//!
//! Alternatively, you can use a preset configuration provided by `ssd1315`:
//!
//! ```rust,no_run
//! use ssd1315::config;
//!
//! let config = config::Ssd1315DisplayConfig::preset_config();
//! ```
//!
//! Now you can see the change in contrast!
//!
//! You might also want to draw some raw image(s) manually to fit your specific requirements.
//! No problem! `ssd1315` fits your need! You can draw it/them in an easy way:
//!
//! ```rust,ignore
//! // let interface = ...; // Initialize your I2C or SPI interface here
//! let mut display = Ssd1315::new(interface);
//!
//! let raw_image = [[0b1010_1010; 128]; 8];
//! raw_image.draw_from_raw(&mut display);
//!
//! display.init_screen();
//! display.flush_screen();
//! ```

#![cfg_attr(not(test), no_std)]

mod command;
pub mod config;
mod draw_buffer;
pub mod interface;

use command::{oled_init, oled_set_cursor};
use config::Ssd1315DisplayConfig;

use display_interface::{DataFormat, WriteOnlyDataCommand};

pub(crate) const DISPLAY_WIDTH: usize = 128;
pub(crate) const DISPLAY_HEIGHT: usize = 64;

/// A virtual SSD1315 device that holds interface data, a buffer
/// that maps to the actual buffer in the SSD1315 and a configuration.
pub struct Ssd1315<DI> {
    interface: DI,
    buffer: [[u8; DISPLAY_WIDTH]; DISPLAY_HEIGHT / 8],
    config: Ssd1315DisplayConfig,
}

impl<DI: WriteOnlyDataCommand> Ssd1315<DI> {
    /// Creates a new instance of SSD1315.
    ///
    /// The `interface` can be either an I2C or an SPI interface.
    pub fn new(interface: DI) -> Self {
        Self {
            interface,
            buffer: [[0; DISPLAY_WIDTH]; DISPLAY_HEIGHT / 8],
            config: Default::default(),
        }
    }

    /// Sets your custom configuration for the SSD1315.
    /// If you do not call this, the display will be initialized with the default configuration.
    pub fn set_custom_config(&mut self, config: Ssd1315DisplayConfig) {
        self.config = config;
    }

    /// Initializes the SSD1315.
    pub fn init_screen(&mut self) {
        oled_init(&mut self.interface, self.config);
    }

    /// Flushes the SSD1315 buffer to display its contents on the OLED screen.
    ///
    /// The buffer is not cleared after flushing; call [`clear`] if
    /// you need a fresh framebuffer for the next frame.
    pub fn flush_screen(&mut self) {
        for (page, data) in self.buffer.iter().enumerate() {
            oled_set_cursor(&mut self.interface, page as u8);
            self.interface.send_data(DataFormat::U8(data)).unwrap();
        }
    }

    /// Clears the local framebuffer, resetting all pixels to off.
    pub fn clear(&mut self) {
        self.buffer = [[0; DISPLAY_WIDTH]; DISPLAY_HEIGHT / 8];
    }
}

pub trait DrawFromRaw {
    fn draw_from_raw<DI>(&self, instance: &mut Ssd1315<DI>);
}