Hi,
I'm trying to write voltages to the Fastino channels in parallel.
According to the manual i've tried use "with parallel" but then no channel is updating.

`from artiq.experiment import *
import numpy as np

class Test(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("fastino0")
@kernel
def run(self):

    self.core.reset()
    self.fastino0.init()
    f = self.fastino0
    omega=50e3
    t=(1/omega)*1e6
    n = 36
    s = [f.voltage_to_mu(5*np.cos(2*np.pi*i/n))
        for i in range(n)]
    delay(100*ms)
    T=t/n
    cycle=1
    self.core.break_realtime()
    
    while cycle<4:
        for i in range(100000):
            for j in range(n):

                with parallel:
                    f.set_dac_mu(0, s[j])
                    f.set_dac_mu(2, s[j])
                delay(T*us)
        cycle=cycle+1
        delay(1000*ms)

`
Will appreciate some guidance, thanks.

Use set_group_mu instead.

  • yosi replied to this.

    sb10q Thanks, I thought about it but couldn’t find any documentation about how to change the log2_width so group will be taken into account. Any idea?

    Assuming I need to flash Kasli in order to update log2_width parameter I will state my progress so far:

    • download the artiq-board-* for my variant
      -adding "log2_width": 5 to the device_db file in the Fastino arguments
      I'm struggling with what to do next.. should I change the log2_width in the fastino.py (both driver and gateware)? and then what? flashing via artiq_flash -V * will do the trick?

    Thanks

    What variant do you have?

    • yosi replied to this.

      OK, please write to helpdesk@ to get updated firmware.

      The wide interface is not needed here. with parallel is not supported and you will get an error in the log. Refer to the documentation about atomic updates:

      The RTIO PHY supports staging DAC data before transmitting them by writing to the DAC RTIO addresses, if a channel is not “held” by setting its bit using set_hold(), the next frame will contain the update. For the DACs held, the update is triggered explicitly by setting the corresponding bit using set_update(). Update is self-clearing. This enables atomic DAC updates synchronized to a frame edge.

      • yosi replied to this.

        rjo
        I figured how to use the set_hold() but it is limiting the sample rate because each set_dac() will be count as an action and you will not be able to get 2.5 Ms/s on all channels.

        Now if I decide to use this method, I still can't set a TTL pulse to start together with the fastino.
        I end up with a 1.5 us delay
        my minimal code is-

        class Test(EnvExperiment):
            def build(self):
                self.setattr_device("core")
                self.setattr_device("core_dma")
                self.setattr_device("fastino0")
                self.setattr_device("ttl5")
            @kernel
            def record(self):
                f = self.fastino0
                omega=50e3
                t=(1/omega)*1e6
                n = 36
                s = [f.voltage_to_mu(5*np.sin(2*np.pi*i/n))
                    for i in range(n)]
                T=t/n
                with self.core_dma.record("sin"):
                    for i in range(3):
                      for j in range(n):
                        f.set_hold(21)
                        delay(.05*us)
                        f.set_dac_mu(1,s[j])
                        delay(.05*us)
                        f.write(3,s[j])
                        delay(.05*us)
                        f.write(5,s[j])
                        delay((T-0.15)*us)
                        f.update(21)
            @kernel
            def run(self):
                self.core.reset()
                self.fastino0.init()
                self.ttl5.output()
                self.record()
                sin_handle = self.core_dma.get_handle("sin")
                self.core.break_realtime()
                with parallel:
                    self.ttl5.pulse(3*us)
                    self.core_dma.playback_handle(sin_handle)

        The behavior is the same without the DMA.
        Below is the scope output

        Latencies are not matched between different modules. That needs to be calibrated and implemented by the user.

        And 2.5 MS/s can only be bursted and not be sustained on a large number of channels. DMA pushes the limit further. And the wide interface (log2_width) also changes the achievable sustained rate. There are several discussions in the forum and on github about this.