FHM GPIO Mode

Hi everyone,

I am trying to use Fast Frequency Hopping with GPIO trigger mode.

I have this schema:

*** High on the GPIO pin => LO switch to fhm_init_frequency
chn_trx_lo.attrs['frequency_hopping_mode'].value = freq_A
*** High on the GPIO pin => LO switch to fhm_init_frequency
chn_trx_lo.attrs['frequency_hopping_mode'].value = freq_B
*** High on the GPIO pin => LO switch to freq_A
chn_trx_lo.attrs['frequency_hopping_mode'].value = freq_C
*** High on the GPIO pin => LO switch to freq_B

I want to hop to frequency "freq_A" right after setting it or later to "freq_B" but not to the previous registered frequency. Indeed, in this mode, the LO hops twice to the init frequency set in adi,fhm-mode-fhm-init-frequency_hz..

I have seen that in API mode it is possible to hop to the latest supplied frequency instead of the previous registered. But in this mode the hopping is too slow.

Thanks in advance,

D



update
[edited by: dannirodri at 3:16 PM (GMT 0) on 18 Feb 2020]
Parents
  • 0
    •  Analog Employees 
    on Feb 19, 2020 12:00 AM over 1 year ago

    What are your FHM settings in device tree? I assume what you want is the FHM cal to happen at boot?

    -Travis

  • Frist of all, thanks for your response.

    Sencond,

    I have not modified any FW, I am using the latest SD Image release 2019_R1 RC

    1.- What FHM calibration does? I have not found any information on that.

    2.- I want this schema, in FHM GPIO mode:

    1. Write a frequency in attribute chn_trx_lo.attrs['frequency_hopping']
    2. GPIO gets a high level from an external source
    3. Hop to that frequency

    Thanks,

    D

  • Ok I can repeat this. Basically on the first hop update it goes to init frequency then to the requested one. From what I can tell this is implemented correctly in the Linux driver, but it might be a bug in the transceiver's API. Let me follow up with the transceiver support.

    Thank you, Travis.

    You are really limited on the SPI write here. You would have to increase the SPI clock.

    I have been looking to increase the SPI clock (SCLK), but I have some understanding issues:

    • ZynqUS+ Data Sheet says that the SPI maximum clock frequency is 50 MHz for the master (I understand this is ZCU102 PS/PL part) and 25 MHz for the slave (I understand this is the ADRV9009)
    • I have read in UG-992 SPI maximum clock frequency is 50MHz. However, in ADRV9009's datasheet or UG-1295 I have not found this info.
    • On the other hand, in devicetress:
      • In zynqmp-zcu102-revA.dts is set a 108 MHz for QPSI.
      • In adi-adrv9009.dts at L27 is set a 10 MHz for AD9528 clock device, and at L113 is set a 25 MHz for ADRV9009 device.
      • At zcu102_system_constr.xdc in HDL repository is set a 40 nanoseconds SPI clock period (25 MHz)

    So, my questions are:

    1. What is the meaning of this configurations for QPSI, AD9528 clock and ADRV9009 device?
    2. How can I increase the SPI clock frequency?
    In regards to the transceiver itself, you have to follow the steps 1. send SPI write with desired frequency 2. Trigger Move to frequency (GPIO or SPI). Frequency hopping is independent of data that to send or receive.

    We agree on that.

    I look forward your reply.

    Regards,

    D

  • 0
    •  Analog Employees 
    on Feb 24, 2020 5:50 PM over 1 year ago in reply to dannirodri

    Moving to transceiver support. or can you repeat this issue with FHM? and what is the max SPI clock for ADRV9009?

    -Travis

  • 0
    •  Analog Employees 
    on Mar 9, 2020 10:27 AM 11 months ago in reply to travisfcollins
    Ok I can repeat this. Basically on the first hop update it goes to init frequency then to the requested one. From what I can tell this is implemented correctly in the Linux driver, but it might be a bug in the transceiver's API. Let me follow up with the transceiver support.

    Thank you, Travis.

    ...When you call TALISE_setFhmHop() it hops to frequency set in previous call of TALISE_setFhmHop() and register latest supplied frequency for next TALISE_setFhmHop() call. It allows a quick hopping to a frequency where the system knows in advance the next hopping frequency to a quick hop.

    what is the max SPI clock for ADRV9009?

    Please refer to the SPI timing specifications in the datasheet and the max SPI clock frequency is 50MHz

  • Hi D,

    How fast were you able to get setting of the LO PLL?  I'm using the ADRV9009-ZU11EG, and it takes 0.3 seconds for each of the two ADRV9009's because it is turning off then on the radio.  I'm also working with pyadi-iio right now but over an ip link rather than local. 

    Do you know if the GPIO mode if faster than the API mode? 

    It seems like that would be important to make that list before hand then initilize/calibrate the LO PLL for each frequency setting.  

    I'm not sure how the FHM (freq. hop mode) API mode works, or is also fast because it allow changing to an arbitrary frequency with in the min and max frequencies, in which case it seems like the LO PLL settings would not be known before hand and thus allow faster operation. 

    From the ADRV9008-1-W-9008-2-W-9009-W-Hardware-Reference-Manual-UG-1295.pdf, document it just has initial frequency, min and max frequencies, but does not have a structure for setting frequency increment or step size or a list of frequencies. 

    Thanks,

    Nathan

  • 0
    •  Analog Employees 
    on Mar 20, 2020 10:14 AM 11 months ago in reply to NathanB
    From the ADRV9008-1-W-9008-2-W-9009-W-Hardware-Reference-Manual-UG-1295.pdf, document it just has initial frequency, min and max frequencies, but does not have a structure for setting frequency increment or step size or a list of frequencies. 

    there is no separate API or data structure. You need to call setfhmhop in a sequence.

    TALISE_setFhmHop()
    This function triggers frequency hopping via an Arm command instead of a GPIO pulse.
    TALISE_setFhmHop(taliseDevice_t *device, uint64_t nextRfPllFrequency_Hz)

    freq_hop.txt
    ########################
    #ADI Demo Python Script
    ########################
    
    #Import Reference to the DLL
    import clr
    import System
    import time
    clr.AddReferenceToFileAndPath("C:\\Program Files (x86)\\Analog Devices\\ADRV9009 Transceiver Evaluation Software\\AdiCmdServerClient.dll")
    from AdiCmdServerClient import AdiCommandServerClient
    from AdiCmdServerClient import Talise
    from AdiCmdServerClient import FpgaTalise
    from AdiCmdServerClient import Enums
    from System import Array
    import AdiCmdServerClient
    #Create an Instance of the Class
    Link = AdiCommandServerClient.Instance
    
    #Connect to the Zynq Platform
    if(Link.hw.Connected == 1):
        Connect = 0
    else:
        Connect = 1
        Link.hw.Connect("192.168.1.10", 55555)
    
    print Link.Version()
    
    #####################################################################
    #Frequency hopping config, this can be set in radio off state only
    ####################################################################
    
    Link.Talise.RadioOff()
    Fhm_Config = Link.Talise.FhmConfig()
    Fhm_Config.FhmGpioPin = AdiCmdServerClient.GpioSel.TAL_GPIO_INVALID  #TAL_GPIO_04 #TAL_GPIO_INVALID
    Fhm_Config.FhmMinFreq_MHz = 255
    Fhm_Config.FhmMaxFreq_MHz = 6000
    Link.Talise.SetFhmConfig(Fhm_Config)
    Link.Talise.RadioOn()
    
    #####################################################################
    #Frequency hopping mode setup, this can be called in radio on state
    ####################################################################
    Fhm_Mode = Link.Talise.FhmMode()
    Fhm_Mode.FhmEnable = 1
    Fhm_Mode.EnableMcsSync = 1
    Fhm_Mode.FhmTriggerMode = Talise.FhmTriggerMode.FhmNonGpioMode  #FhmGpioMode, FhmNonGpioMode 
    Fhm_Mode.FhmExitMode = Talise.FhmExitMode.FhmFullExit #FhmQuickExit, FhmFullExit 
    Fhm_Mode.FhmInitFrequency_Hz  = 3500000000
    Link.Talise.SetFhmMode(Fhm_Mode)
    
    ####################################################################
    #Read back the service frequency before starting frequency hopping
    ####################################################################
    
    init_freq = 0
    init_freq = Link.Talise.GetRfPllFrequency(Link.Talise.PllName.RfPll , 0)
    
    #####################################################################
    #Frequency hopping frequency set and can call any nymber of hopps
    ####################################################################
    
    '''
    #Link.Talise.SetFhmHop(3500000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3505000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3510000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3520000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3530000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3540000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    '''
    
    for i in range(0,100,1):
        Link.Talise.SetFhmHop(3505000000)
        Link.Talise.SetFhmHop(3540000000)
        Link.Talise.SetFhmHop(3505000000)
    
    ###################################################################################################################
    #Frequency hopping mode disable, make sure to disable after FHM as the RFPLL loop filter BW is restored to default.
    ###################################################################################################################
    
    Fhm_Mode.FhmEnable = 0
    Link.Talise.SetFhmMode(Fhm_Mode)
    
    ########################################
    #configure back the service frequency 
    ########################################
    
    Link.Talise.RadioOff()
    Link.Talise.SetRfPllFrequency(Link.Talise.PllName.RfPll , init_freq )		
    Link.Talise.RadioOn()
    
    
    #Disconnect from the Zynq Platform
    if(Connect == 1):
        Link.hw.Disconnect()
    
    
    Please refer to the attached sample Iron python script.

