/*********************************************************************** * retro-b5500/emulator B5500CardPunch.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 Punch Peripheral Unit module. * * Defines a card punch peripheral unit type. * ************************************************************************ * 2013-06-16 P.Kimpel * Original version, from B5500CardReader.js & B5500DummyPrinter.js. ***********************************************************************/ "use strict"; /**************************************/ function B5500CardPunch(mnemonic, unitIndex, designate, statusChange, signal) { /* Constructor for the CardPunch 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 (not used here) 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.stacker1 = null; this.endOfStacker1 = null; this.stacker2 = null; this.endOfStacker2 = null; this.window = window.open("/B5500/webUI/B5500CardPunch.html", mnemonic, "scrollbars=no,resizable,width=700,height=500"); this.window.addEventListener("load", function() { that.punchOnload(); }, false); } B5500CardPunch.prototype.cardsPerMinute = 300; // Punch speed B5500CardPunch.prototype.maxScrollLines = 800; // Maximum punch stacker scrollback (stacker capacity) /**************************************/ B5500CardPunch.prototype.$$ = function $$(e) { return this.doc.getElementById(e); }; /**************************************/ B5500CardPunch.prototype.clear = function clear() { /* Initializes (and if necessary, creates) the punch 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.runoutArmed = false; // EOF button: armed state this.stopCount = 0; // stopCount for clearing the input buffer this.stacker1Count = 0; // cards in stacker #1 this.stacker2Count = 0; // cards in stacker #2 }; /**************************************/ B5500CardPunch.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); } }; /**************************************/ B5500CardPunch.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); } }; /**************************************/ B5500CardPunch.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"), ""); }; /**************************************/ B5500CardPunch.prototype.setPunchReady = function setPunchReady(ready) { /* Controls the ready-state of the card punch */ if (ready && !this.ready) { this.statusChange(1); this.removeClass(this.$$("CPNotReadyLight"), "redLit"); this.ready = true; if (this.runoutArmed) { if (this.stacker1Count || this.stacker2Count) { if (this.window.confirm("Empty both " + this.mnemonic + " stackers?")) { this.stacker1Count = this.stacker2Count = 0; this.$$("CPStacker1Bar").value = 0; this.$$("CPStacker2Bar").value = 0; while (this.stacker1.firstChild) { this.stacker1.removeChild(this.stacker1.firstChild); } while (this.stacker2.firstChild) { this.stacker2.removeChild(this.stacker2.firstChild); } } } this.armRunout(false); } } else if (!ready && this.ready) { this.statusChange(0); this.addClass(this.$$("CPNotReadyLight"), "redLit"); this.ready = false; } }; /**************************************/ B5500CardPunch.prototype.armRunout = function armRunout(armed) { /* Controls the arming/disarming of the EOF signal when starting with an empty input stacker */ if (armed && !this.ready) { this.addClass(this.$$("CPRunoutBtn"), "redLit"); this.runoutArmed = true; } else { this.removeClass(this.$$("CPRunoutBtn"), "redLit"); this.runoutArmed = false; } }; /**************************************/ B5500CardPunch.prototype.CPStartBtn_onclick = function CPStartBtn_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.setPunchReady(true); } }; /**************************************/ B5500CardPunch.prototype.CPStopBtn_onclick = function CPStopBtn_onclick(ev) { /* Handle the click event for the STOP button */ if (this.ready) { this.setPunchReady(false); } else if (this.runoutArmed) { this.armRunout(false); } }; /**************************************/ B5500CardPunch.prototype.CPRunoutBtn_onclick = function CPRunoutBtn_onclick(ev) { /* Handle the click event for the EOF button */ this.armRunout(!this.runoutArmed); }; /**************************************/ B5500CardPunch.prototype.punchOnload = function punchOnload() { /* Initializes the punch window and user interface */ var that = this; this.doc = this.window.document; this.doc.title = "retro-B5500 " + this.mnemonic; this.stacker1Frame = this.$$("CPStacker1Frame"); this.stacker1Frame.contentDocument.head.innerHTML += ""; this.stacker1 = this.doc.createElement("pre"); this.stacker1Frame.contentDocument.body.appendChild(this.stacker1); this.endOfStacker1 = this.doc.createElement("div"); this.stacker1Frame.contentDocument.body.appendChild(this.endOfStacker1); this.stacker2Frame = this.$$("CPStacker2Frame"); this.stacker2Frame.contentDocument.head.innerHTML += ""; this.stacker2 = this.doc.createElement("pre"); this.stacker2Frame.contentDocument.body.appendChild(this.stacker2); this.endOfStacker2 = this.doc.createElement("div"); this.stacker2Frame.contentDocument.body.appendChild(this.endOfStacker2); this.window.moveTo(0, 180); this.window.resizeTo(this.window.outerWidth+this.$$("CPDiv").scrollWidth-this.window.innerWidth+12, this.window.outerHeight+this.$$("CPDiv").scrollHeight-this.window.innerHeight+12); this.armRunout(false); this.setPunchReady(true); this.$$("CPStartBtn").addEventListener("click", function(ev) { that.CPStartBtn_onclick(ev); }, false); this.$$("CPStopBtn").addEventListener("click", function(ev) { that.CPStopBtn_onclick(ev); }, false); this.$$("CPRunoutBtn").addEventListener("click", function(ev) { that.CPRunoutBtn_onclick(ev); }, false); this.$$("CPStacker1Bar").max = this.maxScrollLines; this.$$("CPStacker2Bar").max = this.maxScrollLines; }; /**************************************/ B5500CardPunch.prototype.appendLine = function appendLine(stacker, text) { /* Removes excess lines already printed, then appends a new
element
to the