Cleaned up the SerialPort (formerly tty) logic a bit
This commit is contained in:
parent
795d57839b
commit
086ef51588
6 changed files with 482 additions and 449 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue