SSCtlPortsRec:
TYPE =
RECORD[
nBR, nBG, nReset, nSel, nAS, SClk, nLErr, nAck0, nAck1, nAck2, Siz, Read, PA, Data, TxClock, TxCode, TxData, TxEnb, RxClock, RxCode, RxData, SlipEnb, SamClk, SamData, Current, T0, SRegOut, ToDAC, CodeLock, DataLock: Port ← NIL];
SSCtlTestProc: RosemaryUser.TestProc = {
ports: SSCtlPorts ← SSCtlInitialize[p, cellType.public, Eval ! Rosemary.Stop => IF reason = $BoolWireHasX THEN RESUME ELSE REJECT];
{OPEN ports;
txData: NAT = 0;
txCtl: NAT = 1;
rxData: NAT = 2;
rxCtl: NAT = 3;
serialCtl:
NAT = 4;
serialResetCode: NAT = 0;
serialSetCode: NAT = 1;
serialResetData: NAT = 2;
serialSetData: NAT = 3;
SBusStore:
PROC [adr:
NAT, value:
NAT] = {
PB[nSel, FALSE, force];
PB[nAS, FALSE, force];
PB[nLErr, TRUE, expect];
PB[nAck0, TRUE, expect];
PD[nAck1, inspect];
PB[nAck2, TRUE, expect];
PDW[Siz, 1, force];
PB[Read, FALSE, force];
PDW[PA, adr, force];
PDW[Data, BitOps.DShift[value, 24, 32], force];
THROUGH [1..255]
DO
SSCtlCycleClock[ports, Eval];
IF NOT GB[nAck1] THEN EXIT;
REPEAT FINISHED => SIGNAL Warning;
ENDLOOP;
PB[nAS, TRUE, force];
SSCtlCycleClock[ports, Eval];
PB[nSel, TRUE, force];
SSCtlCycleClock[ports, Eval];
};
SBusFetch:
PROC [adr:
NAT]
RETURNS [value:
NAT] = {
PB[nSel, FALSE, force];
PB[nAS, FALSE, force];
PB[nLErr, TRUE, expect];
PB[nAck0, TRUE, expect];
PD[nAck1, inspect];
PB[nAck2, TRUE, expect];
PDW[Siz, 1, force];
PB[Read, TRUE, force];
PDW[PA, adr, force];
PD[Data, inspect];
THROUGH [1..255]
DO
SSCtlCycleClock[ports, Eval];
IF NOT GB[nAck1] THEN EXIT;
REPEAT FINISHED => SIGNAL Warning;
ENDLOOP;
value ← BitOps.ELFD[GDW[Data], 0, 8, 32];
PB[nAS, TRUE, force];
SSCtlCycleClock[ports, Eval];
PB[nSel, TRUE, force];
SSCtlCycleClock[ports, Eval];
};
serialBitCount: NAT = 12;
SerialStore:
PROC [value:
NAT, reg:
NAT] = {
OPEN BitOps;
serialCtlRegLen: NAT = 8;
serialDoIt: NAT = 0;
serialBitOfData: NAT = 1;
serialRegAdr: NAT = 2;
serialRegAdrLen: NAT = 2;
serialBitAdr: NAT = 4;
serialBitAdrLen: NAT = 4;
d: BitWord ← BitWordZero;
d ← ICIW[reg, d, serialRegAdr, serialRegAdrLen, serialCtlRegLen];
FOR bitIndex:
NAT
IN [0..serialBitCount)
DO
d ← IBIW[FALSE, d, serialDoIt, serialCtlRegLen];
d ← ICIW[bitIndex, d, serialBitAdr, serialBitAdrLen, serialCtlRegLen];
d ← IBIW[EBFW[value, serialBitCount-bitIndex-1, serialBitCount], d, serialBitOfData, serialCtlRegLen];
SBusStore[serialCtl, d];
d ← IBID[TRUE, d, serialDoIt, serialCtlRegLen];
SBusStore[serialCtl, d];
SSCtlCycleClock[ports, Eval, 2*serialBitCount];
ENDLOOP;
};
PD[TxEnb, inspect];
SBusStore[txCtl, 40H];
IF NOT GB[TxEnb] THEN SIGNAL Warning;
SerialStore[003H, serialResetCode];
SerialStore[002H, serialSetCode];
SerialStore[005H, serialResetData];
SerialStore[004H, serialSetData];
SSCtlCycleClock[ports, Eval, 10*serialBitCount];
PB[CodeLock, TRUE, expect];
PB[DataLock, TRUE, expect];
SSCtlCycleClock[ports, Eval];
PD[CodeLock, none];
PD[DataLock, none];
THROUGH [1..10]
DO
PB[TxData, FALSE, none];
SSCtlCycleClock[ports, Eval, 16];
PB[TxData, TRUE, none];
SSCtlCycleClock[ports, Eval, 16];
PB[TxData, FALSE, none];
SSCtlCycleClock[ports, Eval, 16];
PB[TxData, TRUE, none];
SSCtlCycleClock[ports, Eval, 16];
ENDLOOP;
PB[CodeLock, FALSE, expect];
PB[DataLock, FALSE, expect];
SSCtlCycleClock[ports, Eval];
PD[CodeLock, none];
PD[DataLock, none];
PD[TxData, inspect];
SSCtlCycleClock[ports, Eval, 510]; -- initialize receiver
IF BitOps.EBFD[SBusFetch[txCtl], 0, 8] THEN SIGNAL Warning; -- tx already busy?
SBusStore[txData, 55H];
IF NOT BitOps.EBFD[SBusFetch[txCtl], 0, 8] THEN SIGNAL Warning; -- tx failed to go busy?
THROUGH [1..100]
DO
IF BitOps.EBFD[SBusFetch[rxCtl], 0, 8] THEN EXIT;
REPEAT FINISHED => SIGNAL Warning; -- rx failed to go ready?
ENDLOOP;
IF SBusFetch[rxData]#55H THEN SIGNAL Warning; -- incorrect data?
SSCtlInitialize:
PROC [p: Ports.Port, public: Core.Wire, eval: RosemaryUser.TestEvalProc]
RETURNS [ports: SSCtlPorts]= {
ports ← NEW[SSCtlPortsRec];
{OPEN ports;
[nBR, nBG, nReset, nSel, nAS, SClk, nLErr, nAck0, nAck1, nAck2] ← Ports.BindPorts[public, p, "nBR", "nBG", "nReset", "nSel", "nAS", "SClk", "nLErr", "nAck0", "nAck1", "nAck2"];
[Siz, Read, PA, Data, TxClock, TxCode, TxData, TxEnb, RxClock, RxCode, RxData] ← Ports.BindPorts[public, p, "Siz", "Read", "PA", "Data", "TxClock", "TxCode", "TxData", "TxEnb", "RxClock", "RxCode", "RxData"];
[SlipEnb, SamClk, SamData, Current, T0, SRegOut, ToDAC, CodeLock, DataLock] ← Ports.BindPorts[public, p, "SlipEnb", "SamClk", "SamData", "Current", "T0", "SRegOut", "ToDAC", "CodeLock", "DataLock"];
PB[nBR, TRUE, force];
PB[nBG, TRUE, force];
PB[nReset, TRUE, force];
PB[nSel, TRUE, force];
PB[nAS, TRUE, force];
PB[nLErr, TRUE, force];
PB[nAck0, TRUE, force];
PB[nAck1, TRUE, force];
PB[nAck2, TRUE, force];
PDW[Siz, 0, force];
PB[Read, TRUE, force];
PDW[PA, 0, force];
PDW[Data, 0, force];
PD[TxCode, none];
PD[TxData, none];
PD[TxEnb, none];
PD[RxCode, none];
PB[RxData, TRUE, force];
PB[SlipEnb, TRUE, force];
PD[SamClk, none];
PD[SamData, none];
PD[Current, none];
PD[T0, none];
PD[SRegOut, none];
PD[ToDAC, none];
PD[CodeLock, none];
PD[DataLock, none];
PB[TxClock, TRUE, force];
SSCtlCycleClock[ports, eval];
}};