]> sigrok.org Git - libsigrok.git/blame - src/hardware/demo/demo.c
hantek-dso: File naming consistency changes.
[libsigrok.git] / src / hardware / demo / demo.c
CommitLineData
6239c175 1/*
50985c20 2 * This file is part of the libsigrok project.
6239c175
UH
3 *
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
fc96e6f8 5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
c216d623 6 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7a8a1aba 7 * Copyright (C) 2015 Bartosz Golaszewski <bgolaszewski@baylibre.com>
6239c175
UH
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
6ec6c43b 24#include <config.h>
6239c175
UH
25#include <stdlib.h>
26#include <string.h>
4374219b 27#include <math.h>
c1aae900 28#include <libsigrok/libsigrok.h>
45c59c8b 29#include "libsigrok-internal.h"
6239c175 30
3544f848 31#define LOG_PREFIX "demo"
92bcedf6 32
d9251a2c
UH
33#define DEFAULT_NUM_LOGIC_CHANNELS 8
34#define DEFAULT_NUM_ANALOG_CHANNELS 4
c03ed397 35
8b2d41ed 36/* The size in bytes of chunks to send through the session bus. */
d9251a2c 37#define LOGIC_BUFSIZE 4096
8b2d41ed 38/* Size of the analog pattern space per channel. */
d9251a2c 39#define ANALOG_BUFSIZE 4096
2474d87e 40
d9251a2c
UH
41#define DEFAULT_ANALOG_AMPLITUDE 10
42#define ANALOG_SAMPLES_PER_PERIOD 20
4374219b 43
2388ae86 44/* Logic patterns we can generate. */
e15f48c2 45enum {
0d31276b 46 /**
ba7dd8bb 47 * Spells "sigrok" across 8 channels using '0's (with '1's as
61c39f54 48 * "background") when displayed using the 'bits' output format.
95035832 49 * The pattern is repeated every 8 channels, shifted to the right
c07f60e7 50 * in time by one bit.
0d31276b 51 */
c8f4624d 52 PATTERN_SIGROK,
0d31276b 53
ba7dd8bb 54 /** Pseudo-random values on all channels. */
c8f4624d 55 PATTERN_RANDOM,
0d31276b
UH
56
57 /**
95035832 58 * Incrementing number across 8 channels. The pattern is repeated
ba7dd8bb 59 * every 8 channels, shifted to the right in time by one bit.
0d31276b 60 */
c8f4624d 61 PATTERN_INC,
c03ed397 62
ba7dd8bb 63 /** All channels have a low logic state. */
c03ed397
UH
64 PATTERN_ALL_LOW,
65
ba7dd8bb 66 /** All channels have a high logic state. */
c03ed397 67 PATTERN_ALL_HIGH,
2388ae86 68};
8b2d41ed 69
2388ae86
BV
70/* Analog patterns we can generate. */
71enum {
8b2d41ed
BV
72 /**
73 * Square wave.
74 */
75 PATTERN_SQUARE,
4374219b 76 PATTERN_SINE,
091c9621 77 PATTERN_TRIANGLE,
9f54e0e8 78 PATTERN_SAWTOOTH,
e15f48c2 79};
85b5af06 80
8b2d41ed 81static const char *logic_pattern_str[] = {
61c39f54
BV
82 "sigrok",
83 "random",
84 "incremental",
85 "all-low",
86 "all-high",
87};
88
8b2d41ed
BV
89static const char *analog_pattern_str[] = {
90 "square",
4374219b 91 "sine",
091c9621 92 "triangle",
9f54e0e8 93 "sawtooth",
8b2d41ed
BV
94};
95
96struct analog_gen {
97 int pattern;
dddabe37 98 float amplitude;
8b2d41ed
BV
99 float pattern_data[ANALOG_BUFSIZE];
100 unsigned int num_samples;
4b770103
UH
101 struct sr_datafeed_analog packet;
102 struct sr_analog_encoding encoding;
103 struct sr_analog_meaning meaning;
104 struct sr_analog_spec spec;
7a8a1aba
BG
105 float avg_val; /* Average value */
106 unsigned num_avgs; /* Number of samples averaged */
8b2d41ed
BV
107};
108
b4750a3a
BV
109/* Private, per-device-instance driver context. */
110struct dev_context {
a7684294
JH
111 uint64_t cur_samplerate;
112 uint64_t limit_samples;
113 uint64_t limit_msec;
a49a320d
DE
114 uint64_t sent_samples;
115 int64_t start_us;
116 int64_t spent_us;
61c39f54 117 uint64_t step;
8b2d41ed 118 /* Logic */
ba7dd8bb 119 int32_t num_logic_channels;
c07f60e7 120 unsigned int logic_unitsize;
660e398f 121 /* There is only ever one logic channel group, so its pattern goes here. */
c07f60e7
BV
122 uint8_t logic_pattern;
123 unsigned char logic_data[LOGIC_BUFSIZE];
8b2d41ed 124 /* Analog */
ba7dd8bb 125 int32_t num_analog_channels;
49224c28 126 GHashTable *ch_ag;
7a8a1aba
BG
127 gboolean avg; /* True if averaging is enabled */
128 uint64_t avg_samples;
c07f60e7
BV
129};
130
1e4a7cac
BV
131static const uint32_t drvopts[] = {
132 SR_CONF_DEMO_DEV,
133 SR_CONF_LOGIC_ANALYZER,
134 SR_CONF_OSCILLOSCOPE,
135};
136
584560f1 137static const uint32_t scanopts[] = {
3f239f08
UH
138 SR_CONF_NUM_LOGIC_CHANNELS,
139 SR_CONF_NUM_ANALOG_CHANNELS,
e15f48c2 140};
85b5af06 141
390795c0 142static const uint32_t devopts[] = {
e91bb0a6 143 SR_CONF_CONTINUOUS,
5827f61b
BV
144 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
145 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
390795c0 146 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
7a8a1aba
BG
147 SR_CONF_AVERAGING | SR_CONF_GET | SR_CONF_SET,
148 SR_CONF_AVG_SAMPLES | SR_CONF_GET | SR_CONF_SET,
390795c0
BV
149};
150
151static const uint32_t devopts_cg_logic[] = {
f12d9979 152 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
49224c28
BV
153};
154
e2b99f04
SA
155static const uint32_t devopts_cg_analog_group[] = {
156 SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
157};
158
159static const uint32_t devopts_cg_analog_channel[] = {
f12d9979
BV
160 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
161 SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
7a1da331
BV
162};
163
d00088ca
BV
164static const uint64_t samplerates[] = {
165 SR_HZ(1),
166 SR_GHZ(1),
167 SR_HZ(1),
4bfbf9fc
BV
168};
169
329733d9 170static const uint8_t pattern_sigrok[] = {
917e0e71
BV
171 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
172 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
173 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
174 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
175 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
176 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179};
180
695dc859 181static int dev_acquisition_stop(struct sr_dev_inst *sdi);
6239c175 182
49224c28 183static void generate_analog_pattern(struct analog_gen *ag, uint64_t sample_rate)
8b2d41ed 184{
4374219b 185 double t, frequency;
8b2d41ed
BV
186 float value;
187 unsigned int num_samples, i;
188 int last_end;
189
49224c28 190 sr_dbg("Generating %s pattern.", analog_pattern_str[ag->pattern]);
4374219b 191
49224c28 192 num_samples = ANALOG_BUFSIZE / sizeof(float);
8b2d41ed 193
4374219b 194 switch (ag->pattern) {
8b2d41ed 195 case PATTERN_SQUARE:
dddabe37 196 value = ag->amplitude;
8b2d41ed
BV
197 last_end = 0;
198 for (i = 0; i < num_samples; i++) {
199 if (i % 5 == 0)
200 value = -value;
201 if (i % 10 == 0)
3772c049 202 last_end = i;
8b2d41ed
BV
203 ag->pattern_data[i] = value;
204 }
205 ag->num_samples = last_end;
206 break;
4374219b 207 case PATTERN_SINE:
9d156555 208 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
4374219b
DJ
209
210 /* Make sure the number of samples we put out is an integer
211 * multiple of our period size */
212 /* FIXME we actually need only one period. A ringbuffer would be
f3f19d11 213 * useful here. */
4374219b
DJ
214 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
215 num_samples--;
216
217 for (i = 0; i < num_samples; i++) {
218 t = (double) i / (double) sample_rate;
dddabe37 219 ag->pattern_data[i] = ag->amplitude *
bbc42811 220 sin(2 * G_PI * frequency * t);
4374219b
DJ
221 }
222
091c9621
DJ
223 ag->num_samples = num_samples;
224 break;
091c9621 225 case PATTERN_TRIANGLE:
9d156555 226 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
091c9621
DJ
227
228 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
229 num_samples--;
230
231 for (i = 0; i < num_samples; i++) {
232 t = (double) i / (double) sample_rate;
bbc42811
AJ
233 ag->pattern_data[i] = (2 * ag->amplitude / G_PI) *
234 asin(sin(2 * G_PI * frequency * t));
091c9621
DJ
235 }
236
9f54e0e8
DJ
237 ag->num_samples = num_samples;
238 break;
9f54e0e8 239 case PATTERN_SAWTOOTH:
9d156555 240 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
9f54e0e8
DJ
241
242 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
243 num_samples--;
244
245 for (i = 0; i < num_samples; i++) {
246 t = (double) i / (double) sample_rate;
dddabe37 247 ag->pattern_data[i] = 2 * ag->amplitude *
9f54e0e8
DJ
248 ((t * frequency) - floor(0.5f + t * frequency));
249 }
250
4374219b
DJ
251 ag->num_samples = num_samples;
252 break;
8b2d41ed
BV
253 }
254}
255
4f840ce9 256static GSList *scan(struct sr_dev_driver *di, GSList *options)
6239c175 257{
33ef7573 258 struct dev_context *devc;
c07f60e7 259 struct sr_dev_inst *sdi;
ba7dd8bb 260 struct sr_channel *ch;
49224c28 261 struct sr_channel_group *cg, *acg;
c07f60e7 262 struct sr_config *src;
8b2d41ed 263 struct analog_gen *ag;
43376f33 264 GSList *l;
ba7dd8bb
UH
265 int num_logic_channels, num_analog_channels, pattern, i;
266 char channel_name[16];
067d0716 267
3f239f08
UH
268 num_logic_channels = DEFAULT_NUM_LOGIC_CHANNELS;
269 num_analog_channels = DEFAULT_NUM_ANALOG_CHANNELS;
c07f60e7
BV
270 for (l = options; l; l = l->next) {
271 src = l->data;
272 switch (src->key) {
3f239f08 273 case SR_CONF_NUM_LOGIC_CHANNELS:
ba7dd8bb 274 num_logic_channels = g_variant_get_int32(src->data);
c07f60e7 275 break;
3f239f08 276 case SR_CONF_NUM_ANALOG_CHANNELS:
ba7dd8bb 277 num_analog_channels = g_variant_get_int32(src->data);
c07f60e7
BV
278 break;
279 }
280 }
85b5af06 281
aac29cc1 282 sdi = g_malloc0(sizeof(struct sr_dev_inst));
45884333 283 sdi->status = SR_ST_INACTIVE;
4b664cd6 284 sdi->model = g_strdup("Demo device");
e15f48c2 285
a49a320d 286 devc = g_malloc0(sizeof(struct dev_context));
8b2d41ed 287 devc->cur_samplerate = SR_KHZ(200);
ba7dd8bb
UH
288 devc->num_logic_channels = num_logic_channels;
289 devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
8b2d41ed 290 devc->logic_pattern = PATTERN_SIGROK;
ba7dd8bb 291 devc->num_analog_channels = num_analog_channels;
8b2d41ed 292
f18e0db3
LPC
293 if (num_logic_channels > 0) {
294 /* Logic channels, all in one channel group. */
295 cg = g_malloc0(sizeof(struct sr_channel_group));
296 cg->name = g_strdup("Logic");
297 for (i = 0; i < num_logic_channels; i++) {
298 sprintf(channel_name, "D%d", i);
299 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
300 cg->channels = g_slist_append(cg->channels, ch);
301 }
302 sdi->channel_groups = g_slist_append(NULL, cg);
87ca93c5
BV
303 }
304
ba7dd8bb 305 /* Analog channels, channel groups and pattern generators. */
f18e0db3
LPC
306 if (num_analog_channels > 0) {
307 pattern = 0;
308 /* An "Analog" channel group with all analog channels in it. */
309 acg = g_malloc0(sizeof(struct sr_channel_group));
310 acg->name = g_strdup("Analog");
311 sdi->channel_groups = g_slist_append(sdi->channel_groups, acg);
312
313 devc->ch_ag = g_hash_table_new(g_direct_hash, g_direct_equal);
314 for (i = 0; i < num_analog_channels; i++) {
315 snprintf(channel_name, 16, "A%d", i);
316 ch = sr_channel_new(sdi, i + num_logic_channels, SR_CHANNEL_ANALOG,
317 TRUE, channel_name);
318 acg->channels = g_slist_append(acg->channels, ch);
319
320 /* Every analog channel gets its own channel group as well. */
321 cg = g_malloc0(sizeof(struct sr_channel_group));
322 cg->name = g_strdup(channel_name);
323 cg->channels = g_slist_append(NULL, ch);
324 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
325
326 /* Every channel gets a generator struct. */
327 ag = g_malloc(sizeof(struct analog_gen));
328 ag->amplitude = DEFAULT_ANALOG_AMPLITUDE;
3be044aa 329 sr_analog_init(&ag->packet, &ag->encoding, &ag->meaning, &ag->spec, 2);
4b770103
UH
330 ag->packet.meaning->channels = cg->channels;
331 ag->packet.meaning->mq = 0;
332 ag->packet.meaning->mqflags = 0;
333 ag->packet.meaning->unit = SR_UNIT_VOLT;
f18e0db3
LPC
334 ag->packet.data = ag->pattern_data;
335 ag->pattern = pattern;
336 ag->avg_val = 0.0f;
337 ag->num_avgs = 0;
338 g_hash_table_insert(devc->ch_ag, ch, ag);
339
340 if (++pattern == ARRAY_SIZE(analog_pattern_str))
341 pattern = 0;
342 }
33ef7573 343 }
33ef7573
JH
344
345 sdi->priv = devc;
346
43376f33 347 return std_scan_complete(di, g_slist_append(NULL, sdi));
6239c175
UH
348}
349
6078d2c9 350static int dev_open(struct sr_dev_inst *sdi)
6239c175 351{
e73ffd42 352 sdi->status = SR_ST_ACTIVE;
697785d1 353
e46b8fb1 354 return SR_OK;
6239c175
UH
355}
356
6078d2c9 357static int dev_close(struct sr_dev_inst *sdi)
6239c175 358{
decfe89d 359 sdi->status = SR_ST_INACTIVE;
697785d1
UH
360
361 return SR_OK;
6239c175
UH
362}
363
ed0b7fed
BV
364static void clear_helper(void *priv)
365{
366 struct dev_context *devc;
49224c28
BV
367 GHashTableIter iter;
368 void *value;
ed0b7fed
BV
369
370 devc = priv;
49224c28
BV
371
372 /* Analog generators. */
373 g_hash_table_iter_init(&iter, devc->ch_ag);
374 while (g_hash_table_iter_next(&iter, NULL, &value))
375 g_free(value);
376 g_hash_table_unref(devc->ch_ag);
ed0b7fed
BV
377 g_free(devc);
378}
379
6ab68731 380static int dev_clear(const struct sr_dev_driver *di)
6239c175 381{
ed0b7fed 382 return std_dev_clear(di, clear_helper);
6239c175
UH
383}
384
584560f1 385static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 386 const struct sr_channel_group *cg)
6239c175 387{
c07f60e7 388 struct dev_context *devc;
ba7dd8bb 389 struct sr_channel *ch;
2388ae86
BV
390 struct analog_gen *ag;
391 int pattern;
6f57fd96 392
2388ae86
BV
393 if (!sdi)
394 return SR_ERR_ARG;
8f996b89 395
c07f60e7 396 devc = sdi->priv;
584560f1 397 switch (key) {
123e1313 398 case SR_CONF_SAMPLERATE:
a7684294 399 *data = g_variant_new_uint64(devc->cur_samplerate);
6239c175 400 break;
2474d87e 401 case SR_CONF_LIMIT_SAMPLES:
a7684294 402 *data = g_variant_new_uint64(devc->limit_samples);
2474d87e
BV
403 break;
404 case SR_CONF_LIMIT_MSEC:
a7684294 405 *data = g_variant_new_uint64(devc->limit_msec);
2474d87e 406 break;
7a8a1aba
BG
407 case SR_CONF_AVERAGING:
408 *data = g_variant_new_boolean(devc->avg);
409 break;
410 case SR_CONF_AVG_SAMPLES:
411 *data = g_variant_new_uint64(devc->avg_samples);
412 break;
2474d87e 413 case SR_CONF_PATTERN_MODE:
53b4680f 414 if (!cg)
660e398f 415 return SR_ERR_CHANNEL_GROUP;
49224c28 416 /* Any channel in the group will do. */
ba7dd8bb 417 ch = cg->channels->data;
3f239f08 418 if (ch->type == SR_CHANNEL_LOGIC) {
2388ae86
BV
419 pattern = devc->logic_pattern;
420 *data = g_variant_new_string(logic_pattern_str[pattern]);
3f239f08 421 } else if (ch->type == SR_CHANNEL_ANALOG) {
49224c28 422 ag = g_hash_table_lookup(devc->ch_ag, ch);
2388ae86
BV
423 pattern = ag->pattern;
424 *data = g_variant_new_string(analog_pattern_str[pattern]);
425 } else
426 return SR_ERR_BUG;
c07f60e7 427 break;
dddabe37
BV
428 case SR_CONF_AMPLITUDE:
429 if (!cg)
430 return SR_ERR_CHANNEL_GROUP;
49224c28 431 /* Any channel in the group will do. */
dddabe37
BV
432 ch = cg->channels->data;
433 if (ch->type != SR_CHANNEL_ANALOG)
434 return SR_ERR_ARG;
49224c28 435 ag = g_hash_table_lookup(devc->ch_ag, ch);
dddabe37
BV
436 *data = g_variant_new_double(ag->amplitude);
437 break;
7dfcf010 438 default:
bd6fbf62 439 return SR_ERR_NA;
6239c175
UH
440 }
441
dfb0fa1a 442 return SR_OK;
6239c175
UH
443}
444
584560f1 445static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 446 const struct sr_channel_group *cg)
6239c175 447{
8b2d41ed 448 struct dev_context *devc;
4374219b 449 struct analog_gen *ag;
ba7dd8bb 450 struct sr_channel *ch;
49224c28
BV
451 GSList *l;
452 int logic_pattern, analog_pattern, ret;
61c39f54 453 unsigned int i;
1b79df2f 454 const char *stropt;
6239c175 455
8b2d41ed 456 devc = sdi->priv;
6239c175 457
e73ffd42
BV
458 if (sdi->status != SR_ST_ACTIVE)
459 return SR_ERR_DEV_CLOSED;
460
2388ae86 461 ret = SR_OK;
584560f1 462 switch (key) {
2388ae86 463 case SR_CONF_SAMPLERATE:
a7684294 464 devc->cur_samplerate = g_variant_get_uint64(data);
2388ae86
BV
465 break;
466 case SR_CONF_LIMIT_SAMPLES:
a7684294
JH
467 devc->limit_msec = 0;
468 devc->limit_samples = g_variant_get_uint64(data);
2388ae86
BV
469 break;
470 case SR_CONF_LIMIT_MSEC:
a7684294
JH
471 devc->limit_msec = g_variant_get_uint64(data);
472 devc->limit_samples = 0;
2388ae86 473 break;
7a8a1aba
BG
474 case SR_CONF_AVERAGING:
475 devc->avg = g_variant_get_boolean(data);
476 sr_dbg("%s averaging", devc->avg ? "Enabling" : "Disabling");
477 break;
478 case SR_CONF_AVG_SAMPLES:
479 devc->avg_samples = g_variant_get_uint64(data);
480 sr_dbg("Setting averaging rate to %" PRIu64, devc->avg_samples);
481 break;
2388ae86 482 case SR_CONF_PATTERN_MODE:
53b4680f 483 if (!cg)
660e398f 484 return SR_ERR_CHANNEL_GROUP;
d00088ca 485 stropt = g_variant_get_string(data, NULL);
49224c28
BV
486 logic_pattern = analog_pattern = -1;
487 for (i = 0; i < ARRAY_SIZE(logic_pattern_str); i++) {
488 if (!strcmp(stropt, logic_pattern_str[i])) {
489 logic_pattern = i;
490 break;
8b2d41ed 491 }
49224c28
BV
492 }
493 for (i = 0; i < ARRAY_SIZE(analog_pattern_str); i++) {
494 if (!strcmp(stropt, analog_pattern_str[i])) {
495 analog_pattern = i;
496 break;
8b2d41ed 497 }
49224c28
BV
498 }
499 if (logic_pattern == -1 && analog_pattern == -1)
500 return SR_ERR_ARG;
501 for (l = cg->channels; l; l = l->next) {
502 ch = l->data;
503 if (ch->type == SR_CHANNEL_LOGIC) {
504 if (logic_pattern == -1)
505 return SR_ERR_ARG;
506 sr_dbg("Setting logic pattern to %s",
507 logic_pattern_str[logic_pattern]);
508 devc->logic_pattern = logic_pattern;
509 /* Might as well do this now, these are static. */
510 if (logic_pattern == PATTERN_ALL_LOW)
511 memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
512 else if (logic_pattern == PATTERN_ALL_HIGH)
513 memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
514 } else if (ch->type == SR_CHANNEL_ANALOG) {
515 if (analog_pattern == -1)
516 return SR_ERR_ARG;
517 sr_dbg("Setting analog pattern for channel %s to %s",
518 ch->name, analog_pattern_str[analog_pattern]);
519 ag = g_hash_table_lookup(devc->ch_ag, ch);
520 ag->pattern = analog_pattern;
521 } else
522 return SR_ERR_BUG;
523 }
2388ae86 524 break;
dddabe37
BV
525 case SR_CONF_AMPLITUDE:
526 if (!cg)
527 return SR_ERR_CHANNEL_GROUP;
49224c28
BV
528 for (l = cg->channels; l; l = l->next) {
529 ch = l->data;
530 if (ch->type != SR_CHANNEL_ANALOG)
531 return SR_ERR_ARG;
532 ag = g_hash_table_lookup(devc->ch_ag, ch);
533 ag->amplitude = g_variant_get_double(data);
534 }
dddabe37 535 break;
2388ae86 536 default:
bd6fbf62 537 ret = SR_ERR_NA;
6239c175
UH
538 }
539
540 return ret;
541}
542
584560f1 543static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 544 const struct sr_channel_group *cg)
a1c743fc 545{
ba7dd8bb 546 struct sr_channel *ch;
d00088ca
BV
547 GVariant *gvar;
548 GVariantBuilder gvb;
a1c743fc 549
7a1da331 550 if (key == SR_CONF_SCAN_OPTIONS) {
584560f1
BV
551 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
552 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
7a1da331
BV
553 return SR_OK;
554 }
555
390795c0
BV
556 if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
557 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
1e4a7cac 558 drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
390795c0
BV
559 return SR_OK;
560 }
561
7a1da331
BV
562 if (!sdi)
563 return SR_ERR_ARG;
564
53b4680f 565 if (!cg) {
7a1da331
BV
566 switch (key) {
567 case SR_CONF_DEVICE_OPTIONS:
584560f1 568 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
1e4a7cac 569 devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
7a1da331
BV
570 break;
571 case SR_CONF_SAMPLERATE:
572 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
573 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
574 ARRAY_SIZE(samplerates), sizeof(uint64_t));
575 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
576 *data = g_variant_builder_end(&gvb);
577 break;
578 default:
579 return SR_ERR_NA;
580 }
581 } else {
ba7dd8bb 582 ch = cg->channels->data;
7a1da331
BV
583 switch (key) {
584 case SR_CONF_DEVICE_OPTIONS:
49224c28 585 if (ch->type == SR_CHANNEL_LOGIC)
8249889d 586 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
49224c28 587 devopts_cg_logic, ARRAY_SIZE(devopts_cg_logic),
584560f1 588 sizeof(uint32_t));
e2b99f04
SA
589 else if (ch->type == SR_CHANNEL_ANALOG) {
590 if (strcmp(cg->name, "Analog") == 0)
591 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
592 devopts_cg_analog_group, ARRAY_SIZE(devopts_cg_analog_group),
593 sizeof(uint32_t));
594 else
595 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
596 devopts_cg_analog_channel, ARRAY_SIZE(devopts_cg_analog_channel),
597 sizeof(uint32_t));
598 }
49224c28
BV
599 else
600 return SR_ERR_BUG;
7a1da331
BV
601 break;
602 case SR_CONF_PATTERN_MODE:
e2b99f04
SA
603 /* The analog group (with all 4 channels) shall not have a pattern property. */
604 if (strcmp(cg->name, "Analog") == 0)
605 return SR_ERR_NA;
606
3f239f08 607 if (ch->type == SR_CHANNEL_LOGIC)
7a1da331
BV
608 *data = g_variant_new_strv(logic_pattern_str,
609 ARRAY_SIZE(logic_pattern_str));
3f239f08 610 else if (ch->type == SR_CHANNEL_ANALOG)
7a1da331
BV
611 *data = g_variant_new_strv(analog_pattern_str,
612 ARRAY_SIZE(analog_pattern_str));
2388ae86
BV
613 else
614 return SR_ERR_BUG;
7a1da331
BV
615 break;
616 default:
617 return SR_ERR_NA;
618 }
a1c743fc
BV
619 }
620
621 return SR_OK;
622}
623
c07f60e7 624static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
85b5af06 625{
61c39f54 626 struct dev_context *devc;
c07f60e7
BV
627 uint64_t i, j;
628 uint8_t pat;
85b5af06 629
61c39f54 630 devc = sdi->priv;
85b5af06 631
c07f60e7 632 switch (devc->logic_pattern) {
61c39f54 633 case PATTERN_SIGROK:
c07f60e7
BV
634 memset(devc->logic_data, 0x00, size);
635 for (i = 0; i < size; i += devc->logic_unitsize) {
636 for (j = 0; j < devc->logic_unitsize; j++) {
637 pat = pattern_sigrok[(devc->step + j) % sizeof(pattern_sigrok)] >> 1;
638 devc->logic_data[i + j] = ~pat;
639 }
640 devc->step++;
917e0e71
BV
641 }
642 break;
61c39f54 643 case PATTERN_RANDOM:
5096c6a6 644 for (i = 0; i < size; i++)
61c39f54 645 devc->logic_data[i] = (uint8_t)(rand() & 0xff);
85b5af06 646 break;
61c39f54 647 case PATTERN_INC:
c07f60e7
BV
648 for (i = 0; i < size; i++) {
649 for (j = 0; j < devc->logic_unitsize; j++) {
650 devc->logic_data[i + j] = devc->step;
651 }
652 devc->step++;
653 }
c03ed397 654 break;
61c39f54
BV
655 case PATTERN_ALL_LOW:
656 case PATTERN_ALL_HIGH:
657 /* These were set when the pattern mode was selected. */
c03ed397
UH
658 break;
659 default:
c07f60e7 660 sr_err("Unknown pattern: %d.", devc->logic_pattern);
c03ed397 661 break;
85b5af06
UH
662 }
663}
664
7a8a1aba 665static void send_analog_packet(struct analog_gen *ag,
d9251a2c
UH
666 struct sr_dev_inst *sdi, uint64_t *analog_sent,
667 uint64_t analog_pos, uint64_t analog_todo)
7a8a1aba
BG
668{
669 struct sr_datafeed_packet packet;
670 struct dev_context *devc;
671 uint64_t sending_now, to_avg;
672 int ag_pattern_pos;
673 unsigned int i;
674
675 devc = sdi->priv;
4b770103 676 packet.type = SR_DF_ANALOG;
7a8a1aba
BG
677 packet.payload = &ag->packet;
678
679 if (!devc->avg) {
a49a320d 680 ag_pattern_pos = analog_pos % ag->num_samples;
7a8a1aba
BG
681 sending_now = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
682 ag->packet.data = ag->pattern_data + ag_pattern_pos;
683 ag->packet.num_samples = sending_now;
684 sr_session_send(sdi, &packet);
685
686 /* Whichever channel group gets there first. */
687 *analog_sent = MAX(*analog_sent, sending_now);
688 } else {
a49a320d 689 ag_pattern_pos = analog_pos % ag->num_samples;
7a8a1aba
BG
690 to_avg = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
691
692 for (i = 0; i < to_avg; i++) {
693 ag->avg_val = (ag->avg_val +
694 *(ag->pattern_data +
695 ag_pattern_pos + i)) / 2;
696 ag->num_avgs++;
697 /* Time to send averaged data? */
698 if (devc->avg_samples > 0 &&
699 ag->num_avgs >= devc->avg_samples)
700 goto do_send;
701 }
702
703 if (devc->avg_samples == 0) {
704 /* We're averaging all the samples, so wait with
705 * sending until the very end.
706 */
707 *analog_sent = ag->num_avgs;
708 return;
709 }
710
711do_send:
712 ag->packet.data = &ag->avg_val;
713 ag->packet.num_samples = 1;
714
715 sr_session_send(sdi, &packet);
716 *analog_sent = ag->num_avgs;
717
718 ag->num_avgs = 0;
719 ag->avg_val = 0.0f;
720 }
721}
722
85b5af06 723/* Callback handling data */
61c39f54 724static int prepare_data(int fd, int revents, void *cb_data)
85b5af06 725{
61c39f54
BV
726 struct sr_dev_inst *sdi;
727 struct dev_context *devc;
b9c735a2 728 struct sr_datafeed_packet packet;
9c939c51 729 struct sr_datafeed_logic logic;
8b2d41ed 730 struct analog_gen *ag;
49224c28
BV
731 GHashTableIter iter;
732 void *value;
a49a320d
DE
733 uint64_t samples_todo, logic_done, analog_done, analog_sent, sending_now;
734 int64_t elapsed_us, limit_us, todo_us;
1924f59f 735
cb93f8a9
UH
736 (void)fd;
737 (void)revents;
1924f59f 738
61c39f54
BV
739 sdi = cb_data;
740 devc = sdi->priv;
741
a49a320d 742 /* Just in case. */
f18e0db3 743 if (devc->cur_samplerate <= 0
a49a320d
DE
744 || (devc->num_logic_channels <= 0
745 && devc->num_analog_channels <= 0)) {
695dc859 746 dev_acquisition_stop(sdi);
a49a320d
DE
747 return G_SOURCE_CONTINUE;
748 }
7f4975b4 749
a49a320d
DE
750 /* What time span should we send samples for? */
751 elapsed_us = g_get_monotonic_time() - devc->start_us;
752 limit_us = 1000 * devc->limit_msec;
753 if (limit_us > 0 && limit_us < elapsed_us)
754 todo_us = MAX(0, limit_us - devc->spent_us);
755 else
756 todo_us = MAX(0, elapsed_us - devc->spent_us);
757
758 /* How many samples are outstanding since the last round? */
36cbd69e 759 samples_todo = (todo_us * devc->cur_samplerate + G_USEC_PER_SEC - 1)
a49a320d
DE
760 / G_USEC_PER_SEC;
761 if (devc->limit_samples > 0) {
762 if (devc->limit_samples < devc->sent_samples)
763 samples_todo = 0;
764 else if (devc->limit_samples - devc->sent_samples < samples_todo)
765 samples_todo = devc->limit_samples - devc->sent_samples;
766 }
767 /* Calculate the actual time covered by this run back from the sample
768 * count, rounded towards zero. This avoids getting stuck on a too-low
769 * time delta with no samples being sent due to round-off.
770 */
771 todo_us = samples_todo * G_USEC_PER_SEC / devc->cur_samplerate;
b62bb97a 772
9dfacd87
AJ
773 logic_done = devc->num_logic_channels > 0 ? 0 : samples_todo;
774 analog_done = devc->num_analog_channels > 0 ? 0 : samples_todo;
85b5af06 775
a49a320d 776 while (logic_done < samples_todo || analog_done < samples_todo) {
c07f60e7 777 /* Logic */
a49a320d
DE
778 if (logic_done < samples_todo) {
779 sending_now = MIN(samples_todo - logic_done,
780 LOGIC_BUFSIZE / devc->logic_unitsize);
8b2d41ed
BV
781 logic_generator(sdi, sending_now * devc->logic_unitsize);
782 packet.type = SR_DF_LOGIC;
783 packet.payload = &logic;
784 logic.length = sending_now * devc->logic_unitsize;
785 logic.unitsize = devc->logic_unitsize;
786 logic.data = devc->logic_data;
787 sr_session_send(sdi, &packet);
a49a320d 788 logic_done += sending_now;
8b2d41ed
BV
789 }
790
ba7dd8bb 791 /* Analog, one channel at a time */
a49a320d 792 if (analog_done < samples_todo) {
b62bb97a 793 analog_sent = 0;
49224c28
BV
794
795 g_hash_table_iter_init(&iter, devc->ch_ag);
796 while (g_hash_table_iter_next(&iter, NULL, &value)) {
a49a320d
DE
797 send_analog_packet(value, sdi, &analog_sent,
798 devc->sent_samples + analog_done,
799 samples_todo - analog_done);
8b2d41ed 800 }
a49a320d 801 analog_done += analog_sent;
8b2d41ed 802 }
3b203673 803 }
a49a320d
DE
804 /* At this point, both logic_done and analog_done should be
805 * exactly equal to samples_todo, or else.
806 */
807 if (logic_done != samples_todo || analog_done != samples_todo) {
808 sr_err("BUG: Sample count mismatch.");
809 return G_SOURCE_REMOVE;
810 }
811 devc->sent_samples += samples_todo;
812 devc->spent_us += todo_us;
813
814 if ((devc->limit_samples > 0 && devc->sent_samples >= devc->limit_samples)
815 || (limit_us > 0 && devc->spent_us >= limit_us)) {
3b203673 816
7a8a1aba
BG
817 /* If we're averaging everything - now is the time to send data */
818 if (devc->avg_samples == 0) {
819 g_hash_table_iter_init(&iter, devc->ch_ag);
820 while (g_hash_table_iter_next(&iter, NULL, &value)) {
821 ag = value;
4b770103 822 packet.type = SR_DF_ANALOG;
7a8a1aba
BG
823 packet.payload = &ag->packet;
824 ag->packet.data = &ag->avg_val;
825 ag->packet.num_samples = 1;
826 sr_session_send(sdi, &packet);
827 }
828 }
7f4975b4 829 sr_dbg("Requested number of samples reached.");
695dc859 830 dev_acquisition_stop(sdi);
85b5af06 831 }
1924f59f 832
a49a320d 833 return G_SOURCE_CONTINUE;
85b5af06
UH
834}
835
695dc859 836static int dev_acquisition_start(const struct sr_dev_inst *sdi)
6239c175 837{
61c39f54 838 struct dev_context *devc;
49224c28
BV
839 GHashTableIter iter;
840 void *value;
85b5af06 841
e73ffd42
BV
842 if (sdi->status != SR_ST_ACTIVE)
843 return SR_ERR_DEV_CLOSED;
844
61c39f54 845 devc = sdi->priv;
a49a320d 846 devc->sent_samples = 0;
85b5af06 847
49224c28
BV
848 g_hash_table_iter_init(&iter, devc->ch_ag);
849 while (g_hash_table_iter_next(&iter, NULL, &value))
850 generate_analog_pattern(value, devc->cur_samplerate);
4374219b 851
98c01fe1
DE
852 sr_session_source_add(sdi->session, -1, 0, 100,
853 prepare_data, (struct sr_dev_inst *)sdi);
85b5af06 854
bee2b016 855 std_session_send_df_header(sdi);
f366e86c 856
3b203673 857 /* We use this timestamp to decide how many more samples to send. */
a49a320d
DE
858 devc->start_us = g_get_monotonic_time();
859 devc->spent_us = 0;
3b203673 860
e46b8fb1 861 return SR_OK;
6239c175
UH
862}
863
695dc859 864static int dev_acquisition_stop(struct sr_dev_inst *sdi)
6239c175 865{
a84f6ad3 866 sr_dbg("Stopping acquisition.");
027bf077 867 sr_session_source_remove(sdi->session, -1);
bee2b016 868 std_session_send_df_end(sdi);
7fd3e859 869
3010f21c 870 return SR_OK;
6239c175
UH
871}
872
dd5c48a6 873static struct sr_dev_driver demo_driver_info = {
e519ba86
UH
874 .name = "demo",
875 .longname = "Demo driver and pattern generator",
876 .api_version = 1,
c2fdcc25 877 .init = std_init,
700d6b64 878 .cleanup = std_cleanup,
6078d2c9 879 .scan = scan,
c01bf34c 880 .dev_list = std_dev_list,
6ab68731 881 .dev_clear = dev_clear,
035a1078
BV
882 .config_get = config_get,
883 .config_set = config_set,
a1c743fc 884 .config_list = config_list,
6078d2c9
UH
885 .dev_open = dev_open,
886 .dev_close = dev_close,
887 .dev_acquisition_start = dev_acquisition_start,
888 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 889 .context = NULL,
6239c175 890};
dd5c48a6 891SR_REGISTER_DEV_DRIVER(demo_driver_info);