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