use std::time::SystemTime; use time::OffsetDateTime; use crate::mem::{GensioState, Mem}; pub struct CurrentController { pub reg: Option, pub control_reg: u8, //TODO: make enum pub charging_mode: u8, pub tenbit_adc: u16, pub head_hook_detection: u8, //TODO: make enum pub watchdog_setting: u8, pub rtc_enable: u8, //TODO: track time in struct pub alarm_minute: u8, pub alarm_hour: u8, pub rtc_calibration: u8, /// Bit 0 - RTC bat present /// Bit 3/3 - CContINT 3-7 pub irq: u8, /// True(1)/False(0) pub irq_mask: u8, } impl CurrentController { pub fn new() -> Self { Self { reg: None, control_reg: 0, charging_mode: 0, tenbit_adc: 0, head_hook_detection: 0, watchdog_setting: 0, rtc_enable: 0, alarm_minute: 0, alarm_hour: 12, rtc_calibration: 0, irq: 0, irq_mask: 0, } } pub fn event(&mut self, mem: &mut Mem) { log::trace!("CCont value={:02X}", mem.inner[Mem::CCONT_WRITE]); log::trace!( "CCont write >> 3 value={:02X}", mem.inner[Mem::CCONT_WRITE] >> 3 ); log::trace!( "CCont read ^ 4 >> 3 value={:02X}", (mem.inner[Mem::CCONT_WRITE] ^ 0x04) >> 3 ); let and_four = mem.inner[Mem::CCONT_WRITE] & 0x04; match self.reg { None => { if and_four > 0 { self.read(mem.inner[Mem::CCONT_WRITE], mem); } else { self.reg = Some(mem.inner[Mem::CCONT_WRITE]) } } Some(reg) => { self.write(reg, mem); self.reg = None; } } } pub fn read(&mut self, addr: u8, mem: &mut Mem) { log::trace!("ccont::read()"); let reg = (addr ^ 0x04) >> 3; match reg { 0x02 => { log::trace!("CCont A/D 0-7 Read"); let adc = self.tenbit_adc.to_be_bytes(); mem.inner[Mem::CCONT_READ] = adc[0]; } 0x03 => { log::trace!("CCont Headset/Hooked flag?"); mem.inner[Mem::CCONT_READ] = self.head_hook_detection; } 0x04 => { log::trace!("CCont A/D 8-9 Read & test bits"); let adc = self.tenbit_adc.to_be_bytes(); mem.inner[Mem::CCONT_READ] = ((adc[1] >> 6) & 3) | 0b101100_00; } 0x09 => { log::trace!("CCont RTC Second"); let time = OffsetDateTime::now_local().unwrap(); mem.inner[Mem::CCONT_READ] = time.second(); } 0x0A => { log::trace!("CCont RTC Minute"); let time = OffsetDateTime::now_local().unwrap(); mem.inner[Mem::CCONT_READ] = time.minute(); } 0x0B => { log::trace!("CCont RTC Hour"); let time = OffsetDateTime::now_local().unwrap(); mem.inner[Mem::CCONT_READ] = time.hour(); } 0x0C => { log::trace!("CCont RTC Day"); let time = OffsetDateTime::now_local().unwrap(); mem.inner[Mem::CCONT_READ] = time.day(); } 0x0D => { log::trace!("CCont RTC Alarm Minute"); mem.inner[Mem::CCONT_READ] = self.alarm_minute; } 0x0E => { log::trace!("CCont RTC Alarm Hour"); mem.inner[Mem::CCONT_READ] = self.alarm_hour; } 0x0F => { log::trace!("CCont RTC Calibration"); mem.inner[Mem::CCONT_READ] = self.rtc_calibration; } 0x10 => { log::trace!("CCont RTC Interrupt Controller"); mem.inner[Mem::CCONT_READ] = self.irq; } 0x11 => { log::trace!("CCont RTC IRQ Mask"); mem.inner[Mem::CCONT_READ] = self.irq_mask; } reg => { log::trace!("CCont !!! {reg:02X} unknown read!"); panic!() } } //mem.gensio_status_clear(); mem.set_gensio_status(GensioState::DataRead); //mem.set_gensio_status(GensioState::TransactionReady); } pub fn write(&mut self, addr: u8, mem: &mut Mem) { log::trace!("ccont::write()"); let reg = addr >> 3; let val = mem.inner[Mem::CCONT_WRITE]; match reg { 0x00 => { log::trace!("CCont control register"); self.control_reg = val; } 0x01 => { log::trace!("CCont PWM (charger)"); self.charging_mode = val; } 0x03 => { log::trace!("CCont A/D Read 0-7 (why call write?)"); log::info!("Not writing to AD due to confusion on how that works"); } 0x05 => { log::trace!("CCont Headset/Hooked flag?"); self.head_hook_detection = val; } 0x06 => { log::trace!("CCont Set Watchdog"); self.watchdog_setting = val; } 0x07 => { log::trace!("CCont RTC Enable"); self.rtc_enable = val; } 0x08 => { log::trace!("CCont RTC Second"); log::info!("Ignoring RTC Second write due to current RTC implementation") } 0x0C => { log::trace!("CCont RTC Day"); log::info!("Ignoring RTC Day write due to current RTC implementation") } 0x0D => { log::trace!("CCont RTC Alarm Minute"); self.alarm_minute = val; } 0x0E => { log::trace!("CCont RTC Alarm Hour"); self.alarm_hour = val; } 0x0F => { log::trace!("CCont RTC Callibration"); self.rtc_calibration = val; } 0x10 => { log::trace!("CCont RTC Interrupt Controller"); self.irq = val; } 0x11 => { log::trace!("CCont RTC IRQ Mask"); self.irq_mask = val; } reg => { log::trace!("CCont !!! {reg:02X} unknown register") } } } }