1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-04-30 13:42:18 +00:00

Emulator version 0.06:

Implement B5500CardReader peripheral device.
This commit is contained in:
paul.kimpel@digm.com
2013-06-15 12:17:05 +00:00
parent 0563664c73
commit 0071af88c8
17 changed files with 1043 additions and 139 deletions

99
webUI/B5500CardReader.css Normal file
View File

@@ -0,0 +1,99 @@
/***********************************************************************
* retro-b5500/emulator B5500CardReader.css
************************************************************************
* Copyright (c) 2013, Nigel Williams and Paul Kimpel.
* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* B5500 emulator Card Reader web interface style sheet.
************************************************************************
* 2013-06-09 P.Kimpel
* Original version, from B5500SPOUnit.css.
***********************************************************************/
BODY {
position: relative;
background-color: black;
margin: 4px}
DIV#CRDiv {
position: relative;
background-color: #666;
width: 280px;
height: 112px;
border: 1px solid black;
border-radius: 8px;
padding: 0;
vertical-align: top}
BUTTON.greenButton {
background-color: #060;
color: white;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: bold;
width: 60px;
height: 40px;
border: 1px solid #DDD;
border-radius: 4px}
BUTTON.blackButton {
background-color: black;
color: white;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: bold;
width: 60px;
height: 40px;
border: 1px solid #DDD;
border-radius: 4px}
BUTTON.redButton {
background-color: #900;
color: white;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: bold;
width: 60px;
height: 40px;
border: 1px solid #DDD;
border-radius: 4px}
BUTTON.greenLit {
background-color: green}
BUTTON.redLit {
background-color: #F00}
#CRNotReadyLight {
position: absolute;
top: 8px;
left: 8px}
#CREOFBtn {
position: absolute;
top: 8px;
left: 76px}
#CRStopBtn {
position: absolute;
top: 8px;
left: 144px}
#CRStartBtn {
position: absolute;
top: 8px;
left: 212px;}
#CRFileSelector {
position: absolute;
border: 1px solid white;
top: 56px;
left: 8px;
width: 120px}
#CRProgressBar {
position: absolute;
border: 1px solid white;
top: 84px;
left: 8px;
width: 262px}

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<head>
<title>B5500 Emulator Card Reader</title>
<meta name="Author" content="Nigel Williams & Paul Kimpel">
<!-- 2013-06-09 Original version, cloned from B5500SPOUnit.html -->
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<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="B5500CardReader.css">
</head>
<body>
<div id=CRDiv>
<button id=CRNotReadyLight class="redButton redLit">NOT READY</button>
<button id=CRStartBtn class="greenButton">START</button>
<button id=CREOFBtn class="redButton">EOF</button>
<button id=CRStopBtn class="redButton">STOP</button>
<input id=CRFileSelector type=file size=29>
<progress id=CRProgressBar min=0 max=100 value=0>
</div>
</body>
</html>

398
webUI/B5500CardReader.js Normal file
View File

