]> sigrok.org Git - pulseview.git/blame_incremental - test/data/logicsegment.cpp
Replace non-ASCII characters
[pulseview.git] / test / data / logicsegment.cpp
... / ...
CommitLineData
1/*
2 * This file is part of the PulseView project.
3 *
4 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <extdef.h>
21
22#include <cstdint>
23
24#include <boost/test/unit_test.hpp>
25
26#include <pv/data/logicsegment.hpp>
27
28#if 0
29using pv::data::LogicSegment;
30using std::vector;
31#endif
32
33// Dummy, remove again when unit tests are fixed.
34BOOST_AUTO_TEST_SUITE(DummyTestSuite)
35BOOST_AUTO_TEST_CASE(DummyTestCase)
36{
37 BOOST_CHECK_EQUAL(1, 1);
38}
39BOOST_AUTO_TEST_SUITE_END()
40
41#if 0
42BOOST_AUTO_TEST_SUITE(LogicSegmentTest)
43
44void push_logic(LogicSegment &s, unsigned int length, uint8_t value)
45{
46 sr_datafeed_logic logic;
47 logic.unitsize = 1;
48 logic.length = length;
49 logic.data = new uint8_t[length];
50 memset(logic.data, value, length * logic.unitsize);
51 s.append_payload(logic);
52 delete[] (uint8_t*)logic.data;
53}
54
55BOOST_AUTO_TEST_CASE(Pow2)
56{
57 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(0, 0), 0);
58 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(1, 0), 1);
59 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(2, 0), 2);
60
61 BOOST_CHECK_EQUAL(
62 LogicSegment::pow2_ceil(INT64_MIN, 0), INT64_MIN);
63 BOOST_CHECK_EQUAL(
64 LogicSegment::pow2_ceil(INT64_MAX, 0), INT64_MAX);
65
66 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(0, 1), 0);
67 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(1, 1), 2);
68 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(2, 1), 2);
69 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(3, 1), 4);
70}
71
72BOOST_AUTO_TEST_CASE(Basic)
73{
74 // Create an empty LogicSegment object
75 sr_datafeed_logic logic;
76 logic.length = 0;
77 logic.unitsize = 1;
78 logic.data = nullptr;
79
80 LogicSegment s(logic);
81
82 //----- Test LogicSegment::push_logic -----//
83
84 BOOST_CHECK(s.get_sample_count() == 0);
85 for (unsigned int i = 0; i < LogicSegment::ScaleStepCount; i++)
86 {
87 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
88 BOOST_CHECK_EQUAL(m.length, 0);
89 BOOST_CHECK_EQUAL(m.data_length, 0);
90 BOOST_CHECK(m.data == nullptr);
91 }
92
93 // Push 8 samples of all zeros
94 push_logic(s, 8, 0);
95
96 BOOST_CHECK(s.get_sample_count() == 8);
97
98 // There should not be enough samples to have a single mip map sample
99 for (unsigned int i = 0; i < LogicSegment::ScaleStepCount; i++)
100 {
101 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
102 BOOST_CHECK_EQUAL(m.length, 0);
103 BOOST_CHECK_EQUAL(m.data_length, 0);
104 BOOST_CHECK(m.data == nullptr);
105 }
106
107 // Push 8 samples of 0x11s to bring the total up to 16
108 push_logic(s, 8, 0x11);
109
110 // There should now be enough data for exactly one sample
111 // in mip map level 0, and that sample should be 0
112 const LogicSegment::MipMapLevel &m0 = s.mip_map_[0];
113 BOOST_CHECK_EQUAL(m0.length, 1);
114 BOOST_CHECK_EQUAL(m0.data_length, LogicSegment::MipMapDataUnit);
115 BOOST_REQUIRE(m0.data != nullptr);
116 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[0], 0x11);
117
118 // The higher levels should still be empty
119 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++)
120 {
121 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
122 BOOST_CHECK_EQUAL(m.length, 0);
123 BOOST_CHECK_EQUAL(m.data_length, 0);
124 BOOST_CHECK(m.data == nullptr);
125 }
126
127 // Push 240 samples of all zeros to bring the total up to 256
128 push_logic(s, 240, 0);
129
130 BOOST_CHECK_EQUAL(m0.length, 16);
131 BOOST_CHECK_EQUAL(m0.data_length, LogicSegment::MipMapDataUnit);
132
133 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[1], 0x11);
134 for (unsigned int i = 2; i < m0.length; i++)
135 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[i], 0);
136
137 const LogicSegment::MipMapLevel &m1 = s.mip_map_[1];
138 BOOST_CHECK_EQUAL(m1.length, 1);
139 BOOST_CHECK_EQUAL(m1.data_length, LogicSegment::MipMapDataUnit);
140 BOOST_REQUIRE(m1.data != nullptr);
141 BOOST_CHECK_EQUAL(((uint8_t*)m1.data)[0], 0x11);
142
143 //----- Test LogicSegment::get_subsampled_edges -----//
144
145 // Test a full view at full zoom.
146 vector<LogicSegment::EdgePair> edges;
147 s.get_subsampled_edges(edges, 0, 255, 1, 0);
148 BOOST_REQUIRE_EQUAL(edges.size(), 4);
149
150 BOOST_CHECK_EQUAL(edges[0].first, 0);
151 BOOST_CHECK_EQUAL(edges[1].first, 8);
152 BOOST_CHECK_EQUAL(edges[2].first, 16);
153 BOOST_CHECK_EQUAL(edges[3].first, 256);
154
155 // Test a subset at high zoom
156 edges.clear();
157 s.get_subsampled_edges(edges, 6, 17, 0.05f, 0);
158 BOOST_REQUIRE_EQUAL(edges.size(), 4);
159
160 BOOST_CHECK_EQUAL(edges[0].first, 6);
161 BOOST_CHECK_EQUAL(edges[1].first, 8);
162 BOOST_CHECK_EQUAL(edges[2].first, 16);
163 BOOST_CHECK_EQUAL(edges[3].first, 18);
164}
165
166BOOST_AUTO_TEST_CASE(LargeData)
167{
168 uint8_t prev_sample;
169 const unsigned int Length = 1000000;
170
171 sr_datafeed_logic logic;
172 logic.unitsize = 1;
173 logic.length = Length;
174 logic.data = new uint8_t[Length];
175 uint8_t *data = (uint8_t*)logic.data;
176
177 for (unsigned int i = 0; i < Length; i++)
178 *data++ = (uint8_t)(i >> 8);
179
180 LogicSegment s(logic);
181 delete[] (uint8_t*)logic.data;
182
183 BOOST_CHECK(s.get_sample_count() == Length);
184
185 // Check mip map level 0
186 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 62500);
187 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
188 LogicSegment::MipMapDataUnit);
189 BOOST_REQUIRE(s.mip_map_[0].data != nullptr);
190
191 prev_sample = 0;
192 for (unsigned int i = 0; i < s.mip_map_[0].length;)
193 {
194 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
195
196 const uint8_t sample = (uint8_t)((i*16) >> 8);
197 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF,
198 prev_sample ^ sample);
199 prev_sample = sample;
200
201 for (int j = 1; i < s.mip_map_[0].length && j < 16; j++)
202 {
203 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
204 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0);
205 }
206 }
207
208 // Check mip map level 1
209 BOOST_CHECK_EQUAL(s.mip_map_[1].length, 3906);
210 BOOST_CHECK_EQUAL(s.mip_map_[1].data_length,
211 LogicSegment::MipMapDataUnit);
212 BOOST_REQUIRE(s.mip_map_[1].data != nullptr);
213
214 prev_sample = 0;
215 for (unsigned int i = 0; i < s.mip_map_[1].length; i++)
216 {
217 BOOST_TEST_MESSAGE("Testing mip_map[1].data[" << i << "]");
218
219 const uint8_t sample = i;
220 const uint8_t expected = sample ^ prev_sample;
221 prev_sample = i;
222
223 BOOST_CHECK_EQUAL(s.get_subsample(1, i) & 0xFF, expected);
224 }
225
226 // Check mip map level 2
227 BOOST_CHECK_EQUAL(s.mip_map_[2].length, 244);
228 BOOST_CHECK_EQUAL(s.mip_map_[2].data_length,
229 LogicSegment::MipMapDataUnit);
230 BOOST_REQUIRE(s.mip_map_[2].data != nullptr);
231
232 prev_sample = 0;
233 for (unsigned int i = 0; i < s.mip_map_[2].length; i++)
234 {
235 BOOST_TEST_MESSAGE("Testing mip_map[2].data[" << i << "]");
236
237 const uint8_t sample = i << 4;
238 const uint8_t expected = (sample ^ prev_sample) | 0x0F;
239 prev_sample = sample;
240
241 BOOST_CHECK_EQUAL(s.get_subsample(2, i) & 0xFF, expected);
242 }
243
244 // Check mip map level 3
245 BOOST_CHECK_EQUAL(s.mip_map_[3].length, 15);
246 BOOST_CHECK_EQUAL(s.mip_map_[3].data_length,
247 LogicSegment::MipMapDataUnit);
248 BOOST_REQUIRE(s.mip_map_[3].data != nullptr);
249
250 for (unsigned int i = 0; i < s.mip_map_[3].length; i++)
251 BOOST_CHECK_EQUAL(*((uint8_t*)s.mip_map_[3].data + i),
252 0xFF);
253
254 // Check the higher levels
255 for (unsigned int i = 4; i < LogicSegment::ScaleStepCount; i++)
256 {
257 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
258 BOOST_CHECK_EQUAL(m.length, 0);
259 BOOST_CHECK_EQUAL(m.data_length, 0);
260 BOOST_CHECK(m.data == nullptr);
261 }
262
263 //----- Test LogicSegment::get_subsampled_edges -----//
264 // Check in normal case
265 vector<LogicSegment::EdgePair> edges;
266 s.get_subsampled_edges(edges, 0, Length-1, 1, 7);
267
268 BOOST_CHECK_EQUAL(edges.size(), 32);
269
270 for (unsigned int i = 0; i < edges.size() - 1; i++)
271 {
272 BOOST_CHECK_EQUAL(edges[i].first, i * 32768);
273 BOOST_CHECK_EQUAL(edges[i].second, i & 1);
274 }
275
276 BOOST_CHECK_EQUAL(edges[31].first, 1000000);
277
278 // Check in very low zoom case
279 edges.clear();
280 s.get_subsampled_edges(edges, 0, Length-1, 50e6f, 7);
281
282 BOOST_CHECK_EQUAL(edges.size(), 2);
283}
284
285BOOST_AUTO_TEST_CASE(Pulses)
286{
287 const int Cycles = 3;
288 const int Period = 64;
289 const int Length = Cycles * Period;
290
291 vector<LogicSegment::EdgePair> edges;
292
293 //----- Create a LogicSegment -----//
294 sr_datafeed_logic logic;
295 logic.unitsize = 1;
296 logic.length = Length;
297 logic.data = (uint64_t*)new uint8_t[Length];
298 uint8_t *p = (uint8_t*)logic.data;
299
300 for (int i = 0; i < Cycles; i++) {
301 *p++ = 0xFF;
302 for (int j = 1; j < Period; j++)
303 *p++ = 0x00;
304 }
305
306 LogicSegment s(logic);
307 delete[] (uint8_t*)logic.data;
308
309 //----- Check the mip-map -----//
310 // Check mip map level 0
311 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 12);
312 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
313 LogicSegment::MipMapDataUnit);
314 BOOST_REQUIRE(s.mip_map_[0].data != nullptr);
315
316 for (unsigned int i = 0; i < s.mip_map_[0].length;) {
317 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
318 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0xFF);
319
320 for (int j = 1;
321 i < s.mip_map_[0].length &&
322 j < Period/LogicSegment::MipMapScaleFactor; j++) {
323 BOOST_TEST_MESSAGE(
324 "Testing mip_map[0].data[" << i << "]");
325 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0x00);
326 }
327 }
328
329 // Check the higher levels are all inactive
330 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++) {
331 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
332 BOOST_CHECK_EQUAL(m.length, 0);
333 BOOST_CHECK_EQUAL(m.data_length, 0);
334 BOOST_CHECK(m.data == nullptr);
335 }
336
337 //----- Test get_subsampled_edges at reduced scale -----//
338 s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
339 BOOST_REQUIRE_EQUAL(edges.size(), Cycles + 2);
340
341 BOOST_CHECK_EQUAL(0, false);
342 for (unsigned int i = 1; i < edges.size(); i++)
343 BOOST_CHECK_EQUAL(edges[i].second, false);
344}
345
346BOOST_AUTO_TEST_CASE(LongPulses)
347{
348 const int Cycles = 3;
349 const int Period = 64;
350 const int PulseWidth = 16;
351 const int Length = Cycles * Period;
352
353 int j;
354 vector<LogicSegment::EdgePair> edges;
355
356 //----- Create a LogicSegment -----//
357 sr_datafeed_logic logic;
358 logic.unitsize = 8;
359 logic.length = Length * 8;
360 logic.data = (uint64_t*)new uint64_t[Length];
361 uint64_t *p = (uint64_t*)logic.data;
362
363 for (int i = 0; i < Cycles; i++) {
364 for (j = 0; j < PulseWidth; j++)
365 *p++ = ~0;
366 for (; j < Period; j++)
367 *p++ = 0;
368 }
369
370 LogicSegment s(logic);
371 delete[] (uint64_t*)logic.data;
372
373 //----- Check the mip-map -----//
374 // Check mip map level 0
375 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 12);
376 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
377 LogicSegment::MipMapDataUnit);
378 BOOST_REQUIRE(s.mip_map_[0].data != nullptr);
379
380 for (unsigned int i = 0; i < s.mip_map_[0].length;) {
381 for (j = 0; i < s.mip_map_[0].length && j < 2; j++) {
382 BOOST_TEST_MESSAGE(
383 "Testing mip_map[0].data[" << i << "]");
384 BOOST_CHECK_EQUAL(s.get_subsample(0, i++), ~0);
385 }
386
387 for (; i < s.mip_map_[0].length &&
388 j < Period/LogicSegment::MipMapScaleFactor; j++) {
389 BOOST_TEST_MESSAGE(
390 "Testing mip_map[0].data[" << i << "]");
391 BOOST_CHECK_EQUAL(s.get_subsample(0, i++), 0);
392 }
393 }
394
395 // Check the higher levels are all inactive
396 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++) {
397 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
398 BOOST_CHECK_EQUAL(m.length, 0);
399 BOOST_CHECK_EQUAL(m.data_length, 0);
400 BOOST_CHECK(m.data == nullptr);
401 }
402
403 //----- Test get_subsampled_edges at a full scale -----//
404 s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
405 BOOST_REQUIRE_EQUAL(edges.size(), Cycles * 2 + 1);
406
407 for (int i = 0; i < Cycles; i++) {
408 BOOST_CHECK_EQUAL(edges[i*2].first, i * Period);
409 BOOST_CHECK_EQUAL(edges[i*2].second, true);
410 BOOST_CHECK_EQUAL(edges[i*2+1].first, i * Period + PulseWidth);
411 BOOST_CHECK_EQUAL(edges[i*2+1].second, false);
412 }
413
414 BOOST_CHECK_EQUAL(edges.back().first, Length);
415 BOOST_CHECK_EQUAL(edges.back().second, false);
416
417 //----- Test get_subsampled_edges at a simplified scale -----//
418 edges.clear();
419 s.get_subsampled_edges(edges, 0, Length-1, 17.0f, 2);
420
421 BOOST_CHECK_EQUAL(edges[0].first, 0);
422 BOOST_CHECK_EQUAL(edges[0].second, true);
423 BOOST_CHECK_EQUAL(edges[1].first, 16);
424 BOOST_CHECK_EQUAL(edges[1].second, false);
425
426 for (int i = 1; i < Cycles; i++) {
427 BOOST_CHECK_EQUAL(edges[i+1].first, i * Period);
428 BOOST_CHECK_EQUAL(edges[i+1].second, false);
429 }
430
431 BOOST_CHECK_EQUAL(edges.back().first, Length);
432 BOOST_CHECK_EQUAL(edges.back().second, false);
433}
434
435BOOST_AUTO_TEST_CASE(LisaMUsbHid)
436{
437 /* This test was created from the beginning of the USB_DM signal in
438 * sigrok-dumps-usb/lisa_m_usbhid/lisa_m_usbhid.sr
439 */
440
441 const int Edges[] = {
442 7028, 7033, 7036, 7041, 7044, 7049, 7053, 7066, 7073, 7079,
443 7086, 7095, 7103, 7108, 7111, 7116, 7119, 7124, 7136, 7141,
444 7148, 7162, 7500
445 };
446 const int Length = Edges[countof(Edges) - 1];
447
448 bool state = false;
449 int lastEdgePos = 0;
450
451 //----- Create a LogicSegment -----//
452 sr_datafeed_logic logic;
453 logic.unitsize = 1;
454 logic.length = Length;
455 logic.data = new uint8_t[Length];
456 uint8_t *data = (uint8_t*)logic.data;
457
458 for (unsigned int i = 0; i < countof(Edges); i++) {
459 const int edgePos = Edges[i];
460 memset(&data[lastEdgePos], state ? 0x02 : 0,
461 edgePos - lastEdgePos - 1);
462
463 lastEdgePos = edgePos;
464 state = !state;
465 }
466
467 LogicSegment s(logic);
468 delete[] (uint64_t*)logic.data;
469
470 vector<LogicSegment::EdgePair> edges;
471
472
473 /* The trailing edge of the pulse train is falling in the source data.
474 * Check this is always true at different scales
475 */
476
477 edges.clear();
478 s.get_subsampled_edges(edges, 0, Length-1, 33.333332f, 1);
479 BOOST_CHECK_EQUAL(edges[edges.size() - 2].second, false);
480}
481
482/*
483 * This test checks the rendering of wide data (more than 8 channels)
484 * Probe signals are either all-high, or all-low, but are interleaved such that
485 * they would toggle during every sample if treated like 8 channels.
486 * The packet contains a large number of samples, so the mipmap generation kicks
487 * in.
488 *
489 * The signals should not toggle (have exactly two edges: the start and end)
490 */
491BOOST_AUTO_TEST_CASE(WideData)
492{
493 const int Length = 512<<10;
494 uint16_t *data = new uint16_t[Length];
495
496 sr_datafeed_logic logic;
497 logic.unitsize = sizeof(data[0]);
498 logic.length = Length * sizeof(data[0]);
499 logic.data = data;
500
501 for (int i = 0; i < Length; i++)
502 data[i] = 0x0FF0;
503
504 LogicSegment s(logic);
505
506 vector<LogicSegment::EdgePair> edges;
507
508 edges.clear();
509 s.get_subsampled_edges(edges, 0, Length-1, 1, 0);
510 BOOST_CHECK_EQUAL(edges.size(), 2);
511
512 edges.clear();
513 s.get_subsampled_edges(edges, 0, Length-1, 1, 8);
514 BOOST_CHECK_EQUAL(edges.size(), 2);
515
516 // Cleanup
517 delete [] data;
518}
519
520/*
521 * This test is a replica of sixteen.sr attached to Bug #33.
522 */
523BOOST_AUTO_TEST_CASE(Sixteen)
524{
525 const int Length = 8;
526 uint16_t data[Length];
527
528 sr_datafeed_logic logic;
529 logic.unitsize = sizeof(data[0]);
530 logic.length = Length * sizeof(data[0]);
531 logic.data = data;
532
533 for (int i = 0; i < Length; i++)
534 data[i] = 0xFFFE;
535
536 LogicSegment s(logic);
537
538 vector<LogicSegment::EdgePair> edges;
539 s.get_subsampled_edges(edges, 0, 2, 0.0004, 1);
540
541 BOOST_CHECK_EQUAL(edges.size(), 2);
542}
543
544BOOST_AUTO_TEST_SUITE_END()
545#endif