Source code for pyfabil.plugins.tpm.test_generator

from __future__ import division
from builtins import range
from math import fabs, cos, sin
from pyfabil.plugins.firmwareblock import FirmwareBlock
from pyfabil.base.definitions import *
import logging
import time

__author__ = 'cbelli'


[docs] class TpmTestGenerator(FirmwareBlock): """ Test signal generator The test generator produces up to 4 signals. Each signal has an associated amplitude, that is initialized to 0 and stored internally. Specifying an amplitude of -1 (default) uses the internally stored value Methods set_tone, set_pulse_frequency, enable_prdg set the parameters for the two tones, the pulse generator and the pseudorandom white noise Each ADC channel has a settable delay, in steps of 1 sample and range of -123 to 127 samples. Delay is applied after the generator and is positive for increased delay. test_generator.set_tone(dds, frequency, ampl=-1.0, phase=0.0) dds = [0 1] DDS number frequency: in Hz ampl: -1 to keep existing, [0.0:1.0] with respect to maximum phase: in turns test_generator.set_delay(delay) delay: array[16] of [-123 to 127] in samples test_generator.disable_prdg() test_generator.enable_prdg(ampl=-1.0) ampl: -1 to keep existing, [0.0:1.0] with respect to maximum test_generator.set_pulse_frequency(freq_code, ampl=-1) freq_code: [0 to 7] selects # of pulses per frame (0.925925 kHz) 0=18 ppf, 1=12, 2=8, 3=6, 4=4, 5=3, 6=2, 7=1, ampl: -1 to keep existing, [0.0:1.0] with respect to maximum test_generator.channel_select(channel_select) channel_select: int16 with 1 bit per channel """ @compatibleboards(BoardMake.TpmBoard, BoardMake.Tpm16Board) @friendlyname('test_generator') @maxinstances(2) def __init__(self, board, fsample=800e6, **kwargs): """ TpmTestGenerator initialiser :param board: Pointer to board instance """ super(TpmTestGenerator, self).__init__(board) if 'device' not in list(kwargs.keys()): raise PluginError("TpmTestGenerator: Require a node instance") self._device = kwargs['device'] if self._device == Device.FPGA_1: self._device = 'fpga1' elif self._device == Device.FPGA_2: self._device = 'fpga2' else: raise PluginError("TpmTestGenerator: Invalid device %s" % self._device) # sampling frequency self.fsample = fsample # Cable delay self.delay = [0] * 16 # Generator parameters self.gain = [0] * 4 ############################################################################
[docs] def initialise(self): """ Initialise Test Generator""" # Load Delay self.board['%s.test_generator.delay_0' % self._device] = self.delay # Disable test input on all signals self.board['%s.test_generator.channel_select' % self._device] = 0 # Set DDS frequency and phase to zero self.set_tone(0, 0.0, 0.0) self.set_tone(1, 0.0, 0.0) # Disable PRDG, set pulse frequency to minimum, gains to 0, to minimize power self.disable_prdg() self.set_pulse_frequency(7, 0.0) self.set_delay(16 * [0]) return True
############################################################################ # Set tone frequency for DDS 0 and 1 ############################################################################
[docs] def set_tone(self, dds, frequency, ampl=-1.0, phase=0.0, timestamp=None): """ Set frequency, amplitude and phase for specified DDS Frequency in Hz, amplitude normalized to maximum (32 units), phase in turns If amplitude is negative, use last specified one """ freq_hw = int(round(frequency / self.fsample * 2 ** 31)) phase_hw = int(round(phase * 2 ** 16)) if (phase_hw < 0) | (phase_hw >= 2 ** 16): phase_hw = 0 if ampl < 0: ampl_hw = self.gain[dds & 1] else: ampl_hw = int(round(ampl * 255)) if ampl_hw > 255: ampl_hw = 255 # Disable autoload while programming self.board['%s.test_generator.control.load_dds0' % self._device] = 0 self.board['%s.test_generator.control.load_dds1' % self._device] = 0 self.board['%s.test_generator.control.trig_req' % self._device] = 0 self.board['%s.test_generator.control.trig_force' % self._device] = 0 if dds == 0: self.gain[0] = ampl_hw self.board['%s.test_generator.frequency_0' % self._device] = freq_hw self.board['%s.test_generator.phase_0' % self._device] = phase_hw self.board['%s.test_generator.gain.dds0' % self._device] = ampl_hw if dds == 1: self.gain[1] = ampl_hw self.board['%s.test_generator.frequency_1' % self._device] = freq_hw self.board['%s.test_generator.phase_1' % self._device] = phase_hw self.board['%s.test_generator.gain.dds1' % self._device] = ampl_hw # Synchronize the load operation if requested # If no timestamp is specified, load immediately if timestamp is None: self.board['%s.test_generator.control.load_dds%d' % (self._device, dds)] = 1 self.board['%s.test_generator.control.trig_force' % self._device] = 1 self.board['%s.test_generator.control.trig_force' % self._device] = 0 else: self.board['%s.test_generator.control.load_dds%d' % (self._device, dds)] = 1 self.board['%s.test_generator.timestamp_req' % self._device] = timestamp self.board['%s.test_generator.control.trig_req' % self._device] = 1 return True
############################################################################ # Set coarse zenith delay # Delay specified in integer samples, nominal is 0, range [-124:127:] ############################################################################
[docs] def set_delay(self, delay): """ Set delay for input ADC streams Delay in samples, positive delay adds delay to the signal stream """ delay_hw = [0]*len(delay) for i in range(len(delay)): del1 = delay[i] + 128 if del1 > 255: del1 = 255 if del1 < 4: del1 = 4 delay_hw[i] = del1 self.delay[i] = del1 - 128 self.board['%s.test_generator.delay_0' % self._device] = delay_hw return True
############################################################################ # Disables and enables pseudo random signal generator # Saves current setting of gain ############################################################################
[docs] def disable_prdg(self): self.board['%s.test_generator.control.load_prdg' % self._device] = 0 self.gain[2] = self.board['%s.test_generator.gain.prdg' % self._device] self.board['%s.test_generator.gain.prdg' % self._device] = 0 self.board['%s.test_generator.control.load_prdg' % self._device] = 1 self.board['%s.test_generator.control.trig_force' % self._device] = 1 self.board['%s.test_generator.control.trig_force' % self._device] = 0 return True
############################################################################
[docs] def enable_prdg(self, ampl=-1.0, timestamp=None): if ampl < 0: ampl_hw = self.gain[2] # restore old gain else: ampl_hw = int(round(ampl * 255)) if ampl_hw > 255: ampl_hw = 255 self.gain[2] = ampl_hw self.board['%s.test_generator.gain.prdg' % self._device] = ampl_hw self.board['%s.test_generator.control.load_prdg' % self._device] = 0 self.board['%s.test_generator.control.trig_force' % self._device] = 0 self.board['%s.test_generator.control.trig_req' % self._device] = 0 if timestamp == None: self.board['%s.test_generator.control.load_prdg' % self._device] = 1 self.board['%s.test_generator.control.trig_force' % self._device] = 1 self.board['%s.test_generator.control.trig_force' % self._device] = 0 else: self.board['%s.test_generator.control.load_prdg' % self._device] = 1 self.board['%s.test_generator.timestamp_req' % self._device] = timestamp self.board['%s.test_generator.control.trig_req' % self._device] = 1 return True
############################################################################ # Sets pulse generator repetition rate # Codes 0-7 correspond to period (samples) and frequency spacing of # 0: 48 16.666667 MHz # 1: 72 11.111111 MHz # 2: 108 7.407407 MHz # 3: 144 5.555555 MHz # 4: 216 3.703704 MHz # 5: 288 2.777778 MHz # 6: 432 1.851852 MHz # 7: 864 0.925925 MHz # ############################################################################
[docs] def set_pulse_frequency(self, freq_code, ampl=-1): """ Sets pulse generator repetition rate Codes 0-7 correspond to period (samples) and frequency spacing of 0: 48 16.666667 MHz 1: 72 11.111111 MHz 2: 108 7.407407 MHz 3: 144 5.555555 MHz 4: 216 3.703704 MHz 5: 288 2.777778 MHz 6: 432 1.851852 MHz 7: 864 0.925925 MHz """ self.board['%s.test_generator.control.pulse_period' % self._device] = freq_code if ampl < 0: ampl_hw = self.gain[3] else: ampl_hw = int(round(ampl * 255)) if ampl_hw > 255: ampl_hw = 255 self.gain[3] = ampl_hw self.board['%s.test_generator.gain.pulse' % self._device] = ampl_hw self.board['%s.test_generator.control.pulse_period' % self._device] = freq_code return True
############################################################################ # Selects channels substitued with test generator output # Input is 16 bit mask ############################################################################
[docs] def channel_select(self, channel_select): self.board['%s.test_generator.channel_select' % self._device] = channel_select return
[docs] def status_check(self): logging.info("TpmTestGenerator : Checking status") return Status.OK
[docs] def clean_up(self): """ Perform cleanup :return: Success """ logging.info("TpmTestGenerator : Cleaning up") return True