mirror of
https://github.com/jonathanhogg/scopething
synced 2025-07-14 11:12:09 +01:00
Include more info in trace objects; fix calibration to work with new return values of capture()
(doh!); fix maximum clock ticks (16bit unsigned value); neaten sample reading code and switch to single-precision floats (easily large enough)
This commit is contained in:
19
scope.py
19
scope.py
@ -217,6 +217,9 @@ class Scope(vm.VirtualMachine):
|
|||||||
|
|
||||||
traces = DotDict()
|
traces = DotDict()
|
||||||
timestamps = array.array('d', (t*self.capture_clock_period for t in range(start_timestamp, timestamp, ticks*clock_scale)))
|
timestamps = array.array('d', (t*self.capture_clock_period for t in range(start_timestamp, timestamp, ticks*clock_scale)))
|
||||||
|
sample_period = ticks*clock_scale*self.capture_clock_period
|
||||||
|
sample_rate = 1/sample_period
|
||||||
|
start_time = start_timestamp*self.capture_clock_period
|
||||||
for dump_channel, channel in enumerate(sorted(analog_channels)):
|
for dump_channel, channel in enumerate(sorted(analog_channels)):
|
||||||
asamples = nsamples // len(analog_channels)
|
asamples = nsamples // len(analog_channels)
|
||||||
async with self.transaction():
|
async with self.transaction():
|
||||||
@ -228,7 +231,10 @@ class Scope(vm.VirtualMachine):
|
|||||||
value_multiplier, value_offset = (1, 0) if raw else ((high-low), low+self.analog_offsets[channel])
|
value_multiplier, value_offset = (1, 0) if raw else ((high-low), low+self.analog_offsets[channel])
|
||||||
data = await self.read_analog_samples(asamples, capture_mode.sample_width)
|
data = await self.read_analog_samples(asamples, capture_mode.sample_width)
|
||||||
traces[channel] = DotDict({'timestamps': timestamps[dump_channel::len(analog_channels)] if len(analog_channels) > 1 else timestamps,
|
traces[channel] = DotDict({'timestamps': timestamps[dump_channel::len(analog_channels)] if len(analog_channels) > 1 else timestamps,
|
||||||
'samples': array.array('d', (value*value_multiplier+value_offset for value in data))})
|
'samples': array.array('d', (value*value_multiplier+value_offset for value in data)),
|
||||||
|
'start_time': start_time+sample_period*dump_channel,
|
||||||
|
'sample_period': sample_period*len(analog_channels),
|
||||||
|
'sample_rate': sample_rate/len(analog_channels)})
|
||||||
if logic_channels:
|
if logic_channels:
|
||||||
async with self.transaction():
|
async with self.transaction():
|
||||||
await self.set_registers(SampleAddress=(address - nsamples) % buffer_width,
|
await self.set_registers(SampleAddress=(address - nsamples) % buffer_width,
|
||||||
@ -239,7 +245,10 @@ class Scope(vm.VirtualMachine):
|
|||||||
for i in logic_channels:
|
for i in logic_channels:
|
||||||
mask = 1<<i
|
mask = 1<<i
|
||||||
traces[f'L{i}'] = DotDict({'timestamps': timestamps,
|
traces[f'L{i}'] = DotDict({'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)),
|
||||||
|
'start_time': start_time,
|
||||||
|
'sample_period': sample_period,
|
||||||
|
'sample_rate': sample_rate})
|
||||||
return traces
|
return traces
|
||||||
|
|
||||||
async def start_generator(self, frequency, waveform='sine', wavetable=None, ratio=0.5,
|
async def start_generator(self, frequency, waveform='sine', wavetable=None, ratio=0.5,
|
||||||
@ -327,13 +336,13 @@ class Scope(vm.VirtualMachine):
|
|||||||
await self.start_generator(frequency=1000, waveform='square')
|
await self.start_generator(frequency=1000, waveform='square')
|
||||||
for lo in np.linspace(self.analog_lo_min, 0.5, n, endpoint=False):
|
for lo in np.linspace(self.analog_lo_min, 0.5, n, endpoint=False):
|
||||||
for hi in np.linspace(0.5, self.analog_hi_max, n):
|
for hi in np.linspace(0.5, self.analog_hi_max, n):
|
||||||
data = await self.capture(channels=['A','B'], period=2e-3, nsamples=2000, timeout=0, low=lo, high=hi, raw=True)
|
traces = await self.capture(channels=['A','B'], period=2e-3, nsamples=2000, timeout=0, low=lo, high=hi, raw=True)
|
||||||
A = np.fromiter(data['A'].values(), count=1000, dtype='float')
|
A = np.array(traces.A.samples)
|
||||||
A.sort()
|
A.sort()
|
||||||
Azero, Amax = A[25:475].mean(), A[525:975].mean()
|
Azero, Amax = A[25:475].mean(), A[525:975].mean()
|
||||||
if Azero < 0.01 or Amax > 0.99:
|
if Azero < 0.01 or Amax > 0.99:
|
||||||
continue
|
continue
|
||||||
B = np.fromiter(data['B'].values(), count=1000, dtype='float')
|
B = np.array(traces.B.samples)
|
||||||
B.sort()
|
B.sort()
|
||||||
Bzero, Bmax = B[25:475].mean(), B[525:975].mean()
|
Bzero, Bmax = B[25:475].mean(), B[525:975].mean()
|
||||||
if Bzero < 0.01 or Bmax > 0.99:
|
if Bzero < 0.01 or Bmax > 0.99:
|
||||||
|
9
vm.py
9
vm.py
@ -162,8 +162,8 @@ CaptureMode = namedtuple('CaptureMode', ('clock_low', 'clock_high', 'clock_max',
|
|||||||
'logic_channels', 'clock_divide', 'trace_mode', 'buffer_mode'))
|
'logic_channels', 'clock_divide', 'trace_mode', 'buffer_mode'))
|
||||||
|
|
||||||
CaptureModes = [
|
CaptureModes = [
|
||||||
CaptureMode(40, 65536, None, 1, 2, False, False, TraceMode.Macro, BufferMode.Macro),
|
CaptureMode(40, 65535, None, 1, 2, False, False, TraceMode.Macro, BufferMode.Macro),
|
||||||
CaptureMode(40, 65536, None, 2, 2, False, False, TraceMode.MacroChop, BufferMode.MacroChop),
|
CaptureMode(40, 65535, None, 2, 2, False, False, TraceMode.MacroChop, BufferMode.MacroChop),
|
||||||
CaptureMode(15, 40, None, 1, 1, False, True, TraceMode.Analog, BufferMode.Single),
|
CaptureMode(15, 40, None, 1, 1, False, True, TraceMode.Analog, BufferMode.Single),
|
||||||
CaptureMode(13, 40, None, 2, 1, False, True, TraceMode.AnalogChop, BufferMode.Chop),
|
CaptureMode(13, 40, None, 2, 1, False, True, TraceMode.AnalogChop, BufferMode.Chop),
|
||||||
CaptureMode( 8, 14, None, 1, 1, False, False, TraceMode.AnalogFast, BufferMode.Single),
|
CaptureMode( 8, 14, None, 1, 1, False, False, TraceMode.AnalogFast, BufferMode.Single),
|
||||||
@ -356,11 +356,10 @@ class VirtualMachine:
|
|||||||
raise TypeError("Command transaction in progress")
|
raise TypeError("Command transaction in progress")
|
||||||
if sample_width == 2:
|
if sample_width == 2:
|
||||||
data = await self._reader.readexactly(2*n)
|
data = await self._reader.readexactly(2*n)
|
||||||
data = struct.unpack(f'>{n}h', data)
|
return array.array('f', ((value+32768)/65535 for (value,) in struct.iter_unpack('>h', data)))
|
||||||
return array.array('d', ((value+32768)/65535 for value in data))
|
|
||||||
elif sample_width == 1:
|
elif sample_width == 1:
|
||||||
data = await self._reader.readexactly(n)
|
data = await self._reader.readexactly(n)
|
||||||
return array.array('d', (value/255 for value in data))
|
return array.array('f', (value/255 for value in data))
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Bad sample width: {sample_width}")
|
raise ValueError(f"Bad sample width: {sample_width}")
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user