- capture timeout added
- auto-trigger initials
This commit is contained in:
parent
dcf7126db3
commit
3b09caaeb0
@ -11,7 +11,7 @@ MultiStreamOscilloscope::MultiStreamOscilloscope() {
|
||||
mTriggerPosition_percent = TRIGGER_POS_PERCENT_DEF;
|
||||
mCapturePeriod_ns = DRAW_WINDOW_PERIOD_NS_DEF;
|
||||
verticalScale = VOLT_PER_BIN_DEF;
|
||||
mTrigState = {false, false, -1, false };
|
||||
mTrigState = {false, false, -1, false, false};
|
||||
|
||||
mFIFOBlockCnt = 0;
|
||||
mCaptureLength = 0;
|
||||
@ -23,11 +23,11 @@ void MultiStreamOscilloscope::setup(const std::vector<in_addr_t> &nodes, const A
|
||||
|
||||
// calculate buffer parameters
|
||||
mCaptureLength = ceil(mCapturePeriod_ns / 1E+09 * acqFmt.sampling_rate_Hz); // calculate draw window period in samples
|
||||
mFIFOBlockCnt = 4 * ceil(mCaptureLength / acqFmt.mch_samples_per_packet); // TODO magic...
|
||||
mFIFOBlockCnt = 10 * ceil(mCaptureLength / acqFmt.mch_samples_per_packet); // TODO magic...
|
||||
|
||||
// setup channel buffers
|
||||
mpChBufs.resize(mChCnt);
|
||||
for (auto& chBuf: mpChBufs) {
|
||||
for (auto &chBuf: mpChBufs) {
|
||||
chBuf.reset(new ChannelBuffer<SamplePoint>(mAcqFmt.mch_samples_per_packet, mFIFOBlockCnt));
|
||||
}
|
||||
|
||||
@ -82,9 +82,9 @@ bool MultiStreamOscilloscope::input(size_t ch, const std::shared_ptr<Timestamp>
|
||||
sample *= verticalScale;
|
||||
|
||||
// save sample point
|
||||
SamplePoint& sp = mpAssemblyBuffer.get()[i];
|
||||
SamplePoint &sp = mpAssemblyBuffer.get()[i];
|
||||
sp.t = pTime.get()[i].to_ns();
|
||||
sp.x = sample;
|
||||
sp.y = sample;
|
||||
}
|
||||
|
||||
// push new block of samples onto the FIFO
|
||||
@ -101,11 +101,13 @@ bool MultiStreamOscilloscope::input(size_t ch, const std::shared_ptr<Timestamp>
|
||||
int64_t tag = mpChBufs[ch]->copyBlock(mTriggerProbeBlock_idx, mpTriggerBuffer.get()); // TODO magic constant!...
|
||||
|
||||
size_t i = 0;
|
||||
int64_t trigTime = 0;
|
||||
if (!mTrigState.trigd) { // if not triggered externally
|
||||
while (i < mAcqFmt.mch_samples_per_packet) {
|
||||
const SamplePoint &samplePoint = mpTriggerBuffer.get()[i]; // get sample
|
||||
mTrigState.trigd = trigger->sample(samplePoint.x); // probe if causes a trigger
|
||||
mTrigState.trigd = trigger->sample(samplePoint.y, samplePoint.t); // probe if causes a trigger
|
||||
if (mTrigState.trigd) { // break if trigger is successful
|
||||
trigTime = trigger->t_trig;
|
||||
break;
|
||||
}
|
||||
i++; // increase index
|
||||
@ -122,8 +124,8 @@ bool MultiStreamOscilloscope::input(size_t ch, const std::shared_ptr<Timestamp>
|
||||
int64_t captureEnd = captureStart + mCaptureLength;
|
||||
|
||||
// get time of trigger occurred
|
||||
SamplePoint trigSP = mpChBufs[ch]->getElementByTag(mTrigState.triggerSampleTag);
|
||||
int64_t t0 = trigSP.t;
|
||||
//SamplePoint trigSP = mpChBufs[ch]->getElementByTag(mTrigState.triggerSampleTag);
|
||||
int64_t t0 = trigTime;
|
||||
|
||||
// get eldest sample's timestamp on the trigger channel
|
||||
int64_t t_eldest_trigger = mpChBufs[ch]->getEldestSample().t;
|
||||
@ -131,7 +133,7 @@ bool MultiStreamOscilloscope::input(size_t ch, const std::shared_ptr<Timestamp>
|
||||
// TODO now full synchronicity is assumed
|
||||
// copy samples from each channel
|
||||
for (size_t k = 0; k < mChCnt; k++) {
|
||||
auto& chBuf = *(mpChBufs[k]); // acquire channel buffer
|
||||
auto &chBuf = *(mpChBufs[k]); // acquire channel buffer
|
||||
|
||||
int64_t t_offset, offset_index = 0;
|
||||
if (k != ch) { // we are NOT processing the trigger channel, since it's the reference
|
||||
@ -189,13 +191,35 @@ void MultiStreamOscilloscope::armTrigger() {
|
||||
mTrigState.armed = true;
|
||||
}
|
||||
|
||||
std::vector<std::vector<MultiStreamOscilloscope::SamplePoint>> MultiStreamOscilloscope::capture() {
|
||||
std::unique_lock<std::mutex> lock(mCapture_mtx);
|
||||
mCapture_cv.wait(lock, [this] { return mTrigState.samplesReady; }); // wait for data to become available
|
||||
void MultiStreamOscilloscope::enableAutoTrigger(bool en) {
|
||||
mTrigState.autoTrigger;
|
||||
}
|
||||
|
||||
auto samples = mCaptureBuffers; // copy buffer
|
||||
mTrigState.samplesReady = false; // invalidate samples
|
||||
return samples;
|
||||
std::vector<std::vector<MultiStreamOscilloscope::SamplePoint>> MultiStreamOscilloscope::capture(size_t timeout_ms) {
|
||||
std::unique_lock<std::mutex> lock(mCapture_mtx);
|
||||
|
||||
// arm trigger if not armed
|
||||
if (!mTrigState.armed) {
|
||||
armTrigger();
|
||||
}
|
||||
|
||||
// wait for data
|
||||
if (timeout_ms > 0) {
|
||||
mCapture_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [this] { return mTrigState.samplesReady; }); // wait for data to become available
|
||||
} else {
|
||||
mCapture_cv.wait(lock, [this] { return mTrigState.samplesReady; }); // ...
|
||||
}
|
||||
|
||||
// handle data or skip
|
||||
if (mTrigState.samplesReady) {
|
||||
mTrigState.samplesReady = false;
|
||||
return mCaptureBuffers;
|
||||
} else {
|
||||
if (mTrigState.autoTrigger) {
|
||||
mTrigState.trigd = true; // trigger if auto-trigger is enabled
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
@ -220,5 +244,5 @@ std::vector<int64_t> MultiStreamOscilloscope::getScreenTimeLimits() const {
|
||||
int64_t lowerLimit, upperLimit;
|
||||
lowerLimit = -ceil(mTriggerPosition_percent / 100.0 * mCapturePeriod_ns);
|
||||
upperLimit = mCapturePeriod_ns + lowerLimit;
|
||||
return std::vector<int64_t>({ lowerLimit, upperLimit });
|
||||
return std::vector<int64_t>({lowerLimit, upperLimit});
|
||||
}
|
@ -20,11 +20,11 @@ public:
|
||||
public:
|
||||
struct SamplePoint {
|
||||
int64_t t; // time
|
||||
double x; // sample data
|
||||
double y; // sample data
|
||||
|
||||
SamplePoint() {
|
||||
t = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -56,6 +56,7 @@ private:
|
||||
bool trigd; // indicates if trigger has fired
|
||||
int64_t triggerSampleTag;
|
||||
bool samplesReady; // samples have been transferred to the output buffer
|
||||
bool autoTrigger; // auto-trigger on/off
|
||||
} mTrigState;
|
||||
public:
|
||||
void setup(const std::vector<in_addr_t> &nodes, const AcquisitionFormat &acqFmt) override;
|
||||
@ -73,7 +74,8 @@ public:
|
||||
|
||||
void triggerNow(); // make the scope trigger regardless conditions
|
||||
void armTrigger(); // arm trigger for next acquisition
|
||||
std::vector<std::vector<MultiStreamOscilloscope::SamplePoint>> capture(); // wait for captured data TODO to be renamed
|
||||
void enableAutoTrigger(bool en); // enable or disable auto trigger
|
||||
std::vector<std::vector<MultiStreamOscilloscope::SamplePoint>> capture(size_t timeout_ms = 0); // wait for captured data TODO to be renamed
|
||||
|
||||
};
|
||||
|
||||
|
@ -142,7 +142,7 @@ void MultiStreamReceiver::fnRecv(MultiStreamReceiver *pMSR) {
|
||||
|
||||
// limit on time difference variation
|
||||
double timeDiffVariation_ns = 1E+09 / pMSR->mAcqFmt.sampling_rate_Hz * TS_VALIDITY_RANGE;
|
||||
uint32_t lastIndex = 0;
|
||||
//uint32_t lastIndex = 0;
|
||||
|
||||
// allocate buffer for interpolated timestamps
|
||||
std::shared_ptr<Timestamp> pTSBuf(new Timestamp[pMSR->mAcqFmt.mch_samples_per_packet]);
|
||||
@ -196,12 +196,12 @@ void MultiStreamReceiver::fnRecv(MultiStreamReceiver *pMSR) {
|
||||
}
|
||||
|
||||
// check index continuity
|
||||
if (lastIndex > 0 && (aph.index) != (lastIndex + 1)) {
|
||||
/*if (lastIndex > 0 && (aph.index) != (lastIndex + 1)) {
|
||||
Logger::logLine("NON-CONTINUOUS packet indices! (" + std::to_string(lastIndex) + " -> " + std::to_string(aph.index) + ")");
|
||||
// TODO Should skip here?
|
||||
}
|
||||
|
||||
lastIndex = aph.index;
|
||||
lastIndex = aph.index;*/
|
||||
|
||||
// ----------- TIME PROCESSING ---------------
|
||||
|
||||
|
@ -12,9 +12,10 @@ TriggerSettings::TriggerSettings() {
|
||||
void TriggerSettings::reset() {
|
||||
mFirstSample = true;
|
||||
ch = 0;
|
||||
t_trig = 0;
|
||||
}
|
||||
|
||||
bool TriggerSettings::sample(double x) {
|
||||
bool TriggerSettings::sample(double y, int64_t t) {
|
||||
return false; // never trigger
|
||||
}
|
||||
|
||||
@ -29,28 +30,33 @@ EdgeTrigger::EdgeTrigger() {
|
||||
void EdgeTrigger::reset() {
|
||||
TriggerSettings::reset();
|
||||
|
||||
x_prev = 0;
|
||||
y_prev = 0;
|
||||
}
|
||||
|
||||
bool EdgeTrigger::sample(double x) {
|
||||
bool EdgeTrigger::sample(double y, int64_t t) {
|
||||
// do not act on first sample
|
||||
if (mFirstSample) {
|
||||
mFirstSample = false;
|
||||
x_prev = x;
|
||||
y_prev = y;
|
||||
t_prev = t;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool trig = false;
|
||||
|
||||
// on every other sample...
|
||||
if (((edge == RISING) && (x_prev < level && x > level)) ||
|
||||
((edge == FALLING) && (x_prev > level && x < level))) {
|
||||
trig = true;
|
||||
if (((edge == RISING) && (y_prev < level && y > level)) ||
|
||||
((edge == FALLING) && (y_prev > level && y < level))) {
|
||||
trig = true; // triggered
|
||||
|
||||
// compute exact trigger time
|
||||
t_trig = t - llabs((level - y) / (y - y_prev) * (t - t_prev));
|
||||
}
|
||||
|
||||
//std::cout << x << " - " << level << std::endl;
|
||||
//std::cout << y << " - " << level << std::endl;
|
||||
|
||||
x_prev = x;
|
||||
y_prev = y;
|
||||
t_prev = t;
|
||||
|
||||
return trig;
|
||||
}
|
||||
|
@ -14,11 +14,12 @@ protected:
|
||||
bool mFirstSample; // indicates the latest sample was the first since the last reset
|
||||
public:
|
||||
size_t ch; // channel to probe
|
||||
int64_t t_trig; // exact trigger time expressed relative to trigger sample time point
|
||||
public:
|
||||
TriggerSettings();
|
||||
|
||||
virtual void reset(); // reset trigger internal state
|
||||
virtual bool sample(double x); // insert sample into the trigger
|
||||
virtual bool sample(double y, int64_t t); // insert sample into the trigger
|
||||
};
|
||||
|
||||
// Simple edge trigger
|
||||
@ -26,14 +27,15 @@ struct EdgeTrigger : public TriggerSettings, public ICreatable<EdgeTrigger> {
|
||||
public:
|
||||
enum EdgeType { RISING, FALLING };
|
||||
private:
|
||||
double x_prev; // previous sample
|
||||
double y_prev; // previous sample
|
||||
int64_t t_prev; // .... sample time point
|
||||
public:
|
||||
double level; // trigger level
|
||||
EdgeType edge; // edge direction
|
||||
public:
|
||||
EdgeTrigger(); // constr.
|
||||
void reset() override;
|
||||
bool sample(double x) override;
|
||||
bool sample(double y, int64_t t) override;
|
||||
};
|
||||
|
||||
#endif //WFR_APP_TRIGGER_H
|
||||
|
2
main.cpp
2
main.cpp
@ -61,7 +61,7 @@ int main(int argc, char * argv[]) {
|
||||
beacon->execCmdOnAllNodes("snd connect 10.42.0.1 20220");
|
||||
|
||||
osc->armTrigger();
|
||||
auto samples = osc->capture();
|
||||
auto samples = osc->capture(0);
|
||||
|
||||
beacon->execCmdOnAllNodes("snd disconnect");
|
||||
msr.stop();
|
||||
|
@ -1,7 +1,7 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
sys.path.extend(['/home/epagris/EGYETEM/DIPTERV2/wfr/python/module'])
|
||||
sys.path.extend(['../module'])
|
||||
|
||||
import pywfs
|
||||
|
||||
@ -11,6 +11,9 @@ from matplotlib import pyplot as plt
|
||||
from matplotlib import animation as anim
|
||||
import time
|
||||
|
||||
LOCAL_ADDR = "192.168.1.204"
|
||||
nodes = [ "192.168.1.180" ]
|
||||
|
||||
# ---------- CONNECT TO AND PREPARE SAMPLING SYSTEM -----------
|
||||
|
||||
# enable logging onto STDOUT
|
||||
@ -18,9 +21,9 @@ pywfs.Logger.start()
|
||||
|
||||
# discover nodes on the network
|
||||
b = pywfs.ServerBeacon()
|
||||
b.setInterfaceAddr("10.42.0.1")
|
||||
b.setInterfaceAddr(LOCAL_ADDR)
|
||||
b.singleScan()
|
||||
nodes = b.getNodesOnNetwork()
|
||||
#nodes = b.getNodesOnNetwork()
|
||||
|
||||
# query acquisition format (assume all nodes are identical in this aspect)
|
||||
f = b.queryFromNode(nodes[0], "snd acqformat mr")
|
||||
@ -37,19 +40,25 @@ ch_n = msr.getChannelCount()
|
||||
# create oscilloscope data feeder object
|
||||
osc = pywfs.MultiStreamOscilloscope.create()
|
||||
|
||||
#index = 2 * nodes.index("192.168.1.180")
|
||||
|
||||
# create a slope trigger
|
||||
edge_trigger = pywfs.EdgeTrigger()
|
||||
edge_trigger.level = 0.2
|
||||
edge_trigger.level = 0.1
|
||||
edge_trigger.edge = pywfs.FALLING
|
||||
#edge_trigger.ch = 0 + index
|
||||
edge_trigger.ch = 0
|
||||
|
||||
osc.trigger = edge_trigger
|
||||
osc.setScreenPeriod(int(20e+06))
|
||||
osc.setScreenPeriod(int(10e+06))
|
||||
|
||||
# start listening for samples
|
||||
msr.listen(osc)
|
||||
|
||||
# enable network sample transmission from every device
|
||||
b.execCmdOnAllNodes("snd connect 10.42.0.1 20220")
|
||||
#b.execCmdOnAllNodes("snd connect 10.42.0.1 20220")
|
||||
for node in nodes:
|
||||
b.execCmdOnNode(node, "snd connect " + LOCAL_ADDR)
|
||||
|
||||
|
||||
# # data collection
|
||||
@ -68,6 +77,10 @@ def data_gen():
|
||||
real_time_last = time.time()
|
||||
index_last = 0
|
||||
|
||||
screen_lim = osc.getScreenTimeLimits()
|
||||
T = [screen_lim[0] * 1e-09, screen_lim[1] * 1e-09]
|
||||
Y = [0, 0]
|
||||
|
||||
for i in itertools.count():
|
||||
# FPS measurement
|
||||
real_time = time.time()
|
||||
@ -78,8 +91,10 @@ def data_gen():
|
||||
|
||||
# data collection
|
||||
osc.armTrigger() # arm trigger
|
||||
channels = osc.capture() # wait for captured data
|
||||
channels = osc.capture(200) # wait for captured data
|
||||
|
||||
# if we have incoming data
|
||||
if (len(channels) > 0):
|
||||
T = list()
|
||||
Y = list()
|
||||
|
||||
@ -89,7 +104,7 @@ def data_gen():
|
||||
|
||||
for sp in ch:
|
||||
t.append(sp.t * 1E-09)
|
||||
y_t.append(sp.x)
|
||||
y_t.append(sp.y)
|
||||
|
||||
T.append(t)
|
||||
Y.append(y_t)
|
||||
|
@ -81,7 +81,7 @@ PYBIND11_MODULE(pywfs, m) {
|
||||
.def_readwrite("verticalScale", &MultiStreamOscilloscope::verticalScale)
|
||||
.def("armTrigger", &MultiStreamOscilloscope::armTrigger)
|
||||
.def("triggerNow", &MultiStreamOscilloscope::triggerNow)
|
||||
.def("capture", &MultiStreamOscilloscope::capture)
|
||||
.def("capture", &MultiStreamOscilloscope::capture, "timeout_ms"_a = 0)
|
||||
.def("getChannelCount", &MultiStreamOscilloscope::getChannelCount)
|
||||
.def("setScreenPeriod", &MultiStreamOscilloscope::setScreenPeriod)
|
||||
.def("getScreenPeriod", &MultiStreamOscilloscope::getScreenPeriod)
|
||||
@ -94,7 +94,7 @@ PYBIND11_MODULE(pywfs, m) {
|
||||
py::class_<MultiStreamOscilloscope::SamplePoint>(m, "SamplePoint")
|
||||
.def(py::init<>())
|
||||
.def_readwrite("t", &MultiStreamOscilloscope::SamplePoint::t)
|
||||
.def_readwrite("x", &MultiStreamOscilloscope::SamplePoint::x);
|
||||
.def_readwrite("y", &MultiStreamOscilloscope::SamplePoint::y);
|
||||
|
||||
// TriggerSettings
|
||||
py::class_<TriggerSettings, std::shared_ptr<TriggerSettings>>(m, "TriggerSettings")
|
||||
|
Loading…
x
Reference in New Issue
Block a user