Merge branch 'master' into rtiobusy

* master:
  coredevice: fix _DDSGeneric __init__ args
  rtio/core: fix syntax
  rtio: disable replace on rt2wb channels
  examples: dds_bus -> core_dds
  fix more multi-DDS-bus problems
  runtime: fix dds declarations
  support for multiple DDS buses (untested)
This commit is contained in:
Robert Jördens 2016-03-09 17:58:58 +01:00
commit 349a66124b
23 changed files with 301 additions and 188 deletions

View File

@ -11,4 +11,8 @@ Release notes
This requires reflashing the runtime and the flash storage filesystem image
or erase and rewrite its entries.
* RTIOCollisionError has been renamed to RTIOCollision
* the new API for DDS batches is:
with self.core_dds.batch:
...
with core_dds a device of type artiq.coredevice.dds.CoreDDS.
The dds_bus device should not be used anymore.

View File

@ -40,16 +40,19 @@ def decode_message(data):
DecodedDump = namedtuple(
"DecodedDump", "log_channel dds_channel dds_onehot_sel messages")
"DecodedDump", "log_channel dds_onehot_sel messages")
def decode_dump(data):
parts = struct.unpack(">IQbbbb", data[:16])
parts = struct.unpack(">IQbbb", data[:15])
(sent_bytes, total_byte_count,
overflow_occured, log_channel, dds_channel, dds_onehot_sel) = parts
overflow_occured, log_channel, dds_onehot_sel) = parts
if sent_bytes + 16 != len(data):
raise ValueError("analyzer dump has incorrect length")
expected_len = sent_bytes + 15
if expected_len != len(data):
raise ValueError("analyzer dump has incorrect length "
"(got {}, expected {})".format(
len(data), expected_len))
if overflow_occured:
logger.warning("analyzer FIFO overflow occured, "
"some messages have been lost")
@ -57,14 +60,12 @@ def decode_dump(data):
logger.info("analyzer ring buffer has wrapped %d times",
total_byte_count//sent_bytes)
position = 16
position = 15
messages = []
for _ in range(sent_bytes//32):
messages.append(decode_message(data[position:position+32]))
position += 32
return DecodedDump(log_channel,
dds_channel, bool(dds_onehot_sel),
messages)
return DecodedDump(log_channel, bool(dds_onehot_sel), messages)
def vcd_codes():
@ -299,21 +300,31 @@ def get_vcd_log_channels(log_channel, messages):
return vcd_log_channels
def get_ref_period(devices):
def get_single_device_argument(devices, module, cls, argument):
ref_period = None
for desc in devices.values():
if isinstance(desc, dict) and desc["type"] == "local":
if (desc["module"] == "artiq.coredevice.core"
and desc["class"] == "Core"):
if (desc["module"] == module
and desc["class"] == cls):
if ref_period is None:
ref_period = desc["arguments"]["ref_period"]
ref_period = desc["arguments"][argument]
else:
return None # more than one core device found
return None # more than one device found
return ref_period
def get_ref_period(devices):
return get_single_device_argument(devices, "artiq.coredevice.core",
"Core", "ref_period")
def get_dds_sysclk(devices):
return get_single_device_argument(devices, "artiq.coredevice.core",
"CoreDDS", "sysclk")
def create_channel_handlers(vcd_manager, devices, ref_period,
dds_channel, dds_onehot_sel):
dds_sysclk, dds_onehot_sel):
channel_handlers = dict()
for name, desc in sorted(devices.items(), key=itemgetter(0)):
if isinstance(desc, dict) and desc["type"] == "local":
@ -327,19 +338,17 @@ def create_channel_handlers(vcd_manager, devices, ref_period,
channel_handlers[channel] = TTLClockGenHandler(vcd_manager, name, ref_period)
if (desc["module"] == "artiq.coredevice.dds"
and desc["class"] in {"AD9858", "AD9914"}):
sysclk = desc["arguments"]["sysclk"]
dds_channel_ddsbus = desc["arguments"]["channel"]
if dds_channel in channel_handlers:
dds_handler = channel_handlers[dds_channel]
dds_bus_channel = desc["arguments"]["bus_channel"]
dds_channel = desc["arguments"]["channel"]
if dds_bus_channel in channel_handlers:
dds_handler = channel_handlers[dds_bus_channel]
if dds_handler.dds_type != desc["class"]:
raise ValueError("All DDS channels must have the same type")
if dds_handler.sysclk != sysclk:
raise ValueError("All DDS channels must have the same sysclk")
else:
dds_handler = DDSHandler(vcd_manager, desc["class"],
dds_onehot_sel, sysclk)
channel_handlers[dds_channel] = dds_handler
dds_handler.add_dds_channel(name, dds_channel_ddsbus)
dds_sysclk, dds_onehot_sel)
channel_handlers[dds_bus_channel] = dds_handler
dds_handler.add_dds_channel(name, dds_channel)
return channel_handlers
@ -355,12 +364,16 @@ def decoded_dump_to_vcd(fileobj, devices, dump):
else:
logger.warning("unable to determine core device ref_period")
ref_period = 1e-9 # guess
dds_sysclk = get_dds_sysclk(devices)
if dds_sysclk is None:
logger.warning("unable to determine DDS sysclk")
dds_sysclk = 3e9 # guess
messages = sorted(dump.messages, key=get_message_time)
channel_handlers = create_channel_handlers(
vcd_manager, devices, ref_period,
dump.dds_channel, dump.dds_onehot_sel)
dds_sysclk, dump.dds_onehot_sel)
vcd_log_channels = get_vcd_log_channels(dump.log_channel, messages)
channel_handlers[dump.log_channel] = LogHandler(vcd_manager, vcd_log_channels)
slack = vcd_manager.get_channel("rtio_slack", 64)

