Support keyboard transmit (bell) requests
Bumping version to 0.4.0, because this is a breaking change.
This commit is contained in:
parent
5fd15da4ae
commit
17b81b71da
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "dmd_core"
|
||||
description = "AT&T / Teletype DMD 5620 Terminal Emulator - Core Library"
|
||||
version = "0.3.1"
|
||||
version = "0.4.0"
|
||||
authors = ["Seth Morabito <web@loomcom.com>"]
|
||||
homepage = "https://github.com/sethm/dmd_core"
|
||||
repository = "https://github.com/sethm/dmd_core"
|
||||
|
@ -16,4 +16,4 @@ lazy_static = "^1.2.0"
|
|||
[badges]
|
||||
travis-ci = { repository = "https://github.com/sethm/dmd_core", branch = "master" }
|
||||
|
||||
maintenance = { status = "actively-developed" }
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
|
|
@ -27,6 +27,10 @@ however.
|
|||
|
||||
## Changelog
|
||||
|
||||
0.4.0: Breaking change. TX to the keyboard from the terminal is
|
||||
now supported, so that clients can use it to detect when
|
||||
a bell (^G) request has been sent.
|
||||
|
||||
0.3.1: Added exception handling for memory errors, and a `run` function
|
||||
to free-run the CPU for a given number of steps.
|
||||
|
||||
|
|
|
@ -184,8 +184,12 @@ impl Bus {
|
|||
self.duart.mouse_up(button);
|
||||
}
|
||||
|
||||
pub fn tx_poll(&mut self) -> Option<u8> {
|
||||
self.duart.tx_poll()
|
||||
pub fn rs232_tx_poll(&mut self) -> Option<u8> {
|
||||
self.duart.rs232_tx_poll()
|
||||
}
|
||||
|
||||
pub fn kb_tx_poll(&mut self) -> Option<u8> {
|
||||
self.duart.kb_tx_poll()
|
||||
}
|
||||
|
||||
pub fn rx_char(&mut self, char: u8) {
|
||||
|
|
|
@ -1315,7 +1315,7 @@ impl Cpu {
|
|||
}
|
||||
MNEGW | MNEGH | MNEGB => {
|
||||
let a = self.read_op(bus, 0)?;
|
||||
let result = !a + 1;
|
||||
let result = (!a).wrapping_add(1);
|
||||
self.write_op(bus, 1, result)?;
|
||||
self.set_nz_flags(result, 1);
|
||||
self.set_c_flag(false);
|
||||
|
|
11
src/dmd.rs
11
src/dmd.rs
|
@ -107,8 +107,15 @@ impl Dmd {
|
|||
///
|
||||
/// Poll for a character to transmit from the terminal to the host.
|
||||
///
|
||||
pub fn tx_poll(&mut self) -> Option<u8> {
|
||||
self.bus.tx_poll()
|
||||
pub fn rs232_tx_poll(&mut self) -> Option<u8> {
|
||||
self.bus.rs232_tx_poll()
|
||||
}
|
||||
|
||||
///
|
||||
/// Poll for a character to transmit from the terminal to the keyboard.
|
||||
///
|
||||
pub fn kb_tx_poll(&mut self) -> Option<u8> {
|
||||
self.bus.kb_tx_poll()
|
||||
}
|
||||
|
||||
///
|
||||
|
|
60
src/duart.rs
60
src/duart.rs
|
@ -81,6 +81,7 @@ const CMD_DTX: u8 = 0x08;
|
|||
//
|
||||
const ISTS_TAI: u8 = 0x01;
|
||||
const ISTS_RAI: u8 = 0x02;
|
||||
const ISTS_TBI: u8 = 0x10;
|
||||
const ISTS_RBI: u8 = 0x20;
|
||||
const ISTS_IPC: u8 = 0x80;
|
||||
|
||||
|
@ -210,34 +211,49 @@ impl Duart {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn service(&mut self) {
|
||||
let mut ctx = &mut self.ports[PORT_0];
|
||||
fn handle_tx(&mut self, port: usize) {
|
||||
let mut ctx = &mut self.ports[port];
|
||||
|
||||
let (tx_istat, rx_istat) = match port {
|
||||
0 => (ISTS_TAI, ISTS_RAI),
|
||||
_ => (ISTS_TBI, ISTS_RBI),
|
||||
};
|
||||
|
||||
// Deal with RS-232 Transmit
|
||||
if (ctx.conf & CNF_ETX) != 0 &&
|
||||
(ctx.stat & STS_TXR) == 0 &&
|
||||
(ctx.stat & STS_TXE) == 0 && Instant::now() >= ctx.next_tx {
|
||||
(ctx.stat & STS_TXE) == 0 && Instant::now() >= ctx.next_tx
|
||||
{
|
||||
let c = ctx.tx_data;
|
||||
ctx.stat |= STS_TXR;
|
||||
ctx.stat |= STS_TXE;
|
||||
self.istat |= ISTS_TAI;
|
||||
self.ivec |= TX_INT;
|
||||
self.istat |= tx_istat;
|
||||
// Only RS232 transmit generates an interrupt.
|
||||
if port == 0 {
|
||||
self.ivec |= TX_INT;
|
||||
}
|
||||
if (ctx.mode[1] >> 6) & 3 == 0x2 {
|
||||
// Loopback Mode.
|
||||
ctx.rx_data = c;
|
||||
ctx.stat |= STS_RXR;
|
||||
self.istat |= ISTS_RAI;
|
||||
self.istat |= rx_istat;
|
||||
self.ivec |= RX_INT;
|
||||
} else {
|
||||
ctx.tx_queue.push_front(c);
|
||||
}
|
||||
|
||||
// ctx.next_tx = Instant::now() + ctx.char_delay;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn service(&mut self) {
|
||||
// Deal with RS-232 Transmit
|
||||
self.handle_tx(PORT_0);
|
||||
|
||||
// Deal with RS-232 Receive
|
||||
self.handle_rx(PORT_0);
|
||||
|
||||
// Deal with Keyboard Transmit
|
||||
// (note: This is used only for keyboard beeps!)
|
||||
self.handle_tx(PORT_1);
|
||||
|
||||
// Deal with Keyboard Receive
|
||||
self.handle_rx(PORT_1);
|
||||
}
|
||||
|
@ -259,10 +275,14 @@ impl Duart {
|
|||
!self.outprt
|
||||
}
|
||||
|
||||
pub fn tx_poll(&mut self) -> Option<u8> {
|
||||
pub fn rs232_tx_poll(&mut self) -> Option<u8> {
|
||||
self.ports[PORT_0].tx_queue.pop_back()
|
||||
}
|
||||
|
||||
pub fn kb_tx_poll(&mut self) -> Option<u8> {
|
||||
self.ports[PORT_1].tx_queue.pop_back()
|
||||
}
|
||||
|
||||
pub fn mouse_down(&mut self, button: u8) {
|
||||
self.ipcr = 0;
|
||||
self.inprt |= 0xb;
|
||||
|
@ -491,8 +511,8 @@ impl Device for Duart {
|
|||
// transmit will happen in the 'service' function.
|
||||
ctx.next_tx = Instant::now() + ctx.char_delay;
|
||||
ctx.stat &= !(STS_TXE | STS_TXR);
|
||||
self.ivec &= !TX_INT;
|
||||
self.istat &= !ISTS_TAI;
|
||||
self.ivec &= !TX_INT;
|
||||
}
|
||||
IPCR_ACR => {
|
||||
self.acr = val;
|
||||
|
@ -509,11 +529,21 @@ impl Device for Duart {
|
|||
self.handle_command(val, PORT_1);
|
||||
}
|
||||
THRB => {
|
||||
// TODO: When OP3 is low, do not send data to
|
||||
// the keyboard! It's meant for the printer.
|
||||
|
||||
// Keyboard transmit requires special handling,
|
||||
// because the only things the terminal transmits to
|
||||
// the keyboard are status requests, or keyboard beep
|
||||
// requests. We ignore status requests, and only
|
||||
// put beep requests into the queue.
|
||||
let mut ctx = &mut self.ports[PORT_1];
|
||||
ctx.tx_data = val;
|
||||
// Special case for status requests from the keyboard
|
||||
if val == 0x02 {
|
||||
ctx.stat = STS_RXR | STS_PER;
|
||||
|
||||
if (val & 0x08) != 0 {
|
||||
ctx.tx_data = val;
|
||||
ctx.next_tx = Instant::now() + ctx.char_delay;
|
||||
ctx.stat &= !(STS_TXE | STS_TXR);
|
||||
self.istat &= !ISTS_TBI;
|
||||
}
|
||||
}
|
||||
IP_OPCR => {
|
||||
|
|
Loading…
Reference in New Issue