コード例 #1
0
ファイル: iceman.py プロジェクト: lcw86/PythonExercise
class IcemanBase(MIXBoard):
    '''
    Base class of Iceman and IcemanCompatible,Providing common Iceman methods.

    Args:
        i2c:             instance(I2C)/None,            i2c bus which is used to access CAT24C32 and NCT75.
        signal_source:   instance(MIXSignalSourceSG)/None, MIXSignalSourceSG used to control DAC output.
        range_ctrl_pin:  instance(GPIO)/None,           GPIO or Pin, which is used to control output range.
        ipcore:          instance(MIXSGT1SGR)/None,        MIXSGT1SGR which include MIXSignalSource and PLGPIO IP.
        eeprom_dev_addr: int,                           Eeprom device address.
        sensor_dev_addr: int,                           NCT75 device address.
    '''

    rpc_public_api = ['module_init', 'get_range', 'set_sampling_rate', 'output_volt', 'output_sine',
                      'output_square', 'output_triangle', 'output_sawtooth', 'output_stop'] + MIXBoard.rpc_public_api

    def __init__(self, i2c, signal_source, range_ctrl_pin, ipcore, eeprom_dev_addr, sensor_dev_addr):
        if not i2c and not signal_source and not range_ctrl_pin and not ipcore:
            self.signal_source = MIXSignalSourceSGEmulator('mix_signalsource_sg_emulator')
            self.range_ctrl_pin = GPIOEmulator('gpio_emulator')
        elif i2c and signal_source and range_ctrl_pin and not ipcore:
            if isinstance(signal_source, basestring):
                axi4_bus = AXI4LiteBus(signal_source, IcemanDef.REG_SIZE)
                self.signal_source = MIXSignalSourceSG(axi4_bus)
            else:
                self.signal_source = signal_source
            self.range_ctrl_pin = range_ctrl_pin
        elif i2c and not signal_source and ipcore:
            if isinstance(ipcore, basestring):
                axi4_bus = AXI4LiteBus(ipcore, IcemanDef.MIX_SGT1_REG_SIZE)
                use_gpio = False if range_ctrl_pin else True
                self.ipcore = MIXSGT1SGR(axi4_bus, use_gpio)
            else:
                self.ipcore = ipcore
            self.signal_source = self.ipcore.signal_source
            self.range_ctrl_pin = range_ctrl_pin or Pin(self.ipcore.gpio, IcemanDef.RANGE_CTRL_PIN)
        else:
            raise IcemanException("Please check init parameters.")
        if i2c:
            eeprom = CAT24C32(eeprom_dev_addr, i2c)
            nct75 = NCT75(sensor_dev_addr, i2c)
        else:
            eeprom = None
            nct75 = None
        super(IcemanBase, self).__init__(eeprom, nct75, cal_table=iceman_calibration, range_table=iceman_range_table)

    def module_init(self):
        '''
        init module, range ctrl pin will be set to output.

        Examples:
            iceman.module_init()

        '''
        self.load_calibration()
        self.range_ctrl_pin.set_dir('output')
        self._select_range('1V')
        self.set_sampling_rate()

    def _check_range(self, range):
        '''
        check signal range if is valid.

        Returns:
            string, convert range string to upper.

        Raise:
            IcemanException:  Parameter 'range' is invalid.

        '''
        if range.upper() == IcemanDef.RANGE_1V:
            return IcemanDef.RANGE_1V
        elif range.upper() == IcemanDef.RANGE_10V:
            return IcemanDef.RANGE_10V
        else:
            raise IcemanException("Parameter 'range' is invalid")

    def _select_range(self, range):
        '''
        Select output range.

        Args:
            range:      string, ['1V', '10V'], signal output range.

        Returns:
            string, "done", api execution successful.

        '''
        range = self._check_range(range)
        if hasattr(self, 'range') and range == self.range:
            return "done"
        if range == IcemanDef.RANGE_1V:
            self.range_ctrl_pin.set_level(0)
        else:
            self.range_ctrl_pin.set_level(1)
        self.range = range
        return "done"

    def get_range(self):
        '''
        Get current range.

        Returns:
            string, ['1V', '10V'], current range.

        '''
        return self.range

    def set_sampling_rate(self, sampling_rate=IcemanDef.SAMPLE_RATE):
        '''
        Iceman set dac sample rate.

        Args:
            sampling_rate:    float,    [5~50000000], unit Hz, default value is 50000000Hz.
        Returns:
            strings, "done", api execution successful.

        '''
        assert 5 <= sampling_rate <= 50000000
        if hasattr(self, 'sampling_rate') and sampling_rate == self.sampling_rate:
            return "done"

        self.sampling_rate = sampling_rate
        return "done"

    def output_volt(self, mvolt, range=IcemanDef.RANGE_1V):
        '''
        Output DC voltage in mV.

        Args:
            mvolt:   float, if range is 1V, -500 mV <= mvolt <= 500 mV,
                            if range is 10V, -5000 mV <= mvolt <= 5000 mV.
            range:   string, ['1V', '10V'], signal output range.

        Returns:
            string, "done", api execution successful.

        '''
        range = self._check_range(range)
        assert mvolt >= iceman_config[range]['offset']['min']
        assert mvolt <= iceman_config[range]['offset']['max']
        self.output_stop()
        self._select_range(range)
        self.signal_source.open()
        mvolt = self.calibrate('DC_{}'.format(self.range), mvolt)

        if self.range == IcemanDef.RANGE_10V:
            mvolt = mvolt * 1.0 / IcemanDef.RANGE_10V_GAIN

        # the volt should be reversed according to hardware
        mvolt = 0 - mvolt

        # get the offset scale
        mvolt = mvolt / (IcemanDef.MAX_MVPP / 2.0)

        if mvolt > IcemanDef.SIGNAL_SOURCE_SCALE_MAX:
            mvolt = IcemanDef.SIGNAL_SOURCE_SCALE_MAX
        elif mvolt < IcemanDef.SIGNAL_SOURCE_SCALE_MIN:
            mvolt = IcemanDef.SIGNAL_SOURCE_SCALE_MIN
        step = [[mvolt, mvolt, IcemanDef.AWG_DC_DURATION]]
        self.signal_source.set_signal_time(IcemanDef.OUTPUT_DURATION)
        self.signal_source.set_signal_type('AWG')
        self.signal_source.set_awg_parameter(self.sampling_rate, step)
        self.signal_source.output_signal()
        return "done"

    def output_sine(self, freq, rms, offset=0, range=IcemanDef.RANGE_1V):
        '''
        Output sine waveform with frequency, rms and offset. offset default is 0.

        Args:
            freq:    int, [1~4000000], unit Hz, output signal frequency in Hz.
            rms:     float, output signal rms. If range is 1V, 0 mVrms <= rms <= 366.1 mVrms.
                                               If range is 10V, 0 mVrms <= rms <= 3661 mVrms.
            offset:  float, signal offset voltage. If range is 1V, -500 mV <= offset <= 500 mV.
            range:   string, ['1V', '10V'], signal output range.

        Returns:
            string, "done", api execution successful.

        '''
        range = self._check_range(range)
        assert IcemanDef.FREQ_MIN <= freq <= IcemanDef.FREQ_MAX
        assert 0 <= rms <= iceman_config[range]['rms']['max']
        assert offset >= iceman_config[range]['offset']['min']
        assert offset <= iceman_config[range]['offset']['max']
        self.output_stop()
        self._select_range(range)
        self.signal_source.open()
        rms = self.calibrate('SINE_VPP_{}'.format(self.range), rms)
        offset = self.calibrate('DC_{}'.format(self.range), offset)
        if self.range == IcemanDef.RANGE_10V:
            rms /= IcemanDef.RANGE_10V_GAIN
            offset /= IcemanDef.RANGE_10V_GAIN
        vpp = 2 * math.sqrt(2) * rms
        vpp = vpp / IcemanDef.MAX_MVPP
        offset = offset / (IcemanDef.MAX_MVPP / 2.0)
        offset = -offset
        if vpp > IcemanDef.SIGNAL_SOURCE_VPP_MAX:
            vpp = IcemanDef.SIGNAL_SOURCE_SCALE_MAX
        if vpp < 0:
            vpp = 0.0
        self.signal_source.set_signal_time(IcemanDef.OUTPUT_DURATION)
        self.signal_source.set_signal_type('sine')
        self.signal_source.set_swg_paramter(self.sampling_rate, freq, vpp, 0, offset)
        self.signal_source.output_signal()
        return "done"

    def output_square(self, freq, vpp, duty, offset=0, range=IcemanDef.RANGE_1V):
        '''
        Ouptut square waveform with frequency, vpp, duty and offset. default offset is 0

        Args:
            freq:     int, [1~4000000], unit Hz, square waveform output frquency in Hz.
            vpp:      float, square waveform output vpp. If range is 1V,
                                                         0 <= vpp <= 1000 mV. If range is 10V,
                                                         0 <= vpp <= 10000 mV.
            duty:     float, [0~100], square waveform output duty.
            offset:   float, default 0,  square waveform offset voltage. If range is 1V,
                                         -500 mV <= offset <= 500 mV. If range is 10V,
                                         -5000 mV <= offset <= 5000 mV.
            range:   string, ['1V', '10V'], signal output range.

        Returns:
            string, "done", api execution successful.

        '''
        range = self._check_range(range)
        assert freq >= IcemanDef.FREQ_MIN and freq <= IcemanDef.FREQ_MAX
        assert vpp >= iceman_config[range]['vpp']['min']
        assert vpp <= iceman_config[range]['vpp']['max']
        assert offset >= iceman_config[range]['offset']['min']
        assert offset <= iceman_config[range]['offset']['max']
        assert duty >= 0 and duty <= 100

        self.output_stop()
        self._select_range(range)
        self.signal_source.open()
        vpp = self.calibrate('SQUARE_VPP_{}'.format(self.range), vpp)
        offset = self.calibrate('DC_{}'.format(self.range), offset)
        if self.range == IcemanDef.RANGE_10V:
            vpp /= IcemanDef.RANGE_10V_GAIN
            offset /= IcemanDef.RANGE_10V_GAIN

        vpp = vpp / IcemanDef.MAX_MVPP
        offset = offset / (IcemanDef.MAX_MVPP / 2.0)
        # the voltage should be reversed according to hardware
        offset = -offset
        if vpp > IcemanDef.SIGNAL_SOURCE_VPP_MAX:
            vpp = IcemanDef.SIGNAL_SOURCE_SCALE_MAX
        if vpp < 0:
            vpp = 0.0
        self.signal_source.set_signal_time(IcemanDef.OUTPUT_DURATION)
        self.signal_source.set_signal_type('square')
        self.signal_source.set_swg_paramter(self.sampling_rate, freq, vpp, 1 - duty / 100.0, offset)
        self.signal_source.output_signal()
        return "done"

    def output_triangle(self, freq, vpp, delay_ms=0, offset=0, range=IcemanDef.RANGE_1V):
        '''
        Output triangle waveform with frequency, vpp, delay_ms and offset.

        Args:
            freq:     int, [1~4000000], unit Hz, triangle waveform output frquency in Hz.
            vpp:      float, square waveform output vpp. If range is 1V,
                                                         0 <= vpp <= 1000 mV. If range is 10V,
                                                         0 <= vpp <= 10000 mV.
            delay_ms:    float, default 0, unit ms,  triangle waveform start delay time.
            offset:   float, default 0,  square waveform offset voltage. If range is 1V,
                                         -500 mV <= offset <= 500 mV. If range is 10V,
                                         -5000 mV <= offset <= 5000 mV.
            range:   string, ['1V', '10V'], signal output range.

        Returns:
            string, "done", api execution successful.

        '''
        range = self._check_range(range)
        assert IcemanDef.FREQ_MIN <= freq <= IcemanDef.FREQ_MAX
        assert vpp >= iceman_config[range]['vpp']['min']
        assert vpp <= iceman_config[range]['vpp']['max']
        assert delay_ms >= 0
        assert offset >= iceman_config[range]['offset']['min']
        assert offset <= iceman_config[range]['offset']['max']

        self.output_stop()
        self._select_range(range)
        self.signal_source.open()
        vpp = self.calibrate('TRIANGLE_VPP_{}'.format(self.range), vpp)
        offset = self.calibrate('DC_{}'.format(self.range), offset)
        if self.range == IcemanDef.RANGE_10V:
            vpp /= IcemanDef.RANGE_10V_GAIN
            offset /= IcemanDef.RANGE_10V_GAIN
        # the voltage should be reversed according to hardware
        v1 = 0 - (vpp / 2.0 + offset)
        v2 = 0 - (offset - vpp / 2.0)
        # get the period in ms
        period = 1000.0 / freq - delay_ms
        if period <= 0:
            raise IcemanException('Iceman board parameter delay_ms out of range')

        v1 = v1 / (IcemanDef.MAX_MVPP / 2.0)
        v2 = v2 / (IcemanDef.MAX_MVPP / 2.0)
        if v1 > IcemanDef.SIGNAL_SOURCE_SCALE_MAX:
            v1 = IcemanDef.SIGNAL_SOURCE_SCALE_MAX
        elif v1 < IcemanDef.SIGNAL_SOURCE_SCALE_MIN:
            v1 = IcemanDef.SIGNAL_SOURCE_SCALE_MIN
        if v2 > IcemanDef.SIGNAL_SOURCE_SCALE_MAX:
            v2 = IcemanDef.SIGNAL_SOURCE_SCALE_MAX
        elif v2 < IcemanDef.SIGNAL_SOURCE_SCALE_MIN:
            v2 = IcemanDef.SIGNAL_SOURCE_SCALE_MIN
        self.signal_source.set_signal_time(IcemanDef.OUTPUT_DURATION)
        self.signal_source.set_signal_type('AWG')

        # FPGA can resolve the minimum processing time for AWG.
        if (period / 2.0) > IcemanDef.AWG_MIN_TIME_RESOLUTION:
            wave_data = [[v2, v1, period / 2.0], [v1, v2, period / 2.0]]
        if delay_ms > IcemanDef.AWG_MIN_TIME_RESOLUTION:
            wave_data.append([v2, v2, delay_ms])
        self.signal_source.set_awg_parameter(self.sampling_rate, wave_data)
        self.signal_source.output_signal()
        return "done"

    def output_sawtooth(self, freq, vpp, trise, delay_ms=0, offset=0, range=IcemanDef.RANGE_1V):
        '''
        Output sawtooth waveform with frequency, vpp, trise, delay_ms and offset.

        Args:
            freq:     float, [1~4000000], unit Hz, sawtooth waveform output frquency in Hz.
            vpp:      float, sawtooth waveform output vpp. If range is 1V,
                                                         0 <= vpp <= 1000 mV. If range is 10V,
                                                         0 <= vpp <= 10000 mV.
            trise:    float,   [0~1000], unit ms, sawtooth waveform rise time.
            delay_ms:    float, default 0, unit ms, sawtooth waveform start delay time.
            offset:   float, default 0,  sawtooth waveform offset voltage. If range is 1V,
                                         -500 mV <= offset <= 500 mV. If range is 10V,
                                         -5000 mV <= offset <= 5000 mV.
            range:   string, ['1V', '10V'], signal output range.

        Returns:
            string, "done", api execution successful.

        '''
        range = self._check_range(range)
        assert IcemanDef.FREQ_MIN <= freq <= IcemanDef.FREQ_MAX
        assert vpp >= iceman_config[range]['vpp']['min']
        assert vpp <= iceman_config[range]['vpp']['max']
        assert 0 <= (trise + delay_ms) <= (1000 / freq)
        assert offset >= iceman_config[range]['offset']['min']
        assert offset <= iceman_config[range]['offset']['max']

        self.output_stop()
        self._select_range(range)
        self.signal_source.open()
        vpp = self.calibrate('SAWTOOTH_VPP_{}'.format(self.range), vpp)
        offset = self.calibrate('DC_{}'.format(self.range), offset)
        if self.range == IcemanDef.RANGE_10V:
            vpp /= IcemanDef.RANGE_10V_GAIN
            offset /= IcemanDef.RANGE_10V_GAIN
        # the voltage should be reversed according to hardware
        v1 = 0 - (vpp / 2.0 + offset)
        v2 = 0 - (offset - vpp / 2.0)
        # get the period in ms
        period = 1000.0 / freq - delay_ms
        if period <= 0:
            raise IcemanException('Iceman board parameter delay_ms out of range')

        v1 = v1 / (IcemanDef.MAX_MVPP / 2.0)
        v2 = v2 / (IcemanDef.MAX_MVPP / 2.0)
        if v1 > IcemanDef.SIGNAL_SOURCE_SCALE_MAX:
            v1 = IcemanDef.SIGNAL_SOURCE_SCALE_MAX
        elif v1 < IcemanDef.SIGNAL_SOURCE_SCALE_MIN:
            v1 = IcemanDef.SIGNAL_SOURCE_SCALE_MIN
        if v2 > IcemanDef.SIGNAL_SOURCE_SCALE_MAX:
            v2 = IcemanDef.SIGNAL_SOURCE_SCALE_MAX
        elif v2 < IcemanDef.SIGNAL_SOURCE_SCALE_MIN:
            v2 = IcemanDef.SIGNAL_SOURCE_SCALE_MIN
        self.signal_source.set_signal_time(IcemanDef.OUTPUT_DURATION)
        self.signal_source.set_signal_type('AWG')

        wave_data = []
        fall_edge = round(period - trise, 6)
        # FPGA can resolve the minimum processing time for AWG.
        if trise > IcemanDef.AWG_MIN_TIME_RESOLUTION:
            wave_data.append([v2, v1, trise])
        if fall_edge > IcemanDef.AWG_MIN_TIME_RESOLUTION:
            wave_data.append([v1, v2, fall_edge])
        if delay_ms > IcemanDef.AWG_MIN_TIME_RESOLUTION:
            wave_data.append([v2, v2, delay_ms])
        self.signal_source.set_awg_parameter(self.sampling_rate, wave_data)
        self.signal_source.output_signal()
        return "done"

    def output_stop(self):
        '''
        Stop output signal.
        '''
        self.signal_source.close()
        return "done"
