The FM code you just ran (also listed here) is fairly
straightforward. The program first calls the
radioinit subroutine. This routine sets the
DDS to single-tone mode and turns off an inverse-sinc filter
to conserve power. Following radioinit, the
setcarrier subroutine is called. This routine
sets the frequency of the DDS output by writing to the two
most significant 8-bit frequency registers of the 48-bit
frequency-tuning word on the DDS. Although the
frequency-tuning word on the DDS has 48 bits of resolution,
the upper 16 bits provide us with enough resolution for the
purposes of this lab, and so we will only be writing to the
two most significant registers. See page 26 in
the DDS data sheet for a layout of the frequency-tuning
word.
To set the carrier frequency, we first need to determine what
frequency word has to be written to the frequency registers on
the DDS. This can be done using Equation 1:
Frequency word=baseband frequency
60
MHz
248
Frequency word
baseband frequency
60
MHz
2
48
(1)
where
baseband frequency corresponds to the
desired frequency that lies in the range of 0-30 MHz. For
example, to get the DDS to transmit at 104.9 MHz, you would
choose the baseband frequency to be 15.1 MHz since 104.9 MHz
is one of the unfiltered spectral replicas of 15.1 MHz.
Then, using
Equation 1, the frequency word for
15.1 MHz (and 104.9 MHz) would be equal to
406D 3A06
D3D4h. But since we only write to the two most
significant registers of the frequency-tuning word, we only
need the first 4 hexadecimal numbers of this result,
i.e.
406Dh. The first two of those,
40h, need to get written to the most
significant 8-bit frequency register, while the second two
hex numbers,
6Dh, need to get written to the
second-most significant 8-bit frequency register. This is
where the
40h and
6Dh in the
setcarrier subroutine of the FM code come from.
Writing to the frequency registers is accomplished using the
portw instruction. To write to the frequency
or phase registers on the DDS, the second operand of the
portw instruction must be
10xxxxxx, where the lower six bits are the
address of the specific register to be written to. The
address of the most significant frequency register on the
DDS is 04h, and the address of the second most
significant frequency register on the DDS is
05h (see page 26 in the data
sheet). It is important to note that the way our DDS boards
were built, you will not be allowed to make two consecutive
writes. To solve this problem, a subroutine called
nullop is called to waste some CPU time between
writes. nullop does this by simply repeating
the nop instruction 128 times.
After the program returns from the setcarrier
subroutine, it enters an infinite loop in which it waits for
a serial interrupt to occur. The serial interrupt occurs
every time a new sample is acquired from one of the two
input channels and is transmitted to the DSP via the serial
port. When the interrupt occurs, an interrupt service
routine called ANALOG_IFC (see
core_mod.asm executes and calls the
handle_sample subroutine. The
handle_sample subroutine reads in the acquired
sample from the serial port and scales that sample so that
it can be "mapped" to a frequency in the range of ±75
kHz. The scaled sample therefore
determines the frequency deviation and is added to
6Dh. The last step is to write the result to
the second most significant frequency register so that the
frequency of the DDS output can be updated.