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::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,
|
||||||
|
|
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;
|
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)
|
||||||
{
|
{
|
||||||
|
|
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