1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-04-25 20:01:52 +00:00

Commit version 1.03d:

1. Implement KEY IN DECK button for B5500CardReader to allow entry of ad-hoc card images.
2. Reduce default height of SPO and LinePrinter windows.
3. Clean up function definitions in B5500MagTapeDrive tape loader sub-window and unregister event handlers when sub-window closes.
This commit is contained in:
Paul Kimpel
2016-05-09 09:43:06 -07:00
parent 0fb010a79f
commit 252c5adfa1
9 changed files with 315 additions and 57 deletions

View File

@@ -61,7 +61,7 @@ function B5500CentralControl(global) {
/**************************************/
/* Global constants */
B5500CentralControl.version = "1.03c";
B5500CentralControl.version = "1.03d";
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)

View File

@@ -43,6 +43,11 @@
position: absolute;
top: 8px;
left: 212px}
#CRKeyinDeckBtn {
position: absolute;
top: 8px;
right: 8px}
#CRStackerDiv {
position: absolute;
@@ -76,3 +81,61 @@
width: 100%;
height: 35px;
border: 1px solid white}
/* Card deck keyin window */
#CRKeyinBody {
height: 100%;
min-height: 100%;
overflow: hidden;
padding: 0}
#CRKeyinDiv {
position: absolute;
top: 4px;
left: 4px;
right: 4px;
bottom: 4px;
padding: 8px}
#CRKeyinText {
position: absolute;
height: calc(100% - 60px);
width: calc(100% - 24px);
z-index: 1;
left: 8px;
top: 20px}
#CRKeyinControlDeckBtn {
position: absolute;
height: 20px;
width: 112px;
bottom: 8px;
left: 8px}
#CRKeyinEndControlBtn {
position: absolute;
height: 20px;
width: 112px;
bottom: 8px;
left: 130px}
#CRKeyinEndCardBtn {
position: absolute;
height: 20px;
bottom: 8px;
left: 250px}
#CRKeyinCancelBtn {
position: absolute;
height: 20px;
z-index: 2;
bottom: 8px;
right: 80px}
#CRKeyinInsertBtn {
position: absolute;
height: 20px;
z-index: 2;
bottom: 8px;
right: 8px}

View File

@@ -31,9 +31,11 @@
<div id=CRDiv class=devicePanel>
<button id=CRNotReadyLight class="whiteButton whiteLit">NOT<br>READY</button>
<button id=CRStartBtn class="greenButton">START</button>
<button id=CREOFBtn class="whiteButton">EOF</button>
<button id=CRStopBtn class="redButton">STOP</button>
<button id=CRStartBtn class="greenButton">START</button>
<button id=CRKeyinDeckBtn class="whiteButton whiteLit">KEY IN DECK</button>
<div id=CRStackerDiv>
<input id=CRFileSelector type=file size=60 multiple>

View File

