33 #include <libsigrokcxx/libsigrokcxx.hpp> 35 using std::lock_guard;
36 using std::recursive_mutex;
39 using std::shared_ptr;
53 unsigned int unit_size, uint64_t samplerate) :
54 Segment(segment_id, samplerate, unit_size),
56 last_append_sample_(0),
57 last_append_accumulator_(0),
65 lock_guard<recursive_mutex> lock(
mutex_);
73 shared_ptr<const Segment> ptr =
nullptr;
76 ptr = shared_from_this();
77 }
catch (std::exception&
e) {
81 return ptr ? std::dynamic_pointer_cast<
const LogicSegment>(ptr) :
nullptr;
96 void LogicSegment::downsampleTmain<uint8_t>(
const uint8_t*&in, uint8_t &acc, uint8_t &prev)
99 uint32_t prev32 = prev | prev << 8 | prev << 16 | prev << 24;
100 uint32_t acc32 = acc;
101 const uint32_t *in32 = (
const uint32_t*)in;
103 uint32_t sample32 = *in32++;
104 acc32 |= prev32 ^ sample32;
108 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 109 prev = (prev32 >> 24) & 0xff;
110 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 111 prev = prev32 & 0xff;
113 #error Endianness unknown 116 acc |= (acc32 >> 8) & 0xff;
117 acc |= (acc32 >> 16) & 0xff;
118 acc |= (acc32 >> 24) & 0xff;
119 in = (
const uint8_t*)in32;
123 void LogicSegment::downsampleTmain<uint16_t>(
const uint16_t*&in, uint16_t &acc, uint16_t &prev)
126 uint32_t prev32 = prev | prev << 16;
127 uint32_t acc32 = acc;
128 const uint32_t *in32 = (
const uint32_t*)in;
130 uint32_t sample32 = *in32++;
131 acc32 |= prev32 ^ sample32;
135 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 136 prev = (prev32 >> 16) & 0xffff;
137 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 138 prev = prev32 & 0xffff;
140 #error Endian unknown 142 acc |= acc32 & 0xffff;
143 acc |= (acc32 >> 16) & 0xffff;
144 in = (
const uint16_t*)in32;
150 const T *in = (
const T*)in_;
157 while (last_append_extra_ < MipMapScaleFactor && len > 0) {
159 acc |= prev ^ sample;
178 downsampleTmain<T>(in, acc, prev);
188 acc |= prev ^ sample;
197 out_ = (uint8_t *)out;
209 while (last_append_extra_ < MipMapScaleFactor && len > 0) {
212 acc |= prev ^ sample;
236 acc |= prev ^ sample;
250 acc |= prev ^ sample;
263 #ifdef HAVE_UNALIGNED_LITTLE_ENDIAN_ACCESS 264 return *(uint64_t*)ptr;
269 value |= ((uint64_t)ptr[7]) << 56;
272 value |= ((uint64_t)ptr[6]) << 48;
275 value |= ((uint64_t)ptr[5]) << 40;
278 value |= ((uint64_t)ptr[4]) << 32;
281 value |= ((uint32_t)ptr[3]) << 24;
284 value |= ((uint32_t)ptr[2]) << 16;
287 value |= ptr[1] << 8;
301 #ifdef HAVE_UNALIGNED_LITTLE_ENDIAN_ACCESS 302 *(uint64_t*)ptr = value;
306 ptr[7] = value >> 56;
309 ptr[6] = value >> 48;
312 ptr[5] = value >> 40;
315 ptr[4] = value >> 32;
318 ptr[3] = value >> 24;
321 ptr[2] = value >> 16;
338 assert((logic->data_length() %
unit_size_) == 0);
348 lock_guard<recursive_mutex> lock(
mutex_);
351 const uint64_t sample_count = data_size /
unit_size_;
358 if (sample_count > 1)
360 prev_sample_count + 1, prev_sample_count + 1 + sample_count);
363 prev_sample_count + 1, prev_sample_count + 1);
367 uint64_t data_size, vector<uint8_t>& destination)
370 destination.resize(data_size *
unit_size_, 0);
374 unsigned int index_byte_offs = index / 8;
375 uint8_t* output_data = destination.data() + index_byte_offs;
376 uint8_t* input_data = (uint8_t*)data;
378 for (uint64_t i = 0; i < data_size; i++) {
379 assert((i * unit_size_ + index_byte_offs) < destination.size());
380 *output_data |= (input_data[i] << index);
392 int64_t end_sample, uint8_t* dest)
const 394 assert(start_sample >= 0);
396 assert(end_sample >= 0);
397 assert(end_sample <= (int64_t)sample_count_);
398 assert(start_sample <= end_sample);
399 assert(dest !=
nullptr);
401 lock_guard<recursive_mutex> lock(
mutex_);
407 vector<EdgePair> &edges,
408 uint64_t start, uint64_t end,
409 float min_length,
int sig_index,
bool first_change_only)
411 uint64_t index = start;
416 assert(start <= end);
417 assert(min_length > 0);
418 assert(sig_index >= 0);
419 assert(sig_index < 64);
421 lock_guard<recursive_mutex> lock(
mutex_);
427 const uint64_t block_length = (uint64_t)
max(min_length, 1.0f);
428 const unsigned int min_level =
max((
int)floorf(logf(min_length) /
430 const uint64_t sig_mask = 1ULL << sig_index;
434 if (!first_change_only)
435 edges.emplace_back(index++, last_sample);
437 while (index + block_length <= end) {
450 for (; index < final_index &&
457 if (sample != last_sample) {
458 fast_forward =
false;
467 index =
pow2_ceil(index, min_level_scale_power);
473 if (last_sample != sample)
474 fast_forward =
false;
488 const uint64_t offset = index >> level_scale_power;
492 if (offset >=
mip_map_[level].length ||
507 index =
pow2_ceil(index + 1, level_scale_power);
517 const uint64_t offset = index >> level_scale_power;
521 if (offset >=
mip_map_[level].length ||
525 if (level == min_level)
532 index =
pow2_ceil(index + 1, level_scale_power);
540 for (; index < end; index++) {
542 if (sample != last_sample)
551 const int64_t final_index = index + block_length;
552 if (index + block_length > end)
557 edges.emplace_back(index, final_sample);
560 last_sample = final_sample;
562 if (first_change_only)
567 if (!first_change_only) {
569 if (last_sample != end_sample)
570 edges.emplace_back(end, end_sample);
571 edges.emplace_back(end + 1, end_sample);
576 uint64_t origin_sample,
float min_length,
int sig_index)
583 vector<EdgePair>* edges =
new vector<EdgePair>;
590 if (edges->size() == 2) {
598 dest.push_back(edges->back());
605 if (edges->size() == 0) {
610 dest.push_back(edges->front());
617 lock_guard<recursive_mutex> lock(
mutex_);
634 uint64_t prev_length;
637 uint64_t accumulator;
638 unsigned int diff_counter;
645 if (m0.
length == prev_length)
655 uint64_t len_sample = end_sample - start_sample;
657 while (len_sample > 0) {
661 count =
std::min(count, len_sample);
665 downsampleT<uint8_t>(src_ptr, dest_ptr, count);
667 downsampleT<uint16_t>(src_ptr, dest_ptr, count);
669 downsampleT<uint32_t>(src_ptr, dest_ptr, count);
671 downsampleT<uint64_t>(src_ptr, dest_ptr, count);
690 if (m.
length == prev_length)
696 const uint8_t* src_ptr = (uint8_t*)ml.
data +
698 const uint8_t *
const end_dest_ptr =
701 for (dest_ptr = (uint8_t*)m.
data +
703 dest_ptr < end_dest_ptr;
707 while (diff_counter-- > 0) {
739 const uint64_t p = UINT64_C(1) << power;
740 return (x + p - 1) / p * p;
void reallocate_mipmap_level(MipMapLevel &m)
void end_sample_iteration(SegmentDataIterator *it)
void get_raw_samples(uint64_t start, uint64_t count, uint8_t *dest) const
void downsampleGeneric(const uint8_t *in, uint8_t *&out, uint64_t len)
static const float LogMipMapScaleFactor
void append_payload(shared_ptr< sigrok::Logic > logic)
static const uint64_t MipMapDataUnit
static const int MipMapScalePower
std::shared_ptr< pv::data::Segment > SharedPtrToSegment
void notify_samples_added(shared_ptr< Segment > segment, uint64_t start_sample, uint64_t end_sample)
uint64_t last_append_extra_
T value(details::expression_node< T > *n)
shared_ptr< const LogicSegment > get_shared_ptr() const
LogicSegment(pv::data::Logic &owner, uint32_t segment_id, unsigned int unit_size, uint64_t samplerate)
SegmentDataIterator * begin_sample_iteration(uint64_t start)
T max(const T v0, const T v1)
uint64_t get_subsample(int level, uint64_t offset) const
uint8_t * get_iterator_value(SegmentDataIterator *it)
uint64_t get_sample_count() const
void downsampleTmain(const T *&in, T &acc, T &prev)
void append_subsignal_payload(unsigned int index, void *data, uint64_t data_size, vector< uint8_t > &destination)
void get_subsampled_edges(vector< EdgePair > &edges, uint64_t start, uint64_t end, float min_length, int sig_index, bool first_change_only=false)
uint64_t last_append_accumulator_
T min(const T v0, const T v1)
void continue_sample_iteration(SegmentDataIterator *it, uint64_t increase)
static const int MipMapScaleFactor
uint64_t get_unpacked_sample(uint64_t index) const
void append_payload_to_mipmap()
static uint64_t pow2_ceil(uint64_t x, unsigned int power)
void get_surrounding_edges(vector< EdgePair > &dest, uint64_t origin_sample, float min_length, int sig_index)
void append_samples(void *data, uint64_t samples)
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t x(y+z)
void get_samples(int64_t start_sample, int64_t end_sample, uint8_t *dest) const
void downsampleT(const uint8_t *in, uint8_t *&out, uint64_t len)
struct MipMapLevel mip_map_[ScaleStepCount]
void pack_sample(uint8_t *ptr, uint64_t value)
uint64_t last_append_sample_
unsigned int num_channels() const
static const unsigned int ScaleStepCount
uint64_t get_iterator_valid_length(SegmentDataIterator *it)
uint64_t unpack_sample(const uint8_t *ptr) const
atomic< uint64_t > sample_count_