View File

@ -22,7 +22,7 @@ def _render_diagnostic(diagnostic, colored):
lines = [shorten_path(path) for path in diagnostic.render(colored=colored)]
return "\n".join(lines)
colors_supported = (os.name == 'posix')
colors_supported = os.name == "posix"
class _DiagnosticEngine(diagnostic.Engine):
def render_diagnostic(self, diagnostic):
sys.stderr.write(_render_diagnostic(diagnostic, colored=colors_supported) + "\n")
@ -49,6 +49,7 @@ def cache_get(key: TStr) -> TList(TInt32):
def cache_put(key: TStr, value: TList(TInt32)) -> TNone:
raise NotImplementedError("syscall not simulated")
class Core:
"""Core device driver.

View File

@ -11,7 +11,12 @@ PHASE_MODE_TRACKING = 2
@syscall
def dds_init(time_mu: TInt64, channel: TInt32) -> TNone:
def dds_init(time_mu: TInt64, bus_channel: TInt32, channel: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall
def dds_set(time_mu: TInt64, bus_channel: TInt32, channel: TInt32, ftw: TInt32,
pow: TInt32, phase_mode: TInt32, amplitude: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall
@ -22,35 +27,36 @@ def dds_batch_enter(time_mu: TInt64) -> TNone:
def dds_batch_exit() -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall
def dds_set(time_mu: TInt64, channel: TInt32, ftw: TInt32,
pow: TInt32, phase_mode: TInt32, amplitude: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
class _BatchContextManager:
def __init__(self, dds_bus):
self.dds_bus = dds_bus
def __init__(self, core_dds):
self.core_dds = core_dds
self.core = self.core_dds.core
@kernel
def __enter__(self):
self.dds_bus.batch_enter()
self.core_dds.dds_batch_enter()
@kernel
def __exit__(self, type, value, traceback):
self.dds_bus.batch_exit()
self.core_dds.dds_batch_exit()
class DDSBus:
"""Core device Direct Digital Synthesis (DDS) bus batching driver.
class CoreDDS:
"""Core device Direct Digital Synthesis (DDS) driver.
Manages batching of DDS commands on a DDS shared bus."""
def __init__(self, dmgr):
self.core = dmgr.get("core")
Gives access to the DDS functionality of the core device.
:param sysclk: DDS system frequency. The DDS system clock must be a
phase-locked multiple of the RTIO clock.
"""
def __init__(self, dmgr, sysclk, core_device="core"):
self.core = dmgr.get(core_device)
self.sysclk = sysclk
self.batch = _BatchContextManager(self)
@kernel
def batch_enter(self):
def dds_batch_enter(self):
"""Starts a DDS command batch. All DDS commands are buffered
after this call, until ``batch_exit`` is called.
@ -59,26 +65,27 @@ class DDSBus:
dds_batch_enter(now_mu())
@kernel
def batch_exit(self):
def dds_batch_exit(self):
"""Ends a DDS command batch. All buffered DDS commands are issued
on the bus."""
dds_batch_exit()
class _DDSGeneric:
"""Core device Direct Digital Synthesis (DDS) driver.
"""Core device Direct Digital Synthesis (DDS) channel driver.
Controls one DDS channel managed directly by the core device's runtime.
This class should not be used directly, instead, use the chip-specific
drivers such as ``AD9858`` and ``AD9914``.
:param sysclk: DDS system frequency.
:param bus: name of the DDS bus device that this DDS is connected to.
:param channel: channel number of the DDS device to control.
"""
def __init__(self, dmgr, sysclk, channel):
self.core = dmgr.get("core")
self.sysclk = sysclk
def __init__(self, dmgr, bus_channel, channel, core_dds_device="core_dds"):
self.core_dds = dmgr.get(core_dds_device)
self.core = self.core_dds.core
self.bus_channel = bus_channel
self.channel = channel
self.phase_mode = PHASE_MODE_CONTINUOUS
@ -87,14 +94,14 @@ class _DDSGeneric:
"""Returns the frequency tuning word corresponding to the given
frequency.
"""
return round(int(2, width=64)**32*frequency/self.sysclk)
return round(int(2, width=64)**32*frequency/self.core_dds.sysclk)
@portable
def ftw_to_frequency(self, ftw):
"""Returns the frequency corresponding to the given frequency tuning
word.
"""
return ftw*self.sysclk/int(2, width=64)**32
return ftw*self.core_dds.sysclk/int(2, width=64)**32
@portable
def turns_to_pow(self, turns):
@ -124,7 +131,7 @@ class _DDSGeneric:
"""Resets and initializes the DDS channel.
The runtime does this for all channels upon core device startup."""
dds_init(now_mu(), self.channel)
dds_init(now_mu(), self.bus_channel, self.channel)
@kernel
def set_phase_mode(self, phase_mode):
@ -163,7 +170,8 @@ class _DDSGeneric:
"""
if phase_mode == _PHASE_MODE_DEFAULT:
phase_mode = self.phase_mode
dds_set(now_mu(), self.channel, frequency, phase, phase_mode, amplitude)
dds_set(now_mu(), self.bus_channel, self.channel,
frequency, phase, phase_mode, amplitude)
@kernel
def set(self, frequency, phase=0.0, phase_mode=_PHASE_MODE_DEFAULT,

View File

@ -130,24 +130,27 @@ class _OutputManager(Module):
collision = Signal()
any_error = Signal()
nop = Signal()
self.sync.rsys += [
if interface.enable_replace:
# Note: replace may be asserted at the same time as collision
# when addresses are different. In that case, it is a collision.
replace.eq(self.ev.timestamp == buf.timestamp),
self.sync.rsys += replace.eq(self.ev.timestamp == buf.timestamp)
# Detect sequence errors on coarse timestamps only
# so that they are mutually exclusive with collision errors.
sequence_error.eq(self.ev.timestamp[fine_ts_width:]
< buf.timestamp[fine_ts_width:])
]
if hasattr(self.ev, "a"):
different_addresses = self.ev.a != buf.a
self.sync.rsys += sequence_error.eq(self.ev.timestamp[fine_ts_width:] <
buf.timestamp[fine_ts_width:])
if interface.enable_replace:
if hasattr(self.ev, "a"):
different_addresses = self.ev.a != buf.a
else:
different_addresses = 0
if fine_ts_width:
self.sync.rsys += collision.eq(
(self.ev.timestamp[fine_ts_width:] == buf.timestamp[fine_ts_width:])
& ((self.ev.timestamp[:fine_ts_width] != buf.timestamp[:fine_ts_width])
|different_addresses))
else:
different_addresses = 0
if fine_ts_width:
self.sync.rsys += collision.eq(
(self.ev.timestamp[fine_ts_width:] == buf.timestamp[fine_ts_width:])
& ((self.ev.timestamp[:fine_ts_width] != buf.timestamp[:fine_ts_width])
|different_addresses))
self.ev.timestamp[fine_ts_width:] == buf.timestamp[fine_ts_width:])
self.comb += any_error.eq(sequence_error | collision)
if interface.suppress_nop:
# disable NOP at reset: do not suppress a first write with all 0s

