1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-02-12 11:17:29 +00:00

Commit DCMCP transcription as of 2012-06-30; commit minor tweaks to

processor panel prototype; commit Nigel's preliminary changes to 
Processor module
This commit is contained in:
paul
2012-06-30 13:52:31 +00:00
parent bf3a48c99a
commit 0e0b288909
4 changed files with 240 additions and 87 deletions

View File

@@ -5157,3 +5157,148 @@ BEGIN 06096600
TEMPDISK:=1; 06100200
GO TO MVE; 06100300
END; 06100400
I:=MV[I+2].LINK; 06100500
END; 06100600
% WILL NOW RECONFIGURE THE AVAILABLE TABLE 06100700
UT[AV]:=HI&(UT[AV].ASIZE+UT[AV+I].ASIZE)[2:28:20]; 06100800
MOVE(S-AV,P([UT[AV+2]],DUP),NOT 0 INX P(XCH)); 06100900
C:=(S:=S-1)-1; FOR I:=C STEP -1 UNTIL D DO 06101000
IF P(UT[I].ASIZE,DUP)>USE THEN USE:=P ELSE P(DEL); 06101100
U[EU]:=P(DUP,LOD,DUP)&USE[1:28:20]&(P(XCH).NUMENT-1)[TONUMENT]; 06101200
EUNOTSQUASHED:=FALSE; 06101300
IF NOT SQALL THEN 06101400
BEGIN 06101500
IF P(SQSIZE,DUP)!0 AND P(XCH) LEQ USE THEN CELL:=1 06101600
ELSE IF P(EUS[EU-1],DSIZE,DUP)!0 AND P(XCH) LEQ USE 06101700
THEN ELSE GO TO ENDMVE; 06101800
P(DEL); GO STOPSQ; 06101900
END; 06102000
ENDMVE: 06102100
END FIXING AND MOVING; 06102200
$ SET OMIT = NOT SHAREDISK 06102220
P(0,0,0,0,0,0,0,0,0,0); 06102500
P(0,0,0,0,0,0,0,0,0,0); 06102600
P(0,0,0,0,0,0,0,0,0,0); 06102700
P(0,0,0,0,0,0,0,0,0); 06102800
P(.DISKSQUASH,DUP,M[(P)]); % PRTADDR,PRTVALUE 06102900
$ SET OMIT = NOT SHAREDISK 06103000
SCANMESSAGE; 06103300
$ SET OMIT = SHAREDISK 06103400
LOCKDIRECTORY; 06103500
$ POP OMIT 06103600
SLEEP([TOGLE],USERDISKMASK); LOCKTOG(USERDISKMASK); 06103700
HALT; % STOP NORMAL STATE PROCESSING WHILE SQUASHING 06103800
A4:=SPACE(30); 06103900
$ SET OMIT = NOT SHAREDISK 06104000
FIXARRAY(DIR,A1,480); FIXARRAY(MV,A2,150); 06107200
A3:=SPACE(900); 06107300
IOD:=@140000100000000&(A3-1)[CTC]; 06107400
IF NOT SQALL THEN FOR EU:=1 STEP 1 UNTIL NEUP.[FF] DO 06107900
IF (CELL:=(P(SQSIZE,DUP)!0 AND P(XCH) LEQ U[EU].[1:20])) 06108000
THEN BEGIN P(2); SQUASHMESS; GO STOPIT END; 06108100
FOR EU:=1 STEP 1 UNTIL NEUP.[FF] DO % 06108200
IF NOT (E:=U[EU]).EUNP THEN % NOT A DUMMY EU 06108300
IF EUS[EU-1] OR SQALL OR SQSIZE!0 THEN % SQUASH THIS EU 06108400
BEGIN 06108500
EUNOTSQUASHED:=TRUE; 06108600
IF NOT SQALL THEN % CHECK IF SQUASH IS NECESSARY 06108700
IF (P(EUS[EU-1].DSIZE,DUP) LEQ E.[1:20] AND P(XCH)!0) 06108800
THEN BEGIN P(3); SQUASHMESS; GO STOPIT END; 06108900
CELL:=0&1[CTF]; 06109000
P(0); SQUASHMESS; 06109100
D:=(I:=E.STARTWRD) MOD 30; 06109200
AVSIZE:=30-(S:=(E AND NUMENTM)+D) MOD 30+S; 06109300
FIXARRAY(UT,R,AVSIZE); 06109400
DISKAV:=I DIV 30+USERDISKBOTTOM; 06109500
$ SET OMIT = NOT SHAREDISK 06109600
DISKWAIT(-R,AVSIZE,DISKAV); 06110300
AGAIN: SUM:=USE:=0; 06110400
FOR I:=S-3 STEP -1 UNTIL D DO 06110500
BEGIN STOPCK; 06110600
IF (UT[I+1]<0)=PASSTWO THEN % NOT CHECKED THIS PASS 06110700
IF ((X1:=UT[I].ASIZE)+(X2:=UT[I+1].ASIZE)) GEQ SUM 06110800
THEN IF (X3:=(((X4:=UT[I+1].DEND)-1)-UT[I+1].ASIZE)- 06110900
X5:=(UT[I].DEND-1)) LEQ FACTOR THEN IF MINSIZE LEQ X2 06111000
THEN IF MINSIZE LEQ X1 THEN 06111100
BEGIN 06111200
SQIT: USE:=X3; AV:=I; 06111300
SUM:=X1-X2; % SUM OF CURRENT AVAILABLE AREAS 06111400
HI:=X4; LO:=X5; 06111500
END ELSE IF I!0 THEN % LOOK AHEAD TO NEXT AREA 06111600
IF ((MINSIZE LEQ UT[I-1].ASIZE) AND (((X5-X1)- 06111700
UT[I-1].DEND-1) LEQ FACTOR)) THEN GO SQIT; 06111800
END; 06111900
IF USE!0 THEN % FUOND A POSSIBLE SQUASH SITUATION 06112000
BEGIN 06112100
IF INUSEOK THEN MOVEANDFIX; 06112200
GO AGAIN; 06112300
END ELSE % TIME TO WRAP IT UP FOR THIS EU UNLESS.... 06112400
IF CONFLICT THEN IF NOT PASSTWO THEN % ..CONFLICTS EXIST 06112500
BEGIN 06112600
PASSTWO:=TRUE; 06112700
GO AGAIN; 06112800
END ELSE 06112900
BEGIN % CLEAN-UP PASS AFTER CONFLICTS RESOLVED. 06113000
PASSTWO:=CONFLICTS:=0; 06113100
GO AGAIN; 06113200
END; 06113300
STOPSQ: FOR I:=D STEP 1 UNTIL S DO UT[I]:=ABS(P(DUP.LOD)&0[2:2:1]); 06113400
IF NOT EUNOTSQUASHED THEN 06113500
$ SET OMIT = NOT SHAREDISK 06113600
DISKWAIT( R,AVSIZ,DISKAV); 06114300
FORGETSPACE(R); 06114400
P(1); SQUASHMESS; 06114500
STOPIT: IF STOP THEN GO OUT; % STOPCK GOT US HERE 06114600
END EU LOOP; 06114700
OUT: 06114800
FORGETSPACE(A1); FORGETSPACE(A2); FORGETSPACE(A3); 06114900
$ SET OMIT = NOT SHAREDISK 06115000
SDXIT: 06115500
FORGETSPACE(A4); FORGETSPACE(A5); 06115600
CELL:=PRTVALUE; 06115700
STREAM(A:=BUFF.[15:15]-1); DS:=13 LIT" END SQUASH.~"; 06115800
SPOUT(BUFF.[15:15]-1); 06115900
$ SET OMIT = SHAREDISK 06115990
UNLOCKDIRECTORY; 06116000
$ POP OMIT 06116010
UNLOCKTOG(USERDISKMASK); 06116100
NOPROCESSTOG:=NOPROCESSTOG-1; 06116200
KILL([MSCW]); 06116300
END SQUASHING; 06116400
PROCEDURE CHANGEABORT(X); VALUE X; REAL X; FORWARD;% 06179000
REAL LOOKQ; 06179200
PROCEDURE SIGNOFF(VECTOR,FILEBLOCK,PKT); 06180000
VALUE VECTOR,FILEBLOCK,PKT; 06181000
ARRAY VECTOR[*],FILEBLOCK[*];% 06182000
REAL PKT; 06182100
BEGIN ARRAY NAME LOG; 06183000
INTEGER N,L,I,J,TIMEX;% 06184000
INTEGER MIX; 06184100
$ SET OMIT = NOT STATISTICS 06184199
REAL TIMEAX,T,A,Q,ESED; 06185000
$ SET OMIT = NOT(PACKETS) 06185099
REAL UNITNO; 06185100
INTEGER ARRAY PM[*]; 06185105
$ POP OMIT 06185110
$ SET OMIT = NOT(WORKSET AND WORKSETMONITOR) 06185111
REAL DD; 06185112
$ POP OMIT % WORKSET AND WORKSETMONITOR 06185113
SUBROUTINE TIMEIT;% 06186000
BEGIN CHANGEABORT(0);% 06187000
WHILE (NT2:=XCLOCK+P(RTR)) GEQ WITCHINGHOUR DO 06188000
MIDNIGHT; 06188100
LOG[TIMEAX+2] ~ NT2;% 06189000
$ SET OMIT = NOT(STATISTICS) 06189099
STOPLOG(P1MIX,0); 06190000
MIX~P1MIX; P1MIX~0; 06190100
IDLETIME;% 06191000
OLDIDLETIME ~ (LOG[TIMEX] ~ VECTOR[3]+% 06192000
PROCTIME[MIX])+OLDIDLETIME; 06193000
PROCTIME[MIX] ~ -VECTOR[3];% %127-06193500
LOG[TIMEX+1]~VECTOR[4]+IOTIME[MIX]; 06194000
$ SET OMIT = NOT WORKSET 06194890
LOG[TIMEX+2] ~ OLAYTIME[MIX]; %710-06194900
$ SET OMIT = WORKSET%710-06194990
$ SET OMIT = NOT(WORKSET AND WORKSETMONITOR) 06195090
IF WKSETMONITOR AND (DD=0) THEN 06195095
BEGIN 06195100

