vines 0.0.3

NES emulator library
Documentation
const RIGHT: u8 = 0b10000000;
const LEFT: u8 = 0b01000000;
const DOWN: u8 = 0b00100000;
const UP: u8 = 0b00010000;
const START: u8 = 0b00001000;
const SELECT: u8 = 0b00000100;
const BUTTON_B: u8 = 0b00000010;
const BUTTON_A: u8 = 0b00000001;

#[derive(PartialEq, Debug)]
enum StrobeMode {
    ON,
    OFF,
}

#[derive(PartialEq, Debug)]
enum ButtonState {
    RELEASED = 0,
    PRESSED = 1,
}

pub struct Controller {
    strobe_mode: StrobeMode,
    index: u8,
    status: u8,
}

impl Controller {
    pub const RIGHT: u8 = RIGHT;
    pub const LEFT: u8 = LEFT;
    pub const DOWN: u8 = DOWN;
    pub const UP: u8 = UP;
    pub const START: u8 = START;
    pub const SELECT: u8 = SELECT;
    pub const BUTTON_B: u8 = BUTTON_B;
    pub const BUTTON_A: u8 = BUTTON_A;
    pub fn new() -> Self {
        return Controller {
            strobe_mode: StrobeMode::OFF,
            index: 0,
            status: 0b0000_0000,
        };
    }

    pub fn read_u8(&mut self) -> u8 {
        return self.read() as u8;
    }

    pub fn write(&mut self, data: u8) {
        assert!(data == 0 || data == 1);

        if data == 0 {
            self.strobe_mode = StrobeMode::OFF;
        } else {
            self.strobe_mode = StrobeMode::ON;
            self.index = 0;
        }
    }
    fn read(&mut self) -> ButtonState {
        if self.index > 7 {
            return ButtonState::PRESSED;
        }
        let result = match self.strobe_mode {
            StrobeMode::ON => self.status & BUTTON_A,
            StrobeMode::OFF => {
                let mut mask = 1;
                mask = mask << self.index;
                self.index += 1;
                self.status & mask
            }
        };

        if result == 0 {
            return ButtonState::RELEASED;
        } else {
            return ButtonState::PRESSED;
        }
    }

    pub fn press_button(&mut self, button: u8) {
        self.status = self.status | button;
    }

    pub fn release_button(&mut self, button: u8) {
        self.status = self.status & (!button);
    }
}

#[cfg(test)]
mod test_controller {
    use super::*;
    use test_case::test_case;
    #[test]
    fn test_controller_init_state() {
        let controller = Controller::new();
        assert_eq!(0b0000_0000, controller.status);
        assert_eq!(0, controller.index);
        assert_eq!(StrobeMode::OFF, controller.strobe_mode);
    }

    #[test_case(0b0000_0001, ButtonState::PRESSED)]
    #[test_case(0b0000_0000, ButtonState::RELEASED)]
    fn test_read_when_strobe_mode_is_on(controller_status: u8, expected_button_state: ButtonState) {
        let mut controller = Controller::new();
        controller.strobe_mode = StrobeMode::ON;

        controller.status = controller_status;
        assert_eq!(expected_button_state, controller.read());
    }

    #[test]
    fn test_read_when_strobe_mode_is_off() {}

    #[test]
    fn test_read_u8_when_strobe_mode_is_off() {}

    #[test]
    fn test_read_u8_when_strobe_mode_is_on() {}

    #[test]
    fn test_write() {}
}