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}