Compare commits

..

No commits in common. "6d17703e6b8dfdf8da562eb369f1b35d9057fd8c" and "232a08f11012fd749b68882140a8b9dc1a653363" have entirely different histories.

6 changed files with 111 additions and 112 deletions

View File

@ -17,7 +17,8 @@ use stm32f4xx_hal::{
spi::Spi, spi::Spi,
time::Hertz time::Hertz
}; };
use enc424j600::smoltcp_phy; use enc424j600;
use enc424j600::{smoltcp_phy, EthController};
use smoltcp::wire::{ use smoltcp::wire::{
EthernetAddress, IpAddress, IpCidr, Ipv6Cidr EthernetAddress, IpAddress, IpCidr, Ipv6Cidr
@ -77,7 +78,7 @@ use stm32f4xx_hal::{
Alternate, AF5, Output, PushPull Alternate, AF5, Output, PushPull
} }
}; };
type SpiEth = enc424j600::Enc424j600< type BoosterSpiEth = enc424j600::SpiEth<
Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>, Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>,
PA4<Output<PushPull>>, PA4<Output<PushPull>>,
fn(u32) -> () fn(u32) -> ()
@ -101,7 +102,7 @@ const APP: () = {
struct Resources { struct Resources {
eth_iface: EthernetInterface< eth_iface: EthernetInterface<
'static, 'static,
smoltcp_phy::SmoltcpDevice<SpiEth>>, smoltcp_phy::SmoltcpDevice<BoosterSpiEth>>,
itm: ITM itm: ITM
} }
@ -156,11 +157,11 @@ const APP: () = {
let delay_ns_fp: fn(u32) -> () = |time_ns| { let delay_ns_fp: fn(u32) -> () = |time_ns| {
cortex_m::asm::delay((time_ns*21)/125 + 1) cortex_m::asm::delay((time_ns*21)/125 + 1)
}; };
SpiEth::new(spi_eth_port, spi1_nss, delay_ns_fp) enc424j600::SpiEth::new(spi_eth_port, spi1_nss, delay_ns_fp)
}; };
// Init controller // Init controller
match spi_eth.reset() { match spi_eth.init_dev() {
Ok(_) => { Ok(_) => {
iprintln!(stim0, "Initializing Ethernet...") iprintln!(stim0, "Initializing Ethernet...")
} }
@ -171,7 +172,7 @@ const APP: () = {
// Read MAC // Read MAC
let mut eth_mac_addr: [u8; 6] = [0; 6]; let mut eth_mac_addr: [u8; 6] = [0; 6];
spi_eth.read_mac_addr(&mut eth_mac_addr); spi_eth.read_from_mac(&mut eth_mac_addr);
for i in 0..6 { for i in 0..6 {
let byte = eth_mac_addr[i]; let byte = eth_mac_addr[i];
match i { match i {

View File

@ -17,7 +17,8 @@ use stm32f4xx_hal::{
spi::Spi, spi::Spi,
time::Hertz time::Hertz
}; };
use enc424j600::EthPhy; use enc424j600;
use enc424j600::EthController;
/// ///
use stm32f4xx_hal::{ use stm32f4xx_hal::{
@ -27,16 +28,15 @@ use stm32f4xx_hal::{
Alternate, AF5, Output, PushPull Alternate, AF5, Output, PushPull
}, },
}; };
type SpiEth = enc424j600::Enc424j600< type BoosterSpiEth = enc424j600::SpiEth<
Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>, Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>,
PA4<Output<PushPull>>, PA4<Output<PushPull>>,
fn(u32) -> () fn(u32)>;
>;
#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] #[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
const APP: () = { const APP: () = {
struct Resources { struct Resources {
spi_eth: SpiEth, spi_eth: BoosterSpiEth,
delay: Delay, delay: Delay,
itm: ITM, itm: ITM,
} }
@ -87,11 +87,11 @@ const APP: () = {
let delay_ns: fn(u32) -> () = |time_ns| { let delay_ns: fn(u32) -> () = |time_ns| {
cortex_m::asm::delay((time_ns*21)/125 + 1) cortex_m::asm::delay((time_ns*21)/125 + 1)
}; };
SpiEth::new(spi_eth_port, spi1_nss, delay_ns) enc424j600::SpiEth::new(spi_eth_port, spi1_nss, delay_ns)
}; };
// Init // Init
match spi_eth.reset() { match spi_eth.init_dev() {
Ok(_) => { Ok(_) => {
iprintln!(stim0, "Initializing Ethernet...") iprintln!(stim0, "Initializing Ethernet...")
} }
@ -102,7 +102,7 @@ const APP: () = {
// Read MAC // Read MAC
let mut eth_mac_addr: [u8; 6] = [0; 6]; let mut eth_mac_addr: [u8; 6] = [0; 6];
spi_eth.read_mac_addr(&mut eth_mac_addr); spi_eth.read_from_mac(&mut eth_mac_addr);
for i in 0..6 { for i in 0..6 {
let byte = eth_mac_addr[i]; let byte = eth_mac_addr[i];
match i { match i {
@ -157,7 +157,7 @@ const APP: () = {
_ => () _ => ()
}; };
} }
c.resources.spi_eth.send_packet(&eth_tx_packet); c.resources.spi_eth.send_raw_packet(&eth_tx_packet);
iprintln!(stim0, "Packet sent"); iprintln!(stim0, "Packet sent");
c.resources.delay.delay_ms(100_u32); c.resources.delay.delay_ms(100_u32);
} }

View File

@ -20,29 +20,34 @@ pub mod nal;
/// Max raw frame array size /// Max raw frame array size
pub const RAW_FRAME_LENGTH_MAX: usize = 1518; pub const RAW_FRAME_LENGTH_MAX: usize = 1518;
/// Trait representing PHY layer of ENC424J600 pub trait EthController {
pub trait EthPhy { fn init_dev(&mut self) -> Result<(), EthControllerError>;
fn recv_packet(&mut self, is_poll: bool) -> Result<rx::RxPacket, Error>; fn init_rxbuf(&mut self) -> Result<(), EthControllerError>;
fn send_packet(&mut self, packet: &tx::TxPacket) -> Result<(), Error>; fn init_txbuf(&mut self) -> Result<(), EthControllerError>;
fn receive_next(&mut self, is_poll: bool) -> Result<rx::RxPacket, EthControllerError>;
fn send_raw_packet(&mut self, packet: &tx::TxPacket) -> Result<(), EthControllerError>;
fn set_promiscuous(&mut self) -> Result<(), EthControllerError>;
fn read_from_mac(&mut self, mac: &mut [u8]) -> Result<(), EthControllerError>;
fn write_mac_address(&mut self, mac: &[u8]) -> Result<(), EthControllerError>;
} }
/// TODO: Improve these error types /// TODO: Improve these error types
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum EthControllerError {
SpiPortError, SpiPortError,
RegisterError, GeneralError,
// TODO: Better name? // TODO: Better name?
NoRxPacketError NoRxPacketError
} }
impl From<spi::Error> for Error { impl From<spi::SpiPortError> for EthControllerError {
fn from(_: spi::Error) -> Error { fn from(_: spi::SpiPortError) -> EthControllerError {
Error::SpiPortError EthControllerError::SpiPortError
} }
} }
/// ENC424J600 controller in SPI mode /// Ethernet controller using SPI interface
pub struct Enc424j600<SPI: Transfer<u8>, pub struct SpiEth<SPI: Transfer<u8>,
NSS: OutputPin, NSS: OutputPin,
F: FnMut(u32) -> ()> { F: FnMut(u32) -> ()> {
spi_port: spi::SpiPort<SPI, NSS, F>, spi_port: spi::SpiPort<SPI, NSS, F>,
@ -52,29 +57,26 @@ pub struct Enc424j600<SPI: Transfer<u8>,
impl <SPI: Transfer<u8>, impl <SPI: Transfer<u8>,
NSS: OutputPin, NSS: OutputPin,
F: FnMut(u32) -> ()> Enc424j600<SPI, NSS, F> { F: FnMut(u32) -> ()> SpiEth<SPI, NSS, F> {
pub fn new(spi: SPI, nss: NSS, delay_ns: F) -> Self { pub fn new(spi: SPI, nss: NSS, delay_ns: F) -> Self {
Enc424j600 { SpiEth {
spi_port: spi::SpiPort::new(spi, nss, delay_ns), spi_port: spi::SpiPort::new(spi, nss, delay_ns),
rx_buf: rx::RxBuffer::new(), rx_buf: rx::RxBuffer::new(),
tx_buf: tx::TxBuffer::new() tx_buf: tx::TxBuffer::new()
} }
} }
pub fn init(&mut self) -> Result<(), Error> {
self.reset()?;
self.init_rxbuf()?;
self.init_txbuf()?;
Ok(())
} }
pub fn reset(&mut self) -> Result<(), Error> { impl <SPI: Transfer<u8>,
NSS: OutputPin,
F: FnMut(u32) -> ()> EthController for SpiEth<SPI, NSS, F> {
fn init_dev(&mut self) -> Result<(), EthControllerError> {
// Write 0x1234 to EUDAST // Write 0x1234 to EUDAST
self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?; self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?;
// Verify that EUDAST is 0x1234 // Verify that EUDAST is 0x1234
let mut eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?; let mut eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?;
if eudast != 0x1234 { if eudast != 0x1234 {
return Err(Error::RegisterError) return Err(EthControllerError::GeneralError)
} }
// Poll CLKRDY (ESTAT<12>) to check if it is set // Poll CLKRDY (ESTAT<12>) to check if it is set
loop { loop {
@ -88,13 +90,13 @@ impl <SPI: Transfer<u8>,
// Verify that EUDAST is 0x0000 // Verify that EUDAST is 0x0000
eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?; eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?;
if eudast != 0x0000 { if eudast != 0x0000 {
return Err(Error::RegisterError) return Err(EthControllerError::GeneralError)
} }
self.spi_port.delay_us(256); self.spi_port.delay_us(256);
Ok(()) Ok(())
} }
pub fn init_rxbuf(&mut self) -> Result<(), Error> { fn init_rxbuf(&mut self) -> Result<(), EthControllerError> {
// Set ERXST pointer // Set ERXST pointer
self.spi_port.write_reg_16b(spi::addrs::ERXST, self.rx_buf.get_wrap_addr())?; self.spi_port.write_reg_16b(spi::addrs::ERXST, self.rx_buf.get_wrap_addr())?;
// Set ERXTAIL pointer // Set ERXTAIL pointer
@ -107,57 +109,22 @@ impl <SPI: Transfer<u8>,
Ok(()) Ok(())
} }
pub fn init_txbuf(&mut self) -> Result<(), Error> { fn init_txbuf(&mut self) -> Result<(), EthControllerError> {
// Set EGPWRPT pointer // Set EGPWRPT pointer
self.spi_port.write_reg_16b(spi::addrs::EGPWRPT, 0x0000)?; self.spi_port.write_reg_16b(spi::addrs::EGPWRPT, 0x0000)?;
Ok(()) Ok(())
} }
/// Set controller to Promiscuous Mode
pub fn set_promiscuous(&mut self) -> Result<(), Error> {
// From Section 10.12, ENC424J600 Data Sheet:
// "To accept all incoming frames regardless of content (Promiscuous mode),
// set the CRCEN, RUNTEN, UCEN, NOTMEEN and MCEN bits."
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(())
}
/// Read MAC to [u8; 6]
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,
F: FnMut(u32) -> ()> EthPhy for Enc424j600<SPI, NSS, F> {
/// Receive the next packet and return it /// Receive the next packet and return it
/// Set is_poll to true for returning until PKTIF is set; /// Set is_poll to true for returning until PKTIF is set;
/// Set is_poll to false for returning Err when PKTIF is not set /// Set is_poll to false for returning Err when PKTIF is not set
fn recv_packet(&mut self, is_poll: bool) -> Result<rx::RxPacket, Error> { fn receive_next(&mut self, is_poll: bool) -> Result<rx::RxPacket, EthControllerError> {
// Poll PKTIF (EIR<4>) to check if it is set // Poll PKTIF (EIR<4>) to check if it is set
loop { loop {
let eir = self.spi_port.read_reg_16b(spi::addrs::EIR)?; let eir = self.spi_port.read_reg_16b(spi::addrs::EIR)?;
if eir & 0x40 == 0x40 { break } if eir & 0x40 == 0x40 { break }
if !is_poll { if !is_poll {
return Err(Error::NoRxPacketError) return Err(EthControllerError::NoRxPacketError)
} }
} }
// Set ERXRDPT pointer to next_addr // Set ERXRDPT pointer to next_addr
@ -193,7 +160,7 @@ impl <SPI: Transfer<u8>,
} }
/// Send an established packet /// Send an established packet
fn send_packet(&mut self, packet: &tx::TxPacket) -> Result<(), Error> { fn send_raw_packet(&mut self, packet: &tx::TxPacket) -> Result<(), EthControllerError> {
// Set EGPWRPT pointer to next_addr // Set EGPWRPT pointer to next_addr
self.spi_port.write_reg_16b(spi::addrs::EGPWRPT, self.tx_buf.get_next_addr())?; self.spi_port.write_reg_16b(spi::addrs::EGPWRPT, self.tx_buf.get_next_addr())?;
// Copy packet data to SRAM Buffer // Copy packet data to SRAM Buffer
@ -220,4 +187,35 @@ impl <SPI: Transfer<u8>,
tx::GPBUFEN_DEFAULT); tx::GPBUFEN_DEFAULT);
Ok(()) Ok(())
} }
/// Set controller to Promiscuous Mode
fn set_promiscuous(&mut self) -> Result<(), EthControllerError> {
// From Section 10.12, ENC424J600 Data Sheet:
// "To accept all incoming frames regardless of content (Promiscuous mode),
// set the CRCEN, RUNTEN, UCEN, NOTMEEN and MCEN bits."
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(())
}
/// Read MAC to [u8; 6]
fn read_from_mac(&mut self, mac: &mut [u8]) -> Result<(), EthControllerError> {
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(())
}
fn write_mac_address(&mut self, mac: &[u8]) -> Result<(), EthControllerError> {
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(())
}
} }

View File

@ -24,7 +24,7 @@ pub enum NetworkError {
pub type NetworkInterface<SPI, NSS> = net::iface::EthernetInterface< pub type NetworkInterface<SPI, NSS> = net::iface::EthernetInterface<
'static, 'static,
crate::smoltcp_phy::SmoltcpDevice< crate::smoltcp_phy::SmoltcpDevice<
crate::Enc424j600<SPI, NSS, fn(u32)> crate::SpiEth<SPI, NSS, fn(u32)>
>, >,
>; >;

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
EthPhy, tx, RAW_FRAME_LENGTH_MAX EthController, tx, RAW_FRAME_LENGTH_MAX
}; };
use core::cell; use core::cell;
use smoltcp::{ use smoltcp::{
@ -8,25 +8,25 @@ use smoltcp::{
Error Error
}; };
pub struct SmoltcpDevice<E: EthPhy> { pub struct SmoltcpDevice<EC: EthController> {
pub eth_phy: cell::RefCell<E>, pub eth_controller: cell::RefCell<EC>,
rx_packet_buf: [u8; RAW_FRAME_LENGTH_MAX], rx_packet_buf: [u8; RAW_FRAME_LENGTH_MAX],
tx_packet_buf: [u8; RAW_FRAME_LENGTH_MAX] tx_packet_buf: [u8; RAW_FRAME_LENGTH_MAX]
} }
impl<E: EthPhy> SmoltcpDevice<E> { impl<EC: EthController> SmoltcpDevice<EC> {
pub fn new(eth_phy: E) -> Self { pub fn new(eth_controller: EC) -> Self {
SmoltcpDevice { SmoltcpDevice {
eth_phy: cell::RefCell::new(eth_phy), eth_controller: cell::RefCell::new(eth_controller),
rx_packet_buf: [0; RAW_FRAME_LENGTH_MAX], rx_packet_buf: [0; RAW_FRAME_LENGTH_MAX],
tx_packet_buf: [0; RAW_FRAME_LENGTH_MAX] tx_packet_buf: [0; RAW_FRAME_LENGTH_MAX]
} }
} }
} }
impl<'a, E: 'a + EthPhy> Device<'a> for SmoltcpDevice<E> { impl<'a, EC: 'a + EthController> Device<'a> for SmoltcpDevice<EC> {
type RxToken = EthRxToken<'a>; type RxToken = EthRxToken<'a>;
type TxToken = EthTxToken<'a, E>; type TxToken = EthTxToken<'a, EC>;
fn capabilities(&self) -> DeviceCapabilities { fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default(); let mut caps = DeviceCapabilities::default();
@ -35,8 +35,8 @@ impl<'a, E: 'a + EthPhy> Device<'a> for SmoltcpDevice<E> {
} }
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
let self_p = (&mut *self) as *mut SmoltcpDevice<E>; let self_p = (&mut *self) as *mut SmoltcpDevice<EC>;
match self.eth_phy.borrow_mut().recv_packet(false) { match self.eth_controller.borrow_mut().receive_next(false) {
Ok(rx_packet) => { Ok(rx_packet) => {
// Write received packet to RX packet buffer // Write received packet to RX packet buffer
rx_packet.write_frame_to(&mut self.rx_packet_buf); rx_packet.write_frame_to(&mut self.rx_packet_buf);
@ -57,7 +57,7 @@ impl<'a, E: 'a + EthPhy> Device<'a> for SmoltcpDevice<E> {
} }
fn transmit(&'a mut self) -> Option<Self::TxToken> { fn transmit(&'a mut self) -> Option<Self::TxToken> {
let self_p = (&mut *self) as *mut SmoltcpDevice<E>; let self_p = (&mut *self) as *mut SmoltcpDevice<EC>;
// Construct a blank TxToken // Construct a blank TxToken
let tx_token = EthTxToken { let tx_token = EthTxToken {
buf: &mut self.tx_packet_buf, buf: &mut self.tx_packet_buf,
@ -81,12 +81,12 @@ impl<'a> RxToken for EthRxToken<'a> {
} }
} }
pub struct EthTxToken<'a, E: EthPhy> { pub struct EthTxToken<'a, EC: EthController> {
buf: &'a mut [u8], buf: &'a mut [u8],
dev: *mut SmoltcpDevice<E> dev: *mut SmoltcpDevice<EC>
} }
impl<'a, E: 'a + EthPhy> TxToken for EthTxToken<'a, E> { impl<'a, EC: 'a + EthController> TxToken for EthTxToken<'a, EC> {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R, Error> fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R, Error>
where where
F: FnOnce(&mut [u8]) -> Result<R, Error>, F: FnOnce(&mut [u8]) -> Result<R, Error>,
@ -97,10 +97,10 @@ impl<'a, E: 'a + EthPhy> TxToken for EthTxToken<'a, E> {
// Update frame length and write frame bytes // Update frame length and write frame bytes
tx_packet.update_frame(&mut self.buf[..len], len); tx_packet.update_frame(&mut self.buf[..len], len);
// Send the packet as raw // Send the packet as raw
let eth_phy = unsafe { let eth_controller = unsafe {
&mut (*self.dev).eth_phy &mut (*self.dev).eth_controller
}; };
match eth_phy.borrow_mut().send_packet(&tx_packet) { match eth_controller.borrow_mut().send_raw_packet(&tx_packet) {
Ok(_) => { result }, Ok(_) => { result },
Err(_) => Err(Error::Exhausted) Err(_) => Err(Error::Exhausted)
} }

View File

@ -59,7 +59,7 @@ pub struct SpiPort<SPI: Transfer<u8>,
delay_ns: F, delay_ns: F,
} }
pub enum Error { pub enum SpiPortError {
TransferError TransferError
} }
@ -78,13 +78,13 @@ impl <SPI: Transfer<u8>,
} }
} }
pub fn read_reg_8b(&mut self, addr: u8) -> Result<u8, Error> { pub fn read_reg_8b(&mut self, addr: u8) -> Result<u8, SpiPortError> {
// Using RCRU instruction to read using unbanked (full) address // Using RCRU instruction to read using unbanked (full) address
let r_data = self.rw_addr_u8(opcodes::RCRU, addr, 0)?; let r_data = self.rw_addr_u8(opcodes::RCRU, addr, 0)?;
Ok(r_data) Ok(r_data)
} }
pub fn read_reg_16b(&mut self, lo_addr: u8) -> Result<u16, Error> { pub fn read_reg_16b(&mut self, lo_addr: u8) -> Result<u16, SpiPortError> {
let r_data_lo = self.read_reg_8b(lo_addr)?; let r_data_lo = self.read_reg_8b(lo_addr)?;
let r_data_hi = self.read_reg_8b(lo_addr + 1)?; let r_data_hi = self.read_reg_8b(lo_addr + 1)?;
// Combine top and bottom 8-bit to return 16-bit // Combine top and bottom 8-bit to return 16-bit
@ -93,7 +93,7 @@ impl <SPI: Transfer<u8>,
// Currently requires manual slicing (buf[1..]) for the data read back // Currently requires manual slicing (buf[1..]) for the data read back
pub fn read_rxdat<'a>(&mut self, buf: &'a mut [u8], data_length: usize) pub fn read_rxdat<'a>(&mut self, buf: &'a mut [u8], data_length: usize)
-> Result<(), Error> { -> Result<(), SpiPortError> {
let r_valid = self.r_n(buf, opcodes::RERXDATA, data_length)?; let r_valid = self.r_n(buf, opcodes::RERXDATA, data_length)?;
Ok(r_valid) Ok(r_valid)
} }
@ -101,19 +101,19 @@ impl <SPI: Transfer<u8>,
// Currenly requires actual data to be stored in buf[1..] instead of buf[0..] // Currenly requires actual data to be stored in buf[1..] instead of buf[0..]
// TODO: Maybe better naming? // TODO: Maybe better naming?
pub fn write_txdat<'a>(&mut self, buf: &'a mut [u8], data_length: usize) pub fn write_txdat<'a>(&mut self, buf: &'a mut [u8], data_length: usize)
-> Result<(), Error> { -> Result<(), SpiPortError> {
let w_valid = self.w_n(buf, opcodes::WEGPDATA, data_length)?; let w_valid = self.w_n(buf, opcodes::WEGPDATA, data_length)?;
Ok(w_valid) Ok(w_valid)
} }
pub fn write_reg_8b(&mut self, addr: u8, data: u8) -> Result<(), Error> { pub fn write_reg_8b(&mut self, addr: u8, data: u8) -> Result<(), SpiPortError> {
// TODO: addr should be separated from w_data // TODO: addr should be separated from w_data
// Using WCRU instruction to write using unbanked (full) address // Using WCRU instruction to write using unbanked (full) address
self.rw_addr_u8(opcodes::WCRU, addr, data)?; self.rw_addr_u8(opcodes::WCRU, addr, data)?;
Ok(()) Ok(())
} }
pub fn write_reg_16b(&mut self, lo_addr: u8, data: u16) -> Result<(), Error> { pub fn write_reg_16b(&mut self, lo_addr: u8, data: u16) -> Result<(), SpiPortError> {
self.write_reg_8b(lo_addr, (data & 0xff) as u8)?; self.write_reg_8b(lo_addr, (data & 0xff) as u8)?;
self.write_reg_8b(lo_addr + 1, ((data & 0xff00) >> 8) as u8)?; self.write_reg_8b(lo_addr + 1, ((data & 0xff00) >> 8) as u8)?;
Ok(()) Ok(())
@ -127,7 +127,7 @@ impl <SPI: Transfer<u8>,
// TODO: (Make data read/write as reference to array) // TODO: (Make data read/write as reference to array)
// Currently requires 1-byte addr, read/write data is only 1-byte // Currently requires 1-byte addr, read/write data is only 1-byte
fn rw_addr_u8(&mut self, opcode: u8, addr: u8, data: u8) fn rw_addr_u8(&mut self, opcode: u8, addr: u8, data: u8)
-> Result<u8, Error> { -> Result<u8, SpiPortError> {
// Enable chip select // Enable chip select
self.nss.set_low(); self.nss.set_low();
// Start writing to SLAVE // Start writing to SLAVE
@ -150,7 +150,7 @@ impl <SPI: Transfer<u8>,
(self.delay_ns)(60); (self.delay_ns)(60);
self.nss.set_high(); self.nss.set_high();
(self.delay_ns)(30); (self.delay_ns)(30);
Err(Error::TransferError) Err(SpiPortError::TransferError)
} }
} }
} }
@ -161,7 +161,7 @@ impl <SPI: Transfer<u8>,
// Note: buf must be at least (data_length + 1)-byte long // Note: buf must be at least (data_length + 1)-byte long
// TODO: Check and raise error for array size < (data_length + 1) // TODO: Check and raise error for array size < (data_length + 1)
fn r_n<'a>(&mut self, buf: &'a mut [u8], opcode: u8, data_length: usize) fn r_n<'a>(&mut self, buf: &'a mut [u8], opcode: u8, data_length: usize)
-> Result<(), Error> { -> Result<(), SpiPortError> {
// Enable chip select // Enable chip select
self.nss.set_low(); self.nss.set_low();
// Start writing to SLAVE // Start writing to SLAVE
@ -176,7 +176,7 @@ impl <SPI: Transfer<u8>,
Err(_) => { Err(_) => {
// Disable chip select // Disable chip select
self.nss.set_high(); self.nss.set_high();
Err(Error::TransferError) Err(SpiPortError::TransferError)
} }
} }
} }
@ -184,7 +184,7 @@ impl <SPI: Transfer<u8>,
// Note: buf[0] is currently reserved for opcode to overwrite // Note: buf[0] is currently reserved for opcode to overwrite
// TODO: Actual data should start from buf[0], not buf[1] // TODO: Actual data should start from buf[0], not buf[1]
fn w_n<'a>(&mut self, buf: &'a mut [u8], opcode: u8, data_length: usize) fn w_n<'a>(&mut self, buf: &'a mut [u8], opcode: u8, data_length: usize)
-> Result<(), Error> { -> Result<(), SpiPortError> {
// Enable chip select // Enable chip select
self.nss.set_low(); self.nss.set_low();
// Start writing to SLAVE // Start writing to SLAVE
@ -200,7 +200,7 @@ impl <SPI: Transfer<u8>,
Err(_) => { Err(_) => {
// Disable chip select // Disable chip select
self.nss.set_high(); self.nss.set_high();
Err(Error::TransferError) Err(SpiPortError::TransferError)
} }
} }
} }