core: Start working on RTC
Former-commit-id: cb23bbade323883509347fce26f78f2cf43d8788 Former-commit-id: d01bef5267429a7d76a50dbc7c185f0513af00ec
This commit is contained in:
parent
d2f4b55f21
commit
304ac31c02
|
@ -7,6 +7,7 @@ use super::super::{GBAError, GBAResult};
|
|||
use super::backup::eeprom::*;
|
||||
use super::backup::flash::*;
|
||||
use super::backup::{BackupFile, BackupType};
|
||||
use super::gpio::Gpio;
|
||||
use super::header;
|
||||
use super::BackupMedia;
|
||||
use super::Cartridge;
|
||||
|
@ -126,9 +127,12 @@ impl GamepakBuilder {
|
|||
|
||||
let backup = create_backup(self.save_type, self.save_path);
|
||||
|
||||
let gpio = Gpio::new();
|
||||
|
||||
let size = bytes.len();
|
||||
Ok(Cartridge {
|
||||
header: header,
|
||||
gpio: gpio,
|
||||
bytes: bytes.into_boxed_slice(),
|
||||
size: size,
|
||||
backup: backup,
|
||||
|
|
90
rustboyadvance-core/src/cartridge/gpio.rs
Normal file
90
rustboyadvance-core/src/cartridge/gpio.rs
Normal 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!();
|
||||
}
|
||||
}
|
|
@ -13,10 +13,18 @@ use backup::flash::Flash;
|
|||
pub use backup::BackupType;
|
||||
use backup::{BackupFile, BackupMemoryInterface};
|
||||
|
||||
mod gpio;
|
||||
mod rtc;
|
||||
use gpio::Gpio;
|
||||
|
||||
mod builder;
|
||||
mod loader;
|
||||
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)]
|
||||
pub enum BackupMedia {
|
||||
Sram(BackupFile),
|
||||
|
@ -32,6 +40,7 @@ pub struct Cartridge {
|
|||
pub header: CartridgeHeader,
|
||||
bytes: Box<[u8]>,
|
||||
size: usize,
|
||||
gpio: Gpio,
|
||||
symbols: Option<SymbolTable>, // TODO move it somewhere else
|
||||
pub(in crate) backup: BackupMedia,
|
||||
}
|
||||
|
@ -46,6 +55,13 @@ use super::sysbus::consts::*;
|
|||
|
||||
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 {
|
||||
fn read_8(&self, addr: Addr) -> u8 {
|
||||
let offset = (addr & 0x01ff_ffff) as usize;
|
||||
|
@ -66,6 +82,10 @@ impl Bus for Cartridge {
|
|||
}
|
||||
|
||||
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
|
||||
&& (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) {
|
||||
if is_gpio_access(addr) {
|
||||
self.gpio.write(addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if addr & 0xff000000 == GAMEPAK_WS2_HI
|
||||
&& (self.bytes.len() <= 16 * 1024 * 1024 || addr >= EEPROM_BASE_ADDR)
|
||||
{
|
||||
|
|
27
rustboyadvance-core/src/cartridge/rtc.rs
Normal file
27
rustboyadvance-core/src/cartridge/rtc.rs
Normal 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) {}
|
||||
}
|
Reference in a new issue