from __future__ import division
__author__ = 'lessju'
from pyfabil.plugins.firmwareblock import FirmwareBlock
from pyfabil.base.definitions import *
from pyfabil.base.utils import *
from time import sleep
import logging
[docs]
class TpmAdc(FirmwareBlock):
""" TpmAdc tests class """
@compatibleboards(BoardMake.TpmBoard)
@friendlyname('tpm_adc')
@maxinstances(16)
def __init__(self, board, **kwargs):
""" TpmAdc initialiser
:param board: Pointer to board instance
"""
super(TpmAdc, self).__init__(board)
if 'adc_id' not in list(kwargs.keys()):
raise PluginError("TpmAdc: adc_id required")
self._adc_id = kwargs['adc_id']
#######################################################################################
[docs]
def adc_reset(self):
self.board[(self._adc_id, 0x0)] = 0x81
time.sleep(0.01) # soft reset requires 5ms, see AD9680 datasheet
[docs]
def adc_power_down_enable(self):
self.board[(self._adc_id, 0x3F)] = 0x0
self.board[(self._adc_id, 0x40)] = 0x0
[docs]
def adc_power_down_disable(self):
self.board[(self._adc_id, 0x3F)] = 0x80
self.board[(self._adc_id, 0x40)] = 0x80
sleep(0.01) # exit from power-down requires 4ms, see AD9680 datasheet
[docs]
def adc_single_start(self, mono_channel_14_bit=False, clock_divider=1, low_bitrate=False, mono_channel_sel=1):
""" Perform the ADC configuration and initialization procedure as implemented in ADI demo """
self.adc_power_down_disable()
self.board[(self._adc_id, 0x18)] = 0x40 # Input buffer current 3.0X
self.board[(self._adc_id, 0x120)] = 0xA # sysref, falling edge
self.board[(self._adc_id, 0x550)] = 0x0 # ADC test mode
self.board[(self._adc_id, 0x573)] = 0x00 # test mode disable
if clock_divider != 1:
if clock_divider in [2, 4, 8]:
self.board[(self._adc_id, 0x10b)] = clock_divider-1
self.board[(self._adc_id, 0x10d)] = 0x80
else:
raise PluginError("TpmAdc: ADC clock divider %d is not supported" % clock_divider)
self.board[(self._adc_id, 0x571)] = 0x15 # JESD Link mode Control 1
self.board[(self._adc_id, 0x572)] = 0x10 # SYNC CMOS level
self.board[(self._adc_id, 0x58b)] = 0x81 # JESD204B scrambler and lanes. lanes are read only here
self.board[(self._adc_id, 0x58d)] = 0x1f # number of frame per multiframe
if mono_channel_14_bit:
self.board[(self._adc_id, 0x58f)] = 0xF # JESD204B CS/N config
self.board[(self._adc_id, 0x590)] = 0x2F # JESD204B subclass and number of bits #X
self.board[(self._adc_id, 0x570)] = 0x40 # JESD204B quick configuration
# Input swap
if mono_channel_sel == 0:
self.board[(self._adc_id, 0x564)] = 0x0
else:
self.board[(self._adc_id, 0x564)] = 0x1
else:
self.board[(self._adc_id, 0x58f)] = 0x7 # JESD204B CS/N config
self.board[(self._adc_id, 0x590)] = 0x27 # JESD204B subclass and number of bits #X
self.board[(self._adc_id, 0x570)] = 0x48 # JESD204B quick configuration
# Lane remap
self.board[(self._adc_id, 0x5b2)] = 0x00
self.board[(self._adc_id, 0x5b3)] = 0x01
self.board[(self._adc_id, 0x5b5)] = 0x00
self.board[(self._adc_id, 0x5b6)] = 0x01
self.board[(self._adc_id, 0x5b0)] = 0xFA # xTPM unused lane power down
if low_bitrate:
self.board[(self._adc_id, 0x56e)] = 0x10 # JESD line rate < 6.25 Gbps
self.board[(self._adc_id, 0x571)] = 0x14
if do_until_eq(lambda: self.board[(self._adc_id, 0x56F)] == 0x80, 1, ms_retry=100, s_timeout=10) is None:
raise PluginError("ADC configuration failed, " + str(self._adc_id).upper() + " PLL not locked")
if self.board[(self._adc_id, 0x58b)] != 0x81: # jesd lane number
raise PluginError("TpmAdc: Number of lane is not correct")
if self.board[(self._adc_id, 0x58c)] != 0: # octets per frame
raise PluginError("TpmAdc: Number of octets per frame is not correct")
if self.board[(self._adc_id, 0x58d)] != 0x1f: # frames per multiframe
raise PluginError("TpmAdc: Number of frame per multiframe is not correct")
if self.board[(self._adc_id, 0x58e)] != 1 and not mono_channel_14_bit: # virtual converters
raise PluginError("TpmAdc: Number of virtual converters is not correct")
if self.board[(self._adc_id, 0x58e)] != 0 and mono_channel_14_bit: # virtual converters
raise PluginError("TpmAdc: Number of virtual converters is not correct")
[docs]
def adc_single_start_dual_14_ddc(self, sampling_frequency=800e6, ddc_frequency=100e6, low_bitrate=False):
""" Perform the ADC configuration and initialization procedure as implemented in ADI demo """
self.adc_power_down_disable()
self.board[(self._adc_id, 0x18)] = 0x40 # Input buffer current 3.0X
self.board[(self._adc_id, 0x120)] = 0xA # sysref, falling edge
self.board[(self._adc_id, 0x550)] = 0x0 # ADC test mode
self.board[(self._adc_id, 0x573)] = 0x00 # test mode disable
self.board[(self._adc_id, 0x571)] = 0x15 # JESD Link mode Control 1, power-down
self.board[(self._adc_id, 0x572)] = 0x10 # SYNC CMOS level
self.board[(self._adc_id, 0x58b)] = 0x80 # JESD204B scrambler and lanes. lanes are read only here
self.board[(self._adc_id, 0x58d)] = 0x1f # number of frame per multiframe
self.board[(self._adc_id, 0x58f)] = 0x0F # JESD204B CS/N config
self.board[(self._adc_id, 0x590)] = 0x2F # JESD204B subclass and number of bits #X
self.board[(self._adc_id, 0x570)] = 0x0A # JESD204B quick configuration
# Lane remap
self.board[(self._adc_id, 0x5b2)] = 0x00
self.board[(self._adc_id, 0x5b3)] = 0x00
self.board[(self._adc_id, 0x5b5)] = 0x00
self.board[(self._adc_id, 0x5b6)] = 0x00
self.board[(self._adc_id, 0x5b0)] = 0xFA # xTPM unused lane power down
# DDC configuration
self.board[(self._adc_id, 0x200)] = 0x22 # (two DDCs; I only selected)
self.board[(self._adc_id, 0x201)] = 0x03 # (chip decimate by 8)
self.board[(self._adc_id, 0x310)] = 0x4A # (real mixer; 6 dB gain; variable IF; real output; HB4 + HB3 + HB2 + HB1 filters)
self.board[(self._adc_id, 0x330)] = 0x4A # (real mixer; 6 dB gain; variable IF; real output; HB4 + HB3 + HB2 + HB1 filters)
self.board[(self._adc_id, 0x311)] = 0x00 # (DDC 0 I input = ADC Channel A; DDC 0 Q input = ADC Channel A)
self.board[(self._adc_id, 0x331)] = 0x05 # (DDC 1 I input = ADC Channel B; DDC 1 Q input = ADC Channel B)
nco_freq = int((ddc_frequency / sampling_frequency) * 4096)
self.board[(self._adc_id, 0x314)] = nco_freq & 0xFF
self.board[(self._adc_id, 0x315)] = nco_freq >> 8
self.board[(self._adc_id, 0x334)] = nco_freq & 0xFF
self.board[(self._adc_id, 0x335)] = nco_freq >> 8
self.board[(self._adc_id, 0x320)] = 0
self.board[(self._adc_id, 0x321)] = 0
self.board[(self._adc_id, 0x340)] = 0
self.board[(self._adc_id, 0x341)] = 0
if low_bitrate:
self.board[(self._adc_id, 0x56e)] = 0x10 # JESD line rate < 6.25 Gbps
self.board[(self._adc_id, 0x571)] = 0x14 # JESD Link mode Control 1, power-up
if do_until_eq(lambda: self.board[(self._adc_id, 0x56F)] == 0x80, 1, ms_retry=100, s_timeout=10) is None:
raise PluginError("ADC configuration failed, ADC" + str(self._adc_id) + " PLL not locked")
if self.board[(self._adc_id, 0x58b)] != 0x80: # jesd lane number
raise PluginError("TpmAdc: Number of lane is not correct")
if self.board[(self._adc_id, 0x58c)] != 3: # octets per frame
raise PluginError("TpmAdc: Number of octets per frame is not correct")
if self.board[(self._adc_id, 0x58d)] != 0x1f: # frames per multiframe
raise PluginError("TpmAdc: Number of frame per multiframe is not correct")
if self.board[(self._adc_id, 0x58e)] != 1: # virtual converters
raise PluginError("TpmAdc: Number of virtual converters is not correct")
[docs]
def adc_single_start_dual_14_divider(self, clock_divider=2, low_bitrate=False):
""" Perform the ADC configuration and initialization procedure as implemented in ADI demo """
self.adc_power_down_disable()
self.board[(self._adc_id, 0x18)] = 0x40 # Input buffer current 3.0X
self.board[(self._adc_id, 0x120)] = 0xA # sysref, falling edge
self.board[(self._adc_id, 0x550)] = 0x0 # ADC test mode
self.board[(self._adc_id, 0x573)] = 0x00 # test mode disable
if clock_divider in [1, 2, 4, 8]:
self.board[(self._adc_id, 0x10b)] = clock_divider-1
self.board[(self._adc_id, 0x10d)] = 0x80
else:
raise PluginError("TpmAdc: ADC clock divider %d is not supported" % clock_divider)
self.board[(self._adc_id, 0x571)] = 0x15 # JESD Link mode Control 1, power-down
self.board[(self._adc_id, 0x572)] = 0x10 # SYNC CMOS level
self.board[(self._adc_id, 0x58b)] = 0x80 # JESD204B scrambler and lanes. lanes are read only here
self.board[(self._adc_id, 0x58d)] = 0x1f # number of frame per multiframe
self.board[(self._adc_id, 0x58f)] = 0x0F # JESD204B CS/N config
self.board[(self._adc_id, 0x590)] = 0x2F # JESD204B subclass and number of bits #X
self.board[(self._adc_id, 0x570)] = 0x49 # JESD204B quick configuration
# Lane remap
self.board[(self._adc_id, 0x5b2)] = 0x00
self.board[(self._adc_id, 0x5b3)] = 0x01
self.board[(self._adc_id, 0x5b5)] = 0x00
self.board[(self._adc_id, 0x5b6)] = 0x01
self.board[(self._adc_id, 0x5b0)] = 0xFA # xTPM unused lane power down
# if low_bitrate:
# self.board[(self._adc_id, 0x56e)] = 0x10 # JESD line rate < 6.25 Gbps
self.board[(self._adc_id, 0x571)] = 0x14 # JESD Link mode Control 1, power-up
if do_until_eq(lambda: self.board[(self._adc_id, 0x56F)] == 0x80, 1, ms_retry=100, s_timeout=10) is None:
raise PluginError("ADC configuration failed, ADC" + str(self._adc_id) + " PLL not locked")
if self.board[(self._adc_id, 0x58b)] != 0x81: # jesd lane number
raise PluginError("TpmAdc: Number of lane is not correct")
if self.board[(self._adc_id, 0x58c)] != 1: # octets per frame
raise PluginError("TpmAdc: Number of octets per frame is not correct")
if self.board[(self._adc_id, 0x58d)] != 0x1f: # frames per multiframe
raise PluginError("TpmAdc: Number of frame per multiframe is not correct")
if self.board[(self._adc_id, 0x58e)] != 1: # virtual converters
raise PluginError("TpmAdc: Number of virtual converters is not correct")
[docs]
def adc_set_fast_detect(self, upper_threshold, lower_threshold=None, dwell_samples=100):
if lower_threshold == None:
lower_threshold = upper_threshold
rd = self.board[(self._adc_id, 0x040)]
self.board[(self._adc_id, 0x040)] = rd & 0xC0
self.board[(self._adc_id, 0x247)] = upper_threshold & 0xFF #Upper Threshold LSB
self.board[(self._adc_id, 0x248)] = (upper_threshold >> 8) & 0xFF #Upper Threshold MSB
self.board[(self._adc_id, 0x249)] = lower_threshold & 0xFF #Lower Threshold LSB
self.board[(self._adc_id, 0x24A)] = (lower_threshold >> 8) & 0xFF #Lower Threshold MSB
self.board[(self._adc_id, 0x24B)] = dwell_samples & 0xFF #Dwell Time LSB
self.board[(self._adc_id, 0x24C)] = (dwell_samples >> 8) & 0xFF #Dwell Time MSB
self.board[(self._adc_id, 0x245)] = 0x1 # Enable Fast Detect ADC outputs
[docs]
def adc_test_pattern_enable(self, pattern_type=0xF):
self.board[(self._adc_id, 0x550)] = pattern_type
[docs]
def adc_test_pattern_disable(self):
self.board[(self._adc_id, 0x550)] = 0x0
##################### Superclass method implementations #################################
[docs]
def initialise(self):
""" Initialise TpmPll """
logging.info("TpmAdc has been initialised")
return True
[docs]
def status_check(self):
""" Perform status check
:return: Status
"""
logging.info("TpmAdc : Checking status")
return Status.OK
[docs]
def clean_up(self):
""" Perform cleanup
:return: Success
"""
logging.info("TpmAdc : Cleaning up")
return True