1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-02-11 10:55:09 +00:00

Commit initial I/O Unit development.

This commit is contained in:
paul
2012-12-09 04:18:40 +00:00
parent fed3d522f1
commit a55a6779ab
13 changed files with 492 additions and 19 deletions

View File

@@ -26,7 +26,7 @@ function B5500CentralControl() {
this.IO4 = null; // I/O unit 4
this.P1 = null; // Reference for Processor 1 (control) [PA or PB]
this.P1 = null; // Reference for Processor 2 (slave) [PA or PB]
this.P2 = null; // Reference for Processor 2 (slave) [PA or PB]
this.AddressSpace = [ // Array of memory module address spaces (8 x 32KB each)
null, null, null, null, null, null, null, null];
@@ -35,6 +35,7 @@ function B5500CentralControl() {
// Instance variables and flags
this.poweredUp = 0; // System power indicator
this.unitStatusMask = 0; // Peripheral unit ready-status bitmask
this.PB1L = 0; // 0=> PA is P1, 1=> PB is P1
this.cardLoadSelect = 0; // 0=> load from disk/drum; 1=> load from cards
@@ -385,15 +386,19 @@ B5500CentralControl.prototype.clearInterrupt = function() {
break;
case 0x17: // @27: I/O 1 finished
this.CCI08F = 0;
this.AD1F = 0; // make unit non-busy
break;
case 0x18: // @30: I/O 2 finished
this.CCI09F = 0;
this.AD2F = 0; // make unit non-busy
break;
case 0x19: // @31: I/O 3 finished
this.CCI10F = 0;
this.AD3F = 0; // make unit non-busy
break;
case 0x1A: // @32: I/O 4 finished
this.CCI11F = 0;
this.AD4F = 0; // make unit non-busy
break;
case 0x1B: // @33: P2 busy
this.CCI12F = 0;
@@ -510,16 +515,16 @@ B5500CentralControl.prototype.initiateP2 = function() {
B5500CentralControl.prototype.initiateIO = function() {
/* Selects an I/O unit and initiates an I/O */
if (this.IO1) {
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
this.AD1F = 1;
this.IO1.initiate();
} else if (this.IO2) {
} else if (this.IO2 && this.IO2.REMF && !this.AD2F) {
this.AD2F = 1;
this.IO2.initiate();
} else if (this.IO3) {
} else if (this.IO3 && this.IO3.REMF && !this.AD3F) {
this.AD3F = 1;
this.IO3.initiate();
} else if (this.IO4) {
} else if (this.IO4 && this.IO4.REMF && !this.AD4F) {
this.AD4F = 1;
this.IO4.initiate();
} else {
@@ -528,6 +533,68 @@ B5500CentralControl.prototype.initiateIO = function() {
}
};
/**************************************/
B5500CentralControl.prototype.interrogateIOChannel = function() {
/* Returns a value as for the processor TIO syllable indicating the first
available and non-busy I/O Unit */
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
return 1;
} else if (this.IO2 && this.IO2.REMF && !this.AD2F) {
return 2;
} else if (this.IO3 && this.IO3.REMF && !this.AD3F) {
return 3;
} else if (this.IO4 && this.IO4.REMF && !this.AD4F) {
return 4;
} else {
return 0; // All I/O Units busy
}
};
/**************************************/
B5500CentralControl.prototype.interrogateUnitStatus = function() {
/* Returns a bitmask as for the processor TUS syllable indicating the
ready status of all peripheral units */
return this.unitStatusMask;
};
/**************************************/
B5500CentralControl.prototype.testUnitBusy = function(ioUnit, unit) {
/* Determines whether the unit designate "unit" is currently in use by any other
I/O Unit than the one designated by "ioUnit". Returns 0 if not busy */
if (ioUnit != "1" && this.IO1 && this.IO1.REMF && this.AD1F && this.IO1.Dunit == unit) {
return 1;
} else if (ioUnit != "2" && this.IO2 && this.IO2.REMF && this.AD2F && this.IO2.Dunit == unit) {
return 2;
} else if (ioUnit != "3" && this.IO3 && this.IO3.REMF && this.AD3F && this.IO3.Dunit == unit) {
return 3;
} else if (ioUnit != "4" && this.IO4 && this.IO4.REMF && this.AD4F && this.IO4.Dunit == unit) {
return 4;
} else {
return 0; // peripheral unit not in use by any other I/O Unit
}
};
/**************************************/
B5500CentralControl.prototype.testUnitReady = function(unit) {
/* Determines whether the unit designate "unit" is currently in ready status.
Returns 0 if not ready */
if (ioUnit != "1" && this.IO1 && this.IO1.REMF && this.AD1F && this.IO1.Dunit == unit) {
return 1;
} else if (ioUnit != "2" && this.IO2 && this.IO2.REMF && this.AD2F && this.IO2.Dunit == unit) {
return 2;
} else if (ioUnit != "3" && this.IO3 && this.IO3.REMF && this.AD3F && this.IO3.Dunit == unit) {
return 3;
} else if (ioUnit != "4" && this.IO4 && this.IO4.REMF && this.AD4F && this.IO4.Dunit == unit) {
return 4;
} else {
return 0; // peripheral unit not in use by any other I/O Unit
}
};
/**************************************/
B5500CentralControl.prototype.halt = function() {
/* Halts the processors. Any in-process I/Os are allowed to complete */
@@ -560,11 +627,30 @@ B5500CentralControl.prototype.halt = function() {
B5500CentralControl.prototype.loadComplete = function loadComplete() {
/* Monitors an initial load I/O operation for complete status.
When complete, initiates P1 */
var completed = false; // true if some I/O Unit finished
var that = loadComplete.that; // capture the current closure context
if (!that.CCI08F) {
if (that.CCI08F) { // I/O Unit 1 finished
completed = true;
that.CCI08F = 0;
that.AD1F = 0;
} else if (that.CCI09F) { // I/O Unit 2 finished
completed = true;
that.CCI09F = 0;
that.AD2F = 0;
} else if (that.CCI10F) { // I/O Unit 3 finished
completed = true;
that.CCI10F = 0;
that.AD3F = 0;
} else if (that.CCI11F) { // I/O Unit 4 finished
completed = true;
that.CCI11F = 0;
that.AD4F = 0;
} else { // Nothing finished yet (or there was an error)
that.loadTimer = setTimeout(that.loadComplete, 100);
} else {
}
if (completed) {
that.loadTimer = null;
that.LOFF = 0;
that.P1.C = 0x10; // execute from address @20
@@ -583,14 +669,27 @@ B5500CentralControl.prototype.loadComplete = function loadComplete() {
B5500CentralControl.prototype.load = function() {
/* Initiates a Load operation to start the system */
if ((this.PA && this.PA.busy) || (this.PB && this.PB.busy)) {
if (this.P1 && !this.P1.busy) {
this.clear();
if (this.P1) {
this.LOFF = 1;
if (this.IO1) { // !! not sure about I/O selection here
this.IO1.initiateLoad(this.cardLoadSelect);
this.loadComplete();
}
this.LOFF = 1;
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
this.AD1F = 1;
this.IO1.initiateLoad(this.cardLoadSelect);
this.loadComplete();
} else if (this.IO2 && this.IO2.REMF && !this.AD2F) {
this.AD2F = 1;
this.IO2.initiateLoad(this.cardLoadSelect);
this.loadComplete();
} else if (this.IO3 && this.IO3.REMF && !this.AD3F) {
this.AD3F = 1;
this.IO3.initiateLoad(this.cardLoadSelect);
this.loadComplete();
} else if (this.IO4 && this.IO4.REMF && !this.AD4F) {
this.AD4F = 1;
this.IO4.initiateLoad(this.cardLoadSelect);
this.loadComplete();
} else {
this.CCI04F = 1; // set I/O busy interrupt
}
}
};
@@ -679,12 +778,10 @@ B5500CentralControl.prototype.configureSystem = function() {
this.PB1L = (cfg.PB1L ? 1 : 0);
/*** enable once I/O exists ***
if (cfg.IO1) {this.IO1 = new B5500IOUnit("1", this)};
if (cfg.IO2) {this.IO2 = new B5500IOUnit("2", this)};
if (cfg.IO3) {this.IO3 = new B5500IOUnit("3", this)};
if (cfg.IO4) {this.IO4 = new B5500IOUnit("4", this)};
***/
for (x=0; x<8; x++) {
if (cfg.MemMod[x]) {

293
emulator/B5500IOUnit.js Normal file
View File

@@ -0,0 +1,293 @@
/***********************************************************************
* retro-b5500/emulator B5500IOUnit.js
************************************************************************
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* B5500 Input/Output Unit module.
*
* Instance variables in all caps generally refer to register or flip-flop (FF)
* entities in the processor hardware. See the Burroughs B5500 Reference Manual
* (1021326, May 1967) and B5283 Input/Output Training Manual (1036993, January 1969)
* for details:
* http://bitsavers.org/pdf/burroughs/B5000_5500_5700/1021326_B5500_RefMan_May67.pdf
* http://bitsavers.org/pdf/burroughs/B5000_5500_5700/1036993_B5283_TrainingMan_Jan69.pdf
*
* B5500 word format: 48 bits plus (hidden) parity.
* Bit 0 is high-order, bit 47 is low-order, big-endian character ordering.
* I/O and Result Descriptors have the following general format:
* [0:1] Flag bit (1=descriptor)
* [1:1] (0=descriptor)
* [2:1] Presence bit (1=present and available in memory, 0=absent or unavailable)
* [3:5] Unit designate
* [8:10] Word count (optional, see [23:1])
* [18:1] Memory inhibit bit (1=no data transfer)
* [19:2] (not used by I/O Unit)
* [21:1] Mode bit (0=alpha, 1=binary)
* [22:1] Direction bit (0=forward, 1=reverse for mag tape, 120/132 col for printers)
* [23:1] Word count bit (0=ignore, 1=use word count in [8:10])
* [24:1] I/O bit (0=write, 1=read)
* [25:1] (not used by I/O Unit)
* [26:7] Control and error-reporting bits (depend on unit)
* [33:15] Memory address
*
************************************************************************
* 2012-12-08 P.Kimpel
* Original version, from thin air.
***********************************************************************/
"use strict";
/**************************************/
function B5500IOUnit(ioUnitID, cc) {
/* Constructor for the I/O Unit object */
this.ioUnitID = ioUnitID; // I/O Unit ID ("1", "2", "3", or "4")
this.cc = cc; // Reference back to Central Control module
this.rdAddress = {"1": 0x0C, "2": 0x0D, "3": 0x0E, "4": 0x0F}[ioUnitID];
this.scheduler = null; // Reference to current setTimeout id
this.accessor = { // Memory access control block
requestorID: procID, // Memory requestor ID
addr: 0, // Memory address
word: 0, // 48-bit data word
MAIL: 0, // Truthy if attempt to access @000-@777 in normal state
MPED: 0, // Truthy if memory parity error
MAED: 0 // Truthy if memory address/inhibit error
};
this.schedule.that = this; // Establish context for when called from setTimeout()
// Establish a buffer for the peripheral modules to use during their I/O.
// The size is sufficient for 63 disk sectors, rounded up to the next 8KB.
this.bufferArea = new ArrayBuffer(16384);
this.buffer = new UInt8Array(bufferArea);
this.clear(); // Create and initialize the processor state
}
/**************************************/
B5500IOUnit.timeSlice = 5000; // Standard run() timeslice, about 5ms (we hope)
B5500IOUnit.memCycles = 6; // assume 6 us memory cycle time (the other option was 4 usec)
B5500IOUnit.BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI code
"0", "1", "2", "3", "4", "5", "6", "7", // 00-07, @00-07
"8", "9", "#", "@", "?", ":", ">", "}", // 08-1F, @10-17
"+", "A", "B", "C", "D", "E", "F", "G", // 10-17, @20-27
"H", "I", ".", "[", "&", "(", "<", "~", // 18-1F, @30-37
"|", "J", "K", "L", "M", "N", "O", "P", // 20-27, @40-47
"Q", "R", "$", "*", "-", ")", ";", "{", // 28-2F, @50-57
" ", "/", "S", "T", "U", "V", "W", "X", // 30-37, @60-67
"Y", "Z", ",", "%", "!", "=", "]", "\""]; // 38-3F, @70-77
B5500IOUnit.ANSItoBIC = [ // Index by 8-bit ANSI to get 6-bit BIC (upcased, invalid=>"?")
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
0x30,0x3C,0x3F,0x0A,0x2A,0x3B,0x1C,0x0C,0x1D,0x2D,0x2B,0x10,0x3A,0x2C,0x1A,0x31, // 20-2F
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0D,0x2E,0x1E,0x3D,0x0E,0x0C, // 30-3F
0x0B,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 40-4F
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x1B,0x0C,0x3E,0x0C,0x0C, // 50-5F
0x0C,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 60-6F
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2F,0x20,0x0F,0x1F,0x0C, // 70-7F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 80-8F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 90-9F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // A0-AF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // B0-BF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // C0-CF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // D0-DF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // E0-EF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
/**************************************/
B5500IOUnit.prototype.clear = function() {
/* Initializes (and if necessary, creates) the processor state */
this.W = 0; // Memory buffer register
this.D = 0; // I/O descriptor (control) register
this.clearD(); // clear the D-register exploded fields
this.CC = 0; // Character counter (3 bits)
this.IB = 0; // Input buffer register (6 bits+parity)
this.IR = 0; // Tape read register (6 bits+parity)
this.OB = 0; // Output buffer register (6 bits+parity)
this.WB = 0; // Tape write register (6 bits+parity)
this.LP = 0; // Longitudinal parity register (6 bits+parity)
this.SC = 0; // Sequence counter (4 bits)
this.PC = 0; // Pulse counter register (6 bits, 1MHz rate)
this.AOFF = 0; // Address overflow FF
this.EXNF = 0; // W-contents FF (0=has address, 1=has descriptor)
this.HOLF = 0; // Hold-over FF (for alpha vs. binary card read)
this.LCHF = 0; // Last-character FF (triggers RD construction)
this.LPWF = 0; // (unknown)
this.MANF = 0; // Memory access needed FF
this.MAOF = 0; // Memory access obtained FF
this.OBCF = 0; // (unknown)
this.STRF = 0; // Strobe FF
this.BKWF = 0; // Tape control FF
this.FWDF = 0; // Tape control FF
this.IM1F = 0; // Tape control FF
this.IMFF = 0; // Tape control FF
this.PUCF = 0; // Tape control FF
this.RCNF = 0; // Tape control FF
this.SHOF = 0; // Tape control FF
this.SKFF = 0; // Tape control FF
this.VRCF = 0; // Tape control FF
this.IMCF = 0; // (unknown)
this.RECF = 0; // (unknown)
this.REMF = 1; // Remote FF (0=local, 1=remote and available)
this.busy = 0; // I/O Unit is busy
this.cycleCount = 0; // Current cycle count for this.run()
this.cycleLimit = 0; // Cycle limit for this.run()
this.totalCycles = 0; // Total cycles executed on this I/O Unit
this.ioUnitTime = 0; // Total I/O Unit running time, based on cycles executed
this.ioUnitSlack = 0; // Total I/O Unit throttling delay, milliseconds
};
/**************************************/
B5500IOUnit.prototype.clearD = function() {
/* Clears the D-register and the exploded field variables used internally */
this.D = 0;
this.Dunit = 0; // Unit designate field (5 bits)
this.DwordCount = 0; // Word count field (10 bits)
this.D18F = 0; // Memory inhibit bit (0=transfer, 1=no transfer)
this.D21F = 0; // Mode bit (0=alpha, 1=binary)
this.D22F = 0; // Direction bit (0=forward), etc.
this.D23F = 0; // Word counter bit (0=ignore, 1=use)
this.D24F = 0; // I/O bit (0=write, 1=read)
this.D26F = 0; // Memory address error bit
this.D27F = 0; // Device error bit 1
this.D28F = 0; // Device error bit 2
this.D29F = 0; // Device error bit 3
this.D30F = 0; // Unit not-ready bit
this.D31F = 0; // Memory parity error on descriptor fetch bit
this.D32F = 0; // Unit busy bit
this.Daddress = 0; // Memory transfer address (15 bits)
};
/**************************************/
B5500IOUnit.prototype.fetch = function(addr) {
/* Fetch a word from memory at address "addr" and leave it in the W register.
Returns 1 if a memory access error occurred, 0 if no error */
var acc = this.accessor; // get a local reference to the accessor object
acc.addr = addr;
this.cc.fetch(acc);
this.W = acc.word;
acc.addr = this.S;
acc.MAIL = (this.S < 0x0200 && this.NCSF);
acc.word = this.A;
this.cc.store(acc);
this.cycleCount += B5500IOUnit.memCycles;
if (acc.MAED) {
this.D26F = 1; // memory address error
return 1;
} else if (acc.MPED) {
this.D29F = 1; // memory parity error on data transfer
return 1;
} else {
return 0; // no error
}
};
/**************************************/
B5500IOUnit.prototype.store = function(addr) {
/* Store a word in memory at address "addr" from the W register.
Returns 1 if a memory access error occurred, 0 if no error */
var acc = this.accessor; // get a local reference to the accessor object
acc.addr = addr;
acc.word = this.W;
this.cc.store(acc);
this.cycleCount += B5500IOUnit.memCycles;
if (acc.MAED) {
this.D26F = 1; // memory address error
return 1;
} else {
return 0; // no error
}
};
/**************************************/
B5500IOUnit.prototype.initiate = function() {
/* Initiates an I/O operation on this I/O Unit */
var addr; // memory address
var x;
this.clearD();
this.EXNF = 0;
this.D31F = 1; // preset IOD fetch error condition (cleared if successful)
if (this.fetch(0x08)) { // fetch the IOD address from @10
... return descriptor ...
} else {
this.EXNF = 1;
this.Daddress = addr = this.W % 0x7FFF;
if (this.fetch(addr)) { // fetch the IOD from that address
... return descriptor ...
} else {
this.D31F = 0; // reset the IOD-fetch error condition
this.D = x = this.W; // explode the D-register into its fields
this.Dunit = this.cc.fieldIsolate(x, 3, 5);
this.DwordCount = this.cc.fieldIsolate(x, 8, 10);
x = x % 0x40000000;
this.D18F = (x >>> 29) & 1;
this.D21F = (x >>> 26) & 1;
this.D22F = (x >>> 25) & 1;
this.D23F = (x >>> 24) & 1;
this.D24F = (x >>> 23) & 1;
this.Daddress = x % 0x7FFF;
if (this.cc.testUnitBusy(this.ioUnitID, this.Dunit)) {
this.D32F = 1; // set unit busy error
... return descriptor ...
} else if (!this.cc.testUnitReady(this.Dunit)) {
this.D30F = 1; // set unit not-ready error
... return descriptor ...
} else {
}
}
}
};
/**************************************/
B5500IOUnit.prototype.run = function() {
};
/**************************************/
B5500IOUnit.prototype.schedule = function schedule() {
/* Schedules the I/O Unit run time and attempts to throttle performance
to approximate that of a real B5500. Well, at least we hope this will run
fast enough that the performance will need to be throttled. It establishes
a timeslice in terms of a number of I/O Unit "cycles" of 1 microsecond
each and calls run() to execute at most that number of cycles. run()
counts up cycles until it reaches this limit or some terminating event
(such as a halt), then exits back here. If the I/O Unit remains active,
this routine will reschedule itself for an appropriate later time, thereby
throttling the performance and allowing other modules a chance at the
Javascript execution thread. */
var delayTime;
var that = schedule.that;
that.scheduler = null;
that.cycleLimit = B5500IOUnit.timeSlice;
that.cycleCount = 0;
that.run();
that.totalCycles += that.cycleCount
that.ioUnitTime += that.cycleCount;
if (that.busy) {
delayTime = that.ioUnitTime/1000 - new Date().getTime();
that.ioUnitSlack += delayTime;
that.scheduler = setTimeout(that.schedule, (delayTime < 0 ? 1 : delayTime));
}
};

View File

@@ -4,6 +4,8 @@
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
* Licensed under the MIT License, see
* http://www.opensource.org/licenses/mit-license.php
************************************************************************
* B5500 Processor (CPU) module.
*
* Instance variables in all caps generally refer to register or flip-flop (FF)
* entities in the processor hardware. See the Burroughs B5500 Reference Manual
@@ -14,15 +16,13 @@
*
* B5500 word format: 48 bits plus (hidden) parity.
* Bit 0 is high-order, bit 47 is low-order, big-endian character ordering.
* [0:1] Flag bit (1=descriptor)
* [0:1] Flag bit (1=control word or descriptor)
* [1:1] Mantissa sign bit (1=negative)
* [2:1] Exponent sign bit (1=negative)
* [3:6] Exponent (power of 8, signed-magnitude)
* [9:39] Mantissa (signed-magnitude, scaling point after bit 47)
*
************************************************************************
* B5500 Processor (CPU) module.
************************************************************************
* 2012-06-03 P.Kimpel
* Original version, from thin air.
***********************************************************************/
@@ -3559,6 +3559,9 @@ B5500Processor.prototype.run = function() {
break;
case 0x14: // 2431: TUS=interrogate peripheral status
this.adjustAEmpty();
this.A = this.cc.interrogateUnitStatus();
this.AROF = 1;
break;
case 0x21: // 4131: BBW=branch backward unconditional
@@ -3581,6 +3584,9 @@ B5500Processor.prototype.run = function() {
break;
case 0x34: // 6431: TIO=interrogate I/O channel
this.adjustAEmpty();
this.A = this.cc.interrogateIOChannel();
this.AROF = 1;
break;
case 0x38: // 7031: FBS=stack search for flag

View File

@@ -0,0 +1,73 @@
<html>
<body>
<script>
var c;
var d;
var x;
var y;
var BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI code
"0", "1", "2", "3", "4", "5", "6", "7", // 00-07, @00-07
"8", "9", "#", "@", "?", ":", ">", "}", // 08-1F, @10-17
"+", "A", "B", "C", "D", "E", "F", "G", // 10-17, @20-27
"H", "I", ".", "[", "&", "(", "<", "~", // 18-1F, @30-37
"|", "J", "K", "L", "M", "N", "O", "P", // 20-27, @40-47
"Q", "R", "$", "*", "-", ")", ";", "{", // 28-2F, @50-57
" ", "/", "S", "T", "U", "V", "W", "X", // 30-37, @60-67
"Y", "Z", ",", "%", "!", "=", "]", "\""]; // 38-3F, @70-77
var ANSItoBIC = [ // Index by 8-bit ANSI to get 6-bit BIC (upcased, invalid=>"?")
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
0x30,0x3C,0x3F,0x0A,0x2A,0x3B,0x1C,0x0C,0x1D,0x2D,0x2B,0x10,0x3A,0x2C,0x1A,0x31, // 20-2F
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0D,0x2E,0x1E,0x3D,0x0E,0x0C, // 30-3F
0x0B,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 40-4F
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x1B,0x0C,0x3E,0x0C,0x0C, // 50-5F
0x0C,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 60-6F
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2F,0x20,0x0F,0x1F,0x0C, // 70-7F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 80-8F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 90-9F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // A0-AF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // B0-BF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // C0-CF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // D0-DF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // E0-EF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
function html(c) {
switch(c) {
case "<": return("&lt;");
case ">": return("&gt;");
case '"': return("&quot;");
case "&": return("&amp;");
default: return c;
}
}
document.write("<h3>Test BIC to ANSI</h3>");
for (x=0; x<64; x++) {
c = BICtoANSI[x];
y = ANSItoBIC[c.charCodeAt(0)];
document.write("[" + x + "=" + y + "] = " + html(c) + "<br>");
if (x != y) {
alert("BICtoANSI mismatch: " + x + "!=" + y + ", " + html(c));
}
}
document.write("<h3>Test ANSI to BIC</h3>");
for (x=0; x<256; x++) {
y = ANSItoBIC[x];
d = String.fromCharCode(x);
c = BICtoANSI[y];
y = c.charCodeAt(0);
document.write("[" + x + "=" + y + "] : " + html(c) + "=" + html(d) + "<br>");
if (y != 63 && c != d.toUpperCase()) {
alert("ANSItoBIC mismatch: " + x + "!=" + y + ", " + html(c));
}
}
</script>
</body>
</html>

View File

@@ -10,6 +10,7 @@
<script src="../emulator/B5500SystemConfiguration.js"></script>
<script src="../emulator/B5500CentralControl.js"></script>
<script src="../emulator/B5500Processor.js"></script>
<script src="../emulator/B5500IOUnit.js"></script>
<script>
"use strict";

View File

@@ -10,6 +10,7 @@
<script src="../emulator/B5500SystemConfiguration.js"></script>
<script src="../emulator/B5500CentralControl.js"></script>
<script src="../emulator/B5500Processor.js"></script>
<script src="../emulator/B5500IOUnit.js"></script>
<script>
"use strict";

View File

@@ -10,6 +10,7 @@
<script src="../emulator/B5500SystemConfiguration.js"></script>
<script src="../emulator/B5500CentralControl.js"></script>
<script src="../emulator/B5500Processor.js"></script>
<script src="../emulator/B5500IOUnit.js"></script>
<script>
"use strict";

View File

@@ -10,6 +10,7 @@
<script src="../emulator/B5500SystemConfiguration.js"></script>
<script src="../emulator/B5500CentralControl.js"></script>
<script src="../emulator/B5500Processor.js"></script>
<script src="../emulator/B5500IOUnit.js"></script>
<script>
"use strict";