#![no_std]
use embedded_hal::i2c::I2c;
use bit_field::BitField;
#[derive(Copy, Clone)]
pub enum Address {
Standard = 0x69,
Alternate = 0x68,
}
#[allow(dead_code)]
#[derive(Copy, Clone)]
enum Register {
PowerControl = 0x00,
Reset = 0x01,
Framerate = 0x02,
IntControl = 0x03,
Status = 0x04,
StatusClear = 0x05,
Average = 0x07,
IntLevelUpperLsb = 0x08,
IntLevelUpperMsb = 0x09,
IntLevelLowerLsb = 0x0A,
IntLevelLowerMsb = 0x0B,
IntLevelHystLsb = 0x0C,
IntLevelHystMsb = 0x0D,
ThermistorLsb = 0x0E,
ThermistorMsb = 0x0F,
IntTableInt0 = 0x10,
ReservedAverage = 0x1F,
TemperatureStart = 0x80,
}
#[derive(Copy, Clone)]
pub enum Power {
Wakeup = 0x00,
Sleep = 0x10,
Standby60Seconds = 0x20,
Standby10Seconds = 0x21,
}
#[derive(Copy, Clone)]
pub enum Framerate {
Fps10 = 0x00,
Fps1 = 0x01,
}
#[allow(dead_code)]
pub struct GridEye<I2C> {
i2c: I2C,
address: Address,
}
impl<I2C: I2c> GridEye<I2C>
{
pub fn new(i2c: I2C, address: Address) -> Self {
GridEye {
i2c,
address,
}
}
pub fn get_pixel_temperature_raw(&mut self, pixel: u8) -> Result<u16, I2C::Error> {
let pixel_low = Register::TemperatureStart as u8 + (2 * pixel);
self.get_register_as_u16(pixel_low)
}
pub fn get_pixel_temperature_celsius(&mut self, pixel: u8) -> Result<f32, I2C::Error> {
let temperature = self.get_pixel_temperature_raw(pixel)?;
Ok(temperature_u12_to_f32_celsius(temperature, 0.25))
}
pub fn get_device_temperature_raw(&mut self) -> Result<u16, I2C::Error> {
self.get_register_as_u16(Register::ThermistorLsb as u8)
}
pub fn get_device_temperature_celsius(&mut self) -> Result<f32, I2C::Error> {
let temperature = self.get_device_temperature_raw()?;
Ok(temperature_u12_to_f32_celsius(temperature, 0.0625))
}
pub fn set_framerate(&mut self, framerate: Framerate) -> Result<(), I2C::Error> {
self.set_register(Register::Framerate, framerate as u8)
}
pub fn get_framerate(&mut self) -> Result<Framerate, I2C::Error> {
let fps = self.get_register(Register::Framerate as u8)?;
if fps == 0 {
Ok(Framerate::Fps10)
} else {
Ok(Framerate::Fps1)
}
}
pub fn power(&mut self, power: Power) -> Result<(), I2C::Error> {
self.set_register(Register::PowerControl, power as u8)
}
pub fn enable_interrupt(&mut self) -> Result<(), I2C::Error> {
let mut icr = self.get_register(Register::IntControl as u8)?;
self.set_register(Register::IntControl, *icr.set_bit(0, true))?;
Ok(())
}
pub fn disable_interrupt(&mut self) -> Result<(), I2C::Error> {
let mut icr = self.get_register(Register::IntControl as u8)?;
self.set_register(Register::IntControl, *icr.set_bit(0, false))?;
Ok(())
}
pub fn interrupt_enabled(&mut self) -> Result<bool, I2C::Error> {
let icr = self.get_register(Register::IntControl as u8)?;
Ok(icr.get_bit(1))
}
pub fn interrupt_mode_absolut(&mut self) -> Result<(), I2C::Error> {
let mut icr = self.get_register(Register::IntControl as u8)?;
self.set_register(Register::IntControl, *icr.set_bit(1, true))?;
Ok(())
}
pub fn interrupt_mode_difference(&mut self) -> Result<(), I2C::Error> {
let mut icr = self.get_register(Register::IntControl as u8)?;
self.set_register(Register::IntControl, *icr.set_bit(1, true))?;
Ok(())
}
pub fn interrupt_flag_set(&mut self) -> Result<bool, I2C::Error> {
let status = self.get_register(Register::IntControl as u8)?;
Ok(status.get_bit(1))
}
pub fn pixel_temperature_out_ok(&mut self) -> Result<bool, I2C::Error> {
let status = self.get_register(Register::IntControl as u8)?;
Ok(status.get_bit(2))
}
pub fn device_temperature_out_ok(&mut self) -> Result<bool, I2C::Error> {
let status = self.get_register(Register::IntControl as u8)?;
Ok(status.get_bit(3))
}
pub fn clear_interrupt_flag(&mut self) -> Result<(), I2C::Error> {
self.set_register(Register::StatusClear, 0x02)?;
Ok(())
}
pub fn clear_pixel_temperatur_overflow(&mut self) -> Result<(), I2C::Error> {
self.set_register(Register::StatusClear, 0x04)?;
Ok(())
}
pub fn clear_device_temperature_overflow(&mut self) -> Result<(), I2C::Error> {
self.set_register(Register::StatusClear, 0x08)?;
Ok(())
}
pub fn clear_all_overflow(&mut self) -> Result<(), I2C::Error> {
self.set_register(Register::StatusClear, 0x0c)?;
Ok(())
}
pub fn clear_all_status(&mut self) -> Result<(), I2C::Error> {
self.set_register(Register::StatusClear, 0x0e)?;
Ok(())
}
pub fn pixel_interrupt_enabled(&mut self, pixel: u8) -> Result<bool, I2C::Error> {
let intreg = (Register::IntTableInt0 as u8) + (pixel / 8);
let pos = pixel % 8;
let inttable = self.get_register(intreg)?;
Ok(inttable.get_bit(pos as usize))
}
pub fn enable_moving_average(&mut self) -> Result<(), I2C::Error> {
self.set_register(Register::ReservedAverage, 0x50)?;
self.set_register(Register::ReservedAverage, 0x45)?;
self.set_register(Register::ReservedAverage, 0x57)?;
self.set_register(Register::Average, 0x20)?;
self.set_register(Register::ReservedAverage, 0x00)?;
Ok(())
}
pub fn disable_moving_average(&mut self) -> Result<(), I2C::Error> {
self.set_register(Register::ReservedAverage, 0x50)?;
self.set_register(Register::ReservedAverage, 0x45)?;
self.set_register(Register::ReservedAverage, 0x57)?;
self.set_register(Register::Average, 0x00)?;
self.set_register(Register::ReservedAverage, 0x00)?;
Ok(())
}
pub fn moving_average_enabled(&mut self) -> Result<bool, I2C::Error> {
let avg = self.get_register(Register::Average as u8)?;
Ok(avg.get_bit(5))
}
pub fn set_upper_int_value_celsius(&mut self, celsius: f32) -> Result<(), I2C::Error> {
self.set_upper_int_value_raw(temperature_f32_to_u16_celsius(celsius))
}
pub fn set_upper_int_value_raw(&mut self, value: u16) -> Result<(), I2C::Error> {
let bytes = value.to_le_bytes();
self.set_register(Register::IntLevelUpperLsb, bytes[0])?;
self.set_register(Register::IntLevelUpperMsb, bytes[1])?;
Ok(())
}
pub fn set_lower_int_value_celsius(&mut self, celsius: f32) -> Result<(), I2C::Error> {
self.set_lower_int_value_raw(temperature_f32_to_u16_celsius(celsius))
}
pub fn set_lower_int_value_raw(&mut self, value: u16) -> Result<(), I2C::Error> {
let bytes = value.to_le_bytes();
self.set_register(Register::IntLevelLowerLsb, bytes[0])?;
self.set_register(Register::IntLevelLowerMsb, bytes[1])?;
Ok(())
}
pub fn set_int_hysteresis_celsius(&mut self, celsius: f32) -> Result<(), I2C::Error> {
self.set_int_hysteresis_raw(temperature_f32_to_u16_celsius(celsius))
}
pub fn set_int_hysteresis_raw(&mut self, value: u16) -> Result<(), I2C::Error> {
let bytes = value.to_le_bytes();
self.set_register(Register::IntLevelHystLsb, bytes[0])?;
self.set_register(Register::IntLevelHystMsb, bytes[1])?;
Ok(())
}
pub fn upper_int_value_celsius(&mut self) -> Result<f32, I2C::Error> {
let temperature = self.upper_int_value_raw()?;
Ok(temperature_u12_to_f32_celsius(temperature, 0.25))
}
pub fn upper_int_value_raw(&mut self) -> Result<u16, I2C::Error> {
let intval = self.get_register_as_u16(Register::IntLevelUpperLsb as u8)?;
Ok(intval)
}
pub fn lower_int_value_celsius(&mut self) -> Result<f32, I2C::Error> {
let temperature = self.lower_int_value_raw()?;
Ok(temperature_u12_to_f32_celsius(temperature, 0.25))
}
pub fn lower_int_value_raw(&mut self) -> Result<u16, I2C::Error> {
let intval = self.get_register_as_u16(Register::IntLevelLowerLsb as u8)?;
Ok(intval)
}
pub fn hysteresis_int_value_celsius(&mut self) -> Result<f32, I2C::Error> {
let temperature = self.hysteresis_int_value_raw()?;
Ok(temperature_u12_to_f32_celsius(temperature, 0.25))
}
pub fn hysteresis_int_value_raw(&mut self) -> Result<u16, I2C::Error> {
let intval = self.get_register_as_u16(Register::IntLevelHystLsb as u8)?;
Ok(intval)
}
fn set_register(&mut self, register: Register, value: u8) -> Result<(), I2C::Error> {
let cmd_bytes = [register as u8, value];
self.i2c
.write(self.address as u8, &cmd_bytes)?;
Ok(())
}
fn get_register(&mut self, register: u8) -> Result<u8, I2C::Error> {
let cmd = [register];
self.i2c
.write(self.address as u8, &cmd)?;
let mut buffer = [0];
self.i2c
.read(self.address as u8, &mut buffer)?;
Ok(buffer[0])
}
fn get_register_as_u16(&mut self, register: u8) -> Result<u16, I2C::Error> {
let cmd = [register];
self.i2c
.write(self.address as u8, &cmd)?;
let mut buffer = [0, 0];
self.i2c
.read(self.address as u8, &mut buffer)?;
Ok(((buffer[1] as u16) << 8) + (buffer[0] as u16))
}
}
fn temperature_u12_to_f32_celsius(temperature: u16, factor: f32) -> f32 {
if !temperature.get_bit(11) {
temperature as f32 * factor
} else {
let mut bnot = !temperature;
let temp = *bnot.set_bits(11..16, 0b00000);
temp as f32 * -factor
}
}
fn temperature_f32_to_u16_celsius(mut celsius: f32) -> u16 {
let mut neg = false;
if celsius < 0.0 {
celsius = libm::fabsf(celsius);
neg = true;
}
let mut temp = celsius as u16;
if neg {
temp = *temp.set_bit(11, true);
}
temp
}