DIRECTORY Convert USING [RopeFromTime], FS USING [StreamOpen], IO USING [Close, PutChar, PutRope, STREAM], Loader USING [BCDBuildTime], Rope USING [Cat, Length, ROPE]; DTProms: CEDAR PROGRAM IMPORTS Convert, FS, IO, Loader, Rope = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; mb: STREAM; memory: CARDINAL _ 0; Bit: TYPE = BOOLEAN; virgin: BOOLEAN _ TRUE; -- Virgin bits in TBP28L22s are high TransmitControl: PROC = BEGIN State: TYPE = MACHINE DEPENDENT {idle(0), data(1), crc(2), (3)}; addr: RECORD [ blank: [0..256), state: State, timeout: Bit, inhibit: Bit, ready: Bit, word: Bit, notCollision: Bit, notDefer: Bit ]; output: RECORD [ nextState: State, notIdle: Bit, idle: Bit, carrier: Bit, load: Bit, notLoad: Bit, spare: Bit _ virgin, blank: [0..256) _ 0 ]; StartNewMemory["TC", 8]; FOR i: CARDINAL IN [0..256) DO state, nextState: State; timeout, inhibit, ready, word, collision, defer: Bit; idle, carrier, load: Bit _ FALSE; TRUSTED { addr _ LOOPHOLE[i]; }; state _ addr.state; timeout _ addr.timeout; inhibit _ addr.inhibit; ready _ addr.ready; word _ addr.word; collision _ ~addr.notCollision; defer _ ~addr.notDefer; idle _ TRUE; nextState _ state; SELECT state FROM idle => { IF ~collision AND ~defer AND ~inhibit AND ready THEN { idle _ FALSE; carrier _ TRUE; nextState _ data; }; }; data => { idle _ FALSE; carrier _ TRUE; IF word THEN SELECT TRUE FROM inhibit => nextState _ crc; -- End of Data ready => load _ ~collision; ~ready => nextState _ idle; -- Data Late ENDCASE => ERROR; IF collision OR timeout THEN nextState _ idle; }; -- Catastrophe crc => { idle _ FALSE; carrier _ TRUE; IF word THEN { -- End of CRC idle _ TRUE; carrier _ FALSE; nextState _ idle; }; IF collision OR timeout THEN nextState _ idle; }; -- Catastrophe ENDCASE => nextState _ idle; output.nextState _ nextState; output.notIdle _ ~idle; output.idle _ idle; output.carrier _ carrier; output.load _ load; output.notLoad _ ~load; PutWord[1]; -- Memory contents PutWord[0]; -- Source line number TRUSTED { PutWord[LOOPHOLE[output, CARDINAL]]; }; ENDLOOP; END; BitStuffing: PROC = BEGIN State: TYPE = MACHINE DEPENDENT { idle0, idle1, idle2, idle3, idle4, idle5, idle6, idle7, start0, start1, start2, start3, start4, start5, start6, start7, no0s, one0, two0s, three0s, four0s, five0s, stop0, stop1, stop2, stop3, stop4, stop5, stop6, stop7, (31)}; addr: RECORD [ blank: [0..256), state: State, notTick: Bit, carrier: Bit, dataIn: Bit ]; output: RECORD [ nextState: State, shift: Bit, active: Bit, dataOut: Bit, blank: [0..256) _ 0 ]; StartNewMemory["BS", 8]; FOR i: CARDINAL IN [0..256) DO state, nextState: State; tick, carrier, dataIn: Bit; shift, active, dataOut: Bit; TRUSTED { addr _ LOOPHOLE[i]; }; state _ addr.state; tick _ ~addr.notTick; carrier _ addr.carrier; dataIn _ addr.dataIn; nextState _ state; shift _ tick; dataOut _ TRUE; SELECT state FROM idle0, idle1, idle2, idle3, idle4, idle5, idle6, idle7 => { shift _ ~carrier; IF state IN (idle0..idle7) THEN dataOut _ FALSE; IF tick THEN { nextState _ state.SUCC; IF state = idle7 THEN nextState _ IF carrier THEN start0 ELSE idle0; }; }; start0, start1, start2, start3, start4, start5, start6, start7 => { shift _ FALSE; IF state IN (start0..start7) THEN dataOut _ FALSE; IF tick THEN { nextState _ state.SUCC; IF state = start7 THEN nextState _ no0s; }; IF ~carrier THEN nextState _ idle0; }; no0s, one0, two0s, three0s, four0s => { dataOut _ dataIn; IF tick THEN { nextState _ IF dataIn THEN no0s ELSE state.SUCC; SELECT TRUE FROM (nextState = five0s) => shift _ FALSE; ~carrier => { nextState _ stop0; shift _ FALSE; }; ENDCASE => NULL; }; }; five0s => { dataOut _ TRUE; IF tick THEN { nextState _ no0s; IF ~carrier THEN { nextState _ stop0; shift _ FALSE; }; }; }; stop0, stop1, stop2, stop3, stop4, stop5, stop6, stop7 => { IF state IN (stop0..stop7) THEN dataOut _ FALSE; IF tick THEN { shift _ FALSE; nextState _ state.SUCC; IF state = stop7 THEN nextState _ idle0; }; }; ENDCASE => nextState _ idle0; active _ nextState IN [start0..stop7]; output.nextState _ nextState; output.active _ active; output.shift _ shift; output.dataOut _ dataOut; PutWord[1]; -- Memory contents PutWord[0]; -- Source line number TRUSTED { PutWord[LOOPHOLE[output, CARDINAL]]; }; ENDLOOP; END; ClockRecovery: PROC = BEGIN State: TYPE = MACHINE DEPENDENT { one0(0), one1, one2, one3, one4, one5, one6, one7(7), zero0(8), zero1, zero2, zero3, zero4, zero5, zero6, zero7, (31)}; addr: RECORD [ blank: [0..256), state: State, gnd: Bit, mask: Bit, line: Bit ]; output: RECORD [ nextState: State, spare1: Bit _ virgin, spare2: Bit _ virgin, tick: Bit, blank: [0..256) _ 0 ]; StartNewMemory["CR", 8]; FOR i: CARDINAL IN [0..256) DO state, nextState: State; line, mask: Bit; tick: Bit _ FALSE; addr _ LOOPHOLE[i]; state _ addr.state; line _ addr.line; mask _ addr.mask; IF state # State.LAST THEN nextState _ state.SUCC; SELECT state FROM one0 => NULL; -- This bit is a one IN [one1..one5] => NULL; one6 => IF line THEN nextState _ one0; -- Advance one tick one7 => IF line THEN nextState _ one0; -- Right on zero0 => IF line THEN nextState _ one0 -- Drop back one tick ELSE NULL; -- This bit is a zero IN [zero1..zero5] => IF line THEN nextState _ one0; -- Lost sync?? zero6 => IF line THEN nextState _ one0; -- Advance one tick zero7 => IF line THEN nextState _ one0 -- Right on ELSE nextState _ zero0; ENDCASE => nextState _ one0; IF nextState = one0 OR nextState = zero1 THEN tick _ mask; output.nextState _ nextState; output.tick _ tick; PutWord[1]; -- Memory contents PutWord[0]; -- Source line number TRUSTED { PutWord[LOOPHOLE[output, CARDINAL]]; }; ENDLOOP; END; BitUnstuffing: PROC = BEGIN State: TYPE = MACHINE DEPENDENT { abort(0), flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8, -- Seen bit n of a flag start10, start11, -- start => Seen n bits since flag, m 0s since last 1 start20, start21, start22, start30, start31, start32, start33, start40, start41, start42, start43, start44, start50, start51, start52, start53, start54, start55, start60, start61, start62, start63, start64, start65, start70, start71, start72, start73, start74, start75, data0, data1, data2, data3, data4, data5, data6, end, (63)}; -- n 0s since last 1 -- 1s during idle loops in state flag0 -- Flags during idle loops through flag6, flag7, start11, ..., start55, flag6... addr: RECORD [ blank: [0..256), state: State, tick: Bit, data: Bit ]; output: RECORD [ nextState: State, shift: Bit, carrier: Bit, blank: [0..256) _ 0 ]; StartNewMemory["BU", 8]; FOR i: CARDINAL IN [0..256) DO state, nextState: State; tick, data, shift, carrier: Bit; addr _ LOOPHOLE[i]; state _ addr.state; tick _ addr.tick; data _ addr.data; SELECT state FROM abort => nextState _ IF data THEN flag1 ELSE abort; IN [flag1..flag7) => nextState _ IF data THEN flag1 ELSE state.SUCC; flag7 => nextState _ IF data THEN flag8 ELSE abort; flag8 => nextState _ IF data THEN start10 ELSE start11; start10 => nextState _ IF data THEN start20 ELSE start21; start11 => nextState _ IF data THEN start20 ELSE start22; start20 => nextState _ IF data THEN start30 ELSE start31; start21 => nextState _ IF data THEN start30 ELSE start32; start22 => nextState _ IF data THEN start30 ELSE start33; start30 => nextState _ IF data THEN start40 ELSE start41; start31 => nextState _ IF data THEN start40 ELSE start42; start32 => nextState _ IF data THEN start40 ELSE start43; start33 => nextState _ IF data THEN start40 ELSE start44; start40 => nextState _ IF data THEN start50 ELSE start51; start41 => nextState _ IF data THEN start50 ELSE start52; start42 => nextState _ IF data THEN start50 ELSE start53; start43 => nextState _ IF data THEN start50 ELSE start54; start44 => nextState _ IF data THEN start50 ELSE start55; start50 => nextState _ IF data THEN start60 ELSE start61; start51 => nextState _ IF data THEN start60 ELSE start62; start52 => nextState _ IF data THEN start60 ELSE start63; start53 => nextState _ IF data THEN start60 ELSE start64; start54 => nextState _ IF data THEN start60 ELSE start65; start55 => nextState _ IF data THEN start50 ELSE flag7; -- 10000001000000 start60 => nextState _ IF data THEN start70 ELSE start71; start61 => nextState _ IF data THEN start70 ELSE start72; start62 => nextState _ IF data THEN start70 ELSE start73; start63 => nextState _ IF data THEN start70 ELSE start74; start64 => nextState _ IF data THEN start70 ELSE start75; start65 => nextState _ IF data THEN start60 ELSE flag7; -- 100000011000000 start70 => nextState _ IF data THEN data0 ELSE data1; start71 => nextState _ IF data THEN data0 ELSE data2; start72 => nextState _ IF data THEN data0 ELSE data3; start73 => nextState _ IF data THEN data0 ELSE data4; start74 => nextState _ IF data THEN data0 ELSE data5; start75 => nextState _ IF data THEN start70 ELSE flag7; -- 1000000111000000 IN [data0..data4] => nextState _ IF data THEN data0 ELSE state.SUCC; data5 => nextState _ IF data THEN data0 ELSE data6; data6 => nextState _ IF data THEN end ELSE abort; end => nextState _ IF data THEN flag1 ELSE flag2; -- Kick out last data bit ENDCASE => nextState _ abort; SELECT state FROM start55, start65, start75, data5, end => shift _ FALSE; ENDCASE => shift _ TRUE; IF ~tick THEN { shift _ FALSE; nextState _ state; }; carrier _ (nextState IN [data0..data6]) OR (nextState = end); output.nextState _ nextState; output.shift _ shift; output.carrier _ carrier; PutWord[1]; -- Memory contents PutWord[0]; -- Source line number TRUSTED { PutWord[LOOPHOLE[output, CARDINAL]]; }; ENDLOOP; END; ReceiveControl: PROC = BEGIN State: TYPE = MACHINE DEPENDENT { idle(0), start, data, end(3)}; addr: RECORD [ blank: [0..256), state: State, enable: Bit, match: Bit, word: Bit, shift: Bit, data: Bit, carrier: Bit ]; output: RECORD [ nextState: State, notFce: Bit, crcClr: Bit, notClear: Bit, notAbort: Bit, end: Bit, write: Bit, blank: [0..256) _ 0 ]; StartNewMemory["RC", 8]; FOR i: CARDINAL IN [0..256) DO state, nextState: State; enable, match, word, shift, data, carrier: Bit; fce, crcClr, clear, abort, end, write: Bit _ FALSE; addr _ LOOPHOLE[i]; state _ addr.state; enable _ addr.enable; match _ addr.match; word _ addr.word; shift _ addr.shift; data _ addr.data; carrier _ addr.carrier; nextState _ state; SELECT state FROM idle => { clear _ ~carrier; IF shift THEN { IF ~word THEN nextState _ IF carrier THEN start ELSE end; }; }; start => { fce _ shift; IF ~carrier THEN nextState _ end; -- Noise burst? IF word THEN nextState _ IF match THEN data ELSE end; }; data => { IF shift THEN write _ word; IF ~carrier THEN { nextState _ end; abort _ ~word; write _ TRUE; -- Pass through CRC and/or partial word end _ TRUE; }; }; end => { clear _ TRUE; crcClr _ TRUE; IF ~carrier THEN nextState _ idle; }; ENDCASE => ERROR; IF ~enable THEN { nextState _ idle; fce _ TRUE; crcClr _ TRUE; }; output.nextState _ nextState; output.notFce _ ~fce; output.crcClr _ crcClr; output.notClear _ ~clear; output.notAbort _ ~abort; output.end _ end; output.write _ write; PutWord[1]; -- Memory contents PutWord[0]; -- Source line number TRUSTED { PutWord[LOOPHOLE[output, CARDINAL]]; }; ENDLOOP; END; PutTimeStamp: PROC [name: ROPE] = BEGIN PutWord[4]; -- Define (fake) Memory memory _ memory + 1; PutWord[memory]; PutWord[8]; name _ Rope.Cat[name, " of ", Convert.RopeFromTime[Loader.BCDBuildTime[DoIt]]]; PutRope[name]; END; StartNewMemory: PROC [name: ROPE, bitsPerWord: CARDINAL] = BEGIN PutWord[4]; -- Define Memory memory _ memory + 1; PutWord[memory]; PutWord[bitsPerWord]; PutRope[name]; PutWord[2]; -- Set Current Memory PutWord[memory]; PutWord[0]; -- Current PC END; PutRope: PROC [rope: ROPE] = BEGIN IO.PutRope[mb, rope]; PutByte[0]; -- End of string IF (rope.Length[] MOD 2) = 0 THEN PutByte[0]; -- Round up to word END; PutWord: PROC [data: CARDINAL] = TRUSTED BEGIN IO.PutChar[mb, LOOPHOLE[data/256, CHAR]]; IO.PutChar[mb, LOOPHOLE[data, CHAR]]; END; PutByte: PROC [data: CARDINAL] = TRUSTED BEGIN IO.PutChar[mb, LOOPHOLE[data, CHAR]]; END; DoIt: PROCEDURE = BEGIN mb _ FS.StreamOpen["DTProms.mb", $create]; PutTimeStamp["DTProms.mb"]; TransmitControl[]; BitStuffing[]; ClockRecovery[]; BitUnstuffing[]; ReceiveControl[]; PutWord[0]; -- End of data marker IO.Close[mb]; mb _ NIL; END; DoIt[]; END. @DTProms.mesa - Make Proms for Dicentra T1 board Hal Murray June 5, 1985 6:40:52 pm PDT Compile DTProms Run DTProms Copy /Ivy/Murray/DT/DTProms.mesa _ DTProms.mesa Copy /Ivy/Murray/DT/DTProms.mb _ DTProms.mb one0 => line went up in the previous 1/8th of a bit cell, this bit is a 1 zero0 => line would have gone up in the previous 1/8th of a bit cell, but this bit is a 0 Our clock is running 8 times the nominal bit rate on the line. A bit will normally be 4 slots wide, but asymetries may distort a bit to 3, or 5 slots. tick is raised during the 2nd slot so it becomes available during the 3rd slot. The next stage must grab the bit right away, or it may change if a bit is narrow. This whole mess could be simplified by shrinking the delay buffer. You only need 5 bits since the shifter isn't kicked after seeing 5 0s. Κ˜šœ/™/Icode™&—˜Jšœ™Jšœ ™ J™/J™+J™—J™šΟk ˜ Jšœœ˜Jšœœ˜Jšœœœ˜+Jšœœ˜šœœœ˜J˜——šœ œ˜Jšœ œœ˜'Jš˜J˜Jšœœœ˜Jšœœœœ˜J˜Jšœœ˜ Jšœœ˜J˜Jšœœœ˜JšœœœΟc$˜˜>—šœœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜—šœœ˜Jšœ˜Jšœ ˜ Jšœ ˜ J˜ J˜—J˜šœœœ ˜J˜Jšœ˜Jšœ˜Jšœ œ˜ J˜Jšœ˜J˜J˜J˜Jšœ ˜ Jšœ œ˜šœ˜šœ;˜;Jšœ˜Jšœœœ œ˜0šœœ˜Jšœœ˜Jš œœ œ œœ ˜J——šœC˜CJšœœ˜Jšœœœ œ˜2šœœ˜Jšœœ˜Jšœœ˜+—Jšœ œ˜&—šœ'˜'Jšœ˜šœœ˜Jš œ œœœœ˜0šœœ˜Jšœ œ˜&Jšœ)œ˜2Jšœœ˜———šœ ˜ Jšœ œ˜šœœ˜Jšœ˜Jšœ œœ ˜=——šœ;˜;Jšœœœ œ˜0šœœ˜Jšœœ˜Jšœœ˜Jšœœ˜.——Jšœ˜—Jšœœ˜&Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ž˜Jšœ ž˜!Jšœ œ œ˜1Jšœ˜—Jšœ˜J˜—šŸ œœ˜Jš˜šœœœ œ˜!Jšœ5˜5šœA˜AJšœI™IJšœY™YJ™Ή——šœœ˜J˜J˜ J˜ J˜ J˜ —šœœ˜J˜Jšœ˜Jšœ˜Jšœ ˜ J˜—J˜šœœœ ˜J˜J˜Jšœ œ˜Jšœœ˜J˜J˜J˜Jšœœœœ˜2šœ˜Jšœœž˜"Jšœœ˜šœ˜Jšœœž˜2—šœ˜Jšœœž ˜*—šœ˜Jšœœž˜3Jšœœž˜ —šœ˜Jšœœž˜-—šœ˜Jšœœž˜2—šœ˜Jšœœž ˜)Jšœ˜—Jšœ˜—Jšœœœ ˜:J˜Jšœ˜Jšœ ž˜Jšœ ž˜!Jšœ œ œ˜1Jšœ˜—Jšœ˜J˜—šŸ œœ˜Jš˜J™BJ™Fšœœœ œ˜!Jšœ ˜ Jšœ8ž˜OJšœž;˜MJšœ˜Jšœ#˜#Jšœ,˜,Jšœ5˜5Jšœ5˜5Jšœ5˜5Jšœ=ž˜QJ˜&JšœP˜P—šœœ˜J˜J˜ J˜ J˜ —šœœ˜J˜Jšœ ˜ Jšœ ˜ J˜—J˜šœœœ ˜J˜Jšœ ˜ Jšœœ˜J˜Jšœ˜J˜šœ˜Jšœœœœ˜3Jš œœœœœ˜DJšœœœœ˜3Jšœœœ œ ˜7Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œž˜IJšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œ ˜9Jšœœœ œž˜JJšœœœœ˜5Jšœœœœ˜5Jšœœœœ˜5Jšœœœœ˜5Jšœœœœ˜5Jšœœœ œž˜KJš œœœœœ˜DJšœœœœ˜3Jšœœœœ˜1Jšœœœœž˜KJšœ˜—šœ˜Jšœ1œ˜7Jšœ œ˜—šœœ˜Jšœœ˜Jšœ˜—Jšœœœ˜=J˜Jšœ˜Jšœ˜Jšœ ž˜Jšœ ž˜!Jšœ œ œ˜1Jšœ˜—Jšœ˜J˜—šŸœœ˜Jš˜šœœœ œ˜!Jšœ˜—šœœ˜J˜J˜ J˜ Jšœ ˜ J˜ J˜ J˜ J˜—šœœ˜J˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ J˜—J˜šœœœ ˜J˜Jšœ/˜/Jšœ-œ˜3Jšœœ˜J˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜Jšœ˜Jšœ˜šœ˜šœ ˜ Jšœ˜šœœ˜Jš œœ œ œœ ˜?——šœ ˜ Jšœ ˜ Jšœ œž˜1Jš œœ œœœ˜8—šœ ˜ Jšœœ ˜šœ œ˜Jšœ˜Jšœ˜Jšœœž'˜5Jšœœ˜——šœ˜Jšœœ˜ Jšœ œ˜Jšœ œ˜%—Jšœœ˜—Jšœ œœ œ˜AJšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ž˜Jšœ ž˜!Jšœ œ œ˜1Jšœ˜—Jšœ˜J˜—J˜šŸ œœœ˜!Jš˜Jšœ ž˜#Jšœ˜Jšœ˜Jšœ ˜ JšœO˜OJšœ˜Jšœ˜J˜—šŸœœœœ˜:Jš˜Jšœ ž˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ž˜!Jšœ˜Jšœ ž ˜Jšœ˜J˜—šŸœœœ˜Jš˜Jšœ˜Jšœ ž˜Jšœœœ ž˜AJšœ˜J˜—šŸœœœ˜(Jš˜Jšœ œ œ˜)Jšœ œœ˜%Jšœ˜J˜—šŸœœœ˜(Jš˜Jšœ œœ˜%Jšœ˜J˜—J˜šŸœ œ˜Jš˜Jšœœ#˜*Jšœ˜J˜J˜J˜J˜J˜Jšœ ž˜!Jšœ ˜ Jšœœ˜ Jšœ˜J˜šœ˜J˜—Jšœ˜J˜——…—/΄D‘