/*********************************************************************** * retro-b5500/emulator B5500SPOUnit.js ************************************************************************ * Copyright (c) 2012, Nigel Williams and Paul Kimpel. * Licensed under the MIT License, see * http://www.opensource.org/licenses/mit-license.php ************************************************************************ * B5500 SPO Peripheral Unit module. * * Defines a SPO peripheral unit type that implements the Supervisory * Print Out device on the operator's console. * ************************************************************************ * 2012-12-22 P.Kimpel * Original version, from B5500DummyUnit.js. ***********************************************************************/ "use strict"; /**************************************/ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) { /* Constructor for the SPOUnit object */ var that = this; this.maxScrollLines = 500; // Maximum amount of printer scrollback this.charPeriod = 100; // Printer speed, milliseconds per character 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.backspaceChar.that = this; // Store object context for these functions this.printChar.that = this; this.outputChar.that = this; this.window = window.open("", mnemonic); if (this.window) { this.window.close(); // destroy the previously-existing window this.window = null; } this.doc = null; this.paper = null; this.endOfPaper = null; this.window = window.open("/B5500/webUI/B5500SPOUnit.html", mnemonic, "scrollbars,resizable,width=600,height=500"); this.window.addEventListener("load", function() { that.spoOnload(); }, false); } // this.spoState enumerations B5500SPOUnit.prototype.spoNotReady = 0; B5500SPOUnit.prototype.spoLocal = 1; B5500SPOUnit.prototype.spoRemote = 2; B5500SPOUnit.prototype.spoInput = 3; B5500SPOUnit.prototype.spoOutput = 4; 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 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 /**************************************/ B5500SPOUnit.prototype.$$ = function $$(e) { return this.doc.getElementById(e); }; /**************************************/ B5500SPOUnit.prototype.clear = function clear() { /* Initializes (and if necessary, creates) the SPO 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 = null; this.bufLength = 0; this.bufIndex = 0; this.printCol = 0; this.nextCharTime = 0; this.spoState = this.spoNotReady; // Current state of SPO interface this.spoLocalRequested = false; // LOCAL button pressed while active }; /**************************************/ B5500SPOUnit.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); } }; /**************************************/ B5500SPOUnit.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); } }; /**************************************/ 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 setNotReady() { /* Sets the status of the SPO to Not Ready */ if (this.spoState == this.spoLocal) { this.spoState = this.spoNotReady; this.removeClass(this.$$("SPOReadyBtn"), "yellowLit"); this.statusChange(0); } }; /**************************************/ B5500SPOUnit.prototype.setReady = function setReady() { /* Sets the status of the SPO to Ready */ if (this.spoState == this.spoNotReady) { this.addClass(this.$$("SPOReadyBtn"), "yellowLit"); this.spoState = this.spoLocal; } }; /**************************************/ B5500SPOUnit.prototype.setLocal = function setLocal() { /* Sets the status of the SPO to Local */ if (this.spoState == this.spoRemote) { this.spoState = this.spoLocal; this.addClass(this.$$("SPOLocalBtn"), "yellowLit"); this.removeClass(this.$$("SPORemoteBtn"), "yellowLit"); this.statusChange(0); // Set up to echo characters from the keyboard this.buffer = null; this.bufLength = 0; this.bufIndex = 0; this.printCol = 0; this.nextCharTime = new Date().getTime(); this.finish = null; } }; /**************************************/ B5500SPOUnit.prototype.setRemote = function setRemote() { /* Sets the status of the SPO to Remote */ if (this.spoState == this.spoLocal) { this.spoState = this.spoRemote; this.addClass(this.$$("SPORemoteBtn"), "yellowLit"); this.removeClass(this.$$("SPOLocalBtn"), "yellowLit"); this.statusChange(1); } }; /**************************************/ B5500SPOUnit.prototype.appendEmptyLine = function appendEmptyLine() { /* Removes excess lines already printed, then appends a new
element
to the