コード例 #2
0
class MIXBMUPWMSGR(object):
    '''
    Mix BMU PWM function class

    ClassType = MIXBMUPWMSGR

    Args:
        axi4_bus:    instance(AXI4LiteBus)/string, AXI4LiteBus class intance or device path.

    Examples:
        bmu_pwm = MIXBMUPWMSGR('/dev/MIX_SignalSource_SG')

    '''

    rpc_public_api = ['signal_output', 'open', 'close']

    def __init__(self, axi4_bus):
        if isinstance(axi4_bus, basestring):
            # device path; create axi4lite instance
            self.axi4_bus = AXI4LiteBus(axi4_bus, MIXBMUPWMSGRDef.REG_SIZE)
        else:
            self.axi4_bus = axi4_bus

        axi4_gpio = AXI4LiteSubBus(self.axi4_bus,
                                   MIXBMUPWMSGRDef.MIX_GPIO_IPCORE_ADDR,
                                   MIXBMUPWMSGRDef.GPIO_REG_SIZE)
        axi4_signalsource = AXI4LiteSubBus(self.axi4_bus,
                                           MIXBMUPWMSGRDef.MIX_SS_IPCORE_ADDR,
                                           MIXBMUPWMSGRDef.SS_REG_SIZE)

        self.gpio = MIXGPIOSG(axi4_gpio)
        self.signalsource = MIXSignalSourceSG(axi4_signalsource)
        self.gpio.set_pin_dir(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT0, 'output')
        self.gpio.set_pin_dir(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT1, 'output')

    def close(self):
        '''
        Disable mix BMU PWM function class

        Examples:
            bmu_pwm.close()

        '''
        self.signalsource.close()
        self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT0, 0)
        self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT1, 0)

    def open(self):
        '''
        Enable mix BMU PWM function class

        Examples:
            bmu_pwm.open()

        '''
        self.signalsource.open()
        self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT0, 0)
        self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT1, 0)

    def signal_output(self,
                      signal_frequency,
                      square_duty,
                      signal_time=0xffffffff):
        '''
        Set mix BMU PWM parameters and output.

        Args:
            signal_frequency:   int, unit Hz,              output signal frequency.
            square_duty:        float, [0.001~0.999],      duty of square.
            signal_time:        int, unit us, signal time of signal source.

        Return:
            "done"

        '''
        assert 1 >= square_duty >= 0
        self.signal_time = signal_time
        self.signal_frequency = signal_frequency
        self.square_duty = square_duty

        if square_duty == MIXBMUPWMSGRDef.PWM_OUTPUT_LOW:
            self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT0, 0)
            self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT1, 0)
        elif square_duty == MIXBMUPWMSGRDef.PWM_OUTPUT_HIGH:
            self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT0, 0)
            self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT1, 1)
        else:
            self.gpio.set_pin(MIXBMUPWMSGRDef.CHANNEL_SELECT_BIT0, 1)
            self.signalsource.set_signal_type('square')
            self.signalsource.set_signal_time(self.signal_time)
            self.signalsource.set_swg_paramter(
                sample_rate=125000000,
                signal_frequency=self.signal_frequency,
                vpp_scale=0.5,
                square_duty=self.square_duty)
            self.signalsource.output_signal()
        return "done"
