nsqdriver 0.12.12__cp312-cp312-macosx_10_13_universal2.whl → 0.12.14__cp312-cp312-macosx_10_13_universal2.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.

Potentially problematic release.


This version of nsqdriver might be problematic. Click here for more details.

nsqdriver/NS_DDS_v3.py CHANGED
@@ -4,6 +4,7 @@ from math import ceil
4
4
  from collections import namedtuple
5
5
  from waveforms import Waveform, wave_eval, WaveVStack
6
6
  from waveforms.waveform import _zero
7
+ from waveforms.math.signal import getFTMatrix, shift
7
8
  import nsqdriver.nswave as nw
8
9
 
9
10
  import numpy as np
@@ -38,6 +39,77 @@ except ImportError as e:
38
39
  DEBUG_PRINT = False
39
40
 
40
41
 
42
+ def get_coef(coef_info, sampleRate):
43
+ start, stop = coef_info['start'], coef_info['stop']
44
+ numberOfPoints = int(
45
+ (stop - start) * sampleRate)
46
+ if numberOfPoints % 64 != 0:
47
+ numberOfPoints = numberOfPoints + 64 - numberOfPoints % 64
48
+ t = np.arange(numberOfPoints) / sampleRate + start
49
+
50
+ fList = []
51
+ wList = []
52
+ phases = []
53
+
54
+ for kw in coef_info['wList']:
55
+ Delta, t0, weight, w, phase = kw['Delta'], kw['t0'], kw['weight'], kw['w'], kw['phase']
56
+ fList.append(Delta)
57
+
58
+ if w is not None:
59
+ w = np.zeros(numberOfPoints, dtype=complex)
60
+ w[:len(w)] = w
61
+ w = shift(w, t0 - start)
62
+ phases.append(np.mod(phase + 2 * np.pi * Delta * start, 2 * np.pi))
63
+ else:
64
+ weight = weight
65
+ if isinstance(weight, np.ndarray):
66
+ pass
67
+ else:
68
+ if isinstance(weight, str):
69
+ fun = wave_eval(weight) >> t0
70
+ elif isinstance(weight, Waveform):
71
+ fun = weight >> t0
72
+ else:
73
+ raise TypeError(f'Unsupported type {weight}')
74
+ weight = fun(t)
75
+ phase += 2 * np.pi * Delta * start
76
+ w = getFTMatrix([Delta],
77
+ numberOfPoints,
78
+ phaseList=[phase],
79
+ weight=weight,
80
+ sampleRate=sampleRate)[:, 0]
81
+ phases.append(np.mod(phase, 2 * np.pi))
82
+ wList.append(w)
83
+ return np.asarray(wList), fList, numberOfPoints, phases, round((stop - t0) * sampleRate), t
84
+
85
+
86
+ def get_demod_envelope(coef_info, demod_map, sampleRate):
87
+ start, stop = coef_info['start'], coef_info['stop']
88
+ t0 = coef_info['t0']
89
+ numberOfPoints = int(
90
+ (stop - start) * sampleRate)
91
+ if numberOfPoints % 64 != 0:
92
+ numberOfPoints = numberOfPoints + 64 - numberOfPoints % 64
93
+ t = np.arange(numberOfPoints) / sampleRate + start
94
+ demod_map_list = demod_map
95
+ weight_sum = np.empty(numberOfPoints)
96
+ for weight in demod_map_list:
97
+ if isinstance(weight, np.ndarray):
98
+ pass
99
+ else:
100
+ if isinstance(weight, str):
101
+ fun = wave_eval(weight)
102
+ elif isinstance(weight, Waveform):
103
+ fun = weight
104
+ else:
105
+ raise TypeError(f'Unsupported type {weight}')
106
+ weight = fun(t)
107
+ weight_sum += weight
108
+ return weight_sum
109
+
110
+
111
+
112
+
41
113
  @nw.kernel
42
114
  def program_cap(param: nw.Var):
43
115
  #
@@ -57,16 +129,17 @@ def program_da(p: nw.Var):
57
129
  nw.init_frame(0, 0)
58
130
  nw.wait_for_trigger()
59
131
  # nw.reset_frame()
132
+ e = nw.ins_envelope(p[0][1])
60
133
  for i in p:
61
134
  nw.wait(i[0])
62
- e = nw.ins_envelope(i[1])
135
+ # e = nw.ins_envelope(i[1])
63
136
  nw.play_wave(e, 1, 0, 0)
64
137
 
65
138
 
66
- ProbeSegment = namedtuple('ProbeSegment', ['start', 'stop', 'freq', 'idx'])
139
+ ProbeSegment = namedtuple('ProbeSegment', ['start', 'stop', 'freq', 'demod', 'idx'])
67
140
 
68
141
  CaptureCmd = namedtuple('CaptureCmd', [
69
- 'start', 'ad_duration', 'delay', 'da_duration', 'freqs', 'delays', 'idx_list'
142
+ 'start', 'ad_duration', 'delay', 'da_duration', 'freqs', 'delays', 'demod_wave_list', 'idx_list'
70
143
  ])
71
144
 
72
145
 
@@ -149,6 +222,7 @@ class Driver(BaseDriver):
149
222
  self.IQ_cache = {}
150
223
  self.coef_cache = {}
151
224
  self.res_maps = {}
225
+ self.demod_maps = {}
152
226
  self.probe_da_wave = {}
153
227
  # self.probe_delay = 32e-9
154
228
  self.probe_delay = 0
@@ -156,6 +230,7 @@ class Driver(BaseDriver):
156
230
  self.capture_cali_param: "dict[int, np.ndarray]" = {}
157
231
  self.capture_points: "dict[int, np.ndarray]" = {}
158
232
  self.demodulate_mode = DemodulateMode.MORE_QUBIT
233
+ self.demode_calculus: "dict[int, np.ndarray]" = {}
159
234
 
160
235
  def open(self, **kw):
