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