]> sigrok.org Git - libsigrok.git/blame_incremental - src/hardware/demo/demo.c
scan(): Consistently start out with SR_ST_INACTIVE.
[libsigrok.git] / src / hardware / demo / demo.c
... / ...
CommitLineData
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
6 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7 * Copyright (C) 2015 Bartosz Golaszewski <bgolaszewski@baylibre.com>
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 <config.h>
25#include <stdlib.h>
26#include <string.h>
27#include <math.h>
28#include <libsigrok/libsigrok.h>
29#include "libsigrok-internal.h"
30
31#define LOG_PREFIX "demo"
32
33#define DEFAULT_NUM_LOGIC_CHANNELS 8
34#define DEFAULT_NUM_ANALOG_CHANNELS 4
35
36/* The size in bytes of chunks to send through the session bus. */
37#define LOGIC_BUFSIZE 4096
38/* Size of the analog pattern space per channel. */
39#define ANALOG_BUFSIZE 4096
40
41#define DEFAULT_ANALOG_AMPLITUDE 10
42#define ANALOG_SAMPLES_PER_PERIOD 20
43
44/* Logic patterns we can generate. */
45enum {
46 /**
47 * Spells "sigrok" across 8 channels using '0's (with '1's as
48 * "background") when displayed using the 'bits' output format.
49 * The pattern is repeated every 8 channels, shifted to the right
50 * in time by one bit.
51 */
52 PATTERN_SIGROK,
53
54 /** Pseudo-random values on all channels. */
55 PATTERN_RANDOM,
56
57 /**
58 * Incrementing number across 8 channels. The pattern is repeated
59 * every 8 channels, shifted to the right in time by one bit.
60 */
61 PATTERN_INC,
62
63 /** All channels have a low logic state. */
64 PATTERN_ALL_LOW,
65
66 /** All channels have a high logic state. */
67 PATTERN_ALL_HIGH,
68};
69
70/* Analog patterns we can generate. */
71enum {
72 /**
73 * Square wave.
74 */
75 PATTERN_SQUARE,
76 PATTERN_SINE,
77 PATTERN_TRIANGLE,
78 PATTERN_SAWTOOTH,
79};
80
81static const char *logic_pattern_str[] = {
82 "sigrok",
83 "random",
84 "incremental",
85 "all-low",
86 "all-high",
87};
88
89static const char *analog_pattern_str[] = {
90 "square",
91 "sine",
92 "triangle",
93 "sawtooth",
94};
95
96struct analog_gen {
97 int pattern;
98 float amplitude;
99 float pattern_data[ANALOG_BUFSIZE];
100 unsigned int num_samples;
101 struct sr_datafeed_analog_old packet;
102 float avg_val; /* Average value */
103 unsigned num_avgs; /* Number of samples averaged */
104};
105
106/* Private, per-device-instance driver context. */
107struct dev_context {
108 uint64_t cur_samplerate;
109 uint64_t limit_samples;
110 uint64_t limit_msec;
111 uint64_t sent_samples;
112 int64_t start_us;
113 int64_t spent_us;
114 uint64_t step;
115 /* Logic */
116 int32_t num_logic_channels;
117 unsigned int logic_unitsize;
118 /* There is only ever one logic channel group, so its pattern goes here. */
119 uint8_t logic_pattern;
120 unsigned char logic_data[LOGIC_BUFSIZE];
121 /* Analog */
122 int32_t num_analog_channels;
123 GHashTable *ch_ag;
124 gboolean avg; /* True if averaging is enabled */
125 uint64_t avg_samples;
126};
127
128static const uint32_t drvopts[] = {
129 SR_CONF_DEMO_DEV,
130 SR_CONF_LOGIC_ANALYZER,
131 SR_CONF_OSCILLOSCOPE,
132};
133
134static const uint32_t scanopts[] = {
135 SR_CONF_NUM_LOGIC_CHANNELS,
136 SR_CONF_NUM_ANALOG_CHANNELS,
137};
138
139static const uint32_t devopts[] = {
140 SR_CONF_CONTINUOUS,
141 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
142 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
143 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
144 SR_CONF_AVERAGING | SR_CONF_GET | SR_CONF_SET,
145 SR_CONF_AVG_SAMPLES | SR_CONF_GET | SR_CONF_SET,
146};
147
148static const uint32_t devopts_cg_logic[] = {
149 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
150};
151
152static const uint32_t devopts_cg_analog_group[] = {
153 SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
154};
155
156static const uint32_t devopts_cg_analog_channel[] = {
157 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
158 SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
159};
160
161static const uint64_t samplerates[] = {
162 SR_HZ(1),
163 SR_GHZ(1),
164 SR_HZ(1),
165};
166
167static const uint8_t pattern_sigrok[] = {
168 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
169 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
170 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
171 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
172 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
173 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176};
177
178SR_PRIV struct sr_dev_driver demo_driver_info;
179
180static int dev_acquisition_stop(struct sr_dev_inst *sdi);
181
182static void generate_analog_pattern(struct analog_gen *ag, uint64_t sample_rate)
183{
184 double t, frequency;
185 float value;
186 unsigned int num_samples, i;
187 int last_end;
188
189 sr_dbg("Generating %s pattern.", analog_pattern_str[ag->pattern]);
190
191 num_samples = ANALOG_BUFSIZE / sizeof(float);
192
193 switch (ag->pattern) {
194 case PATTERN_SQUARE:
195 value = ag->amplitude;
196 last_end = 0;
197 for (i = 0; i < num_samples; i++) {
198 if (i % 5 == 0)
199 value = -value;
200 if (i % 10 == 0)
201 last_end = i;
202 ag->pattern_data[i] = value;
203 }
204 ag->num_samples = last_end;
205 break;
206 case PATTERN_SINE:
207 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
208
209 /* Make sure the number of samples we put out is an integer
210 * multiple of our period size */
211 /* FIXME we actually need only one period. A ringbuffer would be
212 * useful here. */
213 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
214 num_samples--;
215
216 for (i = 0; i < num_samples; i++) {
217 t = (double) i / (double) sample_rate;
218 ag->pattern_data[i] = ag->amplitude *
219 sin(2 * G_PI * frequency * t);
220 }
221
222 ag->num_samples = num_samples;
223 break;
224 case PATTERN_TRIANGLE:
225 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
226
227 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
228 num_samples--;
229
230 for (i = 0; i < num_samples; i++) {
231 t = (double) i / (double) sample_rate;
232 ag->pattern_data[i] = (2 * ag->amplitude / G_PI) *
233 asin(sin(2 * G_PI * frequency * t));
234 }
235
236 ag->num_samples = num_samples;
237 break;
238 case PATTERN_SAWTOOTH:
239 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
240
241 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
242 num_samples--;
243
244 for (i = 0; i < num_samples; i++) {
245 t = (double) i / (double) sample_rate;
246 ag->pattern_data[i] = 2 * ag->amplitude *
247 ((t * frequency) - floor(0.5f + t * frequency));
248 }
249
250 ag->num_samples = num_samples;
251 break;
252 }
253}
254
255static GSList *scan(struct sr_dev_driver *di, GSList *options)
256{
257 struct drv_context *drvc;
258 struct dev_context *devc;
259 struct sr_dev_inst *sdi;
260 struct sr_channel *ch;
261 struct sr_channel_group *cg, *acg;
262 struct sr_config *src;
263 struct analog_gen *ag;
264 GSList *devices, *l;
265 int num_logic_channels, num_analog_channels, pattern, i;
266 char channel_name[16];
267
268 drvc = di->context;
269
270 num_logic_channels = DEFAULT_NUM_LOGIC_CHANNELS;
271 num_analog_channels = DEFAULT_NUM_ANALOG_CHANNELS;
272 for (l = options; l; l = l->next) {
273 src = l->data;
274 switch (src->key) {
275 case SR_CONF_NUM_LOGIC_CHANNELS:
276 num_logic_channels = g_variant_get_int32(src->data);
277 break;
278 case SR_CONF_NUM_ANALOG_CHANNELS:
279 num_analog_channels = g_variant_get_int32(src->data);
280 break;
281 }
282 }
283
284 devices = NULL;
285
286 sdi = g_malloc0(sizeof(struct sr_dev_inst));
287 sdi->status = SR_ST_INACTIVE;
288 sdi->model = g_strdup("Demo device");
289 sdi->driver = di;
290
291 devc = g_malloc0(sizeof(struct dev_context));
292 devc->cur_samplerate = SR_KHZ(200);
293 devc->num_logic_channels = num_logic_channels;
294 devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
295 devc->logic_pattern = PATTERN_SIGROK;
296 devc->num_analog_channels = num_analog_channels;
297
298 /* Logic channels, all in one channel group. */
299 cg = g_malloc0(sizeof(struct sr_channel_group));
300 cg->name = g_strdup("Logic");
301 for (i = 0; i < num_logic_channels; i++) {
302 sprintf(channel_name, "D%d", i);
303 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
304 cg->channels = g_slist_append(cg->channels, ch);
305 }
306 sdi->channel_groups = g_slist_append(NULL, cg);
307
308 /* Analog channels, channel groups and pattern generators. */
309 pattern = 0;
310 /* An "Analog" channel group with all analog channels in it. */
311 acg = g_malloc0(sizeof(struct sr_channel_group));
312 acg->name = g_strdup("Analog");
313 sdi->channel_groups = g_slist_append(sdi->channel_groups, acg);
314
315 devc->ch_ag = g_hash_table_new(g_direct_hash, g_direct_equal);
316 for (i = 0; i < num_analog_channels; i++) {
317 snprintf(channel_name, 16, "A%d", i);
318 ch = sr_channel_new(sdi, i + num_logic_channels, SR_CHANNEL_ANALOG,
319 TRUE, channel_name);
320 acg->channels = g_slist_append(acg->channels, ch);
321
322 /* Every analog channel gets its own channel group as well. */
323 cg = g_malloc0(sizeof(struct sr_channel_group));
324 cg->name = g_strdup(channel_name);
325 cg->channels = g_slist_append(NULL, ch);
326 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
327
328 /* Every channel gets a generator struct. */
329 ag = g_malloc(sizeof(struct analog_gen));
330 ag->amplitude = DEFAULT_ANALOG_AMPLITUDE;
331 ag->packet.channels = cg->channels;
332 ag->packet.mq = 0;
333 ag->packet.mqflags = 0;
334 ag->packet.unit = SR_UNIT_VOLT;
335 ag->packet.data = ag->pattern_data;
336 ag->pattern = pattern;
337 ag->avg_val = 0.0f;
338 ag->num_avgs = 0;
339 g_hash_table_insert(devc->ch_ag, ch, ag);
340
341 if (++pattern == ARRAY_SIZE(analog_pattern_str))
342 pattern = 0;
343 }
344
345 sdi->priv = devc;
346 devices = g_slist_append(devices, sdi);
347 drvc->instances = g_slist_append(drvc->instances, sdi);
348
349 return devices;
350}
351
352static int dev_open(struct sr_dev_inst *sdi)
353{
354 sdi->status = SR_ST_ACTIVE;
355
356 return SR_OK;
357}
358
359static int dev_close(struct sr_dev_inst *sdi)
360{
361 sdi->status = SR_ST_INACTIVE;
362
363 return SR_OK;
364}
365
366static void clear_helper(void *priv)
367{
368 struct dev_context *devc;
369 GHashTableIter iter;
370 void *value;
371
372 devc = priv;
373
374 /* Analog generators. */
375 g_hash_table_iter_init(&iter, devc->ch_ag);
376 while (g_hash_table_iter_next(&iter, NULL, &value))
377 g_free(value);
378 g_hash_table_unref(devc->ch_ag);
379 g_free(devc);
380}
381
382static int dev_clear(const struct sr_dev_driver *di)
383{
384 return std_dev_clear(di, clear_helper);
385}
386
387static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
388 const struct sr_channel_group *cg)
389{
390 struct dev_context *devc;
391 struct sr_channel *ch;
392 struct analog_gen *ag;
393 int pattern;
394
395 if (!sdi)
396 return SR_ERR_ARG;
397
398 devc = sdi->priv;
399 switch (key) {
400 case SR_CONF_SAMPLERATE:
401 *data = g_variant_new_uint64(devc->cur_samplerate);
402 break;
403 case SR_CONF_LIMIT_SAMPLES:
404 *data = g_variant_new_uint64(devc->limit_samples);
405 break;
406 case SR_CONF_LIMIT_MSEC:
407 *data = g_variant_new_uint64(devc->limit_msec);
408 break;
409 case SR_CONF_AVERAGING:
410 *data = g_variant_new_boolean(devc->avg);
411 break;
412 case SR_CONF_AVG_SAMPLES:
413 *data = g_variant_new_uint64(devc->avg_samples);
414 break;
415 case SR_CONF_PATTERN_MODE:
416 if (!cg)
417 return SR_ERR_CHANNEL_GROUP;
418 /* Any channel in the group will do. */
419 ch = cg->channels->data;
420 if (ch->type == SR_CHANNEL_LOGIC) {
421 pattern = devc->logic_pattern;
422 *data = g_variant_new_string(logic_pattern_str[pattern]);
423 } else if (ch->type == SR_CHANNEL_ANALOG) {
424 ag = g_hash_table_lookup(devc->ch_ag, ch);
425 pattern = ag->pattern;
426 *data = g_variant_new_string(analog_pattern_str[pattern]);
427 } else
428 return SR_ERR_BUG;
429 break;
430 case SR_CONF_AMPLITUDE:
431 if (!cg)
432 return SR_ERR_CHANNEL_GROUP;
433 /* Any channel in the group will do. */
434 ch = cg->channels->data;
435 if (ch->type != SR_CHANNEL_ANALOG)
436 return SR_ERR_ARG;
437 ag = g_hash_table_lookup(devc->ch_ag, ch);
438 *data = g_variant_new_double(ag->amplitude);
439 break;
440 default:
441 return SR_ERR_NA;
442 }
443
444 return SR_OK;
445}
446
447static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
448 const struct sr_channel_group *cg)
449{
450 struct dev_context *devc;
451 struct analog_gen *ag;
452 struct sr_channel *ch;
453 GSList *l;
454 int logic_pattern, analog_pattern, ret;
455 unsigned int i;
456 const char *stropt;
457
458 devc = sdi->priv;
459
460 if (sdi->status != SR_ST_ACTIVE)
461 return SR_ERR_DEV_CLOSED;
462
463 ret = SR_OK;
464 switch (key) {
465 case SR_CONF_SAMPLERATE:
466 devc->cur_samplerate = g_variant_get_uint64(data);
467 break;
468 case SR_CONF_LIMIT_SAMPLES:
469 devc->limit_msec = 0;
470 devc->limit_samples = g_variant_get_uint64(data);
471 break;
472 case SR_CONF_LIMIT_MSEC:
473 devc->limit_msec = g_variant_get_uint64(data);
474 devc->limit_samples = 0;
475 break;
476 case SR_CONF_AVERAGING:
477 devc->avg = g_variant_get_boolean(data);
478 sr_dbg("%s averaging", devc->avg ? "Enabling" : "Disabling");
479 break;
480 case SR_CONF_AVG_SAMPLES:
481 devc->avg_samples = g_variant_get_uint64(data);
482 sr_dbg("Setting averaging rate to %" PRIu64, devc->avg_samples);
483 break;
484 case SR_CONF_PATTERN_MODE:
485 if (!cg)
486 return SR_ERR_CHANNEL_GROUP;
487 stropt = g_variant_get_string(data, NULL);
488 logic_pattern = analog_pattern = -1;
489 for (i = 0; i < ARRAY_SIZE(logic_pattern_str); i++) {
490 if (!strcmp(stropt, logic_pattern_str[i])) {
491 logic_pattern = i;
492 break;
493 }
494 }
495 for (i = 0; i < ARRAY_SIZE(analog_pattern_str); i++) {
496 if (!strcmp(stropt, analog_pattern_str[i])) {
497 analog_pattern = i;
498 break;
499 }
500 }
501 if (logic_pattern == -1 && analog_pattern == -1)
502 return SR_ERR_ARG;
503 for (l = cg->channels; l; l = l->next) {
504 ch = l->data;
505 if (ch->type == SR_CHANNEL_LOGIC) {
506 if (logic_pattern == -1)
507 return SR_ERR_ARG;
508 sr_dbg("Setting logic pattern to %s",
509 logic_pattern_str[logic_pattern]);
510 devc->logic_pattern = logic_pattern;
511 /* Might as well do this now, these are static. */
512 if (logic_pattern == PATTERN_ALL_LOW)
513 memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
514 else if (logic_pattern == PATTERN_ALL_HIGH)
515 memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
516 } else if (ch->type == SR_CHANNEL_ANALOG) {
517 if (analog_pattern == -1)
518 return SR_ERR_ARG;
519 sr_dbg("Setting analog pattern for channel %s to %s",
520 ch->name, analog_pattern_str[analog_pattern]);
521 ag = g_hash_table_lookup(devc->ch_ag, ch);
522 ag->pattern = analog_pattern;
523 } else
524 return SR_ERR_BUG;
525 }
526 break;
527 case SR_CONF_AMPLITUDE:
528 if (!cg)
529 return SR_ERR_CHANNEL_GROUP;
530 for (l = cg->channels; l; l = l->next) {
531 ch = l->data;
532 if (ch->type != SR_CHANNEL_ANALOG)
533 return SR_ERR_ARG;
534 ag = g_hash_table_lookup(devc->ch_ag, ch);
535 ag->amplitude = g_variant_get_double(data);
536 }
537 break;
538 default:
539 ret = SR_ERR_NA;
540 }
541
542 return ret;
543}
544
545static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
546 const struct sr_channel_group *cg)
547{
548 struct sr_channel *ch;
549 GVariant *gvar;
550 GVariantBuilder gvb;
551
552 if (key == SR_CONF_SCAN_OPTIONS) {
553 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
554 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
555 return SR_OK;
556 }
557
558 if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
559 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
560 drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
561 return SR_OK;
562 }
563
564 if (!sdi)
565 return SR_ERR_ARG;
566
567 if (!cg) {
568 switch (key) {
569 case SR_CONF_DEVICE_OPTIONS:
570 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
571 devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
572 break;
573 case SR_CONF_SAMPLERATE:
574 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
575 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
576 ARRAY_SIZE(samplerates), sizeof(uint64_t));
577 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
578 *data = g_variant_builder_end(&gvb);
579 break;
580 default:
581 return SR_ERR_NA;
582 }
583 } else {
584 ch = cg->channels->data;
585 switch (key) {
586 case SR_CONF_DEVICE_OPTIONS:
587 if (ch->type == SR_CHANNEL_LOGIC)
588 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
589 devopts_cg_logic, ARRAY_SIZE(devopts_cg_logic),
590 sizeof(uint32_t));
591 else if (ch->type == SR_CHANNEL_ANALOG) {
592 if (strcmp(cg->name, "Analog") == 0)
593 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
594 devopts_cg_analog_group, ARRAY_SIZE(devopts_cg_analog_group),
595 sizeof(uint32_t));
596 else
597 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
598 devopts_cg_analog_channel, ARRAY_SIZE(devopts_cg_analog_channel),
599 sizeof(uint32_t));
600 }
601 else
602 return SR_ERR_BUG;
603 break;
604 case SR_CONF_PATTERN_MODE:
605 /* The analog group (with all 4 channels) shall not have a pattern property. */
606 if (strcmp(cg->name, "Analog") == 0)
607 return SR_ERR_NA;
608
609 if (ch->type == SR_CHANNEL_LOGIC)
610 *data = g_variant_new_strv(logic_pattern_str,
611 ARRAY_SIZE(logic_pattern_str));
612 else if (ch->type == SR_CHANNEL_ANALOG)
613 *data = g_variant_new_strv(analog_pattern_str,
614 ARRAY_SIZE(analog_pattern_str));
615 else
616 return SR_ERR_BUG;
617 break;
618 default:
619 return SR_ERR_NA;
620 }
621 }
622
623 return SR_OK;
624}
625
626static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
627{
628 struct dev_context *devc;
629 uint64_t i, j;
630 uint8_t pat;
631
632 devc = sdi->priv;
633
634 switch (devc->logic_pattern) {
635 case PATTERN_SIGROK:
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++;
643 }
644 break;
645 case PATTERN_RANDOM:
646 for (i = 0; i < size; i++)
647 devc->logic_data[i] = (uint8_t)(rand() & 0xff);
648 break;
649 case PATTERN_INC:
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 }
656 break;
657 case PATTERN_ALL_LOW:
658 case PATTERN_ALL_HIGH:
659 /* These were set when the pattern mode was selected. */
660 break;
661 default:
662 sr_err("Unknown pattern: %d.", devc->logic_pattern);
663 break;
664 }
665}
666
667static void send_analog_packet(struct analog_gen *ag,
668 struct sr_dev_inst *sdi,
669 uint64_t *analog_sent,
670 uint64_t analog_pos,
671 uint64_t analog_todo)
672{
673 struct sr_datafeed_packet packet;
674 struct dev_context *devc;
675 uint64_t sending_now, to_avg;
676 int ag_pattern_pos;
677 unsigned int i;
678
679 devc = sdi->priv;
680 packet.type = SR_DF_ANALOG_OLD;
681 packet.payload = &ag->packet;
682
683 if (!devc->avg) {
684 ag_pattern_pos = analog_pos % ag->num_samples;
685 sending_now = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
686 ag->packet.data = ag->pattern_data + ag_pattern_pos;
687 ag->packet.num_samples = sending_now;
688 sr_session_send(sdi, &packet);
689
690 /* Whichever channel group gets there first. */
691 *analog_sent = MAX(*analog_sent, sending_now);
692 } else {
693 ag_pattern_pos = analog_pos % ag->num_samples;
694 to_avg = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
695
696 for (i = 0; i < to_avg; i++) {
697 ag->avg_val = (ag->avg_val +
698 *(ag->pattern_data +
699 ag_pattern_pos + i)) / 2;
700 ag->num_avgs++;
701 /* Time to send averaged data? */
702 if (devc->avg_samples > 0 &&
703 ag->num_avgs >= devc->avg_samples)
704 goto do_send;
705 }
706
707 if (devc->avg_samples == 0) {
708 /* We're averaging all the samples, so wait with
709 * sending until the very end.
710 */
711 *analog_sent = ag->num_avgs;
712 return;
713 }
714
715do_send:
716 ag->packet.data = &ag->avg_val;
717 ag->packet.num_samples = 1;
718
719 sr_session_send(sdi, &packet);
720 *analog_sent = ag->num_avgs;
721
722 ag->num_avgs = 0;
723 ag->avg_val = 0.0f;
724 }
725}
726
727/* Callback handling data */
728static int prepare_data(int fd, int revents, void *cb_data)
729{
730 struct sr_dev_inst *sdi;
731 struct dev_context *devc;
732 struct sr_datafeed_packet packet;
733 struct sr_datafeed_logic logic;
734 struct analog_gen *ag;
735 GHashTableIter iter;
736 void *value;
737 uint64_t samples_todo, logic_done, analog_done, analog_sent, sending_now;
738 int64_t elapsed_us, limit_us, todo_us;
739
740 (void)fd;
741 (void)revents;
742
743 sdi = cb_data;
744 devc = sdi->priv;
745
746 /* Just in case. */
747 if (devc->cur_samplerate <= 0 || devc->logic_unitsize <= 0
748 || (devc->num_logic_channels <= 0
749 && devc->num_analog_channels <= 0)) {
750 dev_acquisition_stop(sdi);
751 return G_SOURCE_CONTINUE;
752 }
753
754 /* What time span should we send samples for? */
755 elapsed_us = g_get_monotonic_time() - devc->start_us;
756 limit_us = 1000 * devc->limit_msec;
757 if (limit_us > 0 && limit_us < elapsed_us)
758 todo_us = MAX(0, limit_us - devc->spent_us);
759 else
760 todo_us = MAX(0, elapsed_us - devc->spent_us);
761
762 /* How many samples are outstanding since the last round? */
763 samples_todo = (todo_us * devc->cur_samplerate + G_USEC_PER_SEC - 1)
764 / G_USEC_PER_SEC;
765 if (devc->limit_samples > 0) {
766 if (devc->limit_samples < devc->sent_samples)
767 samples_todo = 0;
768 else if (devc->limit_samples - devc->sent_samples < samples_todo)
769 samples_todo = devc->limit_samples - devc->sent_samples;
770 }
771 /* Calculate the actual time covered by this run back from the sample
772 * count, rounded towards zero. This avoids getting stuck on a too-low
773 * time delta with no samples being sent due to round-off.
774 */
775 todo_us = samples_todo * G_USEC_PER_SEC / devc->cur_samplerate;
776
777 logic_done = devc->num_logic_channels > 0 ? 0 : samples_todo;
778 analog_done = devc->num_analog_channels > 0 ? 0 : samples_todo;
779
780 while (logic_done < samples_todo || analog_done < samples_todo) {
781 /* Logic */
782 if (logic_done < samples_todo) {
783 sending_now = MIN(samples_todo - logic_done,
784 LOGIC_BUFSIZE / devc->logic_unitsize);
785 logic_generator(sdi, sending_now * devc->logic_unitsize);
786 packet.type = SR_DF_LOGIC;
787 packet.payload = &logic;
788 logic.length = sending_now * devc->logic_unitsize;
789 logic.unitsize = devc->logic_unitsize;
790 logic.data = devc->logic_data;
791 sr_session_send(sdi, &packet);
792 logic_done += sending_now;
793 }
794
795 /* Analog, one channel at a time */
796 if (analog_done < samples_todo) {
797 analog_sent = 0;
798
799 g_hash_table_iter_init(&iter, devc->ch_ag);
800 while (g_hash_table_iter_next(&iter, NULL, &value)) {
801 send_analog_packet(value, sdi, &analog_sent,
802 devc->sent_samples + analog_done,
803 samples_todo - analog_done);
804 }
805 analog_done += analog_sent;
806 }
807 }
808 /* At this point, both logic_done and analog_done should be
809 * exactly equal to samples_todo, or else.
810 */
811 if (logic_done != samples_todo || analog_done != samples_todo) {
812 sr_err("BUG: Sample count mismatch.");
813 return G_SOURCE_REMOVE;
814 }
815 devc->sent_samples += samples_todo;
816 devc->spent_us += todo_us;
817
818 if ((devc->limit_samples > 0 && devc->sent_samples >= devc->limit_samples)
819 || (limit_us > 0 && devc->spent_us >= limit_us)) {
820
821 /* If we're averaging everything - now is the time to send data */
822 if (devc->avg_samples == 0) {
823 g_hash_table_iter_init(&iter, devc->ch_ag);
824 while (g_hash_table_iter_next(&iter, NULL, &value)) {
825 ag = value;
826 packet.type = SR_DF_ANALOG_OLD;
827 packet.payload = &ag->packet;
828 ag->packet.data = &ag->avg_val;
829 ag->packet.num_samples = 1;
830 sr_session_send(sdi, &packet);
831 }
832 }
833 sr_dbg("Requested number of samples reached.");
834 dev_acquisition_stop(sdi);
835 }
836
837 return G_SOURCE_CONTINUE;
838}
839
840static int dev_acquisition_start(const struct sr_dev_inst *sdi)
841{
842 struct dev_context *devc;
843 GHashTableIter iter;
844 void *value;
845
846 if (sdi->status != SR_ST_ACTIVE)
847 return SR_ERR_DEV_CLOSED;
848
849 devc = sdi->priv;
850 devc->sent_samples = 0;
851
852 g_hash_table_iter_init(&iter, devc->ch_ag);
853 while (g_hash_table_iter_next(&iter, NULL, &value))
854 generate_analog_pattern(value, devc->cur_samplerate);
855
856 sr_session_source_add(sdi->session, -1, 0, 100,
857 prepare_data, (struct sr_dev_inst *)sdi);
858
859 std_session_send_df_header(sdi, LOG_PREFIX);
860
861 /* We use this timestamp to decide how many more samples to send. */
862 devc->start_us = g_get_monotonic_time();
863 devc->spent_us = 0;
864
865 return SR_OK;
866}
867
868static int dev_acquisition_stop(struct sr_dev_inst *sdi)
869{
870 sr_dbg("Stopping acquisition.");
871 sr_session_source_remove(sdi->session, -1);
872 std_session_send_df_end(sdi, LOG_PREFIX);
873
874 return SR_OK;
875}
876
877SR_PRIV struct sr_dev_driver demo_driver_info = {
878 .name = "demo",
879 .longname = "Demo driver and pattern generator",
880 .api_version = 1,
881 .init = std_init,
882 .cleanup = std_cleanup,
883 .scan = scan,
884 .dev_list = std_dev_list,
885 .dev_clear = dev_clear,
886 .config_get = config_get,
887 .config_set = config_set,
888 .config_list = config_list,
889 .dev_open = dev_open,
890 .dev_close = dev_close,
891 .dev_acquisition_start = dev_acquisition_start,
892 .dev_acquisition_stop = dev_acquisition_stop,
893 .context = NULL,
894};