161
236
  """
@@ -202,7 +277,7 @@ class Driver(BaseDriver):
202
277
  _start, _stop = int(round(_start * 1e9)), int(round(_stop * 1e9))
203
278
 
204
279
  # 将区间加入列表
205
- seg = ProbeSegment(t0 + _start, t0 + _stop, wave['Delta'], idx)
280
+ seg = ProbeSegment(t0 + _start, t0 + _stop, wave['Delta'], weight_expr, idx)
206
281
  time_segments.append(seg)
207
282
 
208
283
  # 按起始时间排序
@@ -211,9 +286,9 @@ class Driver(BaseDriver):
211
286
  # 结果存储
212
287
  non_overlapping_segments: list[CaptureCmd] = []
213
288
  current_start, current_end = time_segments[0].start, time_segments[0].stop
214
- current_cmd = CaptureCmd(0, 0, 0, 0, [time_segments[0].freq], [0.], [time_segments[0].idx])
289
+ current_cmd = CaptureCmd(0, 0, 0, 0, [time_segments[0].freq], [0.],[time_segments[0].demod],
290
+ [time_segments[0].idx])
215
291
  pointer = 0
216
-
217
292
  for seg in time_segments[1:]:
218
293
  if seg.start > current_end:
219
294
  # 如果不重叠,保存当前段并移动到下一段
@@ -224,9 +299,10 @@ class Driver(BaseDriver):
224
299
  current_cmd = current_cmd._replace(ad_duration=current_end - current_start)
225
300
  current_cmd = current_cmd._replace(delay=self.probe_delay)
226
301
  current_cmd = current_cmd._replace(da_duration=current_end - current_start)
302
+ current_cmd = current_cmd._replace(demod_wave_list=[time_segments[0].demod])
227
303
  non_overlapping_segments.append(current_cmd)
228
304
 
229
- current_cmd = CaptureCmd(0, 0, 0, 0, [seg.freq], [0.], [seg.idx])
305
+ current_cmd = CaptureCmd(0, 0, 0, 0, [seg.freq], [0.], [seg.demod], [seg.idx])
230
306
  pointer = current_end
231
307
  current_start, current_end = seg.start, seg.stop
232
308
  else:
@@ -234,6 +310,7 @@ class Driver(BaseDriver):
234
310
  current_end = max(current_end, seg.stop)
235
311
  current_cmd.idx_list.append(seg.idx)
236
312
  current_cmd.freqs.append(seg.freq)
313
+ current_cmd.demod_wave_list.append(seg.demod)
237
314
  # 由delay换算解缠绕相位
238
315
  current_cmd.delays.append(seg.start - current_start)
239
316
  else:
@@ -247,11 +324,14 @@ class Driver(BaseDriver):
247
324
 
248
325
  def generate_in_program(self, coef_info, ch):
249
326
  freq_map = []
327
+ demod_wave_map = []
250
328
  seq_param = []
251
329
 
252
330
  self.capture_cmds[ch] = seq = self.in_sequence_in_time(coef_info)
253
331
 
254
332
  for segment in seq:
333
+ demod_wave_map.extend(segment.demod_wave_list)
334
+ demod_wave_map = list(set(demod_wave_map))
255
335
  freq_map.extend(segment.freqs)
256
336
  freq_map = list(set(freq_map))
257
337
 
@@ -260,9 +340,9 @@ class Driver(BaseDriver):
260
340
  phase_map = [0]*len(coef_info['wList'])
261
341
  points_map = [0]*len(coef_info['wList'])
262
342
  for cap_num, segment in enumerate(seq):
263
- _align_start = self.granularity4ns(segment.start)
343
+ _align_start = self.granularity4ns(segment.start) # 向前取整
264
344
  _start_diff = segment.start - _align_start
265
- _align_end = ceil((segment.start+segment.ad_duration)/4)*4
345
+ _align_end = ceil((segment.start+segment.ad_duration)/4)*4 #向上取整
266
346
  seq_param.append([
267
347
  (_align_start-_t_end)*1e-9,
268
348
  (_align_end-_align_start)*1e-9,
@@ -270,15 +350,16 @@ class Driver(BaseDriver):
270
350
  (_align_end-_align_start)*1e-9,
271
351
  ])
272
352
  _t_end = _align_end
273
- for idx, delay, freq in zip(segment.idx_list, segment.delays, segment.freqs):
353
+ for idx, delay, freq, demod_wave in zip(segment.idx_list, segment.delays, segment.freqs,
354
+ segment.demod_wave_list):
274
355
  res_map[idx] = [freq_map.index(freq), cap_num]
275
- phase_map[idx] = self._delay2_phase(delay + _start_diff, freq)
356
+ phase_map[idx] = self._delay2_phase(delay + _start_diff, freq) # 向前取整的缩进加上起始时间的差值来计算相位
276
357
  points_map[idx] = segment.ad_duration * 1e-9 * self.ad_srate
277
358
 
278
359
  self.res_maps[ch] = res_map
279
360
  self.capture_cali_param[ch] = np.exp(-1j * np.array(phase_map)).reshape((-1, 1))
280
361
  self.capture_points[ch] = np.array(points_map).reshape((-1, 1))
281
- return program_cap(seq_param), freq_map
362
+ return program_cap(seq_param), freq_map, demod_wave_map
282
363
 
283
364
  def out_sequence_in_time(self, wave_list: list):
284
365
  last_start = wave_list[0][0]
@@ -349,7 +430,7 @@ class Driver(BaseDriver):
349
430
  for (freq_num, cap_num) in self.res_maps[ch]:
350
431
  res.append(iq_res[freq_num][cap_num::len(self.capture_cmds[ch])])
351
432
  # 采样点归一化
352
- res = np.array(res) / self.capture_points[ch]
433
+ res = np.array(res) / self.demode_calculus[ch]
353
434
  # 校准相位
354
435
  res *= self.capture_cali_param[ch]
355
436
 
@@ -376,9 +457,13 @@ class Driver(BaseDriver):
376
457
  if name in {'Coefficient'}:
377
458
  coef_info = value
378
459
  self.chs.add(channel)
379
- kernel, freq_map = self.generate_in_program(coef_info, channel)
460
+ kernel, freq_map, demod_wave_map = self.generate_in_program(coef_info, channel)
380
461
  self.handle.set("ProgramIN", kernel, channel)
462
+ demode_wave = get_demod_envelope(coef_info, demod_wave_map, sampleRate=8e9)
463
+ self.demode_calculus[channel] = np.sum(demode_wave)
464
+ self.handle.set("DemodulationParam", demode_wave, channel)
381
465
  self.handle.set('TimeWidth', 2e-6, channel)
466
+
382
467
  self.handle.set("FreqList", freq_map, channel)
383
468
  self.coef_cache.update({channel: coef_info})
384
469
  elif name in {
nsqdriver/NS_DDS_v4.py ADDED
@@ -0,0 +1,778 @@
1
+ import copy
2
+ import time
3
+ from enum import Enum
4
+ from math import ceil
5
+ from collections import namedtuple
6
+ from waveforms import Waveform, wave_eval, WaveVStack
7
+ from waveforms.waveform import _zero
8
+ # from waveforms.math.signal import getFTMatrix, shift
9
+ import nsqdriver.nswave as nw
10
+
11
+ import numpy as np
12
+
13
+ try:
14
+ import waveforms
15
+
16
+ HAS_WAVEFORMS = True
17
+ except ImportError as e:
18
+ HAS_WAVEFORMS = False
19
+
20
+ try:
21
+ from .common import BaseDriver, Quantity, get_coef
22
+ except ImportError as e:
23
+
24
+ class BaseDriver:
25
+
26
+ def __init__(self, addr, timeout, **kw):
27
+ self.addr = addr
28
+ self.timeout = timeout
29
+
30
+
31
+ class Quantity(object):
32
+
33
+ def __init__(self, name: str, value=None, ch: int = 1, unit: str = ''):
34
+ self.name = name
35
+ self.default = dict(value=value, ch=ch, unit=unit)
36
+
37
+ # def get_coef(*args):
38
+ # return '', '', '', ''
39
+
40
+ DEBUG_PRINT = False
41
+
42
+
43
+ def get_coef(coef_info, sampleRate):
44
+ start, stop = coef_info['start'], coef_info['stop']
45
+ numberOfPoints = int(
46
+ (stop - start) * sampleRate)
47
+ if numberOfPoints % 64 != 0:
48
+ numberOfPoints = numberOfPoints + 64 - numberOfPoints % 64
49
+ t = np.arange(numberOfPoints) / sampleRate + start
50
+
51
+ fList = []
52
+ wList = []
53
+ phases = []
54
+
55
+ for kw in coef_info['wList']:
56
+ Delta, t0, weight, w, phase = kw['Delta'], kw['t0'], kw['weight'], kw['w'], kw['phase']
57
+ fList.append(Delta)
58
+
59
+ if w is not None:
60
+ w = np.zeros(numberOfPoints, dtype=complex)
61
+ w[:len(w)] = w
62
+ w = shift(w, t0 - start)
63
+ phases.append(np.mod(phase + 2 * np.pi * Delta * start, 2 * np.pi))
64
+ else:
65
+ weight = weight
66
+ if isinstance(weight, np.ndarray):
67
+ pass
68
+ else:
69
+ if isinstance(weight, str):
70
+ fun = wave_eval(weight) >> t0
71
+ elif isinstance(weight, Waveform):
72
+ fun = weight >> t0
73
+ else:
74
+ raise TypeError(f'Unsupported type {weight}')
75
+ weight = fun(t)
76
+ phase += 2 * np.pi * Delta * start
77
+ w = getFTMatrix([Delta],
78
+ numberOfPoints,
79
+ phaseList=[phase],
80
+ weight=weight,
81
+ sampleRate=sampleRate)[:, 0]
82
+ phases.append(np.mod(phase, 2 * np.pi))
83
+ wList.append(w)
84
+ return np.asarray(wList), fList, numberOfPoints, phases, round((stop - t0) * sampleRate), t
85
+
86
+
87
+ def get_demod_envelope(coef_info, demod_map, freq_map, sampleRate):
88
+ start, stop = coef_info['start'], coef_info['stop']
89
+ # t0 = coef_info['wList']['t0']
90
+ # numberOfPoints = int(
91
+ # (stop - start) * sampleRate)
92
+ # if numberOfPoints % 64 != 0:
93
+ # numberOfPoints = numberOfPoints + 64 - numberOfPoints % 64
94
+ # t = np.arange(numberOfPoints) / sampleRate
95
+ demod_width = 2.048e-6
96
+ t_p = int(demod_width * sampleRate)
97
+ t = np.linspace(0, demod_width, round(demod_width*sampleRate), endpoint=False)
98
+ demod_map_list = demod_map
99
+ weight_sum = np.zeros((len(freq_map), t_p))
100
+
101
+ for idx, weight in enumerate(demod_map_list):
102
+ if isinstance(weight, np.ndarray):
103
+ weight_sum[idx] = weight
104
+ else:
105
+ if isinstance(weight, str):
106
+ fun = wave_eval(weight)
107
+ elif isinstance(weight, Waveform):
108
+ fun = weight
109
+ else:
110
+ raise TypeError(f'Unsupported type {weight}')
111
+ weight_sum[idx] = fun(t)
112
+ print(f'{freq_map=}, {len(freq_map)=}')
113
+ combined_wave = []
114
+ for idx, freq in enumerate(freq_map):
115
+ wave = (np.exp(2 * np.pi * freq * t * 1j)).reshape((1, -1))
116
+ print(f"wave {wave} {weight_sum[idx, :]}")
117
+ wave = weight_sum[idx, :] * wave
118
+ # plt.figure()
119
+ # plt.plot(weight_sum[idx, :])
120
+ # plt.plot(wave.T)
121
+ # plt.show()
122
+ combined_wave.append(wave)
123
+ combined_wave = np.concatenate(combined_wave, axis=0)
124
+ return weight_sum, combined_wave
125
+
126
+
127
+ @nw.kernel
128
+ def program_cap(param: nw.Var, indelay: nw.Var):
129
+
130
+ nw.wait_for_trigger()
131
+ i: nw.Var
132
+ # param: [[100e-9, 1e-6], [200e-9, 1e-6]]
133
+ nw.wait(indelay)
134
+ for i in param:
135
+ nw.wait(i[0])
136
+ nw.capture(i[1], 0, i[1])
137
+
138
+
139
+ @nw.kernel
140
+ def program_da(p: nw.Var):
141
+ i: nw.Var
142
+ e: nw.Var
143
+ nw.init_frame(0, 0)
144
+ nw.wait_for_trigger()
145
+ # nw.reset_frame()
146
+ e = nw.ins_envelope(p[0][1])
147
+ for i in p:
148
+ nw.wait(i[0])
149
+ # e = nw.ins_envelope(i[1])
150
+ nw.play_wave(e, 1, 0, 0)
151
+
152
+
153
+ ProbeSegment = namedtuple('ProbeSegment', ['start', 'stop', 'freq', 'demod', 'idx'])
154
+
155
+ CaptureCmd = namedtuple('CaptureCmd', [
156
+ 'start', 'ad_duration', 'delay', 'da_duration', 'freqs', 'delays', 'demod_wave_list', 'idx_list'
157
+ ])
158
+
159
+
160
+ class DemodulateMode(str, Enum):
161
+ MORE_QUBIT = 'more_qubit'
162
+ COMPLEX_SEQ = 'complex_seq'
163
+
164
+
165
+ class Driver(BaseDriver):
166
+ CHs = list(range(1, 25))
167
+ segment = ('ns', '111|112|113|114|115')
168
+ res_map = []
169
+
170
+ quants = [
171
+ Quantity('ReInit', value={}, ch=1), # set, 设备重新初始化
172
+ Quantity('Instruction', value=None, ch=1), # set 参数化波形指令队列配置
173
+ # 采集运行参数
174
+ Quantity('Shot', value=1024, ch=1), # set,运行次数
175
+ Quantity('PointNumber', value=16384, unit='point'), # set/get,AD采样点数
176
+ Quantity('TriggerDelay', value=0, ch=1, unit='s'), # set/get,AD采样延时
177
+ Quantity('FrequencyList', value=[], ch=1,
178
+ unit='Hz'), # set/get,解调频率列表,list,单位Hz
179
+ Quantity('PhaseList', value=[], ch=1,
180
+ unit='Hz'), # set/get,解调频率列表,list,单位Hz
181
+ Quantity('Coefficient', value=None, ch=1),
182
+ Quantity('DemodulationParam', value=None, ch=1),
183
+ Quantity('CaptureMode'),
184
+ Quantity('StartCapture'), # set,开启采集(执行前复位)
185
+ Quantity('TraceIQ', ch=1), # get,获取原始时域数据
186
+ # 返回:array(shot, point)
187
+ Quantity('IQ', ch=1), # get,获取解调后数据,默认复数返回
188
+ # 系统参数,宏定义修改,open时下发
189
+ # 复数返回:array(shot,frequency)
190
+ # 实数返回:array(IQ,shot,frequency)
191
+
192
+ # 任意波形发生器
193
+ Quantity('Waveform', value=np.array([]), ch=1), # set/get,下发原始波形数据
194
+ Quantity('Delay', value=0, ch=1), # set/get,播放延时
195
+ Quantity('KeepAmp', value=0
196
+ ), # set, 电平是否维持在波形最后一个值, 0:波形播放完成后归0,1:保持波形最后一个值,2:保持波形第一个值
197
+ Quantity('Biasing', value=0, ch=1), # set, 播放延迟
198
+ Quantity('LinSpace', value=[0, 30e-6, 1000],
199
+ ch=1), # set/get, np.linspace函数,用于生成timeline
200
+ Quantity('Output', value=True, ch=1), # set/get,播放通道开关设置
201
+ Quantity('GenWave', value=None,
202
+ ch=1), # set/get, 设备接收waveform对象,根据waveform对象直接生成波形
203
+ # set/get, 设备接收IQ分离的waveform对象列表,根据waveform对象列表直接生成波形
204
+ Quantity('GenWaveIQ', value=None, ch=1),
205
+ Quantity('MultiGenWave', value={1: np.ndarray([])}), # 多通道波形同时下发
206
+ Quantity('EnableWaveCache', value=False), # 是否开启waveform缓存
207
+ Quantity('PushWaveCache'), # 使waveform缓存中的波形数据生效
208
+ # 混频相关配置
209
+ Quantity('EnableDAMixer', value=False, ch=1), # DA通道混频模式开关
210
+ Quantity('MixingWave', ), # 修改完混频相关参数后,运行混频器
211
+ Quantity('DAIQRate', value=1e9, ch=1), # 基带信号采样率
212
+ Quantity('DALOFreq', value=100e6, ch=1), # 中频信号频率
213
+ Quantity('DALOPhase', value=0, ch=1), # 基带信号相位,弧度制
214
+ Quantity('DASideband', value='lower', ch=1), # 混频后取的边带
215
+ Quantity('DAWindow', value=None, ch=1),
216
+ # 基带信号升采样率时所使用的窗函数,默认不使用任何窗,
217
+ # 可选:None、boxcar、triang、blackman、hamming、hann、bartlett、flattop、parzen、bohman、blackmanharris、nuttall、
218
+ # barthann、cosine、exponential、tukey、taylor
219
+
220
+ # 内触发
221
+ Quantity('GenerateTrig', value=1e7,
222
+ unit='ns'), # set/get,触发周期单位ns,触发数量=shot
223
+ Quantity('UpdateFirmware', value='', ch=1), # qsync固件更新
224
+ Quantity('PipInstall'), # pip install in instance
225
+ Quantity('Timeout'),
226
+ ]
227
+
228
+ def __init__(self, addr: str = '', timeout: float = 20.0, **kw):
229
+ super().__init__(addr, timeout=timeout, **kw)
230
+ self.handle = None
231
+ self.model = 'NS_MCI' # 默认为设备名字
232
+ self.srate = 8e9
233
+ self.ad_srate = 4e9
234
+ self.addr = addr
235
+ self.timeout = timeout
236
+ self.chs = set() # 记录配置过的ch通道
237
+ self.IQ_cache = {}
238
+ self.coef_cache = {}
239
+ self.res_maps = {}
240
+ self.demod_maps = {}
241
+ self.probe_da_wave = {}
242
+ self.programout_para = {} # {ch : para}
243
+ self.programin_para = {}
244
+ self.programin_para_indelay = {i: 136e-9 for i in range(1, 13)}
245
+ # self.probe_delay = 32e-9
246
+ self.probe_delay = 0
247
+ self.capture_cmds: "dict[int, list[CaptureCmd]]" = {}
248
+ self.capture_cali_param: "dict[int, np.ndarray]" = {}
249
+ self.capture_points: "dict[int, np.ndarray]" = {}
250
+ self.demodulate_mode = DemodulateMode.MORE_QUBIT
251
+ self.demode_calculus: "dict[int, np.ndarray]" = {}
252
+
253
+ def open(self, **kw):
254
+ """
255
+ 输入IP打开设备,配置默认超时时间为5秒
256
+ 打开设备时配置RFSoC采样时钟,采样时钟以参数定义
257
+ """
258
+ from nsqdriver import MCIDriver
259
+
260
+ DArate = 8e9
261
+ ADrate = 4e9
262
+ sysparam = {
263
+ "MixMode": 2,
264
+ "RefClock": "out",
265
+ "DArate": DArate,
266
+ "ADrate": ADrate,
267
+ "CaptureMode": 0,
268
+ "INMixMode": 2, # 4~6 GHz 取 1, 6 ~ 8 GHz 取 2
269
+ }
270
+ sysparam.update(kw.get('system_parameter', {}))
271
+ print(f"{self.timeout=}")
272
+ device = MCIDriver(self.addr, self.timeout)
273
+ device.open(system_parameter=sysparam)
274
+ self.handle = device
275
+
276
+ def granularity4ns(self, delay):
277
+ # points_4ns = 16 # self.ad_srate*4e-6
278
+ return delay // 4 * 4
279
+
280
+ @staticmethod
281
+ def _delay2_phase(delay, freq):
282
+ return 2 * np.pi * freq * (delay * 1e-9)
283
+
284
+ def in_sequence_in_time(self, coef_info: dict) -> list[CaptureCmd]:
285
+ """
286
+ 合并重叠项,取并集,记录合并延迟时间,合并频点,合并包络
287
+ """
288
+
289
+ w_list = coef_info.get('wList', [])
290
+ time_segments: "list[ProbeSegment]" = []
291
+
292
+ for idx, wave in enumerate(w_list):
293
+ t0 = int(round(wave['t0'] * 1e9))
294
+ weight_expr = wave['weight']
295
+
296
+ # 假设 weight 表达式格式为 "square(X) >> Y",我们提取实际时间宽度
297
+ # duration = float(weight_expr.split('>>')[1].strip())
298
+ _start, _stop, _ = wave_eval(weight_expr).bounds
299
+ _start, _stop = int(round(_start * 1e9)), int(round(_stop * 1e9))
300
+
301
+ # 将区间加入列表
302
+ seg = ProbeSegment(t0 + _start, t0 + _stop, wave['Delta'], weight_expr, idx)
303
+ time_segments.append(seg)
304
+
305
+ # 按起始时间排序
306
+ time_segments.sort()
307
+
308
+ # 结果存储
309
+ non_overlapping_segments: list[CaptureCmd] = []
310
+ current_start, current_end = time_segments[0].start, time_segments[0].stop
311
+ current_cmd = CaptureCmd(0, 0, 0, 0, [time_segments[0].freq], [0.], [time_segments[0].demod],
312
+ [time_segments[0].idx])
313
+ pointer = 0
314
+ for seg in time_segments[1:]:
315
+ if seg.start > current_end:
316
+ # 如果不重叠,保存当前段并移动到下一段
317
+ if pointer == 0:
318
+ current_cmd = current_cmd._replace(start=current_start)
319
+ else:
320
+ current_cmd = current_cmd._replace(start=current_start - self.probe_delay)
321
+ current_cmd = current_cmd._replace(ad_duration=current_end - current_start)
322
+ current_cmd = current_cmd._replace(delay=self.probe_delay)
323
+ current_cmd = current_cmd._replace(da_duration=current_end - current_start)
324
+ non_overlapping_segments.append(current_cmd)
325
+
326
+ current_cmd = CaptureCmd(0, 0, 0, 0, [seg.freq], [0.], [seg.demod], [seg.idx])
327
+ pointer = current_end
328
+ current_start, current_end = seg.start, seg.stop
329
+ else:
330
+ # 如果有重叠,扩展当前段
331
+ current_end = max(current_end, seg.stop)
332
+ current_cmd.idx_list.append(seg.idx)
333
+ current_cmd.freqs.append(seg.freq)
334
+ current_cmd.demod_wave_list.append(seg.demod)
335
+ # 由delay换算解缠绕相位
336
+ current_cmd.delays.append(seg.start - current_start)
337
+ print(f'{current_cmd=}')
338
+ else:
339
+ # 添加最后一个段
340
+ current_cmd = current_cmd._replace(start=current_start - self.probe_delay)
341
+ current_cmd = current_cmd._replace(ad_duration=current_end - current_start)
342
+ current_cmd = current_cmd._replace(delay=self.probe_delay)
343
+ current_cmd = current_cmd._replace(da_duration=current_end - current_start)
344
+ non_overlapping_segments.append(current_cmd)
345
+ return non_overlapping_segments
346
+
347
+ def generate_in_program(self, coef_info, ch):
348
+ freq_map = []
349
+ demod_wave_map = []
350
+ seq_param = []
351
+
352
+ self.capture_cmds[ch] = seq = self.in_sequence_in_time(coef_info) # 得到合并重叠后的list
353
+ print(f'{seq=}')
354
+ # for segment in seq:
355
+ # demod_wave_map.extend(segment.demod_wave_list)
356
+ # demod_wave_map = list(set(demod_wave_map))
357
+ # freq_map.extend(segment.freqs)
358
+ # freq_map = list(set(freq_map))
359
+
360
+ for segment in seq:
361
+ for n, f in enumerate(segment.freqs):
362
+ if f not in freq_map:
363
+ demod_wave_map.append(segment.demod_wave_list[n])
364
+ freq_map.append(f)
365
+
366
+ _t_end = 0
367
+ res_map = [[]] * len(coef_info['wList'])
368
+ phase_map = [0] * len(coef_info['wList'])
369
+ points_map = [0] * len(coef_info['wList'])
370
+ for cap_num, segment in enumerate(seq):
371
+ _align_start = self.granularity4ns(segment.start) # 向前取整
372
+ _start_diff = segment.start - _align_start
373
+ # _align_end = ceil((segment.start + segment.ad_duration) / 4) * 4 # 向上取整
374
+ _align_end = (segment.start + segment.ad_duration) // 4 * 4 # 向上取整
375
+ seq_param.append([
376
+ (_align_start - _t_end) * 1e-9,
377
+ (_align_end - _align_start) * 1e-9,
378
+ segment.delay * 1e-9,
379
+ (_align_end - _align_start) * 1e-9,
380
+ ])
381
+ print(f"{_align_start=} {_align_end=} {(_align_start - _t_end)} {_t_end=}")
382
+ _t_end = _align_end
383
+ for idx, delay, freq, demod_wave in zip(segment.idx_list, segment.delays, segment.freqs,
384
+ segment.demod_wave_list):
385
+ res_map[idx] = [freq_map.index(freq), cap_num]
386
+ # print("下面 + t0")
387
+ # phase_map[idx] = self._delay2_phase(delay + _start_diff, freq) # 向前取整的缩进加上起始时间的差值来计算相位
388
+ # phase_map[idx] = self._delay2_phase(_align_start + _start_diff, freq) # 向前取整的缩进加上起始时间的差值来计算相位
389
+ # phase_map[idx] = self._delay2_phase(0, freq) # 向前取整的缩进加上起始时间的差值来计算相位
390
+ points_map[idx] = (_align_end - _align_start) * 1e-9 * self.ad_srate
391
+ # points_map[idx] = segment.ad_duration * 1e-9 * self.ad_srate
392
+
393
+ ad_abs_end = 0
394
+ da_abs_end = 0
395
+ # 根据ad 的延迟重新下发da program
396
+ delta_t = self.programout_para[ch][0][0] - seq_param[0][0]
397
+ for n, i in enumerate(self.programout_para[ch]):
398
+ if n == 0:
399
+ continue
400
+ ad_abs_end += seq_param[n-1][0] + seq_param[n-1][1]
401
+ da_abs_end += self.programout_para[ch][n-1][0] + self.programout_para[ch][n-1][1].shape[0] / self.srate
402
+ da_next_start = ad_abs_end + seq_param[n][0] + delta_t
403
+ da_wait = da_next_start - da_abs_end
404
+ i[0] = da_wait
405
+ # kernel_da = program_da(self.programout_para[ch])
406
+ # self.handle.set("ProgramOUT", kernel_da, ch)
407
+ print(f"重下da 程序 {self.programout_para[ch]=}")
408
+
409
+ for idx, freq in zip(segment.idx_list, segment.freqs):
410
+ phase_map[idx] = self._delay2_phase(0 , freq)
411
+
412
+ self.res_maps[ch] = res_map
413
+ self.capture_cali_param[ch] = np.exp(-1j * np.array(phase_map)).reshape((-1, 1))
414
+ self.capture_points[ch] = np.array(points_map).reshape((-1, 1))
415
+ print(f"{seq_param=} para_angle {np.angle(self.capture_cali_param[ch], deg=True)} {self.capture_points}")
416
+ self.programin_para[ch] = seq_param
417
+ return program_cap(seq_param, self.programin_para_indelay[ch]), freq_map, demod_wave_map
418
+
419
+ def out_sequence_in_time(self, wave_list: list):
420
+ last_start = wave_list[0][0]
421
+ last_stop = wave_list[0][1]
422
+ temp_w = [wave_list[0][2]]
423
+ _res = []
424
+
425
+ for idx, (start, stop, seg) in enumerate(wave_list[1:]):
426
+ if start > last_stop:
427
+ _res.append([last_start, last_stop, np.hstack(temp_w)])
428
+ last_start = start
429
+ last_stop = stop
430
+ temp_w.clear()
431
+ temp_w.append(seg)
432
+ else:
433
+ last_stop = max(last_stop, stop)
434
+ temp_w.append(seg)
435
+ else:
436
+ _res.append([last_start, last_stop, np.hstack(temp_w)])
437
+ return _res
438
+
439
+ def gen_wave_frag(self, x, wave: "Waveform"):
440
+ range_list = np.searchsorted(x, wave.bounds)
441
+ # ret = np.zeros_like(x)
442
+ ret = []
443
+ start, stop = 0, 0
444
+ for i, stop in enumerate(range_list):
445
+ if start < stop and wave.seq[i] != _zero:
446
+ _w = copy.deepcopy(wave)
447
+ _w.start = start / self.srate
448
+ _w.stop = stop / self.srate
449
+ part = _w.sample(self.srate)
450
+ part = part if part is None else part[:(stop - start)]
451
+ ret.append((start, stop, part))
452
+ start = stop
453
+ else:
454
+ if not ret:
455
+ ret.append((0, 128, np.zeros((128,))))
456
+ return ret
457
+
458
+ def generate_out_program(self, _wave, ch):
459
+ align_points = 32 # 4ns*8e9
460
+ if isinstance(_wave, WaveVStack):
461
+ _wave = _wave.simplify()
462
+ if len(_wave.seq) == 1 and _wave.seq[0] == _zero:
463
+ wave_list = [(0, 128, np.zeros((128,)))]
464
+ else:
465
+ _wave.stop = _wave.bounds[-2]
466
+ wave_list = self.gen_wave_frag(
467
+ np.linspace(_wave.start, _wave.stop, int((_wave.stop - _wave.start) * self.srate)), _wave)
468
+ print(f'generate_out_program: {_wave.start=}, {_wave.stop=}, {len(wave_list)=}, {ch=}')
469
+ _t_end = 0
470
+ para = []
471
+ wave = self.out_sequence_in_time(wave_list) # 得到合并重叠后的list
472
+
473
+ for num, i in enumerate(wave):
474
+ wait = (i[0] - _t_end)
475
+ # if wait % 32 != 0:
476
+ # # 若wait 不是4ns整倍数,根据ad的逻辑会往后多财季4ns
477
+ align_wait = wait // align_points * align_points
478
+ zero_num = wait - align_wait
479
+ align_end = i[1] // align_points * align_points
480
+ align_wave = [i[2],]
481
+ para.append([align_wait / self.srate, np.hstack(align_wave)])
482
+ _t_end = align_end
483
+ print(f"out {para=}")
484
+ self.programout_para[ch] = para
485
+ # print(para[0][1].max())
486
+ # plt.plot(para[0][1])
487
+ # plt.show()
488
+ return program_da(para)
489
+
490
+ def get_coef_res(self, iq_res, ch):
491
+ res = []
492
+ print(f'{self.res_maps[ch]=}')
493
+ for (freq_num, cap_num) in self.res_maps[ch]:
494
+ res.append(iq_res[freq_num][cap_num::len(self.capture_cmds[ch])])
495
+ # 采样点归一化
496
+ res = np.array(res) / self.demode_calculus[ch]
497
+ # 校准相位
498
+ res *= self.capture_cali_param[ch]
499
+
500
+ return res
501
+
502
+ def close(self, **kw):
503
+ """
504
+ 关闭设备
505
+ """
506
+ if getattr(self, 'handle', None) is not None:
507
+ self.handle.close()
508
+ self.handle = None
509
+
510
+ def set(self, *args, **kwargs):
511
+ return self.handle.set(*args, **kwargs)
512
+
513
+ def get(self, *args, **kwargs):
514
+
515
+ return self.handle.get(*args, **kwargs)
516
+
517
+ # def generate_demo(self, co):
518
+ # _wave = wf.zero()
519
+ # min_t0 = 10
520
+ # for _w in co['wList']:
521
+ # t0 = _w['t0']
522
+ # min_t0 = min(min_t0, t0)
523
+ # _wave += (wf.wave_eval(_w['weight']) * wf.cos(2 * np.pi * _w['Delta'])) >> t0
524
+ # _wave /= 8
525
+ # # _wave = _wave << 50e-9
526
+ # _wave.start = 0
527
+ # _wave.stop = co['stop']
528
+ # bk = self.srate
529
+ # self.srate = self.ad_srate
530
+ # _, para = self.generate_out_program(co, 1)
531
+ # self.srate = bk
532
+ # demo = para[0][1]
533
+ # return demo
534
+
535
+ def write(self, name: str, value, **kw):
536
+ channel = kw.get('ch', 1)
537
+ print(f'NS_DDS_v3 write: {name=}, {channel=}')
538
+ if name in {'Coefficient'}:
539
+ print("Coefficient" * 3)
540
+ coef_info = value
541
+ self.chs.add(channel)
542
+ kernel, freq_map, demod_wave_map = self.generate_in_program(coef_info, channel)
543
+ self.handle.set("ProgramIN", kernel, channel)
544
+ demode_weight, demode_wave = get_demod_envelope(coef_info, demod_wave_map, freq_map, sampleRate=4e9)
545
+ self.demode_calculus[channel] = np.sum(demode_weight[0])
546
+ self.handle.set("DemodulationParam", demode_wave, channel)
547
+ # print(f"demode_wave {demode_wave}")
548
+ # plt.figure()
549
+ # plt.plot(demode_wave[0].real)
550
+ # plt.plot(demode_wave[0].imag)
551
+ # plt.show()
552
+ self.handle.set('TimeWidth', self.capture_points[channel].max()/self.ad_srate, channel)
553
+ # self.handle.set('TimeWidth', 87 / self.ad_srate, channel)
554
+ # self.handle.set("FreqList", freq_map, channel)
555
+ self.coef_cache.update({channel: coef_info})
556
+ elif name in {"TriggerDelay", "INDelay"}:
557
+ print("INDelay" * 3)
558
+ self.programin_para_indelay[channel] = value
559
+ # kernel = program_cap(self.programin_para[channel], self.programin_para_indelay[channel])
560
+ # self.handle.set("ProgramIN", kernel, channel)
561
+ elif name in {
562
+ 'CaptureMode', 'SystemSync', 'ResetTrig', 'TrigPeriod',
563
+ 'TrigFrom'
564
+ }:
565
+ pass
566
+ elif name in {
567
+ 'GenWave', 'Waveform'
568
+ } and isinstance(value, Waveform):
569
+ kernel_da = self.generate_out_program(value, channel)
570
+ # self.handle.set("ProgramOUT", kernel_da, channel)
571
+ elif name in {
572
+ 'StartCapture', 'Capture'
573
+ }:
574
+ for channel, param in self.programin_para.items():
575
+ kernel = program_cap(self.programin_para[channel], self.programin_para_indelay[channel])
576
+ self.handle.set("ProgramIN", kernel, channel)
577
+ for channel in self.programout_para:
578
+ kernel = program_da(self.programout_para[channel])
579
+ self.handle.set("ProgramOUT", kernel, channel)
580
+ print(f"{self.programin_para=} {self.programin_para_indelay=} {self.programout_para=}")
581
+ return self.handle.set(name, value)
582
+ else:
583
+ if name in {"Shot"}:
584
+ self.shots = value
585
+ return self.handle.set(name, value, channel)
586
+
587
+ def read(self, name: str, **kw):
588
+ channel = kw.get('ch', 1)
589
+ if name in {"IQ"}:
590
+ iq_res = self.handle.get(
591
+ "IQ", channel, round(self.shots * len(self.capture_cmds[channel]))
592
+ )
593
+ result = self.get_coef_res(iq_res, channel).T
594
+ if len(self.chs) != 0 and channel in self.chs:
595
+ self.chs.remove(channel)
596
+ # self.IQ_cache.update({channel: result})
597
+ if len(self.chs) == 0:
598
+ self.write("TerminateUpload", 1) # 实验的开始必须加此句话
599
+ elif name in {'TraceIQ'}:
600
+ print(f"{self.shots=} {len(self.capture_cmds[channel])=}")
601
+ result = self.handle.get(
602
+ "TraceIQ", channel, round(self.shots * len(self.capture_cmds[channel]))
603
+ )
604
+ else:
605
+ result = self.handle.get(name, channel)
606
+ return result
607
+
608
+
609
+ if __name__ == '__main__':
610
+ # 7.052186177715091e9 1.418e-6 7.062146892655367e9 1.416e-6 6.191950464396285e9 1.615e-6
611
+ # 6.188118811881188e9 1.616e-6
612
+ # 6.184291898577612e9 1.617e-6
613
+ # 6.180469715698393e9 1.618e-6
614
+ # 6.176652254478073e9 1.619e-6
615
+ co = {'start': 0.0, 'stop': 70.605e-06, 'wList': [
616
+ {'Delta': 6967500000.0, 'phase': -0.0, 'weight': 'square(0.8e-06)>>(4e-07)', 'window': (0, 1024), 'w': None,
617
+ 't0': 1.618e-6, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
618
+ # {'Delta': 4.176652254478073e9, 'phase': -0.0, 'weight': 'gaussian(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
619
+ # 't0': 1.618e-6, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
620
+ # {'Delta': 6.180469715698393e9, 'phase': -0.0, 'weight': 'gaussian(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
621
+ # 't0': 1.618e-6 * 20, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
622
+ # {'Delta': 4.176652254478073e9, 'phase': -0.0, 'weight': 'gaussian(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
623
+ # 't0': 1.618e-6 * 20, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
624
+ # {'Delta': 6.180469715698393e9, 'phase': -0.0, 'weight': 'gaussian(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
625
+ # 't0': 1.618e-6 * 40, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
626
+ # {'Delta': 6.176652254478073e9, 'phase': -0.0, 'weight': 'gaussian(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
627
+ # 't0': 1.618e-6 * 40, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
628
+ # {'Delta': 5.12311e9, 'phase': -0.0, 'weight': 'square(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
629
+ # 't0': 1/5.12311 * 1e-4 * 2, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
630
+ # {'Delta': 5.2231e9, 'phase': -0.0, 'weight': 'square(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
631
+ # 't0': 1/5.12311 * 1e-4 * 2, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
632
+ # {'Delta': 5.1e9, 'phase': -0.0, 'weight': 'square(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
633
+ # 't0': 6.401e-06, 'phi': 2.1739656328752264, 'threshold': 20.36802101135254},
634
+ # {'Delta': 5.2e9, 'phase': -0.0, 'weight': 'square(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
635
+ # 't0': 6.401e-06, 'phi': 1.851749364542847, 'threshold': 21.65827751159668},
636
+ # {'Delta': 1e9, 'phase': -0.0, 'weight': 'square(8e-07) >> 4e-07', 'window': (0, 1024), 'w': None,
637
+ # 't0': 5.5e-06, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
638
+ # {'Delta': 1.1e9, 'phase': -0.0, 'weight': 'square(8e-07) >> 4e-07', 'window': (0, 1024), 'w': None,
639
+ # 't0': 5.5e-06, 'phi': 2.1739656328752264, 'threshold': 20.36802101135254},
640
+ # {'Delta': 1.2e9, 'phase': -0.0, 'weight': 'square(8e-07) >> 4e-07', 'window': (0, 1024), 'w': None,
641
+ # 't0': 5.5e-06, 'phi': 1.851749364542847, 'threshold': 21.65827751159668},
642
+ # {'Delta': 1e9, 'phase': -0.0, 'weight': 'square(8e-07) >> 4e-07', 'window': (0, 1024), 'w': None,
643
+ # 't0': 7.805e-06, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
644
+ # {'Delta': 1e9, 'phase': -0.0, 'weight': 'square(8e-07) >> 4e-07', 'window': (0, 1024), 'w': None,
645
+ # 't0': 8.805e-06, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
646
+ # {'Delta': 1.1e9, 'phase': -0.0, 'weight': 'square(8e-07) >> 4e-07', 'window': (0, 1024), 'w': None,
647
+ # 't0': 9.005e-06, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926}
648
+ ]}
649
+ co = {'start': 5.760000000000001e-07, 'stop': 1.581e-06, 'wList': [{'Delta': 6967500000.0, 'phase': -0.0, 'weight': '(sin(3141592.6535897935)**3)*(square(1e-06)>>(5e-07))',
650
+ 'window': (0, 1024), 'w': None, 't0': 5.81e-07, 'phi': -0.16222877291938465, 'threshold': 0.4922424554824829}]}
651
+ co = {'start': 5.760000000000001e-07, 'stop': 9.310000000000001e-07, 'wList': [{'Delta': 6967500000.0, 'phase': -0.0, 'weight': '(sin(8975979.010256553)**3)*(square(3.5e-07)>>(1.75e-07))', 'window': (0, 1024), 'w': None, 't0': 5.81e-07,
652
+ 'phi': 2.4011441876721005, 'threshold': 3.5368497371673584}]}
653
+ co = {'start': 5.760000000000001e-07, 'stop': 9.310000000000001e-07, 'wList': [{'Delta': 6967500000.0, 'phase': -0.0, 'weight': '(sin(8975979.010256553)**3)*(square(3.5e-07)>>(1.74e-07))', 'window': (0, 1024), 'w': None, 't0': 5.81e-07,
654
+ 'phi': 2.4011441876721005, 'threshold': 3.5368497371673584}]}
655
+
656
+ import numpy as np
657
+ # from nsqdriver.NS_DDS_v3_2 import Driver, get_coef
658
+ from nsqdriver import QSYNCDriver
659
+ from nsqdriver.NS_MCI import SHARED_DEVICE_MEM
660
+ import matplotlib.pyplot as plt
661
+ import waveforms as wf
662
+
663
+ SHARED_DEVICE_MEM.clear_ip()
664
+ _d = Driver('192.168.0.229', 50)
665
+ _q = QSYNCDriver('192.168.0.229')
666
+ _q.open(system_parameter={'RefClock': 'in'})
667
+ _d.open(system_parameter={'MixMode': 2, 'CaptureMode': 0, "DArate": 8e9, "RefClock": "out"})
668
+ _q.sync_system()
669
+ time.sleep(2)
670
+ _wave = wf.zero()
671
+ min_t0 = 10
672
+ for _w in co['wList']:
673
+ t0 = _w['t0']
674
+ min_t0 = min(min_t0, t0)
675
+ _wave += (wf.wave_eval(_w['weight']) * wf.cos(2 * np.pi * _w['Delta'])) >> t0
676
+ _wave /= 8
677
+ # _wave = _wave << 50e-9
678
+ _wave.start = 0
679
+ _wave.stop = co['stop']
680
+
681
+ _wave(np.linspace(0, _wave.stop, int(_wave.stop * 8e9)), frag=True)
682
+
683
+ wave = _wave.sample(8e9)
684
+ # plt.figure()
685
+ # plt.plot(wave)
686
+ # plt.show()
687
+ ch = 1
688
+ _wave.start = 0
689
+ _wave.stop = co["stop"]
690
+ shots = 8192
691
+
692
+ _q.set('Shot', shots)
693
+ _d.write('Shot', shots)
694
+
695
+
696
+ # 测试解模数据
697
+
698
+ # _d.write("INDelay", 136e-9, ch=ch) # INDelay 要在 Coefficient前面
699
+ # _d.write("Coefficient", co, ch=ch)
700
+ # _d.write("GenWave", _wave, ch=ch)
701
+
702
+ # _d.set('StartCapture')
703
+ # _q.set('GenerateTrig', 90e-6)
704
+ # data = _d.read("IQ", ch=ch)
705
+ # print(f"angle= {np.angle(data.mean(axis=0), deg=True)}")
706
+ # print(f"abs= {np.abs(data.mean(axis=0))}")
707
+
708
+ # 测试原始数据
709
+ # 将采集间隔改大
710
+ _d.set('CaptureMode', 1)
711
+ _d.write("GenWave", _wave, ch=ch)
712
+ _d.write("Coefficient", co, ch=ch) # 获取原始数据也要下发,用于配置indelay
713
+ _d.write("INDelay", 136e-9, ch=ch) # INDelay 要在 Coefficient前面
714
+
715
+ _d.write('StartCapture', 1)
716
+ _q.set('GenerateTrig', 500e-6)
717
+ data = _d.read("TraceIQ", ch=ch)
718
+ data = data.reshape((shots, -1))
719
+ plt.figure()
720
+ plt.plot(data.mean(axis=0))
721
+ plt.show()
722
+
723
+ # 测试波形连续播放
724
+ # 修改波形频率,在示波器可见
725
+
726
+ # _q.set("Shot", 0xFFFFFFFF)
727
+ # _q.set("GenerateTrig", 500e-6)
728
+ # time.sleep(10)
729
+ # _q.set("ResetTrig")
730
+
731
+ # 带包络扫描S21
732
+ # freq_range = np.linspace(4.01e9, 6.01e9, 51)
733
+ # s21_res = []
734
+ # _d.write("INDelay", 136e-9, ch=ch) # INDelay 要在 Coefficient前面
735
+ # for f in freq_range:
736
+ # co = {'start': 0.0, 'stop': 70.605e-06, 'wList': [
737
+ # {'Delta': f, 'phase': -0.0, 'weight': 'square(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
738
+ # 't0': 1.618e-6, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
739
+ # {'Delta': 6.176652254478073e9, 'phase': -0.0, 'weight': 'gaussian(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
740
+ # 't0': 1.618e-6, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
741
+ # {'Delta': f, 'phase': -0.0, 'weight': 'square(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
742
+ # 't0': 1.618e-6 * 20, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
743
+ # {'Delta': 6.176652254478073e9, 'phase': -0.0, 'weight': 'gaussian(0.8e-06) >> 4e-07', 'window': (0, 1024), 'w': None,
744
+ # 't0': 1.618e-6 * 20, 'phi': 2.4311851282940524, 'threshold': 9.645718574523926},
745
+ # ]}
746
+ # _wave = wf.zero()
747
+ # for _w in co['wList']:
748
+ # t0 = _w['t0']
749
+ # min_t0 = min(min_t0, t0)
750
+ # _wave += (wf.wave_eval(_w['weight']) * wf.cos(2 * np.pi * _w['Delta'])) >> t0
751
+ # _wave /= 8
752
+ # # _wave = _wave << 50e-9
753
+ # _wave.start = 0
754
+ # _wave.stop = co['stop']
755
+ # # plt.figure()
756
+ # # plt.plot(_wave.sample(8e9))
757
+ # # plt.show()
758
+ # _d.write("Coefficient", co, ch=ch)
759
+ # _d.write("GenWave", _wave, ch=ch)
760
+
761
+ # _d.set('StartCapture')
762
+ # _q.set('GenerateTrig', 90e-6)
763
+ # data = _d.read("IQ", ch=ch)
764
+ # s21_res.append(data)
765
+ # # 取第一次采集的第一个频点画图
766
+ # cap1 = np.array(s21_res)
767
+ # cap1 = cap1[:, :, 0].mean(axis=1)
768
+ # cap1 = 20 * np.log10(np.abs(cap1))
769
+ # plt.figure()
770
+ # plt.plot(freq_range, cap1)
771
+ # plt.show()
772
+ # # 取第二次采集的第一个频点画图
773
+ # cap2 = np.array(s21_res)
774
+ # cap2 = cap2[:, :, 2].mean(axis=1)
775
+ # cap2 = 20 * np.log10(np.abs(cap2))
776
+ # plt.figure()
777
+ # plt.plot(freq_range, cap2)
778
+ # plt.show()
nsqdriver/NS_MCI.py CHANGED
@@ -212,7 +212,9 @@ class Driver(BaseDriver):
212
212
  values.update(system_parameter)
213
213
  for name, value in values.items():
214
214
  if value is not None:
215
- self.fast_rpc.rpc_set(name, value, 0, False)
215
+ res = self.fast_rpc.rpc_set(name, value, 0, False)
216
+ if isinstance(res, str):
217
+ print("*********后台提示*********\n", res)
216
218
  print_debug('Driver: 后端参数配置成功')
217
219
 
218
220
  # 系统开启前必须进行过一次初始化
@@ -550,12 +552,10 @@ class RPCValueParser:
550
552
  value = [RPCValueParser.load(_v) for _v in value]
551
553
  return value
552
554
 
553
-
554
555
  class InfoSharedList:
555
556
  memory_name = 'NS_DEVICE_MEMORY'
556
557
  memory_size = 1024 ** 2
557
558
  head_size = 32 # memory中前head_size的长度为头部预留信息
558
-
559
559
  def __init__(self):
560
560
  try:
561
561
  self._memory = shared_memory.SharedMemory(name=self.memory_name, create=True, size=self.memory_size)
nsqdriver/NS_QSYNC.py CHANGED
@@ -608,7 +608,8 @@ class DeviceCmdHandle:
608
608
  error_map = {b'\x1a\x00\x001': {1: '指令Resync执行失败',
609
609
  2: 'REFCLK not Detected',
610
610
  3: 'Clock Maybe unstable, DAC Settings Error',
611
- 4: 'Clock Maybe unstable, ADC Settings Error',
611
+ 4: 'Clock Maybe unstable, ADC Settings Error, '
612
+ 'Please check if the amplifier is too large',
612
613
  5: 'SYSREF(External TRIG) not Detected, MTS failed / Sample Rate not Support',
613
614
  7: 'ADC Calibration Failed'}
614
615
  }
@@ -622,7 +623,7 @@ class DeviceCmdHandle:
622
623
  errors = []
623
624
  for board, future in zip(boards, futures):
624
625
  if board.has_cmd_link and board.has_stream_link:
625
- _id = (board.ds_id & 0xFF) << 24
626
+ _id = (board.sig_fpga_pci_port & 0xFF) << 24
626
627
  _res = struct.unpack('IIIII', future.result())[-1] & 0xFFFFFF
627
628
  if _res:
628
629
  errors.append(f'指令{cmd_data[4:8].tobytes()}向{board.cs_target}转发失败\n')
nsqdriver/__init__.py CHANGED
@@ -1,10 +1,10 @@
1
1
  from .NS_MCI import Driver as MCIDriver
2
2
  from .NS_QSYNC import Driver as QSYNCDriver
3
3
  from .NS_CST import Driver as CSTDriver
4
- from .compiler.ns_wave import InsChannel
5
- from .compiler.py_wave_asm import nsw_config, AssemblyError
4
+ # from .compiler.ns_wave import InsChannel
5
+ # from .compiler.py_wave_asm import nsw_config, AssemblyError
6
6
 
7
- version_pack = (0, 12, 12)
7
+ version_pack = (0, 12, 14)
8
8
 
9
9
  __version__ = '.'.join(str(_) for _ in version_pack)
10
10
  __all__ = ['MCIDriver', 'QSYNCDriver', 'CSTDriver', 'InsChannel']
Binary file
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: nsqdriver
3
- Version: 0.12.12
3
+ Version: 0.12.14
4
4
  Summary: Q series measurement and control equipment driver interface
5
5
  Home-page: https://g2hoyqcmh4.feishu.cn/wiki/Jgt1wxlKniveYQkqCgbcJHsMnoe
6
6
  Classifier: Intended Audience :: Developers
@@ -0,0 +1,41 @@
1
+ nsqdriver/NS_CST.py,sha256=_QYCjg1YglIJ4YVmxvISqvy5rExWGlMhyrK9zYIRbRY,7877
2
+ nsqdriver/NS_DDS_v3.py,sha256=VoTHf9fEknw0gU35c-trraf_7fqasKyyRZxGMsmExfU,23780
3
+ nsqdriver/NS_DDS_v4.py,sha256=vKmbJ9txOrWzUqK2Vxc--0GmLU44RFyPkLJHlHcJYjA,34442
4
+ nsqdriver/NS_MCI.py,sha256=Z2iCSEsnuodqtcWvCey7i0-l6vgn6dKeHzDzjmZ7858,22038
5
+ nsqdriver/NS_QSYNC.py,sha256=DIoPTFlEEFJZ9GQ3Ot4nM6thkQmRXaj1d-p9q2tLVTc,27219
6
+ nsqdriver/__init__.py,sha256=kEVy3TjFi4mOnXXI7pihq-U5dBv7Q4Pdvgo986f2_i8,377
7
+ nsqdriver/common.py,sha256=IHfShqgNN3THbe7KD7ICdfFY7JKC_kQj0_KJk-449gQ,499
8
+ nsqdriver/compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ nsqdriver/compiler/assembler.cpython-312-darwin.so,sha256=aOYfdfOiQ9nUEUihULnoTp90O68jbO5Fjh5myPph4O4,1119904
10
+ nsqdriver/compiler/ns_wave.cpython-312-darwin.so,sha256=k0rAHFHV1xrHnROazOlCxRoDN9EJbkuNUA4sSM7T_cM,640752
11
+ nsqdriver/compiler/ns_wave.pyi,sha256=JQiE_9HqCzm00bS6c2JaaIXwt7xN_x9XXax-BBrE7-o,3824
12
+ nsqdriver/compiler/py_wave_asm.cpython-312-darwin.so,sha256=zE-TencBOoJAyNJxFtVBg8-3r6s_s3ariFYHaD5Yacc,838840
13
+ nsqdriver/compiler/py_wave_asm.pyi,sha256=w2PWlBrns4tfDYjTLyOBfNgjjjVA_xzMJZYYyDPKce4,656
14
+ nsqdriver/nswave/__init__.py,sha256=1-DljzsjzvnHRnD0tlpVTWSZjHtlCnP-yRirOJuG8Co,293
15
+ nsqdriver/nswave/_asm.pyi,sha256=kayOim0cSLXwSCAAXkMu0-IsLusY95dTFORTNrHzFo8,2749
16
+ nsqdriver/nswave/_checkers.cpython-312-darwin.so,sha256=htmICZfcnctWfpVGZZTILY1NBALtlobhsyygiraWWUw,580464
17
+ nsqdriver/nswave/_checkers.pyi,sha256=h_lMi6vWZ4SYe_5GDyOuYNbzL1nVDGvy4E-nAb9tzsk,1412
18
+ nsqdriver/nswave/_errors.cpython-312-darwin.so,sha256=SrnbHrXiWBbBnv3D4ke2lmQN_kSBZZHGWhiQlW3gHU0,239136
19
+ nsqdriver/nswave/_errors.pyi,sha256=pYt3VZxWgXWVNGvbQ3g6IwxItCmPcW_EfN3l1YfLk2o,640
20
+ nsqdriver/nswave/_functions.cpython-312-darwin.so,sha256=hUykw6Kv-lwOUtQTDvGLB6FMFdt6P3dCMFj0T4D0zhg,588344
21
+ nsqdriver/nswave/_functions.pyi,sha256=lHSxiqHwZVvdjs-53KiFlTGAGCHsvOU3DKDGRVM7ur8,1958
22
+ nsqdriver/nswave/_ir.cpython-312-darwin.so,sha256=Xsi4ZM30UI19zuNzutY8CX4Z_uGlmXdlOevFCpjrjQE,1180096
23
+ nsqdriver/nswave/_ir.pyi,sha256=tC4iVf0dUOevZhwbCm77pDk87PbaIbhpNGHFamNdx5k,7130
24
+ nsqdriver/nswave/_ir_pass.cpython-312-darwin.so,sha256=Ae2wz-aYJbcfpmE8BCQeg07JRyjcAYsFa3gUvtYBpcQ,183952
25
+ nsqdriver/nswave/_ir_pass.pyi,sha256=wYOesXdZnTlZ0Ph06VVP65uc6n-k8gywEkHaaSSyPmQ,282
26
+ nsqdriver/nswave/_optimizations.cpython-312-darwin.so,sha256=bRMDd834K1RxUeJZsrHTOASUCAf5UBBv8eTB2FEfwuQ,217800
27
+ nsqdriver/nswave/_optimizations.pyi,sha256=y6ytCU8SSlD4mzXe-V2GjFrvpafumK388pgxHuxDBnI,492
28
+ nsqdriver/nswave/_rules.cpython-312-darwin.so,sha256=WAblj4TYP4MxWherzRZ0NXlOYLmWkD0SEkvw0_pTJWs,581264
29
+ nsqdriver/nswave/_rules.pyi,sha256=AxXSBY0xM3PMrZqIvqSDJB53eScU_XatNWiul57ZytU,1870
30
+ nsqdriver/nswave/_simulator.cpython-312-darwin.so,sha256=Y1eM7UJckhZbElFqU9rgiuNf6ruqMzcZiGcBauItiSw,398616
31
+ nsqdriver/nswave/_translate.cpython-312-darwin.so,sha256=KQlDWwY_aH7ec2q0sIICr1uvbWtQff2YyhWtma82qx8,362072
32
+ nsqdriver/nswave/_translate.pyi,sha256=JAFEJpAw5k2yx3uKNcKPCNV--fxTneDbfm4xA8fW_kw,375
33
+ nsqdriver/nswave/kernel.cpython-312-darwin.so,sha256=C6mNcZaoW1vbUzcTHzuG_ZZBrDRerFcA96v08FaQqIo,857648
34
+ nsqdriver/nswave/kernel.pyi,sha256=Fs-_v2XT0UpRSSoogwIbejXna6uAfceYv41PyL2m-NM,1952
35
+ nsqdriver/wrapper/AWG_ADC.py,sha256=ktQkORc8VZUFkNg6huC7DKIkvZyHYXRolQ2SAA89JnM,19199
36
+ nsqdriver/wrapper/ND_NSMCI.py,sha256=gTyrDObhbggl35V_q-kpDoPsfttIEnDFc6f0-pk_P0k,6288
37
+ nsqdriver/wrapper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ nsqdriver-0.12.14.dist-info/METADATA,sha256=vLn76IGoD8jOeNkJjg527rJ-WMAlKayfDSwkUtm_ZHI,4459
39
+ nsqdriver-0.12.14.dist-info/WHEEL,sha256=Inq8GN4B3FxqLqMouJgNCh3_KlBp46ucqLBYqKIagAU,115
40
+ nsqdriver-0.12.14.dist-info/top_level.txt,sha256=o7EbQoFO6BoaG3KGbS9Lg_aRheZSY5KYzoYuI9vx-AI,10
41
+ nsqdriver-0.12.14.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (79.0.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp312-cp312-macosx_10_13_universal2
5
5
 
@@ -1,40 +0,0 @@
1
- nsqdriver/NS_CST.py,sha256=_QYCjg1YglIJ4YVmxvISqvy5rExWGlMhyrK9zYIRbRY,7877
2
- nsqdriver/NS_DDS_v3.py,sha256=1nixUlD8iMJkuvWMxGFNQOQ48AYOhbcT37Do5Aip9vs,20278
3
- nsqdriver/NS_MCI.py,sha256=Hr3asdyGPGTEBFg_bSvfdSBfjc9J-ybNr5pSv5q6go4,21926
4
- nsqdriver/NS_QSYNC.py,sha256=ZSOznM5PMlOm89rWAMiqVyZLWn3y0lTQp3d1z6LnkV0,27121
5
- nsqdriver/__init__.py,sha256=S4mxgWtqf_fxlBhX20vUkPaKmfU8jFzKHnSCUv23Wnc,373
6
- nsqdriver/common.py,sha256=IHfShqgNN3THbe7KD7ICdfFY7JKC_kQj0_KJk-449gQ,499
7
- nsqdriver/compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- nsqdriver/compiler/assembler.cpython-312-darwin.so,sha256=rd2dZedco5qqRKUggjIb7uEIHhsM7edlnCve04xsBmc,1102912
9
- nsqdriver/compiler/ns_wave.cpython-312-darwin.so,sha256=hkIoLMcTtKDHR659_SaQF2MKyWvNZEG1DwWjA3JKwTE,640752
10
- nsqdriver/compiler/ns_wave.pyi,sha256=JQiE_9HqCzm00bS6c2JaaIXwt7xN_x9XXax-BBrE7-o,3824
11
- nsqdriver/compiler/py_wave_asm.cpython-312-darwin.so,sha256=pfnvVjNoC1bh2y-Ek2amrBJnNPLw9rJ6osAyBxFP420,838840
12
- nsqdriver/compiler/py_wave_asm.pyi,sha256=w2PWlBrns4tfDYjTLyOBfNgjjjVA_xzMJZYYyDPKce4,656
13
- nsqdriver/nswave/__init__.py,sha256=1-DljzsjzvnHRnD0tlpVTWSZjHtlCnP-yRirOJuG8Co,293
14
- nsqdriver/nswave/_asm.pyi,sha256=kayOim0cSLXwSCAAXkMu0-IsLusY95dTFORTNrHzFo8,2749
15
- nsqdriver/nswave/_checkers.cpython-312-darwin.so,sha256=KwOII8j8PZkMUNZNjtSa65gZTYHIqDe06xhIQ72SugY,580464
16
- nsqdriver/nswave/_checkers.pyi,sha256=h_lMi6vWZ4SYe_5GDyOuYNbzL1nVDGvy4E-nAb9tzsk,1412
17
- nsqdriver/nswave/_errors.cpython-312-darwin.so,sha256=D384pj0_155E-QSQC8uOet6a4xLgzGQeY0hz0mxksG0,239136
18
- nsqdriver/nswave/_errors.pyi,sha256=pYt3VZxWgXWVNGvbQ3g6IwxItCmPcW_EfN3l1YfLk2o,640
19
- nsqdriver/nswave/_functions.cpython-312-darwin.so,sha256=vbMNrmNRaKGOE3PwiWwCMlmgZlSkjfy4RE4NCdqaSks,571336
20
- nsqdriver/nswave/_functions.pyi,sha256=lHSxiqHwZVvdjs-53KiFlTGAGCHsvOU3DKDGRVM7ur8,1958
21
- nsqdriver/nswave/_ir.cpython-312-darwin.so,sha256=biElTbXPX0TSMQWAvMn9z_yIFdMIR1ihS1iWPZGGqxg,1162672
22
- nsqdriver/nswave/_ir.pyi,sha256=tC4iVf0dUOevZhwbCm77pDk87PbaIbhpNGHFamNdx5k,7130
23
- nsqdriver/nswave/_ir_pass.cpython-312-darwin.so,sha256=cZay8g-BUmcyy892Icb1yu4NGqUvzZQyb5AmCNq412Y,183952
24
- nsqdriver/nswave/_ir_pass.pyi,sha256=wYOesXdZnTlZ0Ph06VVP65uc6n-k8gywEkHaaSSyPmQ,282
25
- nsqdriver/nswave/_optimizations.cpython-312-darwin.so,sha256=TdPrWZgXVNlZoJ5KqBvqDwaCqXKZV11HQtBbbr_3LUk,217800
26
- nsqdriver/nswave/_optimizations.pyi,sha256=y6ytCU8SSlD4mzXe-V2GjFrvpafumK388pgxHuxDBnI,492
27
- nsqdriver/nswave/_rules.cpython-312-darwin.so,sha256=_STlPAn4-LTs0lF-pmZlJE4yc2X2pEokwDIL7zCjd7s,529952
28
- nsqdriver/nswave/_rules.pyi,sha256=AxXSBY0xM3PMrZqIvqSDJB53eScU_XatNWiul57ZytU,1870
29
- nsqdriver/nswave/_simulator.cpython-312-darwin.so,sha256=A3xRXAKa96xkDCyuluZ6IPKAHkNaklOYLvlnw3NO9-k,398616
30
- nsqdriver/nswave/_translate.cpython-312-darwin.so,sha256=CIvY5QLlfHe3CqvT-8fzK98FF4w3sg09pnhoPOHB11E,362072
31
- nsqdriver/nswave/_translate.pyi,sha256=JAFEJpAw5k2yx3uKNcKPCNV--fxTneDbfm4xA8fW_kw,375
32
- nsqdriver/nswave/kernel.cpython-312-darwin.so,sha256=zsZtxHMBRTxKkFmrY2M6APA79dHWIiXyWxBYOFT_crU,840704
33
- nsqdriver/nswave/kernel.pyi,sha256=Fs-_v2XT0UpRSSoogwIbejXna6uAfceYv41PyL2m-NM,1952
34
- nsqdriver/wrapper/AWG_ADC.py,sha256=ktQkORc8VZUFkNg6huC7DKIkvZyHYXRolQ2SAA89JnM,19199
35
- nsqdriver/wrapper/ND_NSMCI.py,sha256=gTyrDObhbggl35V_q-kpDoPsfttIEnDFc6f0-pk_P0k,6288
36
- nsqdriver/wrapper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- nsqdriver-0.12.12.dist-info/METADATA,sha256=ZO6NmvK6JV8FUh-xbYG7hhXgbalWjuKx6GpDzZ1BCUQ,4459
38
- nsqdriver-0.12.12.dist-info/WHEEL,sha256=iDXcyuxg-66TzzqHGH-kgw_HJdaJE_1RHznrvPNCSNs,115
39
- nsqdriver-0.12.12.dist-info/top_level.txt,sha256=o7EbQoFO6BoaG3KGbS9Lg_aRheZSY5KYzoYuI9vx-AI,10
40
- nsqdriver-0.12.12.dist-info/RECORD,,