1
0
mirror of https://github.com/pkimpel/retro-220.git synced 2026-04-15 16:10:49 +00:00

Commit release 0.01a:

1. Initial Cardatron implementation with CardatronInput (card reader).
2. Implement default Pi demo program at address 0300.
3. Implement WINTER.PI card-load deck to boot from card reader 1 and run at address 0500.
4. Fix syntax typos in tools/BAC-Assembler.html.
This commit is contained in:
Paul Kimpel
2017-05-20 18:34:01 -07:00
parent e66666048b
commit 33c195ae84
21 changed files with 3476 additions and 297 deletions

View File

@@ -77,6 +77,7 @@ function B220Processor(config, devices) {
// Memory
this.memorySize = config.getNode("memorySize"); // memory size, words
this.bcdMemorySize = B220Processor.binaryBCD(this.memorySize);
this.MM = new Float64Array(this.memorySize); // main memory, 11-digit words
this.IB = new B220Processor.Register(11*4, this, true); // memory Input Buffer
@@ -108,6 +109,14 @@ function B220Processor(config, devices) {
this.R = new B220Processor.Register(11*4, this, false);
this.S = new B220Processor.Register( 4*4, this, false);
// Register E decrements modulo the system memory size, so override dec().
this.E.dec = function decE() {
if (this.value == 0) {
this.value = this.p.bcdMemorySize;
}
return this.constructor.prototype.dec.apply(this);
};
// Control Console Lamps
this.digitCheckAlarm = new B220Processor.FlipFlop(this, false);
@@ -232,10 +241,8 @@ function B220Processor(config, devices) {
this.boundConsoleReceiveDigit = B220Processor.bindMethod(this, B220Processor.prototype.consoleReceiveDigit);
this.boundConsoleReceiveSingleDigit = B220Processor.bindMethod(this, B220Processor.prototype.consoleReceiveSingleDigit);
this.boundCardatronOutputWordReady = B220Processor.bindMethod(this, B220Processor.prototype.cardatronOutputWordReady);
this.boundCardatronOutputWord= B220Processor.bindMethod(this, B220Processor.prototype.cardatronOutputWord);
this.boundCardatronOutputFinished = B220Processor.bindMethod(this, B220Processor.prototype.cardatronOutputFinished);
this.boundCardatronInputWord = B220Processor.bindMethod(this, B220Processor.prototype.cardatronInputWord);
this.boundCardatronReceiveWord = B220Processor.bindMethod(this, B220Processor.prototype.cardatronReceiveWord);
this.boundMagTapeReceiveBlock = B220Processor.bindMethod(this, B220Processor.prototype.magTapeReceiveBlock);
@@ -253,7 +260,7 @@ function B220Processor(config, devices) {
* Global Constants *
***********************************************************************/
B220Processor.version = "0.01";
B220Processor.version = "0.01a";
B220Processor.tick = 1000/200000; // milliseconds per clock cycle (200KHz)
B220Processor.cyclesPerMilli = 1/B220Processor.tick;
@@ -561,17 +568,17 @@ B220Processor.prototype.clear = function clear() {
this.COP = 0; // copy of C register op code (2 digits)
this.CADDR = 0; // copy of C register operand address (4 digits)
// I/O globals
this.rDigit = 0; // variant/format digit from control part of instruction
this.vDigit = 0; // variant digit from control part of instruction
this.selectedUnit = 0; // currently-selected unit number
// Kill any pending action that may be in process
if (this.scheduler) {
clearCallback(this.scheduler);
this.scheduler = 0;
}
// Clear Cardatron Control Unit
if (this.cardatron) {
this.cardatron.clear();
}
this.updateGlow(1); // initialize the lamp states
};
@@ -1060,6 +1067,49 @@ B220Processor.prototype.setHighSpeedPrinterCheck = function setHighSpeedPrinterC
};
/***********************************************************************
* Memory Access *
***********************************************************************/
/**************************************/
B220Processor.prototype.readMemory = function readMemory() {
/* Reads the contents of one word of memory into the IB register from the
address in the E register. Sets the Storage Check alarm if the address is
not valid. Returns the word fetched, or the current value of IB if invalid
address */
var addr = B220Processor.bcdBinary(this.E.value);
if (isNaN(addr)) {
this.setStorageCheck(1);
return this.IB.value;
} else if (addr >= this.memorySize) {
this.setStorageCheck(1);
return this.IB.value;
} else if (this.MEMORYLOCKOUTSW) {
return this.IB.set(this.D.value);
} else {
return this.IB.set(this.MM[addr]);
}
};
/**************************************/
B220Processor.prototype.writeMemory = function writeMemory() {
/* Stores one word of memory from the IB register to the address in the E
register. Sets the Storage Check alarm if the address is not valid */
var addr = B220Processor.bcdBinary(this.E.value);
if (isNaN(addr)) {
this.setStorageCheck(1);
} else if (addr >= this.memorySize) {
this.setStorageCheck(1);
} else if (this.MEMORYLOCKOUTSW) {
this.D.set(this.IB.value);
} else {
this.MM[addr] = this.IB.value;
}
};
/***********************************************************************
* The 220 Adder and Arithmetic Operations *
***********************************************************************/
@@ -2263,49 +2313,6 @@ B220Processor.prototype.storeRegister = function storeRegister() {
};
/***********************************************************************
* Memory Access *
***********************************************************************/
/**************************************/
B220Processor.prototype.readMemory = function readMemory() {
/* Reads the contents of one word of memory into the IB register from the
address in the E register. Sets the Storage Check alarm if the address is
not valid. Returns the word fetched, or the current value of IB if invalid
address */
var addr = B220Processor.bcdBinary(this.E.value);
if (isNaN(addr)) {
this.setStorageCheck(1);
return this.IB.value;
} else if (addr >= this.memorySize) {
this.setStorageCheck(1);
return this.IB.value;
} else if (this.MEMORYLOCKOUTSW) {
return this.IB.set(this.D.value);
} else {
return this.IB.set(this.MM[addr]);
}
};
/**************************************/
B220Processor.prototype.writeMemory = function writeMemory() {
/* Stores one word of memory from the IB register to the address in the E
register. Sets the Storage Check alarm if the address is not valid */
var addr = B220Processor.bcdBinary(this.E.value);
if (isNaN(addr)) {
this.setStorageCheck(1);
} else if (addr >= this.memorySize) {
this.setStorageCheck(1);
} else if (this.MEMORYLOCKOUTSW) {
this.D.set(this.IB.value);
} else {
this.MM[addr] = this.IB.value;
}
};
/***********************************************************************
* Console I/O Module *
***********************************************************************/
@@ -2427,7 +2434,7 @@ B220Processor.prototype.consoleOutputSign = function consoleOutputSign(printSign
this.E.set(this.CADDR);
this.readMemory();
if (this.MET.value) { // invalid address
this.ioComplete();
this.ioComplete(true);
} else {
this.D.set(this.IB.value);
this.opTime += 0.070; // estimate for memory access and rotation
@@ -2517,7 +2524,7 @@ B220Processor.prototype.consoleOutputFinished = function consoleOutputFinished()
this.clockIn();
if (this.AST.value) { // if false, we've probably been cleared
this.EWT.set(0);
this.ioComplete();
this.ioComplete(true);
}
};
@@ -2574,8 +2581,8 @@ B220Processor.prototype.consoleReceiveDigit = function consoleReceiveDigit(digit
this.CCONTROL = this.bcdAdd(this.CADDR, 1, 4);
}
this.CEXTRA = (this.D.value - word%0x1000000)/0x1000000;
this.kDigit = (this.CEXTRA >>> 8) & 0x0F;
this.CCONTROL = (this.D.value - word%0x1000000)/0x1000000;
this.rDigit = (this.CCONTROL >>> 8) & 0x0F;
// do not set this.selectedUnit from the word -- keep the same unit
// Shift D5-D10 into C1-C6, modify by B as necessary, and execute
@@ -2654,175 +2661,113 @@ B220Processor.prototype.consoleReceiveSingleDigit = function consoleReceiveSingl
***********************************************************************/
/**************************************/
B220Processor.prototype.cardatronOutputWordReady = function cardatronOutputWordReady() {
/* Successor function for readMemory that sets up the next word of output
and calls the current ioCallback function to output that word */
if (this.tog3IO) { // if false, we've probably been cleared
this.SHIFT = 0x09; // for display only
this.A.set(this.D.value); // move D with the memory word to A
this.togTWA = 1; // for display only
this.execTime -= performance.now()*B220Processor.wordsPerMilli;
this.ioCallback(this.A.value, this.boundCardatronOutputWord, this.boundCardatronOutputFinished);
}
};
/**************************************/
B220Processor.prototype.cardatronOutputWord = function cardatronOutputWord(receiver) {
B220Processor.prototype.cardatronOutputWord = function cardatronOutputWord() {
/* Initiates a read of the next word from memory for output to the
Cardatron Control Unit */
Cardatron Control Unit. Returns a negative number to stop transfer */
var word;
this.execTime += performance.now()*B220Processor.wordsPerMilli;
if (this.tog3IO) { // if false, we've probably been cleared
// Increment the source address (except on the first word)
this.SHIFTCONTROL = 0x01; // for display only
this.SHIFT = 0x15; // for display only
if (this.togCOUNT) {
this.CADDR = this.bcdAdd(this.CADDR, 1, 4);
this.clockIn();
if (!this.AST.value) { // we've probably been cleared
word = -1;
} else if (this.MET.value) { // previous memory access error
word = 0;
} else {
word = this.readMemory(); // address in E was previously set
if (this.MET.value) {
word = 0;
} else {
this.togCOUNT = 1;
this.E.dec(); // step down to next memory address
}
this.C.set((this.COP*0x10000 + this.CADDR)*0x10000 + this.CCONTROL);
this.ioCallback = receiver;
this.readMemory(this.boundCardatronOutputWordReady);
}
return word;
};
/**************************************/
B220Processor.prototype.cardatronOutputFinished = function cardatronOutputFinished() {
/* Handles the final cycle of an I/O operation and restores this.execTime */
if (this.tog3IO) { // if false, we've probably been cleared
this.tog3IO = 0;
this.togTWA = 0; // for display only
this.execTime += performance.now()*B220Processor.wordsPerMilli;
this.schedule();
if (this.AST.value) { // if false, we've probably been cleared
this.ioComplete(true);
}
};
/**************************************/
B220Processor.prototype.cardatronInputWord = function cardatronInputWord() {
// Solicits the next input word from the Cardatron Control Unit */
this.togTF = 0; // for display only, reset finish pulse
this.togTWA = 1; // for display only
this.execTime -= performance.now()*B220Processor.wordsPerMilli; // mark time during I/O
this.cardatron.inputWord(this.selectedUnit, this.boundCardatronReceiveWord);
};
/**************************************/
B220Processor.prototype.cardatronReceiveWord = function cardatronReceiveWord(word) {
/* Handles a word coming from the Cardatron input unit. Negative values for
the word indicate the last word was previously sent and the I/O is finished.
The word is stored into the D register and is handled according to the sign
digit in the D register. Any partial word received at the end of the
I/O is abandoned */
the word indicates this is the last word and the I/O is finished. The word
is stored into the D register and is handled according to the sign digit in
the D register. The last word received (typically a "pusher" word of zeroes)
is abandoned and not acted upon. Returns -1 if further data transfer is to
be terminated, 0 otherwise */
var returnCode = 0; // default is to continue receiving
var sign; // D-register sign digit
this.execTime += performance.now()*B220Processor.wordsPerMilli; // restore time after I/O
if (word < 0) {
this.clockIn();
if (!this.AST.value) { // we've probably been cleared
returnCode = -1;
} else if (word < 0) {
// Last word received -- finished with the I/O
this.tog3IO = 0;
this.togSTART = 0;
this.togTF = 0; // for display only
this.togTWA = 0; // for display only
this.D.set(word-900000000000); // remove the finished signal; for display only, not stored
this.schedule();
this.D.set(word-0x900000000000);// remove the finished signal; for display only, not stored
this.ioComplete(true);
returnCode = -1;
} else if (this.MET.value) {
// Memory error has occurred: just ignore further data from Cardatron
} else {
// Full word accumulated -- process it and initialize for the next word
this.SHIFT = 0x19; // for display only
this.togTF = 1; // for display only
this.D.set(word);
word %= 0x10000000000; // strip the sign digit
sign = (this.D.value - word)/0x10000000000; // get D-sign
if (sign & 0x04) {
// D-sign is 4, 5, 6, 7: execute the word as an instruction
this.execTime += 2;
this.togTF = 0; // for display only
this.togSTART = 1-((sign >>> 1)%2); // whether to continue in input mode
this.setTimingToggle(0); // Execute mode
this.togCOUNT = 0;
this.togBTOAIN = 0;
this.togADDAB = 1; // for display only
this.togADDER = 1; // for display only
this.togDPCTR = 1; // for display only
this.togCLEAR = ((this.kDigit & 0x08) ? 1 : 1-(sign%2));
this.togSIGN = ((this.A.value - this.A.value%0x10000000000)/0x10000000000)%2; // display only
this.CEXTRA = (this.D - word%0x1000000)/0x1000000;
this.kDigit = (this.CEXTRA >>> 8) & 0x0F;
// do not set this.selectedUnit from the word -- keep the same unit
// Shift D5-D10 into C1-C6, modify by B as necessary, and execute
if (this.togCLEAR) {
word = this.bcdAdd(word%0x1000000, 0, 11);
} else {
word = this.bcdAdd(word%0x1000000, this.B.value, 11) % 0x1000000;
}
this.C.set(word*0x10000 + this.CCONTROL); // put C back together
this.CADDR = word % 0x10000;
this.COP = (word - this.CADDR)/0x10000;
if (sign & 0x02) { // sign-6 or -7
this.tog3IO = 0;
this.togTF = 0; // for display only
this.cardatron.inputStop(this.selectedUnit);
this.execute();
} else { // sign-4 or -5
/* It's not exactly clear what should happen at this point. The
documentation states that a sign-4 or -5 word coming from a Cardatron
input unit can only contain a CDR (44) instruction, which is sensible,
since sign-4/5 words are generally used to change the destination memory
address for the data transfer, and the Cardatron presumably still had
words to transfer. What it doesn't say is what happened if the sign-4/5
word contained something else. My guess is that either the Processor
ignored any other op code and proceeded as if it had been a CDR, or more
likely, things went to hell in a handbasket. The latter is a little
difficult to emulate, especially since we don't know which hell or
handbasket might be involved, so we'll assume the former, and just
continue requesting words from the Cardatron */
this.SHIFT = 0x09; // reset shift counter for next word
this.D.set(0); // clear D to prepare for next word
this.cardatronInputWord(); // request the next word
}
} else {
// D-sign is 0, 1, 2, 3, 8, 9: store word, possibly modified by B
this.execTime += 3;
this.setTimingToggle(1); // Fetch mode
this.togCOUNT = this.togBTOAIN;
this.togBTOAIN = 1;
this.togADDAB = 1; // for display only
this.togADDER = 1; // for display only
this.togDPCTR = 1; // for display only
this.togSIGN = sign%2;
if (this.kDigit & 0x08) {
this.togCLEAR = 1;
} else {
this.togCLEAR = 1-((sign >>> 1)%2);
sign &= 0x0D;
switch (sign) {
case 0: // sign is 0-5: store word normally
case 1:
case 2:
case 3:
case 4:
case 5:
this.IB.set(this.D.value);
this.writeMemory();
if (!this.MET.value) {
this.E.dec(); // decrement memory address for next word
}
break;
// Increment the destination address (except on the first word)
this.SHIFTCONTROL = 0x01; // for display only
this.SHIFT = 0x15; // for display only
if (this.togCOUNT) {
this.CADDR = this.bcdAdd(this.CADDR, 1, 4);
case 6: // sign is 6, 7: execute control word
case 7:
if (this.vDigit & 0x01) { // input control words are inhibited
this.IB.set(this.D.value);
this.writeMemory(); // just store the word with its sign
if (!this.MET.value) {
this.E.dec(); // decrement memory address for next word
}
} else { // input control words are executed
this.IB.set(this.D.value); // move word to IB for use by fetch()
this.ioComplete(false); // terminate I/O but do not restart Processor yet
this.fetch(true); // set up to execute control word
returnCode = -1; // stop further input from Cardatron
// Schedule the Processor to give Cardatron a chance to finish its operation.
setCallback(this.mnemonic, this, 0, this.schedule);
}
this.C.set((this.COP*0x10000 + this.CADDR)*0x10000 + this.CCONTROL);
break;
// Modify the word by B as necessary and store it
if (this.togCLEAR) {
word = this.bcdAdd(word, 0, 11);
} else {
word = this.bcdAdd(word, this.B.value, 11);
default: // sign is 8, 9: store word with optional B mod
if (!(this.rDigit & 0x08)) { // no B-register modification
this.IB.set(this.D.value);
} else { // add B to low-order five digits of word
word = word - word%0x100000 + this.bcdAdd(word, this.B.value, 5);
this.C10.set(0); // reset carry toggle
this.IB.set((sign%2)*0x10000000000 + word);
}
this.A.set(sign*0x10000000000 + word%0x10000000000);
this.SHIFT = 0x09; // reset shift counter for next word
this.D.set(0); // clear D and request the next word after storing this one
this.writeMemory(this.boundCardatronInputWord, false);
}
this.writeMemory();
if (!this.MET.value) {
this.E.dec(); // decrement memory address for next word
}
break;
} // switch sign
}
return returnCode;
};
/***********************************************************************
@@ -3047,18 +2992,18 @@ B220Processor.prototype.fetchWordToC = function fetchWordToC(word) {
};
/**************************************/
B220Processor.prototype.fetch = function fetch() {
B220Processor.prototype.fetch = function fetch(entryP) {
/* Implements the Fetch cycle of the 220 processor. This is initiated either
by pressing START on the Console with EXT=0 (Fetch), pressing STEP on the
Console when the computer is stopped and EXT=0, during I/O when a control
word (sign>3) is received from a peripheral device, or by the prior
Operation Complete if the processor is in continuous mode. Note that the
time for fetch is built into the individual instruction times, and is
accumulated here only if the Execute cycle is skipped */
word (sign 6,7) is received from a peripheral device, or by the prior
Operation Complete if the processor is in continuous mode. The "entryP"
parameter indicates whether the instruction word is already in IB (true)
or must be fetched from the address in P first (false) */
var dSign; // sign bit of IB register
var word; // instruction word
if (this.AST.value) { // if doing I/O
if (entryP) { // if instruction already loaded
word = this.IB.value;
} else { // if doing normal fetch
this.E.set(this.P.value);
@@ -3070,7 +3015,7 @@ B220Processor.prototype.fetch = function fetch() {
this.fetchWordToC(word);
this.D.set(word); // D contains a copy of memory word
if (!this.AST.value && !this.PCOUNTSW) {
if (!entryP && !this.PCOUNTSW) {
this.P.inc(); // if not doing I/O, bump the program counter
}
}
@@ -3150,7 +3095,7 @@ B220Processor.prototype.execute = function execute() {
d = this.console.outputUnitSelect(d, this.boundConsoleOutputSign);
if (d < 0) { // no unit available -- set alarm and quit
this.setPaperTapeCheck(1);
this.ioComplete();
this.ioComplete(true);
}
break;
@@ -3182,7 +3127,7 @@ B220Processor.prototype.execute = function execute() {
d = this.console.outputUnitSelect(0, this.boundConsoleOutputSign);
if (d < 0) { // no unit available -- set alarm and quit
this.setPaperTapeCheck(1);
this.ioComplete();
this.ioComplete(true);
}
break;
@@ -3677,8 +3622,23 @@ B220Processor.prototype.execute = function execute() {
break;
case 0x60: //--------------------- CRD Card read
this.setProgramCheck(1);
this.operationComplete();
this.opTime = 1.600; // rough minimum estimage
this.E.set(this.CADDR);
this.D.set(0);
if (!this.cardatron) {
this.setCardatronCheck(1);
this.operationComplete();
} else {
this.selectedUnit = (this.CCONTROL >>> 12) & 0x0F;
this.rDigit = this.CCONTROL & 0x0F;
this.vDigit = (this.CCONTROL >>> 4) & 0x0F;
this.ioInitiate();
d = this.cardatron.inputInitiate(this.selectedUnit, this.rDigit, this.boundCardatronReceiveWord);
if (d < 0) { // invalid unit
this.setCardatronCheck(1);
this.ioComplete(true);
}
}
break;
case 0x61: //--------------------- CWR Card write
@@ -3688,6 +3648,23 @@ B220Processor.prototype.execute = function execute() {
case 0x62: //--------------------- CRF Card read, format load
this.setProgramCheck(1);
this.opTime = 2.940; // rough minimum estimage
this.E.set(this.CADDR);
this.D.set(0);
if (!this.cardatron) {
this.setCardatronCheck(1);
this.operationComplete();
} else {
this.selectedUnit = (this.CCONTROL >>> 12) & 0x0F;
this.rDigit = this.CCONTROL & 0x0F;
this.ioInitiate();
d = this.cardatron.inputFormatInitiate(this.selectedUnit, this.rDigit,
this.boundCardatronOutputWord, this.boundCardatronOutputFinished);
if (d < 0) { // invalid unit
this.setCardatronCheck(1);
this.ioComplete(true);
}
}
this.operationComplete();
break;
@@ -3697,7 +3674,22 @@ B220Processor.prototype.execute = function execute() {
break;
case 0x64: //--------------------- CRI Card read interrogate, branch
this.setProgramCheck(1);
this.opTime = 0.265; // average
this.E.set(this.CADDR);
this.D.set(0);
if (!this.cardatron) {
this.setCardatronCheck(1);
} else {
this.E.set(this.CADDR);
this.selectedUnit = (this.CCONTROL >>> 12) & 0x0F;
d = this.cardatron.inputReadyInterrogate(this.selectedUnit);
if (d < 0) { // invalid unit
this.setCardatronCheck(1);
} else if (d > 0) {
this.opTime += 0.020;
this.P.set(this.CADDR);
}
}
this.operationComplete();
break;
@@ -3736,8 +3728,8 @@ B220Processor.prototype.execute = function execute() {
if (!this.magTape) {
//this.schedule();
} else {
this.selectedUnit = (this.CEXTRA >>> 4) & 0x0F;
d = (this.CEXTRA >>> 8) & 0xFF; // number of blocks
this.selectedUnit = (this.CCONTROL >>> 4) & 0x0F;
d = (this.CCONTROL >>> 8) & 0xFF; // number of blocks
this.togMT3P = 1;
this.togMT1BV4 = d%2; // select initial loop buffer
this.togMT1BV5 = 1-this.togMT1BV4;
@@ -3752,8 +3744,8 @@ B220Processor.prototype.execute = function execute() {
case 0x42: //---------------- MTS Magnetic Tape Search
if (this.magTape) {
this.selectedUnit = (this.CEXTRA >>> 4) & 0x0F;
d = (this.CEXTRA >>> 8) & 0xFF; // lane number
this.selectedUnit = (this.CCONTROL >>> 4) & 0x0F;
d = (this.CCONTROL >>> 8) & 0xFF; // lane number
if (this.magTape.search(this.selectedUnit, d, this.CADDR)) {
this.OFT.set(1); // control or tape unit busy/not-ready
}
@@ -3761,52 +3753,12 @@ B220Processor.prototype.execute = function execute() {
//this.schedule();
break;
case 0x44: //---------------- CDR Card Read (Cardatron)
this.D.set(0);
if (!this.cardatron) {
//this.schedule();
} else {
this.tog3IO = 1;
this.kDigit = (this.CEXTRA >>> 8) & 0x0F;
this.selectedUnit = (this.CEXTRA >>> 4) & 0x07;
this.SHIFT = 0x08; // prepare to receive 11 digits
this.execTime -= performance.now()*B220Processor.wordsPerMilli; // mark time during I/O
this.cardatron.inputInitiate(this.selectedUnit, this.kDigit, this.boundCardatronReceiveWord);
}
break;
case 0x45: //---------------- CDRI Card Read Interrogate
this.selectedUnit = (this.CEXTRA >>> 4) & 0x07;
if (this.cardatron && this.cardatron.inputReadyInterrogate(this.selectedUnit)) {
this.R.set(this.CCONTROL*0x1000000);
this.setTimingToggle(0); // stay in Execute
this.OFT.set(1); // set overflow
this.COP = 0x28; // make into a CC
this.C.set((this.COP*0x10000 + this.CADDR)*0x10000 + this.CCONTROL);
}
//this.schedule();
break;
case 0x48: //---------------- CDRF Card Read Format
if (!this.cardatron) {
//this.schedule();
} else {
this.tog3IO = 1;
this.kDigit = (this.CEXTRA >>> 8) & 0x0F;
this.selectedUnit = (this.CEXTRA >>> 4) & 0x07;
this.SHIFT = 0x19; // start at beginning of a word
this.execTime -= performance.now()*B220Processor.wordsPerMilli; // mark time during I/O
this.cardatron.inputFormatInitiate(this.selectedUnit, this.kDigit,
this.boundCardatronOutputWord, this.boundCardatronOutputFinished);
}
break;
case 0x50: //---------------- MTW Magnetic Tape Write
if (!this.magTape) {
//this.schedule();
} else {
this.selectedUnit = (this.CEXTRA >>> 4) & 0x0F;
d = (this.CEXTRA >>> 8) & 0xFF; // number of blocks
this.selectedUnit = (this.CCONTROL >>> 4) & 0x0F;
d = (this.CCONTROL >>> 8) & 0xFF; // number of blocks
this.togMT3P = 1;
this.togMT1BV4 = d%2; // select initial loop buffer
this.togMT1BV5 = 1-this.togMT1BV4;
@@ -3821,7 +3773,7 @@ B220Processor.prototype.execute = function execute() {
case 0x52: //---------------- MTRW Magnetic Tape Rewind
if (this.magTape) {
this.selectedUnit = (this.CEXTRA >>> 4) & 0x0F;
this.selectedUnit = (this.CCONTROL >>> 4) & 0x0F;
if (this.magTape.rewind(this.selectedUnit)) {
this.OFT.set(1); // control or tape unit busy/not-ready
}
@@ -3833,17 +3785,17 @@ B220Processor.prototype.execute = function execute() {
//this.schedule();
} else {
this.tog3IO = 1;
this.kDigit = (this.CEXTRA >>> 8) & 0x0F;
this.selectedUnit = (this.CEXTRA >>> 4) & 0x07;
this.kDigit = (this.CCONTROL >>> 8) & 0x0F;
this.selectedUnit = (this.CCONTROL >>> 4) & 0x07;
this.SHIFT = 0x19; // start at beginning of a word
this.execTime -= performance.now()*B220Processor.wordsPerMilli; // mark time during I/O
this.cardatron.outputInitiate(this.selectedUnit, this.kDigit, (this.CEXTRA >>> 12) & 0x0F,
this.cardatron.outputInitiate(this.selectedUnit, this.kDigit, (this.CCONTROL >>> 12) & 0x0F,
this.boundCardatronOutputWord, this.boundCardatronOutputFinished);
}
break;
case 0x55: //---------------- CDWI Card Write Interrogate
this.selectedUnit = (this.CEXTRA >>> 4) & 0x07;
this.selectedUnit = (this.CCONTROL >>> 4) & 0x07;
if (this.cardatron && this.cardatron.outputReadyInterrogate(this.selectedUnit)) {
this.R.set(this.CCONTROL*0x1000000);
this.setTimingToggle(0); // stay in Execute
@@ -3858,8 +3810,8 @@ B220Processor.prototype.execute = function execute() {
//this.schedule();
} else {
this.tog3IO = 1;
this.kDigit = (this.CEXTRA >>> 8) & 0x0F;
this.selectedUnit = (this.CEXTRA >>> 4) & 0x07;
this.kDigit = (this.CCONTROL >>> 8) & 0x0F;
this.selectedUnit = (this.CCONTROL >>> 4) & 0x07;
this.SHIFT = 0x19; // start at beginning of a word
this.execTime -= performance.now()*B220Processor.wordsPerMilli; // mark time during I/O
this.cardatron.outputFormatInitiate(this.selectedUnit, this.kDigit,
@@ -3911,9 +3863,10 @@ B220Processor.prototype.operationComplete = function operationComplete() {
};
/**************************************/
B220Processor.prototype.ioComplete = function ioComplete() {
B220Processor.prototype.ioComplete = function ioComplete(restart) {
/* Implements completion of the Execute cycle for an I/O instruction that
has been executing asynchronously */
has been executing asynchronously. If "restart" is true, the Processor will
resume automatic operation */
this.AST.set(0);
this.clockIn();
@@ -3922,7 +3875,7 @@ B220Processor.prototype.ioComplete = function ioComplete() {
}
this.operationComplete();
if (this.RUT.value) {
if (restart && this.RUT.value) {
this.schedule();
}
};
@@ -3968,7 +3921,7 @@ B220Processor.prototype.run = function run() {
}
}
this.fetch();
this.fetch(false);
if (this.SST.value) {
this.stop(); // single-stepping
}
@@ -4199,20 +4152,6 @@ B220Processor.prototype.tcuClear = function tcuClear() {
}
};
/**************************************/
B220Processor.prototype.inputSetup = function inputSetup(unitNr) {
/* Called from the Cardatron Control Unit. If the Processor is stopped,
loads a CDR (60) instruction into C for unit "unitNr" and sets Execute cycle */
if (this.poweredOn && !this.RUT.value) {
this.CONTROL = unitNr*0x1000; // recognize control words, no lockout
this.COP = 0x60; // CDR instruction
this.CADDR = 0;
this.C.set((this.CCONTROL*0x100 + this.COP)*0x10000 + this.CADDR);
this.EXT.set(1);
}
};
/**************************************/
B220Processor.prototype.powerUp = function powerUp() {
/* Powers up the system */
@@ -4343,7 +4282,7 @@ B220Processor.prototype.loadDefaultProgram = function loadDefaultProgram() {
this.MM[ 229] = 0;
this.MM[ 230] = 0;
this.MM[ 231] = 0;
this.MM[ 232] = 0x20000000016; // carriage return
this.MM[ 232] = 0x20202020216; // carriage return
this.MM[ 233] = 0x05110000000; // 1.0 literal: argument increment
this.MM[ 234] = 0x05120000000; // 2.0 literal
this.MM[ 235] = 0x05099999990; // 0.99999990 literal: target precision
@@ -4351,4 +4290,92 @@ B220Processor.prototype.loadDefaultProgram = function loadDefaultProgram() {
this.MM[ 237] = 0; // current sqrt result
this.MM[ 238] = 0; // current upper bound on result
this.MM[ 239] = 0x05120000000; // 2.0 sqrt argument
// Print first 800 digits of Pi; adapted from C program by Dik Winter of CWI, Amsterdam
this.MM[ 300]= 0x00000100371; // CAD FLIM
this.MM[ 301]= 0x00000400365; // STA C C=FLIM
this.MM[ 302]= 0x00000100363; // CAD A
this.MM[ 303]= 0x00001480010; // SRT 10
this.MM[ 304]= 0x00000150375; // DIV FIVE A DIV 5
this.MM[ 305]= 0x00000420365; // LDB C FOR (B=C; B>=0; --B)
this.MM[ 306]= 0x10000401000; // STA - F F[B]=A DIV 5
this.MM[ 307]= 0x00001210306; // DBB *-1,1
this.MM[ 308]= 0x00000100365; // L1 CAD C START OF OUTER LOOP
this.MM[ 309]= 0x00000140374; // MUL TWO
this.MM[ 310]= 0x00001400368; // STR G G=C*2
this.MM[ 311]= 0x00000370362; // BFR ENDL1,00,00 IF G EQL 0, BRANCH OUT OF LOOP
this.MM[ 312]= 0x00000460366; // CLL D D=0
this.MM[ 313]= 0x00000100365; // CAD C
this.MM[ 314]= 0x00000400364; // STA B B=C
this.MM[ 315]= 0x00000420364; // LDB B
this.MM[ 316]= 0x10000101000; // DO CAD - F START OF INNER LOOP
this.MM[ 317]= 0x00000140363; // MUL A F[B]*A
this.MM[ 318]= 0x00001490010; // SLT 10 SHIFT PRODUCT TO RA
this.MM[ 319]= 0x00000120366; // ADD D
this.MM[ 320]= 0x00000400366; // STA D D+=F[B]*A
this.MM[ 321]= 0x00001480010; // SRT 10 SAVE NEW D IN RR
this.MM[ 322]= 0x00001270368; // DFL G,00,1 G-=1
this.MM[ 323]= 0x00000150368; // DIV G D DIV G
this.MM[ 324]= 0x10001401000; // STR - F F[B]=D MOD G
this.MM[ 325]= 0x00000400366; // STA D D=D DIV G
this.MM[ 326]= 0x00001270368; // DFL G,00,1 G-=1
this.MM[ 327]= 0x00000100364; // CAD B
this.MM[ 328]= 0x00000130373; // SUB ONE
this.MM[ 329]= 0x00000400364; // STA B B-=1
this.MM[ 330]= 0x00000360334; // BFA ENDDO,00,00 IF B EQL 0, BRANCH OUT OF INNER LOOP
this.MM[ 331]= 0x00000140366; // MUL D
this.MM[ 332]= 0x00001400366; // STR D D*=B
this.MM[ 333]= 0x00001210316; // DBB DO,1 DECREMENT RB, REPEAT INNER LOOP IF >= 0
this.MM[ 334]= 0x00014270365; // ENDDO DFL C,00,14 C-=14
this.MM[ 335]= 0x00000100366; // CAD D
this.MM[ 336]= 0x00001480010; // SRT 10
this.MM[ 337]= 0x00000150363; // DIV A D DIV A
this.MM[ 338]= 0x00000120367; // ADD E RA=E+D DIV A
this.MM[ 339]= 0x00001400367; // STR E E=D MOD A
// FORMAT 4 DIGITS FOR SPO OUTPUT
this.MM[ 340]= 0x00001480003; // SRT 3 ISOLATE HIGH-ORDER DIGIT IN A
this.MM[ 341]= 0x00000120376; // ADD N80 CONVERT 1ST DIGIT TO ALPHA
this.MM[ 342]= 0x00000490001; // SLA 1
this.MM[ 343]= 0x00001490001; // SLT 1
this.MM[ 344]= 0x00000120376; // ADD N80 CONVERT 2ND DIGIT TO ALPHA
this.MM[ 345]= 0x00000490001; // SLA 1
this.MM[ 346]= 0x00001490001; // SLT 1
this.MM[ 347]= 0x00000120376; // ADD N80 CONVERT 3RD DIGIT TO ALPHA
this.MM[ 348]= 0x00000490001; // SLA 1
this.MM[ 349]= 0x00001490001; // SLT 1
this.MM[ 350]= 0x00000120376; // ADD N80 CONVERT 4TH DIGIT TO ALPHA
this.MM[ 351]= 0x00000490002; // SLA 2 INSERT TRAILING SPACE
this.MM[ 352]= 0x00002430000; // LSA 2 SET SIGN TO TWO FOR ALPHA WORD
this.MM[ 353]= 0x00000400364; // STA B STORE IN WORD BUFFER
this.MM[ 354]= 0x00010090364; // SPO B,1
this.MM[ 355]= 0x00405260369; // IFL COL,04,1 CHECK FOR FULL LINE ON SPO
this.MM[ 356]= 0x00000100369; // CAD COL
this.MM[ 357]= 0x00000180370; // CFA ECOL
this.MM[ 358]= 0x00001340308; // BCL L1 IF COL < ECOL, BRANCH
this.MM[ 359]= 0x00010090377; // SPO CR,1 OUTPUT NEWLINES
this.MM[ 360]= 0x00000460369; // CLL COL CLEAR COLUMN COUNTER
this.MM[ 361]= 0x00000300308; // BUN L1
this.MM[ 362]= 0x00000007557; // ENDL1 HLT 7557
this.MM[ 363]= 0x00000010000; // A CNST 10000
this.MM[ 364]= 0x00000000000; // B CNST 0
this.MM[ 365]= 0x00000000000; // C CNST 0
this.MM[ 366]= 0x00000000000; // D CNST 0
this.MM[ 367]= 0x00000000000; // E CNST 0
this.MM[ 368]= 0x00000000000; // G CNST 0
this.MM[ 369]= 0x00000000000; // COL CNST 0
this.MM[ 370]= 0x00000000050; // ECOL CNST 50
this.MM[ 371]= 0x00000002800; // FLIM CNST 2800
this.MM[ 372]= 0x00000000000; // ZERO CNST 0
this.MM[ 373]= 0x00000000001; // ONE CNST 1
this.MM[ 374]= 0x00000000002; // TWO CNST 2
this.MM[ 375]= 0x00000000005; // FIVE CNST 5
this.MM[ 376]= 0x00000000080; // N80 CNST 80
this.MM[ 377]= 0x20202021616; // CR CNST 20202021616 NEWLINES
this.MM[1000]= 0x00000000000; // F DEFN * ARRAY F[2800]
};

View File

@@ -0,0 +1,17 @@
777 PRINT FIRST 800 DIGITS OF PI
777 ADAPTED BY P.KIMPEL FROM C PROGRAM BY DIK WINTER OF CWI, AMSTERDAM
666 61000600505
66661000600511000001005710000040056500000100563000014800100000015057500000420565
66661000600517100004010000000121050600000100565000001405740000140056800000370562
66661000600523000004605660000010056500000400564000004205641000010100000000140563
66661000600529000014900100000012056600000400566000014800100000127056800000150568
66661000600535100014010000000040056600001270568000001005640000013057300000400564
66661000600541000003605340000014056600001400566000012105160001427056500000100566
66661000600547000014800100000015056300000120567000014005670000148000300000120576
66661000600553000004900010000149000100000120576000004900010000149000100000120576
66661000600559000004900010000149000100000120576000004900020000243000000000400564
66661000600562000100905640040526056900000100569000001805700000134050800010090577
666 61000600568000004605690000030050800000007557
66661000600574000000100000000000000000000000000000000000000000000000000000000000
66661000600577000000000000000000005000000002800000000000000000000000100000000002
666 60000300500000000000050000000008020202021616

View File

@@ -0,0 +1,93 @@
1 REM PRINT FIRST 800 DIGITS OF PI
1 REM ADAPTED FROM C PROGRAM B DIK WINTER OF CWI, AMSTERDAM
LOCN 0300
CAD FLIM
STA C C=FLIM
CAD A
SRT 10
DIV FIVE A DIV 5
LDB C FOR (B=C; B>=0; --B)
STA - F F[B]=A DIV 5
DBB *-1,1
REM
L1 CAD C START OF OUTER LOOP
MUL TWO
STR G G=C*2
BFR ENDL1,00,00 IF G EQL 0, BRANCH OUT OF LOOP
CLL D D=0
CAD C
STA B B=C
LDB B
REM
DO CAD - F START OF INNER LOOP
MUL A F[B]*A
SLT 10 SHIFT PRODUCT TO RA
ADD D
STA D D+=F[B]*A
SRT 10 SAVE NEW D IN RR
DFL G,00,1 G-=1
DIV G D DIV G
STR - F F[B]=D MOD G
STA D D=D DIV G
DFL G,00,1 G-=1
CAD B
SUB ONE
STA B B-=1
BFA ENDDO,00,00 IF B EQL 0, BRANCH OUT OF INNER LOOP
MUL D
STR D D*=B
DBB DO,1 DECREMENT RB, REPEAT INNER LOOP IF >= 0
REM
ENDDO DFL C,00,14 C-=14
CAD D
SRT 10
DIV A D DIV A
ADD E RA=E+D DIV A
STR E E=D MOD A
REM
REM FORMAT 4 DIGITS FOR SPO OUTPUT
SRT 3 ISOLATE HIGH-ORDER DIGIT IN A
ADD N80 CONVERT 1ST DIGIT TO ALPHA
SLA 1
SLT 1
ADD N80 CONVERT 2ND DIGIT TO ALPHA
SLA 1
SLT 1
ADD N80 CONVERT 3RD DIGIT TO ALPHA
SLA 1
SLT 1
ADD N80 CONVERT 4TH DIGIT TO ALPHA
SLA 2 INSERT TRAILING SPACE
LSA 2 SET SIGN TO TWO FOR ALPHA WORD
STA B STORE IN WORD BUFFER
SPO B,1
IFL COL,04,5 CHECK FOR FULL LINE ON SPO
CAD COL
CFA ECOL
BCL L1 IF COL < ECOL, BRANCH
SPO CR,1 OUTPUT NEWLINES
CLL COL CLEAR COLUMN COUNTER
BUN L1
ENDL1 HLT 7557
REM
REM SCALARS
A CNST 10000
B CNST 0
C CNST 0
D CNST 0
E CNST 0
G CNST 0
COL CNST 0
ECOL CNST 50
FLIM CNST 2800
ZERO CNST 0
ONE CNST 1
TWO CNST 2
FIVE CNST 5
N80 CNST 80
CR CNST 20202021616 NEWLINES
REM
LOCN 1000
F DEFN *
LOCN *+2800
FINI 300

View File

@@ -0,0 +1,153 @@
Assembler for the Burroughs 220 BALGOL Compiler & Intrinsics
Pass 1 Listing Pass 2 Listing
END OF PASS 1, ERRORS = 0
SYMBOL TABLE
363 A 364 B 1 BMOD 365 C 369 COL
377 CR 366 D 316 DO 367 E 370 ECOL
334 ENDDO 362 ENDL1 1000 F 375 FIVE 371 FLIM
368 G 308 L1 376 N80 373 ONE 1 RLO
374 TWO 372 ZERO
PRINT FIRST 800 DIGITS OF PI
ADAPTED FROM C PROGRAM B DIK WINTER OF CWI, AMSTERDAM
3 0000 LOCN 0300
4 0300 0 0000 10 0371 CAD FLIM
5 0301 0 0000 40 0365 STA C C=FLIM
6 0302 0 0000 10 0363 CAD A
7 0303 0 0001 48 0010 SRT 10
8 0304 0 0000 15 0375 DIV FIVE A DIV 5
9 0305 0 0000 42 0365 LDB C FOR (B=C; B>=0; --B)
10 0306 1 0000 40 1000 STA - F F[B]=A DIV 5
11 0307 0 0001 21 0306 DBB *-1,1
13 0308 0 0000 10 0365 L1 CAD C START OF OUTER LOOP
14 0309 0 0000 14 0374 MUL TWO
15 0310 0 0001 40 0368 STR G G=C*2
16 0311 0 0000 37 0362 BFR ENDL1,00,00 IF G EQL 0, BRANCH OUT OF LOOP
17 0312 0 0000 46 0366 CLL D D=0
18 0313 0 0000 10 0365 CAD C
19 0314 0 0000 40 0364 STA B B=C
20 0315 0 0000 42 0364 LDB B
22 0316 1 0000 10 1000 DO CAD - F START OF INNER LOOP
23 0317 0 0000 14 0363 MUL A F[B]*A
24 0318 0 0001 49 0010 SLT 10 SHIFT PRODUCT TO RA
25 0319 0 0000 12 0366 ADD D
26 0320 0 0000 40 0366 STA D D+=F[B]*A
27 0321 0 0001 48 0010 SRT 10 SAVE NEW D IN RR
28 0322 0 0001 27 0368 DFL G,00,1 G-=1
29 0323 0 0000 15 0368 DIV G D DIV G
30 0324 1 0001 40 1000 STR - F F[B]=D MOD G
31 0325 0 0000 40 0366 STA D D=D DIV G
32 0326 0 0001 27 0368 DFL G,00,1 G-=1
33 0327 0 0000 10 0364 CAD B
34 0328 0 0000 13 0373 SUB ONE
35 0329 0 0000 40 0364 STA B B-=1
36 0330 0 0000 36 0334 BFA ENDDO,00,00 IF B EQL 0, BRANCH OUT OF INNER LOOP
37 0331 0 0000 14 0366 MUL D
38 0332 0 0001 40 0366 STR D D*=B
39 0333 0 0001 21 0316 DBB DO,1 DECREMENT RB, REPEAT INNER LOOP IF >= 0
41 0334 0 0014 27 0365 ENDDO DFL C,00,14 C-=14
42 0335 0 0000 10 0366 CAD D
43 0336 0 0001 48 0010 SRT 10
44 0337 0 0000 15 0363 DIV A D DIV A
45 0338 0 0000 12 0367 ADD E RA=E+D DIV A
46 0339 0 0001 40 0367 STR E E=D MOD A
FORMAT 4 DIGITS FOR SPO OUTPUT
49 0340 0 0001 48 0003 SRT 3 ISOLATE HIGH-ORDER DIGIT IN A
50 0341 0 0000 12 0376 ADD N80 CONVERT 1ST DIGIT TO ALPHA
51 0342 0 0000 49 0001 SLA 1
52 0343 0 0001 49 0001 SLT 1
53 0344 0 0000 12 0376 ADD N80 CONVERT 2ND DIGIT TO ALPHA
54 0345 0 0000 49 0001 SLA 1
55 0346 0 0001 49 0001 SLT 1
56 0347 0 0000 12 0376 ADD N80 CONVERT 3RD DIGIT TO ALPHA
57 0348 0 0000 49 0001 SLA 1
58 0349 0 0001 49 0001 SLT 1
59 0350 0 0000 12 0376 ADD N80 CONVERT 4TH DIGIT TO ALPHA
60 0351 0 0000 49 0002 SLA 2 INSERT TRAILING SPACE
61 0352 0 0002 43 0000 LSA 2 SET SIGN TO TWO FOR ALPHA WORD
62 0353 0 0000 40 0364 STA B STORE IN WORD BUFFER
63 0354 0 0010 09 0364 SPO B,1
64 0355 0 0405 26 0369 IFL COL,04,5 CHECK FOR FULL LINE ON SPO
65 0356 0 0000 10 0369 CAD COL
66 0357 0 0000 18 0370 CFA ECOL
67 0358 0 0001 34 0308 BCL L1 IF COL < ECOL, BRANCH
68 0359 0 0010 09 0377 SPO CR,1 OUTPUT NEWLINES
69 0360 0 0000 46 0369 CLL COL CLEAR COLUMN COUNTER
70 0361 0 0000 30 0308 BUN L1
71 0362 0 0000 00 7557 ENDL1 HLT 7557
SCALARS
74 0363 0 0000 01 0000 A CNST 10000
75 0364 0 0000 00 0000 B CNST 0
76 0365 0 0000 00 0000 C CNST 0
77 0366 0 0000 00 0000 D CNST 0
78 0367 0 0000 00 0000 E CNST 0
79 0368 0 0000 00 0000 G CNST 0
80 0369 0 0000 00 0000 COL CNST 0
81 0370 0 0000 00 0050 ECOL CNST 50
82 0371 0 0000 00 2800 FLIM CNST 2800
83 0372 0 0000 00 0000 ZERO CNST 0
84 0373 0 0000 00 0001 ONE CNST 1
85 0374 0 0000 00 0002 TWO CNST 2
86 0375 0 0000 00 0005 FIVE CNST 5
87 0376 0 0000 00 0080 N80 CNST 80
88 0377 2 0202 02 1616 CR CNST 20202021616 NEWLINES
90 0378 LOCN 1000
91 1000 F DEFN *
92 1000 LOCN *+2800
93 3800 FINI 300
END OF PASS 2, ERRORS = 0
3141 5926 5358 9793 2384 6264 3383 2795 0288 4197
1693 9937 5105 8209 7494 4592 3078 1640 6286 2089
9862 8034 8253 4211 7067 9821 4808 6513 2823 0664
7093 8446 0955 0582 2317 2535 9408 1284 8111 7450
2841 0270 1938 5211 0555 9644 6229 4895 4930 3819
6442 8810 9756 6593 3446 1284 7564 8233 7867 8316
5271 2019 0914 5648 5669 2346 0348 6104 5432 6648
2133 9360 7260 2491 4127 3724 5870 0660 6315 5881
7488 1520 9209 6282 9254 0917 1536 4367 8925 9036
0011 3305 3054 8820 4665 2138 4146 9519 4151 1609
4330 5727 0365 7595 9195 3092 1861 1738 1932 6117
9310 5118 5480 7446 2379 9627 4956 7351 8857 5272
4891 2279 3818 3011 9491 2983 3673 3624 4065 6643
0860 2139 4946 3952 2473 7190 7021 7986 0943 7027
7053 9217 1762 9317 6752 3846 7481 8467 6694 0513
2000 5681 2714 5263 5608 2778 5771 3427 5778 9609
1736 3717 8721 4684 4090 1224 9534 3014 6549 5853
7105 0792 2796 8925 8923 5420 1995 6112 1290 2196
0864 0344 1815 9813 6297 7477 1309 9605 1870 7211
3499 9999 8372 9780 4995 1059 7317 3281 6096 3185

View File

@@ -1705,11 +1705,11 @@ window.addEventListener("load", function() {
switch (opCode) {
case "ASMBL":
printLine(padRight("", 8+5+4+3+8+4+6) +
cardData.text.substring(opCodeIndex, operandIndex+operandLength).trim();
cardData.text.substring(opCodeIndex, operandIndex+operandLength).trim());
break;
case "REORD":
printLine(padRight("", 8+5+4+3+8+4+6) +
cardData.text.substring(opCodeIndex, operandIndex+operandLength).trim();
cardData.text.substring(opCodeIndex, operandIndex+operandLength).trim());
break;
default:
done = true;

View File

@@ -30,16 +30,16 @@
<script src="../emulator/B220Processor.js"></script>
<!--
<script src="./B220ConsoleInput.js"></script>
<script src="./B220CardatronInput.js"></script>
<script src="./B220CardatronOutput.js"></script>
<script src="./B220CardatronControl.js"></script>
<!--
<script src="./B220DataFile.js"></script>
<script src="./B220MagTapeDrive.js"></script>
<script src="./B220MagTapeControl.js"></script>
<script src="./B220ConsoleInput.js"></script>
-->
<script src="./B220ConsoleKeyboard.js"></script>

View File

@@ -54,13 +54,13 @@ window.addEventListener("load", function() {
processor = new B220Processor(config, devices);
/********************
if (config.getNode("Cardatron.hasCardatron")) {
devices.CardatronControl = new B220CardatronControl(processor);
} else {
devices.CardatronControl = null;
}
/********************
if (config.getNode("MagTape.hasMagTape")) {
devices.MagTapeControl = new B220MagTapeControl(processor);
} else {

View File

@@ -0,0 +1,77 @@
/***********************************************************************
* retro-220/webUI B220CardatronControl.css
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 emulator Cardatron Control style sheet.
************************************************************************
* 2017-05-19 P.Kimpel
* Original version, from retro-205 D205CardatronControl.css
***********************************************************************/
#cardatronControlBody {
height: 100%;
min-height: 100%;
overflow: hidden;
padding: 0}
#PanelSurface {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0}
#ControlPanel {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 4px}
#ClearBtn {
bottom: 16px;
right: 4px}
#ClearBtnCaption {
bottom: 4px;
right: 4px;
width: 40px}
#OutputUnitLamp {
top: 8px;
left: 8px}
#UnitDesignate4Lamp {
top: 8px;
left: 32px}
#UnitDesignate2Lamp {
top: 8px;
left: 56px}
#UnitDesignate1Lamp {
top: 8px;
left: 80px}
#RelayDesignate8Lamp {
top: 40px;
left: 8px}
#RelayDesignate4Lamp {
top: 40px;
left: 32px}
#RelayDesignate2Lamp {
top: 40px;
left: 56px}
#RelayDesignate1Lamp {
top: 40px;
left: 80px}
#BufferReadLamp {
top: 72px;
left: 8px}
#BufferWriteLamp {
top: 72px;
left: 32px}
#FormatLoadLamp {
top: 72px;
left: 56px}

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>retro-220 Cardatron Control Unit</title>
<!--
/***********************************************************************
* retro-220/webUI B220CardatronControl.html
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 Cardatron Control page.
************************************************************************
* 2017-05-19 P.Kimpel
* Original version, from retro-205 D205CardatronControl.html.
***********************************************************************/
-->
<meta name="Author" content="Paul Kimpel">
<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="B220Common.css">
<link id=consoleStyleSheet rel=stylesheet type="text/css" href="B220CardatronControl.css">
</head>
<body id=cardatronControlBody>
<div id=PanelSurface class=panelSurface>
<div id=ControlPanel class=panelDiv>
<div id=ClearBtn class=redButton1>&nbsp;</div>
<div id=ClearBtnCaption class=caption>CLEAR</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,301 @@
/***********************************************************************
* retro-220/webUI B220CardatronControl.js
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 Cardatron Control object.
************************************************************************
* 2017-05-19 P.Kimpel
* Original version, from retro-205 D205CardatronControl.js.
***********************************************************************/
"use strict";
/**************************************/
function B220CardatronControl(p) {
/* Constructor for the CardatronControl object */
var left = 660; // left window margin
var u; // unit config object
var x; // unit index
this.config = p.config; // System configuration object
this.mnemonic = "CCU";
this.p = p; // B220Processor object
// Do not call this.clear() here -- call from onLoad instead
this.doc = null;
this.window = window.open("../webUI/B220CardatronControl.html", this.mnemonic,
"location=no,scrollbars=no,resizable,width=140,height=140,top=0,left=" + left);
this.window.addEventListener("load",
B220Util.bindMethod(this, B220CardatronControl.prototype.cardatronOnLoad));
// Set up the I/O devices from the system configuration
this.inputUnit = [
null, // no input unit 0
null, // input unit 1
null, // input unit 2
null, // input unit 3
null, // input unit 4
null, // input unit 5
null, // input unit 6
null]; // input unit 7
this.outputUnit = [
null, // no output unit 0
null, // output unit 1
null, // output unit 2
null, // output unit 3
null, // output unit 4
null, // output unit 5
null, // output unit 6
null]; // output unit 7
for (x=7; x>0; --x) {
u = this.config.getNode("Cardatron.units", x);
switch (u.type.substring(0, 2)) {
case "CR":
this.inputUnit[x] = new B220CardatronInput(u.type, x, this.config);
this.outputUnit[8-x] = null;
break;
case "CP":
case "LP":
this.inputUnit[x] = null;
this.outputUnit[8-x] = new B220CardatronOutput(u.type, x, this.config);
break;
default:
this.inputUnit[x] = null;
this.outputUnit[8-x] = null;
break;
} // switch u.type
} // for x
}
/**************************************/
B220CardatronControl.prototype.$$ = function $$(e) {
return this.doc.getElementById(e);
};
/**************************************/
B220CardatronControl.prototype.clear = function clear() {
/* Initializes the panel state */
this.bufferReadLamp.set(0);
this.bufferWriteLamp.set(0);
this.formatLoadLamp.set(0);
this.outputUnitLamp.set(0);
this.setUnitDesignateLamps(0);
this.setRelayDesignateLamps(0);
};
/**************************************/
B220CardatronControl.prototype.setUnitDesignateLamps = function setUnitDesignateLamps(unit) {
/* Sets the UD lamps on the panel from the low-order three bits of "unit" */
this.unitDesignate1Lamp.set(unit & 0x01);
this.unitDesignate2Lamp.set((unit >>> 1) & 0x01);
this.unitDesignate4Lamp.set((unit >>> 2) & 0x01);
};
/**************************************/
B220CardatronControl.prototype.setRelayDesignateLamps = function setRelayDesignateLamps(mask) {
/* Sets the RD lamps on the panel from the low-order four bits of "mask" */
this.relayDesignate1Lamp.set(mask & 0x01);
this.relayDesignate2Lamp.set((mask >>> 1) & 0x01);
this.relayDesignate4Lamp.set((mask >>> 2) & 0x01);
this.relayDesignate8Lamp.set((mask >>> 3) & 0x01);
};
/**************************************/
B220CardatronControl.prototype.ClearBtn_onClick = function ClearBtn_onClick(ev) {
/* Handle the click event for the CLEAR button, which will clear the
Cardatron Control state */
this.clear();
};
/**************************************/
B220CardatronControl.prototype.beforeUnload = function beforeUnload(ev) {
var msg = "Closing this window will make the panel unusable.\n" +
"Suggest you stay on the page and minimize this window instead";
ev.preventDefault();
ev.returnValue = msg;
return msg;
};
/**************************************/
B220CardatronControl.prototype.cardatronOnLoad = function cardatronOnLoad() {
/* Initializes the Cardatron Control window and user interface */
var body;
var box;
var e;
var x;
this.doc = this.window.document;
body = this.$$("PanelSurface");
this.bufferReadLamp = new NeonLampBox(body, null, null, "BufferReadLamp");
this.bufferReadLamp.setCaption("BR", true);
this.bufferWriteLamp = new NeonLampBox(body, null, null, "BufferWriteLamp");
this.bufferWriteLamp.setCaption("BW", true);
this.formatLoadLamp = new NeonLampBox(body, null, null, "FormatLoadLamp");
this.formatLoadLamp.setCaption("FL", true);
this.outputUnitLamp = new NeonLampBox(body, null, null, "OutputUnitLamp");
this.outputUnitLamp.setCaption("OU", true);
this.unitDesignate4Lamp = new NeonLampBox(body, null, null, "UnitDesignate4Lamp");
this.unitDesignate4Lamp.setCaption("UD4", true);
this.unitDesignate2Lamp = new NeonLampBox(body, null, null, "UnitDesignate2Lamp");
this.unitDesignate2Lamp.setCaption("UD2", true);
this.unitDesignate1Lamp = new NeonLampBox(body, null, null, "UnitDesignate1Lamp");
this.unitDesignate1Lamp.setCaption("UD1", true);
this.relayDesignate8Lamp = new NeonLampBox(body, null, null, "RelayDesignate8Lamp");
this.relayDesignate8Lamp.setCaption("RD8", true);
this.relayDesignate4Lamp = new NeonLampBox(body, null, null, "RelayDesignate4Lamp");
this.relayDesignate4Lamp.setCaption("RD4", true);
this.relayDesignate2Lamp = new NeonLampBox(body, null, null, "RelayDesignate2Lamp");
this.relayDesignate2Lamp.setCaption("RD2", true);
this.relayDesignate1Lamp = new NeonLampBox(body, null, null, "RelayDesignate1Lamp");
this.relayDesignate1Lamp.setCaption("RD1", true);
// Events
this.window.addEventListener("beforeunload", B220CardatronControl.prototype.beforeUnload);
this.$$("ClearBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronControl.prototype.ClearBtn_onClick));
this.clear();
};
/**************************************/
B220CardatronControl.prototype.inputInitiate = function inputInitiate(unitNr, kDigit, wordSender) {
/* Initiates the read from one of the Cardatron input devices.
Returns 0 if device exists and the I/O was initiated; returns -1 if device
not present */
this.bufferReadLamp.set(1);
this.bufferWriteLamp.set(0);
this.formatLoadLamp.set(0);
this.outputUnitLamp.set(0);
this.setRelayDesignateLamps(0);
this.setUnitDesignateLamps(unitNr);
if (!this.inputUnit[unitNr]) {
return -1; // just terminate the I/O
} else {
this.inputUnit[unitNr].inputInitiate(kDigit, wordSender);
return 0;
}
};
/**************************************/
B220CardatronControl.prototype.inputReadyInterrogate = function inputReadyInterrogate(unitNr) {
/* Interrogates the ready status of a Cardatron input device.
Returns -1 if device not present, 0 if device not ready, 1 if device is ready */
if (!this.inputUnit[unitNr]) {
return -1;
} else {
return (this.inputUnit[unitNr].inputReadyInterrogate() ? 1 : 0);
}
};
/**************************************/
B220CardatronControl.prototype.inputFormatInitiate = function inputFormatInitiate(
unitNr, kDigit, requestNextWord, signalFinished) {
/* Initiates loading a format band for one of the Cardatron input devices.
Returns 0 if device exists and the I/O was initiated; returns -1 if device
not present */
this.bufferReadLamp.set(0);
this.bufferWriteLamp.set(0);
this.formatLoadLamp.set(1);
this.outputUnitLamp.set(0);
this.setRelayDesignateLamps(0);
this.setUnitDesignateLamps(unitNr);
if (!this.inputUnit[unitNr]) {
return -1; // just terminate the I/O
} else {
this.inputUnit[unitNr].inputFormatInitiate(kDigit, requestNextWord, signalFinished);
return 0;
}
};
/**************************************/
B220CardatronControl.prototype.outputInitiate = function outputInitiate(
unitNr, kDigit, tDigit, requestNextWord, signalFinished) {
/* Initiates writing to one of the Cardatron output devices */
this.bufferReadLamp.set(0);
this.bufferWriteLamp.set(1);
this.formatLoadLamp.set(0);
this.outputUnitLamp.set(1);
this.setRelayDesignateLamps(tDigit);
if (!this.outputUnit[unitNr]) {
// ?? what happens if the unitNr is invalid? Halt?
signalFinished(); // just terminate the I/O
} else {
this.setUnitDesignateLamps(unitNr);
this.outputUnit[unitNr].outputInitiate(kDigit, tDigit, requestNextWord, signalFinished);
}
};
/**************************************/
B220CardatronControl.prototype.outputReadyInterrogate = function outputReadyInterrogate(unitNr) {
/* Interrogates the ready status of a Cardatron output device */
if (!this.outputUnit[unitNr]) {
// ?? what happens if the unitNr is invalid? Halt?
return false;
} else {
return this.outputUnit[unitNr].outputReadyInterrogate();
}
};
/**************************************/
B220CardatronControl.prototype.outputFormatInitiate = function outputFormatInitiate(
unitNr, kDigit, requestNextWord, signalFinished) {
/* Initiates loading a format band for one of the Cardatron output devices */
this.bufferReadLamp.set(0);
this.bufferWriteLamp.set(0);
this.formatLoadLamp.set(1);
this.outputUnitLamp.set(1);
this.setRelayDesignateLamps(0);
if (!this.outputUnit[unitNr]) {
// ?? what happens if the unitNr is invalid? Halt?
signalFinished(); // just terminate the I/O
} else {
this.setUnitDesignateLamps(unitNr);
this.outputUnit[unitNr].outputFormatInitiate(kDigit, requestNextWord, signalFinished);
}
};
/**************************************/
B220CardatronControl.prototype.shutDown = function shutDown() {
/* Shuts down the panel */
var x;
if (this.inputUnit) {
for (x=this.inputUnit.length-1; x>=0; --x) {
if (this.inputUnit[x]) {
this.inputUnit[x].shutDown();
this.inputUnit[x] = null;
}
}
}
if (this.outputUnit) {
for (x=this.outputUnit.length-1; x>=0; --x) {
if (this.outputUnit[x]) {
this.outputUnit[x].shutDown();
this.outputUnit[x] = null;
}
}
}
this.window.removeEventListener("beforeunload", B220CardatronControl.prototype.beforeUnload);
this.window.close();
};

View File

@@ -0,0 +1,116 @@
/***********************************************************************
* retro-220/webUI B220CardatronInput.css
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License,
* see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 emulator Cardatron Input Unit web interface style sheet.
************************************************************************
* 2017-05-19 P.Kimpel
* Original version, from retro-205 D205CardatronInput.css.
***********************************************************************/
#readerBody {
height: 100%;
min-height: 100%;
overflow: hidden;
padding: 0}
#CIDiv {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 4px}
#CIStopBtn {
position: absolute;
top: 8px;
left: 8px}
#CIStartBtn {
position: absolute;
top: 8px;
left: 76px}
#NoFormatLamp {
top: 16px;
left: 160px}
#StartMachineLamp {
top: 0;
left: 208px}
#ReloadLockoutLamp {
top: 0;
left: 240px}
#FormatLockoutLamp {
top: 0;
left: 272px}
#FormatSelect4Lamp {
top: 28px;
left: 208px}
#FormatSelect2Lamp {
top: 28px;
left: 240px}
#FormatSelect1Lamp {
top: 28px;
left: 272px}
#FormatSelectDiv {
position: absolute;
text-align: center;
font-size: 5pt;
font-weight: bold;
top: 16px;
left: 304px}
#FormatColumnDiv {
position: absolute;
text-align: center;
font-size: 5pt;
font-weight: bold;
top: 16px;
left: 388px}
#ClearBtn {
top: 8px;
right: 8px}
#ClearBtnCaption {
top: 44px;
right: 8px;
width: 32px}
#CIStackerDiv {
position: absolute;
top: 58px;
left: 8px;
right: 8px;
bottom: auto}
#CIFileSelector {
width: 100%;
color: white;
border: 1px solid white}
#CIHopperBar {
margin-top: 4px;
width: 100%;
height: 16px;
border: 1px solid white}
#CIHopperCaption {
position: absolute;
right: 4px;
top: 30px;
z-index: 1;
height: 12px;
color: black;
font-weight: bold}
#CIOutHopperFrame {
margin-top: 4px;
width: 100%;
height: 35px;
border: 1px solid white}

View File

@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Burroughs 220 Emulator Cardatron Input Unit</title>
<!--
/***********************************************************************
* retro-220/webUI B220CardatronInput.html
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 Cardatron Input Unit device page.
*
* Implements the 220 card reader peripheral.
*
************************************************************************
* 2017-05-19 P.Kimpel
* Original version, from retro-205 D205CardatronInput.html.
***********************************************************************/
-->
<meta name="Author" content="Paul Kimpel">
<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="B220Common.css">
<link id=cardReaderStyleSheet rel=stylesheet type="text/css" href="B220CardatronInput.css">
</head>
<body id=readerBody class=deviceBody>
<div id=CIDiv>
<button id=CIStartBtn class="large greenButton">START</button>
<button id=CIStopBtn class="large redButton">STOP</button>
<div id=FormatSelectDiv>
<select id=FormatSelect>
<option value=0 selected>By Col
<option value=1>1
<option value=2>2
<option value=3>3
<option value=4>4
<option value=5>5
<option value=6>6
</select>
<br>FORMAT SELECT
</div>
<div id=FormatColumnDiv>
<select id=FormatColumn>
<option value=80>80
<option value= 1 selected> 1
<option value= 2> 2
<option value= 3> 3
<option value= 4> 4
<option value= 5> 5
<option value= 6> 6
<option value= 7> 7
<option value= 8> 8
<option value= 9> 9
<option value=10>10
<option value=11>11
<option value=12>12
<option value=13>13
<option value=14>14
<option value=15>15
<option value=16>16
<option value=17>17
<option value=18>18
<option value=19>19
<option value=20>20
<option value=21>21
<option value=22>22
<option value=23>23
<option value=24>24
<option value=25>25
<option value=26>26
<option value=27>27
<option value=28>28
<option value=29>29
<option value=30>30
<option value=31>31
<option value=32>32
<option value=33>33
<option value=34>34
<option value=35>35
<option value=36>36
<option value=37>37
<option value=38>38
<option value=39>39
<option value=40>40
<option value=41>41
<option value=42>42
<option value=43>43
<option value=44>44
<option value=45>45
<option value=46>46
<option value=47>47
<option value=48>48
<option value=49>49
<option value=50>50
<option value=51>51
<option value=52>52
<option value=53>53
<option value=54>54
<option value=55>55
<option value=56>56
<option value=57>57
<option value=58>58
<option value=59>59
<option value=60>60
<option value=61>61
<option value=62>62
<option value=63>63
<option value=64>64
<option value=65>65
<option value=66>66
<option value=67>67
<option value=68>68
<option value=69>69
<option value=70>70
<option value=71>71
<option value=72>72
<option value=73>73
<option value=74>74
<option value=75>75
<option value=76>76
<option value=77>77
<option value=78>78
<option value=79>79
</select>
<br>FORMAT COL
</div>
<div id=ClearBtn class=redButton1>&nbsp;</div>
<div id=ClearBtnCaption class=caption>CLEAR</div>
<div id=CIStackerDiv>
<input id=CIFileSelector type=file size=60 multiple>
<label id=CIHopperCaption for=CIHopperBar>INPUT HOPPER</label>
<meter id=CIHopperBar min=0 max=100 value=0 title="Click to clear input hopper"></meter>
<iframe id=CIOutHopperFrame class=paper scrolling=no src="./B220FramePaper.html"></iframe>
</div>
</div>
</body>
</html>

911
webUI/B220CardatronInput.js Normal file
View File

@@ -0,0 +1,911 @@
/***********************************************************************
* retro-220/webUI B220CardatronInput.js
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 Cardatron Input Unit module.
*
* Defines a card reader peripheral unit type.
*
************************************************************************
* 2017-05-19 P.Kimpel
* Original version, from retro-205 D205CardatronInput.js.
***********************************************************************/
"use strict";
/**************************************/
function B220CardatronInput(mnemonic, unitIndex, config) {
/* Constructor for the Cardatron Input object */
var h = 160; // window height
var left = 0; // (temporary window x-offset)
var tks = B220CardatronInput.trackSize;
var w = 560; // window width
var x;
this.config = config; // System configuration object
this.mnemonic = mnemonic; // Unit mnemonic
this.unitIndex = unitIndex; // Input unit number
this.timer = 0; // setCallback() token
this.boundFinishCardRead = B220Util.bindMethod(this, B220CardatronInput.prototype.finishCardRead);
this.boundInputFormatWord = B220Util.bindMethod(this, B220CardatronInput.prototype.inputFormatWord);
this.clear();
// Buffer drum: information band is [0], format bands are [1]-[6], [7] is a dummy for indexing only
this.bufferDrum = new ArrayBuffer(tks*8);
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
new Uint8Array(this.bufferDrum, tks*6, tks), // format band 6 (fixed)
new Uint8Array(this.bufferDrum, tks*7, tks)]; // format band 7 (dummy)
// Initialize format band 6 for all-numeric transfer
// (note that ArrayBuffer storage is initialized to zero, so band[160..233] == 0)
for (x=0; x<160; x+=2) {
this.formatBand[6][x] = 1;
this.formatBand[6][x+1] = 3;
}
for (x=234; x<this.info.length; ++x) {
this.formatBand[6][x] = 3;
}
this.doc = null;
this.hopperBar = null;
this.outHopperFrame = null;
this.outHopper = null;
this.formatCol = 0; // current format-determination column
this.formatColumnList = null;
this.formatSelect = 0; // current format selection
this.formatSelectList = null;
this.window = window.open("../webUI/B220CardatronInput.html", mnemonic,
"location=no,scrollbars,resizable,width=" + w + ",height=" + h +
",left=" + (unitIndex*24) + ",top=" + (unitIndex*24));
this.window.addEventListener("load",
B220Util.bindMethod(this, B220CardatronInput.prototype.readerOnLoad), false);
}
/**************************************/
B220CardatronInput.prototype.eolRex = /([^\n\r\f]*)((:?\r[\n\f]?)|\n|\f)?/g;
B220CardatronInput.prototype.cardsPerMinute = 240; // IBM Type 087/089 collator
B220CardatronInput.prototype.eodBias = -0x900000000000; // signals end-of-data to Processor
B220CardatronInput.trackSize = 319; // digits
B220CardatronInput.drumTransferTime = 60000/21600*1.5;
// one drum rotation, plus a half rotation for
// average latency, about 4.17 ms
// Filter ASCII character values to buffer drum info band zone/numeric digits.
// See U.S. Patent 3,000,556, September 16, 1961, L.L. Bewley et al, Figure 2.
B220CardatronInput.prototype.cardFilter = [
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 00-0F
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 10-1F
0x00,0x60,0x07,0x0B,0x2B,0x4C,0x10,0x0C,0x4C,0x1C,0x2C,0x10,0x4B,0x20,0x1B,0x41, // 20-2F
0x40,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x02,0x2B,0x1C,0x0B,0x00,0x00, // 30-3F
0x0C,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 40-4F
0x27,0x28,0x29,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x00,0x00,0x00,0x00,0x00, // 50-5F
0x01,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 60-6F
0x27,0x28,0x29,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x50,0x05,0x06,0x07,0x00]; // 70-7F
// Translate buffer zone digits to internal zone decades.
// Each row is indexed by the zone digit from the buffer drum info band;
// each column is indexed by the PREVIOUS numeric digit from the info band.
// See U.S. Patent 3,000,556, September 16, 1961, L.L. Bewley et al, Figure 9.
B220CardatronInput.prototype.zoneXlate = [
//0 1 2 3 4 5 6 7 8 9 10 11 12
[0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 3, 3], // zone digit 0
[1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0], // zone digit 1
[2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 1, 1], // zone digit 2
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // there no zone=3 digits
[8, 2, 6, 6, 6, 6, 6, 6, 6, 6, 0, 2, 2], // zone digit 4
[4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // zone digit 5
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // zone digit 6
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // there no zone=7 digits
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // there no zone=8 digits
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; // there no zone=9 digits
/**************************************/
B220CardatronInput.prototype.clear = function clear() {
/* Initializes (and if necessary, creates) the reader unit state */
this.ready = false; // ready status
this.bufferReady = false; // buffer drum info band is ready to send data to Processor
this.noFormatAlarm = false; // No Formal Alarm toggle
this.reloadLockout = false; // Reload Lockout toggle
this.formatLockout = false; // Format Lockout toggle
this.readRequested = false; // Processor has initiated a read, waiting for buffer
this.togNumeric = false; // current digit came from zone (false) or numeric (true) punches
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.digitCount = 0; // digit within word being returned (sign=10)
this.infoIndex = 0; // 0-relative offset into info band on drum
this.lastNumericDigit = 0; // last numeric digit encountered
this.pendingInputWord = 0; // partially-accumulated input word
this.rDigit = 0; // stashed reload-lockout/format band number
this.selectedFormat = 0; // currently-selected format band
this.pendingCall = null; // stashed pending function reference
this.pendingParams = null; // stashed pending function parameters
};
/**************************************/
B220CardatronInput.prototype.$$ = function $$(e) {
return this.doc.getElementById(e);
};
/**************************************/
B220CardatronInput.prototype.setFormatColumn = function setFormatColumn(index) {
/* Determines the zero-relative format-selection column from the selectedIndex
of the FormatColumn select list and sets this.formatCol */
if (index < 0) {
this.formatCol = 0; // treat unselected as column 1
} else if (index == 0) {
this.formatCol = 79; // column 80
} else if (index < 80) {
this.formatCol = index-1; // columns 1-79
} else {
this.formatCol = 0; // treat everything else as col 1
}
};
/**************************************/
B220CardatronInput.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;
}
};
/**************************************/
B220CardatronInput.prototype.setReaderReady = function setReaderReady(ready) {
/* Controls the ready-state of the card reader */
this.$$("CIFileSelector").disabled = ready;
if (ready && !this.ready) {
B220Util.addClass(this.$$("CIStartBtn"), "greenLit")
B220Util.removeClass(this.$$("CIStopBtn"), "redLit");
this.ready = true;
} else if (this.ready && !ready) {
B220Util.removeClass(this.$$("CIStartBtn"), "greenLit")
B220Util.addClass(this.$$("CIStopBtn"), "redLit");
this.ready = false;
}
};
/**************************************/
B220CardatronInput.prototype.setNoFormatAlarm = function setNoFormatAlarm(noFormat) {
/* Controls the state of the No Format alarm and lamp */
this.noFormatAlarm = noFormat;
if (noFormat) {
this.setReaderReady(false);
this.noFormatLamp.set(1);
} else {
this.noFormatLamp.set(0);
}
};
/**************************************/
B220CardatronInput.prototype.setReloadLockout = function setReloadLockout(lockout) {
/* Controls the state of the Reload Lockout (RLO) toggle and lamp */
this.reloadLockout = lockout;
if (lockout) {
this.reloadLockoutLamp.set(1);
} else {
this.bufferReady = false;
this.setFormatLockout(false);
this.reloadLockoutLamp.set(0);
}
};
/**************************************/
B220CardatronInput.prototype.setFormatLockout = function setFormatLockout(lockout) {
/* Controls the state of the Format Lockout (FLO) toggle and lamp.
Setting Format Lockout implicitly sets Reload Lockout */
this.formatLockout = lockout;
if (lockout) {
this.setReloadLockout(true);
this.formatLockoutLamp.set(1);
} else {
this.formatLockoutLamp.set(0);
}
};
/**************************************/
B220CardatronInput.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);
};
/**************************************/
B220CardatronInput.prototype.CIStartBtn_onClick = function CIStartBtn_onClick(ev) {
/* Handle the click event for the START button */
if (!this.ready) {
this.setNoFormatAlarm(false);
if (this.bufIndex < this.bufLength) {
this.setReaderReady(true);
if (!this.bufferReady) {
this.initiateCardRead();
}
}
}
};
/**************************************/
B220CardatronInput.prototype.CIStopBtn_onClick = function CIStopBtn_onClick(ev) {
/* Handle the click event for the STOP button */
this.$$("CIFileSelector").value = null; // reset the control so the same file can be reloaded
if (this.ready) {
this.setReaderReady(false);
this.startMachineLamp.set(0);
this.setFormatSelectLamps(0);
}
};
/**************************************/
B220CardatronInput.prototype.ClearBtn_onClick = function ClearBtn_onClick(ev) {
/* Handle the click event for the CLEAR button */
this.clearUnit();
};
/**************************************/
B220CardatronInput.prototype.CIHopperBar_onClick = function CIHopperBar_onClick(ev) {
/* Handle the click event for the "input hopper" meter bar */
if (this.bufIndex < this.bufLength && !this.ready) {
if (this.window.confirm((this.bufLength-this.bufIndex).toString() + " of " + this.bufLength.toString() +
" characters remaining to read.\nDo you want to clear the input hopper?")) {
this.buffer = "";
this.bufLength = 0;
this.bufIndex = 0;
this.hopperBar.value = 0;
this.$$("CIFileSelector").value = null; // reset the control
while (this.outHopper.childNodes.length > 0) {
this.outHopper.removeChild(this.outHopper.firstChild);
}
}
}
};
/**************************************/
B220CardatronInput.prototype.fileSelector_onChange = function fileSelector_onChange(ev) {
/* Handle the <input type=file> onchange event when files are selected. For each
file, load it and add it to the "input hopper" of the reader */
var deck;
var f = ev.target.files;
var that = this;
var x;
function fileLoader_onLoad(ev) {
/* Handle the onLoad event for a Text FileReader */
if (that.bufIndex >= that.bufLength) {
that.buffer = ev.target.result;
} else {
switch (that.buffer.charAt(that.buffer.length-1)) {
case "\r":
case "\n":
case "\f":
break; // do nothing -- the last card has a delimiter
default:
that.buffer += "\n"; // so the next deck starts on a new line
break;
}
that.buffer = that.buffer.substring(that.bufIndex) + ev.target.result;
}
that.bufIndex = 0;
that.bufLength = that.buffer.length;
that.$$("CIHopperBar").value = that.bufLength;
that.$$("CIHopperBar").max = that.bufLength;
}
for (x=f.length-1; x>=0; x--) {
deck = new FileReader();
deck.onload = fileLoader_onLoad;
deck.readAsText(f[x]);
}
};
/**************************************/
B220CardatronInput.prototype.format_onChange = function format_onChange(ev) {
/* Event handler for changes to the FormatColumn and FormatSelect lists */
var prefs = this.config.getNode("Cardatron.units", this.unitIndex);
var x;
switch (ev.target.id) {
case "FormatColumn":
x = this.formatColumnList.selectedIndex;
this.setFormatColumn(x);
prefs.formatCol = x;
this.config.putNode("Cardatron.units", prefs, this.unitIndex);
break;
case "FormatSelect":
x = this.formatColumnList.selectedIndex;
prefs.formatSelect = this.formatSelect = x;
this.config.putNode("Cardatron.units", prefs, this.unitIndex);
break;
}
};
/**************************************/
B220CardatronInput.prototype.readCardImage = function readCardImage() {
/* Reads one card image from the buffer; pads or trims the image as necessary
to 80 characters. Detects empty buffer (hopper) and sets the reader not ready
after reading the last card. Updates the progress bar. Returns the raw ASCII
card image as a string */
var card; // card image
var match; // result of eolRex.exec()
this.eolRex.lastIndex = this.bufIndex;
match = this.eolRex.exec(this.buffer);
if (!match) {
card = "";
} else {
this.bufIndex += match[0].length;
card = match[1].toUpperCase();
}
if (card.length > 80) {
card = card.substring(0, 80);
} else {
while (card.length <= 70) {
card += " "; // pad with spaces
}
while (card.length < 80) {
card += " ";
}
}
if (this.bufIndex < this.bufLength) {
this.hopperBar.value = this.bufLength-this.bufIndex;
} else {
this.hopperBar.value = 0;
this.buffer = ""; // discard the input buffer
this.bufLength = 0;
this.bufIndex = 0;
this.setReaderReady(false);
this.$$("CIFileSelector").value = null; // reset the control so the same file can be reloaded
}
while (this.outHopper.childNodes.length > 1) {
this.outHopper.removeChild(this.outHopper.firstChild);
}
this.outHopper.appendChild(this.doc.createTextNode("\n"));
this.outHopper.appendChild(this.doc.createTextNode(card));
return card;
};
/**************************************/
B220CardatronInput.prototype.determineFormatBand = function determineFormatBand(card) {
/* Determines the format band number to be applied to the current card.
Returns the format band number or zero if No Format Alarm is set */
var c; // selected column character code
var format; // selected format band
// Check for format override on the reader panel
format = this.formatSelect;
if (format > 6) {
format = 0;
this.setNoFormatAlarm(true);
} else if (format <= 0) {
// No format override, so determine format from a card column
c = card.charAt(this.formatCol);
switch (c) {
case "1":
format = 1;
break;
case "2":
format = 2;
break;
case "3":
format = 3;
break;
case "4":
format = 4;
break;
case "5":
format = 5;
break;
case "6":
format = 6;
break;
case "7":
format = 7;
break;
case "`": // 1-8 punch
format = 1;
this.setFormatLockout(true);
break;
case ":": // 2-8 punch
format = 2;
this.setFormatLockout(true);
break;
case "#": // 3-8 punch
format = 3;
this.setFormatLockout(true);
break;
case "@": // 4-8 punch
format = 4;
this.setFormatLockout(true);
break;
case "'": // 5-8 punch
case "|": // translates to a 5-numeric digit
format = 5;
this.setFormatLockout(true);
break;
case "=": // 6-8 punch
case "}": // translates to a 6-numeric digit
format = 6;
this.setFormatLockout(true);
break;
case "\"": // 7-8 punch -- reject plus lockout
case "~": // translates to a 7-numeric digit
format = 7+8;
this.setFormatLockout(true);
break;
default:
format = 0;
this.setNoFormatAlarm(true);
break;
} // switch c
}
this.setFormatSelectLamps(format);
return format;
};
/**************************************/
B220CardatronInput.prototype.finishCardRead = function finishCardRead() {
/* Processes a card image after the delay to read the card. Establishes the
format band to be used and encodes the data from the card image onto the
info band of the buffer drum per Figure 2 in US Patent 3,000,556 */
var band; // local copy of selected format band
var c; // current character code
var card = this.readCardImage(); // the card image in ASCII
var col; // current card column
var format; // selected format band
var fmax; // length of format band
var info = this.info; // local copy of info band on buffer drum
var nu; // numeric (true), zone (false) toggle
var x; // info/format band digit index
this.startMachineLamp.set(0);
format = this.determineFormatBand(card);
if ((format & 0x07) == 7) {
// Reject format -- clear the information band and read next card
this.selectedFormat = 7;
// If reject+lockout was imposed by a 7-8 punch, read next card and lock out its successor
if ((format & 0x08) || !this.reloadLockout) {
this.initiateCardRead();
}
} else if (format > 0) {
this.selectedFormat = format;
band = this.formatBand[format];
fmax = band.length;
col = card.length-1; // start with last column on card
nu = true; // start with the numeric digit
for (x=0; x<fmax; ++x) {
switch (band[x]) {
case 0:
info[x] = 0;
break;
case 2:
info[x] = 2;
break;
default:
if (nu) {
c = card.charCodeAt(col); // translate char to buffer code
if (c < 0x80) {
c = this.cardFilter[c];
} else if (c == 0xA4) { // the "lozenge" ("¤")
c = this.cardFilter[0x3C]; // use the code for "<"
} else {
c = 0;
}
info[x] = c & 0x0F; // take the numeric half
nu = false; // next will be the zone digit
} else {
info[x] = (c >>> 4) & 0x0F; // take the zone half
nu = true; // next will be the numeric digit
if (col > 0) { // advance to next card column
--col;
}
}
} // switch
} // for x
this.bufferReady = true;
if (this.readRequested) { // fire up any pending read from Processor
this.readRequested = false;
this.pendingCall.apply(this, this.pendingParams);
}
}
};
/**************************************/
B220CardatronInput.prototype.initiateCardRead = function initiateCardRead() {
/* Initiates the read of the next card into the buffer drum */
if (this.ready) {
this.startMachineLamp.set(1);
this.setNoFormatAlarm(false);
this.clearInfoBand();
this.timer = setCallback(this.mnemonic, this,
60000/this.cardsPerMinute, this.boundFinishCardRead);
}
};
/**************************************/
B220CardatronInput.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;
};
/**************************************/
B220CardatronInput.prototype.readerOnLoad = function readerOnLoad() {
/* Initializes the reader window and user interface */
var body;
var de;
var prefs = this.config.getNode("Cardatron.units", this.unitIndex);
this.doc = this.window.document;
de = this.doc.documentElement;
this.doc.title = "retro-220 Cardatron Reader " + this.mnemonic;
body = this.$$("CIDiv");
this.hopperBar = this.$$("CIHopperBar");
this.outHopperFrame = this.$$("CIOutHopperFrame");
this.outHopper = this.outHopperFrame.contentDocument.getElementById("Paper");
this.formatColumnList = this.$$("FormatColumn");
this.formatColumnList.selectedIndex = prefs.formatCol;
this.setFormatColumn(prefs.formatCol);
this.formatSelectList = this.$$("FormatSelect");
this.formatSelectList.selectedIndex = this.formatSelect = prefs.formatSelect;
this.noFormatLamp = new ColoredLamp(body, null, null, "NoFormatLamp", "redLamp", "redLit");
this.noFormatLamp.setCaption("NO FORMAT", true);
this.startMachineLamp = new NeonLamp(body, null, null, "StartMachineLamp");
this.startMachineLamp.setCaption("SM", true);
this.reloadLockoutLamp = new NeonLamp(body, null, null, "ReloadLockoutLamp");
this.reloadLockoutLamp.setCaption("RLO", true);
this.formatLockoutLamp = new NeonLamp(body, null, null, "FormatLockoutLamp");
this.formatLockoutLamp.setCaption("FLO", 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.ready = true; // so that setReaderReady called from clearUnit
this.clearUnit(); // will actually set the state and lamps correctly
this.window.addEventListener("beforeunload",
B220CardatronInput.prototype.beforeUnload);
this.$$("CIFileSelector").addEventListener("change",
B220Util.bindMethod(this, B220CardatronInput.prototype.fileSelector_onChange));
this.$$("FormatColumn").addEventListener("change",
B220Util.bindMethod(this, B220CardatronInput.prototype.format_onChange));
this.$$("FormatSelect").addEventListener("change",
B220Util.bindMethod(this, B220CardatronInput.prototype.format_onChange));
this.$$("CIStartBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronInput.prototype.CIStartBtn_onClick));
this.$$("CIStopBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronInput.prototype.CIStopBtn_onClick));
this.$$("ClearBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronInput.prototype.ClearBtn_onClick));
this.hopperBar.addEventListener("click",
B220Util.bindMethod(this, B220CardatronInput.prototype.CIHopperBar_onClick));
this.window.resizeBy(de.scrollWidth - this.window.innerWidth + 4, // kludge for right-padding/margin
de.scrollHeight - this.window.innerHeight);
};
/**************************************/
B220CardatronInput.prototype.inputInitiate = function inputInitiate(rDigit, wordReceiver) {
/* Initiates a read against the buffer drum on this unit. rDigit is the
(41) numeric digit from the instruction word, with odd values indicating
reload-lockout should be imposed at the end of the read. wordReceiver is the
callback function that will receive one word at a time for return to the
Processor. If the buffer is not ready, simply sets the readRequested flag
and exits after stashing rDigit and the wordReceiver callback */
if (!this.bufferReady) {
this.readRequested = true; // wait for the buffer to be filled
this.pendingCall = inputInitiate;
this.pendingParams = [rDigit, wordReceiver];
if (!this.ready) {
this.window.focus();
}
} else {
this.rDigit = rDigit;
this.infoIndex = 0; // start at the beginning of the info band
this.digitCount = 0;
this.pendingInputWord = 0;
this.togNumeric = true;
this.lastNumericDigit = 0;
setCallback(this.mnemonic, this, B220CardatronInput.drumTransferTime,
this.inputTransfer, wordReceiver);
}
};
/**************************************/
B220CardatronInput.prototype.inputTransfer = function inputTransfer(wordReceiver) {
/* Driver for sending words assembled from the info band to the Processor */
while (this.infoIndex < this.info.length) {
this.inputWord(wordReceiver);
}
this.inputStop();
};
/**************************************/
B220CardatronInput.prototype.inputWord = function inputWord(wordReceiver) {
/* Reads the next word of digits from the info band of the buffer drum,
translating the digits to Datatron Processor code and sending the word to the
Processor via the wordReceiver callback function. If at end of band, returns any
partially-accumulated word minus 0x900000000000 to signal end of I/O. Note that
sign digits must be translated from zone digits specially. Also note that a
completed word is not returned until the next digit is obtained from the info band */
var band; // local copy of format band
var d; // result digit
var eod; // finished with current digit
var eow = false; // finished with word
var ix = this.infoIndex; // current info/format band index
var lastNumeric = this.lastNumericDigit;
var nu = this.togNumeric; // numeric/zone digit toggle
var word = this.pendingInputWord; // word being assembled
var x = this.digitCount; // word-digit index
band = this.formatBand[this.selectedFormat];
do {
eod = false;
do {
if (ix >= this.info.length) {
// At end of info band -- finish the I/O
d = 0;
word = word + this.eodBias; // flag this as the final word of the I/O
eow = eod = true;
} else {
// Translate or delete the current digit
switch (band[ix]) {
case 0: // insert 0 digit
d = 0;
++ix;
eod = true;
break;
case 1: // translate zone/numeric digit
d = this.info[ix];
if (nu) {
// Numeric digit: straight translation except for 3-8 and 4-8 punches
nu = false; // next is a zone digit
lastNumeric = d;
if (d > 9) {
d -= 8;
}
} else {
// Zone digit: requires special handling in the sign-digit position
nu = true; // next is a numeric digit
d = this.zoneXlate[d][lastNumeric];
if (x == 10) {
d &= 0x0B; // zero the 4-bit in the sign digit
}
}
++ix;
eod = true;
break;
case 2: // insert 2 digit
d = 2;
++ix;
eod = true;
break;
default: // (3) delete the digit
if (nu) {
nu = false; // next is a zone digit
lastNumeric = this.info[ix];
} else {
nu = true; // next is a numeric digit
}
++ix;
// We are not yet done producing the next digit...
break;
} // switch band[ix]
}
} while (!eod);
if (x < 11) {
// Increment the digit index and shift this digit into the word
++x;
word = word/0x10 + d*0x10000000000;
} else {
// Word has overflowed -- send the word to the Processor and save
// this digit for the next word
eow = true;
this.pendingInputWord = d*0x10000000000;
this.digitCount = 1;
}
} while (!eow);
this.lastNumericDigit = lastNumeric;
this.togNumeric = nu;
// Send the word to the Processor
if (wordReceiver(word) < 0) {
this.infoIndex = this.info.length; // stop the I/O
} else {
this.infoIndex = ix;
}
};
/**************************************/
B220CardatronInput.prototype.inputStop = function inputStop() {
/* Terminates data transfer from the input unit and releases the card */
this.setFormatSelectLamps(0);
if (this.rDigit % 2) { // set reload-lockout
if (!this.reloadLockout) {
this.setReloadLockout(true);
}
} else if (this.reloadLockout) { // reset reload-lockout
this.setReloadLockout(false);
}
if (!this.reloadLockout) {
this.bufferReady = false;
this.initiateCardRead();
}
};
/**************************************/
B220CardatronInput.prototype.inputReadyInterrogate = function inputReadyInterrogate() {
/* Returns the current ready status of the input unit */
return this.bufferReady;
};
/**************************************/
B220CardatronInput.prototype.inputFormatInitiate = function inputFormatInitiate(
rDigit, requestNextWord, signalFinished) {
/* Initiates the loading of a format band on this unit. rDigit is the
(41) numeric digit from the instruction word, with odd values indicating
reload-lockout should be imposed at the end of the read and the remaining
three bits indicating the format band to be loaded. requestNextWord is the
callback function that will trigger the Processor to send the next digit.
signalFinished is the callback function that will signal the Processor to
terminate the I/O */
if (rDigit > 9) {
signalFinished();
} else {
this.rDigit = rDigit;
this.selectedFormat = ((rDigit >>> 1) & 0x07) + 1;
this.infoIndex = 0; // start at the beginning of the format band
this.digitCount = 0;
this.togNumeric = true;
this.lastNumericDigit = 0;
this.pendingCall = signalFinished; // stash the call-back function
this.setFormatSelectLamps(this.selectedFormat);
setCallback(this.mnemonic, this, B220CardatronInput.drumTransferTime*1.67,
this.inputFormatTransfer, requestNextWord);
}
};
/**************************************/
B220CardatronInput.prototype.inputFormatTransfer = function inputFormatTransfer(requestNextWord) {
/* Driver for sending words assembled from the info band to the Processor */
while (this.infoIndex < B220CardatronInput.trackSize) {
this.inputFormatWord(requestNextWord);
}
this.pendingCall(); // call signalFinished();
this.inputStop();
};
/**************************************/
B220CardatronInput.prototype.inputFormatWord = function inputFormatWord(requestNextWord) {
/* Receives the next input format band word from the Processor and
stores the digits from the word into the next 11 format band digits */
var band = this.formatBand[this.selectedFormat];
var d; // current format digit
var ix = this.infoIndex; // current format band digit index
var word = requestNextWord(); // band word from Processor
var x; // word-digit index
if (word < 0) { // transfer terminated
ix = B220CardatronInput.tracksize;
} else {
for (x=0; x<11; ++x) {
d = word % 0x10;
word = (word-d)/0x10;
if (ix < B220CardatronInput.trackSize) {
band[ix++] = d % 4;
} else {
break; // out of for loop
}
} // for x
}
this.infoIndex = ix;
};
/**************************************/
B220CardatronInput.prototype.clearUnit = function clearUnit() {
/* Clears the input unit and resets all internal state */
this.$$("CIFileSelector").value = null; // reset the control so the same file can be reloaded
this.bufferReady = false;
this.setReaderReady(false);
this.setNoFormatAlarm(false);
this.setReloadLockout(false);
this.setFormatLockout(false);
this.startMachineLamp.set(0);
this.setFormatSelectLamps(7);
// If there is a pending read, confirm that this.pendingParams[1] is a
// function and call it with the end-of-data signal. We assume it's the
// Processor's wordReceiver function. This will prevent the Processor
// from hanging on an I/O to a cleared input unit.
if (this.readRequested) {
if (Object.prototype.toString.call(this.pendingParams) === "[object Array]") {
if (Object.prototype.toString.call(this.pendingParams[1]) === "[object Function]") {
this.pendingParams[1](this.eodBias);
}
}
}
this.clear();
if (this.timer) {
clearCallback(this.timer);
this.timer = 0;
}
};
/**************************************/
B220CardatronInput.prototype.shutDown = function shutDown() {
/* Shuts down the device */
if (this.timer) {
clearCallback(this.timer);
}
this.window.removeEventListener("beforeunload", B220CardatronInput.prototype.beforeUnload);
this.window.close();
};

View File

@@ -0,0 +1,150 @@
/***********************************************************************
* retro-220/webUI B220CardatronOutput.css
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License,
* see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 emulator Cardatron Output Unit web interface style sheet.
************************************************************************
* 2017-01-19 P.Kimpel
* Original version, from retro-205 D205CardatronOutput.css.
***********************************************************************/
#writerBody {
height: 100%;
min-height: 100%;
overflow: hidden;
padding: 0}
#CODiv {
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;}
#COStopBtn {
position: absolute;
top: 8px;
left: 8px}
#COStartBtn {
position: absolute;
top: 8px;
left: 76px}
#COEndOfSupplyBtn {
position: absolute;
top: 8px;
left: 144px}
#CORunoutSupplyBtn {
position: absolute;
line-height: 100%;
top: 8px;
left: 212px}
#ClearBtn {
top: 8px;
left: 288px}
#ClearBtnCaption {
top: 44px;
left: 288px;
width: 32px}
#COSetZSBtn {
top: 8px;
left: 336px}
#COSetZSBtnCaption {
top: 44px;
left: 336px;
width: 32px}
#StartMachineLamp {
top: 4px;
left: 384px}
#FormatSelect4Lamp {
top: 4px;
left: 416px}
#FormatSelect2Lamp {
top: 4px;
left: 448px}
#FormatSelect1Lamp {
top: 4px;
left: 480px}
#COOptionsDiv {
position: absolute;
top: 4px;
right: 8px;
width: auto}
#COGreenbarSpan {
display: none}
#COSupplyMeter {
position: absolute;
top: 32px;
left: 384px;
right: 0;
width: calc(100% - 346px);
height: 18px;
border: 1px solid white}
#COSupplyMeterCaption {
position: absolute;
top: 35px;
right: 18px;
z-index: 1;
height: 12px;
color: black;
font-weight: bold}
#COSupplyFrame {
position: absolute;
top: 56px;
bottom: 8px;
left: 8px;
right: 8px;
width: calc(100% - 18px);
height: calc(100% - 66px);
border: 1px solid black}
/* Zero-Suppress Panel */
#COZSGroup {
position: absolute;
top: 8px;
left: 8px;
right: 8px}
#COZSColumnList {
border: 1px solid white;
color: black;
width: 100%}
#COZSNotes {
position: absolute;
top: 40px;
width: 300px;
left: 0}
#COZSButtonGroup {
position: absolute;
top: 40px;
right: 0}
#COZSCancelBtn {
background-image: none;
background-color: #900;
height: 20px;
bottom: 0;
right: 64px}
#COZSOKBtn {
background-image: none;
background-color: #060;
height: 20px;
bottom: 0;
right: 0}

