about summary refs log tree commit diff
path: root/src/ccont.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ccont.rs')
-rwxr-xr-xsrc/ccont.rs207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/ccont.rs b/src/ccont.rs
new file mode 100755
index 0000000..7a39770
--- /dev/null
+++ b/src/ccont.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")
+			}
+		}
+	}
+}