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