pub struct Controller<R: RawMutex + 'static, const IN: usize = INCOMING_SIZE, const OUT: usize = OUTGOING_SIZE> { /* private fields */ }
Expand description

Controller interface and data storage

The static Controller is intended to be used in two separate places in an application:

  1. In one place, where Controller::step() is called periodically, to service bus operations
  2. In another place, where Controller::recv_from() or Controller::send() are called, to process or forward messages to/from the bus

In a typical example where the Controller is acting as a Bridge/Router over USB, place 1. would be a standalone task, calling step at some periodic polling rate, and place 2. would be grouped with the USB interface for sending/receiving frames over USB.

The Controller contains an async Mutex which provides interior mutable access to information such as the table of connected Targets, or any “in flight” messages.

Implementations§

source§

impl<R: RawMutex + 'static, const IN: usize, const OUT: usize> Controller<R, IN, OUT>

Instantiation and Initialization methods

source

pub const fn uninit() -> Controller<R, IN, OUT>

Create a new, uninitialized controller structure

Intended to be used to create as a static to avoid large stack initializations.

Users must still call Controller::init() before use.

use erdnuss_comms::controller::Controller;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;

// NOTE: you can use any mutex suitable for you, such as `ThreadModeRawMutex`
// if you not using this from an interrupt context
static CONTROLLER: Controller<CriticalSectionRawMutex> = Controller::uninit();
source

pub async fn init(&self, sli: &mut RawFrameSlice)

Initialize the Controller

This initialization provides the backing storage for the incoming target frames. RawFrameSlice must contain AT LEAST IN times OUT frame storage slots. sli’s capacity will be reduced by this amount.

source§

impl<R: RawMutex + 'static> Controller<R>

Bus management and operation method(s)

source

pub async fn step<T, Rand>( &self, serial: &mut T, rand: &mut Rand ) -> Result<(), Error<T::SerError>>
where T: FrameSerial, Rand: RngCore,

Perform one “step” of the bus

One call to step will:

  1. Send UP TO one message to any known Targets, and Receive UP TO one message from any known Target
  2. Attempt to complete any pending logical address offers
  3. Attempt to offer UP TO one unused logical address

This method should be called regularly.

The serial and rand resources are passed in on every call to step, rather than making them part of the entire Controller entity for a couple of stylistic reasons:

  • Keep the static type-generics less complex
  • Make initialization less complex
  • Make these generics NOT required for the shared send/recv_from interface methods

The inner async mutex will be locked for the entire duration of the call to step, which may be held for some amount of time, depending on the number of bus timeouts and total amount of data transferred. This may be on the order of millisecond(s).

source§

impl<R: RawMutex + 'static> Controller<R>

Bus I/O methods

source

pub async fn send(&self, mac: u64, frame: SendFrameBox) -> Result<(), SendError>

Attempt to enqueue a message for sending

source

pub async fn recv_from(&self, mac: u64) -> Result<WireFrameBox, RecvError>

Attempt to receive a message from the given unique address

source

pub async fn connected(&self) -> Vec<u64, { _ }>

Get a list of all target devices on the bus

This list DOES NOT include the Controller’s MAC address, but the returned heapless::Vec does reserve enough room to contain all MAX_TARGETS plus one.

Auto Trait Implementations§

§

impl<R, const IN: usize = INCOMING_SIZE, const OUT: usize = OUTGOING_SIZE> !RefUnwindSafe for Controller<R, IN, OUT>

§

impl<R, const IN: usize, const OUT: usize> Send for Controller<R, IN, OUT>
where R: Send,

§

impl<R, const IN: usize, const OUT: usize> Sync for Controller<R, IN, OUT>
where R: Sync,

§

impl<R, const IN: usize, const OUT: usize> Unpin for Controller<R, IN, OUT>
where R: Unpin,

§

impl<R, const IN: usize, const OUT: usize> UnwindSafe for Controller<R, IN, OUT>
where R: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

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

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.