mirror of
https://github.com/pkimpel/retro-220.git
synced 2026-03-10 04:24:41 +00:00
1. Tune internal processor timing to adjust neon glow persistence and attempt to make the Control Console display more realistic. 2. Change form-feed behavior in ConsolePrinter to embed an ASCII form- feed character in the text instead of emitting a number of newlines based upon the current line counter. 3. Corrections to rounding code in experimental version of floatingAdd() function (not currently enabled in the emulator).
641 lines
25 KiB
JavaScript
641 lines
25 KiB
JavaScript
/***********************************************************************
|
|
* retro-220/webUI B220ConsolePrinter.js
|
|
************************************************************************
|
|
* Copyright (c) 2017, Paul Kimpel.
|
|
* Licensed under the MIT License, see
|
|
* http://www.opensource.org/licenses/mit-license.php
|
|
************************************************************************
|
|
* Burroughs 220 Console Printer and
|
|
* High-Speed Paper Tape Punch devices.
|
|
************************************************************************
|
|
* 2017-03-17 P.Kimpel
|
|
* Original version, from retro-205 D205ConsoleOutput.js.
|
|
***********************************************************************/
|
|
"use strict";
|
|
|
|
/**************************************/
|
|
function B220ConsolePrinter(mnemonic, unitIndex, config) {
|
|
/* Constructor for the Console Printer object */
|
|
var top = unitIndex*32;
|
|
var left = unitIndex*32;
|
|
|
|
this.config = config; // System configuration object
|
|
this.mnemonic = mnemonic; // Unit mnemonic
|
|
this.unitIndex = unitIndex; // Unit index into console output units
|
|
this.outTimer = 0; // output setCallback() token
|
|
|
|
this.columns = 72; // right-margin auto-return position
|
|
this.format = 0; // 0=space, 1=tab, 2=carriage-return
|
|
this.nextCharTime = 0; // next time a character can be printed
|
|
this.mapMemory = 0; // map-memory switch setting
|
|
this.unitMask = 0; // unit selection mask
|
|
this.unitSwitch = new Array(11); // unit selection switch objects
|
|
this.tabStop = []; // 0-relative tab stop positions
|
|
this.zeroSuppress = 0; // zero-suppression switch setting
|
|
this.charPeriod = 0; // printer speed, ms/char
|
|
this.newLinePeriod = 0; // delay for carriage-returns
|
|
|
|
this.boundButton_Click = B220ConsolePrinter.prototype.button_Click.bind(this);
|
|
this.boundText_OnChange = B220ConsolePrinter.prototype.text_OnChange.bind(this);
|
|
this.boundFlipSwitch = B220ConsolePrinter.prototype.flipSwitch.bind(this);
|
|
this.boundReceiveSign = B220ConsolePrinter.prototype.receiveSign.bind(this);
|
|
this.boundReceiveChar = B220ConsolePrinter.prototype.receiveChar.bind(this);
|
|
|
|
this.clear();
|
|
|
|
// Create the printer window and onload event
|
|
this.doc = null;
|
|
this.window = null;
|
|
this.paper = null;
|
|
this.printerEOP = null;
|
|
this.printerLine = 0;
|
|
this.printerCol = 0;
|
|
B220Util.openPopup(window, "../webUI/B220ConsolePrinter.html", mnemonic,
|
|
"location=no,scrollbars=no,resizable,width=640,height=240," +
|
|
"left=" + left + ",top=" + top,
|
|
this, B220ConsolePrinter.prototype.printerOnLoad);
|
|
}
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.offSwitchImage = "./resources/ToggleDown.png";
|
|
B220ConsolePrinter.onSwitchImage = "./resources/ToggleUp.png";
|
|
|
|
B220ConsolePrinter.ttySpeed = 10; // TTY printer speed, char/sec
|
|
B220ConsolePrinter.ttyNewLine = 200; // TTY carriage-return delay, ms
|
|
B220ConsolePrinter.whippetSpeed = 1000; // Whippet printer speed, char/sec
|
|
B220ConsolePrinter.whippetNewLine = 75; // Whippet carriage-return delay, ms
|
|
B220ConsolePrinter.formFeedPeriod = 500;// full-page form-feed delay, ms
|
|
|
|
B220ConsolePrinter.pageSize = 66; // lines/page for form-feed
|
|
B220ConsolePrinter.maxScrollLines = 15000;
|
|
// Maximum amount of paper scrollback
|
|
|
|
B220ConsolePrinter.codeXlate = [ // translate internal B220 code to ANSI
|
|
" ", "?", " ", ".", "\u00A4", "?", "?", "?", "?", "?", "!", "!", "!", "!", "!", "!", // 00-0F
|
|
"&", "?", "?", "$", "*", "\f", "\n", "?", "?", "?", "!", "!", "!", "!", "!", "!", // 10-1F
|
|
"-", "/", "?", ",", "%", "?", "\t", "?", "?", "?", "!", "!", "!", "!", "!", "!", // 20-2F
|
|
"?", "?", "?", "#", "@", "\\", "?", "?", "?", "?", "!", "!", "!", "!", "!", "!", // 30-3F
|
|
"?", "A", "B", "C", "D", "E", "F", "G", "H", "I", "!", "!", "!", "!", "!", "!", // 40-4F
|
|
"?", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "!", "!", "!", "!", "!", "!", // 50-5F
|
|
"?", "?", "S", "T", "U", "V", "W", "X", "Y", "Z", "!", "!", "!", "!", "!", "!", // 60-6F
|
|
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "!", "!", "!", "!", "!", "!", // 70-7F
|
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "!", "!", "!", "!", "!", "!", // 80-8F
|
|
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "!", "!", "!", "!", "!", "!", // 90-9F
|
|
"!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", // A0-AF
|
|
"!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", // B0-BF
|
|
"!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", // C0-CF
|
|
"!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", // D0-DF
|
|
"!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", // E0-EF
|
|
"!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!", "!"]; // F0-FF
|
|
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.clear = function clear() {
|
|
/* Initializes (and if necessary, creates) the SPO unit state */
|
|
|
|
this.ready = false; // ready status
|
|
this.busy = false; // busy status
|
|
|
|
this.eowAction = 0; // 1 => End-of-Word action needed
|
|
this.suppressLZ = 0; // 1 => currently suppressing leading zeroes
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.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;
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.$$ = function $$(e) {
|
|
return this.doc.getElementById(e);
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.emptyPaper = function emptyPaper() {
|
|
/* Empties the printer output "paper" and initializes it for new output */
|
|
|
|
while (this.paper.firstChild) {
|
|
this.paper.removeChild(this.paper.firstChild);
|
|
}
|
|
|
|
this.paper.appendChild(this.doc.createTextNode(""));
|
|
this.printerLine = 0;
|
|
this.printerCol = 0;
|
|
this.printerEOP.scrollIntoView();
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.printNewLine = function printNewLine(text) {
|
|
/* Removes excess lines already output, then appends a newline to the
|
|
current text node, and then a new text node to the end of the <pre> element
|
|
within the paper element. Note that "text" is an ANSI string */
|
|
var paper = this.paper;
|
|
var line = text || "";
|
|
|
|
while (paper.childNodes.length > B220ConsolePrinter.maxScrollLines) {
|
|
paper.removeChild(paper.firstChild);
|
|
}
|
|
|
|
paper.lastChild.nodeValue += "\n"; // newline
|
|
paper.appendChild(this.doc.createTextNode(line));
|
|
++this.printerLine;
|
|
this.printerCol = line.length;
|
|
this.printerEOP.scrollIntoView();
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.printChar = function printChar(code) {
|
|
/* Outputs the character "code" to the device */
|
|
var c = B220ConsolePrinter.codeXlate[code];
|
|
var line;
|
|
var len;
|
|
|
|
if (c != "?") { // some 220 codes just don't print
|
|
line = this.paper.lastChild.nodeValue;
|
|
len = line.length;
|
|
if (len < 1) { // first char on line
|
|
this.paper.lastChild.nodeValue = c;
|
|
this.printerCol = 1;
|
|
} else if (len < this.columns) {// normal char
|
|
this.paper.lastChild.nodeValue = line + c;
|
|
++this.printerCol;
|
|
} else { // right margin overflow
|
|
this.printNewLine(c);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.printTab = function printTab() {
|
|
/* Simulates tabulation by outputting an appropriate number of spaces */
|
|
var tabCol = this.columns+1; // tabulation column (defaults to line overflow)
|
|
var x = 0; // scratch index
|
|
|
|
for (x=0; x<this.tabStop.length; ++x) {
|
|
if (this.tabStop[x] > this.printerCol) {
|
|
tabCol = this.tabStop[x];
|
|
break; // out of for loop
|
|
}
|
|
} // for x
|
|
|
|
if (this.columns < tabCol) {
|
|
this.printNewLine(); // tab would overflow right margin
|
|
} else {
|
|
while (this.printerCol < tabCol) {
|
|
this.printChar(0x00); // output a space
|
|
}
|
|
}
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.printFormFeed = function printFormFeed() {
|
|
/* Simulates a form feed by appending a newline and form feed to the
|
|
current text node, and then a new text node to the end of the <pre> element
|
|
within the paper element, with sufficient spaces to position the print head
|
|
to the same position on the line */
|
|
var paper = this.paper;
|
|
var line = "";
|
|
|
|
while (line.length < this.printerCol-8) {
|
|
line += " ";
|
|
}
|
|
|
|
while (line.length < this.printerCol) {
|
|
line += " ";
|
|
}
|
|
|
|
paper.lastChild.nodeValue += "\n\f"; // newline + formfeed
|
|
paper.appendChild(this.doc.createTextNode(line));
|
|
this.printerLine = 0;
|
|
this.printerEOP.scrollIntoView();
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.resizeWindow = function resizeWindow(ev) {
|
|
/* Handles the window onresize event by scrolling the "paper" so it remains at the end */
|
|
|
|
this.printerEOP.scrollIntoView();
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.copyPaper = function copyPaper(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 text = this.paper.textContent;
|
|
var title = "B220 " + this.mnemonic + " Text Snapshot";
|
|
|
|
B220Util.openPopup(this.window, "./B220FramePaper.html", "",
|
|
"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.emptyPaper();
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.button_Click = function button_Click(ev) {
|
|
/* Handler for button clicks */
|
|
|
|
switch (ev.target.id) {
|
|
case "LineFeedBtn":
|
|
this.printNewLine();
|
|
break;
|
|
case "CarriageReturnBtn":
|
|
if (this.printerCol > 0) {
|
|
this.printNewLine();
|
|
}
|
|
break;
|
|
case "OpenPanelBtn":
|
|
ev.target.disabled = true;
|
|
this.$$("FormatControlsDiv").style.display = "block";
|
|
break;
|
|
case "ClosePanelBtn":
|
|
this.$$("OpenPanelBtn").disabled = false;
|
|
this.$$("FormatControlsDiv").style.display = "none";
|
|
break;
|
|
} // switch ev.target.id
|
|
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.flipSwitch = function flipSwitch(ev) {
|
|
/* Handler for switch clicks */
|
|
var id = ev.target.id;
|
|
var prefs = this.config.getNode("ConsoleOutput.units", this.unitIndex);
|
|
var x;
|
|
|
|
switch (id) {
|
|
case "ZeroSuppressSwitch":
|
|
this.zeroSuppressSwitch.flip();
|
|
prefs.zeroSuppress = this.zeroSuppress = this.zeroSuppressSwitch.state;
|
|
break;
|
|
case "MapMemorySwitch":
|
|
this.mapMemorySwitch.flip();
|
|
prefs.mapMemory = this.mapMemory = this.mapMemorySwitch.state;
|
|
break;
|
|
case "RemoteKnob":
|
|
this.remoteKnob.step();
|
|
prefs.remote = this.remoteKnob.position;
|
|
this.ready = (this.remoteKnob.position != 0);
|
|
break;
|
|
case "FormatKnob":
|
|
this.formatKnob.step();
|
|
prefs.format = this.formatKnob.position;
|
|
this.format = this.formatKnob.position;
|
|
break;
|
|
case "SpeedSwitch":
|
|
this.speedSwitch.flip();
|
|
prefs.printerSpeed = this.speedSwitch.state;
|
|
if (this.speedSwitch.state) {
|
|
this.charPeriod = 1000/B220ConsolePrinter.whippetSpeed;
|
|
this.newLinePeriod = B220ConsolePrinter.whippetNewLine;
|
|
} else {
|
|
this.charPeriod = 1000/B220ConsolePrinter.ttySpeed;
|
|
this.newLinePeriod = B220ConsolePrinter.ttyNewLine;
|
|
}
|
|
break;
|
|
default:
|
|
x = id.indexOf("UnitSwitch");
|
|
if (x == 0) {
|
|
x = parseInt(id.substring(10), 10);
|
|
if (!isNaN(x)) {
|
|
this.unitSwitch[x].flip();
|
|
this.unitMask ^= B220Processor.pow2[x];
|
|
prefs.unitMask = this.unitMask;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
this.config.putNode("ConsoleOutput.units", prefs, this.unitIndex);
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.text_OnChange = function text_OnChange(ev) {
|
|
/* Handler for text onchange events */
|
|
var prefs = this.config.getNode("ConsoleOutput.units", this.unitIndex);
|
|
var text = ev.target.value;
|
|
var v = null;
|
|
|
|
switch (ev.target.id) {
|
|
case "Columns":
|
|
v = parseInt(text, 10);
|
|
if (!isNaN(v)) {
|
|
this.columns = v;
|
|
ev.target.value = text = v.toFixed();
|
|
prefs.columns = v;
|
|
}
|
|
break;
|
|
case "TabStops":
|
|
v = this.parseTabStops(prefs.tabs || "", this.window);
|
|
if (v !== null) {
|
|
this.tabStop = v;
|
|
ev.target.value = text = this.formatTabStops(v);
|
|
prefs.tabs = text;
|
|
}
|
|
break;
|
|
} // switch ev.target.id
|
|
|
|
this.config.putNode("ConsoleOutput.units", prefs, this.unitIndex);
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.formatTabStops = function formatTabStops(tabStops) {
|
|
/* Formats the array "tabStops" of 0-relative tab stop positions as a comma-
|
|
delimited string of 1-relative numbers */
|
|
var s = (tabStops[0]+1).toString();
|
|
var x = 0;
|
|
|
|
for (x=1; x<tabStops.length; ++x) {
|
|
s += "," + (tabStops[x]+1).toString();
|
|
}
|
|
|
|
return s;
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.parseTabStops = function parseTabStops(text, alertWin) {
|
|
/* Parses a comma-delimited list of 1-relative tab stops. If the list is parsed
|
|
successfully, returns an array of 0-relative tab stop positions; 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 tabStop = [];
|
|
|
|
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("Tab stop #" + (x+1) + " (\"" + cols[x] + "\") is not numeric");
|
|
break; // out of for loop
|
|
} else if (col <= lastCol) {
|
|
copacetic = false;
|
|
alertWin.alert("Tab stop #" + (x+1) + " (\"" + col + "\") is out of sequence");
|
|
break; // out of for loop
|
|
} else {
|
|
lastCol = col;
|
|
tabStop.push(col-1);
|
|
}
|
|
}
|
|
} // for x
|
|
}
|
|
|
|
return (copacetic ? tabStop : null);
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.printerOnLoad = function printerOnLoad(ev) {
|
|
/* Initializes the Teletype printer window and user interface */
|
|
var body;
|
|
var id;
|
|
var mask;
|
|
var prefs = this.config.getNode("ConsoleOutput.units", this.unitIndex);
|
|
var tabStop = null;
|
|
var x;
|
|
|
|
this.doc = ev.target;
|
|
this.window = this.doc.defaultView;
|
|
this.doc.title = "retro-220 Printer - " + this.mnemonic;
|
|
this.paper = this.$$("Paper");
|
|
this.printerEOP = this.$$("EndOfPaper");
|
|
this.emptyPaper();
|
|
|
|
body = this.$$("FormatControlsDiv");
|
|
this.remoteKnob = new BlackControlKnob(body, null, null, "RemoteKnob",
|
|
prefs.remote, [20, -20]);
|
|
this.ready = (prefs.remote != 0);
|
|
|
|
this.zeroSuppressSwitch = new ToggleSwitch(body, null, null, "ZeroSuppressSwitch",
|
|
B220ConsolePrinter.offSwitchImage, B220ConsolePrinter.onSwitchImage);
|
|
this.zeroSuppressSwitch.set(prefs.zeroSuppress);
|
|
this.zeroSuppress = this.zeroSuppressSwitch.state;
|
|
this.mapMemorySwitch = new ToggleSwitch(body, null, null, "MapMemorySwitch",
|
|
B220ConsolePrinter.offSwitchImage, B220ConsolePrinter.onSwitchImage);
|
|
this.mapMemorySwitch.set(prefs.mapMemory);
|
|
this.mapMemory = this.mapMemorySwitch.state;
|
|
this.speedSwitch = new ToggleSwitch(body, null, null, "SpeedSwitch",
|
|
B220ConsolePrinter.offSwitchImage, B220ConsolePrinter.onSwitchImage);
|
|
this.speedSwitch.set(prefs.printerSpeed);
|
|
if (this.speedSwitch.state) {
|
|
this.charPeriod = 1000/B220ConsolePrinter.whippetSpeed;
|
|
this.newLinePeriod = B220ConsolePrinter.whippetNewLine;
|
|
} else {
|
|
this.charPeriod = 1000/B220ConsolePrinter.ttySpeed;
|
|
this.newLinePeriod = B220ConsolePrinter.ttyNewLine;
|
|
}
|
|
|
|
mask = 0x001;
|
|
this.unitMask = prefs.unitMask;
|
|
for (x=0; x<this.unitSwitch.length; ++x) {
|
|
id = "UnitSwitch" + x.toFixed();
|
|
this.unitSwitch[x] = new ToggleSwitch(body, null, null, id,
|
|
B220ConsolePrinter.offSwitchImage, B220ConsolePrinter.onSwitchImage);
|
|
this.unitSwitch[x].set(prefs.unitMask & mask ? 1 : 0);
|
|
this.unitSwitch[x].addEventListener("click", this.boundFlipSwitch);
|
|
mask <<= 1;
|
|
}
|
|
|
|
this.formatKnob = new BlackControlKnob(body, null, null, "FormatKnob",
|
|
prefs.format, [-30, 0, 30]);
|
|
this.format = prefs.format;
|
|
|
|
this.columns = prefs.columns;
|
|
this.$$("Columns").value = prefs.columns.toFixed();
|
|
|
|
tabStop = this.parseTabStops(prefs.tabs || "", this.window);
|
|
if (tabStop !== null) {
|
|
this.tabStop = tabStop;
|
|
this.$$("TabStops").value = this.formatTabStops(tabStop);
|
|
}
|
|
|
|
// Events
|
|
this.window.addEventListener("beforeunload",
|
|
B220ConsolePrinter.prototype.beforeUnload, false);
|
|
this.window.addEventListener("resize",
|
|
B220ConsolePrinter.prototype.resizeWindow.bind(this), false);
|
|
this.paper.addEventListener("dblclick",
|
|
B220ConsolePrinter.prototype.copyPaper.bind(this), false);
|
|
|
|
this.$$("OpenPanelBtn").addEventListener("click", this.boundButton_Click);
|
|
this.$$("ClosePanelBtn").addEventListener("click", this.boundButton_Click);
|
|
this.$$("LineFeedBtn").addEventListener("click", this.boundButton_Click);
|
|
this.$$("CarriageReturnBtn").addEventListener("click", this.boundButton_Click);
|
|
|
|
this.zeroSuppressSwitch.addEventListener("click", this.boundFlipSwitch);
|
|
this.mapMemorySwitch.addEventListener("click", this.boundFlipSwitch);
|
|
this.speedSwitch.addEventListener("click", this.boundFlipSwitch);
|
|
this.remoteKnob.addEventListener("click", this.boundFlipSwitch);
|
|
this.formatKnob.addEventListener("click", this.boundFlipSwitch);
|
|
this.$$("Columns").addEventListener("change", this.boundText_OnChange);
|
|
this.$$("TabStops").addEventListener("change", this.boundText_OnChange);
|
|
|
|
this.window.focus();
|
|
};
|
|
|
|
/***********************************************************************
|
|
* Output Entry Points *
|
|
***********************************************************************/
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.initiateOutput = function initiateOutput(successor) {
|
|
/* Initiates output to the printer. This simply calls the successor function,
|
|
passing our receiver function, so the processor can get the ball rolling */
|
|
|
|
successor(this.boundReceiveSign);
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.receiveSign = function receiveSign(char, successor) {
|
|
/* Receives the sign character from the processor and handles it according
|
|
to the value of the sign and the setting of the Map Memory and LZ Suppress
|
|
switches */
|
|
var delay = this.charPeriod; // default character delay
|
|
var stamp = performance.now(); // current time
|
|
|
|
switch (true) {
|
|
case this.mapMemory != 0: // transparent output
|
|
this.eowAction = 1;
|
|
this.suppressLZ = 0;
|
|
this.printChar(char);
|
|
break;
|
|
|
|
case char == 0x82: // sign = 2, print alphanumeric
|
|
this.eowAction = 0;
|
|
this.suppressLZ = 0;
|
|
delay = 0; // eat the sign char
|
|
break;
|
|
|
|
case this.zeroSuppress == 1: // sign != 2, zero suppress
|
|
this.eowAction = 1;
|
|
this.suppressLZ = (char == 0x80 ? 1 : 0);
|
|
this.printChar(0x00); // print " "
|
|
break;
|
|
|
|
case (char & 0x01) == 1: // sign odd, no zero suppress
|
|
this.eowAction = 1;
|
|
this.suppressLZ = 0;
|
|
this.printChar(0x20); // print "-"
|
|
break;
|
|
|
|
default: // sign even, no zero suppress
|
|
this.eowAction = 1;
|
|
this.suppressLZ = 0;
|
|
this.printChar(0x00); // print " "
|
|
break;
|
|
} // switch
|
|
|
|
if (this.nextCharTime < stamp) {
|
|
this.nextCharTime = stamp;
|
|
}
|
|
|
|
setCallback(this.mnemonic, this, this.nextCharTime-stamp+delay, successor, this.boundReceiveChar);
|
|
this.nextCharTime += delay;
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.receiveChar = function receiveChar(char, successor) {
|
|
/* Receives a non-sign character from the processor and outputs it. Special handling
|
|
is provided for tabs, carriage returns, form feeds, and end-of-word characters */
|
|
var delay = this.charPeriod; // default character delay, ms
|
|
var nextReceiver = this.boundReceiveChar; // default routine to receive next char
|
|
var stamp = performance.now(); // current time
|
|
|
|
switch (char) {
|
|
case 0x80: // zero
|
|
this.printChar(this.suppressLZ ? 0x00 : char);
|
|
break;
|
|
|
|
case 0x02: // blank (non-print)
|
|
delay = 10; // a guess...
|
|
break;
|
|
|
|
case 0x15: // form-feed
|
|
delay = this.newLinePeriod + B220ConsolePrinter.formFeedPeriod *
|
|
(1 - (this.printerLine%B220ConsolePrinter.pageSize)/B220ConsolePrinter.pageSize);
|
|
this.suppressLZ = 0;
|
|
this.printFormFeed();
|
|
break;
|
|
|
|
case 0x16: // carriage-return
|
|
delay = this.newLinePeriod;
|
|
this.suppressLZ = 0;
|
|
this.printNewLine();
|
|
break;
|
|
|
|
case 0x26: // tab
|
|
this.suppressLZ = 0;
|
|
this.printTab();
|
|
break;
|
|
|
|
case 0x35: // end-of-word
|
|
nextReceiver = this.boundReceiveSign; // next will be start of a new word
|
|
if (this.eowAction) {
|
|
switch (this.format) {
|
|
case 0: // EOW = space
|
|
this.printChar(0x00);
|
|
break;
|
|
case 1: // EOW = tab
|
|
this.printTab();
|
|
break;
|
|
case 2: // EOW = carriage-return
|
|
delay = this.newLinePeriod;
|
|
this.printNewLine();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default: // all others
|
|
this.suppressLZ = 0;
|
|
this.printChar(char);
|
|
break;
|
|
} // switch char
|
|
|
|
setCallback(this.mnemonic, this, this.nextCharTime-stamp+delay, successor, nextReceiver);
|
|
this.nextCharTime += delay;
|
|
};
|
|
|
|
/**************************************/
|
|
B220ConsolePrinter.prototype.shutDown = function shutDown() {
|
|
/* Shuts down the device */
|
|
|
|
if (this.outTimer) {
|
|
clearCallback(this.outTimer);
|
|
}
|
|
|
|
if (this.window) {
|
|
this.window.removeEventListener("beforeunload", B220ConsolePrinter.prototype.beforeUnload, false);
|
|
this.window.close();
|
|
this.window = null;
|
|
}
|
|
};
|