From 28c012c6cbc10c575ee8f16a0cd7edf67388cba5 Mon Sep 17 00:00:00 2001 From: JP Stringham Date: Fri, 26 Dec 2025 21:21:01 -0500 Subject: [PATCH] Making i2c more generic over any i2c pins --- .vscode/settings.json | 7 +++ src/main.rs | 130 ++++++++++++++++++------------------------ 2 files changed, 62 insertions(+), 75 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..aa6e6ab --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "rust-lang.rust-analyzer", + "workbench.editor.customLabels.patterns": { + "**/mod.rs": "mod | ${dirname}" + }, +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9640031..4ef2bd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,23 +1,13 @@ // Intended to be used with a 1.3" OLED // resolution is 128*64 -// - #![no_std] #![no_main] -use embedded_hal::{ - digital::OutputPin, - i2c::I2c -}; -use hal::gpio::bank0::{Gpio8, Gpio9}; -use rp2040_hal::gpio::PullUp; +use embedded_hal::{digital::OutputPin, i2c::I2c}; +use hal::{fugit::RateExtU32, pac}; use rp2040_hal as hal; -use hal::{ - pac as pac, - gpio::{FunctionI2C, Pin}, - fugit::RateExtU32, -}; +use rp2040_hal::i2c::Error; use defmt as _; use panic_probe as _; @@ -42,7 +32,7 @@ enum SH1106Cmd { SetPage = 0xB0, } -const SH1106_I2C_ADDR:u8 = 0x78u8 >> 1; +const SH1106_I2C_ADDR: u8 = 0x78u8 >> 1; #[rp2040_hal::entry] fn main() -> ! { @@ -76,10 +66,9 @@ fn main() -> ! { pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, - &mut pac.RESETS + &mut pac.RESETS, ); - // Create the I²C drive, using the two pre-configured pins. let mut i2c = hal::I2C::i2c0( pac.I2C0, @@ -92,7 +81,7 @@ fn main() -> ! { let mut led_pin = pins.gpio25.into_push_pull_output(); led_pin.set_high().unwrap(); - + send_command(&mut i2c, &SH1106Cmd::DisplayOnOff, 0x00); delay.delay_ms(100); send_command(&mut i2c, &SH1106Cmd::DisplayInvert, 0); @@ -116,18 +105,30 @@ fn main() -> ! { sprites[0].visible = true; loop { - gfx_buf.iter_mut().for_each(|x| *x = 0); sprites.iter_mut().for_each(|s| { if s.visible { - sprite_atlas.draw_sprite(s.sprite_index, s.x as u8, s.y as u8, s.flip, &mut gfx_buf); + sprite_atlas.draw_sprite( + s.sprite_index, + s.x as u8, + s.y as u8, + s.flip, + &mut gfx_buf, + ); } }); sprite_atlas.draw_string(10, 10, "Hello World!", &mut gfx_buf); - sprite_atlas.draw_textfield(10, 20, 110, 10, "I think this font has a *lot* of 'character'! ;)", &mut gfx_buf); + sprite_atlas.draw_textfield( + 10, + 20, + 110, + 10, + "I think this font has a *lot* of 'character'! ;)", + &mut gfx_buf, + ); draw_bresenham_line(0, 0, 127, 0, &mut gfx_buf); draw_bresenham_line(0, 63, 128, 63, &mut gfx_buf); @@ -139,12 +140,8 @@ fn main() -> ! { } } -fn draw_bresenham_line( - x0: u8, y0: u8, - x1: u8, y1: u8, - gfx_buf: &mut [u8; 8192], -) { - let x0 = (x0 as i32).clamp(0,127); +fn draw_bresenham_line(x0: u8, y0: u8, x1: u8, y1: u8, gfx_buf: &mut [u8; 8192]) { + let x0 = (x0 as i32).clamp(0, 127); let x1 = (x1 as i32).clamp(0, 127); let y0 = (y0 as i32).clamp(0, 63); let y1 = (y1 as i32).clamp(0, 63); @@ -172,7 +169,7 @@ fn draw_bresenham_line( if dx > dy { for _ in 0..dx { - gfx_buf[(y*128+x) as usize] = 1; + gfx_buf[(y * 128 + x) as usize] = 1; x += step_x; err += 2 * dy; @@ -184,7 +181,7 @@ fn draw_bresenham_line( } } else { for _ in 0..dy { - gfx_buf[(y*128+x) as usize] = 1; + gfx_buf[(y * 128 + x) as usize] = 1; y += step_y; err += 2 * dx; @@ -195,48 +192,39 @@ fn draw_bresenham_line( } } } - } +fn blit_framebuffer(i2c: &mut dyn I2c, graphic: &[u8; 8192]) { + // 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 -fn blit_framebuffer( - i2c: &mut hal::I2C, Pin)>, - graphic: &[u8; 8192]) { + // start assembling the 8x8 cel + for x in 0..8 { + let mut col_byte = 0u8; - // 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 |= graphic[pix_y*128 + pix_x] << y; - } - - cel[x] = col_byte; + // 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 |= graphic[pix_y * 128 + pix_x] << y; } - write_cel_pixels(i2c, &cel); + cel[x] = col_byte; } + write_cel_pixels(i2c, &cel); } - + } } -fn set_col(i2c: &mut hal::I2C, Pin)>, - col: u8) { +fn set_col(i2c: &mut dyn I2c, col: u8) { let col_lo = col & 0b0000_1111; let col_hi = (col & 0b1111_0000) >> 4; @@ -244,54 +232,46 @@ fn set_col(i2c: &mut hal::I2C, Pin, Pin)>, - page: u8) { +fn set_page(i2c: &mut dyn I2c, page: u8) { send_command(i2c, &SH1106Cmd::SetPage, page & 0b0000_0111); } -fn clr_screen(i2c: &mut hal::I2C, Pin)>) { - let mut writebuf = [0u8; 132*8+1]; +fn clr_screen(i2c: &mut dyn I2c) { + 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 hal::I2C, Pin)>, - data: &[u8]) { - +fn write_cel_pixels(i2c: &mut dyn I2c, 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) { - _ => () + _ => (), }; } - -fn send_command(i2c: &mut hal::I2C, Pin)>, - command: &SH1106Cmd, - data:u8) { +fn send_command(i2c: &mut dyn I2c, 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) { - _ => () + _ => (), }; } // static GRAPHIC:[u8;8192] = *include_bytes!("../image.bin"); // static TILES_COMPRESSED:[u8;12800] = *include_bytes!("../kenney_comp.bin"); -// static TILES:[u8;102400] = *include_bytes!("../kenney_mono.bin"); \ No newline at end of file +// static TILES:[u8;102400] = *include_bytes!("../kenney_mono.bin");