"
module P302702A

title 'P302702A'


"Message Detector for the Data Receiver A3027A."
"=============================================="

"Version 1: Based upon P3007C07, the Message Detector contains eight"
"independent Message Decoders. The decoders are identical and defined"
"in a separate source file as a module. The Message Detector watches"
"the eight decoders. When a message arrives in one of them, the Decoder"
"transfers the message ID, its data value, and the current timestamp"
"to the Message Router of the A3027, through the message_data pins."

"The timestamp is a twenty-four bit counter running off the RCK clock,"
"which is 32.768 kHz. A message consists of an eight-bit ID, of which"
"the top four bits are always zero, followed by a sixteen-bit data"
"value, and then the lower eight bits of the timestamp."

"The Message Detector generates clock messages every 128 cycles of"
"RCK, and transfers these to the Message Router. A clock message"
"consists of an eight-bit ID byte that is zero, the top and middle bytes"
"of the timestamp, and a final byte that, instead of containing the"
"lower eight bits of the timestamp, which would at this time always"
"be zero, contains the Message Detector firmware version number."

"The firmware version numbers of the Data Recevier (A3018) went from"
"1 to the current value 7, leaving room to go to 19. The Data Receiver"
"(A3027) numbers start at 20."

"The A3027 serial inputs and outputs connect to the Message Detector."
"In this version of the code, we do nothing with these connections."

"This version of the code takes a minute to compile. It uses most of"
"the GLB inputs and logic clusters. We may not be able to fit much more"
"functionality into the chip. There are more logic lines available to"
"transfer signals to the Message Router, where we could do work that"
"the Message Detector cannot accommodate. Alternatively, we may be able"
"to improve the efficiency of the existing functions by building a byte"
"multiplexer in front of the final message data selector for the transfer"
"to the Storage Controller."

"Version 2: We expand the byte multiplexer so that fewer of the message"
"data logic block inputs are used. This makes the code faster to compile,"
"and permits us to compile with version numbers other than 27."

"We add duplicate message detection that operates upon intervals of time"
"for which one or more message decoders have messages ready. Most of the"
"time, no decoders will have messages ready. When more than one has a"
"message from the same channel, these will almost always be duplicates."

"The Message Detector Code (MDC) output transmits a serial byte every"
"time the Message Detector fetches a message from one of its message"
"decoders. This byte contains the decoder number, which is the antenna"
"number minus one, and the channel id of the message."

"We introduce some primitive handling of the digial input-output. Because"
"the Message Detector has so little spare capacity, we pass the digital"
"input-output signals through to the Message Router. We test Y1 and Y2 as"
"inputs and outputs, and X1 and X2 as inputs and outputs. Then we set the"
"code to handle the I/O in a default mannter."

"Version 3: First thing we have to do is modify the byte multiplexer so"
"we can set the version number to 33. Otherwise won't compile. Modify the"
"pins used for SCK to suite A3027B."

"Version 4: We reduce the size of the decoder logic so we can fit more"
"functionality in here. We add the receive indicator to the decoders. we "
"forward the receive indicator for the first decoder, which is the one"
"decoding the signal on Antenna One, to the X1 output as a diagnostic"
"aid."

"Version 5: We set up X2 as an output, forwarding serial transmissions"
"from the Message Router."

"Version 6: We set up X1 and X2 as user-controlled outputs, and we set up"
"Y1 and Y2 as outputs also. Y1 produces a pulse when Decoer One is active,"
"and Y2 provides immediate message transmission for a selectect channel, as"
"did X2 in firmware Version 5."

"Version 7: We configure X1 to emit 1-ms pulses at 24.6 Hz to drive video"
"capture. We enable the pulses in the same way we previously asserted X1"
"with LWDAQ commands."

"Version 8: We support the transmission of Message Notifications. The"
"notifications are serial transmission generated in the Message Router"
"and relayed through the Message Detector to Y1 and Y2. To support the"
"notifications, the Message Detector provides three signals. The MSGI"
"signal is Message Incoming. This is asserted whenever one of the"
"message decoders is eight or more bits into receiving a message."
"The CMIMM bit is Clock Message Imminent, which we assert one RCK cycle"
"(30 us) before a clock message appears, so as to suppress all other"
"notifications and ensure that a clock message notification is transmitted."
"The CMST bit is Clock Store. We assert CMST when a clock message is being"
"transferred to the Message Router. The X1 and X2 bits come from the Message"
"Router also. X1 is a logic output set by LWDAQ command. X2 is immediate"
"sample transmission as in Version 5."