Reply
  • 0
    •  Analog Employees 
    on Mar 20, 2020 10:14 AM 11 months ago in reply to NathanB
    From the ADRV9008-1-W-9008-2-W-9009-W-Hardware-Reference-Manual-UG-1295.pdf, document it just has initial frequency, min and max frequencies, but does not have a structure for setting frequency increment or step size or a list of frequencies. 

    there is no separate API or data structure. You need to call setfhmhop in a sequence.

    TALISE_setFhmHop()
    This function triggers frequency hopping via an Arm command instead of a GPIO pulse.
    TALISE_setFhmHop(taliseDevice_t *device, uint64_t nextRfPllFrequency_Hz)

    freq_hop.txt
    ########################
    #ADI Demo Python Script
    ########################
    
    #Import Reference to the DLL
    import clr
    import System
    import time
    clr.AddReferenceToFileAndPath("C:\\Program Files (x86)\\Analog Devices\\ADRV9009 Transceiver Evaluation Software\\AdiCmdServerClient.dll")
    from AdiCmdServerClient import AdiCommandServerClient
    from AdiCmdServerClient import Talise
    from AdiCmdServerClient import FpgaTalise
    from AdiCmdServerClient import Enums
    from System import Array
    import AdiCmdServerClient
    #Create an Instance of the Class
    Link = AdiCommandServerClient.Instance
    
    #Connect to the Zynq Platform
    if(Link.hw.Connected == 1):
        Connect = 0
    else:
        Connect = 1
        Link.hw.Connect("192.168.1.10", 55555)
    
    print Link.Version()
    
    #####################################################################
    #Frequency hopping config, this can be set in radio off state only
    ####################################################################
    
    Link.Talise.RadioOff()
    Fhm_Config = Link.Talise.FhmConfig()
    Fhm_Config.FhmGpioPin = AdiCmdServerClient.GpioSel.TAL_GPIO_INVALID  #TAL_GPIO_04 #TAL_GPIO_INVALID
    Fhm_Config.FhmMinFreq_MHz = 255
    Fhm_Config.FhmMaxFreq_MHz = 6000
    Link.Talise.SetFhmConfig(Fhm_Config)
    Link.Talise.RadioOn()
    
    #####################################################################
    #Frequency hopping mode setup, this can be called in radio on state
    ####################################################################
    Fhm_Mode = Link.Talise.FhmMode()
    Fhm_Mode.FhmEnable = 1
    Fhm_Mode.EnableMcsSync = 1
    Fhm_Mode.FhmTriggerMode = Talise.FhmTriggerMode.FhmNonGpioMode  #FhmGpioMode, FhmNonGpioMode 
    Fhm_Mode.FhmExitMode = Talise.FhmExitMode.FhmFullExit #FhmQuickExit, FhmFullExit 
    Fhm_Mode.FhmInitFrequency_Hz  = 3500000000
    Link.Talise.SetFhmMode(Fhm_Mode)
    
    ####################################################################
    #Read back the service frequency before starting frequency hopping
    ####################################################################
    
    init_freq = 0
    init_freq = Link.Talise.GetRfPllFrequency(Link.Talise.PllName.RfPll , 0)
    
    #####################################################################
    #Frequency hopping frequency set and can call any nymber of hopps
    ####################################################################
    
    '''
    #Link.Talise.SetFhmHop(3500000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3505000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3510000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3520000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3530000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    Link.Talise.SetFhmHop(3540000000)
    time.sleep(5)
    print Link.Talise.GetFhmRfPllFrequency(0)
    '''
    
    for i in range(0,100,1):
        Link.Talise.SetFhmHop(3505000000)
        Link.Talise.SetFhmHop(3540000000)
        Link.Talise.SetFhmHop(3505000000)
    
    ###################################################################################################################
    #Frequency hopping mode disable, make sure to disable after FHM as the RFPLL loop filter BW is restored to default.
    ###################################################################################################################
    
    Fhm_Mode.FhmEnable = 0
    Link.Talise.SetFhmMode(Fhm_Mode)
    
    ########################################
    #configure back the service frequency 
    ########################################
    
    Link.Talise.RadioOff()
    Link.Talise.SetRfPllFrequency(Link.Talise.PllName.RfPll , init_freq )		
    Link.Talise.RadioOn()
    
    
    #Disconnect from the Zynq Platform
    if(Connect == 1):
        Link.hw.Disconnect()
    
    
    Please refer to the attached sample Iron python script.

