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