コード例 #3
0
ファイル: ad506x.py プロジェクト: lcw86/PythonExercise
class AD506x(object):
    '''
    AD506x chip function class.

    ClassType = DAC

    Args:
        dac_volt_min:     int, default 0, Dac min voltage of AD506X.
        dac_volt_max:     int, default 2048, Dac max voltage of AD506X.
        sample_rate:      int, default 200000, Sample_rate of AD506X.
        sck_speed:        int, default 10000000, Sck_speed of AD506X.
        signal_source:    instance(MIXSignalSourceSG)/string/None, dev_name of mix_signalsource_sg device,
                                                                or Class instance of mix_signalsource_sg.
        pl_spi_dac:       instance(PLSPIDAC)/string/None, dev_name of pl_spi_dac device,
                                                          Class instance of pl_spi_dac.

    Examples:
        signal_source = '/dev/MIX_Signal_Source_0'
        pl_spi_dac = '/dev/MIX_Spi_Dac_0'
        ad506x = AD506X(0, 2048, 200000, 10000000, signal_source, pl_spi_dac)

    '''
    def __init__(self,
                 dac_volt_min=0,
                 dac_volt_max=2048,
                 sample_rate=200000,
                 sck_speed=10000000,
                 signal_source=None,
                 pl_spi_dac=None):

        if signal_source is None:
            self.signal_source = MIXSignalSourceSGEmulator(
                "mix_signalsource_sg_emulator")
        elif isinstance(signal_source, basestring):
            # device path; create singla_source instance here.
            self.signal_source = MIXSignalSourceSG(signal_source)
        else:
            self.signal_source = signal_source

        if pl_spi_dac is None:
            self.pl_spi_dac = PLSPIDACEmulator('pl_spi_dac_emulator')
        elif isinstance(pl_spi_dac, basestring):
            # device path; create singla_source instance here.
            self.pl_spi_dac = PLSPIDAC(pl_spi_dac)
        else:
            self.pl_spi_dac = pl_spi_dac

        self.sample_rate = sample_rate
        self.dac_volt_min = dac_volt_min
        self.dac_volt_max = dac_volt_max
        self.resolution = None

        self.sck_speed = sck_speed
        self.pl_spi_dac.open()
        self.pl_spi_dac.dac_mode_set(0x0)
        self.pl_spi_dac.spi_sclk_frequency_set(self.sck_speed)
        self.pl_spi_dac.sample_data_set(self.sample_rate)

        # k and b values of pulse, dc_voltage and triangular wave
        self.k = (PLAD506xDef.AWG_VALUE_MAX -
                  PLAD506xDef.AWG_VALUE_MIN) / (dac_volt_max - dac_volt_min)
        self.b = PLAD506xDef.AWG_VALUE_MAX - self.k * dac_volt_max

        # k and b values of sine wave reference vpp
        self.vpp_k = (PLAD506xDef.SINE_VALUE_MAX - PLAD506xDef.SINE_VALUE_MIN
                      ) / (dac_volt_max - dac_volt_min)
        self.vpp_b = PLAD506xDef.SINE_VALUE_MAX - self.vpp_k * (dac_volt_max -
                                                                dac_volt_min)

        # k and b values of sine wave offset
        self.offset_k = (PLAD506xDef.SINE_OFFSET_MAX -
                         PLAD506xDef.SINE_OFFSET_MIN) / (dac_volt_max -
                                                         dac_volt_min)
        self.offset_b = PLAD506xDef.SINE_OFFSET_MAX - self.offset_k * dac_volt_max

    def disable_output(self):
        '''
        Disable the current waveform output function, not disable the chip

        Examples:
            ad506x.disable_output()

        '''
        self.signal_source.close()

    def sine(self,
             vpp,
             offset,
             frequency,
             output_time=PLAD506xDef.ALWAYS_OUTPUT):
        '''
        Output sine wave

        Args:
            vpp:          float, [dac_volt_min-dac_volt_max], unit mV, vpp voltage to config sine wave.
            offset:       float, offset to config sine wave.
            frequency:    float, frequency to config sine wave.
            output_time:  int, unit us, default 0xFFFFFF, output time of pulse wave.

        Examples:
            ad506x.sine(2000, 1, 1000, 10000)

        '''
        assert self.dac_volt_min <= vpp <= self.dac_volt_max
        vpp_scale = self.vpp_k * vpp + self.vpp_b
        offset_volt = self.offset_k * offset + self.offset_b

        self.signal_source.close()
        self.signal_source.set_signal_time(output_time)
        self.signal_source.set_signal_type('sine')
        # 0.5 is square_duty(float): duty of square
        self.signal_source.set_swg_paramter(self.sample_rate, frequency,
                                            vpp_scale, 0.5, offset_volt)
        self.signal_source.open()
        self.signal_source.output_signal()

    def output_volt_dc(self, channel, volt):
        '''
        Output dc_voltage wave

        Args:
            channel:   int, [0], channel must be 0.
            volt:      float, voltage reference to config dc_voltage wave.

        Examples:
            ad506x.output_volt_dc(0, 2000)

        '''
        assert channel == 0
        output_time = PLAD506xDef.ALWAYS_OUTPUT
        start_volt = self.k * volt + self.b
        stop_volt = start_volt
        self.signal_source.close()
        self.signal_source.set_signal_type('AWG')
        # 0.5 is duration time
        self.signal_source.set_awg_parameter(self.sample_rate,
                                             [(start_volt, stop_volt, 0.5)])
        self.signal_source.set_signal_time(output_time)
        self.signal_source.open()
        self.signal_source.output_signal()

    def triangle(self,
                 v1,
                 v2,
                 triangle_width,
                 period,
                 output_time=PLAD506xDef.ALWAYS_OUTPUT):
        '''
        Output triangle wave

        Args:
            v1:             float, Max voltage or min voltage, if v1>v2, the wave starts at v1 to v2.
            v2:             float, Max voltage or min voltage, if v2>v1, the wave starts at v2 to v1.
            triangle_width: float, Triangle_width to triangle wave.
            period:         float, Triangle_width to triangle wave.
            output_time:    int, unit us, default 0xFFFFFF, output time of pulse wave.

        Examples:
                   ad506x.triangle(1000, 2000, 100, 100, 10000)

        '''

        v1 = self.k * v1 + self.b
        v2 = self.k * v2 + self.b
        self.signal_source.close()
        self.signal_source.set_signal_type('AWG')
        if v1 > v2:
            self.signal_source.set_awg_parameter(
                self.sample_rate, [(v1, v2, triangle_width / 2),
                                   (v2, v2, period - triangle_width),
                                   (v2, v1, triangle_width / 2)])
        else:
            self.signal_source.set_awg_parameter(
                self.sample_rate, [(v1, v2, triangle_width / 2),
                                   (v2, v1, triangle_width / 2),
                                   (v1, v1, period - triangle_width)])

        self.signal_source.set_signal_time(output_time)
        self.signal_source.open()
        self.signal_source.output_signal()

    def pulse(self,
              v1,
              v2,
              edge_width,
              pulse_width,
              period,
              output_time=PLAD506xDef.ALWAYS_OUTPUT):
        '''
        Output pulse wave

        Args:
            v1:             float, Max voltage or min voltage, if v1>v2, the wave starts at v1 to v2.
            v2:             float, Max voltage or min voltage, if v2>v1, the wave starts at v2 to v1.
            edge_width:     float, Edge width of pulse wave.
            pulse_width:    float, Pulse width of pulse wave.
            period:         float, Period of pulse wave.
            output_time:    int, unit us, default 0xFFFFFF, output time of pulse wave.

        Examples:
                   ad506x.pulse(1000, 2000, 1, 10, 100, 10000)

        '''

        v1 = self.k * v1 + self.b
        v2 = self.k * v2 + self.b

        self.signal_source.close()
        self.signal_source.set_signal_type('AWG')
        if v1 > v2:
            self.signal_source.set_awg_parameter(
                self.sample_rate,
                [(v1, v1, pulse_width), (v1, v2, edge_width),
                 (v2, v2, period - pulse_width - 2 * edge_width),
                 (v2, v1, edge_width)])
        else:
            self.signal_source.set_awg_parameter(
                self.sample_rate,
                [(v1, v1, period - pulse_width - 2 * edge_width),
                 (v1, v2, edge_width), (v2, v2, pulse_width),
                 (v2, v1, edge_width)])

        self.signal_source.set_signal_time(output_time)
        self.signal_source.open()
        self.signal_source.output_signal()