View File

@ -13,7 +13,8 @@ class RT2WB(Module):
rtlink.OInterface(
len(wb.dat_w),
address_width + 1,
suppress_nop=False),
suppress_nop=False,
enable_replace=False),
rtlink.IInterface(
len(wb.dat_r),
timestamped=False)

View File

@ -3,7 +3,8 @@ from migen import *
class OInterface:
def __init__(self, data_width, address_width=0,
fine_ts_width=0, suppress_nop=True):
fine_ts_width=0, suppress_nop=True,
enable_replace=True):
self.stb = Signal()
self.busy = Signal()
@ -15,6 +16,7 @@ class OInterface:
self.fine_ts = Signal(fine_ts_width)
self.suppress_nop = suppress_nop
self.enable_replace = enable_replace
@classmethod
def like(cls, other):

View File

@ -204,8 +204,9 @@ class NIST_QC1(_NIST_Ions):
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
self.config["DDS_CHANNEL_COUNT"] = 8
self.config["RTIO_FIRST_DDS_CHANNEL"] = len(rtio_channels)
self.config["RTIO_DDS_COUNT"] = 1
self.config["DDS_CHANNELS_PER_BUS"] = 8
self.config["DDS_AD9858"] = True
phy = dds.AD9858(platform.request("dds"), 8)
self.submodules += phy
@ -277,8 +278,9 @@ class NIST_CLOCK(_NIST_Ions):
rtio_channels.append(rtio.Channel.from_phy(
phy, ofifo_depth=128, ififo_depth=128))
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
self.config["DDS_CHANNEL_COUNT"] = 11
self.config["RTIO_FIRST_DDS_CHANNEL"] = len(rtio_channels)
self.config["RTIO_DDS_COUNT"] = 1
self.config["DDS_CHANNELS_PER_BUS"] = 11
self.config["DDS_AD9914"] = True
self.config["DDS_ONEHOT_SEL"] = True
phy = dds.AD9914(platform.request("dds"), 11, onehot=True)
@ -331,8 +333,9 @@ class NIST_QC2(_NIST_Ions):
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
self.config["DDS_CHANNEL_COUNT"] = 12
self.config["RTIO_FIRST_DDS_CHANNEL"] = len(rtio_channels)
self.config["RTIO_DDS_COUNT"] = 1
self.config["DDS_CHANNELS_PER_BUS"] = 12
self.config["DDS_AD9914"] = True
self.config["DDS_ONEHOT_SEL"] = True
phy = dds.AD9914(platform.request("dds"), 12, onehot=True)

View File

@ -215,8 +215,9 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd
rtio_channels.append(rtio.Channel.from_phy(
phy, ofifo_depth=256, ififo_depth=256))
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
self.config["DDS_CHANNEL_COUNT"] = 8
self.config["RTIO_FIRST_DDS_CHANNEL"] = len(rtio_channels)
self.config["RTIO_DDS_COUNT"] = 1
self.config["DDS_CHANNELS_PER_BUS"] = 8
self.config["DDS_AD9858"] = True
dds_pins = platform.request("dds")
self.comb += dds_pins.p.eq(0)

View File

