"
module P3007C

title 'P3007C'

"Version 7, Fix severe bug in the Receiver, where we were waiting"
"for rising or falling edges for 120 us instead of 200 ns. Bad"
"message rate in basement lab dropped from several per second"
"to per minute."

"Version 6, Added diagnostic functions that help us find problems"
"in the storage and retrieval of messages from RAM. Removed the"
"fast_messages function because we are now committed to 5 MBPS."
"In order to test writing and reading from RAM, set fake_write_data"
"and fake_ramp and fake_messages to 1 so that the RAM Controller will"
"store fake message in RAM as fast as it can. You may now unplug"
"the Data Recorder from its RF circuit and the RAM Controller will"
"store a repeating gray-scale ramp 0 to 255. Read this out with the"
"LWDAQ Terminal instrument set to image width 1024 and height 550"
"and set the rx_size to 524288 so as to read the entire RAM."
"You will see the entire 512 KBytes of the Data Recorder memory displayed"
"with four gray-scale stripes running top to bottom, assuming everything"
"is working. If you have a problem, try disabling the read and write"
"from RAM by setting fake_transmit_data to 1. Now you will get a"
"a repeating 0-255 ramp generated by the state machine that uploads"
"bytes to the LWDAQ Driver."

"Verion 5, Is identical to Version 4 except the test points are"
"devoted to upload to the driver instead of monitoring message"
"reception."

"Version 4 introduces a new format for messages in RAM. The"
"ID now occupies one byte. This allows the Recorder software"
"to support up to 255 different channels. The data occupies"
"two consecutive bytes. The timestamp is the final byte, as"
"before. But the clock message timestamp is now forced equal"
"to firmware_version, so that a stretch of four zeros is"
"impossible. The Recorder can use such a stretch of zeros"
"as a the start and end-marker for blocks of messages. Also,"
"the presense of the firmware version will allow later versions"
"of the Recoder software to be compatible with future versions"
"of this firmware."

"Version 4 takes care of a minor bug that affected 25 out of"
"every million messages received (about 0.01 messages/s on a"
"512 SPS channel). It is now impossible for a message to be"
"stored with timestamp 0 before the clock message corresponding"
"to timestamp 0 has been stored." 

"Version 3 receives SCT messages with bit rate 5 MBPS (200 ns)"
"or 2.5 MBPS (400 ns). Use fast_messages to set the bit rate."
"With fast_messages set to 1, the message clock is 40 MHz (25 ns)"
"so we have eight clock cycles in one 200-ns bit time."
"With fast_messages set to 0, the message clock is 20 MHz (50 ns)"
"so we again have eight clock cycles in one bit time of 400 ns."

"We use TP7 as a marker for message storage. We use TP8 to indicate"
"reception of a message-like bit sequence."

declarations
  firmware_version=^d7;
  min_sync_edges=5; 
  num_message_bits=24;
  fake_transmit_data=0;
  fake_write_data=0;
  fake_ramp=0;
  fake_messages=0;
equations

"Pins"
declarations
A pin 3; "LVDS input"
B pin 10 istype 'com'; "LVDS output"
C pin 43; "Comparator Output"
LB pin 8 istype 'com'; "Loop Back"
!RESET pin 22;"Hardware Reset"			
ARCK pin 20; "Asynchronous 32.768 kHz reference clock input"
DCKI pin 27; "Data Clock input from crystal oscillator"
DCK pin 39; "Data Clock on Global CLK2"
DCKO pin 42 istype 'com'; "Source of DCK"
!RW pin 59 istype 'com'; "RAM Write"
!RCE pin 66 istype 'reg'; "RAM Chip Enable"
!ROE pin 6 istype 'com'; "RAM Output Enable"
RA18..RA0 pin 85,80,79,78,16,17,19,31,30,53,
  54,55,56,58,67,69,70,71,72 istype 'com'; "RAM Address"
ram_addr = [RA18..RA0];
RD7..RD0 pin 9,11,14,15,60,61,64,65 istype 'com'; "RAM Data"
ram_data = [RD7..RD0];
RECEIVE pin 93 istype 'reg'; "Receive Indicator, through monostable"
UPLOAD pin 84 istype 'com'; "Upload Indicator, through monostable"
EMPTY pin 97 istype 'com'; "Empty Indicator, direct to LED"
TP7 pin 47 istype 'com'; "Test Point 7"
TP8 pin 48 istype 'com'; "Test Point 8"
equations


"Clock Generation"
"----------------"

DCKO = DCKI;


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

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

declarations
RCK node istype 'reg'; "Reference Clock"
equations

RCK.clk = DCK;
RCK := ARCK;


"LWDAQ Command and Address Decoding"
"----------------------------------"

"This LWDAQ receiver uses the 40-MHz data clock to generate"
"the DA and DDA signals. We synchronise the incoming serial"
"logic signal, A, with the data clock."

