mirror of
https://github.com/pkimpel/retro-220.git
synced 2026-01-11 23:52:46 +00:00
1. Implement centralized pop-up window opening mechanism to enforce a delay between pop-up opens. This is to satisfy new restrictions on multiple pop-ups imposed by the Apple Safari 11.0 browser. 2. Correct Reload-Lockout behavior and format band 6 initialization in B220CardatronInput. 3. Correct translation of sign digits and skip-to-channel behavior in B220CardatronOutput. 4. Strip sign digit from search/scan argument word when storing into B220MagTapeControl T register. 5. Remove option for 1000-word system memory size and correct handling of memory size list selection in B220SystemConfig. 6. Change reel-to-reel magnetic tape name from DataReader to TSU in B220SystemConfig.
1055 lines
47 KiB
JavaScript
1055 lines
47 KiB
JavaScript
/***********************************************************************
|
||
* retro-220/webUI B220CardatronOutput.js
|
||
************************************************************************
|
||
* Copyright (c) 2017, Paul Kimpel.
|
||
* Licensed under the MIT License, see
|
||
* http://www.opensource.org/licenses/mit-license.php
|
||
************************************************************************
|
||
* Burroughs 220 Cardatron Output Unit module.
|
||
*
|
||
* Defines a line-printer/card-punch peripheral unit type.
|
||
*
|
||
************************************************************************
|
||
* 2017-05-19 P.Kimpel
|
||
* Original version, from retro-205 D105CardatronOutput.js.
|
||
***********************************************************************/
|
||
"use strict";
|
||
|
||
/**************************************/
|
||
function B220CardatronOutput(mnemonic, unitIndex, config) {
|
||
/* Constructor for the Cardatron Output object */
|
||
var h = screen.availHeight*0.25; // window height
|
||
var tks = B220CardatronOutput.trackSize;
|
||
var w; // window width
|
||
var x;
|
||
|
||
this.config = config;
|
||
this.isPrinter = (mnemonic.indexOf("LP") == 0);
|
||
// Whether printer (true) or punch (false)
|
||
this.lineWidth = (this.isPrinter ? 120 : 80);
|
||
this.linesPerMinute = (this.isPrinter ? 150 : 100);
|
||
// IBM 407=150 LPM, IBM 523=100 CPM
|
||
this.mnemonic = mnemonic; // Unit mnemonic
|
||
this.unitIndex = unitIndex; // Output unit number
|
||
|
||
this.timer = 0; // setCallback() token
|
||
this.useAlgolGlyphs = false; // output using special Algol chars
|
||
this.useGreenbar = false; // format "greenbar" shading on the paper (printer only)
|
||
this.lpi = 6; // lines/inch (actually, lines per greenbar group, should be even)
|
||
|
||
this.clear();
|
||
|
||
// Line buffer for assembling the print/punch line
|
||
this.lineBuffer = new Uint8Array(B220CardatronOutput.trackSize + 4);
|
||
|
||
// Buffer drum: information band is [0], format bands are [1]-[5]
|
||
this.bufferDrum = new ArrayBuffer(tks*6);
|
||
this.info = new Uint8Array(this.bufferDrum, 0, tks); // information band
|
||
this.formatBand = [
|
||
null, // no format band 0
|
||
new Uint8Array(this.bufferDrum, tks*1, tks), // format band 1
|
||
new Uint8Array(this.bufferDrum, tks*2, tks), // format band 2
|
||
new Uint8Array(this.bufferDrum, tks*3, tks), // format band 3
|
||
new Uint8Array(this.bufferDrum, tks*4, tks), // format band 4
|
||
new Uint8Array(this.bufferDrum, tks*5, tks)]; // format band 5
|
||
|
||
// Zero-Suppress controls
|
||
this.zsWindow = null; // handle for the tape loader window
|
||
this.zsCol = []; // list of 1-relative zero-suppress column numbers
|
||
|
||
// Device window
|
||
this.doc = null;
|
||
this.window = null;
|
||
this.barGroup = null; // current greenbar line group
|
||
this.supplyDoc = null; // the content document for the supply frame
|
||
this.supply = null; // the "paper" or "cards" we print/punch on
|
||
this.endOfSupply = null; // dummy element used to control scrolling
|
||
this.supplyMeter = null; // <meter> element showing amount of paper/card supply remaining
|
||
w = (this.isPrinter ? 790 : 608);
|
||
|
||
B220Util.openPopup(window, "../webUI/B220CardatronOutput.html", mnemonic,
|
||
"location=no,scrollbars,resizable,width=" + w + ",height=" + h +
|
||
",left=" + (screen.availWidth - w) +
|
||
",top=" + (screen.availHeight - h - (unitIndex-3)*32),
|
||
this, B220CardatronOutput.prototype.deviceOnLoad);
|
||
}
|
||
|
||
/**************************************/
|
||
|
||
B220CardatronOutput.prototype.maxSupplyLines = 150000; // maximum output scrollback (about a box of paper)
|
||
B220CardatronOutput.prototype.rtrimRex = /\s+$/; // regular expression for right-trimming lines
|
||
B220CardatronOutput.prototype.theColorGreen = "#CFC"; // for greenbar shading
|
||
|
||
B220CardatronOutput.trackSize = 319; // digits
|
||
B220CardatronOutput.drumTransferTime = 60000/21600;
|
||
// one drum rotation, about 2.78 ms
|
||
|
||
// Translate info band zone & numeric digits to ASCII character codes.
|
||
// See U.S. Patent 3,072,328, January 8, 1963, L.L. Bewley et al, Figure 2;
|
||
// and ElectroData Technical Newsletter #5 of February 14, 1958.
|
||
B220CardatronOutput.prototype.outputXlate = [
|
||
// 0 1 2 3 4 5 6 7 8 9 10 11 12
|
||
[0x20,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x20,0x23,0x40], // zone digit 0
|
||
[0x26,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x20,0x2E,0xA4], // zone digit 1
|
||
[0x2D,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x20,0x24,0x2A], // zone digit 2
|
||
[0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20], // zone digit 3
|
||
[0x30,0x2F,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x20,0x2C,0x25], // zone digit 4
|
||
[0x26,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x20,0x2E,0xA4], // zone digit 5
|
||
[0x2D,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x20,0x24,0x2A], // zone digit 6
|
||
[0x20,0x20,0x39,0x2E,0xA4,0xA4,0x2E,0xA4,0x20,0x20,0x20,0x2E,0xA4], // zone digit 7
|
||
[0x20,0x4A,0x49,0x24,0x2A,0x2A,0x24,0x2A,0x20,0x20,0x20,0x24,0x2A], // zone digit 8
|
||
[0x20,0x20,0x52,0x27,0x25,0x25,0x2C,0x25,0x20,0x20,0x20,0x27,0x25], // zone digit 9
|
||
[0x2D,0x20,0x52,0x20,0x20,0x40,0x23,0x40,0x20,0x20,0x20,0x20,0x20], // zone digit 10
|
||
[0x20,0x26,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20], // zone digit 11
|
||
[0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20]]; // zone digit 12
|
||
|
||
// Translate internal zone decades to buffer zone digits.
|
||
// Each row is indexed by the zone digit from the internal character code;
|
||
// each column is indexed by the PREVIOUS numeric digit from the character code.
|
||
// See U.S. Patent 3,072,328, January 8, 1963, L.L. Bewley et al, Figure 12;
|
||
// and ElectroData Technical Newsletter #5 of February 14, 1958.
|
||
B220CardatronOutput.prototype.zoneXlate = [ // numeric digit:0 1 2 3 4 5 6 7 8 9
|
||
//0 1 2 3 4 5 6 7 8 9 // = = = = = = = = = =
|
||
[ 0, 1, 7, 1, 7, 7, 7, 7, 0, 1], // zone digit 0: A 9 . <20> <20> . <20> 8 I
|
||
[ 1, 8, 8, 8, 8, 8, 8, 8, 1, 2], // zone digit 1: & J I $ * * $ * H R
|
||
[ 2, 4, 9, 4, 4, 9, 9, 9, 2, 4], // zone digit 2: - / R , % % , % Q Z
|
||
[10, 0, 10, 0, 0, 10, 10, 10, 2, 0], // zone digit 3: - 1 R # @ @ # @ Q 9
|
||
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // zone digit 4: & A B C D E F G H I
|
||
[ 6, 2, 2, 2, 2, 2, 2, 2, 2, 2], // zone digit 5: - J K L M N O P Q R
|
||
[ 4, 11, 4, 4, 4, 4, 4, 4, 4, 4], // zone digit 6: 0 & S T U V W X Y Z
|
||
[ 6, 2, 2, 2, 2, 2, 2, 2, 2, 2], // zone digit 7: - J K L M N O P Q R
|
||
[ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0], // zone digit 8: 0 1 2 3 4 5 6 7 8 9
|
||
[ 1, 2, 1, 2, 2, 2, 2, 2, 1, 2]]; // zone digit 9: & J B L M N O P H R
|
||
|
||
|
||
// Truthset for leading-zero suppression in output lines. A 1 indicates the
|
||
// character is to be replaced by a space; a 0 indicates a non-suppressable
|
||
// code and the end of leading-zero suppression.
|
||
B220CardatronOutput.prototype.zeroSuppressSet = [
|
||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00-0F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10-1F
|
||
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, // 20-2F
|
||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30-3F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-4F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 50-5F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60-6F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 70-7F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-8F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 90-9F
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A0-AF
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B0-BF
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C0-CF
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D0-DF
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E0-EF
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // F0-FF
|
||
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.clear = function clear() {
|
||
/* Initializes (and if necessary, creates) the reader unit state */
|
||
|
||
this.ready = false; // ready status
|
||
this.bufferReady = true; // buffer drum info band is ready to accept data from Processor
|
||
this.writeRequested = false; // Processor has initiated a write, waiting for buffer
|
||
this.togNumeric = false; // current digit came from zone (false) or numeric (true) punches
|
||
this.suppress12Mode = false; // suppresses 12 zones for sign digits
|
||
|
||
this.supplyLeft = this.maxSupplyLines; // lines/cards remaining in output supply
|
||
this.runoutSupplyCount = 0; // counter for triple-formfeed => rip paper/empty hopper
|
||
this.groupLinesLeft = 0; // lines remaining in current greenbar group
|
||
this.atTopOfForm = false; // start new page flag
|
||
this.pendingSpaceBefore = -1; // pending carriage control (eat the initial space-before)
|
||
|
||
this.pendingCall = null; // stashed pending function reference
|
||
this.pendingParams = null; // stashed pending function parameters
|
||
this.pendingFinish = null; // stashed pending signalFinished() reference
|
||
this.cDigit = 0; // stashed Tab Select relay digit
|
||
this.fDigit = 0; // stashed format band number
|
||
this.lastNumericDigit = 0; // last numeric digit encountered
|
||
this.infoIndex = 0; // 0-relative offset into info band on drum
|
||
this.selectedFormat = 0; // currently-selected format band
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.$$ = function $$(e) {
|
||
return this.doc.getElementById(e);
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.setFormatSelectLamps = function setFormatSelectLamps(format) {
|
||
/* Sets the FS lamps on the panel from the low-order three bits of "format" */
|
||
|
||
this.formatSelect1Lamp.set(format & 0x01);
|
||
this.formatSelect2Lamp.set((format >>> 1) & 0x01);
|
||
this.formatSelect4Lamp.set((format >>> 2) & 0x01);
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.clearInfoBand = function clearInfoBand() {
|
||
/* Clears the entire info band to zeroes */
|
||
var x;
|
||
|
||
this.infoIndex = 0; // restart at the beginning of the format band
|
||
for (x=this.info.length-1; x>=0; --x) {
|
||
this.info[x] = 0;
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.ClearBtn_onClick = function ClearBtn_onClick(ev) {
|
||
/* Handle the click event for the CLEAR button */
|
||
|
||
this.clearUnit();
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.setDeviceReady = function setDeviceReady(ready) {
|
||
/* Controls the ready-state of the printer/punch */
|
||
|
||
this.runoutSupplyCount = 0;
|
||
if (ready && !this.ready) {
|
||
B220Util.addClass(this.$$("COStartBtn"), "greenLit")
|
||
B220Util.removeClass(this.$$("COStopBtn"), "redLit");
|
||
this.ready = true;
|
||
} else if (!ready && this.ready) {
|
||
B220Util.removeClass(this.$$("COStartBtn"), "greenLit")
|
||
B220Util.addClass(this.$$("COStopBtn"), "redLit");
|
||
this.ready = false;
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.runoutSupply = function runoutSupply(ev) {
|
||
/* Handles an event to clear the supply from the printer/punch */
|
||
|
||
this.runoutSupplyCount = 0;
|
||
B220Util.removeClass(this.$$("COEndOfSupplyBtn"), "redLit");
|
||
this.supplyMeter.value = this.supplyLeft = this.maxSupplyLines;
|
||
this.groupLinesLeft = 0;
|
||
while (this.supply.firstChild) {
|
||
this.supply.removeChild(this.supply.firstChild);
|
||
}
|
||
if (!this.isPrinter) {
|
||
this.barGroup = this.doc.createElement("pre");
|
||
this.barGroup.className = "paper";
|
||
this.supply.appendChild(this.barGroup);
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.copySupply = function copySupply(ev) {
|
||
/* Copies the text contents of the "paper" area of the device, opens a new
|
||
temporary window, and pastes that text into the window so it can be copied
|
||
or saved by the user */
|
||
var barGroup = this.supply.firstChild;
|
||
var text = "";
|
||
var title = "B220 " + this.mnemonic + " Text Snapshot";
|
||
|
||
while (barGroup) {
|
||
text += barGroup.textContent + "\n";
|
||
barGroup = barGroup.nextSibling;
|
||
}
|
||
|
||
B220Util.openPopup(this.window, "./B220FramePaper.html", this.mnemonic + "-Snapshot",
|
||
"scrollbars,resizable,width=500,height=500",
|
||
this, function(ev) {
|
||
var doc = ev.target;
|
||
var win = doc.defaultView;
|
||
|
||
doc.title = title;
|
||
win.moveTo((screen.availWidth-win.outerWidth)/2, (screen.availHeight-win.outerHeight)/2);
|
||
doc.getElementById("Paper").textContent = text;
|
||
});
|
||
|
||
this.runoutSupply();
|
||
ev.preventDefault();
|
||
ev.stopPropagation();
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.appendLine = function appendLine(text) {
|
||
/* Appends one line, with a trailing new-line character, to the current
|
||
greenbar group, this.barGroup. This handles top-of-form and greenbar
|
||
highlighting */
|
||
var feed = "\n";
|
||
var skip = "";
|
||
|
||
if (this.isPrinter) {
|
||
if (this.groupLinesLeft <= 0) {
|
||
// Start the green half of a greenbar group
|
||
this.barGroup = this.doc.createElement("div");
|
||
this.supply.appendChild(this.barGroup);
|
||
this.groupLinesLeft = this.lpi;
|
||
if (!this.atTopOfForm) {
|
||
this.barGroup.className = "paper greenBar";
|
||
} else {
|
||
skip = "\f"; // prepend a form-feed to the line
|
||
this.atTopOfForm = false;
|
||
this.barGroup.className = "paper greenBar topOfForm";
|
||
}
|
||
} else if (this.groupLinesLeft*2 == this.lpi) {
|
||
// Start the white half of a greenbar group
|
||
this.barGroup = this.doc.createElement("div");
|
||
this.supply.appendChild(this.barGroup);
|
||
this.barGroup.className = "paper whiteBar";
|
||
} else if (this.groupLinesLeft == 1) {
|
||
feed = ""; // no linefeed at end of a bar group
|
||
} else if ((this.groupLinesLeft-1)*2 == this.lpi) {
|
||
feed = ""; // ditto
|
||
}
|
||
}
|
||
|
||
this.barGroup.appendChild(this.doc.createTextNode(skip + text + feed));
|
||
--this.groupLinesLeft;
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.skipToChannel = function skipToChannel() {
|
||
/* Finishes the current page and sets up for top-of-form formatting on the
|
||
next line printed. Adjusts the supply of forms left */
|
||
var lines = 0;
|
||
|
||
while(this.groupLinesLeft > 0) {
|
||
++lines;
|
||
this.appendLine("\xA0");
|
||
}
|
||
|
||
this.atTopOfForm = true;
|
||
this.supplyMeter.value = this.supplyLeft -= lines;
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.printLine = function printLine(text, spaceBefore) {
|
||
/* Prints one line to the output, handling carriage control and greenbar
|
||
group completion. For now, SPACE 0 (overprinting) is treated as single-spacing */
|
||
var lines = spaceBefore;
|
||
|
||
while (lines > 1) { // space before print
|
||
--lines;
|
||
--this.supplyLeft;
|
||
this.appendLine("\xA0");
|
||
}
|
||
|
||
this.appendLine(text || "\xA0");
|
||
if (this.supplyLeft > 0) {
|
||
this.supplyMeter.value = this.supplyLeft -= 1;
|
||
} else {
|
||
this.setDeviceReady(false);
|
||
B220Util.addClass(this.$$("COEndOfSupplyBtn"), "redLit");
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.finishWrite = function finishWrite() {
|
||
/* Callback function activated after a line is printed/punched to set the
|
||
buffer ready and reinitiate any pending write */
|
||
|
||
this.bufferReady = true;
|
||
this.startMachineLamp.set(0);
|
||
this.setFormatSelectLamps(0);
|
||
if (this.writeRequested) {
|
||
this.writeRequested = false;
|
||
this.pendingCall.apply(this, this.pendingParams);
|
||
this.pendingCall = null;
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.initiateWrite = function initiateWrite() {
|
||
/* Initiate formatting of the output line/card from the buffer drum and
|
||
writing it to the output device. If zero-suppression has been configured,
|
||
step through the list of zero-suppression starting columns and replace any
|
||
suppressable leading characters in each field */
|
||
var band = this.formatBand[this.selectedFormat];
|
||
var fmax = band.length; // max info/format band index
|
||
var info = this.info; // local reference to info band
|
||
var lastNumeric = 0; // last numeric digit
|
||
var line; // ASCII line image
|
||
var lx = this.lineBuffer.length; // line image character index: start at end
|
||
var nu = true; // numeric toggle: start as numeric
|
||
var x = 0; // info/format band digit index
|
||
var z; // zero-suppress list index
|
||
var zLen = this.zsCol.length; // length of zsCol[]
|
||
var zNext; // 0-relative column index of next zero-suppress field
|
||
|
||
if (this.ready) {
|
||
this.startMachineLamp.set(1);
|
||
|
||
// Map buffer drum digits to ASCII character codes
|
||
for (x=0; x<fmax; ++x) {
|
||
switch (band[x]) {
|
||
case 0: // insert zero digit
|
||
if (nu) {
|
||
nu = false;
|
||
lastNumeric = 0;
|
||
} else {
|
||
nu = true;
|
||
this.lineBuffer[--lx] = this.outputXlate[0][lastNumeric];
|
||
}
|
||
break;
|
||
case 1: // translate alphanumerically
|
||
if (nu) {
|
||
nu = false;
|
||
lastNumeric = info[x];
|
||
} else {
|
||
nu = true;
|
||
this.lineBuffer[--lx] = this.outputXlate[info[x]][lastNumeric];
|
||
}
|
||
break;
|
||
case 2: // translate numerically
|
||
nu = true;
|
||
this.lineBuffer[--lx] = (lastNumeric = info[x]) + 0x30;
|
||
break;
|
||
default: // (3) delete info band digit
|
||
break;
|
||
} // switch band[x]
|
||
} // for x
|
||
|
||
// Apply zero suppression, if configured
|
||
if (zLen) {
|
||
z = 0;
|
||
zNext = lx + this.zsCol[0] - 1; // compute first 0-relative starting index
|
||
do {
|
||
x = zNext; // set the buffer starting index
|
||
++z;
|
||
if (z < zLen) {
|
||
zNext = lx + this.zsCol[z] - 1; // set the next starting index
|
||
} else {
|
||
zNext = this.lineBuffer.length; // set to end of buffer
|
||
}
|
||
|
||
for (; x<zNext; ++x) {
|
||
if (this.zeroSuppressSet[this.lineBuffer[x]]) {
|
||
this.lineBuffer[x] = 0x20; // convert to a leading space
|
||
} else {
|
||
break; // end zero suppression for this field
|
||
}
|
||
}
|
||
} while (z < zLen);
|
||
}
|
||
|
||
// Convert to ASCII line image and determine carriage control
|
||
line = String.fromCharCode.apply(null, this.lineBuffer.subarray(lx, this.lineWidth+lx));
|
||
if (this.useAlgolGlyphs) {
|
||
line = B220Util.xlateASCIIToAlgol(line.replace(this.rtrimRex, ''));
|
||
} else {
|
||
line = line.replace(this.rtrimRex, '');
|
||
}
|
||
switch (this.cDigit) {
|
||
case 1: // Relay 1 (eject page after printing)
|
||
case 9: // same as 1
|
||
this.printLine(line, this.pendingSpaceBefore);
|
||
this.skipToChannel();
|
||
this.pendingSpaceBefore = 0;
|
||
break;
|
||
case 2: // Relay 2 (single space before and after printing)
|
||
this.printLine(line, this.pendingSpaceBefore+1);
|
||
this.pendingSpaceBefore = 1;
|
||
break;
|
||
case 3: // Relay 3 (eject page before printing)
|
||
case 5: // Relay 5 (skip to channel 2 before printing)
|
||
case 7: // Relay 3+5 (skip to channel 3 before printing)
|
||
this.skipToChannel();
|
||
this.printLine(line, 0);
|
||
this.pendingSpaceBefore = 0;
|
||
break;
|
||
case 4: // Relay 4 (double space before printing)
|
||
this.printLine(line, this.pendingSpaceBefore+2);
|
||
this.pendingSpaceBefore = 0;
|
||
break;
|
||
case 6: // Relay 2+4 (double space before and single space after printing)
|
||
this.printLine(line, this.pendingSpaceBefore+2);
|
||
this.pendingSpaceBefore = 1;
|
||
break;
|
||
default: // single space before printing
|
||
this.printLine(line, this.pendingSpaceBefore+1);
|
||
this.pendingSpaceBefore = 0;
|
||
break;
|
||
}
|
||
|
||
this.endOfSupply.scrollIntoView();
|
||
setCallback(this.mnemonic, this, 60000/this.linesPerMinute, this.finishWrite);
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.setAlgolGlyphs = function setAlgolGlyphs(makeItPretty) {
|
||
/* Controls the display of Unicode glyphs for the special Algol characters */
|
||
|
||
if (makeItPretty) {
|
||
if (!this.useAlgolGlyphs) {
|
||
B220Util.xlateDOMTreeText(this.supply, B220Util.xlateASCIIToAlgol);
|
||
}
|
||
} else {
|
||
if (this.useAlgolGlyphs) {
|
||
B220Util.xlateDOMTreeText(this.supply, B220Util.xlateAlgolToASCII);
|
||
}
|
||
}
|
||
this.$$("COAlgolGlyphsCheck").checked = makeItPretty;
|
||
this.useAlgolGlyphs = makeItPretty;
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.setGreenbar = function setGreenbar(useGreen) {
|
||
/* Controls the display of "greenbar" shading on the output */
|
||
var rule = null;
|
||
var rules = null;
|
||
var sheet;
|
||
var ss = this.supplyDoc.styleSheets;
|
||
var x;
|
||
|
||
// First, find the embedded style sheet for the output frame.
|
||
for (x=ss.length-1; x>=0; --x) {
|
||
sheet = ss[x];
|
||
if (sheet.ownerNode.id == "PaperFrameStyles") {
|
||
rules = sheet.cssRules;
|
||
// Next, search through the rules for the one that controls greenbar shading.
|
||
for (x=rules.length-1; x>=0; --x) {
|
||
rule = rules[x];
|
||
if (rule.selectorText.toLowerCase() == "div.greenbar") {
|
||
// Found it: now flip the background color.
|
||
rule.style.backgroundColor = (useGreen ? this.theColorGreen : "white");
|
||
}
|
||
}
|
||
break; // out of for loop
|
||
}
|
||
}
|
||
this.$$("COGreenbarCheck").checked = useGreen;
|
||
this.useGreenbar = useGreen;
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.COStartBtn_onClick = function COStartBtn_onClick(ev) {
|
||
/* Handle the click event for the START button */
|
||
|
||
if (!this.ready && this.supplyLeft > 0) {
|
||
this.runoutSupplyCount = 0;
|
||
this.setDeviceReady(true);
|
||
if (!this.bufferReady) {
|
||
this.initiateWrite(); // have a full buffer, so output it
|
||
}
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.COStopBtn_onClick = function COStopBtn_onClick(ev) {
|
||
/* Handle the click event for the STOP button */
|
||
|
||
if (this.ready) {
|
||
this.runoutSupplyCount = 0;
|
||
this.setDeviceReady(false);
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.CORunoutSupplyBtn_onClick = function CORunoutSupplyBtn_onClick(ev) {
|
||
/* Handle the click event for the Skip To Heading button */
|
||
|
||
if (!this.ready) {
|
||
this.printLine("", -1);
|
||
this.endOfSupply.scrollIntoView();
|
||
if (++this.runoutSupplyCount >= 3) {
|
||
if (this.window.confirm("Do you want to clear the output from the device?")) {
|
||
this.runoutSupply();
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.COEndOfSupplyBtn_onClick = function COEndOfSupplyBtn_onClick(ev) {
|
||
/* Handle the click event for the End Of Supply button. If the printer/punch
|
||
is in and end-of-supply condition, this will make the printer/punch ready,
|
||
but it will still be in an EOS condition. The next time a print/punch line
|
||
is received, the EOS condition will force it not-ready again. You can print/
|
||
punch only one line at a time (presumably to the end of the current page).
|
||
The EOS condition can be cleared by clicking Supply Feed three times to "rip"
|
||
the paper or empty the punch hopper */
|
||
|
||
if (this.supplyLeft <= 0 && !this.ready) {
|
||
this.runoutSupplyCount = 0;
|
||
B220Util.removeClass(this.$$("COEndOfSupplyBtn"), "redLit");
|
||
this.setDeviceReady(true);
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.COAlgolGlyphsCheck_onClick = function COAlgolGlyphsCheck_onClick(ev) {
|
||
/* Handle the click event for the Algol Glyphs checkbox */
|
||
var prefs = this.config.getNode("Cardatron.units", this.unitIndex);
|
||
|
||
this.setAlgolGlyphs(ev.target.checked);
|
||
prefs.algolGlyphs = this.useAlgolGlyphs;
|
||
this.config.putNode("Cardatron.units", prefs, this.unitIndex);
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.COGreenbarCheck_onClick = function COGreenbarCheck_onClick(ev) {
|
||
/* Handle the click event for the Greenbar checkbox */
|
||
var prefs = this.config.getNode("Cardatron.units", this.unitIndex);
|
||
|
||
this.setGreenbar(ev.target.checked);
|
||
prefs.greenBar = this.useGreenbar;
|
||
this.config.putNode("Cardatron.units", prefs, this.unitIndex);
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.parseZeroSuppressList = function parseZeroSuppressList(text, alertWin) {
|
||
/* Parses a comma-delimited list of zero-suppression starting columns. If the list is
|
||
parsed successfully, returns an array of integers; otherwise returns null. An alert
|
||
is displayed on the window for the first parsing or out-of-sequence error */
|
||
var col;
|
||
var cols;
|
||
var copacetic = true;
|
||
var lastCol = 0;
|
||
var raw;
|
||
var x;
|
||
var zsCol = [];
|
||
|
||
if (text.search(/\S/) >= 0) {
|
||
cols = text.split(",");
|
||
for (x=0; x<cols.length; ++x) {
|
||
raw = cols[x].trim();
|
||
if (raw.length > 0) { // ignore empty fields
|
||
col = parseInt(raw, 10);
|
||
if (isNaN(col)) {
|
||
copacetic = false;
|
||
alertWin.alert("Item #" + (x+1) + " (\"" + cols[x] + "\") is not numeric");
|
||
break; // out of for loop
|
||
} else if (col <= lastCol) {
|
||
copacetic = false;
|
||
alertWin.alert("Item #" + (x+1) + " (\"" + col + "\") is out of sequence");
|
||
break; // out of for loop
|
||
} else {
|
||
lastCol = col;
|
||
zsCol.push(col);
|
||
}
|
||
}
|
||
} // for x
|
||
}
|
||
|
||
return (copacetic ? zsCol : null);
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.COSetZSBtn_onClick = function COSetZSBtn_onClick(ev) {
|
||
/* Displays the Zero Suppress Panel window to capture a list of column numbers */
|
||
var $$$ = null; // getElementById shortcut for loader window
|
||
var doc = null; // zero-suppress window.document
|
||
var tron = this; // this B220CardatronOutput device instance
|
||
var win = null; // zero-suppress window defaultView
|
||
|
||
function zsOK(ev) {
|
||
/* Handler for the OK button. Parses the list of column numbers; if successful,
|
||
sets tron.zsCol to the resulting array, stores the list in the system
|
||
configuration object, and closes the window */
|
||
var prefs;
|
||
var text = $$$("COZSColumnList").value;
|
||
var zsCol;
|
||
|
||
zsCol = tron.parseZeroSuppressList(text, win);
|
||
if (zsCol !== null) {
|
||
tron.zsCol = zsCol;
|
||
B220Util.removeClass(tron.$$("COSetZSBtn"), (zsCol.length > 0 ? "blackButton1" : "greenButton1"));
|
||
B220Util.addClass(tron.$$("COSetZSBtn"), (zsCol.length > 0 ? "greenButton1" : "blackButton1"));
|
||
|
||
// Store the new list in the system configuration object
|
||
text = zsCol.join(",");
|
||
prefs = tron.config.getNode("Cardatron.units", tron.unitIndex);
|
||
prefs.zeroSuppressCols = text;
|
||
tron.config.putNode("Cardatron.units", prefs, tron.unitIndex);
|
||
win.close();
|
||
}
|
||
}
|
||
|
||
function zsOnload (ev) {
|
||
/* Driver for the tape loader window */
|
||
var de;
|
||
|
||
doc = ev.target;
|
||
win = doc.defaultView;
|
||
this.zsWindow = win;
|
||
doc.title = "retro-220 " + tron.mnemonic + " Zero-Suppress Panel";
|
||
de = doc.documentElement;
|
||
$$$ = function $$$(id) {
|
||
return doc.getElementById(id);
|
||
};
|
||
|
||
$$$("COZSColumnList").value = tron.zsCol.join(",");
|
||
$$$("COZSOKBtn").addEventListener("click", zsOK, false);
|
||
$$$("COZSCancelBtn").addEventListener("click", function zsCancelBtn(ev) {
|
||
win.close();
|
||
}, false);
|
||
|
||
win.resizeBy(de.scrollWidth - win.innerWidth,
|
||
de.scrollHeight - win.innerHeight);
|
||
$$$("COZSColumnList").focus();
|
||
win.addEventListener("unload", function zsUnload(ev) {
|
||
this.zsWindow = null;
|
||
}, false);
|
||
}
|
||
|
||
// Outer block of COSetZSBtn_onClick
|
||
if (this.zsWindow && !this.zsWindow.closed) {
|
||
this.zsWindow.close();
|
||
}
|
||
|
||
B220Util.openPopup(this.window, "B220CardatronZeroSuppressPanel.html", this.mnemonic + "ZS",
|
||
"location=no,scrollbars=no,resizable,width=508,height=120,left=" +
|
||
(this.window.screenX+16) +",top=" + (this.window.screenY+16),
|
||
this, zsOnload);
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.beforeUnload = function beforeUnload(ev) {
|
||
var msg = "Closing this window will make the device unusable.\n" +
|
||
"Suggest you stay on the page and minimize this window instead";
|
||
|
||
ev.preventDefault();
|
||
ev.returnValue = msg;
|
||
return msg;
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.deviceOnLoad = function deviceOnLoad(ev) {
|
||
/* Initializes the printer/punch window and user interface */
|
||
var body;
|
||
var de;
|
||
var newChild;
|
||
var prefs = this.config.getNode("Cardatron.units", this.unitIndex);
|
||
var zsCol;
|
||
|
||
this.doc = ev.target;
|
||
this.window = this.doc.defaultView;
|
||
de = this.doc.documentElement;
|
||
this.doc.title = "retro-220 Cardatron " +
|
||
(this.isPrinter ? "Printer " : "Punch ") + this.mnemonic;
|
||
|
||
body = this.$$("CODiv");
|
||
this.supplyDoc = this.$$("COSupplyFrame").contentDocument;
|
||
this.supply = this.supplyDoc.getElementById("Paper");
|
||
this.endOfSupply = this.supplyDoc.getElementById("EndOfPaper");
|
||
this.supplyMeter = this.$$("COSupplyMeter");
|
||
|
||
newChild = this.supplyDoc.createElement("div");
|
||
newChild.id = this.supply.id;
|
||
this.supply.parentNode.replaceChild(newChild, this.supply);
|
||
this.supply = newChild;
|
||
if (!this.isPrinter) {
|
||
this.barGroup = this.doc.createElement("pre");
|
||
this.barGroup.className = "paper";
|
||
this.supply.appendChild(this.barGroup);
|
||
}
|
||
|
||
this.startMachineLamp = new NeonLamp(body, null, null, "StartMachineLamp");
|
||
this.startMachineLamp.setCaption("SM", true);
|
||
|
||
this.formatSelect1Lamp = new NeonLamp(body, null, null, "FormatSelect1Lamp");
|
||
this.formatSelect1Lamp.setCaption("FS1", true);
|
||
this.formatSelect2Lamp = new NeonLamp(body, null, null, "FormatSelect2Lamp");
|
||
this.formatSelect2Lamp.setCaption("FS2", true);
|
||
this.formatSelect4Lamp = new NeonLamp(body, null, null, "FormatSelect4Lamp");
|
||
this.formatSelect4Lamp.setCaption("FS4", true);
|
||
|
||
this.setAlgolGlyphs(prefs.algolGlyphs);
|
||
this.setGreenbar(prefs.greenBar);
|
||
zsCol = this.parseZeroSuppressList(prefs.zeroSuppressCols || "", this.window);
|
||
if (zsCol !== null) {
|
||
this.zsCol = zsCol;
|
||
if (zsCol.length > 0) {
|
||
B220Util.removeClass(this.$$("COSetZSBtn"), (zsCol.length > 0 ? "blackButton1" : "greenButton1"));
|
||
B220Util.addClass(this.$$("COSetZSBtn"), (zsCol.length > 0 ? "greenButton1" : "blackButton1"));
|
||
}
|
||
}
|
||
|
||
this.supplyMeter.max = this.maxSupplyLines;
|
||
this.supplyMeter.low = this.maxSupplyLines*0.1;
|
||
this.supplyMeter.value = this.supplyLeft = this.maxSupplyLines;
|
||
this.setDeviceReady(true);
|
||
|
||
this.window.addEventListener("beforeunload",
|
||
B220CardatronOutput.prototype.beforeUnload, false);
|
||
this.supply.addEventListener("dblclick",
|
||
B220CardatronOutput.prototype.copySupply.bind(this), false);
|
||
this.$$("COStopBtn").addEventListener("click",
|
||
B220CardatronOutput.prototype.COStopBtn_onClick.bind(this), false);
|
||
this.$$("COStartBtn").addEventListener("click",
|
||
B220CardatronOutput.prototype.COStartBtn_onClick.bind(this), false);
|
||
this.$$("COEndOfSupplyBtn").addEventListener("click",
|
||
B220CardatronOutput.prototype.COEndOfSupplyBtn_onClick.bind(this), false);
|
||
this.$$("CORunoutSupplyBtn").addEventListener("click",
|
||
B220CardatronOutput.prototype.CORunoutSupplyBtn_onClick.bind(this), false);
|
||
this.$$("COAlgolGlyphsCheck").addEventListener("click",
|
||
B220CardatronOutput.prototype.COAlgolGlyphsCheck_onClick.bind(this), false);
|
||
this.$$("COSetZSBtn").addEventListener("click",
|
||
B220CardatronOutput.prototype.COSetZSBtn_onClick.bind(this), false);
|
||
this.$$("ClearBtn").addEventListener("click",
|
||
B220CardatronOutput.prototype.ClearBtn_onClick.bind(this), false);
|
||
|
||
if (!this.isPrinter) {
|
||
this.$$("COEndOfSupplyBtn").innerHTML = "OUT OF<br>CARDS";
|
||
this.$$("CORunoutSupplyBtn").innerHTML = "RUNOUT<br>CARDS";
|
||
this.$$("COGreenbarSpan").style.display = "none";
|
||
this.$$("COGreenbarCheck").disabled = true;
|
||
} else {
|
||
this.$$("COEndOfSupplyBtn").innerHTML = "OUT OF<br>PAPER";
|
||
this.$$("CORunoutSupplyBtn").innerHTML = "FORM<br>FEED";
|
||
this.$$("COGreenbarSpan").style.display = "inline";
|
||
this.$$("COGreenbarCheck").addEventListener("click",
|
||
B220CardatronOutput.prototype.COGreenbarCheck_onClick.bind(this), false);
|
||
}
|
||
|
||
this.window.moveTo(screen.availWidth - this.window.outerWidth,
|
||
screen.availHeight - this.window.outerHeight - (7-this.unitIndex)*32);
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.outputWord = function outputWord(requestNextWord) {
|
||
/* Receives the next info band word from the Processor and stores its digits
|
||
under control of the selected format band. requestNextWord is the callback function
|
||
to request the next word from the Processor; signalFinished is the callback
|
||
function to tell the Processor we are done with data transfer */
|
||
var band; // local copy of format band
|
||
var d; // current digit
|
||
var eod; // done with current digit
|
||
var eow = false; // done with current word
|
||
var drumAddr; // buffer drum address
|
||
var info = this.info; // local reference to info band
|
||
var ix = this.infoIndex; // current info/format band index
|
||
var lastNumeric = this.lastNumericDigit;
|
||
var nu = this.togNumeric; // numeric/zone digit toggle
|
||
var word = requestNextWord(); // word received from processor
|
||
var x = 0; // word-digit index
|
||
|
||
band = this.formatBand[this.selectedFormat];
|
||
|
||
// Loop through the digits in the word, processing each one
|
||
do {
|
||
eod = false;
|
||
d = word % 0x10;
|
||
word = (word-d)/0x10;
|
||
|
||
// Loop through the format band digits until the current word-digit is consumed
|
||
do {
|
||
if (ix >= info.length) {
|
||
eow = eod = true;
|
||
} else {
|
||
// Translate the current digit
|
||
switch (band[ix]) {
|
||
case 0: // insert 0 digit
|
||
nu = !nu;
|
||
info[ix] = lastNumeric = 0;
|
||
++ix;
|
||
// we are not done with the current word-digit yet...
|
||
break;
|
||
case 1: // translate zone/numeric digit
|
||
if (nu) {
|
||
// Numeric digit: straight translation except for 3-8 and 4-8 punches
|
||
nu = false; // next is a zone digit
|
||
info[ix] = lastNumeric = d;
|
||
} else {
|
||
// Zone digit: requires special handling in the sign-digit position
|
||
// and if the corresponding numeric digit came from a 3-8 or 4-8 punch
|
||
nu = true; // next is a numeric digit
|
||
if (x > 9) {
|
||
// For a zone digit in the sign position, store a 5 (+) or 6 (-)
|
||
// so that the sign will be printed/punched as a zone 11/12, UNLESS
|
||
// the sign is positive and Suppress-12 mode is in effect. In that
|
||
// case, store a zero to the zone so the sign will not print/punch.
|
||
if (d%2 == 0 && this.suppress12Mode) {
|
||
info[ix] = 0; // suppress the 12-zone output
|
||
} else {
|
||
info[ix] = d%2 + 5;
|
||
}
|
||
} else if (d > 3) {
|
||
info[ix] = this.zoneXlate[d][lastNumeric];
|
||
} else {
|
||
// If the prior numeric digit was 3 or 4 AND this zone is 0-3,
|
||
// store an 11 or 12 for the prior digit to indicate a 3-8 or 4-8 punch.
|
||
if (ix > 0 && (lastNumeric == 3 || lastNumeric == 4)) {
|
||
info[ix-1] = lastNumeric+8;
|
||
}
|
||
info[ix] = this.zoneXlate[d][lastNumeric];
|
||
}
|
||
}
|
||
++ix;
|
||
eod = true;
|
||
break;
|
||
case 2: // translate numerically
|
||
nu = true; // next is forced to be another numeric digit
|
||
info[ix] = lastNumeric = d;
|
||
++ix;
|
||
eod = true;
|
||
break;
|
||
default: // (3) delete the digit -- store nothing
|
||
++ix;
|
||
eod = true;
|
||
break;
|
||
} // switch band[ix]
|
||
}
|
||
} while (!eod);
|
||
|
||
if (x < 10) {
|
||
++x;
|
||
} else {
|
||
eow = true;
|
||
}
|
||
} while (!eow);
|
||
|
||
this.lastNumericDigit = lastNumeric;
|
||
this.togNumeric = nu;
|
||
this.infoIndex = ix;
|
||
}
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.outputTransfer = function outputTransfer(requestNextWord) {
|
||
/* Driver for receiving info band words from the Processor */
|
||
|
||
while (this.infoIndex < this.info.length) {
|
||
this.outputWord(requestNextWord);
|
||
}
|
||
|
||
this.pendingFinish(); // call signalFinished()
|
||
this.pendingFinish = null;
|
||
this.initiateWrite();
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.outputInitiate = function outputInitiate(
|
||
fDigit, cDigit, requestNextWord, signalFinished) {
|
||
/* Initiates a write to the buffer drum on this unit. fDigit is the
|
||
(41) numeric digit from the instruction word containing the format number.
|
||
cDigit is the (31) numeric digit from the instruction word and sets the
|
||
Tab Select relays for the IBM device. We use it for carriage control as
|
||
implemented by the standard Burroughs 205/220 plugboard for the 407:
|
||
0 = No relays (single space before printing)
|
||
1 = Relay 1 (eject page after printing)
|
||
2 = Relay 2 (single space before and after printing)
|
||
3 = Relay 3 (eject page before printing)
|
||
4 = Relay 4 (double space before printing)
|
||
5 = Relay 5 (skip to channel 2 before printing)
|
||
6 = Relay 2+4 (double space before and single space after printing)
|
||
7 = Relay 3+5 (skip to channel 3 before printing)
|
||
8 = same as 0
|
||
9 = same as 1
|
||
Carriage control is ignored for punch devices and always set to single spacing.
|
||
requestNextWord is the callback function that will request the next word from the
|
||
processor. signalFinished is the callback function that tells the Processor
|
||
we're done. If the buffer is not ready, simply sets the writeRequested flag
|
||
and exits after stashing fDigit, cDigit, and the callbacks. Note that if the
|
||
device is not ready, the buffer can still be loaded */
|
||
|
||
if (!this.bufferReady) {
|
||
this.writeRequested = true; // wait for the buffer to be emptied
|
||
this.pendingCall = outputInitiate;
|
||
this.pendingParams = [fDigit, cDigit, requestNextWord, signalFinished];
|
||
} else if (fDigit > 9) {
|
||
signalFinished();
|
||
} else {
|
||
this.cDigit = (this.isPrinter ? cDigit : 0);
|
||
this.fDigit = fDigit;
|
||
this.suppress12Mode = (fDigit%2 == 0);
|
||
this.selectedFormat = ((fDigit >>> 1) & 0x07) + 1;
|
||
this.setFormatSelectLamps(this.selectedFormat);
|
||
this.togNumeric = true;
|
||
this.lastNumericDigit = 0;
|
||
this.bufferReady = false;
|
||
this.clearInfoBand();
|
||
this.pendingFinish = signalFinished; // stash the callback function
|
||
setCallback(this.mnemonic, this, B220CardatronOutput.drumTransferTime*(Math.random()+2),
|
||
this.outputTransfer, requestNextWord);
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.outputReadyInterrogate = function outputReadyInterrogate() {
|
||
/* Returns the current ready status of the output unit */
|
||
|
||
return this.bufferReady;
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.outputFormatTransfer = function outputFormatTransfer(requestNextWord) {
|
||
/* Receives output format band words from the Processor and stores the
|
||
digits from each word into the next 11 format band digits */
|
||
var band = this.formatBand[this.selectedFormat];
|
||
var d; // current format digit
|
||
var ix = 0; // current format band digit index
|
||
var word; // band word received from Processor
|
||
var x; // word-digit index
|
||
|
||
while (ix < B220CardatronOutput.trackSize) {
|
||
word = requestNextWord();
|
||
if (word < 0) { // transfer terminated
|
||
ix = B220CardatronOutput.tracksize;
|
||
} else {
|
||
for (x=0; x<11; ++x) {
|
||
d = word % 0x10;
|
||
word = (word-d)/0x10;
|
||
if (ix < B220CardatronOutput.trackSize) {
|
||
band[ix++] = d % 4;
|
||
} else {
|
||
break; // out of for loop
|
||
}
|
||
} // for x
|
||
}
|
||
}
|
||
|
||
this.pendingFinish(); // call signalFinished();
|
||
this.pendingFinish = null;
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.outputFormatInitiate = function outputFormatInitiate(
|
||
fDigit, requestNextWord, signalFinished) {
|
||
/* Initiates the loading of a format band on this unit. fDigit is the
|
||
(41) numeric digit from the instruction word, the low-order bit is ignored,
|
||
and the remaining three bits indicate the format band to be loaded. requestNextWord
|
||
is the callback function that will trigger the Processor to send the next word.
|
||
signalFinished is the callback function that will signal the Processor to
|
||
terminate the I/O */
|
||
|
||
if (fDigit > 9) {
|
||
signalFinished();
|
||
} else {
|
||
this.fDigit = fDigit;
|
||
this.selectedFormat = ((fDigit >>> 1) & 0x07) + 1;
|
||
this.pendingFinish = signalFinished; // stash the call-back function
|
||
this.setFormatSelectLamps(this.selectedFormat);
|
||
setCallback(this.mnemonic, this, B220CardatronOutput.drumTransferTime*(Math.random()+2),
|
||
this.outputFormatTransfer, requestNextWord);
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.clearUnit = function clearUnit() {
|
||
/* Clears the output unit and resets all internal state */
|
||
|
||
this.$$("CRFileSelector").value = null; // reset the control so the same file can be reloaded
|
||
this.bufferReady = true;
|
||
this.setDeviceReady(true);
|
||
this.startMachineLamp.set(0);
|
||
this.setFormatSelectLamps(0);
|
||
|
||
this.clear();
|
||
if (this.timer) {
|
||
clearCallback(this.timer);
|
||
this.timer = 0;
|
||
}
|
||
};
|
||
|
||
/**************************************/
|
||
B220CardatronOutput.prototype.shutDown = function shutDown() {
|
||
/* Shuts down the device */
|
||
|
||
if (this.timer) {
|
||
clearCallback(this.timer);
|
||
}
|
||
this.window.removeEventListener("beforeunload", B220CardatronOutput.prototype.beforeUnload, false);
|
||
this.window.close();
|
||
if (this.zsWindow && !this.zsWindow.closed) {
|
||
this.zsWindow.close();
|
||
}
|
||
};
|