View File

@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Burroughs 220 Emulator Cardatron Output Unit</title>
<!--
/***********************************************************************
* retro-220/webUI B220CardatronOutput.html
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 Cardatron Output Unit device page.
*
* Implements the 220 line-printer/card-punch peripheral.
*
************************************************************************
* 2017-05-19 P.Kimpel
* Original version, from retro-205 D205CardatronOutput.html.
***********************************************************************/
-->
<meta name="Author" content="Paul Kimpel">
<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="B220Common.css">
<link id=writerStyleSheet rel=stylesheet type="text/css" href="B220CardatronOutput.css">
</head>
<body id=writerBody class=deviceBody>
<div id=CODiv>
<button id=COStartBtn class="large greenButton">START</button>
<button id=COStopBtn class="large redButton">STOP</button>
<button id=COEndOfSupplyBtn class="large redButton">END OF<br>PAPER</button>
<button id=CORunoutSupplyBtn class="large redButton"
title="Triple-click to rip paper or empty hopper"
>FORM<br>FEED</button>
<div id=ClearBtn class=redButton1>&nbsp;</div>
<div id=ClearBtnCaption class=caption>CLEAR</div>
<div id=COSetZSBtn class=blackButton1 title="Click to set zero-suppression starting columns">&nbsp;</div>
<div id=COSetZSBtnCaption class=caption>SET ZS</div>
<div id=COOptionsDiv>
<span id=COGreenbarSpan>
<input id=COGreenbarCheck type=checkbox value=1 checked>
<label for=COGreenbarCheck class="annunciator annunciatorLit">GREENBAR</label>
&nbsp;&nbsp;
</span>
<input id=COAlgolGlyphsCheck type=checkbox value=1 checked>
<label for=COAlgolGlyphsCheck class="annunciator annunciatorLit">ALGOL GLYPHS</label>
</div>
<meter id=COSupplyMeter min=0 max=100 low=10 value=100></meter>
<label id=COSupplyMeterCaption for=COSupplyMeter>SUPPLY REMAINING</label>
<iframe id=COSupplyFrame class=paper scrolling=auto src="./B220FramePaper.html"></iframe>
</div>
</body>
</html>