@@ -32,6 +32,7 @@ function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal, o
this.clear();
this.doc = null;
this.keyinWindow = null;
this.window = window.open("../webUI/B5500CardReader.html", mnemonic,
"location=no,scrollbars=no,resizable,width=560,height=160,left=0,top="+x);
this.window.addEventListener("load",
@@ -78,6 +79,35 @@ B5500CardReader.prototype.$$ = function $$(e) {
return this.doc.getElementById(e);
};
/**************************************/
B5500CardReader.prototype.appendDeckText = function appendDeckText(text) {
/* Appends "text" to the card reader "input stacker" buffer, discards any
portion of the buffer that has already been read, and updates the hopper
progress bar */
if (this.bufIndex >= this.bufLength) {
this.buffer = text;
} else {
switch (this.buffer.charAt(this.buffer.length-1)) {
case "\r":
case "\n":
case "\f":
break; // do nothing -- the last card has a delimiter
default:
this.buffer += "\n"; // so the next deck starts on a new line
break;
}
this.buffer = this.buffer.substring(this.bufIndex) + text;
}
this.bufIndex = 0;
this.bufLength = this.buffer.length;
if (this.bufLength > 0) {
this.$$("CRHopperBar").value = this.bufLength;
this.$$("CRHopperBar").max = this.bufLength;
}
};
/**************************************/
B5500CardReader.prototype.setReaderReady = function setReaderReady(ready) {
/* Controls the ready-state of the card reader */
@@ -88,10 +118,14 @@ B5500CardReader.prototype.setReaderReady = function setReaderReady(ready) {
this.statusChange(1);
B5500Util.addClass(this.$$("CRStartBtn"), "greenLit")
B5500Util.removeClass(this.$$("CRNotReadyLight"), "whiteLit");
this.$$("CRKeyinDeckBtn").disabled = true;
B5500Util.removeClass(this.$$("CRKeyinDeckBtn"), "whiteLit");
} else {
this.statusChange(0);
B5500Util.removeClass(this.$$("CRStartBtn"), "greenLit")
B5500Util.addClass(this.$$("CRNotReadyLight"), "whiteLit");
this.$$("CRKeyinDeckBtn").disabled = false;
B5500Util.addClass(this.$$("CRKeyinDeckBtn"), "whiteLit");
}
};
@@ -138,6 +172,104 @@ B5500CardReader.prototype.CREOFBtn_onClick = function CREOFBtn_onClick(ev) {
this.armEOF(!this.eofArmed);
};
/**************************************/
B5500CardReader.prototype.CRKeyinDeckBtn_onClick = function CRKeyinDeckBtn_onClick(ev) {
/* Handler for the click event for the Insert Deck button on the reader window */
var cr = this; // this B5500CardReader instance
var $$$ = null; // getElementById shortcut for keyin window
var doc = null; // loader window.document
var keyinText = null; // keyin text area
var win = this.window.open("B5500CardReaderKeyin.html", this.mnemonic + "Keyin",
"location=no,scrollbars=no,resizable,width=640,height=240,left=" +
(this.window.screenX+32) +",top=" + (this.window.screenY+32));
function keyinCancelDeck(ev) {
/* Handler for the Cancel button on the deck keyin window -- closes it */
win.close();
}
function keyinInsertDeck(ev) {
/* Handler for the Insert buttons on the deck keyin window -- extracts the
text from the window and appends it to the reader's "input stacker" buffer */
switch (ev.target) {
case $$$("CRKeyinControlDeckBtn"):
keyinText.value += "?LABEL 0CONTROL0DECK\n";
keyinText.focus();
break;
case $$$("CRKeyinEndControlBtn"):
keyinText.value += "?END CONTROL\n";
keyinText.focus();
break;
case $$$("CRKeyinEndCardBtn"):
keyinText.value += "?END\n";
keyinText.focus();
break;
default:
cr.appendDeckText(keyinText.value);
win.close();
break;
} // switch ev.target
}
function keyinOnload(ev) {
/* On-load handler for the deck keyin window */
var de;
doc = win.document;
de = doc.documentElement;
$$$ = function $$$(id) {
return doc.getElementById(id);
};
doc.title = "B5500 " + cr.mnemonic + " Deck Keyin";
keyinText = $$$("CRKeyinText")
keyinText.focus();
$$$("CRKeyinControlDeckBtn").addEventListener("click", keyinInsertDeck, false);
$$$("CRKeyinEndControlBtn").addEventListener("click", keyinInsertDeck, false);
$$$("CRKeyinEndCardBtn").addEventListener("click", keyinInsertDeck, false);
$$$("CRKeyinInsertBtn").addEventListener("click", keyinInsertDeck, false);
$$$("CRKeyinCancelBtn").addEventListener("click", keyinCancelDeck, false);
win.addEventListener("unload", keyinOnUnload, false);
win.resizeBy(de.scrollWidth - win.innerWidth,
de.scrollHeight - win.innerHeight);
}
function keyinOnUnload(ev) {
/* On-unload handler for the deck keyin window */
$$$("CRKeyinControlDeckBtn").removeEventListener("click", keyinInsertDeck, false);
$$$("CRKeyinEndControlBtn").removeEventListener("click", keyinInsertDeck, false);
$$$("CRKeyinEndCardBtn").removeEventListener("click", keyinInsertDeck, false);
$$$("CRKeyinInsertBtn").removeEventListener("click", keyinInsertDeck, false);
$$$("CRKeyinCancelBtn").removeEventListener("click", keyinCancelDeck, false);
win.removeEventListener("load", keyinOnload, false);
win.removeEventListener("unload", keyinOnUnload, false);
keyinText = null;
cr.keyinWindow = null;
cr.$$("CRStartBtn").disabled = false;
cr.$$("CRKeyinDeckBtn").disabled = false;
B5500Util.addClass(cr.$$("CRKeyinDeckBtn"), "whiteLit");
}
// Outer block of loadTape
if (this.keyinWindow && !this.keyinWindow.closed) {
this.keyinWindow.close();
}
this.keyinWindow = win;
this.$$("CRStartBtn").disabled = true;
this.$$("CRKeyinDeckBtn").disabled = true;
B5500Util.removeClass(this.$$("CRKeyinDeckBtn"), "whiteLit");
win.addEventListener("load", keyinOnload, false);
};
/**************************************/
B5500CardReader.prototype.CRHopperBar_onClick = function CRHopperBar_onClick(ev) {
/* Handle the click event for the "input hopper" meter bar */
@@ -161,40 +293,30 @@ B5500CardReader.prototype.CRHopperBar_onClick = function CRHopperBar_onClick(ev)
B5500CardReader.prototype.fileSelector_onChange = function fileSelector_onChange(ev) {
/* Handle the <input type=file> onchange event when files are selected. For each
file, load it and add it to the "input hopper" of the reader */
var deck;
var f = ev.target.files;
var that = this;
var x;
var index = 0;
function fileLoader_onLoad(ev) {
/* Handle the onload event for a Text FileReader */
/* Handle the onload event for a Text FileReader and advances to the next
selected deck, if any */
if (that.bufIndex >= that.bufLength) {
that.buffer = ev.target.result;
} else {
switch (that.buffer.charAt(that.buffer.length-1)) {
case "\r":
case "\n":
case "\f":
break; // do nothing -- the last card has a delimiter
default:
that.buffer += "\n"; // so the next deck starts on a new line
break;
}
that.buffer = that.buffer.substring(that.bufIndex) + ev.target.result;
that.appendDeckText(ev.target.result);
if (++index < f.length) {
loadDeck(index);
}
that.bufIndex = 0;
that.bufLength = that.buffer.length;
that.$$("CRHopperBar").value = that.bufLength;
that.$$("CRHopperBar").max = that.bufLength;
}
for (x=f.length-1; x>=0; x--) {
function loadDeck(x) {
/* Initiates the load for the selected file indicated by "x" */
var deck;
deck = new FileReader();
deck.onload = fileLoader_onLoad;
deck.readAsText(f[x]);
}
loadDeck(index);
};
/**************************************/
@@ -325,6 +447,8 @@ B5500CardReader.prototype.readerOnload = function readerOnload() {
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRStopBtn_onClick), false);
this.$$("CREOFBtn").addEventListener("click",
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CREOFBtn_onClick), false);
this.$$("CRKeyinDeckBtn").addEventListener("click",
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRKeyinDeckBtn_onClick), false);
this.hopperBar.addEventListener("click",
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRHopperBar_onClick), false);

