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