@@ -292,27 +292,63 @@ def transition_to_buffered(self, device_name, h5file, initial_values, fresh):
292292
293293 # Program instructions
294294 for pseudoclock , pulse_program in enumerate (pulse_programs ):
295- for i , instruction in enumerate (pulse_program ):
296- if i == len (self .smart_cache [pseudoclock ]):
297- # Pad the smart cache out to be as long as the program:
298- self .smart_cache [pseudoclock ].append (None )
299-
300- # Only program instructions that differ from what's in the smart cache:
301- if self .smart_cache [pseudoclock ][i ] != instruction :
302- self .prawnblaster .write (
303- b"set %d %d %d %d\r \n "
304- % (
305- pseudoclock ,
306- i ,
307- instruction ["half_period" ],
308- instruction ["reps" ],
295+ # check if it is more efficient to fully refresh
296+ if not fresh and self .smart_cache [pseudoclock ] is not None :
297+ # get more convenient handles to smart cache arrays
298+ curr_inst = self .smart_cache [pseudoclock ]
299+
300+ # if arrays aren't of same shape, only compare up to smaller array size
301+ n_curr = len (curr_inst )
302+ n_new = len (pulse_program )
303+ if n_curr > n_new :
304+ # technically don't need to reprogram current elements beyond end of new elements
305+ new_inst = np .sum (curr_inst [:n_new ] != pulse_program )
306+ elif n_curr < n_new :
307+ n_diff = n_new - n_curr
308+ val_diffs = np .sum (curr_inst != pulse_program [:n_curr ])
309+ new_inst = val_diffs + n_diff
310+ else :
311+ new_inst = np .sum (curr_inst != inst )
312+
313+ if new_inst / total_inst > 0.1 :
314+ fresh = True
315+
316+ if fresh or self .smart_cache [pseudoclock ] is None :
317+ print ('programming from scratch' )
318+ self .prawnblaster .write (b"setb %d %d %d\r \n " % (pseudoclock , 0 , len (pulse_program )))
319+ serial_buffer = b''
320+ for i in range (0 , len (pulse_program )):
321+ serial_buffer += struct .pack ('<I' , pulse_program [i ]['half_period' ])
322+ serial_buffer += struct .pack ('<I' , pulse_program [i ]['reps' ])
323+ self .prawnblaster .write (serial_buffer )
324+ response = self .prawnblaster .readline ().decode ()
325+ assert (
326+ response == "ok\r \n "
327+ ), f"PrawnBlaster said '{ response } ', expected 'ok'"
328+ self .smart_cache [pseudoclock ] = pulse_program
329+ else :
330+ print ('incremental programming' )
331+ for i , instruction in enumerate (pulse_program ):
332+ if i == len (self .smart_cache [pseudoclock ]):
333+ # Pad the smart cache out to be as long as the program:
334+ self .smart_cache [pseudoclock ].append (None )
335+
336+ # Only program instructions that differ from what's in the smart cache:
337+ if self .smart_cache [pseudoclock ][i ] != instruction :
338+ self .prawnblaster .write (
339+ b"set %d %d %d %d\r \n "
340+ % (
341+ pseudoclock ,
342+ i ,
343+ instruction ["half_period" ],
344+ instruction ["reps" ],
345+ )
309346 )
310- )
311- response = self .prawnblaster .readline ().decode ()
312- assert (
313- response == "ok\r \n "
314- ), f"PrawnBlaster said '{ response } ', expected 'ok'"
315- self .smart_cache [pseudoclock ][i ] = instruction
347+ response = self .prawnblaster .readline ().decode ()
348+ assert (
349+ response == "ok\r \n "
350+ ), f"PrawnBlaster said '{ response } ', expected 'ok'"
351+ self .smart_cache [pseudoclock ][i ] = instruction
316352
317353 if not self .is_master_pseudoclock :
318354 # Start the Prawnblaster and have it wait for a hardware trigger
0 commit comments