1035
webUI/B220CardatronOutput.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Burroughs 220 Emulator Cardatron Zero-Suppress Panel</title>
<!--
/***********************************************************************
* retro-220/webUI B220CardatronZeroSuppressPanel.html
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 Cardatron Zero-Suppress Panel page.
*
* Implements a dialog to specify a list of zero-suppress starting columns
* for Cardatron output devices.
*
************************************************************************
* 2017-05-19 P.Kimpel
* Original version, from retro-205 D205CardatronZeroSuppressPanel.html.
***********************************************************************/
-->
<meta name="Author" content="Paul Kimpel">
<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="B220Common.css">
<link id=tapeLoadStyleSheet rel=stylesheet type="text/css" href="B220CardatronOutput.css">
</head>
<body class=deviceBody>
<div id=COZSGroup>
Begin zero-suppression in these columns:<br>
<input id=COZSColumnList type=text size=60>
<div id=COZSNotes>
Enter a comma-delimited list of 1-relative column numbers in ascending
order; click <b>OK</b> to save and apply to the device.
</div>
<div id=COZSButtonGroup>
<button id=COZSCancelBtn class="large redButton">Cancel</button>
&nbsp;
<button id=COZSOKBtn class="large greenButton">OK</button>
</div>
</div>
</body>
</html>

