core: Start working on RTC

Former-commit-id: cb23bbade323883509347fce26f78f2cf43d8788
Former-commit-id: d01bef5267429a7d76a50dbc7c185f0513af00ec
This commit is contained in:
Michel Heily 2020-05-16 19:42:24 +03:00 committed by MishMish
parent d2f4b55f21
commit 304ac31c02
4 changed files with 146 additions and 0 deletions

View file

@ -7,6 +7,7 @@ use super::super::{GBAError, GBAResult};
use super::backup::eeprom::*; use super::backup::eeprom::*;
use super::backup::flash::*; use super::backup::flash::*;
use super::backup::{BackupFile, BackupType}; use super::backup::{BackupFile, BackupType};
use super::gpio::Gpio;
use super::header; use super::header;
use super::BackupMedia; use super::BackupMedia;
use super::Cartridge; use super::Cartridge;
@ -126,9 +127,12 @@ impl GamepakBuilder {
let backup = create_backup(self.save_type, self.save_path); let backup = create_backup(self.save_type, self.save_path);
let gpio = Gpio::new();
let size = bytes.len(); let size = bytes.len();
Ok(Cartridge { Ok(Cartridge {
header: header, header: header,
gpio: gpio,
bytes: bytes.into_boxed_slice(), bytes: bytes.into_boxed_slice(),
size: size, size: size,
backup: backup, backup: backup,

View file

@ -0,0 +1,90 @@
use super::rtc::Rtc;
use super::{GPIO_PORT_CONTROL, GPIO_PORT_DATA, GPIO_PORT_DIRECTION};
use bit::BitIndex;
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
enum GpioDirection {
In = 0,
Out = 1,
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
enum GpioPortControl {
WriteOnly = 0,
ReadWrite = 1,
}
trait GpioDevice: Sized {
fn write(&mut self);
fn read(&mut self);
}
enum GpioDeviceType {
Rtc,
SolarSensor,
Gyro,
None,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Gpio {
rtc: Option<RefCell<Rtc>>,
direction: [GpioDirection; 4],
control: GpioPortControl,
}
impl Gpio {
pub fn new() -> Self {
Gpio {
rtc: None,
direction: [GpioDirection::In; 4],
control: GpioPortControl::WriteOnly,
}
}
pub fn is_readable(&self) -> bool {
self.control != GpioPortControl::WriteOnly
}
pub fn read(&self, addr: u32) -> u16 {
match addr {
GPIO_PORT_DATA => unimplemented!(),
GPIO_PORT_DIRECTION => {
let mut direction = 0u16;
for i in 0..4 {
direction.set_bit(i, self.direction[i] == GpioDirection::Out);
}
direction
}
GPIO_PORT_CONTROL => self.control as u16,
_ => unreachable!(),
}
}
pub fn write(&mut self, addr: u32) -> u16 {
match addr {
GPIO_PORT_DATA => unimplemented!(),
GPIO_PORT_DIRECTION => {
let mut direction = 0u16;
for i in 0..4 {
direction.set_bit(i, self.direction[i] == GpioDirection::Out);
}
direction
}
GPIO_PORT_CONTROL => self.control as u16,
_ => unreachable!(),
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_gpio() {
unimplemented!();
}
}

View file

@ -13,10 +13,18 @@ use backup::flash::Flash;
pub use backup::BackupType; pub use backup::BackupType;
use backup::{BackupFile, BackupMemoryInterface}; use backup::{BackupFile, BackupMemoryInterface};
mod gpio;
mod rtc;
use gpio::Gpio;
mod builder; mod builder;
mod loader; mod loader;
pub use builder::GamepakBuilder; pub use builder::GamepakBuilder;
pub const GPIO_PORT_DATA: u32 = 0x0800_00C4;
pub const GPIO_PORT_DIRECTION: u32 = 0x0800_00C6;
pub const GPIO_PORT_CONTROL: u32 = 0x0800_00C8;
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub enum BackupMedia { pub enum BackupMedia {
Sram(BackupFile), Sram(BackupFile),
@ -32,6 +40,7 @@ pub struct Cartridge {
pub header: CartridgeHeader, pub header: CartridgeHeader,
bytes: Box<[u8]>, bytes: Box<[u8]>,
size: usize, size: usize,
gpio: Gpio,
symbols: Option<SymbolTable>, // TODO move it somewhere else symbols: Option<SymbolTable>, // TODO move it somewhere else
pub(in crate) backup: BackupMedia, pub(in crate) backup: BackupMedia,
} }
@ -46,6 +55,13 @@ use super::sysbus::consts::*;
pub const EEPROM_BASE_ADDR: u32 = 0x0DFF_FF00; pub const EEPROM_BASE_ADDR: u32 = 0x0DFF_FF00;
fn is_gpio_access(addr: u32) -> bool {
match addr {
GPIO_PORT_DATA | GPIO_PORT_DIRECTION | GPIO_PORT_CONTROL => true,
_ => false,
}
}
impl Bus for Cartridge { impl Bus for Cartridge {
fn read_8(&self, addr: Addr) -> u8 { fn read_8(&self, addr: Addr) -> u8 {
let offset = (addr & 0x01ff_ffff) as usize; let offset = (addr & 0x01ff_ffff) as usize;
@ -66,6 +82,10 @@ impl Bus for Cartridge {
} }
fn read_16(&self, addr: u32) -> u16 { fn read_16(&self, addr: u32) -> u16 {
if is_gpio_access(addr) && self.gpio.is_readable() {
return self.gpio.read(addr);
}
if addr & 0xff000000 == GAMEPAK_WS2_HI if addr & 0xff000000 == GAMEPAK_WS2_HI
&& (self.bytes.len() <= 16 * 1024 * 1024 || addr >= EEPROM_BASE_ADDR) && (self.bytes.len() <= 16 * 1024 * 1024 || addr >= EEPROM_BASE_ADDR)
{ {
@ -88,6 +108,11 @@ impl Bus for Cartridge {
} }
fn write_16(&mut self, addr: u32, value: u16) { fn write_16(&mut self, addr: u32, value: u16) {
if is_gpio_access(addr) {
self.gpio.write(addr);
return;
}
if addr & 0xff000000 == GAMEPAK_WS2_HI if addr & 0xff000000 == GAMEPAK_WS2_HI
&& (self.bytes.len() <= 16 * 1024 * 1024 || addr >= EEPROM_BASE_ADDR) && (self.bytes.len() <= 16 * 1024 * 1024 || addr >= EEPROM_BASE_ADDR)
{ {

View file

@ -0,0 +1,27 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
enum Port {
#[doc("Serial Clock")]
Sck = 0,
#[doc("Serial IO")]
Sio = 1,
#[doc("Chip Select")]
Cs = 2,
}
/// Model of the S3511 8pin RTC
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Rtc {}
impl Rtc {
pub fn new() -> Self {
Rtc {}
}
pub fn read_port(port: usize) -> u8 {
0
}
pub fn write_port(port: usize) {}
}