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"
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"
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()
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"