"Version 9: Fixed problems with the message notification and is coupled"
"with a new version of the decoder."

"Version 10: Add support for set numbers. We transmit the message bits to the"
"Message Router, which compares the channel identifier and the completion code"
"to the set slection register and generates a set match signal. The Message"
"Detector uses SETMATCH to accept or reject incoming messages, to count them"
"in duplicate detection or not, and to report or ignore them for display lamps."
"The Message Detector does not know what the set number is, and stores only"
"the four-bit transmitter channel number with four zeros above it to compose"
"the eight-bit channel number."

"Version 11: Add support for all-set recording. The DDD input disables duplicate"
"detection so that all messages will be stored, leaving duplicate rejection as a"
"job for software. The top four bits of the channel ID will be equal to the set"
"number, as reported in the ID4..ID7 bits from the Message Router. The Message"
"Router's Set Select Register controls the behavior of DDD and the ID bits."

declarations
  firmware_version=^d41;
  fake_message_data=0;
equations


"Pins"
declarations
!RESET pin 70;"Hardware Reset"			
ARCK pin 120; "Asynchronous 32.768 kHz reference clock input"
DCK pin 66; "Data Clock 40 MHz"
TP3, TP4, TP6 pin 10, 20, 30 istype 'com'; "Test Points"
MRDY pin 62 istype 'com,pos'; "Message Ready"
MDS pin 61; "Message Data Strobe"
MD7..MD0 pin 51, 52, 53, 54, 57, 58, 59, 60 istype 'com'; "Message Data"
SCK pin 49 istype 'com'; "Slow Clock Output, 2.048 kHz"
DBC pin 63; "Display Board Code"
MDC pin 64 istype 'com,keep'; "Message Detector Code"
message_data = [MD7..MD0];
Q1..Q8 pin 39, 35, 175, 165, 152, 174, 112, 103; "Demodulator Outputs"
RECEIVE pin 148 istype 'reg,keep'; "Receive Indicator Lamp"
X1 pin 146 istype 'com'; "X1 output to BNC"
X2 pin 145 istype 'com'; "X2 output to BNC"
Y1I pin 169; "Y1 input from USB"
Y1O pin 168 istype 'com'; "Y1 output value to USB"
Y1EN pin 158 istype 'com'; "Enable Y1 output on USB"
Y2I pin 170; "Y2 input from USB"
Y2O pin 162 istype 'com'; "Y2 output value to USB."
Y2EN pin 159 istype 'com'; "Enable Y2 output on USB"
X1_IN pin 80; "X1 value from Message Router"
X2_IN pin 81; "X2 value from Message Router"
Y1_IN pin 82; "Y1 value from Message Router"
Y2_IN pin 83; "Y2 value from Message Router"
MSGI pin 84 istype 'com'; "Message Incoming"
CMIMM pin 85 istype 'reg'; "Clock Message Imminent"
CMST pin 86 istype 'com'; "Clock Message Store"
M_OUT pin 74 istype 'com'; "Message data output to Message Router"
SHIFT_OUT pin 75 istype 'com'; "Shift message data output to Message Router" 
SETMATCH pin 76; "Set Match answer from Message Router"
ID4..ID7 pin 72, 73, 48, 47; "Top Nibble of Channel ID from Message Router"
DDD pin 71; "Disable Duplicate Detection"
equations


"Reference Clock"
"---------------"

"The reference clock is exactly 30.768 kHz, and we use it for"
"our longer time measurements."

declarations
RCK node istype 'reg';
equations

RCK.clk = DCK;
RCK := ARCK;


"Time Stamp"
"----------"

