Skip to main content

EpidFastDeviceSupport

Struct EpidFastDeviceSupport 

Source
pub struct EpidFastDeviceSupport { /* private fields */ }
Expand description

Fast Epid device support using asyn driver for high-speed (1+ kHz) PID.

Ported from devEpidFast.c. The PID computation runs in a background tokio task driven by asyn interrupt callbacks, not during record processing. The record merely copies parameters to/from the fast computation thread.

§Architecture

┌─────────────┐    interrupt     ┌──────────────────┐
│ asyn driver  │ ──────────────► │ PID callback task │
│ (input ADC)  │    (new cval)   │  (tokio::spawn)   │
└─────────────┘                  │  runs do_pid()    │
                                 │  writes output    │
      ┌──────────────────────────┤  to output driver │
      │  shared EpidFastPvt      └──────────────────┘
      │  (Arc<Mutex>)                    ▲
      ▼                                  │
┌─────────────┐  read()         params   │
│ EpidRecord   │ ◄─────── copy ──────────┘
│ (process)    │ ────────► copy ──────────►
└─────────────┘  results

The start_callback_loop() method spawns the background task. Call it after connecting to the asyn input port.

Implementations§

Source§

impl EpidFastDeviceSupport

Source

pub fn new() -> Self

Source

pub fn pvt(&self) -> Arc<Mutex<EpidFastPvt>>

Get a handle to the shared PID state for callback registration.

Source

pub fn set_output_reader( &self, reader: Arc<Mutex<dyn FnMut() -> Option<f64> + Send>>, )

Wire the output-port readback used for bumpless transfer.

C devEpidFast.c:446-448 reads the actual current output value (pfloat64Output->read) on the feedback OFF->ON edge to seed the integral term. Supply a closure that returns the output port’s current value; without it the bumpless edge falls back to the last commanded OVAL.

Source

pub fn set_output_port(&self, sync_io: SyncIOHandle, reason: usize)

Wire the asyn output port: install both the output writer and the bumpless-transfer output reader from a single asyn Float64 port handle.

This mirrors C devEpidFast.c exactly. init_record (devEpidFast.c:264-303) connects to one output asyn port and captures pPvt->pfloat64Output / float64OutputPvt. do_PID then uses that same interface for both directions:

  • the bumpless OFF->ON edge reads the output port’s present value — pPvt->pfloat64Output->read(...) (devEpidFast.c:446-448);
  • the feedback write — pPvt->pfloat64Output->write(...) (devEpidFast.c:471-473).

sync_io is the asyn Float64 output port handle and reason the parameter index (asyn drvUser “outputDataString” channel, devEpidFast.c:296-303). The reader calls read_float64(reason) on it; a failed read yields None, so do_pid falls back to the last commanded OVAL safety net.

Source

pub fn start_callback_loop( &self, input_rx: Receiver<f64>, output_fn: Arc<Mutex<dyn FnMut(f64) + Send>>, )

Start the interrupt-driven PID callback loop.

Spawns a tokio task that receives new readback values from input_rx and runs do_pid() on each. This is the high-speed PID path that runs at the interrupt rate (1kHz+), independent of record processing.

input_rx: receives new controlled-variable values from the input driver output_fn: called with each new output value (writes to output driver)

This bare-closure form leaves the bumpless-transfer output_reader untouched — wire it separately with set_output_reader or set_output_port, otherwise the OFF->ON edge falls back to the last commanded OVAL. When the output is a real asyn Float64 port, prefer start_callback_loop_with_port, which installs both writer and reader from the same port handle (mirroring C devEpidFast.c pPvt->pfloat64Output).

Source

pub fn start_callback_loop_with_port( &self, input_rx: Receiver<f64>, output_sync_io: SyncIOHandle, output_reason: usize, )

Start the PID callback loop driven by an asyn Float64 output port.

