han94ros

I'm just starting to play around with the ram_mode functionality. I'm wondering if you've resolved your issue and how?

Also, is there a way to individually set the DDS profiles on a particular urukul? It seems that self.u.cpld.set_profile(0) sets the profile to 0 for all of the dds chips on the board corresponding to that cpld??

    jbroz Yes I have created a completed and tested script. You should note there was an issue with the amplitude decreasing with decreasing time step between the RAM samples. This can be fixed from the solution proposed in this github issue. https://github.com/m-labs/artiq/issues/1554. I have attached my tested code below so feel free to test and improve this code.

    `

            
            from artiq.experiment import *
            from artiq.coredevice import ad9910
            import numpy as np
            #there are 1024 values for each profile, and the control parameters are the CF, MF, and MD
            #The standard value has been set as N = 1024
            #first write a simple script and then looking to optimise it.
    
            N  = 25
            
            #f1 = 99.*MHz
            #f2 = 100.*MHz
            
            
            #CF, MD, and MF are all in MHz
            CF = 100
            MF = 0.05
            MD = 0.5
            
            #Converting to time period in seconds. 
            time_period = (1/(MF*MHz))*(1e9)
            print(time_period)
            time_step= (time_period/N)
            print(time_step)
            t_step = int(round(time_step/4))
            print(t_step, "t_step")
            T = int(1e2)  
             
            class DDS_freq_ramp(EnvExperiment):
             
                def build(self):
                    self.setattr_device("core")
                    self.setattr_device("urukul1_cpld") #2nd Urukul module
                    self.setattr_device("urukul1_ch3") #Urukul module
                    self.u = self.urukul1_ch3
             
                def prepare(self):
                    
                    #create list of frequencies in FTW format to write to RAM
            
                    self.f = [0.]*N
                    self.f_ram = [0]*N
                    time = np.arange(0,N,1)
                    amplitude = np.sin(2*np.pi*time/(N-1))
                    amplitude2 = amplitude*MD
                    amplitude3 = amplitude2+CF
                    amplitude4 = amplitude3*MHz
                    #f_span = f2 - f1
                    #f_step = f_span / N
                    #print(f_step)
                    print(amplitude4)
                    #I want to see the first step
                    #print(f1+f_step)
                    for i in range(N):
                        self.f[i] = amplitude4[i]
                        self.u.frequency_to_ram(self.f,self.f_ram)
             
                @kernel
                def run(self):
                    #self.core.reset()
                    self.core.break_realtime()
                    '''initialize DDS channel'''
                    self.u.cpld.init()
                    self.u.init()
                    self.u.cpld.io_update.pulse(100*ns)
                    #self.core.break_realtime()
                    self.u.set_amplitude(1.)
                    self.u.set_att(0.*dB)
                    self.u.set(100.*MHz)
             
                    '''prepare RAM profile:'''
                    self.u.set_cfr1(ram_enable=0) #disable RAM for writing data
                    self.u.cpld.io_update.pulse(100*ns) #I/O pulse to enact RAM change
                    self.u.set_profile_ram(start=0, end=N-1, step=t_step, profile=0, mode=ad9910.RAM_MODE_CONT_RAMPUP)
                    self.u.cpld.set_profile(0)
                    delay(10 * us)
                    self.u.cpld.io_update.pulse(100*ns)
                
             
                    '''write data to RAM:'''
                    delay(10*us)
                    self.u.write_ram(self.f_ram)
                    delay(10*us)
             
                    '''enable RAM mode (enacted by IO pulse) and fix other parameters:'''
                    self.u.set_cfr1(internal_profile=0, ram_enable = 1, ram_destination=ad9910.RAM_DEST_FTW, manual_osk_external=0, osk_enable=1, select_auto_osk=0)
                    self.u.sw.on()
                    delay(10 *us)
                    self.u.cpld.io_update.pulse_mu(8)
                    delay(1 * ms)
                    self.u.set_cfr1(ram_enable =0)

    `

    han94ros Will do. So far, I've just been playing with the amplitude modulation. But for the most part I'm doing everything the same way as you and it seems to be working fine. I don't know how much there is to improve.

    I'm still surprised that you can't set the profiles individually for the different DDS chips on the board (if this is, in fact, the case -- though, I haven't tested it yet).

    Also, thanks for pointing out the osk_enable hack! I'm sure that will save me some time tomorrow.

      jbroz Sure no worries, I am also working on the amplitude modulation today and perhaps we can compare codes. I will post it here after I have completed it.

      jbroz Have you been able to find a workaround to setting different modulation profiles for the different chips/channels on the board?

      I can only seem to run this script on a single channel, it is suprising the RAM cannot be made to output to more than one channel simulatenously.

      jbroz seems to work if you do not disable the RAM when writing the waveform to another chip/channel. This allows for the setting of independent frequency modulated signals to the different chips.

      It says in the manual however that it is strongly recommended that RAM_enable = 0 when performing load/retrieve operations - do you believe writing to the RAM whilst it is still enabled would cause any damage.

      Ahh, that makes sense. I think the warning in the manual doesn't apply since the load/retrieve operations are just being performed on a single DDS (even though we've switched the profile setting on all of them). But I could be wrong.

      a month later

      No additional interest or development that I know of.

        airwoodix Thanks for the information.
        rjo Exposure of the DRG api would simplify the programming significantly in some frequency sweep tasks. Is there any advice on what I can do since I really need the function?

        As always: fund the development and talk to people that can implement it or if you feel up to it, do it yourself.

          han94ros Thanks for the advice. In fact, I've implemented a workable solution with DMA. But I still think that being able to get direct access to DRG would enable us to tackle the problem in a more elegant way.

          a year later

          airwoodix
          I tried your method and the DDS frequency was stuck in the lower limit for >250 us.

          I am not sure how to control/eliminate the time gap (where its stuck at lower limit). Couldn't find anything relevant in the datasheet. Alternatively I have fixed the DRCTL pins to high in the CPLD, and just use the increment fields instead. This is what I got by combining the DRG (frequency) and RAM (amplitude).

          Amplitude and frequency changes simultaneously at a defined interval.

          Are there any interest for this CPLD patch?
          Nvm, just enable load LRR @ I/O Update in CFR1. See the DRG usage in ARTIQ.