1
0
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:
Jonathan Hogg
2017-07-31 17:58:10 +01:00
parent 33311848f0
commit dc99b64274
2 changed files with 19 additions and 11 deletions

View File

@ -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:

11
vm.py
View File

@ -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),
@ -355,12 +355,11 @@ class VirtualMachine:
if self._transactions: if self._transactions:
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}")