View File

@@ -58,7 +58,7 @@ BODY.deviceBody {
overflow: hidden;
margin: 0;
padding: 0;
background-color: #246;
background-color: #678; /* IBM 1950s blue-gray equipment color */
color: white}
H1 {

View File

@@ -509,6 +509,9 @@ B220ConsolePrinter.prototype.receiveChar = function receiveChar(char, successor)
this.printChar(this.suppressLZ ? 0x00 : char);
break;
case 0x02: // blank (non-print)
break;
case 0x15: // form-feed
delay *= 4;
this.suppressLZ = 0;

View File

@@ -1,20 +1,20 @@
CACHE MANIFEST
# retro-220 emulator 0.01, 2017-05-13 18:30
# retro-220 emulator 0.01a, 2017-05-20 18:30
CACHE:
../emulator/B220Processor.js
B220.css
B220.html
B220.js
#B220CardatronControl.css
#B220CardatronControl.html
#B220CardatronControl.js
#B220CardatronInput.css
#B220CardatronInput.html
#B220CardatronInput.js
#B220CardatronOutput.css
#B220CardatronOutput.html
#B220CardatronOutput.js
#B220CardatronZeroSuppressPanel.html
B220CardatronControl.css
B220CardatronControl.html
B220CardatronControl.js
B220CardatronInput.css
B220CardatronInput.html
B220CardatronInput.js
B220CardatronOutput.css
B220CardatronOutput.html
B220CardatronOutput.js
B220CardatronZeroSuppressPanel.html
B220Common.css
#B220ConsoleInput.css
#B220ConsoleInput.js

View File

@@ -75,7 +75,8 @@ B220SystemConfig.prototype.createConfigData = function createConfigData() {
ConsoleOutput: {
units: [
{type: "TTYA", zeroSuppress: 0, mapMemory: 0, unitMask: 0x001, remote: 1, format: 0, columns: 72, tabs: "9,17,25,33,41,49,57,65,73,81"},
{type: "TTYA", zeroSuppress: 0, mapMemory: 0, unitMask: 0x001, remote: 1, format: 0,
columns: 72, tabs: "9,17,25,33,41,49,57,65,73,81"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
@@ -96,8 +97,8 @@ B220SystemConfig.prototype.createConfigData = function createConfigData() {
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "LP3", algolGlyphs: true, greenBar: true, zeroSuppressCols: ""},
{type: "CP2", algolGlyphs: true, greenBar: false, zeroSuppressCols: ""},
{type: "NONE"},
{type: "LP2", algolGlyphs: true, greenBar: true, zeroSuppressCols: ""},
{type: "CP1", algolGlyphs: true, greenBar: false, zeroSuppressCols: ""}
]},