コード例 #4
0
class MIXAUT1SGR(object):
    '''
    MIXAUT1SGR aggregated IPcore has 3 child IP, MIXFftAnalyzerSG, MIXSignalSourceSG, MIXGPIOSG.

    ClassType = MIXAUT1SGR

    Args:
        axi4_bus:            instance(AXI4LiteBus)/string, axi4lite instance or dev path.
        fft_data_cnt:        int,    get fft absolute data count, if not give, with get count from register.

    Examples:
        mix_aut1 = MIXAUT1SGR('/dev/MIX_AUT1_x')

    '''

    rpc_public_api = [
        'reset_adc', 'reset_dac', 'enable_rx', 'disable_rx', 'enable_tx',
        'disable_tx', 'enable_upload', 'disable_upload', 'measure',
        'enable_output', 'disable_output'
    ]

    def __init__(self, axi4_bus, fft_data_cnt=None):
        if isinstance(axi4_bus, basestring):
            # device path; create axi4lite instance
            self.axi4_bus = AXI4LiteBus(axi4_bus, MIXAUT1SGRDef.REG_SIZE)
        else:
            self.axi4_bus = axi4_bus

        if self.axi4_bus is None:
            self.analyzer = MIXFftAnalyzerSGEmulator(
                'mix_fftanalyzer_sg_emulator')
            self.signal_source = MIXSignalSourceSGEmulator(
                "mix_signalsource_sg_emulator")
            self.gpio = MIXGPIOSGEmulator("mix_gpio_sg_emulator", 256)
        else:
            self.fft_analyzer_axi4_bus = AXI4LiteSubBus(
                self.axi4_bus, MIXAUT1SGRDef.MIX_FFT_ANAYLZER_IPCORE_ADDR,
                MIXAUT1SGRDef.MIX_FFT_REG_SIZE)
            self.analyzer = MIXFftAnalyzerSG(self.fft_analyzer_axi4_bus,
                                             fft_data_cnt)

            self.signal_source_axi4_bus = AXI4LiteSubBus(
                self.axi4_bus, MIXAUT1SGRDef.MIX_SIGNAL_SOURCE_IPCORE_ADDR,
                MIXAUT1SGRDef.MIX_SIGNAL_SOURCE_REG_SIZE)
            self.signal_source = MIXSignalSourceSG(self.signal_source_axi4_bus)

            self.gpio_axi4_bus = AXI4LiteSubBus(
                self.axi4_bus, MIXAUT1SGRDef.MIX_GPIO_IPCORE_ADDR,
                MIXAUT1SGRDef.MIX_GPIO_REG_SIZE)
            self.gpio = MIXGPIOSG(self.gpio_axi4_bus)
        self.adc_rst_pin = Pin(self.gpio, MIXAUT1SGRDef.ADC_RESET_PIN)
        self.i2s_rx_en_pin = Pin(self.gpio, MIXAUT1SGRDef.I2S_RX_EN_PIN)
        self.dac_rst_pin = Pin(self.gpio, MIXAUT1SGRDef.DAC_RESET_PIN)
        self.i2s_tx_en_pin = Pin(self.gpio, MIXAUT1SGRDef.I2S_TX_EN_PIN)

    def reset_adc(self, delay_ms):
        '''
        Reset ADC.

        Args:
            delay_ms:   int, unit ms, reset time in ms

        Returns:
            "done"

        '''
        self.adc_rst_pin.set_level(0)
        time.sleep(delay_ms / 1000.0)
        self.adc_rst_pin.set_level(1)
        return "done"

    def reset_dac(self, delay_ms):
        '''
        Reset DAC.

        Args:
            delay_ms:   int, unit ms, reset time in ms

        Returns:
            "done"

        '''
        self.dac_rst_pin.set_level(0)
        time.sleep(delay_ms / 1000.0)
        self.dac_rst_pin.set_level(1)
        return "done"

    def enable_rx(self):
        '''
        Enable I2S RX
        '''
        self.i2s_rx_en_pin.set_level(1)
        return "done"

    def disable_rx(self):
        '''
        Disable I2S RX
        '''
        self.i2s_rx_en_pin.set_level(0)
        return "done"

    def enable_tx(self):
        '''
        Enable I2S TX
        '''
        self.i2s_tx_en_pin.set_level(1)
        return "done"

    def disable_tx(self):
        '''
        Disable I2S TX
        '''
        self.i2s_tx_en_pin.set_level(0)
        return "done"

    def enable_upload(self):
        '''
        Enable FFT data upload

        Returns:
            string, "done", api execution successful.

        '''
        self.analyzer.enable_upload()
        return "done"

    def disable_upload(self):
        '''
        Disable FFT data upload

        Returns:
            string, "done", api execution successful.

        '''
        self.analyzer.disable_upload()
        return "done"

    def measure(self,
                sampling_rate,
                decimation_type,
                bandwidth_hz='auto',
                harmonic_num=None,
                freq_point=None):
        '''
        Measure signal's freq, vpp, THD+N, THD.

        Args:
            sample_rate:     int, Sample rate of your ADC device, unit is Hz. Eg. 192000.
            decimation_type: int, [1~255],    Decimation for FPGA to get datas. If decimation is 0xFF, FPGA will
                                              choose one suitable number.
            bandwidth:       int/string,       FFT calculation bandwidth limit, must smaller than half of sample_rate,
                                               unit is Hz. Eg. 20000. If 'auto' given, bandwidth will be automatically
                                               adjust based on base frequency.
            harmonic_count:  int/None, [1~10]  The harmonic count of signal, default is None will not do calculate.
            freq_point:      int/None,         Specified frequency for calculating amplitude at this special frequency,
                                               default is None will not do this.

        Returns:
            dict, {'vpp': value, 'freq': value, 'thd': value, 'thdn': value),
                  dict with vpp, freq, thd, thdn.

        Examples:
            result = aut1.measure(48000, 5, 0xff)
            print(result['frequency'], result['vpp'], ['thdn'], ['thd'])

        '''
        self.analyzer.disable()
        self.analyzer.enable()
        self.analyzer.analyze_config(sampling_rate, decimation_type,
                                     bandwidth_hz, harmonic_num, freq_point)
        self.analyzer.analyze()
        result = dict()
        result["vpp"] = self.analyzer.get_vpp()
        result["freq"] = self.analyzer.get_frequency()
        result["thd"] = self.analyzer.get_thd()
        result["thdn"] = self.analyzer.get_thdn()

        return result

    def enable_output(self, sampling_rate, freq, vpp):
        '''
        Enable signal source output

        Args:
            sampling_rate:  int, in SPS, DAC sampling rate.
            freq:           int, unit Hz, Ouput signal's frequency.
            vpp:            float, [0.000~0.999], output signal vpp scale.

        Returns:
            string, "done", api execution successful.

        Examples:
            aut1.enable_output(10000, 500)

        '''
        self.signal_source.open()

        self.signal_source.set_signal_type(MIXAUT1SGRDef.OUTPUT_TYPE)
        self.signal_source.set_signal_time(MIXAUT1SGRDef.ALWAYS_OUTPUT)
        self.signal_source.set_swg_paramter(sampling_rate, freq, vpp,
                                            MIXAUT1SGRDef.OUTPUT_DUTY)
        self.signal_source.output_signal()
        return "done"

    def disable_output(self):
        '''
        Disable signal source output
        '''
        self.signal_source.close()
        return "done"