set(pulseview_SOURCES
main.cpp
- pv/analogdata.cpp
- pv/analogdatasnapshot.cpp
- pv/datasnapshot.cpp
- pv/logicdata.cpp
- pv/logicdatasnapshot.cpp
pv/mainwindow.cpp
pv/samplingbar.cpp
- pv/signaldata.cpp
pv/sigsession.cpp
+ pv/data/analog.cpp
+ pv/data/analogsnapshot.cpp
+ pv/data/logic.cpp
+ pv/data/logicsnapshot.cpp
+ pv/data/signaldata.cpp
+ pv/data/snapshot.cpp
pv/dialogs/about.cpp
pv/view/analogsignal.cpp
pv/view/cursor.cpp
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "analogdata.h"
-#include "analogdatasnapshot.h"
-
-using namespace boost;
-using namespace std;
-
-namespace pv {
-
-AnalogData::AnalogData(const sr_datafeed_meta_analog &meta,
- uint64_t samplerate) :
- SignalData(samplerate)
-{
-}
-
-void AnalogData::push_snapshot(
- boost::shared_ptr<AnalogDataSnapshot> &snapshot)
-{
- _snapshots.push_front(snapshot);
-}
-
-deque< shared_ptr<AnalogDataSnapshot> >& AnalogData::get_snapshots()
-{
- return _snapshots;
-}
-
-} // namespace pv
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef PULSEVIEW_PV_ANALOGDATA_H
-#define PULSEVIEW_PV_ANALOGDATA_H
-
-#include "signaldata.h"
-
-#include <boost/shared_ptr.hpp>
-#include <deque>
-
-extern "C" {
-#include <libsigrok/libsigrok.h>
-}
-
-namespace pv {
-
-class AnalogDataSnapshot;
-
-class AnalogData : public SignalData
-{
-public:
- AnalogData(const sr_datafeed_meta_analog &meta,
- uint64_t samplerate);
-
- void push_snapshot(
- boost::shared_ptr<AnalogDataSnapshot> &snapshot);
-
- std::deque< boost::shared_ptr<AnalogDataSnapshot> >&
- get_snapshots();
-
-private:
- std::deque< boost::shared_ptr<AnalogDataSnapshot> >
- _snapshots;
-};
-
-} // namespace pv
-
-#endif // PULSEVIEW_PV_ANALOGDATA_H
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <extdef.h>
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include <boost/foreach.hpp>
-
-#include "analogdatasnapshot.h"
-
-using namespace boost;
-using namespace std;
-
-namespace pv {
-
-AnalogDataSnapshot::AnalogDataSnapshot(
- const sr_datafeed_analog &analog) :
- DataSnapshot(sizeof(float))
-{
- lock_guard<recursive_mutex> lock(_mutex);
- append_payload(analog);
-}
-
-void AnalogDataSnapshot::append_payload(
- const sr_datafeed_analog &analog)
-{
- lock_guard<recursive_mutex> lock(_mutex);
- append_data(analog.data, analog.num_samples);
-}
-
-const float* AnalogDataSnapshot::get_samples() const
-{
- return (const float*)_data;
-}
-
-} // namespace pv
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef PULSEVIEW_PV_ANALOGDATASNAPSHOT_H
-#define PULSEVIEW_PV_ANALOGDATASNAPSHOT_H
-
-#include "datasnapshot.h"
-
-#include <utility>
-#include <vector>
-
-namespace pv {
-
-class AnalogDataSnapshot : public DataSnapshot
-{
-public:
- AnalogDataSnapshot(const sr_datafeed_analog &analog);
-
- void append_payload(const sr_datafeed_analog &analog);
-
- const float* get_samples() const;
-};
-
-} // namespace pv
-
-#endif // PULSEVIEW_PV_ANALOGDATASNAPSHOT_H
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "analog.h"
+#include "analogsnapshot.h"
+
+using namespace boost;
+using namespace std;
+
+namespace pv {
+namespace data {
+
+Analog::Analog(const sr_datafeed_meta_analog &meta,
+ uint64_t samplerate) :
+ SignalData(samplerate)
+{
+}
+
+void Analog::push_snapshot(shared_ptr<AnalogSnapshot> &snapshot)
+{
+ _snapshots.push_front(snapshot);
+}
+
+deque< shared_ptr<AnalogSnapshot> >& Analog::get_snapshots()
+{
+ return _snapshots;
+}
+
+} // namespace data
+} // namespace pv
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PULSEVIEW_PV_DATA_ANALOG_H
+#define PULSEVIEW_PV_DATA_ANALOG_H
+
+#include "signaldata.h"
+
+#include <boost/shared_ptr.hpp>
+#include <deque>
+
+extern "C" {
+#include <libsigrok/libsigrok.h>
+}
+
+namespace pv {
+namespace data {
+
+class AnalogSnapshot;
+
+class Analog : public SignalData
+{
+public:
+ Analog(const sr_datafeed_meta_analog &meta,
+ uint64_t samplerate);
+
+ void push_snapshot(
+ boost::shared_ptr<AnalogSnapshot> &snapshot);
+
+ std::deque< boost::shared_ptr<AnalogSnapshot> >&
+ get_snapshots();
+
+private:
+ std::deque< boost::shared_ptr<AnalogSnapshot> > _snapshots;
+};
+
+} // namespace data
+} // namespace pv
+
+#endif // PULSEVIEW_PV_DATA_ANALOG_H
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <extdef.h>
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <boost/foreach.hpp>
+
+#include "analogsnapshot.h"
+
+using namespace boost;
+using namespace std;
+
+namespace pv {
+namespace data {
+
+AnalogSnapshot::AnalogSnapshot(const sr_datafeed_analog &analog) :
+ Snapshot(sizeof(float))
+{
+ lock_guard<recursive_mutex> lock(_mutex);
+ append_payload(analog);
+}
+
+void AnalogSnapshot::append_payload(
+ const sr_datafeed_analog &analog)
+{
+ lock_guard<recursive_mutex> lock(_mutex);
+ append_data(analog.data, analog.num_samples);
+}
+
+const float* AnalogSnapshot::get_samples() const
+{
+ return (const float*)_data;
+}
+
+} // namespace data
+} // namespace pv
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PULSEVIEW_PV_DATA_ANALOGSNAPSHOT_H
+#define PULSEVIEW_PV_DATA_ANALOGSNAPSHOT_H
+
+#include "snapshot.h"
+
+#include <utility>
+#include <vector>
+
+namespace pv {
+namespace data {
+
+class AnalogSnapshot : public Snapshot
+{
+public:
+ AnalogSnapshot(const sr_datafeed_analog &analog);
+
+ void append_payload(const sr_datafeed_analog &analog);
+
+ const float* get_samples() const;
+};
+
+} // namespace data
+} // namespace pv
+
+#endif // PULSEVIEW_PV_DATA_ANALOGSNAPSHOT_H
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "logic.h"
+#include "logicsnapshot.h"
+
+using namespace boost;
+using namespace std;
+
+namespace pv {
+namespace data {
+
+Logic::Logic(const sr_datafeed_meta_logic &meta,
+ uint64_t samplerate) :
+ SignalData(samplerate),
+ _num_probes(meta.num_probes)
+{
+}
+
+int Logic::get_num_probes() const
+{
+ return _num_probes;
+}
+
+void Logic::push_snapshot(
+ shared_ptr<LogicSnapshot> &snapshot)
+{
+ _snapshots.push_front(snapshot);
+}
+
+deque< shared_ptr<LogicSnapshot> >& Logic::get_snapshots()
+{
+ return _snapshots;
+}
+
+} // namespace data
+} // namespace pv
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PULSEVIEW_PV_DATA_LOGIC_H
+#define PULSEVIEW_PV_DATA_LOGIC_H
+
+#include "signaldata.h"
+
+#include <boost/shared_ptr.hpp>
+#include <deque>
+
+extern "C" {
+#include <libsigrok/libsigrok.h>
+}
+
+namespace pv {
+namespace data {
+
+class LogicSnapshot;
+
+class Logic : public SignalData
+{
+public:
+ Logic(const sr_datafeed_meta_logic &meta, uint64_t samplerate);
+
+ int get_num_probes() const;
+
+ void push_snapshot(
+ boost::shared_ptr<LogicSnapshot> &snapshot);
+
+ std::deque< boost::shared_ptr<LogicSnapshot> >&
+ get_snapshots();
+
+private:
+ const int _num_probes;
+ std::deque< boost::shared_ptr<LogicSnapshot> > _snapshots;
+};
+
+} // namespace data
+} // namespace pv
+
+#endif // PULSEVIEW_PV_DATA_LOGIC_H
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <extdef.h>
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <boost/foreach.hpp>
+
+#include "logicsnapshot.h"
+
+using namespace boost;
+using namespace std;
+
+namespace pv {
+namespace data {
+
+const int LogicSnapshot::MipMapScalePower = 4;
+const int LogicSnapshot::MipMapScaleFactor = 1 << MipMapScalePower;
+const float LogicSnapshot::LogMipMapScaleFactor = logf(MipMapScaleFactor);
+const uint64_t LogicSnapshot::MipMapDataUnit = 64*1024; // bytes
+
+LogicSnapshot::LogicSnapshot(const sr_datafeed_logic &logic) :
+ Snapshot(logic.unitsize),
+ _last_append_sample(0)
+{
+ lock_guard<recursive_mutex> lock(_mutex);
+ memset(_mip_map, 0, sizeof(_mip_map));
+ append_payload(logic);
+}
+
+LogicSnapshot::~LogicSnapshot()
+{
+ lock_guard<recursive_mutex> lock(_mutex);
+ BOOST_FOREACH(MipMapLevel &l, _mip_map)
+ free(l.data);
+}
+
+void LogicSnapshot::append_payload(
+ const sr_datafeed_logic &logic)
+{
+ assert(_unit_size == logic.unitsize);
+
+ lock_guard<recursive_mutex> lock(_mutex);
+
+ append_data(logic.data, logic.length);
+
+ // Generate the first mip-map from the data
+ append_payload_to_mipmap();
+}
+
+void LogicSnapshot::reallocate_mip_map(MipMapLevel &m)
+{
+ const uint64_t new_data_length = ((m.length + MipMapDataUnit - 1) /
+ MipMapDataUnit) * MipMapDataUnit;
+ if (new_data_length > m.data_length)
+ {
+ m.data_length = new_data_length;
+ m.data = realloc(m.data, new_data_length * _unit_size);
+ }
+}
+
+void LogicSnapshot::append_payload_to_mipmap()
+{
+ MipMapLevel &m0 = _mip_map[0];
+ uint64_t prev_length;
+ const uint8_t *src_ptr;
+ uint8_t *dest_ptr;
+ uint64_t accumulator;
+ unsigned int diff_counter;
+
+ // Expand the data buffer to fit the new samples
+ prev_length = m0.length;
+ m0.length = _sample_count / MipMapScaleFactor;
+
+ // Break off if there are no new samples to compute
+ if (m0.length == prev_length)
+ return;
+
+ reallocate_mip_map(m0);
+
+ dest_ptr = (uint8_t*)m0.data + prev_length * _unit_size;
+
+ // Iterate through the samples to populate the first level mipmap
+ accumulator = 0;
+ diff_counter = MipMapScaleFactor;
+ const uint8_t *end_src_ptr = (uint8_t*)_data +
+ m0.length * _unit_size * MipMapScaleFactor;
+ for (src_ptr = (uint8_t*)_data +
+ prev_length * _unit_size * MipMapScaleFactor;
+ src_ptr < end_src_ptr;)
+ {
+ // Accumulate transitions which have occurred in this sample
+ accumulator = 0;
+ diff_counter = MipMapScaleFactor;
+ while (diff_counter-- > 0)
+ {
+ const uint64_t sample = *(uint64_t*)src_ptr;
+ accumulator |= _last_append_sample ^ sample;
+ _last_append_sample = sample;
+ src_ptr += _unit_size;
+ }
+
+ *(uint64_t*)dest_ptr = accumulator;
+ dest_ptr += _unit_size;
+ }
+
+ // Compute higher level mipmaps
+ for (unsigned int level = 1; level < ScaleStepCount; level++)
+ {
+ MipMapLevel &m = _mip_map[level];
+ const MipMapLevel &ml = _mip_map[level-1];
+
+ // Expand the data buffer to fit the new samples
+ prev_length = m.length;
+ m.length = ml.length / MipMapScaleFactor;
+
+ // Break off if there are no more samples to computed
+ if (m.length == prev_length)
+ break;
+
+ reallocate_mip_map(m);
+
+ // Subsample the level lower level
+ src_ptr = (uint8_t*)ml.data +
+ _unit_size * prev_length * MipMapScaleFactor;
+ const uint8_t *end_dest_ptr =
+ (uint8_t*)m.data + _unit_size * m.length;
+ for (dest_ptr = (uint8_t*)m.data +
+ _unit_size * prev_length;
+ dest_ptr < end_dest_ptr;
+ dest_ptr += _unit_size)
+ {
+ accumulator = 0;
+ diff_counter = MipMapScaleFactor;
+ while (diff_counter-- > 0)
+ {
+ accumulator |= *(uint64_t*)src_ptr;
+ src_ptr += _unit_size;
+ }
+
+ *(uint64_t*)dest_ptr = accumulator;
+ }
+ }
+}
+
+uint64_t LogicSnapshot::get_sample(uint64_t index) const
+{
+ assert(_data);
+ assert(index >= 0 && index < _sample_count);
+
+ return *(uint64_t*)((uint8_t*)_data + index * _unit_size);
+}
+
+void LogicSnapshot::get_subsampled_edges(
+ std::vector<EdgePair> &edges,
+ uint64_t start, uint64_t end,
+ float min_length, int sig_index)
+{
+ uint64_t index = start;
+ unsigned int level;
+ bool last_sample;
+ bool fast_forward;
+
+ assert(start >= 0);
+ assert(end <= get_sample_count());
+ assert(start <= end);
+ assert(min_length > 0);
+ assert(sig_index >= 0);
+ assert(sig_index < SR_MAX_NUM_PROBES);
+
+ lock_guard<recursive_mutex> lock(_mutex);
+
+ const uint64_t block_length = (uint64_t)max(min_length, 1.0f);
+ const unsigned int min_level = max((int)floorf(logf(min_length) /
+ LogMipMapScaleFactor) - 1, 0);
+ const uint64_t sig_mask = 1ULL << sig_index;
+
+ // Store the initial state
+ last_sample = (get_sample(start) & sig_mask) != 0;
+ edges.push_back(pair<int64_t, bool>(index++, last_sample));
+
+ while (index + block_length <= end)
+ {
+ //----- Continue to search -----//
+ level = min_level;
+ fast_forward = true;
+
+ if (min_length < MipMapScaleFactor)
+ {
+ // Search individual samples up to the beginning of
+ // the next first level mip map block
+ const uint64_t final_index = min(end,
+ pow2_ceil(index, MipMapScalePower));
+
+ for (; index < final_index &&
+ (index & ~(~0 << MipMapScalePower)) != 0;
+ index++)
+ {
+ const bool sample =
+ (get_sample(index) & sig_mask) != 0;
+
+ // If there was a change we cannot fast forward
+ if (sample != last_sample) {
+ fast_forward = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // If resolution is less than a mip map block,
+ // round up to the beginning of the mip-map block
+ // for this level of detail
+ const int min_level_scale_power =
+ (level + 1) * MipMapScalePower;
+ index = pow2_ceil(index, min_level_scale_power);
+ if (index >= end)
+ break;
+
+ // We can fast forward only if there was no change
+ const bool sample =
+ (get_sample(index) & sig_mask) != 0;
+ fast_forward = last_sample == sample;
+ }
+
+ if (fast_forward) {
+
+ // Fast forward: This involves zooming out to higher
+ // levels of the mip map searching for changes, then
+ // zooming in on them to find the point where the edge
+ // begins.
+
+ // Slide right and zoom out at the beginnings of mip-map
+ // blocks until we encounter a change
+ while (1) {
+ const int level_scale_power =
+ (level + 1) * MipMapScalePower;
+ const uint64_t offset =
+ index >> level_scale_power;
+ assert(offset >= 0);
+
+ // Check if we reached the last block at this
+ // level, or if there was a change in this block
+ if (offset >= _mip_map[level].length ||
+ (get_subsample(level, offset) &
+ sig_mask))
+ break;
+
+ if ((offset & ~(~0 << MipMapScalePower)) == 0) {
+ // If we are now at the beginning of a
+ // higher level mip-map block ascend one
+ // level
+ if (level + 1 >= ScaleStepCount ||
+ !_mip_map[level + 1].data)
+ break;
+
+ level++;
+ } else {
+ // Slide right to the beginning of the
+ // next mip map block
+ index = pow2_ceil(index + 1,
+ level_scale_power);
+ }
+ }
+
+ // Zoom in, and slide right until we encounter a change,
+ // and repeat until we reach min_level
+ while (1) {
+ assert(_mip_map[level].data);
+
+ const int level_scale_power =
+ (level + 1) * MipMapScalePower;
+ const uint64_t offset =
+ index >> level_scale_power;
+ assert(offset >= 0);
+
+ // Check if we reached the last block at this
+ // level, or if there was a change in this block
+ if (offset >= _mip_map[level].length ||
+ (get_subsample(level, offset) &
+ sig_mask)) {
+ // Zoom in unless we reached the minimum
+ // zoom
+ if (level == min_level)
+ break;
+
+ level--;
+ } else {
+ // Slide right to the beginning of the
+ // next mip map block
+ index = pow2_ceil(index + 1,
+ level_scale_power);
+ }
+ }
+
+ // If individual samples within the limit of resolution,
+ // do a linear search for the next transition within the
+ // block
+ if (min_length < MipMapScaleFactor) {
+ for (; index < end; index++) {
+ const bool sample = (get_sample(index) &
+ sig_mask) != 0;
+ if (sample != last_sample)
+ break;
+ }
+ }
+ }
+
+ //----- Store the edge -----//
+
+ // Take the last sample of the quanization block
+ const int64_t final_index = index + block_length;
+ if (index + block_length > end)
+ break;
+
+ // Store the final state
+ const bool final_sample =
+ (get_sample(final_index - 1) & sig_mask) != 0;
+ edges.push_back(pair<int64_t, bool>(index, final_sample));
+
+ index = final_index;
+ last_sample = final_sample;
+ }
+
+ // Add the final state
+ edges.push_back(pair<int64_t, bool>(end,
+ get_sample(end) & sig_mask));
+}
+
+uint64_t LogicSnapshot::get_subsample(int level, uint64_t offset) const
+{
+ assert(level >= 0);
+ assert(_mip_map[level].data);
+ return *(uint64_t*)((uint8_t*)_mip_map[level].data +
+ _unit_size * offset);
+}
+
+uint64_t LogicSnapshot::pow2_ceil(uint64_t x, unsigned int power)
+{
+ const uint64_t p = 1 << power;
+ return (x + p - 1) / p * p;
+}
+
+} // namespace data
+} // namespace pv
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PULSEVIEW_PV_DATA_LOGICSNAPSHOT_H
+#define PULSEVIEW_PV_DATA_LOGICSNAPSHOT_H
+
+#include "snapshot.h"
+
+#include <utility>
+#include <vector>
+
+namespace LogicSnapshotTest {
+ class Pow2;
+ class Basic;
+ class LargeData;
+ class Pulses;
+ class LongPulses;
+}
+
+namespace pv {
+namespace data {
+
+class LogicSnapshot : public Snapshot
+{
+private:
+ struct MipMapLevel
+ {
+ uint64_t length;
+ uint64_t data_length;
+ void *data;
+ };
+
+private:
+ static const unsigned int ScaleStepCount = 10;
+ static const int MipMapScalePower;
+ static const int MipMapScaleFactor;
+ static const float LogMipMapScaleFactor;
+ static const uint64_t MipMapDataUnit;
+
+public:
+ typedef std::pair<int64_t, bool> EdgePair;
+
+public:
+ LogicSnapshot(const sr_datafeed_logic &logic);
+
+ virtual ~LogicSnapshot();
+
+ void append_payload(const sr_datafeed_logic &logic);
+
+private:
+ void reallocate_mip_map(MipMapLevel &m);
+
+ void append_payload_to_mipmap();
+
+ uint64_t get_sample(uint64_t index) const;
+
+public:
+ /**
+ * Parses a logic data snapshot to generate a list of transitions
+ * in a time interval to a given level of detail.
+ * @param[out] edges The vector to place the edges into.
+ * @param[in] start The start sample index.
+ * @param[in] end The end sample index.
+ * @param[in] min_length The minimum number of samples that
+ * can be resolved at this level of detail.
+ * @param[in] sig_index The index of the signal.
+ **/
+ void get_subsampled_edges(std::vector<EdgePair> &edges,
+ uint64_t start, uint64_t end,
+ float min_length, int sig_index);
+
+private:
+ uint64_t get_subsample(int level, uint64_t offset) const;
+
+ static uint64_t pow2_ceil(uint64_t x, unsigned int power);
+
+private:
+ struct MipMapLevel _mip_map[ScaleStepCount];
+ uint64_t _last_append_sample;
+
+ friend class LogicSnapshotTest::Pow2;
+ friend class LogicSnapshotTest::Basic;
+ friend class LogicSnapshotTest::LargeData;
+ friend class LogicSnapshotTest::Pulses;
+ friend class LogicSnapshotTest::LongPulses;
+};
+
+} // namespace data
+} // namespace pv
+
+#endif // PULSEVIEW_PV_DATA_LOGICSNAPSHOT_H
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "signaldata.h"
+
+namespace pv {
+namespace data {
+
+SignalData::SignalData(double samplerate) :
+ _samplerate(samplerate),
+ _start_time(0)
+{
+}
+
+double SignalData::get_samplerate() const
+{
+ return _samplerate;
+}
+
+double SignalData::get_start_time() const
+{
+ return _start_time;
+}
+
+} // namespace data
+} // namespace pv
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PULSEVIEW_PV_DATA_SIGNALDATA_H
+#define PULSEVIEW_PV_DATA_SIGNALDATA_H
+
+#include <stdint.h>
+
+namespace pv {
+namespace data {
+
+class SignalData
+{
+public:
+ SignalData(double samplerate);
+
+public:
+ double get_samplerate() const;
+ double get_start_time() const;
+
+protected:
+ const double _samplerate;
+ const double _start_time;
+};
+
+} // namespace data
+} // namespace pv
+
+#endif // PULSEVIEW_PV_DATA_SIGNALDATA_H
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "snapshot.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+using namespace boost;
+
+namespace pv {
+namespace data {
+
+Snapshot::Snapshot(int unit_size) :
+ _data(NULL),
+ _sample_count(0),
+ _unit_size(unit_size)
+{
+ lock_guard<recursive_mutex> lock(_mutex);
+ assert(_unit_size > 0);
+}
+
+Snapshot::~Snapshot()
+{
+ lock_guard<recursive_mutex> lock(_mutex);
+ free(_data);
+}
+
+uint64_t Snapshot::get_sample_count()
+{
+ lock_guard<recursive_mutex> lock(_mutex);
+ return _sample_count;
+}
+
+void Snapshot::append_data(void *data, uint64_t samples)
+{
+ lock_guard<recursive_mutex> lock(_mutex);
+ _data = realloc(_data, (_sample_count + samples) * _unit_size);
+ memcpy((uint8_t*)_data + _sample_count * _unit_size,
+ data, samples * _unit_size);
+ _sample_count += samples;
+}
+
+} // namespace data
+} // namespace pv
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PULSEVIEW_PV_DATA_SNAPSHOT_H
+#define PULSEVIEW_PV_DATA_SNAPSHOT_H
+
+extern "C" {
+#include <libsigrok/libsigrok.h>
+}
+
+#include <boost/thread.hpp>
+
+namespace pv {
+namespace data {
+
+class Snapshot
+{
+public:
+ Snapshot(int unit_size);
+
+ virtual ~Snapshot();
+
+ uint64_t get_sample_count();
+
+protected:
+ void append_data(void *data, uint64_t samples);
+
+protected:
+ mutable boost::recursive_mutex _mutex;
+ void *_data;
+ uint64_t _sample_count;
+ int _unit_size;
+};
+
+} // namespace data
+} // namespace pv
+
+#endif // PULSEVIEW_PV_DATA_SNAPSHOT_H
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "datasnapshot.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-using namespace boost;
-
-namespace pv {
-
-DataSnapshot::DataSnapshot(int unit_size) :
- _data(NULL),
- _sample_count(0),
- _unit_size(unit_size)
-{
- lock_guard<recursive_mutex> lock(_mutex);
- assert(_unit_size > 0);
-}
-
-DataSnapshot::~DataSnapshot()
-{
- lock_guard<recursive_mutex> lock(_mutex);
- free(_data);
-}
-
-uint64_t DataSnapshot::get_sample_count()
-{
- lock_guard<recursive_mutex> lock(_mutex);
- return _sample_count;
-}
-
-void DataSnapshot::append_data(void *data, uint64_t samples)
-{
- lock_guard<recursive_mutex> lock(_mutex);
- _data = realloc(_data, (_sample_count + samples) * _unit_size);
- memcpy((uint8_t*)_data + _sample_count * _unit_size,
- data, samples * _unit_size);
- _sample_count += samples;
-}
-
-} // namespace pv
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef PULSEVIEW_PV_DATASNAPSHOT_H
-#define PULSEVIEW_PV_DATASNAPSHOT_H
-
-extern "C" {
-#include <libsigrok/libsigrok.h>
-}
-
-#include <boost/thread.hpp>
-
-namespace pv {
-
-class DataSnapshot
-{
-public:
- DataSnapshot(int unit_size);
-
- virtual ~DataSnapshot();
-
- uint64_t get_sample_count();
-
-protected:
- void append_data(void *data, uint64_t samples);
-
-protected:
- mutable boost::recursive_mutex _mutex;
- void *_data;
- uint64_t _sample_count;
- int _unit_size;
-};
-
-} // namespace pv
-
-#endif // PULSEVIEW_PV_DATASNAPSHOT_H
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "logicdata.h"
-#include "logicdatasnapshot.h"
-
-using namespace boost;
-using namespace std;
-
-namespace pv {
-
-LogicData::LogicData(const sr_datafeed_meta_logic &meta,
- uint64_t samplerate) :
- SignalData(samplerate),
- _num_probes(meta.num_probes)
-{
-}
-
-int LogicData::get_num_probes() const
-{
- return _num_probes;
-}
-
-void LogicData::push_snapshot(
- boost::shared_ptr<LogicDataSnapshot> &snapshot)
-{
- _snapshots.push_front(snapshot);
-}
-
-deque< shared_ptr<LogicDataSnapshot> >& LogicData::get_snapshots()
-{
- return _snapshots;
-}
-
-} // namespace pv
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef PULSEVIEW_PV_LOGICDATA_H
-#define PULSEVIEW_PV_LOGICDATA_H
-
-#include "signaldata.h"
-
-#include <boost/shared_ptr.hpp>
-#include <deque>
-
-extern "C" {
-#include <libsigrok/libsigrok.h>
-}
-
-namespace pv {
-
-class LogicDataSnapshot;
-
-class LogicData : public SignalData
-{
-public:
- LogicData(const sr_datafeed_meta_logic &meta, uint64_t samplerate);
-
- int get_num_probes() const;
-
- void push_snapshot(
- boost::shared_ptr<LogicDataSnapshot> &snapshot);
-
- std::deque< boost::shared_ptr<LogicDataSnapshot> >&
- get_snapshots();
-
-private:
- const int _num_probes;
- std::deque< boost::shared_ptr<LogicDataSnapshot> >
- _snapshots;
-};
-
-} // namespace pv
-
-#endif // PULSEVIEW_PV_LOGICDATA_H
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <extdef.h>
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include <boost/foreach.hpp>
-
-#include "logicdatasnapshot.h"
-
-using namespace boost;
-using namespace std;
-
-namespace pv {
-
-const int LogicDataSnapshot::MipMapScalePower = 4;
-const int LogicDataSnapshot::MipMapScaleFactor = 1 << MipMapScalePower;
-const float LogicDataSnapshot::LogMipMapScaleFactor = logf(MipMapScaleFactor);
-const uint64_t LogicDataSnapshot::MipMapDataUnit = 64*1024; // bytes
-
-LogicDataSnapshot::LogicDataSnapshot(
- const sr_datafeed_logic &logic) :
- DataSnapshot(logic.unitsize),
- _last_append_sample(0)
-{
- lock_guard<recursive_mutex> lock(_mutex);
- memset(_mip_map, 0, sizeof(_mip_map));
- append_payload(logic);
-}
-
-LogicDataSnapshot::~LogicDataSnapshot()
-{
- lock_guard<recursive_mutex> lock(_mutex);
- BOOST_FOREACH(MipMapLevel &l, _mip_map)
- free(l.data);
-}
-
-void LogicDataSnapshot::append_payload(
- const sr_datafeed_logic &logic)
-{
- assert(_unit_size == logic.unitsize);
-
- lock_guard<recursive_mutex> lock(_mutex);
-
- append_data(logic.data, logic.length);
-
- // Generate the first mip-map from the data
- append_payload_to_mipmap();
-}
-
-void LogicDataSnapshot::reallocate_mip_map(MipMapLevel &m)
-{
- const uint64_t new_data_length = ((m.length + MipMapDataUnit - 1) /
- MipMapDataUnit) * MipMapDataUnit;
- if (new_data_length > m.data_length)
- {
- m.data_length = new_data_length;
- m.data = realloc(m.data, new_data_length * _unit_size);
- }
-}
-
-void LogicDataSnapshot::append_payload_to_mipmap()
-{
- MipMapLevel &m0 = _mip_map[0];
- uint64_t prev_length;
- const uint8_t *src_ptr;
- uint8_t *dest_ptr;
- uint64_t accumulator;
- unsigned int diff_counter;
-
- // Expand the data buffer to fit the new samples
- prev_length = m0.length;
- m0.length = _sample_count / MipMapScaleFactor;
-
- // Break off if there are no new samples to compute
- if (m0.length == prev_length)
- return;
-
- reallocate_mip_map(m0);
-
- dest_ptr = (uint8_t*)m0.data + prev_length * _unit_size;
-
- // Iterate through the samples to populate the first level mipmap
- accumulator = 0;
- diff_counter = MipMapScaleFactor;
- const uint8_t *end_src_ptr = (uint8_t*)_data +
- m0.length * _unit_size * MipMapScaleFactor;
- for (src_ptr = (uint8_t*)_data +
- prev_length * _unit_size * MipMapScaleFactor;
- src_ptr < end_src_ptr;)
- {
- // Accumulate transitions which have occurred in this sample
- accumulator = 0;
- diff_counter = MipMapScaleFactor;
- while (diff_counter-- > 0)
- {
- const uint64_t sample = *(uint64_t*)src_ptr;
- accumulator |= _last_append_sample ^ sample;
- _last_append_sample = sample;
- src_ptr += _unit_size;
- }
-
- *(uint64_t*)dest_ptr = accumulator;
- dest_ptr += _unit_size;
- }
-
- // Compute higher level mipmaps
- for (unsigned int level = 1; level < ScaleStepCount; level++)
- {
- MipMapLevel &m = _mip_map[level];
- const MipMapLevel &ml = _mip_map[level-1];
-
- // Expand the data buffer to fit the new samples
- prev_length = m.length;
- m.length = ml.length / MipMapScaleFactor;
-
- // Break off if there are no more samples to computed
- if (m.length == prev_length)
- break;
-
- reallocate_mip_map(m);
-
- // Subsample the level lower level
- src_ptr = (uint8_t*)ml.data +
- _unit_size * prev_length * MipMapScaleFactor;
- const uint8_t *end_dest_ptr =
- (uint8_t*)m.data + _unit_size * m.length;
- for (dest_ptr = (uint8_t*)m.data +
- _unit_size * prev_length;
- dest_ptr < end_dest_ptr;
- dest_ptr += _unit_size)
- {
- accumulator = 0;
- diff_counter = MipMapScaleFactor;
- while (diff_counter-- > 0)
- {
- accumulator |= *(uint64_t*)src_ptr;
- src_ptr += _unit_size;
- }
-
- *(uint64_t*)dest_ptr = accumulator;
- }
- }
-}
-
-uint64_t LogicDataSnapshot::get_sample(uint64_t index) const
-{
- assert(_data);
- assert(index >= 0 && index < _sample_count);
-
- return *(uint64_t*)((uint8_t*)_data + index * _unit_size);
-}
-
-void LogicDataSnapshot::get_subsampled_edges(
- std::vector<EdgePair> &edges,
- uint64_t start, uint64_t end,
- float min_length, int sig_index)
-{
- uint64_t index = start;
- unsigned int level;
- bool last_sample;
- bool fast_forward;
-
- assert(start >= 0);
- assert(end <= get_sample_count());
- assert(start <= end);
- assert(min_length > 0);
- assert(sig_index >= 0);
- assert(sig_index < SR_MAX_NUM_PROBES);
-
- lock_guard<recursive_mutex> lock(_mutex);
-
- const uint64_t block_length = (uint64_t)max(min_length, 1.0f);
- const unsigned int min_level = max((int)floorf(logf(min_length) /
- LogMipMapScaleFactor) - 1, 0);
- const uint64_t sig_mask = 1ULL << sig_index;
-
- // Store the initial state
- last_sample = (get_sample(start) & sig_mask) != 0;
- edges.push_back(pair<int64_t, bool>(index++, last_sample));
-
- while (index + block_length <= end)
- {
- //----- Continue to search -----//
- level = min_level;
- fast_forward = true;
-
- if (min_length < MipMapScaleFactor)
- {
- // Search individual samples up to the beginning of
- // the next first level mip map block
- const uint64_t final_index = min(end,
- pow2_ceil(index, MipMapScalePower));
-
- for (; index < final_index &&
- (index & ~(~0 << MipMapScalePower)) != 0;
- index++)
- {
- const bool sample =
- (get_sample(index) & sig_mask) != 0;
-
- // If there was a change we cannot fast forward
- if (sample != last_sample) {
- fast_forward = false;
- break;
- }
- }
- }
- else
- {
- // If resolution is less than a mip map block,
- // round up to the beginning of the mip-map block
- // for this level of detail
- const int min_level_scale_power =
- (level + 1) * MipMapScalePower;
- index = pow2_ceil(index, min_level_scale_power);
- if (index >= end)
- break;
-
- // We can fast forward only if there was no change
- const bool sample =
- (get_sample(index) & sig_mask) != 0;
- fast_forward = last_sample == sample;
- }
-
- if (fast_forward) {
-
- // Fast forward: This involves zooming out to higher
- // levels of the mip map searching for changes, then
- // zooming in on them to find the point where the edge
- // begins.
-
- // Slide right and zoom out at the beginnings of mip-map
- // blocks until we encounter a change
- while (1) {
- const int level_scale_power =
- (level + 1) * MipMapScalePower;
- const uint64_t offset =
- index >> level_scale_power;
- assert(offset >= 0);
-
- // Check if we reached the last block at this
- // level, or if there was a change in this block
- if (offset >= _mip_map[level].length ||
- (get_subsample(level, offset) &
- sig_mask))
- break;
-
- if ((offset & ~(~0 << MipMapScalePower)) == 0) {
- // If we are now at the beginning of a
- // higher level mip-map block ascend one
- // level
- if (level + 1 >= ScaleStepCount ||
- !_mip_map[level + 1].data)
- break;
-
- level++;
- } else {
- // Slide right to the beginning of the
- // next mip map block
- index = pow2_ceil(index + 1,
- level_scale_power);
- }
- }
-
- // Zoom in, and slide right until we encounter a change,
- // and repeat until we reach min_level
- while (1) {
- assert(_mip_map[level].data);
-
- const int level_scale_power =
- (level + 1) * MipMapScalePower;
- const uint64_t offset =
- index >> level_scale_power;
- assert(offset >= 0);
-
- // Check if we reached the last block at this
- // level, or if there was a change in this block
- if (offset >= _mip_map[level].length ||
- (get_subsample(level, offset) &
- sig_mask)) {
- // Zoom in unless we reached the minimum
- // zoom
- if (level == min_level)
- break;
-
- level--;
- } else {
- // Slide right to the beginning of the
- // next mip map block
- index = pow2_ceil(index + 1,
- level_scale_power);
- }
- }
-
- // If individual samples within the limit of resolution,
- // do a linear search for the next transition within the
- // block
- if (min_length < MipMapScaleFactor) {
- for (; index < end; index++) {
- const bool sample = (get_sample(index) &
- sig_mask) != 0;
- if (sample != last_sample)
- break;
- }
- }
- }
-
- //----- Store the edge -----//
-
- // Take the last sample of the quanization block
- const int64_t final_index = index + block_length;
- if (index + block_length > end)
- break;
-
- // Store the final state
- const bool final_sample =
- (get_sample(final_index - 1) & sig_mask) != 0;
- edges.push_back(pair<int64_t, bool>(index, final_sample));
-
- index = final_index;
- last_sample = final_sample;
- }
-
- // Add the final state
- edges.push_back(pair<int64_t, bool>(end,
- get_sample(end) & sig_mask));
-}
-
-uint64_t LogicDataSnapshot::get_subsample(int level, uint64_t offset) const
-{
- assert(level >= 0);
- assert(_mip_map[level].data);
- return *(uint64_t*)((uint8_t*)_mip_map[level].data +
- _unit_size * offset);
-}
-
-uint64_t LogicDataSnapshot::pow2_ceil(uint64_t x, unsigned int power)
-{
- const uint64_t p = 1 << power;
- return (x + p - 1) / p * p;
-}
-
-} // namespace pv
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef PULSEVIEW_PV_LOGICDATASNAPSHOT_H
-#define PULSEVIEW_PV_LOGICDATASNAPSHOT_H
-
-#include "datasnapshot.h"
-
-#include <utility>
-#include <vector>
-
-namespace LogicDataSnapshotTest {
- class Pow2;
- class Basic;
- class LargeData;
- class Pulses;
- class LongPulses;
-}
-
-namespace pv {
-
-class LogicDataSnapshot : public DataSnapshot
-{
-private:
- struct MipMapLevel
- {
- uint64_t length;
- uint64_t data_length;
- void *data;
- };
-
-private:
- static const unsigned int ScaleStepCount = 10;
- static const int MipMapScalePower;
- static const int MipMapScaleFactor;
- static const float LogMipMapScaleFactor;
- static const uint64_t MipMapDataUnit;
-
-public:
- typedef std::pair<int64_t, bool> EdgePair;
-
-public:
- LogicDataSnapshot(const sr_datafeed_logic &logic);
-
- virtual ~LogicDataSnapshot();
-
- void append_payload(const sr_datafeed_logic &logic);
-
-private:
- void reallocate_mip_map(MipMapLevel &m);
-
- void append_payload_to_mipmap();
-
- uint64_t get_sample(uint64_t index) const;
-
-public:
- /**
- * Parses a logic data snapshot to generate a list of transitions
- * in a time interval to a given level of detail.
- * @param[out] edges The vector to place the edges into.
- * @param[in] start The start sample index.
- * @param[in] end The end sample index.
- * @param[in] min_length The minimum number of samples that
- * can be resolved at this level of detail.
- * @param[in] sig_index The index of the signal.
- **/
- void get_subsampled_edges(std::vector<EdgePair> &edges,
- uint64_t start, uint64_t end,
- float min_length, int sig_index);
-
-private:
- uint64_t get_subsample(int level, uint64_t offset) const;
-
- static uint64_t pow2_ceil(uint64_t x, unsigned int power);
-
-private:
- struct MipMapLevel _mip_map[ScaleStepCount];
- uint64_t _last_append_sample;
-
- friend class LogicDataSnapshotTest::Pow2;
- friend class LogicDataSnapshotTest::Basic;
- friend class LogicDataSnapshotTest::LargeData;
- friend class LogicDataSnapshotTest::Pulses;
- friend class LogicDataSnapshotTest::LongPulses;
-};
-
-} // namespace pv
-
-#endif // PULSEVIEW_PV_LOGICDATASNAPSHOT_H
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "signaldata.h"
-
-namespace pv {
-
-SignalData::SignalData(double samplerate) :
- _samplerate(samplerate),
- _start_time(0)
-{
-}
-
-double SignalData::get_samplerate() const
-{
- return _samplerate;
-}
-
-double SignalData::get_start_time() const
-{
- return _start_time;
-}
-
-} // namespace pv
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef PULSEVIEW_PV_SIGNALDATA_H
-#define PULSEVIEW_PV_SIGNALDATA_H
-
-#include <stdint.h>
-
-namespace pv {
-
-class SignalData
-{
-public:
- SignalData(double samplerate);
-
-public:
- double get_samplerate() const;
- double get_start_time() const;
-
-protected:
- const double _samplerate;
- const double _start_time;
-};
-
-} // namespace pv
-
-#endif // PULSEVIEW_PV_SIGNALDATA_H
#include "sigsession.h"
-#include "analogdata.h"
-#include "analogdatasnapshot.h"
-#include "logicdata.h"
-#include "logicdatasnapshot.h"
+#include "data/analog.h"
+#include "data/analogsnapshot.h"
+#include "data/logic.h"
+#include "data/logicsnapshot.h"
#include "view/analogsignal.h"
#include "view/logicsignal.h"
return _signals;
}
-boost::shared_ptr<LogicData> SigSession::get_data()
+boost::shared_ptr<data::Logic> SigSession::get_data()
{
return _logic_data;
}
lock_guard<mutex> data_lock(_data_mutex);
lock_guard<mutex> sampling_lock(_sampling_mutex);
- // Create an empty LogicData for coming data snapshots
- _logic_data.reset(new LogicData(meta_logic, _sample_rate));
+ // Create an empty data::Logic for coming data snapshots
+ _logic_data.reset(new data::Logic(meta_logic, _sample_rate));
assert(_logic_data);
if (!_logic_data)
return;
lock_guard<mutex> data_lock(_data_mutex);
lock_guard<mutex> sampling_lock(_sampling_mutex);
- // Create an empty AnalogData for coming data snapshots
- _analog_data.reset(new AnalogData(
+ // Create an empty data::Analog for coming data snapshots
+ _analog_data.reset(new data::Analog(
meta_analog, _sample_rate));
assert(_analog_data);
if (!_analog_data)
if (!_cur_logic_snapshot)
{
// Create a new data snapshot
- _cur_logic_snapshot = shared_ptr<LogicDataSnapshot>(
- new LogicDataSnapshot(logic));
+ _cur_logic_snapshot = shared_ptr<data::LogicSnapshot>(
+ new data::LogicSnapshot(logic));
_logic_data->push_snapshot(_cur_logic_snapshot);
}
else
if (!_cur_analog_snapshot)
{
// Create a new data snapshot
- _cur_analog_snapshot = shared_ptr<AnalogDataSnapshot>(
- new AnalogDataSnapshot(analog));
+ _cur_analog_snapshot = shared_ptr<data::AnalogSnapshot>(
+ new data::AnalogSnapshot(analog));
_analog_data->push_snapshot(_cur_analog_snapshot);
}
else
namespace pv {
-class AnalogData;
-class AnalogDataSnapshot;
-class LogicData;
-class LogicDataSnapshot;
+namespace data {
+class Analog;
+class AnalogSnapshot;
+class Logic;
+class LogicSnapshot;
+}
namespace view {
class Signal;
std::vector< boost::shared_ptr<view::Signal> >
get_signals();
- boost::shared_ptr<LogicData> get_data();
+ boost::shared_ptr<data::Logic> get_data();
private:
void set_capture_state(capture_state state);
std::vector< boost::shared_ptr<view::Signal> > _signals;
mutable boost::mutex _data_mutex;
- boost::shared_ptr<LogicData> _logic_data;
- boost::shared_ptr<LogicDataSnapshot> _cur_logic_snapshot;
- boost::shared_ptr<AnalogData> _analog_data;
- boost::shared_ptr<AnalogDataSnapshot> _cur_analog_snapshot;
+ boost::shared_ptr<data::Logic> _logic_data;
+ boost::shared_ptr<data::LogicSnapshot> _cur_logic_snapshot;
+ boost::shared_ptr<data::Analog> _analog_data;
+ boost::shared_ptr<data::AnalogSnapshot> _cur_analog_snapshot;
std::auto_ptr<boost::thread> _sampling_thread;
#include <math.h>
#include "analogsignal.h"
-#include "../analogdata.h"
-#include "../analogdatasnapshot.h"
+#include "pv/data/analog.h"
+#include "pv/data/analogsnapshot.h"
using namespace boost;
using namespace std;
namespace pv {
namespace view {
-AnalogSignal::AnalogSignal(QString name, shared_ptr<AnalogData> data) :
+AnalogSignal::AnalogSignal(QString name, shared_ptr<data::Analog> data) :
Signal(name),
_data(data)
{
assert(scale > 0);
assert(_data);
- const deque< shared_ptr<pv::AnalogDataSnapshot> > &snapshots =
+ const deque< shared_ptr<pv::data::AnalogSnapshot> > &snapshots =
_data->get_snapshots();
if (snapshots.empty())
return;
- const shared_ptr<pv::AnalogDataSnapshot> &snapshot =
+ const shared_ptr<pv::data::AnalogSnapshot> &snapshot =
snapshots.front();
const double pixels_offset = offset / scale;
namespace pv {
-class AnalogData;
+namespace data {
+class Analog;
+}
namespace view {
{
public:
AnalogSignal(QString name,
- boost::shared_ptr<pv::AnalogData> data);
+ boost::shared_ptr<pv::data::Analog> data);
/**
* Paints the signal with a QPainter
int get_nominal_offset(const QRect &rect) const;
private:
- boost::shared_ptr<pv::AnalogData> _data;
+ boost::shared_ptr<pv::data::Analog> _data;
};
} // namespace view
#include <math.h>
#include "logicsignal.h"
-#include "../logicdata.h"
-#include "../logicdatasnapshot.h"
+#include "pv/data/logic.h"
+#include "pv/data/logicsnapshot.h"
using namespace boost;
using namespace std;
QColor(0xEE, 0xEE, 0xEC), // White
};
-LogicSignal::LogicSignal(QString name, shared_ptr<LogicData> data,
+LogicSignal::LogicSignal(QString name, shared_ptr<data::Logic> data,
int probe_index) :
Signal(name),
_probe_index(probe_index),
const float high_offset = rect.top() + 0.5f;
const float low_offset = rect.bottom() + 0.5f;
- const deque< shared_ptr<pv::LogicDataSnapshot> > &snapshots =
+ const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots =
_data->get_snapshots();
if (snapshots.empty())
return;
- const shared_ptr<pv::LogicDataSnapshot> &snapshot =
+ const shared_ptr<pv::data::LogicSnapshot> &snapshot =
snapshots.front();
const double pixels_offset = offset / scale;
QLineF *const edge_lines = new QLineF[edge_count];
line = edge_lines;
- for (vector<pv::LogicDataSnapshot::EdgePair>::const_iterator i =
+ for (vector<pv::data::LogicSnapshot::EdgePair>::const_iterator i =
edges.begin() + 1;
i != edges.end() - 1; i++) {
const float x = ((*i).first / samples_per_pixel -
{
QLineF *line = lines;
- for (vector<pv::LogicDataSnapshot::EdgePair>::const_iterator i =
+ for (vector<pv::data::LogicSnapshot::EdgePair>::const_iterator i =
edges.begin(); i != (edges.end() - 1); i++)
if ((*i).second == level) {
*line++ = QLineF(
namespace pv {
-class LogicData;
+namespace data {
+class Logic;
+}
namespace view {
public:
LogicSignal(QString name,
- boost::shared_ptr<pv::LogicData> data,
+ boost::shared_ptr<pv::data::Logic> data,
int probe_index);
/**
private:
int _probe_index;
- boost::shared_ptr<pv::LogicData> _data;
+ boost::shared_ptr<pv::data::Logic> _data;
};
} // namespace view
namespace pv {
+namespace data {
class SignalData;
+}
namespace view {
#include "view.h"
#include "viewport.h"
-#include "../logicdata.h"
-#include "../logicdatasnapshot.h"
-#include "../sigsession.h"
+#include "pv/sigsession.h"
+#include "pv/data/logic.h"
+#include "pv/data/logicsnapshot.h"
using namespace boost;
using namespace std;
void View::get_scroll_layout(double &length, double &offset) const
{
- const shared_ptr<SignalData> sig_data = _session.get_data();
+ const shared_ptr<data::SignalData> sig_data = _session.get_data();
if (!sig_data)
return;
{
// Get the new data length
_data_length = 0;
- shared_ptr<LogicData> sig_data = _session.get_data();
+ shared_ptr<data::Logic> sig_data = _session.get_data();
if (sig_data) {
- deque< shared_ptr<LogicDataSnapshot> > &snapshots =
+ deque< shared_ptr<data::LogicSnapshot> > &snapshots =
sig_data->get_snapshots();
- BOOST_FOREACH(shared_ptr<LogicDataSnapshot> s, snapshots)
+ BOOST_FOREACH(shared_ptr<data::LogicSnapshot> s, snapshots)
if (s)
_data_length = max(_data_length,
s->get_sample_count());
find_package(Boost 1.46 COMPONENTS unit_test_framework REQUIRED)
set(pulseview_TEST_SOURCES
- ${PROJECT_SOURCE_DIR}/pv/datasnapshot.cpp
- ${PROJECT_SOURCE_DIR}/pv/logicdatasnapshot.cpp
- logicdatasnapshot.cpp
+ ${PROJECT_SOURCE_DIR}/pv/data/snapshot.cpp
+ ${PROJECT_SOURCE_DIR}/pv/data/logicsnapshot.cpp
+ data/logicsnapshot.cpp
test.cpp
)
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <extdef.h>
+
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include <boost/test/unit_test.hpp>
+
+#include "../../pv/data/logicsnapshot.h"
+
+using namespace std;
+
+using pv::data::LogicSnapshot;
+
+BOOST_AUTO_TEST_SUITE(LogicSnapshotTest)
+
+void push_logic(LogicSnapshot &s, unsigned int length, uint8_t value)
+{
+ sr_datafeed_logic logic;
+ logic.unitsize = 1;
+ logic.length = length;
+ logic.data = new uint8_t[length];
+ memset(logic.data, value, length * logic.unitsize);
+ s.append_payload(logic);
+ delete[] (uint8_t*)logic.data;
+}
+
+BOOST_AUTO_TEST_CASE(Pow2)
+{
+ BOOST_CHECK_EQUAL(LogicSnapshot::pow2_ceil(0, 0), 0);
+ BOOST_CHECK_EQUAL(LogicSnapshot::pow2_ceil(1, 0), 1);
+ BOOST_CHECK_EQUAL(LogicSnapshot::pow2_ceil(2, 0), 2);
+
+ BOOST_CHECK_EQUAL(
+ LogicSnapshot::pow2_ceil(INT64_MIN, 0), INT64_MIN);
+ BOOST_CHECK_EQUAL(
+ LogicSnapshot::pow2_ceil(INT64_MAX, 0), INT64_MAX);
+
+ BOOST_CHECK_EQUAL(LogicSnapshot::pow2_ceil(0, 1), 0);
+ BOOST_CHECK_EQUAL(LogicSnapshot::pow2_ceil(1, 1), 2);
+ BOOST_CHECK_EQUAL(LogicSnapshot::pow2_ceil(2, 1), 2);
+ BOOST_CHECK_EQUAL(LogicSnapshot::pow2_ceil(3, 1), 4);
+}
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ // Create an empty LogicSnapshot object
+ sr_datafeed_logic logic;
+ logic.length = 0;
+ logic.unitsize = 1;
+ logic.data = NULL;
+
+ LogicSnapshot s(logic);
+
+ //----- Test LogicSnapshot::push_logic -----//
+
+ BOOST_CHECK(s.get_sample_count() == 0);
+ for (unsigned int i = 0; i < LogicSnapshot::ScaleStepCount; i++)
+ {
+ const LogicSnapshot::MipMapLevel &m = s._mip_map[i];
+ BOOST_CHECK_EQUAL(m.length, 0);
+ BOOST_CHECK_EQUAL(m.data_length, 0);
+ BOOST_CHECK(m.data == NULL);
+ }
+
+ // Push 8 samples of all zeros
+ push_logic(s, 8, 0);
+
+ BOOST_CHECK(s.get_sample_count() == 8);
+
+ // There should not be enough samples to have a single mip map sample
+ for (unsigned int i = 0; i < LogicSnapshot::ScaleStepCount; i++)
+ {
+ const LogicSnapshot::MipMapLevel &m = s._mip_map[i];
+ BOOST_CHECK_EQUAL(m.length, 0);
+ BOOST_CHECK_EQUAL(m.data_length, 0);
+ BOOST_CHECK(m.data == NULL);
+ }
+
+ // Push 8 samples of 0x11s to bring the total up to 16
+ push_logic(s, 8, 0x11);
+
+ // There should now be enough data for exactly one sample
+ // in mip map level 0, and that sample should be 0
+ const LogicSnapshot::MipMapLevel &m0 = s._mip_map[0];
+ BOOST_CHECK_EQUAL(m0.length, 1);
+ BOOST_CHECK_EQUAL(m0.data_length, LogicSnapshot::MipMapDataUnit);
+ BOOST_REQUIRE(m0.data != NULL);
+ BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[0], 0x11);
+
+ // The higher levels should still be empty
+ for (unsigned int i = 1; i < LogicSnapshot::ScaleStepCount; i++)
+ {
+ const LogicSnapshot::MipMapLevel &m = s._mip_map[i];
+ BOOST_CHECK_EQUAL(m.length, 0);
+ BOOST_CHECK_EQUAL(m.data_length, 0);
+ BOOST_CHECK(m.data == NULL);
+ }
+
+ // Push 240 samples of all zeros to bring the total up to 256
+ push_logic(s, 240, 0);
+
+ BOOST_CHECK_EQUAL(m0.length, 16);
+ BOOST_CHECK_EQUAL(m0.data_length, LogicSnapshot::MipMapDataUnit);
+
+ BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[1], 0x11);
+ for (unsigned int i = 2; i < m0.length; i++)
+ BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[i], 0);
+
+ const LogicSnapshot::MipMapLevel &m1 = s._mip_map[1];
+ BOOST_CHECK_EQUAL(m1.length, 1);
+ BOOST_CHECK_EQUAL(m1.data_length, LogicSnapshot::MipMapDataUnit);
+ BOOST_REQUIRE(m1.data != NULL);
+ BOOST_CHECK_EQUAL(((uint8_t*)m1.data)[0], 0x11);
+
+ //----- Test LogicSnapshot::get_subsampled_edges -----//
+
+ // Test a full view at full zoom.
+ vector<LogicSnapshot::EdgePair> edges;
+ s.get_subsampled_edges(edges, 0, 255, 1, 0);
+ BOOST_REQUIRE_EQUAL(edges.size(), 4);
+
+ BOOST_CHECK_EQUAL(edges[0].first, 0);
+ BOOST_CHECK_EQUAL(edges[1].first, 8);
+ BOOST_CHECK_EQUAL(edges[2].first, 16);
+ BOOST_CHECK_EQUAL(edges[3].first, 255);
+
+ // Test a subset at high zoom
+ edges.clear();
+ s.get_subsampled_edges(edges, 6, 17, 0.05f, 0);
+ BOOST_REQUIRE_EQUAL(edges.size(), 4);
+
+ BOOST_CHECK_EQUAL(edges[0].first, 6);
+ BOOST_CHECK_EQUAL(edges[1].first, 8);
+ BOOST_CHECK_EQUAL(edges[2].first, 16);
+ BOOST_CHECK_EQUAL(edges[3].first, 17);
+}
+
+BOOST_AUTO_TEST_CASE(LargeData)
+{
+ uint8_t prev_sample;
+ const unsigned int Length = 1000000;
+
+ sr_datafeed_logic logic;
+ logic.unitsize = 1;
+ logic.length = Length;
+ logic.data = new uint8_t[Length];
+ uint8_t *data = (uint8_t*)logic.data;
+
+ for (unsigned int i = 0; i < Length; i++)
+ *data++ = (uint8_t)(i >> 8);
+
+ LogicSnapshot s(logic);
+ delete[] (uint8_t*)logic.data;
+
+ BOOST_CHECK(s.get_sample_count() == Length);
+
+ // Check mip map level 0
+ BOOST_CHECK_EQUAL(s._mip_map[0].length, 62500);
+ BOOST_CHECK_EQUAL(s._mip_map[0].data_length,
+ LogicSnapshot::MipMapDataUnit);
+ BOOST_REQUIRE(s._mip_map[0].data != NULL);
+
+ prev_sample = 0;
+ for (unsigned int i = 0; i < s._mip_map[0].length;)
+ {
+ BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
+
+ const uint8_t sample = (uint8_t)((i*16) >> 8);
+ BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF,
+ prev_sample ^ sample);
+ prev_sample = sample;
+
+ for (int j = 1; i < s._mip_map[0].length && j < 16; j++)
+ {
+ BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
+ BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0);
+ }
+ }
+
+ // Check mip map level 1
+ BOOST_CHECK_EQUAL(s._mip_map[1].length, 3906);
+ BOOST_CHECK_EQUAL(s._mip_map[1].data_length,
+ LogicSnapshot::MipMapDataUnit);
+ BOOST_REQUIRE(s._mip_map[1].data != NULL);
+
+ prev_sample = 0;
+ for (unsigned int i = 0; i < s._mip_map[1].length; i++)
+ {
+ BOOST_TEST_MESSAGE("Testing mip_map[1].data[" << i << "]");
+
+ const uint8_t sample = i;
+ const uint8_t expected = sample ^ prev_sample;
+ prev_sample = i;
+
+ BOOST_CHECK_EQUAL(s.get_subsample(1, i) & 0xFF, expected);
+ }
+
+ // Check mip map level 2
+ BOOST_CHECK_EQUAL(s._mip_map[2].length, 244);
+ BOOST_CHECK_EQUAL(s._mip_map[2].data_length,
+ LogicSnapshot::MipMapDataUnit);
+ BOOST_REQUIRE(s._mip_map[2].data != NULL);
+
+ prev_sample = 0;
+ for (unsigned int i = 0; i < s._mip_map[2].length; i++)
+ {
+ BOOST_TEST_MESSAGE("Testing mip_map[2].data[" << i << "]");
+
+ const uint8_t sample = i << 4;
+ const uint8_t expected = (sample ^ prev_sample) | 0x0F;
+ prev_sample = sample;
+
+ BOOST_CHECK_EQUAL(s.get_subsample(2, i) & 0xFF, expected);
+ }
+
+ // Check mip map level 3
+ BOOST_CHECK_EQUAL(s._mip_map[3].length, 15);
+ BOOST_CHECK_EQUAL(s._mip_map[3].data_length,
+ LogicSnapshot::MipMapDataUnit);
+ BOOST_REQUIRE(s._mip_map[3].data != NULL);
+
+ for (unsigned int i = 0; i < s._mip_map[3].length; i++)
+ BOOST_CHECK_EQUAL(*((uint8_t*)s._mip_map[3].data + i),
+ 0xFF);
+
+ // Check the higher levels
+ for (unsigned int i = 4; i < LogicSnapshot::ScaleStepCount; i++)
+ {
+ const LogicSnapshot::MipMapLevel &m = s._mip_map[i];
+ BOOST_CHECK_EQUAL(m.length, 0);
+ BOOST_CHECK_EQUAL(m.data_length, 0);
+ BOOST_CHECK(m.data == NULL);
+ }
+
+ //----- Test LogicSnapshot::get_subsampled_edges -----//
+ // Check in normal case
+ vector<LogicSnapshot::EdgePair> edges;
+ s.get_subsampled_edges(edges, 0, Length-1, 1, 7);
+
+ BOOST_CHECK_EQUAL(edges.size(), 32);
+
+ for (unsigned int i = 0; i < edges.size() - 1; i++)
+ {
+ BOOST_CHECK_EQUAL(edges[i].first, i * 32768);
+ BOOST_CHECK_EQUAL(edges[i].second, i & 1);
+ }
+
+ BOOST_CHECK_EQUAL(edges[31].first, 999999);
+
+ // Check in very low zoom case
+ edges.clear();
+ s.get_subsampled_edges(edges, 0, Length-1, 50e6f, 7);
+
+ BOOST_CHECK_EQUAL(edges.size(), 2);
+}
+
+BOOST_AUTO_TEST_CASE(Pulses)
+{
+ const int Cycles = 3;
+ const int Period = 64;
+ const int Length = Cycles * Period;
+
+ vector<LogicSnapshot::EdgePair> edges;
+
+ //----- Create a LogicSnapshot -----//
+ sr_datafeed_logic logic;
+ logic.unitsize = 1;
+ logic.length = Length;
+ logic.data = (uint64_t*)new uint8_t[Length];
+ uint8_t *p = (uint8_t*)logic.data;
+
+ for (int i = 0; i < Cycles; i++) {
+ *p++ = 0xFF;
+ for (int j = 1; j < Period; j++)
+ *p++ = 0x00;
+ }
+
+ LogicSnapshot s(logic);
+ delete[] (uint8_t*)logic.data;
+
+ //----- Check the mip-map -----//
+ // Check mip map level 0
+ BOOST_CHECK_EQUAL(s._mip_map[0].length, 12);
+ BOOST_CHECK_EQUAL(s._mip_map[0].data_length,
+ LogicSnapshot::MipMapDataUnit);
+ BOOST_REQUIRE(s._mip_map[0].data != NULL);
+
+ for (unsigned int i = 0; i < s._mip_map[0].length;) {
+ BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
+ BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0xFF);
+
+ for (int j = 1;
+ i < s._mip_map[0].length &&
+ j < Period/LogicSnapshot::MipMapScaleFactor; j++) {
+ BOOST_TEST_MESSAGE(
+ "Testing mip_map[0].data[" << i << "]");
+ BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0x00);
+ }
+ }
+
+ // Check the higher levels are all inactive
+ for (unsigned int i = 1; i < LogicSnapshot::ScaleStepCount; i++) {
+ const LogicSnapshot::MipMapLevel &m = s._mip_map[i];
+ BOOST_CHECK_EQUAL(m.length, 0);
+ BOOST_CHECK_EQUAL(m.data_length, 0);
+ BOOST_CHECK(m.data == NULL);
+ }
+
+ //----- Test get_subsampled_edges at reduced scale -----//
+ s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
+ BOOST_REQUIRE_EQUAL(edges.size(), Cycles + 2);
+
+ BOOST_CHECK_EQUAL(0, false);
+ for (unsigned int i = 1; i < edges.size(); i++)
+ BOOST_CHECK_EQUAL(edges[i].second, false);
+}
+
+BOOST_AUTO_TEST_CASE(LongPulses)
+{
+ const int Cycles = 3;
+ const int Period = 64;
+ const int PulseWidth = 16;
+ const int Length = Cycles * Period;
+
+ int j;
+ vector<LogicSnapshot::EdgePair> edges;
+
+ //----- Create a LogicSnapshot -----//
+ sr_datafeed_logic logic;
+ logic.unitsize = 8;
+ logic.length = Length;
+ logic.data = (uint64_t*)new uint64_t[Length];
+ uint64_t *p = (uint64_t*)logic.data;
+
+ for (int i = 0; i < Cycles; i++) {
+ for (j = 0; j < PulseWidth; j++)
+ *p++ = ~0;
+ for (; j < Period; j++)
+ *p++ = 0;
+ }
+
+ LogicSnapshot s(logic);
+ delete[] (uint64_t*)logic.data;
+
+ //----- Check the mip-map -----//
+ // Check mip map level 0
+ BOOST_CHECK_EQUAL(s._mip_map[0].length, 12);
+ BOOST_CHECK_EQUAL(s._mip_map[0].data_length,
+ LogicSnapshot::MipMapDataUnit);
+ BOOST_REQUIRE(s._mip_map[0].data != NULL);
+
+ for (unsigned int i = 0; i < s._mip_map[0].length;) {
+ for (j = 0; i < s._mip_map[0].length && j < 2; j++) {
+ BOOST_TEST_MESSAGE(
+ "Testing mip_map[0].data[" << i << "]");
+ BOOST_CHECK_EQUAL(s.get_subsample(0, i++), ~0);
+ }
+
+ for (; i < s._mip_map[0].length &&
+ j < Period/LogicSnapshot::MipMapScaleFactor; j++) {
+ BOOST_TEST_MESSAGE(
+ "Testing mip_map[0].data[" << i << "]");
+ BOOST_CHECK_EQUAL(s.get_subsample(0, i++), 0);
+ }
+ }
+
+ // Check the higher levels are all inactive
+ for (unsigned int i = 1; i < LogicSnapshot::ScaleStepCount; i++) {
+ const LogicSnapshot::MipMapLevel &m = s._mip_map[i];
+ BOOST_CHECK_EQUAL(m.length, 0);
+ BOOST_CHECK_EQUAL(m.data_length, 0);
+ BOOST_CHECK(m.data == NULL);
+ }
+
+ //----- Test get_subsampled_edges at a full scale -----//
+ s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
+ BOOST_REQUIRE_EQUAL(edges.size(), Cycles * 2 + 1);
+
+ for (int i = 0; i < Cycles; i++) {
+ BOOST_CHECK_EQUAL(edges[i*2].first, i * Period);
+ BOOST_CHECK_EQUAL(edges[i*2].second, true);
+ BOOST_CHECK_EQUAL(edges[i*2+1].first, i * Period + PulseWidth);
+ BOOST_CHECK_EQUAL(edges[i*2+1].second, false);
+ }
+
+ BOOST_CHECK_EQUAL(edges.back().first, Length-1);
+ BOOST_CHECK_EQUAL(edges.back().second, false);
+
+ //----- Test get_subsampled_edges at a simplified scale -----//
+ edges.clear();
+ s.get_subsampled_edges(edges, 0, Length-1, 17.0f, 2);
+
+ BOOST_CHECK_EQUAL(edges[0].first, 0);
+ BOOST_CHECK_EQUAL(edges[0].second, true);
+ BOOST_CHECK_EQUAL(edges[1].first, 16);
+ BOOST_CHECK_EQUAL(edges[1].second, false);
+
+ for (int i = 1; i < Cycles; i++) {
+ BOOST_CHECK_EQUAL(edges[i+1].first, i * Period);
+ BOOST_CHECK_EQUAL(edges[i+1].second, false);
+ }
+
+ BOOST_CHECK_EQUAL(edges.back().first, Length-1);
+ BOOST_CHECK_EQUAL(edges.back().second, false);
+}
+
+BOOST_AUTO_TEST_CASE(LisaMUsbHid)
+{
+ /* This test was created from the beginning of the USB_DM signal in
+ * sigrok-dumps-usb/lisa_m_usbhid/lisa_m_usbhid.sr
+ */
+
+ const int Edges[] = {
+ 7028, 7033, 7036, 7041, 7044, 7049, 7053, 7066, 7073, 7079,
+ 7086, 7095, 7103, 7108, 7111, 7116, 7119, 7124, 7136, 7141,
+ 7148, 7162, 7500
+ };
+ const int Length = Edges[countof(Edges) - 1];
+
+ bool state = false;
+ int lastEdgePos = 0;
+
+ //----- Create a LogicSnapshot -----//
+ sr_datafeed_logic logic;
+ logic.unitsize = 1;
+ logic.length = Length;
+ logic.data = new uint8_t[Length];
+ uint8_t *data = (uint8_t*)logic.data;
+
+ for (unsigned int i = 0; i < countof(Edges); i++) {
+ const int edgePos = Edges[i];
+ memset(&data[lastEdgePos], state ? 0x02 : 0,
+ edgePos - lastEdgePos - 1);
+
+ lastEdgePos = edgePos;
+ state = !state;
+ }
+
+ LogicSnapshot s(logic);
+ delete[] (uint64_t*)logic.data;
+
+ vector<LogicSnapshot::EdgePair> edges;
+
+
+ /* The trailing edge of the pulse train is falling in the source data.
+ * Check this is always true at different scales
+ */
+
+ edges.clear();
+ s.get_subsampled_edges(edges, 0, Length-1, 33.333332f, 1);
+ BOOST_CHECK_EQUAL(edges[edges.size() - 2].second, false);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
+++ /dev/null
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <extdef.h>
-
-#define __STDC_LIMIT_MACROS
-#include <stdint.h>
-
-#include <boost/test/unit_test.hpp>
-
-#include "../pv/logicdatasnapshot.h"
-
-using namespace std;
-
-using pv::LogicDataSnapshot;
-
-BOOST_AUTO_TEST_SUITE(LogicDataSnapshotTest)
-
-void push_logic(LogicDataSnapshot &s, unsigned int length, uint8_t value)
-{
- sr_datafeed_logic logic;
- logic.unitsize = 1;
- logic.length = length;
- logic.data = new uint8_t[length];
- memset(logic.data, value, length * logic.unitsize);
- s.append_payload(logic);
- delete[] (uint8_t*)logic.data;
-}
-
-BOOST_AUTO_TEST_CASE(Pow2)
-{
- BOOST_CHECK_EQUAL(LogicDataSnapshot::pow2_ceil(0, 0), 0);
- BOOST_CHECK_EQUAL(LogicDataSnapshot::pow2_ceil(1, 0), 1);
- BOOST_CHECK_EQUAL(LogicDataSnapshot::pow2_ceil(2, 0), 2);
-
- BOOST_CHECK_EQUAL(
- LogicDataSnapshot::pow2_ceil(INT64_MIN, 0), INT64_MIN);
- BOOST_CHECK_EQUAL(
- LogicDataSnapshot::pow2_ceil(INT64_MAX, 0), INT64_MAX);
-
- BOOST_CHECK_EQUAL(LogicDataSnapshot::pow2_ceil(0, 1), 0);
- BOOST_CHECK_EQUAL(LogicDataSnapshot::pow2_ceil(1, 1), 2);
- BOOST_CHECK_EQUAL(LogicDataSnapshot::pow2_ceil(2, 1), 2);
- BOOST_CHECK_EQUAL(LogicDataSnapshot::pow2_ceil(3, 1), 4);
-}
-
-BOOST_AUTO_TEST_CASE(Basic)
-{
- // Create an empty LogicDataSnapshot object
- sr_datafeed_logic logic;
- logic.length = 0;
- logic.unitsize = 1;
- logic.data = NULL;
-
- LogicDataSnapshot s(logic);
-
- //----- Test LogicDataSnapshot::push_logic -----//
-
- BOOST_CHECK(s.get_sample_count() == 0);
- for (unsigned int i = 0; i < LogicDataSnapshot::ScaleStepCount; i++)
- {
- const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
- BOOST_CHECK_EQUAL(m.length, 0);
- BOOST_CHECK_EQUAL(m.data_length, 0);
- BOOST_CHECK(m.data == NULL);
- }
-
- // Push 8 samples of all zeros
- push_logic(s, 8, 0);
-
- BOOST_CHECK(s.get_sample_count() == 8);
-
- // There should not be enough samples to have a single mip map sample
- for (unsigned int i = 0; i < LogicDataSnapshot::ScaleStepCount; i++)
- {
- const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
- BOOST_CHECK_EQUAL(m.length, 0);
- BOOST_CHECK_EQUAL(m.data_length, 0);
- BOOST_CHECK(m.data == NULL);
- }
-
- // Push 8 samples of 0x11s to bring the total up to 16
- push_logic(s, 8, 0x11);
-
- // There should now be enough data for exactly one sample
- // in mip map level 0, and that sample should be 0
- const LogicDataSnapshot::MipMapLevel &m0 = s._mip_map[0];
- BOOST_CHECK_EQUAL(m0.length, 1);
- BOOST_CHECK_EQUAL(m0.data_length, LogicDataSnapshot::MipMapDataUnit);
- BOOST_REQUIRE(m0.data != NULL);
- BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[0], 0x11);
-
- // The higher levels should still be empty
- for (unsigned int i = 1; i < LogicDataSnapshot::ScaleStepCount; i++)
- {
- const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
- BOOST_CHECK_EQUAL(m.length, 0);
- BOOST_CHECK_EQUAL(m.data_length, 0);
- BOOST_CHECK(m.data == NULL);
- }
-
- // Push 240 samples of all zeros to bring the total up to 256
- push_logic(s, 240, 0);
-
- BOOST_CHECK_EQUAL(m0.length, 16);
- BOOST_CHECK_EQUAL(m0.data_length, LogicDataSnapshot::MipMapDataUnit);
-
- BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[1], 0x11);
- for (unsigned int i = 2; i < m0.length; i++)
- BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[i], 0);
-
- const LogicDataSnapshot::MipMapLevel &m1 = s._mip_map[1];
- BOOST_CHECK_EQUAL(m1.length, 1);
- BOOST_CHECK_EQUAL(m1.data_length, LogicDataSnapshot::MipMapDataUnit);
- BOOST_REQUIRE(m1.data != NULL);
- BOOST_CHECK_EQUAL(((uint8_t*)m1.data)[0], 0x11);
-
- //----- Test LogicDataSnapshot::get_subsampled_edges -----//
-
- // Test a full view at full zoom.
- vector<LogicDataSnapshot::EdgePair> edges;
- s.get_subsampled_edges(edges, 0, 255, 1, 0);
- BOOST_REQUIRE_EQUAL(edges.size(), 4);
-
- BOOST_CHECK_EQUAL(edges[0].first, 0);
- BOOST_CHECK_EQUAL(edges[1].first, 8);
- BOOST_CHECK_EQUAL(edges[2].first, 16);
- BOOST_CHECK_EQUAL(edges[3].first, 255);
-
- // Test a subset at high zoom
- edges.clear();
- s.get_subsampled_edges(edges, 6, 17, 0.05f, 0);
- BOOST_REQUIRE_EQUAL(edges.size(), 4);
-
- BOOST_CHECK_EQUAL(edges[0].first, 6);
- BOOST_CHECK_EQUAL(edges[1].first, 8);
- BOOST_CHECK_EQUAL(edges[2].first, 16);
- BOOST_CHECK_EQUAL(edges[3].first, 17);
-}
-
-BOOST_AUTO_TEST_CASE(LargeData)
-{
- uint8_t prev_sample;
- const unsigned int Length = 1000000;
-
- sr_datafeed_logic logic;
- logic.unitsize = 1;
- logic.length = Length;
- logic.data = new uint8_t[Length];
- uint8_t *data = (uint8_t*)logic.data;
-
- for (unsigned int i = 0; i < Length; i++)
- *data++ = (uint8_t)(i >> 8);
-
- LogicDataSnapshot s(logic);
- delete[] (uint8_t*)logic.data;
-
- BOOST_CHECK(s.get_sample_count() == Length);
-
- // Check mip map level 0
- BOOST_CHECK_EQUAL(s._mip_map[0].length, 62500);
- BOOST_CHECK_EQUAL(s._mip_map[0].data_length,
- LogicDataSnapshot::MipMapDataUnit);
- BOOST_REQUIRE(s._mip_map[0].data != NULL);
-
- prev_sample = 0;
- for (unsigned int i = 0; i < s._mip_map[0].length;)
- {
- BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
-
- const uint8_t sample = (uint8_t)((i*16) >> 8);
- BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF,
- prev_sample ^ sample);
- prev_sample = sample;
-
- for (int j = 1; i < s._mip_map[0].length && j < 16; j++)
- {
- BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
- BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0);
- }
- }
-
- // Check mip map level 1
- BOOST_CHECK_EQUAL(s._mip_map[1].length, 3906);
- BOOST_CHECK_EQUAL(s._mip_map[1].data_length,
- LogicDataSnapshot::MipMapDataUnit);
- BOOST_REQUIRE(s._mip_map[1].data != NULL);
-
- prev_sample = 0;
- for (unsigned int i = 0; i < s._mip_map[1].length; i++)
- {
- BOOST_TEST_MESSAGE("Testing mip_map[1].data[" << i << "]");
-
- const uint8_t sample = i;
- const uint8_t expected = sample ^ prev_sample;
- prev_sample = i;
-
- BOOST_CHECK_EQUAL(s.get_subsample(1, i) & 0xFF, expected);
- }
-
- // Check mip map level 2
- BOOST_CHECK_EQUAL(s._mip_map[2].length, 244);
- BOOST_CHECK_EQUAL(s._mip_map[2].data_length,
- LogicDataSnapshot::MipMapDataUnit);
- BOOST_REQUIRE(s._mip_map[2].data != NULL);
-
- prev_sample = 0;
- for (unsigned int i = 0; i < s._mip_map[2].length; i++)
- {
- BOOST_TEST_MESSAGE("Testing mip_map[2].data[" << i << "]");
-
- const uint8_t sample = i << 4;
- const uint8_t expected = (sample ^ prev_sample) | 0x0F;
- prev_sample = sample;
-
- BOOST_CHECK_EQUAL(s.get_subsample(2, i) & 0xFF, expected);
- }
-
- // Check mip map level 3
- BOOST_CHECK_EQUAL(s._mip_map[3].length, 15);
- BOOST_CHECK_EQUAL(s._mip_map[3].data_length,
- LogicDataSnapshot::MipMapDataUnit);
- BOOST_REQUIRE(s._mip_map[3].data != NULL);
-
- for (unsigned int i = 0; i < s._mip_map[3].length; i++)
- BOOST_CHECK_EQUAL(*((uint8_t*)s._mip_map[3].data + i),
- 0xFF);
-
- // Check the higher levels
- for (unsigned int i = 4; i < LogicDataSnapshot::ScaleStepCount; i++)
- {
- const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
- BOOST_CHECK_EQUAL(m.length, 0);
- BOOST_CHECK_EQUAL(m.data_length, 0);
- BOOST_CHECK(m.data == NULL);
- }
-
- //----- Test LogicDataSnapshot::get_subsampled_edges -----//
- // Check in normal case
- vector<LogicDataSnapshot::EdgePair> edges;
- s.get_subsampled_edges(edges, 0, Length-1, 1, 7);
-
- BOOST_CHECK_EQUAL(edges.size(), 32);
-
- for (unsigned int i = 0; i < edges.size() - 1; i++)
- {
- BOOST_CHECK_EQUAL(edges[i].first, i * 32768);
- BOOST_CHECK_EQUAL(edges[i].second, i & 1);
- }
-
- BOOST_CHECK_EQUAL(edges[31].first, 999999);
-
- // Check in very low zoom case
- edges.clear();
- s.get_subsampled_edges(edges, 0, Length-1, 50e6f, 7);
-
- BOOST_CHECK_EQUAL(edges.size(), 2);
-}
-
-BOOST_AUTO_TEST_CASE(Pulses)
-{
- const int Cycles = 3;
- const int Period = 64;
- const int Length = Cycles * Period;
-
- vector<LogicDataSnapshot::EdgePair> edges;
-
- //----- Create a LogicDataSnapshot -----//
- sr_datafeed_logic logic;
- logic.unitsize = 1;
- logic.length = Length;
- logic.data = (uint64_t*)new uint8_t[Length];
- uint8_t *p = (uint8_t*)logic.data;
-
- for (int i = 0; i < Cycles; i++) {
- *p++ = 0xFF;
- for (int j = 1; j < Period; j++)
- *p++ = 0x00;
- }
-
- LogicDataSnapshot s(logic);
- delete[] (uint8_t*)logic.data;
-
- //----- Check the mip-map -----//
- // Check mip map level 0
- BOOST_CHECK_EQUAL(s._mip_map[0].length, 12);
- BOOST_CHECK_EQUAL(s._mip_map[0].data_length,
- LogicDataSnapshot::MipMapDataUnit);
- BOOST_REQUIRE(s._mip_map[0].data != NULL);
-
- for (unsigned int i = 0; i < s._mip_map[0].length;) {
- BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
- BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0xFF);
-
- for (int j = 1;
- i < s._mip_map[0].length &&
- j < Period/LogicDataSnapshot::MipMapScaleFactor; j++) {
- BOOST_TEST_MESSAGE(
- "Testing mip_map[0].data[" << i << "]");
- BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0x00);
- }
- }
-
- // Check the higher levels are all inactive
- for (unsigned int i = 1; i < LogicDataSnapshot::ScaleStepCount; i++) {
- const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
- BOOST_CHECK_EQUAL(m.length, 0);
- BOOST_CHECK_EQUAL(m.data_length, 0);
- BOOST_CHECK(m.data == NULL);
- }
-
- //----- Test get_subsampled_edges at reduced scale -----//
- s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
- BOOST_REQUIRE_EQUAL(edges.size(), Cycles + 2);
-
- BOOST_CHECK_EQUAL(0, false);
- for (unsigned int i = 1; i < edges.size(); i++)
- BOOST_CHECK_EQUAL(edges[i].second, false);
-}
-
-BOOST_AUTO_TEST_CASE(LongPulses)
-{
- const int Cycles = 3;
- const int Period = 64;
- const int PulseWidth = 16;
- const int Length = Cycles * Period;
-
- int j;
- vector<LogicDataSnapshot::EdgePair> edges;
-
- //----- Create a LogicDataSnapshot -----//
- sr_datafeed_logic logic;
- logic.unitsize = 8;
- logic.length = Length;
- logic.data = (uint64_t*)new uint64_t[Length];
- uint64_t *p = (uint64_t*)logic.data;
-
- for (int i = 0; i < Cycles; i++) {
- for (j = 0; j < PulseWidth; j++)
- *p++ = ~0;
- for (; j < Period; j++)
- *p++ = 0;
- }
-
- LogicDataSnapshot s(logic);
- delete[] (uint64_t*)logic.data;
-
- //----- Check the mip-map -----//
- // Check mip map level 0
- BOOST_CHECK_EQUAL(s._mip_map[0].length, 12);
- BOOST_CHECK_EQUAL(s._mip_map[0].data_length,
- LogicDataSnapshot::MipMapDataUnit);
- BOOST_REQUIRE(s._mip_map[0].data != NULL);
-
- for (unsigned int i = 0; i < s._mip_map[0].length;) {
- for (j = 0; i < s._mip_map[0].length && j < 2; j++) {
- BOOST_TEST_MESSAGE(
- "Testing mip_map[0].data[" << i << "]");
- BOOST_CHECK_EQUAL(s.get_subsample(0, i++), ~0);
- }
-
- for (; i < s._mip_map[0].length &&
- j < Period/LogicDataSnapshot::MipMapScaleFactor; j++) {
- BOOST_TEST_MESSAGE(
- "Testing mip_map[0].data[" << i << "]");
- BOOST_CHECK_EQUAL(s.get_subsample(0, i++), 0);
- }
- }
-
- // Check the higher levels are all inactive
- for (unsigned int i = 1; i < LogicDataSnapshot::ScaleStepCount; i++) {
- const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
- BOOST_CHECK_EQUAL(m.length, 0);
- BOOST_CHECK_EQUAL(m.data_length, 0);
- BOOST_CHECK(m.data == NULL);
- }
-
- //----- Test get_subsampled_edges at a full scale -----//
- s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
- BOOST_REQUIRE_EQUAL(edges.size(), Cycles * 2 + 1);
-
- for (int i = 0; i < Cycles; i++) {
- BOOST_CHECK_EQUAL(edges[i*2].first, i * Period);
- BOOST_CHECK_EQUAL(edges[i*2].second, true);
- BOOST_CHECK_EQUAL(edges[i*2+1].first, i * Period + PulseWidth);
- BOOST_CHECK_EQUAL(edges[i*2+1].second, false);
- }
-
- BOOST_CHECK_EQUAL(edges.back().first, Length-1);
- BOOST_CHECK_EQUAL(edges.back().second, false);
-
- //----- Test get_subsampled_edges at a simplified scale -----//
- edges.clear();
- s.get_subsampled_edges(edges, 0, Length-1, 17.0f, 2);
-
- BOOST_CHECK_EQUAL(edges[0].first, 0);
- BOOST_CHECK_EQUAL(edges[0].second, true);
- BOOST_CHECK_EQUAL(edges[1].first, 16);
- BOOST_CHECK_EQUAL(edges[1].second, false);
-
- for (int i = 1; i < Cycles; i++) {
- BOOST_CHECK_EQUAL(edges[i+1].first, i * Period);
- BOOST_CHECK_EQUAL(edges[i+1].second, false);
- }
-
- BOOST_CHECK_EQUAL(edges.back().first, Length-1);
- BOOST_CHECK_EQUAL(edges.back().second, false);
-}
-
-BOOST_AUTO_TEST_CASE(LisaMUsbHid)
-{
- /* This test was created from the beginning of the USB_DM signal in
- * sigrok-dumps-usb/lisa_m_usbhid/lisa_m_usbhid.sr
- */
-
- const int Edges[] = {
- 7028, 7033, 7036, 7041, 7044, 7049, 7053, 7066, 7073, 7079,
- 7086, 7095, 7103, 7108, 7111, 7116, 7119, 7124, 7136, 7141,
- 7148, 7162, 7500
- };
- const int Length = Edges[countof(Edges) - 1];
-
- bool state = false;
- int lastEdgePos = 0;
-
- //----- Create a LogicDataSnapshot -----//
- sr_datafeed_logic logic;
- logic.unitsize = 1;
- logic.length = Length;
- logic.data = new uint8_t[Length];
- uint8_t *data = (uint8_t*)logic.data;
-
- for (unsigned int i = 0; i < countof(Edges); i++) {
- const int edgePos = Edges[i];
- memset(&data[lastEdgePos], state ? 0x02 : 0,
- edgePos - lastEdgePos - 1);
-
- lastEdgePos = edgePos;
- state = !state;
- }
-
- LogicDataSnapshot s(logic);
- delete[] (uint64_t*)logic.data;
-
- vector<LogicDataSnapshot::EdgePair> edges;
-
-
- /* The trailing edge of the pulse train is falling in the source data.
- * Check this is always true at different scales
- */
-
- edges.clear();
- s.get_subsampled_edges(edges, 0, Length-1, 33.333332f, 1);
- BOOST_CHECK_EQUAL(edges[edges.size() - 2].second, false);
-}
-
-
-BOOST_AUTO_TEST_SUITE_END()