Struct evegfx::commands::Coprocessor[][src]

pub struct Coprocessor<M: Model, I: Interface, W: Waiter<M, I>> { /* fields omitted */ }

An interface to the command ring buffer for the EVE chip's coprocessor component.

This object encapsulates the handling of the ring buffer and provides an API for appending

Implementations

impl<M: Model, I: Interface, W: Waiter<M, I>> Coprocessor<M, I, W>[src]

The methods which submit new commands into the coprocessor ringbuffer.

These will block using the waiter if they run out of coprocessor buffer space, but they will not wait if there's enough buffer space available to write into.

Although these commands do block for there being sufficient buffer space to write them, they don't wait for the coprocessor to actually execute the instructions, because the goal is for the coprocessor to primarily run concurrently with code on the host processor. However, there are some methods which do block for the completion of certain operations, which all have the name prefix block_ to indicate that.

pub fn ram_ptr(&self, offset: u32) -> Ptr<M::MainMem>[src]

Creates a pointer into the main memory ("RAM_G") area of the EVE address space, with the given offset in bytes.

pub fn new_display_list<F>(&mut self, f: F) -> Result<(), M, I, W> where
    F: FnOnce(&mut Self) -> Result<(), M, I, W>, 
[src]

A convenience function for enclosing a series of coprocessor commands in start_display_list and display_list_swap commands.

The given closure can in principle call all of the same methods as directly on the coprocessor object, but it's best to avoid any action that interacts with anything outside of the coprocessor. It definitely doesn't make sense to recursively call into new_display_list again.

cp.new_display_list(|cp| {
    use evegfx::display_list::Builder; // so trait methods are available
    cp.clear_all()?;

    // ... other display list methods ...

    // The display list should always end with the "display" command.
    cp.display()
}).unwrap();

pub fn trigger_cmdflag_interrupt(
    &mut self,
    delay: Duration
) -> Result<(), M, I, W>
[src]

Wait for at least the given delay and then have the coprocessor trigger the EVE interrupt CMDFLAG.

In a system that's able to respond to interrupts from the EVE chip, you can use this to get a proactive notification when the coprocessor reaches a particular point in the command stream, such as if you are waiting for a particular command to be run before taking some other action that isn't controlled by the EVE coprocessor but must still be synchronized with it.

Use a duration of zero (i.e. Duration::from_millis(0) or similar) to have the coprocessor fire the interrupt immediately on decoding this command, without any extra delay.

If you use a delay of more than 4,294,967 seconds then the delay sent to the EVE chip will saturate at that amount of seconds, due to the physical constraint on number of bits available to express the precision in the protocol.

pub fn cold_start(&mut self) -> Result<(), M, I, W>[src]

Resets the coprocessor's state to the boot-time defaults before continuing with later commands. For example, this discards the currently-selected widget colors and reverts to the default color scheme.

pub fn append_display_list_from_main_mem<S: Into<Slice<M::MainMem>>>(
    &mut self,
    slice: S
) -> Result<(), M, I, W>
[src]

Reads a slice of display list command bytes from a location in the main memory space.

You can use this, for example, to keep various pre-built display list sequences prepared in the main EVE RAM and then efficiently retrieve them into display list memory without having to re-transmit them from host CPU to EVE. However, these commands do ultimately still take real space in the display list memory after the command completes.

The bounds of the given slice must both be addresses that are a multiple of four, to respect the required memory alignment.

pub fn write_register(&mut self, reg: Register, v: u32) -> Result<(), M, I, W>[src]

pub fn write_memory<'a, IntoIter, R>(
    &mut self,
    to: Ptr<R>,
    from: IntoIter
) -> Result<(), M, I, W> where
    IntoIter: IntoIterator<Item = &'a u8>,
    IntoIter::IntoIter: Iterator<Item = &'a u8> + ExactSizeIterator,
    R: MemoryRegion + HostAccessible
[src]

Writes raw data from host memory into locations in the directly-addressable part of the EVE memory space.

You can provide the data as any type that can convert to an exact-size iterator for u8, which includes slices of u8 but you could also supply other iterables in order to generate data progressively, rather than buffering it all in memory. However, the result must always have a length that can fit inside a u32, because that's the maximum size supported by EVE.

// Write the byte string "hello world" to memory
// address zero.
cp.write_memory(
    cp.ram_ptr(0),
    b"hello world",
).unwrap();

This is similar to writing memory with the LowLevel API, but having the coprocessor do it means that you can synchronize memory writes with other actions the coprocessor is taking, such as in conjunction with wait_video_scanout to do writes synchronized with the framerate.

Don't use this method to write over memory areas related to the coprocessor ring buffer, because that will likely cause the internal state of the Coprocessor object to become invalid.

pub fn write_memory_inflate<'a, IntoIter, R>(
    &mut self,
    to: Ptr<R>,
    from: IntoIter
) -> Result<(), M, I, W> where
    IntoIter: IntoIterator<Item = &'a u8>,
    IntoIter::IntoIter: Iterator<Item = &'a u8>,
    R: MemoryRegion + HostAccessible