Children
  • Thanks.  How fast were you able to set the LO PLL ?

    It looks like this was running over an IP connection.  I was able to get my frequency hop code working over an IP connection in Python, but it only went from taking 0.3 seconds to taking 0.1 seconds with FHMmode.  I would like to be able to set the LO PLLin ~1ms. The UG-1295 hardware guide says you can get down to about 60us, so I would think 1ms should be achievable, but my 100ms number is way off from this. 

    I'm working on porting the python code from Windows with an IP connection,to the target Linux environment.  THis should provide some speed improvement but I'm not sure how much.  Any idea here?

    After that if that is not fast enough, I will port to C then see how fast that is.  

    Do you know if the LO PLL loop bandwidth has to be adjusted in FHM mode or is it automatic?

    Nathan

  • 0
    •  Analog Employees 
    on Mar 23, 2020 1:48 PM 11 months ago in reply to NathanB
    I'm working on porting the python code from Windows with an IP connection,to the target Linux environment.  THis should provide some speed improvement but I'm not sure how much.  Any idea here?

    Yes, the software layer could add more delays. 

    Are you using GPIO or GPIO mode?

    Do you know if the LO PLL loop bandwidth has to be adjusted in FHM mode or is it automatic?

    Loop Filter is taken care by FHM mode.

  • Hi,

    I'm trying to speed up the FHM, LO changes.  I've ran Python code in host and target of the ADRV9009-ZU11EG, but both changes together take about 200 ms (100ms per part) to change the LO frequency in FHM mode.  Do you know if a C code implementation would speed this up?  (I'm not sure how much over head there is in Python)  

    I know the SPI has some overhead, but the device tree file already has the SPI set to 25MHz and the maximum is 50MHz.  That should cut the time in half.    

    I'm trying to figure out how you all intended to use the GPIO mode and what its purpose is for controlling the LO on the ADRV9009 parts.  From Travis comment below, it looks like in GPIO mode, an SPI write is still required.  Is there something I'm missing here?     

    Travis said: 

    In regards to the transceiver itself, you have to follow the steps 1. send SPI write with desired frequency 2. Trigger Move to frequency (GPIO or SPI). Frequency hopping is independent of data that to send or receive.

    The UG-1295 says, it takes a minimum of 60us to change the LO frequency depending on the profile settings. Are there any profile settings that can help speed up the change? 

    I'm trying to get to about 1ms for setting the LO (2ms for both).  Is it possible to go this fast in FHM including any SPI communications?    

    If the SPI communications takes half the time, and the actual trigger and transition takes the other half of the time, i can see how creating a thread to write the next SPI LO frequency and seperate step to trigger the transition could speed things up, but not if the actual transition time is already close to ~60us.  

    Nathan

    ps How do I reference someone else's comment on this blog?  I couldn't find this option. 

  • 0
    •  Analog Employees 
    on May 16, 2020 4:16 AM 9 months ago in reply to NathanB
  • Hi,

    I see that the device tree has the GPIO pin set to zero by default (adi,fhm-config-fhm-gpio-pin = <0>).

    https://github.com/analogdevicesinc/linux/blob/master/arch/arm64/boot/dts/xilinx/zynqmp-adrv9009-zu11eg-reva.dtsi

    It looks like the GPIO referred to in (adi,fhm-cinfig-fhm-gpio-pin) is associated with the 3.3V supply because of this next link.  Is this correct?  

    https://wiki.analog.com/resources/tools-software/linux-drivers/iio-transceiver/adrv9009-customization

    From the RFSOM schematic however, there is a little note that says, "AUXDAC_4" on the GPIO_3P3_0_A line.  Does the GPIO_3P3_0_A serve as dual purpose in the ADRV9009?  I did not see any references in the schematic to FHM GPIO.   

    How do I write a one or a zero to the GPIO pin, associated with the FHM?

    This is what I have tried in Python but it does not cause the LO frequency to trigger and advance after writing the next frequency value via SPI ... 

    sdr._ctrl.debug_attrs["adi,gpio3v3-source-control"].value = "0x0003"                     #bit bang mode with API
    sdr._ctrl.debug_attrs["adi,gpio3v3-output-enable-mask"].value = "0x0001"            #set to GPIO_0 as output
    sdr._ctrl.debug_attrs["adi,gpio3v3-output-level-mask"].value = "0x0000"                #set GPIO_0 to level 0

    sdr._ctrl_b.debug_attrs["adi,gpio3v3-source-control"].value = "0x0003"                 #bit band mode with API
    sdr._ctrl_b.debug_attrs["adi,gpio3v3-output-enable-mask"].value = "0x0001"        #set to GPIO_0 as output
    sdr._ctrl_b.debug_attrs["adi,gpio3v3-output-level-mask"].value = "0x0000"            #set GPIO_0 to level 0
    I see that after writing the above values, I can read them back and they have changed. 

    Nathan