declarations
STAMP23..STAMP0 node istype 'reg'; "Time Stamp"
timestamp=[STAMP23..STAMP0];
tsb0=[STAMP7..STAMP0];
tsb1=[STAMP15..STAMP8];
tsb2=[STAMP23..STAMP16];
TSC1..TSC0 node istype 'com,keep'; "Time Stamp Carry"
TSS1..TSS0 node istype 'reg'; "Time Stamp State"
tss=[TSS1..TSS0];
TSCNT node istype 'com,keep'; "Time Stamp Continue"
TSCC1..TSCC0 node istype 'reg'; "Time Stamp Clock Control"
tscc=[TSCC1..TSCC0];
SCREST node istype 'com,keep'; "Storage Controller Rest"
TSRDY node istype 'com,keep'; "Time Stamp Ready"
equations

"We increment the timestamp only when the Storage Controller"
"is at rest. Otherwise we might increment the timestamp half-way"
"through storing a clock message, or half-way through storing"
"a transmitter message. In that case, the message would have"
"timestamp zero before the clock message marking the return"
"of the lower byte of the timestamp to zero has itself been stored"
"in memory."
tscc.clk = DCK;
tscc.aclr = RESET;
state_diagram tscc;
  state 0:if RCK then 1 else 0; "TSCC1 is low"
  state 1:if SCREST then 2 else 1; "TSCC1 stays low"
  state 2:goto 3; "TSCC1 goes high"
  state 3:if !RCK then 0 else 3; "TSCC1 stays high"
equations;

"We clock the timestamp with TSCC1. We cannot increment the"
"timestamp unless the Storage Controller is at rest. In order"
"to maintain the count of RCK rising edges, the Storage"
"Controller must return to its rest state within 30 us of each"
"rising edge of RCK."
timestamp.clk = TSCC1;
timestamp.aclr = RESET;
tsb0:=tsb0+1;
TSC0=(tsb0==255);
when TSC0 then tsb1:=tsb1+1;
else tsb1:=tsb1;
TSC1=(tsb1==255);
when TSC0 & TSC1 then tsb2:=tsb2+1;
else tsb2:=tsb2;

"When the timestamp returns to zero, we request that the"
"Storage Controller transfer a clock message to the"
"Message Router."
tss.clk = DCK;
tss.aclr = RESET;
state_diagram tss;
  state 0:if tsb0==0 then 1 else 0;
  state 1:if TSCNT then 2 else 1;
  state 2:if tsb0==0 then 2 else 0;
equations;

"The Slow Clock we pass to the Message Router is 2.048 kHz. This"
"clock is used to flash display lamps."
SCK = STAMP3;

"We use TSRDY to indicate that the timestamp is ready to store. This"
"flag is used by the Storage Controller to initiate storage of a clock"
"message."
TSRDY = (tss==1);

"We use CMIMM (Clock Message Imminent) to indicate to the Message Router"
"that a timestamp message will be generated in the next 30 us. This"
"forewarning allows the Message Router to suppress the transmission of"
"non-clock messages in its Message Notification system, ensuring that the"
"clock message will be transmitted."
CMIMM.clk = DCK;
when (CMIMM == 0) then {
  when TSC0 then CMIMM := 1
  else CMIMM := 0;
}
when (CMIMM == 1) then{
  when TSCNT then CMIMM := 0
  else CMIMM := 1;
}


"Message Decoders"
"----------------"

"The message decoders are defined in a separate ABEL file as"
"a module."

declarations
decoder interface (Q, CNT, CK, RST, S -> RDY, M, RCV);
decoder1 functional_block decoder;
decoder2 functional_block decoder;
decoder3 functional_block decoder;
decoder4 functional_block decoder;
decoder5 functional_block decoder;
decoder6 functional_block decoder;
decoder7 functional_block decoder;
decoder8 functional_block decoder;
MDRDY node istype 'com,keep'; "Message Decoder Ready"
equations

"Set up the inputs to the message decoders."
decoder1.Q = Q1;
decoder1.CK = DCK;
decoder1.RST = RESET;
decoder2.Q = Q2;
decoder2.CK = DCK;
decoder2.RST = RESET;
decoder3.Q = Q3;
decoder3.CK = DCK;
decoder3.RST = RESET;
decoder4.Q = Q4;
decoder4.CK = DCK;
decoder4.RST = RESET;
decoder5.Q = Q5;
decoder5.CK = DCK;
decoder5.RST = RESET;
decoder6.Q = Q6;
decoder6.CK = DCK;
decoder6.RST = RESET;
decoder7.Q = Q7;
decoder7.CK = DCK;
decoder7.RST = RESET;
decoder8.Q = Q8;
decoder8.CK = DCK;
decoder8.RST = RESET;

