dds: support amplitude tuning on AD9914

Closes #108
This commit is contained in:
Raghavendra Srinivas 2015-09-05 13:14:01 -06:00 committed by Sebastien Bourdeauducq
parent 2921bd6501
commit b3831d3387
4 changed files with 38 additions and 14 deletions

View File

@ -89,6 +89,17 @@ class _DDSGeneric:
word.""" word."""
return pow/2**self.pow_width return pow/2**self.pow_width
@portable
def amplitude_to_asf(self, amplitude):
"""Returns amplitude scale factor corresponding to given amplitude."""
return round(amplitude*0x0fff)
@portable
def asf_to_amplitude(self, asf):
"""Returns the amplitude corresponding to the given amplitude scale
factor."""
return round(amplitude*0x0fff)
@kernel @kernel
def init(self): def init(self):
"""Resets and initializes the DDS channel. """Resets and initializes the DDS channel.
@ -117,12 +128,14 @@ class _DDSGeneric:
self.phase_mode = phase_mode self.phase_mode = phase_mode
@kernel @kernel
def set_mu(self, frequency, phase=0, phase_mode=_PHASE_MODE_DEFAULT): def set_mu(self, frequency, phase=0, phase_mode=_PHASE_MODE_DEFAULT,
amplitude=0x0fff):
"""Sets the DDS channel to the specified frequency and phase. """Sets the DDS channel to the specified frequency and phase.
This uses machine units (FTW and POW). The frequency tuning word width This uses machine units (FTW and POW). The frequency tuning word width
is 32, whereas the phase offset word width depends on the type of DDS is 32, whereas the phase offset word width depends on the type of DDS
chip and can be retrieved via the ``pow_width`` attribute. chip and can be retrieved via the ``pow_width`` attribute. The amplitude
width is 12.
:param frequency: frequency to generate. :param frequency: frequency to generate.
:param phase: adds an offset, in turns, to the phase. :param phase: adds an offset, in turns, to the phase.
@ -132,13 +145,15 @@ class _DDSGeneric:
if phase_mode == _PHASE_MODE_DEFAULT: if phase_mode == _PHASE_MODE_DEFAULT:
phase_mode = self.phase_mode phase_mode = self.phase_mode
syscall("dds_set", now_mu(), self.channel, frequency, syscall("dds_set", now_mu(), self.channel, frequency,
phase, phase_mode) phase, phase_mode, amplitude)
@kernel @kernel
def set(self, frequency, phase=0.0, phase_mode=_PHASE_MODE_DEFAULT): def set(self, frequency, phase=0.0, phase_mode=_PHASE_MODE_DEFAULT,
amplitude=1.0):
"""Like ``set_mu``, but uses Hz and turns.""" """Like ``set_mu``, but uses Hz and turns."""
self.set_mu(self.frequency_to_ftw(frequency), self.set_mu(self.frequency_to_ftw(frequency),
self.turns_to_pow(phase), phase_mode) self.turns_to_pow(phase), phase_mode,
self.amplitude_to_asf(amplitude))
class AD9858(_DDSGeneric): class AD9858(_DDSGeneric):

View File

@ -25,7 +25,7 @@ _syscalls = {
"dds_init": "Ii:n", "dds_init": "Ii:n",
"dds_batch_enter": "I:n", "dds_batch_enter": "I:n",
"dds_batch_exit": "n:n", "dds_batch_exit": "n:n",
"dds_set": "Iiiii:n", "dds_set": "Iiiiii:n",
} }

View File

