1
0
mirror of https://github.com/pkimpel/retro-220.git synced 2026-04-04 21:07:29 +00:00

Commit retro-220 version 0.03:

1. Implementation Paper Tape Reader devices and op codes.
2. Commit standard and inverse-format paper tape loaders for WINTER.PI program.
3. Fix positioning of Cardatron and TTY/Paper Tape Punch device windows.
This commit is contained in:
Paul Kimpel
2017-05-29 14:03:42 -07:00
parent 8b6199afd8
commit a95b75bc88
18 changed files with 1555 additions and 315 deletions

View File

@@ -12,8 +12,8 @@ The contents of this project are licensed under the [MIT License](http://www.ope
| Related Sites | URL |
| ------------- | ----- |
| Emulator hosting site | http://www.phkimpel.us/ElectroData/220/ |
| Emulator hosting site | http://www.phkimpel.us/Burroughs-220/ |
| Burroughs 205/220 blog | http://datatron.blogspot.com |
| Datatron 205 site | http://www.phkimpel.us/ElectroData/205/ |
| Datatron 205 site | http://www.phkimpel.us/ElectroData-205/ |
| Documents at bitsavers | http://bitsavers.org/pdf/burroughs/electrodata/220/ |

View File

@@ -237,9 +237,9 @@ function B220Processor(config, devices) {
this.boundConsoleOutputSign = B220Processor.bindMethod(this, B220Processor.prototype.consoleOutputSign);
this.boundConsoleOutputChar = B220Processor.bindMethod(this, B220Processor.prototype.consoleOutputChar);
this.boundConsoleOutputFinished = B220Processor.bindMethod(this, B220Processor.prototype.consoleOutputFinished);
this.boundConsoleInputDigit = B220Processor.bindMethod(this, B220Processor.prototype.consoleInputDigit);
this.boundConsoleReceiveDigit = B220Processor.bindMethod(this, B220Processor.prototype.consoleReceiveDigit);
this.boundConsoleReceiveSingleDigit = B220Processor.bindMethod(this, B220Processor.prototype.consoleReceiveSingleDigit);
this.boundConsoleInputReceiveChar = B220Processor.bindMethod(this, B220Processor.prototype.consoleInputReceiveChar);
this.boundConsoleInputInitiateNormal = B220Processor.bindMethod(this, B220Processor.prototype.consoleInputInitiateNormal);
this.boundConsoleInputInitiateInverse = B220Processor.bindMethod(this, B220Processor.prototype.consoleInputInitiateInverse);
this.boundCardatronOutputWord= B220Processor.bindMethod(this, B220Processor.prototype.cardatronOutputWord);
this.boundCardatronOutputFinished = B220Processor.bindMethod(this, B220Processor.prototype.cardatronOutputFinished);
@@ -260,7 +260,7 @@ function B220Processor(config, devices) {
* Global Constants *
***********************************************************************/
B220Processor.version = "0.02";
B220Processor.version = "0.03";
B220Processor.tick = 1000/200000; // milliseconds per clock cycle (200KHz)
B220Processor.cyclesPerMilli = 1/B220Processor.tick;
@@ -2470,8 +2470,7 @@ B220Processor.prototype.consoleOutputChar = function consoleOutputChar(printChar
this.CADDR = this.C.value%0x10000;
printChar(0x35, this.boundConsoleOutputSign);
}
} else if (this.PZT.value) {
// Output alphabetically
} else if (this.PZT.value) { // Output alphabetically
w = this.D.value % 0x1000000000;
d = (this.D.value - w)/0x1000000000; // get next 2 digits
this.D.set(w*0x100 + d); // rotate D+sign left by two
@@ -2483,8 +2482,7 @@ B220Processor.prototype.consoleOutputChar = function consoleOutputChar(printChar
this.EWT.set(1);
}
printChar(d, this.boundConsoleOutputChar);
} else {
// Output numerically
} else { // Output numerically
if (this.DPT.value && !this.LEADINGZEROESSW) {
// decimal point may be needed
d = this.CCONTROL >>> 12;
@@ -2529,130 +2527,191 @@ B220Processor.prototype.consoleOutputFinished = function consoleOutputFinished()
};
/**************************************/
B220Processor.prototype.consoleInputDigit = function consoleInputDigit() {
// Solicits the next input digit from the Control Console */
B220Processor.prototype.consoleInputFinishWord = function consoleInputFinishWord(result) {
/* Finishes the receipt of a word from the Console paper tape reader and
either stores it in memory or shunts it to the C register for execution.
Updates the C register as necessary and decides whether to initiate receipt
of another word */
var d;
var w;
this.togTF = 0; // for display only, reset finish pulse
this.execTime -= performance.now()*B220Processor.wordsPerMilli; // mark time during I/O
this.console.readDigit(this.boundConsoleReceiveDigit);
};
if (this.sDigit) { // decrement word count
d = this.bcdAdd(this.CCONTROL, 0x990, 3);
this.CCONTROL += d - this.CCONTROL%0x1000;
this.C.set((this.CCONTROL*0x100 + this.COP)*0x10000 + this.CADDR);
}
/**************************************/
B220Processor.prototype.consoleReceiveDigit = function consoleReceiveDigit(digit) {
/* Handles an input digit coming from the Control Console keyboard or
paper-tape reader. Negative values indicate a finish pulse; otherwise
the digit is data read from the device. Data digits are rotated into
the D register; finish pulses are handled according to the sign digit
in the D register */
var sign; // register sign digit
var word; // register word less sign
if (this.COP == 0x05) { // read inverse: permute the sign digit
d = this.D.value%0x10;
w = (this.D.value - d)/0x10;
this.D.set(w + d*0x10000000000);
if (d == 2) { // alphanumeric translation is invalid for inverse mode
this.setPaperTapeCheck(1);
this.ioComplete(true);
return; // >>> ALARM ERROR EXIT <<<
}
} else { // sign digit in normal position
w = this.D.value%0x10000000000;
d = (this.D.value - w)/0x10000000000;
}
this.execTime += performance.now()*B220Processor.wordsPerMilli; // restore time after I/O
if (digit >= 0) {
this.togTC1 = 1-this.togTC1; // for display only
this.togTC2 = 1-this.togTC2; // for display only
this.D.set((this.D.value % 0x10000000000)*0x10 + digit);
this.consoleInputDigit();
} else {
this.togTF = 1;
this.togTC1 = this.togTC2 = 0; // for display only
word = this.D.value%0x10000000000;
sign = (this.D.value - word)/0x10000000000; // get D-sign
if (sign & 0x04) {
// D-sign is 4, 5, 6, 7: execute a "tape control" command
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 = 1;
this.togBTOAIN = 0;
this.togADDAB = 1; // for display only
this.togADDER = 1; // for display only
this.togDPCTR = 1; // for display only
this.togCLEAR = 1-(sign%2);
this.togSIGN = ((this.A.value - this.A.value%0x10000000000)/0x10000000000)%2; // display only
sign &= 0x08;
// Increment the destination address (except on the first word)
this.SHIFTCONTROL = 0x01; // for display only
this.SHIFT = 0x13; // for display only
if (this.togCOUNT) {
this.CCONTROL = this.bcdAdd(this.CADDR, 1, 4);
}
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
this.D.set(sign*0x100000 + (word - word%0x1000000)/0x1000000);
if (this.togCLEAR) {
word = this.bcdAdd(word%0x1000000, 0, 11);
} else {
word = this.bcdAdd(word%0x1000000, this.B.value, 11) % 0x1000000;
}
this.SHIFT = 0x19; // for display only
this.C.set(word*0x10000 + this.CCONTROL); // put C back together
this.CADDR = word % 0x10000;
this.COP = (word - this.CADDR)/0x10000;
this.execute();
} else {
// D-sign is 0, 1, 2, 3: 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.togCLEAR = 1-((sign >>> 1)%2);
this.togSIGN = sign%2;
// 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);
}
this.CCONTROL = this.CADDR;
this.C.set((this.COP*0x10000 + this.CADDR)*0x10000 + this.CCONTROL);
// Modify the word by B as necessary and store it
this.D.set((sign & 0x0C)*0x10000000000 + word);
if (this.togCLEAR) {
this.A.set(this.bcdAdd(this.D.value, 0, 11));
} else {
this.A.set(this.bcdAdd(this.D.value, this.B.value, 11));
}
if (this.rDigit & d & 0x08) { // B-modify word before storing
this.D.set(w + (d&0x07)*0x10000000000);
this.IB.set(this.D.value - w%0x10000 + this.bcdAdd(w, this.B.value, 4));
this.C10.set(0);
} else { // store word as-is
this.IB.set(this.D.value);
}
if (this.rDigit == 1 && (d & 0x0E) == 0x06) { // control word to C register
this.ioComplete(false); // terminate I/O but do not restart Processor yet
this.fetch(true); // set up to execute control word
// Schedule the Processor to give the reader a chance to finish its operation.
setCallback(this.mnemonic, this, 0, this.schedule);
} else { // just store the word
this.writeMemory();
if (this.MET.value) { // memory address error
this.ioComplete(true);
} else if (this.sDigit && this.CCONTROL%0x1000 < 0x10) { // word count exhausted
this.ioComplete(true);
} else { // initiate input of another word
this.D.set(0);
word = this.A.value % 0x10000000000;
sign = (((this.A.value - word)/0x10000000000) & 0x0E) | (sign%2);
this.A.set(sign*0x10000000000 + word);
this.writeMemory(this.boundConsoleInputDigit, false);
if (this.COP == 0x05) {
d = this.console.inputUnitSelect(this.selectedUnit, this.boundConsoleInputInitiateInverse);
} else {
d = this.console.inputUnitSelect(this.selectedUnit, this.boundConsoleInputInitiateNormal);
}
if (d < 0) { // no unit available -- set alarm and quit
this.setPaperTapeCheck(1);
this.ioComplete(true);
}
}
}
};
/**************************************/
B220Processor.prototype.consoleReceiveSingleDigit = function consoleReceiveSingleDigit(digit) {
/* Handles a single input digit coming from the Control Console keyboard
or paper-tape reader, as in the case of Digit Add (10). Negative values
indicate a finish pulse, which is ignored, and causes another digit to be
solicited from the Console; otherwise the digit is (virtually) moved to
the D register and then (actually) added to the A register */
B220Processor.prototype.consoleInputInitiateNormal = function consoleInputInitiateNormal(result) {
/* Initiates the receipt into a word of characters from the Console tape
reader in normal (sign-first) mode. Increments the C register operand address,
rotates the sign digit into the D register, and determines whether the word
should be translated numerically or alphanumerically */
var code = result.code;
this.clockIn();
if (this.AST.value) { // if false, we've probably been cleared
this.E.set(this.CADDR);
this.C.inc();
this.CADDR = this.C.value%0x10000;
switch (code) {
case 0x17: // invalid character/parity error
this.setPaperTapeCheck(1);
this.ioComplete(true);
break;
case 0x35: // end-of-word
this.consoleInputFinishWord(result);
break;
case 0x82: // sign=2, set alpha translation
this.PZT.set(!this.HOLDPZTZEROSW);
this.D.set(2);
result.readChar(this.boundConsoleInputReceiveChar);
break;
default: // anything else, set numeric translation
this.PZT.set(0);
if ((code & 0xF0) == 0x80) {// it's a numeric sign -- okay
this.D.set(code%0x10);
result.readChar(this.boundConsoleInputReceiveChar);
} else if (code == 0) { // we'll take a space as a zero
this.D.set(0);
result.readChar(this.boundConsoleInputReceiveChar);
} else { // sign is non-numeric -- invalid
this.D.set(0);
this.setPaperTapeCheck(1);
this.ioComplete(true);
}
break;
} // switch code
}
};
/**************************************/
B220Processor.prototype.consoleInputInitiateInverse = function consoleInputInitiateInverse(result) {
/* Initiates the receipt into a word of characters from the Console tape
reader in inverse (sign-last) mode. Increments the C register operand address,
rotates the sign digit into the D register, and sets PZT for numeric translation */
var code = result.code;
this.clockIn();
if (this.AST.value) { // if false, we've probably been cleared
this.E.set(this.CADDR);
this.C.inc();
this.CADDR = this.C.value%0x10000;
switch (code) {
case 0x17: // invalid character/parity error
this.setPaperTapeCheck(1);
this.ioComplete(true);
break;
case 0x35: // end-of-word
this.consoleInputFinishWord(result);
break;
default: // anything else, set numeric translation
this.PZT.set(0);
if ((code & 0xF0) == 0x80) {// it's a numeric code -- okay
this.D.set(code%0x10);
result.readChar(this.boundConsoleInputReceiveChar);
} else if (code == 0) { // we'll take a space as a zero
this.D.set(0);
result.readChar(this.boundConsoleInputReceiveChar);
} else { // digit is non-numeric -- invalid
this.D.set(0);
this.setPaperTapeCheck(1);
this.ioComplete(true);
}
break;
} // switch code
}
};
/**************************************/
B220Processor.prototype.consoleInputReceiveChar = function consoleInputReceiveChar(result) {
/* Handles an input character coming from the Console paper-tape reader.
result.code is the B220 character code read from the device. result.readChar
is the callback function to request the next character. Data digits are
rotated into the D register; end-of-word (0x35) codes are handled according
to the sign digit in the D register */
var code = result.code; // character received
var sign; // register sign digit
var word; // register word less sign
if (digit < 0) { // ignore finish pulse and just re-solicit
this.console.readDigit(this.boundConsoleReceiveSingleDigit);
} else {
this.execTime += performance.now()*B220Processor.wordsPerMilli + 4; // restore time after I/O
this.togSTART = 0;
this.D.set(digit);
this.integerAdd(false, false);
this.schedule();
this.clockIn();
if (this.AST.value) { // if false, we've probably been cleared
switch (code) {
case 0x17: // invalid character/parity error
this.setPaperTapeCheck(1);
this.ioComplete(true);
break;
case 0x35: // end-of-word
this.consoleInputFinishWord(result);
break;
default: // anything else, accumulate digits in word
if (this.PZT.value) { // alphanumeric translation
this.D.set((this.D.value % 0x1000000000)*0x100 + code);
result.readChar(this.boundConsoleInputReceiveChar);
} else { // numeric translation
if ((code & 0xF0) == 0x80) {// it's a numeric code -- okay
this.D.set((this.D.value % 0x10000000000)*0x10 + code%0x10);
result.readChar(this.boundConsoleInputReceiveChar);
} else if (code == 0) { // we'll take a space as a zero
this.D.set((this.D.value % 0x10000000000)*0x10);
result.readChar(this.boundConsoleInputReceiveChar);
} else { // code is non-numeric -- invalid
this.setPaperTapeCheck(1);
this.ioComplete(true);
}
}
break;
} // switch code
}
};
@@ -3072,18 +3131,60 @@ B220Processor.prototype.execute = function execute() {
break;
case 0x03: //--------------------- PRD Paper tape read
this.setProgramCheck(1);
this.operationComplete();
this.opTime = 0.185; // just a guess...
d = this.CCONTROL >>> 12; // get unit number
if (d == 0) {
d = 10; // xlate unit 0 to unit 10
}
this.selectedUnit = d;
this.rDigit = this.CCONTROL & 0x0F;
this.sDigit = 1; // use word count in C (32)
this.D.set(0);
this.ioInitiate();
d = this.console.inputUnitSelect(this.selectedUnit, this.boundConsoleInputInitiateNormal);
if (d < 0) { // no unit available -- set alarm and quit
this.setPaperTapeCheck(1);
this.ioComplete(true);
}
break;
case 0x04: //--------------------- PRB Paper tape read, branch
this.setProgramCheck(1);
this.operationComplete();
this.opTime = 0.185; // just a guess...
d = this.CCONTROL >>> 12; // get unit number
if (d == 0) {
d = 10; // xlate unit 0 to unit 10
}
this.selectedUnit = d;
this.rDigit = (this.CCONTROL & 0x0E) | 1; // force recognition of control words
this.sDigit = 0; // do not use word count in C (32)
this.D.set(0);
this.ioInitiate();
d = this.console.inputUnitSelect(this.selectedUnit, this.boundConsoleInputInitiateNormal);
if (d < 0) { // no unit available -- set alarm and quit
this.setPaperTapeCheck(1);
this.ioComplete(true);
}
break;
case 0x05: //--------------------- PRI Paper tape read, inverse format
this.setProgramCheck(1);
this.operationComplete();
this.opTime = 0.185; // just a guess...
d = this.CCONTROL >>> 12; // get unit number
if (d == 0) {
d = 10; // xlate unit 0 to unit 10
}
this.selectedUnit = d;
this.rDigit = (this.CCONTROL & 0x0E) | 1; // force recognition of control words
this.sDigit = 1; // use word count in C (32)
this.D.set(0);
this.ioInitiate();
d = this.console.inputUnitSelect(this.selectedUnit, this.boundConsoleInputInitiateInverse);
if (d < 0) { // no unit available -- set alarm and quit
this.setPaperTapeCheck(1);
this.ioComplete(true);
}
break;
case 0x06: //--------------------- PWR Paper tape write
@@ -3093,6 +3194,7 @@ B220Processor.prototype.execute = function execute() {
d = 10; // xlate unit 0 to unit 10
}
this.selectedUnit = d;
this.ioInitiate();
d = this.console.outputUnitSelect(d, this.boundConsoleOutputSign);
if (d < 0) { // no unit available -- set alarm and quit
@@ -3107,6 +3209,7 @@ B220Processor.prototype.execute = function execute() {
d = 10; // xlate unit 0 to unit 10
}
this.selectedUnit = d;
d = this.console.outputUnitSelect(d, B220Processor.emptyFunction);
if (d < 0) { // if not ready, continue in sequence
this.opTime = 0.015;
@@ -3762,11 +3865,6 @@ B220Processor.prototype.execute = function execute() {
switch (-1) {
case 0x00: //---------------- PTR Paper-tape/keyboard read
this.D.set(0);
this.togSTART = 1;
this.consoleInputDigit();
break;
case 0x40: //---------------- MTR Magnetic Tape Read
if (!this.magTape) {
@@ -3823,46 +3921,6 @@ B220Processor.prototype.execute = function execute() {
}
}
break;
case 0x54: //---------------- CDW Card Write (Cardatron)
if (!this.cardatron) {
//this.schedule();
} else {
this.tog3IO = 1;
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.CCONTROL >>> 12) & 0x0F,
this.boundCardatronOutputWord, this.boundCardatronOutputFinished);
}
break;
case 0x55: //---------------- CDWI Card Write Interrogate
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
this.OFT.set(1); // set overflow
this.COP = 0x28; // make into a CC
this.C.set((this.COP*0x10000 + this.CADDR)*0x10000 + this.CCONTROL);
}
break;
case 0x58: //---------------- CDWF Card Write Format
if (!this.cardatron) {
//this.schedule();
} else {
this.tog3IO = 1;
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,
this.boundCardatronOutputWord, this.boundCardatronOutputFinished);
}
break;
default: //---------------- (unimplemented instruction -- alarm)
break;
} // switch this.COP

View File

@@ -0,0 +1,81 @@
61000050500
1005710
4005650
1005630
14800100
1505750
4205650
00004010001
12105060
1005650
1405740
14005680
3705620
4605660
1005650
4005640
4205640
00001010001
1405630
14900100
1205660
4005660
14800100
12705680
1505680
00014010001
4005660
12705680
1005640
1305730
4005640
3605340
1405660
14005660
12105160
142705650
1005660
14800100
1505630
1205670
14005670
14800030
1205760
4900010
14900010
1205760
4900010
14900010
1205760
4900010
14900010
1205760
4900020
24300000
4005640
100905640
4052605690
1005690
1805700
13405080
100905770
4605690
3005080
75570
100000
0
0
0
0
0
0
500
28000
0
10
20
50
800
10000405776
20202021616
60000300500

View File

@@ -0,0 +1,80 @@
61000040500
00000100571
00000400565
00000100563
00001480010
00000150575
00000420565
10000401000
00001210506
00000100565
00000140574
00001400568
00000370562
00000460566
00000100565
00000400564
00000420564
10000101000
00000140563
00001490010
00000120566
00000400566
00001480010
00001270568
00000150568
10001401000
00000400566
00001270568
00000100564
00000130573
00000400564
00000360534
00000140566
00001400566
00001210516
00014270565
00000100566
00001480010
00000150563
00000120567
00001400567
00001480003
00000120576
00000490001
00001490001
00000120576
00000490001
00001490001
00000120576
00000490001
00001490001
00000120576
00000490002
00002430000
00000400564
00010090564
00405260569
00000100569
00000180570
00001340508
00010090577
00000460569
00000300508
00000007557
00000010000
00000000000
00000000000
00000000000
00000000000
00000000000
00000000000
00000000050
00000002800
00000000000
00000000001
00000000002
00000000005
00000000080
2___||
60000300500

View File

@@ -38,13 +38,12 @@
<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>
<script src="./B220ConsolePrinter.js"></script>
<script src="./B220PaperTapePunch.js"></script>
<script src="./B220PaperTapeReader.js"></script>
<script src="./B220ControlConsole.js"></script>
<script src="./B220.js"></script>

View File

@@ -15,7 +15,7 @@
/**************************************/
function B220CardatronControl(p) {
/* Constructor for the CardatronControl object */
var left = 660; // left window margin
var left = 600; // left window margin
var u; // unit config object
var x; // unit index
@@ -27,7 +27,8 @@ function B220CardatronControl(p) {
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);
"location=no,scrollbars=no,resizable,width=140,height=140,left=" + left +
",top=" + (screen.availHeight-140));
this.window.addEventListener("load",
B220Util.bindMethod(this, B220CardatronControl.prototype.cardatronOnLoad));
@@ -168,6 +169,8 @@ B220CardatronControl.prototype.cardatronOnLoad = function cardatronOnLoad() {
B220Util.bindMethod(this, B220CardatronControl.prototype.ClearBtn_onClick));
this.clear();
this.window.moveTo(this.window.screenX, screen.availHeight - this.window.outerHeight);
};
/**************************************/

View File

@@ -65,7 +65,8 @@ function B220CardatronInput(mnemonic, unitIndex, config) {
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));
",left=" + ((unitIndex-1)*32) +
",top=" + (screen.availHeight - h - (unitIndex-1)*32));
this.window.addEventListener("load",
B220Util.bindMethod(this, B220CardatronInput.prototype.readerOnLoad), false);
}
@@ -522,7 +523,7 @@ B220CardatronInput.prototype.finishCardRead = function finishCardRead() {
c = card.charCodeAt(col); // translate char to buffer code
if (c < 0x80) {
c = this.cardFilter[c];
} else if (c == 0xA4) { // the "lozenge" ("¤")
} else if (c == 0xA4) { // the "lozenge" ("¤")
c = this.cardFilter[0x3C]; // use the code for "<"
} else {
c = 0;
@@ -632,6 +633,8 @@ B220CardatronInput.prototype.readerOnLoad = function readerOnLoad() {
this.window.resizeBy(de.scrollWidth - this.window.innerWidth + 4, // kludge for right-padding/margin
de.scrollHeight - this.window.innerHeight);
this.window.moveTo(0, screen.availHeight - this.window.outerHeight - (this.unitIndex-1)*32);
};
/**************************************/

View File

@@ -68,7 +68,7 @@ function B220CardatronOutput(mnemonic, unitIndex, config) {
this.window = window.open("../webUI/B220CardatronOutput.html", mnemonic,
"location=no,scrollbars,resizable,width=" + w + ",height=" + h +
",left=" + (screen.availWidth - w) +
",top=" + (screen.availHeight - h - (unitIndex-1)*24));
",top=" + (screen.availHeight - h - (unitIndex-3)*32));
this.window.addEventListener("load",
B220Util.bindMethod(this, B220CardatronOutput.prototype.deviceOnLoad), false);
}
@@ -786,6 +786,9 @@ B220CardatronOutput.prototype.deviceOnLoad = function deviceOnLoad() {
this.$$("COGreenbarCheck").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.COGreenbarCheck_onClick), false);
}
this.window.moveTo(screen.availWidth - this.window.outerWidth,
screen.availHeight - this.window.outerHeight - (7-this.unitIndex)*32);
};
/**************************************/

View File

@@ -18,6 +18,7 @@ function B220ControlConsole(p, systemShutdown) {
var h = 600;
var w = 1064;
var mnemonic = "ControlConsole";
var inputConfig = p.config.getNode("ConsoleInput");
var outputConfig = p.config.getNode("ConsoleOutput");
var u;
var x;
@@ -36,8 +37,34 @@ function B220ControlConsole(p, systemShutdown) {
this.boundResetTimer = B220Util.bindMethod(this, B220ControlConsole.prototype.resetTimer);
this.boundUpdatePanel = B220Util.bindMethod(this, B220ControlConsole.prototype.updatePanel);
// Configure the console input unit objects. These are paper-tape readers.
this.inputUnit = [
null, // unit[0] not used
null, // 1=unit A
null, // 2=unit B
null, // 3=unit C
null, // 4=unit D
null, // 5=unit E
null, // 6=unit F
null, // 7=unit G
null, // 8=unit H
null, // 9=unit I
null]; //10=unit J
for (x=1; x<inputConfig.units.length; ++x) {
u = inputConfig.units[x];
switch (u.type.substring(0, 3)) {
case "PTR":
this.inputUnit[x] = new B220PaperTapeReader(u.type, x, this.config);
break;
default:
this.inputUnit[x] = null;
break;
} // switch u.type
}
// Configure the console output unit objects. These can be any combination
// of paper tape punches and teletype printers.
// of paper-tape punches and teletype printers.
this.outputUnit = [
null, // 0=unit A (usually the SPO)
null, // 1=unit B
@@ -717,6 +744,8 @@ B220ControlConsole.prototype.consoleOnLoad = function consoleOnLoad() {
this.$$("EmulatorVersion").textContent = B220Processor.version;
this.window.moveTo(screen.availWidth - this.window.outerWidth, 0);
// Power on the system by default...
setCallback(this.mnemonic, this, 1000, function powerOnTimer() {
this.powerOnSystem();
@@ -755,6 +784,30 @@ B220ControlConsole.prototype.outputUnitSelect = function outputUnitSelect(unitNr
return result;
};
/**************************************/
B220ControlConsole.prototype.inputUnitSelect = function inputUnitSelect(unitNr, successor) {
/* Prepares for paper-tape input by selecting the first ready device
having a unitMask matching the unitNr parameter. If one is found, returns
that index and schedules initiateInput() for the unit. If no such unit is
found, returns -1 */
var result = -1; // be pessimistic
var u = null; // input unit object
var x; // for loop index
for (x=1; x<this.inputUnit.length; ++x) {
u = this.inputUnit[x];
if (u && u.ready) {
if (u.unitMask & B220Processor.pow2[unitNr]) {
result = x;
setCallback(this.mnemonic, u, 1, u.initiateInput, successor);
break; // out of for loop
}
}
}
return result;
};
/**************************************/
B220ControlConsole.prototype.shutDown = function shutDown() {
/* Shuts down the panel */
@@ -774,5 +827,12 @@ B220ControlConsole.prototype.shutDown = function shutDown() {
}
}
for (x=1; x<this.inputUnit.length; ++x) {
if (this.inputUnit[x]) {
this.inputUnit[x].shutDown();
this.inputUnit[x] = null;
}
}
this.window.close();
};

View File

@@ -1,5 +1,5 @@
CACHE MANIFEST
# retro-220 emulator 0.02, 2017-05-24 09:00
# retro-220 emulator 0.03, 2017-05-29 13:30
CACHE:
../emulator/B220Processor.js
B220.css
@@ -16,8 +16,6 @@ B220CardatronOutput.html
B220CardatronOutput.js
B220CardatronZeroSuppressPanel.html
B220Common.css
#B220ConsoleInput.css
#B220ConsoleInput.js
B220ConsoleKeyboard.css
B220ConsoleKeyboard.html
B220ConsoleKeyboard.js
@@ -43,7 +41,9 @@ B220PanelUtil.js
B220PaperTapePunch.css
B220PaperTapePunch.html
B220PaperTapePunch.js
#B220PaperTapeReader.html
B220PaperTapeReader.css
B220PaperTapeReader.html
B220PaperTapeReader.js
B220SetCallback.js
B220SystemConfig.css
B220SystemConfig.html

View File

@@ -26,36 +26,6 @@
margin: 4px;
border-radius: 8px}
#PunchTape {
position: absolute;
left: 8px;
right: 8px;
top: 60px;
bottom: 8px;
min-height: 32px;
min-width: 120px;
overflow-x: hidden;
overflow-y: scroll;
color: black;
background-color: white;
padding: 4px;
border: 1px solid gray}
#Paper {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding: 0}
#EndOfPaper {
display: block;
margin: 0;
padding: 0;
opacity: 0}
#EndOfPaper.hidden {
display: none}
#RemoteSwitch {
position: absolute;
width: 24px;
@@ -92,3 +62,33 @@
width: 64px;
right: 8px;
top: 6px}
#PunchTape {
position: absolute;
left: 8px;
right: 8px;
top: 60px;
bottom: 8px;
min-height: 32px;
min-width: 120px;
overflow-x: hidden;
overflow-y: scroll;
color: black;
background-color: white;
padding: 4px;
border: 1px solid gray}
#Paper {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding: 0}
#EndOfPaper {
display: block;
margin: 0;
padding: 0;
opacity: 0}
#EndOfPaper.hidden {
display: none}

