"

MODULE P3019

TITLE 'P3019A'

"NOTE: For all versions, make sure the compiler sets all inputs"
"to input HOLD rather than PULLUP or PULLDOWN."

"Version 1:"
"[17-JUN-10] Improve ID definition with use of dummy nodes."
"[31-MAR-10] Start with A3020A01 and make slight modifications to"
"pin numbers."
"[07-APR-10] Learn that we can't drive U4-1 tristate input with 3V"
"logic. So will cut track to U4-1. Thus remove CKEN signal from code."
"Add enable_test_pins to allow reduction fo 1.3 uA in ON current."

"Version 2:"
"[01-JUN-2012] Add support for sample rates higher than 512 SPS."
"We must set scatter_xmit to 2 for 2048 SPS to reduce the scatter"
"width to less than one period. We correct the sample time clock"
"so that it resets when it reaches tck_divisor-1."

"Version 3:"
"[01-JAN-14] Change the ring oscillator calibration so as to guarantee"
"the mark-space ratio is 50%, sacrificing frequency resolition. We remove"
"the code that dealt with auxilliary channel transmission. We tidy up the"
"top of the code to make the essential calibration parameters more prominent."

"Calibration Parameters"
id = 1; "Transmitter ID number, 1-14."
fck_divisor = 13; "Fast Clock Divisor, gives 5 MHz from ring oscillator."
frequency_low = 9; "Set the lower of the two RF frequencies for transmission."

"Other Parameters"
tck_divisor = 64; "max transmit cycle timer + 1"
frequency_step=2; "HI frequency - LO frequency"
scatter_xmit=1; "Turn on scattering of transmission instants."
enable_rf=1; "Turns on RF oscillator during transmission"
num_sync_bits=11; "Number of synchronizing bits at transmission start."
enable_test_pins=1; "Disable for final program, saves 2uA."

"Inputs and Outputs"
CK pin A7; "Clock From 32-kHz Oscillator"
F4..F0 pin C10,D10,E10,G10,H10 istype 'reg'; "DAC for frequency"
!SHDN pin G1 istype 'com'; "Shutdown Control for Transmitter"
TP1 pin A1 istype 'com'; "Test Point"
TP2 pin C3 istype 'com'; "Test Point"
CONV pin A4 istype 'com'; "Convert for ADC"
SDI pin F1 istype 'com,pos'; "Serial Data In for ADC"
SDO pin D1; "Serial Data Out for ADC"
SCK pin C1 istype 'com'; "Serial Clock for ADC"

"Nodes"
FCK node istype 'com,keep'; "Fast Clock"
TCK node istype 'reg'; "Transmission Clock"
ECK node istype 'reg'; "End Clock"
T0..T5 node istype 'reg'; "Timer Running off 32-kHz"
R1 node istype 'com,keep'; "Ring Oscillator Bit"
TXS0..TXS5 node istype 'reg,pos'; "Transmitter State"
ACTIVE node istype 'reg'; "Active period of 32-kHz"
TXD node istype 'com,keep'; "Transmitter Done"
TCD3..TCD0 node istype 'reg'; "Transmit Clock Divider"
TCDZ node istype 'reg'; "Transmit Clock Divider Zero"
ADC0..ADC3 node istype 'reg'; "ADC Bits"
TTS0..TTS3 node istype 'reg'; "Transmit Time Shift"
SDOS node istype 'reg'; "SDO Synchronized"
RSC3..RSC0 node istype 'reg'; "Reference Signal Counter"
IDR3..IDR0 node istype 'com'; "Transmitter ID Registser Nodes"

"Sets"
idr = [IDR3..IDR0]; "Transmitter ID Register"
time = [T5..T0]; "Transmit Cycle Timer"
tcd = [TCD3..TCD0]; "Transmit Clock Divider"
txs = [TXS5..TXS0]; "Transmitter State"
adc_bits = [ADC3..ADC0]; "ADC Bits"
xmit_time_shift = [TTS3..TTS0]; "Transmit Time Shift"
active_time = [0,0,TTS3..TTS0]; "Active Time"
frequency = [F4..F0]; "Frequency Voltage"
ref_signal_count = [RSC3..RSC0]; "Reference Signal Counter"

