mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-04-09 23:18:20 +00:00
Emulator version 0.06:
Implement B5500CardReader peripheral device.
This commit is contained in:
@@ -62,7 +62,7 @@ function B5500CentralControl() {
|
||||
/**************************************/
|
||||
/* Global constants */
|
||||
|
||||
B5500CentralControl.version = "0.05";
|
||||
B5500CentralControl.version = "0.06";
|
||||
|
||||
B5500CentralControl.rtcTick = 1000/60; // Real-time clock period, milliseconds
|
||||
|
||||
@@ -119,8 +119,8 @@ B5500CentralControl.unitSpecs = {
|
||||
SPO: {unitIndex: 22, designate: 30, unitClass: B5500SPOUnit},
|
||||
DKA: {unitIndex: 29, designate: 6, unitClass: B5500DiskUnit},
|
||||
DKB: {unitIndex: 28, designate: 12, unitClass: B5500DiskUnit},
|
||||
CRA: {unitIndex: 24, designate: 10, unitClass: null},
|
||||
CRB: {unitIndex: 23, designate: 14, unitClass: null},
|
||||
CRA: {unitIndex: 24, designate: 10, unitClass: B5500CardReader},
|
||||
CRB: {unitIndex: 23, designate: 14, unitClass: B5500CardReader},
|
||||
CPA: {unitIndex: 25, designate: 10, unitClass: null},
|
||||
LPA: {unitIndex: 27, designate: 22, unitClass: null},
|
||||
LPB: {unitIndex: 26, designate: 26, unitClass: null},
|
||||
@@ -150,7 +150,7 @@ B5500CentralControl.unitSpecs = {
|
||||
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.bindMethod = function(f, context) {
|
||||
B5500CentralControl.bindMethod = function bindMethod(f, context) {
|
||||
/* Returns a new function that binds the function "f" to the object "context".
|
||||
Note that this is a constructor property function, NOT an instance method of
|
||||
the CC object */
|
||||
@@ -159,7 +159,7 @@ B5500CentralControl.bindMethod = function(f, context) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.clear = function() {
|
||||
B5500CentralControl.prototype.clear = function clear() {
|
||||
/* Initializes (and if necessary, creates) the system and starts the
|
||||
real-time clock */
|
||||
|
||||
@@ -218,7 +218,7 @@ B5500CentralControl.prototype.clear = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.bit = function(word, bit) {
|
||||
B5500CentralControl.prototype.bit = function bit(word, bit) {
|
||||
/* Extracts and returns the specified bit from the word */
|
||||
var e = 47-bit; // word lower power exponent
|
||||
var p; // bottom portion of word power of 2
|
||||
@@ -231,7 +231,7 @@ B5500CentralControl.prototype.bit = function(word, bit) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.bitSet = function(word, bit) {
|
||||
B5500CentralControl.prototype.bitSet = function bitSet(word, bit) {
|
||||
/* Sets the specified bit in word and returns the updated word */
|
||||
var ue = 48-bit; // word upper power exponent
|
||||
var le = ue-1; // word lower power exponent
|
||||
@@ -245,7 +245,7 @@ B5500CentralControl.prototype.bitSet = function(word, bit) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.bitReset = function(word, bit) {
|
||||
B5500CentralControl.prototype.bitReset = function bitReset(word, bit) {
|
||||
/* Resets the specified bit in word and returns the updated word */
|
||||
var ue = 48-bit; // word upper power exponent
|
||||
var le = ue-1; // word lower power exponent
|
||||
@@ -258,7 +258,7 @@ B5500CentralControl.prototype.bitReset = function(word, bit) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.fieldIsolate = function(word, start, width) {
|
||||
B5500CentralControl.prototype.fieldIsolate = function fieldIsolate(word, start, width) {
|
||||
/* Extracts a bit field [start:width] from word and returns the field */
|
||||
var le = 48-start-width; // lower power exponent
|
||||
var p; // bottom portion of word power of 2
|
||||
@@ -269,7 +269,7 @@ B5500CentralControl.prototype.fieldIsolate = function(word, start, width) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.fieldInsert = function(word, start, width, value) {
|
||||
B5500CentralControl.prototype.fieldInsert = function fieldInsert(word, start, width, value) {
|
||||
/* Inserts a bit field from the low-order bits of value ([48-width:width])
|
||||
into word.[start:width] and returns the updated word */
|
||||
var ue = 48-start; // word upper power exponent
|
||||
@@ -284,7 +284,7 @@ B5500CentralControl.prototype.fieldInsert = function(word, start, width, value)
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.fieldTransfer = function(word, wstart, width, value, vstart) {
|
||||
B5500CentralControl.prototype.fieldTransfer = function fieldTransfer(word, wstart, width, value, vstart) {
|
||||
/* Inserts a bit field from value.[vstart:width] into word.[wstart:width] and
|
||||
returns the updated word */
|
||||
var ue = 48-wstart; // word upper power exponent
|
||||
@@ -304,7 +304,7 @@ B5500CentralControl.prototype.fieldTransfer = function(word, wstart, width, valu
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.fetch = function(acc) {
|
||||
B5500CentralControl.prototype.fetch = function fetch(acc) {
|
||||
/* Called by a requestor module passing accessor object "acc" to fetch a
|
||||
word from memory. */
|
||||
var addr = acc.addr;
|
||||
@@ -348,7 +348,7 @@ B5500CentralControl.prototype.fetch = function(acc) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.store = function(acc) {
|
||||
B5500CentralControl.prototype.store = function store(acc) {
|
||||
/* Called by requestor module passing accessor object "acc" to store a
|
||||
word into memory. */
|
||||
var addr = acc.addr;
|
||||
@@ -392,7 +392,7 @@ B5500CentralControl.prototype.store = function(acc) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.signalInterrupt = function() {
|
||||
B5500CentralControl.prototype.signalInterrupt = function signalInterrupt() {
|
||||
/* Called by all modules to signal that an interrupt has occurred and
|
||||
to invoke the interrupt prioritization mechanism. This will result in
|
||||
an updated vector address in the IAR. Can also be called to reprioritize
|
||||
@@ -430,7 +430,7 @@ B5500CentralControl.prototype.signalInterrupt = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.clearInterrupt = function() {
|
||||
B5500CentralControl.prototype.clearInterrupt = function clearInterrupt() {
|
||||
/* Resets an interrupt based on the current setting of this.IAR, then
|
||||
reprioritizes any remaining interrupts, leaving the new vector address
|
||||
in this.IAR. */
|
||||
@@ -555,7 +555,7 @@ B5500CentralControl.prototype.tock = function tock() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.haltP2 = function() {
|
||||
B5500CentralControl.prototype.haltP2 = function haltP2() {
|
||||
/* Called by P1 to halt P2. storeForInterrupt() will set P2BF=0 */
|
||||
|
||||
this.HP2F = 1;
|
||||
@@ -566,7 +566,7 @@ B5500CentralControl.prototype.haltP2 = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.initiateP2 = function() {
|
||||
B5500CentralControl.prototype.initiateP2 = function initiateP2() {
|
||||
/* Called by P1 to initiate P2. Assumes that an INCW has been stored at
|
||||
memory location @10. If P2 is busy or not present, sets the P2 busy
|
||||
interrupt. Otherwise, loads the INCW into P2's A register and initiates
|
||||
@@ -583,7 +583,7 @@ B5500CentralControl.prototype.initiateP2 = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.initiateIO = function() {
|
||||
B5500CentralControl.prototype.initiateIO = function initiateIO() {
|
||||
/* Selects an I/O unit and initiates an I/O */
|
||||
|
||||
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
|
||||
@@ -605,7 +605,7 @@ B5500CentralControl.prototype.initiateIO = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.interrogateIOChannel = function() {
|
||||
B5500CentralControl.prototype.interrogateIOChannel = function interrogateIOChannel() {
|
||||
/* Returns a value as for the processor TIO syllable indicating the first
|
||||
available and non-busy I/O Unit */
|
||||
|
||||
@@ -623,7 +623,7 @@ B5500CentralControl.prototype.interrogateIOChannel = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.interrogateUnitStatus = function() {
|
||||
B5500CentralControl.prototype.interrogateUnitStatus = function interrogateUnitStatus() {
|
||||
/* Returns a bitmask as for the processor TUS syllable indicating the
|
||||
ready status of all peripheral units */
|
||||
|
||||
@@ -631,7 +631,7 @@ B5500CentralControl.prototype.interrogateUnitStatus = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.testUnitReady = function(index) {
|
||||
B5500CentralControl.prototype.testUnitReady = function testUnitReady(index) {
|
||||
/* Determines whether the unit index "index" is currently in ready status.
|
||||
Returns 1 if ready, 0 if not ready */
|
||||
|
||||
@@ -639,7 +639,7 @@ B5500CentralControl.prototype.testUnitReady = function(index) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.testUnitBusy = function(index) {
|
||||
B5500CentralControl.prototype.testUnitBusy = function testUnitBusy(index) {
|
||||
/* Determines whether the unit index "index" is currently in use by any other
|
||||
I/O Unit. Returns 1 if busy, 0 if not busy */
|
||||
|
||||
@@ -647,7 +647,7 @@ B5500CentralControl.prototype.testUnitBusy = function(index) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.setUnitBusy = function(index, busy) {
|
||||
B5500CentralControl.prototype.setUnitBusy = function setUnitBusy(index, busy) {
|
||||
/* Sets or resets the unit-busy mask bit for unit index "index" */
|
||||
|
||||
if (index) {
|
||||
@@ -657,7 +657,7 @@ B5500CentralControl.prototype.setUnitBusy = function(index, busy) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.halt = function() {
|
||||
B5500CentralControl.prototype.halt = function halt() {
|
||||
/* Halts the processors. Any in-process I/Os are allowed to complete */
|
||||
|
||||
if (this.timer) {
|
||||
@@ -723,10 +723,10 @@ B5500CentralControl.prototype.loadComplete = function loadComplete(dontStart) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.load = function(dontStart) {
|
||||
B5500CentralControl.prototype.load = function load(dontStart) {
|
||||
/* Initiates a Load operation to start the system. If "dontStart" is truthy, then
|
||||
only the MCP bootstrap is loaded into memory -- P1 is not started */
|
||||
var boundLoadComplete = (function(that, dontStart) {
|
||||
var boundLoadComplete = (function boundLoadComplete(that, dontStart) {
|
||||
return function() {return that.loadComplete(dontStart)}
|
||||
})(this, dontStart);
|
||||
|
||||
@@ -754,7 +754,7 @@ B5500CentralControl.prototype.load = function(dontStart) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.loadTest = function(buf, loadAddr) {
|
||||
B5500CentralControl.prototype.loadTest = function loadTest(buf, loadAddr) {
|
||||
/* Loads a test codestream into memory starting at B5500 word address
|
||||
"loadAddr" from the ArrayBuffer "buf". Returns the number of B5500
|
||||
words loaded into memory. Note that when loading an ESPOL "DISK" file,
|
||||
@@ -809,7 +809,7 @@ B5500CentralControl.prototype.loadTest = function(buf, loadAddr) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.runTest = function(runAddr) {
|
||||
B5500CentralControl.prototype.runTest = function runTest(runAddr) {
|
||||
/* Executes a test program previously loaded by this.loadTest on processor
|
||||
P1. "runAddr" is the B5500 word address at which execution will begin
|
||||
(typically 0x10 [octal 20]) */
|
||||
@@ -822,7 +822,7 @@ B5500CentralControl.prototype.runTest = function(runAddr) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.configureSystem = function() {
|
||||
B5500CentralControl.prototype.configureSystem = function configureSystem() {
|
||||
/* Establishes the hardware module configuration from the
|
||||
B5500SystemConfiguration module */
|
||||
var cfg = B5500SystemConfiguration;
|
||||
@@ -834,7 +834,7 @@ B5500CentralControl.prototype.configureSystem = function() {
|
||||
var x;
|
||||
|
||||
function makeChange(cc, maskBit) {
|
||||
return function(ready) {
|
||||
return function statusChange(ready) {
|
||||
cc.unitStatusMask = (ready ? cc.bitSet(cc.unitStatusMask, maskBit)
|
||||
: cc.bitReset(cc.unitStatusMask, maskBit));
|
||||
};
|
||||
@@ -843,41 +843,41 @@ B5500CentralControl.prototype.configureSystem = function() {
|
||||
function makeSignal(cc, mnemonic) {
|
||||
switch (mnemonic) {
|
||||
case "SPO":
|
||||
return function() {
|
||||
return function signalSPO() {
|
||||
cc.CCI05F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
break;
|
||||
case "LPA":
|
||||
return function() {
|
||||
return function signalLPA() {
|
||||
cc.setUnitBusy(27, 0);
|
||||
cc.CCI06F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
break;
|
||||
case "LPB":
|
||||
return function() {
|
||||
return function signalLPB() {
|
||||
cc.setUnitBusy(26, 0);
|
||||
cc.CCI07F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
break;
|
||||
case "DKA":
|
||||
return function() {
|
||||
return function signalDKA() {
|
||||
cc.setUnitBusy(29, 0);
|
||||
cc.CCI15F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
break;
|
||||
case "DKB":
|
||||
return function() {
|
||||
return function signalDKB() {
|
||||
cc.setUnitBusy(28, 0);
|
||||
cc.CCI16F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
break;
|
||||
default:
|
||||
return function() {};
|
||||
return function signalDefault() {};
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -924,7 +924,7 @@ B5500CentralControl.prototype.configureSystem = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.powerOn = function() {
|
||||
B5500CentralControl.prototype.powerOn = function powerOn() {
|
||||
/* Powers up the system and establishes the hardware module configuration.
|
||||
Redundant power-ons are ignored. */
|
||||
|
||||
@@ -935,7 +935,7 @@ B5500CentralControl.prototype.powerOn = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.powerOff = function() {
|
||||
B5500CentralControl.prototype.powerOff = function powerOff() {
|
||||
/* Powers down the system and deallocates the hardware modules.
|
||||
Redundant power-offs are ignored. */
|
||||
var x;
|
||||
|
||||
@@ -63,6 +63,7 @@ function B5500IOUnit(ioUnitID, cc) {
|
||||
// Establish contexts for asynchronously-called methods
|
||||
this.boundForkIO = B5500CentralControl.bindMethod(this.forkIO, this);
|
||||
this.boundFinishGeneric = this.makeFinish(this.finishGeneric);
|
||||
this.boundFinishGenericRead = this.makeFinish(this.finishGenericRead);
|
||||
this.boundFinishBusy = this.makeFinish(this.finishBusy);
|
||||
this.boundFinishDiskRead = this.makeFinish(this.finishDiskRead);
|
||||
this.boundFinishSPORead = this.makeFinish(this.finishSPORead);
|
||||
@@ -132,7 +133,7 @@ B5500IOUnit.BCLANSItoBIC = [ // Index by 8-bit BCL-as-ANSI to get 6-b
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.clear = function() {
|
||||
B5500IOUnit.prototype.clear = function clear() {
|
||||
/* Initializes (and if necessary, creates) the I/O Unit state */
|
||||
|
||||
this.W = 0; // Memory buffer register
|
||||
@@ -187,7 +188,7 @@ B5500IOUnit.prototype.clear = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.clearD = function() {
|
||||
B5500IOUnit.prototype.clearD = function clearD() {
|
||||
/* Clears the D-register and the exploded field variables used internally */
|
||||
|
||||
this.D = 0;
|
||||
@@ -209,7 +210,7 @@ B5500IOUnit.prototype.clearD = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.fetch = function(addr) {
|
||||
B5500IOUnit.prototype.fetch = function fetch(addr) {
|
||||
/* Fetch a word from memory at address "addr" and leave it in the W register.
|
||||
Returns 1 if a memory access error occurred, 0 if no error */
|
||||
var acc = this.accessor; // get a local reference to the accessor object
|
||||
@@ -231,7 +232,7 @@ B5500IOUnit.prototype.fetch = function(addr) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.store = function(addr) {
|
||||
B5500IOUnit.prototype.store = function store(addr) {
|
||||
/* Store a word in memory at address "addr" from the W register.
|
||||
Returns 1 if a memory access error occurred, 0 if no error */
|
||||
var acc = this.accessor; // get a local reference to the accessor object
|
||||
@@ -250,7 +251,7 @@ B5500IOUnit.prototype.store = function(addr) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.fetchBuffer = function(mode, words) {
|
||||
B5500IOUnit.prototype.fetchBuffer = function fetchBuffer(mode, words) {
|
||||
/* Fetches words from memory starting at this.Daddress and coverts the
|
||||
BIC characters to ANSI or BCLANSI in this.buffer. "mode": 0=BCLANSI, 1=ANSI;
|
||||
"words": maximum number of words to transfer. At exit, updates this.Daddress
|
||||
@@ -300,7 +301,7 @@ B5500IOUnit.prototype.fetchBuffer = function(mode, words) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.fetchBufferWithGM = function(mode, words) {
|
||||
B5500IOUnit.prototype.fetchBufferWithGM = function fetchBufferWithGM(mode, words) {
|
||||
/* Fetches words from memory starting at this.Daddress and coverts the
|
||||
BIC characters to ANSI or BCLANSI in this.buffer. "mode": 0=BCLANSI, 1=ANSI;
|
||||
"words": maximum number of words to transfer. The transfer can be terminated
|
||||
@@ -356,7 +357,7 @@ B5500IOUnit.prototype.fetchBufferWithGM = function(mode, words) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.storeBuffer = function(chars, offset, mode, words) {
|
||||
B5500IOUnit.prototype.storeBuffer = function storeBuffer(chars, offset, mode, words) {
|
||||
/* Converts characters in this.buffer from ANSI or BCLANSI to BIC, assembles
|
||||
them into words, and stores the words into memory starting at this.Daddress.
|
||||
"chars": the number of characters to store, starting at "offset" in the buffer;
|
||||
@@ -428,7 +429,7 @@ B5500IOUnit.prototype.storeBuffer = function(chars, offset, mode, words) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.storeBufferWithGM = function(chars, offset, mode, words) {
|
||||
B5500IOUnit.prototype.storeBufferWithGM = function storeBufferWithGM(chars, offset, mode, words) {
|
||||
/* Converts characters in this.buffer from ANSI to BIC, assembles them into
|
||||
words, and stores the words into memory starting at this.Daddress.
|
||||
"chars": the number of characters to store, starting at "offset" in the buffer;
|
||||
@@ -507,7 +508,7 @@ B5500IOUnit.prototype.storeBufferWithGM = function(chars, offset, mode, words) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.finish = function () {
|
||||
B5500IOUnit.prototype.finish = function finish() {
|
||||
/* Called to finish an I/O operation on this I/O Unit. Constructs and stores
|
||||
the result descriptor, sets the appropriate I/O Finished interrupt in CC */
|
||||
|
||||
@@ -553,7 +554,7 @@ B5500IOUnit.prototype.finish = function () {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.makeFinish = function(f) {
|
||||
B5500IOUnit.prototype.makeFinish = function makeFinish(f) {
|
||||
/* Utility function to create a closure for I/O finish handlers */
|
||||
var that = this;
|
||||
|
||||
@@ -561,7 +562,7 @@ B5500IOUnit.prototype.makeFinish = function(f) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.decodeErrorMask = function(errorMask) {
|
||||
B5500IOUnit.prototype.decodeErrorMask = function decodeErrorMask(errorMask) {
|
||||
/* Decodes the errorMask returned by the device drivers and ORs it into
|
||||
the D-register error bits */
|
||||
|
||||
@@ -575,7 +576,7 @@ B5500IOUnit.prototype.decodeErrorMask = function(errorMask) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.finishBusy = function(errorMask, length) {
|
||||
B5500IOUnit.prototype.finishBusy = function finishBusy(errorMask, length) {
|
||||
/* Handles a generic I/O finish when no word-count update or input data
|
||||
transfer is needed, but leaves the unit marked as busy in CC. This is needed
|
||||
by device operations that have a separate completion signal, such as line
|
||||
@@ -587,7 +588,7 @@ B5500IOUnit.prototype.finishBusy = function(errorMask, length) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.finishGeneric = function(errorMask, length) {
|
||||
B5500IOUnit.prototype.finishGeneric = function finishGeneric(errorMask, length) {
|
||||
/* Handles a generic I/O finish when no word-count update or input data
|
||||
transfer is needed. Can also be used to apply common error mask posting
|
||||
at the end of specialized finish handlers. Note that this turns off the
|
||||
@@ -599,7 +600,16 @@ B5500IOUnit.prototype.finishGeneric = function(errorMask, length) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.finishSPORead = function(errorMask, length) {
|
||||
B5500IOUnit.prototype.finishGenericRead = function finishGenericRead(errorMask, length) {
|
||||
/* Handles a generic I/O finish when input data transfer, and optionally,
|
||||
word-count update, is needed. Note that this turns off the busyUnit mask bit in CC */
|
||||
|
||||
this.storeBuffer(length, 0, 1, (this.D23F ? this.DwordCount : 0x7FFF));
|
||||
this.finishGeneric(errorMask, length);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.finishSPORead = function finishSPORead(errorMask, length) {
|
||||
/* Handles I/O finish for a SPO keyboard input operation */
|
||||
|
||||
this.storeBufferWithGM(length, 0, 1, 0x7FFF);
|
||||
@@ -607,7 +617,7 @@ B5500IOUnit.prototype.finishSPORead = function(errorMask, length) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.finishDiskRead = function(errorMask, length) {
|
||||
B5500IOUnit.prototype.finishDiskRead = function finishDiskRead(errorMask, length) {
|
||||
/* Handles I/O finish for a DFCU data read operation */
|
||||
var segWords = Math.floor((length+7)/8);
|
||||
var memWords = (this.D23F ? this.DwordCount : segWords);
|
||||
@@ -620,7 +630,7 @@ B5500IOUnit.prototype.finishDiskRead = function(errorMask, length) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.initiateDiskIO = function(u) {
|
||||
B5500IOUnit.prototype.initiateDiskIO = function initiateDiskIO(u) {
|
||||
/* Initiates an I/O to the Disk File Control Unit. The disk address is fetched from
|
||||
the first word of the memory area and converted to binary for the DFCU module. Read
|
||||
check and interrogate operations are determined from their respective IOD bits. If
|
||||
@@ -678,7 +688,7 @@ B5500IOUnit.prototype.initiateDiskIO = function(u) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.initiatePrinterIO = function(u) {
|
||||
B5500IOUnit.prototype.initiatePrinterIO = function initiatePrinterIO(u) {
|
||||
/* Initiates an I/O to a Line Printer unit */
|
||||
var addr = this.Daddress; // initial data transfer address
|
||||
var cc; // carriage control value to driver
|
||||
@@ -766,12 +776,22 @@ B5500IOUnit.prototype.forkIO = function forkIO() {
|
||||
|
||||
// card #1 reader/punch
|
||||
case 10:
|
||||
this.D30F = 1; this.finish(); // >>> temp until implemented <<<
|
||||
if (this.D24F) { // CRA
|
||||
u.read(this.boundFinishGenericRead, this.buffer, (this.D21F ? 160 : 80), this.D21F, 0);
|
||||
} else { // CPA
|
||||
this.D30F = 1; // >>> temp until CPA implemented <<<
|
||||
this.finish();
|
||||
}
|
||||
break;
|
||||
|
||||
// card #2 reader
|
||||
case 14:
|
||||
this.D30F = 1; this.finish(); // >>> temp until implemented <<<
|
||||
if (this.D24F) {
|
||||
u.read(this.boundFinishGenericRead, this.buffer, (this.D21F ? 160 : 80), this.D21F, 0);
|
||||
} else {
|
||||
this.D30F = 1; // can't write to CRB, report as not ready
|
||||
this.finish();
|
||||
}
|
||||
break;
|
||||
|
||||
// SPO designate
|
||||
@@ -812,7 +832,7 @@ B5500IOUnit.prototype.forkIO = function forkIO() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.initiate = function() {
|
||||
B5500IOUnit.prototype.initiate = function initiate() {
|
||||
/* Initiates an I/O operation on this I/O Unit. When P1 executes an IIO instruction,
|
||||
it calls the CentralControl.initiateIO() function, which selects an idle I/O Unit and
|
||||
calls this function for that unit. Thus, at entry we are still running on top of the
|
||||
@@ -842,7 +862,7 @@ B5500IOUnit.prototype.initiate = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.initiateLoad = function(cardLoadSelect, loadComplete) {
|
||||
B5500IOUnit.prototype.initiateLoad = function initiateLoad(cardLoadSelect, loadComplete) {
|
||||
/* Initiates a hardware load operation on this I/O unit. "cardLoadSelect" is true
|
||||
if the load is to come from the card reader, otherwise it will come from sector 1
|
||||
of DKA EU0. "loadComplete" is called on completion of the I/O.
|
||||
@@ -850,10 +870,11 @@ B5500IOUnit.prototype.initiateLoad = function(cardLoadSelect, loadComplete) {
|
||||
pressed and released. Since there is no IOD in memory, we must generate one in the
|
||||
D register and initiate the I/O intrinsically. Note that if the I/O has an error,
|
||||
the RD is not stored and the I/O finish interrupt is not set in CC */
|
||||
var chars;
|
||||
var index;
|
||||
var u;
|
||||
|
||||
function finishDiskLoad(errorMask, length) {
|
||||
function finishLoad(errorMask, length) {
|
||||
var memWords = Math.floor((length+7)/8);
|
||||
|
||||
this.storeBuffer(length, 0, this.D21F, memWords);
|
||||
@@ -870,22 +891,28 @@ B5500IOUnit.prototype.initiateLoad = function(cardLoadSelect, loadComplete) {
|
||||
|
||||
this.clearD();
|
||||
if (cardLoadSelect) {
|
||||
alert("Card Load Select is not yet implemented");
|
||||
} else {
|
||||
this.D = 0x0600009F8010; // unit 6, read, 63 segs, addr @00020
|
||||
this.Dunit = 6; // 6=DKA
|
||||
this.D = 0x0A0004800010; // unit 10, read, binary mode, addr @00020
|
||||
this.Dunit = 10; // 10=CRA
|
||||
this.D24F = 1; // read
|
||||
chars = 20*8;
|
||||
} else {
|
||||
this.D = 0x0600009F8010; // unit 6, read, alpha mode, 63 segs, addr @00020
|
||||
this.Dunit = 6; // 6=DKA
|
||||
this.D21F = 0; // alpha mode
|
||||
this.LP = 63; // 63 sectors
|
||||
this.Daddress = 0x10; // memory address @20
|
||||
this.busyUnit = index = B5500CentralControl.unitIndex[this.D24F & 1][this.Dunit & 0x1F];
|
||||
if (this.cc.testUnitBusy(index)) {
|
||||
this.D32F = 1; // set unit busy error
|
||||
} else if (!this.cc.testUnitReady(index)) {
|
||||
this.D30F = 1; // set unit not-ready error
|
||||
} else {
|
||||
this.cc.setUnitBusy(index, 1);
|
||||
u = this.cc.unit[index];
|
||||
u.read(this.makeFinish(finishDiskLoad), this.buffer, 63*240, this.D21F, 1);
|
||||
}
|
||||
chars = 63*240;
|
||||
}
|
||||
|
||||
this.D24F = 1; // read
|
||||
this.Daddress = 0x10; // memory address @20
|
||||
this.busyUnit = index = B5500CentralControl.unitIndex[this.D24F & 1][this.Dunit & 0x1F];
|
||||
if (this.cc.testUnitBusy(index)) {
|
||||
this.D32F = 1; // set unit busy error
|
||||
} else if (!this.cc.testUnitReady(index)) {
|
||||
this.D30F = 1; // set unit not-ready error
|
||||
} else {
|
||||
this.cc.setUnitBusy(index, 1);
|
||||
u = this.cc.unit[index];
|
||||
u.read(this.makeFinish(finishLoad), this.buffer, chars, this.D21F, 1);
|
||||
}
|
||||
};
|
||||
@@ -41,7 +41,7 @@ var B5500SystemConfiguration = {
|
||||
SPO: true, // SPO keyboard/printer
|
||||
DKA: true, // Disk File Control A
|
||||
DKB: false, // Disk File Control B
|
||||
CRA: false, // Card Reader A
|
||||
CRA: true, // Card Reader A
|
||||
CRB: false, // Card Reader B
|
||||
CPA: false, // Card Punch A
|
||||
LPA: false, // Line Printer A
|
||||
|
||||
99
webUI/B5500CardReader.css
Normal file
99
webUI/B5500CardReader.css
Normal 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}
|
||||
26
webUI/B5500CardReader.html
Normal file
26
webUI/B5500CardReader.html
Normal 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
398
webUI/B5500CardReader.js
Normal 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
|
||||
};
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
344
webUI/prototypes/B5500CardReaderPrototype.html
Normal file
344
webUI/prototypes/B5500CardReaderPrototype.html
Normal 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
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
BIN
webUI/retro-Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 410 B |
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user