2 * This file is part of the PulseView project.
4 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
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.
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.
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/>.
24 #include <boost/test/unit_test.hpp>
26 #include <pv/data/logicsegment.hpp>
28 using pv::data::LogicSegment
;
31 // Dummy, remove again when unit tests are fixed.
32 BOOST_AUTO_TEST_SUITE(DummyTestSuite
)
33 BOOST_AUTO_TEST_CASE(DummyTestCase
)
35 BOOST_CHECK_EQUAL(1, 1);
37 BOOST_AUTO_TEST_SUITE_END()
40 BOOST_AUTO_TEST_SUITE(LogicSegmentTest
)
42 void push_logic(LogicSegment
&s
, unsigned int length
, uint8_t value
)
44 sr_datafeed_logic logic
;
46 logic
.length
= length
;
47 logic
.data
= new uint8_t[length
];
48 memset(logic
.data
, value
, length
* logic
.unitsize
);
49 s
.append_payload(logic
);
50 delete[] (uint8_t*)logic
.data
;
53 BOOST_AUTO_TEST_CASE(Pow2
)
55 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(0, 0), 0);
56 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(1, 0), 1);
57 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(2, 0), 2);
60 LogicSegment::pow2_ceil(INT64_MIN
, 0), INT64_MIN
);
62 LogicSegment::pow2_ceil(INT64_MAX
, 0), INT64_MAX
);
64 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(0, 1), 0);
65 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(1, 1), 2);
66 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(2, 1), 2);
67 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(3, 1), 4);
70 BOOST_AUTO_TEST_CASE(Basic
)
72 // Create an empty LogicSegment object
73 sr_datafeed_logic logic
;
78 LogicSegment
s(logic
);
80 //----- Test LogicSegment::push_logic -----//
82 BOOST_CHECK(s
.get_sample_count() == 0);
83 for (unsigned int i
= 0; i
< LogicSegment::ScaleStepCount
; i
++)
85 const LogicSegment::MipMapLevel
&m
= s
.mip_map_
[i
];
86 BOOST_CHECK_EQUAL(m
.length
, 0);
87 BOOST_CHECK_EQUAL(m
.data_length
, 0);
88 BOOST_CHECK(m
.data
== nullptr);
91 // Push 8 samples of all zeros
94 BOOST_CHECK(s
.get_sample_count() == 8);
96 // There should not be enough samples to have a single mip map sample
97 for (unsigned int i
= 0; i
< LogicSegment::ScaleStepCount
; i
++)
99 const LogicSegment::MipMapLevel
&m
= s
.mip_map_
[i
];
100 BOOST_CHECK_EQUAL(m
.length
, 0);
101 BOOST_CHECK_EQUAL(m
.data_length
, 0);
102 BOOST_CHECK(m
.data
== nullptr);
105 // Push 8 samples of 0x11s to bring the total up to 16
106 push_logic(s
, 8, 0x11);
108 // There should now be enough data for exactly one sample
109 // in mip map level 0, and that sample should be 0
110 const LogicSegment::MipMapLevel
&m0
= s
.mip_map_
[0];
111 BOOST_CHECK_EQUAL(m0
.length
, 1);
112 BOOST_CHECK_EQUAL(m0
.data_length
, LogicSegment::MipMapDataUnit
);
113 BOOST_REQUIRE(m0
.data
!= nullptr);
114 BOOST_CHECK_EQUAL(((uint8_t*)m0
.data
)[0], 0x11);
116 // The higher levels should still be empty
117 for (unsigned int i
= 1; i
< LogicSegment::ScaleStepCount
; i
++)
119 const LogicSegment::MipMapLevel
&m
= s
.mip_map_
[i
];
120 BOOST_CHECK_EQUAL(m
.length
, 0);
121 BOOST_CHECK_EQUAL(m
.data_length
, 0);
122 BOOST_CHECK(m
.data
== nullptr);
125 // Push 240 samples of all zeros to bring the total up to 256
126 push_logic(s
, 240, 0);
128 BOOST_CHECK_EQUAL(m0
.length
, 16);
129 BOOST_CHECK_EQUAL(m0
.data_length
, LogicSegment::MipMapDataUnit
);
131 BOOST_CHECK_EQUAL(((uint8_t*)m0
.data
)[1], 0x11);
132 for (unsigned int i
= 2; i
< m0
.length
; i
++)
133 BOOST_CHECK_EQUAL(((uint8_t*)m0
.data
)[i
], 0);
135 const LogicSegment::MipMapLevel
&m1
= s
.mip_map_
[1];
136 BOOST_CHECK_EQUAL(m1
.length
, 1);
137 BOOST_CHECK_EQUAL(m1
.data_length
, LogicSegment::MipMapDataUnit
);
138 BOOST_REQUIRE(m1
.data
!= nullptr);
139 BOOST_CHECK_EQUAL(((uint8_t*)m1
.data
)[0], 0x11);
141 //----- Test LogicSegment::get_subsampled_edges -----//
143 // Test a full view at full zoom.
144 vector
<LogicSegment::EdgePair
> edges
;
145 s
.get_subsampled_edges(edges
, 0, 255, 1, 0);
146 BOOST_REQUIRE_EQUAL(edges
.size(), 4);
148 BOOST_CHECK_EQUAL(edges
[0].first
, 0);
149 BOOST_CHECK_EQUAL(edges
[1].first
, 8);
150 BOOST_CHECK_EQUAL(edges
[2].first
, 16);
151 BOOST_CHECK_EQUAL(edges
[3].first
, 256);
153 // Test a subset at high zoom
155 s
.get_subsampled_edges(edges
, 6, 17, 0.05f
, 0);
156 BOOST_REQUIRE_EQUAL(edges
.size(), 4);
158 BOOST_CHECK_EQUAL(edges
[0].first
, 6);
159 BOOST_CHECK_EQUAL(edges
[1].first
, 8);
160 BOOST_CHECK_EQUAL(edges
[2].first
, 16);
161 BOOST_CHECK_EQUAL(edges
[3].first
, 18);
164 BOOST_AUTO_TEST_CASE(LargeData
)
167 const unsigned int Length
= 1000000;
169 sr_datafeed_logic logic
;
171 logic
.length
= Length
;
172 logic
.data
= new uint8_t[Length
];
173 uint8_t *data
= (uint8_t*)logic
.data
;
175 for (unsigned int i
= 0; i
< Length
; i
++)
176 *data
++ = (uint8_t)(i
>> 8);
178 LogicSegment
s(logic
);
179 delete[] (uint8_t*)logic
.data
;
181 BOOST_CHECK(s
.get_sample_count() == Length
);
183 // Check mip map level 0
184 BOOST_CHECK_EQUAL(s
.mip_map_
[0].length
, 62500);
185 BOOST_CHECK_EQUAL(s
.mip_map_
[0].data_length
,
186 LogicSegment::MipMapDataUnit
);
187 BOOST_REQUIRE(s
.mip_map_
[0].data
!= nullptr);
190 for (unsigned int i
= 0; i
< s
.mip_map_
[0].length
;)
192 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i
<< "]");
194 const uint8_t sample
= (uint8_t)((i
*16) >> 8);
195 BOOST_CHECK_EQUAL(s
.get_subsample(0, i
++) & 0xFF,
196 prev_sample
^ sample
);
197 prev_sample
= sample
;
199 for (int j
= 1; i
< s
.mip_map_
[0].length
&& j
< 16; j
++)
201 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i
<< "]");
202 BOOST_CHECK_EQUAL(s
.get_subsample(0, i
++) & 0xFF, 0);
206 // Check mip map level 1
207 BOOST_CHECK_EQUAL(s
.mip_map_
[1].length
, 3906);
208 BOOST_CHECK_EQUAL(s
.mip_map_
[1].data_length
,
209 LogicSegment::MipMapDataUnit
);
210 BOOST_REQUIRE(s
.mip_map_
[1].data
!= nullptr);
213 for (unsigned int i
= 0; i
< s
.mip_map_
[1].length
; i
++)
215 BOOST_TEST_MESSAGE("Testing mip_map[1].data[" << i
<< "]");
217 const uint8_t sample
= i
;
218 const uint8_t expected
= sample
^ prev_sample
;
221 BOOST_CHECK_EQUAL(s
.get_subsample(1, i
) & 0xFF, expected
);
224 // Check mip map level 2
225 BOOST_CHECK_EQUAL(s
.mip_map_
[2].length
, 244);
226 BOOST_CHECK_EQUAL(s
.mip_map_
[2].data_length
,
227 LogicSegment::MipMapDataUnit
);
228 BOOST_REQUIRE(s
.mip_map_
[2].data
!= nullptr);
231 for (unsigned int i
= 0; i
< s
.mip_map_
[2].length
; i
++)
233 BOOST_TEST_MESSAGE("Testing mip_map[2].data[" << i
<< "]");
235 const uint8_t sample
= i
<< 4;
236 const uint8_t expected
= (sample
^ prev_sample
) | 0x0F;
237 prev_sample
= sample
;
239 BOOST_CHECK_EQUAL(s
.get_subsample(2, i
) & 0xFF, expected
);
242 // Check mip map level 3
243 BOOST_CHECK_EQUAL(s
.mip_map_
[3].length
, 15);
244 BOOST_CHECK_EQUAL(s
.mip_map_
[3].data_length
,
245 LogicSegment::MipMapDataUnit
);
246 BOOST_REQUIRE(s
.mip_map_
[3].data
!= nullptr);
248 for (unsigned int i
= 0; i
< s
.mip_map_
[3].length
; i
++)
249 BOOST_CHECK_EQUAL(*((uint8_t*)s
.mip_map_
[3].data
+ i
),
252 // Check the higher levels
253 for (unsigned int i
= 4; i
< LogicSegment::ScaleStepCount
; i
++)
255 const LogicSegment::MipMapLevel
&m
= s
.mip_map_
[i
];
256 BOOST_CHECK_EQUAL(m
.length
, 0);
257 BOOST_CHECK_EQUAL(m
.data_length
, 0);
258 BOOST_CHECK(m
.data
== nullptr);
261 //----- Test LogicSegment::get_subsampled_edges -----//
262 // Check in normal case
263 vector
<LogicSegment::EdgePair
> edges
;
264 s
.get_subsampled_edges(edges
, 0, Length
-1, 1, 7);
266 BOOST_CHECK_EQUAL(edges
.size(), 32);
268 for (unsigned int i
= 0; i
< edges
.size() - 1; i
++)
270 BOOST_CHECK_EQUAL(edges
[i
].first
, i
* 32768);
271 BOOST_CHECK_EQUAL(edges
[i
].second
, i
& 1);
274 BOOST_CHECK_EQUAL(edges
[31].first
, 1000000);
276 // Check in very low zoom case
278 s
.get_subsampled_edges(edges
, 0, Length
-1, 50e6f
, 7);
280 BOOST_CHECK_EQUAL(edges
.size(), 2);
283 BOOST_AUTO_TEST_CASE(Pulses
)
285 const int Cycles
= 3;
286 const int Period
= 64;
287 const int Length
= Cycles
* Period
;
289 vector
<LogicSegment::EdgePair
> edges
;
291 //----- Create a LogicSegment -----//
292 sr_datafeed_logic logic
;
294 logic
.length
= Length
;
295 logic
.data
= (uint64_t*)new uint8_t[Length
];
296 uint8_t *p
= (uint8_t*)logic
.data
;
298 for (int i
= 0; i
< Cycles
; i
++) {
300 for (int j
= 1; j
< Period
; j
++)
304 LogicSegment
s(logic
);
305 delete[] (uint8_t*)logic
.data
;
307 //----- Check the mip-map -----//
308 // Check mip map level 0
309 BOOST_CHECK_EQUAL(s
.mip_map_
[0].length
, 12);
310 BOOST_CHECK_EQUAL(s
.mip_map_
[0].data_length
,
311 LogicSegment::MipMapDataUnit
);
312 BOOST_REQUIRE(s
.mip_map_
[0].data
!= nullptr);
314 for (unsigned int i
= 0; i
< s
.mip_map_
[0].length
;) {
315 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i
<< "]");
316 BOOST_CHECK_EQUAL(s
.get_subsample(0, i
++) & 0xFF, 0xFF);
319 i
< s
.mip_map_
[0].length
&&
320 j
< Period
/LogicSegment::MipMapScaleFactor
; j
++) {
322 "Testing mip_map[0].data[" << i
<< "]");
323 BOOST_CHECK_EQUAL(s
.get_subsample(0, i
++) & 0xFF, 0x00);
327 // Check the higher levels are all inactive
328 for (unsigned int i
= 1; i
< LogicSegment::ScaleStepCount
; i
++) {
329 const LogicSegment::MipMapLevel
&m
= s
.mip_map_
[i
];
330 BOOST_CHECK_EQUAL(m
.length
, 0);
331 BOOST_CHECK_EQUAL(m
.data_length
, 0);
332 BOOST_CHECK(m
.data
== nullptr);
335 //----- Test get_subsampled_edges at reduced scale -----//
336 s
.get_subsampled_edges(edges
, 0, Length
-1, 16.0f
, 2);
337 BOOST_REQUIRE_EQUAL(edges
.size(), Cycles
+ 2);
339 BOOST_CHECK_EQUAL(0, false);
340 for (unsigned int i
= 1; i
< edges
.size(); i
++)
341 BOOST_CHECK_EQUAL(edges
[i
].second
, false);
344 BOOST_AUTO_TEST_CASE(LongPulses
)
346 const int Cycles
= 3;
347 const int Period
= 64;
348 const int PulseWidth
= 16;
349 const int Length
= Cycles
* Period
;
352 vector
<LogicSegment::EdgePair
> edges
;
354 //----- Create a LogicSegment -----//
355 sr_datafeed_logic logic
;
357 logic
.length
= Length
* 8;
358 logic
.data
= (uint64_t*)new uint64_t[Length
];
359 uint64_t *p
= (uint64_t*)logic
.data
;
361 for (int i
= 0; i
< Cycles
; i
++) {
362 for (j
= 0; j
< PulseWidth
; j
++)
364 for (; j
< Period
; j
++)
368 LogicSegment
s(logic
);
369 delete[] (uint64_t*)logic
.data
;
371 //----- Check the mip-map -----//
372 // Check mip map level 0
373 BOOST_CHECK_EQUAL(s
.mip_map_
[0].length
, 12);
374 BOOST_CHECK_EQUAL(s
.mip_map_
[0].data_length
,
375 LogicSegment::MipMapDataUnit
);
376 BOOST_REQUIRE(s
.mip_map_
[0].data
!= nullptr);
378 for (unsigned int i
= 0; i
< s
.mip_map_
[0].length
;) {
379 for (j
= 0; i
< s
.mip_map_
[0].length
&& j
< 2; j
++) {
381 "Testing mip_map[0].data[" << i
<< "]");
382 BOOST_CHECK_EQUAL(s
.get_subsample(0, i
++), ~0);
385 for (; i
< s
.mip_map_
[0].length
&&
386 j
< Period
/LogicSegment::MipMapScaleFactor
; j
++) {
388 "Testing mip_map[0].data[" << i
<< "]");
389 BOOST_CHECK_EQUAL(s
.get_subsample(0, i
++), 0);
393 // Check the higher levels are all inactive
394 for (unsigned int i
= 1; i
< LogicSegment::ScaleStepCount
; i
++) {
395 const LogicSegment::MipMapLevel
&m
= s
.mip_map_
[i
];
396 BOOST_CHECK_EQUAL(m
.length
, 0);
397 BOOST_CHECK_EQUAL(m
.data_length
, 0);
398 BOOST_CHECK(m
.data
== nullptr);
401 //----- Test get_subsampled_edges at a full scale -----//
402 s
.get_subsampled_edges(edges
, 0, Length
-1, 16.0f
, 2);
403 BOOST_REQUIRE_EQUAL(edges
.size(), Cycles
* 2 + 1);
405 for (int i
= 0; i
< Cycles
; i
++) {
406 BOOST_CHECK_EQUAL(edges
[i
*2].first
, i
* Period
);
407 BOOST_CHECK_EQUAL(edges
[i
*2].second
, true);
408 BOOST_CHECK_EQUAL(edges
[i
*2+1].first
, i
* Period
+ PulseWidth
);
409 BOOST_CHECK_EQUAL(edges
[i
*2+1].second
, false);
412 BOOST_CHECK_EQUAL(edges
.back().first
, Length
);
413 BOOST_CHECK_EQUAL(edges
.back().second
, false);
415 //----- Test get_subsampled_edges at a simplified scale -----//
417 s
.get_subsampled_edges(edges
, 0, Length
-1, 17.0f
, 2);
419 BOOST_CHECK_EQUAL(edges
[0].first
, 0);
420 BOOST_CHECK_EQUAL(edges
[0].second
, true);
421 BOOST_CHECK_EQUAL(edges
[1].first
, 16);
422 BOOST_CHECK_EQUAL(edges
[1].second
, false);
424 for (int i
= 1; i
< Cycles
; i
++) {
425 BOOST_CHECK_EQUAL(edges
[i
+1].first
, i
* Period
);
426 BOOST_CHECK_EQUAL(edges
[i
+1].second
, false);
429 BOOST_CHECK_EQUAL(edges
.back().first
, Length
);
430 BOOST_CHECK_EQUAL(edges
.back().second
, false);
433 BOOST_AUTO_TEST_CASE(LisaMUsbHid
)
435 /* This test was created from the beginning of the USB_DM signal in
436 * sigrok-dumps-usb/lisa_m_usbhid/lisa_m_usbhid.sr
439 const int Edges
[] = {
440 7028, 7033, 7036, 7041, 7044, 7049, 7053, 7066, 7073, 7079,
441 7086, 7095, 7103, 7108, 7111, 7116, 7119, 7124, 7136, 7141,
444 const int Length
= Edges
[countof(Edges
) - 1];
449 //----- Create a LogicSegment -----//
450 sr_datafeed_logic logic
;
452 logic
.length
= Length
;
453 logic
.data
= new uint8_t[Length
];
454 uint8_t *data
= (uint8_t*)logic
.data
;
456 for (unsigned int i
= 0; i
< countof(Edges
); i
++) {
457 const int edgePos
= Edges
[i
];
458 memset(&data
[lastEdgePos
], state
? 0x02 : 0,
459 edgePos
- lastEdgePos
- 1);
461 lastEdgePos
= edgePos
;
465 LogicSegment
s(logic
);
466 delete[] (uint64_t*)logic
.data
;
468 vector
<LogicSegment::EdgePair
> edges
;
471 /* The trailing edge of the pulse train is falling in the source data.
472 * Check this is always true at different scales
476 s
.get_subsampled_edges(edges
, 0, Length
-1, 33.333332f
, 1);
477 BOOST_CHECK_EQUAL(edges
[edges
.size() - 2].second
, false);
481 * This test checks the rendering of wide data (more than 8 channels)
482 * Probe signals are either all-high, or all-low, but are interleaved such that
483 * they would toggle during every sample if treated like 8 channels.
484 * The packet contains a large number of samples, so the mipmap generation kicks
487 * The signals should not toggle (have exactly two edges: the start and end)
489 BOOST_AUTO_TEST_CASE(WideData
)
491 const int Length
= 512<<10;
492 uint16_t *data
= new uint16_t[Length
];
494 sr_datafeed_logic logic
;
495 logic
.unitsize
= sizeof(data
[0]);
496 logic
.length
= Length
* sizeof(data
[0]);
499 for (int i
= 0; i
< Length
; i
++)
502 LogicSegment
s(logic
);
504 vector
<LogicSegment::EdgePair
> edges
;
507 s
.get_subsampled_edges(edges
, 0, Length
-1, 1, 0);
508 BOOST_CHECK_EQUAL(edges
.size(), 2);
511 s
.get_subsampled_edges(edges
, 0, Length
-1, 1, 8);
512 BOOST_CHECK_EQUAL(edges
.size(), 2);
519 * This test is a replica of sixteen.sr attached to Bug #33.
521 BOOST_AUTO_TEST_CASE(Sixteen
)
523 const int Length
= 8;
524 uint16_t data
[Length
];
526 sr_datafeed_logic logic
;
527 logic
.unitsize
= sizeof(data
[0]);
528 logic
.length
= Length
* sizeof(data
[0]);
531 for (int i
= 0; i
< Length
; i
++)
534 LogicSegment
s(logic
);
536 vector
<LogicSegment::EdgePair
> edges
;
537 s
.get_subsampled_edges(edges
, 0, 2, 0.0004, 1);
539 BOOST_CHECK_EQUAL(edges
.size(), 2);
542 BOOST_AUTO_TEST_SUITE_END()