declarations
SA node istype 'reg'; "Synchronized A"
DSA node istype 'reg'; "Delayed SA"
DA node istype 'com,keep'; "Delayed A Rising Edge"
DDA node istype 'com,keep'; "Delayed DA"
AA node istype 'reg'; "Address Active"
DAA node istype 'reg'; "Delayed AA"
CA node istype 'reg'; "Command Active"
DCA node istype 'reg'; "Delayed CA"
ER,Q1..Q16 node istype 'reg'; "Receiver Bits"
LT3..LT0 node istype 'reg'; "LWDAQ Timer"
lt = [LT3..LT0];
AS node istype 'reg'; "Address Strobe"
CS node istype 'reg'; "Command Strobe"
DS node istype 'reg'; "Data Strobe"
DC1..DC16 node istype 'reg';"Device Command Bits"
DA0..DA15 node istype 'reg';"Device Address Bits"
WAKE node istype 'com'; "Wake"
DTX node istype 'com'; "Device Transmit"
ATR node istype 'com'; "Address and Timestamp Reset"
equations

"We synchronize A with DCK, and provide a delayed"
"version of A that allows us to detect edges."
[SA,DSA].clk = DCK;
[SA,DSA].aclr = RESET;
SA := A;
DSA := SA;

"This timer allows us to generate the Delayed A (DA)"
"and Double-Delayed A (DDA) signals for serial reception."
lt.clk = DCK;
lt.aclr = RESET;
when lt==0 then {
  when SA & !DSA then lt:=1
  else lt:=0;
} else {
  when lt==9 then lt:=0
  else lt:=lt+1;
}
DA = (lt==4);
DDA = (lt==9);

"We use DCK to clock the receiver registers, and RESET to"
"clear them."
[ER,Q1..Q16,AA,DAA,AS,CA,DCA,CS,DS,DC1..DC16,DA0..DA15].clk = DCK;
[ER,Q1..Q16,AA,DAA,AS,CA,DCA,CS,DS,DC1..DC16,DA0..DA15].aclr = RESET;

"We move bits along the shift register on DA."
when DA then [ER,Q1..Q16] := [SA,ER,Q1..Q15];
else [ER,Q1..Q16] := [ER,Q1..Q16];

"Address Active provides a pulse that begins with DDA"
"on the start bit of an address transmission, and ends"
"with the stop bit of an address transmission. Delayed"
"AA allows us to create Address Strobe, or AS. Address"
"Strobe provides a pulse at the end of an address"
"reception. We clock the receiver bits into the address"
"register on a rusing edge of AS."
when DDA then AA := (!AA & !CA & !SA & !ER) # (AA & !SA)
else AA := AA;
DAA := AA;
AS := DAA & !AA;
when AS then [DA0..DA15] := [Q1..Q16]
else [DA0..DA15] := [DA0..DA15];

"Command Active provides a pulse that begins with DDA"
"on the start bit of a command transmission, and ends"
"with the stop bit of a command transmission. Delayed"
"CA allows us to create Command Strobe, or CS. Command"
"strobe provides a pulse at the end of each command"
"reception. We clock the receiver bits into the command"
"register on a rusing edge of CS."
when DDA then CA := (!AA & !CA & !SA & ER) # (CA & !SA)
else CA := CA;
DCA := CA;
CS := DCA & !CA;
when CS then [DC1..DC16] := [Q1..Q16]
else [DC1..DC16] := [DC1..DC16];

"Data Strobe identifies a solitary low pulse on A. A"
"solitary low pulse, combined with DTX, indicates that"
"the drivers is expecting this device to upload eight"
"bits of data."
DS := DDA & SA & !AA & !CA;

"Address and Timestamp Reset"
ATR = DC1 # RESET;

"Device Transmit Bit"
DTX = DC5;

"We loop back A to B so long as DTX is not set."
when !DTX then B = A;

"We enable the return LVDS driver when DC7 is set."
LB = DC7;

"WAKE bit."
WAKE = DC8;


"Data Transmitter"
"----------------"

"The transmitter sends bytes back to the driver. It waits for"
"DS combined with DTX (DC5). When it receives DS and DTX, it"
"waits for Transmission Byte Load (TBL). The transmitter uses"
"DCK to time its serial transmission to the driver. It transmits"
"a leading zero followed by the eight bits of the transmission"
"byte (tb)."

declarations
TS4..TS0 node istype 'reg'; "Transmit State"
TBD7..TBD0 node istype 'reg'; "Transmission Bits"
ts=[TS4..TS0];"Transmission State"
tbd=[TBD7..TBD0]; "Transmission Byte Data"
TBL node istype 'reg,pos'; "Transmitter Byte Load"
TBO node istype 'com,keep'; "Transmitter Bit Out"
equations

"We assert Transmit Byte Load, TBL, elsewhere in the code"
"when we want to clock ram_data.pin into the Transmit Byte."
TBL.clk = DCK;
TBL.aclr = RESET; 

"The Transmit Byte, tb, holds a byte for transmission to"
"the LWDAQ driver."
tbd.clk = DCK;
tbd.aclr = RESET;

