eth-phy-lan867x 0.1.0

LAN8670/8671/8672 10BASE-T1S Ethernet PHY driver for no_std over MDIO
Documentation
// SPDX-License-Identifier: GPL-2.0-or-later OR Apache-2.0
// Copyright (c) Viacheslav Bocharov <v@baodeep.com> and JetHome (r)

//! PLCA (Physical Layer Collision Avoidance) configuration types.
//!
//! `PlcaConfig` is the input to `PhyLan867x::configure_plca`,
//! `PlcaStatus` the output of `PhyLan867x::plca_status`, and
//! `PlcaError` the error type shared by `configure_plca`,
//! `disable_plca`, and `plca_status`. The methods themselves are
//! implemented on `PhyLan867x` in `lib.rs`.

/// PLCA configuration (IEEE 802.3 Clause 148).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PlcaConfig {
    /// Local node ID. `0` = bus coordinator (must be exactly one on the
    /// segment), `1..=0xFE` = follower.
    ///
    /// `0xFF` is rejected by `configure_plca` — the silicon uses it as
    /// a sentinel that disables PLCA, so the driver refuses to write it
    /// via the configure path. Use `disable_plca` instead.
    pub node_id: u8,
    /// Total node count on the segment (`NCNT`). Must be ≥ active node
    /// count. Only the coordinator strictly cares about this; followers
    /// may set it to 0 and still operate, but supplying the right number
    /// makes diagnostics meaningful on every node.
    pub node_count: u8,
    /// Burst-mode max additional packets per transmit opportunity.
    /// `0` = burst disabled (one frame per TXOP — Clause 148 default).
    pub burst_count: u8,
    /// Burst timer in BT (100 ns units). `0` is a sentinel meaning
    /// "use the chip default" (`0x80` = 128 BT) — `configure_plca`
    /// substitutes `0x80` before writing `PLCA_BURST.BTMR`.
    ///
    /// Note: the chip's `BTMR` field is always written as part of
    /// `PLCA_BURST` regardless of `burst_count`. The silicon honours
    /// `BTMR` only when `MAXBC > 0` (i.e. burst is actually enabled),
    /// so a non-zero `burst_timer` with `burst_count == 0` is harmless
    /// — it lands in the register but never gates a TXOP.
    pub burst_timer: u8,
}

impl Default for PlcaConfig {
    /// Coordinator with an 8-node segment, no burst.
    fn default() -> Self {
        Self {
            node_id: 0,
            node_count: 8,
            burst_count: 0,
            burst_timer: 0,
        }
    }
}

/// PLCA runtime state.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PlcaStatus {
    /// PLCA reconciliation sublayer enabled (`PLCA_CTRL0.EN`).
    pub enabled: bool,
    /// Local node ID (`PLCA_CTRL1.ID`).
    pub node_id: u8,
    /// `node_id == 0`. The coordinator transmits the periodic BEACONs.
    pub is_coordinator: bool,
    /// `PLCA_STS.PST` — BEACONs are being transmitted (coordinator) or
    /// received (follower) regularly. The closest thing to a "link is
    /// up" signal on a 10BASE-T1S multidrop bus.
    pub stable: bool,
}

/// Errors from PLCA-related driver methods.
#[derive(Debug)]
#[non_exhaustive]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum PlcaError<E> {
    /// MDIO bus error (passthrough).
    Mdio(E),
    /// Configuration values are invalid: `node_id == 0xFF` (silicon
    /// reserved sentinel for "disabled"), or a follower with
    /// `node_id ≥ node_count` such that no transmit opportunity is
    /// ever granted to this node.
    InvalidConfig,
}