#![no_std]
#![deny(warnings)]
use bit_field::BitField;
use embedded_hal::i2c::{ErrorType, I2c};
pub struct Max6639<I2C> {
i2c: I2C,
address: u8,
}
pub enum AddressPin {
Pullup = 0x2F,
Float = 0x2E,
Pulldown = 0x2C,
}
#[doc(hidden)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug)]
enum Register {
Status = 0x02,
GlobalConfig = 0x04,
Fan1Config1 = 0x10,
Fan1Config2a = 0x11,
Fan1Config2b = 0x12,
Fan1Config3 = 0x13,
Fan2Config1 = 0x14,
Fan2Config2a = 0x15,
Fan2Config2b = 0x16,
Fan2Config3 = 0x17,
Fan1TachCount = 0x20,
Fan2TachCount = 0x21,
Fan1DutyCycle = 0x26,
Fan2DutyCycle = 0x27,
DeviceId = 0x3d,
ManufacturerId = 0x3e,
DeviceRevision = 0x3f,
}
#[derive(Copy, Clone, Debug)]
pub enum Error<E> {
Interface(E),
FanFail,
Bounds,
}
impl<E> From<E> for Error<E> {
fn from(err: E) -> Error<E> {
Error::Interface(err)
}
}
#[derive(Copy, Clone, Debug)]
pub enum Fan {
Fan1,
Fan2,
}
impl<I2C> Max6639<I2C>
where
I2C: I2c,
<I2C as ErrorType>::Error: Into<<I2C as ErrorType>::Error>,
{
pub fn new(
i2c: I2C,
address_pin: AddressPin,
) -> Result<Self, Error<<I2C as ErrorType>::Error>> {
let mut device = Max6639 {
i2c,
address: address_pin as u8,
};
device.write(Register::GlobalConfig, 1 << 6)?;
device.write(Register::Fan1DutyCycle, 0)?;
device.write(Register::Fan2DutyCycle, 0)?;
device.write(Register::Fan1Config1, 1 << 7 | 0b10)?;
device.write(Register::Fan2Config1, 1 << 7 | 0b10)?;
Ok(device)
}
fn write(
&mut self,
register: Register,
value: u8,
) -> Result<(), Error<<I2C as ErrorType>::Error>> {
let write_data: [u8; 2] = [register as u8, value];
self.i2c
.write(self.address, &write_data)
.map_err(|err| err.into())?;
Ok(())
}
fn read(&mut self, register: Register) -> Result<u8, Error<<I2C as ErrorType>::Error>> {
let mut result: [u8; 1] = [0; 1];
self.i2c
.write_read(self.address, &[register as u8], &mut result)?;
Ok(result[0])
}
pub fn set_duty_cycle(
&mut self,
fan: Fan,
duty_cycle: f32,
) -> Result<(), Error<<I2C as ErrorType>::Error>> {
if duty_cycle < 0.0 || duty_cycle > 1.0 {
return Err(Error::Bounds);
}
let register_value = (duty_cycle * 120.0) as u8;
let register = match fan {
Fan::Fan1 => Register::Fan1DutyCycle,
Fan::Fan2 => Register::Fan2DutyCycle,
};
self.write(register, register_value)?;
if self.check_fan_fault(fan)? {
Err(Error::FanFail)
} else {
Ok(())
}
}
pub fn check_fan_fault(&mut self, fan: Fan) -> Result<bool, Error<<I2C as ErrorType>::Error>> {
let status_register = self.read(Register::Status)?;
match fan {
Fan::Fan1 => Ok(status_register.get_bit(1)),
Fan::Fan2 => Ok(status_register.get_bit(0)),
}
}
pub fn current_rpms(&mut self, fan: Fan) -> Result<u16, Error<<I2C as ErrorType>::Error>> {
let tach_reg = match fan {
Fan::Fan1 => Register::Fan1TachCount,
Fan::Fan2 => Register::Fan2TachCount,
};
let tach_count = self.read(tach_reg)?;
if tach_count == 0xFF {
Ok(0)
} else {
Ok(((60 * 4000) as f32 / tach_count as f32) as u16)
}
}
}