Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial draft of hw accel primitives #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

sthornington
Copy link

Hiya - here's an implementation of draw_hw_line and draw_hw_rect. I'm not sure it's really superior in any way to the buffered scheme currently in use, there are so few pixels on these displays anyway. If you think it might be helpful to implement delta updates of the buffer then maybe it would be useful?

The delay on the filled rectangles is also pretty annoying, 10us covered it for a handful of tests for me, could probably be less.

Copy link
Collaborator

@jamwaffles jamwaffles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far! I don't have much free time at the moment, but I'll try and get round to testing this on real hardware asap.

/// hardware acceleration. This does no bounds checking.
pub fn draw_hw_line(&mut self, x1: u32, y1: u32, x2: u32, y2: u32, value: u16
) -> Result<(), Error<CommE, PinE>> {
// TODO: should we try to clip the line to the display here? that could be tricky.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What behaviour does the display have in clipping cases? If it goes offscreen and doesn't do anything like wrapping around, it should be fine to not bother clipping. Presumably this also applies to draw_hw_rect too.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok do we need to clip, or just abort, if any of it is off-screen? I am unfamiliar with what is the standard for these drivers.

Also, generally, do you think this is going to be helpful? I am still on the fence, since mixing blit and hw accel causes noticeable flashing (at least on my softcore).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't done anything using both blitting and HW accel, so I can't comment on that. The draw_hw_rect method may be useful for the new embedded-graphics 0.7 features so would be worth keeping in IMO, although I can see complications arising when using both HW and the software buffer in this driver.

@jamwaffles
Copy link
Collaborator

I found some issues when testing on hardware. What the test pattern should look like:

image

Drawing rectangles off the right of the screen causes them to wrap back round:

image

And drawing lines out of bounds does this weird thing:

image

The display is also not cleared of HW drawn items when it's reset, so that we should probably add that in somewhere too.

@jamwaffles
Copy link
Collaborator

Complete example code for the tests above is:

#![no_std]
#![no_main]

use cortex_m_rt::{entry, exception, ExceptionFrame};
use panic_semihosting as _;
use ssd1331::{DisplayRotation::Rotate0, Ssd1331};
use stm32f1xx_hal::{
    delay::Delay,
    prelude::*,
    spi::{Mode, Phase, Polarity, Spi},
    stm32,
};

#[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, Rotate0);

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

    let white = 0xffff;
    let red = 0xf800;
    let green = 0x07e0;
    let blue = 0x001f;

    let h_x = 96 / 2;
    let h_y = 64 / 2;

    disp.draw_hw_rect(5, 5, 15, 15, white, Some(white), &mut delay);
    disp.draw_hw_rect(10, 10, 20, 20, red, Some(red), &mut delay);
    disp.draw_hw_rect(15, 15, 25, 25, green, Some(green), &mut delay);
    disp.draw_hw_rect(20, 20, 30, 30, blue, Some(blue), &mut delay);

    // // Goes off the right edge of the screen
    // disp.draw_hw_rect(101, 5, 15, 15, white, Some(white), &mut delay);
    // disp.draw_hw_rect(106, 10, 20, 20, red, Some(red), &mut delay);
    // disp.draw_hw_rect(111, 15, 25, 25, green, Some(green), &mut delay);
    // disp.draw_hw_rect(116, 20, 30, 30, blue, Some(blue), &mut delay);

    disp.draw_hw_line(5, 5, 91, 59, white);
    disp.draw_hw_line(91, 5, 5, 59, red);
    disp.draw_hw_line(h_x, 5, h_x, 59, green);
    disp.draw_hw_line(5, h_y, 91, h_y, blue);

    // // Completely off screen lines
    // disp.draw_hw_line(5 + 100, 5 + 100, 91 + 100, 59 + 100, white);
    // disp.draw_hw_line(91 + 100, 5 + 100, 5 + 100, 59 + 100, red);
    // disp.draw_hw_line(h_x + 100, 5 + 100, h_x + 100, 59 + 100, green);
    // disp.draw_hw_line(5 + 100, h_y + 100, 91 + 100, h_y + 100, blue);

    // NOTE: Flush will replace any HW-drawn pixels with the current buffer data.

    loop {}
}

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

@sthornington
Copy link
Author

I haven't forgotten about this, just moved (again). I hope to update this PR soon per your comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants