ksz8863/
lib.rs

1//! A driver for the KSZ8863 Ethernet Switch.
2//!
3//! This driver is split into two main modules:
4//!
5//! - [`miim`](./miim/index.html) for the MII Management Interface (MIIM).
6//! - [`smi`](./smi/index.html) for the Serial Management Interface (SMI).
7//!
8//! While these two terms often refer to same protocol, their usage in the KSZ8863 documentation
9//! refers to two distinct protocols and sets of registers. Please refer to the datasheet for
10//! details.
11//!
12//! These modules contain a type and module for every documented register along with typed access
13//! to each of their respective fields. High-level read/write/modify access to these registers are
14//! provided via the `Miim` and `Smi` types respectively.
15//!
16//! *Note that the SPI and I2C interfaces are not currently supported, though PRs are welcome.*
17//!
18//! # Usage
19//!
20//! At the foundation of this crate are the `miim::{Read, Write}` and `smi::{Read, Write}` traits.
21//! The first step is to implement these for your respective MIIM and SMI interfaces. For details
22//! on how to implement these, visit sections `3.3.10` and `3.3.11` of the datasheet.
23//!
24//! Implementing these traits unlocks high level access via the [`Smi`](./smi/struct.Smi.html) and
25//! [`Miim`](./miim/struct.Miim.html) interface type wrappers. These types provide short-hand
26//! methods for reading, writing and modifying registers and their individual fields. The provided
27//! API for these types is inspired by the `svd2rust` crate.
28//!
29//! Here is an example of using the `Miim`.
30//!
31//! ```rust
32//! use ksz8863::{miim, Miim};
33//!
34//! fn main() {
35//! #    let miim_iface = miim::Map::default();
36//!     // Wrap the type that impls the Read/Write traits with `Miim`.
37//!     // Note: We could also wrap `&mut miim_iface` here if we only local scope access is needed.
38//!     let mut miim = Miim(miim_iface);
39//!
40//!     // Specify which phy we want to communicate with via its PHY address.
41//!     let mut phy = miim.phy(0);
42//!
43//!     // Read the value of the "Basic Control Register".
44//!     assert_eq!(phy.bcr().read().unwrap(), miim::Bcr::default());
45//!
46//!     // Modify the "Force 100BT" field of the "Basic Control Register" in place.
47//!     let mut bcr = phy.bcr();
48//!     assert!(bcr.read().unwrap().read().force_fd().bit_is_clear());
49//!     bcr.modify(|w| w.force_fd().set_bit()).unwrap();
50//!     let reg = bcr.read().unwrap();
51//!     assert!(reg != miim::Bcr::default());
52//!     assert!(reg.read().force_fd().bit_is_set());
53//! }
54//! ```
55//!
56//! The `Smi` API is similar, but we don't need to specify a PHY address.
57//!
58//! ```rust
59//! use ksz8863::{smi, Smi};
60//!
61//! fn main() {
62//! #    let smi_iface = smi::Map::default();
63//!     let mut smi = Smi(smi_iface);
64//!     assert_eq!(smi.gc1().read().unwrap(), smi::Gc1::default());
65//!     smi.gc1().modify(|w| w.tx_flow_control().clear_bit()).unwrap();
66//!     assert!(smi.gc1().read().unwrap() != smi::Gc1::default());
67//! }
68//! ```
69//!
70//! ## Extras
71//!
72//! The `Address` type in each module represents the unique index at which the register is located.
73//!
74//! The `State` type from each module is a dynamic representation of register state, useful for
75//! storing the state of multiple registers in a collection.
76//!
77//! The `Map` type from each module is a collection that is guaranteed to contain the state of all
78//! registers. This is useful for remotely monitoring the state of registers while reducing I/O,
79//! and for simulating an MIIM/SMI interface in the case that you don't have access to one.
80//!
81//! # Features
82//!
83//! - `hash-32` provides `Hash32` implementations from the `hash32` crate.
84//! - `serde` provides `Deserialize` and `Serialize` implementations.
85//! - `ufmt` provides `ufmt::uDebug` implementations.
86//!
87//! All of these features are **opt-in** and disabled by default.
88
89#![no_std]
90#![recursion_limit = "256"]
91
92#[macro_use]
93mod macros;
94pub mod miim;
95pub mod smi;
96
97pub use miim::Miim;
98pub use smi::Smi;
99
100/// The error returned when no attempting to produce an `Address` from an unknown byte.
101#[derive(Debug)]
102pub struct InvalidAddress;
103
104/// Allow for using bit values (1 and 0) as default values in register macro.
105trait IntoBool {
106    /// Convert `self` into a `bool`.
107    fn into_bool(self) -> bool;
108}
109
110impl IntoBool for bool {
111    fn into_bool(self) -> bool {
112        self
113    }
114}
115
116impl IntoBool for u8 {
117    fn into_bool(self) -> bool {
118        self != 0
119    }
120}