mirror of
https://github.com/jonathanhogg/scopething
synced 2025-07-13 18:52:10 +01:00
More overdue fixes. The more I look, the more I see this shit everywhere in my code...
This commit is contained in:
36
scope.py
36
scope.py
@ -72,8 +72,8 @@ class Scope(vm.VirtualMachine):
|
|||||||
await self.issue_get_revision()
|
await self.issue_get_revision()
|
||||||
revision = ((await self.read_replies(2))[1]).decode('ascii')
|
revision = ((await self.read_replies(2))[1]).decode('ascii')
|
||||||
if revision == 'BS000501':
|
if revision == 'BS000501':
|
||||||
self.master_clock_rate = 40000000
|
self.primary_clock_rate = 40000000
|
||||||
self.master_clock_period = 1/self.master_clock_rate
|
self.primary_clock_period = 1/self.primary_clock_rate
|
||||||
self.capture_buffer_size = 12 << 10
|
self.capture_buffer_size = 12 << 10
|
||||||
self.awg_wavetable_size = 1024
|
self.awg_wavetable_size = 1024
|
||||||
self.awg_sample_buffer_size = 1024
|
self.awg_sample_buffer_size = 1024
|
||||||
@ -83,8 +83,8 @@ class Scope(vm.VirtualMachine):
|
|||||||
self.analog_params = {'x1': self.AnalogParams(1.1, -.05, 0, 1.1, -.05, -.05, 18.333, -7.517, -5.5, 8, 0)}
|
self.analog_params = {'x1': self.AnalogParams(1.1, -.05, 0, 1.1, -.05, -.05, 18.333, -7.517, -5.5, 8, 0)}
|
||||||
self.analog_lo_min = 0.07
|
self.analog_lo_min = 0.07
|
||||||
self.analog_hi_max = 0.88
|
self.analog_hi_max = 0.88
|
||||||
self.timeout_clock_period = (1 << 8) * self.master_clock_period
|
self.timeout_clock_period = (1 << 8) * self.primary_clock_period
|
||||||
self.timestamp_rollover = (1 << 32) * self.master_clock_period
|
self.timestamp_rollover = (1 << 32) * self.primary_clock_period
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f"Unsupported scope, revision: {revision}")
|
raise RuntimeError(f"Unsupported scope, revision: {revision}")
|
||||||
self._awg_running = False
|
self._awg_running = False
|
||||||
@ -169,13 +169,13 @@ class Scope(vm.VirtualMachine):
|
|||||||
logic_enable = sum(1 << channel for channel in logic_channels)
|
logic_enable = sum(1 << channel for channel in logic_channels)
|
||||||
|
|
||||||
for capture_mode in vm.CaptureModes:
|
for capture_mode in vm.CaptureModes:
|
||||||
ticks = int(round(period / self.master_clock_period / nsamples))
|
ticks = int(round(period / self.primary_clock_period / nsamples))
|
||||||
clock_scale = 1
|
clock_scale = 1
|
||||||
if capture_mode.analog_channels == len(analog_channels) and capture_mode.logic_channels == bool(logic_channels):
|
if capture_mode.analog_channels == len(analog_channels) and capture_mode.logic_channels == bool(logic_channels):
|
||||||
Log.debug(f"Considering trace mode {capture_mode.trace_mode.name}...")
|
Log.debug(f"Considering trace mode {capture_mode.trace_mode.name}...")
|
||||||
if ticks > capture_mode.clock_high and capture_mode.clock_divide > 1:
|
if ticks > capture_mode.clock_high and capture_mode.clock_divide > 1:
|
||||||
clock_scale = int(math.ceil(period / self.master_clock_period / nsamples / capture_mode.clock_high))
|
clock_scale = int(math.ceil(period / self.primary_clock_period / nsamples / capture_mode.clock_high))
|
||||||
ticks = int(round(period / self.master_clock_period / nsamples / clock_scale))
|
ticks = int(round(period / self.primary_clock_period / nsamples / clock_scale))
|
||||||
if ticks in range(capture_mode.clock_low, capture_mode.clock_high+1):
|
if ticks in range(capture_mode.clock_low, capture_mode.clock_high+1):
|
||||||
Log.debug(f"- try with tick count {ticks} x {clock_scale}")
|
Log.debug(f"- try with tick count {ticks} x {clock_scale}")
|
||||||
else:
|
else:
|
||||||
@ -187,7 +187,7 @@ class Scope(vm.VirtualMachine):
|
|||||||
else:
|
else:
|
||||||
Log.debug("- mode too slow")
|
Log.debug("- mode too slow")
|
||||||
continue
|
continue
|
||||||
actual_nsamples = int(round(period / self.master_clock_period / ticks / clock_scale))
|
actual_nsamples = int(round(period / self.primary_clock_period / ticks / clock_scale))
|
||||||
if len(analog_channels) == 2:
|
if len(analog_channels) == 2:
|
||||||
actual_nsamples -= actual_nsamples % 2
|
actual_nsamples -= actual_nsamples % 2
|
||||||
buffer_width = self.capture_buffer_size // capture_mode.sample_width
|
buffer_width = self.capture_buffer_size // capture_mode.sample_width
|
||||||
@ -200,7 +200,7 @@ class Scope(vm.VirtualMachine):
|
|||||||
Log.debug(f"- insufficient buffer space for necessary {actual_nsamples} samples")
|
Log.debug(f"- insufficient buffer space for necessary {actual_nsamples} samples")
|
||||||
else:
|
else:
|
||||||
raise ConfigurationError("Unable to find appropriate capture mode")
|
raise ConfigurationError("Unable to find appropriate capture mode")
|
||||||
sample_period = ticks*clock_scale*self.master_clock_period
|
sample_period = ticks*clock_scale*self.primary_clock_period
|
||||||
sample_rate = 1/sample_period
|
sample_rate = 1/sample_period
|
||||||
if trigger_position and sample_rate > 5e6:
|
if trigger_position and sample_rate > 5e6:
|
||||||
Log.warning("Pre-trigger capture not supported above 5M samples/s; forcing trigger_position=0")
|
Log.warning("Pre-trigger capture not supported above 5M samples/s; forcing trigger_position=0")
|
||||||
@ -272,7 +272,7 @@ class Scope(vm.VirtualMachine):
|
|||||||
if timeout is None:
|
if timeout is None:
|
||||||
trigger_timeout = 0
|
trigger_timeout = 0
|
||||||
else:
|
else:
|
||||||
trigger_timeout = int(math.ceil(((trigger_intro+trigger_outro+trace_outro+2)*ticks*clock_scale*self.master_clock_period
|
trigger_timeout = int(math.ceil(((trigger_intro+trigger_outro+trace_outro+2)*ticks*clock_scale*self.primary_clock_period
|
||||||
+ timeout)/self.timeout_clock_period))
|
+ timeout)/self.timeout_clock_period))
|
||||||
if trigger_timeout > vm.Registers.Timeout.maximum_value:
|
if trigger_timeout > vm.Registers.Timeout.maximum_value:
|
||||||
if timeout > 0:
|
if timeout > 0:
|
||||||
@ -323,7 +323,7 @@ class Scope(vm.VirtualMachine):
|
|||||||
value_multiplier, value_offset = (1, 0) if raw else (high-low, low-analog_params.ab_offset/2*(1 if channel == 'A' else -1))
|
value_multiplier, value_offset = (1, 0) if raw else (high-low, low-analog_params.ab_offset/2*(1 if channel == 'A' else -1))
|
||||||
data = await self.read_analog_samples(asamples, capture_mode.sample_width)
|
data = await self.read_analog_samples(asamples, capture_mode.sample_width)
|
||||||
series = DotDict({'channel': channel,
|
series = DotDict({'channel': channel,
|
||||||
'capture_start': start_timestamp * self.master_clock_period,
|
'capture_start': start_timestamp * self.primary_clock_period,
|
||||||
'timestamps': timestamps[dump_channel::len(analog_channels)] if len(analog_channels) > 1 else timestamps,
|
'timestamps': timestamps[dump_channel::len(analog_channels)] if len(analog_channels) > 1 else timestamps,
|
||||||
'samples': array.array('f', (value*value_multiplier+value_offset for value in data)),
|
'samples': array.array('f', (value*value_multiplier+value_offset for value in data)),
|
||||||
'sample_period': sample_period*len(analog_channels),
|
'sample_period': sample_period*len(analog_channels),
|
||||||
@ -345,7 +345,7 @@ class Scope(vm.VirtualMachine):
|
|||||||
mask = 1 << i
|
mask = 1 << i
|
||||||
channel = f'L{i}'
|
channel = f'L{i}'
|
||||||
series = DotDict({'channel': channel,
|
series = DotDict({'channel': channel,
|
||||||
'capture_start': start_timestamp * self.master_clock_period,
|
'capture_start': start_timestamp * self.primary_clock_period,
|
||||||
'timestamps': timestamps,
|
'timestamps': timestamps,
|
||||||
'samples': array.array('B', (1 if value & mask else 0 for value in data)),
|
'samples': array.array('B', (1 if value & mask else 0 for value in data)),
|
||||||
'sample_period': sample_period,
|
'sample_period': sample_period,
|
||||||
@ -368,14 +368,14 @@ class Scope(vm.VirtualMachine):
|
|||||||
raise ValueError(f"high out of range (0-{self.awg_maximum_voltage})")
|
raise ValueError(f"high out of range (0-{self.awg_maximum_voltage})")
|
||||||
if low < 0 or low > high:
|
if low < 0 or low > high:
|
||||||
raise ValueError("low out of range (0-high)")
|
raise ValueError("low out of range (0-high)")
|
||||||
max_clock = min(vm.Registers.Clock.maximum_value, int(math.floor(self.master_clock_rate / frequency / min_samples)))
|
max_clock = min(vm.Registers.Clock.maximum_value, int(math.floor(self.primary_clock_rate / frequency / min_samples)))
|
||||||
min_clock = max(self.awg_minimum_clock, int(math.ceil(self.master_clock_rate / frequency / self.awg_sample_buffer_size)))
|
min_clock = max(self.awg_minimum_clock, int(math.ceil(self.primary_clock_rate / frequency / self.awg_sample_buffer_size)))
|
||||||
best_solution = None
|
best_solution = None
|
||||||
for clock in range(min_clock, max_clock+1):
|
for clock in range(min_clock, max_clock+1):
|
||||||
width = self.master_clock_rate / frequency / clock
|
width = self.primary_clock_rate / frequency / clock
|
||||||
nwaves = int(self.awg_sample_buffer_size / width)
|
nwaves = int(self.awg_sample_buffer_size / width)
|
||||||
size = int(round(nwaves * width))
|
size = int(round(nwaves * width))
|
||||||
actualf = self.master_clock_rate * nwaves / size / clock
|
actualf = self.primary_clock_rate * nwaves / size / clock
|
||||||
if actualf == frequency:
|
if actualf == frequency:
|
||||||
Log.debug(f"Exact solution: size={size} nwaves={nwaves} clock={clock}")
|
Log.debug(f"Exact solution: size={size} nwaves={nwaves} clock={clock}")
|
||||||
break
|
break
|
||||||
@ -430,9 +430,9 @@ class Scope(vm.VirtualMachine):
|
|||||||
async def start_clock(self, frequency, ratio=0.5, max_error=1e-4):
|
async def start_clock(self, frequency, ratio=0.5, max_error=1e-4):
|
||||||
if self._awg_running:
|
if self._awg_running:
|
||||||
raise UsageError("Cannot start clock while waveform generator in use")
|
raise UsageError("Cannot start clock while waveform generator in use")
|
||||||
ticks = min(max(2, int(round(self.master_clock_rate / frequency))), vm.Registers.Clock.maximum_value)
|
ticks = min(max(2, int(round(self.primary_clock_rate / frequency))), vm.Registers.Clock.maximum_value)
|
||||||
fall = min(max(1, int(round(ticks * ratio))), ticks-1)
|
fall = min(max(1, int(round(ticks * ratio))), ticks-1)
|
||||||
actualf, actualr = self.master_clock_rate / ticks, fall / ticks
|
actualf, actualr = self.primary_clock_rate / ticks, fall / ticks
|
||||||
if abs(actualf - frequency) / frequency > max_error:
|
if abs(actualf - frequency) / frequency > max_error:
|
||||||
raise ConfigurationError("No solution to required frequency and max_error")
|
raise ConfigurationError("No solution to required frequency and max_error")
|
||||||
async with self.transaction():
|
async with self.transaction():
|
||||||
|
Reference in New Issue
Block a user