<> <> <> DIRECTORY Multibus, MultibusRpcControl, Rope, SageFace, SageFaceRpcControl, ViewRec; SageTest: CEDAR PROGRAM IMPORTS Multibus, MultibusRpcControl, SageFace, SageFaceRpcControl, ViewRec = BEGIN OPEN SageFace; UserHandle: TYPE = REF UserRec; UserRec: TYPE = RECORD [ pulseTap: ARRAY PulseLine OF Tap, outPair: ARRAY Channel OF PulsePair, inPulse: ARRAY Channel OF PulseLine, inData: ARRAY InputStage OF BOOL, bigChip: BOOL _ FALSE, continuous: BOOL _ FALSE, quit: BOOL _ FALSE, FoolAround: PROC[uh: UserHandle], SetChannels: PROC[uh: UserHandle] ]; data: PACKED ARRAY Channel OF ARRAY ShiftStage OF DriveState; PulseGenCounterReg: TYPE = MACHINE DEPENDENT RECORD[ null(0: 0..11): [0..4096) _ 0, counter(0: 12..15): [0..16) _ 0]; PulseGenCounterCtlReg: TYPE = MACHINE DEPENDENT RECORD[ null(0: 0..13): [0..16384) _ 0, continuous(0: 14..14): BOOL _ FALSE, go(0: 15..15): BOOL _ FALSE]; PulseGenCtlReg: TYPE = MACHINE DEPENDENT RECORD[ null(0: 0..12): [0..8192) _ 0, nReset(0: 13..13): BOOL _ FALSE, feedBack15(0: 14..14): BOOL _ FALSE, globalHold(0: 15..15): BOOL _ FALSE]; ChannelCtlReg: TYPE = MACHINE DEPENDENT RECORD[ null(0: 0..7): [0..256) _ 0, localHold(0: 8..8): BOOL _ FALSE, inPulseLine(0: 9..12): PulseLine _ 0, outPulsePair(0: 13..15): [0..8) _ 0]; PulseLine: TYPE = [0..16); PulsePair: TYPE = [0..8); Channel: TYPE = [0..64); Tap: TYPE = [0..64); ShiftStage: TYPE = [0..32); InputStage: TYPE = [0..16); DriveState: TYPE = {H, L, T}; PulseGenTapAddress: MultibusAddress = SageDeviceAddress+0H; PulseGenCounterRegAddress: MultibusAddress = SageDeviceAddress+10H; PulseGenCounterRegHackAddress: MultibusAddress = SageDeviceAddress+01E0H; ChannelAddress: MultibusAddress = SageDeviceAddress+20H; WidthPulseLine: PulseLine = 7; CyclePulseLine: PulseLine = 15; ControlValue: TYPE = {continuous, go, reset, feedBack15, globalHold}; InputCount: CARDINAL = 8; InputData: TYPE = MACHINE DEPENDENT RECORD[ null(0: 0..InputCount-1): [0..256), bits(0: InputCount..15): PACKED ARRAY InputIndex OF BOOL]; InputIndex: TYPE = [0..InputCount); pulseGenCounterRegState: PulseGenCounterReg _ [0, 0]; pulseGenCounterCtlRegState: PulseGenCounterCtlReg _ [0, FALSE, FALSE]; pulseGenCtlRegState: PulseGenCtlReg _ [0, FALSE, FALSE, FALSE]; Start: PROCEDURE [name: Rope.ROPE] = TRUSTED { TRUSTED { MultibusRpcControl.ImportInterface[interfaceName: [NIL, name]]; SageFaceRpcControl.ImportInterface[interfaceName: [NIL, name]]; }; DoOutput[LOOPHOLE[pulseGenCounterRegState], PulseGenCounterRegHackAddress]; DoOutput[LOOPHOLE[pulseGenCounterCtlRegState], PulseGenCounterCtlRegHackAddress]; DoOutput[LOOPHOLE[pulseGenCtlRegState], PulseGenCtlRegAddress]; }; FoolAround: PROCEDURE [uh: UserHandle] = { UNTIL uh.quit DO TRUSTED {SageFace.Start[firstCounterCtlReg: 2, newCtlReg: 4, secondCounterCtlReg: 3, wait: FALSE]}; ENDLOOP; }; SetChannels: PROCEDURE [uh: UserHandle] = { SetControl[go, FALSE]; SetControl[continuous]; SetControl[globalHold]; SetControl[reset]; SetControl[reset, FALSE]; FOR pl: PulseLine IN PulseLine DO SetPulseLineTap[pulseLine: pl, tap: uh.pulseTap[pl]]; ENDLOOP; FOR c: Channel IN Channel DO SetChannelCtlReg[channel: c, register: [localHold: TRUE, inPulseLine: uh.inPulse[c], outPulsePair: uh.outPair[c]], bigChip: uh.bigChip]; ENDLOOP; LoadOutputShiftRegisters[uh]; SetCount[0]; FaceStart[cont1: uh.continuous, go1: FALSE, globalHold: FALSE, cont2: uh.continuous, go2: TRUE, wait: NOT uh.continuous]; FOR i: InputStage IN InputStage DO data: InputData _ ReadChannelOctetData[channel0: 0, bigChip: uh.bigChip]; uh.inData[i] _ data.bits[1]; ENDLOOP; }; FaceStart: PROC [cont1, go1, globalHold, cont2, go2, wait: BOOL] = { ToCard: PROC [c,g: BOOL] RETURNS [foo:CARDINAL] = { foo _ IF c THEN 2 ELSE 0; IF g THEN foo _ foo+1; }; pulseGenCounterCtlRegState.continuous _ cont2; pulseGenCounterCtlRegState.go _ go2; pulseGenCtlRegState.nReset _ TRUE; pulseGenCtlRegState.feedBack15 _ FALSE; pulseGenCtlRegState.globalHold _ globalHold; TRUSTED {SageFace.Start[firstCounterCtlReg: ToCard[cont1, go1], newCtlReg: IF globalHold THEN 5 ELSE 4, secondCounterCtlReg: ToCard[cont2, go2], wait: wait]}; }; <<>> LoadOutputShiftRegisters: PROC [uh: UserHandle] = { FOR c: CARDINAL _ 0, c+2 UNTIL c>LAST[Channel] DO FOR i: CARDINAL _ 0, i+2 UNTIL i>LAST[ShiftStage] DO dl0, dh0, dl1, dh1: DriveState; dl0 _ data[c][i]; dh0 _ data[c][i+1]; dl1 _ data[c+1][i]; dh1 _ data[c+1][i+1]; IF i MOD 4 #0 THEN { t: DriveState _ dl0; dl0 _ dh0; dh0 _ t; t _ dl1; dl1 _ dh1; dh1 _ t; }; WriteChannelPairData[channel0: c, dataLow0: dl0, dataHigh0: dh0, dataLow1: dl1, dataHigh1: dh1, bigChip: uh.bigChip]; ENDLOOP; ENDLOOP; }; <<>> WriteChannelPairData: PROCEDURE [channel0: Channel, dataLow0, dataHigh0, dataLow1, dataHigh1: DriveState, bigChip: BOOL] = { dataLow: CARDINAL _ ConvertToBits[dataLow0, dataHigh0]; dataHigh: CARDINAL _ ConvertToBits[dataLow1, dataHigh1]; <<*** I'm not sure about this next line, data may be reversed...JAG ***>> IF bigChip THEN DoOutput[16*dataLow + dataHigh, ChannelAddress + (channel0/(IF bigChip THEN 32 ELSE 16))*(IF bigChip THEN 40H ELSE 20H) + channel0 MOD (IF bigChip THEN 32 ELSE 16)] ELSE IF (channel0 MOD 16) < 8 THEN DoOutput[16*dataLow + dataHigh, ChannelAddress + (channel0/(IF bigChip THEN 32 ELSE 16))*(IF bigChip THEN 40H ELSE 20H) + channel0 MOD (IF bigChip THEN 32 ELSE 16)] ELSE DoOutput[dataLow + 16*dataHigh, ChannelAddress + (channel0/(IF bigChip THEN 32 ELSE 16))*(IF bigChip THEN 40H ELSE 20H) + channel0 MOD (IF bigChip THEN 32 ELSE 16)]; }; ConvertToBits: PROC[dataLow, dataHigh: DriveState] RETURNS [dataOut: CARDINAL] = { <<01 => H, 10 => L, 11 => T, dataLow goes in bits 1 and 3 of a nibble, dataHigh goes in bits 0 and 2 of the nibble, numbering the nibble bits from left to right, 0 to 3, high order to low order of course.>> Bits: ARRAY DriveState OF ARRAY DriveState OF CARDINAL = [[03H, 09H, 0BH], [06H, 0CH, 0EH], [07H, 0DH, 0FH]]; RETURN[Bits[dataLow][dataHigh]]; }; SetCount: PROCEDURE [value: CARDINAL] = { pulseGenCounterRegState.counter _ value; DoOutput[LOOPHOLE[pulseGenCounterRegState], PulseGenCounterRegHackAddress]; }; SetControl: PROCEDURE [value: ControlValue, newValue: BOOL _ TRUE] = { SELECT value FROM continuous => pulseGenCounterCtlRegState.continuous _ newValue; go => pulseGenCounterCtlRegState.go _ newValue; reset => pulseGenCtlRegState.nReset _ NOT newValue; feedBack15 => pulseGenCtlRegState.feedBack15 _ newValue; globalHold => pulseGenCtlRegState.globalHold _ newValue; ENDCASE => ERROR; IF value IN [continuous .. go] THEN DoOutput[LOOPHOLE[pulseGenCounterCtlRegState], PulseGenCounterCtlRegHackAddress] ELSE DoOutput[LOOPHOLE[pulseGenCtlRegState], PulseGenCtlRegAddress]; }; SetPulseLineTap: PROCEDURE [pulseLine: PulseLine, tap: Tap] = { DoOutput[tap, PulseGenTapAddress+pulseLine]; }; SetChannelCtlReg: PROCEDURE [channel: Channel, register: ChannelCtlReg, bigChip: BOOL] = { DoOutput[LOOPHOLE[register], ChannelAddress + (channel/(IF bigChip THEN 32 ELSE 16))*(IF bigChip THEN 40H ELSE 20H) + (IF bigChip THEN 20H ELSE 10H) + channel MOD (IF bigChip THEN 32 ELSE 16)]; }; ReadChannelOctetData: PROCEDURE [channel0: Channel, bigChip: BOOL] RETURNS [InputData] = { RETURN[ LOOPHOLE [DoInput[ChannelAddress + (channel0/(IF bigChip THEN 32 ELSE 16))*(IF bigChip THEN 40H ELSE 20H) + channel0 MOD (IF bigChip THEN 32 ELSE 16)]]]; }; DoInput: PROCEDURE [address: LONG CARDINAL] RETURNS [word: CARDINAL] = TRUSTED { RETURN[Multibus.Input[LOOPHOLE[address]]]; }; DoOutput: PROCEDURE [word: CARDINAL, address: LONG CARDINAL] = TRUSTED { Multibus.Output[LOOPHOLE[word, UNSPECIFIED], LOOPHOLE[address]]; }; h: UserHandle _ NEW [UserRec]; h.FoolAround _ FoolAround; h.SetChannels _ SetChannels; h.quit _ FALSE; FOR pl: PulseLine IN PulseLine DO h.pulseTap[pl] _ 4*pl; ENDLOOP; h.pulseTap[WidthPulseLine] _ 1; h.pulseTap[CyclePulseLine] _ 60; h.pulseTap[0] _ 47; h.pulseTap[8] _ 63; FOR c: Channel IN Channel DO h.outPair[c] _ 2; h.inPulse[c] _ 3; FOR s: ShiftStage IN ShiftStage DO data[c][s] _ IF s MOD 2 = 0 THEN L ELSE H; ENDLOOP; ENDLOOP; h.outPair[1] _ 0; [] _ ViewRec.ViewRef[agg: h, specs: ViewRec.BindAllOfATypeFromRefs[h, NEW[UserHandle _ h]], createOptions: [maxEltsHeight: 320], viewerInit: [iconic: FALSE, name: "Sage Tester"], paint: TRUE]; END.