"We assert MDRDY when any one of the message decoders"
"has a message ready."
MDRDY = decoder1.RDY
  # decoder2.RDY
  # decoder3.RDY
  # decoder4.RDY
  # decoder5.RDY
  # decoder6.RDY
  # decoder7.RDY
  # decoder8.RDY;


"Message Selector"
"----------------"

"The Message Selector has to select one of the Message Decoders"
"and read out its message. There may be only one decoder with a"
"message available, in which case our selection is simple. But"
"with eight independent decoders, we may have all eight of them"
"receiving the same message, and asserting their RDY outputs at"
"the same time, or within one clock cycle of one another. In"
"this case, the Message Selector chooses the lowest-numbered"
"decoder with a message available, and does not change its"
"selection until this message has been read out and transferred"
"to the Message Router. The selection takes place when the"
"Storage Controller, which performs the transfers, is in its"
"rest state."

"The Message Selector must read out the message one bit at"
"a time. Serial exchanges are far more efficient in their use"
"of registers and AND-arrays than parallel exchanges. The"
"Storage Controller initiates this serial exchange with the"
"FETCH signal, and the Message Selector organises the shifting"
"of the message into the M19..M0 with the help of the fetch"
"shift state machine and the SHIFT signal."

"The Message Selector directs the MDCNT signal from the Storage"
"Controller to the correct Message Decoder."


declarations
MIN node istype 'com,keep'; "Message Data Input Bit"
M23..M0 node istype 'reg,keep';  "Message Data"
message = [M23..M0];
MDCNT node istype 'com,keep'; "Message Decoder Continute"
SHIFT node istype 'com,keep'; "Message Shift"
FETCH node istype 'com,keep'; "Message Fetch"
FDONE node istype 'com,keep'; "Fetch Done"
FS4..FS0 node istype 'reg'; "Fetch Shift State"
fss = [FS4..FS0];
MSEL2..MSEL0 node istype 'reg'; "Message Select"
msel = [MSEL2..MSEL0];
sel_1 = 0;
sel_2 = 1;
sel_3 = 2;
sel_4 = 3;
sel_5 = 4;
sel_6 = 5;
sel_7 = 6;
sel_8 = 7;
equations


"We set msel when the storage controller is in its rest state,"
"and we find that one or more of the message decoders is ready."
msel.clk = DCK;
msel.aclr = RESET;
when SCREST then {
  when decoder1.RDY then msel := sel_1
  else when decoder2.RDY then msel := sel_2
  else when decoder3.RDY then msel := sel_3
  else when decoder4.RDY then msel := sel_4
  else when decoder5.RDY then msel := sel_5
  else when decoder6.RDY then msel := sel_6
  else when decoder7.RDY then msel := sel_7
  else when decoder8.RDY then msel := sel_8
  else msel := sel_1;
} else {
  msel := msel;
}

"We use msel to select one of the decoder data outputs."
when msel == sel_1 then MIN = decoder1.M;
when msel == sel_2 then MIN = decoder2.M;
when msel == sel_3 then MIN = decoder3.M;
when msel == sel_4 then MIN = decoder4.M;
when msel == sel_5 then MIN = decoder5.M;
when msel == sel_6 then MIN = decoder6.M;
when msel == sel_7 then MIN = decoder7.M;
when msel == sel_8 then MIN = decoder8.M;

"The Fetch Shift State Machine controls the transfer"
"of message bits from the selected message decoder."
fss.clk = DCK;
fss.aclr = RESET;

"Waiting to fetch a message."
when fss == 0 then {
  when FETCH then fss:=1 else fss:=0;
} 

"Shifting out the mesage bits."
when (fss>=1) & (fss<=24) then {
  fss:=fss+1;
}

"Checking for duplication."
when (fss>=25) & (fss<=28) then {
  fss:=fss+1;
}

