More PDP-11 front panel functionality

This commit is contained in:
Jeff 2016-11-01 19:02:06 -07:00 committed by Jeff Parsons
commit caf0a728f8
20 changed files with 1379 additions and 615 deletions

View file

@ -186,6 +186,7 @@ CPUPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
this.cmp = cmp;
this.bus = bus;
this.dbg = dbg;
this.panel = cmp.panel;
for (var i = 0; i < CPUPDP11.BUTTONS.length; i++) {
var control = this.bindings[CPUPDP11.BUTTONS[i]];

View file

@ -1411,8 +1411,8 @@ PDP11.opNOP = function(opCode)
PDP11.opRESET = function(opCode)
{
if (!(this.regPSW & PDP11.PSW.CMODE)) {
this.resetRegs();
this.bus.reset();
this.resetRegs();
// display.data = this.regsGen[0]; // TODO: Review
}
this.nStepCycles -= 667; // TODO: Review (but it's definitely a big number)

View file

@ -310,6 +310,7 @@ CPUStatePDP11.prototype.setMMR0 = function(newMMR0)
this.mmuEnable = mmuEnable;
this.setMemoryAccess();
}
if (this.panel) this.panel.updateStatus();
}
};
@ -357,6 +358,7 @@ CPUStatePDP11.prototype.setMMR3 = function(newMMR3)
this.regMMR3 = newMMR3;
this.mmuMask = (newMMR3 & PDP11.MMR3.MMU_22BIT)? 0x3fffff : 0x3ffff;
this.setMemoryAccess();
if (this.panel) this.panel.updateStatus();
}
};

View file

