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

help wanted: embedded-graphics driver #22

Closed
jamesmunns opened this issue Jul 16, 2022 · 5 comments
Closed

help wanted: embedded-graphics driver #22

jamesmunns opened this issue Jul 16, 2022 · 5 comments
Labels
meta: good first issue Good for newcomers meta: help wanted Extra attention is needed

Comments

@jamesmunns
Copy link
Contributor

The goal is to have a basic "framebuffer driver" for mnemos.

I think this would work something like:

  • use the embedded graphics simulator, or similar sdl2/web tech to build a gui window
  • use embedded-graphics (and maybe embedded-text) as graphics primitives
  • provide some kind of interface to draw to the frame buffer, such as:
    • providing an X/Y start coord, and a rectangle to be painted on to the frame buffer
    • provide a way to provide a "full frame update" (this might just be the other option starting at (0, 0) and fully sized).

I think mostly, you'll want a "whole framebuffer", say 800x600, and you should take smaller rectangle chunks of arbitrary size, and draw them to the frame buffer. This way your "demo task" can draw something like a 320x240 chunk using embedded-graphics, and just paint that on to the large, "dumb" framebuffer.

To do this, you will likely need to do the following (short summary):

  1. Add a new driver to the kernel that owns the frame buffer and whatever window context that needs to exist.
  2. Define a message type for sending update commands.
  3. Process incoming commands, update the framebuffer, redraw the framebuffer whenever updated
  4. Provide some kind of demo that draws something, or does an animation, or takes data from a virtual port or something and draws it

Longer summary:

make a driver

misc note: The simulator is called "melpomene". You can find it in source/melpomene. You can run it with MELPOMENE_TRACE=trace cargo run. You'll see a lot of tracing events there. If you want to see a lot more, check out this comment which will show you how to run the virtual serial ports that are already working in the simulator.

Drivers in mnemos are basically just async tasks. "real drivers" should be self contained, but for the simulator, you can use whatever. You can spawn threads if you want, and we also have a tokio runtime going that provides sleep and uart stuff.

Check out the sim drivers folder for simulator specific drivers, and kernel drivers for real drivers. You'll probably want to use the Heap types to allocate your frame buffer.

Don't worry about getting any of this perfect yet.

Once you have a driver, you'll probably need to set it up in the initialization function, and spawn it into the kernel's executor. Check out [kernel_entry()](

fn kernel_entry() {
) in melpo for how other tasks do this. You might also need to modify how much memory is given to the kernel at initialization. Go ahead and bump it to like 16MiB or whatever you need.

Define message types

mnemos has two main communication channels you'll see. One is stream based, and that's all the ones you see called bbq. I don't think you'll need those for this. The other one is basically an MPSC async queue, called KChannel. You can basically create a kchannel that contains your type (and optionally a "reply" channel producer), and define whatever message types you want. Since it'll probably be relatively "big" buffers, your message should probably also use heap types for this.

You can see an example of a message type in the serial_mux driver, and how a kchannel is used in the current main task.

You might want to have something like a FrameChunk, which holds an appropriately sized heap allocation, and implements that DrawTarget trait from e-g.

This way you could do something like:

// this makes a 320 x 240 x 2 allocation to act as a 16bpp frame chunk
let mut new_frame = FrameChunk::new(320, 240).await;
// This uses e-g methods to paint this sub-frame
Circle::new(...)
    .whatever(...)
    .eg(...)
    .methods(...)
    .draw(&mut new_frame).unwrap();
// send the sub-frame over the kchannel
driver_producer.send(Command::Draw { x: 0, y: 100, chunk: new_frame }).await.unwrap();

Process incoming commands

Again, the serial mux driver is a good example of accepting messages and doing stuff with them. Here you will do whatever your framebuffer logic stuff is.

Provide some kind of demo

Right now, userspace isn't up and running. So just define some async demo task (in melpo's main, or somewhere else), that holds the new driver's kchannel producer, and draw something every 1 second or so.

@jamesmunns jamesmunns added meta: good first issue Good for newcomers meta: help wanted Extra attention is needed labels Jul 16, 2022
@Dajamante
Copy link

Tentatively claiming point 1. about the new driver.

@arunvijayshankar
Copy link
Contributor

Claiming message type definitions.

@jamesmunns
Copy link
Contributor Author

Thanks @Dajamante and @arunvijayshankar! Let me know if I can help or answer any questions (or write any docs). Happy to help y'all succeed!

@arunvijayshankar
Copy link
Contributor

hey @Dajamante, @jamesmunns, I was wondering, if instead of the driver owning the embedded-graphics window contexts, we could have e-g simulator run as a separate task? I was thinking the driver could spawn this task as part of a init_display function. The e-g task would own the window, and the driver could talk to it on a kchannel as if it were an actual display. This might make it easier to adapt the driver for a physical device in the future. What do you think?

@jamesmunns
Copy link
Contributor Author

Closed by #35, thanks y'all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
meta: good first issue Good for newcomers meta: help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants