#![no_std]
pub mod spi;
use embedded_hal::{
blocking::{delay::DelayUs, spi::Transfer},
digital::v2::OutputPin,
};
pub mod rx;
pub mod tx;
#[cfg(feature = "smoltcp")]
pub mod smoltcp_phy;
pub const RAW_FRAME_LENGTH_MAX: usize = 1518;
pub trait EthPhy {
fn recv_packet(&mut self, is_poll: bool) -> Result<rx::RxPacket, Error>;
fn send_packet(&mut self, packet: &tx::TxPacket) -> Result<(), Error>;
}
#[derive(Debug)]
pub enum Error {
SpiPortError,
RegisterError,
NoRxPacketError,
}
impl From<spi::Error> for Error {
fn from(_: spi::Error) -> Error {
Error::SpiPortError
}
}
pub struct Enc424j600<SPI: Transfer<u8>, NSS: OutputPin> {
spi_port: spi::SpiPort<SPI, NSS>,
rx_buf: rx::RxBuffer,
tx_buf: tx::TxBuffer,
}
impl<SPI: Transfer<u8>, NSS: OutputPin> Enc424j600<SPI, NSS> {
pub fn new(spi: SPI, nss: NSS) -> Self {
Enc424j600 {
spi_port: spi::SpiPort::new(spi, nss),
rx_buf: rx::RxBuffer::new(),
tx_buf: tx::TxBuffer::new(),
}
}
#[cfg(feature = "cortex-m-cpu")]
pub fn cpu_freq_mhz(mut self, freq: u32) -> Self {
self.spi_port = self.spi_port.cpu_freq_mhz(freq);
self
}
pub fn init(&mut self, delay: &mut impl DelayUs<u16>) -> Result<(), Error> {
self.reset(delay)?;
self.init_rxbuf()?;
self.init_txbuf()?;
Ok(())
}
pub fn reset(&mut self, delay: &mut impl DelayUs<u16>) -> Result<(), Error> {
self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?;
let mut eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?;
if eudast != 0x1234 {
return Err(Error::RegisterError);
}
loop {
let estat = self.spi_port.read_reg_16b(spi::addrs::ESTAT)?;
if estat & 0x1000 == 0x1000 {
break;
}
}
self.spi_port.send_opcode(spi::opcodes::SETETHRST)?;
delay.delay_us(25);
eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?;
if eudast != 0x0000 {
return Err(Error::RegisterError);
}
delay.delay_us(256);
Ok(())
}
pub fn init_rxbuf(&mut self) -> Result<(), Error> {
self.spi_port
.write_reg_16b(spi::addrs::ERXST, self.rx_buf.get_start_addr())?;
self.spi_port
.write_reg_16b(spi::addrs::ERXTAIL, self.rx_buf.get_tail_addr())?;
self.spi_port
.write_reg_16b(spi::addrs::MAMXFL, RAW_FRAME_LENGTH_MAX as u16)?;
self.spi_port.send_opcode(spi::opcodes::ENABLERX)?;
Ok(())
}
pub fn init_txbuf(&mut self) -> Result<(), Error> {
self.spi_port.write_reg_16b(spi::addrs::EGPWRPT, 0x0000)?;
Ok(())
}
pub fn set_promiscuous(&mut self) -> Result<(), Error> {
let erxfcon_lo = self.spi_port.read_reg_8b(spi::addrs::ERXFCON)?;
self.spi_port.write_reg_8b(
spi::addrs::ERXFCON,
0b0101_1110 | (erxfcon_lo & 0b1010_0001),
)?;
Ok(())
}
pub fn read_mac_addr(&mut self, mac: &mut [u8]) -> Result<(), Error> {
mac[0] = self.spi_port.read_reg_8b(spi::addrs::MAADR1)?;
mac[1] = self.spi_port.read_reg_8b(spi::addrs::MAADR1 + 1)?;
mac[2] = self.spi_port.read_reg_8b(spi::addrs::MAADR2)?;
mac[3] = self.spi_port.read_reg_8b(spi::addrs::MAADR2 + 1)?;
mac[4] = self.spi_port.read_reg_8b(spi::addrs::MAADR3)?;
mac[5] = self.spi_port.read_reg_8b(spi::addrs::MAADR3 + 1)?;
Ok(())
}
pub fn write_mac_addr(&mut self, mac: &[u8]) -> Result<(), Error> {
self.spi_port.write_reg_8b(spi::addrs::MAADR1, mac[0])?;
self.spi_port.write_reg_8b(spi::addrs::MAADR1 + 1, mac[1])?;
self.spi_port.write_reg_8b(spi::addrs::MAADR2, mac[2])?;
self.spi_port.write_reg_8b(spi::addrs::MAADR2 + 1, mac[3])?;
self.spi_port.write_reg_8b(spi::addrs::MAADR3, mac[4])?;
self.spi_port.write_reg_8b(spi::addrs::MAADR3 + 1, mac[5])?;
Ok(())
}
}
impl<SPI: Transfer<u8>, NSS: OutputPin> EthPhy for Enc424j600<SPI, NSS> {
fn recv_packet(&mut self, is_poll: bool) -> Result<rx::RxPacket, Error> {
loop {
let eir = self.spi_port.read_reg_16b(spi::addrs::EIR)?;
if eir & 0x40 == 0x40 {
break;
}
if !is_poll {
return Err(Error::NoRxPacketError);
}
}
self.spi_port
.write_reg_16b(spi::addrs::ERXRDPT, self.rx_buf.get_next_addr())?;
let mut next_addr_buf = [0; 3];
self.spi_port.read_rxdat(&mut next_addr_buf, 2)?;
self.rx_buf
.set_next_addr((next_addr_buf[1] as u16) | ((next_addr_buf[2] as u16) << 8));
let mut rsv_buf = [0; 7];
self.spi_port.read_rxdat(&mut rsv_buf, 6)?;
let mut rx_packet = rx::RxPacket::new();
rx_packet.write_to_rsv(&rsv_buf[1..]);
rx_packet.update_frame_length();
let mut frame_buf = [0; RAW_FRAME_LENGTH_MAX];
self.spi_port
.read_rxdat(&mut frame_buf, rx_packet.get_frame_length())?;
rx_packet.copy_frame_from(&frame_buf[1..]);
if self.rx_buf.get_next_addr() > self.rx_buf.get_start_addr() {
self.spi_port
.write_reg_16b(spi::addrs::ERXTAIL, self.rx_buf.get_next_addr() - 2)?;
} else {
self.spi_port
.write_reg_16b(spi::addrs::ERXTAIL, rx::RX_MAX_ADDRESS - 1)?;
}
self.spi_port.send_opcode(spi::opcodes::SETPKTDEC)?;
Ok(rx_packet)
}
fn send_packet(&mut self, packet: &tx::TxPacket) -> Result<(), Error> {
self.spi_port
.write_reg_16b(spi::addrs::EGPWRPT, self.tx_buf.get_next_addr())?;
let mut txdat_buf: [u8; RAW_FRAME_LENGTH_MAX + 1] = [0; RAW_FRAME_LENGTH_MAX + 1];
packet.write_frame_to(&mut txdat_buf[1..]);
self.spi_port
.write_txdat(&mut txdat_buf, packet.get_frame_length())?;
self.spi_port
.write_reg_16b(spi::addrs::ETXST, self.tx_buf.get_next_addr())?;
self.spi_port
.write_reg_16b(spi::addrs::ETXLEN, packet.get_frame_length() as u16)?;
self.spi_port.send_opcode(spi::opcodes::SETTXRTS)?;
loop {
let econ1_lo = self.spi_port.read_reg_8b(spi::addrs::ECON1)?;
if econ1_lo & 0x02 == 0 {
break;
}
}
self.tx_buf.set_next_addr(
(self.tx_buf.get_next_addr() + packet.get_frame_length() as u16)
% self.rx_buf.get_start_addr()
- self.tx_buf.get_start_addr(),
);
Ok(())
}
}