View File

@@ -15,8 +15,8 @@
/**************************************/
function B220PaperTapePunch(mnemonic, unitIndex, config) {
/* Constructor for the Console Paper Tape Punch object */
var top = unitIndex*32;
var left = unitIndex*32;
var top = unitIndex*32 + 360;
var left = (unitIndex-1)*32;
this.config = config; // System configuration object
this.mnemonic = mnemonic; // Unit mnemonic
@@ -25,8 +25,6 @@ function B220PaperTapePunch(mnemonic, unitIndex, config) {
this.nextCharTime = 0; // next time a character can be punched
this.unitMask = 0; // unit selection mask
this.unitSwitch = new Array(11); // unit selection switch objects
this.tabStop = []; // 0-relative tab stop positions
this.boundFlipSwitch = B220Util.bindMethod(this, B220PaperTapePunch.prototype.flipSwitch);
this.boundReceiveSign = B220Util.bindMethod(this, B220PaperTapePunch.prototype.receiveSign);
@@ -57,18 +55,19 @@ B220PaperTapePunch.maxScrollLines = 45000;
B220PaperTapePunch.codeXlate = [ // translate internal B220 code to ANSI
// Note that ANSI new-line sequences are used for end-of-word characters,
// so B220 carriage-return translates to "|". To avoide space-expansion of
// tab characters, they are translated to "~".
" ", "?", " ", ".", "\u00A4", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 00-0F
"&", "?", "?", "$", "*", "\f", "|", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 10-1F
"-", "/", "?", ",", "%", "?", "~", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 20-2F
"?", "?", "?", "#", "@", "!", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 30-3F
"?", "A", "B", "C", "D", "E", "F", "G", "H", "I", "?", "?", "?", "?", "?", "?", // 40-4F
"?", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "?", "?", "?", "?", "?", "?", // 50-5F
"?", "?", "S", "T", "U", "V", "W", "X", "Y", "Z", "?", "?", "?", "?", "?", "?", // 60-6F
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 70-7F
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "?", "?", "?", "?", "?", "?", // 80-8F
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]; // 90-9F
// so B220 carriage-return (16) translates to "|". To avoid space-expansion
// of tabs (26), they are translated to "~". The 02 "blank" code is "_".
// Form-feed (15) translates to "^".
" ", "?", "_", ".", "\u00A4", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 00-0F
"&", "?", "?", "$", "*", "^", "|", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 10-1F
"-", "/", "?", ",", "%", "?", "~", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 20-2F
"?", "?", "?", "#", "@", "!", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 30-3F
"?", "A", "B", "C", "D", "E", "F", "G", "H", "I", "?", "?", "?", "?", "?", "?", // 40-4F
"?", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "?", "?", "?", "?", "?", "?", // 50-5F
"?", "?", "S", "T", "U", "V", "W", "X", "Y", "Z", "?", "?", "?", "?", "?", "?", // 60-6F
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 70-7F
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "?", "?", "?", "?", "?", "?", // 80-8F
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]; // 90-9F
/**************************************/
@@ -79,16 +78,6 @@ B220PaperTapePunch.prototype.clear = function clear() {
this.busy = false; // busy status
};
/**************************************/
B220PaperTapePunch.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;
};
/**************************************/
B220PaperTapePunch.prototype.$$ = function $$(e) {
return this.doc.getElementById(e);
@@ -136,6 +125,16 @@ B220PaperTapePunch.prototype.punchChar = function punchChar(code) {
}
};
/**************************************/
B220PaperTapePunch.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;
};
/**************************************/
B220PaperTapePunch.prototype.resizeWindow = function resizeWindow(ev) {
/* Handles the window onresize event by scrolling the "tape" so it remains at the end */
@@ -202,13 +201,13 @@ B220PaperTapePunch.prototype.flipSwitch = function flipSwitch(ev) {
B220PaperTapePunch.prototype.punchOnLoad = function punchOnLoad() {
/* Initializes the Paper Tape Punch window and user interface */
var body;
var id;
var mask;
var prefs = this.config.getNode("ConsoleOutput.units", this.unitIndex);
var x;
this.doc = this.window.document;
this.doc.title = "retro-220 Punch - " + this.mnemonic;
this.punchTape = this.$$("Paper");
this.punchEOP = this.$$("EndOfPaper");
this.punchEmptyPaper();
@@ -248,8 +247,8 @@ B220PaperTapePunch.prototype.punchOnLoad = function punchOnLoad() {
this.remoteSwitch.addEventListener("click", this.boundFlipSwitch);
this.unitDesignateKnob.addEventListener("change", this.boundFlipSwitch);
//this.punchWin.moveTo(screen.availWidth-this.punchWin.outerWidth,
// screen.availHeight-this.punchWin.outerHeight);
//this.punchWin.resizeBy(screen.availWidth - this.punchWin.outerWidth,
// screen.availHeight - this.punchWin.outerHeight);
//this.punchWin.moveTo(0, 430);
this.window.focus();
};

View File

@@ -0,0 +1,108 @@
/***********************************************************************
* retro-220/webUI B220PaperTapeReader.css
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php.
************************************************************************
* Burroughs 220 emulator Paper Tape Reader interface style sheet.
************************************************************************
* 2017-05-27 P.Kimpel
* Original version, from retro-205 D205ConsoleInput.css.
***********************************************************************/
#ReaderBody {
height: 100%;
min-height: 100%;
overflow: hidden;
padding: 0}
#PaperTapeReader {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 4px;
border-radius: 8px}
#RemoteSwitch {
position: absolute;
width: 24px;
left: 18px;
top: 12px}
#RemoteSwitchOn {
width: 36px;
left: 12px;
top: 6px}
#RemoteSwitchOff {
width: 36px;
left: 12px;
top: 42px}
#ReadyLamp {
position: absolute;
width: 24px;
left: 56px;
top: 14px}
#ReadyLampCaption {
width: 36px;
left: 52px;
top: 6px}
#SpeedSwitch {
position: absolute;
width: 24px;
left: 96px;
top: 12px}
#SpeedSwitchHi {
width: 36px;
left: 92px;
top: 6px}
#SpeedSwitchLow {
width: 36px;
left: 92px;
top: 42px}
#SpeedSwitchCaption {
width: 36px;
left: 120px;
top: 24px}
#UnitDesignateKnob {
position: absolute;
text-align: center;
width: 64px;
right: 8px;
top: 18px;
color: white;
background-color: #333}
#UnitDesignateKnobCaption {
width: 64px;
right: 8px;
top: 6px}
#PRFileSelector {
position: absolute;
left: 8px;
top: 60px;
width: calc(100% - 16px);
color: black;
border: 1px solid #666}
#PRTapeSupplyBar {
position: absolute;
top: 92px;
left: 8px;
width: calc(100% - 16px);
height: 16px;
border: 1px solid #666}
#PRTapeView {
position: absolute;
text-align: right;
bottom: 8px;
left: 8px;
width: calc(100% - 16px);
height: 2em;
background-color: white;
border: none}

