]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
Replace 'probe' with 'channel' in most places.
[libsigrok.git] / 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
c07f60e7
BV
37#define DEFAULT_NUM_LOGIC_PROBES 8
38#define DEFAULT_NUM_ANALOG_PROBES 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
4374219b
DJ
45#define ANALOG_AMPLITUDE 25
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.
ba7dd8bb 53 * The pattern is repeasted 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 /**
ba7dd8bb
UH
62 * Incrementing number across 8 channels. The pattern is repeasted
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;
102 float pattern_data[ANALOG_BUFSIZE];
103 unsigned int num_samples;
104 struct sr_datafeed_analog packet;
105};
106
b4750a3a
BV
107/* Private, per-device-instance driver context. */
108struct dev_context {
e15f48c2 109 int pipe_fds[2];
e0532047 110 GIOChannel *channel;
a7684294
JH
111 uint64_t cur_samplerate;
112 uint64_t limit_samples;
113 uint64_t limit_msec;
7f4975b4
BV
114 uint64_t logic_counter;
115 uint64_t analog_counter;
3b203673 116 int64_t starttime;
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;
660e398f 126 GSList *analog_channel_groups;
c07f60e7
BV
127};
128
7a1da331 129static const int32_t scanopts[] = {
c07f60e7
BV
130 SR_CONF_NUM_LOGIC_PROBES,
131 SR_CONF_NUM_ANALOG_PROBES,
e15f48c2 132};
85b5af06 133
7a1da331 134static const int devopts[] = {
1953564a
BV
135 SR_CONF_LOGIC_ANALYZER,
136 SR_CONF_DEMO_DEV,
137 SR_CONF_SAMPLERATE,
1953564a
BV
138 SR_CONF_LIMIT_SAMPLES,
139 SR_CONF_LIMIT_MSEC,
6239c175
UH
140};
141
40fd0264 142static const int devopts_cg[] = {
7a1da331
BV
143 SR_CONF_PATTERN_MODE,
144};
145
d00088ca
BV
146static const uint64_t samplerates[] = {
147 SR_HZ(1),
148 SR_GHZ(1),
149 SR_HZ(1),
4bfbf9fc
BV
150};
151
c8f4624d 152static uint8_t pattern_sigrok[] = {
917e0e71
BV
153 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
154 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
155 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
156 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
157 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
158 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161};
162
dcf03d6d 163SR_PRIV struct sr_dev_driver demo_driver_info;
a873c594 164static struct sr_dev_driver *di = &demo_driver_info;
6239c175 165
6078d2c9 166static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 167
c07f60e7 168
6078d2c9 169static int init(struct sr_context *sr_ctx)
61136ea6 170{
f6beaac5 171 return std_init(sr_ctx, di, LOG_PREFIX);
61136ea6
BV
172}
173
53b4680f 174static void generate_analog_pattern(const struct sr_channel_group *cg, uint64_t sample_rate)
8b2d41ed
BV
175{
176 struct analog_gen *ag;
4374219b 177 double t, frequency;
8b2d41ed
BV
178 float value;
179 unsigned int num_samples, i;
180 int last_end;
181
53b4680f 182 ag = cg->priv;
4374219b
DJ
183 num_samples = ANALOG_BUFSIZE / sizeof(float);
184
660e398f 185 sr_dbg("Generating %s pattern for channel group %s",
53b4680f 186 analog_pattern_str[ag->pattern], cg->name);
8b2d41ed 187
4374219b 188 switch (ag->pattern) {
8b2d41ed 189 case PATTERN_SQUARE:
2438b737 190 value = ANALOG_AMPLITUDE;
8b2d41ed
BV
191 last_end = 0;
192 for (i = 0; i < num_samples; i++) {
193 if (i % 5 == 0)
194 value = -value;
195 if (i % 10 == 0)
196 last_end = i - 1;
197 ag->pattern_data[i] = value;
198 }
199 ag->num_samples = last_end;
200 break;
4374219b
DJ
201
202 case PATTERN_SINE:
9d156555 203 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
4374219b
DJ
204
205 /* Make sure the number of samples we put out is an integer
206 * multiple of our period size */
207 /* FIXME we actually need only one period. A ringbuffer would be
208 * usefull here.*/
209 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
210 num_samples--;
211
212 for (i = 0; i < num_samples; i++) {
213 t = (double) i / (double) sample_rate;
214 ag->pattern_data[i] = ANALOG_AMPLITUDE *
215 sin(2 * M_PI * frequency * t);
216 }
217
091c9621
DJ
218 ag->num_samples = num_samples;
219 break;
220
221 case PATTERN_TRIANGLE:
9d156555 222 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
091c9621
DJ
223
224 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
225 num_samples--;
226
227 for (i = 0; i < num_samples; i++) {
228 t = (double) i / (double) sample_rate;
229 ag->pattern_data[i] = (2 * ANALOG_AMPLITUDE / M_PI) *
230 asin(sin(2 * M_PI * frequency * t));
231 }
232
9f54e0e8
DJ
233 ag->num_samples = num_samples;
234 break;
235
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;
244 ag->pattern_data[i] = 2 * ANALOG_AMPLITUDE *
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
6078d2c9 253static GSList *scan(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;
40fd0264 259 struct sr_channel_group *cg;
c07f60e7 260 struct sr_config *src;
8b2d41ed 261 struct analog_gen *ag;
c07f60e7 262 GSList *devices, *l;
ba7dd8bb
UH
263 int num_logic_channels, num_analog_channels, pattern, i;
264 char channel_name[16];
067d0716 265
a873c594 266 drvc = di->priv;
4b97c74e 267
ba7dd8bb
UH
268 num_logic_channels = DEFAULT_NUM_LOGIC_PROBES;
269 num_analog_channels = DEFAULT_NUM_ANALOG_PROBES;
c07f60e7
BV
270 for (l = options; l; l = l->next) {
271 src = l->data;
272 switch (src->key) {
273 case SR_CONF_NUM_LOGIC_PROBES:
ba7dd8bb 274 num_logic_channels = g_variant_get_int32(src->data);
c07f60e7
BV
275 break;
276 case SR_CONF_NUM_ANALOG_PROBES:
ba7dd8bb 277 num_analog_channels = g_variant_get_int32(src->data);
c07f60e7
BV
278 break;
279 }
280 }
85b5af06 281
c07f60e7 282 devices = NULL;
61c39f54 283 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, "Demo device", NULL, NULL);
c03ed397 284 if (!sdi) {
e45ad6e2
UH
285 sr_err("Device instance creation failed.");
286 return NULL;
c03ed397 287 }
a873c594 288 sdi->driver = di;
e15f48c2 289
8b2d41ed
BV
290 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
291 sr_err("Device context malloc failed.");
292 return NULL;
293 }
294 devc->cur_samplerate = SR_KHZ(200);
295 devc->limit_samples = 0;
296 devc->limit_msec = 0;
297 devc->step = 0;
ba7dd8bb
UH
298 devc->num_logic_channels = num_logic_channels;
299 devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
8b2d41ed 300 devc->logic_pattern = PATTERN_SIGROK;
ba7dd8bb 301 devc->num_analog_channels = num_analog_channels;
660e398f 302 devc->analog_channel_groups = NULL;
8b2d41ed 303
ba7dd8bb 304 /* Logic channels, all in one channel group. */
40fd0264 305 if (!(cg = g_try_malloc(sizeof(struct sr_channel_group))))
8b2d41ed 306 return NULL;
40fd0264 307 cg->name = g_strdup("Logic");
a68bf88e 308 cg->channels = NULL;
40fd0264 309 cg->priv = NULL;
ba7dd8bb
UH
310 for (i = 0; i < num_logic_channels; i++) {
311 sprintf(channel_name, "D%d", i);
312 if (!(ch = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name)))
87ca93c5 313 return NULL;
ba7dd8bb
UH
314 sdi->channels = g_slist_append(sdi->channels, ch);
315 cg->channels = g_slist_append(cg->channels, ch);
87ca93c5 316 }
40fd0264 317 sdi->channel_groups = g_slist_append(NULL, cg);
87ca93c5 318
ba7dd8bb 319 /* Analog channels, channel groups and pattern generators. */
2b36d6c6
BV
320
321 pattern = 0;
ba7dd8bb
UH
322 for (i = 0; i < num_analog_channels; i++) {
323 sprintf(channel_name, "A%d", i);
324 if (!(ch = sr_probe_new(i + num_logic_channels,
325 SR_PROBE_ANALOG, TRUE, channel_name)))
c07f60e7 326 return NULL;
ba7dd8bb 327 sdi->channels = g_slist_append(sdi->channels, ch);
c07f60e7 328
ba7dd8bb 329 /* Every analog channel gets its own channel group. */
40fd0264 330 if (!(cg = g_try_malloc(sizeof(struct sr_channel_group))))
8b2d41ed 331 return NULL;
ba7dd8bb
UH
332 cg->name = g_strdup(channel_name);
333 cg->channels = g_slist_append(NULL, ch);
85b5af06 334
660e398f 335 /* Every channel group gets a generator struct. */
8b2d41ed
BV
336 if (!(ag = g_try_malloc(sizeof(struct analog_gen))))
337 return NULL;
ba7dd8bb 338 ag->packet.channels = cg->channels;
8b2d41ed
BV
339 ag->packet.mq = 0;
340 ag->packet.mqflags = 0;
341 ag->packet.unit = SR_UNIT_VOLT;
342 ag->packet.data = ag->pattern_data;
2b36d6c6 343 ag->pattern = pattern;
40fd0264 344 cg->priv = ag;
8b2d41ed 345
40fd0264
UH
346 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
347 devc->analog_channel_groups = g_slist_append(devc->analog_channel_groups, cg);
2b36d6c6
BV
348
349 if (++pattern == ARRAY_SIZE(analog_pattern_str))
350 pattern = 0;
33ef7573 351 }
33ef7573
JH
352
353 sdi->priv = devc;
8b2d41ed
BV
354 devices = g_slist_append(devices, sdi);
355 drvc->instances = g_slist_append(drvc->instances, sdi);
33ef7573 356
067d0716 357 return devices;
6239c175
UH
358}
359
6078d2c9 360static GSList *dev_list(void)
811deee4 361{
0e94d524 362 return ((struct drv_context *)(di->priv))->instances;
811deee4
BV
363}
364
6078d2c9 365static int dev_open(struct sr_dev_inst *sdi)
6239c175 366{
e73ffd42 367 sdi->status = SR_ST_ACTIVE;
697785d1 368
e46b8fb1 369 return SR_OK;
6239c175
UH
370}
371
6078d2c9 372static int dev_close(struct sr_dev_inst *sdi)
6239c175 373{
decfe89d 374 sdi->status = SR_ST_INACTIVE;
697785d1
UH
375
376 return SR_OK;
6239c175
UH
377}
378
6078d2c9 379static int cleanup(void)
6239c175 380{
a6630742 381 return std_dev_clear(di, NULL);
6239c175
UH
382}
383
8f996b89 384static int config_get(int id, 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;
035a1078 396 switch (id) {
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
BV
405 break;
406 case SR_CONF_PATTERN_MODE:
53b4680f 407 if (!cg)
660e398f 408 return SR_ERR_CHANNEL_GROUP;
ba7dd8bb
UH
409 ch = cg->channels->data;
410 if (ch->type == SR_PROBE_LOGIC) {
2388ae86
BV
411 pattern = devc->logic_pattern;
412 *data = g_variant_new_string(logic_pattern_str[pattern]);
ba7dd8bb 413 } else if (ch->type == SR_PROBE_ANALOG) {
53b4680f 414 ag = cg->priv;
2388ae86
BV
415 pattern = ag->pattern;
416 *data = g_variant_new_string(analog_pattern_str[pattern]);
417 } else
418 return SR_ERR_BUG;
c07f60e7
BV
419 break;
420 case SR_CONF_NUM_LOGIC_PROBES:
ba7dd8bb 421 *data = g_variant_new_int32(devc->num_logic_channels);
c07f60e7
BV
422 break;
423 case SR_CONF_NUM_ANALOG_PROBES:
ba7dd8bb 424 *data = g_variant_new_int32(devc->num_analog_channels);
2474d87e 425 break;
7dfcf010 426 default:
bd6fbf62 427 return SR_ERR_NA;
6239c175
UH
428 }
429
dfb0fa1a 430 return SR_OK;
6239c175
UH
431}
432
8f996b89 433static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 434 const struct sr_channel_group *cg)
6239c175 435{
8b2d41ed 436 struct dev_context *devc;
4374219b 437 struct analog_gen *ag;
ba7dd8bb 438 struct sr_channel *ch;
2388ae86 439 int pattern, ret;
61c39f54 440 unsigned int i;
1b79df2f 441 const char *stropt;
6239c175 442
8b2d41ed 443 devc = sdi->priv;
6239c175 444
e73ffd42
BV
445 if (sdi->status != SR_ST_ACTIVE)
446 return SR_ERR_DEV_CLOSED;
447
2388ae86
BV
448 ret = SR_OK;
449 switch (id) {
450 case SR_CONF_SAMPLERATE:
a7684294 451 devc->cur_samplerate = g_variant_get_uint64(data);
61c39f54 452 sr_dbg("Setting samplerate to %" PRIu64, devc->cur_samplerate);
2388ae86
BV
453 break;
454 case SR_CONF_LIMIT_SAMPLES:
a7684294
JH
455 devc->limit_msec = 0;
456 devc->limit_samples = g_variant_get_uint64(data);
8b2d41ed 457 sr_dbg("Setting sample limit to %" PRIu64, devc->limit_samples);
2388ae86
BV
458 break;
459 case SR_CONF_LIMIT_MSEC:
a7684294
JH
460 devc->limit_msec = g_variant_get_uint64(data);
461 devc->limit_samples = 0;
8b2d41ed 462 sr_dbg("Setting time limit to %" PRIu64"ms", devc->limit_msec);
2388ae86
BV
463 break;
464 case SR_CONF_PATTERN_MODE:
53b4680f 465 if (!cg)
660e398f 466 return SR_ERR_CHANNEL_GROUP;
d00088ca 467 stropt = g_variant_get_string(data, NULL);
ba7dd8bb 468 ch = cg->channels->data;
2388ae86 469 pattern = -1;
ba7dd8bb 470 if (ch->type == SR_PROBE_LOGIC) {
2388ae86
BV
471 for (i = 0; i < ARRAY_SIZE(logic_pattern_str); i++) {
472 if (!strcmp(stropt, logic_pattern_str[i])) {
473 pattern = i;
8b2d41ed
BV
474 break;
475 }
476 }
2388ae86
BV
477 if (pattern == -1)
478 return SR_ERR_ARG;
479 devc->logic_pattern = pattern;
480
481 /* Might as well do this now, these are static. */
482 if (pattern == PATTERN_ALL_LOW)
8b2d41ed 483 memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
2388ae86 484 else if (pattern == PATTERN_ALL_HIGH)
8b2d41ed 485 memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
2388ae86
BV
486 sr_dbg("Setting logic pattern to %s",
487 logic_pattern_str[pattern]);
ba7dd8bb 488 } else if (ch->type == SR_PROBE_ANALOG) {
2388ae86
BV
489 for (i = 0; i < ARRAY_SIZE(analog_pattern_str); i++) {
490 if (!strcmp(stropt, analog_pattern_str[i])) {
491 pattern = i;
492 break;
8b2d41ed 493 }
8b2d41ed 494 }
2388ae86
BV
495 if (pattern == -1)
496 return SR_ERR_ARG;
660e398f 497 sr_dbg("Setting analog pattern for channel group %s to %s",
53b4680f
UH
498 cg->name, analog_pattern_str[pattern]);
499 ag = cg->priv;
4374219b 500 ag->pattern = pattern;
2388ae86
BV
501 } else
502 return SR_ERR_BUG;
503 break;
504 default:
bd6fbf62 505 ret = SR_ERR_NA;
6239c175
UH
506 }
507
508 return ret;
509}
510
8f996b89 511static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 512 const struct sr_channel_group *cg)
a1c743fc 513{
ba7dd8bb 514 struct sr_channel *ch;
d00088ca
BV
515 GVariant *gvar;
516 GVariantBuilder gvb;
a1c743fc
BV
517
518 (void)sdi;
519
7a1da331 520 if (key == SR_CONF_SCAN_OPTIONS) {
c07f60e7 521 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
7a1da331
BV
522 scanopts, ARRAY_SIZE(scanopts), sizeof(int32_t));
523 return SR_OK;
524 }
525
526 if (!sdi)
527 return SR_ERR_ARG;
528
53b4680f 529 if (!cg) {
7a1da331
BV
530 switch (key) {
531 case SR_CONF_DEVICE_OPTIONS:
532 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
533 devopts, ARRAY_SIZE(devopts), sizeof(int32_t));
534 break;
535 case SR_CONF_SAMPLERATE:
536 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
537 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
538 ARRAY_SIZE(samplerates), sizeof(uint64_t));
539 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
540 *data = g_variant_builder_end(&gvb);
541 break;
542 default:
543 return SR_ERR_NA;
544 }
545 } else {
ba7dd8bb 546 ch = cg->channels->data;
7a1da331
BV
547 switch (key) {
548 case SR_CONF_DEVICE_OPTIONS:
549 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
40fd0264 550 devopts_cg, ARRAY_SIZE(devopts_cg), sizeof(int32_t));
7a1da331
BV
551 break;
552 case SR_CONF_PATTERN_MODE:
ba7dd8bb 553 if (ch->type == SR_PROBE_LOGIC)
7a1da331
BV
554 *data = g_variant_new_strv(logic_pattern_str,
555 ARRAY_SIZE(logic_pattern_str));
ba7dd8bb 556 else if (ch->type == SR_PROBE_ANALOG)
7a1da331
BV
557 *data = g_variant_new_strv(analog_pattern_str,
558 ARRAY_SIZE(analog_pattern_str));
2388ae86
BV
559 else
560 return SR_ERR_BUG;
7a1da331
BV
561 break;
562 default:
563 return SR_ERR_NA;
564 }
a1c743fc
BV
565 }
566
567 return SR_OK;
568}
569
c07f60e7 570static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
85b5af06 571{
61c39f54 572 struct dev_context *devc;
c07f60e7
BV
573 uint64_t i, j;
574 uint8_t pat;
85b5af06 575
61c39f54 576 devc = sdi->priv;
85b5af06 577
c07f60e7 578 switch (devc->logic_pattern) {
61c39f54 579 case PATTERN_SIGROK:
c07f60e7
BV
580 memset(devc->logic_data, 0x00, size);
581 for (i = 0; i < size; i += devc->logic_unitsize) {
582 for (j = 0; j < devc->logic_unitsize; j++) {
583 pat = pattern_sigrok[(devc->step + j) % sizeof(pattern_sigrok)] >> 1;
584 devc->logic_data[i + j] = ~pat;
585 }
586 devc->step++;
917e0e71
BV
587 }
588 break;
61c39f54 589 case PATTERN_RANDOM:
5096c6a6 590 for (i = 0; i < size; i++)
61c39f54 591 devc->logic_data[i] = (uint8_t)(rand() & 0xff);
85b5af06 592 break;
61c39f54 593 case PATTERN_INC:
c07f60e7
BV
594 for (i = 0; i < size; i++) {
595 for (j = 0; j < devc->logic_unitsize; j++) {
596 devc->logic_data[i + j] = devc->step;
597 }
598 devc->step++;
599 }
c03ed397 600 break;
61c39f54
BV
601 case PATTERN_ALL_LOW:
602 case PATTERN_ALL_HIGH:
603 /* These were set when the pattern mode was selected. */
c03ed397
UH
604 break;
605 default:
c07f60e7 606 sr_err("Unknown pattern: %d.", devc->logic_pattern);
c03ed397 607 break;
85b5af06
UH
608 }
609}
610
85b5af06 611/* Callback handling data */
61c39f54 612static int prepare_data(int fd, int revents, void *cb_data)
85b5af06 613{
61c39f54
BV
614 struct sr_dev_inst *sdi;
615 struct dev_context *devc;
b9c735a2 616 struct sr_datafeed_packet packet;
9c939c51 617 struct sr_datafeed_logic logic;
40fd0264 618 struct sr_channel_group *cg;
8b2d41ed
BV
619 struct analog_gen *ag;
620 GSList *l;
7f4975b4 621 uint64_t logic_todo, analog_todo, expected_samplenum, analog_samples, sending_now;
3b203673 622 int64_t time, elapsed;
1924f59f 623
cb93f8a9
UH
624 (void)fd;
625 (void)revents;
1924f59f 626
61c39f54
BV
627 sdi = cb_data;
628 devc = sdi->priv;
629
3b203673
AG
630 /* How many "virtual" samples should we have collected by now? */
631 time = g_get_monotonic_time();
632 elapsed = time - devc->starttime;
a7684294 633 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
7f4975b4 634
3b203673 635 /* Of those, how many do we still have to send? */
fe90fbb7
BV
636 logic_todo = MIN(expected_samplenum, devc->limit_samples) - devc->logic_counter;
637 analog_todo = MIN(expected_samplenum, devc->limit_samples) - devc->analog_counter;
85b5af06 638
7f4975b4 639 while (logic_todo || analog_todo) {
c07f60e7 640 /* Logic */
ba7dd8bb 641 if (devc->num_logic_channels > 0 && logic_todo > 0) {
7f4975b4 642 sending_now = MIN(logic_todo,
8b2d41ed
BV
643 LOGIC_BUFSIZE / devc->logic_unitsize);
644 logic_generator(sdi, sending_now * devc->logic_unitsize);
645 packet.type = SR_DF_LOGIC;
646 packet.payload = &logic;
647 logic.length = sending_now * devc->logic_unitsize;
648 logic.unitsize = devc->logic_unitsize;
649 logic.data = devc->logic_data;
650 sr_session_send(sdi, &packet);
7f4975b4
BV
651 logic_todo -= sending_now;
652 devc->logic_counter += sending_now;
8b2d41ed
BV
653 }
654
ba7dd8bb
UH
655 /* Analog, one channel at a time */
656 if (devc->num_analog_channels > 0 && analog_todo > 0) {
8b2d41ed 657 sending_now = 0;
660e398f 658 for (l = devc->analog_channel_groups; l; l = l->next) {
40fd0264
UH
659 cg = l->data;
660 ag = cg->priv;
8b2d41ed
BV
661 packet.type = SR_DF_ANALOG;
662 packet.payload = &ag->packet;
4374219b
DJ
663
664 /* FIXME we should make sure we output a whole
665 * period of data before we send out again the
666 * beginning of our buffer. A ring buffer would
667 * help here as well */
668
7f4975b4 669 analog_samples = MIN(analog_todo, ag->num_samples);
660e398f 670 /* Whichever channel group gets there first. */
8b2d41ed
BV
671 sending_now = MAX(sending_now, analog_samples);
672 ag->packet.num_samples = analog_samples;
673 sr_session_send(sdi, &packet);
674 }
7f4975b4
BV
675 analog_todo -= sending_now;
676 devc->analog_counter += sending_now;
8b2d41ed 677 }
3b203673
AG
678 }
679
fe90fbb7 680 if (devc->logic_counter >= devc->limit_samples &&
7f4975b4
BV
681 devc->analog_counter >= devc->limit_samples) {
682 sr_dbg("Requested number of samples reached.");
61c39f54 683 dev_acquisition_stop(sdi, cb_data);
c216d623 684 return TRUE;
85b5af06 685 }
1924f59f 686
85b5af06
UH
687 return TRUE;
688}
689
6078d2c9 690static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
6239c175 691{
4374219b 692 GSList *l;
61c39f54 693 struct dev_context *devc;
85b5af06 694
e73ffd42
BV
695 if (sdi->status != SR_ST_ACTIVE)
696 return SR_ERR_DEV_CLOSED;
697
61c39f54 698 devc = sdi->priv;
fe90fbb7
BV
699 if (devc->limit_samples == 0)
700 return SR_ERR;
7f4975b4 701 devc->logic_counter = devc->analog_counter = 0;
85b5af06 702
3b203673
AG
703 /*
704 * Setting two channels connected by a pipe is a remnant from when the
705 * demo driver generated data in a thread, and collected and sent the
706 * data in the main program loop.
707 * They are kept here because it provides a convenient way of setting
708 * up a timeout-based polling mechanism.
709 */
b4750a3a 710 if (pipe(devc->pipe_fds)) {
92bcedf6 711 sr_err("%s: pipe() failed", __func__);
e46b8fb1 712 return SR_ERR;
c03ed397 713 }
85b5af06 714
660e398f 715 for (l = devc->analog_channel_groups; l; l = l->next) {
4374219b
DJ
716 generate_analog_pattern(l->data, devc->cur_samplerate);
717 }
718
e0532047 719 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
d35aaf02 720
e0532047 721 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 722
d35aaf02 723 /* Set channel encoding to binary (default is UTF-8). */
e0532047 724 g_io_channel_set_encoding(devc->channel, NULL, NULL);
d35aaf02
UH
725
726 /* Make channels to unbuffered. */
e0532047 727 g_io_channel_set_buffered(devc->channel, FALSE);
d35aaf02 728
e0532047 729 sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
61c39f54 730 40, prepare_data, (void *)sdi);
85b5af06 731
4afdfd46 732 /* Send header packet to the session bus. */
29a27196 733 std_session_send_df_header(cb_data, LOG_PREFIX);
f366e86c 734
3b203673
AG
735 /* We use this timestamp to decide how many more samples to send. */
736 devc->starttime = g_get_monotonic_time();
737
e46b8fb1 738 return SR_OK;
6239c175
UH
739}
740
6078d2c9 741static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 742{
8b2d41ed 743 struct dev_context *devc;
c216d623 744 struct sr_datafeed_packet packet;
7fd3e859 745
33ef7573 746 (void)cb_data;
7fd3e859 747
8b2d41ed 748 devc = sdi->priv;
a84f6ad3 749 sr_dbg("Stopping acquisition.");
49145a63 750
e0532047
JH
751 sr_session_source_remove_channel(devc->channel);
752 g_io_channel_shutdown(devc->channel, FALSE, NULL);
2150a69b
JH
753 g_io_channel_unref(devc->channel);
754 devc->channel = NULL;
c216d623
AG
755
756 /* Send last packet. */
757 packet.type = SR_DF_END;
c07f60e7 758 sr_session_send(sdi, &packet);
7fd3e859 759
3010f21c 760 return SR_OK;
6239c175
UH
761}
762
c09f0b57 763SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
764 .name = "demo",
765 .longname = "Demo driver and pattern generator",
766 .api_version = 1,
6078d2c9
UH
767 .init = init,
768 .cleanup = cleanup,
769 .scan = scan,
770 .dev_list = dev_list,
a6630742 771 .dev_clear = NULL,
035a1078
BV
772 .config_get = config_get,
773 .config_set = config_set,
a1c743fc 774 .config_list = config_list,
6078d2c9
UH
775 .dev_open = dev_open,
776 .dev_close = dev_close,
777 .dev_acquisition_start = dev_acquisition_start,
778 .dev_acquisition_stop = dev_acquisition_stop,
b4750a3a 779 .priv = NULL,
6239c175 780};