"
MODULE P300403

TITLE 'P3004A03'

"Firmware for Transmitter with Logic Chip (A3004)

"Copyright (C) 2005 Kevan Hashemi, hashemi@brandeis.edu, Open 
"Source "Instruments Inc.

"This program is free software; you can redistribute it and/or
"modify it under the terms of the GNU General Public License
"as published by the Free Software Foundation; either version 2
"of the License, or (at your option) any later version.

"This program is distributed in the hope that it will be useful,
"but WITHOUT ANY WARRANTY; without even the implied warranty of
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
"GNU General Public License for more details.

"You should have received a copy of the GNU General Public License
"along with this program; if not, write to the Free Software
"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
"02111-1307, USA.

declarations

"Inputs and Outputs"
CK   pin 38; "Clock From 32-kHz Oscillator"
SCK pin 43; "Slow Clock, or Global CLK0, Connected to Pin 44"
SCKO pin 44; "Source of SCK"
FCK pin 18; "Fast Clock, or Global CLK1 Connected to Pin 17"
FCKO pin 17; "Source of CK1"
TCK pin 19; "Transmission Clock, or Global CLK2 Connected to Pin 20"
TCKO pin 20 istype 'reg'; "Source of CK2"
CK3 pin 42; "Global CLK3 Connected to Pin 41"
CK3O pin 41; "Source of CK3"
RELAY pin 40 istype 'com'; "Relay Connection"
TUNE pin 45 istype 'com'; "Tune Control for Transmitter"
!SHDN pin 34 istype 'com'; "Shutdown Control for Transmitter"
SRIN pin 21; "Serial Input from P2"
SRCK pin 22; "Serial Clock from P2"
TP1..TP3 pin 23,24,26 istype 'com'; "Test Points on P2"

"Nodes"
T0..T23 node istype 'reg'; "Timer Running off 32-kHz"
TC0..TC1 node istype 'com,keep'; "Timer Carry Bits"
R1..R4 node istype 'com,keep'; "Ring Oscillator"
D0..D3 node istype 'reg'; "Ring Oscillator Divider"
TXS0..TXS4 node istype 'reg,pos'; "Transmitter State"
ACTIVE node istype 'reg'; "Active period of 32-kHz"
TXD node istype 'com'; "Transmitter Done"
PMS1..PMS0 node istype 'reg,pos'; "Power Master State"
RELAYOE node istype 'com,keep'; "Drive Relay Ouput"

"Sets"
time = [T23..T0]; "Timer"
time_b2 = [T23..T16];
time_b1 = [T15..T8];
time_b0 = [T7..T0];
transmit_cycle = [T5..T0]; "Transmit Cycle Timer"
divider = [D3..D0]; "Ring Oscillator Divider"
txs = [TXS4..TXS0]; "Transmitter State"
pms = [PMS1..PMS0]; "Power Master State"

"Constants"
divider_end = 10;
pms_asleep_magnet = 0;
pms_asleep_no_magnet = 1;
pms_awake_magnet = 2;
pms_awake_no_magnet = 3;

equations

"We set SCK, one of the global clock pins, equal to"
"the 32-kHz input via the SCKOT pin."
SCKO=CK;

"The twenty-three bit timer runs off the 32-kHz clock"
time.clk=SCK;
time_b0:=time_b0+1;
TC0 = (time_b0==^hFF);
when TC0 then time_b1:=time_b1+1
else time_b1:=time_b1;
TC1 = (time_b1==^hFF);
when TC1 & TC0 then time_b2:=time_b2+1
else time_b2:=time_b2;

"The RELAY pin is connected to 0V through a reed relay"
"and a resistor. Whever transmit_cycle becomes zero, we"
"drive the RELAY pin high for the next half-period of"
"SCK. The Power Master checks the voltage on the RELAY"
"pin at the next rising edge of SCK. If the relay is"
"closed, RELAY.pin will be LO. If the relay is open,"
"the bus hold circuits on the input will hold RELAY.pin"
"HI."
RELAY=1;
RELAYOE=(transmit_cycle==0) & CK;
RELAY.oe=RELAYOE;

"The Power Master watches RELAY.pin and turns on and off"
"transmission as if the relay were a push-button."
pms.clk=SCK;
state_diagram pms;
  state pms_asleep_no_magnet:
    if !RELAY.pin then pms_asleep_magnet
    else pms_asleep_no_magnet;
  state pms_asleep_magnet:
    if RELAY.pin then pms_awake_no_magnet
    else pms_asleep_magnet;
  state pms_awake_no_magnet:
    if !RELAY.pin then pms_awake_magnet
    else pms_awake_no_magnet;
  state pms_awake_magnet:
    if RELAY.pin then pms_asleep_no_magnet
    else pms_awake_magnet;
equations

"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=!SCK;
ACTIVE:=(transmit_cycle>=0)&(transmit_cycle<=1)
  & ((pms==pms_awake_no_magnet)#(pms==pms_awake_magnet));

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

"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"
"therefore 4 ns multiplied by the number of gates."
[FCKO,R2..R1]=[R2..R1,!FCKO & ACTIVE & !TXD];

"The divider divides FCK."
divider.clk=FCK;
when (divider==divider_end) then divider:=0
else divider:=divider+1;

"We use the divider to create the TCK global clock pin through"
"TCKO."
TCKO.clk=!FCK;
when !TCKO then {
  when (divider==0) then TCKO:=1
  else TCKO:=0;
} else {
  when (divider==0) then TCKO:=0
  else TCKO:=1;
}

"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==31) then txs:=31
else txs:=txs+1;

"We use shutdown to turn on the VCO for the duration of
"the transmission.
SHDN=(txs==0)#(txs==31);

"We use TUNE to modulate the VCO output frequency between"
"875 MHz (zero) and 950 MHz (one).
TUNE= (
    ((txs>=1) & (txs<=4))
  # ((txs==6) & T23)
  # ((txs==7) & T22)
  # ((txs==8) & T21)
  # ((txs==9) & T20)
  # ((txs==10) & T19)
  # ((txs==11) & T18)
  # ((txs==12) & T17)
  # ((txs==13) & T16) 
  # ((txs==14) & T15) 
  # ((txs==15) & T14) 
  # ((txs==16) & T13)
  # ((txs==17) & T12)
  # ((txs==18) & T11)
  # ((txs==19) & T10)
  # ((txs==20) & T9)
  # ((txs==21) & T8)
  # ((txs==22) & T7)
  # ((txs==23) & T6)
  # (txs==30)
);


END