rust-embedded-community / ssd1306

SSD1306 OLED driver
Apache License 2.0
300 stars 68 forks source link

wrong part of the screen is updated for Rotate180 and <128 wide screens #138

Closed martin2250 closed 3 years ago

martin2250 commented 3 years ago

Hi James,

I've run into an issue with setting the rotation of the OLED. It seems that for DisplayRotation::Rotate180, the wrong part of the display is updated (approx. 128-96=32 columns at the right side of the screen contain only random noise). I don't have a good debugging setup here for fixing this, so I hope you can reproduce this bug and help me out :)

Cheers! Martin

image

#![no_main]
#![no_std]

use panic_halt as _;
use cortex_m_rt::entry;

use stm32f0xx_hal as hal;

use crate::hal::{
    stm32,
    prelude::*,
    i2c::I2c,
};

use embedded_graphics::{
    fonts::{Font6x8, Text},
    pixelcolor::BinaryColor,
    prelude::*,
    style::{TextStyle, TextStyleBuilder},
};

use ssd1306::{prelude::*, Builder, I2CDIBuilder, displayrotation::DisplayRotation};

#[entry]
fn main() -> ! {
    let mut p = stm32::Peripherals::take().unwrap();
    let mut cp = cortex_m::Peripherals::take().unwrap();

    cortex_m::interrupt::free(move |cs| {
        let mut flash = p.FLASH;
        let mut rcc = p.RCC.configure().freeze(&mut flash);

        let gpioa = p.GPIOA.split(&mut rcc);
        let gpiob = p.GPIOB.split(&mut rcc);
        let gpioc = p.GPIOC.split(&mut rcc);

        let mut delay = hal::delay::Delay::new(cp.SYST, &rcc);
        // lcd reset pin
        let mut lcd_rst = gpioa.pa10.into_open_drain_output(cs);

        // Configure pins for I2C
        let scl = gpiob.pb6.into_alternate_af1(cs);
        let sda = gpiob.pb7.into_alternate_af1(cs);

        let mut i2c = I2c::i2c1(p.I2C1, (scl, sda), 100.khz(), &mut rcc);

        let interface = I2CDIBuilder::new().init(i2c);
        let mut disp: GraphicsMode<_, DisplaySize96x16> = Builder::new().size(DisplaySize96x16).connect(interface).into();
        disp.reset(&mut lcd_rst, &mut delay).unwrap();
        disp.init().unwrap();
        disp.set_rotation(DisplayRotation::Rotate180).unwrap();
        disp.flush().unwrap();
        disp.clear();
        disp.flush().unwrap();

        let text_style = TextStyleBuilder::new(Font6x8)
        .text_color(BinaryColor::On)
        .build();

        Text::new("Hello world!", Point::zero())
            .into_styled(text_style)
            .draw(&mut disp)
            .unwrap();

        disp.flush().unwrap();

        let btn = gpioa.pa3.into_pull_down_input(cs);
        loop {
            if btn.is_high().unwrap() {
                cortex_m::peripheral::SCB::sys_reset();
            }
        }
    });

    loop {}
}
jamwaffles commented 3 years ago

Thanks for the bug report, especially with a test case attached! I'll try and reproduce this on my end when I have a few minutes spare.

martin2250 commented 3 years ago

Did some more tinkering, this fixed it (src/mode/graphics.rs):

image

Now this only needs to be selected automatically somehow

bugadani commented 3 years ago

It would help if someone who has a 72x40 could figure out the offsets necessary for a fix. (I bet that's wrong as well and I would like to not having to guess how the horizontal offset value should be taken into account without having the display myself)