mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-04-25 11:51:49 +00:00
1. Release emulator version 0.14.
2. Fix normalization and rounding problems in Processor. 3. Fix Card-Load-Select -- emulator now boots from cards. 4. Commit LDCNTRL label and end cards to source CONTROL.DECK.job 5. Delete unused activeIOUnit property in all I/O drivers. 6. Change CardReader to reset file selector control when hopper becomes empty, instead of when START button is clicked. 7. Minor adjustments to CentralControl annunciator layout and behavior on Console. 8. Increase SPO paper scroll-back to 1500 lines (was 500). 9. Correct Card-Load-Select behavior in SyllableDebugger. 10. Implement setCallback() to replace setImmediate() in SyllableDebugger.
This commit is contained in:
@@ -61,7 +61,7 @@ function B5500CentralControl() {
|
||||
/**************************************/
|
||||
/* Global constants */
|
||||
|
||||
B5500CentralControl.version = "0.13";
|
||||
B5500CentralControl.version = "0.14";
|
||||
|
||||
B5500CentralControl.memReadCycles = 2; // assume 2 µs memory read cycle time (the other option was 3 µs)
|
||||
B5500CentralControl.memWriteCycles = 4; // assume 4 µs memory write cycle time (the other option was 6 µs)
|
||||
@@ -770,6 +770,7 @@ B5500CentralControl.prototype.loadComplete = function loadComplete(dontStart) {
|
||||
}
|
||||
|
||||
if (completed) {
|
||||
this.signalInterrupt(); // reset the pending I/O complete interrupt
|
||||
this.LOFF = 0;
|
||||
this.P1.preset(0x10); // start execution at C=@20
|
||||
if (!dontStart) {
|
||||
@@ -785,7 +786,7 @@ B5500CentralControl.prototype.load = function load(dontStart) {
|
||||
var result;
|
||||
var boundLoadComplete = (function boundLoadComplete(that, dontStart) {
|
||||
return function boundLoadCompleteAnon() {return that.loadComplete(dontStart)}
|
||||
})(this, dontStart);
|
||||
}(this, dontStart));
|
||||
|
||||
if (!this.P1 || this.P1.busy) { // P1 is busy or not available
|
||||
result = 1;
|
||||
|
||||
@@ -846,7 +846,7 @@ B5500IOUnit.prototype.initiate = function initiate() {
|
||||
to run asynchronously. Then we exit back through CC and into P1, thus allowing the
|
||||
actual I/O operation to run asynchronously from the processor. Of course, in a browser
|
||||
environment, all of the Javascript action occurs on one thread, so this allows us to
|
||||
multiplex what are supposed to be asynchronous operations on that thread */
|
||||
multiplex what normally would be asynchronous operations on that thread */
|
||||
|
||||
this.initiateStamp = new Date().getTime();
|
||||
this.clearD();
|
||||
|
||||
@@ -1611,10 +1611,9 @@ B5500Processor.prototype.singlePrecisionAdd = function singlePrecisionAdd(adding
|
||||
d = mb % 8;
|
||||
mb = (mb - d)/8; // shift right into extension
|
||||
xb = (xb - xb%8)/8 + d*0x1000000000;
|
||||
if (mb) {
|
||||
eb++;
|
||||
} else {
|
||||
eb = ea; // if B=0, result will have exponent of A
|
||||
eb++;
|
||||
if (mb == 0 && ea != eb) {
|
||||
eb = ea; // if B=0, kill the scaling loop: result will have exponent of A
|
||||
xb = 0; // prevent rounding of result
|
||||
}
|
||||
}
|
||||
@@ -1631,9 +1630,8 @@ B5500Processor.prototype.singlePrecisionAdd = function singlePrecisionAdd(adding
|
||||
d = ma % 8;
|
||||
ma = (ma - d)/8; // shift right into extension
|
||||
xa = (xa - xa%8)/8 + d*0x1000000000;
|
||||
if (ma) {
|
||||
ea++;
|
||||
} else {
|
||||
ea++;
|
||||
if (ma == 0 && eb != ea) {
|
||||
ea = eb; // if A=0, kill the scaling loop
|
||||
xa = 0; // prevent rounding of result
|
||||
}
|
||||
@@ -1646,68 +1644,72 @@ B5500Processor.prototype.singlePrecisionAdd = function singlePrecisionAdd(adding
|
||||
xb = (sb ? -xb : xb) + (sa ? -xa : xa); // compute the extension
|
||||
if (xb < 0) {
|
||||
xb += 0x8000000000; // adjust for underflow in the extension
|
||||
mb += (sb ? 1 : -1); // adjust B for borrow into extension
|
||||
d = -1; // adjust B for borrow into extension
|
||||
} else if (xb > 0x8000000000) {
|
||||
xb -= 0x8000000000; // adjust for overflow in the extension
|
||||
mb += (sb? -1 : 1); // adjust B for carry from extension
|
||||
d = 1; // adjust B for carry from extension
|
||||
} else {
|
||||
d = 0; // no adjustment
|
||||
}
|
||||
|
||||
mb = (sb ? -mb : mb) + (sa ? -ma : ma); // compute the mantissa
|
||||
mb = (sb ? -mb : mb) + (sa ? -ma : ma) + d; // compute the mantissa
|
||||
if (mb >= 0) { // if non-negative...
|
||||
sb = 0; // reset the B sign bit
|
||||
} else { // if negative...
|
||||
sb = 1; // set the B sign bit
|
||||
mb = -mb; // negate the B mantissa
|
||||
if (xb) { // if non-zero octades have been shifted into X (and ONLY if... learned THAT the hard way...)
|
||||
xb = 0x8000000000 - xb; // negate the extension in X
|
||||
mb--; // and adjust for borrow into X
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize and round as necessary
|
||||
if (mb < 0x1000000000) { // Normalization can be required for subtract
|
||||
if (xb < 0x800000000) { // if first two octades in X < @04 then
|
||||
d = 0; // no rounding will take place
|
||||
} else {
|
||||
this.cycleCount++;
|
||||
d = (xb - xb%0x1000000000)/0x1000000000; // get the high-order digit from X
|
||||
xb = (xb%0x1000000000)*8; // shift B and X left together
|
||||
mb = mb*8 + d;
|
||||
eb--;
|
||||
d = (xb - xb%0x1000000000)/0x1000000000; // get the rounding digit from X
|
||||
}
|
||||
} else if (mb >= 0x8000000000) { // Scaling can be required for add
|
||||
this.cycleCount++;
|
||||
d = mb % 8; // get the rounding digit from B
|
||||
mb = (mb - d)/8; // shift right due to overflow
|
||||
eb++;
|
||||
} else {
|
||||
d = (xb - xb%0x1000000000)/0x1000000000; // another hard-earned lesson...
|
||||
}
|
||||
|
||||
// Note: the Training Manual does not say that rounding is suppressed
|
||||
// for add/subtract when the mantissa is all ones, but it does say so
|
||||
// for multiply/divide, so we assume it's also the case here.
|
||||
if (d & 0x04) { // if the guard digit >= 4
|
||||
if (mb < 0x7FFFFFFFFF) { // and rounding would not cause overflow
|
||||
this.cycleCount++;
|
||||
mb++; // round up the result
|
||||
}
|
||||
}
|
||||
|
||||
// Check for exponent overflow
|
||||
if (eb > 63) {
|
||||
eb %= 64;
|
||||
if (this.NCSF) {
|
||||
this.I = (this.I & 0x0F) | 0xB0; // set I05/6/8: exponent-overflow
|
||||
this.cc.signalInterrupt();
|
||||
}
|
||||
} else if (eb < 0) {
|
||||
eb = (-eb) | 0x40; // set the exponent sign bit
|
||||
}
|
||||
|
||||
this.X = xb; // for display purposes only
|
||||
if (mb == 0) { // if the mantissa is zero...
|
||||
this.B = 0; // the whole result is zero, and we're done
|
||||
} else { // otherwise, determine the resulting sign
|
||||
if (mb > 0) { // if positive...
|
||||
sb = 0; // reset the B sign bit
|
||||
} else { // if negative...
|
||||
sb = 1; // set the B sign bit
|
||||
mb = -mb; // negate the B mantissa
|
||||
if (xb) { // if non-zero octades have been shifted into X (and ONLY if... learned THAT the hard way...)
|
||||
xb = 0x8000000000 - xb; // negate the extension in X
|
||||
mb--; // and adjust for borrow into X
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize and round as necessary
|
||||
if (mb < 0x1000000000) { // Normalization can be required for subtract
|
||||
if (xb < 0x800000000) { // if first two octades in X < @04 then
|
||||
d = 0; // no rounding will take place
|
||||
} else {
|
||||
this.cycleCount++;
|
||||
d = (xb - xb%0x1000000000)/0x1000000000; // get the rounding digit from X
|
||||
xb = (xb%0x1000000000)*8; // shift B and X left together
|
||||
mb = mb*8 + d;
|
||||
eb--;
|
||||
d = (xb - xb%0x1000000000)/0x1000000000; // get the next rounding digit from X
|
||||
}
|
||||
} else if (mb >= 0x8000000000) { // Scaling can be required for add
|
||||
this.cycleCount++;
|
||||
d = mb % 8; // get the rounding digit from B
|
||||
mb = (mb - d)/8; // shift right due to overflow
|
||||
eb++;
|
||||
}
|
||||
|
||||
// Note: the Training Manual does not say that rounding is suppressed
|
||||
// for add/subtract when the mantissa is all ones, but it does say so
|
||||
// for multiply/divide, so we assume it's also the case here.
|
||||
if (d & 0x04) { // if the guard digit >= 4
|
||||
if (mb < 0x7FFFFFFFFF) {// and rounding would not cause overflow
|
||||
this.cycleCount++;
|
||||
mb++; // round up the result
|
||||
}
|
||||
}
|
||||
|
||||
// Check for exponent overflow
|
||||
if (eb > 63) {
|
||||
eb %= 64;
|
||||
if (this.NCSF) {
|
||||
this.I = (this.I & 0x0F) | 0xB0; // set I05/6/8: exponent-overflow
|
||||
this.cc.signalInterrupt();
|
||||
}
|
||||
} else if (eb < 0) {
|
||||
eb = (-eb) | 0x40; // set the exponent sign bit
|
||||
}
|
||||
|
||||
this.X = xb; // for display purposes only
|
||||
this.B = (sb*128 + eb)*0x8000000000 + mb; // Final Answer
|
||||
}
|
||||
}
|
||||
@@ -1792,6 +1794,7 @@ B5500Processor.prototype.singlePrecisionMultiply = function singlePrecisionMulti
|
||||
// Normalize the result
|
||||
if (this.Q & 0x10 && mb == 0) { // if it's integer multiply (Q05F) with integer result
|
||||
mb = mx; // just use the low-order 39 bits
|
||||
mx = 0;
|
||||
eb = 0; // and don't normalize
|
||||
} else {
|
||||
eb += ea+13; // compute resulting exponent from multiply
|
||||
|
||||
1
tools/CONTROL.DECK.job
Normal file
1
tools/CONTROL.DECK.job
Normal file
@@ -0,0 +1 @@
|
||||
?LABEL 0CONTROL0DECK 0018317900
|
||||
1
tools/END.CONTROL.job
Normal file
1
tools/END.CONTROL.job
Normal file
@@ -0,0 +1 @@
|
||||
? END CONTROL
|
||||
@@ -62,7 +62,6 @@ B5500CardPunch.prototype.clear = function clear() {
|
||||
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
|
||||
@@ -73,7 +73,6 @@ B5500CardReader.prototype.clear = function clear() {
|
||||
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
@@ -148,7 +147,6 @@ B5500CardReader.prototype.CRStartBtn_onclick = function CRStartBtn_onclick(ev) {
|
||||
var that = this;
|
||||
|
||||
if (!this.ready) {
|
||||
this.$$("CRFileSelector").value = null; // reset the control so the same file can be reloaded
|
||||
if (this.bufIndex < this.bufLength) {
|
||||
this.setReaderReady(true);
|
||||
}
|
||||
@@ -185,6 +183,9 @@ B5500CardReader.prototype.CRProgressBar_onclick = function CRProgressBar_onclick
|
||||
this.bufLength = 0;
|
||||
this.bufIndex = 0;
|
||||
this.$$("CRProgressBar").value = 0;
|
||||
while (this.outHopper.childNodes.length > 0) {
|
||||
this.outHopper.removeChild(this.outHopper.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -392,6 +393,7 @@ B5500CardReader.prototype.read = function read(finish, buffer, length, mode, con
|
||||
this.bufLength = 0;
|
||||
this.bufIndex = 0;
|
||||
this.setReaderReady(false);
|
||||
this.$$("CRFileSelector").value = null; // reset the control so the same file can be reloaded
|
||||
}
|
||||
|
||||
this.timer = setTimeout(function readDelay() {
|
||||
|
||||
@@ -15,15 +15,17 @@ BODY {
|
||||
margin: 4px}
|
||||
|
||||
DIV#consoleDiv {
|
||||
position: relative;
|
||||
width: 1052px;
|
||||
height: 72px;
|
||||
padding: 32px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1125px;
|
||||
height: 140px;
|
||||
border-radius: 8px;
|
||||
background-color: #666}
|
||||
|
||||
DIV#BurroughsLogo {
|
||||
background-color: black;
|
||||
position: absolute;
|
||||
background-color: black;
|
||||
top: 32px;
|
||||
right: 32px;
|
||||
border-top: 3px solid #EEE;
|
||||
@@ -202,17 +204,17 @@ BUTTON#PowerOffBtn {
|
||||
TABLE#CentralControl {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
color: #666;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 7pt;
|
||||
font-weight: bold}
|
||||
|
||||
COL.AnnunciatorCol {
|
||||
width: 2.9%}
|
||||
width: 28px}
|
||||
|
||||
TD#procDelay, TD#procSlack {
|
||||
color: white;
|
||||
width: 64px;
|
||||
text-align: right}
|
||||
TD.statLabel {
|
||||
color: white;
|
||||
|
||||
@@ -47,7 +47,7 @@ window.addEventListener("load", function() {
|
||||
var perLightsMap = new Array(48);
|
||||
var procDelay;
|
||||
var procSlack;
|
||||
var showAnnunciators = false;
|
||||
var showAnnunciators = true;
|
||||
var timer;
|
||||
var timerInterval = 50; // milliseconds
|
||||
|
||||
@@ -77,8 +77,10 @@ window.addEventListener("load", function() {
|
||||
$$("LoadBtn").disabled = false;
|
||||
$$("HaltBtn").disabled = true;
|
||||
boundBlinkenlicht();
|
||||
BurroughsLogo_Click(); // turn on the annunciators
|
||||
window.focus();
|
||||
if (showAnnunciators) {
|
||||
$$("CentralControl").style.visibility = "visible";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -92,6 +94,7 @@ window.addEventListener("load", function() {
|
||||
$$("MemoryCheckBtn").className = "redButton";
|
||||
$$("NotReadyBtn").className = "whiteButton";
|
||||
$$("HaltBtn").className = "redButton";
|
||||
$$("CentralControl").style.visibility = "hidden";
|
||||
cc.powerOff();
|
||||
$$("PowerOnBtn").disabled = false;
|
||||
$$("PowerOffBtn").disabled = true;
|
||||
|
||||
@@ -97,7 +97,6 @@ B5500DiskUnit.prototype.clear = function clear() {
|
||||
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
|
||||
@@ -65,7 +65,6 @@ B5500DummyPrinter.prototype.clear = function clear() {
|
||||
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
|
||||
@@ -40,7 +40,6 @@ B5500DummyUnit.prototype.clear = function clear() {
|
||||
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
/* Constructor for the SPOUnit object */
|
||||
|
||||
this.maxScrollLines = 500; // Maximum amount of printer scrollback
|
||||
this.maxScrollLines = 1500; // Maximum amount of printer scrollback
|
||||
this.charPeriod = 100; // Printer speed, milliseconds per character
|
||||
|
||||
this.mnemonic = mnemonic; // Unit mnemonic
|
||||
@@ -76,7 +76,6 @@ B5500SPOUnit.prototype.clear = function clear() {
|
||||
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500SyllableDebugger.css">
|
||||
|
||||
<script src="./setImmediate.js"></script>
|
||||
<script src="./B5500SetCallback.js"></script>
|
||||
|
||||
<script src="./B5500DummyUnit.js"></script>
|
||||
<script src="./B5500SPOUnit.js"></script>
|
||||
@@ -714,8 +714,47 @@ function runIt(ev) {
|
||||
var stopAddr = $$("StopAddr");
|
||||
|
||||
function syllabicate() {
|
||||
var addr;
|
||||
var prt;
|
||||
var word;
|
||||
|
||||
do {
|
||||
cc.P1.step();
|
||||
|
||||
if (false) { // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DEBUG <<<<<<<<<<
|
||||
addr = cc.memMod[0][149] % 0x8000 + 1; // MCP PRT @225: addr of PRT[1,*] DD
|
||||
word = cc.memMod[addr >>> 12][addr & 0xFFF]; // PRT[2,*] DD
|
||||
if (word > 0xA00000000000) {
|
||||
prt = word % 0x8000
|
||||
|
||||
if (false) { // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DEBUG <<<<<<<<<<
|
||||
addr = prt + 70; // addr of STACKHEAD DD
|
||||
word = cc.memMod[addr >>> 12][addr & 0xFFF]; // STACKHEAD DD
|
||||
if (word > 0xA00000000000) {
|
||||
addr = word % 0x8000 + 66; // addr of STACKHEAD[66]
|
||||
word = cc.memMod[addr >>> 12][addr & 0xFFF];
|
||||
if (word == 2) {
|
||||
alert("STACKHEAD[66]==2");
|
||||
stopAddress = 0;
|
||||
}
|
||||
}
|
||||
} // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
addr = prt + 204; // addr of NEXTINFO
|
||||
word = cc.memMod[addr >>> 12][addr & 0xFFF]; // NEXTINFO
|
||||
if (window.uglyLatch) {
|
||||
if (word <= 2) {
|
||||
alert("NEXTINFO==1");
|
||||
stopAddress = 0;
|
||||
}
|
||||
} else {
|
||||
if (word > 255) {
|
||||
window.uglyLatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
if (cc.P1.S > 0x7FFF) {
|
||||
alert("P1.S out of range");
|
||||
stopAddress = 0;
|
||||
@@ -740,7 +779,7 @@ function runIt(ev) {
|
||||
} while (runSilently && stopAddress && cc.P1.C != stopAddress);
|
||||
|
||||
if (stopAddress && cc.P1.C != stopAddress) {
|
||||
setImmediate(syllabicate);
|
||||
setCallback(syllabicate, this, 0);
|
||||
if (!runSilently) {
|
||||
displaySystemState();
|
||||
}
|
||||
@@ -884,11 +923,11 @@ function hardwareLoad_onClick(ev) {
|
||||
var result;
|
||||
|
||||
cc.clear();
|
||||
cc.P1.clear();
|
||||
cc.cardLoadSelect = $$("CardLoadSelect").checked;
|
||||
result = cc.load(true);
|
||||
switch (result) {
|
||||
case 0: // load initiated successfully
|
||||
cc.P1.clear();
|
||||
cc.cardLoadSelect = $$("CardLoadSelect").checked;
|
||||
displaySystemState();
|
||||
break;
|
||||
case 1:
|
||||
@@ -1103,6 +1142,7 @@ function initialize() {
|
||||
displaySystemState();
|
||||
displayOctal("StopAddr", stopAddress, 5);
|
||||
establishSilence(runSilently);
|
||||
$$("StepBtn").disabled = false;
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
|
||||
16
webUI/prototypes/B5500SPOPaperPrototype.html
Normal file
16
webUI/prototypes/B5500SPOPaperPrototype.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>B5500 Emulator SPO Paper Prototype</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Nigel Williams & Paul Kimpel">
|
||||
<!-- 2013-07-25 Orignal version -->
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500SPOPrototype.css">
|
||||
</head>
|
||||
|
||||
<body class="SPOUT">
|
||||
TEST TEST
|
||||
</body>
|
||||
</html>
|
||||
@@ -14,46 +14,52 @@ BODY {
|
||||
position: relative;
|
||||
background-color: black;
|
||||
margin: 4px}
|
||||
|
||||
|
||||
PRE {
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 10pt;
|
||||
font-size: xx-small;
|
||||
margin: 0}
|
||||
|
||||
|
||||
|
||||
DIV#SPODiv {
|
||||
position: relative;
|
||||
width: 800px;
|
||||
width: 660px;
|
||||
height: 500px;
|
||||
background-color: #FDA;
|
||||
border-radius: 32px;
|
||||
padding: 2em;
|
||||
border-radius: 16px;
|
||||
text-align: left}
|
||||
|
||||
|
||||
IFRAME#SPOUT {
|
||||
width: 620px;
|
||||
height: 475px;
|
||||
border: 2px solid black;
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
bottom: 16px;
|
||||
height: 468px;
|
||||
width: 470px;
|
||||
border: 1px solid black}
|
||||
|
||||
BODY.SPOUT {
|
||||
background-color: #FFE;
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 10pt}
|
||||
|
||||
font-size: xx-small}
|
||||
|
||||
DIV#SPOControlsDiv {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 136px;
|
||||
left: 690px;
|
||||
top: 32px}
|
||||
|
||||
right: 16px;
|
||||
bottom: 16px}
|
||||
|
||||
IMG#TeletypeLogo {
|
||||
left: auto;
|
||||
right: auto}
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 66px}
|
||||
|
||||
BUTTON.whiteButton {
|
||||
position: absolute;
|
||||
background-color: #CCC;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: xx-small;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -65,7 +71,7 @@ BUTTON.blackButton {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: xx-small;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -77,7 +83,7 @@ BUTTON.yellowButton {
|
||||
background-color: #990;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: xx-small;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -89,48 +95,48 @@ BUTTON.whiteLit {
|
||||
|
||||
BUTTON.yellowLit {
|
||||
background-color: #FF0}
|
||||
|
||||
|
||||
BUTTON.blackBorder {
|
||||
border: 1px solid black}
|
||||
|
||||
|
||||
BUTTON#SPOReadyBtn {
|
||||
top: 187px;
|
||||
bottom: 224px;
|
||||
left: 0px}
|
||||
|
||||
|
||||
BUTTON#SPOPowerBtn {
|
||||
top: 187px;
|
||||
bottom: 224px;
|
||||
right: 0px}
|
||||
|
||||
|
||||
BUTTON#SPORemoteBtn {
|
||||
top: 243px;
|
||||
bottom: 168px;
|
||||
left: 0px}
|
||||
|
||||
|
||||
BUTTON#SPOLocalBtn {
|
||||
top: 243px;
|
||||
bottom: 168px;
|
||||
right: 0px}
|
||||
|
||||
|
||||
BUTTON#SPOInputRequestBtn {
|
||||
top: 299px;
|
||||
bottom: 112px;
|
||||
left: 0px}
|
||||
|
||||
|
||||
BUTTON#SPOEndOfMessageBtn {
|
||||
top: 299px;
|
||||
bottom: 112px;
|
||||
right: 0px}
|
||||
|
||||
|
||||
BUTTON#SPOBlank1Btn {
|
||||
top: 355px;
|
||||
bottom: 56px;
|
||||
left: 0px}
|
||||
|
||||
|
||||
BUTTON#SPOErrorBtn {
|
||||
top: 355px;
|
||||
bottom: 56px;
|
||||
right: 0px}
|
||||
|
||||
|
||||
BUTTON#SPOBlank2Btn {
|
||||
top: 411px;
|
||||
bottom: 0px;
|
||||
left: 0px}
|
||||
|
||||
|
||||
BUTTON#SPOBlank3Btn {
|
||||
top: 411px;
|
||||
bottom: 0px;
|
||||
right: 0px}
|
||||
|
||||
.center {
|
||||
@@ -139,7 +145,7 @@ BUTTON#SPOBlank3Btn {
|
||||
.data {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
text-align: left}
|
||||
|
||||
|
||||
.number {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
text-align: right}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>B5500 Emulator SPO Unit Prototype</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
@@ -10,8 +11,7 @@
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
window.onload = function() {
|
||||
const spoNotReady = 0;
|
||||
window.addEventListener("load", function() {
|
||||
const spoLocal = 1;
|
||||
const spoRemote = 2;
|
||||
const spoInput = 3;
|
||||
@@ -19,7 +19,7 @@ window.onload = function() {
|
||||
|
||||
var $$ = function(e) {return document.getElementById(e)};
|
||||
var msgTank = [];
|
||||
var spoState = spoNotReady;
|
||||
var spoState = spoLocal;
|
||||
var spoLocalRequested = false;
|
||||
var spoInputActive = false;
|
||||
var spoInputRequested = false;
|
||||
@@ -74,7 +74,7 @@ window.onload = function() {
|
||||
|
||||
frame.contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #FFE} " +
|
||||
"PRE {margin: 0; font-size: 10pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"PRE {margin: 0; font-size: x-small; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
};
|
||||
|
||||
@@ -94,10 +94,10 @@ window.onload = function() {
|
||||
};
|
||||
|
||||
var accept = function() {
|
||||
var inputBtn = $$("SPOInputRequestBtn");
|
||||
|
||||
spoState = spoInput;
|
||||
addClass(inputBtn, "yellowLit");
|
||||
removeClass($$("SPOInputRequestBtn"), "yellowLit");
|
||||
addClass($$("SPOReadyBtn"), "yellowLit")
|
||||
window.focus();
|
||||
|
||||
msgCtl.buffer = new Uint8Array(80);
|
||||
@@ -218,20 +218,6 @@ window.onload = function() {
|
||||
}
|
||||
};
|
||||
|
||||
var setReady = function(ready) {
|
||||
/* Sets the ready status of the SPO based on the truth of "ready" */
|
||||
var readyBtn = $$("SPOReadyBtn");
|
||||
|
||||
if (ready && spoState == spoNotReady) {
|
||||
addClass(readyBtn, "yellowLit");
|
||||
spoState = spoLocal;
|
||||
setRemote(true);
|
||||
} else if (!ready && spoState != spoNotReady) {
|
||||
spoState = spoNotReady;
|
||||
removeClass(readyBtn, "yellowLit");
|
||||
}
|
||||
};
|
||||
|
||||
var setRemote = function(remote) {
|
||||
/* Sets the remote status of the SPO based on the truth of "remote" */
|
||||
var localBtn = $$("SPOLocalBtn");
|
||||
@@ -252,6 +238,7 @@ window.onload = function() {
|
||||
var initiateInput = function(ev) {
|
||||
/* Handles a successful Input Request event and enables the keyboard */
|
||||
|
||||
addClass($$("SPOInputRequestBtn"), "yellowLit");
|
||||
if (spoState == spoRemote) {
|
||||
accept();
|
||||
} else if (spoState == spoOutput) {
|
||||
@@ -269,7 +256,7 @@ window.onload = function() {
|
||||
} else {
|
||||
spoState = spoRemote;
|
||||
}
|
||||
removeClass($$("SPOInputRequestBtn"), "yellowLit");
|
||||
removeClass($$("SPOReadyBtn"), "yellowLit");
|
||||
text = String.fromCharCode.apply(null, msgCtl.buffer.subarray(0, msgCtl.length));
|
||||
printChar();
|
||||
printText("YOU ENTERED: " + text);
|
||||
@@ -286,7 +273,7 @@ window.onload = function() {
|
||||
} else {
|
||||
spoState = spoRemote;
|
||||
}
|
||||
removeClass($$("SPOInputRequestBtn"), "yellowLit");
|
||||
removeClass($$("SPOReadyBtn"), "yellowLit");
|
||||
printChar();
|
||||
printText("**ERROR");
|
||||
}
|
||||
@@ -425,19 +412,18 @@ window.onload = function() {
|
||||
};
|
||||
|
||||
addFrameStyles($$("SPOUT"));
|
||||
appendEmptyLine(32);
|
||||
setReady(true);
|
||||
appendEmptyLine(100);
|
||||
setRemote(true);
|
||||
|
||||
doTests();
|
||||
};
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id=SPODiv>
|
||||
<iframe id=SPOUT scrolling=auto></iframe>
|
||||
<iframe id=SPOUT data-type-src="./B5500SPOPaperPrototype.html" scrolling=auto></iframe>
|
||||
<div id=SPOControlsDiv>
|
||||
<img id=TeletypeLogo src="TeletypeLogo.gif">
|
||||
<button id=SPOReadyBtn class="yellowButton blackBorder">READY</button>
|
||||
|
||||
Reference in New Issue
Block a user