[src]

Similar to write_memory, but for compressed data.

If your host has data compressed using the deflate algorithm (e.g. using zlib) then it can stream that data in compressed form and have the coprocessor "inflate" the data back into its original form while writing it into main memory. This can both reduce data overhead in the host program and reduce the time taken to stream the data into EVE.

The number of bytes written to main memory by this function will depend on the content of the deflate stream. The application is expected to know the original size of the compressed data in order to determine the final bounds of the written data.

All of the same usage concerns from write_memory apply here too, with the addition of the requirement that the data must be a valid deflate stream to avoid a coprocessor fault.

pub fn write_memory_image<'a, IntoIter, R>(
    &mut self,
    to: Ptr<R>,
    from: IntoIter,
    opts: LoadImage
) -> Result<(), M, I, W> where
    IntoIter: IntoIterator<Item = &'a u8>,
    IntoIter::IntoIter: Iterator<Item = &'a u8>,
    R: MemoryRegion + HostAccessible
[src]

Similar to write_memory, but specifically for JPEG or PNG images.

The number of bytes written to main memory by this function will depend on the content of the image. The application is expected to know the dimensions and pixel format of the image to predict the final bounds of the written data.

All of the same usage concerns from write_memory apply here too, with the addition of the requirement that the data must be a valid deflate stream to avoid a coprocessor fault.

pub fn show_testcard(&mut self) -> Result<(), M, I, W>[src]

pub fn start_spinner(&mut self) -> Result<(), M, I, W>[src]

pub fn start_display_list(&mut self) -> Result<(), M, I, W>[src]

Sends just the coprocessor command to start a new display list, which waits for the display list memory to become writable before executing any subsequent commands and resets the pointer for new display list commands back to the top of display list memory.

It's generally more convenient to use new_display_list, which handles both starting the display list and swapping it to be visible all in a single method call.

pub fn display_list_swap(&mut self) -> Result<(), M, I, W>[src]

Sends just the coprocessor command to swap in the newly-populated display list commands.

It's generally more convenient to use new_display_list, which handles both starting the display list and swapping it to be visible all in a single method call.

pub fn draw_button<Rect: Into<WidgetRect>>(
    &mut self,
    rect: Rect,
    msg: Message<'_, '_, M::MainMem>,
    font: FontRef,
    options: Button
) -> Result<(), M, I, W>
[src]

pub fn draw_text<Pos: Into<WidgetPos>>(
    &mut self,
    pos: Pos,
    msg: Message<'_, '_, M::MainMem>,
    font: FontRef,
    options: Text
) -> Result<(), M, I, W>
[src]

Direct the coprocessor to generate coprocessor commands to render a text message.

use evegfx::commands::options;
use options::Options;

let name_addr = cp.ram_ptr(0);
cp.write_memory(name_addr, b"world\0");
cp.draw_text(
    (100, 100),
    evegfx::format!("hello %s", name_addr),
    options::FontRef::new_raw(18),
    options::Text::new(),
);

This command supports EVE-side text formatting, so the message is provided as the result of the evegfx::format! macro, which understands EVE's printf-like formatting syntax enough to provide a strongly-typed interface.

pub fn append_display_list(&mut self, cmd: DLCmd) -> Result<(), M, I, W>[src]

pub fn append_raw_word(&mut self, word: u32) -> Result<(), M, I, W>[src]

pub fn wait_microseconds(&mut self, delay: u32) -> Result<(), M, I, W>[src]

pub fn wait_video_scanout(&mut self) -> Result<(), M, I, W>[src]

impl<M: Model, I: Interface, W: Waiter<M, I>> Coprocessor<M, I, W>[src]

The methods which block until the coprocessor has "caught up" with particular events.

These make use of the associated "waiter" to block until specific coprocessor commands have completed, and so applications making heavy use of these may wish to consider supplying a tailored waiter implementation that can avoid busy-waiting.

pub fn space_when_empty() -> u16[src]

pub fn block_until_idle(&mut self) -> Result<(), M, I, W>[src]

Blocks until the coprocessor buffer is empty, signalling that the coprocessor has completed all of the commands issued so far.

pub fn block_until_video_scanout(&mut self) -> Result<(), M, I, W>[src]

Blocks until EVE has finished scanning out the current frame. Callers can use this as part of a main loop which takes actions synchronized with the video framerate.

This is a blocking version of wait_video_scanout.

pub fn block_read_register(&mut self, reg: Register) -> Result<u32, M, I, W>[src]

Blocks until the coprocessor has completed all of the commands issued so far and then returns the value of the given system register.

You can use this in situations where earlier coprocessor commands may have modified the register value, in order to capture that result at the correct time.

pub fn block_for_memory_crc<R, S>(&mut self, region: S) -> Result<u32, M, I, W> where
    R: MemoryRegion,
    S: Into<Slice<R>>, 
[src]