View File

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>retro-220 Emulator Paper Tape Reader</title>
<!--
/***********************************************************************
* retro-220/webUI B220PaperTapeReader.html
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 Paper Tape Reader device page.
************************************************************************
* 2017-05-27 P.Kimpel
* Original version, from retro-205 D205PaperTapeReader.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=tapeReaderStyleSheet rel=stylesheet type="text/css" href="B220PaperTapeReader.css">
</head>
<body id=ReaderBody class=deviceBody>
<div id=PaperTapeReader class=panelSurface>
<div id=RemoteSwitchOn class=caption>REMOTE</div>
<div id=RemoteSwitchOff class=caption>LOCAL</div>
<div id=ReadyLampCaption class=caption>READY</div>
<div id=SpeedSwitchHi class=caption>HI</div>
<div id=SpeedSwitchLow class=caption>LOW</div>
<div id=SpeedSwitchCaption class=caption>SPEED</div>
<div id=UnitDesignateKnobCaption class=caption>UNIT DESIGNATE</div>
<select id=UnitDesignateKnob>
<option value= 0>SPO
<option value= 1>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>0
<option value=99>OFF
</select>
<input id=PRFileSelector type=file size=60 multiple>
<meter id=PRTapeSupplyBar min=0 max=100 value=0 title="Click to clear input tape"></meter>
<input id=PRTapeView type=text READONLY>
</div>
</body>
</html>

View File

@@ -0,0 +1,412 @@
/***********************************************************************
* retro-220/webUI B220PaperTapeReader.js
************************************************************************
* Copyright (c) 2017, Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* Burroughs 220 Paper Tape Reader module.
*
* Defines the paper tape input devices.
*
************************************************************************
* 2017-05-27 P.Kimpel
* Original version, from retro-205 D205ConsoleInput.js.
***********************************************************************/
"use strict";
/**************************************/
function B220PaperTapeReader(mnemonic, unitIndex, config) {
/* Constructor for the PaperTapeReader object */
var top = unitIndex*32 + 360;
var left = (unitIndex-1)*32 + 250;
this.config = config; // System configuration object
this.mnemonic = mnemonic; // Unit mnemonic
this.unitIndex = unitIndex; // Unit index into console output units
this.inTimer = 0; // input setCallback() token
this.charPeriod = B220PaperTapeReader.highSpeedPeriod;
// paper-tape reader speed [ms/char]
this.nextCharTime = 0; // next time a character can be read
this.unitMask = 0; // unit selection mask
this.boundFlipSwitch = B220Util.bindMethod(this, B220PaperTapeReader.prototype.flipSwitch);
this.boundReadTapeChar = B220Util.bindMethod(this, B220PaperTapeReader.prototype.readTapeChar);
this.readResult = { // object passed back to Processor for each read
code: 0,
readChar: this.boundReadTapeChar
};
this.clear();
// Create the reader window and onload event
this.doc = null;
this.tapeSupplyBar = null;
this.tapeView = null;
this.window = window.open("../webUI/B220PaperTapeReader.html", mnemonic,
"location=no,scrollbars=no,resizable,width=420,height=160,left=" + left + ",top=" + top);
this.window.addEventListener("load",
B220Util.bindMethod(this, B220PaperTapeReader.prototype.readerOnload), false);
}
/**************************************/
B220PaperTapeReader.offSwitchImage = "./resources/ToggleDown.png";
B220PaperTapeReader.onSwitchImage = "./resources/ToggleUp.png";
B220PaperTapeReader.lowSpeedPeriod = 1000/500;
// low reader speed: 500 cps
B220PaperTapeReader.highSpeedPeriod = 1000/1000;
// high reader speed: 1000 cps
B220PaperTapeReader.startupTime = 5; // reader start-up delay, ms
B220PaperTapeReader.idleTime = 50; // idle time before reader requires start-up delay, ms
// Translate ANSI character codes to B220 charater codes.
// Note that ANSI new-line sequences are used for end-of-word characters,
// so "|" translates to B220 carriage-return (16). To avoid space-expansion
// of tabs, "~" translates to tab (26). "_" translates to the "blank" code (02).
// "^" translates to form-feed (15).
B220PaperTapeReader.xlate220 = [
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x26, 0x16, 0x17, 0x15, 0x16, 0x17, 0x17, // 00-0F
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // 10-1F
0x00, 0x17, 0x17, 0x33, 0x13, 0x24, 0x10, 0x34, 0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, // 20-2F
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x17, 0x13, 0x04, 0x33, 0x17, 0x17, // 30-3F
0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, // 40-4F
0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x17, 0x17, 0x17, 0x15, 0x02, // 50-5F
0x17, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, // 60-6F
0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x17, 0x16, 0x17, 0x26, 0x17, // 70-7F
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // 80-8F
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // 90-9F
0x17, 0x17, 0x17, 0x17, 0x04, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // A0-AF
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // B0-BF
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // C0-CF
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // D0-DF
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // E0-EF
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17];// F0-FF
/**************************************/
B220PaperTapeReader.prototype.clear = function clear() {
/* Initializes (and if necessary, creates) the reader unit state */
this.ready = false; // a tape has been loaded into the reader
this.busy = false; // a request for a digit is outstanding
this.pendingReceiver = null; // stashed digit-receiver function
this.buffer = ""; // reader input buffer (paper-tape reel)
this.bufLength = 0; // current input buffer length (characters)
this.bufIndex = 0; // 0-relative offset to next character to be read
};
/**************************************/
B220PaperTapeReader.prototype.$$ = function $$(e) {
return this.doc.getElementById(e);
};
/**************************************/
B220PaperTapeReader.prototype.PRTapeSupplyBar_onclick = function PRTapeSupplyBar_onclick(ev) {
/* Handle the click event for the "input hopper" meter bar */
if (!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 reader input?")) {
this.tapeView.value = "";
this.setReaderEmpty();
}
}
};
/**************************************/
B220PaperTapeReader.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 buffer of the reader */
var tape;
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":
break; // do nothing -- the last word has a delimiter
default:
that.buffer += "\n"; // so the next tape 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.$$("PRTapeSupplyBar").value = that.bufLength;
that.$$("PRTapeSupplyBar").max = that.bufLength;
that.setReaderReady(true);
if (that.busy && that.ready) { // reinitiate the pending read
that.readTapeChar(that.pendingReceiver);
that.receiver = null;
}
}
for (x=f.length-1; x>=0; x--) {
tape = new FileReader();
tape.onload = fileLoader_onLoad;
tape.readAsText(f[x]);
}
};
/**************************************/
B220PaperTapeReader.prototype.setReaderReady = function setReaderReady(ready) {
/* Sets the reader to a ready or not-ready status */
this.ready = ready && this.remoteSwitch.state && (this.bufIndex < this.bufLength);
this.readyLamp.set(this.ready ? 1 : 0);
};
/**************************************/
B220PaperTapeReader.prototype.setReaderEmpty = function setReaderEmpty() {
/* Sets the reader to a not-ready status and empties the buffer */
this.setReaderReady(false);
this.tapeSupplyBar.value = 0;
this.buffer = ""; // discard the input buffer
this.bufLength = 0;
this.bufIndex = 0;
this.fileSelector.value = null; // reset the control so the same file can be reloaded
};
/**************************************/
B220PaperTapeReader.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;
};
/**************************************/
B220PaperTapeReader.prototype.flipSwitch = function flipSwitch(ev) {
/* Handler for switch clicks */
var id = ev.target.id;
var prefs = this.config.getNode("ConsoleInput.units", this.unitIndex);
var x;
switch (id) {
case "RemoteSwitch":
this.remoteSwitch.flip();
prefs.remote = this.remoteSwitch.state;
this.setReaderReady(this.remoteSwitch.state != 0);
this.fileSelector.disabled = (this.remoteSwitch.state != 0);
break;
case "SpeedSwitch":
this.speedSwitch.flip();
prefs.speed = this.speedSwitch.state;
this.charPeriod = (this.speedSwitch.state ? B220PaperTapeReader.highSpeedPeriod : B220PaperTapeReader.lowSpeedPeriod);
break;
case "UnitDesignateKnob":
x = this.unitDesignateKnob.selectedIndex;
if (x < 0) {
x = this.unitDesignateKnob.length-1;
this.unitMask = 0;
} else {
this.unitMask = B220Processor.pow2[x];
prefs.unitMask = this.unitMask
}
break;
}
this.config.putNode("ConsoleInput.units", prefs, this.unitIndex);
ev.preventDefault();
ev.stopPropagation();
};
/**************************************/
B220PaperTapeReader.prototype.readerOnload = function readerOnload() {
/* Initializes the reader window and user interface */
var body;
var mask;
var prefs = this.config.getNode("ConsoleInput.units", this.unitIndex);
var x;
this.doc = this.window.document;
//de = this.doc.documentElement;
this.doc.title = "retro-220 - Reader - " + this.mnemonic;
this.fileSelector = this.$$("PRFileSelector");
this.tapeSupplyBar = this.$$("PRTapeSupplyBar");
this.tapeView = this.$$("PRTapeView");
body = this.$$("PaperTapeReader")
this.remoteSwitch = new ToggleSwitch(body, null, null, "RemoteSwitch",
B220PaperTapeReader.offSwitchImage, B220PaperTapeReader.onSwitchImage);
this.remoteSwitch.set(prefs.remote);
this.readyLamp = new ColoredLamp(body, null, null, "ReadyLamp", "blueLamp lampCollar", "blueLit");
this.setReaderReady(this.remoteSwitch.state != 0);
this.speedSwitch = new ToggleSwitch(body, null, null, "SpeedSwitch",
B220PaperTapeReader.offSwitchImage, B220PaperTapeReader.onSwitchImage);
this.speedSwitch.set(prefs.speed);
this.charPeriod = (this.speedSwitch.state ? B220PaperTapeReader.highSpeedPeriod : B220PaperTapeReader.lowSpeedPeriod);
this.unitDesignateKnob = this.$$("UnitDesignateKnob");
mask = 0x001;
this.unitMask = prefs.unitMask;
if (this.unitMask == 0) {
this.unitDesignateKnob.selectedIndex = this.unitDesignateKnob.length-1; // OFF
} else {
for (x=0; x<this.unitDesignateKnob.length; ++x) {
if (this.unitMask & mask) {
this.unitDesignateKnob.selectedIndex = x;
break; // out of for loop
} else {
mask <<= 1;
}
}
}
this.fileSelector.disabled = (this.remoteSwitch.state != 0);
// Events
this.window.addEventListener("beforeunload",
B220PaperTapeReader.prototype.beforeUnload, false);
this.fileSelector.addEventListener("change",
B220Util.bindMethod(this, B220PaperTapeReader.prototype.fileSelector_onChange));
this.tapeSupplyBar.addEventListener("click",
B220Util.bindMethod(this, B220PaperTapeReader.prototype.PRTapeSupplyBar_onclick));
this.remoteSwitch.addEventListener("click", this.boundFlipSwitch);
this.speedSwitch.addEventListener("click", this.boundFlipSwitch);
this.unitDesignateKnob.addEventListener("change", this.boundFlipSwitch);
//this.window.resizeBy(de.scrollWidth - this.window.innerWidth + 4, // kludge for right-padding/margin
// de.scrollHeight - this.window.innerHeight);
};
/***********************************************************************
* Input Entry Points *
***********************************************************************/
/**************************************/
B220PaperTapeReader.prototype.initiateInput = function initiateInput(successor) {
/* Initiates input to the reader. This simply calls this.readTapeChar(),
which returns the first tape character (which should be the sign digit) to
the processor and gets the ball rolling */
var stamp = performance.now();
if (stamp-this.nextCharTime < B220PaperTapeReader.idleTime) {
this.readTapeChar(successor);
} else {
setCallback(this.mnemonic, this, B220PaperTapeReader.startupTime, this.readTapeChar, successor);
}
};
/**************************************/
B220PaperTapeReader.prototype.sendTapeChar = function sendTapeChar(c, code, receiver) {
/* Sends the character or EOW code read from the tape back to the
Processor after an appropriate delay. Updates the TapeView display with the
character sent */
var delay;
var length;
var stamp = performance.now();
var text = this.tapeView.value;
this.readResult.code = code;
if (this.nextCharTime < stamp) {
delay = 0;
this.nextCharTime = stamp + this.charPeriod;
} else {
delay = this.nextCharTime - stamp;
this.nextCharTime += this.charPeriod;
}
this.inTimer = setCallback(this.mnemonic, this, delay, receiver, this.readResult);
length = text.length;
if (length < 120) {
this.tapeView.value = text + String.fromCharCode(c);
++length;
} else {
this.tapeView.value = text.substring(length-119) + String.fromCharCode(c);
}
this.tapeView.setSelectionRange(length-1, length);
};
/**************************************/
B220PaperTapeReader.prototype.readTapeChar = function readTapeChar(receiver) {
/* Reads one character frame from the paper-tape buffer and passes it to the
"receiver" function. If at end-of-line, passes an end-of-word (0x35) code;
an error or invalid character is passed as a 0x17 code. Otherwise, the ANSI
character is translated to B220 code and that code is passed.
If the buffer is empty (this.ready=false) or we are at end of buffer,
simply exits after stashing a reference to the receiver function in
this.pendingReceiver. This will leave the processor hanging until more tape
is loaded into the reader or the processor is cleared. Once more tape is
loaded, the fileSelector_onChange event will set ready, notice the hanging
read (this.busy=true) and restart the read */
var bufLength = this.bufLength; // current buffer length
var c; // current character ANSI code
var x = this.bufIndex; // current buffer index
if (!this.ready) {
this.busy = true;
this.pendingReceiver = receiver;// stash the receiver until tape is loaded
this.window.focus(); // call attention to the tape reader
} else {
this.busy = false;
do {
if (x >= bufLength) { // end of buffer -- send finish
this.sendTapeChar(0x20, 0x35, receiver);
this.setReaderEmpty();
break; // out of do loop
} else {
c = this.buffer.charCodeAt(x) % 0x100;
if (c == 0x0D) { // carriage return -- send EOW and check for LF
if (++x < bufLength && this.buffer.charCodeAt(x) == 0x0A) {
++x;
}
this.sendTapeChar(0x20, 0x35, receiver);
if (x >= bufLength) {
this.setReaderEmpty();
}
break; // out of do loop
} else if (c == 0x0A) { // line feed -- send EOW
++x;
this.sendTapeChar(0x20, 0x35, receiver);
if (x >= bufLength) {
this.setReaderEmpty();
}
break; // out of do loop
} else { // translate character and send its code
++x;
this.sendTapeChar(c, B220PaperTapeReader.xlate220[c], receiver);
break; // out of do loop
}
}
} while (true);
this.tapeSupplyBar.value = bufLength-x;
this.bufIndex = x;
}
};
/**************************************/
B220PaperTapeReader.prototype.shutDown = function shutDown() {
/* Shuts down the device */
if (this.inTimer) {
clearCallback(this.inTimer);
}
if (this.window) {
this.window.removeEventListener("beforeunload", B220PaperTapeReader.prototype.beforeUnload, false);
this.window.close();
this.window = null;
}
};

