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