@ -118,7 +118,8 @@ class _TTLWidget(QtWidgets.QFrame):
class _DDSWidget(QtWidgets.QFrame):
def __init__(self, channel, sysclk, title):
def __init__(self, bus_channel, channel, sysclk, title):
self.bus_channel = bus_channel
self.channel = channel
self.sysclk = sysclk
@ -146,13 +147,14 @@ class _DDSWidget(QtWidgets.QFrame):
self.set_value(0)
def set_value(self, ftw):
frequency = ftw*self.sysclk/2**32
frequency = ftw*self.sysclk()/2**32
self._value.setText("<font size=\"6\">{:.7f} MHz</font>"
.format(float(frequency)/1e6))
class _DeviceManager:
def __init__(self, send_to_device, init):
self.dds_sysclk = 0
self.send_to_device = send_to_device
self.ddb = dict()
self.ttl_cb = lambda: None
@ -162,6 +164,9 @@ class _DeviceManager:
for k, v in init.items():
self[k] = v
def get_dds_sysclk(self):
return self.dds_sysclk
def __setitem__(self, k, v):
if k in self.ttl_widgets:
del self[k]
@ -181,12 +186,15 @@ class _DeviceManager:
self.ttl_widgets[k] = _TTLWidget(
channel, self.send_to_device, force_out, title)
self.ttl_cb()
if (v["module"] == "artiq.coredevice.dds"
and v["class"] == "CoreDDS"):
self.dds_sysclk = v["arguments"]["sysclk"]
if (v["module"] == "artiq.coredevice.dds"
and v["class"] in {"AD9858", "AD9914"}):
bus_channel = v["arguments"]["bus_channel"]
channel = v["arguments"]["channel"]
sysclk = v["arguments"]["sysclk"]
self.dds_widgets[channel] = _DDSWidget(
channel, sysclk, title)
bus_channel, channel, self.get_dds_sysclk, title)
self.dds_cb()
except KeyError:
pass
@ -275,19 +283,23 @@ class MonInj(TaskObject):
"is not present yet")
return
try:
ttl_levels, ttl_oes, ttl_overrides = \
struct.unpack(">QQQ", data[:8*3])
hlen = 8*3+4
(ttl_levels, ttl_oes, ttl_overrides,
dds_rtio_first_channel, dds_channels_per_bus) = \
struct.unpack(">QQQHH", data[:hlen])
for w in self.dm.ttl_widgets.values():
channel = w.channel
w.set_value(ttl_levels & (1 << channel),
ttl_oes & (1 << channel),
ttl_overrides & (1 << channel))
dds_data = data[8*3:]
dds_data = data[hlen:]
ndds = len(dds_data)//4
ftws = struct.unpack(">" + "I"*ndds, dds_data)
for w in self.dm.dds_widgets.values():
offset = (dds_channels_per_bus*w.bus_channel
+ w.channel-dds_rtio_first_channel)
try:
ftw = ftws[w.channel]
ftw = ftws[offset]
except KeyError:
pass
else:

View File

@ -12,7 +12,6 @@ struct analyzer_header {
unsigned long long int total_byte_count;
unsigned char overflow_occured;
unsigned char log_channel;
unsigned char dds_channel;
unsigned char dds_onehot_sel;
} __attribute__((packed));
@ -72,7 +71,6 @@ void analyzer_start(void)
analyzer_header.overflow_occured = rtio_analyzer_message_encoder_overflow_read();
analyzer_header.log_channel = CONFIG_RTIO_LOG_CHANNEL;
analyzer_header.dds_channel = CONFIG_RTIO_DDS_CHANNEL;
#ifdef CONFIG_DDS_ONEHOT_SEL
analyzer_header.dds_onehot_sel = 1;
#else

View File

@ -16,12 +16,12 @@ static void rtio_output_blind(int channel, int addr, int data)
rtio_o_we_write(1);
}
static void dds_write(int addr, int data)
static void dds_write(int bus_channel, int addr, int data)
{
rtio_output_blind(CONFIG_RTIO_DDS_CHANNEL, addr, data);
rtio_output_blind(bus_channel, addr, data);
}
static int dds_read(int addr)
static int dds_read(int bus_channel, int addr)
{
int r;
@ -31,7 +31,7 @@ static int dds_read(int addr)
#ifdef CONFIG_DDS_AD9914
#define DDS_READ_FLAG 256
#endif
dds_write(addr | DDS_READ_FLAG, 0);
dds_write(bus_channel, addr | DDS_READ_FLAG, 0);
while(rtio_i_status_read() & RTIO_I_STATUS_EMPTY);
r = rtio_i_data_read();
rtio_i_re_write(1);
@ -75,16 +75,18 @@ void bridge_main(void)
struct msg_brg_dds_sel *msg;
msg = (struct msg_brg_dds_sel *)umsg;
dds_write(DDS_GPIO, msg->channel << 1);
dds_write(msg->bus_channel, DDS_GPIO, msg->channel << 1);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_BRG_DDS_RESET: {
unsigned int g;
struct msg_brg_dds_reset *msg;
g = dds_read(DDS_GPIO);
dds_write(DDS_GPIO, g | 1);
dds_write(DDS_GPIO, g);
msg = (struct msg_brg_dds_reset *)umsg;
g = dds_read(msg->bus_channel, DDS_GPIO);
dds_write(msg->bus_channel, DDS_GPIO, g | 1);
dds_write(msg->bus_channel, DDS_GPIO, g);
mailbox_acknowledge();
break;
@ -95,7 +97,7 @@ void bridge_main(void)
msg = (struct msg_brg_dds_read_request *)umsg;
rmsg.type = MESSAGE_TYPE_BRG_DDS_READ_REPLY;
rmsg.data = dds_read(msg->address);
rmsg.data = dds_read(msg->bus_channel, msg->address);
mailbox_send_and_wait(&rmsg);
break;
}
@ -103,14 +105,18 @@ void bridge_main(void)
struct msg_brg_dds_write *msg;
msg = (struct msg_brg_dds_write *)umsg;
dds_write(msg->address, msg->data);
dds_write(msg->bus_channel, msg->address, msg->data);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_BRG_DDS_FUD:
dds_write(DDS_FUD, 0);
case MESSAGE_TYPE_BRG_DDS_FUD: {
struct msg_brg_dds_fud *msg;
msg = (struct msg_brg_dds_fud *)umsg;
dds_write(msg->bus_channel, DDS_FUD, 0);
mailbox_acknowledge();
break;
}
default:
mailbox_acknowledge();
break;

View File

@ -43,30 +43,33 @@ void brg_ttlo(int n, int value)
mailbox_send_and_wait(&msg);
}
void brg_ddssel(int channel)
void brg_ddssel(int bus_channel, int channel)
{
struct msg_brg_dds_sel msg;
msg.type = MESSAGE_TYPE_BRG_DDS_SEL;
msg.bus_channel = bus_channel;
msg.channel = channel;
mailbox_send_and_wait(&msg);
}
void brg_ddsreset(void)
void brg_ddsreset(int bus_channel)
{
struct msg_base msg;
struct msg_brg_dds_reset msg;
msg.type = MESSAGE_TYPE_BRG_DDS_RESET;
msg.bus_channel = bus_channel;
mailbox_send_and_wait(&msg);
}
unsigned int brg_ddsread(unsigned int address)
unsigned int brg_ddsread(int bus_channel, unsigned int address)
{
struct msg_brg_dds_read_request msg;
struct msg_brg_dds_read_reply *rmsg;
unsigned int r;
msg.type = MESSAGE_TYPE_BRG_DDS_READ_REQUEST;
msg.bus_channel = bus_channel;
msg.address = address;
mailbox_send(&msg);
while(1) {
@ -82,20 +85,22 @@ unsigned int brg_ddsread(unsigned int address)
}
}
void brg_ddswrite(unsigned int address, unsigned int data)
void brg_ddswrite(int bus_channel, unsigned int address, unsigned int data)
{
struct msg_brg_dds_write msg;
msg.type = MESSAGE_TYPE_BRG_DDS_WRITE;
msg.bus_channel = bus_channel;
msg.address = address;
msg.data = data;
mailbox_send_and_wait(&msg);
}
void brg_ddsfud(void)
void brg_ddsfud(int bus_channel)
{
struct msg_base msg;
struct msg_brg_dds_fud msg;
msg.type = MESSAGE_TYPE_BRG_DDS_FUD;
msg.bus_channel = bus_channel;
mailbox_send_and_wait(&msg);
}

