From f0b0b1bac7968af5a6cab9858ce915e29cb4d08d Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 9 Mar 2016 17:12:50 +0800 Subject: [PATCH] support for multiple DDS buses (untested) --- RELEASE_NOTES.rst | 6 +- artiq/coredevice/analyzer.py | 63 +++++++++------ artiq/coredevice/core.py | 3 +- artiq/coredevice/dds.py | 60 ++++++++------ artiq/gateware/targets/kc705.py | 15 ++-- artiq/gateware/targets/pipistrello.py | 5 +- artiq/gui/moninj.py | 28 +++++-- artiq/runtime/analyzer.c | 2 - artiq/runtime/bridge.c | 30 ++++--- artiq/runtime/bridge_ctl.c | 19 +++-- artiq/runtime/bridge_ctl.h | 10 +-- artiq/runtime/dds.c | 19 +++-- artiq/runtime/messages.h | 14 ++++ artiq/runtime/moninj.c | 22 +++-- artiq/runtime/test_mode.c | 112 ++++++++++++++++---------- doc/manual/core_device.rst | 2 + examples/master/device_db.pyon | 18 ++--- 17 files changed, 265 insertions(+), 163 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 4c905ea5a..d675623d8 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -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 - \ No newline at end of file +* 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. diff --git a/artiq/coredevice/analyzer.py b/artiq/coredevice/analyzer.py index b2b458bff..f526bb2ec 100644 --- a/artiq/coredevice/analyzer.py +++ b/artiq/coredevice/analyzer.py @@ -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) diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index 32c2501bd..7aa17fa9b 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -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. diff --git a/artiq/coredevice/dds.py b/artiq/coredevice/dds.py index 99cbc72af..b375292de 100644 --- a/artiq/coredevice/dds.py +++ b/artiq/coredevice/dds.py @@ -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, sysclk, 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, diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 8f766ecce..ae15ec179 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -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) diff --git a/artiq/gateware/targets/pipistrello.py b/artiq/gateware/targets/pipistrello.py index 620810b60..2b2c7de65 100755 --- a/artiq/gateware/targets/pipistrello.py +++ b/artiq/gateware/targets/pipistrello.py @@ -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) diff --git a/artiq/gui/moninj.py b/artiq/gui/moninj.py index 43892876a..818c148f6 100644 --- a/artiq/gui/moninj.py +++ b/artiq/gui/moninj.py @@ -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("{:.7f} MHz" .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: diff --git a/artiq/runtime/analyzer.c b/artiq/runtime/analyzer.c index a1b71b428..23f77c98d 100644 --- a/artiq/runtime/analyzer.c +++ b/artiq/runtime/analyzer.c @@ -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 diff --git a/artiq/runtime/bridge.c b/artiq/runtime/bridge.c index d1157cf65..bfe3e1fcf 100644 --- a/artiq/runtime/bridge.c +++ b/artiq/runtime/bridge.c @@ -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; diff --git a/artiq/runtime/bridge_ctl.c b/artiq/runtime/bridge_ctl.c index 11182efb9..1ebc4b0bc 100644 --- a/artiq/runtime/bridge_ctl.c +++ b/artiq/runtime/bridge_ctl.c @@ -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); } diff --git a/artiq/runtime/bridge_ctl.h b/artiq/runtime/bridge_ctl.h index e6d2b7306..2929ee8f0 100644 --- a/artiq/runtime/bridge_ctl.h +++ b/artiq/runtime/bridge_ctl.h @@ -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 */ diff --git a/artiq/runtime/dds.c b/artiq/runtime/dds.c index 3f8e728c1..ea6d650db 100644 --- a/artiq/runtime/dds.c +++ b/artiq/runtime/dds.c @@ -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; @@ -84,7 +84,8 @@ void dds_init(long long int timestamp, int channel) * to continuous phase mode. */ static unsigned int continuous_phase_comp[CONFIG_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 bus_channel, unsigned int channel, unsigned int ftw, unsigned int pow, int phase_mode, unsigned int amplitude) { unsigned int channel_enc; @@ -157,6 +158,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 +191,22 @@ void dds_batch_exit(void) now = batch_ref_time - batch_count*(DURATION_PROGRAM + DURATION_WRITE); for(i=0;i= 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 +214,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); } } diff --git a/artiq/runtime/messages.h b/artiq/runtime/messages.h index bd2adc912..49df62319 100644 --- a/artiq/runtime/messages.h +++ b/artiq/runtime/messages.h @@ -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 */ diff --git a/artiq/runtime/moninj.c b/artiq/runtime/moninj.c index aea5bfd69..4a7c14205 100644 --- a/artiq/runtime/moninj.c +++ b/artiq/runtime/moninj.c @@ -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\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(); #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 - select RTIO clock source"); puts("ttloe - set TTL output enable"); puts("ttlo - set TTL output value"); + puts("ddsbus - select the DDS bus RTIO channel"); puts("ddssel - 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)); diff --git a/doc/manual/core_device.rst b/doc/manual/core_device.rst index 484f69358..9489277a7 100644 --- a/doc/manual/core_device.rst +++ b/doc/manual/core_device.rst @@ -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 ++++++++ diff --git a/examples/master/device_db.pyon b/examples/master/device_db.pyon index f10b1e6b2..05f9bc7ca 100644 --- a/examples/master/device_db.pyon +++ b/examples/master/device_db.pyon @@ -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": {