pub struct BusTiming { /* private fields */ }Expand description
Tracks bus activity and enforces minimum frame spacing.
Thread-safe: uses AtomicU64 for lock-free timestamp updates.
Pass to crate::ClientOptions::with_bus_timing to activate.
§Frame spacing
- Every bus I/O event (read/write) calls
touchto record the last activity timestamp. - Before sending,
wait_if_neededchecks if enough time has elapsed. If not, it sleeps for the remaining gap.
§Examples
use std::time::Duration;
use oms_modbus::BusTiming;
// RTU 3.5T @ 9600 baud ≈ 4.01ms
let timing = BusTiming::rtu_35t(9600);
// Custom 100ms — for slow devices
let timing = BusTiming::custom(Duration::from_millis(100));Implementations§
Source§impl BusTiming
impl BusTiming
Sourcepub fn custom(min_spacing: Duration) -> Self
pub fn custom(min_spacing: Duration) -> Self
Create with a custom minimum spacing.
use std::time::Duration;
use oms_modbus::BusTiming;
let timing = BusTiming::custom(Duration::from_millis(50));Sourcepub fn rtu_35t(baud_rate: u32) -> Self
pub fn rtu_35t(baud_rate: u32) -> Self
RTU standard 3.5 character times at the given baud rate.
Per MODBUS over Serial Line Specification V1.02 §1.4:
- ≤ 19200 bps:
3.5 × 11 bits / baud_rate(the full formula). - > 19200 bps: fixed minimum of 1.75 ms (1750 µs).
Without the cap, 115200 baud would give only ~334 µs — too short for
real RS-485 transceivers and low-end MCU interrupt latency. Use
rtu_35t_raw if you need the uncapped formula.
| Baud | 3.5T spacing |
|---|---|
| 9600 | ~4.01 ms |
| 19200 | ~2.01 ms |
| 38400 | 1.75 ms |
| 115200 | 1.75 ms |
| 921600 | 1.75 ms |
Sourcepub fn rtu_35t_raw(baud_rate: u32) -> Self
pub fn rtu_35t_raw(baud_rate: u32) -> Self
Raw 3.5 character-time formula at any baud rate — no 1.75 ms cap.
Unlike rtu_35t, this always computes the raw formula,
even at high baud rates where the Modbus spec recommends a fixed
minimum of 1.75 ms. Baud rate 0 is silently clamped to 1.
Use this only if you understand the implications for your specific hardware.
use oms_modbus::BusTiming;
// 115200 baud → ~334 µs (raw formula, no cap)
let timing = BusTiming::rtu_35t_raw(115200);
assert_eq!(timing.min_spacing().as_micros(), 334);Sourcepub fn ascii_35t(baud_rate: u32) -> Self
pub fn ascii_35t(baud_rate: u32) -> Self
ASCII standard 3.5 character times — same timing as RTU.
Sourcepub fn touch(&self)
pub fn touch(&self)
Record bus activity at the current instant.
Call on every I/O read/write to keep the timestamp fresh. Uses a monotonic, syscall-free clock for microsecond timestamps.
Sourcepub async fn wait_if_needed(&self)
pub async fn wait_if_needed(&self)
Wait until the minimum spacing has elapsed since the last touch.
Returns immediately (no sleep) if:
- Enough time has already passed
- No previous activity was recorded (first call)
Sourcepub fn min_spacing(&self) -> Duration
pub fn min_spacing(&self) -> Duration
Current minimum spacing.