Source code for ska_low_sps_tpm_api.plugins.adc_ad9695

import time
from time import sleep

from ska_low_sps_tpm_api.base.definitions import *
from ska_low_sps_tpm_api.base.utils import *
from ska_low_sps_tpm_api.plugins.firmwareblock import FirmwareBlock


[docs] class TpmAdc9695(FirmwareBlock): """TpmAdc plugin""" _adc_fullscale_map = { 2.04: 0x0, 1.36: 0xA, 1.47: 0xB, 1.59: 0xC, 1.70: 0xD, 1.81: 0xE, 1.93: 0xF, } _adc_fullscale_reverse_lookup = {v: k for k, v in _adc_fullscale_map.items()}
[docs] @compatibleboards(BoardMake.TpmBoard) @friendlyname("tpm_adc") @maxinstances(16) def __init__(self, board, logger=None, **kwargs): """ TpmAdc initialiser. :param board: Pointer to board instance :param logger: Logger instance """ super(TpmAdc9695, self).__init__(board, logger=logger) if "adc_id" not in kwargs.keys(): raise PluginError("TpmAdc: adc_id required") self._adc_id = kwargs["adc_id"] self._name = kwargs["adc_id"].upper()
[docs] def adc_set_full_scale_config(self, fullscale_voltage): """ Set ADC input full-scale voltage. :param fullscale_voltage: ADC input full-scale Voltage (in V) :type fullscale_voltage: float """ reg_val = self._adc_fullscale_map.get( fullscale_voltage, self._adc_fullscale_map[1.59] ) # Write to ADC input full-scale voltage register self.adc_write_reg(0x1910, reg_val) if fullscale_voltage not in self._adc_fullscale_map: self.logger.warning( f"TpmAdc: Invalid full-scale voltage setting entered. Setting to default: 1.59 V. " f"Options are: {list(self._adc_fullscale_map.keys())}" )
[docs] def adc_get_full_scale_config(self): """ Get ADC input full-scale voltage. :return: ADC input full-scale voltage (in V) :rtype: float """ # Read ADC input full-scale control register fullscale_config = self.adc_read_reg(0x1910) & 0x0F voltage = self._adc_fullscale_reverse_lookup.get(fullscale_config) if voltage is not None: return voltage raise PluginError( f"TpmAdc: Invalid input fullscale setting configured: {hex(fullscale_config)}" )
[docs] def adc_set_vref_high_z(self): """Set ADC Vref pin to High-Z""" self.adc_write_reg(0x08, 0x3) # select both channels self.adc_write_reg(0x18E3, 0x0) # turn off Vcm export self.adc_write_reg(0x18A6, 0x0) # turn off voltage reference export self.adc_write_reg( 0x18E6, 0x0 ) # Central diode VREF pin = high-Z, i.e. use internal voltage ref # fmt: skip
[docs] def adc_jesd204b_init(self): """JESD204B Initialization sequence.""" self.adc_write_reg(0x1228, 0x4F) # Reset JESD204B start-up circuit self.adc_write_reg( 0x1228, 0x0F ) # JESD204B start-up circuit in normal operation # fmt: skip self.adc_write_reg(0x1222, 0x00) # JESD204B PLL force normal operation self.adc_write_reg(0x1222, 0x04) # Reset JESD204B PLL calibration self.adc_write_reg(0x1222, 0x00) # JESD204B PLL normal operation self.adc_write_reg(0x1262, 0x08) # Clear loss of lock bit self.adc_write_reg(0x1262, 0x00) # Loss of lock bit normal operation
[docs] def adc_lane_remap(self, logical_lane_vals): """Lane remapping helper. :param logical_lane_vals: List of 4 logical lane values (0 to 3) mapped to physical lanes 0 to 3 :type logical_lane_vals: list(int) """ self.adc_write_reg(0x5B2, logical_lane_vals[0]) # Physical Lane 0 assignment self.adc_write_reg(0x5B3, logical_lane_vals[1]) # Physical Lane 1 assignment self.adc_write_reg(0x5B5, logical_lane_vals[2]) # Physical Lane 2 assignment self.adc_write_reg(0x5B6, logical_lane_vals[3]) # Physical Lane 3 assignment self.adc_write_reg( 0x5B0, 0x50 ) # Physical Lanes 2 & 3 force power-down (xTPM unused lane) # fmt: skip
[docs] def adc_pll_lock_poll(self): """Poll PLL lock status.""" if ( do_until_eq( lambda: self.adc_read_reg(0x56F) == 0x80, 1, ms_retry=100, s_timeout=5 ) is None ): self.logger.warning(f"{self._name} configuration failed") # TODO: Should an exception be raised if ADC configuration fails? # Currently we just log a warning return self.logger.debug(f"{self._name} configuration OK")
[docs] def adc_configure_ddc(self, sampling_frequency, ddc_frequency, decimation_factor): """ Configure DDC registers. :param sampling_frequency: ADC sampling frequency in Hertz :type sampling_frequency: float :param ddc_frequency: DDC frequency in Hertz :type ddc_frequency: float :param decimation_factor: Chip decimation ratio (8, 20) :type decimation_factor: int """ nco_freq = int((ddc_frequency / sampling_frequency) * 2**48) if decimation_factor == 8: self.adc_write_reg(0x200, 0x22) # (two DDCs; I only selected) self.adc_write_reg(0x201, 0x03) # (chip decimate by 8) # DDC0 and DDC1 self.adc_write_reg( 0x310, 0x4A ) # (real mixer; 6 dB gain; variable IF; real output; HB4 + HB3 + HB2 + HB1 filters) self.adc_write_reg( 0x311, 0x00 ) # (DDC 0 I input = ADC Channel A; DDC 0 Q input = ADC Channel A) self.adc_write_reg( 0x330, 0x4A ) # (real mixer; 6 dB gain; variable IF; real output; HB4 + HB3 + HB2 + HB1 filters) self.adc_write_reg( 0x331, 0x05 ) # (DDC 1 I input = ADC Channel B; DDC 1 Q input = ADC Channel B) elif decimation_factor == 20: self.adc_write_reg(0x200, 0x23) # (two DDCs; I only selected) self.adc_write_reg(0x201, 0x0D) # (chip decimate by 20) # DDC0 and DDC1 self.adc_write_reg( 0x310, 0x4F ) # (real mixer; 6 dB gain; variable IF; real output; filters selected by next register) self.adc_write_reg( 0x311, 0x40 ) # (FB2 + HB3 + HB2 + HB1 filters; DDC 0 I input = ADC Channel A; DDC 0 Q input = ADC Channel A) self.adc_write_reg( 0x330, 0x4F ) # (real mixer; 6 dB gain; variable IF; real output; filters selected by next register) self.adc_write_reg( 0x331, 0x45 ) # (FB2 + HB3 + HB2 + HB1 filters; DDC 1 I input = ADC Channel B; DDC 1 Q input = ADC Channel B) else: raise PluginError( f"TpmAdc: not supported decimation factor {decimation_factor}" ) for n in range(2): self.adc_write_reg(0x314 + 0x20 * n, 0) # DDC0 NCO control self.adc_write_reg(0x315 + 0x20 * n, 0) # DDC0 Phase control for m in range(6): self.adc_write_reg(0x316 + 0x20 * n + m, (nco_freq >> (m * 8)) & 0xFF) for m in range(6): self.adc_write_reg(0x31D + 0x20 * n + m, 0) # phase offset
[docs] def adc_single_start( self, mono_channel_14_bit=False, adc_test_pattern=0x0, mono_channel_sel=0, fullscale_voltage=1.59, ): """ Perform the ADC configuration and initialization procedure as implemented in ADI demo :param mono_channel_14_bit: Use mono channel 14-bit mode :type mono_channel_14_bit: bool :param adc_test_pattern: ADC test mode option (default=0=off) :type adc_test_pattern: int :param mono_channel_sel: Select mono channel (0=A, 1=B) :type mono_channel_sel: int :param fullscale_voltage: ADC input full-scale voltage :type fullscale_voltage: float """ # JESD: 800 MSPS - 2 Virtual Converters - 2 lanes # N'=8 n=8 # L = 2 M = 2 F = 1 S = 1 HD = 0 self.board.set_qsfp_led(6, 0) # Turn off ADC indicator LED self.adc_write_reg(0x0, 0x81) # Soft ADC reset (self cleared) sleep(0.1) self.adc_write_reg(0x571, 0x15) # Power down JESD204B link self.adc_write_reg(0x3F, 0x80) # Disable power-down pin self.adc_write_reg(0x40, 0x00) # FD_A|B pins configured as Fast Detect outputs. self.adc_write_reg( 0x120, 0xA ) # SYSREF continuous mode, valid on hight to low transitions, using rising CLK edge # fmt: skip self.adc_write_reg(0x200, 0x0) # Chip application mode: Full bandwidth mode self.adc_write_reg(0x201, 0x0) # Chip decimation ratio = 1, full sample rate self.adc_write_reg(0x550, adc_test_pattern) # ADC test mode (default=off) # self.write_adc_reg(0x573, 0x00) # test mode disable self.adc_write_reg(0x56E, 0x0) # Lane Rate = 6.75 Gbps to 13.5 Gbps self.adc_write_reg(0x572, 0x10) # CMOS single-ended SYNC input # Configure JESD204B link self.adc_write_reg(0x58B, 0x81) # JESD204B scrambler (SCR=1) and lanes (L=2). self.adc_write_reg(0x58C, 0x0) # JESD204B number of octets (F=1) self.adc_write_reg( 0x58D, 0x1F ) # JESD204B number of frame per multiframe (K=JESD204B_K_CONFIG+1) # fmt: skip if mono_channel_14_bit: self.adc_write_reg(0x58E, 0x0) # JESD204B number of converters (M=1) self.adc_write_reg( 0x58F, 0xF ) # JESD204B number of control bits (CS=0) and ADC resolution (N=16-bit) # fmt: skip self.adc_write_reg( 0x590, 0x2F ) # JESD204B Subclass (1) and number of bits per ADC sample (N'=16) # fmt: skip if mono_channel_sel == 0: self.logger.info("TpmAdc mono_channel_14_bit - selected channel A") self.adc_write_reg( 0x564, 0 ) # Output channel select, Converter channel swap control - Normal channel ordering # fmt: skip else: self.logger.info("TpmAdc mono_channel_14_bit - selected channel B") self.adc_write_reg( 0x564, 1 ) # Output channel select, Converter channel swap control - Channel swap enabled # fmt: skip else: self.adc_write_reg(0x58E, 0x1) # JESD204B number of converters (M=2) self.adc_write_reg( 0x58F, 0x7 ) # JESD204B number of control bits (CS=0) and ADC resolution (N=8) # fmt: skip self.adc_write_reg( 0x590, 0x27 ) # JESD204B Subclass (1) and number of bits per sample (N'=8) # fmt: skip self.adc_write_reg( 0x564, 0 ) # Output channel select, Converter channel swap control - Normal channel ordering # fmt: skip if mono_channel_sel == 1: self.logger.warning("TpmAdc mono_channel_sel ignored") # pre-emphasis test # pre_emphasis = 0xc # self.write_adc_reg(0x5c4, pre_emphasis) # self.write_adc_reg(0x5c6, pre_emphasis) # Lane remapping self.adc_lane_remap(logical_lane_vals=[0x00, 0x01, 0x00, 0x01]) self.adc_write_reg(0x571, 0x14) # Power up JESD204B link self.adc_jesd204b_init() # JESD204B initialization sequence self.adc_set_vref_high_z() # Set external Vref pin as high-Z self.adc_set_full_scale_config( fullscale_voltage ) # Set ADC input full-scale voltage # fmt: skip self.adc_clear_overrange() # Clear the overrange register sticky bits self.adc_pll_lock_poll() # Poll PLL lock status self.board.set_qsfp_led(6, 1) # Turn on ADC indicator LED
[docs] def adc_single_start_dual_14_ddc( self, sampling_frequency=800e6, ddc_frequency=100e6, adc_test_pattern=0x0, decimation_factor=0x8, low_bitrate=0x1, fullscale_voltage=1.59, ): """ Perform the ADC configuration and initialization procedure as implemented in ADI demo low_bitrate: JESD204B lane rate control 0x3 => Lane rate = 13.5 Gbps to 16 Gbps. 0x0 => Lane rate = 6.75 Gbps to 13.5 Gbps. 0x1 => Lane rate = 3.375 Gbps to 6.75 Gbps. 0x5 => Lane rate = 1.6875 Gbps to 3.375 Gbps. :param sampling_frequency: ADC sampling frequency in Hertz :type sampling_frequency: float :param ddc_frequency: DDC frequency in Hertz :type ddc_frequency: float :param adc_test_pattern: ADC test mode option (default=0=off) :type adc_test_pattern: int :param decimation_factor: Chip decimation ratio (8, 20) :type decimation_factor: int :param low_bitrate: JESD204B lane rate control option (True, False, 0x0, 0x1, 0x3, 0x5) :type low_bitrate: bool or int :param fullscale_voltage: ADC input full-scale voltage in volts :type fullscale_voltage: float """ self.board.set_qsfp_led(6, 0) # Turn off ADC indicator LED self.adc_write_reg(0x0, 0x81) # soft ADC reset (self cleared) sleep(0.1) self.adc_write_reg(0x571, 0x15) # Power down JESD204B link self.adc_write_reg(0x3F, 0x80) # Disable power-down pin self.adc_write_reg(0x40, 0x00) # FD_A|B pins configured as Fast Detect outputs. self.adc_write_reg( 0x120, 0xA ) # SYSREF continuous mode, valid on hight to low transitions, using rising CLK edge # fmt: skip self.adc_write_reg(0x200, 0x0) # Chip application mode: Full bandwidth mode self.adc_write_reg(0x201, 0x0) # Chip decimation ratio = 1, full sample rate self.adc_write_reg(0x550, adc_test_pattern) # ADC test mode (default=off) # self.write_adc_reg(0x573, 0x00) # test mode disable self.adc_write_reg(0x56E, 0x0) # Lane Rate = 6.75 Gbps to 13.5 Gbps self.adc_write_reg(0x572, 0x10) # CMOS single-ended SYNC input # Configure JESD204B link self.adc_write_reg(0x58B, 0x80) # JESD204B scrambler (SCR=1) and lanes (L=1). self.adc_write_reg(0x58C, 0x3) # JESD204B number of octets (F=4) self.adc_write_reg( 0x58D, 0x1F ) # JESD204B number of frame per multiframe (K=JESD204B_K_CONFIG+1) # fmt: skip self.adc_write_reg(0x58E, 0x1) # JESD204B number of converters (M=2) self.adc_write_reg( 0x58F, 0xF ) # JESD204B number of control bits (CS=0) and ADC resolution (N=16-bit) # fmt: skip self.adc_write_reg( 0x590, 0x2F ) # JESD204B Subclass (1) and number of bits per ADC sample (N'=16) # fmt: skip self.adc_write_reg( 0x564, 0 ) # Output channel select, Converter channel swap control - Normal channel ordering # fmt: skip # pre-emphasis test # pre_emphasis = 0xc # self.write_adc_reg(0x5c4, pre_emphasis) # self.write_adc_reg(0x5c6, pre_emphasis) self.adc_lane_remap(logical_lane_vals=[0x00, 0x00, 0x00, 0x00]) # DDC configuration self.adc_configure_ddc(sampling_frequency, ddc_frequency, decimation_factor) # Set JESD204B lane rate if isinstance(low_bitrate, bool): self.adc_write_reg(0x56E, 0x10 if low_bitrate else 0x0) elif isinstance(low_bitrate, int): self.adc_write_reg(0x56E, low_bitrate << 4) self.adc_write_reg(0x571, 0x14) # Power up JESD204B link self.adc_jesd204b_init() # JESD204B initialization sequence self.adc_set_vref_high_z() # Set external Vref pin as high-Z self.adc_set_full_scale_config( fullscale_voltage ) # Set ADC input full-scale voltage # fmt: skip self.adc_clear_overrange() # Clear the overrange register sticky bits self.adc_pll_lock_poll() # Poll PLL lock status self.board.set_qsfp_led(6, 1) # Turn on ADC indicator LED
[docs] def adc_set_fast_detect( self, upper_threshold, lower_threshold=None, dwell_samples=100 ): """ Configure and enable Fast Threshold Detection in pins FD_A and FD_B. :param upper_threshold: Signal magnitude threshold for assertion :type upper_threshold: int :param lower_threshold: Signal magnitude threshold for deassertion :type lower_threshold: int :param dwell_samples: Duration below lower threshold before deassertion :type dwell_samples: int """ if lower_threshold is None: lower_threshold = upper_threshold rd = self.adc_read_reg(0x040) self.adc_write_reg( 0x040, rd & 0xC0 ) # set GPIO A0 and GPIO B0 pins as Fast Detect A and B outputs # fmt: skip self.adc_write_reg(0x247, upper_threshold & 0xFF) # Upper Threshold LSB self.adc_write_reg(0x248, (upper_threshold >> 8) & 0xFF) # Upper Threshold MSB self.adc_write_reg(0x249, lower_threshold & 0xFF) # Lower Threshold LSB self.adc_write_reg(0x24A, (lower_threshold >> 8) & 0xFF) # Lower Threshold MSB self.adc_write_reg(0x24B, dwell_samples & 0xFF) # Dwell Time LSB self.adc_write_reg(0x24C, (dwell_samples >> 8) & 0xFF) # Dwell Time MSB self.adc_write_reg(0x245, 0x1) # Enable Fast Detect ADC outputs
[docs] def enable_test_mode(self, pattern_type): """ Configure ADC Test Mode. The AD9695 ADC supports the following test modes: - ``midscale``: A constant output of the ADC midscale value. - ``full-scale-positive``: A constant output of the ADC positive maximum value. - ``full-scale-negative``: A constant output of the ADC negative maximum value. - ``checkerboard``: A repeating pattern of alternating 1's and 0's. Words alternate between 0x2AAA and 0x1555. - ``pn-long``: A PN23 (Pseudo-Random Noise) sequence. - ``pn-short``: A PN9 (Pseudo-Random Noise) sequence. - ``one-zero-alternate``: A repeating pattern of alternating 1's and 0's. Words alternate between 0x0000 and 0x3FFF. - ``fixed``: A repeating pattern of four user provided values. These can be specified with ``set_test_pattern`` below. - ``ramp`` A linear ramp pattern increasing from 0x000 to 0x3FFF then repeating. For more details see the `Analog Devices AD9695 Data Sheet <https://www.analog.com/media/en/technical-documentation/data-sheets/ad9695.pdf>`_ :param pattern_type: Name of test mode to be enabled :type pattern_type: str """ pattern_type_map = { "midscale": 0x1, "full-scale-positive": 0x2, "full-scale-negative": 0x3, "checkerboard": 0x4, "pn-long": 0x5, "pn-short": 0x6, "one-zero-alternate": 0x7, "fixed": 0x8, "ramp": 0xF, } if pattern_type not in pattern_type_map: self.logger.error( f"Supported pattern_type values are {', '.join(pattern_type_map.keys())}." ) return self.logger.debug(f"Setting {self._name} pattern {pattern_type}") self.adc_write_reg(0x550, pattern_type_map[pattern_type])
[docs] def set_test_pattern(self, pattern=[15, 67, 252, 128]): """ Configure ADC Test Pattern User Input. This is used when the ADC Test Mode is configured as ``fixed``. See the `enable_test_mode` method above. :param pattern: List of four integer values to be applied :type pattern: list(int) """ if not len(pattern) == 4: self.logger.error( "Invalid pattern provided. Pattern must have four values!" ) return if not all(0 <= n < 256 for n in pattern): self.logger.error( f"Invalid pattern provided. Pattern values must be in range 0 to 255." f"{self._name} got {pattern}" ) return # TODO: This currently only sets the User Pattern MSB [15:8] # Do we also need to support setting the User Pattern LSB [7:0]? # These are 0x551, 0x553, 0x555, 0x557 # ADC Test Modes use User Pattern [15:2] # JESD204B Interface Test Modes use User Pattern [15:0] self.adc_write_reg(0x552, pattern[0]) self.adc_write_reg(0x554, pattern[1]) self.adc_write_reg(0x556, pattern[2]) self.adc_write_reg(0x558, pattern[3])
[docs] def disable_test_mode(self): """ Disable AD9695 Test Mode. """ self.adc_write_reg(0x550, 0x0)
[docs] def adc_enable_temp_meas(self, diode_type=1): """ Enable temperature diode voltage on Vref Pin . :param diode_type: select which diode export, 0=High-Z, 1=1xdiode, 2=20xdiode """ self.adc_write_reg(0x18E6, diode_type)
[docs] def check_pll_status(self): """ Status of ADC PLL. This method returns a tuple, True if the lock of the PLL is up and True if no loss of PLL lock has been observed respectively. :return: (True, True) if lock is up and no loss of lock :rtype: tuple """ reg = self.adc_read_reg(0x056F) lock_is_up = reg & 0x80 > 0 no_loss_of_lock = reg & 0x8 == 0 return lock_is_up, no_loss_of_lock
[docs] def clear_pll_status(self): """ Clear the JESD204B PLL loss-of-lock sticky bit (register 0x1262). Performs the two-write sequence required by the AD9695 datasheet: write 0x08 to assert the clear, then write 0x00 to return to normal operation. """ self.board._spi_lock.lock() self.adc_write_reg(0x1262, 0x08, unlock=False) # Assert loss-of-lock clear self.adc_write_reg(0x1262, 0x00) # Return to normal operation
[docs] def check_sysref_setup_and_hold(self, show_info=True): """ Status of the ADC setup and hold monitor. Returns True if no setup or hold error. If show info enabled then desciptions from AD9695 documentation are also displayed to explain the value of the setup and hold monitor. :param show_info: displays info messages about current setup/hold :type show_info: bool :return: True if timing requirements OK :rtype: bool """ case_dict = { "case1": { "hold": [0x0], "setup": [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7], "status": False, "msg": "Possible setup error.The smaller this number, the smaller the setup margin.", }, "case2": { "hold": [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8], "setup": [0x8], "status": True, "msg": "No setup or hold error (best hold margin).", }, "case3": { "hold": [0x8], "setup": [0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF], "status": True, "msg": "No setup or hold error (best setup and hold margin).", }, "case4": { "hold": [0x8], "setup": [0x0], "status": True, "msg": "No setup or hold error (best setup margin).", }, "case5": { "hold": [0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF], "setup": [0x0], "status": False, "msg": "Possible hold error. The larger this number the smaller the hold margin.", }, "case6": { "hold": [0x0], "setup": [0x0], "status": False, "msg": "Possible setup or hold error.", }, } reg = self.adc_read_reg(0x0128) hold = (reg & 0xF0) >> 4 setup = reg & 0x0F for case in case_dict.values(): if hold in case["hold"] and setup in case["setup"]: if show_info: self.logger.info( f"{self._name} {case['msg']} Setup: {hex(setup)}, Hold {hex(hold)}." ) return case["status"] if show_info: self.logger.error( f"{self._name} Invalid Setup and Hold values. Setup: {hex(setup)}, Hold {hex(hold)}." ) return False
[docs] def check_sysref_counter(self, show_info=True): """ Checks ADC sysref counter is incrementing. Sysref counter increments for each sysref event and overflows at 255 ~ every 3.28ms. Returns True if counter is incrementing. Will retry for 1 second until two readings can be taken in under 3ms to guarantee no overflow. For debugging, if show info is enabled then each counter reading will be displayed along with the elapsed time. :param show_info: displays info messages :type show_info: bool :return: True if sysref counter incrementing :rtype: bool """ timeout = time.time() + 1 # 1 second timeout while True: self.board._spi_lock.lock() start_time = time.perf_counter() read1 = self.adc_read_reg(0x012A, unlock=False) read2 = self.adc_read_reg(0x012A) end_time = time.perf_counter() if show_info: self.logger.info(f"{self._name} first read of SYSREF counter: {read1}") self.logger.info(f"{self._name} second read of SYSREF counter: {read2}") self.logger.info( f"{self._name} took {(end_time - start_time) * 1000:.2f} ms to read SYSREF counter twice" ) if end_time - start_time < 0.003: break if time.time() > timeout: raise BoardError( f"Timed out trying to read {self._name} SYSREF counter - 0x012A twice in under 3 ms (took {(end_time - start_time) * 1000:.2f} ms)." ) return read1 != read2
[docs] def adc_read_overrange(self, clear=False): """ Read the overrange status bits of the ADC. Optionally clear the bits afterwards Return the overrange status of the two ADC channels as two booleans :param clear: Clears the overrange status bits after reading if set to true :type clear: bool :return: Overrange status of the two ADC channels; in the form of [CH_A, CH_B] :rtype: list of 2 bools """ overrange_status = self.adc_read_reg(0x0563) overrange_ch_A = overrange_status & 0x1 > 0 overrange_ch_B = overrange_status & 0x2 > 0 if clear: self.adc_clear_overrange() return [overrange_ch_A, overrange_ch_B]
[docs] def adc_clear_overrange(self): """ Clear the 2 LSBs of the overrange status register of the ADC by setting the 2 LSBs HIGH in the overrange clear register """ self.adc_write_reg(0x0562, 0b00000011)
[docs] def adc_write_reg(self, address, value, unlock=None): """ Write value to specified ADC register. :param address: ADC register address :type address: int :param value: value to write :type value: int """ if unlock is not None: return self.board.write_device(self._adc_id, address, value, unlock) self.board[(self._adc_id, address)] = value
[docs] def adc_read_reg(self, address, unlock=None): """ Read value from specified ADC register. :param address: ADC register address :type address: int :return: value stored in register :rtype: int """ if unlock is not None: return self.board.read_device(self._adc_id, address, unlock) return self.board[(self._adc_id, address)]
# ##################### Superclass method implementations #################################
[docs] def initialise(self): """Initialise TpmAdc.""" self.logger.info("TpmAdc has been initialised") return True
[docs] def status_check(self): """ Perform status check. :return: Status """ self.logger.info("TpmAdc : Checking status") return Status.OK
[docs] def clean_up(self): """ Perform cleanup. :return: Success """ self.logger.info("TpmAdc : Cleaning up") return True