"Done with fetching, message data is ready to transfer"
"to the Message Router."
when (fss>=29) then {
  when !FETCH then fss:=0 else fss:=29;
}

"The SHIFT bit is directed by msel to the correct message"
"decoder. We asser the shift bit through twenty states of"
"fss so as to shift all twenty message bits out of the"
"decoder. Because the SHIFT bit is combinatorial, we use"
"it only as a logical input to registers clocked by DCK"
"or !DCK, not as a clock itself."
SHIFT = (fss>=1) & (fss<=24);
decoder1.S = (msel == sel_1) & SHIFT;
decoder2.S = (msel == sel_2) & SHIFT;
decoder3.S = (msel == sel_3) & SHIFT;
decoder4.S = (msel == sel_4) & SHIFT;
decoder5.S = (msel == sel_5) & SHIFT;
decoder6.S = (msel == sel_6) & SHIFT;
decoder7.S = (msel == sel_7) & SHIFT;
decoder8.S = (msel == sel_8) & SHIFT;

"FDONE tells the Storage Controller that the message data"
"is ready."
FDONE = (fss==29);

"Message data is clocked on !DCK as we shift bits out"
"of a message decoder. Otherwise, the message data"
"remains in place."
message.clk = !DCK;
message.aclr = RESET;
when SHIFT then { 
  [M23..M0] := [M22..M0,MIN];
} else {
  message:=message;
}

"When we get MDCNT from the Storage Controller, we can"
"let the selected decoder go back to waiting for another"
"message."
decoder1.CNT = (msel == sel_1) & MDCNT;
decoder2.CNT = (msel == sel_2) & MDCNT;
decoder3.CNT = (msel == sel_3) & MDCNT;
decoder4.CNT = (msel == sel_4) & MDCNT;
decoder5.CNT = (msel == sel_5) & MDCNT;
decoder6.CNT = (msel == sel_6) & MDCNT;
decoder7.CNT = (msel == sel_7) & MDCNT;
decoder8.CNT = (msel == sel_8) & MDCNT;


"Set Discriminator"
"-----------------"

"The Set Discriminator is in the Message Router where we have more"
"unused logic gates. We transfer each message to the router using"
"the M_OUT and SHIFT_OUT signals. Back from the Message Router we"
"get a SETMATCH signal. If it is asserted, the message belongs to"
"a set that the Message Detector is suppose to store."

"The set discrimination is performed by comparing the selected set"
"code, the message ID, and the message completion code. The"
"completion code (C) is a function of the transmitter's channel"
"identifier (N) and set identifier (S): C = 14 - N + S, For S=1, the"
"completion code is the one's compliment of the channel ident-"
"ifier."

"The Message Router calcculates SETMATCH using the channel id and"
"the completion code. The SETMATCH signal is used by the Duplicate"
"Detector, the Storage Controller and the Display Board Interface."
"Here we give SETMATCH one DCK period to settle after the message"
"shifting is complete, so we check SETMATCH on fss == 26, where"
"the last bit is shifted on fss == 24."

M_OUT = MIN;
SHIFT_OUT = SHIFT;


"Duplicate Detector"
"------------------"

"Here we look for multiple messages with the same channel number"
"that are duplicates detected with the A3027's multiple antennas."
"We look for duplicates only when multiple message decoders are"
"ready at the same time, for it is then that we can be confident"
"that messages with the same channel ID are duplicates. We do not"
"look for duplicates in channel 15, because duplication is possible"
"when two transmitters using channel 15 collide."

declarations
DID1..DID14 node istype 'reg'; "Duplicate ID Bits"
did=[DID1..DID14];
DUPLICATE node istype 'reg,keep,pos';
cmid=[M23..M20]; "Current Message ID"
equations