View File

@ -6,10 +6,10 @@ void brg_start(void);
void brg_ttloe(int n, int value);
void brg_ttlo(int n, int value);
void brg_ddssel(int channel);
void brg_ddsreset(void);
unsigned int brg_ddsread(unsigned int address);
void brg_ddswrite(unsigned int address, unsigned int data);
void brg_ddsfud(void);
void brg_ddssel(int bus_channel, int channel);
void brg_ddsreset(int bus_channel);
unsigned int brg_ddsread(int bus_channel, unsigned int address);
void brg_ddswrite(int bus_channel, unsigned int address, unsigned int data);
void brg_ddsfud(int bus_channel);
#endif /* __BRIDGE_CTL_H */

View File

@ -26,11 +26,11 @@
#endif
#define DDS_WRITE(addr, data) do { \
rtio_output(now, CONFIG_RTIO_DDS_CHANNEL, addr, data); \
rtio_output(now, bus_channel, addr, data); \
now += DURATION_WRITE; \
} while(0)
void dds_init(long long int timestamp, int channel)
void dds_init(long long int timestamp, int bus_channel, int channel)
{
long long int now;
@ -82,17 +82,23 @@ void dds_init(long long int timestamp, int channel)
/* Compensation to keep phase continuity when switching from absolute or tracking
* to continuous phase mode. */
static unsigned int continuous_phase_comp[CONFIG_DDS_CHANNEL_COUNT];
static unsigned int continuous_phase_comp[CONFIG_RTIO_DDS_COUNT][CONFIG_DDS_CHANNELS_PER_BUS];
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,
int bus_channel, int channel,
unsigned int ftw, unsigned int pow, int phase_mode, unsigned int amplitude)
{
unsigned int channel_enc;
if(channel >= CONFIG_DDS_CHANNEL_COUNT) {
if((channel < 0) || (channel >= CONFIG_DDS_CHANNELS_PER_BUS)) {
core_log("Attempted to set invalid DDS channel\n");
return;
}
if((bus_channel < CONFIG_RTIO_FIRST_DDS_CHANNEL)
|| (bus_channel >= (CONFIG_RTIO_FIRST_DDS_CHANNEL+CONFIG_RTIO_DDS_COUNT))) {
core_log("Attempted to use invalid DDS bus\n");
return;
}
#ifdef CONFIG_DDS_ONEHOT_SEL
channel_enc = 1 << channel;
#else
@ -124,7 +130,7 @@ static void dds_set_one(long long int now, long long int ref_time, unsigned int
/* Disable autoclear phase accumulator and enables OSK. */
DDS_WRITE(DDS_CFR1L, 0x0108);
#endif
pow += continuous_phase_comp[channel];
pow += continuous_phase_comp[bus_channel-CONFIG_RTIO_FIRST_DDS_CHANNEL][channel];
} else {
long long int fud_time;
@ -140,7 +146,7 @@ static void dds_set_one(long long int now, long long int ref_time, unsigned int
pow -= (ref_time - fud_time)*CONFIG_DDS_RTIO_CLK_RATIO*ftw >> (32-DDS_POW_WIDTH);
if(phase_mode == PHASE_MODE_TRACKING)
pow += ref_time*CONFIG_DDS_RTIO_CLK_RATIO*ftw >> (32-DDS_POW_WIDTH);
continuous_phase_comp[channel] = pow;
continuous_phase_comp[bus_channel-CONFIG_RTIO_FIRST_DDS_CHANNEL][channel] = pow;
}
#ifdef CONFIG_DDS_AD9858
@ -157,6 +163,7 @@ static void dds_set_one(long long int now, long long int ref_time, unsigned int
}
struct dds_set_params {
int bus_channel;
int channel;
unsigned int ftw;
unsigned int pow;
@ -189,20 +196,22 @@ void dds_batch_exit(void)
now = batch_ref_time - batch_count*(DURATION_PROGRAM + DURATION_WRITE);
for(i=0;i<batch_count;i++) {
dds_set_one(now, batch_ref_time,
batch[i].channel, batch[i].ftw, batch[i].pow, batch[i].phase_mode,
batch[i].bus_channel, batch[i].channel,
batch[i].ftw, batch[i].pow, batch[i].phase_mode,
batch[i].amplitude);
now += DURATION_PROGRAM + DURATION_WRITE;
}
batch_mode = 0;
}
void dds_set(long long int timestamp, int channel,
void dds_set(long long int timestamp, int bus_channel, int channel,
unsigned int ftw, unsigned int pow, int phase_mode, unsigned int amplitude)
{
if(batch_mode) {
if(batch_count >= DDS_MAX_BATCH)
artiq_raise_from_c("DDSBatchError", "DDS batch error", 0, 0, 0);
/* timestamp parameter ignored (determined by batch) */
batch[batch_count].bus_channel = bus_channel;
batch[batch_count].channel = channel;
batch[batch_count].ftw = ftw;
batch[batch_count].pow = pow;
@ -210,7 +219,8 @@ void dds_set(long long int timestamp, int channel,
batch[batch_count].amplitude = amplitude;
batch_count++;
} else {
dds_set_one(timestamp - DURATION_PROGRAM, timestamp, channel, ftw, pow, phase_mode,
amplitude);
dds_set_one(timestamp - DURATION_PROGRAM, timestamp,
bus_channel, channel,
ftw, pow, phase_mode, amplitude);
}
}

View File

@ -54,10 +54,10 @@ enum {
PHASE_MODE_TRACKING = 2
};
void dds_init(long long int timestamp, int channel);
void dds_init(long long int timestamp, int bus_channel, int channel);
void dds_batch_enter(long long int timestamp);
void dds_batch_exit(void);
void dds_set(long long int timestamp, int channel,
void dds_set(long long int timestamp, int bus_channel, int channel,
unsigned int ftw, unsigned int pow, int phase_mode, unsigned int amplitude);
#endif /* __DDS_H */

View File

@ -150,23 +150,37 @@ struct msg_brg_ttl_out {
struct msg_brg_dds_sel {
int type;
int bus_channel;
int channel;
};
struct msg_brg_dds_reset {
int type;
int bus_channel;
};
struct msg_brg_dds_read_request {
int type;
int bus_channel;
unsigned int address;
};
struct msg_brg_dds_read_reply {
int type;
int bus_channel;
unsigned int data;
};
struct msg_brg_dds_write {
int type;
int bus_channel;
unsigned int address;
unsigned int data;
};
struct msg_brg_dds_fud {
int type;
int bus_channel;
};
#endif /* __MESSAGES_H */

View File

@ -36,13 +36,15 @@ struct monitor_reply {
long long int ttl_levels;
long long int ttl_oes;
long long int ttl_overrides;
unsigned int dds_ftws[CONFIG_DDS_CHANNEL_COUNT];
};
unsigned short int dds_rtio_first_channel;
unsigned short int dds_channels_per_bus;
unsigned int dds_ftws[CONFIG_RTIO_DDS_COUNT*CONFIG_DDS_CHANNELS_PER_BUS];
} __attribute__((packed));
static void moninj_monitor(const ip_addr_t *addr, u16_t port)
{
struct monitor_reply reply;
int i;
int i, j;
struct pbuf *reply_p;
reply.ttl_levels = 0;
@ -64,11 +66,15 @@ static void moninj_monitor(const ip_addr_t *addr, u16_t port)
reply.ttl_overrides |= 1LL << i;
}
rtio_moninj_mon_chan_sel_write(CONFIG_RTIO_DDS_CHANNEL);
for(i=0;i<CONFIG_DDS_CHANNEL_COUNT;i++) {
rtio_moninj_mon_probe_sel_write(i);
rtio_moninj_mon_value_update_write(1);
reply.dds_ftws[i] = rtio_moninj_mon_value_read();
reply.dds_rtio_first_channel = CONFIG_RTIO_FIRST_DDS_CHANNEL;
reply.dds_channels_per_bus = CONFIG_DDS_CHANNELS_PER_BUS;
for(j=0;j<CONFIG_RTIO_DDS_COUNT;j++) {
rtio_moninj_mon_chan_sel_write(CONFIG_RTIO_FIRST_DDS_CHANNEL+j);
for(i=0;i<CONFIG_DDS_CHANNELS_PER_BUS;i++) {
rtio_moninj_mon_probe_sel_write(i);
rtio_moninj_mon_value_update_write(1);
reply.dds_ftws[CONFIG_DDS_CHANNELS_PER_BUS*j+i] = rtio_moninj_mon_value_read();
}
}
reply_p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct monitor_reply), PBUF_RAM);

View File

@ -104,6 +104,28 @@ static void ttlo(char *n, char *value)
brg_ttlo(n2, value2);
}
static int bus_channel = CONFIG_RTIO_FIRST_DDS_CHANNEL;
static void ddsbus(char *n)
{
char *c;
unsigned int n2;
if(*n == 0) {
printf("ddsbus <n>\n");
return;
}
n2 = strtoul(n, &c, 0);
if(*c != 0) {
printf("incorrect bus channel\n");
return;
}
bus_channel = n2;
}
static void ddssel(char *n)
{
char *c;
@ -123,7 +145,7 @@ static void ddssel(char *n)
#ifdef CONFIG_DDS_ONEHOT_SEL
n2 = 1 << n2;
#endif
brg_ddssel(n2);
brg_ddssel(bus_channel, n2);
}
static void ddsw(char *addr, char *value)
@ -147,7 +169,7 @@ static void ddsw(char *addr, char *value)
return;
}
brg_ddswrite(addr2, value2);
brg_ddswrite(bus_channel, addr2, value2);
}
static void ddsr(char *addr)
@ -167,16 +189,16 @@ static void ddsr(char *addr)
}
#ifdef CONFIG_DDS_AD9858
printf("0x%02x\n", brg_ddsread(addr2));
printf("0x%02x\n", brg_ddsread(bus_channel, addr2));
#endif
#ifdef CONFIG_DDS_AD9914
printf("0x%04x\n", brg_ddsread(addr2));
printf("0x%04x\n", brg_ddsread(bus_channel, addr2));
#endif
}
static void ddsfud(void)
{
brg_ddsfud();
brg_ddsfud(bus_channel);
}
static void ddsftw(char *n, char *ftw)
@ -203,36 +225,36 @@ static void ddsftw(char *n, char *ftw)
#ifdef CONFIG_DDS_ONEHOT_SEL
n2 = 1 << n2;
#endif
brg_ddssel(n2);
brg_ddssel(bus_channel, n2);
#ifdef CONFIG_DDS_AD9858
brg_ddswrite(DDS_FTW0, ftw2 & 0xff);
brg_ddswrite(DDS_FTW1, (ftw2 >> 8) & 0xff);
brg_ddswrite(DDS_FTW2, (ftw2 >> 16) & 0xff);
brg_ddswrite(DDS_FTW3, (ftw2 >> 24) & 0xff);
brg_ddswrite(bus_channel, DDS_FTW0, ftw2 & 0xff);
brg_ddswrite(bus_channel, DDS_FTW1, (ftw2 >> 8) & 0xff);
brg_ddswrite(bus_channel, DDS_FTW2, (ftw2 >> 16) & 0xff);
brg_ddswrite(bus_channel, DDS_FTW3, (ftw2 >> 24) & 0xff);
#endif
#ifdef CONFIG_DDS_AD9914
brg_ddswrite(DDS_FTWL, ftw2 & 0xffff);
brg_ddswrite(DDS_FTWH, (ftw2 >> 16) & 0xffff);
brg_ddswrite(bus_channel, DDS_FTWL, ftw2 & 0xffff);
brg_ddswrite(bus_channel, DDS_FTWH, (ftw2 >> 16) & 0xffff);
#endif
brg_ddsfud();
brg_ddsfud(bus_channel);
}
static void ddsreset(void)
{
brg_ddsreset();
brg_ddsreset(bus_channel);
}
#ifdef CONFIG_DDS_AD9858
static void ddsinit(void)
{
brg_ddsreset();
brg_ddswrite(DDS_CFR0, 0x78);
brg_ddswrite(DDS_CFR1, 0x00);
brg_ddswrite(DDS_CFR2, 0x00);
brg_ddswrite(DDS_CFR3, 0x00);
brg_ddsfud();
brg_ddsreset(bus_channel);
brg_ddswrite(bus_channel, DDS_CFR0, 0x78);
brg_ddswrite(bus_channel, DDS_CFR1, 0x00);
brg_ddswrite(bus_channel, DDS_CFR2, 0x00);
brg_ddswrite(bus_channel, DDS_CFR3, 0x00);
brg_ddsfud(bus_channel);
}
#endif
@ -241,17 +263,17 @@ static void ddsinit(void)
{
long long int t;
brg_ddsreset();
brg_ddswrite(DDS_CFR1H, 0x0000); /* Enable cosine output */
brg_ddswrite(DDS_CFR2L, 0x8900); /* Enable matched latency */
brg_ddswrite(DDS_CFR2H, 0x0080); /* Enable profile mode */
brg_ddswrite(DDS_ASF, 0x0fff); /* Set amplitude to maximum */
brg_ddswrite(DDS_CFR4H, 0x0105); /* Enable DAC calibration */
brg_ddswrite(DDS_FUD, 0);
brg_ddsreset(bus_channel);
brg_ddswrite(bus_channel, DDS_CFR1H, 0x0000); /* Enable cosine output */
brg_ddswrite(bus_channel, DDS_CFR2L, 0x8900); /* Enable matched latency */
brg_ddswrite(bus_channel, DDS_CFR2H, 0x0080); /* Enable profile mode */
brg_ddswrite(bus_channel, DDS_ASF, 0x0fff); /* Set amplitude to maximum */
brg_ddswrite(bus_channel, DDS_CFR4H, 0x0105); /* Enable DAC calibration */
brg_ddswrite(bus_channel, DDS_FUD, 0);
t = clock_get_ms();
while(clock_get_ms() < t + 2);
brg_ddswrite(DDS_CFR4H, 0x0005); /* Disable DAC calibration */
brg_ddsfud();
brg_ddswrite(bus_channel, DDS_CFR4H, 0x0005); /* Disable DAC calibration */
brg_ddsfud(bus_channel);
}
#endif
@ -265,34 +287,34 @@ static void do_ddstest_one(unsigned int i)
unsigned int f, g, j;
#ifdef CONFIG_DDS_ONEHOT_SEL
brg_ddssel(1 << i);
brg_ddssel(bus_channel, 1 << i);
#else
brg_ddssel(i);
brg_ddssel(bus_channel, i);
#endif
ddsinit();
for(j=0; j<12; j++) {
f = v[j];
#ifdef CONFIG_DDS_AD9858
brg_ddswrite(DDS_FTW0, f & 0xff);
brg_ddswrite(DDS_FTW1, (f >> 8) & 0xff);
brg_ddswrite(DDS_FTW2, (f >> 16) & 0xff);
brg_ddswrite(DDS_FTW3, (f >> 24) & 0xff);
brg_ddswrite(bus_channel, DDS_FTW0, f & 0xff);
brg_ddswrite(bus_channel, DDS_FTW1, (f >> 8) & 0xff);
brg_ddswrite(bus_channel, DDS_FTW2, (f >> 16) & 0xff);
brg_ddswrite(bus_channel, DDS_FTW3, (f >> 24) & 0xff);
#endif
#ifdef CONFIG_DDS_AD9914
brg_ddswrite(DDS_FTWL, f & 0xffff);
brg_ddswrite(DDS_FTWH, (f >> 16) & 0xffff);
brg_ddswrite(bus_channel, DDS_FTWL, f & 0xffff);
brg_ddswrite(bus_channel, DDS_FTWH, (f >> 16) & 0xffff);
#endif
brg_ddsfud();
brg_ddsfud(bus_channel);
#ifdef CONFIG_DDS_AD9858
g = brg_ddsread(DDS_FTW0);
g |= brg_ddsread(DDS_FTW1) << 8;
g |= brg_ddsread(DDS_FTW2) << 16;
g |= brg_ddsread(DDS_FTW3) << 24;
g = brg_ddsread(bus_channel, DDS_FTW0);
g |= brg_ddsread(bus_channel, DDS_FTW1) << 8;
g |= brg_ddsread(bus_channel, DDS_FTW2) << 16;
g |= brg_ddsread(bus_channel, DDS_FTW3) << 24;
#endif
#ifdef CONFIG_DDS_AD9914
g = brg_ddsread(DDS_FTWL);
g |= brg_ddsread(DDS_FTWH) << 16;
g = brg_ddsread(bus_channel, DDS_FTWL);
g |= brg_ddsread(bus_channel, DDS_FTWH) << 16;
#endif
if(g != f)
printf("readback fail on DDS %d, 0x%08x != 0x%08x\n", i, g, f);
@ -330,7 +352,7 @@ static void ddstest(char *n, char *channel)
do_ddstest_one(channel2);
} else {
for(i=0;i<n2;i++)
for(j=0;j<CONFIG_DDS_CHANNEL_COUNT;j++)
for(j=0;j<CONFIG_DDS_CHANNELS_PER_BUS;j++)
do_ddstest_one(j);
}
}
@ -542,6 +564,7 @@ static void help(void)
puts("clksrc <n> - select RTIO clock source");
puts("ttloe <n> <v> - set TTL output enable");
puts("ttlo <n> <v> - set TTL output value");
puts("ddsbus <n> - select the DDS bus RTIO channel");
puts("ddssel <n> - select a DDS");
puts("ddsinit - reset, config, FUD DDS");
puts("ddsreset - reset DDS");
@ -624,6 +647,7 @@ static void do_command(char *c)
else if(strcmp(token, "ttloe") == 0) ttloe(get_token(&c), get_token(&c));
else if(strcmp(token, "ttlo") == 0) ttlo(get_token(&c), get_token(&c));
else if(strcmp(token, "ddsbus") == 0) ddsbus(get_token(&c));
else if(strcmp(token, "ddssel") == 0) ddssel(get_token(&c));
else if(strcmp(token, "ddsw") == 0) ddsw(get_token(&c), get_token(&c));
else if(strcmp(token, "ddsr") == 0) ddsr(get_token(&c));