View File

@@ -86,6 +86,7 @@
#SystemMemorySize {
text-align: center}
#ConsoleInputTable,
#ConsoleOutputTable,
#CardatronTable,
#MagTapeOptionsTable,
@@ -93,6 +94,8 @@
border-spacing: 0;
border-collapse: collapse}
#ConsoleInputTable TH,
#ConsoleInputTable TD,
#ConsoleOutputTable TH,
#ConsoleOutputTable TD,
#CardatronTable TH,

View File

@@ -43,8 +43,8 @@
<button id=SaveBtn class="greenButton">SAVE</button>
<button id=DefaultsBtn class="redButton" title="Set configurartion to original defaults">SET DEFAULTS</button>
<div class=heading>System Properties:</div>
<div class=heading>System Properties:</div>
<select id=SystemMemorySize>
<option value=1000>1000
@@ -59,6 +59,295 @@
<option value=10000>10000
</select> Word Memory Size
<div class=heading>Console Input:</div>
<table id=ConsoleInputTable>
<thead>
<th>Position<th>Type<th>1<th>2<th>3<th>4<th>5<th>6<th>7<th>8<th>9<th>10
<tbody>
<tr>
<td class=center>1
<td class=center>
<select id=ConsoleIn1Type>
<option selected value=NONE>(not used)
<option value=PTRA>Reader
<select>
<td class=center>
<input id=ConsoleIn1_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn1_10 type=checkbox value=1>
<tr>
<td class=center>2
<td class=center>
<select id=ConsoleIn2Type>
<option selected value=NONE>(not used)
<option value=PTRB>Reader
<select>
<td class=center>
<input id=ConsoleIn2_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn2_10 type=checkbox value=1>
<tr>
<td class=center>3
<td class=center>
<select id=ConsoleIn3Type>
<option selected value=NONE>(not used)
<option value=PTRC>Reader
<select>
<td class=center>
<input id=ConsoleIn3_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn3_10 type=checkbox value=1>
<tr>
<td class=center>4
<td class=center>
<select id=ConsoleIn4Type>
<option selected value=NONE>(not used)
<option value=PTRD>Reader
<select>
<td class=center>
<input id=ConsoleIn4_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn4_10 type=checkbox value=1>
<tr>
<td class=center>5
<td class=center>
<select id=ConsoleIn5Type>
<option selected value=NONE>(not used)
<option value=PTRE>Reader
<select>
<td class=center>
<input id=ConsoleIn5_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn5_10 type=checkbox value=1>
<tr>
<td class=center>6
<td class=center>
<select id=ConsoleIn6Type>
<option selected value=NONE>(not used)
<option value=PTRF>Reader
<select>
<td class=center>
<input id=ConsoleIn6_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn6_10 type=checkbox value=1>
<tr>
<td class=center>7
<td class=center>
<select id=ConsoleIn7Type>
<option selected value=NONE>(not used)
<option value=PTRG>Reader
<select>
<td class=center>
<input id=ConsoleIn7_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn7_10 type=checkbox value=1>
<tr>
<td class=center>8
<td class=center>
<select id=ConsoleIn8Type>
<option selected value=NONE>(not used)
<option value=PTRH>Reader
<select>
<td class=center>
<input id=ConsoleIn8_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn8_10 type=checkbox value=1>
<tr>
<td class=center>9
<td class=center>
<select id=ConsoleIn9Type>
<option selected value=NONE>(not used)
<option value=PTRI>Reader
<select>
<td class=center>
<input id=ConsoleIn9_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn9_10 type=checkbox value=1>
<tr>
<td class=center>10
<td class=center>
<select id=ConsoleIn10Type>
<option selected value=NONE>(not used)
<option value=PTRJ>Reader
<select>
<td class=center>
<input id=ConsoleIn10_1 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_2 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_3 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_4 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_5 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_6 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_7 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_8 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_9 type=checkbox value=1>
<td class=center>
<input id=ConsoleIn10_10 type=checkbox value=1>
</table>
<div class=heading>Console Output:</div>
<table id=ConsoleOutputTable>
@@ -517,6 +806,7 @@
&nbsp;
</table>
<div class=heading>Cardatron Unit Selection:</div>
<table id=CardatronTable>
@@ -910,7 +1200,9 @@
<td class=center>
<input id=MagTape10NotWrite type=checkbox value=1>
</table>
<p>&nbsp;</p>
</div>
</body>
</html>