@ -19,7 +19,7 @@
#define DURATION_DAC_CAL (147000 << RTIO_FINE_TS_WIDTH) #define DURATION_DAC_CAL (147000 << RTIO_FINE_TS_WIDTH)
/* not counting final FUD */ /* not counting final FUD */
#define DURATION_INIT (10*DURATION_WRITE + DURATION_DAC_CAL) #define DURATION_INIT (10*DURATION_WRITE + DURATION_DAC_CAL)
#define DURATION_PROGRAM (5*DURATION_WRITE) /* not counting FUD */ #define DURATION_PROGRAM (6*DURATION_WRITE) /* not counting FUD */
#else #else
#error Unknown DDS configuration #error Unknown DDS configuration
@ -94,7 +94,7 @@ void dds_init(long long int timestamp, int channel)
static unsigned int continuous_phase_comp[DDS_CHANNEL_COUNT]; static unsigned int continuous_phase_comp[DDS_CHANNEL_COUNT];
static void dds_set_one(long long int now, long long int ref_time, unsigned int channel, static void dds_set_one(long long int now, long long int ref_time, unsigned int channel,
unsigned int ftw, unsigned int pow, int phase_mode) unsigned int ftw, unsigned int pow, int phase_mode, unsigned int amplitude)
{ {
unsigned int channel_enc; unsigned int channel_enc;
@ -130,7 +130,8 @@ static void dds_set_one(long long int now, long long int ref_time, unsigned int
DDS_WRITE(DDS_CFR2, 0x00); DDS_WRITE(DDS_CFR2, 0x00);
#endif #endif
#ifdef DDS_AD9914 #ifdef DDS_AD9914
DDS_WRITE(DDS_CFR1L, 0x0008); /* Disable autoclear phase accumulator and enables OSK. */
DDS_WRITE(DDS_CFR1L, 0x0108);
#endif #endif
pow += continuous_phase_comp[channel]; pow += continuous_phase_comp[channel];
} else { } else {
@ -141,7 +142,8 @@ static void dds_set_one(long long int now, long long int ref_time, unsigned int
DDS_WRITE(DDS_CFR2, 0x40); DDS_WRITE(DDS_CFR2, 0x40);
#endif #endif
#ifdef DDS_AD9914 #ifdef DDS_AD9914
DDS_WRITE(DDS_CFR1L, 0x2008); /* Enable autoclear phase accumulator and enables OSK. */
DDS_WRITE(DDS_CFR1L, 0x2108);
#endif #endif
fud_time = now + 2*DURATION_WRITE; fud_time = now + 2*DURATION_WRITE;
pow -= (ref_time - fud_time)*DDS_RTIO_CLK_RATIO*ftw >> (32-DDS_POW_WIDTH); pow -= (ref_time - fud_time)*DDS_RTIO_CLK_RATIO*ftw >> (32-DDS_POW_WIDTH);
@ -156,6 +158,9 @@ static void dds_set_one(long long int now, long long int ref_time, unsigned int
#endif #endif
#ifdef DDS_AD9914 #ifdef DDS_AD9914
DDS_WRITE(DDS_POW, pow); DDS_WRITE(DDS_POW, pow);
#endif
#ifdef DDS_AD9914
DDS_WRITE(DDS_ASF, amplitude);
#endif #endif
DDS_WRITE(DDS_FUD, 0); DDS_WRITE(DDS_FUD, 0);
} }
@ -165,6 +170,7 @@ struct dds_set_params {
unsigned int ftw; unsigned int ftw;
unsigned int pow; unsigned int pow;
int phase_mode; int phase_mode;
unsigned int amplitude;
}; };
static int batch_mode; static int batch_mode;
@ -193,14 +199,15 @@ void dds_batch_exit(void)
now = batch_ref_time - batch_count*(DURATION_PROGRAM + DURATION_WRITE); now = batch_ref_time - batch_count*(DURATION_PROGRAM + DURATION_WRITE);
for(i=0;i<batch_count;i++) { for(i=0;i<batch_count;i++) {
dds_set_one(now, batch_ref_time, dds_set_one(now, batch_ref_time,
batch[i].channel, batch[i].ftw, batch[i].pow, batch[i].phase_mode); batch[i].channel, batch[i].ftw, batch[i].pow, batch[i].phase_mode,
batch[i].amplitude);
now += DURATION_PROGRAM + DURATION_WRITE; now += DURATION_PROGRAM + DURATION_WRITE;
} }
batch_mode = 0; batch_mode = 0;
} }
void dds_set(long long int timestamp, int channel, void dds_set(long long int timestamp, int channel,
unsigned int ftw, unsigned int pow, int phase_mode) unsigned int ftw, unsigned int pow, int phase_mode, unsigned int amplitude)
{ {
if(batch_mode) { if(batch_mode) {
if(batch_count >= DDS_MAX_BATCH) if(batch_count >= DDS_MAX_BATCH)
@ -210,9 +217,11 @@ void dds_set(long long int timestamp, int channel,
batch[batch_count].ftw = ftw; batch[batch_count].ftw = ftw;
batch[batch_count].pow = pow; batch[batch_count].pow = pow;
batch[batch_count].phase_mode = phase_mode; batch[batch_count].phase_mode = phase_mode;
batch[batch_count].amplitude = amplitude;
batch_count++; batch_count++;
} else { } else {
rtio_chan_sel_write(RTIO_DDS_CHANNEL); rtio_chan_sel_write(RTIO_DDS_CHANNEL);
dds_set_one(timestamp - DURATION_PROGRAM, timestamp, channel, ftw, pow, phase_mode); dds_set_one(timestamp - DURATION_PROGRAM, timestamp, channel, ftw, pow, phase_mode,
amplitude);
} }
} }

View File

@ -59,6 +59,6 @@ void dds_init(long long int timestamp, int channel);
void dds_batch_enter(long long int timestamp); void dds_batch_enter(long long int timestamp);
void dds_batch_exit(void); void dds_batch_exit(void);
void dds_set(long long int timestamp, int channel, void dds_set(long long int timestamp, int channel,
unsigned int ftw, unsigned int pow, int phase_mode); unsigned int ftw, unsigned int pow, int phase_mode, unsigned int amplitude);
#endif /* __DDS_H */ #endif /* __DDS_H */