mirror of
https://github.com/pkimpel/retro-220.git
synced 2026-03-27 10:20:49 +00:00
Commit 220 emulator version 0.3a:
1. Commit initial (incomplete) implementation of magnetic tape drives (TSU) and control: MLS, MRW, MDA, MIW, MIR, MPF, MPB, MPE, MIB, MIE. 2. Change B220SetCallback.js "setImmediate" mechanism to use DOM Promises instead of window.postMessage(). 3. Minor styling and window positioning changes.
This commit is contained in:
@@ -224,9 +224,6 @@ function B220Processor(config, devices) {
|
||||
this.TAT = new B220Processor.FlipFlop(this, false); // magnetic tape alarm toggle
|
||||
this.UET = new B220Processor.FlipFlop(this, false); // unequal comparison toggle (HIT=UET=0 => off)
|
||||
|
||||
// Mag-Tape Control Unit switch
|
||||
this.tswSuppressB = 0; // Suppress B-register modification on input
|
||||
|
||||
// Left/Right Maintenance Panel
|
||||
this.leftPanelOpen = false;
|
||||
this.rightPanelOpen = false;
|
||||
@@ -245,10 +242,9 @@ function B220Processor(config, devices) {
|
||||
this.boundCardatronOutputFinished = B220Processor.bindMethod(this, B220Processor.prototype.cardatronOutputFinished);
|
||||
this.boundCardatronReceiveWord = B220Processor.bindMethod(this, B220Processor.prototype.cardatronReceiveWord);
|
||||
|
||||
this.boundMagTapeComplete = B220Processor.bindMethod(this, B220Processor.prototype.magTapeComplete);
|
||||
this.boundMagTapeReceiveBlock = B220Processor.bindMethod(this, B220Processor.prototype.magTapeReceiveBlock);
|
||||
this.boundMagTapeInitiateSend = B220Processor.bindMethod(this, B220Processor.prototype.magTapeInitiateSend);
|
||||
this.boundMagTapeSendBlock = B220Processor.bindMethod(this, B220Processor.prototype.magTapeSendBlock);
|
||||
this.boundMagTapeTerminateSend = B220Processor.bindMethod(this, B220Processor.prototype.magTapeTerminateSend);
|
||||
|
||||
this.clear(); // Create and initialize the processor state
|
||||
|
||||
@@ -260,7 +256,7 @@ function B220Processor(config, devices) {
|
||||
* Global Constants *
|
||||
***********************************************************************/
|
||||
|
||||
B220Processor.version = "0.03";
|
||||
B220Processor.version = "0.03a";
|
||||
|
||||
B220Processor.tick = 1000/200000; // milliseconds per clock cycle (200KHz)
|
||||
B220Processor.cyclesPerMilli = 1/B220Processor.tick;
|
||||
@@ -1056,7 +1052,7 @@ B220Processor.prototype.setPaperTapeCheck = function setPaperTapeCheck(value) {
|
||||
|
||||
/**************************************/
|
||||
B220Processor.prototype.setHighSpeedPrinterCheck = function setHighSpeedPrinterCheck(value) {
|
||||
/* Sets the Cardatron Check alarm */
|
||||
/* Sets the High Speed Printer Check alarm */
|
||||
|
||||
if (!this.ALARMSW) {
|
||||
this.HAT.set(value);
|
||||
@@ -2755,11 +2751,11 @@ B220Processor.prototype.cardatronOutputFinished = function cardatronOutputFinish
|
||||
/**************************************/
|
||||
B220Processor.prototype.cardatronReceiveWord = function cardatronReceiveWord(word) {
|
||||
/* Handles a word coming from the Cardatron input unit. Negative values for
|
||||
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 */
|
||||
the word indicates this is the last word and the I/O is finished. Otherwise,
|
||||
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
|
||||
|
||||
@@ -2836,95 +2832,70 @@ B220Processor.prototype.cardatronReceiveWord = function cardatronReceiveWord(wor
|
||||
***********************************************************************/
|
||||
|
||||
/**************************************/
|
||||
B220Processor.prototype.magTapeInitiateSend = function magTapeInitiateSend(writeInitiate) {
|
||||
/* Performs the initial memory block-to-loop operation after the tape control
|
||||
unit has determined the drive is ready and not busy. Once the initial loop is
|
||||
loaded, calls "writeInitiate" to start tape motion, which in turn will cause
|
||||
the control to call this.magTapeSendBlock to pass the loop data to the drive
|
||||
and initiate loading of the alternate loop buffer */
|
||||
var that = this;
|
||||
B220Processor.prototype.magTapeComplete = function magTapeComplete(alarm, control, word) {
|
||||
/* Call-back routine to signal completion of a magnetic tape operation. If
|
||||
"alarm" is true, the Magnetic Tape Alarm will be set. If "control" is true,
|
||||
the contents of "word" are processed as a tape control word and an appropriate
|
||||
branch is set up. Unconditionally terminates the tape I/O instruction */
|
||||
var aaaa;
|
||||
var bbbb;
|
||||
|
||||
if (this.togMT3P) { // if false, we've probably been cleared
|
||||
if (this.CADDR >= 0x8000) {
|
||||
writeInitiate(this.boundMagTapeSendBlock, this.boundMagTapeTerminateSend);
|
||||
} else {
|
||||
this.execTime += performance.now()*B220Processor.wordsPerMilli; // restore time after I/O
|
||||
this.blockToLoop((this.togMT1BV4 ? 4 : 5), function initialBlockComplete() {
|
||||
that.execTime -= performance.now()*B220Processor.wordsPerMilli; // suspend time during I/O
|
||||
writeInitiate(that.boundMagTapeSendBlock, that.boundMagTapeTerminateSend);
|
||||
});
|
||||
if (alarm) {
|
||||
this.setMagneticTapeCheck(true);
|
||||
} else if (control) {
|
||||
this.D.set(word);
|
||||
bbbb = word%0x10000;
|
||||
aaaa = ((word - bbbb)/0x10000)%0x10000;
|
||||
if ((word - word%0x10000000000)%2) { // if sign bit is 1,
|
||||
bbbb = this.bcdAdd(bbbb, this.B.value, 4); // B-adjust the low-order 4 digits
|
||||
}
|
||||
|
||||
this.E.set(aaaa);
|
||||
this.readMemory();
|
||||
if (!this.MET.value) {
|
||||
this.IB.set(this.IB.value - this.IB.value%0x100000000 +
|
||||
(this.C.value%0x10000)*0x10000 + this.P.value%0x10000);
|
||||
this.writeMemory();
|
||||
this.P.set(bbbb);
|
||||
}
|
||||
}
|
||||
|
||||
this.ioComplete(true);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220Processor.prototype.magTapeSendBlock = function magTapeSendBlock(lastBlock) {
|
||||
/* Sends a block of data from a loop buffer to the tape control unit and
|
||||
initiates the load of the alternate loop buffer. this.togMT1BV4 and
|
||||
this.togMT1BV5 control alternation of the loop buffers. "lastBlock" indicates
|
||||
this will be the last block requested by the control unit and no further
|
||||
blocks should be buffered. If the C-register address is 8000 or higher, the
|
||||
loop is not loaded from main memory, and the current contents of the loop
|
||||
are written to tape. Since tape block writes take 46 ms, they are much
|
||||
longer than any memory-to-loop transfer, so this routine simply exits after
|
||||
the next blockToLoop is initiated, and the processor then waits for the tape
|
||||
control unit to request the next block, by which time the blockToLoop will
|
||||
have completed. Returns null if the processor has been cleared and the I/O
|
||||
must be aborted */
|
||||
var loop;
|
||||
var that = this;
|
||||
B220Processor.prototype.magTapeSendBlock = function magTapeSendBlock(buffer, words) {
|
||||
/* Sends a block of data from memory to the tape control unit. "buffer" is an
|
||||
array of words to receive the data to be written to tape. "words" is the number
|
||||
of words to place in the buffer, starting at the current operand address in the
|
||||
C register. Returns true if the processor has been cleared or a memory address
|
||||
error occurs, and the I/O must be aborted */
|
||||
var result = false; // return value
|
||||
var that = this; // local context
|
||||
var x = 0; // buffer index
|
||||
|
||||
function blockFetchComplete() {
|
||||
that.execTime -= performance.now()*B220Processor.wordsPerMilli; // suspend time again during I/O
|
||||
}
|
||||
//console.log("TSU " + this.selectedUnit + " W, Len " + words +
|
||||
// ", ADDR=" + this.CADDR.toString(16));
|
||||
|
||||
//console.log("TSU " + this.selectedUnit + " W, L" + (this.togMT1BV4 ? 4 : 5) +
|
||||
// ", ADDR=" + this.CADDR.toString(16) +
|
||||
// " : " + block[0].toString(16) + ", " + block[19].toString(16));
|
||||
|
||||
if (!this.togMT3P) {
|
||||
loop = null;
|
||||
if (!this.AST.value) {
|
||||
result = true;
|
||||
} else {
|
||||
// Select the appropriate loop to send data to the drive
|
||||
if (this.togMT1BV4) {
|
||||
loop = this.L4;
|
||||
this.toggleGlow.glowL4 = 1; // turn on the lamp and let normal decay work
|
||||
} else {
|
||||
loop = this.L5;
|
||||
this.toggleGlow.glowL5 = 1;
|
||||
}
|
||||
|
||||
if (!lastBlock) {
|
||||
this.execTime += performance.now()*B220Processor.wordsPerMilli; // restore time after I/O
|
||||
// Flip the loop-buffer toggles
|
||||
this.togMT1BV5 = this.togMT1BV4;
|
||||
this.togMT1BV4 = 1-this.togMT1BV4;
|
||||
// Block the loop buffer from main memory if appropriate
|
||||
if (this.CADDR < 0x8000) {
|
||||
this.blockToLoop((this.togMT1BV4 ? 4 : 5), blockFetchComplete);
|
||||
while (x < words) {
|
||||
this.E.set(this.CADDR);
|
||||
this.CADDR = this.bcdAdd(this.CADDR, 1, 4);
|
||||
this.readMemory();
|
||||
if (this.MET.value) { // invalid address
|
||||
result = true;
|
||||
break; // out of do-loop
|
||||
} else {
|
||||
blockFetchComplete();
|
||||
buffer[x] = this.IB.value;
|
||||
++x;
|
||||
}
|
||||
}
|
||||
|
||||
this.A.set(loop[loop.length-1]); // for display only
|
||||
this.D.set(0); // for display only
|
||||
}
|
||||
|
||||
return loop; // give the loop data to the control unit
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220Processor.prototype.magTapeTerminateSend = function magTapeTerminateSend() {
|
||||
/* Called by the tape control unit after the last block has been completely
|
||||
written to tape. Terminates the write instruction */
|
||||
|
||||
if (this.togMT3P) { // if false, we've probably been cleared
|
||||
this.togMT3P = 0;
|
||||
this.togMT1BV4 = this.togMT1BV5 = 0;
|
||||
this.execTime += performance.now()*B220Processor.wordsPerMilli; // restore time after I/O
|
||||
this.schedule();
|
||||
}
|
||||
this.C.set(this.C.value - this.C.value%0x10000 + this.CADDR);
|
||||
return result;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
@@ -3676,9 +3647,32 @@ B220Processor.prototype.execute = function execute() {
|
||||
this.operationComplete();
|
||||
break;
|
||||
|
||||
case 0x50: //--------------------- MT* Magnetic tape search/field search/lane select/rewind
|
||||
this.setProgramCheck(1);
|
||||
this.operationComplete();
|
||||
case 0x50: //--------------------- MTS/MFS/MLS/MRW/MDA Magnetic tape search/field search/lane select/rewind
|
||||
this.opTime = 0.160;
|
||||
if (!this.magTape) {
|
||||
this.setMagneticTapeCheck(true); // no tape control
|
||||
this.operationComplete();
|
||||
} else {
|
||||
this.selectedUnit = (this.CCONTROL >>> 12) & 0x0F;
|
||||
switch (this.CCONTROL%0x10) {
|
||||
case 0: case 1: case 2: case 3: // MTS/MFS: search or field search
|
||||
this.setProgramCheck(true); // TEMP //
|
||||
this.operationComplete();
|
||||
break;
|
||||
case 4: case 5: case 6: case 7: // MLS: lane select
|
||||
this.ioInitiate();
|
||||
this.magTape.laneSelect(this.D.value, this.boundMagTapeComplete);
|
||||
break;
|
||||
case 8: case 9: // MRW/MDA: rewind, with or without lockout
|
||||
this.ioInitiate();
|
||||
this.magTape.rewind(this.D.value, this.boundMagTapeComplete);
|
||||
break;
|
||||
default: // should never happen
|
||||
this.setProgramCheck(true);
|
||||
this.operationComplete();
|
||||
break;
|
||||
} // switch on operation variant
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x51: //--------------------- MTC/MFC Magnetic tape scan/field scan
|
||||
@@ -3697,13 +3691,31 @@ B220Processor.prototype.execute = function execute() {
|
||||
break;
|
||||
|
||||
case 0x54: //--------------------- MIW Magnetic tape initial write
|
||||
this.setProgramCheck(1);
|
||||
this.operationComplete();
|
||||
this.opTime = 0.160;
|
||||
if (!this.magTape) {
|
||||
this.setMagneticTapeCheck(true); // no tape control
|
||||
this.operationComplete();
|
||||
} else {
|
||||
this.selectedUnit = (this.CCONTROL >>> 12) & 0x0F;
|
||||
this.CCONTROL = this.CADDR; // copy C address into control digits
|
||||
this.C.set((this.CCONTROL*0x100 + this.COP)*0x10000 + this.CADDR);
|
||||
this.ioInitiate();
|
||||
this.magTape.initialWrite(this.D.value, this.boundMagTapeComplete, this.boundMagTapeSendBlock);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x55: //--------------------- MIR Magnetic tape initial write, record
|
||||
this.setProgramCheck(1);
|
||||
this.operationComplete();
|
||||
this.opTime = 0.160;
|
||||
if (!this.magTape) {
|
||||
this.setMagneticTapeCheck(true); // no tape control
|
||||
this.operationComplete();
|
||||
} else {
|
||||
this.selectedUnit = (this.CCONTROL >>> 12) & 0x0F;
|
||||
this.CCONTROL = this.CADDR; // copy C address into control digits
|
||||
this.C.set((this.CCONTROL*0x100 + this.COP)*0x10000 + this.CADDR);
|
||||
this.ioInitiate();
|
||||
this.magTape.initialWriteRecord(this.D.value, this.boundMagTapeComplete, this.boundMagTapeSendBlock);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x56: //--------------------- MOW Magnetic tape overwrite
|
||||
@@ -3716,13 +3728,47 @@ B220Processor.prototype.execute = function execute() {
|
||||
this.operationComplete();
|
||||
break;
|
||||
|
||||
case 0x58: //--------------------- MPF/MPB Magnetic tape position forward/backward/at end
|
||||
this.setProgramCheck(1);
|
||||
this.operationComplete();
|
||||
case 0x58: //--------------------- MPF/MPB/MIE Magnetic tape position forward/backward/at end
|
||||
this.opTime = 0.130;
|
||||
if (!this.magTape) {
|
||||
this.setMagneticTapeCheck(true); // no tape control
|
||||
this.operationComplete();
|
||||
} else {
|
||||
this.selectedUnit = (this.CCONTROL >>> 12) & 0x0F;
|
||||
this.ioInitiate();
|
||||
switch (this.CCONTROL%0x10) {
|
||||
case 1: // MPB: position tape backward
|
||||
this.magTape.positionBackward(this.D.value, this.boundMagTapeComplete);
|
||||
break;
|
||||
case 2: // MPE: position tape at end
|
||||
this.magTape.positionAtEnd(this.D.value, this.boundMagTapeComplete);
|
||||
break;
|
||||
default: // MPF: position tape forward
|
||||
this.magTape.positionForward(this.D.value, this.boundMagTapeComplete);
|
||||
break;
|
||||
} // switch on operation variant
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x59: //--------------------- MIB/MIE Magnetic tape interrogate, branch/end of tape, branch
|
||||
this.setProgramCheck(1);
|
||||
if (!this.magTape) {
|
||||
this.opTime = 0.01;
|
||||
} else if (this.magTape.controlBusy) {
|
||||
this.opTime = 0.01;
|
||||
} else {
|
||||
opTime = 0.14;
|
||||
if (this.CCONTROL%0x10 == 1) { // MIE
|
||||
if (this.magTape.testUnitAtMagneticEOT(this.D.value)) {
|
||||
this.P.set(this.CADDR);
|
||||
this.opTime += 0.020;
|
||||
}
|
||||
} else { // MIB
|
||||
if (this.magTape.testUnitReady(this.D.value)) {
|
||||
this.P.set(this.CADDR);
|
||||
this.opTime += 0.020;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.operationComplete();
|
||||
break;
|
||||
|
||||
@@ -3913,14 +3959,6 @@ B220Processor.prototype.execute = function execute() {
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x52: //---------------- MTRW Magnetic Tape Rewind
|
||||
if (this.magTape) {
|
||||
this.selectedUnit = (this.CCONTROL >>> 4) & 0x0F;
|
||||
if (this.magTape.rewind(this.selectedUnit)) {
|
||||
this.OFT.set(1); // control or tape unit busy/not-ready
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: //---------------- (unimplemented instruction -- alarm)
|
||||
break;
|
||||
} // switch this.COP
|
||||
@@ -4132,6 +4170,7 @@ B220Processor.prototype.stop = function stop() {
|
||||
this.execLimit = 0; // kill the time slice
|
||||
this.SST.set(0);
|
||||
this.RUT.set(0);
|
||||
this.AST.set(0);
|
||||
|
||||
// Stop the timers
|
||||
this.clockIn();
|
||||
@@ -4169,7 +4208,11 @@ B220Processor.prototype.setStop = function setStop() {
|
||||
the end of the Execute cycle, then stop */
|
||||
|
||||
if (this.poweredOn) {
|
||||
this.RUT.set(0);
|
||||
if (this.RUT.value) {
|
||||
this.RUT.set(0);
|
||||
} else {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4250,7 +4293,9 @@ B220Processor.prototype.tcuClear = function tcuClear() {
|
||||
/* Clears the Tape Control Unit */
|
||||
|
||||
if (this.poweredOn) {
|
||||
//?? TBD ??
|
||||
if (this.magTape) {
|
||||
this.magTape.clearUnit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4297,6 +4342,22 @@ B220Processor.prototype.powerDown = function powerDown() {
|
||||
B220Processor.prototype.loadDefaultProgram = function loadDefaultProgram() {
|
||||
/* Loads a set of default demo programs to the memory drum */
|
||||
|
||||
// TEMP // Tape tests
|
||||
this.MM[ 0] = 0x1008500000; // MRW 1
|
||||
this.MM[ 1] = 0x1002580000; // MPE 1
|
||||
this.MM[ 2] = 0x1000540000; // MIW 0,1,10,100
|
||||
this.MM[ 3] = 0x1750540100; // MIW 100,1,7,50
|
||||
this.MM[ 4] = 0x1500550079; // MIR 79,1,5,00
|
||||
this.MM[ 5] = 0x1101540200; // MIW 200,1,1,1
|
||||
this.MM[ 6] = 0x1009500000; // MDA 1
|
||||
this.MM[ 7] = 0x7777009999; // HLT 9999,7777
|
||||
|
||||
this.MM[ 79] = 0x1900000000; // preface for 19 words, 80-98
|
||||
this.MM[ 99] = 0x4000000000; // preface for 40 words, 100-139
|
||||
this.MM[ 140] = 0x5800000000; // preface for 58 words, 141-198
|
||||
this.MM[ 199] = 0x9900000000; // preface for 99 words, 200-298
|
||||
this.MM[ 299] = 0x0000000000; // preface for 100 words, 300-399
|
||||
|
||||
// Simple counter speed test
|
||||
this.MM[ 80] = 0x0000120082; // ADD 82
|
||||
this.MM[ 81] = 0x0000300080; // BUN 80
|
||||
|
||||
@@ -36,14 +36,15 @@
|
||||
|
||||
<!--
|
||||
<script src="./B220DataFile.js"></script>
|
||||
-->
|
||||
<script src="./B220MagTapeDrive.js"></script>
|
||||
<script src="./B220MagTapeControl.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>
|
||||
|
||||
@@ -60,13 +60,11 @@ window.addEventListener("load", function() {
|
||||
devices.CardatronControl = null;
|
||||
}
|
||||
|
||||
/********************
|
||||
if (config.getNode("MagTape.hasMagTape")) {
|
||||
devices.MagTapeControl = new B220MagTapeControl(processor);
|
||||
} else {
|
||||
devices.MagTapeControl = null;
|
||||
}
|
||||
********************/
|
||||
|
||||
// Control Console must be instantiated last
|
||||
devices.ControlConsole = new B220ControlConsole(processor, systemShutDown);
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#ClearBtnCaption {
|
||||
bottom: 4px;
|
||||
right: 4px;
|
||||
width: 40px}
|
||||
width: 32px}
|
||||
|
||||
#OutputUnitLamp {
|
||||
top: 8px;
|
||||
|
||||
@@ -445,7 +445,7 @@ DIV.redButton1 {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
font-size: 4px;
|
||||
background-image: radial-gradient(circle, #C00, #F00);
|
||||
background-image: radial-gradient(circle, #C00, #E00, #F00);
|
||||
border-radius: 50%;
|
||||
border: 10px solid #CCC}
|
||||
DIV.redButton2 {
|
||||
@@ -453,7 +453,7 @@ DIV.redButton2 {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
font-size: 4px;
|
||||
background-image: radial-gradient(circle, #C00, #F00);
|
||||
background-image: radial-gradient(circle, #C00, #E00, #F00);
|
||||
border-radius: 50%;
|
||||
border: 6px solid #CCC}
|
||||
DIV.redButton3 {
|
||||
@@ -461,7 +461,7 @@ DIV.redButton3 {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 4px;
|
||||
background-image: radial-gradient(circle, #C00, #F00);
|
||||
background-image: radial-gradient(circle, #C00, #E00, #F00);
|
||||
border-radius: 50%;
|
||||
border: 2px solid #CCC}
|
||||
DIV.blackButton1 {
|
||||
@@ -469,7 +469,7 @@ DIV.blackButton1 {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
font-size: 4px;
|
||||
background-image: radial-gradient(circle, #000, #333);
|
||||
background-image: radial-gradient(circle, #333, #111, #000);
|
||||
border-radius: 50%;
|
||||
border: 10px solid #CCC}
|
||||
DIV.blackButton3 {
|
||||
@@ -477,7 +477,7 @@ DIV.blackButton3 {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 4px;
|
||||
background-image: radial-gradient(circle, #000, #333);
|
||||
background-image: radial-gradient(circle, #333, #111, #000);
|
||||
border-radius: 50%;
|
||||
border: 2px solid #CCC}
|
||||
|
||||
|
||||
@@ -84,12 +84,14 @@
|
||||
#EndOfPaper.hidden {
|
||||
display: none}
|
||||
|
||||
/***** TTY Control Panel *****/
|
||||
|
||||
#FormatControlsDiv {
|
||||
position: absolute;
|
||||
overflow: visible;
|
||||
display: none;
|
||||
left: calc(50% - 312px);
|
||||
top: 48px;
|
||||
left: 2px;
|
||||
top: 4px;
|
||||
z-index: 10;
|
||||
height: 216px;
|
||||
width: 624px;
|
||||
|
||||
@@ -48,7 +48,7 @@ function B220ConsolePrinter(mnemonic, unitIndex, config) {
|
||||
this.printerLine = 0;
|
||||
this.printerCol = 0;
|
||||
this.window = window.open("../webUI/B220ConsolePrinter.html", mnemonic,
|
||||
"location=no,scrollbars=no,resizable,width=640,height=300," +
|
||||
"location=no,scrollbars=no,resizable,width=640,height=240," +
|
||||
"left=" + left + ",top=" + top);
|
||||
this.window.addEventListener("load", B220Util.bindMethod(this,
|
||||
B220ConsolePrinter.prototype.printerOnLoad));
|
||||
|
||||
57
webUI/B220MagTapeControl.css
Normal file
57
webUI/B220MagTapeControl.css
Normal file
@@ -0,0 +1,57 @@
|
||||
/***********************************************************************
|
||||
* retro-220/webUI B220MagTapeControl.css
|
||||
************************************************************************
|
||||
* Copyright (c) 2017, Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* Burroughs 220 emulator Magnetic Tape Control style sheet.
|
||||
************************************************************************
|
||||
* 2017-07-09 P.Kimpel
|
||||
* Original version, from retro-205 D205MagTapeControl.css.
|
||||
***********************************************************************/
|
||||
|
||||
DIV.panelRegCaption { /* Overrides class in B220Common.css */
|
||||
border-top: none}
|
||||
|
||||
#mtControlBody {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0}
|
||||
|
||||
#PanelSurface {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0}
|
||||
|
||||
#ClearBtn {
|
||||
bottom: 60px;
|
||||
left: 8px;
|
||||
border: 10px solid #CCC;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#ClearBtnCaption {
|
||||
bottom: 48px;
|
||||
left: 8px;
|
||||
width: 32px}
|
||||
|
||||
#MiscRegPanel {
|
||||
left: 52px;
|
||||
top: 4px;
|
||||
width: 144px;
|
||||
height: 128px}
|
||||
|
||||
#CRegPanel {
|
||||
left: 208px;
|
||||
top: 4px;
|
||||
width: 192px;
|
||||
height: 128px}
|
||||
|
||||
#TRegPanel {
|
||||
left: 412px;
|
||||
top: 4px;
|
||||
width: 288px;
|
||||
height: 128px}
|
||||
39
webUI/B220MagTapeControl.html
Normal file
39
webUI/B220MagTapeControl.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>retro-220 Mag Tape Control Unit</title>
|
||||
<!--
|
||||
/***********************************************************************
|
||||
* retro-220/webUI B220MagTapeControl.html
|
||||
************************************************************************
|
||||
* Copyright (c) 2017, Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* Burroughs 220 Magnetic Tape Control page.
|
||||
************************************************************************
|
||||
* 2017-07-09 P.Kimpel
|
||||
* Original version, from retro-205 D205MagTapeControl.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="B220MagTapeControl.css">
|
||||
</head>
|
||||
|
||||
<body id=mtControlBody class=panelBody>
|
||||
<div id=PanelSurface class=panelSurface>
|
||||
<div id=ClearBtn class=redButton1> </div>
|
||||
<div id=ClearBtnCaption class=caption>CLEAR</div>
|
||||
|
||||
<div id=MiscRegPanel class=panelRegister></div>
|
||||
|
||||
<div id=CRegPanel class=panelRegister></div>
|
||||
|
||||
<div id=TRegPanel class=panelRegister></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
819
webUI/B220MagTapeControl.js
Normal file
819
webUI/B220MagTapeControl.js
Normal file
@@ -0,0 +1,819 @@
|
||||
/***********************************************************************
|
||||
* retro-220/webUI B220MagTapeControl.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2017, Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* Burroughs 220 MagTape Control unit module.
|
||||
************************************************************************
|
||||
* 2017-07-09 P.Kimpel
|
||||
* Original version, from retro-205 D205MagTapeControl.js.
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
/**************************************/
|
||||
function B220MagTapeControl(p) {
|
||||
/* Constructor for the MagTapeControl object */
|
||||
var left = 0; // control window left position
|
||||
var top = 412; // control window top-from-bottom position
|
||||
var u; // unit configuration object
|
||||
var x; // unit index
|
||||
|
||||
this.config = p.config; // System configuration object
|
||||
this.mnemonic = "MCU";
|
||||
this.p = p; // B220Processor object
|
||||
|
||||
// Do not call this.clear() here -- call this.clearUnit() from onLoad instead
|
||||
|
||||
this.doc = null;
|
||||
this.window = window.open("../webUI/B220MagTapeControl.html", this.mnemonic,
|
||||
"location=no,scrollbars=no,resizable,width=712,height=144,top=" +
|
||||
(screen.availHeight - top) + ",left=" + left);
|
||||
this.window.addEventListener("load",
|
||||
B220Util.bindMethod(this, B220MagTapeControl.prototype.magTapeOnLoad));
|
||||
|
||||
this.boundControlFinished = B220Util.bindMethod(this, B220MagTapeControl.prototype.controlFinished);
|
||||
this.boundTapeUnitFinished = B220Util.bindMethod(this, B220MagTapeControl.prototype.tapeUnitFinished);
|
||||
this.boundReadReceiveBlock = B220Util.bindMethod(this, B220MagTapeControl.prototype.readReceiveBlock);
|
||||
this.boundWriteTerminate = B220Util.bindMethod(this, B220MagTapeControl.prototype.writeTerminate);
|
||||
this.boundWriteSendBlock = B220Util.bindMethod(this, B220MagTapeControl.prototype.writeSendBlock);
|
||||
this.boundWriteInitiate = B220Util.bindMethod(this, B220MagTapeControl.prototype.writeInitiate);
|
||||
this.boundSearchComplete = B220Util.bindMethod(this, B220MagTapeControl.prototype.searchComplete);
|
||||
|
||||
this.currentUnit = null; // stashed tape unit object
|
||||
this.memoryBlockCallback = null; // stashed block-sending/receiving call-back function
|
||||
this.memoryTerminateCallback = null;// stashed memory-sending terminate call-back function
|
||||
this.tapeBlock = new Float64Array(101);
|
||||
// block buffer for tape I/O
|
||||
|
||||
/* Set up the tape units from the system configuration. These can be any
|
||||
combination of Tape Storage Units (DataReaders) and DataFiles. The indexes
|
||||
into this array are physical unit numbers used internally -- unit designate
|
||||
is set on the tape unit itself */
|
||||
|
||||
this.tapeUnit = [
|
||||
null, // 0=not used
|
||||
null, // tape unit A
|
||||
null, // tape unit B
|
||||
null, // tape unit C
|
||||
null, // tape unit D
|
||||
null, // tape unit E
|
||||
null, // tape unit F
|
||||
null, // tape unit G
|
||||
null, // tape unit H
|
||||
null, // tape unit I
|
||||
null]; // tape unit J
|
||||
|
||||
for (x=1; x<this.tapeUnit.length; ++x) {
|
||||
u = this.config.getNode("MagTape.units", x);
|
||||
switch (u.type.substring(0, 2)) {
|
||||
case "MT":
|
||||
this.tapeUnit[x] = new B220MagTapeDrive(u.type, x, this.config);
|
||||
break;
|
||||
case "DF":
|
||||
this.tapeUnit[x] = new B220DataFile(u.type, x, this.config);
|
||||
break;
|
||||
default:
|
||||
this.tapeUnit[x] = null;
|
||||
break;
|
||||
} // switch u.type
|
||||
} // for x
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.$$ = function $$(e) {
|
||||
return this.doc.getElementById(e);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.clear = function clear() {
|
||||
/* Initializes (and if necessary, creates) the panel state */
|
||||
|
||||
this.MISC = 0; // Miscellaneous control register
|
||||
this.C = 0; // C register (block number, etc.)
|
||||
this.T = 0; // T register
|
||||
|
||||
this.unitNr = 0; // current unit number from command
|
||||
this.unitIndex = 0; // current index into this.tapeUnit[]
|
||||
this.blockCount = 0; // number of blocks for current operation
|
||||
this.blockWords = 0; // number of words/block for current operation
|
||||
|
||||
this.controlBusy = false; // control unit is busy with read/write/search
|
||||
this.pendingCallee = null; // method to call for a pending operation
|
||||
this.pendingArgs = null; // Arguments object for a pending operation
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.findDesignate = function findDesignate(u) {
|
||||
/* Searches this.tapeUnit[] to find the internal index of the unit that is
|
||||
designated as "u". If found, returns the internal index; if not found,
|
||||
returns -1. If more than one ready unit with the same designate is found,
|
||||
returns -2 */
|
||||
var index = -1;
|
||||
var unit;
|
||||
var x;
|
||||
|
||||
for (x=this.tapeUnit.length-1; x>=0; --x) {
|
||||
unit = this.tapeUnit[x];
|
||||
if (unit && unit.ready) {
|
||||
if (unit.unitDesignate == u) {
|
||||
if (index == -1) {
|
||||
index = x;
|
||||
} else {
|
||||
index = -2;
|
||||
break; // out of for loop
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for x
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.queuePendingOperation = function queuePendingOperation(callee, args) {
|
||||
/* Queues a pending tape operation */
|
||||
|
||||
//console.log(this.mnemonic + " queuePendingOperation: " + args[0].toString(16));
|
||||
if (this.pendingCallee !== null) {
|
||||
throw new Error("More than one pending tape control operation");
|
||||
}
|
||||
|
||||
this.pendingCallee = callee;
|
||||
this.pendingArgs = args;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.loadCommand = function loadCommand(dReg, releaseProcessor, callee, args) {
|
||||
/* If the control unit or the tape unit addressed by the unit field in dReg
|
||||
are currently busy, queues the args parameter (an Arguments object) in
|
||||
this.pendingCallee and -Args, and returns false. If the control is idle but
|
||||
the tape unit is not ready or not present, or two units have the same designate,
|
||||
calls the releaseProcessor call-back and returns false. If the control and
|
||||
tape unit are ready for their next operation, loads the contents of the processor's
|
||||
D register passed to the operation routines into the T, C, and MISC registers.
|
||||
Sets this.unitNr, this.unitIndex, this.blockCount, and this.blockWords from
|
||||
the digits in T. Then returns true */
|
||||
var c; // scratch
|
||||
var t = dReg%0x10000000000; // scratch
|
||||
var ux; // internal unit index
|
||||
var result = false; // return value
|
||||
|
||||
//console.log(this.mnemonic + " loadCommand: " + dReg.toString(16));
|
||||
if (this.controlBusy) {
|
||||
this.queuePendingOperation(callee, args);
|
||||
} else {
|
||||
this.MISC = 0;
|
||||
this.T = t;
|
||||
this.unitNr = (t - t%0x1000000000)/0x1000000000;
|
||||
t = (t - t%0x10000)/0x10000;
|
||||
c = t%0x10; // low-order digit of op code
|
||||
t = (t - t%0x100)/0x100; // control digits from instruction
|
||||
this.blockWords = t%0x100;
|
||||
this.blockCount = ((t - this.blockWords)/0x100)%0x10;
|
||||
if (this.blockWords == 0) {
|
||||
this.blockWords = 100;
|
||||
} else {
|
||||
this.blockWords = B220Processor.bcdBinary(this.blockWords);
|
||||
}
|
||||
|
||||
this.C = this.unitNr*0x100000 + t*0x10 + c;
|
||||
this.regMisc.update(this.MISC);
|
||||
this.regC.update(this.C);
|
||||
this.regT.update(this.T);
|
||||
this.unitIndex = ux = this.findDesignate(this.unitNr);
|
||||
if (ux < 0) {
|
||||
setCallback(this.mnemonic, this, 0, releaseProcessor, true);
|
||||
} else if (this.tapeUnit[ux].busy) {
|
||||
this.queuePendingOperation(callee, args);
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.controlFinished = function controlFinished(alarm) {
|
||||
/* Releases the busy status of the control. Typically used as a timed call-
|
||||
back to simulate the amount of time the control unit is busy with an I/O.
|
||||
If alarm is true, sets the Processor's Magnetic Tape Check alarm.
|
||||
If another operation is pending, initiates that operation */
|
||||
var args; // pending Arguments object
|
||||
var callee; // pending method to call
|
||||
|
||||
//console.log(this.mnemonic + " controlFinished: " + alarm + ", busy=" + this.controlBusy);
|
||||
if (alarm) {
|
||||
this.p.setMagneticTapeCheck(true);
|
||||
}
|
||||
|
||||
this.controlBusy = false;
|
||||
if (this.pendingCallee !== null) {
|
||||
callee = this.pendingCallee;
|
||||
args = this.pendingArgs;
|
||||
this.pendingCallee = this.pendingArgs = null;
|
||||
callee.apply(this, args);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.tapeUnitFinished = function tapeUnitFinished(alarm) {
|
||||
/* Call-back function passed to tape unit methods to signal when the unit has
|
||||
completed its asynchronous operation */
|
||||
|
||||
if (!this.controlBusy) { // if the control unit is currently idle...
|
||||
this.controlFinished(alarm); // initiate any pending operation
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.decrementBlockCount = function decrementBlockCount() {
|
||||
/* Decrements the block-count digit in the C register. Returns true if the
|
||||
remaining block count is non-zero, false otherwise */
|
||||
var c1 = this.C; // will hold two high-order digits of C: uu0000
|
||||
var c2 = c1%0x10000; // four low-order digits of C: bddd, b=block count
|
||||
var result = true;
|
||||
|
||||
c1 -= c2;
|
||||
if (c2 < 0x1000) {
|
||||
c2 += 0x9000; // decrement 0x0ddd to 0x9ddd as count=0 => 10
|
||||
} else {
|
||||
c2 -= 0x1000; // decrement 0xddd..0x9ddd
|
||||
if (c2 < 0x1000) {
|
||||
result = false; // decremented 0x1ddd to 0x0ddd: no more blocks
|
||||
}
|
||||
}
|
||||
|
||||
this.C = c1+c2;
|
||||
this.regC.update(this.C);
|
||||
return result;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.ClearBtn_onClick = function ClearBtn_onClick(ev) {
|
||||
/* Handle the click event for the tape control CLEAR button */
|
||||
|
||||
this.clearUnit();
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.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;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.magTapeOnLoad = function magTapeOnLoad() {
|
||||
/* Initializes the MagTape Control window and user interface */
|
||||
var body;
|
||||
var box;
|
||||
var e;
|
||||
var x;
|
||||
|
||||
this.doc = this.window.document;
|
||||
body = this.$$("PanelSurface");
|
||||
|
||||
// Misc Register
|
||||
this.regMisc = new PanelRegister(this.$$("MiscRegPanel"), 4*4, 4, "Misc_", " ");
|
||||
this.regMisc.lamps[15].setCaption("MCL", true);
|
||||
this.regMisc.lamps[14].setCaption("MC6", true);
|
||||
this.TYC1Lamp = this.regMisc.lamps[13];
|
||||
this.TYC1Lamp.setCaption("TYC", true);
|
||||
this.TYC2Lamp = this.regMisc.lamps[12];
|
||||
this.TYC2Lamp.setCaption("TYC", true);
|
||||
this.TCFLamp = this.regMisc.lamps[10]; // not in this physical position on a 220
|
||||
this.TCFLamp.setCaption("TCF", true);
|
||||
this.TPCLamp = this.regMisc.lamps[7];
|
||||
this.TPCLamp.setCaption("TPC", true);
|
||||
this.regMisc.lamps[6].setCaption("TSX", true);
|
||||
this.regMisc.lamps[5].setCaption("1R6", true);
|
||||
this.TX1Lamp = this.regMisc.lamps[4];
|
||||
this.TX1Lamp.setCaption("TX1", true);
|
||||
this.TX10Lamp = this.regMisc.lamps[3];
|
||||
this.TX10Lamp.setCaption("TX10", true);
|
||||
this.TX8Lamp = this.regMisc.lamps[2];
|
||||
this.TX8Lamp.setCaption("TX8", true);
|
||||
this.TX4Lamp = this.regMisc.lamps[1];
|
||||
this.TX4Lamp.setCaption("TX4", true);
|
||||
this.TX2Lamp = this.regMisc.lamps[0];
|
||||
this.TX2Lamp.setCaption("TX2", true);
|
||||
|
||||
// C Register
|
||||
this.regC = new PanelRegister(this.$$("CRegPanel"), 6*4, 4, "C_", "C");
|
||||
|
||||
// T Register
|
||||
this.regT = new PanelRegister(this.$$("TRegPanel"), 10*4, 4, "T_", "T");
|
||||
|
||||
|
||||
// Events
|
||||
|
||||
this.window.addEventListener("beforeunload", B220MagTapeControl.prototype.beforeUnload);
|
||||
this.$$("ClearBtn").addEventListener("click",
|
||||
B220Util.bindMethod(this, B220MagTapeControl.prototype.ClearBtn_onClick));
|
||||
|
||||
this.clearUnit();
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.readTerminate = function readTerminate() {
|
||||
/* Terminates the read operation, sets the control to not-busy, and signals
|
||||
the processor we are finished with the I/O */
|
||||
|
||||
this.controlBusy = false;
|
||||
this.currentUnit.readTerminate();
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.readReceiveBlock = function readReceiveBlock(block, abortRead) {
|
||||
/* Receives the next block read by the tape unit. Sends the block to the
|
||||
processor for storage in memory, updates the block counter, and if not
|
||||
finished, requests the next block from the tape. Termination is a little
|
||||
tricky here, as readTerminate() must be called to release the drive before
|
||||
the block is stored in memory (and p.executeComplete() called to advance to
|
||||
the next instruction, but if the memory call-back tells us the processor
|
||||
has been cleared, we must release the drive after the attempt to store the
|
||||
block in memory. Mess with the sequencing below at your peril */
|
||||
var lastBlock;
|
||||
var t = B220Processor.bcdBinary(this.T);
|
||||
|
||||
if (abortRead) {
|
||||
this.readTerminate();
|
||||
this.memoryBlockCallback(null, true);
|
||||
} else {
|
||||
// Decrement the block counter in the T register:
|
||||
t = (t + 990)%1000; // subtract 1 from the counter field without overflow
|
||||
this.T = B220Processor.binaryBCD(t);
|
||||
this.regT.update(this.T);
|
||||
|
||||
// If there are more blocks to read, request the next one
|
||||
lastBlock = (t < 10);
|
||||
if (lastBlock) {
|
||||
this.readTerminate();
|
||||
abortRead = this.memoryBlockCallback(block, true);
|
||||
} else {
|
||||
abortRead = this.memoryBlockCallback(block, false);
|
||||
if (abortRead) { // processor was cleared
|
||||
this.readTerminate();
|
||||
} else { // at least one block left to go
|
||||
this.currentUnit.readBlock(this.boundReadReceiveBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.read = function read(unitNr, blocks, blockSender) {
|
||||
/* Initiates a read on the designated unit. "blocks" is the number of blocks
|
||||
to read in BCD; "blockSender" is the call-back function to send a block of data
|
||||
to the processor. "terminator" is the call-back function to tell the Processor
|
||||
the I/O is finished. Returns true if the control is still busy with another command
|
||||
or the unit is busy, and does not do the read */
|
||||
var result = false; // return value
|
||||
var unit; // tape unit object
|
||||
var ux; // internal unit index
|
||||
|
||||
if (this.controlBusy) {
|
||||
result = true;
|
||||
} else {
|
||||
this.C = unitNr;
|
||||
this.regC.update(unitNr);
|
||||
ux = this.findDesignate(unitNr);
|
||||
if (ux < 0) {
|
||||
result = true;
|
||||
} else {
|
||||
this.controlBusy = true;
|
||||
this.currentUnit = unit = this.tapeUnit[ux];
|
||||
this.MISC = B220Processor.binaryBCD(unit.laneNr);
|
||||
this.regMisc.update(this.MISC);
|
||||
this.T = blocks*0x10 + unitNr;
|
||||
this.regT.update(this.T);
|
||||
this.memoryBlockCallback = blockSender;
|
||||
result = unit.readInitiate(this.boundReadReceiveBlock);
|
||||
if (result) {
|
||||
this.controlBusy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.writeTerminate = function writeTerminate(abortWrite) {
|
||||
/* Called by the drive after the last block is written to release the
|
||||
control unit and terminate the I/O. Note that "abortWrite" is not used, but
|
||||
exists for signature compatibility with writeSendBlock() */
|
||||
|
||||
this.recordLamp.set(0);
|
||||
this.controlBusy = false;
|
||||
this.memoryTerminateCallback();
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.writeSendBlock = function writeSendBlock(abortWrite) {
|
||||
/* Called by the tape drive when it is ready for the next block to be written.
|
||||
Retrieves the next buffered block from the Processor and passes it to the drive.
|
||||
Unless this is the last block to write, the drive will call this again after
|
||||
tape motion is complete. Note that this.memoryBlockCallback() will return true
|
||||
if the processor has been cleared and the I/O must be aborted */
|
||||
var aborted; // true if processor aborted the I/O
|
||||
var lastBlock = abortWrite; // true if this will be the last block
|
||||
var t = B220Processor.bcdBinary(this.T);
|
||||
|
||||
// First, decrement the block counter in the T register:
|
||||
t = (t + 990)%1000; // subtract 1 from the counter field without overflow
|
||||
this.T = B220Processor.binaryBCD(t);
|
||||
this.regT.update(this.T);
|
||||
if (t < 10) {
|
||||
lastBlock = true;
|
||||
}
|
||||
|
||||
aborted = this.memoryBlockCallback(this.tapeBlock, lastBlock);
|
||||
if (abortWrite || aborted) {
|
||||
this.writeTerminate(false);
|
||||
} else if (lastBlock) {
|
||||
this.currentUnit.writeBlock(this.tapeBlock, this.boundWriteTerminate, true);
|
||||
} else {
|
||||
this.currentUnit.writeBlock(this.tapeBlock, this.boundWriteSendBlock, false);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.writeInitiate = function writeInitiate(blockReceiver, terminator) {
|
||||
/* Call-back function called by the Processor once the initial block to be
|
||||
written is buffered in one of the high-speed loops. Once this block is
|
||||
buffered, the drive can start tape motion and begin writing to tape */
|
||||
|
||||
this.memoryBlockCallback = blockReceiver;
|
||||
this.memoryTerminateCallback = terminator;
|
||||
this.currentUnit.writeInitiate(this.boundWriteSendBlock);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.write = function write(unitNr, blocks, receiveInitiate) {
|
||||
/* Initiates a write on the designated unit. "blocks" is the number of blocks
|
||||
to write in BCD; "receiveInitiate" is the call-back function to begin memory
|
||||
transfer from the processor. Returns true if the control is still busy with
|
||||
another command or the unit is busy, and does not do the write */
|
||||
var result = false; // return value
|
||||
var unit; // tape unit object
|
||||
var ux; // internal unit index
|
||||
|
||||
if (this.controlBusy) {
|
||||
result = true;
|
||||
} else {
|
||||
this.C = unitNr;
|
||||
this.regC.update(unitNr);
|
||||
ux = this.findDesignate(unitNr);
|
||||
if (ux < 0) {
|
||||
result = true;
|
||||
} else {
|
||||
this.controlBusy = true;
|
||||
this.currentUnit = unit = this.tapeUnit[ux];
|
||||
this.MISC = B220Processor.binaryBCD(unit.laneNr);
|
||||
this.regMisc.update(this.MISC);
|
||||
this.T = blocks*0x10 + unitNr;
|
||||
this.regT.update(this.T);
|
||||
result = unit.writeReadyTest();
|
||||
if (result) {
|
||||
this.controlBusy = false;
|
||||
} else {
|
||||
receiveInitiate(this.boundWriteInitiate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.searchComplete = function searchComplete(success) {
|
||||
/* Resets the busy status at the completion of a search */
|
||||
var d; // scratch digit
|
||||
|
||||
if (success) {
|
||||
// rotate T one digit right at end of successful search
|
||||
d = this.T % 0x10;
|
||||
this.T = d*0x1000 + (this.T - d)/0x10;
|
||||
this.regT.update(this.T);
|
||||
}
|
||||
|
||||
this.controlBusy = false;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.search = function search(unitNr, laneNr, addr) {
|
||||
/* Initiates a search on the designated unit. "laneNr" is the lane number in
|
||||
BCD; "addr" is the number of the block to search for in BCD. The search
|
||||
Takes place in the control unit and drive independently of the processor.
|
||||
Returns true if the control is still busy with another command or the unit
|
||||
is busy, and does not do the search */
|
||||
var block = B220Processor.bcdBinary(addr);
|
||||
var lane = B220Processor.bcdBinary(laneNr);
|
||||
var result = false; // return value
|
||||
var unit; // tape unit object
|
||||
var ux; // internal unit index
|
||||
|
||||
if (this.controlBusy) {
|
||||
result = true;
|
||||
} else {
|
||||
this.C = unitNr;
|
||||
this.regC.update(unitNr);
|
||||
this.MISC = laneNr;
|
||||
this.regMisc.update(laneNr);
|
||||
this.T = addr;
|
||||
this.regT.update(addr);
|
||||
ux = this.findDesignate(unitNr);
|
||||
if (ux < 0) {
|
||||
result = true;
|
||||
} else {
|
||||
this.controlBusy = true;
|
||||
unit = this.tapeUnit[ux];
|
||||
result = unit.search(lane, block, this.boundSearchComplete,
|
||||
this.boundDirectionLampSet, this.boundTestDisabled);
|
||||
if (result) {
|
||||
this.controlBusy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.initialWrite = function initialWrite(dReg, releaseProcessor, fetchBlock) {
|
||||
/* Initial-writes the number of blocks and of the size indicated in dReg.
|
||||
This routine is used by MIW */
|
||||
var alarm = false; // error result
|
||||
var blocksLeft = true; // true => more blocks to process
|
||||
var that = this; // local self-reference
|
||||
var unit = null; // selected tape unit
|
||||
|
||||
function blockReady(alarm, writeBlock, completed) {
|
||||
/* Call-back function when the drive is ready to receive the next block
|
||||
of data, or when it has encountered an error such as EOT. If there are
|
||||
more blocks to write, fetches the next block from the Processor and calls
|
||||
the drive's "writeBlock" function, otherwise calls "completed" to finish
|
||||
the operation */
|
||||
|
||||
if (alarm) {
|
||||
setCallback(that.mnemonic, that, 0, releaseProcessor, true);
|
||||
completed(true); // drive detected an error
|
||||
} else if (blocksLeft) {
|
||||
blocksLeft = that.decrementBlockCount(); // set to false on last block
|
||||
if (that.blockWords < unit.minBlockWords && that.blockWords > 1) {
|
||||
completed(true); // invalid block size
|
||||
} else if (fetchBlock(that.tapeBlock, that.blockWords)) {
|
||||
completed(true); // Processor cleared or memory address error
|
||||
} else {
|
||||
writeBlock(that.tapeBlock, that.blockWords); // write next block
|
||||
}
|
||||
} else {
|
||||
setCallback(that.mnemonic, that, 0, releaseProcessor, false);
|
||||
completed(false); // normal termination
|
||||
}
|
||||
}
|
||||
|
||||
if (this.loadCommand(dReg, releaseProcessor, initialWrite, arguments)) {
|
||||
this.controlBusy = true;
|
||||
unit = this.tapeUnit[this.unitIndex];
|
||||
alarm = unit.initialWriteBlock(blockReady, this.boundControlFinished);
|
||||
if (alarm) {
|
||||
setCallback(this.mnemonic, this, 0, releaseProcessor, alarm);
|
||||
controlFinished(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.initialWriteRecord = function initialWriteRecord(dReg, releaseProcessor, fetchBlock) {
|
||||
/* Initial-writes the number of blocks indicated in dReg. Block lengths
|
||||
(preface words) are taken from the word in memory preceding the data to be
|
||||
written. This routine is used by MIR */
|
||||
var alarm = false; // error result
|
||||
var blocksLeft = true; // true => more blocks to process
|
||||
var that = this; // local self-reference
|
||||
var unit = null; // selected tape unit
|
||||
|
||||
function blockReady(alarm, writeBlock, completed) {
|
||||
/* Call-back function when the drive is ready to receive the next block
|
||||
of data, or when it has encountered an error such as EOT. If there are
|
||||
more blocks to write, fetches the next block and its size from the
|
||||
Processor and calls the drive's "writeBlock" function, otherwise calls
|
||||
"completed" to finish the operation */
|
||||
var words; // words to write for block
|
||||
|
||||
if (alarm) {
|
||||
setCallback(that.mnemonic, that, 0, releaseProcessor, true);
|
||||
completed(true); // drive detected an error
|
||||
} else if (blocksLeft) {
|
||||
blocksLeft = that.decrementBlockCount(); // set to false on last block
|
||||
if (fetchBlock(that.tapeBlock, 1)) { // fetch the preface word
|
||||
completed(true); // Processor cleared or memory address error
|
||||
} else {
|
||||
words = that.tapeBlock[0]; // convert preface to binary
|
||||
words = ((words - words%0x100000000)/0x100000000)%0x100;
|
||||
if (words) {
|
||||
words = (words >>> 4)*10 + words%0x10;
|
||||
} else {
|
||||
words = 100; // preface == 0 => 100
|
||||
}
|
||||
|
||||
if (words < unit.minBlockWords && words > 1) {
|
||||
completed(true); // invalid block size
|
||||
} else if (fetchBlock(that.tapeBlock, words)) {
|
||||
completed(true); // Processor cleared or memory address error
|
||||
} else {
|
||||
writeBlock(that.tapeBlock, words); // write next block
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setCallback(that.mnemonic, that, 0, releaseProcessor, false);
|
||||
completed(false); // normal termination
|
||||
}
|
||||
}
|
||||
|
||||
if (this.loadCommand(dReg, releaseProcessor, initialWriteRecord, arguments)) {
|
||||
this.controlBusy = true;
|
||||
unit = this.tapeUnit[this.unitIndex];
|
||||
alarm = unit.initialWriteBlock(blockReady, this.boundControlFinished);
|
||||
if (alarm) {
|
||||
setCallback(this.mnemonic, this, 0, releaseProcessor, alarm);
|
||||
controlFinished(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.positionForward = function positionForward(dReg, releaseProcessor) {
|
||||
/* Positions the tape forward the number of blocks indicated in dReg */
|
||||
var alarm = false; // error result
|
||||
var that = this; // local self-reference
|
||||
var unit = null; // selected tape unit
|
||||
|
||||
function blockFinished(nextBlock, completed) {
|
||||
/* Call-back function when the drive has finished spacing one block
|
||||
forward. If there are more blocks to space, calls "nextBlock", otherwise
|
||||
calls "completed" to finish the operation */
|
||||
|
||||
if (that.decrementBlockCount()) {
|
||||
nextBlock(blockFinished);
|
||||
} else {
|
||||
completed(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.loadCommand(dReg, releaseProcessor, positionForward, arguments)) {
|
||||
this.controlBusy = true;
|
||||
unit = this.tapeUnit[this.unitIndex];
|
||||
alarm = unit.positionForward(blockFinished, this.boundControlFinished);
|
||||
setCallback(this.mnemonic, this, 0, releaseProcessor, alarm);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.positionBackward = function positionBackward(dReg, releaseProcessor) {
|
||||
/* Positions the tape backward the number of blocks indicated in dReg */
|
||||
var alarm = false; // error result
|
||||
var that = this; // local self-reference
|
||||
var unit = null; // selected tape unit
|
||||
|
||||
function blockFinished(nextBlock, completed) {
|
||||
/* Call-back function when the drive has finished spacing one block
|
||||
backward. If there are more blocks to space, calls "nextBlock", otherwise
|
||||
calls "completed" to finish the operation */
|
||||
|
||||
if (that.decrementBlockCount()) {
|
||||
nextBlock(blockFinished);
|
||||
} else {
|
||||
completed(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.loadCommand(dReg, releaseProcessor, positionBackward, arguments)) {
|
||||
this.controlBusy = true;
|
||||
unit = this.tapeUnit[this.unitIndex];
|
||||
alarm = unit.positionBackward(blockFinished, this.boundControlFinished);
|
||||
setCallback(this.mnemonic, this, 0, releaseProcessor, alarm);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.positionAtEnd = function positionAtEnd(dReg, releaseProcessor) {
|
||||
/* Positions the tape to the end of recorded information (i.e., when a gap
|
||||
longer than inter-block gap is detected. Leaves the tape at the end of the
|
||||
prior recorded block */
|
||||
var alarm = false; // error result
|
||||
|
||||
if (this.loadCommand(dReg, releaseProcessor, positionAtEnd, arguments)) {
|
||||
this.controlBusy = true;
|
||||
alarm = this.tapeUnit[this.unitIndex].positionAtEnd(this.boundControlFinished);
|
||||
setCallback(this.mnemonic, this, 0, releaseProcessor, alarm);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.laneSelect = function laneSelect(dReg, releaseProcessor) {
|
||||
/* Selects the tape lane of the designated unit. Returns an alarm if the
|
||||
unit does not exist or is not ready */
|
||||
var alarm = false; // error result
|
||||
var laneNr; // lane to select (0, 1)
|
||||
|
||||
if (this.loadCommand(dReg, releaseProcessor,laneSelect, arguments)) {
|
||||
this.controlBusy = true;
|
||||
laneNr = ((this.C - this.C%0x100)/0x100)%2;
|
||||
alarm = this.tapeUnit[this.unitIndex].laneSelect(laneNr, this.boundControlFinished);
|
||||
setCallback(this.mnemonic, this, 0, releaseProcessor, alarm);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.rewind = function rewind(dReg, releaseProcessor) {
|
||||
/* Initiates rewind of the designated unit. Returns an alarm if the unit
|
||||
does not exist or is not ready */
|
||||
var alarm = false; // error result
|
||||
var laneNr; // lane to select (0, 1)
|
||||
var lockout; // lockout after rewind (0, 1)
|
||||
|
||||
if (this.loadCommand(dReg, releaseProcessor, rewind, arguments)) {
|
||||
this.controlBusy = true;
|
||||
laneNr = ((this.C - this.C%0x100)/0x100)%2;
|
||||
lockout = ((this.C - this.C%0x10)/0x10)%2;
|
||||
alarm = this.tapeUnit[this.unitIndex].rewind(laneNr, lockout, this.boundTapeUnitFinished);
|
||||
setCallback(this.mnemonic, this, 50, this.controlFinished, false);
|
||||
setCallback(this.mnemonic, this, 0, releaseProcessor, alarm);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.testUnitReady = function testUnitReady(dReg) {
|
||||
/* Interrogates status of the designated unit. Returns true if ready */
|
||||
var result = false; // return value
|
||||
var ux; // internal unit index
|
||||
|
||||
ux = ((dReg - dReg%0x1000000000)/0x1000000000)%0x10;
|
||||
ux = this.findDesignate(ux);
|
||||
if (ux >= 0) {
|
||||
if (this.tapeUnit[ux].ready) {
|
||||
if (!this.tapeUnit[ux].busy) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.testUnitAtMagneticEOT = function testUnitAtMagneticEOT(dReg) {
|
||||
/* Interrogates status of the designated unit. Returns true if ready and at
|
||||
Magnetic-End-of-Tape */
|
||||
var result = false; // return value
|
||||
var ux; // internal unit index
|
||||
|
||||
ux = ((dReg - dReg%0x1000000000)/0x1000000000)%0x10;
|
||||
ux = this.findDesignate(ux);
|
||||
if (ux >= 0) {
|
||||
if (this.tapeUnit[ux].ready) {
|
||||
if (this.tapeUnit[ux].atEOT) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.clearUnit = function clearUnit() {
|
||||
/* Clears the internal state of the control unit */
|
||||
|
||||
this.clear();
|
||||
this.regMisc.update(this.MISC);
|
||||
this.regC.update(this.C);
|
||||
this.regT.update(this.T);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B220MagTapeControl.prototype.shutDown = function shutDown() {
|
||||
/* Shuts down the panel */
|
||||
var x;
|
||||
|
||||
if (this.tapeUnit) {
|
||||
for (x=this.tapeUnit.length-1; x>=0; --x) {
|
||||
if (this.tapeUnit[x]) {
|
||||
this.tapeUnit[x].shutDown();
|
||||
this.tapeUnit[x] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.window.removeEventListener("beforeunload", B220MagTapeControl.prototype.beforeUnload);
|
||||
this.window.close();
|
||||
};
|
||||
294
webUI/B220MagTapeDrive.css
Normal file
294
webUI/B220MagTapeDrive.css
Normal file
@@ -0,0 +1,294 @@
|
||||
/***********************************************************************
|
||||
* retro-220/webUI B220MagTapeDrive.css
|
||||
************************************************************************
|
||||
* Copyright (c) 2017, Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* Burroughs 220 emulator Magnetic Tape Drive
|
||||
* web interface style sheet.
|
||||
************************************************************************
|
||||
* 2017-07-09 P.Kimpel
|
||||
* Original version, from retro-205 D205MagTapeDrive.css.
|
||||
***********************************************************************/
|
||||
|
||||
#magTapeBody {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0}
|
||||
|
||||
#MTDiv {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0px}
|
||||
|
||||
DIV.annunciator {
|
||||
color: #F93;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
text-align: center;
|
||||
position: absolute}
|
||||
|
||||
DIV.annunciatorLit {
|
||||
background-color: black}
|
||||
|
||||
SELECT {
|
||||
text-align: center}
|
||||
|
||||
|
||||
#RWLLamp {
|
||||
top: 18px;
|
||||
left: 10px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#RWLLampCaption {
|
||||
top: 10px;
|
||||
left: 0px;
|
||||
width: 48px}
|
||||
|
||||
#NotWriteLamp {
|
||||
top: 18px;
|
||||
left: 58px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#NotWriteLampCaption {
|
||||
top: 10px;
|
||||
left: 48px;
|
||||
width: 48px}
|
||||
|
||||
#NotReadyLamp {
|
||||
top: 18px;
|
||||
left: 106px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#NotReadyLampCaption {
|
||||
top: 10px;
|
||||
left: 96px;
|
||||
width: 48px}
|
||||
|
||||
#DesignatedLamp {
|
||||
top: 18px;
|
||||
left: 154px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#DesignatedLampCaption {
|
||||
top: 3px;
|
||||
left: 144px;
|
||||
width: 48px}
|
||||
|
||||
#TransportPowerCaption {
|
||||
top: 4px;
|
||||
left: 192px;
|
||||
width: 96px}
|
||||
|
||||
#TransportOnLamp {
|
||||
top: 18px;
|
||||
left: 202px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#TransportOnLampCaption {
|
||||
top: 10px;
|
||||
left: 192px;
|
||||
width: 48px}
|
||||
|
||||
#TransportStandbyLamp {
|
||||
top: 18px;
|
||||
left: 250px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#TransportStandbyLampCaption {
|
||||
top: 10px;
|
||||
left: 240px;
|
||||
width: 48px}
|
||||
|
||||
#LoadBtn {
|
||||
top: 64px;
|
||||
left: 12px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#LoadBtnCaption {
|
||||
top: 56px;
|
||||
left: 0px;
|
||||
width: 48px}
|
||||
|
||||
#UnloadBtn {
|
||||
top: 64px;
|
||||
left: 60px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#UnloadBtnCaption {
|
||||
top: 56px;
|
||||
left: 48px;
|
||||
width: 48px}
|
||||
|
||||
#RewindBtn {
|
||||
top: 64px;
|
||||
left: 108px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#RewindBtnCaption {
|
||||
top: 56px;
|
||||
left: 96px;
|
||||
width: 48px}
|
||||
|
||||
#TransportPowerBtnCaption {
|
||||
top: 58px;
|
||||
left: 192px;
|
||||
width: 96px}
|
||||
|
||||
#TransportOnBtn {
|
||||
top: 64px;
|
||||
left: 204px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#TransportOnBtnCaption {
|
||||
top: 56px;
|
||||
left: 192px;
|
||||
width: 48px}
|
||||
|
||||
#TransportStandbyBtn {
|
||||
top: 64px;
|
||||
left: 252px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#TransportStandbyBtnCaption {
|
||||
top: 56px;
|
||||
left: 240px;
|
||||
width: 48px}
|
||||
|
||||
#RWLRBtn {
|
||||
top: 104px;
|
||||
left: 12px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#RWLRBtnCaption {
|
||||
top: 96px;
|
||||
left: 0px;
|
||||
width: 48px}
|
||||
|
||||
#WriteBtn {
|
||||
top: 104px;
|
||||
left: 60px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#WriteBtnCaption {
|
||||
top: 96px;
|
||||
left: 48px;
|
||||
width: 48px}
|
||||
|
||||
#NotWriteBtn {
|
||||
top: 104px;
|
||||
left: 108px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#NotWriteBtnCaption {
|
||||
top: 96px;
|
||||
left: 96px;
|
||||
width: 48px}
|
||||
|
||||
#UnitDesignate {
|
||||
position: absolute;
|
||||
top: 106px;
|
||||
left: 204px;
|
||||
width: 72px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#UnitDesignateCaption {
|
||||
top: 96px;
|
||||
left: 192px;
|
||||
width: 96px}
|
||||
|
||||
|
||||
#MTReel {
|
||||
position: absolute;
|
||||
height: 48px;
|
||||
visibility: hidden;
|
||||
border-radius: 50%;
|
||||
top: 8px;
|
||||
right: 16px}
|
||||
|
||||
#MTUnloadedLight {
|
||||
top: 60px;
|
||||
right: 8px;
|
||||
width: 64px}
|
||||
|
||||
#MTAtBOTLight {
|
||||
top: 78px;
|
||||
right: 8px;
|
||||
width: 64px}
|
||||
|
||||
#MTAtEOTLight {
|
||||
top: 96px;
|
||||
right: 8px;
|
||||
width: 64px}
|
||||
|
||||
#MTRewindingLight {
|
||||
top: 114px;
|
||||
right: 8px;
|
||||
width: 64px}
|
||||
|
||||
#MTStatusDiv {
|
||||
position: absolute;
|
||||
bottom: 4px;
|
||||
left: 8px;
|
||||
right: 8px}
|
||||
|
||||
#MTFileName {
|
||||
width: 100%;
|
||||
font-family: DejaVuSansWeb, sans-serif;
|
||||
color: black;
|
||||
background-color: inherit;
|
||||
border: none}
|
||||
|
||||
#MTReelBar {
|
||||
margin-top: 4px;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
border: 1px solid white}
|
||||
|
||||
#MTReelBarCaption {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 24px;
|
||||
z-index: 1;
|
||||
height: 12px;
|
||||
color: black;
|
||||
font-weight: bold}
|
||||
|
||||
/* Tape Load Panel */
|
||||
|
||||
#MTLoadFileGroup {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
right: 8px}
|
||||
|
||||
#MTLoadFileSelector {
|
||||
border: 1px solid white;
|
||||
color: white;
|
||||
width: 100%}
|
||||
|
||||
#MTLoadFormatGroup {
|
||||
position: absolute;
|
||||
top: 32px;
|
||||
left: 0}
|
||||
|
||||
#MTLoadFormatSelect {
|
||||
border: 1px solid white}
|
||||
|
||||
#MTLoadWriteEnableCheck {
|
||||
border: 1px solid white}
|
||||
|
||||
#MTLoadNotes {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
width: 300px;
|
||||
left: 0}
|
||||
|
||||
#MTLoadButtonGroup {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
right: 0}
|
||||
|
||||
#MTLoadCancelBtn {
|
||||
background-image: none;
|
||||
background-color: #900;
|
||||
height: 20px;
|
||||
bottom: 0;
|
||||
right: 64px}
|
||||
|
||||
#MTLoadOKBtn {
|
||||
background-image: none;
|
||||
background-color: #060;
|
||||
height: 20px;
|
||||
bottom: 0;
|
||||
right: 0}
|
||||
102
webUI/B220MagTapeDrive.html
Normal file
102
webUI/B220MagTapeDrive.html
Normal file
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>220 Emulator Magnetic Tape Drive</title>
|
||||
<!--
|
||||
/***********************************************************************
|
||||
* retro-220/webUI B220MagTapeDrive.html
|
||||
************************************************************************
|
||||
* Copyright (c) 2017, Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* Burroughs 220 Magnetic Tape Drive device page.
|
||||
*
|
||||
* Implements the 220 magnetic tape drive storage unit peripheral.
|
||||
*
|
||||
************************************************************************
|
||||
* 2017-07-09 P.Kimpel
|
||||
* Original version, from retro-205 D205MagTapeDrive.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=tapeDriveStyleSheet rel=stylesheet type="text/css" href="B220MagTapeDrive.css">
|
||||
</head>
|
||||
|
||||
<body id=magTapeBody class=deviceBody>
|
||||
|
||||
<div id=MTDiv class=panelSurface>
|
||||
|
||||
<div id=RWLLampCaption class=caption>RWL</div>
|
||||
|
||||
<div id=NotWriteLampCaption class=caption>NOT WRITE</div>
|
||||
|
||||
<div id=NotReadyLampCaption class=caption>NOT READY</div>
|
||||
|
||||
<div id=DesignatedLampCaption class=caption>UNIT<br>DESIGNATE</div>
|
||||
|
||||
<div id=TransportPowerCaption class=caption>TRANSPORT POWER</div>
|
||||
|
||||
<div id=TransportOnLampCaption class=caption>ON</div>
|
||||
|
||||
<div id=TransportStandbyLampCaption class=caption>STANDBY</div>
|
||||
|
||||
<div id=LoadBtn class=redButton3> </div>
|
||||
<div id=LoadBtnCaption class=caption>LOAD</div>
|
||||
|
||||
<div id=UnloadBtn class=blackButton3> </div>
|
||||
<div id=UnloadBtnCaption class=caption>UNLOAD</div>
|
||||
|
||||
<div id=RewindBtn class=redButton3> </div>
|
||||
<div id=RewindBtnCaption class=caption>REWIND</div>
|
||||
|
||||
<select id=UnitDesignate>
|
||||
<option value="">LOCAL
|
||||
<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=0>10
|
||||
</select>
|
||||
<div id=UnitDesignateCaption class=caption>UNIT DESIGNATE</div>
|
||||
|
||||
<div id=RWLRBtn class=blackButton3> </div>
|
||||
<div id=RWLRBtnCaption class=caption>RWLR</div>
|
||||
|
||||
<div id=WriteBtn class=redButton3> </div>
|
||||
<div id=WriteBtnCaption class=caption>WRITE</div>
|
||||
|
||||
<div id=NotWriteBtn class=blackButton3> </div>
|
||||
<div id=NotWriteBtnCaption class=caption>NOT WRITE</div>
|
||||
|
||||
<div id=TransportOnBtn class=redButton3> </div>
|
||||
<div id=TransportOnBtnCaption class=caption>ON</div>
|
||||
|
||||
<div id=TransportStandbyBtn class=blackButton3> </div>
|
||||
<div id=TransportStandbyBtnCaption class=caption>ST'DBY</div>
|
||||
|
||||
<img id=MTReel src="./resources/MagTapeReel.jpg">
|
||||
|
||||
<div id=MTUnloadedLight class=annunciator>UNLOADED</div>
|
||||
<div id=MTAtBOTLight class=annunciator>AT BOT</div>
|
||||
<div id=MTAtEOTLight class=annunciator>AT EOT</div>
|
||||
<div id=MTRewindingLight class=annunciator>REWINDING</div>
|
||||
|
||||
<div id=MTStatusDiv>
|
||||
<input id=MTFileName type=text READONLY><br>
|
||||
<meter id=MTReelBar min=0 max=100 value=0 title="Tape remaining on supply reel"></meter>
|
||||
<label id=MTReelBarCaption for=MTReelBar>SUPPLY REEL</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1899
webUI/B220MagTapeDrive.js
Normal file
1899
webUI/B220MagTapeDrive.js
Normal file
File diff suppressed because it is too large
Load Diff
69
webUI/B220MagTapeLoadPanel.html
Normal file
69
webUI/B220MagTapeLoadPanel.html
Normal file
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>220 Emulator Magnetic Tape Loader</title>
|
||||
<!--
|
||||
/***********************************************************************
|
||||
* retro-220/webUI B220MagTapeLoadPanel.html
|
||||
************************************************************************
|
||||
* Copyright (c) 2017, Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* Burroughs 220 Magnetic Tape Drive Loader page.
|
||||
*
|
||||
* Implements a dialog to load blank tapes or tape-image files for the
|
||||
* magnetic tape drive device.
|
||||
*
|
||||
************************************************************************
|
||||
* 2017-07-09 P.Kimpel
|
||||
* Original version, from retro-205 D205MagTapeLoadPanel.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="B220MagTapeDrive.css">
|
||||
</head>
|
||||
|
||||
<body class=deviceBody>
|
||||
|
||||
<div id=MTLoadFileGroup>
|
||||
<input id=MTLoadFileSelector type=file size=60>
|
||||
|
||||
<div id=MTLoadFormatGroup>
|
||||
Format
|
||||
<select id=MTLoadFormatSelect>
|
||||
<option value="edited" selected>(Edited tape)
|
||||
<option value="10">10-word blocks
|
||||
<option value="20">20-word blocks
|
||||
<option value="30">30-word blocks
|
||||
<option value="40">40-word blocks
|
||||
<option value="50">50-word blocks
|
||||
<option value="60">60-word blocks
|
||||
<option value="70">70-word blocks
|
||||
<option value="80">80-word blocks
|
||||
<option value="90">90-word blocks
|
||||
<option value="100">100-word blocks
|
||||
</select>
|
||||
|
||||
<input id=MTLoadWriteEnableCheck type=checkbox value="1">
|
||||
<label for=MTLoadWriteEnableCheck>Write Enabled</label>
|
||||
</div>
|
||||
|
||||
<div id=MTLoadNotes>
|
||||
To load a blank tape, simply click <b>OK</b>; otherwise
|
||||
select a tape-image file before clicking <b>OK</b>.
|
||||
</div>
|
||||
|
||||
<div id=MTLoadButtonGroup>
|
||||
<button id=MTLoadCancelBtn class="large redButton">Cancel</button>
|
||||
|
||||
<button id=MTLoadOKBtn class="large greenButton">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,5 @@
|
||||
CACHE MANIFEST
|
||||
# retro-220 emulator 0.03, 2017-05-29 13:30
|
||||
# retro-220 emulator 0.03a, 2017-10-19 08:45
|
||||
CACHE:
|
||||
../emulator/B220Processor.js
|
||||
B220.css
|
||||
@@ -30,13 +30,13 @@ B220ControlConsole.js
|
||||
#B220DataFile.js
|
||||
B220DiagMonitor.html
|
||||
B220FramePaper.html
|
||||
#B220MagTapeControl.css
|
||||
#B220MagTapeControl.html
|
||||
#B220MagTapeControl.js
|
||||
#B220MagTapeDrive.css
|
||||
#B220MagTapeDrive.html
|
||||
#B220MagTapeDrive.js
|
||||
#B220MagTapeLoadPanel.html
|
||||
B220MagTapeControl.css
|
||||
B220MagTapeControl.html
|
||||
B220MagTapeControl.js
|
||||
B220MagTapeDrive.css
|
||||
B220MagTapeDrive.html
|
||||
B220MagTapeDrive.js
|
||||
B220MagTapeLoadPanel.html
|
||||
B220PanelUtil.js
|
||||
B220PaperTapePunch.css
|
||||
B220PaperTapePunch.html
|
||||
@@ -60,7 +60,7 @@ resources/DejaVuSans-webfont.ttf
|
||||
resources/DejaVuSans-webfont.woff
|
||||
resources/DejaVuSansMono-webfont.ttf
|
||||
resources/DejaVuSansMono-webfont.woff
|
||||
#resources/MagTapeReel.jpg
|
||||
resources/MagTapeReel.jpg
|
||||
resources/Organ-Switch-Down.png
|
||||
resources/Organ-Switch-Up.png
|
||||
resources/retro-220-Logo.png
|
||||
|
||||
@@ -824,7 +824,6 @@ PanelRegister.prototype.drawBox = function drawBox(col, lamps, rows, leftStyle,
|
||||
leftStyle and rightStyle specify the left and right borders of the box using
|
||||
standard CSS border syntax. Returns the box element */
|
||||
var box = document.createElement("div");
|
||||
var rightBias = (rightStyle ? 1 : 0);
|
||||
|
||||
box.style.position = "absolute";
|
||||
box.style.left = (this.xCoord(col) - (PanelRegister.hSpacing-PanelRegister.lampDiameter)/2 + 1).toString() + "px";
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
left: 56px;
|
||||
top: 14px}
|
||||
top: 14px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#ReadyLampCaption {
|
||||
width: 36px;
|
||||
left: 52px;
|
||||
@@ -57,7 +58,8 @@
|
||||
right: 8px;
|
||||
top: 18px;
|
||||
color: white;
|
||||
background-color: #333}
|
||||
background-color: #333;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#UnitDesignateKnobCaption {
|
||||
width: 64px;
|
||||
right: 8px;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
/**************************************/
|
||||
function B220PaperTapePunch(mnemonic, unitIndex, config) {
|
||||
/* Constructor for the Console Paper Tape Punch object */
|
||||
var top = unitIndex*32 + 360;
|
||||
var top = unitIndex*32 + 264;
|
||||
var left = (unitIndex-1)*32;
|
||||
|
||||
this.config = config; // System configuration object
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
left: 56px;
|
||||
top: 14px}
|
||||
top: 14px;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#ReadyLampCaption {
|
||||
width: 36px;
|
||||
left: 52px;
|
||||
@@ -75,7 +76,8 @@
|
||||
right: 8px;
|
||||
top: 18px;
|
||||
color: white;
|
||||
background-color: #333}
|
||||
background-color: #333;
|
||||
box-shadow: 3px 3px 2px #999}
|
||||
#UnitDesignateKnobCaption {
|
||||
width: 64px;
|
||||
right: 8px;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
/**************************************/
|
||||
function B220PaperTapeReader(mnemonic, unitIndex, config) {
|
||||
/* Constructor for the PaperTapeReader object */
|
||||
var top = unitIndex*32 + 360;
|
||||
var top = unitIndex*32 + 264;
|
||||
var left = (unitIndex-1)*32 + 250;
|
||||
|
||||
this.config = config; // System configuration object
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* minimum they use, and their precision in activating the call-back function
|
||||
* once the actual delay is established varies even more. This module will use
|
||||
* setTimeout() if the requested delay time is above a certain threshold, and
|
||||
* a setImmediate-like mechanism (based on window.postMessage) if the requested
|
||||
* delay is below that threshold.
|
||||
* a setImmediate-like mechanism (based on Promise) if the requested delay is
|
||||
* below that threshold.
|
||||
*
|
||||
* To help compensate for the fact that the call-back function may be called
|
||||
* sooner than requested, and that due either to other activity or to browser
|
||||
@@ -43,9 +43,9 @@
|
||||
* earlier or later than the specified delay. The string "category" (which
|
||||
* may be empty, null, or undefined) defines the category under which the
|
||||
* average delay difference will be maintained. setCallBack returns a
|
||||
* numeric token identifying the call-back event, which can be used
|
||||
* with clearCallback(). Note that passing a string in lieu of a function
|
||||
* object is not permitted.
|
||||
* numeric token identifying the call-back event, which can be used with
|
||||
* clearCallback() to cancel the callback. Note that passing a string in
|
||||
* lieu of a function object is not permitted.
|
||||
*
|
||||
* clearCallBack(token)
|
||||
*
|
||||
@@ -77,6 +77,8 @@
|
||||
* Original version, cloned from retro-205 emulator D205SetCallback.js.
|
||||
* 2017-02-18 P.Kimpel
|
||||
* Redesign yet again the delay adjustment mechanism -- from 205 project.
|
||||
* 2017-10-16 P.Kimpel
|
||||
* Replace window.postMessage yield mechanism with one based on Promise().
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
@@ -89,7 +91,6 @@
|
||||
var perf = global.performance; // cached window.performance object
|
||||
var pool = []; // pool of reusable callback objects
|
||||
var poolLength = 0; // length of active entries in pool
|
||||
var secretPrefix = "retro-205.webUI." + Date.now().toString(16);
|
||||
|
||||
/**************************************/
|
||||
function activateCallback(token) {
|
||||
@@ -140,7 +141,7 @@
|
||||
/* Sets up and schedules a callback for function "fcn", called with context
|
||||
"context", after a delay of "delay" ms. An optional "arg" value will be passed
|
||||
to "fcn". If the delay is less than "minTimeout", a setImmediate-like mechanism
|
||||
based on window.postsMessage() will be used; otherwise the environment's standard
|
||||
based on DOM Promise() will be used; otherwise the environment's standard
|
||||
setTimeout mechanism will be used */
|
||||
var adj = 0; // adjustment to delay and delayDev[]
|
||||
var categoryName = (category || "NUL").toString();
|
||||
@@ -213,25 +214,12 @@
|
||||
thisCallback.cancelToken = global.setTimeout(activateCallback, delay, token);
|
||||
} else {
|
||||
thisCallback.cancelToken = 0;
|
||||
global.postMessage(secretPrefix + tokenName, "*");
|
||||
Promise.resolve(token).then(activateCallback);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function onMessage(ev) {
|
||||
/* Handler for the global.onmessage event. Activates the callback */
|
||||
var payload;
|
||||
|
||||
if (ev.source === global) {
|
||||
payload = ev.data.toString();
|
||||
if (payload.substring(0, secretPrefix.length) === secretPrefix) {
|
||||
activateCallback(payload.substring(secretPrefix.length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function getCallbackState(optionMask) {
|
||||
/* Diagnostic function. Returns an object that, depending upon bits in
|
||||
@@ -270,7 +258,7 @@
|
||||
}
|
||||
|
||||
/********** Outer block of anonymous closure **********/
|
||||
if (!global.setCallback && global.postMessage && !global.importScripts) {
|
||||
if (!global.setCallback && !global.importScripts) {
|
||||
// Attach to the prototype of global, if possible, otherwise to global itself
|
||||
var attachee = global;
|
||||
|
||||
@@ -282,7 +270,6 @@
|
||||
}
|
||||
*****/
|
||||
|
||||
global.addEventListener("message", onMessage, false);
|
||||
attachee.setCallback = setCallback;
|
||||
attachee.clearCallback = clearCallback;
|
||||
attachee.getCallbackState = getCallbackState;
|
||||
|
||||
@@ -89,7 +89,6 @@
|
||||
#ConsoleInputTable,
|
||||
#ConsoleOutputTable,
|
||||
#CardatronTable,
|
||||
#MagTapeOptionsTable,
|
||||
#MagTapeTable {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse}
|
||||
@@ -100,8 +99,6 @@
|
||||
#ConsoleOutputTable TD,
|
||||
#CardatronTable TH,
|
||||
#CardatronTable TD,
|
||||
#MagTapeOptionsTable TH,
|
||||
#MagTapeOptionsTable TD,
|
||||
#MagTapeTable TH,
|
||||
#MagTapeTable TD {
|
||||
padding-left: 4px;
|
||||
|
||||
@@ -925,19 +925,10 @@
|
||||
|
||||
<div class=heading>Magnetic Tape Unit Selection:</div>
|
||||
|
||||
<table id=MagTapeOptionsTable>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class=center>
|
||||
<input id=SuppressBMod type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<label for=SuppressBMod>Suppress B-Register Modification
|
||||
</table>
|
||||
|
||||
<table id=MagTapeTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Unit<th>Type<th>Designate<th>Remote<th>Rewind-Ready<th>Not-Write
|
||||
<th>Unit<th>Type<th>Designate
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class=center>A
|
||||
@@ -959,12 +950,6 @@
|
||||
<option value=8>8
|
||||
<option value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape1Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape1RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape1NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>B
|
||||
<td class=center>
|
||||
@@ -985,12 +970,6 @@
|
||||
<option value=8>8
|
||||
<option value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape2Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape2RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape2NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>C
|
||||
<td class=center>
|
||||
@@ -1011,12 +990,6 @@
|
||||
<option value=8>8
|
||||
<option value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape3Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape3RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape3NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>D
|
||||
<td class=center>
|
||||
@@ -1037,12 +1010,6 @@
|
||||
<option value=8>8
|
||||
<option value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape4Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape4RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape4NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>E
|
||||
<td class=center>
|
||||
@@ -1063,12 +1030,6 @@
|
||||
<option value=8>8
|
||||
<option value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape5Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape5RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape5NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>F
|
||||
<td class=center>
|
||||
@@ -1089,12 +1050,6 @@
|
||||
<option value=8>8
|
||||
<option value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape6Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape6RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape6NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>G
|
||||
<td class=center>
|
||||
@@ -1115,12 +1070,6 @@
|
||||
<option value=8>8
|
||||
<option value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape7Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape7RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape7NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>H
|
||||
<td class=center>
|
||||
@@ -1141,12 +1090,6 @@
|
||||
<option selected value=8>8
|
||||
<option value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape8Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape8RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape8NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>I
|
||||
<td class=center>
|
||||
@@ -1167,12 +1110,6 @@
|
||||
<option value=8>8
|
||||
<option selected value=9>9
|
||||
<option value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape9Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape9RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape9NotWrite type=checkbox value=1>
|
||||
<tr>
|
||||
<td class=center>J
|
||||
<td class=center>
|
||||
@@ -1193,12 +1130,6 @@
|
||||
<option value=8>8
|
||||
<option value=9>9
|
||||
<option selected value=0>0
|
||||
<td class=center>
|
||||
<input id=MagTape10Remote type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape10RewindReady type=checkbox value=1 checked>
|
||||
<td class=center>
|
||||
<input id=MagTape10NotWrite type=checkbox value=1>
|
||||
</table>
|
||||
<p> </p>
|
||||
</div>
|
||||
|
||||
@@ -107,11 +107,11 @@ B220SystemConfig.defaultConfig = {
|
||||
hasMagTape: true,
|
||||
units: [
|
||||
null, // unit[0] not used
|
||||
{type: "MTA", designate: 0, remoteSwitch: false, rewindReadySwitch: true, notWriteSwitch: false},
|
||||
{type: "MTA", designate: 1},
|
||||
{type: "MTB", designate: 2},
|
||||
{type: "NONE"},
|
||||
{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"},
|
||||
@@ -371,15 +371,11 @@ B220SystemConfig.prototype.loadConfigDialog = function loadConfigDialog() {
|
||||
cd.MagTape = B220SystemConfig.defaultConfig.MagTape;
|
||||
}
|
||||
|
||||
this.$$("SuppressBMod").checked = !cd.MagTape.suppressBSwitch;
|
||||
for (x=1; x<=10; ++x) {
|
||||
unit = cd.MagTape.units[x];
|
||||
prefix = "MagTape" + x;
|
||||
this.setListValue(prefix + "Type", unit.type);
|
||||
this.$$(prefix + "Designate").selectedIndex = unit.designate;
|
||||
this.$$(prefix + "Remote").checked = unit.remoteSwitch;
|
||||
this.$$(prefix + "RewindReady").checked = unit.rewindReadySwitch;
|
||||
this.$$(prefix + "NotWrite").checked = unit.notWriteSwitch;
|
||||
this.$$(prefix + "Designate").selectedIndex = unit.designate-1;
|
||||
} // for x
|
||||
|
||||
this.$$("MessageArea").textContent = "220 System Configuration loaded.";
|
||||
@@ -509,17 +505,13 @@ B220SystemConfig.prototype.saveConfigDialog = function saveConfigDialog() {
|
||||
// Magnetic Tape units
|
||||
|
||||
cd.MagTape.hasMagTape = false;
|
||||
cd.MagTape.suppressBSwitch = !this.$$("SuppressBMod").checked;
|
||||
|
||||
for (x=1; x<=10; ++x) {
|
||||
unit = cd.MagTape.units[x];
|
||||
prefix = "MagTape" + x;
|
||||
e = this.$$(prefix + "Type");
|
||||
unit.type = (e.selectedIndex < 0 ? "NONE" : e.options[e.selectedIndex].value);
|
||||
unit.designate = this.$$(prefix + "Designate").selectedIndex;
|
||||
unit.remoteSwitch = this.$$(prefix + "Remote").checked;
|
||||
unit.rewindReadySwitch = this.$$(prefix + "RewindReady").checked;
|
||||
unit.notWriteSwitch = this.$$(prefix + "NotWrite").checked;
|
||||
unit.designate = this.$$(prefix + "Designate").selectedIndex+1;
|
||||
if (unit.type != "NONE") {
|
||||
cd.MagTape.hasMagTape = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user