Skip to content

Commit 8195534

Browse files
novatech_phase_mode_fix: Fix issue #37, incorrect transition to manual/buffered semantics for novatech.
It appears that it was a misunderstanding to think of 'm 0' 'm a' and 'm n' as three options for the phase mode (with 'm 0' meaning 'default' - corresponding to one of the others). Rather, 'm n' and 'm a' are the two options for the phase mode, and 'm 0' and 'm t' are for switching between table mode and single-tone mode. Therefore this PR calls 'm 0' at startup, and then one of 'm a' or 'm n' to set the phase mode, which is now by default 'continuous', with 'default' having been removed as an option, but being interpreted as 'continuous' for the case of already-compiled shots that used it. Thereafter, transition between single-tone mode and table mode is done with 'm 0' and 'm t', with no further calls to set the phase mode. Also added a better explanation of the 'double clutch' hack.
1 parent 885ed42 commit 8195534

File tree

1 file changed

+46
-14
lines changed

1 file changed

+46
-14
lines changed

NovaTechDDS9M.py

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,29 @@ class NovaTechDDS9M(IntermediateDevice):
4242
clock_limit = 9990 # This is a realistic estimate of the max clock rate (100us for TS/pin10 processing to load next value into buffer and 100ns pipeline delay on pin 14 edge to update output values)
4343

4444
@set_passed_properties(
45-
property_names = {'connection_table_properties': ['com_port', 'baud_rate', 'default_baud_rate', 'update_mode', 'synchronous_first_line_repeat', 'phase_mode']}
46-
)
47-
def __init__(self, name, parent_device,
48-
com_port = "", baud_rate=115200, default_baud_rate=None, update_mode='synchronous', synchronous_first_line_repeat=False, phase_mode='default', **kwargs):
49-
45+
property_names={
46+
'connection_table_properties': [
47+
'com_port',
48+
'baud_rate',
49+
'default_baud_rate',
50+
'update_mode',
51+
'synchronous_first_line_repeat',
52+
'phase_mode',
53+
]
54+
}
55+
)
56+
def __init__(
57+
self,
58+
name,
59+
parent_device,
60+
com_port="",
61+
baud_rate=115200,
62+
default_baud_rate=None,
63+
update_mode='synchronous',
64+
synchronous_first_line_repeat=False,
65+
phase_mode='continuous',
66+
**kwargs
67+
):
5068
IntermediateDevice.__init__(self, name, parent_device, **kwargs)
5169
self.BLACS_connection = '%s,%s'%(com_port, str(baud_rate))
5270

@@ -59,8 +77,8 @@ def __init__(self, name, parent_device,
5977
if not default_baud_rate in bauds and default_baud_rate is not None:
6078
raise LabscriptError('default_baud_rate must be one of {0} or None (to indicate no default)'.format(list(bauds)))
6179

62-
if not phase_mode in ['default', 'aligned', 'continuous']:
63-
raise LabscriptError('phase_mode must be \'default\', \'aligned\' or \'continuous\'')
80+
if not phase_mode in ['aligned', 'continuous']:
81+
raise LabscriptError('phase_mode must be \'aligned\' or \'continuous\'')
6482

6583
self.update_mode = update_mode
6684
self.phase_mode = phase_mode
@@ -251,7 +269,7 @@ def initialise_GUI(self):
251269
connection_object = self.settings['connection_table'].find_by_name(self.device_name)
252270
connection_table_properties = connection_object.properties
253271

254-
self.phase_mode = connection_table_properties.get('phase_mode', 'default')
272+
self.phase_mode = connection_table_properties.get('phase_mode', 'continuous')
255273

256274
self.com_port = connection_table_properties.get('com_port', None)
257275
self.baud_rate = connection_table_properties.get('baud_rate', None)
@@ -327,10 +345,14 @@ def init(self):
327345

328346
# Set phase mode method
329347
phase_mode_commands = {
330-
'default': b'm 0',
331348
'aligned': b'm a',
332349
'continuous': b'm n',
333350
}
351+
352+
# Backward compat for shots compiled with phase_mode='default', which was based
353+
# on a misunderstanding of the working of the device and never did anything.
354+
phase_mode_commands['default'] = phase_mode_commands['continuous']
355+
334356
self.phase_mode_command = phase_mode_commands[self.phase_mode]
335357

336358
self.connection.write(b'e d\r\n')
@@ -346,6 +368,12 @@ def init(self):
346368
if self.connection.readline() != b"OK\r\n":
347369
raise Exception('Error: Failed to execute command: "I a"')
348370

371+
# Ensure we are in single-tone mode:
372+
self.connection.write(b'm 0\r\n')
373+
if self.connection.readline() != b"OK\r\n":
374+
raise Exception('Error: Failed to execute command: "m 0"')
375+
376+
# Set the phase mode:
349377
self.connection.write(b'%s\r\n'%self.phase_mode_command)
350378
if self.connection.readline() != b"OK\r\n":
351379
raise Exception('Error: Failed to execute command: "%s"'%self.phase_mode.decode('utf8'))
@@ -412,15 +440,19 @@ def program_static(self,channel,type,value):
412440

413441
def transition_to_buffered(self,device_name,h5file,initial_values,fresh):
414442

415-
# Pretty please reset your memory pointer to zero:
443+
# The "double clutch" trick: switching to table mode and back again, before
444+
# going into table mode for real, is observed empirically to resolve an
445+
# off-by-one error in table mode in some circumstances. Presumably it resets the
446+
# memory pointer of the device to zero (though it is a mystery why it would not
447+
# be zero already at this point)
416448

417449
# Transition to table mode:
418450
self.connection.write(b'm t\r\n')
419451
self.connection.readline()
420452
# And back to manual mode
421-
self.connection.write(b'%s\r\n'%self.phase_mode_command)
453+
self.connection.write(b'm 0\r\n')
422454
if self.connection.readline() != b"OK\r\n":
423-
raise Exception('Error: Failed to execute command: "%s"' % self.phase_mode_command.decode('utf8'))
455+
raise Exception('Error: Failed to execute command: "m 0"')
424456

425457

426458
# Store the initial values in case we have to abort and restore them:
@@ -525,9 +557,9 @@ def abort_buffered(self):
525557
return self.transition_to_manual(True)
526558

527559
def transition_to_manual(self,abort = False):
528-
self.connection.write(b'%s\r\n'%self.phase_mode_command)
560+
self.connection.write(b'm 0\r\n')
529561
if self.connection.readline() != b"OK\r\n":
530-
raise Exception('Error: Failed to execute command: "%s"'%self.phase_mode_command.decode('utf8'))
562+
raise Exception('Error: Failed to execute command: "m 0"')
531563
self.connection.write(b'I a\r\n')
532564
if self.connection.readline() != b"OK\r\n":
533565
raise Exception('Error: Failed to execute command: "I a"')

0 commit comments

Comments
 (0)