"We declare a duplicate if the message ID corresponds to a message"
"bit that is set."
DUPLICATE.clk = DCK;
DUPLICATE.aclr=!MDRDY;
when (fss==26) & SETMATCH then {
  when cmid==0 then DUPLICATE:=0;
  when cmid==1 then DUPLICATE:=DID1;
  when cmid==2 then DUPLICATE:=DID2;
  when cmid==3 then DUPLICATE:=DID3;
  when cmid==4 then DUPLICATE:=DID4;
  when cmid==5 then DUPLICATE:=DID5;
  when cmid==6 then DUPLICATE:=DID6;
  when cmid==7 then DUPLICATE:=DID7;
  when cmid==8 then DUPLICATE:=DID8;
  when cmid==9 then DUPLICATE:=DID9;
  when cmid==10 then DUPLICATE:=DID10;
  when cmid==11 then DUPLICATE:=DID11;
  when cmid==12 then DUPLICATE:=DID12;
  when cmid==13 then DUPLICATE:=DID13;
  when cmid==14 then DUPLICATE:=DID14;
  when cmid==15 then DUPLICATE:=0;
} else {
  DUPLICATE:=DUPLICATE;
}

"We clear all the duplicate ID bits when there is no message"
"ready."
did.clk=DCK;
did.aclr=!MDRDY;

"We set a duplicate ID bit after we have compared the existing"
"bits to the message ID, and provided the set matches and the"
"Message Router is not asserting Duplicate Detection Disable."
when (fss==28) & SETMATCH & !DDD then {
  when cmid==1 then DID1:=1 else DID1:=DID1;
  when cmid==2 then DID2:=1 else DID2:=DID2;
  when cmid==3 then DID3:=1 else DID3:=DID3;
  when cmid==4 then DID4:=1 else DID4:=DID4;
  when cmid==5 then DID5:=1 else DID5:=DID5;
  when cmid==6 then DID6:=1 else DID6:=DID6;
  when cmid==7 then DID7:=1 else DID7:=DID7;
  when cmid==8 then DID8:=1 else DID8:=DID8;
  when cmid==9 then DID9:=1 else DID9:=DID9;
  when cmid==10 then DID10:=1 else DID10:=DID10;
  when cmid==11 then DID11:=1 else DID11:=DID11;
  when cmid==12 then DID12:=1 else DID12:=DID12;
  when cmid==13 then DID13:=1 else DID13:=DID13;
  when cmid==14 then DID14:=1 else DID14:=DID14;
} else {
  did:=did;
}


"Storage Controller"
"------------------"

"The Storage Controller provides the process that transfers"
"bytes to the Message Router. It transfers the four bytes of"
"a clock message whenever a new clock message is ready. It"
"waits for a new message to be fetched from its Message Decoder"
"and transfers the message one byte at a time."

declarations
SCS3..SCS0 node istype 'reg'; "Storage Controller State"
scs=[SCS3..SCS0];
TXDC node istype 'com'; "Transmit Display Command"
equations

"The state names for the Storage Controller."
declarations
  scs_rest = 0;
  scs_clock_id = 1;
  scs_clock_hi = 2;
  scs_clock_mid = 3;
  scs_clock_fv = 4;
  scs_clock_done = 5;
  scs_message_fetch = 6;
  scs_message_id = 7;
  scs_message_hi = 8;
  scs_message_lo = 9;
  scs_message_ts = 10;
  scs_message_done = 11;
equations

