Updated for better use as a module
This commit is contained in:
@@ -4,7 +4,7 @@ use sprite::*;
|
||||
|
||||
pub struct GraphicsBuf {
|
||||
buffer: [u8; 8192],
|
||||
sprites: [Sprite; 30],
|
||||
pub sprites: [Sprite; 30],
|
||||
sprite_atlas: SpriteAtlas,
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ impl Sprite {
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(unused)]
|
||||
pub enum SpriteFlip {
|
||||
None = 0,
|
||||
Horizontal = 1,
|
||||
|
||||
126
src/sh1106.rs
Normal file
126
src/sh1106.rs
Normal file
@@ -0,0 +1,126 @@
|
||||
use cortex_m::delay::Delay;
|
||||
use embedded_hal::i2c::I2c;
|
||||
use rp2040_hal::i2c::Error;
|
||||
|
||||
use defmt as _;
|
||||
|
||||
use crate::graphics::GraphicsBuf;
|
||||
|
||||
#[allow(unused)]
|
||||
#[repr(u8)]
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum SH1106Cmd {
|
||||
SetColumnLo = 0,
|
||||
SetColumnHi = 0x10,
|
||||
DisplayInvert = 0xA6,
|
||||
DisplayOnOff = 0xAE,
|
||||
ColDirectionNorm = 0xC0,
|
||||
ColDirectionRev = 0xC8,
|
||||
SetPage = 0xB0,
|
||||
}
|
||||
|
||||
pub const SH1106_I2C_ADDR: u8 = 0x78u8 >> 1;
|
||||
|
||||
pub struct SH1106Dev {
|
||||
ready: bool,
|
||||
}
|
||||
|
||||
impl SH1106Dev {
|
||||
pub fn new(delay: &mut Delay, mut i2c: &mut dyn I2c<Error = Error>) -> Self {
|
||||
send_command(&mut i2c, &SH1106Cmd::DisplayOnOff, 0x00);
|
||||
delay.delay_ms(100);
|
||||
send_command(&mut i2c, &SH1106Cmd::DisplayInvert, 0);
|
||||
send_command(&mut i2c, &SH1106Cmd::ColDirectionNorm, 0);
|
||||
|
||||
set_col(&mut i2c, 2);
|
||||
set_page(&mut i2c, 0);
|
||||
clr_screen(&mut i2c);
|
||||
delay.delay_ms(500);
|
||||
send_command(&mut i2c, &SH1106Cmd::DisplayOnOff, 0x01);
|
||||
|
||||
SH1106Dev { ready: true }
|
||||
}
|
||||
|
||||
pub fn blit_framebuffer(&self, i2c: &mut dyn I2c<Error = Error>, gfx_buf: &GraphicsBuf) {
|
||||
if !self.ready {
|
||||
panic!("Attempted to use SSH1106 before initialized.");
|
||||
}
|
||||
|
||||
let buf = gfx_buf.get_px_buffer();
|
||||
// for each row of 8x8 pixels
|
||||
for r in 0..8 {
|
||||
set_page(i2c, r);
|
||||
set_col(i2c, 2);
|
||||
// for each cel of 8x8 pixels
|
||||
for c in 0..16 {
|
||||
let mut cel = [0u8; 8];
|
||||
|
||||
// so our x,y here would be r * 128 + c * 8
|
||||
|
||||
// start assembling the 8x8 cel
|
||||
for x in 0..8 {
|
||||
let mut col_byte = 0u8;
|
||||
|
||||
// for each row of the cel
|
||||
for y in 0..8 {
|
||||
let pix_x = (c as usize) * 8 + x;
|
||||
let pix_y = (r as usize) * 8 + y;
|
||||
col_byte |= buf[pix_y * 128 + pix_x] << y;
|
||||
}
|
||||
|
||||
cel[x] = col_byte;
|
||||
}
|
||||
|
||||
write_cel_pixels(i2c, &cel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn send_command(i2c: &mut dyn I2c<Error = Error>, command: &SH1106Cmd, data: u8) {
|
||||
let mut writebuf: [u8; 2] = [0; 2];
|
||||
|
||||
writebuf[0] = 0b1000_0000;
|
||||
writebuf[1] = (command.clone() as u8) | data;
|
||||
|
||||
match i2c.write(SH1106_I2C_ADDR, &writebuf) {
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
|
||||
fn set_col(i2c: &mut dyn I2c<Error = Error>, col: u8) {
|
||||
let col_lo = col & 0b0000_1111;
|
||||
let col_hi = (col & 0b1111_0000) >> 4;
|
||||
|
||||
send_command(i2c, &SH1106Cmd::SetColumnLo, col_lo);
|
||||
send_command(i2c, &SH1106Cmd::SetColumnHi, col_hi);
|
||||
}
|
||||
|
||||
fn set_page(i2c: &mut dyn I2c<Error = Error>, page: u8) {
|
||||
send_command(i2c, &SH1106Cmd::SetPage, page & 0b0000_0111);
|
||||
}
|
||||
|
||||
fn clr_screen(i2c: &mut dyn I2c<Error = Error>) {
|
||||
let mut writebuf = [0u8; 132 * 8 + 1];
|
||||
|
||||
writebuf[0] = 0b0100_0000;
|
||||
|
||||
for i in 0..8 {
|
||||
match i2c.write(SH1106_I2C_ADDR, &writebuf) {
|
||||
_ => (),
|
||||
};
|
||||
|
||||
set_page(i2c, i);
|
||||
}
|
||||
}
|
||||
|
||||
fn write_cel_pixels(i2c: &mut dyn I2c<Error = Error>, data: &[u8]) {
|
||||
let mut writebuf = [0b0100_0000u8; 9];
|
||||
|
||||
writebuf[0] = 0b0100_0000;
|
||||
writebuf[1..].copy_from_slice(&data[0..8]);
|
||||
|
||||
match i2c.write(SH1106_I2C_ADDR, &writebuf) {
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user