]> sigrok.org Git - libsigrok.git/blob - src/hardware/demo/protocol.c
demo: Add random analog signal generation
[libsigrok.git] / src / hardware / demo / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5  * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
6  * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7  * Copyright (C) 2015 Bartosz Golaszewski <bgolaszewski@baylibre.com>
8  * Copyright (C) 2019 Frank Stettner <frank-stettner@gmx.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #include <config.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <math.h>
28 #include <libsigrok/libsigrok.h>
29 #include "libsigrok-internal.h"
30 #include "protocol.h"
31
32 #define ANALOG_SAMPLES_PER_PERIOD 20
33
34 static const uint8_t pattern_sigrok[] = {
35         0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
36         0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
37         0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
38         0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
39         0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
40         0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
41         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42         0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 };
44
45 static const uint8_t pattern_squid[128][128 / 8] = {
46         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
47         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
48         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
49         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
50         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
51         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
52         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
53         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
54         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
55         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
56         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
57         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xe0, 0x00, },
58         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xe1, 0x01, },
59         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xe1, 0x01, },
60         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xe3, 0x03, },
61         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x03, },
62         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc3, 0x03, },
63         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xc7, 0x03, },
64         { 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xc7, 0x03, },
65         { 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x87, 0x03, },
66         { 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xc7, 0x03, },
67         { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xcf, 0x03, },
68         { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xcf, 0x03, },
69         { 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x03, },
70         { 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xff, 0x03, },
71         { 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0xfe, 0x01, },
72         { 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xfe, 0x01, },
73         { 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xfc, 0x00, },
74         { 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
75         { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
76         { 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
77         { 0x00, 0xc0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
78         { 0x00, 0x80, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xfe, 0xff, 0x03, },
79         { 0x00, 0x00, 0x07, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xfe, 0xff, 0x03, },
80         { 0x00, 0x00, 0x1c, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xfe, 0xff, 0x03, },
81         { 0x00, 0x00, 0x78, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xfe, 0xff, 0x03, },
82         { 0x00, 0x00, 0xe0, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xfe, 0xff, 0x03, },
83         { 0x00, 0x00, 0xc0, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
84         { 0x00, 0x00, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
85         { 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
86         { 0x00, 0x00, 0x00, 0xf8, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, },
87         { 0x00, 0x00, 0x00, 0xf0, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0xf0, 0x1f, 0x1c, },
88         { 0x00, 0x00, 0x00, 0xe0, 0x07, 0x70, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfc, 0x3f, 0x3c, },
89         { 0x80, 0x03, 0x00, 0xc0, 0x0f, 0xe0, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0x7f, 0x7c, },
90         { 0x00, 0x1e, 0x00, 0x00, 0x1f, 0xc0, 0x01, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0x7c, },
91         { 0x00, 0xf0, 0x01, 0x00, 0x7c, 0x80, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0xfe, 0xff, 0x7c, },
92         { 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x00, 0x07, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x3f, 0xf8, 0x78, },
93         { 0x00, 0x00, 0x3e, 0x00, 0xc0, 0x03, 0x0e, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xf0, 0xf0, },
94         { 0x00, 0x00, 0xf0, 0x07, 0x80, 0x07, 0x3c, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xf0, 0xf0, },
95         { 0x00, 0x00, 0x80, 0x3f, 0x00, 0x1e, 0x78, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xe0, 0xf0, },
96         { 0x00, 0x00, 0x00, 0xff, 0x00, 0x7c, 0xe0, 0x01, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xe0, 0xf0, },
97         { 0x00, 0x00, 0x00, 0xfc, 0x03, 0xf0, 0xc1, 0x07, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xf0, 0xf0, },
98         { 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xc0, 0x03, 0x1f, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xf0, 0x78, },
99         { 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x1f, 0xfc, 0xe0, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0x7f, },
100         { 0xf8, 0x03, 0x00, 0x00, 0xf0, 0x07, 0xfe, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0x7f, },
101         { 0x80, 0xff, 0x01, 0x00, 0x80, 0x3f, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfe, 0xff, 0x3f, },
102         { 0x00, 0xf0, 0xff, 0x07, 0x00, 0xfc, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfe, 0xff, 0x3f, },
103         { 0x00, 0x00, 0xfc, 0x7f, 0x00, 0xe0, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfe, 0xff, 0x1f, },
104         { 0x00, 0x00, 0xc0, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0xff, 0x03, },
105         { 0x00, 0x00, 0x00, 0xf8, 0xff, 0x07, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, },
106         { 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, },
107         { 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, },
108         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, },
109         { 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0x03, },
110         { 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0x03, },
111         { 0x00, 0x10, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x03, },
112         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x03, },
113         { 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x03, },
114         { 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x7c, 0x00, 0x00, },
115         { 0x00, 0x00, 0x00, 0xf8, 0xff, 0x07, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3c, 0x00, 0x00, },
116         { 0x00, 0x00, 0xc0, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x00, },
117         { 0x00, 0x00, 0xf8, 0x7f, 0x00, 0xe0, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x00, },
118         { 0x00, 0xf0, 0xff, 0x07, 0x00, 0xfc, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x0f, 0x00, 0x00, },
119         { 0x80, 0xff, 0x01, 0x00, 0x80, 0x3f, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0x01, 0x0f, 0x00, 0x00, },
120         { 0xf8, 0x03, 0x00, 0x00, 0xf0, 0x07, 0xfe, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, },
121         { 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x1f, 0xfc, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, },
122         { 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xc0, 0x07, 0x1f, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, },
123         { 0x00, 0x00, 0x00, 0xfc, 0x03, 0xf0, 0xc1, 0x07, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, },
124         { 0x00, 0x00, 0x00, 0xff, 0x00, 0x7c, 0xe0, 0x01, 0xf0, 0xff, 0xff, 0xff, 0x01, 0xe0, 0x1f, 0x00, },
125         { 0x00, 0x00, 0x80, 0x3f, 0x00, 0x1e, 0x78, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0xf0, 0x7f, 0x00, },
126         { 0x00, 0x00, 0xf0, 0x0f, 0x80, 0x07, 0x3c, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x01, 0xfc, 0xff, 0x00, },
127         { 0x00, 0x00, 0x3e, 0x00, 0xc0, 0x03, 0x0e, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x01, 0xfc, 0xff, 0x01, },
128         { 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x00, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0x01, },
129         { 0x00, 0xf0, 0x01, 0x00, 0x7c, 0x80, 0x03, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x03, },
130         { 0x00, 0x3e, 0x00, 0x00, 0x1f, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, 0x1f, 0xe0, 0x03, },
131         { 0x80, 0x03, 0x00, 0xc0, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xc0, 0x03, },
132         { 0x00, 0x00, 0x00, 0xe0, 0x07, 0x70, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x0f, 0xc0, 0x03, },
133         { 0x00, 0x00, 0x00, 0xf0, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x0f, 0x80, 0x03, },
134         { 0x00, 0x00, 0x00, 0xf8, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x03, },
135         { 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x03, },
136         { 0x00, 0x00, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x03, },
137         { 0x00, 0x00, 0xc0, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x03, },
138         { 0x00, 0x00, 0xe0, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, },
139         { 0x00, 0x00, 0x78, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, },
140         { 0x00, 0x00, 0x1c, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x00, },
141         { 0x00, 0x00, 0x06, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, },
142         { 0x00, 0x80, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, },
143         { 0x00, 0xc0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
144         { 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
145         { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
146         { 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, },
147         { 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, },
148         { 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, },
149         { 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, },
150         { 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, },
151         { 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, },
152         { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, },
153         { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, },
154         { 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, },
155         { 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, },
156         { 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, },
157         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x00, },
158         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, },
159         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x03, },
160         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x03, },
161         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x03, },
162         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x03, },
163         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, },
164         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
165         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
166         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
167         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
168         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
169         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
170         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
171         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
172         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
173         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
174 };
175
176 SR_PRIV void demo_generate_analog_pattern(struct dev_context *devc)
177 {
178         double t, frequency;
179         float amplitude, offset;
180         struct analog_pattern *pattern;
181         unsigned int num_samples, i;
182         float value;
183         int last_end;
184
185         num_samples = ANALOG_BUFSIZE / sizeof(float);
186         frequency = (double) devc->cur_samplerate / ANALOG_SAMPLES_PER_PERIOD;
187         amplitude = DEFAULT_ANALOG_AMPLITUDE;
188         offset = DEFAULT_ANALOG_OFFSET;
189
190         /*
191          * FIXME: We actually need only one period. A ringbuffer would be
192          * useful here.
193          * Make sure the number of samples we put out is an integer
194          * multiple of our period size.
195          */
196
197         /* PATTERN_SQUARE: */
198         sr_dbg("Generating %s pattern.", analog_pattern_str[PATTERN_SQUARE]);
199         pattern = g_malloc(sizeof(struct analog_pattern));
200         value = amplitude;
201         last_end = 0;
202         for (i = 0; i < num_samples; i++) {
203                 if (i % 5 == 0)
204                         value = -value;
205                 if (i % 10 == 0)
206                         last_end = i;
207                 pattern->data[i] = value + offset;
208         }
209         pattern->num_samples = last_end;
210         devc->analog_patterns[PATTERN_SQUARE] = pattern;
211
212         /* Readjusting num_samples for all other patterns. */
213         while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
214                 num_samples--;
215
216         /* PATTERN_SINE: */
217         sr_dbg("Generating %s pattern.", analog_pattern_str[PATTERN_SINE]);
218         pattern = g_malloc(sizeof(struct analog_pattern));
219         for (i = 0; i < num_samples; i++) {
220                 t = (double) i / (double) devc->cur_samplerate;
221                 pattern->data[i] = sin(2 * G_PI * frequency * t) * amplitude + offset;
222         }
223         pattern->num_samples = last_end;
224         devc->analog_patterns[PATTERN_SINE] = pattern;
225
226         /* PATTERN_TRIANGLE: */
227         sr_dbg("Generating %s pattern.", analog_pattern_str[PATTERN_TRIANGLE]);
228         pattern = g_malloc(sizeof(struct analog_pattern));
229         for (i = 0; i < num_samples; i++) {
230                 t = (double) i / (double) devc->cur_samplerate;
231                 pattern->data[i] = (2 / G_PI) * asin(sin(2 * G_PI * frequency * t)) *
232                         amplitude + offset;
233         }
234         pattern->num_samples = last_end;
235         devc->analog_patterns[PATTERN_TRIANGLE] = pattern;
236
237         /* PATTERN_SAWTOOTH: */
238         sr_dbg("Generating %s pattern.", analog_pattern_str[PATTERN_SAWTOOTH]);
239         pattern = g_malloc(sizeof(struct analog_pattern));
240         for (i = 0; i < num_samples; i++) {
241                 t = (double) i / (double) devc->cur_samplerate;
242                 pattern->data[i] = 2 * ((t * frequency) - floor(0.5f + t * frequency)) *
243                         amplitude + offset;
244         }
245         pattern->num_samples = last_end;
246         devc->analog_patterns[PATTERN_SAWTOOTH] = pattern;
247
248         /* PATTERN_ANALOG_RANDOM */
249         /* Data not filled here, will be generated in send_analog_packet(). */
250         pattern = g_malloc(sizeof(struct analog_pattern));
251         pattern->num_samples = last_end;
252         devc->analog_patterns[PATTERN_ANALOG_RANDOM] = pattern;
253 }
254
255 static uint64_t encode_number_to_gray(uint64_t nr)
256 {
257         return nr ^ (nr >> 1);
258 }
259
260 static void set_logic_data(uint64_t bits, uint8_t *data, size_t len)
261 {
262         while (len--) {
263                 *data++ = bits & 0xff;
264                 bits >>= 8;
265         }
266 }
267
268 static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
269 {
270         struct dev_context *devc;
271         uint64_t i, j;
272         uint8_t pat;
273         uint8_t *sample;
274         const uint8_t *image_col;
275         size_t col_count, col_height;
276         uint64_t gray;
277
278         devc = sdi->priv;
279
280         switch (devc->logic_pattern) {
281         case PATTERN_SIGROK:
282                 memset(devc->logic_data, 0x00, size);
283                 for (i = 0; i < size; i += devc->logic_unitsize) {
284                         for (j = 0; j < devc->logic_unitsize; j++) {
285                                 pat = pattern_sigrok[(devc->step + j) % sizeof(pattern_sigrok)] >> 1;
286                                 devc->logic_data[i + j] = ~pat;
287                         }
288                         devc->step++;
289                 }
290                 break;
291         case PATTERN_RANDOM:
292                 for (i = 0; i < size; i++)
293                         devc->logic_data[i] = (uint8_t)(rand() & 0xff);
294                 break;
295         case PATTERN_INC:
296                 for (i = 0; i < size; i++) {
297                         for (j = 0; j < devc->logic_unitsize; j++)
298                                 devc->logic_data[i + j] = devc->step;
299                         devc->step++;
300                 }
301                 break;
302         case PATTERN_WALKING_ONE:
303                 /* j contains the value of the highest bit */
304                 j = 1 << (devc->num_logic_channels - 1);
305                 for (i = 0; i < size; i++) {
306                         devc->logic_data[i] = devc->step;
307                         if (devc->step == 0)
308                                 devc->step = 1;
309                         else
310                                 if (devc->step == j)
311                                         devc->step = 0;
312                                 else
313                                         devc->step <<= 1;
314                 }
315                 break;
316         case PATTERN_WALKING_ZERO:
317                 /* Same as walking one, only with inverted output */
318                 /* j contains the value of the highest bit */
319                 j = 1 << (devc->num_logic_channels - 1);
320                 for (i = 0; i < size; i++) {
321                         devc->logic_data[i] = ~devc->step;
322                         if (devc->step == 0)
323                                 devc->step = 1;
324                         else
325                                 if (devc->step == j)
326                                         devc->step = 0;
327                                 else
328                                         devc->step <<= 1;
329                 }
330                 break;
331         case PATTERN_ALL_LOW:
332         case PATTERN_ALL_HIGH:
333                 /* These were set when the pattern mode was selected. */
334                 break;
335         case PATTERN_SQUID:
336                 memset(devc->logic_data, 0x00, size);
337                 col_count = ARRAY_SIZE(pattern_squid);
338                 col_height = ARRAY_SIZE(pattern_squid[0]);
339                 for (i = 0; i < size; i += devc->logic_unitsize) {
340                         sample = &devc->logic_data[i];
341                         image_col = pattern_squid[devc->step];
342                         for (j = 0; j < devc->logic_unitsize; j++) {
343                                 pat = image_col[j % col_height];
344                                 sample[j] = pat;
345                         }
346                         devc->step++;
347                         devc->step %= col_count;
348                 }
349                 break;
350         case PATTERN_GRAYCODE:
351                 for (i = 0; i < size; i += devc->logic_unitsize) {
352                         devc->step++;
353                         devc->step &= devc->all_logic_channels_mask;
354                         gray = encode_number_to_gray(devc->step);
355                         gray &= devc->all_logic_channels_mask;
356                         set_logic_data(gray, &devc->logic_data[i], devc->logic_unitsize);
357                 }
358                 break;
359         default:
360                 sr_err("Unknown pattern: %d.", devc->logic_pattern);
361                 break;
362         }
363 }
364
365 /*
366  * Fixup a memory image of generated logic data before it gets sent to
367  * the session's datafeed. Mask out content from disabled channels.
368  *
369  * TODO: Need we apply a channel map, and enforce a dense representation
370  * of the enabled channels' data?
371  */
372 static void logic_fixup_feed(struct dev_context *devc,
373                 struct sr_datafeed_logic *logic)
374 {
375         size_t fp_off;
376         uint8_t fp_mask;
377         size_t off, idx;
378         uint8_t *sample;
379
380         fp_off = devc->first_partial_logic_index;
381         fp_mask = devc->first_partial_logic_mask;
382         if (fp_off == logic->unitsize)
383                 return;
384
385         for (off = 0; off < logic->length; off += logic->unitsize) {
386                 sample = logic->data + off;
387                 sample[fp_off] &= fp_mask;
388                 for (idx = fp_off + 1; idx < logic->unitsize; idx++)
389                         sample[idx] = 0x00;
390         }
391 }
392
393 static void send_analog_packet(struct analog_gen *ag,
394                 struct sr_dev_inst *sdi, uint64_t *analog_sent,
395                 uint64_t analog_pos, uint64_t analog_todo)
396 {
397         struct sr_datafeed_packet packet;
398         struct dev_context *devc;
399         struct analog_pattern *pattern;
400         uint64_t sending_now, to_avg;
401         int ag_pattern_pos;
402         unsigned int i;
403         float amplitude, offset, value;
404         float *data;
405
406         if (!ag->ch || !ag->ch->enabled)
407                 return;
408
409         devc = sdi->priv;
410         packet.type = SR_DF_ANALOG;
411         packet.payload = &ag->packet;
412
413         pattern = devc->analog_patterns[ag->pattern];
414
415         ag->packet.meaning->channels = g_slist_append(NULL, ag->ch);
416         ag->packet.meaning->mq = ag->mq;
417         ag->packet.meaning->mqflags = ag->mq_flags;
418
419         /* Set a unit for the given quantity. */
420         if (ag->mq == SR_MQ_VOLTAGE)
421                 ag->packet.meaning->unit = SR_UNIT_VOLT;
422         else if (ag->mq == SR_MQ_CURRENT)
423                 ag->packet.meaning->unit = SR_UNIT_AMPERE;
424         else if (ag->mq == SR_MQ_RESISTANCE)
425                 ag->packet.meaning->unit = SR_UNIT_OHM;
426         else if (ag->mq == SR_MQ_CAPACITANCE)
427                 ag->packet.meaning->unit = SR_UNIT_FARAD;
428         else if (ag->mq == SR_MQ_TEMPERATURE)
429                 ag->packet.meaning->unit = SR_UNIT_CELSIUS;
430         else if (ag->mq == SR_MQ_FREQUENCY)
431                 ag->packet.meaning->unit = SR_UNIT_HERTZ;
432         else if (ag->mq == SR_MQ_DUTY_CYCLE)
433                 ag->packet.meaning->unit = SR_UNIT_PERCENTAGE;
434         else if (ag->mq == SR_MQ_CONTINUITY)
435                 ag->packet.meaning->unit = SR_UNIT_OHM;
436         else if (ag->mq == SR_MQ_PULSE_WIDTH)
437                 ag->packet.meaning->unit = SR_UNIT_PERCENTAGE;
438         else if (ag->mq == SR_MQ_CONDUCTANCE)
439                 ag->packet.meaning->unit = SR_UNIT_SIEMENS;
440         else if (ag->mq == SR_MQ_POWER)
441                 ag->packet.meaning->unit = SR_UNIT_WATT;
442         else if (ag->mq == SR_MQ_GAIN)
443                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
444         else if (ag->mq == SR_MQ_SOUND_PRESSURE_LEVEL)
445                 ag->packet.meaning->unit = SR_UNIT_DECIBEL_SPL;
446         else if (ag->mq == SR_MQ_CARBON_MONOXIDE)
447                 ag->packet.meaning->unit = SR_UNIT_CONCENTRATION;
448         else if (ag->mq == SR_MQ_RELATIVE_HUMIDITY)
449                 ag->packet.meaning->unit = SR_UNIT_HUMIDITY_293K;
450         else if (ag->mq == SR_MQ_TIME)
451                 ag->packet.meaning->unit = SR_UNIT_SECOND;
452         else if (ag->mq == SR_MQ_WIND_SPEED)
453                 ag->packet.meaning->unit = SR_UNIT_METER_SECOND;
454         else if (ag->mq == SR_MQ_PRESSURE)
455                 ag->packet.meaning->unit = SR_UNIT_HECTOPASCAL;
456         else if (ag->mq == SR_MQ_PARALLEL_INDUCTANCE)
457                 ag->packet.meaning->unit = SR_UNIT_HENRY;
458         else if (ag->mq == SR_MQ_PARALLEL_CAPACITANCE)
459                 ag->packet.meaning->unit = SR_UNIT_FARAD;
460         else if (ag->mq == SR_MQ_PARALLEL_RESISTANCE)
461                 ag->packet.meaning->unit = SR_UNIT_OHM;
462         else if (ag->mq == SR_MQ_SERIES_INDUCTANCE)
463                 ag->packet.meaning->unit = SR_UNIT_HENRY;
464         else if (ag->mq == SR_MQ_SERIES_CAPACITANCE)
465                 ag->packet.meaning->unit = SR_UNIT_FARAD;
466         else if (ag->mq == SR_MQ_SERIES_RESISTANCE)
467                 ag->packet.meaning->unit = SR_UNIT_OHM;
468         else if (ag->mq == SR_MQ_DISSIPATION_FACTOR)
469                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
470         else if (ag->mq == SR_MQ_QUALITY_FACTOR)
471                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
472         else if (ag->mq == SR_MQ_PHASE_ANGLE)
473                 ag->packet.meaning->unit = SR_UNIT_DEGREE;
474         else if (ag->mq == SR_MQ_DIFFERENCE)
475                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
476         else if (ag->mq == SR_MQ_COUNT)
477                 ag->packet.meaning->unit = SR_UNIT_PIECE;
478         else if (ag->mq == SR_MQ_POWER_FACTOR)
479                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
480         else if (ag->mq == SR_MQ_APPARENT_POWER)
481                 ag->packet.meaning->unit = SR_UNIT_VOLT_AMPERE;
482         else if (ag->mq == SR_MQ_MASS)
483                 ag->packet.meaning->unit = SR_UNIT_GRAM;
484         else if (ag->mq == SR_MQ_HARMONIC_RATIO)
485                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
486         else
487                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
488
489         if (!devc->avg) {
490                 ag_pattern_pos = analog_pos % pattern->num_samples;
491                 sending_now = MIN(analog_todo, pattern->num_samples - ag_pattern_pos);
492                 if (ag->amplitude != DEFAULT_ANALOG_AMPLITUDE ||
493                         ag->offset != DEFAULT_ANALOG_OFFSET ||
494                         ag->pattern == PATTERN_ANALOG_RANDOM) {
495                         /*
496                          * Amplitude or offset changed (or we are generating
497                          * random data), modify each sample.
498                          */
499                         if (ag->pattern == PATTERN_ANALOG_RANDOM) {
500                                 amplitude = ag->amplitude / 500.0;
501                                 offset = ag->offset - DEFAULT_ANALOG_OFFSET - ag->amplitude;
502                         } else {
503                                 amplitude = ag->amplitude / DEFAULT_ANALOG_AMPLITUDE;
504                                 offset = ag->offset - DEFAULT_ANALOG_OFFSET;
505                         }
506                         data = ag->packet.data;
507                         for (i = 0; i < sending_now; i++) {
508                                 if (ag->pattern == PATTERN_ANALOG_RANDOM)
509                                         data[i] = (rand() % 1000) * amplitude + offset;
510                                 else
511                                         data[i] = pattern->data[ag_pattern_pos + i] * amplitude + offset;
512                         }
513                 } else {
514                         /* Amplitude and offset unchanged, use the fast way. */
515                         ag->packet.data = pattern->data + ag_pattern_pos;
516                 }
517                 ag->packet.num_samples = sending_now;
518                 sr_session_send(sdi, &packet);
519
520                 /* Whichever channel group gets there first. */
521                 *analog_sent = MAX(*analog_sent, sending_now);
522         } else {
523                 ag_pattern_pos = analog_pos % pattern->num_samples;
524                 to_avg = MIN(analog_todo, pattern->num_samples - ag_pattern_pos);
525                 if (ag->pattern == PATTERN_ANALOG_RANDOM) {
526                         amplitude = ag->amplitude / 500.0;
527                         offset = ag->offset - DEFAULT_ANALOG_OFFSET - ag->amplitude;
528                 } else {
529                         amplitude = ag->amplitude / DEFAULT_ANALOG_AMPLITUDE;
530                         offset = ag->offset - DEFAULT_ANALOG_OFFSET;
531                 }
532
533                 for (i = 0; i < to_avg; i++) {
534                         if (ag->pattern == PATTERN_ANALOG_RANDOM)
535                                 value = (rand() % 1000) * amplitude + offset;
536                         else
537                                 value = *(pattern->data + ag_pattern_pos + i) * amplitude + offset;
538                         ag->avg_val = (ag->avg_val + value) / 2;
539                         ag->num_avgs++;
540                         /* Time to send averaged data? */
541                         if ((devc->avg_samples > 0) && (ag->num_avgs >= devc->avg_samples))
542                                 goto do_send;
543                 }
544
545                 if (devc->avg_samples == 0) {
546                         /*
547                          * We're averaging all the samples, so wait with
548                          * sending until the very end.
549                          */
550                         *analog_sent = ag->num_avgs;
551                         return;
552                 }
553
554 do_send:
555                 ag->packet.data = &ag->avg_val;
556                 ag->packet.num_samples = 1;
557
558                 sr_session_send(sdi, &packet);
559                 *analog_sent = ag->num_avgs;
560
561                 ag->num_avgs = 0;
562                 ag->avg_val = 0.0f;
563         }
564 }
565
566 /* Callback handling data */
567 SR_PRIV int demo_prepare_data(int fd, int revents, void *cb_data)
568 {
569         struct sr_dev_inst *sdi;
570         struct dev_context *devc;
571         struct sr_datafeed_packet packet;
572         struct sr_datafeed_logic logic;
573         struct analog_gen *ag;
574         GHashTableIter iter;
575         void *value;
576         uint64_t samples_todo, logic_done, analog_done, analog_sent, sending_now;
577         int64_t elapsed_us, limit_us, todo_us;
578         int64_t trigger_offset;
579         int pre_trigger_samples;
580
581         (void)fd;
582         (void)revents;
583
584         sdi = cb_data;
585         devc = sdi->priv;
586
587         /* Just in case. */
588         if (devc->cur_samplerate <= 0
589                         || (devc->num_logic_channels <= 0
590                         && devc->num_analog_channels <= 0)) {
591                 sr_dev_acquisition_stop(sdi);
592                 return G_SOURCE_CONTINUE;
593         }
594
595         /* What time span should we send samples for? */
596         elapsed_us = g_get_monotonic_time() - devc->start_us;
597         limit_us = 1000 * devc->limit_msec;
598         if (limit_us > 0 && limit_us < elapsed_us)
599                 todo_us = MAX(0, limit_us - devc->spent_us);
600         else
601                 todo_us = MAX(0, elapsed_us - devc->spent_us);
602
603         /* How many samples are outstanding since the last round? */
604         samples_todo = (todo_us * devc->cur_samplerate + G_USEC_PER_SEC - 1)
605                         / G_USEC_PER_SEC;
606
607         if (devc->limit_samples > 0) {
608                 if (devc->limit_samples < devc->sent_samples)
609                         samples_todo = 0;
610                 else if (devc->limit_samples - devc->sent_samples < samples_todo)
611                         samples_todo = devc->limit_samples - devc->sent_samples;
612         }
613
614         if (samples_todo == 0)
615                 return G_SOURCE_CONTINUE;
616
617         if (devc->limit_frames) {
618                 /* Never send more samples than a frame can fit... */
619                 samples_todo = MIN(samples_todo, SAMPLES_PER_FRAME);
620                 /* ...or than we need to finish the current frame. */
621                 samples_todo = MIN(samples_todo,
622                         SAMPLES_PER_FRAME - devc->sent_frame_samples);
623         }
624
625         /* Calculate the actual time covered by this run back from the sample
626          * count, rounded towards zero. This avoids getting stuck on a too-low
627          * time delta with no samples being sent due to round-off.
628          */
629         todo_us = samples_todo * G_USEC_PER_SEC / devc->cur_samplerate;
630
631         logic_done = devc->num_logic_channels > 0 ? 0 : samples_todo;
632         if (!devc->enabled_logic_channels)
633                 logic_done = samples_todo;
634
635         analog_done = devc->num_analog_channels > 0 ? 0 : samples_todo;
636         if (!devc->enabled_analog_channels)
637                 analog_done = samples_todo;
638
639         while (logic_done < samples_todo || analog_done < samples_todo) {
640                 /* Logic */
641                 if (logic_done < samples_todo) {
642                         sending_now = MIN(samples_todo - logic_done,
643                                         LOGIC_BUFSIZE / devc->logic_unitsize);
644                         logic_generator(sdi, sending_now * devc->logic_unitsize);
645                         /* Check for trigger and send pre-trigger data if needed */
646                         if (devc->stl && (!devc->trigger_fired)) {
647                                 trigger_offset = soft_trigger_logic_check(devc->stl,
648                                                 devc->logic_data, sending_now * devc->logic_unitsize,
649                                                 &pre_trigger_samples);
650                                 if (trigger_offset > -1) {
651                                         devc->trigger_fired = TRUE;
652                                         logic_done = pre_trigger_samples;
653                                 }
654                         } else
655                                 trigger_offset = 0;
656
657                         /* Send logic samples if needed */
658                         packet.type = SR_DF_LOGIC;
659                         packet.payload = &logic;
660                         logic.unitsize = devc->logic_unitsize;
661
662                         if (devc->stl) {
663                                 if (devc->trigger_fired && (trigger_offset < (int)sending_now)) {
664                                         /* Send after-trigger data */
665                                         logic.length = (sending_now - trigger_offset) * devc->logic_unitsize;
666                                         logic.data = devc->logic_data + trigger_offset * devc->logic_unitsize;
667                                         logic_fixup_feed(devc, &logic);
668                                         sr_session_send(sdi, &packet);
669                                         logic_done += sending_now - trigger_offset;
670                                         /* End acquisition */
671                                         sr_dbg("Triggered, stopping acquisition.");
672                                         sr_dev_acquisition_stop(sdi);
673                                         break;
674                                 } else {
675                                         /* Send nothing */
676                                         logic_done += sending_now;
677                                 }
678                         } else if (!devc->stl) {
679                                 /* No trigger defined, send logic samples */
680                                 logic.length = sending_now * devc->logic_unitsize;
681                                 logic.data = devc->logic_data;
682                                 logic_fixup_feed(devc, &logic);
683                                 sr_session_send(sdi, &packet);
684                                 logic_done += sending_now;
685                         }
686                 }
687
688                 /* Analog, one channel at a time */
689                 if (analog_done < samples_todo) {
690                         analog_sent = 0;
691
692                         g_hash_table_iter_init(&iter, devc->ch_ag);
693                         while (g_hash_table_iter_next(&iter, NULL, &value)) {
694                                 send_analog_packet(value, sdi, &analog_sent,
695                                                 devc->sent_samples + analog_done,
696                                                 samples_todo - analog_done);
697                         }
698                         analog_done += analog_sent;
699                 }
700         }
701
702         uint64_t min = MIN(logic_done, analog_done);
703         devc->sent_samples += min;
704         devc->sent_frame_samples += min;
705         devc->spent_us += todo_us;
706
707         if (devc->limit_frames && devc->sent_frame_samples >= SAMPLES_PER_FRAME) {
708                 std_session_send_frame_end(sdi);
709                 devc->sent_frame_samples = 0;
710                 devc->limit_frames--;
711                 if (!devc->limit_frames) {
712                         sr_dbg("Requested number of frames reached.");
713                         sr_dev_acquisition_stop(sdi);
714                 }
715         }
716
717         if ((devc->limit_samples > 0 && devc->sent_samples >= devc->limit_samples)
718                         || (limit_us > 0 && devc->spent_us >= limit_us)) {
719
720                 /* If we're averaging everything - now is the time to send data */
721                 if (devc->avg && devc->avg_samples == 0) {
722                         g_hash_table_iter_init(&iter, devc->ch_ag);
723                         while (g_hash_table_iter_next(&iter, NULL, &value)) {
724                                 ag = value;
725                                 packet.type = SR_DF_ANALOG;
726                                 packet.payload = &ag->packet;
727                                 ag->packet.data = &ag->avg_val;
728                                 ag->packet.num_samples = 1;
729                                 sr_session_send(sdi, &packet);
730                         }
731                 }
732                 sr_dbg("Requested number of samples reached.");
733                 sr_dev_acquisition_stop(sdi);
734         } else if (devc->limit_frames) {
735                 if (devc->sent_frame_samples == 0)
736                         std_session_send_frame_begin(sdi);
737         }
738
739         return G_SOURCE_CONTINUE;
740 }