A sine wave generator using AD9833 and AD9850 using STM32F103RB

Dependencies:   mbed

This is a sine wave generator using DDS IC' AD9833 and AD9850. The STM32F1 microcontroller produces the SPI commands for the two DDS.

Learn more about STM32F1 in my blog: https://www.teachmemicro.com

Committer:
roland_tmm
Date:
Tue Nov 21 11:24:25 2017 +0000
Revision:
0:6069c0f2a245
Child:
2:602f7589c53e
Version 1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
roland_tmm 0:6069c0f2a245 1 /*
roland_tmm 0:6069c0f2a245 2 * AD9833.cpp
roland_tmm 0:6069c0f2a245 3 *
roland_tmm 0:6069c0f2a245 4 * Copyright 2016 Bill Williams <wlwilliams1952@gmail.com, github/BillWilliams1952>
roland_tmm 0:6069c0f2a245 5 *
roland_tmm 0:6069c0f2a245 6 * Thanks to john@vwlowen.co.uk for his work on the AD9833. His web page
roland_tmm 0:6069c0f2a245 7 * is: http://www.vwlowen.co.uk/arduino/AD9833-waveform-generator/AD9833-waveform-generator.htm
roland_tmm 0:6069c0f2a245 8 *
roland_tmm 0:6069c0f2a245 9 * This program is free software; you can redistribute it and/or modify
roland_tmm 0:6069c0f2a245 10 * it under the terms of the GNU General Public License as published by
roland_tmm 0:6069c0f2a245 11 * the Free Software Foundation; either version 2 of the License, or
roland_tmm 0:6069c0f2a245 12 * (at your option) any later version.
roland_tmm 0:6069c0f2a245 13 *
roland_tmm 0:6069c0f2a245 14 * This program is distributed in the hope that it will be useful,
roland_tmm 0:6069c0f2a245 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
roland_tmm 0:6069c0f2a245 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
roland_tmm 0:6069c0f2a245 17 * GNU General Public License for more details.
roland_tmm 0:6069c0f2a245 18 *
roland_tmm 0:6069c0f2a245 19 * You should have received a copy of the GNU General Public License
roland_tmm 0:6069c0f2a245 20 * along with this program; if not, write to the Free Software
roland_tmm 0:6069c0f2a245 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
roland_tmm 0:6069c0f2a245 22 * MA 02110-1301, USA.
roland_tmm 0:6069c0f2a245 23 *
roland_tmm 0:6069c0f2a245 24 */
roland_tmm 0:6069c0f2a245 25 #include "mbed.h"
roland_tmm 0:6069c0f2a245 26 #include "AD9833.h"
roland_tmm 0:6069c0f2a245 27
roland_tmm 0:6069c0f2a245 28 #define SPI_MOSI PA_7
roland_tmm 0:6069c0f2a245 29 #define SPI_MISO PA_6
roland_tmm 0:6069c0f2a245 30 #define SPI_SCK PA_5
roland_tmm 0:6069c0f2a245 31 #define FNCpin PA_4
roland_tmm 0:6069c0f2a245 32
roland_tmm 0:6069c0f2a245 33 DigitalOut fnc_pin(FNCpin);
roland_tmm 0:6069c0f2a245 34 SPI SPI_dev(SPI_MOSI, SPI_MISO, SPI_SCK);
roland_tmm 0:6069c0f2a245 35
roland_tmm 0:6069c0f2a245 36 /*
roland_tmm 0:6069c0f2a245 37 * Create an AD9833 object
roland_tmm 0:6069c0f2a245 38 */
roland_tmm 0:6069c0f2a245 39 AD9833 :: AD9833 (uint32_t referenceFrequency ) {
roland_tmm 0:6069c0f2a245 40 // Pin used to enable SPI communication (active LOW)
roland_tmm 0:6069c0f2a245 41
roland_tmm 0:6069c0f2a245 42 FNCWrite(1);
roland_tmm 0:6069c0f2a245 43
roland_tmm 0:6069c0f2a245 44 /* TODO: The minimum resolution and max frequency are determined by
roland_tmm 0:6069c0f2a245 45 * by referenceFrequency. We should calculate these values and use
roland_tmm 0:6069c0f2a245 46 * them during setFrequency. The problem is if the user programs a
roland_tmm 0:6069c0f2a245 47 * square wave at refFrequency/2, then changes the waveform to sine.
roland_tmm 0:6069c0f2a245 48 * The sine wave will not have enough points?
roland_tmm 0:6069c0f2a245 49 */
roland_tmm 0:6069c0f2a245 50 refFrequency = referenceFrequency;
roland_tmm 0:6069c0f2a245 51
roland_tmm 0:6069c0f2a245 52 // Setup some defaults
roland_tmm 0:6069c0f2a245 53 DacDisabled = false;
roland_tmm 0:6069c0f2a245 54 IntClkDisabled = false;
roland_tmm 0:6069c0f2a245 55 outputEnabled = false;
roland_tmm 0:6069c0f2a245 56 waveForm0 = waveForm1 = SINE_WAVE;
roland_tmm 0:6069c0f2a245 57 frequency0 = frequency1 = 1000; // 1 KHz sine wave to start
roland_tmm 0:6069c0f2a245 58 phase0 = phase1 = 0.0; // 0 phase
roland_tmm 0:6069c0f2a245 59 activeFreq = REG0; activePhase = REG0;
roland_tmm 0:6069c0f2a245 60 }
roland_tmm 0:6069c0f2a245 61
roland_tmm 0:6069c0f2a245 62 /*
roland_tmm 0:6069c0f2a245 63 * This MUST be the first command after declaring the AD9833 object
roland_tmm 0:6069c0f2a245 64 * Start SPI and place the AD9833 in the RESET state
roland_tmm 0:6069c0f2a245 65 */
roland_tmm 0:6069c0f2a245 66 void AD9833 :: Begin ( void ) {
roland_tmm 0:6069c0f2a245 67 wait(0.1);
roland_tmm 0:6069c0f2a245 68 Reset(); // Hold in RESET until first WriteRegister command
roland_tmm 0:6069c0f2a245 69 }
roland_tmm 0:6069c0f2a245 70
roland_tmm 0:6069c0f2a245 71 /*
roland_tmm 0:6069c0f2a245 72 * Setup and apply a signal. phaseInDeg defaults to 0.0 if not supplied.
roland_tmm 0:6069c0f2a245 73 * phaseReg defaults to value of freqReg if not supplied.
roland_tmm 0:6069c0f2a245 74 * Note that any previous calls to EnableOut,
roland_tmm 0:6069c0f2a245 75 * SleepMode, DisableDAC, or DisableInternalClock remain in effect.
roland_tmm 0:6069c0f2a245 76 */
roland_tmm 0:6069c0f2a245 77 void AD9833 :: ApplySignal ( WaveformType waveType,
roland_tmm 0:6069c0f2a245 78 Registers freqReg, float frequencyInHz,
roland_tmm 0:6069c0f2a245 79 Registers phaseReg, float phaseInDeg ) {
roland_tmm 0:6069c0f2a245 80 SetGENFrequency ( freqReg, frequencyInHz );
roland_tmm 0:6069c0f2a245 81 SetPhase ( phaseReg, phaseInDeg );
roland_tmm 0:6069c0f2a245 82 SetWaveform ( freqReg, waveType );
roland_tmm 0:6069c0f2a245 83 SetOutputSource ( freqReg, phaseReg );
roland_tmm 0:6069c0f2a245 84 }
roland_tmm 0:6069c0f2a245 85
roland_tmm 0:6069c0f2a245 86 /***********************************************************************
roland_tmm 0:6069c0f2a245 87 Control Register
roland_tmm 0:6069c0f2a245 88 ------------------------------------------------------------------------
roland_tmm 0:6069c0f2a245 89 D15,D14(MSB) 10 = FREQ1 write, 01 = FREQ0 write,
roland_tmm 0:6069c0f2a245 90 11 = PHASE write, 00 = control write
roland_tmm 0:6069c0f2a245 91 D13 If D15,D14 = 00, 0 = individual LSB and MSB FREQ write,
roland_tmm 0:6069c0f2a245 92 1 = both LSB and MSB FREQ writes consecutively
roland_tmm 0:6069c0f2a245 93 If D15,D14 = 11, 0 = PHASE0 write, 1 = PHASE1 write
roland_tmm 0:6069c0f2a245 94 D12 0 = writing LSB independently
roland_tmm 0:6069c0f2a245 95 1 = writing MSB independently
roland_tmm 0:6069c0f2a245 96 D11 0 = output FREQ0,
roland_tmm 0:6069c0f2a245 97 1 = output FREQ1
roland_tmm 0:6069c0f2a245 98 D10 0 = output PHASE0
roland_tmm 0:6069c0f2a245 99 1 = output PHASE1
roland_tmm 0:6069c0f2a245 100 D9 Reserved. Must be 0.
roland_tmm 0:6069c0f2a245 101 D8 0 = RESET disabled
roland_tmm 0:6069c0f2a245 102 1 = RESET enabled
roland_tmm 0:6069c0f2a245 103 D7 0 = internal clock is enabled
roland_tmm 0:6069c0f2a245 104 1 = internal clock is disabled
roland_tmm 0:6069c0f2a245 105 D6 0 = onboard DAC is active for sine and triangle wave output,
roland_tmm 0:6069c0f2a245 106 1 = put DAC to sleep for square wave output
roland_tmm 0:6069c0f2a245 107 D5 0 = output depends on D1
roland_tmm 0:6069c0f2a245 108 1 = output is a square wave
roland_tmm 0:6069c0f2a245 109 D4 Reserved. Must be 0.
roland_tmm 0:6069c0f2a245 110 D3 0 = square wave of half frequency output
roland_tmm 0:6069c0f2a245 111 1 = square wave output
roland_tmm 0:6069c0f2a245 112 D2 Reserved. Must be 0.
roland_tmm 0:6069c0f2a245 113 D1 If D5 = 1, D1 = 0.
roland_tmm 0:6069c0f2a245 114 Otherwise 0 = sine output, 1 = triangle output
roland_tmm 0:6069c0f2a245 115 D0 Reserved. Must be 0.
roland_tmm 0:6069c0f2a245 116 ***********************************************************************/
roland_tmm 0:6069c0f2a245 117
roland_tmm 0:6069c0f2a245 118 /*
roland_tmm 0:6069c0f2a245 119 * Hold the AD9833 in RESET state.
roland_tmm 0:6069c0f2a245 120 * Resets internal registers to 0, which corresponds to an output of
roland_tmm 0:6069c0f2a245 121 * midscale - digital output at 0.
roland_tmm 0:6069c0f2a245 122 *
roland_tmm 0:6069c0f2a245 123 * The difference between Reset() and EnableOutput(false) is that
roland_tmm 0:6069c0f2a245 124 * EnableOutput(false) keeps the AD9833 in the RESET state until you
roland_tmm 0:6069c0f2a245 125 * specifically remove the RESET state using EnableOutput(true).
roland_tmm 0:6069c0f2a245 126 * With a call to Reset(), ANY subsequent call to ANY function (other
roland_tmm 0:6069c0f2a245 127 * than Reset itself and Set/IncrementPhase) will also remove the RESET
roland_tmm 0:6069c0f2a245 128 * state.
roland_tmm 0:6069c0f2a245 129 */
roland_tmm 0:6069c0f2a245 130 void AD9833 :: Reset ( void ) {
roland_tmm 0:6069c0f2a245 131 WriteRegister(RESET_CMD);
roland_tmm 0:6069c0f2a245 132 wait(0.015);
roland_tmm 0:6069c0f2a245 133 }
roland_tmm 0:6069c0f2a245 134
roland_tmm 0:6069c0f2a245 135 /*
roland_tmm 0:6069c0f2a245 136 * Set the specified frequency register with the frequency (in Hz)
roland_tmm 0:6069c0f2a245 137 */
roland_tmm 0:6069c0f2a245 138 void AD9833 :: SetGENFrequency ( Registers freqReg, float frequency ) {
roland_tmm 0:6069c0f2a245 139 // TODO: calculate max frequency based on refFrequency.
roland_tmm 0:6069c0f2a245 140 // Use the calculations for sanity checks on numbers.
roland_tmm 0:6069c0f2a245 141 // Sanity check on frequency: Square - refFrequency / 2
roland_tmm 0:6069c0f2a245 142 // Sine/Triangle - refFrequency / 4
roland_tmm 0:6069c0f2a245 143 if ( frequency > 12.5e6 ) // TODO: Fix this based on refFreq
roland_tmm 0:6069c0f2a245 144 frequency = 12.5e6;
roland_tmm 0:6069c0f2a245 145 if ( frequency < 0.0 ) frequency = 0.0;
roland_tmm 0:6069c0f2a245 146
roland_tmm 0:6069c0f2a245 147 // Save frequency for use by IncrementFrequency function
roland_tmm 0:6069c0f2a245 148 if ( freqReg == REG0 ) frequency0 = frequency;
roland_tmm 0:6069c0f2a245 149 else frequency1 = frequency;
roland_tmm 0:6069c0f2a245 150
roland_tmm 0:6069c0f2a245 151 int32_t freqWord = (frequency * pow2_28) / (float)refFrequency;
roland_tmm 0:6069c0f2a245 152 int16_t upper14 = (int16_t)((freqWord & 0xFFFC000) >> 14),
roland_tmm 0:6069c0f2a245 153 lower14 = (int16_t)(freqWord & 0x3FFF);
roland_tmm 0:6069c0f2a245 154
roland_tmm 0:6069c0f2a245 155 // Which frequency register are we updating?
roland_tmm 0:6069c0f2a245 156 uint16_t reg = freqReg == REG0 ? FREQ0_WRITE_REG : FREQ1_WRITE_REG;
roland_tmm 0:6069c0f2a245 157 lower14 |= reg;
roland_tmm 0:6069c0f2a245 158 upper14 |= reg;
roland_tmm 0:6069c0f2a245 159
roland_tmm 0:6069c0f2a245 160 // I do not reset the registers during write. It seems to remove
roland_tmm 0:6069c0f2a245 161 // 'glitching' on the outputs.
roland_tmm 0:6069c0f2a245 162 WriteControlRegister();
roland_tmm 0:6069c0f2a245 163 // Control register has already been setup to accept two frequency
roland_tmm 0:6069c0f2a245 164 // writes, one for each 14 bit part of the 28 bit frequency word
roland_tmm 0:6069c0f2a245 165 WriteRegister(lower14); // Write lower 14 bits to AD9833
roland_tmm 0:6069c0f2a245 166 WriteRegister(upper14); // Write upper 14 bits to AD9833
roland_tmm 0:6069c0f2a245 167 }
roland_tmm 0:6069c0f2a245 168
roland_tmm 0:6069c0f2a245 169 /*
roland_tmm 0:6069c0f2a245 170 * Increment the specified frequency register with the frequency (in Hz)
roland_tmm 0:6069c0f2a245 171 */
roland_tmm 0:6069c0f2a245 172 void AD9833 :: IncrementFrequency ( Registers freqReg, float freqIncHz ) {
roland_tmm 0:6069c0f2a245 173 // Add/subtract a value from the current frequency programmed in
roland_tmm 0:6069c0f2a245 174 // freqReg by the amount given
roland_tmm 0:6069c0f2a245 175 float frequency = (freqReg == REG0) ? frequency0 : frequency1;
roland_tmm 0:6069c0f2a245 176 SetGENFrequency(freqReg,frequency+freqIncHz);
roland_tmm 0:6069c0f2a245 177 }
roland_tmm 0:6069c0f2a245 178
roland_tmm 0:6069c0f2a245 179 /*
roland_tmm 0:6069c0f2a245 180 * Set the specified phase register with the phase (in degrees)
roland_tmm 0:6069c0f2a245 181 * The output signal will be phase shifted by 2π/4096 x PHASEREG
roland_tmm 0:6069c0f2a245 182 */
roland_tmm 0:6069c0f2a245 183 void AD9833 :: SetPhase ( Registers phaseReg, float phaseInDeg ) {
roland_tmm 0:6069c0f2a245 184 // Sanity checks on input
roland_tmm 0:6069c0f2a245 185 phaseInDeg = fmod(phaseInDeg,360);
roland_tmm 0:6069c0f2a245 186 if ( phaseInDeg < 0 ) phaseInDeg += 360;
roland_tmm 0:6069c0f2a245 187
roland_tmm 0:6069c0f2a245 188 // Phase is in float degrees ( 0.0 - 360.0 )
roland_tmm 0:6069c0f2a245 189 // Convert to a number 0 to 4096 where 4096 = 0 by masking
roland_tmm 0:6069c0f2a245 190 uint16_t phaseVal = (uint16_t)(BITS_PER_DEG * phaseInDeg) & 0x0FFF;
roland_tmm 0:6069c0f2a245 191 phaseVal |= PHASE_WRITE_CMD;
roland_tmm 0:6069c0f2a245 192
roland_tmm 0:6069c0f2a245 193 // Save phase for use by IncrementPhase function
roland_tmm 0:6069c0f2a245 194 if ( phaseReg == REG0 ) {
roland_tmm 0:6069c0f2a245 195 phase0 = phaseInDeg;
roland_tmm 0:6069c0f2a245 196 }
roland_tmm 0:6069c0f2a245 197 else {
roland_tmm 0:6069c0f2a245 198 phase1 = phaseInDeg;
roland_tmm 0:6069c0f2a245 199 phaseVal |= PHASE1_WRITE_REG;
roland_tmm 0:6069c0f2a245 200 }
roland_tmm 0:6069c0f2a245 201 WriteRegister(phaseVal);
roland_tmm 0:6069c0f2a245 202 }
roland_tmm 0:6069c0f2a245 203
roland_tmm 0:6069c0f2a245 204 /*
roland_tmm 0:6069c0f2a245 205 * Increment the specified phase register by the phase (in degrees)
roland_tmm 0:6069c0f2a245 206 */
roland_tmm 0:6069c0f2a245 207 void AD9833 :: IncrementPhase ( Registers phaseReg, float phaseIncDeg ) {
roland_tmm 0:6069c0f2a245 208 // Add/subtract a value from the current phase programmed in
roland_tmm 0:6069c0f2a245 209 // phaseReg by the amount given
roland_tmm 0:6069c0f2a245 210 float phase = (phaseReg == REG0) ? phase0 : phase1;
roland_tmm 0:6069c0f2a245 211 SetPhase(phaseReg,phase + phaseIncDeg);
roland_tmm 0:6069c0f2a245 212 }
roland_tmm 0:6069c0f2a245 213
roland_tmm 0:6069c0f2a245 214 /*
roland_tmm 0:6069c0f2a245 215 * Set the type of waveform that is output for a frequency register
roland_tmm 0:6069c0f2a245 216 * SINE_WAVE, TRIANGLE_WAVE, SQUARE_WAVE, HALF_SQUARE_WAVE
roland_tmm 0:6069c0f2a245 217 */
roland_tmm 0:6069c0f2a245 218 void AD9833 :: SetWaveform ( Registers waveFormReg, WaveformType waveType ) {
roland_tmm 0:6069c0f2a245 219 // TODO: Add more error checking?
roland_tmm 0:6069c0f2a245 220 if ( waveFormReg == REG0 )
roland_tmm 0:6069c0f2a245 221 waveForm0 = waveType;
roland_tmm 0:6069c0f2a245 222 else
roland_tmm 0:6069c0f2a245 223 waveForm1 = waveType;
roland_tmm 0:6069c0f2a245 224 WriteControlRegister();
roland_tmm 0:6069c0f2a245 225 }
roland_tmm 0:6069c0f2a245 226
roland_tmm 0:6069c0f2a245 227 /*
roland_tmm 0:6069c0f2a245 228 * EnableOutput(false) keeps the AD9833 is RESET state until a call to
roland_tmm 0:6069c0f2a245 229 * EnableOutput(true). See the Reset function description.
roland_tmm 0:6069c0f2a245 230 */
roland_tmm 0:6069c0f2a245 231 void AD9833 :: EnableOutput ( bool enable ) {
roland_tmm 0:6069c0f2a245 232 outputEnabled = enable;
roland_tmm 0:6069c0f2a245 233 WriteControlRegister();
roland_tmm 0:6069c0f2a245 234 }
roland_tmm 0:6069c0f2a245 235
roland_tmm 0:6069c0f2a245 236 /*
roland_tmm 0:6069c0f2a245 237 * Set which frequency and phase register is being used to output the
roland_tmm 0:6069c0f2a245 238 * waveform. If phaseReg is not supplied, it defaults to the same
roland_tmm 0:6069c0f2a245 239 * register as freqReg.
roland_tmm 0:6069c0f2a245 240 */
roland_tmm 0:6069c0f2a245 241 void AD9833 :: SetOutputSource ( Registers freqReg, Registers phaseReg ) {
roland_tmm 0:6069c0f2a245 242 // TODO: Add more error checking?
roland_tmm 0:6069c0f2a245 243 activeFreq = freqReg;
roland_tmm 0:6069c0f2a245 244 if ( phaseReg == SAME_AS_REG0 ) activePhase = activeFreq;
roland_tmm 0:6069c0f2a245 245 else activePhase = phaseReg;
roland_tmm 0:6069c0f2a245 246 WriteControlRegister();
roland_tmm 0:6069c0f2a245 247 }
roland_tmm 0:6069c0f2a245 248
roland_tmm 0:6069c0f2a245 249 //---------- LOWER LEVEL FUNCTIONS NOT NORMALLY NEEDED -------------
roland_tmm 0:6069c0f2a245 250
roland_tmm 0:6069c0f2a245 251 /*
roland_tmm 0:6069c0f2a245 252 * Disable/enable both the internal clock and the DAC. Note that square
roland_tmm 0:6069c0f2a245 253 * wave outputs are avaiable if using an external Reference.
roland_tmm 0:6069c0f2a245 254 * TODO: ?? IS THIS TRUE ??
roland_tmm 0:6069c0f2a245 255 */
roland_tmm 0:6069c0f2a245 256 void AD9833 :: SleepMode ( bool enable ) {
roland_tmm 0:6069c0f2a245 257 DacDisabled = enable;
roland_tmm 0:6069c0f2a245 258 IntClkDisabled = enable;
roland_tmm 0:6069c0f2a245 259 WriteControlRegister();
roland_tmm 0:6069c0f2a245 260 }
roland_tmm 0:6069c0f2a245 261
roland_tmm 0:6069c0f2a245 262 /*
roland_tmm 0:6069c0f2a245 263 * Enables / disables the DAC. It will override any previous DAC
roland_tmm 0:6069c0f2a245 264 * setting by Waveform type, or via the SleepMode function
roland_tmm 0:6069c0f2a245 265 */
roland_tmm 0:6069c0f2a245 266 void AD9833 :: DisableDAC ( bool enable ) {
roland_tmm 0:6069c0f2a245 267 DacDisabled = enable;
roland_tmm 0:6069c0f2a245 268 WriteControlRegister();
roland_tmm 0:6069c0f2a245 269 }
roland_tmm 0:6069c0f2a245 270
roland_tmm 0:6069c0f2a245 271 /*
roland_tmm 0:6069c0f2a245 272 * Enables / disables the internal clock. It will override any
roland_tmm 0:6069c0f2a245 273 * previous clock setting by the SleepMode function
roland_tmm 0:6069c0f2a245 274 */
roland_tmm 0:6069c0f2a245 275 void AD9833 :: DisableInternalClock ( bool enable ) {
roland_tmm 0:6069c0f2a245 276 IntClkDisabled = enable;
roland_tmm 0:6069c0f2a245 277 WriteControlRegister();
roland_tmm 0:6069c0f2a245 278 }
roland_tmm 0:6069c0f2a245 279
roland_tmm 0:6069c0f2a245 280 // ------------ STATUS / INFORMATION FUNCTIONS -------------------
roland_tmm 0:6069c0f2a245 281 /*
roland_tmm 0:6069c0f2a245 282 * Return actual frequency programmed
roland_tmm 0:6069c0f2a245 283 */
roland_tmm 0:6069c0f2a245 284 float AD9833 :: GetActualProgrammedFrequency ( Registers reg ) {
roland_tmm 0:6069c0f2a245 285 float frequency = reg == REG0 ? frequency0 : frequency1;
roland_tmm 0:6069c0f2a245 286 int32_t freqWord = (uint32_t)((frequency * pow2_28) / (float)refFrequency) & 0x0FFFFFFFUL;
roland_tmm 0:6069c0f2a245 287 return (float)freqWord * (float)refFrequency / (float)pow2_28;
roland_tmm 0:6069c0f2a245 288 }
roland_tmm 0:6069c0f2a245 289
roland_tmm 0:6069c0f2a245 290 /*
roland_tmm 0:6069c0f2a245 291 * Return actual phase programmed
roland_tmm 0:6069c0f2a245 292 */
roland_tmm 0:6069c0f2a245 293 float AD9833 :: GetActualProgrammedPhase ( Registers reg ) {
roland_tmm 0:6069c0f2a245 294 float phase = reg == REG0 ? phase0 : phase1;
roland_tmm 0:6069c0f2a245 295 uint16_t phaseVal = (uint16_t)(BITS_PER_DEG * phase) & 0x0FFF;
roland_tmm 0:6069c0f2a245 296 return (float)phaseVal / BITS_PER_DEG;
roland_tmm 0:6069c0f2a245 297 }
roland_tmm 0:6069c0f2a245 298
roland_tmm 0:6069c0f2a245 299 /*
roland_tmm 0:6069c0f2a245 300 * Return frequency resolution
roland_tmm 0:6069c0f2a245 301 */
roland_tmm 0:6069c0f2a245 302 float AD9833 :: GetResolution ( void ) {
roland_tmm 0:6069c0f2a245 303 return (float)refFrequency / (float)pow2_28;
roland_tmm 0:6069c0f2a245 304 }
roland_tmm 0:6069c0f2a245 305
roland_tmm 0:6069c0f2a245 306 // --------------------- PRIVATE FUNCTIONS --------------------------
roland_tmm 0:6069c0f2a245 307
roland_tmm 0:6069c0f2a245 308 /*
roland_tmm 0:6069c0f2a245 309 * Write control register. Setup register based on defined states
roland_tmm 0:6069c0f2a245 310 */
roland_tmm 0:6069c0f2a245 311 void AD9833 :: WriteControlRegister ( void ) {
roland_tmm 0:6069c0f2a245 312 uint16_t waveForm;
roland_tmm 0:6069c0f2a245 313 // TODO: can speed things up by keeping a writeReg0 and writeReg1
roland_tmm 0:6069c0f2a245 314 // that presets all bits during the various setup function calls
roland_tmm 0:6069c0f2a245 315 // rather than setting flags. Then we could just call WriteRegister
roland_tmm 0:6069c0f2a245 316 // directly.
roland_tmm 0:6069c0f2a245 317 if ( activeFreq == REG0 ) {
roland_tmm 0:6069c0f2a245 318 waveForm = waveForm0;
roland_tmm 0:6069c0f2a245 319 waveForm &= ~FREQ1_OUTPUT_REG;
roland_tmm 0:6069c0f2a245 320 }
roland_tmm 0:6069c0f2a245 321 else {
roland_tmm 0:6069c0f2a245 322 waveForm = waveForm1;
roland_tmm 0:6069c0f2a245 323 waveForm |= FREQ1_OUTPUT_REG;
roland_tmm 0:6069c0f2a245 324 }
roland_tmm 0:6069c0f2a245 325 if ( activePhase == REG0 )
roland_tmm 0:6069c0f2a245 326 waveForm &= ~PHASE1_OUTPUT_REG;
roland_tmm 0:6069c0f2a245 327 else
roland_tmm 0:6069c0f2a245 328 waveForm |= PHASE1_OUTPUT_REG;
roland_tmm 0:6069c0f2a245 329 if ( outputEnabled )
roland_tmm 0:6069c0f2a245 330 waveForm &= ~RESET_CMD;
roland_tmm 0:6069c0f2a245 331 else
roland_tmm 0:6069c0f2a245 332 waveForm |= RESET_CMD;
roland_tmm 0:6069c0f2a245 333 if ( DacDisabled )
roland_tmm 0:6069c0f2a245 334 waveForm |= DISABLE_DAC;
roland_tmm 0:6069c0f2a245 335 else
roland_tmm 0:6069c0f2a245 336 waveForm &= ~DISABLE_DAC;
roland_tmm 0:6069c0f2a245 337 if ( IntClkDisabled )
roland_tmm 0:6069c0f2a245 338 waveForm |= DISABLE_INT_CLK;
roland_tmm 0:6069c0f2a245 339 else
roland_tmm 0:6069c0f2a245 340 waveForm &= ~DISABLE_INT_CLK;
roland_tmm 0:6069c0f2a245 341
roland_tmm 0:6069c0f2a245 342 WriteRegister ( waveForm );
roland_tmm 0:6069c0f2a245 343 }
roland_tmm 0:6069c0f2a245 344
roland_tmm 0:6069c0f2a245 345 void AD9833 :: FNCWrite(int val){
roland_tmm 0:6069c0f2a245 346 fnc_pin = val;
roland_tmm 0:6069c0f2a245 347 }
roland_tmm 0:6069c0f2a245 348
roland_tmm 0:6069c0f2a245 349 void AD9833 :: WriteRegister ( int16_t dat ) {
roland_tmm 0:6069c0f2a245 350 /*
roland_tmm 0:6069c0f2a245 351 * We set the mode here, because other hardware may be doing SPI also
roland_tmm 0:6069c0f2a245 352 */
roland_tmm 0:6069c0f2a245 353 SPI_dev.format(8, 2);
roland_tmm 0:6069c0f2a245 354
roland_tmm 0:6069c0f2a245 355 /* Improve overall switching speed
roland_tmm 0:6069c0f2a245 356 * Note, the times are for this function call, not the write.
roland_tmm 0:6069c0f2a245 357 * digitalWrite(FNCpin) ~ 17.6 usec
roland_tmm 0:6069c0f2a245 358 * digitalWriteFast2(FNC_PIN) ~ 8.8 usec
roland_tmm 0:6069c0f2a245 359 */
roland_tmm 0:6069c0f2a245 360 FNCWrite(0); // FNCpin low to write to AD9833
roland_tmm 0:6069c0f2a245 361
roland_tmm 0:6069c0f2a245 362 //delayMicroseconds(2); // Some delay may be needed
roland_tmm 0:6069c0f2a245 363
roland_tmm 0:6069c0f2a245 364 // TODO: Are we running at the highest clock rate?
roland_tmm 0:6069c0f2a245 365 SPI_dev.write(dat & 0xF0); // Transmit 16 bits 8 bits at a time
roland_tmm 0:6069c0f2a245 366 SPI_dev.write(dat & 0x0F);
roland_tmm 0:6069c0f2a245 367
roland_tmm 0:6069c0f2a245 368 FNCWrite(1); // Write done
roland_tmm 0:6069c0f2a245 369 }