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, MIXMagneto002SGRDef.REG_SIZE) else: self.axi4_bus = axi4_bus self.fft_analyzer_axi4_bus = AXI4LiteSubBus( self.axi4_bus, MIXMagneto002SGRDef.MIX_FFT_ANAYLZER_IPCORE_ADDR, MIXMagneto002SGRDef.MIX_FFT_REG_SIZE) self.gpio_axi4_bus = AXI4LiteSubBus( self.axi4_bus, MIXMagneto002SGRDef.MIX_GPIO_IPCORE_ADDR, MIXMagneto002SGRDef.MIX_GPIO_REG_SIZE) self.gpio = MIXGPIOSG(self.gpio_axi4_bus) self.i2s_conf_0 = Pin(self.gpio, MIXMagneto002SGRDef.I2S_CONF0_BIT) self.i2s_conf_1 = Pin(self.gpio, MIXMagneto002SGRDef.I2S_CONF1_BIT) self.cs5361_ovfl = Pin(self.gpio, MIXMagneto002SGRDef.CS5361_OVFL_BIT) self.cs5361_rst = Pin(self.gpio, MIXMagneto002SGRDef.CS5361_RST_BIT) self.i2s_en = Pin(self.gpio, MIXMagneto002SGRDef.I2S_EN_BIT) self.analyzer = MIXFftAnalyzerSG(self.fft_analyzer_axi4_bus, fft_data_cnt) self.reset()
def create_dazzler_dbg(i2s_rx_en_pin, adc_rst_pin, gpio_dev, i2s_tx_en_pin, dac_rst_pin, i2c_dev, mix_aut1_dev): dazzler_dbg = DazzlerDebuger() if utility.is_pl_device(i2c_dev): axi4_bus = AXI4LiteBus(i2c_dev, 256) i2c_bus = MIXI2CSG(axi4_bus) else: i2c_bus = I2C(i2c_dev) axi4 = AXI4LiteBus(mix_aut1_dev, 0x8000) mix_aut1 = MIXAUT1SGR(axi4) if gpio_dev != "": axi4 = AXI4LiteBus(gpio_dev, 256) gpio = MIXGPIOSG(axi4) analyzer_rst = Pin(gpio, adc_rst_pin) analyzer_en = Pin(gpio, i2s_rx_en_pin) signal_source_rst = Pin(gpio, dac_rst_pin) signal_source_en = Pin(gpio, i2s_tx_en_pin) dazzler_dbg.audio = Audio001004(i2c=i2c_bus, adc_rst_pin=analyzer_rst, i2s_rx_en_pin=analyzer_en, dac_rst_pin=signal_source_rst, i2s_tx_en_pin=signal_source_en, ipcore=mix_aut1) else: dazzler_dbg.audio = Audio001004(i2c=i2c_bus, ipcore=mix_aut1) return dazzler_dbg
def __init__(self, i2c, ipcore, dma=None, left_ch_id=None, right_ch_id=None, dma_mem_size=1): super(Audio005002, self).__init__(i2c, ipcore) self.ram_signal = self.ipcore.ram_signal self.audio_cache = self.ipcore.audio_cache self.ram_out_pin = Pin(self.ipcore.gpio, Audio005002Def.RAM_OUT_PIN) self.adc_sample_rate = Audio005002Def.DEF_SAMPLING_RATE self.dac_sample_rate = Audio005002Def.AUDIO_SAMPLING_RATE self.vref = [ Audio005002Def.ANALYZER_2V_VOLT, Audio005002Def.ANALYZER_2V_VOLT ] self.input_enable = [False, False] self.output_enable = False self.model = Audio005002Def.AUDIO005002_CONFIG self.dma = dma if self.dma is not None: self.left_ch_id = left_ch_id self.right_ch_id = right_ch_id self.dma_mem_size = dma_mem_size if self.left_ch_id is None or self.right_ch_id is None or self.dma_mem_size is None: raise Audio005002Exception("dma parameter error")
def __init__(self, i2c, ipcore, range_table=starlordii_range_table): self.eeprom = CAT24C32(Audio005Def.EEPROM_I2C_ADDR, i2c) self.nct75 = NCT75(Audio005Def.TEMP_I2C_ADDR, i2c) self.pca9536 = PCA9536(Audio005Def.PCA9536_DEV_ADDR, i2c) if isinstance(ipcore, basestring): ipcore = MIXAudio005SGR(ipcore) self.ipcore = ipcore self.analyzer = self.ipcore.analyzer self.signal_source = self.ipcore.signal_source self.adc_rst_pin = Pin(self.ipcore.gpio, Audio005Def.ADC_RESET_PIN) self.i2s_rx_en_pin = Pin(self.ipcore.gpio, Audio005Def.I2S_RX_EN_PIN) self.dac_rst_pin = Pin(self.ipcore.gpio, Audio005Def.DAC_RESET_PIN) self.i2s_tx_en_pin = Pin(self.ipcore.gpio, Audio005Def.I2S_TX_EN_PIN) self.i2s_ch_select = [ Pin(self.ipcore.gpio, Audio005Def.I2S_CH_SELECT_2), Pin(self.ipcore.gpio, Audio005Def.I2S_CH_SELECT_3) ] super(Audio005Base, self).__init__(self.eeprom, self.nct75, range_table=range_table) self.is_enable_upload = False
def create_wolverine_dbg(ad7175_bus_name, vref, i2c_bus0_name, i2c_bus1_name, i2c_dev_addr1, range_sel_bit, meter_sel_bit, ip_dev_name): if ad7175_bus_name == '': ad7175 = None else: axi4_bus = AXI4LiteBus(ad7175_bus_name, 8192) ad7175 = MIXAd7175SG(axi4_bus, vref) if i2c_bus0_name == '': i2c_bus0 = None else: if utility.is_pl_device(i2c_bus0_name): axi4_bus = AXI4LiteBus(i2c_bus0_name, 256) i2c_bus0 = MIXI2CSG(axi4_bus) else: i2c_bus0 = I2C(i2c_bus0_name) if i2c_bus1_name == '': cat9555 = None else: if utility.is_pl_device(i2c_bus1_name): axi4_bus = AXI4LiteBus(i2c_bus1_name, 256) i2c_bus1 = MIXI2CSG(axi4_bus) else: i2c_bus1 = I2C(i2c_bus1_name) cat9555 = CAT9555(i2c_dev_addr1, i2c_bus1) if ip_dev_name == '': ipcore = None else: axi4_bus = AXI4LiteBus(ip_dev_name, 0x8000) ipcore = MIXDAQT1SGR(axi4_bus, ad717x_chip='AD7175', use_spi=False, use_gpio=True) if range_sel_bit == '': range_sel_bit = None else: range_sel_bit = int(range_sel_bit) if meter_sel_bit == '': meter_sel_bit = None else: meter_sel_bit = int(meter_sel_bit) wolverine_dbg = WolverineDebugger( Wolverine(i2c_bus0, ad7175, Pin(cat9555, range_sel_bit), Pin(cat9555, meter_sel_bit), ipcore)) return wolverine_dbg
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 __init__(self, firmware_path, pl_uart_drv_ko_file, i2c, pull_up_pin, pull_down_pin, tx_en_pin, removal_det_pin, connect_det_pin, a0_pin, a1_pin, a2_pin, elaod_en_pin, eeprom_devaddr, gpio): self.path = firmware_path self.process = None self.pl_uart_drv_ko_file = pl_uart_drv_ko_file if (firmware_path == '' and pl_uart_drv_ko_file == '' and i2c is None and pull_up_pin is None and pull_down_pin is None and tx_en_pin is None and removal_det_pin is None and connect_det_pin is None): self.eeprom = EepromEmulator('eeprom_emulator') self.pull_up_pin = GPIOEmulator('pull_up_pin') self.pull_down_pin = GPIOEmulator('pull_down_pin') self.tx_en_pin = GPIOEmulator('tx_en_pin') self.removal_det_pin = GPIOEmulator('removal_det_pin') self.connect_det_pin = GPIOEmulator('connect_det_pin') elif (firmware_path != '' and pl_uart_drv_ko_file != '' and i2c is not None and pull_up_pin is not None and pull_down_pin is not None and tx_en_pin is not None and removal_det_pin is not None and connect_det_pin is not None): self.eeprom = CAT24C02(eeprom_devaddr, i2c) self.pull_up_pin = pull_up_pin self.pull_down_pin = pull_down_pin self.tx_en_pin = tx_en_pin self.removal_det_pin = removal_det_pin self.connect_det_pin = connect_det_pin else: raise DarkBeastException( '__init__ error! Please check the parameters!') self.gpio = gpio if (a0_pin is None and a1_pin is None and a2_pin is None and elaod_en_pin is None): self.a0_pin = Pin(None, DarkBeastDef.A0_PIN_ID) self.a1_pin = Pin(None, DarkBeastDef.A1_PIN_ID) self.a2_pin = Pin(None, DarkBeastDef.A2_PIN_ID) self.elaod_en_pin = Pin(None, DarkBeastDef.ELAOD_EN_PIN_ID) elif (a0_pin is not None and a1_pin is not None and a2_pin is not None and elaod_en_pin is not None): self.a0_pin = a0_pin self.a1_pin = a1_pin self.a2_pin = a2_pin self.elaod_en_pin = elaod_en_pin else: raise DarkBeastException( '__init__ error! Please check the parameters!') super(DarkBeastBase, self).__init__(self.eeprom, None) self.pin_def = { 'PULL_UP': self.pull_up_pin, 'PULL_DOWN': self.pull_down_pin, 'TX_EN': self.tx_en_pin, 'REMOVAL_DETECTION': self.removal_det_pin, 'CONNECT_DETECTION': self.connect_det_pin, 'A0': self.a0_pin, 'A1': self.a1_pin, 'A2': self.a2_pin, 'ELAOD_EN': self.elaod_en_pin }
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 create_ad9102_dbg(spi_bus_name, cs_ctrl=None, cs_chip=None, cs_addr=None, cs_i2c=None): ad9102_dbg = AD9102Debuger() if spi_bus_name == '': spi_bus = None else: axi4_bus = AXI4LiteBus(spi_bus_name, PLSPIDef.REG_SIZE) spi_bus = MIXQSPISG(axi4_bus) spi_bus.set_mode('MODE3') spi_bus.set_speed(800000) if cs_ctrl is not None: cs_chip = str(cs_chip) if '0x' in cs_addr: cs_addr = int(cs_addr, 16) else: cs_addr = int(cs_addr) cs_i2c = str(cs_i2c) cs_i2c = I2C(cs_i2c) exec('from ..ic.{} import {}'.format(cs_chip.lower(), cs_chip.upper())) cs_chip = eval(cs_chip.upper())(cs_addr, cs_i2c) cs = Pin(cs_chip, int(cs_ctrl)) else: cs = None ad9102_dbg.ad9102 = AD9102(spi_bus, cs=cs) return ad9102_dbg
def create_dazzler_dbg(fftrt_dev, i2s_rx_en_pin, adc_rst_pin, gpio_dev, signal_source_dev, i2s_tx_en_pin, dac_rst_pin, i2c_dev, mix_aut1_dev): dazzler_dbg = DazzlerDebuger() if i2c_dev != '': if utility.is_pl_device(i2c_dev): axi4_bus = AXI4LiteBus(i2c_dev, 256) i2c_bus = MIXI2CSG(axi4_bus) else: i2c_bus = I2C(i2c_dev) else: i2c_bus = None if mix_aut1_dev != '': axi4 = AXI4LiteBus(mix_aut1_dev, 0x8000) mix_aut1 = MIXAUT1SGR(axi4) dazzler_dbg.audio = Dazzler(i2c_bus, ip=mix_aut1) else: axi4 = AXI4LiteBus(fftrt_dev, 256) analyzer = MIXFftAnalyzerSG(axi4) axi4 = AXI4LiteBus(signal_source_dev, 256) signal_source = MIXSignalSourceSG(axi4) axi4 = AXI4LiteBus(gpio_dev, 256) gpio = MIXGPIOSG(axi4) analyzer_rst = Pin(gpio, adc_rst_pin) analyzer_en = Pin(gpio, i2s_rx_en_pin) signal_source_rst = Pin(gpio, dac_rst_pin) signal_source_en = Pin(gpio, i2s_tx_en_pin) dazzler_dbg.audio = Dazzler(i2c_bus, analyzer=analyzer, signal_source=signal_source, adc_rst_pin=analyzer_rst, i2s_rx_en_pin=analyzer_en, dac_rst_pin=signal_source_rst, i2s_tx_en_pin=signal_source_en, ip=mix_aut1) return dazzler_dbg
def create_dbg(file, uart, i2c_bus_name, plgpio, pull_up_pin_num, pull_down_pin_num, tx_en_pin_num, removal_det_pin_num, connect_det_pin_num, a0_pin_id, a1_pin_id, a2_pin_id, elaod_en_pin_id): dbg = DarkBeastDebuger() firmware_path = file pl_uart_drv_ko_file = uart if i2c_bus_name == '': i2c_bus = None else: if utility.is_pl_device(i2c_bus_name): axi4_bus = AXI4LiteBus(i2c_bus_name, 256) i2c_bus = MIXI2CSG(axi4_bus) else: i2c_bus = I2C(i2c_bus_name) if plgpio == '': gpio = None else: axi4_bus = AXI4LiteBus(plgpio, 256) gpio = MIXGPIOSG(axi4_bus) pull_up_pin = GPIO(int(pull_up_pin_num)) pull_down_pin = GPIO(int(pull_down_pin_num)) tx_en_pin = GPIO(int(tx_en_pin_num)) removal_det_pin = GPIO(int(removal_det_pin_num)) connect_det_pin = GPIO(int(connect_det_pin_num)) cat9555 = CAT9555(0x20, i2c_bus) a0_pin = Pin(cat9555, a0_pin_id) a1_pin = Pin(cat9555, a1_pin_id) a2_pin = Pin(cat9555, a2_pin_id) elaod_en_pin = Pin(cat9555, elaod_en_pin_id) dbg.darkbeast = DarkBeast(firmware_path, pl_uart_drv_ko_file, i2c_bus, gpio, pull_up_pin, pull_down_pin, tx_en_pin, removal_det_pin, connect_det_pin, a0_pin, a1_pin, a2_pin, elaod_en_pin) return dbg
def create_negasonic_dbg(fftrt_dev, i2s_rx_en_pin, adc_rst_pin, gpio_dev, signal_source_dev, i2s_tx_en_pin, dac_rst_pin, i2c_dev, mix_aut1_dev): audio002002_dbg = NegasonicDebuger() if utility.is_pl_device(i2c_dev): axi4_bus = AXI4LiteBus(i2c_dev, 256) i2c_bus = MIXI2CSG(axi4_bus) else: i2c_bus = I2C(i2c_dev) if mix_aut1_dev != '': axi4 = AXI4LiteBus(mix_aut1_dev, 0x8000) mix_aut1 = MIXAUT1(axi4) audio002002_dbg.audio = Negasonic(i2c_bus, ip=mix_aut1) else: axi4 = AXI4LiteBus(fftrt_dev, 256) analyzer = MIXFftAnalyzerSG(axi4) axi4 = AXI4LiteBus(signal_source_dev, 256) signal_source = MIXSignalSourceSG(axi4) axi4 = AXI4LiteBus(gpio_dev, 256) gpio = MIXGPIOSG(axi4) analyzer_rst = Pin(gpio, adc_rst_pin) analyzer_en = Pin(gpio, i2s_rx_en_pin) signal_source_rst = Pin(gpio, dac_rst_pin) signal_source_en = Pin(gpio, i2s_tx_en_pin) audio002002_dbg.audio = Negasonic(i2c_bus, analyzer=analyzer, signal_sourc=signal_source, analyzer_rst=analyzer_rst, analyzer_en=analyzer_en, signal_source_rst=signal_source_rst, signal_source_en=signal_source_en) return audio002002_dbg
def create_se2300_dbg(gpio_device, i2c_bus_1, i2c_bus_2, ps_ipcore, trigger_ipcore): se2300_dbg = Se2300ps01pcbDebuger() if gpio_device == '': gpio = None else: axi4_bus = AXI4LiteBus(gpio_device, 256) gpio = MIXGPIOSG(axi4_bus) ads5231_oea = Pin(gpio, 1) data_upload = Pin(gpio, 4) if i2c_bus_1 == '': iic_1 = None else: axi4_bus = AXI4LiteBus(i2c_bus_1, 256) iic_1 = MIXI2CSG(axi4_bus) if i2c_bus_2 == '': iic_2 = None else: axi4_bus = AXI4LiteBus(i2c_bus_2, 256) iic_2 = MIXI2CSG(axi4_bus) if ps_ipcore == '': power_sequency = None else: axi4_bus = AXI4LiteBus(ps_ipcore, 1024) power_sequency = MIXPowerSequenceSG(axi4_bus) if trigger_ipcore == '': trigger_core = None else: axi4_bus = AXI4LiteBus(trigger_ipcore, 1024) trigger_core = MIXPowerSequenceSG(axi4_bus) se2300_dbg.se2300 = SE2300PS01PCB(ads5231_oea, data_upload, iic_1, iic_2, power_sequency, trigger_core) return se2300_dbg
def __init__(self, i2c, adc_rst_pin=None, i2s_rx_en_pin=None, dac_rst_pin=None, i2s_tx_en_pin=None, sample_rate=192000, ipcore=None): assert sample_rate > 0 and sample_rate <= DazzlerDef.MAX_SAMPLING_RATE self.eeprom = CAT24C32(DazzlerDef.EEPROM_I2C_ADDR, i2c) self.nct75 = NCT75(DazzlerDef.SENSOR_I2C_ADDR, i2c) super(DazzlerBase, self).__init__(self.eeprom, self.nct75, range_table=dazzler_range_table) if ipcore: if isinstance(ipcore, basestring): axi4 = AXI4LiteBus(ipcore, DazzlerDef.MIX_AUT1_REG_SIZE) self.ip = MIXAUT1SGR(axi4) else: self.ip = ipcore self.analyzer = self.ip.analyzer self.signal_source = self.ip.signal_source self.adc_rst_pin = adc_rst_pin or Pin(self.ip.gpio, DazzlerDef.ADC_RESET_PIN) self.i2s_rx_en_pin = i2s_rx_en_pin or Pin(self.ip.gpio, DazzlerDef.I2S_RX_EN_PIN) self.dac_rst_pin = dac_rst_pin or Pin(self.ip.gpio, DazzlerDef.DAC_RESET_PIN) self.i2s_tx_en_pin = i2s_tx_en_pin or Pin(self.ip.gpio, DazzlerDef.I2S_TX_EN_PIN) else: raise DazzlerException("parameter 'ipcore' can not be None") self.sample_rate = sample_rate
def __init__(self, i2c, ad7175=None, ipcore=None): self.eeprom = CAT24C32(Scope002006Def.EEPROM_DEV_ADDR, i2c) self.sensor = NCT75(Scope002006Def.SENSOR_DEV_ADDR, i2c) if ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, Scope002006Def.MIX_DAQT1_REG_SIZE) ipcore = MIXDAQT1SGR( axi4_bus, 'AD7175', ad717x_mvref=Scope002006Def.AD7175_MVREF, code_polar=Scope002006Def.AD7175_CODE_POLAR, reference=Scope002006Def.AD7175_REFERENCE_SOURCE, buffer_flag=Scope002006Def.AD7175_BUFFER_FLAG, clock=Scope002006Def.AD7175_CLOCK, use_spi=False, use_gpio=True) ipcore.ad717x.config = {"ch0": {"P": "AIN0", "N": "AIN1"}} self.ad7175 = ipcore.ad717x self.gpio = ipcore.gpio self.tag_pins = [ Pin(self.gpio, Scope002006Def.TAG_BASE_PIN + x, Scope002006Def.GPIO_OUTPUT_DIR) for x in xrange(4) ] elif ad7175: if isinstance(ad7175, basestring): axi4_bus = AXI4LiteBus(ad7175, Scope002006Def.AD7175_REG_SIZE) ad7175 = MIXAd7175SG( axi4_bus, mvref=Scope002006Def.AD7175_MVREF, code_polar=Scope002006Def.AD7175_CODE_POLAR, reference=Scope002006Def.AD7175_REFERENCE_SOURCE, buffer_flag=Scope002006Def.AD7175_BUFFER_FLAG, clock=Scope002006Def.AD7175_CLOCK) ad7175.config = {"ch0": {"P": "AIN0", "N": "AIN1"}} self.ad7175 = ad7175 else: raise Scope002006Exception('Use one of aggregated IP or AD717X') super(Scope002006, self).__init__(self.eeprom, self.sensor, range_table=scope002006_range_table)
def __init__(self, i2c, ad7175=None, range_ctrl_pin=None, meter_ctrl_pin=None, ipcore=None): if ad7175 and range_ctrl_pin and meter_ctrl_pin and not ipcore: if isinstance(ad7175, basestring): axi4 = AXI4LiteBus(ad7175, WolverineDef.PLAD7175_REG_SIZE) self.ad7175 = MIXAd7175SG(axi4, mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK) else: self.ad7175 = ad7175 self.range_ctrl_pin = range_ctrl_pin self.meter_ctrl_pin = meter_ctrl_pin elif not ad7175 and not range_ctrl_pin and not meter_ctrl_pin and ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineDef.MIX_DAQT1_REG_SIZE) self.ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK, use_gpio=True) else: self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x gpio = self.ipcore.gpio self.range_ctrl_pin = Pin(gpio, WolverineDef.RANGE_SEL_BIT) self.meter_ctrl_pin = Pin(gpio, WolverineDef.METER_SEL_BIT) self.tag_pins = [ Pin(gpio, WolverineDef.TAG_BASE_PIN + x, WolverineDef.GPIO_OUTPUT_DIR) for x in range(4) ] elif not ad7175 and range_ctrl_pin and meter_ctrl_pin and ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineDef.MIX_DAQT1_REG_SIZE) self.ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK, use_gpio=True) else: self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x self.range_ctrl_pin = range_ctrl_pin self.meter_ctrl_pin = meter_ctrl_pin gpio = self.ipcore.gpio self.tag_pins = [ Pin(gpio, WolverineDef.TAG_BASE_PIN + x, WolverineDef.GPIO_OUTPUT_DIR) for x in range(4) ] else: raise WolverineException("Invalid parameter, please check") eeprom = CAT24C32(WolverineDef.EEPROM_DEV_ADDR, i2c) nct75 = NCT75(WolverineDef.NCT75_DEV_ADDR, i2c) super(Wolverine, self).__init__(eeprom, nct75, range_table=wolverine_range_table) self.channel_path = {'range_sel_bit': self.range_ctrl_pin, 'meter_sel_bit': self.meter_ctrl_pin} self.measure_path = dict() self.measure_path['range'] = WolverineDef.VOLT_5V
def create_elektra_dbg(i2c_name, spi_name, ad760x_name, gpio_id, volt_ch_1, volt_ch_2, curr_ch_1, curr_ch_2): scope_dbg = ElektraDebuger() if i2c_name == '': i2c_bus = None else: if utility.is_pl_device(i2c_name): axi4_bus = AXI4LiteBus(i2c_name, 256) i2c_bus = MIXI2CSG(axi4_bus) else: i2c_bus = I2C(i2c_name) if spi_name == '': spi_bus = None else: axi4_bus = AXI4LiteBus(spi_name, 8192) spi_bus = MIXQSPISG(axi4_bus) if ad760x_name == '': ad7608_ip = None else: axi4 = AXI4LiteBus(ad760x_name, 8192) ad7608_ip = MIXAd7608SG(axi4) if gpio_id == '': gpio_bus = None else: io = GPIO(gpio_id, "output") gpio_bus = Pin(io, gpio_id, "output") volt_1 = int(volt_ch_1) volt_2 = int(volt_ch_2) curr_1 = int(curr_ch_1) curr_2 = int(curr_ch_2) scope_dbg.elektra = Elektra(i2c=i2c_bus, spi=spi_bus, ad7608=ad7608_ip, gpio=gpio_bus, volt_ch1=volt_1, volt_ch2=volt_2, curr_ch1=curr_1, curr_ch2=curr_2) return scope_dbg
def create_elektra_dbg(i2c_name, spi_name, ad717x_name, gpio_id, ipcore_name): scope_dbg = ElektraDebuger() if i2c_name == '': i2c_bus = None else: if utility.is_pl_device(i2c_name): axi4_bus = AXI4LiteBus(i2c_name, 256) i2c_bus = MIXI2CSG(axi4_bus) else: i2c_bus = I2C(i2c_name) if spi_name == '': spi_bus = None else: axi4_bus = AXI4LiteBus(spi_name, 8192) spi_bus = MIXQSPISG(axi4_bus) ipcore = None ad7175 = None vref = 5000 if ipcore_name != '': axi4_bus = AXI4LiteBus(ipcore_name, 9548) ipcore = MIXDAQT1SGR(axi4_bus, ad717x_mvref=vref, use_spi=True, use_gpio=False) elif ad717x_name != '': axi4_bus = AXI4LiteBus(ad717x_name, 256) ad7175 = MIXAd7175SG(axi4_bus, vref) if gpio_id == '': gpio_bus = None else: io = GPIO(gpio_id, "output") gpio_bus = Pin(io, gpio_id, "output") scope_dbg.elektra = EL004002A(i2c=i2c_bus, spi=spi_bus, ad7175=ad7175, gpio=gpio_bus, ipcore=ipcore) return scope_dbg
def __init__(self, i2c, ipcore): self.eeprom = CAT24C32(WolverineiiDef.EEPROM_DEV_ADDR, i2c) self.sensor = NCT75(WolverineiiDef.SENSOR_DEV_ADDR, i2c) self.pca9536 = PCA9536(WolverineiiDef.IO_EXP_DEV_ADDR, i2c) if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineiiDef.MIXDAQT1_REG_SIZE) ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineiiDef.AD7175_MVREF, code_polar=WolverineiiDef.AD7175_CODE_POLAR, reference=WolverineiiDef.AD7175_REFERENCE, clock=WolverineiiDef.AD7175_CLOCK, use_gpio=True) self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x self.ad7175.config = { 'ch0': { 'P': 'AIN0', 'N': 'AIN1' }, 'ch1': { 'P': 'AIN2', 'N': 'AIN3' } } self.measure_path = dict() self.continuous_sample_mode = None self.gpio = ipcore.gpio self.tag_pins = [ Pin(self.gpio, WolverineiiDef.TAG_BASE_PIN + x, WolverineiiDef.GPIO_OUTPUT_DIR) for x in range(4) ] super(WolverineII, self).__init__(self.eeprom, self.sensor, range_table=wolverineii_range_table)
def create_iceman_dbg(ip_name, signal_source_name, io_name, pin, i2c_name): iceman_dbg = None if utility.is_pl_device(i2c_name): axi4_bus = AXI4LiteBus(i2c_name, 256) i2c = MIXI2CSG(axi4_bus) else: i2c = I2C(i2c_name) if ip_name == '': axi4_bus = AXI4LiteBus(signal_source_name, 256) signal_source = MIXSignalSourceSG(axi4_bus) axi4_bus = AXI4LiteBus(io_name, 256) pl_gpio = MIXGPIOSG(axi4_bus) iceman_dbg = IcemanDebugger() iceman_dbg.iceman = Iceman(i2c, signal_source, Pin(pl_gpio, pin)) else: axi4_bus = AXI4LiteBus(ip_name, 0x8000) mix_sgt1 = MIXSGT1SGR(axi4_bus) iceman_dbg = IcemanDebugger() iceman_dbg.iceman = Iceman(i2c, ipcore=mix_sgt1) return iceman_dbg
def __init__(self, i2c, ad7177=None, ipcore=None): if ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, CloakDef.MIX_DAQT1_REG_SIZE) ipcore = MIXDAQT1SGR( axi4_bus, 'AD7177', ad717x_mvref=CloakDef.AD7177_MVREF, code_polar=CloakDef.AD7177_CODE_POLAR, reference=CloakDef.AD7177_REFERENCE_SOURCE, buffer_flag=CloakDef.AD7177_BUFFER_FLAG, clock=CloakDef.AD7177_CLOCK, use_spi=False, use_gpio=True) self.gpio = ipcore.gpio self.tag_pins = [ Pin(self.gpio, CloakDef.TAG_BASE_PIN + x, CloakDef.GPIO_OUTPUT_DIR) for x in xrange(4) ] elif ad7177: if isinstance(ad7177, basestring): axi4_bus = AXI4LiteBus(ad7177, CloakDef.AD7177_REG_SIZE) ad7177 = MIXAd7177SG( axi4_bus, mvref=CloakDef.AD7177_MVREF, code_polar=CloakDef.AD7177_CODE_POLAR, reference=CloakDef.AD7177_REFERENCE_SOURCE, buffer_flag=CloakDef.AD7177_BUFFER_FLAG, clock=CloakDef.AD7177_CLOCK) else: ad7177 = MIXAd7177SGEmulator('mix_ad7177_sg_emulator', 2500) super(Cloak, self).__init__(i2c, ad7177, ipcore, CloakDef.EEPROM_DEV_ADDR, CloakDef.SENSOR_DEV_ADDR, cloak_calibration_info, cloak_range_table)
def __init__(self, spi_bus=None, pdwn_ctrl=None, oeb_ctrl=None, cs_ctrl=None, use_cs=True): if(spi_bus is None and pdwn_ctrl is None and oeb_ctrl is None): self.spi_bus = MIXQSPISGEmulator("ad9628_emulator", 256) self.pdwn = Pin(None, 6) self.oeb = Pin(None, 7) elif(spi_bus is not None and pdwn_ctrl is not None and oeb_ctrl is not None): self.spi_bus = spi_bus self.pdwn = pdwn_ctrl self.oeb = oeb_ctrl else: raise AD9628RException('__init__ error! Please check the parameters') self.use_cs = use_cs if(self.use_cs is True and cs_ctrl is not None): self.cs = cs_ctrl elif(self.use_cs is False and cs_ctrl is None): self.cs = Pin(None, 12) else: raise AD9628RException('cs use error! Please check the parameters')
def __init__(self, ipcore=None, signal_meter_0=None, signal_meter_1=None, spi=None, i2c=None, eeprom_dev_addr=MagikDef.EEPROM_DEV_ADDR, sensor_dev_addr=MagikDef.SENSOR_DEV_ADDR): if ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, MagikDef.MIX_DAQT2_REG_SIZE) self.mix_daqt2 = MIXDAQT2SGR(axi4_bus, use_signal_meter1=True, use_spi=True, use_gpio=False) self.signal_meter0 = self.mix_daqt2.signal_meter0 self.signal_meter1 = self.mix_daqt2.signal_meter1 self.spi = self.mix_daqt2.spi else: self.ipcore = ipcore self.signal_meter0 = ipcore.signal_meter0 self.signal_meter1 = ipcore.signal_meter1 self.spi = ipcore.spi if signal_meter_0 or signal_meter_1 or spi: raise MagikException( 'Not allowed to use both Integrated IP and Separated IP at the same time!' ) else: if signal_meter_0 and signal_meter_1: if isinstance(signal_meter_0, basestring): axi4_bus = AXI4LiteBus(signal_meter_0, MagikDef.SIGNAL_METER_REG_SIZE) self.signal_meter0 = MIXSignalMeterSG(axi4_bus) else: self.signal_meter0 = signal_meter_0 if isinstance(signal_meter_1, basestring): axi4_bus = AXI4LiteBus(signal_meter_1, MagikDef.SIGNAL_METER_REG_SIZE) self.signal_meter1 = MIXSignalMeterSG(axi4_bus) else: self.signal_meter1 = signal_meter_1 elif not signal_meter_0 and not signal_meter_1: self.signal_meter0 = MIXSignalMeterSGEmulator( 'mix_signalmeter_sg_emulator', 256) self.signal_meter1 = MIXSignalMeterSGEmulator( 'mix_signalmeter_sg_emulator', 256) else: raise MagikException( 'signal_meter_0 and signal_meter_1 IP need to exist or be empty at the same time!' ) self.spi = spi if spi else MIXQSPISGEmulator( 'mix_qspi_sg_emulator', 256) if i2c: self.cat9555 = CAT9555(MagikDef.CAT9555_ADDR, i2c) self.nct75 = NCT75(sensor_dev_addr, i2c) self.eeprom = CAT24C32(eeprom_dev_addr, i2c) else: self.cat9555 = CAT9555Emulator(MagikDef.CAT9555_ADDR, None, None) self.eeprom = EepromEmulator('eeprom_emulator') self.nct75 = NCT75Emulator('nct75_emulator') self.spi.open() self.spi.set_speed(MagikDef.SPI_CLOCK_SPEED) self.spi.set_mode(MagikDef.SPI_BUS_MODE) ad9628_pdwn = Pin(self.cat9555, 6) ad9628_oeb = Pin(self.cat9555, 7) ad9628_cs = Pin(self.cat9555, 12) self.ad9628 = AD9628(self.spi, ad9628_pdwn, ad9628_oeb, ad9628_cs) super(MagikBase, self).__init__(self.eeprom, self.nct75, cal_table=magik_calibration_info, range_table=magik_range_table)
def __init__(self, i2c, ipcore=None, range_table=starlord_table): if i2c: self.eeprom = CAT24C32(StarLordDef.EEPROM_I2C_ADDR, i2c) self.nct75 = NCT75(StarLordDef.TEMP_I2C_ADDR, i2c) self.pca9536 = PCA9536(StarLordDef.PCA9536_DEV_ADDR, i2c) else: self.eeprom = EepromEmulator("cat24cxx_emulator") self.nct75 = NCT75Emulator("nct75_emulator") self.pca9536 = PCA9536Emulator("PCA9536_emulator") if ipcore: if isinstance(ipcore, basestring): ipcore = MIXAUT5SGR(ipcore) self.ipcore = ipcore self.analyzer = self.ipcore.analyzer self.signal_source = self.ipcore.signal_source self.ad7175 = self.ipcore.ad717x self.ad7175.config = { 'ch0': { 'P': 'AIN0', 'N': 'AIN1' }, 'ch1': { 'P': 'AIN2', 'N': 'AIN3' } } self.adc_rst_pin = Pin(self.ipcore.gpio, StarLordDef.ADC_RESET_PIN) self.i2s_rx_en_pin = Pin(self.ipcore.gpio, StarLordDef.I2S_RX_EN_PIN) self.dac_rst_pin = Pin(self.ipcore.gpio, StarLordDef.DAC_RESET_PIN) self.i2s_tx_en_pin = Pin(self.ipcore.gpio, StarLordDef.I2S_TX_EN_PIN) self.i2s_ch_select = [ Pin(self.ipcore.gpio, StarLordDef.I2S_CH_SELECT_2), Pin(self.ipcore.gpio, StarLordDef.I2S_CH_SELECT_3) ] self.fft_source_select = Pin(self.ipcore.gpio, StarLordDef.FFT_SOURCE_SELECT) self.ad7175_upload_select = Pin(self.ipcore.gpio, StarLordDef.AD7175_TO_FFT_OR_NOT) else: self.analyzer = MIXFftAnalyzerSGEmulator( "mix_fftanalyzer_sg_emulator") self.signal_source = MIXSignalSourceSGEmulator( "mix_signalsource_sg_emulator") self.adc_rst_pin = Pin(None, StarLordDef.ADC_RESET_PIN) self.i2s_rx_en_pin = Pin(None, StarLordDef.I2S_RX_EN_PIN) self.dac_rst_pin = Pin(None, StarLordDef.DAC_RESET_PIN) self.i2s_tx_en_pin = Pin(None, StarLordDef.I2S_TX_EN_PIN) self.ad7175 = MIXAd7175SGEmulator('mix_ad7175_sg_emulator', StarLordDef.EMULATOR_REG_SIZE) self.i2s_ch_select = [ Pin(None, StarLordDef.I2S_CH_SELECT_2), Pin(None, StarLordDef.I2S_CH_SELECT_3) ] self.fft_source_select = Pin(None, StarLordDef.FFT_SOURCE_SELECT) self.ad7175_upload_select = Pin(None, StarLordDef.AD7175_TO_FFT_OR_NOT) super(StarLord, self).__init__(self.eeprom, self.nct75, cal_table={}, range_table=range_table) self.is_lna_up = False self.is_analyzer_up = False self.is_enable_upload = False
class StarLord(MIXBoard): ''' StarLord is a high resolution differential input digital audio analyzer module Args: i2c: instance(I2C), the instance of I2C bus. which will be used to used to control eeprom, sensor and io expander. ipcore: instance(MIXAUT5SGR), the instance of MIXAUT5SGR, which include AD717x, FFT Analyzer, Signal Source and gpio function. If device name string is passed to the parameter, the ipcore can be instanced in the module. Examples: i2c = I2C('/dev/i2c-0') starlord = StarLord(i2c, '/dev/MIX_AUT5_SG_R_0') starlord.module_init() # measure left channel input result = starlord.measure('left', 20000, 3) print("vpp={}, freq={}, thd={}, thdn={}, rms={}, noisefloor={}".format(result['vpp'], result['freq'], result['thd'], result['thdn'], result['rms'], result['noisefloor'])) # measure LNA signal result = starlord.measure('left', '50mV', 20000, 3, 1000) print("vpp={}, freq={}, thd={}, thdn={}, rms={}".format(result['vpp'], result['freq'], result['thd'], result['thdn'], result['rms'])) ''' compatible = ['GQQ-AUD003002-000'] rpc_public_api = [ 'module_init', 'enable_upload', 'disable_upload', 'measure', 'enable_output', 'disable_output', 'measure_lna', 'enable_lna_upload', 'disable_lna_upload', 'config_lna_scope' ] + MIXBoard.rpc_public_api def __init__(self, i2c, ipcore=None, range_table=starlord_table): if i2c: self.eeprom = CAT24C32(StarLordDef.EEPROM_I2C_ADDR, i2c) self.nct75 = NCT75(StarLordDef.TEMP_I2C_ADDR, i2c) self.pca9536 = PCA9536(StarLordDef.PCA9536_DEV_ADDR, i2c) else: self.eeprom = EepromEmulator("cat24cxx_emulator") self.nct75 = NCT75Emulator("nct75_emulator") self.pca9536 = PCA9536Emulator("PCA9536_emulator") if ipcore: if isinstance(ipcore, basestring): ipcore = MIXAUT5SGR(ipcore) self.ipcore = ipcore self.analyzer = self.ipcore.analyzer self.signal_source = self.ipcore.signal_source self.ad7175 = self.ipcore.ad717x self.ad7175.config = { 'ch0': { 'P': 'AIN0', 'N': 'AIN1' }, 'ch1': { 'P': 'AIN2', 'N': 'AIN3' } } self.adc_rst_pin = Pin(self.ipcore.gpio, StarLordDef.ADC_RESET_PIN) self.i2s_rx_en_pin = Pin(self.ipcore.gpio, StarLordDef.I2S_RX_EN_PIN) self.dac_rst_pin = Pin(self.ipcore.gpio, StarLordDef.DAC_RESET_PIN) self.i2s_tx_en_pin = Pin(self.ipcore.gpio, StarLordDef.I2S_TX_EN_PIN) self.i2s_ch_select = [ Pin(self.ipcore.gpio, StarLordDef.I2S_CH_SELECT_2), Pin(self.ipcore.gpio, StarLordDef.I2S_CH_SELECT_3) ] self.fft_source_select = Pin(self.ipcore.gpio, StarLordDef.FFT_SOURCE_SELECT) self.ad7175_upload_select = Pin(self.ipcore.gpio, StarLordDef.AD7175_TO_FFT_OR_NOT) else: self.analyzer = MIXFftAnalyzerSGEmulator( "mix_fftanalyzer_sg_emulator") self.signal_source = MIXSignalSourceSGEmulator( "mix_signalsource_sg_emulator") self.adc_rst_pin = Pin(None, StarLordDef.ADC_RESET_PIN) self.i2s_rx_en_pin = Pin(None, StarLordDef.I2S_RX_EN_PIN) self.dac_rst_pin = Pin(None, StarLordDef.DAC_RESET_PIN) self.i2s_tx_en_pin = Pin(None, StarLordDef.I2S_TX_EN_PIN) self.ad7175 = MIXAd7175SGEmulator('mix_ad7175_sg_emulator', StarLordDef.EMULATOR_REG_SIZE) self.i2s_ch_select = [ Pin(None, StarLordDef.I2S_CH_SELECT_2), Pin(None, StarLordDef.I2S_CH_SELECT_3) ] self.fft_source_select = Pin(None, StarLordDef.FFT_SOURCE_SELECT) self.ad7175_upload_select = Pin(None, StarLordDef.AD7175_TO_FFT_OR_NOT) super(StarLord, self).__init__(self.eeprom, self.nct75, cal_table={}, range_table=range_table) self.is_lna_up = False self.is_analyzer_up = False self.is_enable_upload = False def module_init(self): ''' Init module, which will reset dac/adc, i2s module and load calibration Returns: string, "done", execution successful. Examples: starloard.module_init() ''' self.adc_rst_pin.set_dir(StarLordDef.IO_DIR_OUTPUT) self.dac_rst_pin.set_dir(StarLordDef.IO_DIR_OUTPUT) self.i2s_rx_en_pin.set_dir(StarLordDef.IO_DIR_OUTPUT) self.i2s_tx_en_pin.set_dir(StarLordDef.IO_DIR_OUTPUT) self.i2s_ch_select[StarLordDef.AUDIO_CHANNEL_SELECT_BIT0].set_dir( StarLordDef.IO_DIR_OUTPUT) self.i2s_ch_select[StarLordDef.AUDIO_CHANNEL_SELECT_BIT1].set_dir( StarLordDef.IO_DIR_OUTPUT) self.fft_source_select.set_dir(StarLordDef.IO_DIR_OUTPUT) self.ad7175_upload_select.set_dir(StarLordDef.IO_DIR_OUTPUT) # reset ADC self.adc_rst_pin.set_level(0) time.sleep(StarLordDef.RELAY_DELAY_S) self.adc_rst_pin.set_level(1) # reset DAC self.dac_rst_pin.set_level(0) time.sleep(StarLordDef.RELAY_DELAY_S) self.dac_rst_pin.set_level(1) # reset i2s rx self.i2s_rx_en_pin.set_level(0) # reset i2s tx self.i2s_tx_en_pin.set_level(0) # io init self.pca9536.set_pin_dir(StarLordDef.AD7175_CH_LEFT_CTL_BIT, StarLordDef.IO_DIR_OUTPUT) self.pca9536.set_pin_dir(StarLordDef.AD7175_CH_RIGHT_CTL_BIT, StarLordDef.IO_DIR_OUTPUT) self.pca9536.set_pin(StarLordDef.AD7175_CH_LEFT_CTL_BIT, 0) self.pca9536.set_pin(StarLordDef.AD7175_CH_RIGHT_CTL_BIT, 0) # ad7175 init self.ad7175.channel_init() # measure lna config init self.config_lna_scope(StarLordDef.CH_LEFT, StarLordDef.LNA_RANGE_5V) self.load_calibration() return "done" def enable_upload(self): ''' Enable module data upload. Returns: string, "done", execution successful. ''' self.i2s_rx_en_pin.set_level(StarLordDef.I2S_RX_ENABLE) self.analyzer.enable_upload() self.is_enable_upload = True return "done" def disable_upload(self): ''' Disable module data upload. Returns: string, "done", execution successful. ''' self.analyzer.disable_upload() self.i2s_rx_en_pin.set_level(StarLordDef.I2S_RX_DISABLE) self.is_enable_upload = False return "done" def measure(self, channel, bandwidth_hz, harmonic_count, decimation_type=0xFF, sampling_rate=StarLordDef.AUDIO_SAMPLING_RATE): ''' Measure audio input signal, which captures data using CS5361. Args: channel: string, ['left', 'right'], select input signal channel. bandwidth_hz: int/string, [42~48000], unit Hz, the signal bandwidth. harmonic_count: int, [2~10], The harmonic count of signal. decimation_type: int, [1~255], default 0xFF, sample data decimation. sampling_rate: int, [1~192000], default 192000, unit Hz, ADC sampling rate. Returns: dict, {'vpp': value, 'freq': value, 'thd': value, 'thdn': value, 'rms': value, 'noisefloor': value}, measurement result. ''' assert channel in StarLordDef.AUDIO_CHANNEL_LIST if self.is_enable_upload is False: self.i2s_rx_en_pin.set_level(StarLordDef.I2S_RX_ENABLE) pin = self.i2s_ch_select[StarLordDef.AUDIO_CHANNEL_SELECT_BIT0] pin.set_level(StarLordDef.AUDIO_CHANNEL_LIST[channel][ StarLordDef.AUDIO_CHANNEL_SELECT_BIT0]) pin = self.i2s_ch_select[StarLordDef.AUDIO_CHANNEL_SELECT_BIT1] pin.set_level(StarLordDef.AUDIO_CHANNEL_LIST[channel][ StarLordDef.AUDIO_CHANNEL_SELECT_BIT1]) self.fft_source_select.set_level(StarLordDef.FFT_SOURCE_FROM_CS5361) result = self._analyzer(sampling_rate, decimation_type, bandwidth_hz, harmonic_count) range_name = "AUDIO_CS5361_RMS_" + channel result['rms'] = (self.calibrate(range_name, result['rms'][0]), StarLordDef.VOLT_UNIT_RMS) if self.is_enable_upload is False: self.i2s_rx_en_pin.set_level(StarLordDef.I2S_RX_DISABLE) return result def config_lna_scope(self, channel, scope, adc_upload_ch=StarLordDef.AD7175_UPLOAD_TO_FFT): ''' Config LNA measurement scope Args: channel: string, ['left', 'right'], the channel to be upload. scope: string, ['5V', '50mV'], AD7175 measurement range. adc_upload_ch: string, ['dma', 'fft'], default 'fft', AD7175 source data is uploaded to DMA or FFT. Returns: string, "done", execution successful. ''' assert channel in StarLordDef.AD7175_CH_LIST assert scope in StarLordDef.LNA_SCOPE assert adc_upload_ch in StarLordDef.AD7175_UPLOAD_CH self.channel = channel self.scope = scope if scope == StarLordDef.LNA_RANGE_5V: self.pca9536.set_pin(StarLordDef.AD7175_CH_LIST[channel], StarLordDef.SEL_GAIN_1) else: self.pca9536.set_pin(StarLordDef.AD7175_CH_LIST[channel], StarLordDef.SEL_GAIN_100) self.ad7175_upload_select.set_level( StarLordDef.AD7175_UPLOAD_CH[adc_upload_ch]) return "done" def enable_lna_upload(self, channel, sampling_rate=StarLordDef.LNA_SAMPLING_RATE): ''' Enable LNA adc data upload Args: channel: string, ['left', 'right'], the channel to be upload. sampling_rate: float, default 250000, unit Hz, AD7175 sampling rate, please refer to datasheet for more information. Returns: string, "done", execution successful. ''' assert channel in StarLordDef.AD7175_CH_LIST self.is_lna_up = True self.ad7175.disable_continuous_sampling( StarLordDef.AD7175_CH_LIST[channel]) time.sleep(StarLordDef.RELAY_DELAY_S) self.ad7175.enable_continuous_sampling( StarLordDef.AD7175_CH_LIST[channel], sampling_rate) return "done" def disable_lna_upload(self, channel): ''' Disable LNA adc data upload Args: channel: string, ['left', 'right'], the channel to be upload. Returns: string, "done", execution successful. ''' assert channel in StarLordDef.AD7175_CH_LIST self.is_lna_up = False if self.is_analyzer_up is True: self.analyzer.disable_upload() self.is_analyzer_up = False self.ad7175.disable_continuous_sampling( StarLordDef.AD7175_CH_LIST[channel]) return "done" def measure_lna(self, bandwidth_hz, harmonic_count, decimation_type=0xFF, sampling_rate=StarLordDef.LNA_SAMPLING_RATE): ''' Measure audio LNA input signal, which captures data using AD7175. Args: bandwidth_hz: int/string, [42~48000], unit Hz, the signal bandwidth. harmonic_count: int, [2~10], The harmonic count of signal. decimation_type: int, [1~255], default 0xFF, sample data decimation. sampling_rate: int, [5~250000], default 250000, unit Hz, Sample rate of your ADC device. Returns: dict, {'vpp': value, 'freq': value, 'thd': value, 'thdn': value, 'rms': value, 'noisefloor': value}, measurement result. ''' self.fft_source_select.set_level(StarLordDef.FFT_SOURCE_FROM_AD7175) if self.is_lna_up is True and self.is_analyzer_up is False: self.analyzer.enable_upload() self.is_analyzer_up = True self.analyzer.disable() self.analyzer.enable() self.analyzer.analyze_config(sampling_rate, decimation_type, bandwidth_hz, harmonic_count) self.analyzer.analyze() range_name = "LNA_" + self.scope + "_" + self.channel gain = StarLordDef.GAIN_VALUE[self.scope] vpp = self.analyzer.get_vpp() * gain rms = vpp / StarLordDef.RMS_TO_VPP_RATIO rms = self.calibrate(range_name, rms) thdn_value = self.analyzer.get_thdn() result = dict() result["vpp"] = (vpp, StarLordDef.VOLT_UNIT_MV) result["freq"] = (self.analyzer.get_frequency(), StarLordDef.FREQ_UNIT_HZ) result["thd"] = (self.analyzer.get_thd(), StarLordDef.THD_UNIT_DB) result["thdn"] = (thdn_value, StarLordDef.THDN_UNIT_DB) result["rms"] = (rms, StarLordDef.VOLT_UNIT_RMS) result["noisefloor"] = (10**(thdn_value / 20) * rms, StarLordDef.VOLT_UNIT_RMS) return result def enable_output(self, freq, vpp): ''' StarLord CS5361 output audio sine waveform. Args: freq: int, [5~50000], unit Hz, output signal's frequency. vpp: float, [0~6504], unit mV, output signal's vpp. Returns: string, "done", execution successful. ''' assert StarLordDef.OUTPUT_FREQ_MIN <= freq assert freq <= StarLordDef.OUTPUT_FREQ_MAX assert StarLordDef.OUTPUT_VPP_MIN <= vpp assert vpp <= StarLordDef.OUTPUT_VPP_MAX vpp = self.calibrate(StarLordDef.OUTPUT_CAL_ITEM, vpp) vpp = 0 if vpp < 0 else vpp # enable I2S tx module self.i2s_tx_en_pin.set_level(StarLordDef.AUDIO_OUTPUT_ENABLE) self.signal_source.close() self.signal_source.open() # calculate vpp to vpp scale for FPGA vpp_scale = vpp * StarLordDef.VPP_2_SCALE_RATIO self.signal_source.set_swg_paramter(StarLordDef.AUDIO_SAMPLING_RATE, freq, vpp_scale, StarLordDef.OUTPUT_SIGNAL_DUTY) self.signal_source.set_signal_type(StarLordDef.OUTPUT_WAVE) self.signal_source.set_signal_time(StarLordDef.SIGNAL_ALWAYS_OUTPUT) self.signal_source.output_signal() return "done" def disable_output(self): ''' Disable Cs5361 output signal. Returns: string, "done", execution successful. ''' self.signal_source.close() self.i2s_tx_en_pin.set_level(StarLordDef.AUDIO_OUTPUT_DISABLE) return "done" def _analyzer(self, sampling_rate, decimation_type, bandwidth_hz, harmonic_count): ''' Measure audio input signal. Returns: dict, {'vpp': value, 'freq': value, 'thd': value, 'thdn': value, 'rms': value, 'noisefloor': value}, measurement result. ''' self.analyzer.disable() self.analyzer.enable() self.analyzer.analyze_config(sampling_rate, decimation_type, bandwidth_hz, harmonic_count) self.analyzer.analyze() # calculate the actual vpp of HW by VREF vpp = self.analyzer.get_vpp() * StarLordDef.AUDIO_ANALYZER_VREF # vpp = RMS * 2 * sqrt(2) rms = vpp / StarLordDef.RMS_TO_VPP_RATIO vpp = rms * StarLordDef.RMS_TO_VPP_RATIO thdn_value = self.analyzer.get_thdn() result = dict() result["vpp"] = (vpp, StarLordDef.VOLT_UNIT_MV) result["freq"] = (self.analyzer.get_frequency(), StarLordDef.FREQ_UNIT_HZ) result["thd"] = (self.analyzer.get_thd(), StarLordDef.THD_UNIT_DB) result["thdn"] = (thdn_value, StarLordDef.THDN_UNIT_DB) result["rms"] = (rms, StarLordDef.VOLT_UNIT_RMS) result["noisefloor"] = (10**(thdn_value / 20) * rms, StarLordDef.VOLT_UNIT_RMS) return result
def __init__(self, i2c, ad7175=None, range_sel=None, meter_sel=None, ipcore=None): if i2c and ad7175 and range_sel and meter_sel and not ipcore: if isinstance(ad7175, basestring): axi4 = AXI4LiteBus(ad7175, WolverineDef.PLAD7175_REG_SIZE) self.ad7175 = MIXAd7175SG(axi4, mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK) else: self.ad7175 = ad7175 self.range_sel = range_sel self.meter_sel = meter_sel elif i2c and not ad7175 and not range_sel and not meter_sel and ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineDef.MIX_DAQT1_REG_SIZE) self.ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK, use_gpio=True) else: self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x gpio = self.ipcore.gpio self.range_sel = Pin(gpio, WolverineDef.RANGE_SEL_BIT) self.meter_sel = Pin(gpio, WolverineDef.METER_SEL_BIT) elif i2c and not ad7175 and range_sel and meter_sel and ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineDef.REG_SIZE) self.ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK, use_gpio=False) else: self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x self.range_sel = range_sel self.meter_sel = meter_sel elif not i2c and not ad7175 and not range_sel and not meter_sel and not ipcore: self.ad7175 = MIXAd7175SGEmulator("ad7175_emulator", WolverineDef.EMULATOR_REG_SIZE) self.range_sel = Pin(None, WolverineDef.RANGE_SEL_BIT) self.meter_sel = Pin(None, WolverineDef.METER_SEL_BIT) else: raise WolverineException("Invalid parameter, please check") if i2c: eeprom = CAT24C32(WolverineDef.EEPROM_DEV_ADDR, i2c) nct75 = NCT75(WolverineDef.NCT75_DEV_ADDR, i2c) super(Wolverine, self).__init__(eeprom, nct75, cal_table=wolverine_calibration_info, range_table=wolverine_range_table) else: super(Wolverine, self).__init__(None, None, cal_table=wolverine_calibration_info, range_table=wolverine_range_table) self.channel_path = { 'range_sel_bit': self.range_sel, 'meter_sel_bit': self.meter_sel } self.measure_path = {"channel": None, "range": None}
class Wolverine(MIXBoard): ''' DMM001 is a compact version of the digital multimeter which internal ADC resolution is 24 bit. compatible = ["GQQ-DMM001003-000"] It can be used as high performance DMM to measure DC voltage and small signal DC current. In this class, adc channel 0 is current channel, adc channel 1 is voltage channel. DMM001 support signal measurement and continuous measurement. Note that if range_ctrl0 and range_ctrl1 not given, internal submodule GPIO device of MIX_DAQT1 will be used to control range. Note that calibration default is enabled. This class is legacy driver for normal boot. Args: i2c: instance(I2C)/None, which is used to control nct75 and cat24c32. If not given, emulator will be created. ad7175: instance(ADC)/None, Class instance of AD7175, if not using this parameter, will create emulator range_sel: instance(GPIO), This can be Pin or xilinx gpio, used to control range. meter_sel: instance(GPIO), This can be Pin or xilinx gpio, used to control measure channel ipcore: instance(MIXDAQT1SGR)/string, MIXDAQT1SGR ipcore driver instance or device name string, if given, user should not use ad7175. Examples: Example for using no-aggregate IP: # normal init ad7175 = MIXAd7175SG('/dev/MIX_AD717X_0', 5000) i2c = I2C('/dev/i2c-1') gpio = GPIO(i2c) range_sel = Pin(gpio, 1) meter_sel = Pin(gpio, 3) wolverine = Wolverine(i2c, ad7175, range_sel=range_sel, meter_sel=meter_sel) # using ipcore device name string i2c = I2C('/dev/i2c-1') gpio = GPIO(i2c) range_sel = Pin(gpio, 1) meter_sel = Pin(gpio, 3) wolverine = Wolverine(i2c, '/dev/MIX_AD717X_0', range_sel=range_sel, meter_sel=meter_sel) Example for using aggregate IP: # normal init i2c = I2C('/dev/i2c-1') daqt1 = MIXDAQT1SGR('/dev/MIX_DAQT1', ad717x_chip='AD7175', ad717x_mvref=5000, use_spi=False, use_gpio=True) wolverine = Wolverine(i2c, ipcore=daqt1) # using ipcore device name i2c = I2C('/dev/i2c-1') wolverine = Wolverine(i2c, ipcore='/dev/MIX_DAQT1') Example for measuring voltage: result = wolverine.voltage_measure(5) print("voltage={}, unit={}".format(result[0], result[1])) result = wolverine.multi_points_voltage_measure(3, 5) print("average={}, max={}, min={}, rms={}".format(result['average'], result['max'], result['min'], result['rms'])) Example for measuring current: result = wolverine.current_measure('2mA', 5) print("current={}, unit={}".format(result[0], result[1])) result = wolverine.multi_points_current_measure(3, '2mA', 5) print("average={}, max={}, min={}, rms={}".format(result['average'], result['max'], result['min'], result['rms'])) ''' # launcher will use this to match driver compatible string and load driver if matched. compatible = ["GQQ-DMM001003-000"] rpc_public_api = [ 'module_init', 'get_sampling_rate', 'set_measure_path', 'get_measure_path', 'voltage_measure', 'multi_points_voltage_measure', 'current_measure', 'multi_points_current_measure' ] + MIXBoard.rpc_public_api def __init__(self, i2c, ad7175=None, range_sel=None, meter_sel=None, ipcore=None): if i2c and ad7175 and range_sel and meter_sel and not ipcore: if isinstance(ad7175, basestring): axi4 = AXI4LiteBus(ad7175, WolverineDef.PLAD7175_REG_SIZE) self.ad7175 = MIXAd7175SG(axi4, mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK) else: self.ad7175 = ad7175 self.range_sel = range_sel self.meter_sel = meter_sel elif i2c and not ad7175 and not range_sel and not meter_sel and ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineDef.MIX_DAQT1_REG_SIZE) self.ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK, use_gpio=True) else: self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x gpio = self.ipcore.gpio self.range_sel = Pin(gpio, WolverineDef.RANGE_SEL_BIT) self.meter_sel = Pin(gpio, WolverineDef.METER_SEL_BIT) elif i2c and not ad7175 and range_sel and meter_sel and ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineDef.REG_SIZE) self.ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK, use_gpio=False) else: self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x self.range_sel = range_sel self.meter_sel = meter_sel elif not i2c and not ad7175 and not range_sel and not meter_sel and not ipcore: self.ad7175 = MIXAd7175SGEmulator("ad7175_emulator", WolverineDef.EMULATOR_REG_SIZE) self.range_sel = Pin(None, WolverineDef.RANGE_SEL_BIT) self.meter_sel = Pin(None, WolverineDef.METER_SEL_BIT) else: raise WolverineException("Invalid parameter, please check") if i2c: eeprom = CAT24C32(WolverineDef.EEPROM_DEV_ADDR, i2c) nct75 = NCT75(WolverineDef.NCT75_DEV_ADDR, i2c) super(Wolverine, self).__init__(eeprom, nct75, cal_table=wolverine_calibration_info, range_table=wolverine_range_table) else: super(Wolverine, self).__init__(None, None, cal_table=wolverine_calibration_info, range_table=wolverine_range_table) self.channel_path = { 'range_sel_bit': self.range_sel, 'meter_sel_bit': self.meter_sel } self.measure_path = {"channel": None, "range": None} def _check_channel(self, channel): ''' Check the channel if it is valid. Args: channel: string, ['CURR', 'VOLT'], the channel to check. Returns: string, ['CURR', 'VOLT'], the channel in specific format. Raise: WolverineException: If channel is invalid, exception will be raised. ''' for ch in WolverineDef.CHANNEL_CONFIG: if channel.lower() == ch.lower(): return ch raise WolverineException("channel {} is invalid".format(channel)) def _check_scope(self, channel, scope): ''' Check valid of the specific scope. Args: channel: string, the channel to change scope. scope: string, the scope string to be checked. Returns: string, str, the scope in specific format. Raise: WolverineException: If the scope is invalid, exception will be raised. ''' range_config = WolverineDef.CHANNEL_CONFIG[channel]['range'] for rng in range_config: if rng.lower() == scope.lower(): return rng raise WolverineException( 'scope {} in channel {} is not invalid'.format(channel, scope)) def module_init(self): ''' Init wolverine module. This function will set io direction to output and set default range to '5V' Returns: string, "done", api execution successful. ''' self.range_sel.set_dir('output') self.meter_sel.set_dir('output') self.set_measure_path(WolverineDef.VOLT_5V) self.ad7175.channel_init() self.set_sampling_rate(WolverineDef.VOLTAGE_CHANNEL, WolverineDef.DEFAULT_SAMPLE_RATE) self.set_sampling_rate(WolverineDef.CURRENT_CHANNEL, WolverineDef.DEFAULT_SAMPLE_RATE) self.load_calibration() return "done" def set_sampling_rate(self, channel, sampling_rate): ''' Wolverine set sampling rate. Note that sampling rate is not discontinuous, all support sampling rate can be found in ad7175 datasheet. Args: channel: string, ['VOLT', 'CURR'], the channel to change sampling rate. sampling_rate: float, [5~250000], adc measure sampling rate, which is not continuous, please refer to ad7175 datasheet. Returns: string, "done", api execution successful. Examples: wolverine.set_sampling_rate('VOLT', 10000) ''' assert 5 <= sampling_rate <= 250000 channel = self._check_channel(channel) if sampling_rate != self.get_sampling_rate(channel): self.ad7175.set_sampling_rate( WolverineDef.CHANNEL_CONFIG[channel]['adc_channel'], sampling_rate) def get_sampling_rate(self, channel): ''' Wolverine get sampling rate of adc Args: channel: string, ['VOLT', 'CURR'], the channel to get sampling rate. Returns: int, value, current module sampling rate. Examples: sampling_rate = wolverine.set_sampling_rate('VOLT') print(sampling_rate) ''' channel = self._check_channel(channel) return self.ad7175.get_sampling_rate( WolverineDef.CHANNEL_CONFIG[channel]['adc_channel']) def _get_channel_from_scope(self, scope): ''' Get channel from scope string. Args: scope: string, ['5V', '2mA', '100uA'], measure range string. Examples: string, ['VOLT', 'CURR', wolverine measure channel. ''' if scope.lower() == WolverineDef.VOLT_5V.lower(): return WolverineDef.VOLTAGE_CHANNEL elif scope.lower() in [ WolverineDef.CURR_2MA.lower(), WolverineDef.CURR_100UA.lower() ]: return WolverineDef.CURRENT_CHANNEL else: raise WolverineException("scope {} is invalid.".format(scope)) def set_measure_path(self, scope): ''' Wolverine set measure path. Args: scope: string, ['100uA', '2mA', '5V''], set range for different channel Returns: string, "done", api execution successful. Examples: wolverine.setmeasure_path('5V') ''' channel = self._get_channel_from_scope(scope) scope = self._check_scope(channel, scope) path_bits = WolverineDef.CHANNEL_CONFIG[channel]['range'][scope][ 'path'] if self.measure_path["channel"] != channel or \ self.measure_path["range"] != scope: for bits in path_bits: self.channel_path[bits[0]].set_level(bits[1]) self.measure_path["channel"] = channel self.measure_path["range"] = scope def get_measure_path(self): ''' Wolverine get measure path. Returns: dict, current channel and range. Examples: path = wolverine.get_measure_path() printf(path) ''' return self.measure_path def voltage_measure(self, sampling_rate=WolverineDef.DEFAULT_SAMPLE_RATE): ''' Wolverine measure voltage once Args: sampling_rate: float, [5~250000], default 5, not continuous, please refer to ad7175 datasheet. Returns: list, [value, 'mV'], voltage value and unit. ''' # Slect range: VOLT_5V = '5V' self.set_measure_path(WolverineDef.VOLT_5V) # Set sampling_rate self.set_sampling_rate(WolverineDef.VOLTAGE_CHANNEL, sampling_rate) voltage = self.ad7175.read_volt(WolverineDef.CHANNEL_CONFIG[ self.measure_path['channel']]['adc_channel']) gain = WolverineDef.VOLTAGE_5V_GAIN voltage /= gain cal_item = self.measure_path["channel"] + "_" + self.measure_path[ "range"] voltage = self.calibrate(cal_item, voltage) return [voltage, 'mV'] def multi_points_voltage_measure(self, count, sampling_rate=WolverineDef. DEFAULT_SAMPLE_RATE): ''' Wolverine measure voltage in continuous mode. Notice that before call this function, continuous voltage measure has been started. Args: count: int, [1~512], Get count voltage in continuous mode. sampling_rate: float, [5~250000], default 5, not continuous, please refer to ad7175 datasheet. Returns: dict, {"rms":[value, 'mVrms'], "average":[value, 'mV'], "max":[value, 'mV'], "min":[value, 'mV']}, rms, average, max and min voltage with unit. ''' adc_channel = WolverineDef.CHANNEL_CONFIG[ self.measure_path['channel']]['adc_channel'] # Slect range: VOLT_5V = '5V' self.set_measure_path(WolverineDef.VOLT_5V) self.ad7175.disable_continuous_sampling(adc_channel) time.sleep(WolverineDef.SWITCH_DELAY) self.ad7175.enable_continuous_sampling(adc_channel, sampling_rate) adc_volt = self.ad7175.get_continuous_sampling_voltage( adc_channel, count) self.ad7175.disable_continuous_sampling(adc_channel) min_data = min(adc_volt) max_data = max(adc_volt) sum_Data = sum(adc_volt) avg_data = sum_Data / len(adc_volt) suqare_sum_data = sum([x**2 for x in adc_volt]) rms_data = math.sqrt(suqare_sum_data / len(adc_volt)) gain = WolverineDef.VOLTAGE_5V_GAIN rms = rms_data / gain voltage = avg_data / gain max_voltage = max_data / gain min_voltage = min_data / gain cal_item = self.measure_path["channel"] + "_" + self.measure_path[ "range"] voltage = self.calibrate(cal_item, voltage) result = dict() result['rms'] = (rms, 'mVrms') result['average'] = (voltage, 'mV') result['max'] = (max_voltage, 'mV') result['min'] = (min_voltage, 'mV') return result def current_measure(self, curr_range=WolverineDef.CURR_2MA, sampling_rate=WolverineDef.DEFAULT_SAMPLE_RATE): ''' Wolverine measure current once Args: curr_range: string, ['2mA', '100uA'], default '2mA', measure range string. sampling_rate: float, [5~250000], default 5, not continuous, please refer to ad7175 datasheet. Returns: list, [value, 'mA'], current value and unit. ''' assert curr_range in [WolverineDef.CURR_100UA, WolverineDef.CURR_2MA] # Slect range: CURR_100UA = '100uA', CURR_2MA = '2mA' self.set_measure_path(curr_range) # Set sampling_rate self.set_sampling_rate(WolverineDef.CURRENT_CHANNEL, sampling_rate) volt = self.ad7175.read_volt(WolverineDef.CHANNEL_CONFIG[ self.measure_path['channel']]['adc_channel']) sample_res = WolverineDef.CURRENT_100UA_SAMPLE_RES if \ self.measure_path["range"] == WolverineDef.CURR_100UA else \ WolverineDef.CURRENT_2MA_SAMPLE_RES gain = WolverineDef.CURRENT_100UA_GAIN if \ self.measure_path["range"] == WolverineDef.CURR_100UA else \ WolverineDef.CURRENT_2MA_GAIN current = (volt / gain) / sample_res cal_item = self.measure_path["channel"] + "_" + self.measure_path[ "range"] current = self.calibrate(cal_item, current) return [current, 'mA'] def multi_points_current_measure( self, count, curr_range=WolverineDef.CURR_2MA, sampling_rate=WolverineDef.DEFAULT_SAMPLE_RATE): ''' Wolverine measure current in continuous mode. Note that before call this function, continuous current measure must be started first Args: count: int, [1~512], number current value to be get curr_range: string, ['2mA', '100uA'], default '2mA', measure range string. sampling_rate: float, [5~250000], default 5, not continuous, please refer to ad7175 datasheet. Returns: dict, {"rms":[value, 'mVrms'], "average":[value, 'mA'], "max":[value, 'mA'], "min":[value, 'mA']}, rms, average, max and min current with unit. ''' assert curr_range in [WolverineDef.CURR_100UA, WolverineDef.CURR_2MA] adc_channel = WolverineDef.CHANNEL_CONFIG[ self.measure_path['channel']]['adc_channel'] # Slect range: CURR_100UA = '100uA', CURR_2MA = '2mA' self.set_measure_path(curr_range) self.ad7175.disable_continuous_sampling(adc_channel) time.sleep(WolverineDef.SWITCH_DELAY) self.ad7175.enable_continuous_sampling(adc_channel, sampling_rate) adc_volt = self.ad7175.get_continuous_sampling_voltage( adc_channel, count) self.ad7175.disable_continuous_sampling(adc_channel) min_data = min(adc_volt) max_data = max(adc_volt) sum_Data = sum(adc_volt) avg_data = sum_Data / len(adc_volt) suqare_sum_data = sum([x**2 for x in adc_volt]) rms_data = math.sqrt(suqare_sum_data / len(adc_volt)) sample_res = WolverineDef.CURRENT_100UA_SAMPLE_RES if \ self.measure_path["range"] == WolverineDef.CURR_100UA else \ WolverineDef.CURRENT_2MA_SAMPLE_RES gain = WolverineDef.CURRENT_100UA_GAIN if \ self.measure_path["range"] == WolverineDef.CURR_100UA else \ WolverineDef.CURRENT_2MA_GAIN rms = (rms_data / gain) / sample_res current = (avg_data / gain) / sample_res max_current = (max_data / gain) / sample_res min_current = (min_data / gain) / sample_res cal_item = self.measure_path["channel"] + "_" + self.measure_path[ "range"] current = self.calibrate(cal_item, current) result = dict() result['rms'] = (rms, 'mArms') result['average'] = (current, 'mA') result['max'] = (max_current, 'mA') result['min'] = (min_current, 'mA') return result def legacy_write_calibration_cell(self, unit_index, gain, offset, threshold): ''' MIXBoard calibration data write Args: unit_index: int, calibration unit index. gain: float, calibration gain. offset: float, calibration offset. threshold: float, if value < threshold, use this calibration unit data. Returns: string, "done", api execution successful. Examples: board.write_calibration_cel(0, 1.1, 0.1, 100) Raise: BoardArgCheckError: unit_index data type is not int type or unit_index < 0. calibration unit format: Meaning: Gain, Offset, threshold value, Use flag Mem size: 4Bytes, 4Bytes, 4Bytes, Byte Data type: float, float, float, uint8_t Formula: Y = Gain * X + Offset ''' if not isinstance(unit_index, int) or unit_index < 0: raise BoardArgCheckError( "calibration unit memory unit_index data type is not int type or unit_index < 0" ) use_flag = self.calibration_info["use_flag"] data = (gain, offset, use_flag) s = struct.Struct(WolverineDef.WRITE_CAL_DATA_PACK_FORMAT) pack_data = s.pack(*data) s = struct.Struct(WolverineDef.WRITE_CAL_DATA_UNPACK_FORMAT) data = s.unpack(pack_data) address = self.calibration_info[ "unit_start_addr"] + WolverineDef.CAL_DATA_LEN * unit_index self.write_eeprom(address, data) return "done" def legacy_read_calibration_cell(self, unit_index): ''' MIXBoard read calibration data Args: unit_index: int, calibration unit index. Returns: dict, {"gain": value, "offset":value, "threshold": value, "is_use": value}. Examples: data = board.read_calibration_cel(0) print(data) Raise: BoardArgCheckError: unit_index data type is not int type or unit_index < 0. calibration unit format: Meaning: Gain, Offset, threshold value, Use flag Mem size: 4Bytes, 4Bytes, 4Bytes, Byte Data type: float, float, float, uint8_t Formula: Y = Gain * X + Offset ''' if not isinstance(unit_index, int) or unit_index < 0: raise BoardArgCheckError( "calibration unit memory unit_index data type is not int type or unit_index < 0" ) address = self.calibration_info[ "unit_start_addr"] + WolverineDef.CAL_DATA_LEN * unit_index data = self.read_eeprom(address, WolverineDef.READ_CAL_BYTE) s = struct.Struct(WolverineDef.READ_CAL_DATA_PACK_FORMAT) pack_data = s.pack(*data) s = struct.Struct(WolverineDef.READ_CAL_DATA_UNPACK_FORMAT) result = s.unpack(pack_data) threshold = 0.0 for cal_item in wolverine_calibration_info: for level in wolverine_calibration_info[cal_item]: if unit_index == wolverine_calibration_info[cal_item][level][ "unit_index"]: threshold = wolverine_calibration_info[cal_item][level][ "limit"][0] if self.calibration_info["use_flag"] != result[2]: return {"gain": 1.0, "offset": 0.0, "threshold": 0, "is_use": True} else: return { "gain": result[0], "offset": result[1], "threshold": threshold, "is_use": True }
class Wolverine(SGModuleDriver): ''' Wolverine is a compact version of the digital multimeter which internal ADC resolution is 24 bit. It can be used as high performance DMM to measure DC voltage and small signal DC current. In this class, adc channel 0 is current channel, adc channel 1 is voltage channel. DMM001 support signal measurement and continuous measurement. Note that if range_ctrl0 and range_ctrl1 not given, internal submodule GPIO device of MIX_DAQT1 will be used to control range. Note that calibration default is enabled. This class is legacy driver for normal boot. Args: i2c: instance(I2C)/None, which is used to control nct75 and cat24c32. If not given, emulator will be created. ad7175: instance(ADC)/None, Class instance of AD7175, if not using this parameter, will create emulator range_ctrl_pin: instance(GPIO), This can be Pin or xilinx gpio, used to control range. meter_ctrl_pin: instance(GPIO), This can be Pin or xilinx gpio, used to control measure channel ipcore: instance(MIXDAQT1SGR)/string, MIXDAQT1SGR ipcore driver instance or device name string, if given, user should not use ad7175. Examples: Example for using no-aggregate IP: # normal init ad7175 = MIXAd7175SG('/dev/MIX_AD717X_0', 5000) i2c = I2C('/dev/i2c-1') gpio = GPIO(i2c) range_ctrl_pin = Pin(gpio, 1) meter_ctrl_pin = Pin(gpio, 3) wolverine = Wolverine(i2c, ad7175, range_ctrl_pin=range_ctrl_pin, meter_ctrl_pin=meter_ctrl_pin) # using ipcore device name string i2c = I2C('/dev/i2c-1') gpio = GPIO(i2c) range_ctrl_pin = Pin(gpio, 1) meter_ctrl_pin = Pin(gpio, 3) wolverine = Wolverine(i2c, '/dev/MIX_AD717X_0', range_ctrl_pin=range_ctrl_pin, meter_ctrl_pin=meter_ctrl_pin) Example for using aggregate IP: # normal init i2c = I2C('/dev/i2c-1') daqt1 = MIXDAQT1SGR('/dev/MIX_DAQT1', ad717x_chip='AD7175', ad717x_mvref=5000, use_spi=False, use_gpio=True) wolverine = Wolverine(i2c, ipcore=daqt1) # using ipcore device name i2c = I2C('/dev/i2c-1') wolverine = Wolverine(i2c, ipcore='/dev/MIX_DAQT1') Example for measuring voltage/current: wolverine.disable_continuous_sampling() wolverine.set_measure_path('5V') result = wolverine.read_measure_value() print("voltage={}, unit is mV".format(result)) result = wolverine.read_measure_list(count=5) print("voltage_list={}, unit is mV".format(result)) wolverine.set_measure_path('2mA') result = wolverine.read_measure_value() print("voltage={}, unit is mA".format(result)) result = wolverine.read_measure_list(count=5) print("voltage_list={}, unit is mA".format(result)) Example for continuous measuring: wolverine.enable_continuous_sampling('5V') result = wolverine.read_continuous_sampling_statistics(256) print("5V Result: average={}, max={}, min={}, rms={}".format(result['avg_v1'], result['max_v1'], result['min_v1'], result['rms_v1'])) wolverine.enable_continuous_sampling('2mA') result = wolverine.read_continuous_sampling_statistics(256) print("2mA Result: average={}, max={}, min={}, rms={}".format(result['avg_i'], result['max_i'], result['min_i'], result['rms_i'])) ''' # launcher will use this to match driver compatible string and load driver if matched. compatible = ["GQQ-LTJW-5-030"] rpc_public_api = [ 'set_sinc', 'get_sampling_rate', 'set_measure_path', 'get_measure_path', 'read_measure_value', 'read_measure_list', 'enable_continuous_sampling', 'disable_continuous_sampling', 'read_continuous_sampling_statistics', 'datalogger_start', 'datalogger_end' ] + SGModuleDriver.rpc_public_api def __init__(self, i2c, ad7175=None, range_ctrl_pin=None, meter_ctrl_pin=None, ipcore=None): if ad7175 and range_ctrl_pin and meter_ctrl_pin and not ipcore: if isinstance(ad7175, basestring): axi4 = AXI4LiteBus(ad7175, WolverineDef.PLAD7175_REG_SIZE) self.ad7175 = MIXAd7175SG(axi4, mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK) else: self.ad7175 = ad7175 self.range_ctrl_pin = range_ctrl_pin self.meter_ctrl_pin = meter_ctrl_pin elif not ad7175 and not range_ctrl_pin and not meter_ctrl_pin and ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineDef.MIX_DAQT1_REG_SIZE) self.ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK, use_gpio=True) else: self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x gpio = self.ipcore.gpio self.range_ctrl_pin = Pin(gpio, WolverineDef.RANGE_SEL_BIT) self.meter_ctrl_pin = Pin(gpio, WolverineDef.METER_SEL_BIT) self.tag_pins = [ Pin(gpio, WolverineDef.TAG_BASE_PIN + x, WolverineDef.GPIO_OUTPUT_DIR) for x in range(4) ] elif not ad7175 and range_ctrl_pin and meter_ctrl_pin and ipcore: if isinstance(ipcore, basestring): axi4_bus = AXI4LiteBus(ipcore, WolverineDef.MIX_DAQT1_REG_SIZE) self.ipcore = MIXDAQT1SGR(axi4_bus, 'AD7175', ad717x_mvref=WolverineDef.MVREF, code_polar=WolverineDef.POLAR, clock=WolverineDef.CLOCK, use_gpio=True) else: self.ipcore = ipcore self.ad7175 = self.ipcore.ad717x self.range_ctrl_pin = range_ctrl_pin self.meter_ctrl_pin = meter_ctrl_pin gpio = self.ipcore.gpio self.tag_pins = [ Pin(gpio, WolverineDef.TAG_BASE_PIN + x, WolverineDef.GPIO_OUTPUT_DIR) for x in range(4) ] else: raise WolverineException("Invalid parameter, please check") eeprom = CAT24C32(WolverineDef.EEPROM_DEV_ADDR, i2c) nct75 = NCT75(WolverineDef.NCT75_DEV_ADDR, i2c) super(Wolverine, self).__init__(eeprom, nct75, range_table=wolverine_range_table) self.channel_path = {'range_sel_bit': self.range_ctrl_pin, 'meter_sel_bit': self.meter_ctrl_pin} self.measure_path = dict() self.measure_path['range'] = WolverineDef.VOLT_5V def post_power_on_init(self, timeout=WolverineDef.TIME_OUT): ''' Init wolverine module to a know harware state. This function will set io direction to output and set default range to '5V'. Args: timeout: float, unit Second, execute timeout ''' self.reset(timeout) self.load_calibration() return "done" def reset(self, timeout=WolverineDef.TIME_OUT): ''' Reset the instrument module to a know hardware state. Args: timeout: float, unit Second, execute timeout. ''' self.range_ctrl_pin.set_dir('output') self.meter_ctrl_pin.set_dir('output') self.set_measure_path(WolverineDef.VOLT_5V) self.ad7175.channel_init() self.set_sampling_rate(WolverineDef.DEFAULT_SAMPLE_RATE) def get_driver_version(self): ''' Get wolverine driver version. Returns: string, current driver version. ''' return __version__ def write_module_calibration(self, channel, calibration_vectors): ''' Calculate module calibration and write to eeprom. Xavier timestamp must be synced with host first before call this function. All channels must be calibrated in one day. Args: channel: string, ['5V', '2mA', '100uA'], voltage or current channel calibration_vectors: list, it contains value pairs of module reading and benchmark value got from external equipemnets. [[module_raw1,benchmark1], [module_raw1,benchmark2], ... [module_rawN,benchmarkN]] Returns: string, 'done', execute successful. ''' assert channel in ['5V', '100uA', '2mA'] return super(Wolverine, self).write_module_calibration(channel, calibration_vectors) def set_sinc(self, channel, sinc): ''' wolverineii set digtal filter. Args: channel: string, ['100uA', '2mA', '5V'], set range for different channel. sinc: string, ["sinc5_sinc1", "sinc3"] Example: wolverineii.set_sinc("100uA", "sinc5_sinc1") ''' assert channel in WolverineDef.CHANNEL_CONFIG.keys() assert sinc in WolverineDef.ADC_SINC_SEL self.ad7175.set_sinc(WolverineDef.CHANNEL_CONFIG[channel]['adc_channel'], sinc) def set_sampling_rate(self, sampling_rate): ''' wolverine set sampling rate. Note that sampling rate is not discontinuous, all support sampling rate can be found in ad7175 datasheet. Args: sampling_rate: float, [5~250000], adc measure sampling rate, which is not continuous, please refer to ad7175 datasheet. Returns: string, "done", api execution successful. ''' assert 5 <= sampling_rate <= 250000 channel = self.measure_path['range'] if sampling_rate != self.get_sampling_rate(channel): self.ad7175.set_sampling_rate(WolverineDef.CHANNEL_CONFIG[channel]['adc_channel'], sampling_rate) def get_sampling_rate(self, channel=WolverineDef.VOLT_5V): ''' wolverine Read the sampling rate setting Args: channel: string, ['5V', '2mA', '100uA'], get sampling rate for different channel. Returns: int, value, current module sampling rate in SPS. ''' assert channel in WolverineDef.CHANNEL_CONFIG.keys() return self.ad7175.get_sampling_rate(WolverineDef.CHANNEL_CONFIG[channel]['adc_channel']) def set_measure_path(self, channel=WolverineDef.VOLT_5V): ''' wolverine set measure path. Args: channel: string, ['100uA', '2mA', '5V'], set range for different channel Returns: string, "done", api execution successful. ''' assert channel in WolverineDef.CHANNEL_CONFIG.keys() if channel != self.get_measure_path(): path_bits = WolverineDef.CHANNEL_CONFIG[channel]['path'] for bits in path_bits: self.channel_path[bits[0]].set_level(bits[1]) time.sleep(WolverineDef.RELAY_DELAY_S) self.measure_path.clear() self.measure_path[WolverineDef.SELECT_RANGE_KEY] = channel return "done" def get_measure_path(self): ''' wolverine get measure path. Returns: dict, current channel and range. ''' return self.measure_path def read_measure_value(self, sample_rate=WolverineDef.DEFAULT_SAMPLE_RATE, count=WolverineDef.DEFAULT_COUNT): ''' Read current average value. The returned value is calibrated if calibration mode is `cal` Args: sample_rate (int, optional): set sampling rate of data acquisition, in SPS. Default 1000 count (int, optional): samples count taken for averaging. Default 1 Returns: Int: measured value defined by set_measure_path() Voltage Channel always in mV Current Channel always in mA ''' assert isinstance(sample_rate, int) assert isinstance(count, int) and count >= 1 measure_path = self.get_measure_path() adc_channel = WolverineDef.CHANNEL_CONFIG[measure_path['range']]['adc_channel'] self.set_sampling_rate(sample_rate) cal_item = WolverineDef.CURRENT_CHANNEL + "_" + measure_path['range'] if measure_path['range'] == WolverineDef.VOLT_5V: gain = WolverineDef.VOLTAGE_5V_GAIN cal_item = WolverineDef.VOLTAGE_CHANNEL + "_" + measure_path['range'] elif measure_path['range'] == WolverineDef.CURR_100UA: gain = WolverineDef.CURRENT_100UA_GAIN sample_res = WolverineDef.CURRENT_100UA_SAMPLE_RES else: gain = WolverineDef.CURRENT_2MA_GAIN sample_res = WolverineDef.CURRENT_2MA_SAMPLE_RES target_data = list() for x in range(count): voltage = self.ad7175.read_volt(adc_channel) adc_value = (voltage / gain) if \ measure_path['range'] == WolverineDef.VOLT_5V else \ voltage / gain / sample_res adc_value = self.calibrate(cal_item, adc_value) target_data.append(adc_value) target_value = sum(target_data) / count return target_value def read_measure_list(self, sample_rate=WolverineDef.DEFAULT_SAMPLE_RATE, count=WolverineDef.DEFAULT_COUNT): ''' For example if count is 5, the return list can be: [3711, 3712, 3709, 3703, 3702]. The returned value is calibrated if calibration mode is `cal` Args: sample_rate (int, optional): set sampling rate of data acquisition, in SPS. Default 1000 count (int, optional): samples count taken for averaging. Default 1 Returns: List: measured value defined by set_measure_path() Voltage Channel always in mV Current Channel always in mA ''' assert isinstance(sample_rate, int) assert isinstance(count, int) and count >= 1 measure_path = self.get_measure_path() adc_channel = WolverineDef.CHANNEL_CONFIG[measure_path['range']]['adc_channel'] self.set_sampling_rate(sample_rate) cal_item = WolverineDef.CURRENT_CHANNEL + "_" + measure_path['range'] if measure_path['range'] == WolverineDef.VOLT_5V: gain = WolverineDef.VOLTAGE_5V_GAIN cal_item = WolverineDef.VOLTAGE_CHANNEL + "_" + measure_path['range'] elif measure_path['range'] == WolverineDef.CURR_100UA: gain = WolverineDef.CURRENT_100UA_GAIN sample_res = WolverineDef.CURRENT_100UA_SAMPLE_RES else: gain = WolverineDef.CURRENT_2MA_GAIN sample_res = WolverineDef.CURRENT_2MA_SAMPLE_RES target_data = list() for x in range(count): voltage = self.ad7175.read_volt(adc_channel) adc_value = (voltage / gain) if \ measure_path['range'] == WolverineDef.VOLT_5V else \ (voltage / gain / sample_res) adc_value = self.calibrate(cal_item, adc_value) target_data.append(adc_value) return target_data def enable_continuous_sampling(self, channel=WolverineDef.VOLT_5V, sample_rate=WolverineDef.DEFAULT_SAMPLE_RATE, down_sample=WolverineDef.DEFAULT_DOWN_SAMPLE, selection=WolverineDef.DEFAULT_SELECTION): ''' This function enables continuous sampling and data throughput upload to upper stream. Down sampling is supported. For example: when down_sample =5, selection=max, select the maximal value from every 5 samples, so the actual data rate is reduced by 5. The output data inflow is calibrated if calibration mode is `cal` During continuous sampling, the setting functions, like set_calibration_mode(), set_measure_path(), cannot be called. Args: channel (string): '5V': voltage channel #1 '100uA': 100uA current channel '2mA': 2mA current channel Default: 5V sample_rate (int): set sampling rate of data acquisition, in SPS. Default 1000 down_sample (int): down sample rate for decimation. selection (string): 'max'|'min'. This parameter takes effect as long as down_sample is higher than 1. Default 'max' Returns: Str: 'done' ''' assert channel in WolverineDef.CHANNEL_CONFIG.keys() adc_channel = WolverineDef.CHANNEL_CONFIG[channel]['adc_channel'] self.ad7175.disable_continuous_sampling(adc_channel) time.sleep(WolverineDef.SWITCH_DELAY) self.ad7175.enable_continuous_sampling(adc_channel, sample_rate, down_sample, selection) self.measure_path[WolverineDef.SELECT_RANGE_KEY] = channel return "done" def disable_continuous_sampling(self): ''' This function disables continuous sampling and data throughput upload to upper stream. This function can only be called in continuous mode, a.k.a, after enable_continuous_sampling() function is called. Returns: Str: 'done' ''' measure_path = self.get_measure_path() adc_channel = WolverineDef.CHANNEL_CONFIG[measure_path['range']]['adc_channel'] self.ad7175.disable_continuous_sampling(adc_channel) return "done" def read_continuous_sampling_statistics(self, count=WolverineDef.DEFAULT_COUNT): ''' This function takes a number of samples to calculate RMS/average/max/min value of the set of sampled value.This function can only be called in continuous mode, a.k.a, after enable_continuous_sampling() function is called. Return 0 for the channels that are not enabled. The returned value is calibrated if calibration mode is `cal` Args: count (int): samples count taken for calculation. Default 1 Returns: Dict: { (rms_v1, <RMS in mVrms>), (avg_v1, <average in mVrms>), (max_v1, <maximal in mV>), (min_v1, <minimal in mV>), (rms_i, <RMS in mArms>), (avg_i, <average in mArms>), (max_i, <maximal in mA>), (min_i, <minimal in mA>) } for voltage voltage channel #1 and #2. ''' assert isinstance(count, int) and count >= 1 measure_path = self.get_measure_path() adc_channel = WolverineDef.CHANNEL_CONFIG[measure_path['range']]['adc_channel'] channel_data = list() try: channel_data = self.ad7175.get_continuous_sampling_voltage( adc_channel, count) except Exception: raise min_data = min(channel_data) max_data = max(channel_data) sum_Data = sum(channel_data) avg_data = sum_Data / len(channel_data) suqare_sum_data = sum([x**2 for x in channel_data]) rms_data = math.sqrt(suqare_sum_data / len(channel_data)) result = dict() cal_item = WolverineDef.CURRENT_CHANNEL + "_" + measure_path['range'] suffix = WolverineDef.CHANNEL_CONFIG[measure_path['range']]['suffix'] if measure_path['range'] == WolverineDef.VOLT_5V: gain = WolverineDef.VOLTAGE_5V_GAIN rms = rms_data / gain voltage = avg_data / gain max_voltage = max_data / gain min_voltage = min_data / gain cal_item = WolverineDef.VOLTAGE_CHANNEL + "_" + measure_path['range'] voltage = self.calibrate(cal_item, voltage) result['rms_' + suffix] = (rms, 'mVrms') result['avg_' + suffix] = (voltage, 'mV') result['max_' + suffix] = (max_voltage, 'mV') result['min_' + suffix] = (min_voltage, 'mV') return result elif measure_path['range'] == WolverineDef.CURR_100UA: gain = WolverineDef.CURRENT_100UA_GAIN sample_res = WolverineDef.CURRENT_100UA_SAMPLE_RES else: gain = WolverineDef.CURRENT_2MA_GAIN sample_res = WolverineDef.CURRENT_2MA_SAMPLE_RES rms = (rms_data / gain) / sample_res current = (avg_data / gain) / sample_res max_current = (max_data / gain) / sample_res min_current = (min_data / gain) / sample_res current = self.calibrate(cal_item, current) result['rms_' + suffix] = (rms, 'mArms') result['avg_' + suffix] = (current, 'mA') result['max_' + suffix] = (max_current, 'mA') result['min_' + suffix] = (min_current, 'mA') return result def datalogger_start(self, tag=0): ''' Start labeling the samples for on a period of time for calculation. This function can only be called in continuous mode, a.k.a, after enable_continuous_sampling() function is called. Lable shall be on both channels if they are both enabled. Args: tag (int, [0, 0x0f]): the value is low 4 bits are valid, from 0x00 to 0x0f. Returns: Str: 'done' ''' assert tag & 0x0f == tag for i in range(4): self.tag_pins[i].set_level((tag >> i) & 0x1) return "done" def datalogger_end(self): ''' Stop labeling the samples. This function can only be called after enable_continuous_sampling() and datalogger_start() are called. Returns: Str: 'done' ''' for i in range(4): self.tag_pins[i].set_level(0) return "done"
class AD9628(object): ''' The AD9628 is a monolithic, dual-channel, 1.8V supply, 12-bit, 125MSPS/105MSPS analog-to-digital converter (ADC). It features a high performance sample-and-hold circuit and onchip voltage reference. The digital output data is presented in offset binary, Gray code, or twos complement format. A data output clock (DCO) is provided for each ADC channel to ensure proper latch timing with receiving logic. 1.8V CMOS or LVDS output logic levels are supported. Output data can also be multiplexed onto a single output bus. ClassType = ADC Args: spi_bus: instance(QSPI)/None, MIXQSPISG class instance, if not using, will create emulator. pdwn_ctrl: instance(GPIO)/None, Class instance of GPIO, which is used to control ad9628 pdwn_ctrl signal, default None for not use. oeb_ctrl: instance(GPIO)/None, Class instance of GPIO, which is used to control ad9628 oeb_ctrl signal, default None for not use. cs_ctrl: instance(GPIO)/None, Class instance of GPIO, which is used to control ad9628 cs_ctrl signal, default None for not use. use_cs: Bool('True'/'False'), determine if CS is used internally. Examples: pdwn_ctrl = GPIO(cat9555, 6) oeb_ctrl = GPIO(cat9555, 7) cs_ctrl = GPIO(cat9555, 12) axi4_bus = AXI4LiteBus('/dev/MIX_DUT_SPI_0', 256) spi_bus = MIXQSPISG(axi4_bus) ad9628 = AD9628(spi_bus, pdwn_ctrl, oeb_ctrl, cs_ctrl) ''' def __init__(self, spi_bus=None, pdwn_ctrl=None, oeb_ctrl=None, cs_ctrl=None, use_cs=True): if(spi_bus is None and pdwn_ctrl is None and oeb_ctrl is None): self.spi_bus = MIXQSPISGEmulator("ad9628_emulator", 256) self.pdwn = Pin(None, 6) self.oeb = Pin(None, 7) elif(spi_bus is not None and pdwn_ctrl is not None and oeb_ctrl is not None): self.spi_bus = spi_bus self.pdwn = pdwn_ctrl self.oeb = oeb_ctrl else: raise AD9628RException('__init__ error! Please check the parameters') self.use_cs = use_cs if(self.use_cs is True and cs_ctrl is not None): self.cs = cs_ctrl elif(self.use_cs is False and cs_ctrl is None): self.cs = Pin(None, 12) else: raise AD9628RException('cs use error! Please check the parameters') def read_register(self, reg_addr): ''' AD9628 internal function to read register Args: reg_addr: hexmial, [0~0x102], The register range is 0-0x102 in datasheet, register to be read. Returns: int, value, register read data. Examples: rd_data = ad9628.read_register(0x01) print(rd_data) # rd_data will be like 0x05 ''' assert isinstance(reg_addr, int) assert 0 <= reg_addr <= 0x102 if self.use_cs is True: self.cs.set_level(0) reg_address = (1 << 15) + (reg_addr & 0x3FF) read_data = 0 write_date = [(reg_address >> 8) & 0xFF, reg_address & 0xFF] reg_value = self.spi_bus.transfer(write_date, 1, False) read_data = reg_value[0] if self.use_cs is True: self.cs.set_level(1) return read_data def write_register(self, reg_addr, reg_value): ''' AD9628 internal function to write register Args: reg_addr: hexmial, [0~0x102], register to be write. reg_value: hexmial, [0~0xff], data to be write. Examples: ad9628.write_register(0x01, 0x02) ''' assert isinstance(reg_addr, int) assert isinstance(reg_value, int) assert 0 <= reg_addr <= 0x102 assert 0 <= reg_value <= 0xFF if self.use_cs is True: self.cs.set_level(0) reg_address = reg_addr & 0x3FF write_date = [(reg_address >> 8) & 0xFF, reg_address & 0xFF, reg_value] ret = self.spi_bus.write(write_date) if self.use_cs is True: self.cs.set_level(1) if ret is False: return False return True def get_chip_id(self): ''' AD9628 internal function to get AD9628's chip ID number Returns: int, value, variable which to store the chip ID. Examples: id = ad9628.get_chip_id() print(id) ''' chip_id = self.read_register(AD9628Def.REGISTER_ADDRESS["chip_id"]) return chip_id def get_clock_speed_grade(self): ''' AD9628 internal function to check AD9628's input clock speed supported, 105000000SPS or 125000000SPS. Returns: int, value, Return 105000000SPS or 125000000SPS. Examples: grade = ad9628.clock_speed_grade() print(grade) ''' grade = 0 rd_data = self.read_register( AD9628Def.REGISTER_ADDRESS["chip_grade_id"]) if (((rd_data) >> 4) & 0x07) == 0x04: grade = 105000000 elif (((rd_data) >> 4) & 0x07) == 0x05: grade = 125000000 else: raise AD9628RException('get clock speed grade fail!') return grade def select_channel(self, channel): ''' AD9628 internal function to select which channel to receive SPI command. Args: channel: string, ["A", "B", "BOTH"]. select which channel to receive SPI command. Examples: ad9628.select_channel("A") ''' assert channel in AD9628Def.CHANNEL_SELECT self.write_register( AD9628Def.REGISTER_ADDRESS["device_index"], AD9628Def.CHANNEL_SELECT[channel]) def get_sampling_rate(self): ''' AD9628 internal function to get sample rate. Returns: int, value, Return 80000000SPS, 105000000SPS or 125000000SPS. Examples: rate = ad9628.get_sampling_rate() print(rate) ''' sample_rate = 0 rd_data = self.read_register(AD9628Def.REGISTER_ADDRESS["sample_rate"]) if (rd_data & 0x07) == 0x03: sample_rate = 80000000 elif (rd_data & 0x07) == 0x04: sample_rate = 105000000 elif (rd_data & 0x07) == 0x05: sample_rate = 125000000 else: raise AD9628RException('get sampling rate fail!') return sample_rate def setup(self, type, format, msps, bits): ''' AD9628 internal function to Initial AD9628. Args: type: string, ["CMOS", "LVDS_ANSI", "LVDS_REDUCED"], configure the data output type of the AD9628. format: string, ["OFFSET_BIN", "TWOS_COMPLEMENT", "GRAY_CODE"], configure the data output format of the AD9628. msps: int, [80000000, 105000000, 125000000], configure the sample speed of data output of the AD9628. bits: string, ["WIDTH_10", "WIDTH_12"], configure the output data bits of the AD9628. Examples: ad9628.setup("LVDS_ANSI", "OFFSET_BIN", "125000000", "WIDTH_12") ''' assert type in AD9628Def.OUTPUT_TYPE assert format in AD9628Def.OUTPUT_FORMAT assert msps in AD9628Def.SAMPLE_SPEED assert bits in ["WIDTH_10", "WIDTH_12"] # Digital Output Enable Function self.oeb.set_level(0) # self.pdwn.set_level(0), external power down. self.power_mode("EXTERNAL", "POWER_DOWN") # Internal power-down mode ,register digital reset. self.power_mode("INTERNAL", "DIGITAL_RESET") # Set power mode need to reset it and wait 1 millisecond time.sleep(AD9628Def.SLEEP_TIME) self.power_mode("INTERNAL", "POWER_ON") output_mode = AD9628Def.OUTPUT_TYPE[type] | AD9628Def.OUTPUT_FORMAT[format] self.write_register( AD9628Def.REGISTER_ADDRESS["output_mode"], output_mode) sample_rate_bits = AD9628Def.RESOLUTION_12_BITS if bits == "WIDTH_10": sample_rate_bits = AD9628Def.RESOLUTION_10_BITS elif bits == "WIDTH_12": sample_rate_bits = AD9628Def.RESOLUTION_12_BITS else: raise AD9628RException('width bits set fail!') sample = AD9628Def.SAMPLE_SPEED[msps] | sample_rate_bits self.write_register(AD9628Def.REGISTER_ADDRESS["sample_rate"], sample) self.write_register( AD9628Def.REGISTER_ADDRESS["transfer_addr"], AD9628Def.SYNC_TRANSFER) def clock_phase(self, dco_invert_ctrl, phase_ratio): ''' AD9628 internal function to input clock divider phase adjust relative to the encode clock. Args: dco_invert_ctrl: string, ["NOT_INVERT", "INVERT"], control DCO(dat clock output) invert or not. phase_ratio: string, ["NO_DELAY", "ONE_INPUT", "TWO_INPUT", "THREE_INPUT", "FOUR_INPUT", "FIVE_INPUT", "SIX_INPUT", "SEVEN_INPUT"], selection of clock delays into the input clock divider. Examples: ad9628.clock_phase("INVERT", "ONE_INPUT") ''' assert dco_invert_ctrl in ["NOT_INVERT", "INVERT"] assert phase_ratio in AD9628Def.PHASE_INPUT_CLOCK_CYCLES phase_delay = AD9628Def.PHASE_INPUT_CLOCK_CYCLES[phase_ratio] if dco_invert_ctrl == "INVERT": phase_con = (AD9628Def.INVERT_DCO | phase_delay) else: phase_con = (AD9628Def.NOT_INVERT_DCO | phase_delay) self.write_register( AD9628Def.REGISTER_ADDRESS["clock_phase"], phase_con) def clock_divide(self, divide_ratio, div_next_sync, div_sync_en): ''' AD9628 internal function to config clock divider's divide ratio. Args: divide_ratio: string, ["BY_1", "BY_2", "BY_3", "BY_4", "BY_5", "BY_6", "BY_7", "BY_8"], config clock divider's divide ratio. div_next_sync: string, ["NEX_SYNC", "NEX_ASYNC"], config divider next sync only open or not. div_sync_en: string, ["SYNC_OPEN", "SYNC_CLOSE"], config divider sync open or not. Examples: ad9628.clock_divide("BY_1", "NEX_SYNC", "SYNC_OPEN") ''' assert divide_ratio in AD9628Def.CLOCK_DIVIDE assert div_next_sync in ["NEX_SYNC", "NEX_ASYNC"] assert div_sync_en in ["SYNC_OPEN", "SYNC_CLOSE"] divider_con = AD9628Def.CLOCK_DIVIDE[divide_ratio] self.write_register( AD9628Def.REGISTER_ADDRESS["clock_divide"], divider_con) if div_next_sync == "NEX_SYNC": if div_sync_en == "SYNC_OPEN": sync_con = (AD9628Def.DIV_NEX_SYNC | AD9628Def.DIV_SYNC_OPEN) else: sync_con = (AD9628Def.DIV_NEX_SYNC | AD9628Def.DIV_SYNC_CLOSE) else: if div_sync_en == "SYNC_OPEN": sync_con = (AD9628Def.DIV_NEX_ASYNC | AD9628Def.DIV_SYNC_OPEN) else: sync_con = (AD9628Def.DIV_NEX_ASYNC | AD9628Def.DIV_SYNC_CLOSE) self.write_register(AD9628Def.REGISTER_ADDRESS["sync_ctrl"], sync_con) def clock_stabilizer(self, statu): ''' AD9628 internal function to global clock duty cycle stabilizer control. Args: statu: string, ["DIS_STABILIZE"/"EN_STABILIZE"], control clock duty cycle stabilizer open or not. Examples: ad9628.clock_stabilizer("EN_STABILIZE") ''' assert statu in ["DIS_STABILIZE", "EN_STABILIZE"] if statu == "EN_STABILIZE": stabilizer_con = 0x01 else: stabilizer_con = 0x00 self.write_register( AD9628Def.REGISTER_ADDRESS["global_clock"], stabilizer_con) def cmos_output_adjust(self, dco_strength, data_strength): ''' AD9628 internal function to config CMOS output driver strength properties. Args: dco_strength: string, ["1X", "2X", "3X", "4X"], config DCO strength level when chip config in CMOS mode. data_strength: string, ["1X", "2X", "3X", "4X"], config data strength level when chip config in CMOS mode. Examples: ad9628.cmos_output_adjust("1X", "1X") ''' assert dco_strength in AD9628Def.DCO_STRENGTH assert data_strength in AD9628Def.DATA_STRENGTH cmos_adjust = AD9628Def.DCO_STRENGTH[dco_strength] | AD9628Def.DATA_STRENGTH[data_strength] self.write_register( AD9628Def.REGISTER_ADDRESS["output_adjust"], cmos_adjust) def data_output_delay(self, dco_delay_en, data_delay_en, delay): ''' AD9628 internal function to sets the fines output delay of the output clock, not change the internal timeing. Args: dco_delay_en: string, ["DCO_DELAY_OPEN", "DCO_DELAY_CLOSE"], control DCO delay function open or not. data_delay_en: string, ["DATA_DELAY_OPEN", "DATA_DELAY_CLOSE"], control data delay function open or not. delay: string, ["0_56_NS", "1_12_NS", "1_68_NS", "2_24_NS", "2_80_NS", "3_36_NS", "3_92_NS", "4_48_NS"], select data delay level. Examples: ad9628.data_output_delay("DCO_DELAY_OPEN", "DATA_DELAY_OPEN", "1_12_NS") ''' assert delay in AD9628Def.DATA_OUTPUT_DELAY assert dco_delay_en in ["DCO_DELAY_OPEN", "DCO_DELAY_CLOSE"] assert data_delay_en in ["DATA_DELAY_OPEN", "DATA_DELAY_CLOSE"] output_delay = AD9628Def.DATA_OUTPUT_DELAY[delay] if dco_delay_en == "DCO_DELAY_OPEN": if data_delay_en == "DATA_DELAY_OPEN": output_delay = (AD9628Def.DCO_DELAY_OPEN | AD9628Def.DATA_DELAY_OPEN | (output_delay)) else: output_delay = (AD9628Def.DCO_DELAY_OPEN | AD9628Def.DATA_DELAY_CLOSE | (output_delay)) else: if data_delay_en == "DATA_DELAY_OPEN": output_delay = (AD9628Def.DCO_DELAY_CLOSE | AD9628Def.DATA_DELAY_OPEN | (output_delay)) else: output_delay = (AD9628Def.DCO_DELAY_CLOSE | AD9628Def.DATA_DELAY_CLOSE | (output_delay)) self.write_register( AD9628Def.REGISTER_ADDRESS["output_delay"], output_delay) def vref_set(self, vref, overrange_en): ''' AD9628 internal function to adjuse AD9628 VREF level. Args: vref: string, ["1_00", "1_14", "1_33", "1_60", "2_00"], config the inter VREF level. overrange_en: string, ["OVERRANGE", "NOT_OVERRANGE"], config output overrange enable or not. Examples: ad9628.vref_set("1_00", "OVERRANGE") ''' assert vref in AD9628Def.VREF_LEVEL assert overrange_en in ["OVERRANGE", "NOT_OVERRANGE"] overrange_con = 0x01 if overrange_en == "OVERRANGE": overrange_con = 0x01 else: overrange_con = 0x00 self.write_register( AD9628Def.REGISTER_ADDRESS["overrange_reg"], overrange_con) vref_con = AD9628Def.VREF_LEVEL[vref] self.write_register(AD9628Def.REGISTER_ADDRESS["vref_reg"], vref_con) def _internal_power_mode(self, work_mode): ''' AD9628 internal function to config AD9628 internal power mode. Args: work_mode: string, ["POWER_ON", "POWER_DOWN", "STANDBY", "DIGITAL_RESET"], select AD9628's work mode. Examples: ad9628._internal_power_mode("POWER_ON") ''' assert work_mode in AD9628Def.POWER_MODE power_con = 0 power_con = self.read_register( AD9628Def.REGISTER_ADDRESS["power_mode"]) power_con = ((power_con) & 0xFC) | AD9628Def.POWER_MODE[work_mode] self.write_register( AD9628Def.REGISTER_ADDRESS["power_mode"], power_con) def _external_power_mode(self, work_mode): ''' AD9628 internal function to config AD9628 external power mode. Args: work_mode: string, ["POWER_ON", "POWER_DOWN"], select AD9628's work mode. Examples: ad9628._external_power_mode("POWER_ON") ''' assert work_mode in ["POWER_ON", "POWER_DOWN"] if self.pdwn is None: raise AD9628RException('power mode set fail!') if work_mode == "POWER_ON": self.pdwn.set_level(1) else: self.pdwn.set_level(0) def power_mode(self, refer, work_mode): ''' AD9628 internal function to config AD9628 chip power mode. Args: refer: string, ["INTERNAL", "EXTERNAL"], select internal or external power mode for controling. work_mode: string, ["POWER_ON", "POWER_DOWN", "STANDBY", "DIGITAL_RESET"], select AD9628's work mode. Examples: ad9628.power_mode("EXTERNAL", "POWER_ON") ''' assert refer in ["INTERNAL", "EXTERNAL"] if refer == "INTERNAL": self._internal_power_mode(work_mode) else: self._external_power_mode(work_mode) def soft_reset(self): ''' AD9628 internal function to AD9628 soft reset. Examples: ad9628.soft_reset() ''' port_con = self.read_register( AD9628Def.REGISTER_ADDRESS["port_config"]) port_con = ((port_con) | AD9628Def.SOFT_RESET) self.write_register( AD9628Def.REGISTER_ADDRESS["port_config"], port_con) def chop_mode_open(self): ''' AD9628 internal function to AD9628 enhancement control enable. Examples: ad9628.chop_mode_open() ''' self.write_register( AD9628Def.REGISTER_ADDRESS["enhancement_ctrl"], AD9628Def.CHOP_MODE_OPEN) def chop_mode_close(self): ''' AD9628 internal function to AD9628 enhancement control disable. Examples: ad9628.chop_mode_close() ''' self.write_register( AD9628Def.REGISTER_ADDRESS["enhancement_ctrl"], AD9628Def.CHOP_MODE_CLOSE) def test_mode_config(self, user_mode, rst_pn_l_en, rst_pn_s_en, output_mode): ''' AD9628 internal function to Config test data to AD9628's data output pins. Args: user_mode: string, ["SINGLE", "ALTERNATE_REPEAT", "ONCE", "ALTERNATE_ONCE"], select user test mode. rst_pn_l_en: string, ["EN_RESET_L", "DIS_RESET_L"], control reset PN long gen enable or not. rst_pn_s_en: string, ["EN_RESET_S", "DIS_RESET_S"], control reset PN short gen enable or not. output_mode: string, ["OFF", "MIDSCALE_SHORT", "POSITIVE_FS", "NEGATIVE_FS", "ALTERNATING_CHECKERBOARD", "PN_LONG_SEQUENCE", "PN_SHORT_SEQUENCE", "ONE_WORD_TOGGLE", "USER_TEST_MODE", "RAMP_OUTPUT"], select user output mode. Examples: ad9628.test_mode_config("SINGLE", "EN_RESET_L", "EN_RESET_S", "OFF") ''' assert rst_pn_l_en in ["EN_RESET_L", "DIS_RESET_L"] assert rst_pn_s_en in ["EN_RESET_S", "DIS_RESET_S"] assert user_mode in AD9628Def.TEST_MODE assert output_mode in AD9628Def.OUTPUT_TEST_MODE user_test_mode_con = AD9628Def.TEST_MODE[user_mode] output_test_mode_con = AD9628Def.OUTPUT_TEST_MODE[output_mode] test_mode_con = (user_test_mode_con | AD9628Def.DIS_RESET_PN_LONG_GEN | AD9628Def.DIS_RESET_PN_SHORT_GEN | output_test_mode_con) if rst_pn_l_en == "EN_RESET_L": if rst_pn_s_en == "EN_RESET_S": test_mode_con = (user_test_mode_con | AD9628Def.EN_RESET_PN_LONG_GEN | ( AD9628Def.EN_RESET_PN_SHORT_GEN) | output_test_mode_con) else: test_mode_con = (user_test_mode_con | AD9628Def.EN_RESET_PN_LONG_GEN | ( AD9628Def.DIS_RESET_PN_SHORT_GEN) | output_test_mode_con) else: if rst_pn_s_en == "EN_RESET_S": test_mode_con = ((user_test_mode_con) | AD9628Def.DIS_RESET_PN_LONG_GEN | ( AD9628Def.EN_RESET_PN_SHORT_GEN) | (output_test_mode_con)) else: test_mode_con = ((user_test_mode_con) | AD9628Def.DIS_RESET_PN_LONG_GEN | ( AD9628Def.DIS_RESET_PN_SHORT_GEN) | (output_test_mode_con)) self.write_register( AD9628Def.REGISTER_ADDRESS["test_mode"], test_mode_con) def bist_mode_open(self, init_sequence): ''' AD9628 internal function to BIST(build in self test) mode open. Args: init_sequence: string, ["INIT_SEQ", "NOT_INIT_SEQ"], init sequence or not in BIST(build in self test) mode. Examples: ad9628.bist_mode_open("INIT_SEQ") ''' assert init_sequence in ["INIT_SEQ", "NOT_INIT_SEQ"] bist_mode_con = AD9628Def.INIT_BIST_SEQ if init_sequence == "INIT_SEQ": bist_mode_con = AD9628Def.INIT_BIST_SEQ else: bist_mode_con = AD9628Def.NOT_INIT_BIST_SEQ self.write_register( AD9628Def.REGISTER_ADDRESS["bist_reg"], bist_mode_con) def bist_mode_close(self): ''' AD9628 internal function to BIST(build in self test) mode close. Examples: ad9628.bist_mode_close() ''' self.write_register( AD9628Def.REGISTER_ADDRESS["bist_reg"], 0X00) def customer_offset_adjust(self, data): ''' AD9628 internal function to Customer offset adjust when AD9628 config in twos complement format output type. Args: data: hexmial, [0x00~0xFF], write register value. Examples: ad9628.customer_offset_adjust(0x00) ''' assert isinstance(data, int) assert 0 <= data <= 0xFF self.write_register( AD9628Def.REGISTER_ADDRESS["customer_offset"], data) def user_define_pattern(self, pattern, format_data): ''' AD9628 internal function to AD9628 user pattern definetion config. Args: pattern: string, ["PATTERN_1", "PATTERN_2"], select which pattern to control. format_data: hexmial, [0x00~0xFFFF], write register value. Examples: ad9628.user_define_pattern("PATTERN_1", 0x01) ''' assert isinstance(format_data, int) assert pattern in ["PATTERN_1", "PATTERN_2"] assert 0x00 <= format_data <= 0xFFFF if pattern == "PATTERN_1": reg_address = AD9628Def.REGISTER_ADDRESS["user_pattern_1_L"] & 0x3FF else: reg_address = AD9628Def.REGISTER_ADDRESS["user_pattern_2_L"] & 0x3FF write_date = [] write_date.append((reg_address & 0xFF00) >> 8) write_date.append(reg_address & 0x00FF) write_date.append(format_data >> 8 & 0xFF) write_date.append(format_data & 0xFF) self.spi_bus.write(write_date) def user_io_ctrl(self, io, state): ''' AD9628 internal function to multiplexing pins control. Args: io: string, ["OEB", "PDWN", "VCM", "SDIO"], select which IO to control. state: string, ["EN_PIN", "DIS_PIN"], control pin's function disable(effective when pin is PDWN) or enable. Examples: ad9628.user_io_ctrl("OEB", "EN_PIN") ''' assert io in ["OEB", "PDWN", "VCM", "SDIO"] assert state in ["EN_PIN", "DIS_PIN"] if io == "OEB": rd_data = self.read_register( AD9628Def.REGISTER_ADDRESS["user_ctrl_reg_2"]) if state == "EN_PIN": wr_data = (rd_data & 0x7F | AD9628Def.EN_OEB_PIN) else: wr_data = (rd_data & 0x7F | AD9628Def.DIS_OEB_PIN) return self.write_register( AD9628Def.REGISTER_ADDRESS["user_ctrl_reg_2"], wr_data) elif io == "PDWN": rd_data = self.read_register( AD9628Def.REGISTER_ADDRESS["power_mode"]) if state == "EN_PIN": wr_data = (rd_data & 0xDF | AD9628Def.EN_PDWN_PIN) else: wr_data = (rd_data & 0xDF | AD9628Def.DIS_PDWN_PIN) return self.write_register( AD9628Def.REGISTER_ADDRESS["power_mode"], wr_data) elif io == "VCM": if state == "EN_PIN": wr_data = AD9628Def.VCM_POWER_ON else: wr_data = AD9628Def.VCM_POWER_DOWN return self.write_register( AD9628Def.REGISTER_ADDRESS["user_ctrl_reg_3"], wr_data) elif io == "SDIO": rd_data = self.read_register( AD9628Def.REGISTER_ADDRESS["user_ctrl_reg_2"]) if state == "EN_PIN": wr_data = (rd_data & 0xFE | 1) else: wr_data = (rd_data & 0xFE | 0) return self.write_register( AD9628Def.REGISTER_ADDRESS["user_ctrl_reg_2"], wr_data)
def __init__(self, i2c, adc_rst_pin=None, i2s_rx_en_pin=None, dac_rst_pin=None, i2s_tx_en_pin=None, sample_rate=192000, ipcore=None): assert sample_rate > 0 and sample_rate <= DazzlerDef.MAX_SAMPLING_RATE if i2c is None: self.eeprom = EepromEmulator("cat24cxx_emulator") self.nct75 = NCT75Emulator("nct75_emulator") else: self.eeprom = CAT24C32(DazzlerDef.EEPROM_I2C_ADDR, i2c) self.nct75 = NCT75(DazzlerDef.SENSOR_I2C_ADDR, i2c) MIXBoard.__init__(self, self.eeprom, self.nct75, cal_table=dazzler_calibration_info, range_table=dazzler_range_table) if ipcore: if isinstance(ipcore, basestring): axi4 = AXI4LiteBus(ipcore, DazzlerDef.MIX_AUT1_REG_SIZE) self.ip = MIXAUT1SGR(axi4) else: self.ip = ipcore self.analyzer = self.ip.analyzer self.signal_source = self.ip.signal_source self.adc_rst_pin = adc_rst_pin or Pin(self.ip.gpio, DazzlerDef.ADC_RESET_PIN) self.i2s_rx_en_pin = i2s_rx_en_pin or Pin(self.ip.gpio, DazzlerDef.I2S_RX_EN_PIN) self.dac_rst_pin = dac_rst_pin or Pin(self.ip.gpio, DazzlerDef.DAC_RESET_PIN) self.i2s_tx_en_pin = i2s_tx_en_pin or Pin(self.ip.gpio, DazzlerDef.I2S_TX_EN_PIN) elif (not ipcore and not adc_rst_pin and not i2s_rx_en_pin and not dac_rst_pin and not i2s_tx_en_pin): self.analyzer = MIXFftAnalyzerSGEmulator( "mix_fftanalyzer_sg_emulator") self.signal_source = MIXSignalSourceSGEmulator( "mix_signalsource_sg_emulator") self.adc_rst_pin = Pin(None, DazzlerDef.ADC_RESET_PIN) self.i2s_rx_en_pin = Pin(None, DazzlerDef.I2S_RX_EN_PIN) self.dac_rst_pin = Pin(None, DazzlerDef.DAC_RESET_PIN) self.i2s_tx_en_pin = Pin(None, DazzlerDef.I2S_TX_EN_PIN) else: if ipcore: raise DazzlerException( "parameter 'ipcore' can not be given at same time with 'analyzer', " "'signal_source', 'adc_rst_pin', 'i2s_rx_en_pin', " "'dac_rst_pin', 'i2s_tx_en_pin'") else: raise DazzlerException( "parameter 'analyzer', 'signal_source', 'adc_rst_pin', " "'i2s_rx_en_pin', 'dac_rst_pin' and 'i2s_tx_en_pin'" " must be given at the same time") self.sample_rate = sample_rate