Procedures
Run:
PUBLIC
PROC [fixture: Fixture] = {
None of the routines are parameterized by the chip number!
InitSystem[];
Reset[];
SetClock[NARROW[RProperties.GetProp[fixture.properties, $Clock], REF INT]^];
IF hardwareEnabled THEN FindTZero[];
FOR chipIndex:
CARDINAL
IN [0..fixture.size)
DO
chip: Chip ← fixture[chipIndex];
FOR ch: ChannelIndex
IN ChannelIndex
DO
tg: TimingGroup ← chip.formatTiming[ch];
IF tg#
NIL
THEN {
IF hardwareEnabled
THEN
SELECT tg.format
FROM
NRZ => NRZMode[ch, tg.delay];
RZ => RZMode[ch, tg.delay, tg.width];
RO => ROMode[ch, tg.delay, tg.width];
RT => RTMode[ch, tg.delay, tg.width];
RC => RCMode[ch, tg.delay, tg.width];
ENDCASE => ERROR;
SetAnalogSample[ch, tg.variableThreshold];
SetTTLLevels[ch, tg.variableLevels];
};
ENDLOOP;
FOR vi:
CARD
IN [0..chip.firstFreeVector)
DO
RamWrite[VRam, vi, chip.vectors[vi].elements[0], chip.vectors[vi].elements[1], chip.vectors[vi].elements[2], chip.vectors[vi].elements[3]];
ENDLOOP;
FOR imi: InhibitMaskIndex
IN InhibitMaskIndex
DO
data0, data1, data2, data3: Byte10 ← 0;
FOR ch: ChannelIndex
IN ChannelIndex
DO
SELECT ch
FROM
IN [0..6) => {
data0 ← BitOps.IBIW[chip.inhibitMask[imi][ch].mask, data0, ch, 6];
data2 ← BitOps.IBIW[chip.inhibitMask[imi][ch].inhibit, data2, ch, 6];
};
IN [6..16) => {
data1 ← BitOps.IBIW[chip.inhibitMask[imi][ch].mask, data1, ch-6, 10];
data3 ← BitOps.IBIW[chip.inhibitMask[imi][ch].inhibit, data3, ch-6, 10];
};
ENDCASE => ERROR;
ENDLOOP;
RamWrite[CRam, imi, data0, data1, data2, data3];
ENDLOOP;
CBusWrite[writeEndAdd, chip.matchAddress];
CBusWrite[writeLoopAdd, chip.targetAddress];
ENDLOOP;
StartCtl[TRUE, TRUE, FALSE];
};
InitSystem:
PROC ~ {
IF gDebug THEN TerminalIO.PutRope["\nInit\n"];
InitGPIBDevices[];
SetRefDelayAbs[0];
CBusWrite[clkCtl, 0];
gClockCtl ← 0;
SetClock[100];
};
Reset:
PROC ~ {
IF gDebug THEN TerminalIO.PutRope["Reset\n"];
StartCtl[FALSE, FALSE, FALSE];
CBusWrite[writeLoopAdd, 0];
CBusWrite[writeEndAdd, 0];
CBusWrite[writeExtRamCtl, 0];
StartCtl[FALSE, FALSE, TRUE];
StartCtl[FALSE, FALSE, FALSE];
};
FindTZero:
PROC ~ {
In RZ mode force the output of the pulse generator high so that only the transitions resulting from changes in the data pipeline are observed. Skew RefCk to measure the time when the data transition occurs. Measure both rising and falling edges and call the greater of the two times the beginning of the cycle.
biggest: ChannelIndex ← 0;
new: Ns ← 0;
gCycOffset ← 0;
ClearAllPE[];
SetDataPattern[p10];
FOR ch: ChannelIndex
IN ChannelIndex
DO
SetFormat[ch, RZ];
ForcePulseHigh[ch];
new ← MAX[FindOutputEdge[ch, Even, Up], FindOutputEdge[ch, Odd, Down]];
IF new>gCycOffset THEN {gCycOffset ← new; biggest ← ch};
ENDLOOP;
TerminalIO.PutF["Cycle Start Offset = %g, chan: %g\n", IO.int[gCycOffset], IO.int[biggest]];
};
NRZMode:
PROC [ch: ChannelIndex, delay: Delay] ~ {
dhc, whc: HalfClocks ← 0;
dis, wis: InvStages ← 0;
delayFix: NAT ← 0;
TerminalIO.PutF["Chan: %g, NRZ, Delay: %g\n", IO.int[ch], IO.int[delay]];
[dhc, dis] ← CalibrateDL[ch, Delay, delay];
[whc, wis] ← CalibrateDL[ch, Width, delay+20]; --doesn't matter how wide
MakePulse[ch, NRZ, dhc, dis, whc, wis];
DO
WHILE HoneEdge[ch, Leading, Even, Up, delay, p10]
DO
IF (delayFix ← delayFix+1) > 7 THEN ERROR;
[dhc, dis] ← CalibrateDL[ch, Delay, delay-delayFix];
MakePulse[ch, NRZ, dhc, dis, whc, wis];
ENDLOOP;
IF HoneEdge[ch, Leading, Odd, Up, delay, p01]
THEN {
IF (delayFix ← delayFix+1) > 7 THEN ERROR;
[dhc, dis] ← CalibrateDL[ch, Delay, delay-delayFix];
MakePulse[ch, NRZ, dhc, dis, whc, wis];
LOOP;
};
EXIT;
ENDLOOP;
SetDataPattern[p10]; --Display the result
SetRefDelay[0];
};
RZMode:
PROC [ch: ChannelIndex, delay: Delay, width: Width] ~ {
dhc, whc: HalfClocks ← 0;
dis, wis: InvStages ← 0;
delayFix, widthFix: NAT ← 0;
TerminalIO.PutF["Chan: %g, RZ, Delay: %g, Width: %g\n", IO.int[ch], IO.int[delay], IO.int[width]];
[dhc, dis] ← CalibrateDL[ch, Delay, delay];
[whc, wis] ← CalibrateDL[ch, Width, delay+width];
MakePulse[ch, RZ, dhc, dis, whc, wis];
DO
WHILE HoneEdge[ch, Leading, Even, Up, delay, p10]
DO
IF (delayFix ← delayFix+1) > 7 THEN ERROR;
[dhc, dis] ← CalibrateDL[ch, Delay, delay-delayFix];
MakePulse[ch, RZ, dhc, dis, whc, wis];
ENDLOOP;
WHILE HoneEdge[ch, Trailing, Even, Down, delay+width, p10]
DO
IF (widthFix ← widthFix+1) > 7 THEN ERROR;
[whc, wis] ← CalibrateDL[ch, Width, delay+width-widthFix];
MakePulse[ch, RZ, dhc, dis, whc, wis];
ENDLOOP;
IF HoneEdge[ch, Leading, Odd, Up, delay, p01]
THEN {
IF (delayFix ← delayFix+1) > 7 THEN ERROR;
[dhc, dis] ← CalibrateDL[ch, Delay, delay-delayFix];
MakePulse[ch, RZ, dhc, dis, whc, wis];
LOOP;
};
IF HoneEdge[ch, Trailing, Odd, Down, delay+width, p01]
THEN {
IF (widthFix ← widthFix+1) > 7 THEN ERROR;
[whc, wis] ← CalibrateDL[ch, Width, delay+width-widthFix];
MakePulse[ch, RZ, dhc, dis, whc, wis];
LOOP;
};
EXIT;
ENDLOOP;
SetDataPattern[p11]; --Display the result
SetRefDelay[0];
};
ROMode:
PROC [ch: ChannelIndex, delay: Delay, width: Width] ~ {
dhc, whc: HalfClocks ← 0;
dis, wis: InvStages ← 0;
delayFix, widthFix: NAT ← 0;
TerminalIO.PutF["Chan: %g, RO, Delay: %g, Width: %g\n", IO.int[ch], IO.int[delay], IO.int[width]];
[dhc, dis] ← CalibrateDL[ch, Delay, delay];
[whc, wis] ← CalibrateDL[ch, Width, delay+width];
MakePulse[ch, RO, dhc, dis, whc, wis];
DO
WHILE HoneEdge[ch, Leading, Even, Down, delay, p01]
DO
IF (delayFix ← delayFix+1) > 7 THEN ERROR;
[dhc, dis] ← CalibrateDL[ch, Delay, delay-delayFix];
MakePulse[ch, RO, dhc, dis, whc, wis];
ENDLOOP;
WHILE HoneEdge[ch, Trailing, Even, Up, delay+width, p01]
DO
IF (widthFix ← widthFix+1) > 7 THEN ERROR;
[whc, wis] ← CalibrateDL[ch, Width, delay+width-widthFix];
MakePulse[ch, RO, dhc, dis, whc, wis];
ENDLOOP;
IF HoneEdge[ch, Leading, Odd, Down, delay, p10]
THEN {
IF (delayFix ← delayFix+1) > 7 THEN ERROR;
[dhc, dis] ← CalibrateDL[ch, Delay, delay-delayFix];
MakePulse[ch, RO, dhc, dis, whc, wis];
LOOP;
};
IF HoneEdge[ch, Trailing, Odd, Up, delay+width, p10]
THEN {
IF (widthFix ← widthFix+1) > 7 THEN ERROR;
[whc, wis] ← CalibrateDL[ch, Width, delay+width-widthFix];
MakePulse[ch, RO, dhc, dis, whc, wis];
LOOP;
};
EXIT;
ENDLOOP;
SetDataPattern[p00]; --Display the result
SetRefDelay[0];
};
RTMode:
PROC [ch: ChannelIndex, delay: Delay, width: Width] ~ {
RZMode[ch, delay, width];
SetFormat[ch, RT];
};
RCMode:
PROC [ch: ChannelIndex, delay: Delay, width: Width] ~ {
RZMode[ch, delay, width];
SetFormat[ch, RC];
};
MakePulse:
PROC [ch: ChannelIndex, f: Format, dhc: HalfClocks, dis: InvStages, whc: HalfClocks, wis: InvStages] ~ {
SetFormat[ch, f];
SetTimingChan[ch, Delay, dhc, dis];
SetTimingChan[ch, Width, whc, wis];
};
FindHC:
PROC [ch: ChannelIndex, tg: Timing, t: Transition, start: HalfClocks ← 0]
RETURNS [hc: HalfClocks ← 0] ~ {
SetTimingChan[ch, tg, 0, 0];
hc ← start;
WHILE
NOT EdgeIsEarly[ch, t]
DO
SetTimingChan[ch, tg, (hc←hc+1), 0];
ENDLOOP;
WHILE EdgeIsEarly[ch, t]
DO
SetTimingChan[ch, tg, (hc←hc+1), 0];
ENDLOOP;
};
FindIS:
PROC [ch: ChannelIndex, tg: Timing, hc: HalfClocks, t: Transition]
RETURNS [is: InvStages ← 0]~ {
SetTimingChan[ch, tg, hc, 0];
WHILE EdgeIsEarly[ch, t]
DO
SetTimingChan[ch, tg, hc, (is←is+1)];
ENDLOOP;
};
CalibrateDL:
PROC [ch: ChannelIndex, tg: Timing, ns: Ns]
RETURNS [hc: HalfClocks, is: InvStages] ~ {
Cal:
PROC [t: Transition]
RETURNS [hc: HalfClocks ← 0, is: InvStages ← 0] ~ {
IF (hc ← FindHC[ch, tg, t]) = 0 THEN hc ← FindHC[ch, tg, t, 1];
hc ← hc-1;
IF (is ← FindIS[ch, tg, hc, t]) = 0
THEN
IF hc#0
THEN {
hc ← hc-1;
is ← FindIS[ch, tg, hc, t];
} ELSE {
hc ← FindHC[ch, tg, t, 2]-1;
is ← FindIS[ch, tg, hc, t];
IF is=0 THEN ERROR;
};
is←is-1;
SetTimingChan[ch, tg, hc, is];
};
hce, hco: HalfClocks;
ise, iso: InvStages;
SetRefPhase[Even];
SetDataPattern[p11];
SetFormat[ch, RZ];
IF tg=Delay THEN SetDelayPassThru[ch] ELSE SetWidthPassThru[ch];
SetRefDelay[ns];
[hce, ise] ← Cal[Up];
SetRefPhase[Odd];
[hco, iso] ← Cal[Down];
[hc, is] ← MinDelay[hce, ise, hco, iso];
IF gDebug THEN TerminalIO.PutF["Half Clocks: %g, Inv Stages: %g\n", IO.int[hc], IO.int[is]];
};
HoneEdge:
PROC [ch: ChannelIndex, e: Edge, p: Phase, t: Transition, ns: Ns, pat: DataPattern]
RETURNS [tooLate:
BOOL ←
FALSE] ~ {
ec: EdgeC ← 0;
SetRefPhase[p];
SetRefDelay[ns];
SetDataPattern[pat];
FOR i:
NAT
IN EdgeC
DO
TweakEdge[ch, e, p, (ec ← i), 0];
Process.PauseMsec[pause];
IF NOT EdgeIsEarly[ch, t] THEN EXIT;
ENDLOOP;
IF ec#0
THEN TweakEdge[ch, e, p, (ec ← ec-1), 0]
ELSE {
TerminalIO.PutF["Too early\n"];
RETURN[TRUE];
};
FOR i:
NAT
IN EdgeF
DO
TweakEdge[ch, e, p, ec, i];
Process.PauseMsec[pause];
IF NOT EdgeIsEarly[ch, t] THEN GOTO foundIt;
REPEAT
foundIt => {TerminalIO.PutF[" %g %g EdgeC: %g, EdgeF: %g\n",
IO.rope[IF e=Leading THEN "Leading" ELSE "Trailing"],
IO.rope[IF p=Even THEN "Even" ELSE "Odd"],
IO.int[ec], IO.int[i]]};
FINISHED => TerminalIO.PutF["Exceeded range\n"];
ENDLOOP;
};
TweakEdge:
PROCEDURE [ch: ChannelIndex, e: Edge, p: Phase, ec: EdgeC, ef: EdgeF] = {
PEWrite[ch, IF p=Odd THEN risingEdge ELSE fallingEdge, MapEdge[ec, ef], IF e=Leading THEN Delay ELSE Width];
};
ClearAllPE:
PROC ~ {
FOR c: ChannelIndex
IN ChannelIndex
DO
ClearPEChan[c];
ENDLOOP;
};
ClearPEChan:
PROC [c: ChannelIndex] ~ {
FOR t: Timing
IN Timing
DO
SetTimingChan[c, t, 0, 0];
ENDLOOP;
PEWrite[c, ioCtl, 0];
PEWrite[c, format, nrz];
};
MinDelay:
PROC [hc0: HalfClocks, is0: InvStages, hc1: HalfClocks, is1: InvStages]
RETURNS [hs: HalfClocks, is: InvStages] ~ {
SELECT
TRUE
FROM
hc0>hc1 => RETURN[hc1, is1];
hc0<hc1 => RETURN[hc0, is0];
hc0=hc1 AND is0>is1 => RETURN[hc1, is1];
hc0=hc1 AND is0<is1 => RETURN[hc0, is0];
ENDCASE => RETURN[hc0, is0];
};
SetTimingChan:
PROC [chan: ChannelIndex, timing: Timing, halfClocks: HalfClocks, invStages: InvStages, upEdgeC: EdgeC ← 0, upEdgeF: EdgeF ← 0, dnEdgeC: EdgeC ← 0, dnEdgeF: EdgeF ← 0] ~ {
PEWrite[chan, dsr0, DSR[halfClocks].high, timing];
PEWrite[chan, dsr1, DSR[halfClocks].low, timing];
PEWrite[chan, invCh0, IC[invStages, FALSE, FALSE].high, timing];
PEWrite[chan, invCh1, IC[invStages, FALSE, FALSE].mid, timing];
PEWrite[chan, invCh2, IC[invStages, FALSE, FALSE].low, timing];
PEWrite[chan, risingEdge, MapEdge[upEdgeC, upEdgeF], timing];
PEWrite[chan, fallingEdge, MapEdge[dnEdgeC, dnEdgeF], timing];
};
DSR:
PROC [halfClocks: HalfClocks]
RETURNS [high, low:
CARDINAL] ~ {
c: BitOps.BitDWord ← 0;
c ← BitOps.IBID[TRUE, c, halfClocks/2, 12];
c ← BitOps.IBID[TRUE, c, IF (halfClocks MOD 2)=0 THEN 10 ELSE 11, 12];
high ← BitOps.ECFD[c, 0, 8, 12];
low ← Basics.BITSHIFT[BitOps.ECFD[c, 8, 4, 12], 4]; --left justify result
};
IC:
PROC [invStages: InvStages, forceH, forceL:
BOOL]
RETURNS [high, mid, low:
CARDINAL] ~ {
c: BitOps.BitDWord ← 0;
c ← BitOps.IBID[TRUE, c, invStages, 22];
IF forceL THEN c ← BitOps.IBID[TRUE, c, 20, 22];
IF forceH THEN c ← BitOps.IBID[TRUE, c, 21, 22];
high ← BitOps.ECFD[c, 0, 8, 22];
mid ← BitOps.ECFD[c, 8, 8, 22];
low ← Basics.BITSHIFT[BitOps.ECFD[c, 16, 6, 22], 2]; --left justify result
};
MapEdge:
PROC [edgeC: EdgeC, edgeF: EdgeF]
RETURNS [
CARDINAL] ~ {
RETURN[Basics.BITOR[Basics.BITSHIFT[80h, -edgeC], fineMap[edgeF]]];
};
RamWrite:
PROC [which: Ram, add: Address, d0, d1, d2, d3: Byte10] ~ {
IF gRamDebug
THEN TerminalIO.PutRope[
IO.PutFLR["Write %g Add: %x, Data: %x, %x, %x, %x\n",
LIST[
IO.rope[
SELECT which
FROM
VRam => "VRam",
HRam => "HRam",
ERam => "ERam",
CRam => "CRam",
ENDCASE => ERROR],
IO.card[add], IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]];
CBusWrite[writeExtRamAdd, add];
LoadRamWD[d0, d1, d2, d3];
CBusWrite[writeExtRamCtl, extRamAccess];
CBusWrite[writeExtRamCtl,
SELECT which
FROM
VRam => writeVRam,
HRam => writeHRam,
ERam => writeERam,
CRam => writeCRam,
ENDCASE => ERROR];
CBusWrite[writeExtRamCtl, extRamAccess];
CBusWrite[writeExtRamCtl, 0];
};
RamRead:
PROC [which: Ram, add: Address]
RETURNS [d0, d1, d2, d3: Byte10] ~ {
CBusWrite[writeExtRamAdd, add];
CBusWrite[writeExtRamCtl, extRamAccess];
CBusWrite[writeExtRamCtl,
SELECT which
FROM
VRam => readVRam,
HRam => readHRam,
ERam => readERam,
CRam => readCRam,
ENDCASE => ERROR];
[d0, d1, d2, d3] ← FetchRamRD[];
CBusWrite[writeExtRamCtl, 0];
IF gRamDebug
THEN TerminalIO.PutRope[
IO.PutFLR["Read %g Add: %x, Data: %x, %x, %x, %x\n",
LIST[
IO.rope[
SELECT which
FROM
VRam => "VRam",
HRam => "HRam",
ERam => "ERam",
CRam => "CRam",
ENDCASE => ERROR],
IO.card[add], IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]];
};
LoadRamWD:
PROC [d0, d1, d2, d3: Byte10] ~ {
CBusWrite[ramWD0, d0];
CBusWrite[ramWD1, d1];
CBusWrite[ramWD2, d2];
CBusWrite[ramWD3, d3];
};
FetchRamRD:
PROC
RETURNS [d0, d1, d2, d3: Byte10] ~ {
d0 ← CBusRead[ramRD0];
d1 ← CBusRead[ramRD1];
d2 ← CBusRead[ramRD2];
d3 ← CBusRead[ramRD3];
};
InitGPIBDevices:
PROC ~
TRUSTED {
IF hardwareEnabled
THEN {
IF ~GPIB.InitializeController[] THEN ERROR;
GPIB.InterfaceClear[];
GPIB.SelectedDeviceClear[clock8112];
GPIB.SelectedRemoteEnable[clock8112];
-- fixed edge rate, square wave output, 5V, 0V, output on
WriteGPIB[clock8112, "W1 DTY 50% HIL -0.5V LOL -2.0V D0"];
};
};
ForcePulseHigh:
PROC [ch: ChannelIndex] = {
SetTimingChan[ch, Delay, 0, 0];
SetTimingChan[ch, Width, 0, 0];
PEWrite[ch, invCh0, 0, Delay];
PEWrite[ch, invCh2, IC[0, TRUE, FALSE].low, Delay];
PEWrite[ch, invCh0, 0, Width];
PEWrite[ch, invCh2, IC[0, FALSE, TRUE].low, Width];
};
ForcePulseLow:
PROC [ch: ChannelIndex] = {
SetTimingChan[ch, Delay, 0, 0];
SetTimingChan[ch, Width, 0, 0];
PEWrite[ch, invCh0, 0, Delay];
PEWrite[ch, invCh2, IC[0, FALSE, TRUE].low, Delay];
PEWrite[ch, invCh0, 0, Width];
PEWrite[ch, invCh2, IC[0, TRUE, FALSE].low, Width];
};
SetDelayPassThru:
PROC [ch: ChannelIndex] ~ {
IF gDebug THEN TerminalIO.PutF["Set Delay pass thru\n"];
SetTimingChan[ch, Delay, 0, 0];
SetTimingChan[ch, Width, 0, 0];
PEWrite[ch, invCh2, IC[0, FALSE, FALSE].low, Delay];
PEWrite[ch, invCh0, 0, Width];
PEWrite[ch, invCh2, IC[0, FALSE, TRUE].low, Width];
};
SetWidthPassThru:
PROC [ch: ChannelIndex] ~ {
IF gDebug THEN TerminalIO.PutF["Set Width pass thru\n"];
SetTimingChan[ch, Delay, 0, 0];
SetTimingChan[ch, Width, 0, 0];
PEWrite[ch, invCh0, 0, Delay];
PEWrite[ch, invCh2, IC[0, FALSE, TRUE].low, Delay];
PEWrite[ch, invCh2, IC[0, FALSE, FALSE].low, Width];
};
SetDataPattern:
PROC [dp: DataPattern] ~ {
Reset[];
IF gDebug THEN TerminalIO.PutF["Set pattern: %g\n", IO.rope[SELECT dp FROM p00 => "00", p01 => "01", p10 => "10", p11 => "11", ENDCASE => ERROR]];
RamWrite[CRam, 0, 03Fh, 3FFh, 0h, 0h]; --mask: FFFF, inhibit: 0000
SELECT dp
FROM
p00 => {
RamWrite[VRam, 0, 2h, 0h, 0h, 0h]; --Lit 2, 00, 00, 00
RamWrite[VRam, 1, 0h, 080h, 080h, 080h]; -- 00,Cpy 2@0,Cpy 2@0,Cpy 2@0
RamWrite[VRam, 2, 2h, 0h, 0h, 0h]; --Lit 2, 00, 00, 00
RamWrite[VRam, 3, 0h, 080h, 080h, 080h]; -- 00,Cpy 2@0,Cpy 2@0,Cpy 2@0
};
p01 => {
RamWrite[VRam, 0, 2h, 0h, 0h, 3Fh]; --Lit 2, 00, 00, 3f
RamWrite[VRam, 1, 3FFh, 080h, 080h, 080h]; -- 3FF,Cpy 2@0,Cpy 2@0,Cpy 2@0
RamWrite[VRam, 2, 2h, 0h, 0h, 3Fh]; --Lit 2, 00, 00, 3f
RamWrite[VRam, 3, 3FFh, 080h, 080h, 080h]; -- 3FF,Cpy 2@0,Cpy 2@0,Cpy 2@0
};
p10 => {
RamWrite[VRam, 0, 2h, 3Fh, 3FFh, 0h]; --Lit 2, 3f, 3FF, 00
RamWrite[VRam, 1, 0h, 080h, 080h, 080h]; -- 00,Cpy 2@0,Cpy 2@0,Cpy 2@0
RamWrite[VRam, 2, 2h, 3Fh, 3FFh, 0h]; --Lit 2, 3f, 3FF, 00
RamWrite[VRam, 3, 0h, 080h, 080h, 080h]; -- 00,Cpy 2@0,Cpy 2@0,Cpy 2@0
};
p11 => {
RamWrite[VRam, 0, 2h, 3Fh, 3FFh, 3Fh]; --Lit 2, 3f, 3FF, 3f
RamWrite[VRam, 1, 3FFh, 080h, 080h, 080h]; -- 3FF,Cpy 2@0,Cpy 2@0,Cpy 2@0
RamWrite[VRam, 2, 2h, 3Fh, 3FFh, 3Fh]; --Lit 2, 3f, 3FF, 3f
RamWrite[VRam, 3, 3FFh, 080h, 080h, 080h]; -- 3FF,Cpy 2@0,Cpy 2@0,Cpy 2@0
};
ENDCASE => ERROR;
CBusWrite[writeLoopAdd, 0];
CBusWrite[writeEndAdd, 3];
StartCtl[TRUE, TRUE, FALSE];
};
FindOutputEdge:
PROC [ch: ChannelIndex, p: Phase, t: Transition]
RETURNS [time: Ns ← 0] ~ {
SetRefPhase[p];
SetRefDelayAbs[time];
WHILE
NOT EdgeIsEarly[ch, t]
DO
SetRefDelayAbs[(time ← time+1)];
ENDLOOP;
};
EdgeIsEarly:
PROCEDURE [ch: ChannelIndex, t: Transition]
RETURNS [
BOOL] = {
trueCount, falseCount: NAT ← 0;
FOR i:
NAT
IN [0..7)
DO
IF (t=Down) = (Basics.
BITAND[PERead[ch, ioCtl], phaseComp]#0)
THEN trueCount ← trueCount+1
ELSE falseCount ← falseCount + 1;
ENDLOOP;
IF gDebug THEN TerminalIO.PutF[" %g/%g ", IO.card[trueCount], IO.card[falseCount]];
RETURN[trueCount>falseCount];
};
SetFormat:
PROC [ch: ChannelIndex, f: Format] = {
PEWrite[ch, format, SELECT f FROM NRZ => nrz, RZ => rz, RO => ro, RC=> rc, RT => rt, ENDCASE => ERROR];
IF gDebug THEN TerminalIO.PutF["Set format: %g\n", IO.rope[SELECT f FROM NRZ => "NRZ", RZ => "RZ", RO => "RO", RC=> "RC", RT => "RT", ENDCASE => ERROR]]
};
SetAnalogSample:
PROC [ch: ChannelIndex, b:
BOOL] = {
PEWrite[ch, ioCtl, BitOps.IBIW[b, PERead[ch, ioCtl], 2, 5]];
};
SetTTLLevels:
PROC [ch: ChannelIndex, b:
BOOL] = {
PEWrite[ch, ioCtl, BitOps.IBIW[b, PERead[ch, ioCtl], 1, 5]];
};
SetRefDelayAbs:
PROC [d: Delay] ~ {
CBusWrite[refDelay, d];
IF gDebug THEN TerminalIO.PutF["Ref clock delay: %g\n", IO.card[d]];
};
SetRefDelay:
PROC [d: Delay] ~ {
SetRefDelayAbs[d+gCycOffset];
};
SetClock:
PROC [period: Period] ~ {
divisor: ClockDivisor;
SELECT
TRUE
FROM
period IN [30..70) => {divisor ← one; gClkPeriod ← period};
period IN [70..140) => {divisor ← two; gClkPeriod ← (period+1)/2};
period IN [140..280) => {divisor ← four; gClkPeriod ← (period+2)/4};
period IN [280..560) => {divisor ← eight; gClkPeriod ← (period+4)/8};
ENDCASE => ERROR;
SetClockDivisor[divisor];
WriteGPIB[clock8112, IO.PutFR["PER %gNS", IO.card[gClkPeriod]]];
IF gDebug THEN TerminalIO.PutF["Set clock to %g ns\n", IO.card[period]]
};
StartCtl:
PROC [start, loop, reset:
BOOL ←
FALSE] ~ {
gClockCtl ← BitOps.IBIW[start, gClockCtl, 5, 8];
gClockCtl ← BitOps.IBIW[loop, gClockCtl, 4, 8];
gClockCtl ← BitOps.IBIW[reset, gClockCtl, 0, 8];
CBusWrite[clkCtl, gClockCtl];
};
SetRefPhase:
PROC [p: Phase] ~ {
gClockCtl ← BitOps.IBIW[p=Even, gClockCtl, 2, 8];
CBusWrite[clkCtl, gClockCtl];
IF gDebug THEN TerminalIO.PutF["Set reference phase %g\n", IO.rope[IF p=Even THEN "Even" ELSE "Odd"]]
};
SetClockDivisor:
PROC [cd: ClockDivisor] ~ {
gClockCtl ← BitOps.ICIW[ORD[cd], gClockCtl, 6, 2, 8];
CBusWrite[clkCtl, gClockCtl];
gClkDivisor ← cd;
};
PEWrite:
PROC [chan: ChannelIndex, reg: PEReg, data: PEData, timing: Timing ← Sample] ~ {
To write the ioCtl and Format registers, use default: timing ← Sample since these regs are not asociated with any particular timing chain
CBusWrite[(chan*24)+(timing.ORD*8)+reg, data];
};
PERead:
PROC [chan: ChannelIndex, reg: PEReg, timing: Timing ← Sample]
RETURNS [data: PEData] ~ {
To read the ioCtl and Format registers, use default: timing ← Sample since these regs are not asociated with any particular timing chain
data ← Basics.BITAND[CBusRead[(chan*24)+(timing.ORD*8)+reg], 0FFh]; --PE only uses 8 bits
};
CBusRead:
PROC [add: Address]
RETURNS [data: Byte10 ← 0] ~ {
IF hardwareEnabled THEN data ← XBus.IORead[baseAdd + add*2];
};
CBusWrite:
PROC [add: Address, data: Byte10] ~ {
IF hardwareEnabled THEN XBus.IOWrite[baseAdd + add*2, data];
};
WriteGPIB:
PROCEDURE [device:
GPIB.DeviceAddr, msg: Rope.
ROPE] =
TRUSTED {
IF hardwareEnabled THEN GPIB.WriteDevice[device, Rope.Concat[msg, "\n\l"]];
};