Post Go back to editing

Cannot load settings from EEPROM on AD9544

Category: Hardware
Product Number: AD9544

I've created a working configuration in ACE and tested it on the evaluation board. I converted it to a bin file using the python script, which works although it gives a number of warning messages:

Missing data for Register: 0x301.
 Using Default Data.
Missing data for Register: 0x302.
 Using Default Data.
Missing data for Register: 0x303.
 Using Default Data.
Missing data for Register: 0x1029.
 Using Default Data.
Missing data for Register: 0x10c0.
 Using Default Data.
Missing data for Register: 0x10c1.
 Using Default Data.
Missing data for Register: 0x10c2.
 Using Default Data.
Missing data for Register: 0x10c3.
 Using Default Data.
Missing data for Register: 0x10c4.
 Using Default Data.
Missing data for Register: 0x10c5.
 Using Default Data.
Missing data for Register: 0x10c6.
 Using Default Data.
Missing data for Register: 0x10c7.
 Using Default Data.
Missing data for Register: 0x10c8.
 Using Default Data.
Missing data for Register: 0x10c9.
 Using Default Data.
Missing data for Register: 0x10ca.
 Using Default Data.
Missing data for Register: 0x10cb.
 Using Default Data.
Missing data for Register: 0x10cc.
 Using Default Data.
Missing data for Register: 0x10cd.
 Using Default Data.
Missing data for Register: 0x10cf.
 Using Default Data.
Missing data for Register: 0x10d0.
 Using Default Data.
Missing data for Register: 0x10d1.
 Using Default Data.
Requested Register: 0x1429 does not exist.
 Using Data = 0x00.
Missing data for Register: 0x14c0.
 Using Default Data.
Missing data for Register: 0x14c1.
 Using Default Data.
Missing data for Register: 0x14c2.
 Using Default Data.
Missing data for Register: 0x14c3.
 Using Default Data.
Missing data for Register: 0x14c4.
 Using Default Data.
Missing data for Register: 0x14c5.
 Using Default Data.
Missing data for Register: 0x14c6.
 Using Default Data.
Missing data for Register: 0x14c7.
 Using Default Data.
Missing data for Register: 0x14c8.
 Using Default Data.
Missing data for Register: 0x14c9.
 Using Default Data.
Requested Register: 0x14ca does not exist.
 Using Data = 0x00.
Requested Register: 0x14cb does not exist.
 Using Data = 0x00.
Requested Register: 0x14cc does not exist.
 Using Data = 0x00.
Requested Register: 0x14cd does not exist.
 Using Data = 0x00.
Missing data for Register: 0x14cf.
 Using Default Data.
Missing data for Register: 0x14d0.
 Using Default Data.
Requested Register: 0x14d1 does not exist.
 Using Data = 0x00.
Requested Register: 0x14d5 does not exist.
 Using Data = 0x00.
Requested Register: 0x14d9 does not exist.
 Using Data = 0x00.
Requested Register: 0x2015 does not exist.
 Using Data = 0x00.
Requested Register: 0x2204 does not exist.
 Using Data = 0x00.
Missing data for Register: 0x2800.
 Using Default Data.
Missing data for Register: 0x2801.
 Using Default Data.
Missing data for Register: 0x2802.
 Using Default Data.
Missing data for Register: 0x2803.
 Using Default Data.
Missing data for Register: 0x2804.
 Using Default Data.
Missing data for Register: 0x2805.
 Using Default Data.
Missing data for Register: 0x2806.
 Using Default Data.
Missing data for Register: 0x2807.
 Using Default Data.
Missing data for Register: 0x2808.
 Using Default Data.
Missing data for Register: 0x2809.
 Using Default Data.
Missing data for Register: 0x280a.
 Using Default Data.
Missing data for Register: 0x280b.
 Using Default Data.
Missing data for Register: 0x280c.
 Using Default Data.
Missing data for Register: 0x280d.
 Using Default Data.
Missing data for Register: 0x280e.
 Using Default Data.
Missing data for Register: 0x280f.
 Using Default Data.
Missing data for Register: 0x2810.
 Using Default Data.
Missing data for Register: 0x2811.
 Using Default Data.
Missing data for Register: 0x2812.
 Using Default Data.
Missing data for Register: 0x2813.
 Using Default Data.
Missing data for Register: 0x2814.
 Using Default Data.
Missing data for Register: 0x2815.
 Using Default Data.
Missing data for Register: 0x2816.
 Using Default Data.
Missing data for Register: 0x2817.
 Using Default Data.
Missing data for Register: 0x2818.
 Using Default Data.
Missing data for Register: 0x2819.
 Using Default Data.
Missing data for Register: 0x281a.
 Using Default Data.
Missing data for Register: 0x281b.
 Using Default Data.
Missing data for Register: 0x281c.
 Using Default Data.
Missing data for Register: 0x281d.
 Using Default Data.
Missing data for Register: 0x281e.
 Using Default Data.
Missing data for Register: 0x2840.
 Using Default Data.