View File

@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>retro-B5500 Card Reader Keyin</title>
<!--
/***********************************************************************
* retro-b5500/emulator B5500CardReaderKeyin.html
************************************************************************
* Copyright (c) 2016, Nigel Williams and Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* B5500 emulator card reader peripheral keyin window.
*
* Defines a pop-up window with a text area from which a short card deck can
* be quickly keyed in and inserted at the end of the reader's "input stacker"
* buffer.
*
************************************************************************
* 2016-05-07 P.Kimpel
* Original version, from B5500System.Config.html.
***********************************************************************/
-->
<meta name="Author" content="Nigel Williams & Paul Kimpel">
<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="B5500Common.css">
<link id=keyinStyleSheet rel=stylesheet type="text/css" href="B5500CardReader.css">
</head>
<body id=CRKeyinBody class=deviceBody>
<div id=CRKeyinDiv class=devicePanel>
Enter card images and click <b>Insert</b> to add the images to the end of the input stacker:
<textarea id=CRKeyinText></textarea>
<button id=CRKeyinControlDeckBtn class="whiteButton whiteLit">?CONTROL/DECK</button>
<button id=CRKeyinEndControlBtn class="whiteButton whiteLit">?END CONTROL</button>
<button id=CRKeyinEndCardBtn class="whiteButton whiteLit">?END</button>
<button id=CRKeyinCancelBtn class="redButton">Cancel</button>
<button id=CRKeyinInsertBtn class="greenButton">Insert</button>
</div>
</body>
</html>

View File