"The Storage Controller transfers clock messages and transmitter"
"messages to the Message Router. It transfers clock messages in preference"
"to transmitter messages, but clock messages occur only once every"
"256 cycles of RCK, so they are rare compared to transmitter messages,"
"which occur 64 cycles of RCK for 512 SPS, and there may be fourteen"
"transmitters running at once. Note that the Storage Controller always"
"uses the current value of the time stamp lower byte when it transfers"
"a message to the Message Router."
scs.clk = DCK;
scs.aclr = RESET;
state_diagram scs;
  "In the rest state, we are waiting for a message to handle."
  state scs_rest:
    if TSRDY then scs_clock_id 
    else if MDRDY then scs_message_fetch
    else scs_rest;

  "We transfer the clock id, high byte of timestamp, middle byte of timestamp"
  "and the firmware version number that constitute a clock message.:
  state scs_clock_id:if MDS then scs_clock_hi else scs_clock_id; 
  state scs_clock_hi:if MDS then scs_clock_mid else scs_clock_hi;
  state scs_clock_mid:if MDS then scs_clock_fv else scs_clock_mid; 
  state scs_clock_fv:if MDS then scs_clock_done else scs_clock_fv;

  "We have transferred the clock message, so indicate to the timestamp counter"
  "that it can continue counting up."
  state scs_clock_done:goto scs_rest;

  "We fetch the message from the message decoder."
  state scs_message_fetch:
    if FDONE & !DUPLICATE & SETMATCH then scs_message_id;
    if FDONE & DUPLICATE then scs_message_done;
    if FDONE & !SETMATCH then scs_message_done;
    if !FDONE then scs_message_fetch;

  "We transfer the message id, high byte of data, low byte of data, and the"
  "low byte of the timestamp that constitute a transmitter message."
  state scs_message_id:if MDS then scs_message_hi else scs_message_id;
  state scs_message_hi:if MDS then scs_message_lo else scs_message_hi;
  state scs_message_lo:if MDS then scs_message_ts else scs_message_lo;
  state scs_message_ts:if MDS then scs_message_done else scs_message_ts;

  "We are done with the message, so indicate to the decoder that produced the"
  "message that it can continue detecting further messages."
  state scs_message_done:goto scs_rest;
equations

"Fetch message out of the Message Decoder."
FETCH = (scs==scs_message_fetch);

"Tell the Message Decoder to continue."
MDCNT = (scs==scs_message_done);

"Tell the timestamp that we have transferd the clock"
"message"
TSCNT = (scs==scs_clock_done);

"We indicate that the storage controller is not at rest, so"
"the timestamp controller can refrain from incrementing the"
"timestamp."
SCREST = (scs==scs_rest);

"The Message Ready bit indicates to the Message Router that we"
"have a byte to store in RAM."
MRDY = (scs == scs_clock_id) 
  # (scs == scs_clock_hi)
  # (scs == scs_clock_mid)
  # (scs == scs_clock_fv)
  # (scs == scs_message_id)
  # (scs == scs_message_hi)
  # (scs == scs_message_lo)
  # (scs == scs_message_ts);

"The Clock Message Store bit indicates to the Message Router"
"that we are about to store or are currently storing a clock"
"message."
CMST = (TSRDY & (scs == scs_rest))
  # (scs == scs_clock_id)
  # (scs == scs_clock_hi)
  # (scs == scs_clock_mid)
  # (scs == scs_clock_fv);

"We transmit a display command when we start storing a message."
TXDC = (scs == scs_message_id);
 

"Fake Message Data"
"-----------------"

"If we have problems with a Data Receiver, we can track them down with"
"the help of the fake message data, which is activated by the fake message"
"data constant."

declarations
FMD0..FMD7 node istype 'reg,pos'; "Fake Message Data"
fmd=[FMD7..FMD0];
equations

"The Fake Message Data is what we send to the Message Router instead"
"of real data to test if writing and reading from RAM are reliable."
"We use the LWDAQ Terminal Instrument to read blocks of data from"
"the Data Receiver and look at them on the screen to wath for glitches."
fmd.clk = DCK;
fmd.aclr = RESET;
when MDS then fmd:=fmd+1 else fmd:=fmd;


"Byte Multiplexer"
"----------------"

"Here we select which bytes to assert on the message data."
"Note that a bug in the ABEL compiler means that the code"
"does not compile properly if you make an outer conditional"
"with !fake_message_data and a sequence of inner conditionals"
"with the state vector. Instead, we have to put the fake"
"message conditional inside the state vector conditional, and"
"the code compiles correctly."

declarations
  BMA0..BMA7 node istype 'com,keep,dc'; "Byte Multiplexer A"
  bma=[BMA7..BMA0];
  BMB0..BMB7 node istype 'com,keep,dc'; "Byte Multiplexer B"
  bmb=[BMB7..BMB0];
  BMC0..BMC7 node istype 'com,keep,dc'; "Byte Multiplexer C"
  bmc=[BMC7..BMC0];
equations