Missing data for Register: 0x2841.
 Using Default Data.
Missing data for Register: 0x2842.
 Using Default Data.
Missing data for Register: 0x2843.
 Using Default Data.
Missing data for Register: 0x2844.
 Using Default Data.
Missing data for Register: 0x2845.
 Using Default Data.
Missing data for Register: 0x2846.
 Using Default Data.
Missing data for Register: 0x2847.
 Using Default Data.
Missing data for Register: 0x2848.
 Using Default Data.
Missing data for Register: 0x2849.
 Using Default Data.
Missing data for Register: 0x284a.
 Using Default Data.
Missing data for Register: 0x284b.
 Using Default Data.
Missing data for Register: 0x284c.
 Using Default Data.
Missing data for Register: 0x284d.
 Using Default Data.
Missing data for Register: 0x284e.
 Using Default Data.
Missing data for Register: 0x284f.
 Using Default Data.
Missing data for Register: 0x2850.
 Using Default Data.
Missing data for Register: 0x2851.
 Using Default Data.
Missing data for Register: 0x2852.
 Using Default Data.
Missing data for Register: 0x2853.
 Using Default Data.
Missing data for Register: 0x2854.
 Using Default Data.
Missing data for Register: 0x2855.
 Using Default Data.
Missing data for Register: 0x2856.
 Using Default Data.
Missing data for Register: 0x2857.
 Using Default Data.
Missing data for Register: 0x2858.
 Using Default Data.
Missing data for Register: 0x2859.
 Using Default Data.
Missing data for Register: 0x285a.
 Using Default Data.
Missing data for Register: 0x285b.
 Using Default Data.
Missing data for Register: 0x285c.
 Using Default Data.
Missing data for Register: 0x285d.
 Using Default Data.
Missing data for Register: 0x285e.
 Using Default Data.
Missing data for Register: 0x2a00.
 Using Default Data.
Missing data for Register: 0x2a01.
 Using Default Data.
Missing data for Register: 0x2a02.
 Using Default Data.
Missing data for Register: 0x2a03.
 Using Default Data.
Missing data for Register: 0x2a04.
 Using Default Data.
Missing data for Register: 0x2a05.
 Using Default Data.
Missing data for Register: 0x2a06.
 Using Default Data.
Missing data for Register: 0x2a07.
 Using Default Data.
Missing data for Register: 0x2a08.
 Using Default Data.
Missing data for Register: 0x2a09.
 Using Default Data.
Missing data for Register: 0x2a0a.
 Using Default Data.
Missing data for Register: 0x2a0b.
 Using Default Data.
Missing data for Register: 0x2a0c.
 Using Default Data.
Missing data for Register: 0x2a0d.
 Using Default Data.
Missing data for Register: 0x2a0e.
 Using Default Data.
Missing data for Register: 0x2a0f.
 Using Default Data.
Missing data for Register: 0x2a10.
 Using Default Data.
Missing data for Register: 0x2a11.
 Using Default Data.
Missing data for Register: 0x2a12.
 Using Default Data.
Missing data for Register: 0x2a13.
 Using Default Data.
Missing data for Register: 0x2a14.
 Using Default Data.
Missing data for Register: 0x2a15.
 Using Default Data.
Missing data for Register: 0x2a16.
 Using Default Data.
Missing data for Register: 0x2a17.
 Using Default Data.
Checksum is: 0xb4206fd

I removed the EEPROM and put it in an external programmer and verified that the bytes were copied.  Next I put the EEPROM back into the evaluation board, and set the M3 jumper as described in the wiki:

This lights up a red LED and puts TP603 to 1.8V, but on power up the PLL has no output.  If I power up, then remove the M3 jumper, I can read back the registers in ACE, which are default.  

I'm not sure what else to try.  Perhaps I have made the bin file incorrectly?

