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

Using with slint #5

Closed
rsov opened this issue Aug 5, 2024 · 14 comments
Closed

Using with slint #5

rsov opened this issue Aug 5, 2024 · 14 comments

Comments

@rsov
Copy link

rsov commented Aug 5, 2024

Hello, great library!

I am trying to use it with slint on esp32-s3 and I am getting Exception occured 'LoadProhibited' error

The funny thing is, my equivalent implementation of https://github.com/slint-ui/slint/blob/cadfd9e1041214021a375795df9ef96e45d14999/examples/mcu-board-support/esp32_s3_box.rs#L219 is

display.clear();
display.flush().unwrap();

Do you have any ideas why this is happening?

If not, would it be worth while implementing set_pixels method in this driver like it is implemented in this one? https://github.com/almindor/st7789/blob/e18dc571c1e2adb56bf9c6511887845b852f69c6/src/lib.rs#L236

Thank you!

@IniterWorker
Copy link
Owner

Please provide more information:

  • A minimal example to reproduce the issue.
  • A precise request, for example, if you need a feature like set_pixels.

Please do not provide external exceptions such as:

Exception occurred 'LoadProhibited'

At the library level, we cannot support issues caused by other libraries.

What are the requirements for set_pixels when set_pixel is already available with the buffered approach?

pub fn set_pixel(&mut self, x: u32, y: u32, value: u16) {

@rsov
Copy link
Author

rsov commented Aug 5, 2024

I think the key difference between set_pixel is that it changes data in the buffer, while set_pixels writes it straight to the device, line by line

Will try to submit minimal reproduceable example soon

@rsov
Copy link
Author

rsov commented Aug 7, 2024

In progress of stripping down everything, the exception went away but it's not displaying correctly

Here is what is expected:
image

Here is what I get:
Note the little line at the edge changes when background color is changed
image

Branch with code:
https://github.com/rsov/rusty_bucket_face/blob/feature/slint/src/main.rs

I have tried changing rotation and replacing the example fill_contiguous code that yielded same results

for (i, pixel_color) in buffer.iter().enumerate() {
  self.display.set_pixel(i as _, line as _, pixel_color.0);
}

It almost feels like it's either rendering the very last bit or one of the axis is flipped

Any help with this is appreciated

@IniterWorker
Copy link
Owner

@rsov did you/could you display a basic rectangle with embedded_graphics via https://github.com/IniterWorker/esp32-s3-touch-lcd-1-28/blob/d02db8cf16075181fba171390b3d3251ff3f2383/src/main.rs#L34 ?

  1. Try to use the driver standalone, first to validate your setup.
  2. Did you check for memory issues, stack/heap issue with double/triple allocation (slint + gc9a01 Buffered) of the 240*240*size_of(pixel_color) ?

@rsov
Copy link
Author

rsov commented Aug 8, 2024

Yes the example code worked well with direct draw calls

Sorry, I am out of my depth when it comes to embedded environments and rust. What would be some good keywords to search for to get started?

@rsov
Copy link
Author

rsov commented Aug 12, 2024

You may have been on the right track with the double buffering issue

I have forked and added a method to send buffer data directly. It works... but the colors are all wrong and it lost the sharpness. Will see if it's possible to improve it further

https://github.com/rsov/gc9a01/blob/7f5a94657cf327b9a23a1a80a28fe015edc09cdd/src/driver.rs#L287

and i send data to it this way

self.display
        .send_line(&buffer.iter().map(|&x| x.0).collect::<Vec<u16>>())
        .unwrap();

image

@IniterWorker
Copy link
Owner

IniterWorker commented Aug 13, 2024

Please always provide an example. Mainly a color shift from your end with map(|&x| x.0). But, I can't help you without more source.

EDIT

// Pure speculation
use embedded_graphics_core::pixelcolor::raw::RawU16;

self.display
        .send_line(&buffer.iter().map(|&x| RawU16::new(x.0).into()).collect::<Vec<RawU16>>())
        .unwrap();

@IniterWorker
Copy link
Owner

I am implementing the esp32-s3-touch-lcd-1-28 with lvgl. Currently, lvgl provides a specialized trait for drawing lines using embedded_graphics (https://github.com/lvgl/lv_binding_rust/blob/3b3abb3019eef637b932fae967a8d246bf5b6f14/lvgl/src/display.rs#L308).

It seems like a better approach for slint to offer such a trait as well.

@rsov
Copy link
Author

rsov commented Sep 23, 2024

@IniterWorker It does look somewhat similar. I think slint wants to write directly into buffer

I got it to work on my project but haven't had the time to fork your example code and port it there

@rsov
Copy link
Author

rsov commented Sep 25, 2024

@IniterWorker Got the example repo up https://github.com/rsov/esp_s3_touch_lcd_1_28_example_slint

See this commit in driver, gives direct access to the buffer rsov@b1c71fe then it is used here to send data to screen in the example

I can open a PR for it but it does not feel like I have implemented it the correct way

@IniterWorker
Copy link
Owner

IniterWorker commented Sep 25, 2024

Seems like you are missing some commands rsov@b1c71fe like MemoryWrite.

Maybe, I should provide an unbuffered driver to easly customize the driver implementation/usage.

NOTE: You may encouter #8, I will fix this soon.

@rsov
Copy link
Author

rsov commented Sep 27, 2024

So I've tried implementing fill_contiguous method and then using it as it's written in slint docs, going off the work done in this one #8

And it works! 🚀

But UI feels slower compared to just writing it directly like rsov@b1c71fe because you have to flush buffer after each line. And this way doesn't do screen rotation and has endianness issues

I will see if I can make something like this method but public

pub(crate) fn flush_buffer_chunks(

Or this that accepts RBG color

pub fn draw(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {

@IniterWorker
Copy link
Owner

But UI feels slower compared to just writing it directly like rsov@b1c71fe because you have to flush buffer after each line. And this way doesn't do screen rotation and has endianness issues

If you're looking for performance and direct access without buffering, I've made changes to the master branch. Could you please give it a try and provide some feedback?

let mut display_driver = Gc9a01::new(
        interface,
        DisplayResolution240x240,
        DisplayRotation::Rotate180,
    );

I added graphics feature too.

Here is an example with lvgl without BufferedGraphics a.k.a BasicMode.

let buffer = DrawBuffer::<{ 12 * 240_usize }>::default();
let display = Display::register(buffer, 240, 240, |refresh| {
    display_driver
        .fill_contiguous(
            &Rectangle::new(
                Point::new(refresh.area.x1.into(), refresh.area.y1.into()),
                Size::new(
                    (refresh.area.x2 - refresh.area.x1) as u32 + 1,
                    (refresh.area.y2 - refresh.area.y1) as u32 + 1,
                ),
            ),
            refresh
                .as_pixels::<Rgb565>()
                .into_iter()
                .map(|color| color.1),
        )
        .unwrap();
})
.unwrap();

@rsov
Copy link
Author

rsov commented Sep 29, 2024

@IniterWorker Works like a charm!

@rsov rsov closed this as completed Sep 29, 2024
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

No branches or pull requests

2 participants