mod address;
mod eeprom;
pub mod hamming;
use core::cmp::Ordering;
use core::iter;
use crate::common::{Address, MelexisCamera, PixelAddressRange};
use crate::register::{AccessPattern, Subpage};
pub use address::RamAddress;
pub use eeprom::Mlx90641Calibration;
pub(crate) const HEIGHT: usize = 12;
pub(crate) const WIDTH: usize = 16;
pub(crate) const NUM_PIXELS: usize = HEIGHT * WIDTH;
#[derive(Clone, Debug, PartialEq)]
pub struct Mlx90641();
impl MelexisCamera for Mlx90641 {
type PixelRangeIterator = SubpageInterleave;
type PixelsInSubpageIterator = AllPixels<NUM_PIXELS>;
fn pixel_ranges(subpage: Subpage, access_pattern: AccessPattern) -> Self::PixelRangeIterator {
match access_pattern {
AccessPattern::Chess => panic!("The chess pattern is not documented for the MLX90641"),
AccessPattern::Interleave => SubpageInterleave::new(subpage),
}
}
fn pixels_in_subpage(
_subpage: Subpage,
_access_pattern: AccessPattern,
) -> Self::PixelsInSubpageIterator {
AllPixels::default()
}
fn t_a_v_be() -> Address {
RamAddress::AmbientTemperatureVoltageBe.into()
}
fn t_a_ptat() -> Address {
RamAddress::AmbientTemperatureVoltage.into()
}
fn compensation_pixel(subpage: Subpage) -> Address {
match subpage {
Subpage::Zero => RamAddress::CompensationPixelZero,
Subpage::One => RamAddress::CompensationPixelOne,
}
.into()
}
fn gain() -> Address {
RamAddress::Gain.into()
}
fn v_dd_pixel() -> Address {
RamAddress::PixelSupplyVoltage.into()
}
fn resolution_correction(calibrated_resolution: u8, current_resolution: u8) -> f32 {
let resolution_exp: i8 = calibrated_resolution as i8 - current_resolution as i8;
f32::from(resolution_exp).exp2()
}
}
#[derive(Clone, Copy, Debug)]
pub struct SubpageInterleave {
current_address: u16,
}
impl SubpageInterleave {
const STRIDE_LENGTH: u16 = 32 * 2;
const PIXEL_END_ADDRESS: u16 = 0x0580;
fn new(subpage: Subpage) -> Self {
let starting_address: u16 = match subpage {
Subpage::Zero => RamAddress::Base as u16,
Subpage::One => RamAddress::Base as u16 + Self::STRIDE_LENGTH,
};
Self {
current_address: starting_address,
}
}
}
impl iter::Iterator for SubpageInterleave {
type Item = PixelAddressRange;
fn next(&mut self) -> Option<Self::Item> {
match self.current_address.cmp(&Self::PIXEL_END_ADDRESS) {
Ordering::Less => {
let next_value = PixelAddressRange {
start_address: self.current_address.into(),
length: Self::STRIDE_LENGTH as usize,
};
self.current_address += Self::STRIDE_LENGTH * 2;
Some(next_value)
}
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct AllPixels<const COUNT: usize> {
current: usize,
}
impl<const COUNT: usize> iter::Iterator for AllPixels<COUNT> {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
match self.current.cmp(&COUNT) {
Ordering::Less => {
self.current += 1;
Some(true)
}
_ => None,
}
}
}