ad9910: add ram conversion tooling and unittests

Signed-off-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
Robert Jördens 2019-02-21 15:59:52 +00:00
parent ec6588174b
commit aee8965897
2 changed files with 113 additions and 4 deletions

View File

@ -310,8 +310,8 @@ class AD9910:
:param drg_autoclear: Autoclear digital ramp generator. :param drg_autoclear: Autoclear digital ramp generator.
:param internal_profile: Internal profile control. :param internal_profile: Internal profile control.
:param ram_destination: RAM destination :param ram_destination: RAM destination
(:const:`_AD9910_RAM_DEST_FTW`, :const:`_AD9910_RAM_DEST_POW`, (:const:`RAM_DEST_FTW`, :const:`RAM_DEST_POW`,
:const:`_AD9910_RAM_DEST_ASF`, :const:`_AD9910_RAM_DEST_POWASF`). :const:`RAM_DEST_ASF`, :const:`RAM_DEST_POWASF`).
:param ram_enable: RAM mode enable. :param ram_enable: RAM mode enable.
""" """
self.write32(_AD9910_REG_CFR1, self.write32(_AD9910_REG_CFR1,
@ -516,6 +516,60 @@ class AD9910:
amplitude scale factor.""" amplitude scale factor."""
return asf / float(0x3ffe) return asf / float(0x3ffe)
@portable(flags={"fast-math"})
def frequency_to_ram(self, frequency, ram):
"""Convert frequency values to RAM profile data.
To be used with :const:`RAM_DEST_FTW`.
:param frequency: List of frequency values in Hz.
:param ram: List to write RAM data into.
Suitable for :meth:`write_ram`.
"""
for i in range(len(ram)):
ram[i] = self.frequency_to_ftw(frequency[i])
@portable(flags={"fast-math"})
def turns_to_ram(self, turns, ram):
"""Convert phase values to RAM profile data.
To be used with :const:`RAM_DEST_POW`.
:param turns: List of phase values in turns.
:param ram: List to write RAM data into.
Suitable for :meth:`write_ram`.
"""
for i in range(len(ram)):
ram[i] = self.turns_to_pow(turns[i]) << 16
@portable(flags={"fast-math"})
def amplitude_to_ram(self, amplitude, ram):
"""Convert amplitude values to RAM profile data.
To be used with :const:`RAM_DEST_ASF`.
:param amplitude: List of amplitude values in units of full scale.
:param ram: List to write RAM data into.
Suitable for :meth:`write_ram`.
"""
for i in range(len(ram)):
ram[i] = self.amplitude_to_asf(amplitude[i]) << 16
@portable(flags={"fast-math"})
def turns_amplitude_to_ram(self, turns, amplitude, ram):
"""Convert phase and amplitude values to RAM profile data.
To be used with :const:`RAM_DEST_POWASF`.
:param turns: List of phase values in turns.
:param amplitude: List of amplitude values in units of full scale.
:param ram: List to write RAM data into.
Suitable for :meth:`write_ram`.
"""
for i in range(len(ram)):
ram[i] = ((self.turns_to_pow(turns[i]) << 16) |
self.amplitude_to_asf(amplitude[i]))
@kernel @kernel
def set_frequency(self, frequency): def set_frequency(self, frequency):
return self.set_ftw(self.frequency_to_ftw(frequency)) return self.set_ftw(self.frequency_to_ftw(frequency))

View File

@ -231,8 +231,8 @@ class AD9910Exp(EnvExperiment):
@kernel @kernel
def ram_exec(self): def ram_exec(self):
ftw0 = [0x12345678]*10 ftw0 = [0x12345678]*2
ftw1 = [0x55aaaa55]*10 ftw1 = [0x55aaaa55]*2
self.core.break_realtime() self.core.break_realtime()
self.dev.cpld.init() self.dev.cpld.init()
self.dev.init() self.dev.init()
@ -268,6 +268,40 @@ class AD9910Exp(EnvExperiment):
self.set_dataset("ftw", [ftw0[0], ftw0r, ftw1[0], ftw1r]) self.set_dataset("ftw", [ftw0[0], ftw0r, ftw1[0], ftw1r])
@kernel
def ram_convert_frequency(self):
freq = [33*MHz]*2
ram = [0]*len(freq)
self.dev.frequency_to_ram(freq, ram)
self.core.break_realtime()
self.dev.cpld.init()
self.dev.init()
self.dev.set_cfr1(ram_enable=0)
self.dev.cpld.io_update.pulse_mu(8)
self.dev.set_profile_ram(
start=100, end=100 + len(ram) - 1, step=1,
profile=6, mode=RAM_MODE_RAMPUP)
self.dev.cpld.set_profile(6)
self.dev.cpld.io_update.pulse_mu(8)
self.dev.write_ram(ram)
self.dev.set_cfr1(ram_enable=1, ram_destination=RAM_DEST_FTW)
self.dev.cpld.io_update.pulse_mu(8)
ftw_read = self.dev.read32(_AD9910_REG_FTW)
self.set_dataset("ram", ram)
self.set_dataset("ftw_read", ftw_read)
self.set_dataset("freq", freq)
@kernel
def ram_convert_powasf(self):
amplitude = [.1, .9]
turns = [.3, .5]
ram = [0]*2
self.dev.turns_amplitude_to_ram(turns, amplitude, ram)
self.set_dataset("amplitude", amplitude)
self.set_dataset("turns", turns)
self.set_dataset("ram", ram)
class AD9910Test(ExperimentCase): class AD9910Test(ExperimentCase):
def test_instantiate(self): def test_instantiate(self):
@ -353,3 +387,24 @@ class AD9910Test(ExperimentCase):
ftw = self.dataset_mgr.get("ftw") ftw = self.dataset_mgr.get("ftw")
self.assertEqual(ftw[0], ftw[1]) self.assertEqual(ftw[0], ftw[1])
self.assertEqual(ftw[2], ftw[3]) self.assertEqual(ftw[2], ftw[3])
def test_ram_convert_frequency(self):
exp = self.execute(AD9910Exp, "ram_convert_frequency")
ram = self.dataset_mgr.get("ram")
ftw_read = self.dataset_mgr.get("ftw_read")
self.assertEqual(ftw_read, ram[0])
freq = self.dataset_mgr.get("freq")
self.assertEqual(ftw_read, exp.dev.frequency_to_ftw(freq[0]))
self.assertAlmostEqual(freq[0], exp.dev.ftw_to_frequency(ftw_read),
delta=.25)
def test_ram_convert_powasf(self):
exp = self.execute(AD9910Exp, "ram_convert_powasf")
ram = self.dataset_mgr.get("ram")
amplitude = self.dataset_mgr.get("amplitude")
turns = self.dataset_mgr.get("turns")
for i in range(len(ram)):
self.assertEqual((ram[i] >> 16) & 0xffff,
exp.dev.turns_to_pow(turns[i]))
self.assertEqual(ram[i] & 0xffff,
exp.dev.amplitude_to_asf(amplitude[i]))