mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-02-12 03:07:30 +00:00
1. Release emulator version 0.13 (finally).
2. Implement new setCallback() mechanism to wrap setTimeout() and setImmediate(). 2. Minor change to P2 management; remove context-bound callbacks. 3. Reduce window size and font size for peripheral UIs. 4. Implement <label> for file names on ColdLoader Load table. 5. Correct placement and color of buttons on Console and SPO. 6. Minor wiki updates for UI changes. 7. Rework SPO implementation to eliminate ".that" properties, implement setCallback(), and fix long-standing bugs that caused flaky operation.
This commit is contained in:
@@ -25,8 +25,8 @@ DIV#CPDiv {
|
||||
position: relative;
|
||||
color: white;
|
||||
background-color: #666;
|
||||
width: 700px;
|
||||
height: 300px;
|
||||
width: 550px;
|
||||
height: 194px;
|
||||
border: 1px solid black;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
@@ -36,7 +36,7 @@ BUTTON.greenButton {
|
||||
background-color: #060;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -47,7 +47,7 @@ BUTTON.blackButton {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -58,7 +58,7 @@ BUTTON.redButton {
|
||||
background-color: #900;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -96,44 +96,44 @@ BUTTON.redLit {
|
||||
top: 56px;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
height: 160px;
|
||||
height: 80px;
|
||||
font-weight: bold}
|
||||
|
||||
#CPStacker1Bar {
|
||||
border: 1px solid white;
|
||||
width: 610px}
|
||||
width: 450px}
|
||||
|
||||
#CPStacker1Frame {
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
height: 60px;
|
||||
margin-top: 1px;
|
||||
border: 1px solid white;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 10pt;
|
||||
font-size: 8pt;
|
||||
font-weight: normal}
|
||||
|
||||
#CPStacker2Div {
|
||||
position: absolute;
|
||||
top: 220px;
|
||||
top: 140px;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
height: 70px;
|
||||
height: 44px;
|
||||
font-weight: bold}
|
||||
|
||||
#CPStacker2Bar {
|
||||
border: 1px solid white;
|
||||
width: 610px}
|
||||
width: 450px}
|
||||
|
||||
#CPStacker2Frame {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
height: 30px;
|
||||
margin-top: 1px;
|
||||
border: 1px solid white;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 10pt;
|
||||
font-size: 8pt;
|
||||
font-weight: normal}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ function B5500CardPunch(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
this.stacker2 = null;
|
||||
this.endOfStacker2 = null;
|
||||
this.window = window.open("/B5500/webUI/B5500CardPunch.html", mnemonic,
|
||||
"scrollbars=no,resizable,width=700,height=500");
|
||||
"scrollbars=no,resizable,width=560,height=204,left=0,top=220");
|
||||
this.window.addEventListener("load", function windowLoad() {
|
||||
that.punchOnload();
|
||||
}, false);
|
||||
@@ -199,8 +199,8 @@ B5500CardPunch.prototype.punchOnload = function punchOnload() {
|
||||
|
||||
this.stacker1Frame = this.$$("CPStacker1Frame");
|
||||
this.stacker1Frame.contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #FFE; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 9pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"BODY {background-color: white; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 8pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
this.stacker1 = this.doc.createElement("pre");
|
||||
this.stacker1Frame.contentDocument.body.appendChild(this.stacker1);
|
||||
@@ -209,18 +209,14 @@ B5500CardPunch.prototype.punchOnload = function punchOnload() {
|
||||
|
||||
this.stacker2Frame = this.$$("CPStacker2Frame");
|
||||
this.stacker2Frame.contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #FFE; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 9pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"BODY {background-color: white; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 8pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
this.stacker2 = this.doc.createElement("pre");
|
||||
this.stacker2Frame.contentDocument.body.appendChild(this.stacker2);
|
||||
this.endOfStacker2 = this.doc.createElement("div");
|
||||
this.stacker2Frame.contentDocument.body.appendChild(this.endOfStacker2);
|
||||
|
||||
this.window.moveTo(0, 180);
|
||||
this.window.resizeTo(this.window.outerWidth+this.$$("CPDiv").scrollWidth-this.window.innerWidth+12,
|
||||
this.window.outerHeight+this.$$("CPDiv").scrollHeight-this.window.innerHeight+12);
|
||||
|
||||
this.window.addEventListener("beforeunload", this.beforeUnload, false);
|
||||
|
||||
this.armRunout(false);
|
||||
|
||||
@@ -18,7 +18,7 @@ BODY {
|
||||
DIV#CRDiv {
|
||||
position: relative;
|
||||
background-color: #666;
|
||||
width: 700px;
|
||||
width: 550px;
|
||||
height: 150px;
|
||||
border: 1px solid black;
|
||||
border-radius: 8px;
|
||||
@@ -29,7 +29,7 @@ BUTTON.greenButton {
|
||||
background-color: #060;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -40,7 +40,7 @@ BUTTON.blackButton {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -51,7 +51,7 @@ BUTTON.redButton {
|
||||
background-color: #900;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -59,7 +59,7 @@ BUTTON.redButton {
|
||||
border-radius: 4px}
|
||||
|
||||
BUTTON.greenLit {
|
||||
background-color: green}
|
||||
background-color: #0F0}
|
||||
|
||||
BUTTON.redLit {
|
||||
background-color: #F00}
|
||||
@@ -88,14 +88,14 @@ BUTTON.redLit {
|
||||
position: absolute;
|
||||
border: 1px solid white;
|
||||
color: white;
|
||||
width: 680px;
|
||||
width: 530px;
|
||||
top: 54px;
|
||||
left: 8px}
|
||||
|
||||
#CRProgressBar {
|
||||
position: absolute;
|
||||
border: 1px solid white;
|
||||
width: 680px;
|
||||
width: 530px;
|
||||
top: 84px;
|
||||
left: 8px}
|
||||
|
||||
@@ -103,7 +103,7 @@ BUTTON.redLit {
|
||||
position: absolute;
|
||||
top: 106px;
|
||||
left: 8px;
|
||||
width: 680px;
|
||||
width: 530px;
|
||||
height: 35px;
|
||||
border: 1px solid white;
|
||||
color: black;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
/* Constructor for the CardReader object */
|
||||
var that = this;
|
||||
var x = (mnemonic == "CRA" ? 0 : 30);
|
||||
|
||||
this.mnemonic = mnemonic; // Unit mnemonic
|
||||
this.unitIndex = unitIndex; // Ready-mask bit number
|
||||
@@ -38,7 +39,7 @@ function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
}
|
||||
this.doc = null;
|
||||
this.window = window.open("/B5500/webUI/B5500CardReader.html", mnemonic,
|
||||
"scrollbars=no,resizable,width=700,height=150");
|
||||
"scrollbars=no,resizable,width=560,height=160,left="+x+",top="+x);
|
||||
this.window.addEventListener("load", function windowLoad() {
|
||||
that.readerOnload();
|
||||
}, false);
|
||||
@@ -320,19 +321,14 @@ B5500CardReader.prototype.beforeUnload = function beforeUnload(ev) {
|
||||
B5500CardReader.prototype.readerOnload = function readerOnload() {
|
||||
/* Initializes the reader window and user interface */
|
||||
var that = this;
|
||||
var x = (this.mnemonic == "CRA" ? 0 : this.window.outerWidth + 16);
|
||||
|
||||
this.doc = this.window.document;
|
||||
this.doc.title = "retro-B5500 " + this.mnemonic;
|
||||
|
||||
this.window.moveTo(x, 0);
|
||||
this.window.resizeTo(this.window.outerWidth+this.$$("CRDiv").scrollWidth-this.window.innerWidth+12,
|
||||
this.window.outerHeight+this.$$("CRDiv").scrollHeight-this.window.innerHeight+12);
|
||||
|
||||
this.outHopperFrame = this.$$("CROutHopperFrame");
|
||||
this.outHopperFrame.contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #FFE; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 9pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"BODY {background-color: white; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 8pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
this.outHopper = this.doc.createElement("pre");
|
||||
this.outHopperFrame.contentDocument.body.appendChild(this.outHopper);
|
||||
|
||||
@@ -1261,7 +1261,10 @@ window.addEventListener("load", function() {
|
||||
row.appendChild(cell);
|
||||
// File ID
|
||||
cell = document.createElement("td");
|
||||
cell.appendChild(document.createTextNode(tapeDir[x]));
|
||||
e = document.createElement("label");
|
||||
e.appendChild(document.createTextNode(tapeDir[x]));
|
||||
e.htmlFor = "File_" + x;
|
||||
cell.appendChild(e);
|
||||
row.appendChild(cell);
|
||||
// Load as MCP selection radio button
|
||||
cell = document.createElement("td");
|
||||
@@ -2037,7 +2040,8 @@ window.addEventListener("load", function() {
|
||||
if (!checkBrowser()) {
|
||||
$$("FileSelector").addEventListener("change", fileSelector_onChange, false);
|
||||
$$("ColdstartBtn").addEventListener("click", function(ev) {
|
||||
if (confirm("Are you sure you want to do a COLD START?")) {
|
||||
if (confirm("Are you sure you want to do a COLD START?\n" +
|
||||
"This will PERMANENTLY DELETE all files in the B5500 disk subsystem.")) {
|
||||
initializeDisk();
|
||||
}
|
||||
}, false);
|
||||
|
||||
@@ -48,7 +48,7 @@ DIV#RetroVersion {
|
||||
right: 170px;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: x-small;
|
||||
font-size: 7pt;
|
||||
font-weight: bold}
|
||||
|
||||
IMG#BurroughsLogoImage {
|
||||
@@ -65,7 +65,31 @@ BUTTON.whiteButton {
|
||||
background-color: #CCC;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: x-small;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
border: 1px solid #DDD;
|
||||
border-radius: 4px}
|
||||
|
||||
BUTTON.greenButton {
|
||||
position: absolute;
|
||||
background-color: #060;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
border: 1px solid #DDD;
|
||||
border-radius: 4px}
|
||||
|
||||
BUTTON.redButton {
|
||||
position: absolute;
|
||||
background-color: #900;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -77,7 +101,7 @@ BUTTON.blackButton {
|
||||
background-color: black;
|
||||
color: #999;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: x-small;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -89,7 +113,7 @@ BUTTON.yellowButton {
|
||||
background-color: #990;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: x-small;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -102,6 +126,12 @@ BUTTON.whiteLit {
|
||||
BUTTON.blackLit {
|
||||
color: #FFF}
|
||||
|
||||
BUTTON.greenLit {
|
||||
background-color: #0F0}
|
||||
|
||||
BUTTON.redLit {
|
||||
background-color: #F00}
|
||||
|
||||
BUTTON.yellowLit {
|
||||
background-color: #FF0}
|
||||
BUTTON.yellowLit5 {
|
||||
@@ -132,7 +162,7 @@ BUTTON#NotReadyBtn {
|
||||
top: 31px;
|
||||
left: 132px}
|
||||
|
||||
BUTTON#LoadSelectBtn {
|
||||
BUTTON#MemoryCheckBtn {
|
||||
top: 31px;
|
||||
left: 202px}
|
||||
|
||||
@@ -140,7 +170,8 @@ BUTTON#LoadBtn {
|
||||
top: 31px;
|
||||
left: 272px}
|
||||
|
||||
BUTTON#MemoryCheckBtn {
|
||||
BUTTON#LoadSelectBtn {
|
||||
line-height: 100%;
|
||||
top: 31px;
|
||||
left: 372px}
|
||||
|
||||
@@ -171,9 +202,10 @@ BUTTON#PowerOffBtn {
|
||||
TABLE#CentralControl {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
color: #666;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: x-small;
|
||||
font-size: 7pt;
|
||||
font-weight: bold}
|
||||
|
||||
COL.AnnunciatorCol {
|
||||
@@ -182,6 +214,9 @@ COL.AnnunciatorCol {
|
||||
TD#procDelay, TD#procSlack {
|
||||
color: white;
|
||||
text-align: right}
|
||||
TD.statLabel {
|
||||
color: white;
|
||||
text-align: left}
|
||||
|
||||
|
||||
.busy {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500Console.css">
|
||||
|
||||
<script src="./setImmediate.js"></script>
|
||||
<script src="./B5500SetCallback.js"></script>
|
||||
|
||||
<script src="./B5500DummyUnit.js"></script>
|
||||
<script src="./B5500SPOUnit.js"></script>
|
||||
@@ -68,11 +68,12 @@ window.addEventListener("load", function() {
|
||||
}
|
||||
|
||||
function PowerOnBtn_Click(ev) {
|
||||
$$("PowerOnBtn").className = "whiteButton whiteLit";
|
||||
$$("AControlBtn").className = "yellowButton yellowLit";
|
||||
$$("PowerOnBtn").className = "greenButton greenLit";
|
||||
$$("HaltBtn").className = "redButton redLit";
|
||||
cc.powerOn();
|
||||
$$("PowerOnBtn").disabled = true;
|
||||
$$("PowerOffBtn").disabled = false;
|
||||
$$("LoadSelectBtn").disabled = false;
|
||||
$$("LoadBtn").disabled = false;
|
||||
$$("HaltBtn").disabled = true;
|
||||
boundBlinkenlicht();
|
||||
@@ -82,15 +83,21 @@ window.addEventListener("load", function() {
|
||||
}
|
||||
|
||||
function PowerOffBtn_Click(ev) {
|
||||
$$("PowerOnBtn").className = "whiteButton";
|
||||
$$("PowerOnBtn").className = "greenButton";
|
||||
$$("ANormalBtn").className = "yellowButton";
|
||||
$$("AControlBtn").className = "yellowButton";
|
||||
$$("BNormalBtn").className = "yellowButton";
|
||||
$$("BControlBtn").className = "yellowButton";
|
||||
$$("LoadSelectBtn").className = "yellowButton";
|
||||
$$("MemoryCheckBtn").className = "redButton";
|
||||
$$("NotReadyBtn").className = "whiteButton";
|
||||
$$("HaltBtn").className = "redButton";
|
||||
cc.powerOff();
|
||||
$$("PowerOnBtn").disabled = false;
|
||||
$$("PowerOffBtn").disabled = true;
|
||||
$$("HaltBtn").disabled = true;
|
||||
$$("LoadSelectBtn").disabled = true;
|
||||
$$("LoadBtn").disabled = true;
|
||||
$$("HaltBtn").disabled = true;
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
@@ -99,6 +106,7 @@ window.addEventListener("load", function() {
|
||||
}
|
||||
|
||||
function HaltBtn_Click(ev) {
|
||||
$$("HaltBtn").className = "redButton redLit";
|
||||
cc.halt();
|
||||
$$("HaltBtn").disabled = true;
|
||||
$$("LoadBtn").disabled = false;
|
||||
@@ -110,6 +118,7 @@ window.addEventListener("load", function() {
|
||||
result = cc.load(false);
|
||||
switch (result) {
|
||||
case 0: // load initiated successfully
|
||||
$$("HaltBtn").className = "redButton";
|
||||
$$("HaltBtn").disabled = false;
|
||||
$$("LoadBtn").disabled = true;
|
||||
break;
|
||||
@@ -131,10 +140,10 @@ window.addEventListener("load", function() {
|
||||
function LoadSelectBtn_Click(ev) {
|
||||
if (cc.cardLoadSelect) {
|
||||
cc.cardLoadSelect = 0;
|
||||
$$("LoadSelectBtn").className = "blackButton blackLit silverBorder";
|
||||
$$("LoadSelectBtn").className = "yellowButton";
|
||||
} else {
|
||||
cc.cardLoadSelect = 1;
|
||||
$$("LoadSelectBtn").className = "blackButton blackLit yellowBorder";
|
||||
$$("LoadSelectBtn").className = "yellowButton yellowLit";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +349,7 @@ window.addEventListener("load", function() {
|
||||
while (et < 0) {
|
||||
et += stamp;
|
||||
}
|
||||
procDelay.innerHTML = p1.delayDeltaAvg.toFixed(3);
|
||||
procDelay.innerHTML = p1.delayDeltaAvg.toFixed(1);
|
||||
procSlack.innerHTML = (p1.procSlack/et*100).toFixed(1) + "%";
|
||||
|
||||
if (showAnnunciators) {
|
||||
@@ -418,19 +427,19 @@ window.addEventListener("load", function() {
|
||||
<body>
|
||||
|
||||
<div id=consoleDiv>
|
||||
<button id=HaltBtn class="blackButton blackLit" DISABLED>HALT</button>
|
||||
<button id=HaltBtn class="redButton" DISABLED>HALT</button>
|
||||
|
||||
<button id=NotReadyBtn class=yellowButton>NOT READY</button>
|
||||
<button id=LoadSelectBtn class="blackButton blackLit silverBorder">LOAD SELECT</button>
|
||||
<button id=NotReadyBtn class=whiteButton>NOT READY</button>
|
||||
<button id=MemoryCheckBtn class=redButton>MEMORY CHECK</button>
|
||||
<button id=LoadBtn class="blackButton blackLit" DISABLED>LOAD</button>
|
||||
|
||||
<button id=MemoryCheckBtn class=yellowButton>MEMORY CHECK</button>
|
||||
<button id=LoadSelectBtn class="yellowButton" DISABLED>CARD LOAD SELECT</button>
|
||||
<button id=ANormalBtn class=yellowButton>A NORMAL</button>
|
||||
<button id=AControlBtn class=yellowButton>A CONTROL</button>
|
||||
<button id=BNormalBtn class=yellowButton>B NORMAL</button>
|
||||
<button id=BControlBtn class=yellowButton>B CONTROL</button>
|
||||
|
||||
<button id=PowerOnBtn class=whiteButton>POWER<br>ON</button>
|
||||
<button id=PowerOnBtn class=greenButton>POWER<br>ON</button>
|
||||
<button id=PowerOffBtn class="blackButton blackLit" DISABLED>POWER OFF</button>
|
||||
|
||||
<div id=BurroughsLogo>
|
||||
@@ -447,8 +456,8 @@ window.addEventListener("load", function() {
|
||||
|
||||
<table id=CentralControl style="visibility:hidden">
|
||||
<colgroup>
|
||||
<col span=32 class=AnnunciatorCol>
|
||||
<col>
|
||||
<col span=31 class=AnnunciatorCol>
|
||||
<col span=2>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr id=CCInterruptRow>
|
||||
@@ -472,7 +481,7 @@ window.addEventListener("load", function() {
|
||||
<td id=CCI16F>DK2F <!-- Disk file #2 read check finished -->
|
||||
<td colspan=13>
|
||||
<td id=procSlack>
|
||||
<td class=busy title="Percentage of time Processor A is throttling its performance">P1 Slack
|
||||
<td class=statLabel title="Percentage of time Processor A is throttling its performance">P1 Slack
|
||||
<tr id=CCPeripheralRow>
|
||||
<td id=DRA>DRA <!-- 31 -->
|
||||
<td id=DRB>DRB <!-- 30 -->
|
||||
@@ -506,7 +515,7 @@ window.addEventListener("load", function() {
|
||||
<td id=MTS>MTS <!-- 33 -->
|
||||
<td id=MTT>MTT <!-- 32 -->
|
||||
<td id=procDelay>
|
||||
<td class=busy title="Average excess throttling delay for Processor A (ms)">P1 Delay
|
||||
<td class=statLabel title="Average excess throttling delay for Processor A (ms)">P1 Delay
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
<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="B5500SPOUnit.css" -->
|
||||
<style>
|
||||
BODY {
|
||||
padding: 4px}
|
||||
|
||||
PRE {
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 8pt}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
function B5500DummyPrinter(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
/* Constructor for the DummyPrinter object */
|
||||
var that = this;
|
||||
var h = screen.availHeight*0.60;
|
||||
var w = 900;
|
||||
var s;
|
||||
|
||||
this.mnemonic = mnemonic; // Unit mnemonic
|
||||
this.unitIndex = unitIndex; // Ready-mask bit number
|
||||
@@ -41,7 +44,8 @@ function B5500DummyPrinter(mnemonic, unitIndex, designate, statusChange, signal)
|
||||
this.paper = null;
|
||||
this.endOfPaper = null;
|
||||
this.window = window.open("/B5500/webUI/B5500DummyPrinter.html", mnemonic,
|
||||
"scrollbars,resizable,width=600,height=500");
|
||||
s = "scrollbars,resizable,width=" + w + ",height=" + h +
|
||||
",left=0,top=" + (screen.availHeight - h));
|
||||
this.window.addEventListener("load", function windowOnLoad() {
|
||||
that.printerOnload();
|
||||
}, false);
|
||||
@@ -113,9 +117,6 @@ B5500DummyPrinter.prototype.printerOnload = function printerOnload() {
|
||||
this.endOfPaper = this.doc.createElement("div");
|
||||
this.doc.body.appendChild(this.endOfPaper);
|
||||
|
||||
this.window.moveTo(40, 40);
|
||||
this.window.resizeTo(1000, screen.availHeight*0.80);
|
||||
|
||||
this.window.addEventListener("click", function windowOnClick(ev) {
|
||||
if (ev.detail == 2) { // check for left-button double-click
|
||||
that.ripPaper(ev);
|
||||
|
||||
@@ -14,36 +14,42 @@ BODY {
|
||||
position: relative;
|
||||
background-color: black;
|
||||
margin: 4px}
|
||||
|
||||
|
||||
PRE {
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 10pt;
|
||||
font-size: 8pt;
|
||||
margin: 0}
|
||||
|
||||
|
||||
|
||||
DIV#SPODiv {
|
||||
position: relative;
|
||||
width: 800px;
|
||||
background-color: #F7E7CE;
|
||||
border-radius: 32px;
|
||||
padding: 2em;
|
||||
width: 750px;
|
||||
height: 500px;
|
||||
background-color: #FFC;
|
||||
border-radius: 16px;
|
||||
text-align: left}
|
||||
|
||||
|
||||
IFRAME#SPOUT {
|
||||
width: 620px;
|
||||
height: 475px;
|
||||
border: 2px solid black;
|
||||
background-color: #FFE;
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
bottom: 16px;
|
||||
height: 468px;
|
||||
width: 560px;
|
||||
border: 1px solid black}
|
||||
|
||||
BODY.SPOUT {
|
||||
background-color: white;
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 10pt}
|
||||
|
||||
font-size: 8pt}
|
||||
|
||||
DIV#SPOControlsDiv {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
height: 468px;
|
||||
width: 136px;
|
||||
left: 690px;
|
||||
top: 32px}
|
||||
|
||||
right: 16px;
|
||||
bottom: 16px}
|
||||
|
||||
IMG#TeletypeLogo {
|
||||
left: auto;
|
||||
right: auto}
|
||||
@@ -53,19 +59,19 @@ BUTTON.whiteButton {
|
||||
background-color: #CCC;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
border: 1px solid #DDD;
|
||||
border-radius: 4px}
|
||||
|
||||
BUTTON.blackButton {
|
||||
BUTTON.greenButton {
|
||||
position: absolute;
|
||||
background-color: black;
|
||||
color: white;
|
||||
background-color: #060;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 8pt;
|
||||
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: 8pt;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -87,50 +93,53 @@ BUTTON.yellowButton {
|
||||
BUTTON.whiteLit {
|
||||
background-color: white}
|
||||
|
||||
BUTTON.greenLit {
|
||||
background-color: #0F0}
|
||||
|
||||
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 +148,7 @@ BUTTON#SPOBlank3Btn {
|
||||
.data {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
text-align: left}
|
||||
|
||||
|
||||
.number {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
text-align: right}
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
<div id=SPODiv>
|
||||
<iframe id=SPOUT scrolling=auto></iframe>
|
||||
<div id=SPOControlsDiv>
|
||||
<img id=TeletypeLogo src="TeletypeLogo.gif">
|
||||
<img id=TeletypeLogo src="TeletypeLogo.gif" alt="TeleType Model 33 KSR Logo">
|
||||
<button id=SPOReadyBtn class="yellowButton blackBorder">READY</button>
|
||||
<button id=SPOPowerBtn class="blackButton blackBorder">POWER</button>
|
||||
<button id=SPOPowerBtn class="greenButton blackBorder greenLit">POWER</button>
|
||||
<button id=SPORemoteBtn class="yellowButton blackBorder">REMOTE</button>
|
||||
<button id=SPOLocalBtn class="yellowButton blackBorder yellowLit">LOCAL</button>
|
||||
<button id=SPOInputRequestBtn class="yellowButton blackBorder">INPUT REQUEST</button>
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
/**************************************/
|
||||
function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
/* Constructor for the SPOUnit object */
|
||||
var that = this;
|
||||
|
||||
this.maxScrollLines = 500; // Maximum amount of printer scrollback
|
||||
this.charPeriod = 100; // Printer speed, milliseconds per character
|
||||
@@ -31,15 +30,11 @@ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
this.signal = signal; // external function to call for special signals (e.g,. SPO input request)
|
||||
|
||||
this.initiateStamp = 0; // timestamp of last initiation (set by IOUnit)
|
||||
this.inTimer = null; // input setTimeout() token
|
||||
this.outTimer = null; // output setTimeout() token
|
||||
this.inTimer = null; // input setCallback() token
|
||||
this.outTimer = null; // output setCallback() token
|
||||
|
||||
this.clear();
|
||||
|
||||
this.backspaceChar.that = this; // Store object context for these functions
|
||||
this.printChar.that = this;
|
||||
this.outputChar.that = this;
|
||||
|
||||
this.window = window.open("", mnemonic);
|
||||
if (this.window) {
|
||||
this.shutDown(); // destroy the previously-existing window
|
||||
@@ -49,10 +44,9 @@ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
this.paper = null;
|
||||
this.endOfPaper = null;
|
||||
this.window = window.open("/B5500/webUI/B5500SPOUnit.html", mnemonic,
|
||||
"scrollbars,resizable,width=600,height=500");
|
||||
this.window.addEventListener("load", function windowOnLoad() {
|
||||
that.spoOnload();
|
||||
}, false);
|
||||
"scrollbars,resizable,width=758,height=508");
|
||||
this.window.moveTo(screen.availWidth-this.window.outerWidth, screen.availHeight-this.window.outerHeight);
|
||||
this.window.addEventListener("load", B5500CentralControl.bindMethod(B5500SPOUnit.prototype.spoOnload, this), false);
|
||||
}
|
||||
|
||||
// this.spoState enumerations
|
||||
@@ -130,21 +124,20 @@ B5500SPOUnit.prototype.removeClass = function removeClass(e, name) {
|
||||
B5500SPOUnit.prototype.setLocal = function setLocal() {
|
||||
/* Sets the status of the SPO to Local */
|
||||
|
||||
if (this.spoState == this.spoRemote) {
|
||||
this.spoState = this.spoLocal;
|
||||
this.addClass(this.$$("SPOLocalBtn"), "yellowLit");
|
||||
this.removeClass(this.$$("SPORemoteBtn"), "yellowLit");
|
||||
this.removeClass(this.$$("SPOInputRequestBtn"), "yellowLit");
|
||||
this.statusChange(0);
|
||||
this.spoLocalRequested = false;
|
||||
this.spoState = this.spoLocal;
|
||||
this.addClass(this.$$("SPOLocalBtn"), "yellowLit");
|
||||
this.removeClass(this.$$("SPORemoteBtn"), "yellowLit");
|
||||
this.removeClass(this.$$("SPOInputRequestBtn"), "yellowLit");
|
||||
this.statusChange(0);
|
||||
|
||||
// Set up to echo characters from the keyboard
|
||||
this.buffer = null;
|
||||
this.bufLength = 0;
|
||||
this.bufIndex = 0;
|
||||
this.printCol = 0;
|
||||
this.nextCharTime = new Date().getTime();
|
||||
this.finish = null;
|
||||
}
|
||||
// Set up to echo characters from the keyboard
|
||||
this.buffer = null;
|
||||
this.bufLength = 0;
|
||||
this.bufIndex = 0;
|
||||
this.printCol = 0;
|
||||
this.nextCharTime = new Date().getTime();
|
||||
this.finish = null;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
@@ -177,14 +170,13 @@ B5500SPOUnit.prototype.appendEmptyLine = function appendEmptyLine() {
|
||||
/**************************************/
|
||||
B5500SPOUnit.prototype.backspaceChar = function backspaceChar() {
|
||||
/* Handles backspace for SPO input */
|
||||
var that = backspaceChar.that;
|
||||
var line = that.paper.lastChild;
|
||||
var line = this.paper.lastChild;
|
||||
|
||||
if (that.bufLength > 0) {
|
||||
that.bufIndex--;
|
||||
if (this.bufLength > 0) {
|
||||
this.bufIndex--;
|
||||
}
|
||||
if (that.printCol > 0) {
|
||||
that.printCol--;
|
||||
if (this.printCol > 0) {
|
||||
this.printCol--;
|
||||
}
|
||||
if (line.nodeValue.length > 0) {
|
||||
line.nodeValue = line.nodeValue.substring(0, line.nodeValue.length-1);
|
||||
@@ -194,8 +186,7 @@ B5500SPOUnit.prototype.backspaceChar = function backspaceChar() {
|
||||
/**************************************/
|
||||
B5500SPOUnit.prototype.printChar = function printChar(c) {
|
||||
/* Echoes the character code "c" to the SPO printer */
|
||||
var that = printChar.that;
|
||||
var line = that.paper.lastChild;
|
||||
var line = this.paper.lastChild;
|
||||
var len = line.nodeValue.length;
|
||||
|
||||
if (len < 1) {
|
||||
@@ -212,38 +203,35 @@ B5500SPOUnit.prototype.outputChar = function outputChar() {
|
||||
/* Outputs one character from the buffer to the SPO. If more characters remain
|
||||
to be printed, schedules itself 100 ms later to print the next one, otherwise
|
||||
calls finished(). If the column counter exceeds 72, a CR/LF pair is output.
|
||||
A CR/LF pair is also output at the end of the message. Note the use of the local
|
||||
function property "that" (initialized in the constructor), which supplies the
|
||||
necessary SPOUnit object context across setTimeout() calls */
|
||||
var that = outputChar.that; // retrieve our object context
|
||||
var nextTime = that.nextCharTime + that.charPeriod;
|
||||
A CR/LF pair is also output at the end of the message */
|
||||
var nextTime = this.nextCharTime + this.charPeriod;
|
||||
var delay = nextTime - new Date().getTime();
|
||||
|
||||
that.nextCharTime = nextTime;
|
||||
if (that.printCol < 72) { // print the character
|
||||
if (that.bufIndex < that.bufLength) {
|
||||
that.printChar(that.buffer[that.bufIndex]);
|
||||
that.bufIndex++;
|
||||
that.printCol++;
|
||||
this.outTimer = setTimeout(that.outputChar, delay);
|
||||
this.nextCharTime = nextTime;
|
||||
if (this.printCol < 72) { // print the character
|
||||
if (this.bufIndex < this.bufLength) {
|
||||
this.printChar(this.buffer[this.bufIndex]);
|
||||
this.bufIndex++;
|
||||
this.printCol++;
|
||||
this.outTimer = setCallback(this.outputChar, this, delay);
|
||||
} else { // set up for the final CR/LF
|
||||
that.printCol = 72;
|
||||
this.outTimer = setTimeout(that.outputChar, delay);
|
||||
this.printCol = 72;
|
||||
this.outTimer = setCallback(this.outputChar, this, delay);
|
||||
}
|
||||
} else if (that.printCol == 72) { // delay to fake the output of a carriage-return
|
||||
that.printCol++;
|
||||
this.outTimer = setTimeout(that.outputChar, delay+that.charPeriod);
|
||||
} else if (this.printCol == 72) { // delay to fake the output of a carriage-return
|
||||
this.printCol++;
|
||||
this.outTimer = setCallback(this.outputChar, this, delay+this.charPeriod);
|
||||
} else { // actually output the CR/LF
|
||||
that.appendEmptyLine();
|
||||
if (that.bufIndex < that.bufLength) {
|
||||
that.printCol = 0; // more characters to print after the CR/LF
|
||||
this.outTimer = setTimeout(that.outputChar, delay);
|
||||
this.appendEmptyLine();
|
||||
if (this.bufIndex < this.bufLength) {
|
||||
this.printCol = 0; // more characters to print after the CR/LF
|
||||
this.outTimer = setCallback(this.outputChar, this, delay);
|
||||
} else { // message text is exhausted
|
||||
that.finish(that.errorMask, that.bufLength); // report finish with any errors
|
||||
if (that.spoLocalRequested) {
|
||||
that.setLocal();
|
||||
this.finish(this.errorMask, this.bufLength); // report finish with any errors
|
||||
if (this.spoLocalRequested) {
|
||||
this.setLocal();
|
||||
} else {
|
||||
that.spoState = that.spoRemote;
|
||||
this.spoState = this.spoRemote;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,7 +239,7 @@ B5500SPOUnit.prototype.outputChar = function outputChar() {
|
||||
|
||||
/**************************************/
|
||||
B5500SPOUnit.prototype.terminateInput = function terminateInput() {
|
||||
/* Handles the End of Message event. Turns off then Input Request lamp, then
|
||||
/* Handles the End of Message event. Turns off the Ready lamp, then
|
||||
calls outputChar(), which will find bufIndex==bufLength, output a new-line,
|
||||
set the state to Remote, and call finish() for us. Slick, eh? */
|
||||
|
||||
@@ -268,12 +256,9 @@ B5500SPOUnit.prototype.cancelInput = function cancelInput() {
|
||||
/* Handles the Error message event. This is identical to terminateInput(),
|
||||
but it also sets a parity error so the input message will be rejected */
|
||||
|
||||
if (this.spoState = this.spoInput) {
|
||||
this.removeClass(this.$$("SPOReadyBtn"), "yellowLit");
|
||||
if (this.spoState == this.spoInput) {
|
||||
this.errorMask |= 0x10; // set parity/error-button bit
|
||||
this.bufLength = this.bufIndex;
|
||||
this.nextCharTime = new Date().getTime();
|
||||
this.outputChar();
|
||||
this.terminateInput();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -282,7 +267,6 @@ B5500SPOUnit.prototype.keyPress = function keyPress(ev) {
|
||||
/* Handles keyboard character events. Depending on the state of the unit,
|
||||
either buffers the character for transmission to the I/O Unit, simply echos
|
||||
it to the printer, or ignores it altogether */
|
||||
var that = this;
|
||||
var c = ev.charCode;
|
||||
var index = this.bufLength;
|
||||
var nextTime;
|
||||
@@ -300,27 +284,21 @@ B5500SPOUnit.prototype.keyPress = function keyPress(ev) {
|
||||
if (this.printCol < 72) {
|
||||
this.printCol++;
|
||||
}
|
||||
this.inTimer = setTimeout(function keyPressChar() {
|
||||
that.printChar(c);
|
||||
}, nextTime-stamp);
|
||||
this.inTimer = setCallback(this.printChar, this, nextTime-stamp, c);
|
||||
}
|
||||
if (c == 126) { // "~" (B5500 group-mark)
|
||||
c = this.keyFilter[c];
|
||||
if (this.printCol < 72) {
|
||||
this.printCol++;
|
||||
}
|
||||
this.inTimer = setTimeout(function keyPressGM() {
|
||||
that.printChar(c);
|
||||
}, nextTime-stamp);
|
||||
this.inTimer = setCallback(this.printChar, this, nextTime-stamp, c);
|
||||
this.nextCharTime = nextTime + this.charPeriod;
|
||||
this.terminateInput();
|
||||
}
|
||||
} else if (this.spoState == this.spoLocal) {
|
||||
if (c >= 32 && c <= 126) {
|
||||
c = this.keyFilter[c];
|
||||
this.inTimer = setTimeout(function keyPressLocalChar() {
|
||||
that.printChar(c);
|
||||
}, nextTime-stamp);
|
||||
this.inTimer = setCallback(this.printChar, this, nextTime-stamp, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,7 +308,6 @@ B5500SPOUnit.prototype.keyPress = function keyPress(ev) {
|
||||
/**************************************/
|
||||
B5500SPOUnit.prototype.keyDown = function keyDown(ev) {
|
||||
/* Handles key-down events to capture ESC, BS, and Enter keystrokes */
|
||||
var that = this;
|
||||
var c = ev.keyCode;
|
||||
var nextTime;
|
||||
var result = true;
|
||||
@@ -361,7 +338,7 @@ B5500SPOUnit.prototype.keyDown = function keyDown(ev) {
|
||||
switch (this.spoState) {
|
||||
case this.spoInput:
|
||||
case this.spoLocal:
|
||||
this.inTimer = setTimeout(this.backspaceChar, nextTime-stamp);
|
||||
this.inTimer = setCallback(this.backspaceChar, this, nextTime-stamp);
|
||||
this.nextCharTime = nextTime;
|
||||
result = false;
|
||||
break;
|
||||
@@ -375,9 +352,7 @@ B5500SPOUnit.prototype.keyDown = function keyDown(ev) {
|
||||
result = false;
|
||||
break
|
||||
case this.spoLocal:
|
||||
this.inTimer = setTimeout(function keyDownLocal() {
|
||||
that.appendEmptyLine();
|
||||
}, nextTime-stamp+this.charPeriod);
|
||||
this.inTimer = setCallback(this.appendEmptyLine, this, nextTime-stamp+this.charPeriod);
|
||||
this.nextCharTime = nextTime;
|
||||
result = false;
|
||||
break;
|
||||
@@ -424,7 +399,6 @@ B5500SPOUnit.prototype.beforeUnload = function beforeUnload(ev) {
|
||||
/**************************************/
|
||||
B5500SPOUnit.prototype.spoOnload = function spoOnload() {
|
||||
/* Initializes the SPO window and user interface */
|
||||
var that = this;
|
||||
var x;
|
||||
|
||||
this.doc = this.window.document;
|
||||
@@ -436,56 +410,47 @@ B5500SPOUnit.prototype.spoOnload = function spoOnload() {
|
||||
this.endOfPaper.appendChild(this.doc.createTextNode("\xA0"));
|
||||
this.$$("SPOUT").contentDocument.body.appendChild(this.endOfPaper);
|
||||
this.$$("SPOUT").contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #FFE} " +
|
||||
"PRE {margin: 0; font-size: 10pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"BODY {background-color: white} " +
|
||||
"PRE {margin: 0; font-size: 8pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
|
||||
this.window.resizeTo(this.window.outerWidth+this.$$("SPODiv").scrollWidth-this.window.innerWidth+8,
|
||||
this.window.outerHeight+this.$$("SPODiv").scrollHeight-this.window.innerHeight+8);
|
||||
this.window.moveTo(0, screen.availHeight-this.window.outerHeight);
|
||||
this.window.focus();
|
||||
|
||||
this.window.addEventListener("beforeunload", this.beforeUnload, false);
|
||||
|
||||
this.window.addEventListener("keypress", function windowKeyPress(ev) {
|
||||
that.keyPress(ev);
|
||||
}, false);
|
||||
this.window.addEventListener("keypress", B5500CentralControl.bindMethod(B5500SPOUnit.prototype.keyPress, this), false);
|
||||
|
||||
this.window.addEventListener("keydown", function windowKeyDown(ev) {
|
||||
that.keyDown(ev);
|
||||
}, false);
|
||||
this.window.addEventListener("keydown", B5500CentralControl.bindMethod(B5500SPOUnit.prototype.keyDown, this), false);
|
||||
|
||||
this.$$("SPORemoteBtn").addEventListener("click", function remoteClick() {
|
||||
that.setRemote();
|
||||
}, false);
|
||||
this.$$("SPORemoteBtn").addEventListener("click", B5500CentralControl.bindMethod(B5500SPOUnit.prototype.setRemote, this), false);
|
||||
|
||||
this.$$("SPOLocalBtn").addEventListener("click", function localClick() {
|
||||
that.setLocal();
|
||||
}, false);
|
||||
|
||||
this.$$("SPOInputRequestBtn").addEventListener("click", function inputRequestClick() {
|
||||
if (that.spoState == that.spoRemote || that.spoState == that.spoOutput) {
|
||||
that.addClass(that.$$("SPOInputRequestBtn"), "yellowLit");
|
||||
that.signal();
|
||||
this.$$("SPOLocalBtn").addEventListener("click", B5500CentralControl.bindMethod(function localClick() {
|
||||
if (this.spoState == this.spoRemote) {
|
||||
this.setLocal();
|
||||
} else {
|
||||
this.spoLocalRequested = true;
|
||||
}
|
||||
}, false);
|
||||
}, this), false);
|
||||
|
||||
this.$$("SPOErrorBtn").addEventListener("click", function errorClick() {
|
||||
that.cancelInput();
|
||||
}, false);
|
||||
this.$$("SPOInputRequestBtn").addEventListener("click", B5500CentralControl.bindMethod(function inputRequestClick() {
|
||||
if (this.spoState == this.spoRemote || this.spoState == this.spoOutput) {
|
||||
this.addClass(this.$$("SPOInputRequestBtn"), "yellowLit");
|
||||
this.signal();
|
||||
}
|
||||
}, this), false);
|
||||
|
||||
this.$$("SPOEndOfMessageBtn").addEventListener("click", function endOfMessageClick() {
|
||||
that.terminateInput();
|
||||
}, false);
|
||||
this.$$("SPOErrorBtn").addEventListener("click", B5500CentralControl.bindMethod(B5500SPOUnit.prototype.cancelInput, this), false);
|
||||
|
||||
this.$$("SPOEndOfMessageBtn").addEventListener("click", B5500CentralControl.bindMethod(B5500SPOUnit.prototype.terminateInput, this), false);
|
||||
|
||||
for (x=0; x<32; x++) {
|
||||
this.appendEmptyLine();
|
||||
}
|
||||
this.printText("retro-B5500 Emulator Version " + B5500CentralControl.version, function initComplete() {
|
||||
this.printText("retro-B5500 Emulator Version " + B5500CentralControl.version, B5500CentralControl.bindMethod(function initComplete() {
|
||||
this.window.focus();
|
||||
that.setRemote();
|
||||
that.appendEmptyLine();
|
||||
});
|
||||
this.setRemote();
|
||||
this.appendEmptyLine();
|
||||
}, this));
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
|
||||
166
webUI/B5500SetCallback.js
Normal file
166
webUI/B5500SetCallback.js
Normal file
@@ -0,0 +1,166 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/webUI B5500SetCallback.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2013, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 universal function call-back module.
|
||||
*
|
||||
* Implements a combination setTimeout() and setImmediate() facility for the
|
||||
* B5500 emulator web-based user interface. setCallback() is used the same way
|
||||
* that setTimeout() is used, except that for low values of the timeout parameter,
|
||||
* it merely yields control to any other pending events and timers before calling
|
||||
* the call-back function.
|
||||
*
|
||||
* This facility is needed because modern browsers implement a minimum delay
|
||||
* when calling setTimeout(). HTML5 specs require 4ms, but on Microsoft Windows
|
||||
* systems (at least through Win7), the minimum precision of setTimeout() is
|
||||
* about 15ms, unless you are running Google Chrome. This module will use
|
||||
* setTimeout() if the requested delay time is above a certain threshold, and
|
||||
* a setImmediate()-like mechanism (based on window.postMessage) if the requested
|
||||
* delay is above that threshold.
|
||||
*
|
||||
* Even though this mechanism may execute the call-back function sooner than the
|
||||
* requested delay specifies, the timing and throttling mechanisms in the
|
||||
* emulator will correct for that in subsequent delay cycles. We are going for
|
||||
* good average behavior, and quick call-backs are better than consistently
|
||||
* too-long callbacks in this environment, so that I/Os can be initiated and
|
||||
* their finish detected in finer-grained time increments.
|
||||
*
|
||||
* The SetCallback mechanism defines two functions, which become members of the
|
||||
* global (window) object:
|
||||
*
|
||||
* cookie = setCallback(fcn, context, delay, args...)
|
||||
*
|
||||
* Requests that the function "fcn" be called after "delay" milliseconds.
|
||||
* The function will be called as a method of "context", passing the
|
||||
* list of arguments "args...". The call-back "fcn" may be called
|
||||
* earlier or later than the specified delay. setCallBack returns a
|
||||
* numeric token identifying the call-back event, which can be used
|
||||
* with clearCallback(). Note that passing a string in lieu of a function
|
||||
* object is not permitted.
|
||||
*
|
||||
* clearCallBack(cookie)
|
||||
*
|
||||
* Cancels a pending call-back event, if in fact it is still pending.
|
||||
* The "cookie" parameter is a value returned from setCallback().
|
||||
*
|
||||
* This implementation has been inspired by Domenic Denicola's shim for the
|
||||
* setImmediate() API at https://github.com/NobleJS/setImmediate, and
|
||||
* David Baron's setZeroTimeout() implemenmentation described in his blog
|
||||
* at http://dbaron.org/log/20100309-faster-timeouts.
|
||||
*
|
||||
* Stole a little of their code, too.
|
||||
*
|
||||
************************************************************************
|
||||
* 2013-08-04 P.Kimpel
|
||||
* Original version, cloned from B5500DiskUnit.js.
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
(function (global) {
|
||||
/* Define a closure for the setCallback() mechanism */
|
||||
var minTimeout = 4; // minimum setTimeout() threshold, milliseconds
|
||||
var nextCookieNr = 1; // next setCallback cookie return value
|
||||
var pendingCallbacks = {}; // hash of pending callbacks, indexed by cookie as a string
|
||||
var secretPrefix = "com.google.code.p.retro-b5500.webUI." + new Date().getTime().toString(16);
|
||||
|
||||
/**************************************/
|
||||
function activateCallback(cookieName) {
|
||||
/* Activates a callback after its delay period has expired */
|
||||
var thisCallback;
|
||||
|
||||
if (cookieName in pendingCallbacks) {
|
||||
thisCallback = pendingCallbacks[cookieName];
|
||||
delete pendingCallbacks[cookieName];
|
||||
try {
|
||||
thisCallback.fcn.apply(thisCallback.context, thisCallback.args);
|
||||
} catch (err) {
|
||||
console.log("B5500SetCallback.activateCallback: " + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function clearCallback(cookie) {
|
||||
/* Disables a pending callback, if it still exists and is still pending */
|
||||
var cookieName = cookie.toString();
|
||||
var thisCallback;
|
||||
|
||||
if (cookieName in pendingCallbacks) {
|
||||
thisCallback = pendingCallbacks[cookieName];
|
||||
delete pendingCallbacks[cookieName];
|
||||
if (thisCallback.cancelToken) {
|
||||
if (thisCallback.type == 2) {
|
||||
global.clearTimeout(thisCallback.cancelToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function setCallback(fcn, context, callbackDelay, args) {
|
||||
/* Sets up and schedules a callback for function "fcn", called with context
|
||||
"context", after a delay of "delay" ms. Any "args" will be passed to "fcn".
|
||||
If the delay is less than "minTimeout", a setImmediate-like mechanism based on
|
||||
window.postsMessage() will be used; otherwise the environment's standard
|
||||
setTimeout mechanism will be used */
|
||||
var delay = callbackDelay || 0;
|
||||
var cookie = nextCookieNr++;
|
||||
var cookieName = cookie.toString();
|
||||
var thisCallback = {
|
||||
args: null,
|
||||
fcn: fcn,
|
||||
context: context || this,
|
||||
};
|
||||
|
||||
pendingCallbacks[cookieName] = thisCallback;
|
||||
if (arguments.length > 3) {
|
||||
thisCallback.args = Array.slice(arguments, 3);
|
||||
}
|
||||
|
||||
if (delay < minTimeout) {
|
||||
thisCallback.type = 1;
|
||||
global.postMessage(secretPrefix + cookieName, "*");
|
||||
} else {
|
||||
thisCallback.type = 2;
|
||||
thisCallback.cancelToken = global.setTimeout(activateCallback, delay, cookieName);
|
||||
}
|
||||
|
||||
return cookie;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function onMessage(ev) {
|
||||
/* Handler for the global.onmessage event. Activates the callback */
|
||||
var cookieName;
|
||||
var payload;
|
||||
|
||||
if (ev.source === global) {
|
||||
payload = ev.data.toString();
|
||||
if (payload.substring(0, secretPrefix.length) === secretPrefix) {
|
||||
cookieName = payload.substring(secretPrefix.length);
|
||||
activateCallback(cookieName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********** Outer block of anonymous closure **********/
|
||||
if (!global.setCallback && global.postMessage && !global.importScripts) {
|
||||
// Attach to the prototype of global, if possible, otherwise to global itself
|
||||
var attachee = global;
|
||||
|
||||
/*****
|
||||
if (typeof Object.getPrototypeOf === "function") {
|
||||
if ("setTimeout" in Object.getPrototypeOf(global)) {
|
||||
attachee = Object.getPrototypeOf(global);
|
||||
}
|
||||
}
|
||||
*****/
|
||||
|
||||
global.addEventListener("message", onMessage, false);
|
||||
attachee.setCallback = setCallback;
|
||||
attachee.clearCallback = clearCallback;
|
||||
}
|
||||
}(typeof global === "object" && global ? global : this));
|
||||
Reference in New Issue
Block a user