]> sigrok.org Git - libsigrok.git/blame - src/hardware/demo/demo.c
demo: Rearrange driver and device options.
[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>
6239c175
UH
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <stdlib.h>
85b5af06 24#include <unistd.h>
6239c175 25#include <string.h>
4374219b 26#include <math.h>
d35aaf02
UH
27#ifdef _WIN32
28#include <io.h>
29#include <fcntl.h>
30#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
31#endif
45c59c8b
BV
32#include "libsigrok.h"
33#include "libsigrok-internal.h"
6239c175 34
3544f848 35#define LOG_PREFIX "demo"
92bcedf6 36
3f239f08
UH
37#define DEFAULT_NUM_LOGIC_CHANNELS 8
38#define DEFAULT_NUM_ANALOG_CHANNELS 4
c03ed397 39
8b2d41ed 40/* The size in bytes of chunks to send through the session bus. */
61c39f54 41#define LOGIC_BUFSIZE 4096
8b2d41ed
BV
42/* Size of the analog pattern space per channel. */
43#define ANALOG_BUFSIZE 4096
2474d87e 44
dddabe37 45#define DEFAULT_ANALOG_AMPLITUDE 25
4374219b
DJ
46#define ANALOG_SAMPLES_PER_PERIOD 20
47
2388ae86 48/* Logic patterns we can generate. */
e15f48c2 49enum {
0d31276b 50 /**
ba7dd8bb 51 * Spells "sigrok" across 8 channels using '0's (with '1's as
61c39f54 52 * "background") when displayed using the 'bits' output format.
95035832 53 * The pattern is repeated every 8 channels, shifted to the right
c07f60e7 54 * in time by one bit.
0d31276b 55 */
c8f4624d 56 PATTERN_SIGROK,
0d31276b 57
ba7dd8bb 58 /** Pseudo-random values on all channels. */
c8f4624d 59 PATTERN_RANDOM,
0d31276b
UH
60
61 /**
95035832 62 * Incrementing number across 8 channels. The pattern is repeated
ba7dd8bb 63 * every 8 channels, shifted to the right in time by one bit.
0d31276b 64 */
c8f4624d 65 PATTERN_INC,
c03ed397 66
ba7dd8bb 67 /** All channels have a low logic state. */
c03ed397
UH
68 PATTERN_ALL_LOW,
69
ba7dd8bb 70 /** All channels have a high logic state. */
c03ed397 71 PATTERN_ALL_HIGH,
2388ae86 72};
8b2d41ed 73
2388ae86
BV
74/* Analog patterns we can generate. */
75enum {
8b2d41ed
BV
76 /**
77 * Square wave.
78 */
79 PATTERN_SQUARE,
4374219b 80 PATTERN_SINE,
091c9621 81 PATTERN_TRIANGLE,
9f54e0e8 82 PATTERN_SAWTOOTH,
e15f48c2 83};
85b5af06 84
8b2d41ed 85static const char *logic_pattern_str[] = {
61c39f54
BV
86 "sigrok",
87 "random",
88 "incremental",
89 "all-low",
90 "all-high",
91};
92
8b2d41ed
BV
93static const char *analog_pattern_str[] = {
94 "square",
4374219b 95 "sine",
091c9621 96 "triangle",
9f54e0e8 97 "sawtooth",
8b2d41ed
BV
98};
99
100struct analog_gen {
101 int pattern;
dddabe37 102 float amplitude;
8b2d41ed
BV
103 float pattern_data[ANALOG_BUFSIZE];
104 unsigned int num_samples;
105 struct sr_datafeed_analog packet;
106};
107
b4750a3a
BV
108/* Private, per-device-instance driver context. */
109struct dev_context {
e15f48c2 110 int pipe_fds[2];
e0532047 111 GIOChannel *channel;
a7684294 112 uint64_t cur_samplerate;
b62bb97a 113 gboolean continuous;
a7684294
JH
114 uint64_t limit_samples;
115 uint64_t limit_msec;
7f4975b4
BV
116 uint64_t logic_counter;
117 uint64_t analog_counter;
3b203673 118 int64_t starttime;
61c39f54 119 uint64_t step;
8b2d41ed 120 /* Logic */
ba7dd8bb 121 int32_t num_logic_channels;
c07f60e7 122 unsigned int logic_unitsize;
660e398f 123 /* There is only ever one logic channel group, so its pattern goes here. */
c07f60e7
BV
124 uint8_t logic_pattern;
125 unsigned char logic_data[LOGIC_BUFSIZE];
8b2d41ed 126 /* Analog */
ba7dd8bb 127 int32_t num_analog_channels;
49224c28 128 GHashTable *ch_ag;
c07f60e7
BV
129};
130
584560f1 131static const uint32_t scanopts[] = {
3f239f08
UH
132 SR_CONF_NUM_LOGIC_CHANNELS,
133 SR_CONF_NUM_ANALOG_CHANNELS,
e15f48c2 134};
85b5af06 135
390795c0
BV
136static const uint32_t devopts[] = {
137 SR_CONF_DEMO_DEV,
1953564a 138 SR_CONF_LOGIC_ANALYZER,
390795c0 139 SR_CONF_OSCILLOSCOPE,
b62bb97a 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,
6239c175
UH
143};
144
390795c0
BV
145static const uint32_t devopts_global[] = {
146 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
147};
148
149static const uint32_t devopts_cg_logic[] = {
f12d9979 150 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
49224c28
BV
151};
152
390795c0 153static const uint32_t devopts_cg_analog[] = {
f12d9979
BV
154 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
155 SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
7a1da331
BV
156};
157
d00088ca
BV
158static const uint64_t samplerates[] = {
159 SR_HZ(1),
160 SR_GHZ(1),
161 SR_HZ(1),
4bfbf9fc
BV
162};
163
c8f4624d 164static uint8_t pattern_sigrok[] = {
917e0e71
BV
165 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
166 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
167 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
168 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
169 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
170 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173};
174
dcf03d6d 175SR_PRIV struct sr_dev_driver demo_driver_info;
a873c594 176static struct sr_dev_driver *di = &demo_driver_info;
6239c175 177
6078d2c9 178static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 179
c07f60e7 180
6078d2c9 181static int init(struct sr_context *sr_ctx)
61136ea6 182{
f6beaac5 183 return std_init(sr_ctx, di, LOG_PREFIX);
61136ea6
BV
184}
185
49224c28 186static void generate_analog_pattern(struct analog_gen *ag, uint64_t sample_rate)
8b2d41ed 187{
4374219b 188 double t, frequency;
8b2d41ed
BV
189 float value;
190 unsigned int num_samples, i;
191 int last_end;
192
49224c28 193 sr_dbg("Generating %s pattern.", analog_pattern_str[ag->pattern]);
4374219b 194
49224c28 195 num_samples = ANALOG_BUFSIZE / sizeof(float);
8b2d41ed 196
4374219b 197 switch (ag->pattern) {
8b2d41ed 198 case PATTERN_SQUARE:
dddabe37 199 value = ag->amplitude;
8b2d41ed
BV
200 last_end = 0;
201 for (i = 0; i < num_samples; i++) {
202 if (i % 5 == 0)
203 value = -value;
204 if (i % 10 == 0)
205 last_end = i - 1;
206 ag->pattern_data[i] = value;
207 }
208 ag->num_samples = last_end;
209 break;
4374219b
DJ
210
211 case PATTERN_SINE:
9d156555 212 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
4374219b
DJ
213
214 /* Make sure the number of samples we put out is an integer
215 * multiple of our period size */
216 /* FIXME we actually need only one period. A ringbuffer would be
217 * usefull here.*/
218 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
219 num_samples--;
220
221 for (i = 0; i < num_samples; i++) {
222 t = (double) i / (double) sample_rate;
dddabe37 223 ag->pattern_data[i] = ag->amplitude *
4374219b
DJ
224 sin(2 * M_PI * frequency * t);
225 }
226
091c9621
DJ
227 ag->num_samples = num_samples;
228 break;
229
230 case PATTERN_TRIANGLE:
9d156555 231 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
091c9621
DJ
232
233 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
234 num_samples--;
235
236 for (i = 0; i < num_samples; i++) {
237 t = (double) i / (double) sample_rate;
dddabe37 238 ag->pattern_data[i] = (2 * ag->amplitude / M_PI) *
091c9621
DJ
239 asin(sin(2 * M_PI * frequency * t));
240 }
241
9f54e0e8
DJ
242 ag->num_samples = num_samples;
243 break;
244
245 case PATTERN_SAWTOOTH:
9d156555 246 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
9f54e0e8
DJ
247
248 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
249 num_samples--;
250
251 for (i = 0; i < num_samples; i++) {
252 t = (double) i / (double) sample_rate;
dddabe37 253 ag->pattern_data[i] = 2 * ag->amplitude *
9f54e0e8
DJ
254 ((t * frequency) - floor(0.5f + t * frequency));
255 }
256
4374219b
DJ
257 ag->num_samples = num_samples;
258 break;
8b2d41ed
BV
259 }
260}
261
6078d2c9 262static GSList *scan(GSList *options)
6239c175 263{
b4750a3a 264 struct drv_context *drvc;
33ef7573 265 struct dev_context *devc;
c07f60e7 266 struct sr_dev_inst *sdi;
ba7dd8bb 267 struct sr_channel *ch;
49224c28 268 struct sr_channel_group *cg, *acg;
c07f60e7 269 struct sr_config *src;
8b2d41ed 270 struct analog_gen *ag;
c07f60e7 271 GSList *devices, *l;
ba7dd8bb
UH
272 int num_logic_channels, num_analog_channels, pattern, i;
273 char channel_name[16];
067d0716 274
a873c594 275 drvc = di->priv;
4b97c74e 276
3f239f08
UH
277 num_logic_channels = DEFAULT_NUM_LOGIC_CHANNELS;
278 num_analog_channels = DEFAULT_NUM_ANALOG_CHANNELS;
c07f60e7
BV
279 for (l = options; l; l = l->next) {
280 src = l->data;
281 switch (src->key) {
3f239f08 282 case SR_CONF_NUM_LOGIC_CHANNELS:
ba7dd8bb 283 num_logic_channels = g_variant_get_int32(src->data);
c07f60e7 284 break;
3f239f08 285 case SR_CONF_NUM_ANALOG_CHANNELS:
ba7dd8bb 286 num_analog_channels = g_variant_get_int32(src->data);
c07f60e7
BV
287 break;
288 }
289 }
85b5af06 290
c07f60e7 291 devices = NULL;
aed4ad0b 292 sdi = sr_dev_inst_new(SR_ST_ACTIVE, "Demo device", NULL, NULL);
c03ed397 293 if (!sdi) {
e45ad6e2
UH
294 sr_err("Device instance creation failed.");
295 return NULL;
c03ed397 296 }
a873c594 297 sdi->driver = di;
e15f48c2 298
49224c28 299 devc = g_malloc(sizeof(struct dev_context));
8b2d41ed
BV
300 devc->cur_samplerate = SR_KHZ(200);
301 devc->limit_samples = 0;
302 devc->limit_msec = 0;
303 devc->step = 0;
b62bb97a 304 devc->continuous = FALSE;
ba7dd8bb
UH
305 devc->num_logic_channels = num_logic_channels;
306 devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
8b2d41ed 307 devc->logic_pattern = PATTERN_SIGROK;
ba7dd8bb 308 devc->num_analog_channels = num_analog_channels;
8b2d41ed 309
ba7dd8bb 310 /* Logic channels, all in one channel group. */
49224c28 311 cg = g_malloc0(sizeof(struct sr_channel_group));
40fd0264 312 cg->name = g_strdup("Logic");
ba7dd8bb
UH
313 for (i = 0; i < num_logic_channels; i++) {
314 sprintf(channel_name, "D%d", i);
3f239f08 315 if (!(ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, channel_name)))
87ca93c5 316 return NULL;
ba7dd8bb
UH
317 sdi->channels = g_slist_append(sdi->channels, ch);
318 cg->channels = g_slist_append(cg->channels, ch);
87ca93c5 319 }
40fd0264 320 sdi->channel_groups = g_slist_append(NULL, cg);
87ca93c5 321
ba7dd8bb 322 /* Analog channels, channel groups and pattern generators. */
2b36d6c6 323 pattern = 0;
49224c28
BV
324 /* An "Analog" channel group with all analog channels in it. */
325 acg = g_malloc0(sizeof(struct sr_channel_group));
326 acg->name = g_strdup("Analog");
327 sdi->channel_groups = g_slist_append(sdi->channel_groups, acg);
328
329 devc->ch_ag = g_hash_table_new(g_direct_hash, g_direct_equal);
ba7dd8bb 330 for (i = 0; i < num_analog_channels; i++) {
49224c28
BV
331 snprintf(channel_name, 16, "A%d", i);
332 ch = sr_channel_new(i + num_logic_channels, SR_CHANNEL_ANALOG,
333 TRUE, channel_name);
ba7dd8bb 334 sdi->channels = g_slist_append(sdi->channels, ch);
49224c28 335 acg->channels = g_slist_append(acg->channels, ch);
c07f60e7 336
49224c28
BV
337 /* Every analog channel gets its own channel group as well. */
338 cg = g_malloc0(sizeof(struct sr_channel_group));
ba7dd8bb
UH
339 cg->name = g_strdup(channel_name);
340 cg->channels = g_slist_append(NULL, ch);
49224c28 341 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
85b5af06 342
49224c28
BV
343 /* Every channel gets a generator struct. */
344 ag = g_malloc(sizeof(struct analog_gen));
dddabe37 345 ag->amplitude = DEFAULT_ANALOG_AMPLITUDE;
ba7dd8bb 346 ag->packet.channels = cg->channels;
8b2d41ed
BV
347 ag->packet.mq = 0;
348 ag->packet.mqflags = 0;
349 ag->packet.unit = SR_UNIT_VOLT;
350 ag->packet.data = ag->pattern_data;
2b36d6c6 351 ag->pattern = pattern;
49224c28 352 g_hash_table_insert(devc->ch_ag, ch, ag);
2b36d6c6
BV
353
354 if (++pattern == ARRAY_SIZE(analog_pattern_str))
355 pattern = 0;
33ef7573 356 }
33ef7573
JH
357
358 sdi->priv = devc;
8b2d41ed
BV
359 devices = g_slist_append(devices, sdi);
360 drvc->instances = g_slist_append(drvc->instances, sdi);
33ef7573 361
067d0716 362 return devices;
6239c175
UH
363}
364
6078d2c9 365static GSList *dev_list(void)
811deee4 366{
0e94d524 367 return ((struct drv_context *)(di->priv))->instances;
811deee4
BV
368}
369
6078d2c9 370static int dev_open(struct sr_dev_inst *sdi)
6239c175 371{
e73ffd42 372 sdi->status = SR_ST_ACTIVE;
697785d1 373
e46b8fb1 374 return SR_OK;
6239c175
UH
375}
376
6078d2c9 377static int dev_close(struct sr_dev_inst *sdi)
6239c175 378{
decfe89d 379 sdi->status = SR_ST_INACTIVE;
697785d1
UH
380
381 return SR_OK;
6239c175
UH
382}
383
ed0b7fed
BV
384static void clear_helper(void *priv)
385{
386 struct dev_context *devc;
49224c28
BV
387 GHashTableIter iter;
388 void *value;
ed0b7fed
BV
389
390 devc = priv;
49224c28
BV
391
392 /* Analog generators. */
393 g_hash_table_iter_init(&iter, devc->ch_ag);
394 while (g_hash_table_iter_next(&iter, NULL, &value))
395 g_free(value);
396 g_hash_table_unref(devc->ch_ag);
ed0b7fed
BV
397 g_free(devc);
398}
399
6078d2c9 400static int cleanup(void)
6239c175 401{
ed0b7fed 402 return std_dev_clear(di, clear_helper);
6239c175
UH
403}
404
584560f1 405static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 406 const struct sr_channel_group *cg)
6239c175 407{
c07f60e7 408 struct dev_context *devc;
ba7dd8bb 409 struct sr_channel *ch;
2388ae86
BV
410 struct analog_gen *ag;
411 int pattern;
6f57fd96 412
2388ae86
BV
413 if (!sdi)
414 return SR_ERR_ARG;
8f996b89 415
c07f60e7 416 devc = sdi->priv;
584560f1 417 switch (key) {
123e1313 418 case SR_CONF_SAMPLERATE:
a7684294 419 *data = g_variant_new_uint64(devc->cur_samplerate);
6239c175 420 break;
2474d87e 421 case SR_CONF_LIMIT_SAMPLES:
a7684294 422 *data = g_variant_new_uint64(devc->limit_samples);
2474d87e
BV
423 break;
424 case SR_CONF_LIMIT_MSEC:
a7684294 425 *data = g_variant_new_uint64(devc->limit_msec);
2474d87e
BV
426 break;
427 case SR_CONF_PATTERN_MODE:
53b4680f 428 if (!cg)
660e398f 429 return SR_ERR_CHANNEL_GROUP;
49224c28 430 /* Any channel in the group will do. */
ba7dd8bb 431 ch = cg->channels->data;
3f239f08 432 if (ch->type == SR_CHANNEL_LOGIC) {
2388ae86
BV
433 pattern = devc->logic_pattern;
434 *data = g_variant_new_string(logic_pattern_str[pattern]);
3f239f08 435 } else if (ch->type == SR_CHANNEL_ANALOG) {
49224c28 436 ag = g_hash_table_lookup(devc->ch_ag, ch);
2388ae86
BV
437 pattern = ag->pattern;
438 *data = g_variant_new_string(analog_pattern_str[pattern]);
439 } else
440 return SR_ERR_BUG;
c07f60e7 441 break;
dddabe37
BV
442 case SR_CONF_AMPLITUDE:
443 if (!cg)
444 return SR_ERR_CHANNEL_GROUP;
49224c28 445 /* Any channel in the group will do. */
dddabe37
BV
446 ch = cg->channels->data;
447 if (ch->type != SR_CHANNEL_ANALOG)
448 return SR_ERR_ARG;
49224c28 449 ag = g_hash_table_lookup(devc->ch_ag, ch);
dddabe37
BV
450 *data = g_variant_new_double(ag->amplitude);
451 break;
7dfcf010 452 default:
bd6fbf62 453 return SR_ERR_NA;
6239c175
UH
454 }
455
dfb0fa1a 456 return SR_OK;
6239c175
UH
457}
458
584560f1 459static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 460 const struct sr_channel_group *cg)
6239c175 461{
8b2d41ed 462 struct dev_context *devc;
4374219b 463 struct analog_gen *ag;
ba7dd8bb 464 struct sr_channel *ch;
49224c28
BV
465 GSList *l;
466 int logic_pattern, analog_pattern, ret;
61c39f54 467 unsigned int i;
1b79df2f 468 const char *stropt;
6239c175 469
8b2d41ed 470 devc = sdi->priv;
6239c175 471
e73ffd42
BV
472 if (sdi->status != SR_ST_ACTIVE)
473 return SR_ERR_DEV_CLOSED;
474
2388ae86 475 ret = SR_OK;
584560f1 476 switch (key) {
2388ae86 477 case SR_CONF_SAMPLERATE:
a7684294 478 devc->cur_samplerate = g_variant_get_uint64(data);
61c39f54 479 sr_dbg("Setting samplerate to %" PRIu64, devc->cur_samplerate);
2388ae86
BV
480 break;
481 case SR_CONF_LIMIT_SAMPLES:
a7684294
JH
482 devc->limit_msec = 0;
483 devc->limit_samples = g_variant_get_uint64(data);
8b2d41ed 484 sr_dbg("Setting sample limit to %" PRIu64, devc->limit_samples);
2388ae86
BV
485 break;
486 case SR_CONF_LIMIT_MSEC:
a7684294
JH
487 devc->limit_msec = g_variant_get_uint64(data);
488 devc->limit_samples = 0;
8b2d41ed 489 sr_dbg("Setting time limit to %" PRIu64"ms", devc->limit_msec);
2388ae86
BV
490 break;
491 case SR_CONF_PATTERN_MODE:
53b4680f 492 if (!cg)
660e398f 493 return SR_ERR_CHANNEL_GROUP;
d00088ca 494 stropt = g_variant_get_string(data, NULL);
49224c28
BV
495 logic_pattern = analog_pattern = -1;
496 for (i = 0; i < ARRAY_SIZE(logic_pattern_str); i++) {
497 if (!strcmp(stropt, logic_pattern_str[i])) {
498 logic_pattern = i;
499 break;
8b2d41ed 500 }
49224c28
BV
501 }
502 for (i = 0; i < ARRAY_SIZE(analog_pattern_str); i++) {
503 if (!strcmp(stropt, analog_pattern_str[i])) {
504 analog_pattern = i;
505 break;
8b2d41ed 506 }
49224c28
BV
507 }
508 if (logic_pattern == -1 && analog_pattern == -1)
509 return SR_ERR_ARG;
510 for (l = cg->channels; l; l = l->next) {
511 ch = l->data;
512 if (ch->type == SR_CHANNEL_LOGIC) {
513 if (logic_pattern == -1)
514 return SR_ERR_ARG;
515 sr_dbg("Setting logic pattern to %s",
516 logic_pattern_str[logic_pattern]);
517 devc->logic_pattern = logic_pattern;
518 /* Might as well do this now, these are static. */
519 if (logic_pattern == PATTERN_ALL_LOW)
520 memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
521 else if (logic_pattern == PATTERN_ALL_HIGH)
522 memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
523 } else if (ch->type == SR_CHANNEL_ANALOG) {
524 if (analog_pattern == -1)
525 return SR_ERR_ARG;
526 sr_dbg("Setting analog pattern for channel %s to %s",
527 ch->name, analog_pattern_str[analog_pattern]);
528 ag = g_hash_table_lookup(devc->ch_ag, ch);
529 ag->pattern = analog_pattern;
530 } else
531 return SR_ERR_BUG;
532 }
2388ae86 533 break;
dddabe37
BV
534 case SR_CONF_AMPLITUDE:
535 if (!cg)
536 return SR_ERR_CHANNEL_GROUP;
49224c28
BV
537 for (l = cg->channels; l; l = l->next) {
538 ch = l->data;
539 if (ch->type != SR_CHANNEL_ANALOG)
540 return SR_ERR_ARG;
541 ag = g_hash_table_lookup(devc->ch_ag, ch);
542 ag->amplitude = g_variant_get_double(data);
543 }
dddabe37 544 break;
2388ae86 545 default:
bd6fbf62 546 ret = SR_ERR_NA;
6239c175
UH
547 }
548
549 return ret;
550}
551
584560f1 552static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 553 const struct sr_channel_group *cg)
a1c743fc 554{
ba7dd8bb 555 struct sr_channel *ch;
d00088ca
BV
556 GVariant *gvar;
557 GVariantBuilder gvb;
a1c743fc
BV
558
559 (void)sdi;
560
7a1da331 561 if (key == SR_CONF_SCAN_OPTIONS) {
584560f1
BV
562 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
563 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
7a1da331
BV
564 return SR_OK;
565 }
566
390795c0
BV
567 if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
568 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
569 devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
570 return SR_OK;
571 }
572
7a1da331
BV
573 if (!sdi)
574 return SR_ERR_ARG;
575
53b4680f 576 if (!cg) {
7a1da331
BV
577 switch (key) {
578 case SR_CONF_DEVICE_OPTIONS:
584560f1 579 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
390795c0 580 devopts_global, ARRAY_SIZE(devopts_global), sizeof(uint32_t));
7a1da331
BV
581 break;
582 case SR_CONF_SAMPLERATE:
583 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
584 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
585 ARRAY_SIZE(samplerates), sizeof(uint64_t));
586 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
587 *data = g_variant_builder_end(&gvb);
588 break;
589 default:
590 return SR_ERR_NA;
591 }
592 } else {
49224c28 593 /* Any channel in the group will do. */
ba7dd8bb 594 ch = cg->channels->data;
7a1da331
BV
595 switch (key) {
596 case SR_CONF_DEVICE_OPTIONS:
49224c28
BV
597 if (ch->type == SR_CHANNEL_LOGIC)
598 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
599 devopts_cg_logic, ARRAY_SIZE(devopts_cg_logic),
584560f1 600 sizeof(uint32_t));
49224c28
BV
601 else if (ch->type == SR_CHANNEL_ANALOG)
602 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
603 devopts_cg_analog, ARRAY_SIZE(devopts_cg_analog),
584560f1 604 sizeof(uint32_t));
49224c28
BV
605 else
606 return SR_ERR_BUG;
7a1da331
BV
607 break;
608 case SR_CONF_PATTERN_MODE:
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
85b5af06 667/* Callback handling data */
61c39f54 668static int prepare_data(int fd, int revents, void *cb_data)
85b5af06 669{
61c39f54
BV
670 struct sr_dev_inst *sdi;
671 struct dev_context *devc;
b9c735a2 672 struct sr_datafeed_packet packet;
9c939c51 673 struct sr_datafeed_logic logic;
8b2d41ed 674 struct analog_gen *ag;
49224c28
BV
675 GHashTableIter iter;
676 void *value;
b62bb97a 677 uint64_t logic_todo, analog_todo, expected_samplenum, analog_sent, sending_now;
3b203673 678 int64_t time, elapsed;
1924f59f 679
cb93f8a9
UH
680 (void)fd;
681 (void)revents;
1924f59f 682
61c39f54
BV
683 sdi = cb_data;
684 devc = sdi->priv;
b62bb97a 685 logic_todo = analog_todo = 0;
61c39f54 686
b62bb97a 687 /* How many samples should we have sent by now? */
3b203673
AG
688 time = g_get_monotonic_time();
689 elapsed = time - devc->starttime;
a7684294 690 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
7f4975b4 691
b62bb97a
BV
692 /* But never more than the limit, if there is one. */
693 if (!devc->continuous)
694 expected_samplenum = MIN(expected_samplenum, devc->limit_samples);
695
3b203673 696 /* Of those, how many do we still have to send? */
b62bb97a
BV
697 if (devc->num_logic_channels)
698 logic_todo = expected_samplenum - devc->logic_counter;
699 if (devc->num_analog_channels)
700 analog_todo = expected_samplenum - devc->analog_counter;
85b5af06 701
7f4975b4 702 while (logic_todo || analog_todo) {
c07f60e7 703 /* Logic */
b62bb97a
BV
704 if (logic_todo > 0) {
705 sending_now = MIN(logic_todo, LOGIC_BUFSIZE / devc->logic_unitsize);
8b2d41ed
BV
706 logic_generator(sdi, sending_now * devc->logic_unitsize);
707 packet.type = SR_DF_LOGIC;
708 packet.payload = &logic;
709 logic.length = sending_now * devc->logic_unitsize;
710 logic.unitsize = devc->logic_unitsize;
711 logic.data = devc->logic_data;
712 sr_session_send(sdi, &packet);
7f4975b4
BV
713 logic_todo -= sending_now;
714 devc->logic_counter += sending_now;
8b2d41ed
BV
715 }
716
ba7dd8bb 717 /* Analog, one channel at a time */
b62bb97a
BV
718 if (analog_todo > 0) {
719 analog_sent = 0;
49224c28
BV
720
721 g_hash_table_iter_init(&iter, devc->ch_ag);
722 while (g_hash_table_iter_next(&iter, NULL, &value)) {
723 ag = value;
8b2d41ed
BV
724 packet.type = SR_DF_ANALOG;
725 packet.payload = &ag->packet;
4374219b
DJ
726
727 /* FIXME we should make sure we output a whole
728 * period of data before we send out again the
729 * beginning of our buffer. A ring buffer would
730 * help here as well */
731
b62bb97a
BV
732 sending_now = MIN(analog_todo, ag->num_samples);
733 ag->packet.num_samples = sending_now;
8b2d41ed 734 sr_session_send(sdi, &packet);
b62bb97a
BV
735
736 /* Whichever channel group gets there first. */
737 analog_sent = MAX(analog_sent, sending_now);
8b2d41ed 738 }
b62bb97a
BV
739 analog_todo -= analog_sent;
740 devc->analog_counter += analog_sent;
8b2d41ed 741 }
3b203673
AG
742 }
743
b62bb97a
BV
744 if (!devc->continuous
745 && (!devc->num_logic_channels || devc->logic_counter >= devc->limit_samples)
746 && (!devc->num_analog_channels || devc->analog_counter >= devc->limit_samples)) {
7f4975b4 747 sr_dbg("Requested number of samples reached.");
61c39f54 748 dev_acquisition_stop(sdi, cb_data);
c216d623 749 return TRUE;
85b5af06 750 }
1924f59f 751
85b5af06
UH
752 return TRUE;
753}
754
6078d2c9 755static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
6239c175 756{
61c39f54 757 struct dev_context *devc;
49224c28
BV
758 GHashTableIter iter;
759 void *value;
85b5af06 760
102f1239
BV
761 (void)cb_data;
762
e73ffd42
BV
763 if (sdi->status != SR_ST_ACTIVE)
764 return SR_ERR_DEV_CLOSED;
765
61c39f54 766 devc = sdi->priv;
b62bb97a 767 devc->continuous = !devc->limit_samples;
7f4975b4 768 devc->logic_counter = devc->analog_counter = 0;
85b5af06 769
3b203673
AG
770 /*
771 * Setting two channels connected by a pipe is a remnant from when the
772 * demo driver generated data in a thread, and collected and sent the
773 * data in the main program loop.
774 * They are kept here because it provides a convenient way of setting
775 * up a timeout-based polling mechanism.
776 */
b4750a3a 777 if (pipe(devc->pipe_fds)) {
92bcedf6 778 sr_err("%s: pipe() failed", __func__);
e46b8fb1 779 return SR_ERR;
c03ed397 780 }
85b5af06 781
49224c28
BV
782 g_hash_table_iter_init(&iter, devc->ch_ag);
783 while (g_hash_table_iter_next(&iter, NULL, &value))
784 generate_analog_pattern(value, devc->cur_samplerate);
4374219b 785
e0532047 786 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
e0532047 787 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 788
d35aaf02 789 /* Set channel encoding to binary (default is UTF-8). */
e0532047 790 g_io_channel_set_encoding(devc->channel, NULL, NULL);
d35aaf02 791
b62bb97a 792 /* Make channels unbuffered. */
e0532047 793 g_io_channel_set_buffered(devc->channel, FALSE);
d35aaf02 794
b62bb97a
BV
795 sr_session_source_add_channel(sdi->session, devc->channel,
796 G_IO_IN | G_IO_ERR, 40, prepare_data, (void *)sdi);
85b5af06 797
4afdfd46 798 /* Send header packet to the session bus. */
102f1239 799 std_session_send_df_header(sdi, LOG_PREFIX);
f366e86c 800
3b203673
AG
801 /* We use this timestamp to decide how many more samples to send. */
802 devc->starttime = g_get_monotonic_time();
803
e46b8fb1 804 return SR_OK;
6239c175
UH
805}
806
6078d2c9 807static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 808{
8b2d41ed 809 struct dev_context *devc;
c216d623 810 struct sr_datafeed_packet packet;
7fd3e859 811
33ef7573 812 (void)cb_data;
7fd3e859 813
8b2d41ed 814 devc = sdi->priv;
a84f6ad3 815 sr_dbg("Stopping acquisition.");
49145a63 816
102f1239 817 sr_session_source_remove_channel(sdi->session, devc->channel);
e0532047 818 g_io_channel_shutdown(devc->channel, FALSE, NULL);
2150a69b
JH
819 g_io_channel_unref(devc->channel);
820 devc->channel = NULL;
c216d623
AG
821
822 /* Send last packet. */
823 packet.type = SR_DF_END;
c07f60e7 824 sr_session_send(sdi, &packet);
7fd3e859 825
3010f21c 826 return SR_OK;
6239c175
UH
827}
828
c09f0b57 829SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
830 .name = "demo",
831 .longname = "Demo driver and pattern generator",
832 .api_version = 1,
6078d2c9
UH
833 .init = init,
834 .cleanup = cleanup,
835 .scan = scan,
836 .dev_list = dev_list,
a6630742 837 .dev_clear = NULL,
035a1078
BV
838 .config_get = config_get,
839 .config_set = config_set,
a1c743fc 840 .config_list = config_list,
6078d2c9
UH
841 .dev_open = dev_open,
842 .dev_close = dev_close,
843 .dev_acquisition_start = dev_acquisition_start,
844 .dev_acquisition_stop = dev_acquisition_stop,
b4750a3a 845 .priv = NULL,
6239c175 846};