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