View File

@ -89,6 +89,8 @@ The board has RTIO SPI buses mapped as follows:
| 25 | SPI2_CS_N | SPI2_MOSI | SPI2_MISO | SPI2_CLK |
+--------------+-------------+-------------+-----------+------------+
The DDS bus is on channel 26.
NIST QC2
++++++++

View File

@ -14,6 +14,12 @@
"class": "Core",
"arguments": {"ref_period": 1e-9}
},
"core_dds": {
"type": "local",
"module": "artiq.coredevice.dds",
"class": "CoreDDS",
"arguments": {"sysclk": 3e9}
},
"i2c_switch": {
"type": "local",
@ -121,30 +127,24 @@
"arguments": {"spi_device": "spi0", "ldac_device": "ttl0"}
},
"dds_bus": {
"type": "local",
"module": "artiq.coredevice.dds",
"class": "DDSBus",
"arguments": {}
},
"dds0": {
"type": "local",
"module": "artiq.coredevice.dds",
"class": "AD9914",
"arguments": {"sysclk": 3e9, "channel": 0},
"arguments": {"bus_channel": 26, "channel": 0},
"comment": "Comments work in DDS panel as well"
},
"dds1": {
"type": "local",
"module": "artiq.coredevice.dds",
"class": "AD9914",
"arguments": {"sysclk": 3e9, "channel": 1}
"arguments": {"bus_channel": 26, "channel": 1}
},
"dds2": {
"type": "local",
"module": "artiq.coredevice.dds",
"class": "AD9914",
"arguments": {"sysclk": 3e9, "channel": 2}
"arguments": {"bus_channel": 26, "channel": 2}
},
"qc_q1_0": {

View File

@ -6,7 +6,7 @@ class PhotonHistogram(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("dds_bus")
self.setattr_device("core_dds")
self.setattr_device("bd_dds")
self.setattr_device("bd_sw")
self.setattr_device("bdd_dds")
@ -22,7 +22,7 @@ class PhotonHistogram(EnvExperiment):
@kernel
def program_cooling(self):
with self.dds_bus.batch:
with self.core_dds.batch:
self.bd_dds.set(200*MHz)
self.bdd_dds.set(300*MHz)

View File

@ -6,7 +6,7 @@ class DDSTest(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("dds_bus")
self.setattr_device("core_dds")
self.setattr_device("dds0")
self.setattr_device("dds1")
self.setattr_device("dds2")
@ -17,7 +17,7 @@ class DDSTest(EnvExperiment):
@kernel
def run(self):
with self.dds_bus.batch:
with self.core_dds.batch:
self.dds1.set(120*MHz)
self.dds2.set(200*MHz)
delay(1*us)