use crate::{interface, marker, EepromWriteProtection, Error, Mcp794xx};
const EEUNLOCK: u8 = 0b0000_1001;
const EEPROM_STATUS: u8 = 0xFF;
impl<DI, E, IC> Mcp794xx<DI, IC>
where
DI: interface::WriteData<Error = Error<E>> + interface::ReadData<Error = Error<E>>,
IC: marker::WithProtectedEeprom,
{
pub fn read_protected_eeprom_byte(&mut self, address: u8) -> Result<u8, Error<E>> {
if !is_protected_eeprom_address(address) {
return Err(Error::InvalidInputData);
}
self.iface.read_eeprom_byte(address)
}
pub fn read_protected_eeprom_data(
&mut self,
address: u8,
data: &mut [u8],
) -> Result<(), Error<E>> {
if !is_protected_eeprom_address(address)
|| data.len() > 8
|| (data.len() as u8 + address) > 0xF8
{
return Err(Error::InvalidInputData);
}
self.iface.read_eeprom_data(address, data)
}
pub fn write_protected_eeprom_byte(&mut self, address: u8, data: u8) -> Result<(), Error<E>> {
if !is_protected_eeprom_address(address) {
return Err(Error::InvalidInputData);
}
self.iface.write_register(EEUNLOCK, 0x55)?;
self.iface.write_register(EEUNLOCK, 0xAA)?;
self.iface.write_eeprom_byte(address, data)
}
pub fn write_protected_eeprom_data(
&mut self,
address: u8,
data: &[u8],
) -> Result<(), Error<E>> {
if !is_protected_eeprom_address(address)
|| data.len() > 8
|| (data.len() as u8 + address) > 0xF8
{
return Err(Error::InvalidInputData);
}
let mut payload = [0; 9]; payload[0] = address;
payload[1..=data.len()].copy_from_slice(data);
self.iface.write_register(EEUNLOCK, 0x55)?;
self.iface.write_register(EEUNLOCK, 0xAA)?;
self.iface.write_eeprom_data(&payload[..=data.len()])
}
}
#[allow(clippy::manual_range_contains)]
fn is_protected_eeprom_address(address: u8) -> bool {
address >= 0xF0 && address <= 0xF7
}
impl<DI, E, IC> Mcp794xx<DI, IC>
where
DI: interface::WriteData<Error = Error<E>> + interface::ReadData<Error = Error<E>>,
IC: marker::WithEeprom,
{
pub fn set_eeprom_write_protection(
&mut self,
protection: EepromWriteProtection,
) -> Result<(), Error<E>> {
let value = match protection {
EepromWriteProtection::None => 0,
EepromWriteProtection::UpperQuarter => 0b0000_0100,
EepromWriteProtection::UpperHalf => 0b0000_1000,
EepromWriteProtection::All => 0b0000_1100,
};
self.iface.write_eeprom_byte(EEPROM_STATUS, value)
}
pub fn read_eeprom_byte(&mut self, address: u8) -> Result<u8, Error<E>> {
if is_eeprom_address(address) {
self.iface.read_eeprom_byte(address)
} else {
Err(Error::InvalidInputData)
}
}
pub fn read_eeprom_data(&mut self, address: u8, data: &mut [u8]) -> Result<(), Error<E>> {
if is_eeprom_address(address) && data.len() <= 128 && (address + data.len() as u8) < 0x80 {
self.iface.read_eeprom_data(address, data)
} else {
Err(Error::InvalidInputData)
}
}
pub fn write_eeprom_byte(&mut self, address: u8, data: u8) -> Result<(), Error<E>> {
if is_eeprom_address(address) {
self.iface.write_eeprom_byte(address, data)
} else {
Err(Error::InvalidInputData)
}
}
pub fn write_eeprom_data(&mut self, address: u8, data: &[u8]) -> Result<(), Error<E>> {
if is_eeprom_address(address) && data.len() <= 128 && (address + data.len() as u8) < 0x80 {
let mut payload = [0; 128]; payload[0] = address;
payload[1..=data.len()].copy_from_slice(data);
self.iface.write_eeprom_data(&payload[..=data.len()])
} else {
Err(Error::InvalidInputData)
}
}
}
fn is_eeprom_address(address: u8) -> bool {
address < 0x80
}
impl<DI, E, IC> Mcp794xx<DI, IC>
where
DI: interface::ReadCurrent<Error = Error<E>>,
{
pub fn read_eeprom_current_byte(&mut self) -> Result<u8, Error<E>> {
self.iface.read_eeprom()
}
}
impl<DI, E, IC> Mcp794xx<DI, IC>
where
DI: interface::ReadData<Error = Error<E>>,
IC: marker::WithEui48,
{
pub fn read_eui48(&mut self) -> Result<[u8; 6], Error<E>> {
let mut data = [0; 6];
self.iface.read_eeprom_data(0xF2, &mut data).and(Ok(data))
}
}
impl<DI, E, IC> Mcp794xx<DI, IC>
where
DI: interface::ReadData<Error = Error<E>>,
IC: marker::WithEui64,
{
pub fn read_eui64(&mut self) -> Result<[u8; 8], Error<E>> {
let mut data = [0; 8];
self.iface.read_eeprom_data(0xF0, &mut data).and(Ok(data))
}
}