Blocks until the coprocessor has completed all of the commands issued so far and then calculates the CRC32 checksum of the memory covered by the given slice.

impl<M: Model, I: Interface, W: Waiter<M, I>> Coprocessor<M, I, W>[src]

pub fn new(ei: I, wait: W) -> Result<Self, M, I, W>[src]

Consumes the given interface and waiter and returns an interface to the coprocessor via the given interface.

This function consumes the interface because it will be constantly writing into the command ring buffer of the associated EVE chip and so it isn't safe to do any other concurrent access. You can get the underlying interface back again if you need it using some of the methods of Coprocessor.

pub fn with_new_waiter<W2, F>(self, f: F) -> Coprocessor<M, I, W2> where
    W2: Waiter<M, I>,
    F: FnOnce(W) -> W2, 
[src]

Consumes the current coprocessor object and then returns a new one that's the same except that it has a new waiter, which is possibly derived from the previous one.

The main goal here is to allow replacing the waiter with a wrapper implementation that does additional logging or tracking of waiting, if needed for debugging or development, without needing to first determine what kind of waiter the object previously had.

pub fn take_interface(mut self: Self) -> Result<I, M, I, W>[src]

take_interface consumes the coprocessor object and returns its underlying Interface.

To make temporary use of the underlying interface, without also discarding the coprocessor object, use with_interface instead.

pub fn with_interface<R, F: FnOnce(&mut I) -> Result<R, M, I, W>>(
    &mut self,
    f: F
) -> Result<R, M, I, W>
[src]

with_interface runs your given closure with access to the coprocessor object's underlying Interface, temporarily pausing local coprocessor management so the closure can make use of other chip functionality.

impl<M: Model, I: Interface> Coprocessor<M, I, PollingWaiter<M, I>>[src]

pub fn new_polling(ei: I) -> Result<Self, M, I, PollingWaiter<M, I>>[src]

Consumes the given interface and returns an interface to the coprocessor via the given interface, which will use busy-polling to wait when there isn't enough buffer space.

If your platform allows you to detect the EVE coprocessor space interrupt then you might prefer to call new and pass a custom waiter that can put your main processor to sleep while waiting, for better power usage compared to the default busy-polling implementation.

impl<M, I, W> Coprocessor<M, I, W> where
    M: Model + WithCommandErrMem,
    I: Interface,
    W: Waiter<M, I>, 
[src]

These methods are available only when working with a model that has a coprocessor error message memory space.

pub fn coprocessor_fault_msg(
    &mut self
) -> Result<FaultMessage<M::CommandErrMem>, M, I, W>
[src]

Returns the fault message currently available in the EVE coprocessor's fault message memory space.

It's only meaningful to call this immediately after another coprocessor method returns the error variant Fault, before submitting any other coprocessor commands.

The format of the returned message is determined entirely by the EVE chip, though it is typically a sequence of bytes representing an ASCII string.

impl<M, I, W> Coprocessor<M, I, W> where
    M: Model + WithCommandErrMem,
    I: Interface,
    W: Waiter<M, I>, 
[src]

These methods are available only when working with a model that allows selecting coprocessor API level 1.

That doesn't include the BT815 and BT816 models: even though they do support the API now referred to as API level 1, they don't support selecting that version because the idea of API levels was introduced only with the BT817 and BT818 models.

pub fn use_api_level_1(&mut self) -> Result<(), M, I, W>[src]

On models that support multiple API levels, this selects API level 1 which aims to be backward-compatible with the BT815 and BT816 models.

impl<M, I, W> Coprocessor<M, I, W> where
    M: Model + WithCommandErrMem,
    I: Interface,
    W: Waiter<M, I>, 
[src]

These methods are available only when working with a model that allows selecting coprocessor API level 2.

pub fn use_api_level_2(&mut self) -> Result<(), M, I, W>[src]

On models that support multiple API levels, this selects API level 1 which aims to be backward-compatible with the BT815 and BT816 models.

There is no type-system-level enforcement that API level 2 is enabled before using API level 2 features, as a measure of pragmatism to avoid making the typestates of Coprocessor even more complex than they already are. If you try to use API level 2 features without first calling this method then the resulting behavior is undefined.

Trait Implementations

impl<M, I, W> Builder for Coprocessor<M, I, W> where
    M: Model,
    I: Interface,
    W: Waiter<M, I>, 
[src]

type Error = Error<M, I, W>

type Model = M

Auto Trait Implementations

impl<M, I, W> Send for Coprocessor<M, I, W> where
    I: Send,
    M: Send,
    W: Send,
    <M as Model>::DisplayListMem: Send
[src]

impl<M, I, W> Sync for Coprocessor<M, I, W> where
    I: Sync,
    M: Sync,
    W: Sync,
    <M as Model>::DisplayListMem: Sync
[src]

impl<M, I, W> Unpin for Coprocessor<M, I, W> where
    I: Unpin,
    M: Unpin,
    W: Unpin,
    <M as Model>::DisplayListMem: Unpin
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.