// HM62256 Static Ram

pub mod ramchip;
pub mod romchip;
pub mod tick;
pub mod default;
pub mod new;
pub mod dump;
mod control;

use crate::constants::constants_system::SIZE_32KB;
use crate::traits::ram_chip::RamChip;
use crate::traits::rom_chip::RomChip;
use log::debug;

/// Hitachi Semiconductor
/// 8 Bit High Speed Static Ram
/// 32KByte
pub struct Hm62256 {
    pub(crate) offset: u16,
    pub(crate) max_offset: u16,
    pub(crate) data: Box<[u8]>,
    pub(crate) address_bus: u16,
    pub(crate) data_bus: u8,
    // Chip Select
    pub(crate) cs: bool,
    // Write Enable
    pub(crate) we: bool,
    // Output Enable
    pub(crate) oe: bool
}

#[cfg(test)]
mod test {
    use super::*;
    use rand::random;
    use crate::traits::memory_chip::MemoryChip;

    #[test]
    fn smoke() {
        assert!(true)
    }

    #[test]
    fn written_data_comes_back() {
        let mut ram = Hm62256::default();

        // 100,000 random read/writes to ram that all read back right
        for _ in 0..100_000 {
            let mut offset: u16 = random();
            println!("Size = {SIZE_32KB}");
            let value: u8 = random();
            println!("Wrote [{value:02x}] to [{offset:04x}]");
            ram.write(&offset, &value);

            assert_eq!(ram.read(&offset), value)
        }
    }

    #[test]
    fn address_space_is_round() {
        // addresses written past the last address 'loop' back to 0+(offset - MAX_SIZE)
        let max_offset = SIZE_32KB;
        let test_offset = max_offset;

        // all zero
        let mut ram = Hm62256::default();
        // write FF to the addresss after the last
        ram.write(&(test_offset as u16), &0xff);

        // check all the ram for anything that isn't 0x00

        assert_eq!(ram.read(&(0x0000)), 0xff);
        for offset in 1..SIZE_32KB {
            println!("Testing offset {offset:04x} for 0x00");
            assert_eq!(ram.read(&(offset as u16)), 0x00);
        }
    }
}