View File

@@ -2,17 +2,16 @@
* retro-b5500/emulator B5500Processor.js
************************************************************************
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php
* MIT Licensed http://www.opensource.org/licenses/mit-license.php
************************************************************************
* JavaScript object definition for the B5500 Processor (CPU) module.
* B5500 Processor (CPU) module.
************************************************************************
* 2012-06-03 P.Kimpel
* Original version, from thin air.
***********************************************************************/
"use strict";
/**************************************/
function B5500Processor() {
/* Constructor for the Processor module object */
this.scheduler = null; // Reference to current setTimeout id
this.accessor = { // Memory access control block
@@ -20,24 +19,21 @@ function B5500Processor() {
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
MAED: 0 // Truthy if memory address/inhibit error
};
this.schedule.that = this; // Establish context for when called from setTimeout()
this.clear(); // Create and initialize the processor state
}
/**************************************/
B5500Processor.timeSlice = 5000; // Standard run() timeslice, about 5ms (we hope)
/**************************************/
B5500Processor.prototype.clear = function() {
/* Initializes the processor state */
/* Initializes the processor state, FF is FlipFlop (in modern parlance: boolean flag) */
this.A = 0; // Top-of-stack register 1
this.AROF = 0; // A contents valid
this.B = 0; // Top-of-stack register 2
this.A = 0; // Top-of-stack register A
this.AROF = 0; // A Register Occupied Flip-flop
this.B = 0; // Top-of-stack register B
this.BROF = 0; // B contents valid
this.C = 0; // Current program instruction word address
this.CCCF = 0; // Clock-count control FF (maintenance only)
@@ -79,15 +75,15 @@ B5500Processor.prototype.clear = function() {
this.procTime = 0; // Current processor running time, based on cycles executed
this.scheduleSlack = 0; // Total processor throttling delay, milliseconds
this.busy = false; // Proessor is running, not idle or halted
}
};
/**************************************/
B5500Processor.prototype.access = function(eValue) {
B5500Processor.prototype.access = function(cc, eValue) {
/* Access memory based on the E register. If the processor is in normal
state, it cannot access the first 512 words of memory => invalid address */
this.E = eValue; // Just to show the world what's happening
this.accessor.MAIL = (addr < 0x0200 && this.NCSF);
this.accessor.MAIL = (this.addr < 0x0200 && this.NCSF);
switch (eValue) {
case 0x02: // A = [S]
this.accessor.addr = this.S;
@@ -145,11 +141,11 @@ B5500Processor.prototype.access = function(eValue) {
this.PROF = 1;
break;
default:
throw "Invalid E register value: " + eReg.toString(2);
throw "Invalid E register value: " + this.E.toString(2);
break;
}
this.cycleCount += 6; // assume 6 us memory cycle time
this.cycleCount += 6; // assume 6 us memory cycle time (the other option was 4 usec)
if (this.accessor.MAED) {
this.I |= 0x02; // set I02F - memory address/inhibit error
if (this.NCSF || this !== cc.P1) {
@@ -165,16 +161,18 @@ B5500Processor.prototype.access = function(eValue) {
this.busy = false; // P1 memory parity in control state stops the proc
}
}
}
};
/**************************************/
B5500Processor.prototype.adjustAEmpty = function() {
/* Adjusts the A register so that it is empty pushing the prior
contents of A into B and B into memory, as necessary. */
B5500Processor.prototype.adjustAEmpty = function(cc) {
/*
Adjusts the A register so that it is empty pushing the prior
contents of A into B and B into memory, as necessary.
*/
if (this.AROF} {
if (this.AROF) {
if (this.BROF) {
if ((this.S >>> 6) == this.R || !this.NCSF) {
if ((this.S >>> 6) === this.R || !this.NCSF) {
this.I |= 0x04; // set I03F: stack overflow
cc.signalInterrupt();
} else {
@@ -187,7 +185,7 @@ B5500Processor.prototype.adjustAEmpty = function() {
this.BROF = 1;
// else we're done -- A is already empty
}
}
};
/**************************************/
B5500Processor.prototype.adjustAFull = function() {
@@ -205,15 +203,15 @@ B5500Processor.prototype.adjustAFull = function() {
}
// else we're done -- A is already full
}
}
};
/**************************************/
B5500Processor.prototype.adjustBEmpty = function() {
B5500Processor.prototype.adjustBEmpty = function(cc) {
/* Adjusts the B register so that it is empty pushing the prior
contents of B into memory, as necessary. */
if (this.BROF) {
if ((this.S >>> 6) = this.R || !this.NCSF) {
if ((this.S >>> 6) === this.R || !this.NCSF) {
this.I |= 0x04; // set I03F: stack overflow
cc.signalInterrupt();
} else {
@@ -222,7 +220,7 @@ B5500Processor.prototype.adjustBEmpty = function() {
}
// else we're done -- B is already empty
}
}
};
/**************************************/
B5500Processor.prototype.adjustBFull = function() {
@@ -234,10 +232,10 @@ B5500Processor.prototype.adjustBFull = function() {
this.S--;
// else we're done -- B is already full
}
}
};
/**************************************/
B5500Processor.prototype.exchangeTOS() {
B5500Processor.prototype.exchangeTOS = function() {
/* Exchanges the two top-of-stack values */
var temp;
@@ -269,10 +267,10 @@ B5500Processor.prototype.exchangeTOS() {
this.S--;
}
}
}
};
/**************************************/
B5500Processor.storeForInterrupt = function(forTest) {
B5500Processor.storeForInterrupt = function(cc, forTest) {
/* Implements the 3011=SFI operator and the parts of SFT that are
common to it. "forTest" implies use from SFT */
var forced = this.Q & 0x0040; // Q07F: Hardware-induced SFI syllable
@@ -296,9 +294,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
this.S++;
this.access(0x0B); // [S] = B
}
this.B = this.X + // store CM loop-control word
saveAROF * 0x200000000000 +
0xC00000000000;
this.B = this.X + saveAROF * 0x200000000000 + 0xC00000000000; // store CM loop-control word
this.S++;
this.access(0x0B); // [S] = B
} else {
@@ -355,7 +351,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
this.TM = 0;
this.MROF = 0;
this.MWOF = 0;
}
}
this.M = (this.R*64) + 0x08; // store initiate word at R+@10
this.access(0x0D); // [M] = B
@@ -377,7 +373,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
cc.HP2F = 1;
cc.P2BF = 0;
if (cc.P2.scheduler) {
cancelTimeout(cc.P2.scheduler);
cc.cancelTimeout(cc.P2.scheduler);
cc.P2.scheduler = null;
}
}
@@ -401,12 +397,12 @@ B5500Processor.storeForInterrupt = function(forTest) {
cc.HP2F = 1;
cc.P2BF = 0;
if (cc.P2.scheduler) {
cancelTimeout(cc.P2.scheduler);
cc.cancelTimeout(cc.P2.scheduler);
cc.P2.scheduler = null;
}
}
}
}
};
/**************************************/
B5500Processor.initiate = function(forTest) {
@@ -503,10 +499,10 @@ B5500Processor.initiate = function(forTest) {
this.NCSF = 1;
this.busy = true;
}
}
};
/**************************************/
B5500Processor.prototype.computeRelativeAddr(offset, cEnabled) {
B5500Processor.prototype.computeRelativeAddr = function(offset, cEnabled) {
/* Computes an absolute memory address from the relative "offset" parameter
and leaves it in the M register. See Table 6-1 in the B5500 Reference
Manual. "cEnable" determines whether C-relative addressing is permitted.
@@ -550,10 +546,10 @@ B5500Processor.prototype.computeRelativeAddr(offset, cEnabled) {
} else {
this.M = (this.R*64) + (offset & 0x3FF);
}
}
};
/**************************************/
B5500Processor.prototype.indexDescriptor() {
B5500Processor.prototype.indexDescriptor = function() {
/* Indexes a descriptor and, if successful leaves the indexed value in
the A register. Returns true if an interrupt is set and the syllable is
to be exited */
@@ -575,7 +571,7 @@ B5500Processor.prototype.indexDescriptor() {
do {
xo = xm % 8;
xm = (xm - xo)/8;
this.cycleCount++
this.cycleCount++;
} while (--xe > 0);
if (xo >= 4) {
xm++;
@@ -618,21 +614,21 @@ B5500Processor.prototype.indexDescriptor() {
}
return interrupted;
}
};
/**************************************/
B5500Processor.prototype.buildMSCW();
B5500Processor.prototype.buildMSCW = function() {
/* Return a Mark Stack Control Word from current processor state */
return this.F * 0x8000 +
this.SALF * 0x40000000 +
this.MSFF * 0x80000000 +
this.R * 0x200000000 +
0xC00000000000;
}
return this.F * 0x8000 +
this.SALF * 0x40000000 +
this.MSFF * 0x80000000 +
this.R * 0x200000000 +
0xC00000000000;
};
/**************************************/
B5500Processor.prototype.enterSubroutine(descriptorCall) {
B5500Processor.prototype.enterSubroutine = function(cc, descriptorCall) {
/* Enters a subroutine via the present program descriptor in A as part
of an OPDC or DESC syllable. Also handles accidental entry */
var aw = this.A; // local copy of word in A reg
@@ -690,13 +686,15 @@ B5500Processor.prototype.enterSubroutine(descriptorCall) {
this.S = 0;
}
}
}
};
/**************************************/
B5500Processor.prototype.operandCall() {
/* OPDC, the moral equivalent of "load accumulator" on lesser
machines. Assumes the syllable has already loaded a word into A.
See Figures 6-1, 6-3, and 6-4 in the B5500 Reference Manual */
B5500Processor.prototype.operandCall = function() {
/*
OPDC, the moral equivalent of "load accumulator" on lesser
machines. Assumes the syllable has already loaded a word into A.
See Figures 6-1, 6-3, and 6-4 in the B5500 Reference Manual
*/
var aw; // local copy of A reg value
var interrupted = false; // interrupt occurred
@@ -749,14 +747,16 @@ B5500Processor.prototype.operandCall() {
this.SALF = 1;
this.VARF = 0;
}
}
};
/**************************************/
B5500Processor.prototype.descriptorCall() {
/* DESC, the moral equivalent of "load address" on lesser
machines. Assumes the syllable has already loaded a word into A, and
that the address of that word is in M.
See Figures 6-2, 6-3, and 6-4 in the B5500 Reference Manual */
B5500Processor.prototype.descriptorCall = function() {
/*
DESC, the moral equivalent of "load address" on lesser
machines. Assumes the syllable has already loaded a word into A, and
that the address of that word is in M.
See Figures 6-2, 6-3, and 6-4 in the B5500 Reference Manual
*/
var aw = this.A; // local copy of A reg value
var interrupted = false; // interrupt occurred
@@ -804,15 +804,17 @@ B5500Processor.prototype.descriptorCall() {
this.SALF = 1;
this.VARF = 0;
}
}
};
/**************************************/
B5500Processor.prototype.run = function() {
/* Instruction execution driver for the B5500 processor. This function is
an artifact of the emulator design and does not represent any physical
process or state of the processor. This routine assumes the registers are
set up, and in particular a syllable is in T with TROF set. It will run
until cycleCount >= cycleLimit or !this.busy */
/*
Instruction execution driver for the B5500 processor. This function is
an artifact of the emulator design and does not represent any physical
process or state of the processor. This routine assumes the registers are
set up, and in particular a syllable is in T with TROF set. It will run
until cycleCount >= cycleLimit or !this.busy
*/
var opcode;
var t1;
var t2;
@@ -1513,20 +1515,22 @@ B5500Processor.prototype.run = function() {
}
}
} while ((this.cycleCount += 2) < this.cycleLimit && this.busy);
}
};
/**************************************/
B5500Processor.prototype.schedule = function schedule() {
/* Schedules the processor 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 processor "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 processor 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. */
/*
Schedules the processor 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 processor "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 processor 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;
@@ -1543,4 +1547,4 @@ B5500Processor.prototype.schedule = function schedule() {
that.scheduleSlack += delayTime;
that.scheduler = setTimeout(that.schedule, (delayTime < 0 ? 0 : delayTime));
}
}
};

View File

@@ -29,7 +29,7 @@ function B5500DDLamp(x, y) {
/**************************************/
B5500DDLamp.onColor = "#FF9933";
B5500DDLamp.onColor = "#FF9900";
B5500DDLamp.offColor = "#999999";
/**************************************/
@@ -193,7 +193,7 @@ B5500DDRegister.prototype.update = function(value) {
var bit;
var mask = value % 0x1000000000000;
while (mask) {
while (bitNr < this.bits) {
bitNr++;
bit = mask % 2;
this.lamps[bitNr].element.style.backgroundColor = (bit ? B5500DDLamp.onColor : B5500DDLamp.offColor);

View File

@@ -16,17 +16,19 @@ var nextRefresh = 0;
var panel;
var refreshTimer = null;
var totalDelay = 0;
var totalIdle = 0;
var totalTime = 0;
var updateDisplay = function updateDisplay() {
/* Schedules itself to update the display on a periodic basis. */
var thisTime = new Date().getTime();
var delta;
var idle;
var meter = document.getElementById("idleMeter");
var that = updateDisplay.that;
panel.X.update(Math.random()*0x8000000000);
panel.A.update(Math.random()*0x1000000000000);
panel.A.update((Math.random()/65536+Math.random())*0x1000000000000);
panel.B.update(Math.random()*0x1000000000000);
panel.P.update(Math.random()*0x1000000000000);
panel.J.update(Math.random()*0x10);
@@ -58,7 +60,9 @@ var updateDisplay = function updateDisplay() {
refreshTimer = setTimeout(updateDisplay, (delta < 0 ? (delta=0) : delta));
totalTime = (totalTime*99 + displayRefreshPeriod)/100;
totalDelay = (totalDelay*99 + delta)/100;
meter.value = (totalDelay/totalTime*100).toFixed(1) + "%";
idle = nextRefresh-new Date().getTime();
totalIdle = (totalIdle*99 + (idle < 0 ? 0 : idle))/100;
meter.value = (totalIdle/totalTime*100).toFixed(1) + "%";
};
window.onload = function() {