mirror of
https://github.com/jonathanhogg/scopething
synced 2025-07-14 03:02:09 +01:00
Use array
objects for samples and timestamps (as two items in a DotDict
per trace); put +2 back into timeout calculation logic
This commit is contained in:
35
scope.py
35
scope.py
@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import array
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import logging
|
import logging
|
||||||
@ -130,7 +131,7 @@ class Scope(vm.VirtualMachine):
|
|||||||
if nsamples <= buffer_width:
|
if nsamples <= buffer_width:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Unable to find appropriate capture mode")
|
raise ValueError("Unable to find appropriate capture mode")
|
||||||
|
|
||||||
if raw:
|
if raw:
|
||||||
lo, hi = low, high
|
lo, hi = low, high
|
||||||
@ -184,7 +185,7 @@ class Scope(vm.VirtualMachine):
|
|||||||
if timeout is None:
|
if timeout is None:
|
||||||
trigger_timeout = 0
|
trigger_timeout = 0
|
||||||
else:
|
else:
|
||||||
trigger_timeout = max(1, int(math.ceil(((trigger_intro+trigger_outro+trace_outro)*ticks*clock_scale*self.capture_clock_period
|
trigger_timeout = max(1, int(math.ceil(((trigger_intro+trigger_outro+trace_outro+2)*ticks*clock_scale*self.capture_clock_period
|
||||||
+ timeout)/self.timeout_clock_period)))
|
+ timeout)/self.timeout_clock_period)))
|
||||||
|
|
||||||
async with self.transaction():
|
async with self.transaction():
|
||||||
@ -215,6 +216,7 @@ class Scope(vm.VirtualMachine):
|
|||||||
address -= address % 2
|
address -= address % 2
|
||||||
|
|
||||||
traces = DotDict()
|
traces = DotDict()
|
||||||
|
timestamps = array.array('d', (t*self.capture_clock_period for t in range(start_timestamp, timestamp, ticks*clock_scale)))
|
||||||
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():
|
||||||
@ -225,11 +227,8 @@ class Scope(vm.VirtualMachine):
|
|||||||
await self.issue_analog_dump_binary()
|
await self.issue_analog_dump_binary()
|
||||||
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)
|
||||||
data = (value*value_multiplier + value_offset for value in data)
|
traces[channel] = DotDict({'timestamps': timestamps[dump_channel::len(analog_channels)] if len(analog_channels) > 1 else timestamps,
|
||||||
ts = (t*self.capture_clock_period for t in range(start_timestamp+dump_channel*ticks*clock_scale, timestamp,
|
'samples': array.array('d', (value*value_multiplier+value_offset for value in data))})
|
||||||
ticks*clock_scale*len(analog_channels)))
|
|
||||||
traces[channel] = dict(zip(ts, data))
|
|
||||||
|
|
||||||
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,
|
||||||
@ -237,11 +236,10 @@ class Scope(vm.VirtualMachine):
|
|||||||
await self.issue_program_spock_registers()
|
await self.issue_program_spock_registers()
|
||||||
await self.issue_analog_dump_binary()
|
await self.issue_analog_dump_binary()
|
||||||
data = await self.read_logic_samples(nsamples)
|
data = await self.read_logic_samples(nsamples)
|
||||||
ts = [t*self.capture_clock_period for t in range(start_timestamp, timestamp, ticks*clock_scale)]
|
|
||||||
for i in logic_channels:
|
for i in logic_channels:
|
||||||
mask = 1<<i
|
mask = 1<<i
|
||||||
traces[f'L{i}'] = {t: 1 if value & mask else 0 for (t, value) in zip(ts, data)}
|
traces[f'L{i}'] = DotDict({'timestamps': timestamps,
|
||||||
|
'samples': array.array('B', (1 if value & mask else 0 for value in data))})
|
||||||
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,
|
||||||
@ -383,17 +381,13 @@ INFO:scope:Initialised scope, revision: BS000501
|
|||||||
In [3]: generate(2000, 'triangle')
|
In [3]: generate(2000, 'triangle')
|
||||||
Out[3]: 2000.0
|
Out[3]: 2000.0
|
||||||
|
|
||||||
In [4]: t = pandas.DataFrame(capture(['A', 'B'], low=0, high=3.3))
|
In [4]: capturep(['A', 'B'], low=0, high=3.3).interpolate().plot()
|
||||||
|
Out[4]: <matplotlib.axes._subplots.AxesSubplot at 0x10db77d30>
|
||||||
|
|
||||||
In [5]: t.interpolate().plot()
|
In [5]: capturep(['L'], low=0, high=3.3)).plot()
|
||||||
Out[5]: <matplotlib.axes._subplots.AxesSubplot at 0x10db77d30>
|
Out[5]: <matplotlib.axes._subplots.AxesSubplot at 0x10d05d5f8>
|
||||||
|
|
||||||
In [6]: t = pandas.DataFrame(capture(['L'], low=0, high=3.3))
|
In [6]:
|
||||||
|
|
||||||
In [7]: t.plot()
|
|
||||||
Out[7]: <matplotlib.axes._subplots.AxesSubplot at 0x10d05d5f8>
|
|
||||||
|
|
||||||
In [8]:
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
@ -418,7 +412,8 @@ def capture(*args, **kwargs):
|
|||||||
|
|
||||||
def capturep(*args, **kwargs):
|
def capturep(*args, **kwargs):
|
||||||
import pandas
|
import pandas
|
||||||
return pandas.DataFrame(capture(*args, **kwargs))
|
traces = capture(*args, **kwargs)
|
||||||
|
return pandas.DataFrame({channel: pandas.Series(trace.samples, trace.timestamps) for (channel,trace) in traces.items()})
|
||||||
|
|
||||||
def calibrate(*args, **kwargs):
|
def calibrate(*args, **kwargs):
|
||||||
return await(s.calibrate(*args, **kwargs))
|
return await(s.calibrate(*args, **kwargs))
|
||||||
|
5
vm.py
5
vm.py
@ -13,6 +13,7 @@ document][VM01B].
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import array
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
@ -356,10 +357,10 @@ class VirtualMachine:
|
|||||||
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)
|
data = struct.unpack(f'>{n}h', data)
|
||||||
return [(value+32768)/65535 for value in 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 [value/255 for value in data]
|
return array.array('d', (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