"The Transmitter State, ts, controls serial transmission"
"to the LWDAQ driver of the Transmi Byte."
ts.clk = DCK;
ts.aclr = RESET;
state_diagram ts;
  state 0:if DS & DTX then 1 else 0;
  state 1:
    if !DTX then 0;
    if DTX & TBL then 2;
    if DTX & !TBL then 1;
  state 2:goto 3;"Start Bit"
  state 3:goto 4;"Start Bit"
  state 4:goto 5;"TBD7"
  state 5:goto 6;"TBD7"
  state 6:goto 7;
  state 7:goto 8;
  state 8:goto 9;
  state 9:goto 10;
  state 10:goto 11;
  state 11:goto 12;
  state 12:goto 13;
  state 13:goto 14;
  state 14:goto 15;
  state 15:goto 16;
  state 16:goto 17;
  state 17:goto 18;
  state 18:goto 19;"TBD0"
  state 19:goto 20;"TBD0"
  state 20:goto 0;"Stop Bit"
equations;

"TBO is the output of the bit transmitter. It passes through"
"the LVDS return and so along the cables to the driver."
TBO = (
    (ts==0)  & 1   "Idle Bit 1"
  # (ts==1)  & 1   "Idle Bit 1"
  # (ts==2)  & 0   
  # (ts==3)  & 0
  # (ts==4)  & TBD7
  # (ts==5)  & TBD7
  # (ts==6)  & TBD6
  # (ts==7)  & TBD6
  # (ts==8)  & TBD5
  # (ts==9)  & TBD5
  # (ts==10) & TBD4
  # (ts==11) & TBD4
  # (ts==12) & TBD3
  # (ts==13) & TBD3
  # (ts==14) & TBD2
  # (ts==15) & TBD2
  # (ts==16) & TBD1
  # (ts==17) & TBD1
  # (ts==18) & TBD0
  # (ts==19) & TBD0
  # (ts==20) & 1   "Stop Bit 1"
);

"We return TBO to the driver when DTX is set."
when DTX then B = TBO;

"We load the transmitter byte from the RAM data bus. When"
"some other part of the firmware asserts TBL."
when !fake_transmit_data then {
  when TBL then tbd:=ram_data.pin;
  else tbd:=tbd;
}

"We can generate fake data to check for errors in the"
"upload to the LWDAQ driver, as opposed to errors in"
"RF reception."
when fake_transmit_data then {
  TBL := 1;
  when (ts==20) then {tbd:=tbd+1;} else {tbd:=tbd;}
}



"Receiver"
"--------"

declarations
SC node istype 'reg'; "Synchronized C"
DSC node istype 'reg'; "Delayed SC"
RVS4..RVS0 node istype 'reg'; "Receiver State"
rvs=[RVS4..RVS0];
RVD23..RVD0 node istype 'reg'; "Receiver Data"
rvd=[RVD23..RVD0];
EC3..EC0 node istype 'reg'; "Edge Counter"
ec=[EC3..EC0];
BC4..BC0 node istype 'reg'; "Bit Counter"
bc=[BC4..BC0];
DONE node istype 'com,keep'; "Done Receiving"
MSTORED node istype 'com,keep'; "Message Stored in RAM"
MATCH node istype 'com,keep'; "ID Match"
equations

[SC,DSC].clk = DCK;
SC := C;
DSC := SC;

declarations
rvs_rest = ^d0;

rvs_s1 = 1;
rvs_s2 = 2;
rvs_s3 = 3;
rvs_s4 = 4;
rvs_s5 = 5;

rvs_s6 = 6;
rvs_s7 = 7;

rvs_clr_ec = 8;

rvs_r2 = 9;
rvs_r3 = 10;
rvs_r4 = 11;
rvs_r5 = 12;
rvs_r6 = 13;

rvs_receive_1 = 14;
rvs_receive_2 = 15;
rvs_receive_3 = 16;
rvs_receive_4 = 17;

rvs_one = 18;
rvs_zero =19;
rvs_check = 20;
rvs_store = 21;
equations

rvs.clk = DCK;
rvs.aclr = RESET;
state_diagram rvs;
  state rvs_rest: "Waiting for a rising edge."
    if SC & !DSC then rvs_s1
    else rvs_rest;
  state rvs_s1: "Check for !SC too soon"
    if !SC then rvs_clr_ec
    else rvs_s2;
  state rvs_s2: "Check for !SC too soon"
    if !SC then rvs_clr_ec
    else rvs_s3;
  state rvs_s3:"Check for !SC."
    if !SC then rvs_s6
    else rvs_s4;
  state rvs_s4:"Check for !SC."
    if !SC then rvs_s6
    else rvs_s5;
  state rvs_s5:
    "If SC, and we have enough edges already,
    "this is a start bit."
    if SC & (ec>=min_sync_edges) then rvs_receive_1
    "But if SC and we don't have enough edges"
    "already, this is an error, so clear the"
    "edge counter to zero and go back to rest." 
    else if SC & (ec=rvs_r2;
"TP7 = RCE & !RW;
TP8 = RA17;

end