module P2065B title 'P2065B' "Version 1." "This code calibrates the chip's ring oscillator" "on power-up, and so consumes a bunch of gates. It" "then has to save gate in the LWDAQ receiver by" "using the un-latched incoming data bits. That was" "okay when you use the inclinometer without a" "multiplexer. With a multiplexer, it gets messed" "up by the address transmission when we switch from" "the inclinometer branch to another branch. Capacitors" "discharge, and the first waveform to be recorded on" "the next acquisition is offset out of the driver's" "dynamic range." "Pins" A pin 70; "LVDS input" B pin 59 istype 'com'; "LVDS output" LB pin 60 istype 'com'; "Loop Back" !RESET pin 72;"RESET" RCK pin 93; "32 kHz clock input" SCK pin 89; "Slow Clock on Global CLK0" SCKO pin 92 istype 'com'; "Source of SCK" VCK pin 38; "Variable Clock on Global CLK1" VCKO pin 37 istype 'com'; "Source of VCK" DA pin 39 istype 'com';"Delayed A Clock on Global CLK2" DAO pin 42 istype 'com'; "Source of DA" DDA pin 88 istype 'com';"Double-Delayed A Clock on Global CLK3" DDAO pin 86 istype 'com'; "Source of DDA" SQR pin 50 istype 'com'; "Square Wave" DXP pin 6 istype 'com'; "Drive X+" SXP pin 4 istype 'com'; "Select X+" DXM pin 3 istype 'com'; "Drive X-" SXM pin 5 istype 'com'; "Select X-" DYP pin 17 istype 'com'; "Drive Y+" SYP pin 16 istype 'com'; "Select Y+" DYM pin 8 istype 'com'; "Drive Y-" SYM pin 19 istype 'com'; "Select Y-" SCTR pin 20 istype 'com'; "Select Center" SSIN pin 22 istype 'com'; "Select SIN" SCOM pin 28 istype 'com'; "Select VCOM" SGND pin 21 istype 'com'; "Select Ground" "Nodes" WAKE node istype 'com'; "WAKE" R1..R2 node istype 'com,keep'; "Ring Oscillator" RUN node istype 'reg'; "Run Ring Oscillator" RUNRST node istype 'com'; "Run Reset" CS1..CS0 node istype 'reg'; "Calibration State" CC15..CC0 node istype 'reg'; "Clock Calibration" CCLC node istype 'com,keep'; "Clock Calibration Lo Carry" P2..P0 node istype 'reg'; "Pulse" CD4..CD0 node istype 'reg'; "Clock Divider" ACTIVE node istype 'reg,keep';"transmission active" RAE node istype 'reg,keep'; "Receive Active End" CS node istype 'reg,keep';"Command Strobe" ER,Q1..Q16 node istype 'reg';"Receiver Bits" DC1..DC16 node istype 'reg';"Device Command Bits" "Sets" cs=[CS1..CS0]; "Calibration State" calib=[CC15..CC0]; "Ring Oscillator Calibration" calib_lo=[CC7..CC0]; "Calibration LO Byte" calib_hi=[CC15..CC8]; "Calibration HI Byte" ps=[P2..P0]; "Pulse State" div=[CD4..CD0]; "CK divider" equations "Clocks" "------" "Slow Clock" SCKO = RCK; "Controller State" cs.clk=SCK; cs.aclr=RESET; state_diagram cs; state 0: if (calib==^hFFFF) then 1 else 0; "wait for 65,536 periods of SCK" state 1: goto 2; "clear calibration counter" state 2: goto 3; "count ring periods in SCK period" state 3: goto 3; "enable pulse generator" equations "Calibration Counter" calib.clk=VCK; calib.aclr=RESET; when (cs==0) then { VCKO=RCK; CCLC=(calib_lo==^hFF); calib_lo:=calib_lo+1; when CCLC then calib_hi:=calib_hi+1 else calib_hi:=calib_hi; } when (cs==1) then { VCKO=RCK; calib:=0; } when (cs==2) then { [VCKO,R2,R1]=[R2,R1,!VCKO]; CCLC=(calib_lo==^hFF); calib_lo:=calib_lo+1; when CCLC then calib_hi:=calib_hi+1 else calib_hi:=calib_hi; } when (cs==3) then { [VCKO,R2,R1]=[RUN & R2,R1,!VCKO]; calib_hi:=calib_hi; when (ps==0) then calib_lo:=calib_hi; when (ps==1) then calib_lo:=calib_lo-1; when (ps==3) then calib_lo:=calib_hi; when (ps==2) then calib_lo:=calib_lo-1; when (ps==6) then calib_lo:=calib_hi; } RUN.aclr = RUNRST; RUN.clk = A; RUN := (cs==3); RUNRST = RESET # (ps==6); ps.aclr = RUNRST; ps.clk = VCK; state_diagram ps state 0:if RUN then 1 else 0; state 1:if (calib_lo==0) then 3 else 1; state 3:goto 2; state 2:if (calib_lo==0) then 6 else 2; state 6:goto 0; equations DAO = !(ps==1); DDAO = !(ps==2); "Serial Input Decoding" "---------------------" "We assert ACTIVE whenever the driver is transmitting" "a command data bit." ACTIVE.aclr = RESET; ACTIVE.clk = DDA; ACTIVE := !A; "We clock the receiver shift register and the entry" "register with DA, and we clear them on RESET." [ER,Q1..Q16].clk = DA; [ER,Q1..Q16].aclr = RESET; [ER,Q1..Q16] := [A,ER,Q1..Q15]; "Receive Active End allows us to end a reception." RAE.clk = DDA; RAE := A; RAE.aclr = !CS; "Command Strobe provides a falling edge at the end of" "a command transmission." CS.clk = ACTIVE; CS:= ER; CS.aclr = RAE; "We clock the receiver bits into the command register" "on a rising edge of CS." [DC1..DC16].clk = !CS; [DC1..DC16].aclr = RESET; [DC1..DC16] := [Q1..Q16]; "Wake the sine wave generator." WAKE = 1; "We enable the return LVDS driver when DC7 is set." LB = DC7; "We loop back the synchronized value of A to the driver." B = A; "Command Bit Allocation" "----------------------" "In order to pack this code into a 64-cell logic chip, we use" "the Q bits rather than the DC bits. We use the first three" "bits, Q1..Q3, to select which signal will be returned to the" "driver. We have to make sure that [Q1..Q3] == 0 corresponds" "to the return of VCOM, or else the LWDAQ loop-back won't work." SCOM = ([Q3..Q1] == 0); SGND = ([Q3..Q1] == 1); SSIN = ([Q3..Q1] == 2); SCTR = ([Q3..Q1] == 3); SXP = ([Q3..Q1] == 4); SXM = ([Q3..Q1] == 5); SYP = ([Q3..Q1] == 6); SYM = ([Q3..Q1] == 7); "When Q4 and Q5 are zero, we drive all four outer pins of the" "sensor. By driving the sensor, we make sure all the coupling" "capacitors are charged correctly before we begin acquisition." "If we don't pre-charge the coupling capacitors, the sin waves" "will be offset for the first few measurements as the capacitors" "charge up. This offset can be large enough to drive the sin" "waves out of the range of the driver's ADC." DXP = !Q4; DXM = !Q4; DYP = !Q5; DYM = !Q5; "Square Wave Generator" "---------------------" div.aclr=RESET; div.clk=SCK; when div==0 then div:=27 else div:=div-1; SQR = WAKE & (div<14); "test point on board" end