Parents
  • Hi,

    could you please send me the cso file you have used as the input to the python script? I ran the script under Python 3.9 and definitely does not give the messages you show. I only get these messages:

    Then, on the board, I have these indications to make sure the EEPROM is connected to the AD9545 and after power up, the AD9545 will download the EEPROM into its registers:

    • Plug P603 and P602 between pins 2 and 3 (DUT), so the AD9545 can access the EEPROM through I2C. You seem to have done this.
    • Take P601 out, so the EEPROM is not write protected. You seem to have done this.
    • At P604, plug jumpers for M1 and M2 between middle pin and VDD label, so the I2C lines have pull up resistors: MP1_PULL between 4 and 5, MP2_PULL between 7 and 8. Please note that boards with versions other than C2 have the VDD label put vice versa with GND, so you may have to     connect the jumpers toward GND label. You do not seem to have done this.
    • M3 pin must be set high at P604, so after power up, the AD9545 downloads the EEPROM content. You seem to have done this, but check the board version based on the note at the previous bullet

    Petre

  • hi:

    1. My board is AD9545/PCBZ REV C2, but the chip on the board is AD9544;

    2. I burn the AD9545.iic file to the board by "USB Eval Board Programmer" tool,So we can see the AD9545 board in ACE;

    3. we use "TCXO50M-9545-7.908K-55.356M-7.908K-feedback-out7.908K-ok-FD7000-PD7000-1000PPM-OK.cso" and apply/apply and sync buttons,The system works as expected,and OUT1A and OUT1B output clock rightly. FPD and PFD are locked.

    4. I use the python code in website:  and file "defaults.txt" file in Downloaded compressed file,and cso file in step3 above, to generate AD9545_setup.bin. 

     RE: AD9545_eeprom_management_script.py has error "bad magic number in 'bitarray': b'\x03\xf3\r\n'" 

    but the following warning is prompted:

    Requested Register: 0x1029 does not exist.
    Using Data = 0x00.
    Requested Register: 0x1429 does not exist.
    Using Data = 0x00.
    Requested Register: 0x14ca does not exist.
    Using Data = 0x00.
    Requested Register: 0x14cb does not exist.
    Using Data = 0x00.
    Requested Register: 0x14cc does not exist.
    Using Data = 0x00.
    Requested Register: 0x14cd does not exist.
    Using Data = 0x00.
    Requested Register: 0x14d1 does not exist.
    Using Data = 0x00.
    Requested Register: 0x14d5 does not exist.
    Using Data = 0x00.
    Requested Register: 0x14d9 does not exist.
    Using Data = 0x00.
    Requested Register: 0x2015 does not exist.
    Using Data = 0x00.
    Requested Register: 0x2204 does not exist.
    Using Data = 0x00.
    Checksum is: 0x62e31859

    5. Remove the eeprom(U601 24AA16) chip and use the eeprom burning tool to burn the file AD9545_setup.bin. The data read from eeprom matches the burned file(AD9545_setup.bin.),  last install the chip onto U601 on the board.

    6. At P604, plug jumpers for M1 and M2 and M3 between middle pin and VDD label,Tested MP1, MP2, and MP3 at three testing points, all of which are at a high voltage of 1.8V,and the MP1, MP2, and MP3 indicator lights on the board are all on。

    7. But the system does not  work as expected,and OUT1A and OUT1B do not output clock rightly.

    8. After powerup the board, we can seen the waveform on the MP1 MP2 test point,But the waveform does not last long。

    I don't know what the problem is.
    Does the AD9544 chip not match the AD9545 we are using? Do I need to modify the “defaults.txt file”? What else can I try?

    ps: Plug P603 and P602 between pins 2 and 3 (DUT) was done.

    Sorry to forget upload .cso file and .bit file:

    AD9545-EEPROM-TEST.zip

  • Hi,

    sorry for the delay in getting back to you. I was out of office.

    The messages you got when you ran the python script that creates the bin file are to be expected. ACE does not output these registers and the script creates them to make the bin file shorter.

    At P604, you did right to put the jumpers of M1, M2 and M3 to VDD. M1 and M2 set pull up resistors on I2C lines, while M3 being high starts the EEPROM download into the AD9545. 

    You still need to plug P602 and P603 jumpers between middle point and DUT to allow the AD9545 to access the EEPROM. I see you did it.

    You should then introduce in the cso file some flags on the M0 pin to signal if EEPROM general fault was detected (page 14 in the UG-1146 guide). At least you will know if the EEPROM downloaded correctly.

    I obtained the same bin file as you when I ran my script.

    I then opened your cso file in ACE and it seemed to me OK. I also ran it on my AD9545 eval board set with a 50MHz external system clock reference. It worked. I then downloaded it into the EEPROM on the eval board and the AD9545 worked after a power cycle.

    I'll continue to work on this tomorrow and get back to you.

    Petre

  • HI,

    this morning I took an AD9544 eval board and I took out the R319=50 ohm, so it accepts 1.8V CMOS 7.908kHz at REFBB.

    I also modified the USB EEPROM, so now the board is seen by ACE as an AD9545 eval board.

    I then used ACE to configure the AD9544 with your cso file and I was able to see at OUT0A the 7.908kHz clock. DPLL0 locked.

    I then used a python script to upload the AD9544 configuration into the EEPROM. I powered down the board, plug the jumper on M3 to make it high and powered back up the board. I could see on the scope OUT0AP, so the EEPROM downloaded correctly.

    I then created a new python script that creates an AD9544 bin file. What you have creates an AD9545 bin file. I created a bin file.

    I then read the EEPROM with another script and I compared the new bin file against the target bin file and they were identical.

    I then ran another script that writes the EEPROM using the USB chip on the eval board with the bin file. I again cycled the board and the OUT0AP showed the right clock, meaning the EEPROM had the right value and downloaded correctly. I also read the AD9544 registers and they were identical with the target ones.

    I'm sharing the scripts for you to see the procedures I'm following. The problem you have is they use an internal library of read/write registers function that I cannot share. But you can use as an example for you to write a controller program to upload the EEPROM with the correct values.

    The script AD9544_download_config reads the cso file and writes the registers into the AD9544, calibrates the analog PLLs and synchronizes the outputs. You do not need to synchronize the outputs because you use Reference Sync function. For debugging purposes, I recommend not using this function

    # -*- coding: utf-8 -*-
    """
    Created on Thu Oct 03 13:38:08 2019
    
    @author: PMinciu
    This file configures an AD9544 on the AD9544 eval board that had the USB EEPROM
    changed to make the board appear as an AD9545 eval board. So the cso file is
    an AD9545 file and we need to download it into the AD9544
    
    State of board jumpers:
      -P501 is plugged in, so USB EEPROM can be accessed by USB chip and the board 
        can be recognized by Windows
      -P502 is plugged in, so the USB EEPROM is write protected
      -P504, P511, P510 and P503 plugged between pins 2 and 3 (SCLK and SDIO), so 
        PC can use SPI to access the AD9545
      -P603 and P602 plugged between pins 2 and 3 (DUT), so the AD9545 can access 
        the EEPROM through I2C
      -P601 taken out, so the EEPROM is not write protected
      -at P604, plug jumpers for M1 and M2 between middle pin and VDD label, so 
        the I2C lines have pull up resistors: MP1_PULL between 4 and 5, 
        MP2_PULL between 7 and 8. Please note that boards with versions other 
        than C2 have the VDD label put vice versa with GND, so you may have to 
        connect the jumpers toward GND label
    
    """
    
    
    import sys, struct
    import xml.etree.ElementTree as ET
    from bitarray import bitarray as BitArray
    
    import os
    # Add the directory where the usb dlls are located to the environment path
    os.environ['PATH'] = 'C:\Users\PMinciu\OneDrive - Analog Devices, Inc\My Documents\.wcplib' + os.pathsep + os.environ['PATH']
    
    
    #from __future__ import print_function
    import sys, time
    #sys.path.append('z:/')
    sys.path.append('C:\Users\PMinciu\OneDrive - Analog Devices, Inc\My Documents\USB_20220309')
    
    from USB import *
    
    d = devmgr.connect('ad9545')
    
    
    #this is the procedure to read the cso file and extract the register values
    file_output = True
    root        = './'
    fn          = 'AD9545_test_petre.cso'
    #fn          = 'AD9545_second_setup.cso'
    
    
    # Read specified input configuration file
    raw     = [x.strip('\n').strip('\r') for x in open(root + fn,'r').readlines()]
    address = []
    data    = []
    reg_value = []
    ext     = fn.split('.')[-1].lower()
    if (ext == 'cso'):
      vals = [ET.fromstring(x.strip(' ')) for x in raw if x.strip(' ').startswith('<Register Address')]
      for val in vals:
        addr = int(val.attrib['Address'], 16)
        value = int(val.attrib['Value'], 16)
    #    value, addr = list(map(int, val.attrib.values(), [16, 16]))
        #this is an array of the addresses in which we will write register values
        address.append(addr)
        #this is an array of the register values that we will write
        reg_value.append(value)
        #this is a combination between addresses and register values
        data.append((addr, value)) 
    
    
    #write the values of the registers in the chip.
    #Registers between 0x2800 and 0x281E belong to AuxNCO0 and cannot be written
    #Registers between 0x2840 and 0x285E belong to AuxNCO1 and cannot be written
    #Registers between 0x2A00 and 0x2A17 belong to AucTDC and cannot be written
    #Registers after 0x2e00 are EEPROM registers and after 0x3000 are status registers
    #So we write only the registers with addresses below 0x2E00
    #address[993] is 0x2E00
    
    for index in range (0,901):
      d.write(address[index], data[index][1]) #write one register at a time up to address 0x2800
      
    for index in range (962,969):
      d.write(address[index], data[index][1]) #write one register at a time from address 0x2900
    
    
      
    #Calibrate all VCOs by setting bit 1 to 1 in register 0x2000
    value=d.read(0x2000)
    d.write(0x2000, hex(value | 0x2))
    d.write(0xF, 0x1)
    time.sleep(3) #wait 3 sec for the PLLs to calibrate
    d.write(0x2000, hex(value))
    d.write(0xF, 0x1)
    
    #synchronize all distribution dividers by setting bit 3 in register 0x2000 to 1
    value=d.read(0x2000)
    d.write(0x2000, hex(value | 0x8))
    d.write(0xF, 0x1)
    d.write(0x2000, hex(value))
    d.write(0xF, 0x1)
    
    #save all the registers values into a file
    filen = 'AD9545_target_regs_initial_setup.txt'
    
    
    _str = ''
    for i in range(0, 900, 1):
      _str += struct.pack("2s", "0x")
      _str += struct.pack("4s", '{:04X}'.format(address[i]))
      _str += struct.pack("3s", ",0x")
      _str += struct.pack("2s", '{:02X}'.format(reg_value[i]))
      _str += struct.pack("c", "\n")
    
    for i in range(962, 969, 1):
      _str += struct.pack("2s", "0x")
      _str += struct.pack("4s", '{:04X}'.format(address[i]))
      _str += struct.pack("3s", ",0x")
      _str += struct.pack("2s", '{:02X}'.format(reg_value[i]))
      _str += struct.pack("c", "\n")
    
    f = open(root + filen.split('.')[0] + '.txt', 'w')
    f.writelines([_str])
    f.close()
    pass
    
    #read all registers that have been written and verify their values coincide with what was written
    #if the read back value is not equal to the value we wanted to write, print it
    for index in range (0,900):
      read_reg_value=d.read(address[index])      #read the register back
      if int(read_reg_value) != data[index][1]:    
        print ('index: ',index, 'reg addr: ', hex(address[index]), 'reg value: ', 
               hex(read_reg_value), 'target reg value: ', hex(data[index][1]))
    
    for index in range (962,969):
      read_reg_value=d.read(address[index])      #read the register back
      if int(read_reg_value) != data[index][1]:    
        print ('index: ',index, 'reg addr: ', hex(address[index]), 'reg value: ', 
               hex(read_reg_value), 'target reg value: ', hex(data[index][1]))
    
    
    
    
    
    
    

    # -*- coding: utf-8 -*-
    """
    Created on Mon Oct 07 15:38:00 2019
    
    @author: PMinciu
    This program considers an AD9545 that is already configured and running.
    Executing this program takes the live registers from the AD9545 and uploads them
    into the EEPROM
    
    State of board jumpers:
      -P501 is plugged in, so USB EEPROM can be accessed by USB chip and the board 
        can be recognized by Windows
      -P502 is plugged in, so the USB EEPROM is write protected
      -P504, P511, P510 and P503 plugged between pins 2 and 3 (SCLK and SDIO), so 
        PC can use SPI to access the AD9545
      -P603 and P602 plugged between pins 2 and 3 (DUT), so the AD9545 can access 
        the EEPROM through I2C
      -P601 taken out, so the EEPROM is not write protected
      -at P604, plug jumpers for M1 and M2 between middle pin and VDD label, so 
        the I2C lines have pull up resistors: MP1_PULL between 4 and 5, 
        MP2_PULL between 7 and 8. Please note that boards with versions other 
        than C2 have the VDD label put vice versa with GND, so you may have to 
        connect the jumpers toward GND label
    
    
    
    
    """
    import sys, struct
    import xml.etree.ElementTree as ET
    from bitarray import bitarray as BitArray
    
    
    import os
    # Add the directory where the usb dlls are located to the environment path
    os.environ['PATH'] = 'C:\Users\PMinciu\OneDrive - Analog Devices, Inc\My Documents\.wcplib' + os.pathsep + os.environ['PATH']
    
    #from __future__ import print_function
    import sys, time
    sys.path.append('z:/')
    from USB import *
    
    d = devmgr.connect('ad9545')
    
    
    #WRITE THE EEPROM
    
    
    #define a sequence of the headers that manage 
    sequence = [
    3,   0x20, 0x00,   # EEPROM Scratchpad Regs
    26,  0x00, 0x01,   # Mpins and IRQ
    9,   0x00, 0x02,   # SysClk
    0x80, # IO Update
    0x91, # Cal sysclk
    28,  0x80, 0x02, # Sysclk comp
    7,   0x00, 0x03, # References General
    20,  0x00, 0x04, # RefA config
    20,  0x20, 0x04, # RefAA config
    20,  0x40, 0x04, # RefB config
    20,  0x60, 0x04, # RefBB config
    17,  0x00, 0x08, # Source Profile 0
    17,  0x20, 0x08, # Source Profile 1
    17,  0x40, 0x08, # Source Profile 2
    17,  0x60, 0x08, # Source Profile 3
    17,  0x80, 0x08, # Source Profile 4
    17,  0xa0, 0x08, # Source Profile 5
    17,  0xc0, 0x08, # Source Profile 6
    17,  0xe0, 0x08, # Source Profile 7
    23,  0x00, 0x0c, # DPLL LF base coefs
    43,  0x00, 0x10, # DPLL0 general settings
    3,   0x80, 0x10, # APLL0 config and output drivers
    28,  0xc0, 0x10, # Dist 0 General
    53,  0x00, 0x11, # Dist Channels
    23,  0x00, 0x12, # Translation Profile 0-0
    23,  0x20, 0x12, # Translation Profile 0-1
    23,  0x40, 0x12, # Translation Profile 0-2
    23,  0x60, 0x12, # Translation Profile 0-3
    23,  0x80, 0x12, # Translation Profile 0-4
    23,  0xa0, 0x12, # Translation Profile 0-5
    43,  0x00, 0x14, # DPLL1 general settings
    3,   0x80, 0x14, # APLL1 General
    28,  0xc0, 0x14, # Dist 1 General
    35,  0x00, 0x15, # Dist Channels
    23,  0x00, 0x16, # Translation Profile 1-0
    23,  0x20, 0x16, # Translation Profile 1-1
    23,  0x40, 0x16, # Translation Profile 1-2
    23,  0x60, 0x16, # Translation Profile 1-3
    23,  0x80, 0x16, # Translation Profile 1-4
    23,  0xa0, 0x16, # Translation Profile 1-5
    21,  0x00, 0x20, # Operational Controls - Common !!!One byte added for the workaround
    7,   0x00, 0x21, # Operational Controls - Channel 0
    7,   0x00, 0x22, # Operational Controls - Channel 1!!!!One byte added to make registers contiguous
    #30,  0x00, 0x28, # AUXNCO 0
    #30,  0x40, 0x28, # AUXNCO 1
    6,   0x00, 0x29, # Temperature Sensor
    #23,  0x00, 0x2a, # AUXTDCs
    0x80, # IO Update
    0x92, # Cal All Aplls
    0xff
    ]
    
    
    #enable write access to EEPROM 
    d.write(0x2E00, 0x1)
    
    index=0
    while index < len(sequence):
      #if the number is an instruction (0x80, 0x91, 0x92, 0xFF), then write the instruction at 0x2E10
      if sequence[index] >= int(0x80):
        d.write(0x2E10, hex(sequence[index]))
    #    print(hex(sequence[index]))  
        if sequence[index] != int(0xFF):
          d.write(0x2E11, 0xFE)
        index +=1
      else:
        d.write(0x2E10, hex(sequence[index]))
    #    print(hex(sequence[index]))  
        index += 1
        d.write(0x2E11, hex(sequence[index]))
    #    print(hex(sequence[index]))  
        index += 1
        d.write(0x2E12, hex(sequence[index]))    
    #    print(hex(sequence[index]))  
        index += 1
        d.write(0x2E13, 0xFE)
      d.write(0x2E02, 0x01) #start to save into EEPROM
    #wait until content saved into EEPROM  
      wait_cntr=0
      while int(d.read(0x3000) & 0x1) == 1:
        wait_cntr +=1
        pass
    #  print(index, wait_cntr)
    
    #disable write access to EEPROM
    d.write(0x2E00, 0x00)
    #print("EEPROM updated")
    
    

    The script AD9544_write_EEPROM uploads the AD9544 registers into the EEPROM.

    # -*- coding: utf-8 -*-
    """
    This program creates a bin file starting from a cso configuration file
    It writes 21 registers from address 0x2000 instead of only 20. In this way, when
    the AD9544 uploads its memory into the EEPROM, it creates the EEPROM image correctly
    (this deals with the EEPROM workaround)
    The registers at address 0x2200 have the 0x2204 location unused. The program
    was modified to allow for 8 contiguous registers at this location (previously the 
    program was set for only 7, missing the register at 0x2207 location)
    
    @author: NWeeks
    """
    import sys, struct
    import xml.etree.ElementTree as ET
    
    from bitarray import bitarray as BitArray
    
    class crc(object):
      __slots__ = ('val', 'polynomial', 'output')
      def __init__(self):
        self.val        = BitArray(0, 32)
        self.polynomial = 0x02608edb
        self.output     = False
        pass
      
      def update(self, val): # Updates MSB to LSB of a specific byte
        xor = (self.val[31] ^ val)
        if (xor):
          self.val[0:31] = (self.val[0:31] ^ self.polynomial)
        self.val[1:31]  = self.val[0:30]
        self.val[0]     = xor
        if (self.output):
          return hex(self.val.value)
    
    file_output = True
    root        = './'
    fn          = 'AD9545_test_petre.cso'
    
    
    # Populate list of default register data
    default_addr = []
    default_data = []
    raw = [x.strip('\n').strip('\r').split(' ')[0] for x in open('./defaults.txt', 'r+').readlines() if x.startswith('0x')]
    for ln in raw:
      addr, value = [int(x, 16) for x in ln.split(',')]
      default_addr.append(addr)
      default_data.append((addr, value))
      pass
    
    # Read specified input configuration file
    raw     = [x.strip('\n').strip('\r') for x in open(root + fn,'r').readlines()]
    address = []
    data    = []
    ext     = fn.split('.')[-1].lower()
    if (ext == 'cso'):
      vals = [ET.fromstring(x.strip(' ')) for x in raw if x.strip(' ').startswith('<Register Address')]
      for val in vals:
        addr = int(val.attrib['Address'], 16)
        value = int(val.attrib['Value'], 16)
    #    value, addr = list(map(int, val.attrib.values(), [16, 16]))
        address.append(addr)
        data.append((addr, value))
    else:
      try:
        start = raw.index('<registers>') + 2
        stop  = raw.index('</registers>')  
      except ValueError:
        try:
          start = raw.index('Address,Data') + 1
        except ValueError:
          start = 0
        stop  = len(raw)
      for i in range(start, stop, 1):
        temp = raw[i].split(',')
        address.append(int(temp[0].strip('\t'), 16))
        data.append((int(temp[0].strip('\t'), 16), int(temp[1].strip('\t'), 16)))
        pass
      pass
    
    opcode_lib={0x80:[(0xf,0,True)],
                0x90:[(0x2000,1,True),(0xf,0,True),(0x2000,1,False),(0xf,0,True)],
                0x91:[(0x2000,2,True),(0xf,0,True),(0x2000,2,False),(0xf,0,True)], 
                0x92:[(0x2100,1,True),(0x2200,1,True),(0xf,0,True),(0x2100,1,False),(0x2200,1,False),(0xf,0,True)],
                0x93:[(0x2100,1,True),(0xf,0,True),(0x2100,1,False),(0xf,0,True)],
                0x94:[(0x2200,1,True),(0xf,0,True),(0x2200,1,False),(0xf,0,True)],
                0xa0:[(0x2000,3,True),(0xf,0,True),(0x2000,3,False),(0xf,0,True)],
                0xa1:[(0x2101,3,True),(0xf,0,True),(0x2101,3,False),(0xf,0,True)],
                0xa2:[(0x2201,3,True),(0xf,0,True),(0x2201,32,False),(0xf,0,True)]}
    
    #Sans channel specific initialization and ending op-code
    sequence = [
    [3,   0x20, 0x00],   # EEPROM Scratchpad Regs
    [26,  0x00, 0x01],   # Mpins and IRQ
    [9,   0x00, 0x02],   # SysClk
    [0x80], # IO Update
    [0x91], # Cal sysclk
    [28,  0x80, 0x02], # Sysclk comp
    [7,   0x00, 0x03], # References General
    [20,  0x00, 0x04], # RefA config
    [20,  0x20, 0x04], # RefAA config
    [20,  0x40, 0x04], # RefB config
    [20,  0x60, 0x04], # RefBB config
    [17,  0x00, 0x08], # Source Profile 0
    [17,  0x20, 0x08], # Source Profile 1
    [17,  0x40, 0x08], # Source Profile 2
    [17,  0x60, 0x08], # Source Profile 3
    [17,  0x80, 0x08], # Source Profile 4
    [17,  0xa0, 0x08], # Source Profile 5
    [17,  0xc0, 0x08], # Source Profile 6
    [17,  0xe0, 0x08], # Source Profile 7
    [23,  0x00, 0x0c], # DPLL LF base coefs
    [43,  0x00, 0x10], # DPLL0 general settings
    [3,   0x80, 0x10], # APLL0 config and output drivers
    [28,  0xc0, 0x10], # Dist 0 General
    [53,  0x00, 0x11], # Dist Channels
    [23,  0x00, 0x12], # Translation Profile 0-0
    [23,  0x20, 0x12], # Translation Profile 0-1
    [23,  0x40, 0x12], # Translation Profile 0-2
    [23,  0x60, 0x12], # Translation Profile 0-3
    [23,  0x80, 0x12], # Translation Profile 0-4
    [23,  0xa0, 0x12], # Translation Profile 0-5
    [43,  0x00, 0x14], # DPLL1 general settings
    [3,   0x80, 0x14], # APLL1 General
    [28,  0xc0, 0x14], # Dist 1 General
    [35,  0x00, 0x15], # Dist Channels
    [23,  0x00, 0x16], # Translation Profile 1-0
    [23,  0x20, 0x16], # Translation Profile 1-1
    [23,  0x40, 0x16], # Translation Profile 1-2
    [23,  0x60, 0x16], # Translation Profile 1-3
    [23,  0x80, 0x16], # Translation Profile 1-4
    [23,  0xa0, 0x16], # Translation Profile 1-5
    [21,  0x00, 0x20], # Operational Controls - Common !!!One byte added for the workaround
    [7,   0x00, 0x21], # Operational Controls - Channel 0
    [7,   0x00, 0x22], # Operational Controls - Channel 1 !!!!One byte added to make registers contiguous
    #[30,  0x00, 0x28], # AUXNCO 0
    #[30,  0x40, 0x28], # AUXNCO 1
    [6,   0x00, 0x29], # Temperature Sensor
    #[23,  0x00, 0x2a], # AUXTDCs
    [0x80], # IO Update
    [0x92], # Cal All Aplls
    [0xff]
    ]
    
    # Create list to house EEPROM data sequence
    burn = []
    
    # Add Header sequence here [consists of data from R0x0003, R0x0004, R0x0005, R0x0006, R0x000C, R0x000D]
    for each in [0x3, 0x4, 0x5, 0x6, 0xc, 0xd]:
      index = address.index(each)
      burn.append(data[index][1])
      pass
    
    #collect data from dut to include in the burn sequence
    for i in range(len(sequence)):
      burn += sequence[i]
      if sequence[i][0] < 0x80:
        # In this case we need to append register data
        for j in range(sequence[i][0] + 1):
          reg = (sequence[i][2] << 8) + sequence[i][1]
          try:
            index = address.index(reg + j)
            burn.append(data[index][1])
          except ValueError:
            try:
              index = default_addr.index(reg + j)
              burn.append(default_data[index][1])
              sys.stdout.write("Missing data for Register: " + hex(reg + j) + '.\r\n Using Default Data.\r\n')
            except ValueError:
              sys.stdout.write("Requested Register: " + hex(reg + j) + ' does not exist.\r\n Using Data = 0x00.\r\n')
              burn.append(0)
          pass
        pass
      pass
    
    # Add CRC checksum here
    checksum = crc()
    for each in burn:
      temp = BitArray(each, 8)
      for i in range(7,-1,-1):
        checksum.update(temp[i])
      pass
    burn.append(int(checksum.val[24:31].value))
    burn.append(int(checksum.val[16:23].value))
    burn.append(int(checksum.val[8:15].value))
    burn.append(int(checksum.val[0:7].value))
    
    # Add null op-codes 
    for i in range(0, ((256 - len(burn)) % 256), 1):
      burn.append(0xff)
      pass
    
    # conditionally output .bin file
    if file_output:
      _str = b''
      for i in range(0, len(burn), 1):
        _str += struct.pack("B", burn[i])
    #  _str = ''.join(chr(x) for x in burn)
      f = open(root + fn.split('.')[0] + '.bin', 'wb')
      f.writelines([_str])
      f.close()
      pass
    
    print("Checksum is: {0}".format(hex(checksum.val.value)))

    The script ad9544_create_eeprom_bin creates the EEPROM bin file that you could use to program your AD9544 EEPROM.

    AD9545_test_petre.cso.txt

    The AD9545_test_petre is the cso file I used in my tests. It should be identical to the cso file you gave.

     V 	0t;�2���@@�@@|�/P	��
     |�/P	��
    @|�/P	��
    `{�ks@B
    �
    
    �
    
     �
    
    �
    
    @�
    
    �
    
    `'
    
    '
    
    ����
    
    �
    
    ��
    
    �
    
    ��U��\���̩�����y��M��+|�^� ���
    8�����/P	5"]"]���G� ��@��`��������+��m#���
    ��
    ��#P4���� ��@��`�������� !")����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

    AD9545_test_petre.bin is the bin file created with the script ad9544_create_eeprom_bin.

     V 	0t;�2���@@�@@|�/P	��
     |�/P	��
    @|�/P	��
    `{�ks@B
    �
    
    �
    
     �
    
    �
    
    @�
    
    �
    
    `'
    
    '
    
    ����
    
    �
    
    ��
    
    �
    
    ��U��\���̩�����y��M��+|�^� ���
    8�����/P	5"]"]���G� ��@��`��������+��m#���
    ��
    ��#P4���� ��@��`�������� !")����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

    The file ad9545_test_petre_EEPROM is the bin file that I read from the EEPROM.

    Bottom line: I showed you that the bin file you can create using an attached script may be stored into the EEPROM of the board and the AD9544 will download it correctly and initialize itself correctly. I gave you some scripts to help you write a controller program that can upload the AD9544 configuration into the EEPROM.

    Petre

  • hi:

    I'm sorry for the long business trip. Thank you for your reply。I noticed that two Python files use USB library files that cannot be shared to me,I need some time to learn this debugging process。But I did the following debugging work:

    1. modified the USB EEPROM, so the board is seen by ACE as an AD9545 eval board.

    2. Run AD9545_test_petre.cso.txt(download from your reply), and  OUT0A the 7.908kHz clock. DPLL0 locked.

    3. Remove the eeprom(U601 24AA16) chip and use the eeprom burning tool to burn the file AD9545_test_petre.bin that downloaded from your reply. then mount eeprom IC-U601-24AA16 back on the board.

    4. I plug the jumper on M3 to make it high and powered back up the board. But I can't see any clock signal on the scope OUT0AP, 

    Is there any thing wrong?

  • HI,

    Is this to lock to the Novanta 7.9 KHz resonant scanner?  We designed an AD9544 board for this purpose that is easier to configure than the eval board and that outputs LVCMOS levels.  We could share with you if that would be helpful.  

    Michael

Reply Children
  • Hi feitianlaoshu,

    Programming the USB EEPROM to make the board be seen as an AD9545 helps ACE to see the AD9544 on the eval board as an AD9545. It does not help with the EEPROM.

    I'm glad you got the DPLL to lock.

    The fact that you burned the EEPROM with the bin file I sent and then the AD9544 did not generate anything, it means to me that the board was not configured correctly to have the AD9544 download the EEPROM.

    I would start with the oscilloscope probe put on pin 5 of P604 (it is as if you put the probe on M1 pin of the AD9545). This senses the SCL pin of the EEPROM. This supposes R629=0ohm is mounted. Then put the second probe on pin 8 of P604 (it is as if you put the probe on M2 pin of the AD9545). This senses SDA pin of the EEPROM and supposes R630 is mounted.

    See if when AD9545 is powered up, the EEPROM download starts.

    Petre