View File

@@ -39,6 +39,88 @@ B220SystemConfig.prototype.configStorageName = "retro-220-Config";
B220SystemConfig.prototype.configVersion = 1;
B220SystemConfig.prototype.flushDelay = 60000; // flush timer setting, ms
B220SystemConfig.defaultConfig = {
version: this.configVersion,
memorySize: 5000, // 11-digit words
ControlConsole: {
PCS1SW: 0, // Program Control Switches 1-0
PCS2SW: 0,
PCS3SW: 0,
PCS4SW: 0,
PCS5SW: 0,
PCW6SW: 0,
PCS7SW: 0,
PCS8SW: 0,
PCS9SW: 0,
PCS0SW: 0,
SONSW: 0, // S-register on
SUNITSSW: 0, // S-register units
STOCSW: 0, // S-to-C stop
STOPSW: 0}, // S-to-P stop
ConsoleInput: {
units: [
null, // unit[0] not used
{type: "PTRA", unitMask: 0x002, remote: 1, speed: 0},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"}
]},
ConsoleOutput: {
units: [
{type: "TTYA", unitMask: 0x001, remote: 1, format: 0, zeroSuppress: 0, mapMemory: 0,
columns: 72, tabs: "9,17,25,33,41,49,57,65,73,81"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"}
]},
Cardatron: {
hasCardatron: true,
units: [
null, // unit[0] not used
{type: "CR1", formatSelect: 0, formatCol: 1},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "LP2", algolGlyphs: true, greenBar: true, zeroSuppressCols: ""},
{type: "CP1", algolGlyphs: true, greenBar: false, zeroSuppressCols: ""}
]},
MagTape: {
hasMagTape: true,
units: [
null, // unit[0] not used
{type: "MTA", designate: 0, remoteSwitch: false, rewindReadySwitch: true, notWriteSwitch: false},
{type: "NONE"},
{type: "NONE"},
{type: "MTD", designate: 3, remoteSwitch: false, rewindReadySwitch: true, notWriteSwitch: false},
{type: "MTE", designate: 4, remoteSwitch: false, rewindReadySwitch: true, notWriteSwitch: false},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"}
]}
};
/**************************************/
B220SystemConfig.prototype.$$ = function $$(id) {
return this.window.document.getElementById(id);
@@ -53,73 +135,7 @@ B220SystemConfig.prototype.createConfigData = function createConfigData() {
var prefs;
var s;
this.configData = {
version: this.configVersion,
memorySize: 5000, // 11-digit words
ControlConsole: {
PCS1SW: 0, // Program Control Switches 1-0
PCS2SW: 0,
PCS3SW: 0,
PCS4SW: 0,
PCS5SW: 0,
PCW6SW: 0,
PCS7SW: 0,
PCS8SW: 0,
PCS9SW: 0,
PCS0SW: 0,
SONSW: 0, // S-register on
SUNITSSW: 0, // S-register units
STOCSW: 0, // S-to-C stop
STOPSW: 0}, // S-to-P stop
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: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"}
]},
Cardatron: {
hasCardatron: true,
units: [
null, // unit[0] not used
{type: "CR1", formatSelect: 0, formatCol: 1},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "LP2", algolGlyphs: true, greenBar: true, zeroSuppressCols: ""},
{type: "CP1", algolGlyphs: true, greenBar: false, zeroSuppressCols: ""}
]},
MagTape: {
hasMagTape: true,
suppressBSwitch: false, // false => off => suppress B-register modification
units: [
null, // unit[0] not used
{type: "MTA", designate: 0, remoteSwitch: false, rewindReadySwitch: true, notWriteSwitch: false},
{type: "NONE"},
{type: "NONE"},
{type: "MTD", designate: 3, remoteSwitch: false, rewindReadySwitch: true, notWriteSwitch: false},
{type: "MTE", designate: 4, remoteSwitch: false, rewindReadySwitch: true, notWriteSwitch: false},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"}
]}
};
this.configData = B220SystemConfig.defaultConfig;
this.flushHandler();
};
@@ -280,7 +296,29 @@ B220SystemConfig.prototype.loadConfigDialog = function loadConfigDialog() {
// System Properties
this.setListValue("SystemMemorySize", cd.memorySize.toString());
// Console Input units
if (!cd.ConsoleInput) {
cd.ConsoleInput = B220SystemConfig.defaultConfig.ConsoleInput;
}
for (x=1; x<=10; ++x) {
unit = cd.ConsoleInput.units[x];
prefix = "ConsoleIn" + x;
this.setListValue(prefix + "Type", unit.type);
mask = 0x001;
for (y=1; y<=10; ++y) {
mask <<= 1;
this.$$(prefix + "_" + y).checked = (unit.unitMask & mask ? true : false);
} // for y
} // for x
// Console Output units
if (!cd.ConsoleOutput) {
cd.ConsoleOutput = B220SystemConfig.defaultConfig.ConsoleOutput;
}
for (x=0; x<=10; ++x) {
unit = cd.ConsoleOutput.units[x];
prefix = "ConsoleOut" + x;
@@ -298,6 +336,11 @@ B220SystemConfig.prototype.loadConfigDialog = function loadConfigDialog() {
} // for x
// Cardatron units
if (!cd.Cardatron) {
cd.Cardatron = B220SystemConfig.defaultConfig.Cardatron;
}
for (x=1; x<=7; ++x) {
unit = cd.Cardatron.units[x];
prefix = "Cardatron" + x;
@@ -324,6 +367,10 @@ B220SystemConfig.prototype.loadConfigDialog = function loadConfigDialog() {
// Magnetic Tape units
if (!cd.MagTape) {
cd.MagTape = B220SystemConfig.defaultConfig.MagTape;
}
this.$$("SuppressBMod").checked = !cd.MagTape.suppressBSwitch;
for (x=1; x<=10; ++x) {
unit = cd.MagTape.units[x];
@@ -372,6 +419,28 @@ B220SystemConfig.prototype.saveConfigDialog = function saveConfigDialog() {
x = parseInt(e.options[e.selectedIndex], 10);
cd.memorySize = (isNaN(x) ? 5000 : x);
// Console Input units
for (x=1; x<=10; ++x) {
unit = cd.ConsoleInput.units[x];
prefix = "ConsoleIn" + x;
e = this.$$(prefix + "Type");
unit.type = (e.selectedIndex < 0 ? "NONE" : e.options[e.selectedIndex].value);
mask = 0x001;
unit.unitMask = 0;
for (y=1; y<=10; ++y) {
mask <<= 1;
if (this.$$(prefix + "_" + y).checked) {
unit.unitMask |= mask;
}
} // for y
if (unit.type != "NONE") {
unit.remote = (unit.remote || 0);
unit.speed = (unit.speed || 0);
}
} // for x
// Console Output units
for (x=0; x<=10; ++x) {
@@ -391,10 +460,15 @@ B220SystemConfig.prototype.saveConfigDialog = function saveConfigDialog() {
}
} // for y
e = this.$$(prefix + "Format");
unit.format = (e.selectedIndex < 0 ? "NONE" : e.options[e.selectedIndex].value);
unit.columns = (unit.columns ? unit.columns : 72);
unit.tabs = (unit.tabs ? unit.tabs : "1,9,17,25,33,41,49,57,65,73");
if (unit.type != "NONE") {
unit.remote = (unit.remote || 0);
unit.zeroSuppress = (unit.zeroSuppress || 0);
unit.mapMemory = (unit.mapMemory || 0);
e = this.$$(prefix + "Format");
unit.format = (e.selectedIndex < 0 ? "NONE" : e.options[e.selectedIndex].value);
unit.columns = (unit.columns ? unit.columns : 72);
unit.tabs = (unit.tabs ? unit.tabs : "1,9,17,25,33,41,49,57,65,73");
}
} // for x
// Cardatron units
@@ -410,14 +484,18 @@ B220SystemConfig.prototype.saveConfigDialog = function saveConfigDialog() {
cd.Cardatron.hasCardatron = true;
unit.algolGlyphs = this.$$(prefix + "AlgolGlyphs").checked;
unit.greenBar = this.$$(prefix + "Greenbar").checked;
unit.zeroSuppressCols = (unit.zeroSuppressCols || "");
break;
case "CP":
cd.Cardatron.hasCardatron = true;
unit.algolGlyphs = this.$$(prefix + "AlgolGlyphs").checked;
unit.greenBar = false;
unit.zeroSuppressCols = (unit.zeroSuppressCols || "");
break;
case "CR":
cd.Cardatron.hasCardatron = true;
unit.formatSelect = (unit.formatSelect || 0);
unit.formatCol = (unit.formatCol === undefined ? 1 : unit.formatCol)
// no break
default:
unit.algolGlyphs = false;