Skip to content

Commit

Permalink
Implement hle rtc
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak committed Dec 1, 2024
1 parent c2bfad0 commit 07b84d7
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 41 deletions.
26 changes: 17 additions & 9 deletions src/core/hle/rtc_hle.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use crate::core::emu::Emu;
use crate::core::emu::{io_rtc_mut, Emu};
use crate::core::hle::arm7_hle::Arm7Hle;
use crate::core::CpuType::ARM7;

pub(super) struct RtcHle;

impl RtcHle {
pub(super) fn new() -> Self {
RtcHle {}
}

fn read(reg: u8, addr: u32, len: u32, emu: &mut Emu) {
// TODO
RtcHle
}

pub(super) fn ipc_recv(&mut self, data: u32, emu: &mut Emu) {
Expand All @@ -20,20 +17,31 @@ impl RtcHle {
return;
}

let rtc = io_rtc_mut!(emu);

match cmd {
0x10 => {
// read date and time
Self::read(0x20, 0x027FFDE8, 7, emu);
rtc.update_date_time();
for i in 0..7 {
emu.mem_write::<{ ARM7 }, _>(0x027FFDE8 + i, rtc.date_time[i as usize]);
}
Arm7Hle::send_ipc_fifo(0x5, 0x9000, 0, emu);
}
0x11 => {
// read date
Self::read(0x20, 0x027FFDE8, 4, emu);
rtc.update_date_time();
for i in 0..4 {
emu.mem_write::<{ ARM7 }, _>(0x027FFDE8 + i, rtc.date_time[i as usize]);
}
Arm7Hle::send_ipc_fifo(0x5, 0x9100, 0, emu);
}
0x12 => {
// read time
Self::read(0x60, 0x027FFDE8 + 4, 3, emu);
rtc.update_date_time();
for i in 4..7 {
emu.mem_write::<{ ARM7 }, _>(0x027FFDE8 + i, rtc.date_time[i as usize]);
}
Arm7Hle::send_ipc_fifo(0x5, 0x9200, 0, emu);
}
_ => {}
Expand Down
66 changes: 34 additions & 32 deletions src/core/rtc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@ use chrono::{Datelike, Timelike};
#[bitsize(8)]
#[derive(FromBits)]
struct RtcReg {
data_io: u1,
clock_out: u1,
select_out: u1,
data_io: bool,
clock_out: bool,
select_out: bool,
not_used: u1,
data_dir: u1,
clock_dir: u1,
select_dir: u1,
data_dir_write: bool,
clock_dir_write: bool,
select_dir_write: bool,
not_used1: u1,
}

#[derive(Default)]
pub struct Rtc {
rtc: u8,
cs: bool,
sck: bool,
sio: bool,
select_out: bool,
clock_out: bool,
data_io: bool,
write_count: u8,
cmd: u8,
cnt: u8,
date_time: [u8; 7],
pub date_time: [u8; 7],
}

impl Rtc {
Expand All @@ -36,13 +36,13 @@ impl Rtc {
pub fn get_rtc(&self) -> u8 {
let mut reg = RtcReg::from(self.rtc);

let cs = self.cs;
let sck = !bool::from(reg.clock_dir()) && self.sck;
let sio = !bool::from(reg.data_dir()) && self.sio;
let cs = self.select_out;
let sck = !reg.clock_dir_write() && self.clock_out;
let sio = !reg.data_dir_write() && self.data_io;

reg.set_select_out(u1::new(cs as u8));
reg.set_clock_out(u1::new(sck as u8));
reg.set_data_io(u1::new(sio as u8));
reg.set_select_out(cs);
reg.set_clock_out(sck);
reg.set_data_io(sio);

u8::from(reg)
}
Expand All @@ -53,26 +53,26 @@ impl Rtc {
let dir_reg = RtcReg::from(self.rtc);
let data_reg = RtcReg::from(value);

let cs = if bool::from(dir_reg.select_dir()) { bool::from(data_reg.select_out()) } else { self.cs };
let sck = if bool::from(dir_reg.clock_dir()) { !bool::from(data_reg.clock_out()) } else { self.sck };
let sio = if bool::from(dir_reg.data_dir()) { bool::from(data_reg.data_io()) } else { self.sio };
let cs = if dir_reg.select_dir_write() { data_reg.select_out() } else { self.select_out };
let sck = if dir_reg.clock_dir_write() { !data_reg.clock_out() } else { self.clock_out };
let sio = if dir_reg.data_dir_write() { data_reg.data_io() } else { self.data_io };

self.update_rtc(cs, sck, sio);
}

fn update_rtc(&mut self, cs: bool, sck: bool, mut sio: bool) {
if cs {
if !self.sck && sck {
fn update_rtc(&mut self, select_out: bool, clock_out: bool, mut data_io: bool) {
if select_out {
if !self.clock_out && clock_out {
if self.write_count < 8 {
self.cmd |= (sio as u8) << (7 - self.write_count);
self.cmd |= (data_io as u8) << (7 - self.write_count);

if self.write_count == 7 && (self.cmd & 0xF0) != 0x60 {
self.cmd = self.cmd.reverse_bits();
}
} else if self.cmd & 1 == 1 {
sio = self.read_reg((self.cmd >> 1) & 0x7);
data_io = self.read_reg((self.cmd >> 1) & 0x7);
} else {
self.write_reg((self.cmd >> 1) & 0x7, sio);
self.write_reg((self.cmd >> 1) & 0x7, data_io);
}
self.write_count += 1;
}
Expand All @@ -81,9 +81,9 @@ impl Rtc {
self.cmd = 0;
}

self.cs = cs;
self.sck = sck;
self.sio = sio;
self.select_out = select_out;
self.clock_out = clock_out;
self.data_io = data_io;
}

fn reset(&mut self) {
Expand Down Expand Up @@ -133,28 +133,30 @@ impl Rtc {
}
}

fn update_date_time(&mut self) {
let (year, month, day, hour, is_pm, min, sec) = if IS_DEBUG {
(2000, 1, 1, 11, false, 0, 0)
pub fn update_date_time(&mut self) {
let (year, month, day, weekday, hour, is_pm, min, sec) = if IS_DEBUG {
(2000, 1, 1, 0, 11, false, 0, 0)
} else {
let local_now = chrono::Local::now();

let year = local_now.year() as u32 % 100;
let month = local_now.month() as u8;
let day = local_now.day() as u8;
let weekday = local_now.weekday() as u8;
let (hour, is_pm) = {
let hour = local_now.hour();
((if self.cnt & 0x2 == 0 { hour % 12 } else { hour }) as u8, hour >= 12)
};
let min = local_now.minute() as u8;
let sec = local_now.second() as u8;

(year, month, day, hour, is_pm, min, sec)
(year, month, day, weekday, hour, is_pm, min, sec)
};

self.date_time[0] = (((year / 10) << 4) | (year % 10)) as u8;
self.date_time[1] = ((month / 10) << 4) | (month % 10);
self.date_time[2] = ((day / 10) << 4) | (day % 10);
self.date_time[3] = ((weekday / 10) << 4) | (weekday % 10);
self.date_time[4] = ((hour / 10) << 4) | (hour % 10);
self.date_time[4] |= (is_pm as u8) << 6;
self.date_time[5] = ((min / 10) << 4) | (min % 10);
Expand Down

0 comments on commit 07b84d7

Please sign in to comment.