moa/src/devices/mc68681.rs

151 lines
4.1 KiB
Rust
Raw Normal View History

2021-09-30 06:21:11 +00:00
use std::slice::Iter;
use std::process::Command;
use std::io::{Read, Write};
use std::os::unix::io::{RawFd, AsRawFd};
2021-09-30 06:21:11 +00:00
use nix::pty::{self, PtyMaster};
use nix::fcntl::OFlag;
use nix::unistd::sleep;
use nix::poll::{poll, PollFd, PollFlags};
2021-10-02 00:53:55 +00:00
use nix::fcntl::{fcntl, FcntlArg};
use crate::error::Error;
2021-09-30 06:21:11 +00:00
use crate::memory::{Address, Addressable};
const REG_MR1A_MR2A: Address = 0x01;
const REG_SRA_RD: Address = 0x03;
const REG_CSRA_WR: Address = 0x03;
const REG_CRA_WR: Address = 0x05;
const REG_TBA_WR: Address = 0x07;
const REG_RBA_RD: Address = 0x07;
const REG_ACR_WR: Address = 0x09;
const REG_CTUR_WR: Address = 0x0D;
const REG_CTLR_WR: Address = 0x0F;
const REG_START_RD: Address = 0x1D;
const REG_STOP_RD: Address = 0x1F;
const REG_IPCR_RD: Address = 0x09;
const REG_OPCR_WR: Address = 0x1B;
const REG_INPUT_RD: Address = 0x1B;
const REG_OUT_SET: Address = 0x1D;
const REG_OUT_RESET: Address = 0x1F;
const REG_ISR_RD: Address = 0x0B;
const REG_IMR_WR: Address = 0x0B;
const REG_IVR_WR: Address = 0x19;
// Status Register Bits (SRA/SRB)
const SR_RECEIVED_BREAK: u8 = 0x80;
const SR_FRAMING_ERROR: u8 = 0x40;
const SR_PARITY_ERROR: u8 = 0x20;
const SR_OVERRUN_ERROR: u8 = 0x10;
const SR_TX_EMPTY: u8 = 0x08;
const SR_TX_READY: u8 = 0x04;
const SR_RX_FULL: u8 = 0x02;
const SR_RX_READY: u8 = 0x01;
2021-09-30 06:21:11 +00:00
const DEV_NAME: &'static str = "mc68681";
pub struct MC68681 {
pub tty: Option<PtyMaster>,
2021-10-02 00:53:55 +00:00
pub status: u8,
pub input: u8,
2021-09-30 06:21:11 +00:00
}
impl MC68681 {
pub fn new() -> Self {
MC68681 {
tty: None,
2021-10-02 00:53:55 +00:00
status: 0x0C,
input: 0,
2021-09-30 06:21:11 +00:00
}
}
pub fn open(&mut self) -> Result<(), Error> {
let result = pty::posix_openpt(OFlag::O_RDWR).and_then(|master| {
pty::grantpt(&master).and_then(|_| pty::unlockpt(&master)).and_then(|_| Ok(master))
});
match result {
Ok(master) => {
let name = unsafe { pty::ptsname(&master).map_err(|_| Error::new("Unable to get pty name"))? };
println!("Open {}", name);
2021-10-02 00:53:55 +00:00
fcntl(master.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).unwrap();
self.tty = Some(master);
2021-10-02 00:53:55 +00:00
Command::new("x-terminal-emulator").arg("-e").arg(&format!("pyserial-miniterm {}", name)).spawn().unwrap();
sleep(1);
Ok(())
},
Err(_) => Err(Error::new("Error opening new pseudoterminal")),
}
}
pub fn step(&mut self) -> Result<(), Error> {
if !self.rx_ready() && self.tty.is_some() {
2021-10-02 00:53:55 +00:00
let mut buf = [0; 1];
let tty = self.tty.as_mut().unwrap();
match tty.read(&mut buf) {
Ok(count) => {
println!("READ {:?}", count);
self.input = buf[0];
self.status |= SR_RX_READY;
},
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { },
Err(err) => {
println!("ERROR: {:?}", err);
}
}
}
Ok(())
}
pub fn rx_ready(&self) -> bool {
2021-10-02 00:53:55 +00:00
(self.status & SR_RX_READY) != 0
}
2021-09-30 06:21:11 +00:00
}
impl Addressable for MC68681 {
fn len(&self) -> usize {
0x30
}
2021-10-06 02:58:22 +00:00
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
let mut data = vec![0; count];
// TODO this is temporary
self.step();
2021-09-30 06:21:11 +00:00
match addr {
2021-10-02 00:53:55 +00:00
REG_SRA_RD => {
data[0] = self.status
},
REG_RBA_RD => {
2021-10-02 00:53:55 +00:00
data[0] = self.input;
self.status &= !SR_RX_READY;
},
2021-10-02 00:53:55 +00:00
_ => { println!("{}: reading from {:0x}", DEV_NAME, addr); data[0] = self.input; },
}
2021-10-02 00:53:55 +00:00
2021-10-06 02:58:22 +00:00
Ok(data)
}
2021-10-06 02:58:22 +00:00
fn write(&mut self, mut addr: Address, data: &[u8]) -> Result<(), Error> {
match addr {
REG_TBA_WR => {
println!("{}: {}", DEV_NAME, data[0] as char);
self.tty.as_mut().map(|tty| tty.write_all(&[data[0]]));
},
_ => { println!("{}: writing {:0x} to {:0x}", DEV_NAME, data[0], addr); },
}
2021-10-06 02:58:22 +00:00
Ok(())
}
}
2021-10-02 00:53:55 +00:00