#![no_std]
#![allow(missing_docs)]
#![deny(warnings)]
#![deny(missing_copy_implementations)]
#![deny(trivial_casts)]
#![deny(trivial_numeric_casts)]
#![deny(unsafe_code)]
#![deny(unstable_features)]
#![deny(unused_import_braces)]
#![deny(unused_qualifications)]
use embedded_hal as hal;
use crate::hal::blocking::delay::DelayMs;
use crate::hal::blocking::i2c::{Write, WriteRead};
use embedded_hal::blocking::i2c::Read;
pub struct Htpa32x32d<I2C> {
i2c: I2C,
addr_sensor: u8,
#[allow(dead_code)]
addr_eeprom: u8,
woken_up: bool,
}
impl<I2C, E> Htpa32x32d<I2C>
where
I2C: Write<Error = E> + WriteRead<Error = E> + Read<Error = E>,
{
pub fn new(i2c: I2C, addr_sensor: u8, addr_eeprom: u8) -> Self {
let sensor = Self{ i2c, addr_sensor, addr_eeprom, woken_up: false };
return sensor
}
pub fn is_woken_up(&self) -> bool {
self.woken_up
}
pub fn suspend(&mut self) {
self.woken_up = false;
self.i2c.write(self.addr_sensor, &[Register::Configuration as u8, self.woken_up as u8]).err();
}
pub fn wakeup_and_write_config<DELAY>(&mut self, delay: &mut DELAY) -> Result<(), Error<E>>
where DELAY: DelayMs<u8> {
let clk = ClkTrim::from(0x14);
self.woken_up=true;
self.i2c.write(self.addr_sensor, &[Register::Configuration as u8, self.woken_up as u8]).err();
delay.delay_ms(30);
self.i2c.write(self.addr_sensor, &[Register::Trim1 as u8, 0x0C]).err();
delay.delay_ms(5);
self.i2c.write(self.addr_sensor, &[Register::Trim2 as u8, 0x0C]).err();
delay.delay_ms(5);
self.i2c.write(self.addr_sensor, &[Register::Trim3 as u8, 0x0C]).err();
delay.delay_ms(5);
self.i2c.write(self.addr_sensor, &[Register::Trim4 as u8, clk.0]).err();
delay.delay_ms(5);
self.i2c.write(self.addr_sensor, &[Register::Trim5 as u8, 0x0C]).err();
delay.delay_ms(5);
self.i2c.write(self.addr_sensor, &[Register::Trim6 as u8, 0x0C]).err();
delay.delay_ms(5);
self.i2c.write(self.addr_sensor, &[Register::Trim7 as u8, 0x88]).map_err(Error::I2c)
}
pub fn start_measurement(&mut self, measurement: Measurement) -> Result<(), Error<E>> {
if !self.woken_up { return Err(Error::Standby) }
let configuration_mask = measurement.get_configuration_bitmask();
self.i2c
.write(self.addr_sensor, &[Register::Configuration as u8, configuration_mask])
.map_err(Error::I2c)
}
pub fn check_measurement_ready(&mut self, measurement: Measurement) -> Result<bool, Error<E>> {
let status = match self.get_sensor_status() {
Ok(t) => t,
Err(e) => return Err(e)
};
Ok(measurement.check_measurement_readiness(status))
}
fn get_sensor_status(&mut self) -> Result<u8, Error<E>> {
let writebuf: [u8; 1] = [Register::Status as u8];
let mut readbuf: [u8; 1] = [0; 1];
match self.i2c.write_read(self.addr_sensor, &writebuf, &mut readbuf) {
Ok(_) => Ok(readbuf[0]),
Err(e) => Err(Error::I2c(e))
}
}
pub fn get_measurement_data(&mut self, half: SensorHalf, data: &mut [u8; 258]) -> Result<(), Error<E>> {
let sensor_half = [half as u8];
self.i2c.write_read(self.addr_sensor, &sensor_half, data)
.map_err(Error::I2c)
}
}
#[derive(Debug, Clone, Copy)]
pub enum Measurement {
Ptat {block: Block },
Blind {},
VddMeas {block: Block },
}
impl Measurement {
fn get_configuration_bitmask(self) -> u8 {
match self {
Measurement::Ptat {block} => (block as u8) << 4 | 1 << 3 | 1,
Measurement::VddMeas {block} => (block as u8) << 4 | 1 << 3 | 1 << 2 | 1,
Measurement::Blind {} => 1 << 3 | 1 << 1 | 1
}
}
fn check_measurement_readiness(self, status: u8) -> bool {
match self {
Measurement::Ptat {block } => (
((!(StatusBitmasks::Rfu as u8)) & status)
==
((block as u8) << 4) | (StatusBitmasks::Eoc as u8)) ,
Measurement::Blind {} => (
(((!(StatusBitmasks::Rfu as u8)) | (!(StatusBitmasks::Block as u8))) & status)
==
(StatusBitmasks::Blind as u8 | (StatusBitmasks::Eoc as u8))),
Measurement::VddMeas {block } => (
((!(StatusBitmasks::Rfu as u8)) & status)
==
(((block as u8) << 4) | (StatusBitmasks::VddMeas as u8) | (StatusBitmasks::Eoc as u8))),
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Address{
Sensor = 0x1A,
Eeprom = 0x50
}
enum StatusBitmasks {
Eoc = 0b0000_0001,
Blind = 0b0000_0010,
VddMeas = 0b0000_0100,
Block = 0b0011_0000,
Rfu = 0b1100_1000,
}
#[allow(dead_code)]
enum Register {
Configuration = 0x01,
Status = 0x02,
Trim1 = 0x03,
Trim2 = 0x04,
Trim3 = 0x05,
Trim4 = 0x06,
Trim5 = 0x07,
Trim6 = 0x08,
Trim7 = 0x09,
ReadTop = 0x0A,
ReadBottom = 0x0B,
}
#[derive(Debug, Clone, Copy)]
pub struct ClkTrim(u8);
impl From<u8> for ClkTrim {
fn from(val: u8) -> ClkTrim {
if val > 63 {
return ClkTrim(63);
}
return ClkTrim(val);
}
}
#[derive(Debug, Clone, Copy)]
pub enum Block {
Block0 = 0b00,
Block1 = 0b01,
Block2 = 0b10,
Block3 = 0b11,
}
impl From<u8> for Block {
fn from(val: u8) -> Block {
match val {
0 => Block::Block0,
1 => Block::Block1,
2 => Block::Block2,
3 => Block::Block3,
_ => panic!("Block too high"),
}
}
}
#[derive(Debug)]
pub enum Error<E> {
I2c(E),
Standby,
}
#[derive(Clone, Copy)]
pub enum SensorHalf{
Top = 0x0A,
Bottom =0x0B,
}
#[cfg(test)]
mod tests {
}