@@ -18,7 +18,7 @@
/**************************************/
function B5500LinePrinter(mnemonic, unitIndex, designate, statusChange, signal, options) {
/* Constructor for the LinePrinter object */
var h = screen.availHeight*0.60;
var h = Math.max(screen.availHeight*0.33, 420);
var w = 900;
this.mnemonic = mnemonic; // Unit mnemonic

View File

@@ -589,8 +589,35 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() {
}
}
function tapeLoadOnload (ev) {
/* Driver for the tape loader window */
function tapeLoadCancelBtn(ev) {
/* Handler for the Cancel button */
file = null;
mt.$$("MTFileName").value = "";
win.close();
}
function tapeLoadFormatSelect(ev) {
/* Handler for the FormatSelect list */
tapeFormat = ev.target.value;
if (tapeFormat == "blank") {
file = null;
fileSelect.value = null;
writeRingCheck.checked = true;
tapeLengthSelect.disabled = false;
tapeLengthSelect.selectedIndex = tapeLengthSelect.length-1;
}
}
function tapeLoadWriteRingCheck(ev) {
/* Handler for the WriteRingCheck checkbox */
tapeLengthSelect.disabled = !ev.target.checked;
}
function tapeLoadOnload(ev) {
/* On-load handler for the tape loader window */
var de;
doc = win.document;
@@ -607,46 +634,39 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() {
doc.title = "B5500 " + mt.mnemonic + " Tape Loader";
fileSelect.addEventListener("change", fileSelector_onChange, false);
formatSelect.addEventListener("change", function loadFormatSelect(ev) {
tapeFormat = ev.target.value;
if (tapeFormat == "blank") {
file = null;
fileSelect.value = null;
writeRingCheck.checked = true;
tapeLengthSelect.disabled = false;
tapeLengthSelect.selectedIndex = tapeLengthSelect.length-1;
}
}, false);
writeRingCheck.addEventListener("click", function loadWriteRingCheck(ev) {
tapeLengthSelect.disabled = !ev.target.checked;
}, false);
formatSelect.addEventListener("change", tapeLoadFormatSelect, false);
writeRingCheck.addEventListener("click", tapeLoadWriteRingCheck, false);
$$$("MTLoadOKBtn").addEventListener("click", tapeLoadOK, false);
$$$("MTLoadCancelBtn").addEventListener("click", function loadCancelBtn(ev) {
file = null;
mt.$$("MTFileName").value = "";
win.close();
}, false);
$$$("MTLoadCancelBtn").addEventListener("click", tapeLoadCancelBtn, false);
win.addEventListener("unload", tapeLoadOnUnload, false);
win.resizeBy(de.scrollWidth - win.innerWidth,
de.scrollHeight - win.innerHeight);
}
function tapeLoadOnUnload(ev) {
/* On-unload handler for the tape loader window */
fileSelect.removeEventListener("change", fileSelector_onChange, false);
formatSelect.removeEventListener("change", tapeLoadFormatSelect, false);
writeRingCheck.removeEventListener("click", tapeLoadWriteRingCheck, false);
$$$("MTLoadOKBtn").removeEventListener("click", tapeLoadOK, false);
$$$("MTLoadCancelBtn").removeEventListener("click", tapeLoadCancelBtn, false);
win.removeEventListener("load", tapeLoadOnload, false);
win.removeEventListener("unload", tapeLoadOnUnload, false);
mt.loadWindow = null;
mt.$$("MTLoadBtn").disabled = (mt.tapeState != mt.tapeUnloaded);
}
// Outer block of loadTape
if (this.loadWindow && !this.loadWindow.closed) {
this.loadWindow.close();
}
this.loadWindow = win;
mt.$$("MTLoadBtn").disabled = true;
this.$$("MTLoadBtn").disabled = true;
win.addEventListener("load", tapeLoadOnload, false);
win.addEventListener("unload", function tapeLoadUnload(ev) {
this.loadWindow = null;
if (win.closed) {
mt.$$("MTLoadBtn").disabled = (mt.tapeState != mt.tapeUnloaded);
}
}, false);
};
/**************************************/
@@ -710,6 +730,7 @@ B5500MagTapeDrive.prototype.unloadTape = function unloadTape() {
/* Loads a status message into the "paper" rendering area, then calls
unloadDriver after a short wait to allow the message to appear */
win.removeEventListener("load", unloadSetup, false);
win.document.getElementById("Paper").appendChild(
win.document.createTextNode("Rendering tape image... please wait..."));
setTimeout(unloadDriver, 50);

View File

@@ -1,5 +1,5 @@
CACHE MANIFEST
# retro-B5500 emulator 1.03c, 2016-04-18 17:00
# retro-B5500 emulator 1.03d, 2016-05-09 09:30
CACHE:
../emulator/B5500CentralControl.js
@@ -12,6 +12,7 @@ B5500CardPunch.html
B5500CardPunch.js
B5500CardReader.css
B5500CardReader.html
B5500CardReaderKeyin.html
B5500CardReader.js
B5500ColdLoader.html
B5500Common.css

View File

@@ -19,6 +19,8 @@
/**************************************/
function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal, options) {
/* Constructor for the SPOUnit object */
var h = Math.max(screen.availHeight*0.33, 420);
var w = 688;
this.maxScrollLines = 5000; // Maximum amount of printer scrollback
this.charPeriod = 100; // Printer speed, milliseconds per character
@@ -41,7 +43,7 @@ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal, opti
this.inputBox = null;
this.endOfPaper = null;
this.window = window.open("../webUI/B5500SPOUnit.html", mnemonic,
"location=no,scrollbars=no,resizable,width=688,height=508");
"location=no,scrollbars=no,resizable,width=" + w + ",height=" + h);
this.window.addEventListener("load", B5500CentralControl.bindMethod(this,
B5500SPOUnit.prototype.spoOnload), false);
}