"Constants"
num_id_bits = 4; "Number of ID bits"
num_start_bits = 1; "Transmitted zero to mark data start"
num_stop_bits = 2; "Not transmitted, for txs termination"
num_data_bits = 16; "Number of ADC data bits"
num_xmit_bits = "Number of transmission bit periods"
    num_sync_bits
  + num_start_bits
  + num_id_bits
  + num_data_bits
  + num_id_bits; 
txs_done = "Final state of txs machine"
    num_xmit_bits
  + num_stop_bits; 
first_sync_bit = 1;
first_start_bit = first_sync_bit + num_sync_bits;
first_id_bit = first_start_bit + num_start_bits;
first_data_bit = first_id_bit + num_id_bits;
first_iid_bit = first_data_bit + num_data_bits;
start_sck = "The txs state for first SCK falling edge"
    first_data_bit - 1;
end_sck = "The txs state for last SCK falling edge"
    start_sck
  + num_data_bits - 1;

equations

"The transmit cycle timer runs off the 32-kHz clock and"
"counts up to tck_divisor-1."
time.clk=CK;
when (time==tck_divisor-1) then {
  time:=0;
} else {
  time:=time+1;
}

"The ECK clock sets the active_time register at the"
"end of a cycle of tck_divisor CK periods."
ECK.clk=CK;
ECK:=(time==tck_divisor-2);

"When ACTIVE is asserted, we begin a burst transmission."
"When it is unasserted, we reset the burst transmission"
"state machine. We must make sure that ACTIVE remains true"
"for long enough for the burst transmission to complete."
ACTIVE.clk=CK;
ACTIVE:= (time==active_time);

"TXD is true when the transmitter completes its burst"
"transmission."
TXD=(txs==txs_done);

"We set the transmitter ID register."
idr = id;

"The ring oscillator turns on when ACTIVE and remains"
"on until TXD. Each gate in the ring adds 2 ns to the"
"delay around the ring. The period of the oscillation is"
"4 ns multiplied by the number of gates."
[FCK,R1]=[R1,!FCK & ACTIVE & !TXD];

"The transmit clock divider runs off FCK and divides it down"
"to 5 MHz by correct choice of fck_divisor during transmitter"
"calibration."
tcd.aclr=!ACTIVE;
tcd.clk=FCK;
when (tcd==0) then {
  tcd:=fck_divisor-1;
}
when (tcd>0) then {
  tcd:=tcd-1;
}

"We detect the transmit clock divider being zero with TCDZ."
TCDZ.clk=FCK;
TCDZ.aclr=!ACTIVE;
TCDZ:=(tcd==0);

"The transmit clock should be close to or a little less than 5 MHz,"
"with a mark-space ratio of exactly 50%. So we clock it with the top"
"bit of the transmit clock divider."
TCK.aclr=!ACTIVE;
TCK.clk=TCDZ;
TCK := !TCK;

"The transmitter state machine steps through all its"
"states when ACTIVE is asserted, and then stops in its"
"final state, waiting for !ACTIVE, which will reset it"
"to zero."
txs.clk=TCK;
txs.aclr=!ACTIVE;
when (txs==txs_done) then txs:=txs
else txs:=txs+1;

"We clock frequency with the rising edge of FCK."
frequency.clk=FCK;

"Transmit sixteen ADC bits."
when ACTIVE & (txs>0) & (txs=1)&(txs=first_start_bit)&(txs=first_data_bit)&(txs=start_sck) & (txs<=end_sck) & !TCK;

"We configure the ADC for single-ended input by setting"
"SDI to 1 on the first rising edge of SCK after CONV goes"
"low."
when txs==start_sck then SDI=1;

"We select the main or auxilliary channel by setting"
"SDI equal to 1 for main (channel 1) and 0 for auxilliary"
"(channel 0) on the second rising edge of SCK after CONV"
"goes low. This selection affects the next ADC conversion."
when txs==start_sck+1 then SDI=1;

"Test Points"
when (enable_test_pins != 0) then {
  TP1=(frequency==frequency_low+frequency_step);
  TP2=CK;
} {
  TP1=0;
  TP2=0;
}

END