use core::periph::mos6520::Mos6520;

const DDRA_OFFSET: u8 = 0x00;
const PORTA_OFFSET: u8 = 0x01;
const DDRB_OFFSET: u8 = 0x02;
const PORTB_OFFSET: u8 = 0x03;

fn actual(base: u16, offset: u8) -> u16 {
    base + offset as u16
}

#[test]
fn ddrb_tests() {
    let mut x = Mos6520::new(0x1000);
    let params = vec![
        // Offset      data  outa  ina   ddra  porta
        (DDRB_OFFSET,  0xff, 0x00, 0x00, 0xff, 0x00),
        (PORTB_OFFSET, 0xff, 0xff, 0x00, 0xff, 0xff),
        (DDRB_OFFSET,  0xaa, 0xaa, 0x55, 0xaa, 0xff),
        (DDRB_OFFSET,  0x55, 0x55, 0xaa, 0x55, 0xff),
        (PORTB_OFFSET, 0xf0, 0x50, 0xa0, 0x55, 0xf0),
        (PORTB_OFFSET, 0x0f, 0x05, 0x0a, 0x55, 0x0f),
        (DDRB_OFFSET,  0xff, 0x0f, 0x00, 0xff, 0x0f)
    ];

    for (offset, data, outb, inb, ddrb, portb) in params {
        x.tick(actual(x.offset, offset), data);
        assert_eq!(outb, x.out_b);
        assert_eq!(inb, x.in_b);
        assert_eq!(ddrb, x.ddrb);
        assert_eq!(portb, x.port_b);
    }
}

#[test]
fn ddra_tests() {
    let mut x = Mos6520::new(0x1000);
    let params = vec![
        // Offset      data  outa  ina   ddra  porta
        (DDRA_OFFSET,  0xff, 0x00, 0x00, 0xff, 0x00),
        (PORTA_OFFSET, 0xff, 0xff, 0x00, 0xff, 0xff),
        (DDRA_OFFSET,  0xaa, 0xaa, 0x55, 0xaa, 0xff),
        (DDRA_OFFSET,  0x55, 0x55, 0xaa, 0x55, 0xff),
        (PORTA_OFFSET, 0xf0, 0x50, 0xa0, 0x55, 0xf0),
        (PORTA_OFFSET, 0x0f, 0x05, 0x0a, 0x55, 0x0f),
        (DDRA_OFFSET,  0xff, 0x0f, 0x00, 0xff, 0x0f)
    ];

    for (offset, data, outa, ina, ddra, porta) in params {
        x.tick(actual(x.offset, offset), data);
        assert_eq!(outa, x.out_a);
        assert_eq!(ina, x.in_a);
        assert_eq!(ddra, x.ddra);
        assert_eq!(porta, x.port_a);
    }
}