@ -450,7 +450,7 @@ var PDP11 = {
XCSR: 0o177564, // Display Terminal: Transmitter Status Register
XBUF: 0o177566, // Display Terminal: Transmitter Data Buffer Register
CNSL: 0o177570, // Console Switch and Front Panel Display
CNSW: 0o177570, // Console (Front Panel) Switch Register
MMR0: 0o177572, // 777572 17777572
MMR1: 0o177574, // 777574 17777574

View file

@ -49,7 +49,6 @@ if (NODE) {
* The Device component implements the following "default" devices:
*
* KW11 (KW11-L Line Time Clock)
* CNSL (Console Switch and Front Panel Display)
*
* as well providing access to all the MMU and CPU registers, PSW, etc.
*
@ -61,13 +60,6 @@ function DevicePDP11(parmsDevice)
{
Component.call(this, "Device", parmsDevice, DevicePDP11, MessagesPDP11.DEVICE);
this.console = { // CNSL registers
data: 0,
address: 0,
misc: 0x14,
switches: 0
};
this.kw11 = { // LW11 registers
csr: 0,
timer: -1 // initBus() will initialize this timer ID
@ -146,7 +138,6 @@ DevicePDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
*/
DevicePDP11.prototype.reset = function()
{
this.console.misc = (this.console.misc & ~0x77) | 0x14; // kernel 16 bit
this.kw11.lks = 0;
};
@ -194,33 +185,6 @@ DevicePDP11.prototype.writeLKS = function(data, addr)
this.kw11.lks = data & ~PDP11.KW11.LKS.MON;
};
/**
* readCNSL(addr)
*
* If addr is set, then this a normal read, so we should return normal results (ie, switches);
* if addr is NOT set, then this is a read-before-write, so we must return the value being updated (ie, data).
*
* @this {DevicePDP11}
* @param {number} addr (eg, PDP11.UNIBUS.CNSL or 177570)
* @return {number}
*/
DevicePDP11.prototype.readCNSL = function(addr)
{
return (addr? this.console.switches : this.console.data) & 0xffff;
};
/**
* writeCNSL(data, addr)
*
* @this {DevicePDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.CNSL or 177570)
*/
DevicePDP11.prototype.writeCNSL = function(data, addr)
{
this.console.data = data;
};
/**
* readMMR0(addr)
*
@ -243,7 +207,6 @@ DevicePDP11.prototype.readMMR0 = function(addr)
DevicePDP11.prototype.writeMMR0 = function(data, addr)
{
this.cpu.setMMR0(data);
this.updateConsoleMode();
};
/**
@ -304,21 +267,6 @@ DevicePDP11.prototype.readMMR3 = function(addr)
DevicePDP11.prototype.writeMMR3 = function(data, addr)
{
this.cpu.setMMR3(data);
this.updateConsoleMode();
};
/**
* updateConsoleMode()
*
* @this {DevicePDP11}
*/
DevicePDP11.prototype.updateConsoleMode = function()
{
/*
* Set bit to 1 (22-bit), 2 (18-bit), or 4 (16-bit)
*/
var bit = this.cpu.mmuEnable? ((this.cpu.regMMR3 & PDP11.MMR3.MMU_22BIT)? 1 : 2) : 4;
this.console.misc = (this.console.misc & ~7) | bit;
};
/**
@ -1105,7 +1053,6 @@ DevicePDP11.UNIBUS_IOTABLE = {
[PDP11.UNIBUS.KDSAR0]: /* 172360 */ [null, null, DevicePDP11.prototype.readKDSAR, DevicePDP11.prototype.writeKDSAR, "KDSAR", 8, PDP11.MODEL_1145],
[PDP11.UNIBUS.MMR3]: /* 172516 */ [null, null, DevicePDP11.prototype.readMMR3, DevicePDP11.prototype.writeMMR3, "MMR3", 1, PDP11.MODEL_1145],
[PDP11.UNIBUS.LKS]: /* 177546 */ [null, null, DevicePDP11.prototype.readLKS, DevicePDP11.prototype.writeLKS, "LKS"],
[PDP11.UNIBUS.CNSL]: /* 177570 */ [null, null, DevicePDP11.prototype.readCNSL, DevicePDP11.prototype.writeCNSL, "CNSL"],
[PDP11.UNIBUS.MMR0]: /* 177572 */ [null, null, DevicePDP11.prototype.readMMR0, DevicePDP11.prototype.writeMMR0, "MMR0", 1, PDP11.MODEL_1145],
[PDP11.UNIBUS.MMR1]: /* 177574 */ [null, null, DevicePDP11.prototype.readMMR1, DevicePDP11.prototype.writeIgnored, "MMR1", 1, PDP11.MODEL_1145],
[PDP11.UNIBUS.MMR2]: /* 177576 */ [null, null, DevicePDP11.prototype.readMMR2, DevicePDP11.prototype.writeIgnored, "MMR2", 1, PDP11.MODEL_1145],

View file

@ -54,19 +54,112 @@ if (NODE) {
function PanelPDP11(parmsPanel)
{
Component.call(this, "Panel", parmsPanel, PanelPDP11);
/*
* If there are any live registers, LEDs, etc, to display, this will provide a count.
*
* TODO: Add some UI for fDisplayLiveRegs (either an XML property, or a UI checkbox, or both).
*/
this.cLiveRegs = 0;
/*
* TODO: Add some UI for displayLiveRegs (either an XML property, or a UI checkbox, or both)
*/
this.flags.displayLiveRegs = true;
this.fDisplayLiveRegs = true;
this.fLampTest = false;
this.fExamine = this.fDeposit = false;
/*
* regCNSW contains the Console (Front Panel) Switch Register, which is also available as a
* read-only register at 177570 (but only the low 16 bits).
*
* regAddr is an internal register containing the contents of the Front Panel's ADDRESS display,
* and regData corresponds to the DATA display. They are updated by setAddr() and setData(),
* which in turn take care of calling updateLEDArray().
*/
this.regCNSW = 0;
this.regAddr = this.regData = 0;
this.regMisc = 0x14;
/*
* Every LED has a simple numeric value, assigned when setBinding() is called:
*
* 0 if off, 1 if on
*
* initBus() will call updateLEDs() to ensure that every LED is set to its initial value.
*/
this.leds = {};
/*
* Every switch has an array associated with it:
*
* [0]: initial/current value of switch (0 if down, 1 if up)
* [1]: true if the switch is momentary, false if not
* [2]: true if the switch is currently being pressed, false if not
* [3]: optional handler to call whenever the switch is pressed or released
* [4]: optional switch index (used with CNSW switches 'S0' through 'S21')
*
* initBus() will call updateSwitches() to ensure that every switch is the position represented below.
*
* NOTE: Not all switches have the same "process" criteria. For example, 'TEST' will perform a lamp test
* when it is momentarily pressed "up", whereas 'LOAD [ADRS]' will load the address register from the switch
* register when it is momentarily pressed "down".
*
* This means that processLampTest(value) must act when value == 1, whereas processLoadAddr(value) must
* act when value == 0. You can infer all this from the table below, because the initial value of any
* momentary switch is its "passive" value, so the opposite is its "active" value.
*/
this.switches = {
'START': [1, true, false, this.processStart],
'STEP': [1, false, false, this.processStep],
'ENABLE': [1, false, false, this.processEnable],
'CONT': [1, true, false, this.processContinue],
'DEP': [0, true, false, this.processDeposit],
'EXAM': [1, true, false, this.processExamine],
'LOAD': [1, true, false, this.processLoadAddr],
'TEST': [0, true, false, this.processLampTest]
};
for (var i = 0; i < 22; i++) {
this.switches['S'+i] = [0, false, false, this.processSwitchReg, i];
}
}
Component.subclass(PanelPDP11);
/*
* To get the current state of a switch; eg::
*
* this.getSwitch(PanelPDP11.SWITCH.ENABLE)
*
* However, I haven't filled out this table, primarily because the only switches we need to query
* are the non-momentary ones (eg, ENABLE and STEP), and EXAM and DEP (because they have special
* "step" behavior when pressed more than once in a row).
*/
PanelPDP11.SWITCH = {
DEP: 'DEP',
ENABLE: 'ENABLE',
EXAM: 'EXAM',
STEP: 'STEP'
};
/**
* getSwitch(name)
*
* @this {PanelPDP11}
* @param {string} name
* @return {number|undefined} 0 if switch is off ("down"), 1 if on ("up"), or undefined if unrecognized
*/
PanelPDP11.prototype.getSwitch = function(name)
{
return this.switches[name] && this.switches[name][0];
};
/**
* reset()
*
* @this {PanelPDP11}
*/
PanelPDP11.prototype.reset = function()
{
this.regMisc = (this.regMisc & ~0x77) | 0x14; // kernel 16 bit
};
/**
* setBinding(sType, sBinding, control, sValue)
*
@ -93,29 +186,72 @@ PanelPDP11.prototype.setBinding = function(sType, sBinding, control, sValue)
if (DEBUGGER && this.dbg && this.dbg.setBinding(sType, sBinding, control, sValue)) {
return true;
}
switch (sBinding) {
case "R0":
case "R1":
case "R2":
case "R3":
case "R4":
case "R5":
case "R6":
case "R7":
case "NF":
case "ZF":
case "VF":
case "CF":
case "PS":
case 'R0':
case 'R1':
case 'R2':
case 'R3':
case 'R4':
case 'R5':
case 'R6':
case 'R7':
case 'NF':
case 'ZF':
case 'VF':
case 'CF':
case 'PS':
this.bindings[sBinding] = control;
this.cLiveRegs++;
return true;
default:
if (sType == "rled") {
/*
* Square (default) or round LEDs are defined in machine XML files like so:
*
* <control type="rled" binding="A3" value="1" width="100%" container="center"/>
*
* Only *type* and *binding* attributes are required; if *value* is omitted, the default value is 0 (off).
*/
if (sType == "led" || sType == "rled") {
this.bindings[sBinding] = control;
this.leds[sBinding] = sValue? 1 : 0;
this.cLiveRegs++;
return true;
}
/*
* Switches are defined in machine XML files like so:
*
* <control type="switch" binding="S3" value="1" width="100%" container="center"/>
*
* Only *type* and *binding* attributes are required; if *value* is omitted, the default value is 0 ("down").
*
* Currently, there is no XML attribute to indicate whether a switch is "momentary"; only recognized switches
* in our internal table can have that attribute.
*/
if (sType == "switch") {
/*
* Like LEDs, we allow unrecognized switches to be defined as well, but they won't do anything useful,
* since only recognized switches will have handlers that perform the appropriate operations.
*/
if (this.switches[sBinding] === undefined) {
this.switches[sBinding] = [sValue? 1 : 0];
}
this.bindings[sBinding] = control;
var parent = control.parentElement || control;
parent = parent.parentElement || parent;
parent.onmousedown = function(panel, sBinding) {
return function onPressSwitch() {
panel.pressSwitch(sBinding);
};
}(this, sBinding);
parent.onmouseup = parent.onmouseout = function(panel, sBinding) {
return function onReleaseSwitch() {
panel.releaseSwitch(sBinding);
};
}(this, sBinding);
return true;
}
return this.parent.setBinding.call(this, sType, sBinding, control, sValue);
}
};
@ -135,6 +271,12 @@ PanelPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
this.bus = bus;
this.cpu = cpu;
this.dbg = dbg;
bus.addIOTable(this, PanelPDP11.UNIBUS_IOTABLE);
bus.addResetHandler(this.reset.bind(this));
this.updateLEDs();
this.updateSwitches();
};
/**
@ -147,7 +289,20 @@ PanelPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
*/
PanelPDP11.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) PanelPDP11.init();
if (!fRepower) {
/*
* As noted in init(), our powerUp() method gives us a second opportunity to notify any
* components that that might care (eg, CPU, Keyboard, and Debugger) that we have some controls
* they might want to use.
*/
PanelPDP11.init();
/*
* TODO: Until we implement a restore() function, all we can do is reset(); however, that's
* currently unnecessary, since we've added reset() to the addResetHandler() list.
*
* this.reset();
*/
}
return true;
};
@ -184,7 +339,7 @@ PanelPDP11.prototype.updateValue = function(sLabel, nValue, cch)
}
var sVal;
var nBase = this.dbg && this.dbg.nBase || 8;
if (!this.cpu.isRunning() || this.flags.displayLiveRegs) {
if (!this.cpu.isRunning() || this.fDisplayLiveRegs) {
sVal = nBase == 8? str.toOct(nValue, cch) : str.toHex(nValue, cch);
} else {
sVal = "--------".substr(0, cch || 4);
@ -200,39 +355,308 @@ PanelPDP11.prototype.updateValue = function(sLabel, nValue, cch)
};
/**
* setLED(control, f)
* setLED(sBinding, value)
*
* @this {PanelPDP11}
* @param {Object} control is an HTML control DOM object
* @param {boolean|number} f is true if the LED represented by control should be "on", false if "off"
* @param {string} sBinding
* @param {boolean|number} value (true if the LED should be on, false if off)
*/
PanelPDP11.prototype.setLED = function(control, f)
PanelPDP11.prototype.setLED = function(sBinding, value)
{
/*
* TODO: Add support for user-definable LED colors
*/
control.style.backgroundColor = (f? "#ff0000" : "#000000");
var control = this.bindings[sBinding];
if (control) {
/*
* TODO: Add support for user-definable LED colors?
*/
control.style.backgroundColor = (value? "#ff0000" : "#000000");
}
};
/**
* updateLEDs(sPrefix, data, nLEDs)
* updateLEDs(override)
*
* @this {PanelPDP11}
* @param {boolean|number|null} [override] (true turn on all LEDs, false to turn off all LEDs, null or undefined for normal LED activity)
*/
PanelPDP11.prototype.updateLEDs = function(override)
{
for (var sBinding in this.leds) {
this.setLED(sBinding, override != null? override : this.leds[sBinding]);
}
};
/**
* updateLEDArray(sPrefix, data, nLEDs)
*
* @this {PanelPDP11}
* @param {string} sPrefix
* @param {number} data
* @param {number} nLEDs
*/
PanelPDP11.prototype.updateLEDs = function(sPrefix, data, nLEDs)
PanelPDP11.prototype.updateLEDArray = function(sPrefix, data, nLEDs)
{
for (var i = 0; i < nLEDs; i++) {
var id = sPrefix + i;
var control = this.bindings[id];
if (control) {
this.setLED(control, data & (1 << i));
var sBinding = sPrefix + i;
this.setLED(sBinding, data & (1 << i));
}
};
/**
* setSwitch(sBinding, value)
*
* @this {PanelPDP11}
* @param {string} sBinding
* @param {boolean|number} value (true if the switch should be "up" (on), false if "down" (off))
*/
PanelPDP11.prototype.setSwitch = function(sBinding, value)
{
var control = this.bindings[sBinding];
if (control) {
control.style.marginTop = (value? "0px" : "20px");
control.style.backgroundColor = (value? "#00ff00" : "#228B22");
}
};
/**
* pressSwitch(sBinding)
*
* @this {PanelPDP11}
* @param {string} sBinding
*/
PanelPDP11.prototype.pressSwitch = function(sBinding)
{
var sw = this.switches[sBinding];
this.setSwitch(sBinding, sw[0] = 1 - sw[0]);
sw[2] = true;
if (sw[3]) sw[3].call(this, sw[0], sw[4]);
this.fDeposit = (sBinding == PanelPDP11.SWITCH.DEP);
this.fExamine = (sBinding == PanelPDP11.SWITCH.EXAM);
};
/**
* releaseSwitch(sBinding)
*
* @this {PanelPDP11}
* @param {string} sBinding
*/
PanelPDP11.prototype.releaseSwitch = function(sBinding)
{
/*
* pressSwitch() is simple: flip the switch's current value in sw[0] and marked it "pressed" in sw[2].
*
* releaseSwitch() is more complicated, because we must handle both mouseUp and mouseOut events. The first time
* we receive EITHER of those events AND the switch is marked momentary (sw[1]) AND the switch is pressed (sw[2]),
* then we must flip the switch back to its original value.
*
* Otherwise, the only thing we have to do is mark the switch as no longer "pressed" (ie, set sw[2] to false).
*/
var sw = this.switches[sBinding];
if (sw[1] && sw[2]) {
this.setSwitch(sBinding, sw[0] = 1 - sw[0]);
if (sw[3]) sw[3].call(this, sw[0], sw[4]);
}
sw[2] = false;
};
/**
* processStart(value, index)
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} [index]
*/
PanelPDP11.prototype.processStart = function(value, index)
{
if (!value && !this.cpu.isRunning()) {
/*
* TODO: Verify what the PDP-11/70 Handbook means when it says that when the 'START' switch
* is depressed, "the computer system will be cleared." I take it to mean that it performs
* the equivalent of a RESET instruction.
*/
this.bus.reset();
this.cpu.resetRegs();
/*
* The PDP-11/70 Handbook goes on to say: "If the system needs to be initialized but execution
* is not wanted, the START switch should be depressed while the HALT/ENABLE switch is in the HALT
* position."
*/
if (this.getSwitch(PanelPDP11.SWITCH.ENABLE)) {
this.cpu.startCPU();
}
}
};
/**
* processStep(value, index)
*
* If value == 1 (our initial value), then the 'STEP' switch is set to "S INST" (step one instruction);
* otherwise, it's set to "S BUS CYCLE" (step one bus cycle). Note that we don't actually support the
* latter.
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} [index]
*/
PanelPDP11.prototype.processStep = function(value, index)
{
};
/**
* processEnable(value, index)
*
* If value == 1 (our initial value), then the 'ENABLE'/'HALT' switch is set to 'ENABLE', otherwise 'HALT'.
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} [index]
*/
PanelPDP11.prototype.processEnable = function(value, index)
{
/*
* The "down" (0) position is 'HALT', which stops the CPU; however, the "up" (1) position ('ENABLE')
* does NOT start the CPU. You must press 'CONT' to continue execution, which will either continue for
* one instruction if this switch to set to 'HALT' or indefinitely if it is set to 'ENABLE'.
*/
if (!value) {
this.cpu.stopCPU();
}
};
/**
* processContinue(value, index)
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} [index]
*/
PanelPDP11.prototype.processContinue = function(value, index)
{
if (!value && !this.cpu.isRunning()) {
if (!this.getSwitch(PanelPDP11.SWITCH.ENABLE)) {
/*
* TODO: Technically, we're also supposed to check the 'STEP' switch to determine if we should
* step one instruction or just one cycle, but we don't currently have the ability to do the latter.
*/
var dbg = this.dbg;
if (dbg && !dbg.isBusy(true)) {
dbg.setBusy(true);
dbg.stepCPU(0);
dbg.setBusy(false);
} else {
this.cpu.stepCPU(1);
this.updateStatus();
}
}
else {
this.cpu.startCPU();
}
}
};
/**
* processDeposit(value, index)
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} [index]
*/
PanelPDP11.prototype.processDeposit = function(value, index)
{
if (value && !this.cpu.isRunning()) {
if (this.fDeposit) {
this.setAddr(this.regAddr + 2);
}
this.bus.setWordDirect(this.regAddr, this.setData(this.regCNSW));
}
};
/**
* processExamine(value, index)
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} [index]
*/
PanelPDP11.prototype.processExamine = function(value, index)
{
if (!value && !this.cpu.isRunning()) {
if (this.fExamine) {
this.setAddr(this.regAddr + 2);
}
this.setData(this.bus.getWordDirect(this.regAddr));
}
};
/**
* processLoadAddr(value, index)
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} [index]
*/
PanelPDP11.prototype.processLoadAddr = function(value, index)
{
if (!value && !this.cpu.isRunning()) {
this.setAddr(this.regCNSW);
}
};
/**
* processLampTest(value, index)
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} [index]
*/
PanelPDP11.prototype.processLampTest = function(value, index)
{
this.updateLEDs(value || null);
};
/**
* processSwitchReg(value, index)
*
* @this {PanelPDP11}
* @param {number} value (normally 0 or 1, but we only depend on it being zero or non-zero)
* @param {number} index
*/
PanelPDP11.prototype.processSwitchReg = function(value, index)
{
if (value) {
this.regCNSW |= 1 << index;
} else {
this.regCNSW &= ~(1 << index);
}
};
/**
* setAddr(value)
*
* @this {PanelPDP11}
* @param {number} value
* @return {number}
*/
PanelPDP11.prototype.setAddr = function(value)
{
this.regAddr = value & this.bus.nBusMask;
this.updateLEDArray("A", this.regAddr, 22);
return this.regAddr;
};
/**
* setData(value)
*
* @this {PanelPDP11}
* @param {number} value
* @return {number}
*/
PanelPDP11.prototype.setData = function(value)
{
this.regData = value & 0xffff;
this.updateLEDArray("D", this.regData, 16);
return this.regData;
};
/**
* updateStatus(fForce)
*
@ -242,7 +666,7 @@ PanelPDP11.prototype.updateLEDs = function(sPrefix, data, nLEDs)
PanelPDP11.prototype.updateStatus = function(fForce)
{
if (this.cLiveRegs) {
if (fForce || !this.cpu.isRunning() || this.flags.displayLiveRegs) {
if (fForce || !this.cpu.isRunning() || this.fDisplayLiveRegs) {
for (var i = 0; i < this.cpu.regsGen.length; i++) {
this.updateValue('R'+i, this.cpu.regsGen[i]);
}
@ -252,12 +676,62 @@ PanelPDP11.prototype.updateStatus = function(fForce)
this.updateValue("ZF", (regPSW & PDP11.PSW.ZF)? 1 : 0, 1);
this.updateValue("VF", (regPSW & PDP11.PSW.VF)? 1 : 0, 1);
this.updateValue("CF", (regPSW & PDP11.PSW.CF)? 1 : 0, 1);
this.updateLEDs("D", this.cpu.regsGen[0], 16);
this.updateLEDs("A", this.cpu.regsGen[7], 22);
if (!this.fLampTest) {
this.setData(this.cpu.regsGen[0]);
this.setAddr(this.cpu.regsGen[7]);
/*
* Set bit to 1 (22-bit), 2 (18-bit), or 4 (16-bit)
*/
var bit = this.cpu.mmuEnable? ((this.cpu.regMMR3 & PDP11.MMR3.MMU_22BIT)? 1 : 2) : 4;
// this.misc = (this.misc & ~7) | bit;
}
}
}
};
/**
* updateSwitches()
*
* @this {PanelPDP11}
*/
PanelPDP11.prototype.updateSwitches = function()
{
for (var sBinding in this.switches) {
this.setSwitch(sBinding, this.switches[sBinding][0]);
}
};
/**
* readCNSW(addr)
*
* If addr is set, then this a normal read, so we should return normal results (ie, switches);
* if addr is NOT set, then this is a read-before-write, so we must return the value being updated (ie, data).
*
* @this {PanelPDP11}
* @param {number} addr (eg, PDP11.UNIBUS.CNSW or 177570)
* @return {number}
*/
PanelPDP11.prototype.readCNSW = function(addr)
{
return (addr? this.regCNSW : this.regData) & 0xffff;
};
/**
* writeCNSW(data, addr)
*
* @this {PanelPDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.CNSW or 177570)
*/
PanelPDP11.prototype.writeCNSW = function(data, addr)
{
this.regData = data;
};
PanelPDP11.UNIBUS_IOTABLE = {
[PDP11.UNIBUS.CNSW]: /* 177570 */ [null, null, PanelPDP11.prototype.readCNSW, PanelPDP11.prototype.writeCNSW, "CNSW"]
};
/**
* PanelPDP11.init()
*

View file

@ -132,11 +132,19 @@
.pcjs-tripled {
padding: 1px;
}
.pcjs-tripled-label {
.pcjs-ledlbl0 {
text-align: right;
padding: 8px;
font-size: 50%;
background-color: #8d4076;
}
.pcjs-ledlbl1 {
text-align: right;
font-size: 50%;
background-color: #d83662;
}
.pcjs-ledpad {
text-align: center;
font-size: x-small;
line-height: 32px;
background-color: #000000;
}
@ -159,6 +167,25 @@
text-align: center;
vertical-align: middle;
background-color: #ff0000;
max-width: 50%;
max-height: 50%;
}
.pcjs-swlbl {
text-align: center;
font-size: 40%;
line-height: 32px;
background-color: #000000;
}
.pcjs-swpad {
height: 32px;
background-color: #000000;
}
.pcjs-switch {
height: 10px;
width: 28px;
margin-top: 0%;
max-width: 90%;
background-color: #00ff00;
}
.pcjs-screen {
clear: both;

View file

@ -422,7 +422,10 @@
</form>
</xsl:when>
<xsl:when test="@type = 'led' or @type = 'rled'">
<div class="{$APPCLASS}-binding {$CSSCLASS}-{@type}" data-value="{{{$type},{$binding}}}" style="display:inline-block;"><xsl:value-of select="."/></div>
<div class="{$APPCLASS}-binding {$CSSCLASS}-{@type}" data-value="{{{$type},{$binding},{$value}}}" style="display:inline-block;"><xsl:value-of select="."/></div>
</xsl:when>
<xsl:when test="@type = 'switch'">
<div class="{$APPCLASS}-binding {$CSSCLASS}-{@type}" data-value="{{{$type},{$binding},{$value}}}" style="display:inline-block;"><xsl:value-of select="."/></div>
</xsl:when>
<xsl:when test="@type = 'progress'">
<div class="{$APPCLASS}-binding {$CSSCLASS}-{@type}" style="-webkit-user-select:none;{$border}{$width}{$height}{$fontsize}{$style}" data-value="{{{$type},{$binding},{$value}}}">