diff options
Diffstat (limited to 'src/currentcontroller.rs')
-rwxr-xr-x | src/currentcontroller.rs | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/currentcontroller.rs b/src/currentcontroller.rs new file mode 100755 index 0000000..7a39770 --- /dev/null +++ b/src/currentcontroller.rs @@ -0,0 +1,207 @@ +use std::time::SystemTime; + +use time::OffsetDateTime; + +use crate::mem::{GensioState, Mem}; + +pub struct CurrentController { + pub reg: Option<u8>, + 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") + } + } + } +} |