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