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