@@ -0,0 +1,398 @@
/***********************************************************************
* retro-b5500/emulator B5500CardReader.js
************************************************************************
* Copyright (c) 2013, Nigel Williams and Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* B5500 Card Reader Peripheral Unit module.
*
* Defines a card reader peripheral unit type.
*
************************************************************************
* 2013-06-05 P.Kimpel
* Original version, from B5500SPOUnit.js.
***********************************************************************/
"use strict";
/**************************************/
function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal) {
/* Constructor for the CardReader object */
var that = this;
this.mnemonic = mnemonic; // Unit mnemonic
this.unitIndex = unitIndex; // Ready-mask bit number
this.designate = designate; // IOD unit designate number
this.statusChange = statusChange; // external function to call for ready-status change
this.signal = signal; // external function to call for special signals (e.g,. SPO input request)
this.clear();
this.window = window.open("", mnemonic);
if (this.window) {
this.window.close(); // destroy the previously-existing window
this.window = null;
}
this.doc = null;
this.window = window.open("/B5500/webUI/B5500CardReader.html", mnemonic,
"scrollbars=no,resizable,width=200,height=200");
this.window.onload = function() {
that.readerOnload();
};
}
B5500CardReader.prototype.eolRex = /([^\n\r\f]*)((:?\r[\n\f]?)|\n|\f)?/g;
B5500CardReader.prototype.cardsPerMinute = 800;
B5500CardReader.prototype.cardFilter = [ // Filter ASCII character values to valid BIC ones
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, // 00-0F
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, // 10-1F
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x3F,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, // 20-2F
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, // 30-3F
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, // 40-4F
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x3F,0x5D,0x3F,0x3F, // 50-5F
0x3F,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, // 60-6F
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x7B,0x7C,0x7D,0x7E,0x3F]; // 70-7F
/**************************************/
B5500CardReader.prototype.$$ = function $$(e) {
return this.doc.getElementById(e);
};
/**************************************/
B5500CardReader.prototype.clear = function clear() {
/* Initializes (and if necessary, creates) the reader unit state */
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
this.buffer = ""; // Card reader "input hopper"
this.bufLength = 0; // Current input buffer length (characters)
this.bufIndex = 0; // 0-relative offset to next "card" to be read
this.eofArmed = false; // EOF button: armed state
this.stopCount = 0; // stopCount for clearing the input buffer
};
/**************************************/
B5500CardReader.prototype.hasClass = function hasClass(e, name) {
/* returns true if element "e" has class "name" in its class list */
var classes = e.className;
if (!e) {
return false;
} else if (classes == name) {
return true;
} else {
return (classes.search("\\b" + name + "\\b") >= 0);
}
};
/**************************************/
B5500CardReader.prototype.addClass = function addClass(e, name) {
/* Adds a class "name" to the element "e"s class list */
if (!this.hasClass(e, name)) {
e.className += (" " + name);
}
};
/**************************************/
B5500CardReader.prototype.removeClass = function removeClass(e, name) {
/* Removes the class "name" from the element "e"s class list */
e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), "");
};
/**************************************/
B5500CardReader.prototype.setReaderReady = function setReaderReady(ready) {
/* Controls the ready-state of the card reader */
this.$$("CRFileSelector").disabled = ready;
this.ready = ready;
if (ready) {
this.statusChange(1);
this.removeClass(this.$$("CRNotReadyLight"), "redLit");
} else {
this.statusChange(0);
this.addClass(this.$$("CRNotReadyLight"), "redLit");
}
};
/**************************************/
B5500CardReader.prototype.armEOF = function armEOF(armed) {
/* Controls the arming/disarming of the EOF signal when starting with
an empty input hopper */
this.eofArmed = armed;
if (armed) {
this.addClass(this.$$("CREOFBtn"), "redLit");
} else {
this.removeClass(this.$$("CREOFBtn"), "redLit");
}
};
/**************************************/
B5500CardReader.prototype.CRStartBtn_onclick = function CRStartBtn_onclick(ev) {
/* Handle the click event for the START button */
var that = this;
if (!this.ready) {
this.stopCount = 0;
if (this.bufIndex < this.bufLength) {
this.setReaderReady(true);
}
}
};
/**************************************/
B5500CardReader.prototype.CRStopBtn_onclick = function CRStopBtn_onclick(ev) {
/* Handle the click event for the STOP button */
if (this.ready) {
this.setReaderReady(false);
} else if (this.eofArmed) {
this.armEOF(false);
} else if (this.bufIndex < this.bufLength) {
if (this.stopCount < 3) {
this.stopCount++;
} else {
if (confirm("Empty the " + this.mnemonic + " input hopper?")) {
this.stopCount = 0;
this.buffer = "";
this.bufLength = 0;
this.bufIndex = 0;
this.$$("CRProgressBar").value = 0;
}
}
}
};
/**************************************/
B5500CardReader.prototype.CREOFBtn_onclick = function CREOFBtn_onclick(ev) {
/* Handle the click event for the EOF button */
this.armEOF(!this.eofArmed);
};
/**************************************/
B5500CardReader.prototype.fileSelector_onChange = function fileSelector_onChange(ev) {
/* Handle the <input type=file> onchange event when a file is selected */
var f = ev.target.files[0];
var reader = new FileReader();
var that = this;
function fileLoader_onLoad(ev) {
/* Handle the onload event for a Text FileReader */
if (that.bufIndex < that.bufLength) {
that.buffer = that.buffer.substring(that.bufIndex) + ev.target.result;
} else {
that.buffer = ev.target.result;
}
that.bufIndex = 0;
that.bufLength = that.buffer.length;
that.$$("CRProgressBar").value = that.bufLength;
that.$$("CRProgressBar").max = that.bufLength;
}
/********************
alert("File selected: " + f.name +
"\nModified " + f.lastModifiedDate +
"\nType=" + f.type + ", Size=" + f.size + " octets");
********************/
reader.onload = fileLoader_onLoad;
reader.readAsText(f);
};
/**************************************/
B5500CardReader.prototype.readCardAlpha = function readCardAlpha(buffer, length) {
/* Reads one card image from the buffer in alpha mode; pads or trims the
image as necessary to the I/O buffer length. Invalid BCL characters are
translated to ASCII "?" and the invalid character bit is set in the errorMask */
var card; // card image
var cardLength; // length of card image
var match; // result of eolRex.exec()
var x; // for loop index
this.eolRex.lastIndex = this.bufIndex;
match = this.eolRex.exec(this.buffer);
if (!match) {
cardLength = 0;
} else {
this.bufIndex += match[0].length;
card = match[1];
cardLength = card.length;
if (length < cardLength) {
cardLength = length;
}
for (x=0; x<cardLength; x++) {
if ((buffer[x] = this.cardFilter[card.charCodeAt(x) & 0x7F]) == 0x3F) { // intentional assignment
this.errorMask |= 0x08;
}
}
}
while (cardLength < length) {
buffer[cardLength++] = 0x20; // pad with spaces
}
};
/**************************************/
B5500CardReader.prototype.readCardBinary = function readCardBinary(buffer, length) {
/* Reads one card image from the buffer in binary mode; pads or trims the
image as necessary to the I/O buffer length. Invalid BCL characters are
translated to ASCII "?", but are not reported in the errorMask */
var card; // card image
var cardLength; // length of card image
var match; // result of eolRex.exec()
var x; // for loop index
this.eolRex.lastIndex = this.bufIndex;
match = this.eolRex.exec(this.buffer);
if (!match) {
cardLength = 0;
} else {
this.bufIndex += match[0].length;
card = match[1];
cardLength = card.length;
if (length < cardLength) {
cardLength = length;
}
for (x=0; x<cardLength; x++) {
buffer[x] = this.cardFilter[card.charCodeAt(x) & 0x7F];
}
}
while (cardLength < length) {
buffer[cardLength++] = 0x30; // pad with ASCII zeroes
}
};
/**************************************/
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+8,
this.window.outerHeight+this.$$("CRDiv").scrollHeight-this.window.innerHeight+8);
this.armEOF(false);
this.setReaderReady(false);
this.$$("CRFileSelector").addEventListener("change", function(ev) {
that.fileSelector_onChange(ev);
}, false);
this.$$("CRStartBtn").addEventListener("click", function(ev) {
that.CRStartBtn_onclick(ev);
}, false);
this.$$("CRStopBtn").addEventListener("click", function(ev) {
that.CRStopBtn_onclick(ev);
}, false);
this.$$("CREOFBtn").addEventListener("click", function(ev) {
that.CREOFBtn_onclick(ev);
}, false);
};
/**************************************/
B5500CardReader.prototype.read = function read(finish, buffer, length, mode, control) {
/* Initiates a read operation on the unit. If the reader is not ready and the input
buffer is empty and EOF is armed , returns EOF; otherwise if not ready,
returns Not Ready */
var that = this;
this.errorMask = 0;
if (this.busy) {
finish(0x01, 0); // report unit busy
} else if (!this.ready) {
if (this.eofArmed && this.bufIndex >= this.bufLength) {
this.armEOF(false);
finish(0x24, 0); // report unit EOF + not ready
} else {
finish(0x04, 0); // report unit not ready
}
} else {
this.busy = true;
if (mode == 0) {
this.readCardAlpha(buffer, length);
} else {
this.readCardBinary(buffer, length);
}
if (this.bufIndex < this.bufLength) {
this.$$("CRProgressBar").value = this.bufLength-this.bufIndex;
} else {
this.$$("CRProgressBar").value = 0;
this.buffer = ""; // discard the input buffer
this.bufLength = 0;
this.bufIndex = 0;
this.setReaderReady(false);
}
setTimeout(function() {
that.busy = false;
finish(that.errorMask, length);
}, 60000/this.cardsPerMinute);
}
};
/**************************************/
B5500CardReader.prototype.space = function space(finish, length, control) {
/* Initiates a space operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500CardReader.prototype.write = function write(finish, buffer, length, mode, control) {
/* Initiates a write operation on the unit */
finish(0x04); // report unit not ready
};
/**************************************/
B5500CardReader.prototype.erase = function erase(finish, length) {
/* Initiates an erase operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500CardReader.prototype.rewind = function rewind(finish) {
/* Initiates a rewind operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500CardReader.prototype.readCheck = function readCheck(finish, length, control) {
/* Initiates a read check operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500CardReader.prototype.readInterrogate = function readInterrogate(finish, control) {
/* Initiates a read interrogate operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500CardReader.prototype.writeInterrogate = function writeInterrogate(finish, control) {
/* Initiates a write interrogate operation on the unit */
finish(0x04, 0); // report unit not ready
};

