def main(): read_arguments() ctx = create_context(scan_for_context, arg_uri, arg_ip) if timeout >= 0: ctx.set_timeout(timeout) dev = ctx.find_device(device_name) if dev is None: sys.stderr.write('Device %s not found!' % device_name) exit(1) if len(channels) == 0: for channel in dev.channels: channel.enabled = True else: for channel_idx in channels: dev.channels[int(channel_idx)].enabled = True buffer = iio.Buffer(dev, buffer_size, cyclic=cyclic) if buffer is None: sys.stderr.write('Unable to create buffer!') exit(1) write_data(dev, buffer, num_samples, buffer_size, cyclic)
def writeTx(self, samples): #, raw=False): use samples.dtype """write to the Tx buffer and make it cyclic""" if self._tx_buff is not None: self._tx_buff = None # turn off any previous signal if not (isinstance(samples, np.ndarray)): logging.debug('tx: off') # leave with transmitter off self.tx_state = self.TX_OFF return if samples.dtype == np.int16: data = samples << 4 # align 12 bit raw to msb else: # samples can come from some DiscreteSignalSource, if so # data is complex IQ and scaled to +/-1.0 float range # use 16 **not** self.no_bits to align data to msb data = self.complex2raw(samples, 16) # samples are 2 bytes each with interleaved I/Q value (no_samples = len/4) self.tx_state = self.TX_DMA # enable the tx channels try: # create a cyclic iio buffer for continuous tx output self._tx_buff = iio.Buffer(self.dac, len(data) // 4, True) count = self._tx_buff.write(data) logging.debug(str(count) + ' samples transmitted') self._tx_buff.push() except OSError as oserr: self.tx_state = self.TX_OFF raise OSError('failed to create an iio buffer') # buffer retained after a successful call return count # just for now
def run(collector_self): for name, ch in self.channels.items(): ch.iio_channel.enabled = (name in self.active_channels) samples_count = self.buffer_samples_count or self.sample_rate_hz iio_buffer = iio.Buffer(self.iio_device, samples_count, self.buffer_is_circular) # NB: This buffer creates a communication pipe to the # BeagleBone (or is it between the BBB and the ACME?) # that locks down any configuration. The IIO drivers # do not limit access when a buffer exists so that # configuring the INA226 (i.e. accessing iio.Device.attrs # or iio.Channel.attrs from iio.Device.channels i.e. # assigning to or reading from any property of this class # or calling its setup or reset methods) will screw up the # whole system and will require rebooting the BBB-ACME board! self.collector_exception = None try: refilled_once = False while not (refilled_once and self.work_done.is_set()): refilled_once = True iio_buffer.refill() for name in self.active_channels: self.channels[name].iio_store_buffer_samples( iio_buffer) except Exception as e: self.collector_exception = e finally: del iio_buffer for ch in self.channels.values(): ch.enabled = False
def writeTx(self, samples, raw=False): """write to the Tx buffer and make it cyclic""" if self._tx_buff is not None: self._tx_buff = None # turn off any previous signal if isinstance(samples, bool) or len(samples)==0: logging.debug('tx: off') # leave with transmitter off return if raw: data = samples<<4 # align 12 bit raw to msb else: # samples some are from some DiscreteSignalSource, so # data is complex IQ and scaled to +/-1.0 float range # use 16 **not** self.no_bits to align data to msb data = self.complex2raw(samples, 16) no_samples = len(data)//2 for ch in self.tx_channels: # enable the tx channels ch.enabled = True try: # create a cyclic iio buffer for continuous tx output self._tx_buff = iio.Buffer(self.dac, no_samples//2, True) count = self._tx_buff.write(data) logging.debug(str(count)+' samples transmitted') self._tx_buff.push() except OSError: for ch in chs: ch.enabled = False self._tx_buff = None raise OSError('failed to create an iio buffer') # buffer retained after a successful call return count # just for now
def create(self): """Create the IIO buffer.""" self._device() self._channels() buffer = iio.Buffer(self.dev, self.arguments.buffer_size) if buffer is None: raise Exception("Unable to create buffer!\n") return buffer
def create_streams(self, blen): self.dev_rx = self.iio_ctx.find_device("cf-ad9361-A") # configure master streaming devices for n in range(8): chan = self.dev_rx.find_channel("voltage" + str(n)) chan.enabled = True # create IIO buffer object self.buf_rx = iio.Buffer(self.dev_rx, blen)
def _rx_init_channels(self): if self._complex_data: for m in self.rx_enabled_channels: v = self._rxadc.find_channel(self._rx_channel_names[m * 2]) v.enabled = True v = self._rxadc.find_channel(self._rx_channel_names[m * 2 + 1]) v.enabled = True else: for m in self.rx_enabled_channels: v = self._rxadc.find_channel(self._rx_channel_names[m]) v.enabled = True self.__rxbuf = iio.Buffer(self._rxadc, self.__rx_buffer_size, False)
def rx(self): if not self.rxbuf: # Enable all IQ channels v0 = self.rxadc.find_channel("voltage0") v1 = self.rxadc.find_channel("voltage1") v0.enabled = True v1.enabled = True self.rxbuf = iio.Buffer(self.rxadc, 2**15, False) self.rxbuf.refill() data = self.rxbuf.read() x = np.frombuffer(data, dtype=np.int16) sig = x[::2] + 1j * x[1::2] return sig
def _create_buffer(self, buff_size): device = self.context.find_device(DEVICE_TX_NAME) # configure master streaming devices # 1x1 SDR contains only two channels for n in range(2): name = "voltage{0}".format(n) chan = device.find_channel(name, is_output=True) chan.enabled = True # create buffer self.buffer_tx = iio.Buffer(device, buff_size, cyclic=True)
def _tx_init_channels(self): if self._complex_data: for m in self.tx_enabled_channels: v = self._txdac.find_channel(self._tx_channel_names[m * 2], True) v.enabled = True v = self._txdac.find_channel(self._tx_channel_names[m * 2 + 1], True) v.enabled = True else: for m in self.tx_enabled_channels: v = self._txdac.find_channel(self._tx_channel_names[m], True) v.enabled = True self.__txbuf = iio.Buffer( self._txdac, self._tx_buffer_size, self.__tx_cyclic_buffer )
def readRx(self, no_samples, raw=True): # enable the channels for ch in self.adc.channels: ch.enabled = True try: # create a buffer of the right size to use buff = iio.Buffer(self.adc, no_samples) buff.refill() buffer = buff.read() iq = np.frombuffer(buffer, np.int16) except OSError: for ch in self.adc.channels: ch.enabled = True raise OSError('failed to create iio buffer') if raw: return iq else: return self.raw2complex(iq)
def _rx_init_channels(self): for m in self._rx_channel_names: v = self._rxadc.find_channel(m) if not v: raise Exception(f"Channel {m} not found") v.enabled = False if self._complex_data: for m in self.rx_enabled_channels: v = self._rxadc.find_channel(self._rx_channel_names[m * 2]) v.enabled = True v = self._rxadc.find_channel(self._rx_channel_names[m * 2 + 1]) v.enabled = True else: for m in self.rx_enabled_channels: v = self._rxadc.find_channel(self._rx_channel_names[m]) v.enabled = True self.__rxbuf = iio.Buffer(self._rxadc, self.__rx_buffer_size, False)
def allocate_capture_buffer(self, samples_count, cyclic=False): """ Allocate buffer to store captured data. Args: samples_count (int): amount of samples to hold in buffer (> 0). cyclic (bool): True to make the buffer act as a circular buffer, False otherwise. Returns: bool: True if operation is successful, False otherwise. """ self._iio_buffer = iio.Buffer(self._iio_device, samples_count, cyclic) if self._iio_buffer != None: self._trace.trace( 1, "Buffer (count=%d, cyclic=%s) allocated." % (samples_count, cyclic)) return True self._trace.trace( 1, "Failed to allocate buffer! (count=%d, cyclic=%s)" % (samples_count, cyclic)) return False
# https://ez.analog.com/thread/97117-using-iiopy-with-m2k # https://mirrors.dotsrc.org/fosdem/2018/AW1.120/plutosdr.webm # https://wiki.analog.com/resources/tools-software/linux-software/fmcomms2_plugin import iio, struct, time import scipy.signal import numpy as np import matplotlib.pyplot as plt ctxs = iio.scan_contexts() uri = next(iter(ctxs), None) ctx = iio.Context(uri) dev = ctx.find_device('cf-ad9361-lpc') phy = ctx.find_device('ad9361-phy') phy.channels[0].attrs['frequency'].value = str(int(1575.42e6)) dev.channels[0].enabled = True dev.channels[1].enabled = True buf = iio.Buffer(dev, 4096, cyclic=False) ys = [] for i in range(1024): buf.refill() ys.append(buf.read()) d = np.frombuffer(np.array([inner for outer in ys for inner in outer]), dtype=np.int16) q = d[::2] + 1j * d[1::2] f, t, z = scipy.signal.stft(q[0:32 * 4096]) plt.imshow(np.abs(z)) plt.show() print(iio.version) ctxs = iio.scan_contexts()
def get_plot_data(dev, center_freq, min_hw_gain): global fft_rxvals_iq_db global fftfreq_rxvals_iq ylim = [0, 0] # Create IIO RX Buffer rxbuf = iio.Buffer(dev[RXADC], BUFLEN, False) # Window function, max value = unity window = np.blackman(BUFLEN) avg_step = 0 fft_rxvals_iq = np.array([]) fftfreq_rxvals_iq = np.array([]) avgband = np.array([]) while (True): #acquire data for i in range(0, len(center_freq)): RXLO = center_freq[i] TXLO = RXLO rxLO.attrs["frequency"].value = str(int(RXLO)) txLO.attrs["frequency"].value = str(int(TXLO)) time.sleep(0.2) root.update_idletasks() root.update() #Get gain calibration for specific band if (gain_calib_set.get() == True): for index_gain in range(0, len(gain_freq)): gain_frequency = float(gain_freq[index_gain][0]) * 1e6 if ((center_freq[i] - FREQ_BAND / 2) <= gain_frequency <= (center_freq[i] + FREQ_BAND / 2)): gain_calib = float(gain_freq[index_gain][1]) break else: gain_calib = 0 #generate test tone test_tone_freq = str( (TXDAC_FREQ) * (i + 1)) # spread test tones for each new band dds0.attrs["frequency"].value = test_tone_freq #delay before data acquisition time.sleep(0.01) if (progress_en.get() == False): for k in range(0, int(avg_nr.get()) + 1): #flush operations for j in range(5): rxbuf.refill() x = rxbuf.read() buff = np.frombuffer(x, np.int16) #apply window rxvals_i = buff[0::2] * window rxvals_q = buff[1::2] * window #construct complex IQ data rxvals_iq = rxvals_i + (1j * rxvals_q) # apply FFT and get amplitude of the IQ data newband = np.abs(np.fft.fft(rxvals_iq)) #apply averaging if (k != 0): avgband = (newband) * 1 / k + avgband * (k - 1) / k else: avgband = newband else: for j in range(5): rxbuf.refill() x = rxbuf.read() #get data from buffer buff = np.frombuffer(x, np.int16) #apply window rxvals_i = buff[0::2] * window rxvals_q = buff[1::2] * window #construct complex IQ data rxvals_iq = rxvals_i + (1j * rxvals_q) # apply FFT and get amplitude of the IQ data avgband = np.abs(np.fft.fft(rxvals_iq)) txt1.insert( tk.END, "Center Frequency set to: " + str(int(RXLO / 1e6)) + ' MHz\n') txt1.insert( tk.END, "Min / Max i values: " + str(int(np.min(rxvals_i))) + ", " + str(int(np.max(rxvals_i))) + "\n") txt1.see("end") #compute cutoff thresholds low_th = int(((RX0FS - FREQ_BAND) / (RX0FS * 2)) * BUFLEN) high_th = int(BUFLEN - (((RX0FS - FREQ_BAND) / (RX0FS * 2)) * BUFLEN)) #compute frequency bins freq_bins = (np.fft.fftfreq(BUFLEN, 1 / RX0FS) + (center_freq[0] + FREQ_BAND * i)) / 1e6 # Create tuple such that frequencies and corresponding amplitudes can be manipulated together tuple1 = zip(freq_bins, avgband) # Rearrange such that the center frequency is in the middle. tuple1 = sorted(tuple1, key=lambda x: x[0]) # Extract the passband of the FIR response tuple1 = tuple1[low_th:high_th] iq = np.array([nr[1] for nr in tuple1]) / (10**(gain_calib / 10)) if (progress_en.get() == False): if (avg_step == 0): # Append amplitudes to collection of bands fft_rxvals_iq = np.append(fft_rxvals_iq, iq) # Append frequency bins to the frequency collection fftfreq_rxvals_iq = np.append(fftfreq_rxvals_iq, [nr[0] for nr in tuple1]) else: #replace older amplitudes per band with newer amplitudes fft_rxvals_iq[i * (high_th - low_th):(i + 1) * (high_th - low_th)] = iq else: if (avg_step == 0): # Append amplitudes to collection of bands fft_rxvals_iq = np.append(fft_rxvals_iq, iq) fftfreq_rxvals_iq = np.append(fftfreq_rxvals_iq, [nr[0] for nr in tuple1]) else: #replace older amplitudes per band with newer amplitudes iq = iq * 1 / avg_step + fft_rxvals_iq[ i * (high_th - low_th):(i + 1) * (high_th - low_th)] * (avg_step - 1) / avg_step fft_rxvals_iq[i * (high_th - low_th):(i + 1) * (high_th - low_th)] = iq # Compute in dB, subtract hardware gain to normalize to absolute analog signal level at input fft_rxvals_iq_db = 20 * np.log10(fft_rxvals_iq * 2 / (2**11 * BUFLEN)) - min_hw_gain #Perform gain calibration per band #fft_rxvals_iq_db[i * (high_th - low_th) : (i + 1) * (high_th - low_th)] = fft_rxvals_iq_db[i * (high_th - low_th) : (i + 1) * (high_th - low_th)] - gain_calib # Plot data a.clear() a.grid(True) a.set_title('Frequency Spectrum') a.set_xlabel('Fequency (MHz)') a.set_ylabel('Magnitude') a.plot(fftfreq_rxvals_iq, fft_rxvals_iq_db) if (fixed_axis.get() == True and avg_step != 0): a.set_ylim(ylim) if (fixed_axis.get() == False or avg_step == 0): ylim = a.get_ylim() canvas.draw() root.update_idletasks() root.update() if (btn_text.get() == "Start" and sweep_en.get() == False): break if (btn_text.get() == "Start" or sweep_en.get() == True): break avg_step += 1
ctrl.channels[5].attrs['hardwaregain'].value = '-30' # Enable all IQ channels rxadc.channels[0].enabled = True rxadc.channels[1].enabled = True txdac.channels[4].enabled = True txdac.channels[5].enabled = True # Force DAC to use DMA not DDSs txdac.channels[0].attrs['raw'].value = str(0) txdac.channels[1].attrs['raw'].value = str(0) txdac.channels[2].attrs['raw'].value = str(0) txdac.channels[3].attrs['raw'].value = str(0) # Create buffer for RX data rxbuf = iio.Buffer(rxadc, 2**15, False) # Create cyclic buffer for TX data N = 2**15 txbuf = iio.Buffer(txdac, N / 2, True) # Create a sinewave waveform fc = 10000 ts = 1 / float(RXFS) t = np.arange(0, N * ts, ts) i = np.sin(2 * np.pi * t * fc) * 2**14 q = np.cos(2 * np.pi * t * fc) * 2**14 iq = np.empty((i.size + q.size, ), dtype=i.dtype) iq[0::2] = i iq[1::2] = q iq = np.int16(iq)
def run_hardware_tests(TRXLO, sync, runs, uri): # User configurable DDS_Freq = 4000000 # Setup contexts try: ctx = iio.Context(uri) except: raise Exception("No device found") ctrl_chipA = ctx.find_device("adrv9009-phy") ctrl_chipB = ctx.find_device("adrv9009-phy-b") txdac = ctx.find_device("axi-adrv9009-tx-hpc") rxadc = ctx.find_device("axi-adrv9009-rx-hpc") hmc7044 = ctx.find_device("hmc7044") # Configure transceiver settings LO = ctrl_chipA.find_channel("TRX_LO", True) LO.attrs["frequency"].value = str(int(TRXLO)) LO = ctrl_chipB.find_channel("TRX_LO", True) LO.attrs["frequency"].value = str(int(TRXLO)) # rx = ctrl_chipA.find_channel("voltage0") rx.attrs['gain_control_mode'].value = 'slow_attack' rx = ctrl_chipB.find_channel("voltage0") rx.attrs['gain_control_mode'].value = 'slow_attack' if sync: # Calibrate ctrl_chipA.attrs['calibrate_rx_phase_correction_en'] = True ctrl_chipA.attrs['calibrate'] = True ctrl_chipB.attrs['calibrate_rx_phase_correction_en'] = True ctrl_chipB.attrs['calibrate'] = True # MCS hmc7044.reg_write(0x5a, 0) for k in range(12): ctrl_chipA.attrs['multichip_sync'] = str(k) ctrl_chipB.attrs['multichip_sync'] = str(k) # Enable all IQ channels v0 = rxadc.find_channel("voltage0_i") v1 = rxadc.find_channel("voltage0_q") v2 = rxadc.find_channel("voltage1_i") v3 = rxadc.find_channel("voltage1_q") v0.enabled = True v1.enabled = True v2.enabled = True v3.enabled = True # Create buffer for RX data rxbuf = iio.Buffer(rxadc, 2**14, False) # # Enable single tone DDS dds0_tx1 = txdac.find_channel('altvoltage0', True) dds2_tx1 = txdac.find_channel('altvoltage2', True) dds0_tx2 = txdac.find_channel('altvoltage8', True) dds2_tx2 = txdac.find_channel('altvoltage10', True) # Turn all others off dds1 = txdac.find_channel('altvoltage1', True) dds1.attrs['raw'].value = str(0) dds1.attrs['scale'].value = str(0) for r in range(3, 16): dds1 = txdac.find_channel('altvoltage' + str(r), True) dds1.attrs['scale'].value = str(0) dds1.attrs['raw'].value = str(0) # Set frequency of enabled DDSs dds0_tx1.attrs['raw'].value = str(1) dds0_tx1.attrs['frequency'].value = str(DDS_Freq) dds0_tx1.attrs['scale'].value = str(0.5) dds0_tx1.attrs['phase'].value = str(90000) dds2_tx1.attrs['raw'].value = str(1) dds2_tx1.attrs['frequency'].value = str(DDS_Freq) dds2_tx1.attrs['scale'].value = str(0.5) dds2_tx1.attrs['phase'].value = str(0) dds0_tx2.attrs['raw'].value = str(1) dds0_tx2.attrs['frequency'].value = str(DDS_Freq) dds0_tx2.attrs['scale'].value = str(0.5) dds0_tx2.attrs['phase'].value = str(90000) dds2_tx2.attrs['raw'].value = str(1) dds2_tx2.attrs['frequency'].value = str(DDS_Freq) dds2_tx2.attrs['scale'].value = str(0.5) dds2_tx2.attrs['phase'].value = str(0) # Collect data # reals0 = np.array([]) # imags0 = np.array([]) # reals1 = np.array([]) # imags1 = np.array([]) phase_error = np.array([]) for i in range(runs): rxbuf.refill() data = rxbuf.read() x = np.frombuffer(data, dtype=np.int16) # reals0 = np.append(reals0,x[::4]) # imags0 = np.append(imags0,x[1::4]) # reals1 = np.append(reals1,x[2::4]) # imags1 = np.append(imags1,x[3::4]) chan0 = x[0::4] + 1j * x[1::4] chan1 = x[2::4] + 1j * x[3::4] phase_error = np.append(phase_error, measure_phase(chan0, chan1)) # # Plot # if do_plots: # plt.plot(phase_error) # # plt.plot(reals0) # # # plt.plot(imags0) # # plt.plot(reals1) # # # plt.plot(imags1) # plt.xlabel("Samples") # plt.ylabel("Amplitude [dbFS]") # plt.show() return phase_error
def __init__(self, sampling_count=2048, context='ip:192.168.2.1'): ''' Initialization Paramters: handler: when I/Q data get ready, there requires a callback to send data sampling_count: I/Q sampling count, default value: 2048, context: device context, there requires ip address, ''' sys.stdout.write('Initialize Adalm-Pluto (based on AD936x) ...\n') self.__parameters = { 'frequency': (0, [101700000, (70000000, 1, 6000000000)]), # RX frequency 'rf_bandwidth': (4, [2000000, (200000, 1, 56000000)]), # RX bandwidth # 'sampling_frequency': (4, [2500000, (2083333, 1, 61440000)]), 'sampling_frequency': (4, [2500000, (521000, 1, 61440000)]), # Sampling Rate 'gain_control_mode': (4, ['manual', ('manual,fast_attack,slow_attack,hybrid')]), # Gain control 'hardwaregain': (4, [-3, (-3, 1, 71)]), # MGC 'tx_enabled': (1, ['false', ('true,false')]), # TX RF out 'tx_frequency': (1, [101700000, (70000000, 1, 6000000000)]), # TX frequency 'tx_hardwaregain': (5, [0, (-89, 1, 0)]) # TX MGC } self.__callback = None self.__capture = None self.__start_sampling = False self.__lock = threading.Lock() self.__abort_sampling_event = threading.Event() self.__abort_sampling_event.clear() try: # Create device context retry = 10 while retry: try: self.__ctx = iio.Context(context) break except: time.sleep(2) retry -= 1 continue sys.stdout.write(('Initialize device context.\n')) # Initialize device control # channel 0, 4 are manipulated by rx # channel 1, 5 are manipulated by tx self.__ctrl = self.__ctx.find_device('ad9361-phy') # Initialize RX/TX ctrl parameters self.__ctrl.channels[0].attrs['powerdown'].value = '1' self.__ctrl.channels[0].attrs['frequency'].value = '101700000' self.__ctrl.channels[4].attrs['rf_bandwidth'].value = '2000000' self.__ctrl.channels[4].attrs[ 'gain_control_mode'].value = 'slow_attack' self.__ctrl.channels[4].attrs[ 'rf_port_select'].value = 'A_BALANCED' self.__ctrl.channels[1].attrs['powerdown'].value = '1' self.__ctrl.channels[1].attrs['frequency'].value = '101700000' self.__ctrl.channels[5].attrs['rf_bandwidth'].value = '2000000' self.__ctrl.channels[5].attrs['hardwaregain'].value = '0' _ad9361_set_bb_rate(self.__ctrl._device, 2560000) sys.stdout.write('Initialize CTRL: \"ad9361-phy\".\n') # Initialize device receiving channels and enable I/Q data output channels self.__rx = self.__ctx.find_device('cf-ad9361-lpc') sys.stdout.write('Initialize RX: \"cf-ad9361-lpc\".\n') self.__rx.channels[0].enabled = True # I data channel self.__rx.channels[1].enabled = True # Q data channel sys.stdout.write('Enable RX I/Q channels.\n') # Initialize buffer self.__buffer = iio.Buffer(self.__rx, sampling_count, False) sys.stdout.write( 'Initialize I/Q data buffers (sampling count={0}).\n'.format( sampling_count)) except: traceback.print_exc()
tx.attrs["sampling_frequency"].value = str(int(RXFS)) tx.attrs['hardwaregain'].value = '-30' rx = ctrl.find_channel("voltage0") rx.attrs["rf_bandwidth"].value = str(int(TXBW)) rx.attrs["sampling_frequency"].value = str(int(TXFS)) rx.attrs['gain_control_mode'].value = 'slow_attack' # Enable all IQ channels v0 = rxadc.find_channel("voltage0") v1 = rxadc.find_channel("voltage1") v0.enabled = True v1.enabled = True # Create buffer for RX data rxbuf = iio.Buffer(rxadc, 2**15, False) # Enable single tone DDS dds0 = txdac.find_channel('altvoltage0', True) dds2 = txdac.find_channel('altvoltage2', True) dds0.attrs['raw'].value = str(1) dds0.attrs['frequency'].value = str(100000) dds0.attrs['scale'].value = str(0.9) dds0.attrs['phase'].value = str(90000) dds2.attrs['raw'].value = str(1) dds2.attrs['frequency'].value = str(100000) dds2.attrs['scale'].value = str(0.9) dds2.attrs['phase'].value = str(0) # Collect data #reals = np.array([])
ctrl.find_channel('voltage0', True).attrs['hardwaregain'].value = '-30' # Enable all IQ channels rxadc.find_channel("voltage0").enabled = True rxadc.find_channel("voltage1").enabled = True txdac.find_channel("voltage0", True).enabled = True txdac.find_channel("voltage1", True).enabled = True # Force DAC to use DMA not DDS txdac.find_channel('TX1_I_F1', True).attrs['raw'].value = str(0) txdac.find_channel('TX1_Q_F1', True).attrs['raw'].value = str(0) txdac.find_channel('TX1_I_F2', True).attrs['raw'].value = str(0) txdac.find_channel('TX1_Q_F2', True).attrs['raw'].value = str(0) # Create buffer for RX data rxbuf = iio.Buffer(rxadc, 2**15, False) # Create cyclic buffer for TX data samples_per_channel = 2**15 txbuf = iio.Buffer(txdac, samples_per_channel, True) # Create a sinewave waveform fc = 10000 ts = 1 / float(RXFS) t = np.arange(0, samples_per_channel * ts, ts) i = np.sin(2 * np.pi * t * fc) * 2**14 q = np.cos(2 * np.pi * t * fc) * 2**14 iq = np.empty((i.size + q.size, ), dtype=i.dtype) iq[0::2] = i iq[1::2] = q iq = np.int16(iq)
def run_hardware_tests(TRXLO, sync, runs, buf_len, uri1, uri2): # User configurable DDS_Freq = 4000000 # Setup contexts try: ctx1 = iio.Context(uri1) except: raise Exception("No device1 found") try: ctx2 = iio.Context(uri2) except: raise Exception("No device1 found") ctrl_chip1A = ctx1.find_device("adrv9009-phy") ctrl_chip1B = ctx1.find_device("adrv9009-phy-b") ctrl_chip2A = ctx2.find_device("adrv9009-phy") ctrl_chip2B = ctx2.find_device("adrv9009-phy-b") txdac1 = ctx1.find_device("axi-adrv9009-tx-hpc") rxadc1 = ctx1.find_device("axi-adrv9009-rx-hpc") txdac2 = ctx2.find_device("axi-adrv9009-tx-hpc") rxadc2 = ctx2.find_device("axi-adrv9009-rx-hpc") hmc7044_1 = ctx1.find_device("hmc7044") hmc7044_1_car = ctx1.find_device("hmc7044-car") hmc7044_2 = ctx2.find_device("hmc7044") hmc7044_2_car = ctx2.find_device("hmc7044-car") hmc7044_1_ext = ctx1.find_device("hmc7044-ext") # request sync pulse hmc7044_1_ext.attrs["sysref_request"].value = str(1) # Check Sync status # print(hmc7044_1._debug_attrs["status"].value) # Configure transceiver settings LO1 = ctrl_chip1A.find_channel("TRX_LO", True) LO1.attrs["frequency"].value = str(int(TRXLO)) LO1 = ctrl_chip1B.find_channel("TRX_LO", True) LO1.attrs["frequency"].value = str(int(TRXLO)) LO2 = ctrl_chip2A.find_channel("TRX_LO", True) LO2.attrs["frequency"].value = str(int(TRXLO)) LO2 = ctrl_chip2B.find_channel("TRX_LO", True) LO2.attrs["frequency"].value = str(int(TRXLO)) # rx1 = ctrl_chip1A.find_channel("voltage0") rx1.attrs['gain_control_mode'].value = 'slow_attack' rx1 = ctrl_chip1B.find_channel("voltage0") rx1.attrs['gain_control_mode'].value = 'slow_attack' rx2 = ctrl_chip2A.find_channel("voltage0") rx2.attrs['gain_control_mode'].value = 'slow_attack' rx2 = ctrl_chip2B.find_channel("voltage0") rx2.attrs['gain_control_mode'].value = 'slow_attack' if sync: # Calibrate ctrl_chip1A.attrs['calibrate_rx_phase_correction_en'] = True ctrl_chip1A.attrs['calibrate'] = True ctrl_chip1B.attrs['calibrate_rx_phase_correction_en'] = True ctrl_chip1B.attrs['calibrate'] = True ctrl_chip2A.attrs['calibrate_rx_phase_correction_en'] = True ctrl_chip2A.attrs['calibrate'] = True ctrl_chip2B.attrs['calibrate_rx_phase_correction_en'] = True ctrl_chip2B.attrs['calibrate'] = True # MCS #hmc7044_1.reg_write(0x5a,0) for k in range(12): ctrl_chip1A.attrs['multichip_sync'] = str(k) ctrl_chip1B.attrs['multichip_sync'] = str(k) #hmc7044_2.reg_write(0x5a,0) for k in range(12): ctrl_chip2A.attrs['multichip_sync'] = str(k) ctrl_chip2B.attrs['multichip_sync'] = str(k) # Enable all IQ channels v0 = rxadc1.find_channel("voltage0_i") v1 = rxadc1.find_channel("voltage0_q") v2 = rxadc1.find_channel("voltage1_i") v3 = rxadc1.find_channel("voltage1_q") v0.enabled = True v1.enabled = True v2.enabled = True v3.enabled = True v4 = rxadc2.find_channel("voltage0_i") v5 = rxadc2.find_channel("voltage0_q") v6 = rxadc2.find_channel("voltage1_i") v7 = rxadc2.find_channel("voltage1_q") v4.enabled = True v5.enabled = True v6.enabled = True v7.enabled = True # Create buffer for RX data rxbuf1 = iio.Buffer(rxadc1, buf_len, False) rxbuf2 = iio.Buffer(rxadc2, buf_len, False) # # Enable single tone DDS dds0_tx1_1 = txdac1.find_channel('altvoltage0', True) dds2_tx1_1 = txdac1.find_channel('altvoltage2', True) dds0_tx1_2 = txdac1.find_channel('altvoltage8', True) dds2_tx1_2 = txdac1.find_channel('altvoltage10', True) dds0_tx2_1 = txdac2.find_channel('altvoltage0', True) dds2_tx2_1 = txdac2.find_channel('altvoltage2', True) dds0_tx2_2 = txdac2.find_channel('altvoltage8', True) dds2_tx2_2 = txdac2.find_channel('altvoltage10', True) # Turn all others off dds1_1 = txdac1.find_channel('altvoltage1', True) dds1_1.attrs['raw'].value = str(0) dds1_1.attrs['scale'].value = str(0) for r in range(3, 16): dds1_1 = txdac1.find_channel('altvoltage' + str(r), True) dds1_1.attrs['scale'].value = str(0) dds1_1.attrs['raw'].value = str(0) dds2_1 = txdac2.find_channel('altvoltage1', True) dds2_1.attrs['raw'].value = str(0) dds2_1.attrs['scale'].value = str(0) for r in range(3, 16): dds2_1 = txdac2.find_channel('altvoltage' + str(r), True) dds2_1.attrs['scale'].value = str(0) dds2_1.attrs['raw'].value = str(0) # Set frequency of enabled DDSs dds0_tx1_1.attrs['raw'].value = str(1) dds0_tx1_1.attrs['frequency'].value = str(DDS_Freq) dds0_tx1_1.attrs['scale'].value = str(0.5) dds0_tx1_1.attrs['phase'].value = str(90000) dds2_tx1_1.attrs['raw'].value = str(1) dds2_tx1_1.attrs['frequency'].value = str(DDS_Freq) dds2_tx1_1.attrs['scale'].value = str(0.5) dds2_tx1_1.attrs['phase'].value = str(0) dds0_tx2_1.attrs['raw'].value = str(1) dds0_tx2_1.attrs['frequency'].value = str(DDS_Freq) dds0_tx2_1.attrs['scale'].value = str(0.5) dds0_tx2_1.attrs['phase'].value = str(90000) dds2_tx2_1.attrs['raw'].value = str(1) dds2_tx2_1.attrs['frequency'].value = str(DDS_Freq) dds2_tx2_1.attrs['scale'].value = str(0.5) dds2_tx2_1.attrs['phase'].value = str(0) dds0_tx1_2.attrs['raw'].value = str(1) dds0_tx1_2.attrs['frequency'].value = str(DDS_Freq) dds0_tx1_2.attrs['scale'].value = str(0.5) dds0_tx1_2.attrs['phase'].value = str(90000) dds2_tx1_2.attrs['raw'].value = str(1) dds2_tx1_2.attrs['frequency'].value = str(DDS_Freq) dds2_tx1_2.attrs['scale'].value = str(0.5) dds2_tx1_2.attrs['phase'].value = str(0) dds0_tx2_2.attrs['raw'].value = str(1) dds0_tx2_2.attrs['frequency'].value = str(DDS_Freq) dds0_tx2_2.attrs['scale'].value = str(0.5) dds0_tx2_2.attrs['phase'].value = str(90000) dds2_tx2_2.attrs['raw'].value = str(1) dds2_tx2_2.attrs['frequency'].value = str(DDS_Freq) dds2_tx2_2.attrs['scale'].value = str(0.5) dds2_tx2_2.attrs['phase'].value = str(0) # Stop continuous sysref 1 hmc7044_1_ext.reg_write(0x5, 0x2) hmc7044_1_car.reg_write(0x5, 0x42) hmc7044_1_car.reg_write(0x49, 0x0) hmc7044_1_car.reg_write(0x5a, 0x1) hmc7044_1.reg_write(0x49, 0x0) hmc7044_1.reg_write(0x5a, 0x1) hmc7044_1.reg_write(0x5, 0x43) hmc7044_1.reg_write(0x5, 0x83) # Stop continuous sysref 2 # hmc7044_2_ext.reg_write(0x5, 0x2) hmc7044_2_car.reg_write(0x5, 0x42) hmc7044_2_car.reg_write(0x49, 0x0) hmc7044_2_car.reg_write(0x5a, 0x1) hmc7044_2.reg_write(0x49, 0x0) hmc7044_2.reg_write(0x5a, 0x1) hmc7044_2.reg_write(0x5, 0x43) hmc7044_2.reg_write(0x5, 0x83) # Collect data # reals0 = np.array([]) # imags0 = np.array([]) # reals1 = np.array([]) # imags1 = np.array([]) phase_error1 = np.array([]) phase_error2 = np.array([]) phase_error12 = np.array([]) #raw_input("asd") # k = 0 # while rxadc1.reg_read(0x80000068) == 0: # rxadc1.reg_write(0x80000044, 0x8) # if (k == 50): # print("no HDL 1 sync") # break # k += 1 # k = 0 # while rxadc2.reg_read(0x80000068) == 0: # rxadc2.reg_write(0x80000044, 0x8) # if (k == 50): # print("no HDL 2 sync") # break # k += 1 for i in range(runs): k = 0 while rxadc1.reg_read(0x80000068) == 0: rxadc1.reg_write(0x80000044, 0x8) if (k == 50): print("no HDL 1 sync") break k += 1 k = 0 while rxadc2.reg_read(0x80000068) == 0: rxadc2.reg_write(0x80000044, 0x8) if (k == 50): print("no HDL 2 sync") break k += 1 hmc7044_1_ext.attrs["sysref_request"].value = str(1) rxbuf1.refill() rxbuf2.refill() #raw_input("asd") #hmc7044_1_ext.attrs["sysref_request"].value = str(1) data1 = rxbuf1.read() data2 = rxbuf2.read() x1 = np.frombuffer(data1, dtype=np.int16) x2 = np.frombuffer(data2, dtype=np.int16) # reals0 = np.append(reals0,x[::4]) # imags0 = np.append(imags0,x[1::4]) # reals1 = np.append(reals1,x[2::4]) # imags1 = np.append(imags1,x[3::4]) chan1 = x1[2::4] + 1j * x1[3::4] chan0 = x1[0::4] + 1j * x1[1::4] chan3 = x2[2::4] + 1j * x2[3::4] chan2 = x2[0::4] + 1j * x2[1::4] phase_error1 = np.append(phase_error1, measure_phase(chan0, chan1)) phase_error2 = np.append(phase_error2, measure_phase(chan2, chan3)) phase_error12 = np.append(phase_error12, measure_phase(chan0, chan2)) # # Plot # if do_plots: # plt.plot(phase_error) # # plt.plot(reals0) # # # plt.plot(imags0) # # plt.plot(reals1) # # # plt.plot(imags1) # plt.xlabel("Samples") # plt.ylabel("Amplitude [dbFS]") # plt.show() return phase_error1, phase_error2, phase_error12