Identical to start_callback_loop but takes the output asyn port handle directly and installs both the output writer and the bumpless-transfer output reader from it via set_output_port — mirroring C devEpidFast.c init_record, which captures a single pPvt->pfloat64Output interface and uses it for both read (devEpidFast.c:446-448) and write (devEpidFast.c:471-473).

output_sync_io is the asyn Float64 output port handle and output_reason the parameter index for the output channel.

Source

pub fn start_from_asyn_interrupts( &self, interrupt_rx: Receiver<InterruptValue>, input_reason: usize, output_fn: Arc<Mutex<dyn FnMut(f64) + Send>>, )

Start from an asyn interrupt subscription.

Subscribes to Float64 interrupts from the given broadcast sender and feeds them into the PID callback loop.

This bare-closure form leaves the bumpless-transfer output_reader untouched — wire it separately with set_output_reader or set_output_port, or use start_from_asyn_interrupts_with_port to install both writer and reader from one asyn output port.

Source

pub fn start_from_asyn_interrupts_with_port( &self, interrupt_rx: Receiver<InterruptValue>, input_reason: usize, output_sync_io: SyncIOHandle, output_reason: usize, )

Start from an asyn interrupt subscription, driven by an asyn Float64 output port.

Identical to start_from_asyn_interrupts but takes the output asyn port handle directly and installs both the output writer and the bumpless-transfer output reader from it via set_output_port — mirroring C devEpidFast.c init_record, which captures a single pPvt->pfloat64Output interface and uses it for both read (devEpidFast.c:446-448) and write (devEpidFast.c:471-473).

Trait Implementations§

Source§

impl Default for EpidFastDeviceSupport

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl DeviceSupport for EpidFastDeviceSupport

Source§

fn dtyp(&self) -> &str

Source§

fn read(&mut self, record: &mut dyn Record) -> CaResult<DeviceReadOutcome>

Read from hardware into the record. Read more
Source§

fn write(&mut self, _record: &mut dyn Record) -> CaResult<()>

Source§

fn init(&mut self, _record: &mut (dyn Record + 'static)) -> Result<(), CaError>

Source§

fn last_alarm(&self) -> Option<(u16, u16)>

Return the last alarm (status, severity) from the driver. None means the driver does not override alarms.
Source§

fn last_timestamp(&self) -> Option<SystemTime>

Return the last timestamp from the driver. None means the driver does not override timestamps.
Source§

fn set_process_context(&mut self, _ctx: &ProcessContext)

Called by the framework immediately before read() to push a read-only snapshot of framework-owned CommonFields state (crate::server::record::ProcessContext) that the device support needs. Read more
Source§

fn set_record_info(&mut self, _name: &str, _scan: ScanType)

Called after init() with the record name and scan type.
Source§

fn apply_record_info(&mut self, _info: &HashMap<String, String>)

Forward parsed info("key", "value") directives from the .db file to the device support. Default is a no-op; drivers that react to specific tags (asyn asyn:READBACK, EtherCAT terminal hints, etc.) override this. Called once after set_record_info during builder wiring; not called again at runtime.
Source§

fn io_intr_receiver(&mut self) -> Option<Receiver<()>>

Return a receiver for I/O Intr scan notifications. Only called for records with SCAN=I/O Intr.
Source§

fn write_begin( &mut self, _record: &mut (dyn Record + 'static), ) -> Result<Option<Box<dyn WriteCompletion>>, CaError>

Begin an asynchronous write (submit only, no blocking). Returns Some(handle) if the write was submitted to a worker queue — the caller should wait on the handle outside any record lock. Returns None to fall back to synchronous write().
Source§

fn handle_command( &mut self, _record: &mut (dyn Record + 'static), _command: &str, _args: &[EpicsValue], ) -> Result<Vec<&'static str>, CaError>

Handle a named command from the record’s process() via ProcessAction::DeviceCommand. This allows records to request driver operations (e.g., scaler reset/arm/write_preset) without holding a direct driver reference. Read more

Auto Trait Implementations§

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> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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>,

Source§

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>,

Source§

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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more