View File

@@ -10,6 +10,7 @@
<script src="./B5500DummyUnit.js"></script>
<script src="./B5500SPOUnit.js"></script>
<script src="./B5500DiskUnit.js"></script>
<script src="./B5500CardReader.js"></script>
<script src="../emulator/B5500SystemConfiguration.js"></script>
<script src="../emulator/B5500CentralControl.js"></script>

View File

@@ -27,75 +27,75 @@ function B5500DummyUnit(mnemonic, index, designate, statusChange, signal) {
this.designate = designate; // IOD unit designate number
this.statusChange = statusChange; // external function to call for ready-status change
this.signal = signal; // external function to call for special signals (e.g,. SPO input request)
this.clear();
}
/**************************************/
B5500DummyUnit.prototype.clear = function() {
B5500DummyUnit.prototype.clear = function clear() {
/* Initializes (and if necessary, creates) the processor state */
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
this.buffer = null; //
this.buffer = null; //
};
/**************************************/
B5500DummyUnit.prototype.read = function(finish, buffer, length, mode, control) {
B5500DummyUnit.prototype.read = function read(finish, buffer, length, mode, control) {
/* Initiates a read operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500DummyUnit.prototype.space = function(finish, length, control) {
B5500DummyUnit.prototype.space = function space(finish, length, control) {
/* Initiates a space operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500DummyUnit.prototype.write = function(finish, buffer, length, mode, control) {
B5500DummyUnit.prototype.write = function write(finish, buffer, length, mode, control) {
/* Initiates a write operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500DummyUnit.prototype.erase = function(finish, length) {
B5500DummyUnit.prototype.erase = function erase(finish, length) {
/* Initiates an erase operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500DummyUnit.prototype.rewind = function(finish) {
B5500DummyUnit.prototype.rewind = function rewind(finish) {
/* Initiates a rewind operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500DummyUnit.prototype.readCheck = function(finish, length, control) {
B5500DummyUnit.prototype.readCheck = function readCheck(finish, length, control) {
/* Initiates a read check operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500DummyUnit.prototype.readInterrogate = function(finish, control) {
B5500DummyUnit.prototype.readInterrogate = function readInterrogate(finish, control) {
/* Initiates a read interrogate operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500DummyUnit.prototype.writeInterrogate = function (finish, control) {
B5500DummyUnit.prototype.writeInterrogate = function writeInterrogate(finish, control) {
/* Initiates a write interrogate operation on the unit */
finish(0x04, 0); // report unit not ready
};

View File

@@ -1,8 +1,9 @@
<!DOCTYPE html>
<head>
<title>B5500 Emulator SPO Unit</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Nigel Williams & Paul Kimpel">
<!-- 2012-12-16 Original version, cloned from SPO prototype script -->
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<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">

View File

@@ -36,12 +36,13 @@ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) {
this.printChar.that = this;
this.outputChar.that = this;
this.window = window.open("", "SPOWin");
this.window = window.open("", mnemonic);
if (this.window) {
this.window.close(); // destroy the previously-existing window
this.window = null;
}
this.window = window.open("/B5500/webUI/B5500SPOUnit.html", "SPOWin", "scrollbars,resizable,width=600,height=500");
this.doc = null;
this.window = window.open("/B5500/webUI/B5500SPOUnit.html", mnemonic, "scrollbars,resizable,width=600,height=500");
this.window.onload = function() {
that.spoOnload();
};
@@ -54,7 +55,7 @@ B5500SPOUnit.prototype.spoRemote = 2;
B5500SPOUnit.prototype.spoInput = 3;
B5500SPOUnit.prototype.spoOutput = 4;
B5500SPOUnit.prototype.keyFilter = [ // Filter keyCode values to valid B5500 ones
B5500SPOUnit.prototype.keyFilter = [ // Filter keyCode values to valid BIC ones
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, // 00-0F
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, // 10-1F
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x3F,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, // 20-2F
@@ -65,11 +66,12 @@ B5500SPOUnit.prototype.keyFilter = [ // Filter keyCode values to vali
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x7B,0x7C,0x7D,0x7E,0x3F]; // 70-7F
/**************************************/
B5500SPOUnit.prototype.$$ = function(e) {
return this.doc.getElementById(e)};
B5500SPOUnit.prototype.$$ = function $$(e) {
return this.doc.getElementById(e);
};
/**************************************/
B5500SPOUnit.prototype.clear = function() {
B5500SPOUnit.prototype.clear = function clear() {
/* Initializes (and if necessary, creates) the SPO unit state */
this.ready = false; // ready status
@@ -89,7 +91,7 @@ B5500SPOUnit.prototype.clear = function() {
};
/**************************************/
B5500SPOUnit.prototype.hasClass = function(e, name) {
B5500SPOUnit.prototype.hasClass = function hasClass(e, name) {
/* returns true if element "e" has class "name" in its class list */
var classes = e.className;
@@ -103,7 +105,7 @@ B5500SPOUnit.prototype.hasClass = function(e, name) {
};
/**************************************/
B5500SPOUnit.prototype.addClass = function(e, name) {
B5500SPOUnit.prototype.addClass = function addClass(e, name) {
/* Adds a class "name" to the element "e"s class list */
if (!this.hasClass(e, name)) {
@@ -112,14 +114,14 @@ B5500SPOUnit.prototype.addClass = function(e, name) {
};
/**************************************/
B5500SPOUnit.prototype.removeClass = function(e, name) {
B5500SPOUnit.prototype.removeClass = function removeClass(e, name) {
/* Removes the class "name" from the element "e"s class list */
e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), "");
};
/**************************************/
B5500SPOUnit.prototype.setNotReady = function() {
B5500SPOUnit.prototype.setNotReady = function setNotReady() {
/* Sets the status of the SPO to Not Ready */
if (this.spoState == this.spoLocal) {
@@ -130,7 +132,7 @@ B5500SPOUnit.prototype.setNotReady = function() {
};
/**************************************/
B5500SPOUnit.prototype.setReady = function() {
B5500SPOUnit.prototype.setReady = function setReady() {
/* Sets the status of the SPO to Ready */
if (this.spoState == this.spoNotReady) {
@@ -140,7 +142,7 @@ B5500SPOUnit.prototype.setReady = function() {
};
/**************************************/
B5500SPOUnit.prototype.setLocal = function() {
B5500SPOUnit.prototype.setLocal = function setLocal() {
/* Sets the status of the SPO to Local */
if (this.spoState == this.spoRemote) {
@@ -160,7 +162,7 @@ B5500SPOUnit.prototype.setLocal = function() {
};
/**************************************/
B5500SPOUnit.prototype.setRemote = function() {
B5500SPOUnit.prototype.setRemote = function setRemote() {
/* Sets the status of the SPO to Remote */
if (this.spoState == this.spoLocal) {
@@ -172,7 +174,7 @@ B5500SPOUnit.prototype.setRemote = function() {
};
/**************************************/
B5500SPOUnit.prototype.appendEmptyLine = function() {
B5500SPOUnit.prototype.appendEmptyLine = function appendEmptyLine() {
/* Removes excess lines already printed, then appends a new <pre> element
to the <iframe>, creating an empty text node inside the new element */
var count = this.paper.childNodes.length;
@@ -259,7 +261,7 @@ B5500SPOUnit.prototype.outputChar = function outputChar() {
};
/**************************************/
B5500SPOUnit.prototype.terminateInput = function() {
B5500SPOUnit.prototype.terminateInput = function terminateInput() {
/* Handles the End of Message event. Turns off then Input Request 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? */
@@ -273,7 +275,7 @@ B5500SPOUnit.prototype.terminateInput = function() {
};
/**************************************/
B5500SPOUnit.prototype.cancelInput = function() {
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 */
@@ -287,7 +289,7 @@ B5500SPOUnit.prototype.cancelInput = function() {
};
/**************************************/
B5500SPOUnit.prototype.keyPress = function(ev) {
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 */
@@ -334,7 +336,7 @@ B5500SPOUnit.prototype.keyPress = function(ev) {
};
/**************************************/
B5500SPOUnit.prototype.keyDown = function(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;
@@ -392,7 +394,7 @@ B5500SPOUnit.prototype.keyDown = function(ev) {
};
/**************************************/
B5500SPOUnit.prototype.printText = function(msg, finish) {
B5500SPOUnit.prototype.printText = function printText(msg, finish) {
/* Utility function to convert a string to a Typed Array buffer and queue
it for printing. This is intended only for printing an initialization message
in Local state */
@@ -413,12 +415,13 @@ B5500SPOUnit.prototype.printText = function(msg, finish) {
};
/**************************************/
B5500SPOUnit.prototype.spoOnload = function() {
B5500SPOUnit.prototype.spoOnload = function spoOnload() {
/* Initializes the SPO window and user interface */
var that = this;
var x;
this.doc = this.window.document;
this.doc.title = "retro-B5500 " + this.mnemonic;
this.paper = this.$$("SPOUT").contentDocument.body;
this.$$("SPOUT").contentDocument.head.innerHTML += "<style>" +
"BODY {background-color: #FFE} " +
@@ -427,7 +430,7 @@ B5500SPOUnit.prototype.spoOnload = function() {
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.availWidth-this.window.outerWidth-8*/, screen.availHeight-this.window.outerHeight-8);
this.window.moveTo(0, screen.availHeight-this.window.outerHeight);
this.window.focus();
this.$$("SPORemoteBtn").onclick = function() {
@@ -479,7 +482,7 @@ B5500SPOUnit.prototype.spoOnload = function() {
};
/**************************************/
B5500SPOUnit.prototype.read = function(finish, buffer, length, mode, control) {
B5500SPOUnit.prototype.read = function read(finish, buffer, length, mode, control) {
/* Initiates a read operation on the unit */
this.errorMask = 0;
@@ -506,14 +509,14 @@ B5500SPOUnit.prototype.read = function(finish, buffer, length, mode, control) {
};
/**************************************/
B5500SPOUnit.prototype.space = function(finish, length, control) {
B5500SPOUnit.prototype.space = function space(finish, length, control) {
/* Initiates a space operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500SPOUnit.prototype.write = function(finish, buffer, length, mode, control) {
B5500SPOUnit.prototype.write = function write(finish, buffer, length, mode, control) {
/* Initiates a write operation on the unit */
this.errorMask = 0;
@@ -540,35 +543,35 @@ B5500SPOUnit.prototype.write = function(finish, buffer, length, mode, control) {
};
/**************************************/
B5500SPOUnit.prototype.erase = function(finish, length) {
B5500SPOUnit.prototype.erase = function erase(finish, length) {
/* Initiates an erase operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500SPOUnit.prototype.rewind = function(finish) {
B5500SPOUnit.prototype.rewind = function rewind(finish) {
/* Initiates a rewind operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500SPOUnit.prototype.readCheck = function(finish, length, control) {
B5500SPOUnit.prototype.readCheck = function readCheck(finish, length, control) {
/* Initiates a read check operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500SPOUnit.prototype.readInterrogate = function(finish, control) {
B5500SPOUnit.prototype.readInterrogate = function readInterrogate(finish, control) {
/* Initiates a read interrogate operation on the unit */
finish(0x04, 0); // report unit not ready
};
/**************************************/
B5500SPOUnit.prototype.writeInterrogate = function (finish, control) {
B5500SPOUnit.prototype.writeInterrogate = function writeInterrogate(finish, control) {
/* Initiates a write interrogate operation on the unit */
finish(0x04, 0); // report unit not ready

View File

@@ -10,6 +10,7 @@
<script src="/B5500/webUI/B5500DummyUnit.js"></script>
<script src="/B5500/webUI/B5500SPOUnit.js"></script>
<script src="/B5500/webUI/B5500DiskUnit.js"></script>
<script src="./B5500CardReader.js"></script>
<script src="/B5500/emulator/B5500SystemConfiguration.js"></script>
<script src="/B5500/emulator/B5500CentralControl.js"></script>

View File

@@ -0,0 +1,344 @@
<!DOCTYPE html>
<head>
<title>B5500 Card Reader Prototype</title>
<meta name="Author" content="Paul Kimpel">
<!-- 2013-06-08 Original version, cloned from tools/B5500LibMaintDecoder.html -->
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<style>
BUTTON.greenButton {
background-color: #060;
color: white;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: bold;
width: 60px;
height: 40px;
border: 1px solid #DDD;
border-radius: 4px}
BUTTON.blackButton {
background-color: black;
color: white;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: bold;
width: 60px;
height: 40px;
border: 1px solid #DDD;
border-radius: 4px}
BUTTON.redButton {
background-color: #900;
color: white;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: bold;
width: 60px;
height: 40px;
border: 1px solid #DDD;
border-radius: 4px}
BUTTON.greenLit {
background-color: green}
BUTTON.redLit {
background-color: #F00}
#CardReaderPanel {
position: relative;
background-color: #666;
width: 280px;
height: 112px;
border: 1px solid black;
border-radius: 8px;
padding: 0;
vertical-align: top}
#CRNotReadyLight {
position: absolute;
top: 8px;
left: 8px}
#CREOFBtn {
position: absolute;
top: 8px;
left: 76px}
#CRStopBtn {
position: absolute;
top: 8px;
left: 144px}
#CRStartBtn {
position: absolute;
top: 8px;
left: 212px;}
#CRFileSelector {
position: absolute;
top: 56px;
left: 8px;
width: 120px}
#CRProgressBar {
position: absolute;
top: 84px;
left: 8px;
width: 262px}
</style>
<script>
"use strict";
window.onload = function() {
var buffer = "";
var bufferLength = 0;
var bufferOffset = 0;
var eofArmed = 0;
var panel = $$("TextPanel");
var eolRex = /([^\n\r\f]*)((:?\r[\n\f]?)|\n|\f)?/g;
var blankCard = " "; // 80 spaces
var cardsPerMinute = 800;
var readerState = 0;
var readerNotReady = 0;
var readerReady = 1;
function $$(id) {
return document.getElementById(id);
}
function hasClass(e, name) {
/* returns true if element "e" has class "name" in its class list */
var classes = e.className;
if (!e) {
return false;
} else if (classes == name) {
return true;
} else {
return (classes.search("\\b" + name + "\\b") >= 0);
}
}
function addClass(e, name) {
/* Adds a class "name" to the element "e"s class list */
if (!hasClass(e, name)) {
e.className += (" " + name);
}
}
function removeClass(e, name) {
/* Removes the class "name" from the element "e"s class list */
e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), "");
}
function appendLine(panel, text) {
/* Appends "text"+NL as a new text node to the panel DOM element */
var e = document.createTextNode(text + "\n");
panel.appendChild(e);
}
function clearPanel(panel) {
/* Clears the text panel */
var kid;
while (kid = panel.firstChild) {
panel.removeChild(kid);
}
}
function setReaderReady(ready) {
/* Controls the ready-state of the card reader */
$$("CRFileSelector").disabled = ready;
if (ready) {
readerState = readerReady;
removeClass($$("CRNotReadyLight"), "redLit");
} else {
readerState = readerNotReady;
addClass($$("CRNotReadyLight"), "redLit");
}
}
function armEOF(armed) {
/* Controls the arming/disarming of the EOF signal when starting with
an empty input hopper */
if (armed) {
eofArmed = 1;
addClass($$("CREOFBtn"), "redLit");
} else {
eofArmed = 0;
removeClass($$("CREOFBtn"), "redLit");
}
}
function readACard(ev) {
/* Reads one card image from the buffer, pads or trims the image as
necessary to 80 columns, and displays it */
var bx = bufferOffset;
var card;
var cardLength;
var match;
if (bx >= bufferLength) {
setReaderReady(false);
$$("CRProgressBar").value = 0;
} else {
eolRex.lastIndex = bx;
match = eolRex.exec(buffer);
if (!match) {
card = blankCard;
} else {
bx += match[0].length;
card = match[1];
cardLength = card.length;
if (cardLength < 80) {
card += blankCard.substring(0, 80-cardLength);
} else if (cardLength > 80) {
card = card.substring(0, 80);
}
}
$$("CRProgressBar").value = bufferLength-bx;
appendLine(panel, card);
if (readerState == readerReady) {
setTimeout(readACard, 60000/cardsPerMinute);
}
}
bufferOffset = bx;
}
function CRStartBtn_onclick(ev) {
/* Handle the click event for the START button */
if (readerState != readerReady) {
if (bufferOffset >= bufferLength) {
//alert("Empty hopper.");
if (eofArmed) {
appendLine(panel, "\\\\\\\\\\ [EOF] /////");
armEOF(false);
}
} else {
setReaderReady(true);
setTimeout(readACard, 1000); // delay until the reader can come up to speed...
}
}
}
function CRStopBtn_onclick(ev) {
/* Handle the click event for the STOP button */
if (readerState == readerNotReady) {
armEOF(false);
} else if (readerState == readerReady) {
setReaderReady(false);
}
}
function CREOFBtn_onclick(ev) {
/* Handle the click event for the EOF button */
armEOF(!eofArmed);
}
function fileLoader_onLoad(ev) {
/* Handle the onload event for a Text FileReader */
if (bufferOffset < bufferLength) {
buffer = buffer.substring(bufferOffset);
} else {
clearPanel(panel);
buffer = "";
}
buffer += ev.target.result;
bufferOffset = 0;
bufferLength = buffer.length;
$$("CRProgressBar").value = buffer.length;
$$("CRProgressBar").max = buffer.length;
}
function fileSelector_onChange(ev) {
/* Handle the <input type=file> onchange event when a file is selected */
var f = ev.target.files[0];
var reader = new FileReader();
/********************
alert("File selected: " + f.name +
"\nModified " + f.lastModifiedDate +
"\nType=" + f.type + ", Size=" + f.size + " octets");
********************/
reader.onload = fileLoader_onLoad;
reader.readAsText(f);
}
function checkBrowser() {
/* Checks whether this browser can support the necessary stuff */
var missing = "";
if (!window.File) {missing += ", File"}
if (!window.FileReader) {missing += ", FileReader"}
if (!window.FileList) {missing += ", FileList"}
if (!window.Blob) {missing += ", Blob"}
if (!window.ArrayBuffer) {missing += ", ArrayBuffer"}
if (!window.DataView) {missing += ", DataView"}
if (missing.length == 0) {
return false;
} else {
alert("No can do... your browser does not support the following features:\n" + missing.substring(2));
return true;
}
}
/* Start of window.onload() */
if (checkBrowser()) {
return;
}
armEOF(false);
setReaderReady(false);
$$("CRFileSelector").addEventListener("change", fileSelector_onChange, false);
$$("CRStartBtn").addEventListener("click", CRStartBtn_onclick, false);
$$("CRStopBtn").addEventListener("click", CRStopBtn_onclick, false);
$$("CREOFBtn").addEventListener("click", CREOFBtn_onclick, false);
}
</script>
</head>
<body>
<div>
retro-B5500 Card Reader Prototype
</div>
<div id=CardReaderPanel>
<button id=CRNotReadyLight class="redButton redLit">NOT READY</button>
<button id=CRStartBtn class="greenButton">START</button>
<button id=CREOFBtn class="redButton">EOF</button>
<button id=CRStopBtn class="redButton">STOP</button>
<input id=CRFileSelector type=file size=29>
<progress id=CRProgressBar min=0 max=100 value=0>
</div>
<pre id=TextPanel>
</pre>
</body>
</html>

BIN
webUI/retro-Button-Logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

BIN
webUI/retro-Logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

View File

@@ -7,14 +7,15 @@
<meta http-equiv="Content-Style-Type" content="text/css">
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500DistributionAndDisplay.css">
<script src="./B5500DummyUnit.js"></script>
<script src="./B5500SPOUnit.js"></script>
<script src="./B5500DiskUnit.js"></script>
<script src="../B5500DummyUnit.js"></script>
<script src="../B5500SPOUnit.js"></script>
<script src="../B5500DiskUnit.js"></script>
<script src="../B5500CardReader.js"></script>
<script src="../emulator/emulator/B5500SystemConfiguration.js"></script>
<script src="../emulator/emulator/B5500CentralControl.js"></script>
<script src="../emulator/emulator/B5500Processor.js"></script>
<script src="../emulator/emulator/B5500IOUnit.js"></script>
<script src="../../emulator/emulator/B5500SystemConfiguration.js"></script>
<script src="../../emulator/emulator/B5500CentralControl.js"></script>
<script src="../../emulator/emulator/B5500Processor.js"></script>
<script src="../../emulator/emulator/B5500IOUnit.js"></script>
<script>
"use strict";

View File

@@ -7,14 +7,15 @@
<meta http-equiv="Content-Style-Type" content="text/css">
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500DistributionAndDisplay.css">
<script src="./B5500DummyUnit.js"></script>
<script src="./B5500SPOUnit.js"></script>
<script src="./B5500DiskUnit.js"></script>
<script src="../B5500DummyUnit.js"></script>
<script src="../B5500SPOUnit.js"></script>
<script src="../B5500DiskUnit.js"></script>
<script src="../B5500CardReader.js"></script>
<script src="../emulator/emulator/B5500SystemConfiguration.js"></script>
<script src="../emulator/emulator/B5500CentralControl.js"></script>
<script src="../emulator/emulator/B5500Processor.js"></script>
<script src="../emulator/emulator/B5500IOUnit.js"></script>
<script src="../../emulator/emulator/B5500SystemConfiguration.js"></script>
<script src="../../emulator/emulator/B5500CentralControl.js"></script>
<script src="../../emulator/emulator/B5500Processor.js"></script>
<script src="../../emulator/emulator/B5500IOUnit.js"></script>
<script>
"use strict";

View File

@@ -8,6 +8,8 @@
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500DistributionAndDisplay.css">
<script src="../B5500SPOUnit.js"></script>
<script src="../B5500DiskUnit.js"></script>
<script src="../B5500CardReader.js"></script>
<script src="../../emulator/B5500SystemConfiguration.js"></script>
<script src="../../emulator/B5500CentralControl.js"></script>
@@ -40,7 +42,7 @@ function testIt(e) {
cc.P1.step();
cc.P1.step();
cc.P1.step();
alert("Test completed");
}