pyadi-jif 0.1.0__py2.py3-none-any.whl → 0.1.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. adijif/__init__.py +2 -2
  2. adijif/clocks/ad9523_1_bf.py +3 -3
  3. adijif/clocks/ad9528_bf.py +1 -1
  4. adijif/clocks/hmc7044_bf.py +1 -1
  5. adijif/clocks/ltc6952.py +2 -2
  6. adijif/clocks/ltc6952_bf.py +1 -1
  7. adijif/clocks/ltc6953.py +2 -2
  8. adijif/converters/__init__.py +12 -1
  9. adijif/converters/ad9081.py +1 -1
  10. adijif/converters/ad9081_dp.py +2 -0
  11. adijif/converters/ad9084.py +29 -7
  12. adijif/converters/ad9084_draw.py +20 -14
  13. adijif/converters/ad9084_util.py +24 -5
  14. adijif/converters/ad9088_dp.py +111 -0
  15. adijif/converters/converter.py +153 -2
  16. adijif/draw.py +11 -2
  17. adijif/fpgas/xilinx/__init__.py +4 -2
  18. adijif/jesd.py +3 -1
  19. adijif/plls/adf4030.py +6 -1
  20. adijif/plls/adf4382.py +0 -1
  21. adijif/solvers.py +5 -4
  22. adijif/system.py +16 -1
  23. adijif/tools/explorer/cli.py +36 -0
  24. adijif/tools/explorer/main.py +41 -0
  25. adijif/tools/explorer/src/pages/__init__.py +16 -0
  26. adijif/tools/explorer/src/pages/clockconfigurator.py +193 -0
  27. adijif/tools/explorer/src/pages/helpers/datapath.py +85 -0
  28. adijif/tools/explorer/src/pages/helpers/drawers.py +87 -0
  29. adijif/tools/explorer/src/pages/helpers/jesd.py +140 -0
  30. adijif/tools/explorer/src/pages/jesdmodeselector.py +209 -0
  31. adijif/tools/explorer/src/pages/systemconfigurator.py +252 -0
  32. adijif/tools/explorer/src/state.py +141 -0
  33. adijif/tools/explorer/src/utils.py +37 -0
  34. adijif/types.py +23 -4
  35. {pyadi_jif-0.1.0.dist-info → pyadi_jif-0.1.1.dist-info}/METADATA +36 -12
  36. {pyadi_jif-0.1.0.dist-info → pyadi_jif-0.1.1.dist-info}/RECORD +41 -30
  37. pyadi_jif-0.1.1.dist-info/entry_points.txt +2 -0
  38. adijif/d2/__init__.py +0 -26
  39. adijif/d2/d2lib.h +0 -81
  40. {pyadi_jif-0.1.0.dist-info → pyadi_jif-0.1.1.dist-info}/WHEEL +0 -0
  41. {pyadi_jif-0.1.0.dist-info → pyadi_jif-0.1.1.dist-info}/licenses/AUTHORS.rst +0 -0
  42. {pyadi_jif-0.1.0.dist-info → pyadi_jif-0.1.1.dist-info}/licenses/LICENSE +0 -0
  43. {pyadi_jif-0.1.0.dist-info → pyadi_jif-0.1.1.dist-info}/top_level.txt +0 -0
adijif/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  __author__ = """Analog Devices, Inc."""
4
4
  __email__ = "travis.collins@analog.com"
5
- __version__ = "0.1.0"
5
+ __version__ = "0.1.1"
6
6
 
7
7
  import adijif.solvers
8
8
  import adijif.utils
@@ -20,7 +20,7 @@ from adijif.converters.ad9081 import (
20
20
  ad9082_rx,
21
21
  ad9082_tx,
22
22
  )
23
- from adijif.converters.ad9084 import ad9084_rx
23
+ from adijif.converters.ad9084 import ad9084_rx, ad9088_rx
24
24
  from adijif.converters.ad9144 import ad9144
25
25
  from adijif.converters.ad9680 import ad9680
26
26
  from adijif.converters.adrv9009 import adrv9009, adrv9009_rx, adrv9009_tx
@@ -55,7 +55,7 @@ class ad9523_1_bf(clock):
55
55
  if (vco / m1) % mod == 0:
56
56
  # See if we can use only m1 and not both m1+m2
57
57
  rods = (vco / m1) / required_output_rates