when (scs==scs_clock_id) then { "Clock Message ID"
  when fake_message_data then message_data=fmd
  else {
    message_data = bma;
    bma = 0; 
  }
}
when (scs==scs_clock_hi) then { "High Byte of Timestamp"
  when fake_message_data then message_data=fmd
  else {
    message_data = bma;
    bma = tsb2; 
  }
}
when (scs==scs_clock_mid) then { "Middle Byte of Timestamp"
  when fake_message_data then message_data=fmd
  else {
    message_data = bma;
    bma = tsb1; 
  }
}
when (scs==scs_clock_fv) then {  "Firmwave Version"
  when fake_message_data then message_data=fmd
  else  {
    message_data = bma;
    bma = firmware_version; 
  }
}
when (scs==scs_message_id) then { "Message ID"
  when fake_message_data then message_data=fmd
  else {
    message_data = bmb;
    bmb = [ID7..ID4,M23..M20]; 
  }
}
when (scs==scs_message_hi) then { "High Byte of Sample"
  when fake_message_data then message_data=fmd
  else {
    message_data = bmb;
    bmb = bmc;
    bmc = [M19..M12]; 
  }
}
when (scs==scs_message_lo) then { "Low Byte of Sample"
  when fake_message_data then message_data=fmd
  else {
    message_data = bmb;
    bmb = bmc;
    bmc = [M11..M4]; 
  }
}
when (scs==scs_message_ts) then { "Low Byte Timestamp"
  when fake_message_data then message_data=fmd
  else {
    message_data = bmb;
    bmb = bmc;
    bmc = tsb0;
  } 
}


"Display Board Interface"
"-----------------------"

"We transmit eight-bit commands to the Display Board via the Message Router"
"to flash lights that indicate which antennas are receiving messages and"
"what channel numbers are active. These signals are restricted to activity"
"from transmitters with the set identifier selected by the set identifier"
"register in the Message Router."

declarations
  DCS3..DCS0 node istype 'reg';
  dcs = [DCS3..DCS0];
equations

"We clock dcs on the falling edge of DCK so that its state will be"
"changing at the same time as the value of the serial message data."
dcs.clk = !DCK;
dcs.aclr = RESET;
when dcs==0 then {
  when TXDC then dcs:=1 else dcs:=0;
}
when (dcs>=1) & (dcs<=9) then dcs:=dcs+1;
when dcs==10 then {
  when !FDONE then dcs:=0 else dcs:=10;
}

when dcs==0 then MDC = 0;
when dcs==1 then MDC = 1;
when dcs==2 then MDC = M23; "Channel ID 3"
when dcs==3 then MDC = M22; "Channel ID 2"
when dcs==4 then MDC = M21; "Channel ID 1"
when dcs==5 then MDC = M20; "Channel ID 0"
when dcs==6 then MDC = 0;
when dcs==7 then MDC = MSEL2;
when dcs==8 then MDC = MSEL1;
when dcs==9 then MDC = MSEL0;
when dcs==10 then MDC = 0;


"Receive Indicator Lamp"
"----------------------"

declarations
RECEIVE_A node istype 'reg';
equations

RECEIVE_A.ap = SHIFT;
RECEIVE_A.clk = SCK;
RECEIVE_A := 0;
RECEIVE.ap = RESET;
RECEIVE.clk = SCK;
RECEIVE := RECEIVE_A;


"Message Incoming for the Message Router"
"---------------------------------------"

MSGI = decoder1.RCV # decoder2.RCV # decoder3.RCV # decoder4.RCV
  # decoder5.RCV # decoder6.RCV # decoder7.RCV # decoder8.RCV;


"Digital Input-Output"
"--------------------"

"The Message Detector does not have much spare logic capacity, so"
"it cannot perform sophisticated handling of incoming logic signals."
"We use spare pins connecting the Message Detector and Message Router"
"to carry the serial signals."

"Set up Y1 as an output and let it transmit the signal sent from the"
"Message Router."
Y1O = Y1_IN;
Y1EN = 1;

"Set up Y2 as an output and let it transmit the signal sent from the"
"Message Router."
Y2O = Y2_IN;
Y2EN = 1;

"We set up X1 and X2 as outputs that assert the X1_IN and X2_IN signals from"
"the Message Router."
X1 = X1_IN;
X2 = X2_IN;


"Test Points"
"-----------"

TP3 = MDRDY;
TP4 = CMIMM;
TP6 = CMST;


end