]> sigrok.org Git - libsigrok.git/blob - src/hardware/demo/protocol.c
demo: Get/Set measurement quantity for the analog channels.
[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 analog_gen *ag, uint64_t sample_rate)
177 {
178         double t, frequency;
179         float value;
180         unsigned int num_samples, i;
181         int last_end;
182
183         sr_dbg("Generating %s pattern.", analog_pattern_str[ag->pattern]);
184
185         num_samples = ANALOG_BUFSIZE / sizeof(float);
186
187         switch (ag->pattern) {
188         case PATTERN_SQUARE:
189                 value = ag->amplitude;
190                 last_end = 0;
191                 for (i = 0; i < num_samples; i++) {
192                         if (i % 5 == 0)
193                                 value = -value;
194                         if (i % 10 == 0)
195                                 last_end = i;
196                         ag->pattern_data[i] = value;
197                 }
198                 ag->num_samples = last_end;
199                 break;
200         case PATTERN_SINE:
201                 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
202
203                 /* Make sure the number of samples we put out is an integer
204                  * multiple of our period size */
205                 /* FIXME we actually need only one period. A ringbuffer would be
206                  * useful here. */
207                 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
208                         num_samples--;
209
210                 for (i = 0; i < num_samples; i++) {
211                         t = (double) i / (double) sample_rate;
212                         ag->pattern_data[i] = ag->amplitude *
213                                                 sin(2 * G_PI * frequency * t);
214                 }
215
216                 ag->num_samples = num_samples;
217                 break;
218         case PATTERN_TRIANGLE:
219                 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
220
221                 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
222                         num_samples--;
223
224                 for (i = 0; i < num_samples; i++) {
225                         t = (double) i / (double) sample_rate;
226                         ag->pattern_data[i] = (2 * ag->amplitude / G_PI) *
227                                                 asin(sin(2 * G_PI * frequency * t));
228                 }
229
230                 ag->num_samples = num_samples;
231                 break;
232         case PATTERN_SAWTOOTH:
233                 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
234
235                 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
236                         num_samples--;
237
238                 for (i = 0; i < num_samples; i++) {
239                         t = (double) i / (double) sample_rate;
240                         ag->pattern_data[i] = 2 * ag->amplitude *
241                                                 ((t * frequency) - floor(0.5f + t * frequency));
242                 }
243
244                 ag->num_samples = num_samples;
245                 break;
246         }
247 }
248
249 static uint64_t encode_number_to_gray(uint64_t nr)
250 {
251         return nr ^ (nr >> 1);
252 }
253
254 static void set_logic_data(uint64_t bits, uint8_t *data, size_t len)
255 {
256         while (len--) {
257                 *data++ = bits & 0xff;
258                 bits >>= 8;
259         }
260 }
261
262 static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
263 {
264         struct dev_context *devc;
265         uint64_t i, j;
266         uint8_t pat;
267         uint8_t *sample;
268         const uint8_t *image_col;
269         size_t col_count, col_height;
270         uint64_t gray;
271
272         devc = sdi->priv;
273
274         switch (devc->logic_pattern) {
275         case PATTERN_SIGROK:
276                 memset(devc->logic_data, 0x00, size);
277                 for (i = 0; i < size; i += devc->logic_unitsize) {
278                         for (j = 0; j < devc->logic_unitsize; j++) {
279                                 pat = pattern_sigrok[(devc->step + j) % sizeof(pattern_sigrok)] >> 1;
280                                 devc->logic_data[i + j] = ~pat;
281                         }
282                         devc->step++;
283                 }
284                 break;
285         case PATTERN_RANDOM:
286                 for (i = 0; i < size; i++)
287                         devc->logic_data[i] = (uint8_t)(rand() & 0xff);
288                 break;
289         case PATTERN_INC:
290                 for (i = 0; i < size; i++) {
291                         for (j = 0; j < devc->logic_unitsize; j++)
292                                 devc->logic_data[i + j] = devc->step;
293                         devc->step++;
294                 }
295                 break;
296         case PATTERN_WALKING_ONE:
297                 /* j contains the value of the highest bit */
298                 j = 1 << (devc->num_logic_channels - 1);
299                 for (i = 0; i < size; i++) {
300                         devc->logic_data[i] = devc->step;
301                         if (devc->step == 0)
302                                 devc->step = 1;
303                         else
304                                 if (devc->step == j)
305                                         devc->step = 0;
306                                 else
307                                         devc->step <<= 1;
308                 }
309                 break;
310         case PATTERN_WALKING_ZERO:
311                 /* Same as walking one, only with inverted output */
312                 /* j contains the value of the highest bit */
313                 j = 1 << (devc->num_logic_channels - 1);
314                 for (i = 0; i < size; i++) {
315                         devc->logic_data[i] = ~devc->step;
316                         if (devc->step == 0)
317                                 devc->step = 1;
318                         else
319                                 if (devc->step == j)
320                                         devc->step = 0;
321                                 else
322                                         devc->step <<= 1;
323                 }
324                 break;
325         case PATTERN_ALL_LOW:
326         case PATTERN_ALL_HIGH:
327                 /* These were set when the pattern mode was selected. */
328                 break;
329         case PATTERN_SQUID:
330                 memset(devc->logic_data, 0x00, size);
331                 col_count = ARRAY_SIZE(pattern_squid);
332                 col_height = ARRAY_SIZE(pattern_squid[0]);
333                 for (i = 0; i < size; i += devc->logic_unitsize) {
334                         sample = &devc->logic_data[i];
335                         image_col = pattern_squid[devc->step];
336                         for (j = 0; j < devc->logic_unitsize; j++) {
337                                 pat = image_col[j % col_height];
338                                 sample[j] = pat;
339                         }
340                         devc->step++;
341                         devc->step %= col_count;
342                 }
343                 break;
344         case PATTERN_GRAYCODE:
345                 for (i = 0; i < size; i += devc->logic_unitsize) {
346                         devc->step++;
347                         devc->step &= devc->all_logic_channels_mask;
348                         gray = encode_number_to_gray(devc->step);
349                         gray &= devc->all_logic_channels_mask;
350                         set_logic_data(gray, &devc->logic_data[i], devc->logic_unitsize);
351                 }
352                 break;
353         default:
354                 sr_err("Unknown pattern: %d.", devc->logic_pattern);
355                 break;
356         }
357 }
358
359 /*
360  * Fixup a memory image of generated logic data before it gets sent to
361  * the session's datafeed. Mask out content from disabled channels.
362  *
363  * TODO: Need we apply a channel map, and enforce a dense representation
364  * of the enabled channels' data?
365  */
366 static void logic_fixup_feed(struct dev_context *devc,
367                 struct sr_datafeed_logic *logic)
368 {
369         size_t fp_off;
370         uint8_t fp_mask;
371         size_t off, idx;
372         uint8_t *sample;
373
374         fp_off = devc->first_partial_logic_index;
375         fp_mask = devc->first_partial_logic_mask;
376         if (fp_off == logic->unitsize)
377                 return;
378
379         for (off = 0; off < logic->length; off += logic->unitsize) {
380                 sample = logic->data + off;
381                 sample[fp_off] &= fp_mask;
382                 for (idx = fp_off + 1; idx < logic->unitsize; idx++)
383                         sample[idx] = 0x00;
384         }
385 }
386
387 static void send_analog_packet(struct analog_gen *ag,
388                 struct sr_dev_inst *sdi, uint64_t *analog_sent,
389                 uint64_t analog_pos, uint64_t analog_todo)
390 {
391         struct sr_datafeed_packet packet;
392         struct dev_context *devc;
393         uint64_t sending_now, to_avg;
394         int ag_pattern_pos;
395         unsigned int i;
396
397         if (!ag->ch || !ag->ch->enabled)
398                 return;
399
400         devc = sdi->priv;
401         packet.type = SR_DF_ANALOG;
402         packet.payload = &ag->packet;
403
404         ag->packet.meaning->channels = g_slist_append(NULL, ag->ch);
405         ag->packet.meaning->mq = ag->mq;
406         ag->packet.meaning->mqflags = ag->mq_flags;
407
408         /* Set a unit for the given quantity */
409         if (ag->mq == SR_MQ_VOLTAGE)
410                 ag->packet.meaning->unit = SR_UNIT_VOLT;
411         else if (ag->mq == SR_MQ_CURRENT)
412                 ag->packet.meaning->unit = SR_UNIT_AMPERE;
413         else if (ag->mq == SR_MQ_RESISTANCE)
414                 ag->packet.meaning->unit = SR_UNIT_OHM;
415         else if (ag->mq == SR_MQ_CAPACITANCE)
416                 ag->packet.meaning->unit = SR_UNIT_FARAD;
417         else if (ag->mq == SR_MQ_TEMPERATURE)
418                 ag->packet.meaning->unit = SR_UNIT_CELSIUS;
419         else if (ag->mq == SR_MQ_FREQUENCY)
420                 ag->packet.meaning->unit = SR_UNIT_HERTZ;
421         else if (ag->mq == SR_MQ_DUTY_CYCLE)
422                 ag->packet.meaning->unit = SR_UNIT_PERCENTAGE;
423         else if (ag->mq == SR_MQ_CONTINUITY)
424                 ag->packet.meaning->unit = SR_UNIT_OHM;
425         else if (ag->mq == SR_MQ_PULSE_WIDTH)
426                 ag->packet.meaning->unit = SR_UNIT_PERCENTAGE;
427         else if (ag->mq == SR_MQ_CONDUCTANCE)
428                 ag->packet.meaning->unit = SR_UNIT_SIEMENS;
429         else if (ag->mq == SR_MQ_POWER)
430                 ag->packet.meaning->unit = SR_UNIT_WATT;
431         else if (ag->mq == SR_MQ_GAIN)
432                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
433         else if (ag->mq == SR_MQ_SOUND_PRESSURE_LEVEL)
434                 ag->packet.meaning->unit = SR_UNIT_DECIBEL_SPL;
435         else if (ag->mq == SR_MQ_CARBON_MONOXIDE)
436                 ag->packet.meaning->unit = SR_UNIT_CONCENTRATION;
437         else if (ag->mq == SR_MQ_RELATIVE_HUMIDITY)
438                 ag->packet.meaning->unit = SR_UNIT_HUMIDITY_293K;
439         else if (ag->mq == SR_MQ_TIME)
440                 ag->packet.meaning->unit = SR_UNIT_SECOND;
441         else if (ag->mq == SR_MQ_WIND_SPEED)
442                 ag->packet.meaning->unit = SR_UNIT_METER_SECOND;
443         else if (ag->mq == SR_MQ_PRESSURE)
444                 ag->packet.meaning->unit = SR_UNIT_HECTOPASCAL;
445         else if (ag->mq == SR_MQ_PARALLEL_INDUCTANCE)
446                 ag->packet.meaning->unit = SR_UNIT_HENRY;
447         else if (ag->mq == SR_MQ_PARALLEL_CAPACITANCE)
448                 ag->packet.meaning->unit = SR_UNIT_FARAD;
449         else if (ag->mq == SR_MQ_PARALLEL_RESISTANCE)
450                 ag->packet.meaning->unit = SR_UNIT_OHM;
451         else if (ag->mq == SR_MQ_SERIES_INDUCTANCE)
452                 ag->packet.meaning->unit = SR_UNIT_HENRY;
453         else if (ag->mq == SR_MQ_SERIES_CAPACITANCE)
454                 ag->packet.meaning->unit = SR_UNIT_FARAD;
455         else if (ag->mq == SR_MQ_SERIES_RESISTANCE)
456                 ag->packet.meaning->unit = SR_UNIT_OHM;
457         else if (ag->mq == SR_MQ_DISSIPATION_FACTOR)
458                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
459         else if (ag->mq == SR_MQ_QUALITY_FACTOR)
460                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
461         else if (ag->mq == SR_MQ_PHASE_ANGLE)
462                 ag->packet.meaning->unit = SR_UNIT_DEGREE;
463         else if (ag->mq == SR_MQ_DIFFERENCE)
464                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
465         else if (ag->mq == SR_MQ_COUNT)
466                 ag->packet.meaning->unit = SR_UNIT_PIECE;
467         else if (ag->mq == SR_MQ_POWER_FACTOR)
468                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
469         else if (ag->mq == SR_MQ_APPARENT_POWER)
470                 ag->packet.meaning->unit = SR_UNIT_VOLT_AMPERE;
471         else if (ag->mq == SR_MQ_MASS)
472                 ag->packet.meaning->unit = SR_UNIT_GRAM;
473         else if (ag->mq == SR_MQ_HARMONIC_RATIO)
474                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
475         else
476                 ag->packet.meaning->unit = SR_UNIT_UNITLESS;
477
478         if (!devc->avg) {
479                 ag_pattern_pos = analog_pos % ag->num_samples;
480                 sending_now = MIN(analog_todo, ag->num_samples - ag_pattern_pos);
481                 ag->packet.data = ag->pattern_data + ag_pattern_pos;
482                 ag->packet.num_samples = sending_now;
483                 sr_session_send(sdi, &packet);
484
485                 /* Whichever channel group gets there first. */
486                 *analog_sent = MAX(*analog_sent, sending_now);
487         } else {
488                 ag_pattern_pos = analog_pos % ag->num_samples;
489                 to_avg = MIN(analog_todo, ag->num_samples - ag_pattern_pos);
490
491                 for (i = 0; i < to_avg; i++) {
492                         ag->avg_val = (ag->avg_val +
493                                         *(ag->pattern_data +
494                                           ag_pattern_pos + i)) / 2;
495                         ag->num_avgs++;
496                         /* Time to send averaged data? */
497                         if ((devc->avg_samples > 0) && (ag->num_avgs >= devc->avg_samples))
498                                 goto do_send;
499                 }
500
501                 if (devc->avg_samples == 0) {
502                         /* We're averaging all the samples, so wait with
503                          * sending until the very end.
504                          */
505                         *analog_sent = ag->num_avgs;
506                         return;
507                 }
508
509 do_send:
510                 ag->packet.data = &ag->avg_val;
511                 ag->packet.num_samples = 1;
512
513                 sr_session_send(sdi, &packet);
514                 *analog_sent = ag->num_avgs;
515
516                 ag->num_avgs = 0;
517                 ag->avg_val = 0.0f;
518         }
519 }
520
521 /* Callback handling data */
522 SR_PRIV int demo_prepare_data(int fd, int revents, void *cb_data)
523 {
524         struct sr_dev_inst *sdi;
525         struct dev_context *devc;
526         struct sr_datafeed_packet packet;
527         struct sr_datafeed_logic logic;
528         struct analog_gen *ag;
529         GHashTableIter iter;
530         void *value;
531         uint64_t samples_todo, logic_done, analog_done, analog_sent, sending_now;
532         int64_t elapsed_us, limit_us, todo_us;
533         int64_t trigger_offset;
534         int pre_trigger_samples;
535
536         (void)fd;
537         (void)revents;
538
539         sdi = cb_data;
540         devc = sdi->priv;
541
542         /* Just in case. */
543         if (devc->cur_samplerate <= 0
544                         || (devc->num_logic_channels <= 0
545                         && devc->num_analog_channels <= 0)) {
546                 sr_dev_acquisition_stop(sdi);
547                 return G_SOURCE_CONTINUE;
548         }
549
550         /* What time span should we send samples for? */
551         elapsed_us = g_get_monotonic_time() - devc->start_us;
552         limit_us = 1000 * devc->limit_msec;
553         if (limit_us > 0 && limit_us < elapsed_us)
554                 todo_us = MAX(0, limit_us - devc->spent_us);
555         else
556                 todo_us = MAX(0, elapsed_us - devc->spent_us);
557
558         /* How many samples are outstanding since the last round? */
559         samples_todo = (todo_us * devc->cur_samplerate + G_USEC_PER_SEC - 1)
560                         / G_USEC_PER_SEC;
561
562         if (devc->limit_samples > 0) {
563                 if (devc->limit_samples < devc->sent_samples)
564                         samples_todo = 0;
565                 else if (devc->limit_samples - devc->sent_samples < samples_todo)
566                         samples_todo = devc->limit_samples - devc->sent_samples;
567         }
568
569         if (samples_todo == 0)
570                 return G_SOURCE_CONTINUE;
571
572         if (devc->limit_frames) {
573                 /* Never send more samples than a frame can fit... */
574                 samples_todo = MIN(samples_todo, SAMPLES_PER_FRAME);
575                 /* ...or than we need to finish the current frame. */
576                 samples_todo = MIN(samples_todo,
577                         SAMPLES_PER_FRAME - devc->sent_frame_samples);
578         }
579
580         /* Calculate the actual time covered by this run back from the sample
581          * count, rounded towards zero. This avoids getting stuck on a too-low
582          * time delta with no samples being sent due to round-off.
583          */
584         todo_us = samples_todo * G_USEC_PER_SEC / devc->cur_samplerate;
585
586         logic_done = devc->num_logic_channels > 0 ? 0 : samples_todo;
587         if (!devc->enabled_logic_channels)
588                 logic_done = samples_todo;
589
590         analog_done = devc->num_analog_channels > 0 ? 0 : samples_todo;
591         if (!devc->enabled_analog_channels)
592                 analog_done = samples_todo;
593
594         while (logic_done < samples_todo || analog_done < samples_todo) {
595                 /* Logic */
596                 if (logic_done < samples_todo) {
597                         sending_now = MIN(samples_todo - logic_done,
598                                         LOGIC_BUFSIZE / devc->logic_unitsize);
599                         logic_generator(sdi, sending_now * devc->logic_unitsize);
600                         /* Check for trigger and send pre-trigger data if needed */
601                         if (devc->stl && (!devc->trigger_fired)) {
602                                 trigger_offset = soft_trigger_logic_check(devc->stl,
603                                                 devc->logic_data, sending_now * devc->logic_unitsize,
604                                                 &pre_trigger_samples);
605                                 if (trigger_offset > -1) {
606                                         devc->trigger_fired = TRUE;
607                                         logic_done = pre_trigger_samples;
608                                 }
609                         } else
610                                 trigger_offset = 0;
611
612                         /* Send logic samples if needed */
613                         packet.type = SR_DF_LOGIC;
614                         packet.payload = &logic;
615                         logic.unitsize = devc->logic_unitsize;
616
617                         if (devc->stl) {
618                                 if (devc->trigger_fired && (trigger_offset < (int)sending_now)) {
619                                         /* Send after-trigger data */
620                                         logic.length = (sending_now - trigger_offset) * devc->logic_unitsize;
621                                         logic.data = devc->logic_data + trigger_offset * devc->logic_unitsize;
622                                         logic_fixup_feed(devc, &logic);
623                                         sr_session_send(sdi, &packet);
624                                         logic_done += sending_now - trigger_offset;
625                                         /* End acquisition */
626                                         sr_dbg("Triggered, stopping acquisition.");
627                                         sr_dev_acquisition_stop(sdi);
628                                         break;
629                                 } else {
630                                         /* Send nothing */
631                                         logic_done += sending_now;
632                                 }
633                         } else if (!devc->stl) {
634                                 /* No trigger defined, send logic samples */
635                                 logic.length = sending_now * devc->logic_unitsize;
636                                 logic.data = devc->logic_data;
637                                 logic_fixup_feed(devc, &logic);
638                                 sr_session_send(sdi, &packet);
639                                 logic_done += sending_now;
640                         }
641                 }
642
643                 /* Analog, one channel at a time */
644                 if (analog_done < samples_todo) {
645                         analog_sent = 0;
646
647                         g_hash_table_iter_init(&iter, devc->ch_ag);
648                         while (g_hash_table_iter_next(&iter, NULL, &value)) {
649                                 send_analog_packet(value, sdi, &analog_sent,
650                                                 devc->sent_samples + analog_done,
651                                                 samples_todo - analog_done);
652                         }
653                         analog_done += analog_sent;
654                 }
655         }
656
657         uint64_t min = MIN(logic_done, analog_done);
658         devc->sent_samples += min;
659         devc->sent_frame_samples += min;
660         devc->spent_us += todo_us;
661
662         if (devc->limit_frames && devc->sent_frame_samples >= SAMPLES_PER_FRAME) {
663                 std_session_send_frame_end(sdi);
664                 devc->sent_frame_samples = 0;
665                 devc->limit_frames--;
666                 if (!devc->limit_frames) {
667                         sr_dbg("Requested number of frames reached.");
668                         sr_dev_acquisition_stop(sdi);
669                 }
670         }
671
672         if ((devc->limit_samples > 0 && devc->sent_samples >= devc->limit_samples)
673                         || (limit_us > 0 && devc->spent_us >= limit_us)) {
674
675                 /* If we're averaging everything - now is the time to send data */
676                 if (devc->avg && devc->avg_samples == 0) {
677                         g_hash_table_iter_init(&iter, devc->ch_ag);
678                         while (g_hash_table_iter_next(&iter, NULL, &value)) {
679                                 ag = value;
680                                 packet.type = SR_DF_ANALOG;
681                                 packet.payload = &ag->packet;
682                                 ag->packet.data = &ag->avg_val;
683                                 ag->packet.num_samples = 1;
684                                 sr_session_send(sdi, &packet);
685                         }
686                 }
687                 sr_dbg("Requested number of samples reached.");
688                 sr_dev_acquisition_stop(sdi);
689         } else if (devc->limit_frames) {
690                 if (devc->sent_frame_samples == 0)
691                         std_session_send_frame_begin(sdi);
692         }
693
694         return G_SOURCE_CONTINUE;
695 }