Yes, apologies for the typo I do mean direct memory access.
For future reference, I found a way to do the logic-free conversion from a binary string to a pulse sequence that I was initially asking for by running:
for i in bins:
ttl.set_o(bool(bins[i])
delay(period)
where bins is a list with entries corresponding to each digit in the binary number. I’m sure I could skip the list step and do this even more simply directly from the binary number if I so desired. As @architeuthis and @sb10q suggested though, this does not allow me to program pulses any faster without running into an underflow.
Instead, I can program pulses much faster by simplifying how I program the sequence; rather than sending one pulse per bit of each 8 bit word, I instead assemble a list of delays; each delay corresponds to the amount of time that passes between a ttl switching from high to low, or vice versa. This list is much shorter than the word and by using it, I can send pulse sequences at a bitrate of over 70 Mhz without running into underflows; this is more than enough for my purposes.
The funny thing is that although I can send a pulse sequence at frequencies exceeding 70 MHz without triggering an underflow, I do trigger an underflow if I try to send that sequence multiple times in a row with less than about .5 second delay in between rounds. This appears counter to the basic purpose of DMA, and leads me to conclude that I must be misusing it in some way. The relevant structure of my code is:
@kernel
def record(self):
with self.core_dma.record("pulses"):
for i in range(0,len(self.delays)):
delay(float(self.delays[i])*period)
if i%2 != 0:
self.ttl.on()
else:
self.ttl.off()
@kernel
def run(self):
self.core.reset()
self.record()
pulses_handle = self.core_dma.get_handle("pulses")
self.core.break_realtime()
while True:
delay(self.wait_time)
self.core_dma.playback_handle(pulses_handle)
Is there anything in my record method that is slowing me down unnecessarily? Nothing stands out to me.