58
- if np.all(np.in1d(rods, self.d_available)):
58
+ if np.all(np.isin(rods, self.d_available)):
59
59
  configs.append(
60
60
  {
61
61
  "m1": m1,
@@ -67,10 +67,10 @@ class ad9523_1_bf(clock):
67
67
  )
68
68
  else:
69
69
  # Try to use m2 as well to meet required out clocks
70
- f1 = np.in1d(rods, self.d_available)
70
+ f1 = np.isin(rods, self.d_available)
71
71
  for m2 in self.m1_available:
72
72
  rods2 = (vco / m2) / required_output_rates
73
- f2 = np.in1d(rods2, self.d_available)
73
+ f2 = np.isin(rods2, self.d_available)
74
74
  if np.logical_or(f1, f2).all():
75
75
  configs.append(
76
76
  {
@@ -56,7 +56,7 @@ class ad9528_bf(clock):
56
56
  and (vco / m1) % mod == 0
57
57
  ):
58
58
  required_output_divs = (vco / m1) / required_output_rates
59
- if np.all(np.in1d(required_output_divs, self.d_available)):
59
+ if np.all(np.isin(required_output_divs, self.d_available)):
60
60
  configs.append(
61
61
  {
62
62
  "m1": m1,
@@ -52,7 +52,7 @@ class hmc7044_bf(clock):
52
52
  # Check if required dividers for output clocks are in set
53
53
  if f % mod == 0:
54
54
  d = f / rates
55
- if np.all(np.in1d(d, odivs)) and f not in vcos:
55
+ if np.all(np.isin(d, odivs)) and f not in vcos:
56
56
  if f not in vcos:
57
57
  vcos.append(f)
58
58
  config = {
adijif/clocks/ltc6952.py CHANGED
@@ -600,7 +600,7 @@ class ltc6952(ltc6952_bf):
600
600
  self._clk_names = clk_names
601
601
 
602
602
  # Add requested clocks to output constraints
603
- for out_freq in out_freqs:
603
+ for out_freq, clk_name in zip(out_freqs, clk_names): # noqa: B905
604
604
  if self.solver == "gekko":
605
605
  __d = self._d if isinstance(self._d, list) else [self._d]
606
606
  if __d.sort() != self.d_available.sort():
@@ -613,7 +613,7 @@ class ltc6952(ltc6952_bf):
613
613
  od = self.model.Intermediate(mp * pow(2, nx))
614
614
 
615
615
  elif self.solver == "CPLEX":
616
- od = self._convert_input(self._d, "d_" + str(out_freq))
616
+ od = self._convert_input(self._d, f"d_{out_freq}_{clk_name}")
617
617
 
618
618
  self._add_equation(
619
619
  [self.vcxo / self.config["r2"] * self.config["n2"] / od == out_freq]
@@ -51,7 +51,7 @@ class ltc6952_bf(clock):
51
51
  # Check if required dividers for output clocks are in set
52
52
  if f % mod == 0:
53
53
  d = f / rates
54
- if np.all(np.in1d(d, odivs)) and f not in vcos:
54
+ if np.all(np.isin(d, odivs)) and f not in vcos:
55
55
  if f not in vcos:
56
56
  vcos.append(f)
57
57
  config = {
adijif/clocks/ltc6953.py CHANGED
@@ -490,7 +490,7 @@ class ltc6953(clock):
490
490
  self._setup(input_ref)
491
491
 
492
492
  # Add requested clocks to output constraints
493
- for out_freq in out_freqs:
493
+ for out_freq, clk_name in zip(out_freqs, clk_names): # noqa: B905
494
494
  if self.solver == "gekko":
495
495
  __m = self._d if isinstance(self.__m, list) else [self.__m]
496
496
  if __m.sort() != self.m_available.sort():
@@ -503,7 +503,7 @@ class ltc6953(clock):
503
503
  od = self.model.Intermediate(mp * pow(2, nx))
504
504
 
505
505
  elif self.solver == "CPLEX":
506
- od = self._convert_input(self._m, "m_" + str(out_freq))
506
+ od = self._convert_input(self._m, f"m_{out_freq}_{clk_name}")
507
507
 
508
508
  self._add_equation([self.input_ref / od == out_freq])
509
509
  self.config["out_dividers"].append(od)
@@ -1,3 +1,14 @@
1
1
  """ADI JIF converter models."""
2
2
 
3
- supported_parts = ["ad9680", "adrv9009_rx", "ad9081_rx", "ad9144", "ad9084_rx"]
3
+ supported_parts = [
4
+ "ad9680",
5
+ "adrv9009_rx",
6
+ "adrv9009_tx",
7
+ "ad9081_rx",
8
+ "ad9081_tx",
9
+ "ad9082_rx",
10
+ "ad9082_tx",
11
+ "ad9144",
12
+ "ad9084_rx",
13
+ "ad9088_rx",
14
+ ]
@@ -70,7 +70,7 @@ class ad9081_core(converter, metaclass=ABCMeta):
70
70
  M_available = [1, 2, 3, 4, 6, 8, 12, 16]
71
71
  L_available = [1, 2, 3, 4, 6, 8]
72
72
  N_available = [12, 16]
73
- Np_available = [12, 16, 24]
73
+ Np_available = [8, 12, 16, 24]
74
74
  F_available = [1, 2, 3, 4, 6, 8, 12, 16, 24, 32]
75
75
  S_available = [1, 2, 4, 8]
76
76
  # FIXME
@@ -120,11 +120,13 @@ class ad9081_dp_tx:
120
120
 
121
121
  cduc_enabled = [True, True, True, True]
122
122
  cduc_interpolation = 1
123
+ cduc_interpolations_available = [1, 2, 4, 6, 8, 12]
123
124
  cduc_nco_frequencies = [0, 0, 0, 0]
124
125
  cduc_nco_phases = [0, 0, 0, 0]
125
126
 
126
127
  fduc_enabled = [False, False, False, False, False, False, False, False]
127
128
  fduc_interpolation = 1
129
+ fduc_interpolations_available = [1, 2, 3, 4, 6, 8]
128
130
  fduc_nco_frequencies = [0, 0, 0, 0, 0, 0, 0, 0]
129
131
  fduc_nco_phases = [0, 0, 0, 0, 0, 0, 0, 0]
130
132
 
@@ -8,6 +8,7 @@ from .ad9084_dp import ad9084_dp_rx
8
8
  from .ad9084_draw import ad9084_draw
9
9
  from .ad9084_util import _load_rx_config_modes, apply_settings
10
10
  from .ad9084_util import parse_json_config as parse_json_cfg
11
+ from .ad9088_dp import ad9088_dp_rx
11
12
  from .adc import adc
12
13
  from .converter import converter
13
14
 
@@ -132,7 +133,8 @@ class ad9084_core(ad9084_draw, converter, metaclass=ABCMeta):
132
133
  Returns:
133
134
  List[str]: List of strings of clock names in order
134
135
  """
135
- return ["AD9084_ref_clk", "AD9084_sysref"]
136
+ name = "AD9084" if "9084" in self.name else "AD9088"
137
+ return [f"{name}_ref_clk", f"{name}_sysref"]
136
138
 
137
139
  @property
138
140
  @abstractmethod
@@ -280,7 +282,7 @@ class ad9084_rx(adc, ad9084_core):
280
282
  sample_clock_min = 312.5e6 / 16 # FIXME
281
283
  sample_clock_max = 20e9
282
284
 
283
- quick_configuration_modes = _load_rx_config_modes()
285
+ quick_configuration_modes = _load_rx_config_modes(part="AD9084")
284
286
 
285
287
  datapath = ad9084_dp_rx()
286
288
 
@@ -310,11 +312,14 @@ class ad9084_rx(adc, ad9084_core):
310
312
  *args (Any): Pass through arguments
311
313
  **kwargs (Any): Pass through keyword arguments
312
314
  """
313
- self.sample_clock = int(2.5e9)
314
- self.datapath.cddc_decimations = [4] * 4
315
- self.datapath.fddc_decimations = [2] * 8
316
- self.datapath.fddc_enabled = [True] * 8
317
- self.set_quick_configuration_mode("47", "jesd204c")
315
+ self.sample_clock = int(2.5e9) if "AD9084" in self.name else int(1e9)
316
+ N = 1 if "9084" in self.name else 2
317
+ self.datapath.cddc_decimations = [4] * 4 * N
318
+ self.datapath.fddc_decimations = [2] * 8 * N
319
+ self.datapath.fddc_enabled = [True] * 8 * N
320
+ mode = "47" if "9084" in self.name else "45"
321
+
322
+ self.set_quick_configuration_mode(mode, "jesd204c")
318
323
 
319
324
  super().__init__(*args, **kwargs)
320
325
  self._init_diagram()
@@ -372,6 +377,23 @@ class ad9084_rx(adc, ad9084_core):
372
377
  # raise Exception("Decimation not valid")
373
378
 
374
379
 
380
+ class ad9088_rx(ad9084_rx):
381
+ """AD9088 Receive model."""
382
+
383
+ converter_type = "adc"
384
+ name = "AD9088_RX"
385
+
386
+ converter_clock_min = 2.9e9
387
+ converter_clock_max = 8e9
388
+
389
+ sample_clock_min = 2.9e9 / (6 * 24) # with max decimation
390
+ sample_clock_max = 8e9
391
+
392
+ datapath = ad9088_dp_rx()
393
+
394
+ quick_configuration_modes = _load_rx_config_modes(part="AD9088")
395
+
396
+
375
397
  # class ad9084_tx(dac, ad9084_core):
376
398
  # """AD9084 Transmit model."""
377
399
 
@@ -16,7 +16,10 @@ class ad9084_draw:
16
16
  self.ic_diagram_node = None
17
17
  self._diagram_output_dividers = []
18
18
 
19
- self.ic_diagram_node = Node("AD9084")
19
+ name = "AD9084" if "9084" in self.name else "AD9088"
20
+ N = 4 if "9084" in self.name else 8
21
+
22
+ self.ic_diagram_node = Node(name)
20
23
 
21
24
  # External
22
25
  # ref_in = Node("REF_IN", ntype="input")
@@ -28,19 +31,19 @@ class ad9084_draw:
28
31
  self.ic_diagram_node.add_child(crossbar)
29
32
  self.ic_diagram_node.add_child(crossbar_rm)
30
33
 
31
- for adc in range(4):
34
+ for adc in range(N):
32
35
  adc_node = Node(f"ADC{adc}", ntype="adc")
33
36
  self.ic_diagram_node.add_child(adc_node)
34
37
  adc_node.shape = "parallelogram"
35
38
  self.ic_diagram_node.add_connection({"from": adc_node, "to": crossbar})
36
39
 
37
- for cddc in range(4):
40
+ for cddc in range(N):
38
41
  cddc_node = Node(f"CDDC{cddc}", ntype="ddc")
39
42
  self.ic_diagram_node.add_child(cddc_node)
40
43
  self.ic_diagram_node.add_connection({"from": crossbar, "to": cddc_node})
41
44
  self.ic_diagram_node.add_connection({"from": cddc_node, "to": crossbar_rm})
42
45
 
43
- for fddc in range(8):
46
+ for fddc in range(N * 2):
44
47
  fddc_node = Node(f"FDDC{fddc}", ntype="ddc")
45
48
  self.ic_diagram_node.add_child(fddc_node)
46
49
  self.ic_diagram_node.add_connection({"from": crossbar_rm, "to": fddc_node})
@@ -48,7 +51,7 @@ class ad9084_draw:
48
51
  jesd204_framer = Node("JESD204 Framer", ntype="jesd204framer")
49
52
  self.ic_diagram_node.add_child(jesd204_framer)
50
53
 
51
- for ddc in range(8):
54
+ for ddc in range(N * 2):
52
55
  fddc = self.ic_diagram_node.get_child(f"FDDC{ddc}")
53
56
  self.ic_diagram_node.add_connection({"from": fddc, "to": jesd204_framer})
54
57
 
@@ -97,8 +100,11 @@ class ad9084_draw:
97
100
 
98
101
  system_draw = lo is not None
99
102
 
103
+ name = "AD9084" if "9084" in self.name else "AD9088"
104
+ N = 4 if "9084" in self.name else 8
105
+
100
106
  if not system_draw:
101
- lo = Layout("AD9084 Example")
107
+ lo = Layout(f"{name} Example")
102
108
  lo.show_rates = self.show_rates
103
109
  else:
104
110
  # Verify lo is a Layout object
@@ -109,7 +115,7 @@ class ad9084_draw:
109
115
  ref_in = Node("REF_IN", ntype="input")
110
116
  lo.add_node(ref_in)
111
117
  else:
112
- to_node = lo.get_node("AD9084_ref_clk")
118
+ to_node = lo.get_node(f"{name}_ref_clk")
113
119
  # Locate node connected to this one
114
120
  from_node = lo.get_connection(to=to_node.name)
115
121
  assert from_node, "No connection found"
@@ -119,16 +125,16 @@ class ad9084_draw:
119
125
  # Remove to_node since it is not needed
120
126
  lo.remove_node(to_node.name)
121
127
 
122
- for i in range(4):
128
+ for i in range(N):
123
129
  adc = self.ic_diagram_node.get_child(f"ADC{i}")
124
130
  lo.add_connection(
125
- {"from": ref_in, "to": adc, "rate": clocks["AD9084_ref_clk"]}
131
+ {"from": ref_in, "to": adc, "rate": clocks[f"{name}_ref_clk"]}
126
132
  )
127
133
 
128
134
  # Update Node values
129
135
  fddc_index = 0
130
- for cddc in range(4):
131
- rate = clocks["AD9084_ref_clk"]
136
+ for cddc in range(N):
137
+ rate = clocks[f"{name}_ref_clk"]
132
138
  self.ic_diagram_node.update_connection("MUX0", f"CDDC{cddc}", rate)
133
139
 
134
140
  cddc_node = self.ic_diagram_node.get_child(f"CDDC{cddc}")
@@ -163,11 +169,11 @@ class ad9084_draw:
163
169
  {
164
170
  "from": sysref_in,
165
171
  "to": self.ic_diagram_node.get_child("JESD204 Framer"),
166
- "rate": clocks["AD9084_sysref"],
172
+ "rate": clocks[f"{name}_sysref"],
167
173
  }
168
174
  )
169
175
  else:
170
- to_node = lo.get_node("AD9084_sysref")
176
+ to_node = lo.get_node(f"{name}_sysref")
171
177
  # Locate node connected to this one
172
178
  from_node = lo.get_connection(to=to_node.name)
173
179
  assert from_node, "No connection found"
@@ -181,7 +187,7 @@ class ad9084_draw:
181
187
  {
182
188
  "from": sysref_in,
183
189
  "to": self.ic_diagram_node.get_child("JESD204 Framer"),
184
- "rate": clocks["AD9084_sysref"],
190
+ "rate": clocks[f"{name}_sysref"],
185
191
  }
186
192
  )
187
193
 
@@ -41,12 +41,23 @@ def _convert_to_config(
41
41
  }
42
42
 
43
43
 
44
- def _load_rx_config_modes() -> Dict:
45
- """Load RX JESD configuration tables from file."""
46
- return _read_table_xlsx("AD9084_JTX_JRX.xlsx")
44
+ def _load_rx_config_modes(part: str) -> Dict:
45
+ """Load RX JESD configuration tables from file.
46
+
47
+ Args:
48
+ part (str): Part name, either "AD9084" or "AD9088".
49
+
50
+ Returns:
51
+ Dict: Dictionary of JESD configuration modes.
52
+
53
+ Raises:
54
+ AssertionError: If the part is not supported.
55
+ """
56
+ assert part in ["AD9084", "AD9088"], f"Unsupported part: {part}"
57
+ return _read_table_xlsx("AD9084_JTX_JRX.xlsx", part)
47
58
 
48
59
 
49
- def _read_table_xlsx(filename: str) -> Dict:
60
+ def _read_table_xlsx(filename: str, part: str) -> Dict:
50
61
  loc = os.path.dirname(__file__)
51
62
  fn = os.path.join(loc, "resources", filename)
52
63
  table = pd.read_excel(open(fn, "rb"), sheet_name="JTX_RxPath")
@@ -57,7 +68,15 @@ def _read_table_xlsx(filename: str) -> Dict:
57
68
  jrx_modes_204c = {}
58
69
  for prow in table.iterrows():
59
70
  row = prow[1].to_dict()
60
- # print(row)
71
+
72
+ field = "8T8R" if part == "AD9088" else "4T4R"
73
+ data = str(row[field])
74
+
75
+ if "nan" in data:
76
+ continue
77
+ if "Not Supported" in data:
78
+ continue
79
+
61
80
  jrx_modes_204c[str(row["Mode"])] = {
62
81
  "L": row["L"],
63
82
  "M": row["M"],
@@ -0,0 +1,111 @@
1
+ """AD9088 Datapath Description Class."""
2
+
3
+
4
+ class ad9088_dp_rx:
5
+ """AD9088 RX Data Path Configuration."""
6
+
7
+ cddc_enabled = [True, True, True, True]
8
+ cddc_decimations = [1, 1, 1, 1, 1, 1, 1, 1]
9
+ cddc_decimations_available = [1, 2, 3, 4, 6, 12]
10
+ cddc_nco_frequencies = [0, 0, 0, 0, 0, 0, 0, 0]
11
+ cddc_nco_phases = [0, 0, 0, 0, 0, 0, 0, 0]
12
+
13
+ fddc_enabled = [False] * 16
14
+ fddc_decimations = [1] * 16
15
+ fddc_decimations_available = [1, 2, 4, 8, 16, 32, 64]
16
+ fddc_nco_frequencies = [0] * 16
17
+ fddc_nco_phases = [0] * 16
18
+
19
+ fddc_source = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8]
20
+
21
+ def get_config(self) -> dict:
22
+ """Get the datapath configuration for the AD9088 RX.
23
+
24
+ Returns:
25
+ dict: datapath configuration
26
+ """
27
+ datapath = {}
28
+ datapath["cddc"] = {}
29
+ datapath["cddc"]["enabled"] = self.cddc_enabled
30
+ datapath["cddc"]["decimations"] = self.cddc_decimations
31
+ datapath["cddc"]["nco_frequencies"] = self.cddc_nco_frequencies
32
+ datapath["cddc"]["nco_phases"] = self.cddc_nco_phases
33
+
34
+ datapath["fddc"] = {}
35
+ datapath["fddc"]["enabled"] = self.fddc_enabled
36
+ datapath["fddc"]["decimations"] = self.fddc_decimations
37
+ datapath["fddc"]["nco_frequencies"] = self.fddc_nco_frequencies
38
+ datapath["fddc"]["nco_phases"] = self.fddc_nco_phases
39
+ datapath["fddc"]["source"] = self.fddc_source
40
+
41
+ return datapath
42
+
43
+ @property
44
+ def decimation_overall(self) -> int:
45
+ """Minimum Overall Decimation factor.
46
+
47
+ Raises:
48
+ Exception: No FDDC or CDDC enabled
49
+ Exception: Enabled FDDC's source CDDC not enabled
50
+
51
+ Returns:
52
+ int: minimum overall decimation factor
53
+ """
54
+ if (not any(self.fddc_enabled)) and (not any(self.cddc_enabled)):
55
+ raise Exception("No FDDCs or CDDCs enabled")
56
+
57
+ if any(self.fddc_enabled):
58
+ min_dec = -1
59
+ for i, fdec in enumerate(self.fddc_decimations):
60
+ if self.fddc_enabled[i]:
61
+ cddc = self.fddc_source[i]
62
+ if not self.cddc_enabled:
63
+ raise Exception(f"Source CDDC {cddc} not enabled for FDDC {i}")
64
+ cdec = self.cddc_decimations[cddc - 1]
65
+ if (cdec * fdec < min_dec) or min_dec == -1:
66
+ min_dec = cdec * fdec
67
+ else:
68
+ min_dec = -1
69
+ for i, cdec in enumerate(self.cddc_decimations):
70
+ if self.cddc_enabled[i] and (min_dec == -1 or cdec < min_dec):
71
+ min_dec = cdec
72
+
73
+ return min_dec
74
+
75
+
76
+ # class ad9088_dp_tx:
77
+ # """AD9088 TX Data Path Configuration."""
78
+
79
+ # cduc_enabled = [True, True, True, True]
80
+ # cduc_interpolation = 1
81
+ # cduc_nco_frequencies = [0, 0, 0, 0]
82
+ # cduc_nco_phases = [0, 0, 0, 0]
83
+
84
+ # fduc_enabled = [False, False, False, False, False, False, False, False]
85
+ # fduc_interpolation = 1
86
+ # fduc_nco_frequencies = [0, 0, 0, 0, 0, 0, 0, 0]
87
+ # fduc_nco_phases = [0, 0, 0, 0, 0, 0, 0, 0]
88
+
89
+ # cduc_sources = [[1], [1], [3], [3]]
90
+
91
+ # def get_config(self) -> dict:
92
+ # """Get the datapath configuration for the AD9088 TX.
93
+
94
+ # Returns:
95
+ # dict: Datapath configuration
96
+ # """
97
+ # datapath = {}
98
+ # datapath["cduc"] = {}
99
+ # datapath["cduc"]["enabled"] = self.cduc_enabled
100
+ # datapath["cduc"]["interpolation"] = self.cduc_interpolation
101
+ # datapath["cduc"]["nco_frequencies"] = self.cduc_nco_frequencies
102
+ # datapath["cduc"]["nco_phases"] = self.cduc_nco_phases
103
+ # datapath["cduc"]["sources"] = self.cduc_sources
104
+
105
+ # datapath["fduc"] = {}
106
+ # datapath["fduc"]["enabled"] = self.fduc_enabled
107
+ # datapath["fduc"]["interpolation"] = self.fduc_interpolation
108
+ # datapath["fduc"]["nco_frequencies"] = self.fduc_nco_frequencies
109
+ # datapath["fduc"]["nco_phases"] = self.fduc_nco_phases
110
+
111
+ # return datapath