diff --git a/common/__init__.py b/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/common/python/__init__.py b/common/python/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/common/python/compat.py b/common/python/compat.py new file mode 100644 index 0000000..ae78ae4 --- /dev/null +++ b/common/python/compat.py @@ -0,0 +1,29 @@ +try: + # Python2 + import ConfigParser as configparser +except ImportError: + # Python3 + import configparser + +try: + # For type checking only + from typing import TYPE_CHECKING +except ImportError: + TYPE_CHECKING = False + +try: + # Python2 + str_ = basestring +except NameError: + # Python3 + str_ = str + +# Taken from six +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper diff --git a/common/python/ini_util.py b/common/python/ini_util.py new file mode 100644 index 0000000..5bbaa44 --- /dev/null +++ b/common/python/ini_util.py @@ -0,0 +1,69 @@ +import os +from collections import OrderedDict + +from .compat import configparser, TYPE_CHECKING, str_ + +if TYPE_CHECKING: + from typing import Iterable, Tuple, Dict, List, Union + + +def read_ini(paths): + # type: (Union[List[str], str]) -> configparser.SafeConfigParser + app_ini = configparser.ConfigParser() + read_ok = app_ini.read(paths) + if isinstance(paths, str_): + paths = [paths] + errored = set(paths) - set(read_ok) + assert not errored, "Can't read ini files %s" % [ + os.path.abspath(x) for x in sorted(errored)] + return app_ini + + +def ini_get(ini, section, field, default): + try: + return ini.get(section, field) + except configparser.NoOptionError: + return default + + +def parse_assigments(line): + # type: (str) -> Dict[str, str] + """Parse name1=value1, name2=value2 into an OrderedDict""" + ret = OrderedDict() + line = line.strip() + if line: + for assignment in line.split(","): + split = assignment.split("=") + assert len(split) == 2, \ + "Expected name=value, got %r" % line + ret[split[0].strip()] = split[1].strip() + return ret + + +def timing_entries(ini, # type: configparser.SafeConfigParser + section # type: str + ): + # type: (...) -> Iterable[Tuple[int, Dict[str, str], Dict[str, str]]] + """Parse timing lines from ini file, returning timing entries + + Args: + ini: The ini files to parse + section: The name of the section to generate lines from + + Returns: + A list of timing entries. Each entry is a tuple of (ts, inputs, outputs) + where inputs and outputs are dictionaries mapping the string field name + to its string value + """ + for ts, line in ini.items(section): + ts = int(ts) + split = line.split("->") + assert len(split) in (1, 2), \ + "Expected ts1: k1=v1, k2=v2 -> k3=v3, k4=v4, got '%s: %s'" %( + ts, line) + inputs = parse_assigments(split[0]) + if len(split) == 2: + outputs = parse_assigments(split[1]) + else: + outputs = {} + yield ts, inputs, outputs diff --git a/common/python/sphinx_timing_directive.py b/common/python/sphinx_timing_directive.py new file mode 100644 index 0000000..6edf333 --- /dev/null +++ b/common/python/sphinx_timing_directive.py @@ -0,0 +1,348 @@ +import os, csv + +from matplotlib.sphinxext import plot_directive +from docutils.parsers.rst import Directive +from docutils import nodes, statemachine +from .ini_util import read_ini, timing_entries + + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) + + +class sequence_plot_node(nodes.Element): + pass + + +class table_plot_node(nodes.Element): + pass + + +class timing_plot_directive(Directive): + + has_content = False + required_arguments = 0 + optional_arguments = 0 + option_spec = {'path': str, 'section': str, 'table': bool, 'nofigs': bool, + 'xlabel': str} + + def catch_insert_input(self, total_lines, source=None): + self.total_lines = total_lines + + def run(self): + # fill the content code with the options from the directive + path = self.options['path'] + section = self.options['section'] + + # Parse the ini file and make any special tables + path = os.path.join(ROOT, path) + ini = read_ini(path) + tables = [] + for ts, inputs, outputs in timing_entries(ini, section): + for name, val in inputs.items(): + if name == "TABLE_ADDRESS": + tables = self.make_long_tables(ini, section, path) + elif name == "TABLE_DATA": + tables = self.make_all_seq_tables(ini, section) + for name, val in outputs.items(): + # TODO: PCAP_DATA + if name == "DATA": + tables = self.make_pcap_table(ini, section) + + args = [path, section] + if "xlabel" in self.options: + args.append(self.options["xlabel"]) + plot_content = [ + "from common.python.timing_plot import make_timing_plot", + "make_timing_plot(%s)" % (", ".join(repr(x) for x in args))] + + # override include_input so we get the result + old_insert_input = self.state_machine.insert_input + self.state_machine.insert_input = self.catch_insert_input + + d = plot_directive.PlotDirective( + self.name, self.arguments, self.options, plot_content, self.lineno, + self.content_offset, self.block_text, self.state, + self.state_machine) + d.run() + + self.state_machine.insert_input = old_insert_input + plot_node = sequence_plot_node() + node = sequence_plot_node() + + # do a nested parse of the lines + self.state.nested_parse( + statemachine.ViewList(initlist=self.total_lines), + self.content_offset, plot_node) + + # add the directives + node.append(plot_node) + for table_node in tables: + node.append(table_node) + return [node] + + def make_pcap_table(self, sequence, sequence_dir): + table_node = table_plot_node() + # find the inputs that change + input_changes = [] + data_header = [] + for ts, inputs, outputs in timing_entries(sequence, sequence_dir): + for name in inputs: + if "." in name: + input_changes.append(name) + elif name == "START_WRITE": + data_header = [] + elif name == "WRITE": + if "x" in inputs[name]: + hdr_name = "0x%X" % int(inputs[name], 16) + else: + hdr_name = "0x%X" % int(inputs[name], 0) + data_header.append(hdr_name) + if not data_header: + return table_node + table_hdr = ["Row"] + # This contains instructions about how to process each data entry + # - None: Just emit it + # - str name: It is the higher order bits of a given name + # - [int shift]: For each shifted value, emit the relevant bit entry + bit_extracts = [] + for name in data_header: + if name.startswith("BITS"): + # Add relevant bit entries + quadrant = int(name[4]) + shifts = [] + bit_extracts.append(shifts) + for bus_name in input_changes: + r = range(quadrant * 32, (quadrant + 1) * 32) + idx = cparser.bit_bus.get(bus_name, None) + if idx in r and bus_name not in table_hdr: + table_hdr.append(bus_name) + shifts.append(idx - quadrant * 32) + elif name.endswith("_H"): + # This is the higher order entry + bit_extracts.append(name[:-2]) + else: + # Add pos entry + bit_extracts.append(None) + table_hdr.append(name) + # Create a table + table = nodes.table() + table_node += table + tgroup = nodes.tgroup(cols=len(table_hdr)) + table += tgroup + for col_width in [len(x) for x in table_hdr]: + tgroup += nodes.colspec(colwidth=col_width) + # add the header + thead = nodes.thead() + tgroup += thead + thead += self.make_row(table_hdr) + # add the body + tbody = nodes.tbody() + tgroup += tbody + # Add each row + r = 0 + row = [r] + high = {} + i = 0 + for ts, inputs, outputs in timing_entries(sequence, sequence_dir): + for names in outputs: + if names == "DATA": + if "x" in outputs["DATA"]: + data = int(outputs["DATA"], 16) + else: + data = int(outputs["DATA"], 0) + if data is not None: + extract = bit_extracts[i] + if type(extract) == list: + for shift in extract: + row.append((data >> shift) & 1) + elif type(extract) == str: + high[extract] = data + else: + row.append(data) + i += 1 + if i >= len(bit_extracts): + for name, val in high.items(): + idx = [ix for ix, x in enumerate(table_hdr) + if x == name][0] + row[idx] += val << 32 + tbody += self.make_row(row) + r += 1 + row = [r] + high = {} + i = 0 + return table_node + + def make_long_tables(self, sequence, sequence_dir, path): + table_node = table_plot_node() + alltables = [] + table_data = [] + table = nodes.table() + path = os.path.dirname(os.path.abspath(path)) + for ts, inputs, outputs in timing_entries(sequence, sequence_dir): + if 'TABLE_ADDRESS' in inputs: + # open the table + file_dir = os.path.join(path, inputs["TABLE_ADDRESS"]) + assert os.path.isfile(file_dir), "%s does not exist" %(file_dir) + with open(file_dir, "r") as table: + reader = csv.DictReader(table, delimiter='\t') + table_data = [line for line in reader] + alltables.append(table_data) + for lt in alltables: + col_widths = [len(x) for x in table_data[0].values()] + ncols = len(col_widths) + table = nodes.table() + # set the column width specs + tgroup = nodes.tgroup(cols=ncols) + table += tgroup + for col_width in col_widths: + tgroup += nodes.colspec(colwidth=col_width) + # add the header + thead = nodes.thead() + tgroup += thead + thead += self.make_row(["T%d" % len(alltables)], [ncols-1]) + h1_text = table_data[0].keys() + thead += self.make_row(h1_text) + tbody = nodes.tbody() + tgroup += tbody + row = [] + for line in table_data: + tbody += self.make_row(line.values()) + table_node.append(table) + return table_node + + def make_all_seq_tables(self, sequence, sequence_dir): + table_node = table_plot_node() + alltables = [] + seqtable = [] + table_write = 0 + frame_count = 0 + table_count = 0 + # get the table data from the sequence file and count the frames + for ts, inputs, outputs in timing_entries(sequence, sequence_dir): + if 'TABLE_DATA' in inputs: + table_write += 1 + seqtable.append(inputs['TABLE_DATA']) + if table_write % 4 == 0: + frame_count += 1 + if 'TABLE_LENGTH' in inputs: + alltables.append(seqtable) + seqtable = [] + frame_count = 0 + table_write = 0 + + for st in alltables: + table_count += 1 + table_node.append(self.make_seq_table("T%d" % table_count, st)) + return table_node + + def make_seq_table(self, title, data): + hdr = 'Repeats Condition Position Time A B C D E F Time A B C D E F' + hdr = hdr.split() + col_widths = [len(x) for x in hdr] + ncols = len(col_widths) + table = nodes.table() + # set the column width specs + tgroup = nodes.tgroup(cols=ncols) + table += tgroup + for col_width in col_widths: + tgroup += nodes.colspec(colwidth=col_width) + # add the header + thead = nodes.thead() + tgroup += thead + thead += self.make_row([title], [ncols-1]) + h1_text = ["#", "Trigger", "Phase1", "Phase1 Outputs", "Phase2", + "Phase2 Outputs"] + h1_more = [None, 1, None, 5, None, 5] + thead += self.make_row(h1_text, h1_more) + thead += self.make_row(hdr) + tbody = nodes.tbody() + tgroup += tbody + # Add each row + for frame in range(len(data) // 4): + row = [] + # First we get n repeats + rpt = int(data[0 + frame * 4], 0) & 0xFFFF + row.append(rpt) + # Then the trigger values + trigger = int(data[0 + frame * 4], 0) >> 16 & 0xF + strings = [ + "Immediate", + "BITA=0", + "BITA=1", + "BITB=0", + "BITB=1", + "BITC=0", + "BITC=1", + "POSA>=POSITION", + "POSA<=POSITION", + "POSB>=POSITION", + "POSB<=POSITION", + "POSC>=POSITION", + "POSC<=POSITION", + "", + "", + ""] + row.append(strings[trigger]) + # Then the position + position = data[1 + frame * 4] + row.append(position) + # Then the phase 1 time + p1Len = data[2 + frame * 4] + row.append(p1Len) + # Then the phase 1 outputs + p1Out = (int(data[0 + frame * 4], 0) >> 20) & 0x3F + for i in range(6): + row.append(p1Out >> i & 1) + # Then the phase 2 time + p2Len = data[3 + frame * 4] + row.append(p2Len) + # Finally the phase 2 outputs + p2Out = (int(data[0 + frame * 4], 0) >> 26) & 0x3F + for i in range(6): + row.append(p2Out >> i & 1) + tbody += self.make_row(row) + return table + + def make_row(self, data, more_cols=None): + if more_cols is None: + more_cols = [None for x in data] + row = nodes.row() + for text, more in zip(data, more_cols): + entry = nodes.entry() + if more is not None: + entry["morecols"] = more + row += entry + para = nodes.paragraph() + entry += para + para += nodes.Text(text) + return row + + +def setup(app): + + app.add_directive('timing_plot', timing_plot_directive) + + app.add_node(table_plot_node, + html=(visit_table_plot, depart_table_plot), + latex=(visit_table_plot, depart_table_plot), + text=(visit_table_plot, depart_table_plot)) + app.add_node(sequence_plot_node, + html=(visit_sequence_plot, depart_sequence_plot), + latex=(visit_sequence_plot, depart_sequence_plot), + text=(visit_sequence_plot, depart_sequence_plot)) + + +def visit_sequence_plot(self, node): + pass + + +def depart_sequence_plot(self, node): + pass + + +def visit_table_plot(self, node): + pass + + +def depart_table_plot(self, node): + pass diff --git a/common/python/timing_plot.py b/common/python/timing_plot.py new file mode 100755 index 0000000..9c76013 --- /dev/null +++ b/common/python/timing_plot.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python +try: + from pkg_resources import require +except ImportError: + pass +else: + require("matplotlib") + +import sys +import os +from collections import OrderedDict + +import matplotlib.pyplot as plt +import numpy as np + +from .ini_util import read_ini, timing_entries + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) + +TRANSITION_HEIGHT = 0.6 +PULSE_HEIGHT = 1.0 +PLOT_OFFSET = 0.25 +CROSS_PIXELS = 8 +TOP_HEIGHT = 0.6 +BOTTOM_HEIGHT = 1.0 +VERTICAL_STRETCH = 0.5 + + +def legend_label(text, x, y, off): + plt.annotate(text, xy=(x, y), xytext=(x-off, y), + horizontalalignment="right", verticalalignment="center") + + +def plot_bit(trace_items, names, offset, crossdist): + for name, (tracex, tracey) in trace_items.items(): + if name in names: + tracey = np.array([int(y, 0) for y in tracey]) + offset -= PULSE_HEIGHT + PLOT_OFFSET + plt.plot(tracex, tracey + offset, linewidth=2) + # add label + legend_label(name, 0, tracey[0] + offset + PULSE_HEIGHT / 2., crossdist) + return offset + + +def plot_pos(trace_items, names, offset, crossdist, ts): + for name, (tracex, tracey) in trace_items.items(): + if name in names: + offset -= TRANSITION_HEIGHT + PLOT_OFFSET + crossx = [0] + top = [offset + TRANSITION_HEIGHT] + bottom = [offset] + for i, x in enumerate(tracex): + # crossover start + crossx.append(x - crossdist) + top.append(top[-1]) + bottom.append(bottom[-1]) + # crossover end + crossx.append(x + crossdist) + top.append(bottom[-1]) + bottom.append(top[-2]) + # add end point + crossx.append(ts) + top.append(top[-1]) + bottom.append(bottom[-1]) + + lines = plt.plot(crossx, top) + plt.plot(crossx, bottom, color=lines[0].get_color()) + plt.fill_between(crossx, top, bottom, color=lines[0].get_color()) + for x, y in zip(tracex, tracey): + xy = (crossdist + x, TRANSITION_HEIGHT / 2. + offset) + plt.annotate(y, xy, color="white", horizontalalignment="left", + verticalalignment="center") + + # add label + legend_label(name, 0, TRANSITION_HEIGHT / 2. + offset, crossdist) + return offset + + +def make_timing_plot(path, section=None, xlabel="Timestamp (125MHz FPGA clock ticks)"): + # Read the ini file and section + ini = read_ini(os.path.join(ROOT, path)) + if not section: + section = ini.sections()[0] + + # walk the inputs and outputs and add the names we're interested in + in_names = [] + out_names = [] + pos_names = set() + values = {} + + for ts, inputs, outputs in timing_entries(ini, section): + for name, val in inputs.items(): + if name.startswith("TABLE_"): + # Add table special + name = "TABLE" + pos_names.add(name) + elif name.endswith("_L") or name.endswith("_H"): + # Add times for time registers + name = name[:-2] + pos_names.add(name) + else: + val = int(val, 0) + if name not in in_names: + in_names.append(name) + values.setdefault(name, set()).add(val) + for name, val in outputs.items(): + if name != "TABLE_STROBES" and name not in out_names: + out_names.append(name) + values.setdefault(name, set()).add(int(val, 0)) + + # constant traces should be pos_names + for name, sval in values.items(): + if len(sval) == 1: + pos_names.add(name) + else: + for val in sval: + if val not in (0, 1): + pos_names.add(name) + break + + # sort the traces into bit and pos traces + bit_traces = OrderedDict() + pos_traces = OrderedDict() + + for name in in_names + out_names: + if name in pos_names: + pos_traces[name] = ([], []) + else: + bit_traces[name] = ([], []) + + # fill in first point + for name, (tracex, tracey) in bit_traces.items(): + tracex.append(0) + tracey.append('0') + + # now populate traces + table_count = 0 + capture_count = 0 + data_count = 0 + lohi = {} + for ts, inputs, outputs in timing_entries(ini, section): + for name, (tracex, tracey) in bit_traces.items(): + if name in inputs: + tracex.append(ts) + tracex.append(ts) + tracey.append(tracey[-1]) + tracey.append(inputs[name]) + elif name in outputs: + tracex.append(ts+1) + tracex.append(ts+1) + tracey.append(tracey[-1]) + tracey.append(outputs[name]) + for name, (tracex, tracey) in pos_traces.items(): + if name == "TABLE": + if "TABLE_START" in inputs: + inputs["TABLE"] = "load..." + elif "TABLE_LENGTH" in inputs: + table_count += 1 + inputs['TABLE'] = "T%d" % table_count + elif name == "DATA": + if "START_WRITE" in inputs: + capture_count = 0 + elif "WRITE" in inputs: + capture_count += 1 + elif name + "_L" in inputs: + lohi[name + "_L"] = int(inputs[name + "_L"], 0) + inputs[name] = lohi[name + "_L"] + \ + (lohi.get(name + "_H", 0) << 32) + elif name + "_H" in inputs: + lohi[name + "_H"] = int(inputs[name + "_H"], 0) + inputs[name] = lohi.get(name + "_L", 0) + \ + (lohi[name + "_H"] << 32) + if name in inputs: + if not tracey or tracey[-1] != inputs[name]: + tracex.append(ts) + tracey.append(inputs[name]) + elif name in outputs: + # TODO: change to PCAP_DATA + if name == "DATA": + data_count += 1 + if (data_count - 1) % capture_count == 0: + outputs[name] = "Row%d" % (data_count / capture_count) + else: + # This is a subsequent count, ignore it + continue + if not tracey or tracey[-1] != outputs[name]: + tracex.append(ts+1) + tracey.append(outputs[name]) + + # add in an extra point at a major tick interval + ts += 2 + if ts < 15: + div = 2 + elif ts < 100: + div = 5 + else: + div = 10 + # round up to div + off = ts % div + if off: + ts += div - off + plt.xlim(0, ts) + + for name, (tracex, tracey) in bit_traces.items(): + tracex.append(ts) + tracey.append(tracey[-1]) + + # half the width of the crossover in timestamp ticks + crossdist = CROSS_PIXELS * ts / 1000. + + # now plot inputs + offset = 0 + offset = plot_pos(pos_traces, in_names, offset, crossdist, ts) + offset = plot_bit(bit_traces, in_names, offset, crossdist) + + # draw a line + offset -= PLOT_OFFSET + plt.plot([0, ts], [offset, offset], 'k--') + + # and now do outputs + offset = plot_bit(bit_traces, out_names, offset, crossdist) + offset = plot_pos(pos_traces, out_names, offset, crossdist, ts) + + plt.ylim(offset - PLOT_OFFSET, 0) + # add a grid, title, legend, and axis label + plt.title(section) + plt.grid(axis="x") + plt.xlabel(xlabel) + # turn off ticks and labels for y + plt.tick_params(left=False, right=False, labelleft=False) + + # make it the right size + fig = plt.gcf() + total_height = TOP_HEIGHT + BOTTOM_HEIGHT + abs(offset) + fig.set_size_inches(7.5, total_height * VERTICAL_STRETCH, forward=True) + + # set the margins + top_frac = 1.0 - TOP_HEIGHT / total_height + bottom_frac = BOTTOM_HEIGHT / total_height + plt.subplots_adjust(left=0.18, right=0.98, top=top_frac, bottom=bottom_frac) + + plt.show() + + +if __name__ == "__main__": + # test + make_timing_plot(*sys.argv[1:]) diff --git a/docs/conf.py b/docs/conf.py index bf9f28d..df19c14 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,11 +7,18 @@ import sys from pathlib import Path from subprocess import check_output +from pkg_resources import require + import requests import PandABlocks +require("sphinx_rtd_theme") +require("matplotlib") +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +sys.path.insert(0, ROOT) + # -- General configuration ------------------------------------------------ # General information about the project. @@ -44,6 +51,10 @@ "sphinx_copybutton", # For the card element "sphinx_design", + # Timing plots + 'matplotlib.sphinxext.plot_directive', + 'common.python.sphinx_timing_directive', + ] # If true, Sphinx will warn about all references where the target cannot diff --git a/docs/images/tutorial1_bits.png b/docs/images/tutorial1_bits.png new file mode 100644 index 0000000..b02f229 Binary files /dev/null and b/docs/images/tutorial1_bits.png differ diff --git a/docs/images/tutorial1_layout.png b/docs/images/tutorial1_layout.png new file mode 100644 index 0000000..045f2b3 Binary files /dev/null and b/docs/images/tutorial1_layout.png differ diff --git a/docs/images/tutorial1_pulse.png b/docs/images/tutorial1_pulse.png new file mode 100644 index 0000000..13ff161 Binary files /dev/null and b/docs/images/tutorial1_pulse.png differ diff --git a/docs/images/tutorial2_layout.png b/docs/images/tutorial2_layout.png new file mode 100644 index 0000000..2c243c2 Binary files /dev/null and b/docs/images/tutorial2_layout.png differ diff --git a/docs/images/tutorial2_pcap.png b/docs/images/tutorial2_pcap.png new file mode 100644 index 0000000..0b031e5 Binary files /dev/null and b/docs/images/tutorial2_pcap.png differ diff --git a/docs/images/tutorial2_positions.png b/docs/images/tutorial2_positions.png new file mode 100644 index 0000000..27e585b Binary files /dev/null and b/docs/images/tutorial2_positions.png differ diff --git a/docs/user/index.rst b/docs/user/index.rst index 0fe7803..8bba29b 100644 --- a/docs/user/index.rst +++ b/docs/user/index.rst @@ -13,6 +13,9 @@ side-bar. :caption: Tutorials :maxdepth: 1 + tutorials/tutorial1_blinking_leds.rst + tutorials/tutorial2_position_capture.rst + +++ Tutorials for installation and typical usage. New users start here. diff --git a/docs/user/tutorials/template_tutorial1_leds.json b/docs/user/tutorials/template_tutorial1_leds.json new file mode 100644 index 0000000..49b256f --- /dev/null +++ b/docs/user/tutorials/template_tutorial1_leds.json @@ -0,0 +1,1351 @@ +{ + "attributes": { + "layout": { + "BITS": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "CALC1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "CALC2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "CLOCK1": { + "x": -253.55555555555554, + "y": -43.20740226463033, + "visible": true + }, + "CLOCK2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER5": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER6": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER7": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER8": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "DIV1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "DIV2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "FILTER1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "FILTER2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "INENC1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "INENC2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "INENC3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "INENC4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT5": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT6": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT7": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT8": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LVDSIN1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LVDSIN2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LVDSOUT1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LVDSOUT2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "OUTENC1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "OUTENC2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "OUTENC3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "OUTENC4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PCAP": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PCOMP1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PCOMP2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PGEN1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PGEN2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PULSE1": { + "x": 114.44444444444446, + "y": -361.52407300030745, + "visible": true + }, + "PULSE2": { + "x": 114.44444444444446, + "y": -152.82407605206527, + "visible": true + }, + "PULSE3": { + "x": 116.44444444444446, + "y": 51.07591784441911, + "visible": true + }, + "PULSE4": { + "x": 116.44444444444446, + "y": 259.77593005145036, + "visible": true + }, + "SEQ1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SEQ2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SRGATE1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SRGATE2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SRGATE3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SRGATE4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SYSTEM": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN5": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN6": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT1": { + "x": 328.44444444444446, + "y": -360.47406994854964, + "visible": true + }, + "TTLOUT2": { + "x": 328.44444444444446, + "y": -151.77407300030745, + "visible": true + }, + "TTLOUT3": { + "x": 330.44444444444446, + "y": 52.12592089617692, + "visible": true + }, + "TTLOUT4": { + "x": 330.44444444444446, + "y": 260.82592547381364, + "visible": true + }, + "TTLOUT5": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT6": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT7": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT8": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT9": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT10": { + "x": 0.0, + "y": 0.0, + "visible": false + } + }, + "exports": {} + }, + "children": { + "BITS": { + "label": "Soft inputs and constant bits ", + "parameters": "expanded", + "a": false, + "b": false, + "c": false, + "d": false, + "outputs": "expanded" + }, + "CALC1": { + "label": "Position calc 1", + "inputs": "expanded", + "inpa": "ZERO", + "inpb": "ZERO", + "inpc": "ZERO", + "inpd": "ZERO", + "parameters": "expanded", + "typea": "Value", + "typeb": "Value", + "typec": "Value", + "typed": "Value", + "func": "A+B+C+D", + "shift": 0, + "outputs": "expanded" + }, + "CALC2": { + "label": "Position calc 2", + "inputs": "expanded", + "inpa": "ZERO", + "inpb": "ZERO", + "inpc": "ZERO", + "inpd": "ZERO", + "parameters": "expanded", + "typea": "Value", + "typeb": "Value", + "typec": "Value", + "typed": "Value", + "func": "A+B+C+D", + "shift": 0, + "outputs": "expanded" + }, + "CLOCK1": { + "label": "Configurable clocks 1", + "inputs": "expanded", + "enable": "ONE", + "enableDelay": 0, + "parameters": "expanded", + "period": 1.0, + "periodUnits": "s", + "outputs": "expanded" + }, + "CLOCK2": { + "label": "Configurable clocks 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "period": 0.0, + "periodUnits": "s", + "outputs": "expanded" + }, + "COUNTER1": { + "label": "Up/Down pulse counter 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER2": { + "label": "Up/Down pulse counter 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER3": { + "label": "Up/Down pulse counter 3", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER4": { + "label": "Up/Down pulse counter 4", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER5": { + "label": "Up/Down pulse counter 5", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER6": { + "label": "Up/Down pulse counter 6", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER7": { + "label": "Up/Down pulse counter 7", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER8": { + "label": "Up/Down pulse counter 8", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "DIV1": { + "label": "Pulse divider 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "inp": "ZERO", + "inpDelay": 0, + "parameters": "expanded", + "divisor": 0, + "firstPulse": "OutN", + "outputs": "expanded", + "readbacks": "expanded" + }, + "DIV2": { + "label": "Pulse divider 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "inp": "ZERO", + "inpDelay": 0, + "parameters": "expanded", + "divisor": 0, + "firstPulse": "OutN", + "outputs": "expanded", + "readbacks": "expanded" + }, + "FILTER1": { + "label": "Filter block modes are Difference and Divider 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "inp": "ZERO", + "parameters": "expanded", + "mode": "difference", + "outputs": "expanded" + }, + "FILTER2": { + "label": "Filter block modes are Difference and Divider 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "inp": "ZERO", + "parameters": "expanded", + "mode": "difference", + "outputs": "expanded" + }, + "INENC1": { + "label": "Input encoder 1", + "inputs": "expanded", + "clk": "ZERO", + "clkDelay": 0, + "parameters": "expanded", + "protocol": "Quadrature", + "clkSrc": "Internally Generated", + "clkPeriod": 0.0, + "clkPeriodUnits": "s", + "framePeriod": 0.0, + "framePeriodUnits": "s", + "bits": 0, + "lsbDiscard": 0, + "msbDiscard": 0, + "setp": 0, + "rstOnZ": false, + "outputs": "expanded", + "readbacks": "expanded" + }, + "INENC2": { + "label": "Input encoder 2", + "inputs": "expanded", + "clk": "ZERO", + "clkDelay": 0, + "parameters": "expanded", + "protocol": "Quadrature", + "clkSrc": "Internally Generated", + "clkPeriod": 0.0, + "clkPeriodUnits": "s", + "framePeriod": 0.0, + "framePeriodUnits": "s", + "bits": 0, + "lsbDiscard": 0, + "msbDiscard": 0, + "setp": 0, + "rstOnZ": false, + "outputs": "expanded", + "readbacks": "expanded" + }, + "INENC3": { + "label": "Input encoder 3", + "inputs": "expanded", + "clk": "ZERO", + "clkDelay": 0, + "parameters": "expanded", + "protocol": "Quadrature", + "clkSrc": "Internally Generated", + "clkPeriod": 0.0, + "clkPeriodUnits": "s", + "framePeriod": 0.0, + "framePeriodUnits": "s", + "bits": 0, + "lsbDiscard": 0, + "msbDiscard": 0, + "setp": 0, + "rstOnZ": false, + "outputs": "expanded", + "readbacks": "expanded" + }, + "INENC4": { + "label": "Input encoder 4", + "inputs": "expanded", + "clk": "ZERO", + "clkDelay": 0, + "parameters": "expanded", + "protocol": "Quadrature", + "clkSrc": "Internally Generated", + "clkPeriod": 0.0, + "clkPeriodUnits": "s", + "framePeriod": 0.0, + "framePeriodUnits": "s", + "bits": 0, + "lsbDiscard": 0, + "msbDiscard": 0, + "setp": 0, + "rstOnZ": false, + "outputs": "expanded", + "readbacks": "expanded" + }, + "LUT1": { + "label": "Lookup table 1", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT2": { + "label": "Lookup table 2", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT3": { + "label": "Lookup table 3", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT4": { + "label": "Lookup table 4", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT5": { + "label": "Lookup table 5", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT6": { + "label": "Lookup table 6", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT7": { + "label": "Lookup table 7", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT8": { + "label": "Lookup table 8", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LVDSIN1": { + "label": "LVDS input 1", + "outputs": "expanded" + }, + "LVDSIN2": { + "label": "LVDS input 2", + "outputs": "expanded" + }, + "LVDSOUT1": { + "label": "LVDS output 1", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "LVDSOUT2": { + "label": "LVDS output 2", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "OUTENC1": { + "label": "Output encoder 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "generatorError": "No", + "a": "ZERO", + "aDelay": 0, + "b": "ZERO", + "bDelay": 0, + "z": "ZERO", + "zDelay": 0, + "data": "ZERO", + "dataDelay": 0, + "protocol": "Quadrature", + "bits": 0, + "qperiod": 0.0, + "qperiodUnits": "s", + "outputs": "expanded", + "val": "ZERO", + "readbacks": "expanded" + }, + "OUTENC2": { + "label": "Output encoder 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "generatorError": "No", + "a": "ZERO", + "aDelay": 0, + "b": "ZERO", + "bDelay": 0, + "z": "ZERO", + "zDelay": 0, + "data": "ZERO", + "dataDelay": 0, + "protocol": "Quadrature", + "bits": 0, + "qperiod": 0.0, + "qperiodUnits": "s", + "outputs": "expanded", + "val": "ZERO", + "readbacks": "expanded" + }, + "OUTENC3": { + "label": "Output encoder 3", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "generatorError": "No", + "a": "ZERO", + "aDelay": 0, + "b": "ZERO", + "bDelay": 0, + "z": "ZERO", + "zDelay": 0, + "data": "ZERO", + "dataDelay": 0, + "protocol": "Quadrature", + "bits": 0, + "qperiod": 0.0, + "qperiodUnits": "s", + "outputs": "expanded", + "val": "ZERO", + "readbacks": "expanded" + }, + "OUTENC4": { + "label": "Output encoder 4", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "generatorError": "No", + "a": "ZERO", + "aDelay": 0, + "b": "ZERO", + "bDelay": 0, + "z": "ZERO", + "zDelay": 0, + "data": "ZERO", + "dataDelay": 0, + "protocol": "Quadrature", + "bits": 0, + "qperiod": 0.0, + "qperiodUnits": "s", + "outputs": "expanded", + "val": "ZERO", + "readbacks": "expanded" + }, + "PCAP": { + "label": "Position capture control ", + "inputs": "expanded", + "enable": "ONE", + "enableDelay": 0, + "gate": "ZERO", + "gateDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "trigEdge": "Rising", + "shiftSum": 0, + "outputs": "expanded", + "tsStartCapture": "No", + "tsEndCapture": "No", + "tsTrigCapture": "Value", + "samplesCapture": "No" + }, + "PCOMP1": { + "label": "Position compare 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "inp": "ZERO", + "parameters": "expanded", + "preStart": 0, + "start": 0, + "width": 0, + "step": 0, + "pulses": 0, + "relative": "Absolute", + "dir": "Positive", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PCOMP2": { + "label": "Position compare 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "inp": "ZERO", + "parameters": "expanded", + "preStart": 0, + "start": 0, + "width": 0, + "step": 0, + "pulses": 0, + "relative": "Absolute", + "dir": "Positive", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PGEN1": { + "label": "Position generator 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "table": { + "typeid": "malcolm:core/Table:1.0", + "position": [] + }, + "repeats": 0, + "outputs": "expanded" + }, + "PGEN2": { + "label": "Position generator 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "table": { + "typeid": "malcolm:core/Table:1.0", + "position": [] + }, + "repeats": 0, + "outputs": "expanded" + }, + "PULSE1": { + "label": "One-shot pulse delay and stretch 1", + "inputs": "expanded", + "enable": "ONE", + "enableDelay": 0, + "trig": "CLOCK1.OUT", + "trigDelay": 0, + "parameters": "expanded", + "delay": 0.0, + "delayUnits": "s", + "width": 0.7, + "widthUnits": "s", + "trigEdge": "Rising", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PULSE2": { + "label": "One-shot pulse delay and stretch 2", + "inputs": "expanded", + "enable": "ONE", + "enableDelay": 0, + "trig": "CLOCK1.OUT", + "trigDelay": 0, + "parameters": "expanded", + "delay": 0.1, + "delayUnits": "s", + "width": 0.5, + "widthUnits": "s", + "trigEdge": "Rising", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PULSE3": { + "label": "One-shot pulse delay and stretch 3", + "inputs": "expanded", + "enable": "ONE", + "enableDelay": 0, + "trig": "CLOCK1.OUT", + "trigDelay": 0, + "parameters": "expanded", + "delay": 0.2, + "delayUnits": "s", + "width": 0.3, + "widthUnits": "s", + "trigEdge": "Rising", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PULSE4": { + "label": "One-shot pulse delay and stretch 4", + "inputs": "expanded", + "enable": "ONE", + "enableDelay": 0, + "trig": "CLOCK1.OUT", + "trigDelay": 0, + "parameters": "expanded", + "delay": 0.3, + "delayUnits": "s", + "width": 0.1, + "widthUnits": "s", + "trigEdge": "Rising", + "outputs": "expanded", + "readbacks": "expanded" + }, + "SEQ1": { + "label": "Sequencer 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "bita": "ZERO", + "bitaDelay": 0, + "bitb": "ZERO", + "bitbDelay": 0, + "bitc": "ZERO", + "bitcDelay": 0, + "posa": "ZERO", + "posb": "ZERO", + "posc": "ZERO", + "parameters": "expanded", + "table": { + "typeid": "malcolm:core/Table:1.0", + "repeats": [], + "trigger": [], + "position": [], + "time1": [], + "outa1": [], + "outb1": [], + "outc1": [], + "outd1": [], + "oute1": [], + "outf1": [], + "time2": [], + "outa2": [], + "outb2": [], + "outc2": [], + "outd2": [], + "oute2": [], + "outf2": [] + }, + "prescale": 0.0, + "prescaleUnits": "s", + "repeats": 0, + "outputs": "expanded", + "readbacks": "expanded" + }, + "SEQ2": { + "label": "Sequencer 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "bita": "ZERO", + "bitaDelay": 0, + "bitb": "ZERO", + "bitbDelay": 0, + "bitc": "ZERO", + "bitcDelay": 0, + "posa": "ZERO", + "posb": "ZERO", + "posc": "ZERO", + "parameters": "expanded", + "table": { + "typeid": "malcolm:core/Table:1.0", + "repeats": [], + "trigger": [], + "position": [], + "time1": [], + "outa1": [], + "outb1": [], + "outc1": [], + "outd1": [], + "oute1": [], + "outf1": [], + "time2": [], + "outa2": [], + "outb2": [], + "outc2": [], + "outd2": [], + "oute2": [], + "outf2": [] + }, + "prescale": 0.0, + "prescaleUnits": "s", + "repeats": 0, + "outputs": "expanded", + "readbacks": "expanded" + }, + "SRGATE1": { + "label": "Set reset gate 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "set": "ZERO", + "setDelay": 0, + "rst": "ZERO", + "rstDelay": 0, + "parameters": "expanded", + "whenDisabled": "Set output low", + "setEdge": "Rising", + "rstEdge": "Rising", + "outputs": "expanded" + }, + "SRGATE2": { + "label": "Set reset gate 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "set": "ZERO", + "setDelay": 0, + "rst": "ZERO", + "rstDelay": 0, + "parameters": "expanded", + "whenDisabled": "Set output low", + "setEdge": "Rising", + "rstEdge": "Rising", + "outputs": "expanded" + }, + "SRGATE3": { + "label": "Set reset gate 3", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "set": "ZERO", + "setDelay": 0, + "rst": "ZERO", + "rstDelay": 0, + "parameters": "expanded", + "whenDisabled": "Set output low", + "setEdge": "Rising", + "rstEdge": "Rising", + "outputs": "expanded" + }, + "SRGATE4": { + "label": "Set reset gate 4", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "set": "ZERO", + "setDelay": 0, + "rst": "ZERO", + "rstDelay": 0, + "parameters": "expanded", + "whenDisabled": "Set output low", + "setEdge": "Rising", + "rstEdge": "Rising", + "outputs": "expanded" + }, + "SYSTEM": { + "label": "System control FPGA ", + "readbacks": "expanded", + "parameters": "expanded", + "extClock": "sma clock" + }, + "TTLIN1": { + "label": "TTL input 1", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN2": { + "label": "TTL input 2", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN3": { + "label": "TTL input 3", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN4": { + "label": "TTL input 4", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN5": { + "label": "TTL input 5", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN6": { + "label": "TTL input 6", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLOUT1": { + "label": "TTL output 1", + "inputs": "expanded", + "val": "PULSE1.OUT", + "valDelay": 0 + }, + "TTLOUT2": { + "label": "TTL output 2", + "inputs": "expanded", + "val": "PULSE2.OUT", + "valDelay": 0 + }, + "TTLOUT3": { + "label": "TTL output 3", + "inputs": "expanded", + "val": "PULSE3.OUT", + "valDelay": 0 + }, + "TTLOUT4": { + "label": "TTL output 4", + "inputs": "expanded", + "val": "PULSE4.OUT", + "valDelay": 0 + }, + "TTLOUT5": { + "label": "TTL output 5", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT6": { + "label": "TTL output 6", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT7": { + "label": "TTL output 7", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT8": { + "label": "TTL output 8", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT9": { + "label": "TTL output 9", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT10": { + "label": "TTL output 10", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + } + } +} \ No newline at end of file diff --git a/docs/user/tutorials/template_tutorial2_pcap.json b/docs/user/tutorials/template_tutorial2_pcap.json new file mode 100644 index 0000000..b6e0da0 --- /dev/null +++ b/docs/user/tutorials/template_tutorial2_pcap.json @@ -0,0 +1,1363 @@ +{ + "attributes": { + "layout": { + "BITS": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "CALC1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "CALC2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "CLOCK1": { + "x": -4.0, + "y": 70.9406304359436, + "visible": true + }, + "CLOCK2": { + "x": -8.0, + "y": 216.31562280654907, + "visible": true + }, + "COUNTER1": { + "x": 177.0, + "y": 144.32812547683716, + "visible": true + }, + "COUNTER2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER5": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER6": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER7": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "COUNTER8": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "DIV1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "DIV2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "FILTER1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "FILTER2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "INENC1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "INENC2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "INENC3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "INENC4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT5": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT6": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT7": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LUT8": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LVDSIN1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LVDSIN2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LVDSOUT1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "LVDSOUT2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "OUTENC1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "OUTENC2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "OUTENC3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "OUTENC4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PCAP": { + "x": -212.0, + "y": 126.41562128067017, + "visible": true + }, + "PCOMP1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PCOMP2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PGEN1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PGEN2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PULSE1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PULSE2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PULSE3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "PULSE4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SEQ1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SEQ2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SRGATE1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SRGATE2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SRGATE3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SRGATE4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "SYSTEM": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN5": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLIN6": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT1": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT2": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT3": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT4": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT5": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT6": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT7": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT8": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT9": { + "x": 0.0, + "y": 0.0, + "visible": false + }, + "TTLOUT10": { + "x": 0.0, + "y": 0.0, + "visible": false + } + }, + "exports": {} + }, + "children": { + "BITS": { + "label": "Soft inputs and constant bits ", + "parameters": "expanded", + "a": false, + "b": false, + "c": false, + "d": false, + "outputs": "expanded" + }, + "CALC1": { + "label": "Position calc 1", + "inputs": "expanded", + "inpa": "ZERO", + "inpb": "ZERO", + "inpc": "ZERO", + "inpd": "ZERO", + "parameters": "expanded", + "typea": "Value", + "typeb": "Value", + "typec": "Value", + "typed": "Value", + "func": "A+B+C+D", + "shift": 0, + "outputs": "expanded" + }, + "CALC2": { + "label": "Position calc 2", + "inputs": "expanded", + "inpa": "ZERO", + "inpb": "ZERO", + "inpc": "ZERO", + "inpd": "ZERO", + "parameters": "expanded", + "typea": "Value", + "typeb": "Value", + "typec": "Value", + "typed": "Value", + "func": "A+B+C+D", + "shift": 0, + "outputs": "expanded" + }, + "CLOCK1": { + "label": "Configurable clocks 1", + "inputs": "expanded", + "enable": "PCAP.ACTIVE", + "enableDelay": 0, + "parameters": "expanded", + "period": 1.0, + "periodUnits": "s", + "outputs": "expanded" + }, + "CLOCK2": { + "label": "Configurable clocks 2", + "inputs": "expanded", + "enable": "PCAP.ACTIVE", + "enableDelay": 0, + "parameters": "expanded", + "period": 0.2, + "periodUnits": "s", + "outputs": "expanded" + }, + "COUNTER1": { + "label": "Up/Down pulse counter 1", + "inputs": "expanded", + "enable": "PCAP.ACTIVE", + "enableDelay": 0, + "trig": "CLOCK2.OUT", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 1, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER2": { + "label": "Up/Down pulse counter 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 1, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER3": { + "label": "Up/Down pulse counter 3", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER4": { + "label": "Up/Down pulse counter 4", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER5": { + "label": "Up/Down pulse counter 5", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER6": { + "label": "Up/Down pulse counter 6", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER7": { + "label": "Up/Down pulse counter 7", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "COUNTER8": { + "label": "Up/Down pulse counter 8", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "dir": "ZERO", + "dirDelay": 0, + "parameters": "expanded", + "start": 0, + "step": 0, + "max": 0, + "min": 0, + "outputs": "expanded" + }, + "DIV1": { + "label": "Pulse divider 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "inp": "ZERO", + "inpDelay": 0, + "parameters": "expanded", + "divisor": 0, + "firstPulse": "OutN", + "outputs": "expanded", + "readbacks": "expanded" + }, + "DIV2": { + "label": "Pulse divider 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "inp": "ZERO", + "inpDelay": 0, + "parameters": "expanded", + "divisor": 0, + "firstPulse": "OutN", + "outputs": "expanded", + "readbacks": "expanded" + }, + "FILTER1": { + "label": "Filter block modes are Difference and Divider 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "inp": "ZERO", + "parameters": "expanded", + "mode": "average", + "outputs": "expanded" + }, + "FILTER2": { + "label": "Filter block modes are Difference and Divider 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "inp": "ZERO", + "parameters": "expanded", + "mode": "difference", + "outputs": "expanded" + }, + "INENC1": { + "label": "Input encoder 1", + "inputs": "expanded", + "clk": "ZERO", + "clkDelay": 0, + "parameters": "expanded", + "protocol": "Quadrature", + "clkSrc": "Internally Generated", + "clkPeriod": 0.0, + "clkPeriodUnits": "s", + "framePeriod": 0.0, + "framePeriodUnits": "s", + "bits": 0, + "lsbDiscard": 0, + "msbDiscard": 0, + "setp": 0, + "rstOnZ": false, + "outputs": "expanded", + "readbacks": "expanded" + }, + "INENC2": { + "label": "Input encoder 2", + "inputs": "expanded", + "clk": "ZERO", + "clkDelay": 0, + "parameters": "expanded", + "protocol": "Quadrature", + "clkSrc": "Internally Generated", + "clkPeriod": 0.0, + "clkPeriodUnits": "s", + "framePeriod": 0.0, + "framePeriodUnits": "s", + "bits": 0, + "lsbDiscard": 0, + "msbDiscard": 0, + "setp": 0, + "rstOnZ": false, + "outputs": "expanded", + "readbacks": "expanded" + }, + "INENC3": { + "label": "Input encoder 3", + "inputs": "expanded", + "clk": "ZERO", + "clkDelay": 0, + "parameters": "expanded", + "protocol": "Quadrature", + "clkSrc": "Internally Generated", + "clkPeriod": 0.0, + "clkPeriodUnits": "s", + "framePeriod": 0.0, + "framePeriodUnits": "s", + "bits": 0, + "lsbDiscard": 0, + "msbDiscard": 0, + "setp": 0, + "rstOnZ": false, + "outputs": "expanded", + "readbacks": "expanded" + }, + "INENC4": { + "label": "Input encoder 4", + "inputs": "expanded", + "clk": "ZERO", + "clkDelay": 0, + "parameters": "expanded", + "protocol": "Quadrature", + "clkSrc": "Internally Generated", + "clkPeriod": 0.0, + "clkPeriodUnits": "s", + "framePeriod": 0.0, + "framePeriodUnits": "s", + "bits": 0, + "lsbDiscard": 0, + "msbDiscard": 0, + "setp": 0, + "rstOnZ": false, + "outputs": "expanded", + "readbacks": "expanded" + }, + "LUT1": { + "label": "Lookup table 1", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT2": { + "label": "Lookup table 2", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT3": { + "label": "Lookup table 3", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT4": { + "label": "Lookup table 4", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT5": { + "label": "Lookup table 5", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT6": { + "label": "Lookup table 6", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT7": { + "label": "Lookup table 7", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LUT8": { + "label": "Lookup table 8", + "inputs": "expanded", + "inpa": "ZERO", + "inpaDelay": 0, + "inpb": "ZERO", + "inpbDelay": 0, + "inpc": "ZERO", + "inpcDelay": 0, + "inpd": "ZERO", + "inpdDelay": 0, + "inpe": "ZERO", + "inpeDelay": 0, + "parameters": "expanded", + "typea": "Input-Level", + "typeb": "Input-Level", + "typec": "Input-Level", + "typed": "Input-Level", + "typee": "Input-Level", + "func": "0x00000000", + "outputs": "expanded" + }, + "LVDSIN1": { + "label": "LVDS input 1", + "outputs": "expanded" + }, + "LVDSIN2": { + "label": "LVDS input 2", + "outputs": "expanded" + }, + "LVDSOUT1": { + "label": "LVDS output 1", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "LVDSOUT2": { + "label": "LVDS output 2", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "OUTENC1": { + "label": "Output encoder 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "generatorError": "No", + "a": "ZERO", + "aDelay": 0, + "b": "ZERO", + "bDelay": 0, + "z": "ZERO", + "zDelay": 0, + "data": "ZERO", + "dataDelay": 0, + "protocol": "Quadrature", + "bits": 0, + "qperiod": 0.0, + "qperiodUnits": "s", + "outputs": "expanded", + "val": "ZERO", + "readbacks": "expanded" + }, + "OUTENC2": { + "label": "Output encoder 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "generatorError": "No", + "a": "ZERO", + "aDelay": 0, + "b": "ZERO", + "bDelay": 0, + "z": "ZERO", + "zDelay": 0, + "data": "ZERO", + "dataDelay": 0, + "protocol": "Quadrature", + "bits": 0, + "qperiod": 0.0, + "qperiodUnits": "s", + "outputs": "expanded", + "val": "ZERO", + "readbacks": "expanded" + }, + "OUTENC3": { + "label": "Output encoder 3", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "generatorError": "No", + "a": "ZERO", + "aDelay": 0, + "b": "ZERO", + "bDelay": 0, + "z": "ZERO", + "zDelay": 0, + "data": "ZERO", + "dataDelay": 0, + "protocol": "Quadrature", + "bits": 0, + "qperiod": 0.0, + "qperiodUnits": "s", + "outputs": "expanded", + "val": "ZERO", + "readbacks": "expanded" + }, + "OUTENC4": { + "label": "Output encoder 4", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "parameters": "expanded", + "generatorError": "No", + "a": "ZERO", + "aDelay": 0, + "b": "ZERO", + "bDelay": 0, + "z": "ZERO", + "zDelay": 0, + "data": "ZERO", + "dataDelay": 0, + "protocol": "Quadrature", + "bits": 0, + "qperiod": 0.0, + "qperiodUnits": "s", + "outputs": "expanded", + "val": "ZERO", + "readbacks": "expanded" + }, + "PCAP": { + "label": "Position capture control ", + "inputs": "expanded", + "enable": "ONE", + "enableDelay": 0, + "gate": "CLOCK1.OUT", + "gateDelay": 1, + "trig": "CLOCK1.OUT", + "trigDelay": 1, + "parameters": "expanded", + "trigEdge": "Falling", + "shiftSum": 0, + "outputs": "expanded", + "tsStartCapture": "No", + "tsEndCapture": "No", + "tsTrigCapture": "No", + "samplesCapture": "No" + }, + "PCOMP1": { + "label": "Position compare 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "inp": "ZERO", + "parameters": "expanded", + "preStart": 0, + "start": 0, + "width": 0, + "step": 0, + "pulses": 0, + "relative": "Absolute", + "dir": "Positive", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PCOMP2": { + "label": "Position compare 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "inp": "ZERO", + "parameters": "expanded", + "preStart": 0, + "start": 0, + "width": 0, + "step": 0, + "pulses": 0, + "relative": "Absolute", + "dir": "Positive", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PGEN1": { + "label": "Position generator 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "table": { + "typeid": "malcolm:core/Table:1.0", + "position": [] + }, + "repeats": 0, + "outputs": "expanded" + }, + "PGEN2": { + "label": "Position generator 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "table": { + "typeid": "malcolm:core/Table:1.0", + "position": [] + }, + "repeats": 0, + "outputs": "expanded" + }, + "PULSE1": { + "label": "One-shot pulse delay and stretch 1", + "inputs": "expanded", + "enable": "ONE", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "delay": 0.1, + "delayUnits": "s", + "width": 10000.0, + "widthUnits": "ms", + "pulses": 0, + "step": 0.0, + "stepUnits": "s", + "trigEdge": "Rising", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PULSE2": { + "label": "One-shot pulse delay and stretch 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "delay": 0.2, + "delayUnits": "s", + "width": 0.1, + "widthUnits": "s", + "pulses": 0, + "step": 0.0, + "stepUnits": "s", + "trigEdge": "Rising", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PULSE3": { + "label": "One-shot pulse delay and stretch 3", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "delay": 0.3, + "delayUnits": "s", + "width": 0.1, + "widthUnits": "s", + "pulses": 0, + "step": 0.0, + "stepUnits": "s", + "trigEdge": "Rising", + "outputs": "expanded", + "readbacks": "expanded" + }, + "PULSE4": { + "label": "One-shot pulse delay and stretch 4", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "trig": "ZERO", + "trigDelay": 0, + "parameters": "expanded", + "delay": 0.4, + "delayUnits": "s", + "width": 0.1, + "widthUnits": "s", + "pulses": 0, + "step": 0.0, + "stepUnits": "s", + "trigEdge": "Rising", + "outputs": "expanded", + "readbacks": "expanded" + }, + "SEQ1": { + "label": "Sequencer 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "bita": "ZERO", + "bitaDelay": 0, + "bitb": "ZERO", + "bitbDelay": 0, + "bitc": "ZERO", + "bitcDelay": 0, + "posa": "ZERO", + "posb": "ZERO", + "posc": "ZERO", + "parameters": "expanded", + "table": { + "typeid": "malcolm:core/Table:1.0", + "repeats": [], + "trigger": [], + "position": [], + "time1": [], + "outa1": [], + "outb1": [], + "outc1": [], + "outd1": [], + "oute1": [], + "outf1": [], + "time2": [], + "outa2": [], + "outb2": [], + "outc2": [], + "outd2": [], + "oute2": [], + "outf2": [] + }, + "prescale": 0.0, + "prescaleUnits": "s", + "repeats": 0, + "outputs": "expanded", + "readbacks": "expanded" + }, + "SEQ2": { + "label": "Sequencer 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "bita": "ZERO", + "bitaDelay": 0, + "bitb": "ZERO", + "bitbDelay": 0, + "bitc": "ZERO", + "bitcDelay": 0, + "posa": "ZERO", + "posb": "ZERO", + "posc": "ZERO", + "parameters": "expanded", + "table": { + "typeid": "malcolm:core/Table:1.0", + "repeats": [], + "trigger": [], + "position": [], + "time1": [], + "outa1": [], + "outb1": [], + "outc1": [], + "outd1": [], + "oute1": [], + "outf1": [], + "time2": [], + "outa2": [], + "outb2": [], + "outc2": [], + "outd2": [], + "oute2": [], + "outf2": [] + }, + "prescale": 0.0, + "prescaleUnits": "s", + "repeats": 0, + "outputs": "expanded", + "readbacks": "expanded" + }, + "SRGATE1": { + "label": "Set reset gate 1", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "set": "ZERO", + "setDelay": 0, + "rst": "ZERO", + "rstDelay": 0, + "parameters": "expanded", + "whenDisabled": "Set output low", + "setEdge": "Rising", + "rstEdge": "Rising", + "outputs": "expanded" + }, + "SRGATE2": { + "label": "Set reset gate 2", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "set": "ZERO", + "setDelay": 0, + "rst": "ZERO", + "rstDelay": 0, + "parameters": "expanded", + "whenDisabled": "Set output low", + "setEdge": "Rising", + "rstEdge": "Rising", + "outputs": "expanded" + }, + "SRGATE3": { + "label": "Set reset gate 3", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "set": "ZERO", + "setDelay": 0, + "rst": "ZERO", + "rstDelay": 0, + "parameters": "expanded", + "whenDisabled": "Set output low", + "setEdge": "Rising", + "rstEdge": "Rising", + "outputs": "expanded" + }, + "SRGATE4": { + "label": "Set reset gate 4", + "inputs": "expanded", + "enable": "ZERO", + "enableDelay": 0, + "set": "ZERO", + "setDelay": 0, + "rst": "ZERO", + "rstDelay": 0, + "parameters": "expanded", + "whenDisabled": "Set output low", + "setEdge": "Rising", + "rstEdge": "Rising", + "outputs": "expanded" + }, + "SYSTEM": { + "label": "System control FPGA ", + "readbacks": "expanded", + "parameters": "expanded", + "extClock": "int clock" + }, + "TTLIN1": { + "label": "TTL input 1", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN2": { + "label": "TTL input 2", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN3": { + "label": "TTL input 3", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN4": { + "label": "TTL input 4", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN5": { + "label": "TTL input 5", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLIN6": { + "label": "TTL input 6", + "parameters": "expanded", + "term": "High-Z", + "outputs": "expanded" + }, + "TTLOUT1": { + "label": "TTL output 1", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT2": { + "label": "TTL output 2", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT3": { + "label": "TTL output 3", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT4": { + "label": "TTL output 4", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT5": { + "label": "TTL output 5", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT6": { + "label": "TTL output 6", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT7": { + "label": "TTL output 7", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT8": { + "label": "TTL output 8", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT9": { + "label": "TTL output 9", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + }, + "TTLOUT10": { + "label": "TTL output 10", + "inputs": "expanded", + "val": "ZERO", + "valDelay": 0 + } + } +} \ No newline at end of file diff --git a/docs/user/tutorials/tutorial1_blinking_leds.rst b/docs/user/tutorials/tutorial1_blinking_leds.rst new file mode 100644 index 0000000..ad89c10 --- /dev/null +++ b/docs/user/tutorials/tutorial1_blinking_leds.rst @@ -0,0 +1,94 @@ +.. _blinking_leds_tutorial: + +Blinking LEDs Tutorial +====================== + +This tutorial will introduce you to the basics of PandABlocks, how to wire +Blocks together to make different LEDs flash at different rates + + +Opening the GUI +--------------- + +Point your web browser at the ip address or hostname of the PandA and you will +be greeted with a welcome page. At the bottom of this page will be links for +Docs, Control and Admin. You can use the Control link to open the Web Control +page that we will use in these tutorials. For more information on the Web +Control, see its entry in the Docs section. + + +Loading the tutorial design +--------------------------- + +The Design dropdown box allows you to select from saved designs stored on the +PandA. Selecting an item from this list will load the saved design over the +current Block settings. You can use the Save method to save your current +design if you wish to keep it. + +Select "template_tutorial1_leds" from the box and the settings and wiring of +the Blocks in the PandA will be changed to the following: + +.. image:: ../../images/tutorial1_layout.png + +If you now look at the front panel of the PandA you should see the first 4 +TTL output LEDs turn on sequentially, then turn off in the opposite order. + + +How the design works +-------------------- + +The CLOCKS Block is creating a 50% duty cycle pulse train with a period of 1s. +PULSE1..4 are taking this as an input trigger, and producing a different width +pulse with a different delay for each PULSE Block. These PULSE Blocks work as a +delay line, queuing a series of pulses up to be sent out when the delay expires. + +If you click on one of them you can see its settings: + +.. image:: ../../images/tutorial1_pulse.png + +If you increase the delay beyond the 1s period you will notice that the +``Queued`` field will increase, but the PULSE Block will still continue +outputting pulses after the desired delay. However if you increase the width +beyond the pulse period the Block will drop the pulse, reporting it via the +``Dropped`` field. This is so it avoids merging them together. + +You can also try clicking on the CLOCKS Block to modify the period of the input +pulse train. + +You can also try wiring these outputs to different TTLOUT Blocks by clicking +the Palette icon, dragging a TTLOUT Block onto the canvas, and connecting it +up by dragging the PULSE out port to the TTLOUT val port. + + +The Bit Bus +----------- + +All ports on the visible Blocks are blue. They represent bits, single boolean +values that can propagate through the system by connecting Blocks together. +These outputs can be viewed on their respective Blocks by clicking them on the +design, or all together by clicking the Bits field in the left hand pane: + +.. image:: ../../images/tutorial1_bits.png + +If you scroll down to the section with the Pulse blocks you will see the +same pattern of flashing lights as on the front of the PandA + +.. note:: + + The web GUI polls the PandA at 10Hz, receiving the current value of each bit + and whether it has changed. The web GUI uses this information to reflect the + current value of each bit if pulsing at less than 5Hz, and displaying a 5Hz + pulsing value if faster than 5Hz. This means that you will see even short + pulses reflected on the web GUI. The front panel LEDs have a similar + behaviour but with a maximum rate of 10Hz. + + +Conclusion +---------- + +This tutorial has shown how to load a saved design and modify some parameters. +It has also introduced the PULSE delay block that is useful for delaying and +stretching trigger signals. It has introduced bit outputs and shown how they +can be connected to the outside world using the TTLOUT Blocks. In the next +tutorial we will read about position outputs, how they can be set and how they +can be captured. diff --git a/docs/user/tutorials/tutorial2.timing.ini b/docs/user/tutorials/tutorial2.timing.ini new file mode 100644 index 0000000..077b600 --- /dev/null +++ b/docs/user/tutorials/tutorial2.timing.ini @@ -0,0 +1,97 @@ +[.] +description: Timing diagrams for tutorial 2 + +[Trigger Only] +1000 : PCAP.ACTIVE=1 +1002 : CLOCK1.OUT=1, CLOCK2.OUT=1 +1004 : COUNTER1.OUT=1 +1502 : CLOCK1.OUT=0, CLOCK2.OUT=0 +1505 : PCAP.TRIG=1 +1506 : PCAP.TRIG=0 +2002 : CLOCK1.OUT=1, CLOCK2.OUT=1 +2004 : COUNTER1.OUT=2 +2502 : CLOCK1.OUT=0, CLOCK2.OUT=0 +2505 : PCAP.TRIG=1 +2506 : PCAP.TRIG=0 +3002 : CLOCK1.OUT=1, CLOCK2.OUT=1 +3004 : COUNTER1.OUT=3 +3502 : CLOCK1.OUT=0, CLOCK2.OUT=0 +3505 : PCAP.TRIG=1 +3506 : PCAP.TRIG=0 +4002 : CLOCK1.OUT=1, CLOCK2.OUT=1 +4004 : COUNTER1.OUT=4 +4502 : CLOCK1.OUT=0, CLOCK2.OUT=0 +4505 : PCAP.TRIG=1 +4506 : PCAP.TRIG=0 +4690 : PCAP.ACTIVE=0 +5000 : + +[Trigger Counter 5x faster] +1000 : PCAP.ACTIVE=1 +1002 : CLOCK1.OUT=1, CLOCK2.OUT=1 +1004 : COUNTER1.OUT=1 +1102 : CLOCK2.OUT=0 +1202 : CLOCK2.OUT=1 +1204 : COUNTER1.OUT=2 +1302 : CLOCK2.OUT=0 +1402 : CLOCK2.OUT=1 +1404 : COUNTER1.OUT=3 +1502 : CLOCK1.OUT=0, CLOCK2.OUT=0 +1505 : PCAP.TRIG=1 +1506 : PCAP.TRIG=0 +1602 : CLOCK2.OUT=1 +1604 : COUNTER1.OUT=4 +1702 : CLOCK2.OUT=0 +1802 : CLOCK2.OUT=1 +1804 : COUNTER1.OUT=5 +1902 : CLOCK2.OUT=0 +2002 : CLOCK1.OUT=1, CLOCK2.OUT=1 +2004 : COUNTER1.OUT=6 +2102 : CLOCK2.OUT=0 +2202 : CLOCK2.OUT=1 +2204 : COUNTER1.OUT=7 +2302 : CLOCK2.OUT=0 +2402 : CLOCK2.OUT=1 +2404 : COUNTER1.OUT=8 +2502 : CLOCK1.OUT=0, CLOCK2.OUT=0 +2505 : PCAP.TRIG=1 +2506 : PCAP.TRIG=0 +2602 : CLOCK2.OUT=1 +2604 : COUNTER1.OUT=9 +2702 : CLOCK2.OUT=0 +2802 : CLOCK2.OUT=1 +2804 : COUNTER1.OUT=10 +2902 : CLOCK2.OUT=0 +3002 : CLOCK1.OUT=1, CLOCK2.OUT=1 +3004 : COUNTER1.OUT=11 +3102 : CLOCK2.OUT=0 +3202 : CLOCK2.OUT=1 +3204 : COUNTER1.OUT=12 +3302 : CLOCK2.OUT=0 +3402 : CLOCK2.OUT=1 +3404 : COUNTER1.OUT=13 +3502 : CLOCK1.OUT=0, CLOCK2.OUT=0 +3505 : PCAP.TRIG=1 +3506 : PCAP.TRIG=0 +3602 : CLOCK2.OUT=1 +3604 : COUNTER1.OUT=14 +3702 : CLOCK2.OUT=0 +3802 : CLOCK2.OUT=1 +3804 : COUNTER1.OUT=15 +3902 : CLOCK2.OUT=0 +4002 : CLOCK1.OUT=1, CLOCK2.OUT=1 +4004 : COUNTER1.OUT=16 +4102 : CLOCK2.OUT=0 +4202 : CLOCK2.OUT=1 +4204 : COUNTER1.OUT=17 +4302 : CLOCK2.OUT=0 +4402 : CLOCK2.OUT=1 +4404 : COUNTER1.OUT=18 +4502 : CLOCK1.OUT=0, CLOCK2.OUT=0 +4505 : PCAP.TRIG=1 +4506 : PCAP.TRIG=0 +4602 : CLOCK2.OUT=1 +4604 : COUNTER1.OUT=19 +4690 : PCAP.ACTIVE=0 +4691 : CLOCK2.OUT=0 +5000 : \ No newline at end of file diff --git a/docs/user/tutorials/tutorial2_position_capture.rst b/docs/user/tutorials/tutorial2_position_capture.rst new file mode 100644 index 0000000..9581bdb --- /dev/null +++ b/docs/user/tutorials/tutorial2_position_capture.rst @@ -0,0 +1,208 @@ +.. _position_capture_tutorial: + +Position Capture Tutorial +========================= + +This tutorial will introduce you to the Position Capture interface of +PandABlocks, how to provide trigger signals to control when these capture points +are taken and visualize the data. + + +Loading the tutorial design +--------------------------- + +Select "template_tutorial2_pcap" from the Design dropdown box and the settings +and wiring of the Blocks in the PandA will be changed to the following: + +.. image:: ../../images/tutorial2_layout.png + + +How the design works +-------------------- + +This design has two CLOCK Blocks, which are enabled as soon as the PCAP Block +becomes active: + +- The first CLOCK is wired to PCAP trigger and gate. The gate is a level driven + signal that provides the window of time that a capture should be active over. + The trigger is an edge driven signal that actually captures data. In this + example, PCAP.TRIG_EDGE="Falling" so capture will be triggered on a falling + edge of the trigger. +- The second CLOCK is wired to a COUNTER, triggering the increment of the + counter value. + +We start off with both CLOCK Blocks set to a period of 1s, so each second the +COUNTER will increment by one, followed by a PCAP trigger half a second later. +This is best viewed as a timing diagram: + +.. timing_plot:: + :path: docs/user/tutorials/tutorial2.timing.ini + :section: Trigger Only + :xlabel: Milliseconds + +What PCAP does on that trigger is determined by the PCAP Block settings, and +the contents of the Bits and Positions tables. For Bits you can turn capture +(instantaneous at the time of trigger) on and off. For Positions, you have a +choice of: + +============== ======================= +Capture Description +-------------- ----------------------- +No Don't capture +Value Instantaneous capture at time of trigger +Diff The difference in the value while gate was high +Sum The sum of all the samples while gate was high +Min The smallest value seen while gate was high +Max The largest value seen while gate was high +Mean The average value seen while gate was high +Min Max Capture both Min and Max +Min Max Mean Capture Min Max and Mean +============== ======================= + +There are also a handful of other fields like the start of frame, end of frame +and trigger time that can be captured by setting fields on the PCAP Block. If +you click on the PCAP Block you will see them in the Outputs section: + +.. image:: ../../images/tutorial2_pcap.png + +In the inputs section of the PCAP Block we can see that we have set a delay of +1 for both the Trig and Gate. Delays on bit inputs are in FPGA clock ticks, and +are there to compensate for different length data paths that need to be aligned. +Each Block and each wire in PandA take 1 clock tick each. In this example, both +COUNTER1 and PCAP are being triggered by a CLOCK in the same clock tick, but +we want to delay the input to PCAP by one clock tick so that it sees the updated +COUNTER1 value *after* the corresponding CLOCK rising edge. + +.. note:: + + The delay fields of the PCAP Block are also shown as small badges on the + input ports of the Block + +We can set COUNTER1.OUT to capture the Value at trigger by modifying the +Positions table and pressing Submit: + +.. image:: ../../images/tutorial2_positions.png + +Now we can get a client ready to receive data. We can capture data in ASCII or +Binary format as detailed in the TCP server documentation, and TANGO and EPICS +have clients to do this. For this tutorial we will just use the ASCII format on +the commandline to check:: + + $ nc 8889 + +Here we could specify binary output and header format, but we'll just stick +with the default ASCII output (the default). Press Return again, and we will +see:: + + OK + +Now go back to the PandA layout and select the PCAP Block, pressing the ARM +button. The Active light will go on and data will start streaming in the +terminal window until Disarm is pressed:: + + missed: 0 + process: Scaled + format: ASCII + fields: + COUNTER1.OUT double Value scale: 1 offset: 0 units: + + 1 + 2 + 3 + 4 + END 4 Disarmed + +This tallies with the timing diagram we saw above, the captured value matches +the instantaneous value of COUNTER1.OUT when PCAP.TRIG went high. + +We will now make the COUNTER1.OUT increment 5 times faster. Set CLOCK2.PERIOD +to 0.2s, and click PCAP.ARM and you will see the captured value change:: + + missed: 0 + process: Scaled + format: ASCII + fields: + COUNTER1.OUT double Value scale: 1 offset: 0 units: + + 3 + 8 + 13 + 18 + END 4 Disarmed + +If we look at the timing plot, we can see this also matched what we expect, the +value is captured mid way through each increment of 5: + +.. timing_plot:: + :path: docs/user/tutorials/tutorial2.timing.ini + :section: Trigger Counter 5x faster + :xlabel: Milliseconds + +Now let's investigate the other options. If we change the Positions table +so COUNTER1.OUT captures the Diff instead of Value then we will see it captures +the difference between the value at the rising edge of the gate, and the +falling edge:: + + missed: 0 + process: Scaled + format: ASCII + fields: + COUNTER1.OUT double Diff scale: 1 offset: 0 units: + + 2 + 2 + 2 + 2 + END 4 Disarmed + +This again matches the timing plot, GATE rises when COUNTER was at 1, and falls +at 3, then rises at 6 and falls at 8. + +.. note:: + + If we hadn't put in the 1 clock tick delays for Gate and Trig then we would + see 3 rather than 2, as GATE would rise at 0 and fall at 3, then rise at 5 + and fall at 8 + +This capture output is generally used with COUNTER Blocks connected to an input +fed from a V2F_ to capture the total counts produced in a given time window. + +If we change COUNTER1.OUT to capture Min Max and Mean, we will see the other +options:: + + missed: 0 + process: Scaled + format: ASCII + fields: + COUNTER1.OUT double Min scale: 1 offset: 0 units: + COUNTER1.OUT double Max scale: 1 offset: 0 units: + COUNTER1.OUT double Mean scale: 1 offset: 0 units: + + 1 3 1.8 + 6 8 6.8 + 11 13 11.8 + 16 18 16.8 + END 4 Disarmed + +Here we can see our min and max values as we expected, and also the Mean of +the COUNTER value during the total gate:: + + # (sum of counter_value * time_at_value) / gate_time = mean + (1 * 0.2 + 2 * 0.2 + 3 * 0.1) / 0.5 = 1.8 + (6 * 0.2 + 7 * 0.2 + 8 * 0.1) / 0.5 = 6.8 + +This capture output is generally used with encoders, to give the min, max and +mean value of the encoder over a detector frame. + +Conclusion +---------- + +This tutorial has shown how to use the Position Capture interface of a PandA +to capture entries on the position bus, and introduced the different capture +types. It has also introduced the COUNTER block that is useful connecting to +the pulse train produced by a V2F_. In the next tutorial we will read about +how to use position compare to generate triggers from position outputs, and +how to configure position capture to work with it. + + +.. _V2F: https://hal.archives-ouvertes.fr/hal-01573024/document \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 6e3abb6..7a4c249 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,14 +28,17 @@ dev = [ "mypy", "flake8-isort", "Flake8-pyproject", + "matplotlib", "pipdeptree", "pre-commit", "pydata-sphinx-theme>=0.12", "pytest", "pytest-cov", + "sphinx", "sphinx-autobuild", "sphinx-copybutton", "sphinx-design", + "sphinx_rtd_theme", "tox-direct", "types-mock", ]