use bus::I2cBus;
use jetgpio_sys::{i2cClose, i2cReadByteData, i2cWriteByteData};
use thiserror::Error;
pub mod bus;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error("Error Code from JETGPIO: {0}")]
JetGpioSysError(i32),
#[error("Uninitialized Slave Address in i2c")]
UninitializedSlaveAddr,
}
pub struct I2c {
bus: u32,
handle: u32,
slave_addr: Option<u32>,
}
impl I2c {
pub fn init(bus: I2cBus, flags: u32) -> Result<Self> {
let bus = bus.bus_val();
let handle = unsafe { jetgpio_sys::i2cOpen(bus, flags) };
if handle < 0 {
return Err(Error::JetGpioSysError(handle));
}
Ok(Self {
bus,
handle: handle as u32,
slave_addr: None,
})
}
pub fn set_slave_address(&mut self, addr: u32) {
self.slave_addr = Some(addr)
}
pub fn write_byte(&mut self, register: u8, data: u8) -> Result<()> {
let addr = self.slave_addr.ok_or(Error::UninitializedSlaveAddr)?;
let val = unsafe { i2cWriteByteData(self.handle, addr, register as u32, data as u32) };
if val < 0 {
return Err(Error::JetGpioSysError(val));
}
Ok(())
}
pub fn write(&mut self, register: u8, data: &[u8]) -> Result<()> {
for val in data {
self.write_byte(register, *val)?
}
Ok(())
}
pub fn read_byte(&mut self, register: u8) -> Result<u8> {
let addr = self.slave_addr.ok_or(Error::UninitializedSlaveAddr)?;
let read = unsafe { i2cReadByteData(self.handle, addr, register as u32) };
if read < 0 {
Err(Error::JetGpioSysError(read))
} else {
Ok(read as u8)
}
}
pub fn read(&mut self, register: u8, into: &mut [u8]) -> Result<i32> {
self.write_byte(register, 0x0)?;
let mut read = 0;
for val in into {
*val = self.read_byte(register)?;
read += 1
}
Ok(read)
}
}
impl Drop for I2c {
fn drop(&mut self) {
unsafe { i2cClose(self.bus) };
}
}