Cleaned up the SerialPort (formerly tty) logic a bit

This commit is contained in:
Jeff 2016-10-05 12:41:14 -07:00 committed by Jeff Parsons
commit 086ef51588
6 changed files with 482 additions and 449 deletions

View file

@ -644,7 +644,6 @@ CPUStatePDP11.prototype.checkInterruptQueue = function()
this.opFlags |= PDP11.OPFLAG.INTQ;
break; // Decrement only one delay 'difference' per cycle
}
//if (typeof this.interruptQueue[i].callback !== "undefined") {
if (this.interruptQueue[i].callback) {
if (!this.interruptQueue[i].callback()) {
this.interruptQueue.splice(i, 1);

View file

@ -449,28 +449,56 @@ var PDP11 = {
SL: 0o177774, // Stack Limit Register
PSW: 0o177776 // 777776 17777776 0x3FFFFE Processor Status Word
},
DL11: { // SERIAL LINE INTERFACE
DELAY: 8,
DL11: { // Serial Line Interface (program compatible with the KL11 for control of console teleprinters)
PRI: 4,
VEC: 0o64,
XCSR: {
READY: 0x80, // Transmitter Ready (read-only)
INT_ENABLE: 0x40, // Transmitter Interrupt Enable (read-write)
MAINT: 0x04, // Maintenance (read-write)
BREAK: 0x01, // BREAK (read-write)
DELAY: 8
RVEC: 0o60,
XVEC: 0o64,
DELAY: 40,
RCSR: { // 177560
RE: 0x0001, // Reader Enable (W/O) TODO: Determine if we really need to exclude this write-only bit from RMASK
DTR: 0x0002, // Data Terminal Ready (R/W)
RTS: 0x0004, // Request To Send (R/W)
STD: 0x0008, // Secondary Transmitted Data (R/W)
DIE: 0x0020, // Dataset Interrupt Enable (R/W)
RIE: 0x0040, // Receiver Interrupt Enable (R/W)
RD: 0x0080, // Receiver Done (R/O)
SRD: 0x0400, // Secondary Received Data (R/O)
RA: 0x0800, // Receiver Active (R/O)
CD: 0x1000, // Carrier Detect (R/O)
CTS: 0x2000, // Clear To Send (R/O)
RI: 0x4000, // Ring Indicator (R/O)
DSC: 0x8000, // Dataset Status Change (R/O)
RMASK: 0xFFFF, // read mask
WMASK: 0x006F // write mask
},
XBUF: {
DELAY: 100
RBUF: { // 177562
DATA: 0x00ff, // Received Data (R/O)
PARITY: 0x1000, // Received Data Parity (R/O)
FE: 0x2000, // Framing Error (R/O)
OE: 0x4000, // Overrun Error (R/O)
ERROR: 0x8000 // Error (R/O)
},
XCSR: { // 177564
BREAK: 0x0001, // BREAK (R/W)
MAINT: 0x0004, // Maintenance (R/W)
TIE: 0x0040, // Transmitter Interrupt Enable (R/W)
READY: 0x0080, // Transmitter Ready (R/O)
RMASK: 0x00C5,
WMASK: 0x0045,
DELAY: 8
},
XBUF: { // 177566
DATA: 0x00FF, // Transmitted Data (W/O) TODO: Determine why pdp11.js effectively defined this as 0x7F
DELAY: 100
}
},
KW11: { // KW11-L LINE TIME CLOCK
DELAY: 0,
KW11: { // KW11-L Line Time Clock
PRI: 6,
VEC: 0o100,
DELAY: 0,
LKS: {
INT_ENABLE: 0x40,
MONITOR: 0x80
IE: 0x0040, // Interrupt Enable
MON: 0x0080 // Monitor
}
}
};

View file

@ -208,7 +208,7 @@ DevicePDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
DevicePDP11.prototype.readLKS = function(addr)
{
var result = this.kw11.lks;
this.kw11.lks &= ~PDP11.KW11.LKS.MONITOR;
this.kw11.lks &= ~PDP11.KW11.LKS.MON;
return result;
};
@ -222,10 +222,10 @@ DevicePDP11.prototype.readLKS = function(addr)
DevicePDP11.prototype.writeLKS = function(data, addr)
{
this.kw11.lks = data;
if (data & PDP11.KW11.LKS.INT_ENABLE) {
if (data & PDP11.KW11.LKS.IE) {
this.cpu.setTimer(this.kw11.timer, 1000/60);
}
this.kw11.lks = data & ~PDP11.KW11.LKS.MONITOR;
this.kw11.lks = data & ~PDP11.KW11.LKS.MON;
};
/**
@ -668,8 +668,8 @@ DevicePDP11.prototype.rp11_end = function(err, meta, block, address, count)
*/
DevicePDP11.prototype.kw11_interrupt = function()
{
this.kw11.lks |= PDP11.KW11.LKS.MONITOR;
if (this.kw11.lks & PDP11.KW11.LKS.INT_ENABLE) {
this.kw11.lks |= PDP11.KW11.LKS.MON;
if (this.kw11.lks & PDP11.KW11.LKS.IE) {
this.cpu.interrupt(PDP11.KW11.DELAY, PDP11.KW11.PRI, PDP11.KW11.VEC);
this.cpu.setTimer(this.kw11.timer, 1000/60);
}

View file

@ -69,14 +69,6 @@ function SerialPortPDP11(parmsSerial) {
this.iAdapter = parmsSerial['adapter'];
this.tty = {
rbuf: [],
rcsr: 0,
xcsr: PDP11.DL11.XCSR.READY,
delCode: 127,
del: 0
};
/**
* consoleOutput becomes a string that records serial port output if the 'binding' property is set to the
* reserved name "console". Nothing is written to the console, however, until a linefeed (0x0A) is output
@ -267,127 +259,24 @@ SerialPortPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
this.cpu = cpu;
this.dbg = dbg;
var serial = this;
this.timerReceiveData = this.cpu.addTimer(function() {
serial.rcsr |= PDP11.DL11.RCSR.RD;
if (serial.rcsr & PDP11.DL11.RCSR.RIE) {
serial.cpu.interrupt(PDP11.DL11.DELAY, PDP11.DL11.PRI, PDP11.DL11.RVEC);
}
});
this.doneTransmitInterrupt = function() {
serial.xcsr |= PDP11.DL11.XCSR.READY;
return !!(serial.xcsr & PDP11.DL11.XCSR.TIE);
};
bus.addIOTable(this, SerialPortPDP11.UNIBUS_IOTABLE);
this.setReady();
};
/**
* readRCSR(addr)
*
* @this {SerialPortPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.RCSR or 177560)
* @return {number}
*/
SerialPortPDP11.prototype.readRCSR = function(addr)
{
return this.tty.rcsr;
};
/**
* writeRCSR(data, addr)
*
* @this {SerialPortPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.RCSR or 177560)
*/
SerialPortPDP11.prototype.writeRCSR = function(data, addr)
{
this.tty.rcsr = (this.tty.rcsr & 0x80) | (data & ~0x80);
};
/**
* readRBUF(addr)
*
* @this {SerialPortPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.RBUF or 177562)
* @return {number}
*/
SerialPortPDP11.prototype.readRBUF = function(addr)
{
return 0;
};
/**
* writeRBUF(data, addr)
*
* @this {SerialPortPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.RBUF or 177562)
*/
SerialPortPDP11.prototype.writeRBUF = function(data, addr)
{
};
/**
* readXCSR(addr)
*
* @this {SerialPortPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.XCSR or 177564)
* @return {number}
*/
SerialPortPDP11.prototype.readXCSR = function(addr)
{
return this.tty.xcsr;
};
/**
* writeXCSR(data, addr)
*
* @this {SerialPortPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.XCSR or 177564)
*/
SerialPortPDP11.prototype.writeXCSR = function(data, addr)
{
/*
* If the device is READY, and INT_ENABLE is transitioning to *set*, then generate an interrupt.
*/
if ((this.tty.xcsr & (PDP11.DL11.XCSR.READY | PDP11.DL11.XCSR.INT_ENABLE)) == PDP11.DL11.XCSR.READY && (data & PDP11.DL11.XCSR.INT_ENABLE)) {
var device = this;
this.cpu.interrupt(PDP11.DL11.XCSR.DELAY, PDP11.DL11.PRI, PDP11.DL11.VEC, function() {
device.tty.xcsr |= PDP11.DL11.XCSR.READY;
return !!(device.tty.xcsr & PDP11.DL11.XCSR.INT_ENABLE);
});
}
/*
* In any event, propagate all bits from data *except* for READY.
*/
this.tty.xcsr = (this.tty.xcsr & PDP11.DL11.XCSR.READY) | (data & ~PDP11.DL11.XCSR.READY);
};
/**
* readXBUF(addr)
*
* @this {SerialPortPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.XBUF or 177566)
* @return {number}
*/
SerialPortPDP11.prototype.readXBUF = function(addr)
{
return 0;
};
/**
* writeXBUF(data, addr)
*
* @this {SerialPortPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.XBUF or 177566)
*/
SerialPortPDP11.prototype.writeXBUF = function(data, addr)
{
data &= 0x7f;
if (data) {
var serial = this;
this.transmitByte(data);
this.tty.xcsr &= ~PDP11.DL11.XCSR.READY;
this.cpu.interrupt(PDP11.DL11.XBUF.DELAY, PDP11.DL11.PRI, PDP11.DL11.VEC, function() {
serial.tty.xcsr |= PDP11.DL11.XCSR.READY;
return !!(serial.tty.xcsr & PDP11.DL11.XCSR.INT_ENABLE);
});
}
};
/**
* initConnection()
*
@ -489,8 +378,6 @@ SerialPortPDP11.prototype.powerDown = function(fSave, fShutdown)
*/
SerialPortPDP11.prototype.reset = function()
{
this.tty.rcsr = 0;
this.tty.xcsr = 0x80;
this.initState();
};
@ -532,6 +419,9 @@ SerialPortPDP11.prototype.restore = function(data)
*/
SerialPortPDP11.prototype.initState = function(data)
{
this.rbuf = [];
this.rcsr = 0;
this.xcsr = PDP11.DL11.XCSR.READY;
return true;
};
@ -634,6 +524,120 @@ SerialPortPDP11.prototype.transmitByte = function(b)
return fTransmitted;
};
/**
* readRCSR(addr)
*
* @this {SerialPortPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.RCSR or 177560)
* @return {number}
*/
SerialPortPDP11.prototype.readRCSR = function(addr)
{
return this.rcsr & PDP11.DL11.RCSR.RMASK;
};
/**
* writeRCSR(data, addr)
*
* @this {SerialPortPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.RCSR or 177560)
*/
SerialPortPDP11.prototype.writeRCSR = function(data, addr)
{
this.rcsr = (this.rcsr & ~PDP11.DL11.RCSR.WMASK) | (data & PDP11.DL11.RCSR.WMASK);
};
/**
* readRBUF(addr)
*
* @this {SerialPortPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.RBUF or 177562)
* @return {number}
*/
SerialPortPDP11.prototype.readRBUF = function(addr)
{
var result = 0;
this.rcsr &= ~PDP11.DL11.RCSR.RD;
if (this.rbuf.length > 0) {
result = this.rbuf.shift();
if (this.rbuf.length > 0) {
this.cpu.setTimer(this.timerReceiveData, 50);
}
}
return result;
};
/**
* writeRBUF(data, addr)
*
* @this {SerialPortPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.RBUF or 177562)
*/
SerialPortPDP11.prototype.writeRBUF = function(data, addr)
{
};
/**
* readXCSR(addr)
*
* @this {SerialPortPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.XCSR or 177564)
* @return {number}
*/
SerialPortPDP11.prototype.readXCSR = function(addr)
{
return this.xcsr;
};
/**
* writeXCSR(data, addr)
*
* @this {SerialPortPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.XCSR or 177564)
*/
SerialPortPDP11.prototype.writeXCSR = function(data, addr)
{
/*
* If the device is READY, and IE is transitioning on, then request an interrupt.
*/
if ((this.xcsr & (PDP11.DL11.XCSR.READY | PDP11.DL11.XCSR.TIE)) == PDP11.DL11.XCSR.READY && (data & PDP11.DL11.XCSR.TIE)) {
this.cpu.interrupt(PDP11.DL11.XCSR.DELAY, PDP11.DL11.PRI, PDP11.DL11.XVEC, this.doneTransmitInterrupt);
}
this.xcsr = (this.xcsr & ~PDP11.DL11.XCSR.WMASK) | (data & PDP11.DL11.XCSR.WMASK);
};
/**
* readXBUF(addr)
*
* @this {SerialPortPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.XBUF or 177566)
* @return {number}
*/
SerialPortPDP11.prototype.readXBUF = function(addr)
{
return 0;
};
/**
* writeXBUF(data, addr)
*
* @this {SerialPortPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.XBUF or 177566)
*/
SerialPortPDP11.prototype.writeXBUF = function(data, addr)
{
data &= PDP11.DL11.XBUF.DATA;
if (data) {
this.transmitByte(data);
this.xcsr &= ~PDP11.DL11.XCSR.READY;
this.cpu.interrupt(PDP11.DL11.XBUF.DELAY, PDP11.DL11.PRI, PDP11.DL11.XVEC, this.doneTransmitInterrupt);
}
};
/*
* ES6 ALERT: As you can see below, I've finally started using computed property names.
*/