]> sigrok.org Git - libsigrok.git/blame - src/hardware/demo/demo.c
Put driver pointers into special section
[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{
b4750a3a 255 struct drv_context *drvc;
33ef7573 256 struct dev_context *devc;
c07f60e7 257 struct sr_dev_inst *sdi;
ba7dd8bb 258 struct sr_channel *ch;
49224c28 259 struct sr_channel_group *cg, *acg;
c07f60e7 260 struct sr_config *src;
8b2d41ed 261 struct analog_gen *ag;
c07f60e7 262 GSList *devices, *l;
ba7dd8bb
UH
263 int num_logic_channels, num_analog_channels, pattern, i;
264 char channel_name[16];
067d0716 265
41812aca 266 drvc = di->context;
4b97c74e 267
3f239f08
UH
268 num_logic_channels = DEFAULT_NUM_LOGIC_CHANNELS;
269 num_analog_channels = DEFAULT_NUM_ANALOG_CHANNELS;
c07f60e7
BV
270 for (l = options; l; l = l->next) {
271 src = l->data;
272 switch (src->key) {
3f239f08 273 case SR_CONF_NUM_LOGIC_CHANNELS:
ba7dd8bb 274 num_logic_channels = g_variant_get_int32(src->data);
c07f60e7 275 break;
3f239f08 276 case SR_CONF_NUM_ANALOG_CHANNELS:
ba7dd8bb 277 num_analog_channels = g_variant_get_int32(src->data);
c07f60e7
BV
278 break;
279 }
280 }
85b5af06 281
c07f60e7 282 devices = NULL;
0af636be 283
aac29cc1 284 sdi = g_malloc0(sizeof(struct sr_dev_inst));
45884333 285 sdi->status = SR_ST_INACTIVE;
4b664cd6 286 sdi->model = g_strdup("Demo device");
a873c594 287 sdi->driver = di;
e15f48c2 288
a49a320d 289 devc = g_malloc0(sizeof(struct dev_context));
8b2d41ed 290 devc->cur_samplerate = SR_KHZ(200);
ba7dd8bb
UH
291 devc->num_logic_channels = num_logic_channels;
292 devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
8b2d41ed 293 devc->logic_pattern = PATTERN_SIGROK;
ba7dd8bb 294 devc->num_analog_channels = num_analog_channels;
8b2d41ed 295
f18e0db3
LPC
296 if (num_logic_channels > 0) {
297 /* Logic channels, all in one channel group. */
298 cg = g_malloc0(sizeof(struct sr_channel_group));
299 cg->name = g_strdup("Logic");
300 for (i = 0; i < num_logic_channels; i++) {
301 sprintf(channel_name, "D%d", i);
302 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
303 cg->channels = g_slist_append(cg->channels, ch);
304 }
305 sdi->channel_groups = g_slist_append(NULL, cg);
87ca93c5
BV
306 }
307
ba7dd8bb 308 /* Analog channels, channel groups and pattern generators. */
f18e0db3
LPC
309 if (num_analog_channels > 0) {
310 pattern = 0;
311 /* An "Analog" channel group with all analog channels in it. */
312 acg = g_malloc0(sizeof(struct sr_channel_group));
313 acg->name = g_strdup("Analog");
314 sdi->channel_groups = g_slist_append(sdi->channel_groups, acg);
315
316 devc->ch_ag = g_hash_table_new(g_direct_hash, g_direct_equal);
317 for (i = 0; i < num_analog_channels; i++) {
318 snprintf(channel_name, 16, "A%d", i);
319 ch = sr_channel_new(sdi, i + num_logic_channels, SR_CHANNEL_ANALOG,
320 TRUE, channel_name);
321 acg->channels = g_slist_append(acg->channels, ch);
322
323 /* Every analog channel gets its own channel group as well. */
324 cg = g_malloc0(sizeof(struct sr_channel_group));
325 cg->name = g_strdup(channel_name);
326 cg->channels = g_slist_append(NULL, ch);
327 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
328
329 /* Every channel gets a generator struct. */
330 ag = g_malloc(sizeof(struct analog_gen));
331 ag->amplitude = DEFAULT_ANALOG_AMPLITUDE;
332 ag->packet.channels = cg->channels;
333 ag->packet.mq = 0;
334 ag->packet.mqflags = 0;
335 ag->packet.unit = SR_UNIT_VOLT;
336 ag->packet.data = ag->pattern_data;
337 ag->pattern = pattern;
338 ag->avg_val = 0.0f;
339 ag->num_avgs = 0;
340 g_hash_table_insert(devc->ch_ag, ch, ag);
341
342 if (++pattern == ARRAY_SIZE(analog_pattern_str))
343 pattern = 0;
344 }
33ef7573 345 }
33ef7573
JH
346
347 sdi->priv = devc;
8b2d41ed
BV
348 devices = g_slist_append(devices, sdi);
349 drvc->instances = g_slist_append(drvc->instances, sdi);
33ef7573 350
067d0716 351 return devices;
6239c175
UH
352}
353
6078d2c9 354static int dev_open(struct sr_dev_inst *sdi)
6239c175 355{
e73ffd42 356 sdi->status = SR_ST_ACTIVE;
697785d1 357
e46b8fb1 358 return SR_OK;
6239c175
UH
359}
360
6078d2c9 361static int dev_close(struct sr_dev_inst *sdi)
6239c175 362{
decfe89d 363 sdi->status = SR_ST_INACTIVE;
697785d1
UH
364
365 return SR_OK;
6239c175
UH
366}
367
ed0b7fed
BV
368static void clear_helper(void *priv)
369{
370 struct dev_context *devc;
49224c28
BV
371 GHashTableIter iter;
372 void *value;
ed0b7fed
BV
373
374 devc = priv;
49224c28
BV
375
376 /* Analog generators. */
377 g_hash_table_iter_init(&iter, devc->ch_ag);
378 while (g_hash_table_iter_next(&iter, NULL, &value))
379 g_free(value);
380 g_hash_table_unref(devc->ch_ag);
ed0b7fed
BV
381 g_free(devc);
382}
383
6ab68731 384static int dev_clear(const struct sr_dev_driver *di)
6239c175 385{
ed0b7fed 386 return std_dev_clear(di, clear_helper);
6239c175
UH
387}
388
584560f1 389static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 390 const struct sr_channel_group *cg)
6239c175 391{
c07f60e7 392 struct dev_context *devc;
ba7dd8bb 393 struct sr_channel *ch;
2388ae86
BV
394 struct analog_gen *ag;
395 int pattern;
6f57fd96 396
2388ae86
BV
397 if (!sdi)
398 return SR_ERR_ARG;
8f996b89 399
c07f60e7 400 devc = sdi->priv;
584560f1 401 switch (key) {
123e1313 402 case SR_CONF_SAMPLERATE:
a7684294 403 *data = g_variant_new_uint64(devc->cur_samplerate);
6239c175 404 break;
2474d87e 405 case SR_CONF_LIMIT_SAMPLES:
a7684294 406 *data = g_variant_new_uint64(devc->limit_samples);
2474d87e
BV
407 break;
408 case SR_CONF_LIMIT_MSEC:
a7684294 409 *data = g_variant_new_uint64(devc->limit_msec);
2474d87e 410 break;
7a8a1aba
BG
411 case SR_CONF_AVERAGING:
412 *data = g_variant_new_boolean(devc->avg);
413 break;
414 case SR_CONF_AVG_SAMPLES:
415 *data = g_variant_new_uint64(devc->avg_samples);
416 break;
2474d87e 417 case SR_CONF_PATTERN_MODE:
53b4680f 418 if (!cg)
660e398f 419 return SR_ERR_CHANNEL_GROUP;
49224c28 420 /* Any channel in the group will do. */
ba7dd8bb 421 ch = cg->channels->data;
3f239f08 422 if (ch->type == SR_CHANNEL_LOGIC) {
2388ae86
BV
423 pattern = devc->logic_pattern;
424 *data = g_variant_new_string(logic_pattern_str[pattern]);
3f239f08 425 } else if (ch->type == SR_CHANNEL_ANALOG) {
49224c28 426 ag = g_hash_table_lookup(devc->ch_ag, ch);
2388ae86
BV
427 pattern = ag->pattern;
428 *data = g_variant_new_string(analog_pattern_str[pattern]);
429 } else
430 return SR_ERR_BUG;
c07f60e7 431 break;
dddabe37
BV
432 case SR_CONF_AMPLITUDE:
433 if (!cg)
434 return SR_ERR_CHANNEL_GROUP;
49224c28 435 /* Any channel in the group will do. */
dddabe37
BV
436 ch = cg->channels->data;
437 if (ch->type != SR_CHANNEL_ANALOG)
438 return SR_ERR_ARG;
49224c28 439 ag = g_hash_table_lookup(devc->ch_ag, ch);
dddabe37
BV
440 *data = g_variant_new_double(ag->amplitude);
441 break;
7dfcf010 442 default:
bd6fbf62 443 return SR_ERR_NA;
6239c175
UH
444 }
445
dfb0fa1a 446 return SR_OK;
6239c175
UH
447}
448
584560f1 449static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 450 const struct sr_channel_group *cg)
6239c175 451{
8b2d41ed 452 struct dev_context *devc;
4374219b 453 struct analog_gen *ag;
ba7dd8bb 454 struct sr_channel *ch;
49224c28
BV
455 GSList *l;
456 int logic_pattern, analog_pattern, ret;
61c39f54 457 unsigned int i;
1b79df2f 458 const char *stropt;
6239c175 459
8b2d41ed 460 devc = sdi->priv;
6239c175 461
e73ffd42
BV
462 if (sdi->status != SR_ST_ACTIVE)
463 return SR_ERR_DEV_CLOSED;
464
2388ae86 465 ret = SR_OK;
584560f1 466 switch (key) {
2388ae86 467 case SR_CONF_SAMPLERATE:
a7684294 468 devc->cur_samplerate = g_variant_get_uint64(data);
2388ae86
BV
469 break;
470 case SR_CONF_LIMIT_SAMPLES:
a7684294
JH
471 devc->limit_msec = 0;
472 devc->limit_samples = g_variant_get_uint64(data);
2388ae86
BV
473 break;
474 case SR_CONF_LIMIT_MSEC:
a7684294
JH
475 devc->limit_msec = g_variant_get_uint64(data);
476 devc->limit_samples = 0;
2388ae86 477 break;
7a8a1aba
BG
478 case SR_CONF_AVERAGING:
479 devc->avg = g_variant_get_boolean(data);
480 sr_dbg("%s averaging", devc->avg ? "Enabling" : "Disabling");
481 break;
482 case SR_CONF_AVG_SAMPLES:
483 devc->avg_samples = g_variant_get_uint64(data);
484 sr_dbg("Setting averaging rate to %" PRIu64, devc->avg_samples);
485 break;
2388ae86 486 case SR_CONF_PATTERN_MODE:
53b4680f 487 if (!cg)
660e398f 488 return SR_ERR_CHANNEL_GROUP;
d00088ca 489 stropt = g_variant_get_string(data, NULL);
49224c28
BV
490 logic_pattern = analog_pattern = -1;
491 for (i = 0; i < ARRAY_SIZE(logic_pattern_str); i++) {
492 if (!strcmp(stropt, logic_pattern_str[i])) {
493 logic_pattern = i;
494 break;
8b2d41ed 495 }
49224c28
BV
496 }
497 for (i = 0; i < ARRAY_SIZE(analog_pattern_str); i++) {
498 if (!strcmp(stropt, analog_pattern_str[i])) {
499 analog_pattern = i;
500 break;
8b2d41ed 501 }
49224c28
BV
502 }
503 if (logic_pattern == -1 && analog_pattern == -1)
504 return SR_ERR_ARG;
505 for (l = cg->channels; l; l = l->next) {
506 ch = l->data;
507 if (ch->type == SR_CHANNEL_LOGIC) {
508 if (logic_pattern == -1)
509 return SR_ERR_ARG;
510 sr_dbg("Setting logic pattern to %s",
511 logic_pattern_str[logic_pattern]);
512 devc->logic_pattern = logic_pattern;
513 /* Might as well do this now, these are static. */
514 if (logic_pattern == PATTERN_ALL_LOW)
515 memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
516 else if (logic_pattern == PATTERN_ALL_HIGH)
517 memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
518 } else if (ch->type == SR_CHANNEL_ANALOG) {
519 if (analog_pattern == -1)
520 return SR_ERR_ARG;
521 sr_dbg("Setting analog pattern for channel %s to %s",
522 ch->name, analog_pattern_str[analog_pattern]);
523 ag = g_hash_table_lookup(devc->ch_ag, ch);
524 ag->pattern = analog_pattern;
525 } else
526 return SR_ERR_BUG;
527 }
2388ae86 528 break;
dddabe37
BV
529 case SR_CONF_AMPLITUDE:
530 if (!cg)
531 return SR_ERR_CHANNEL_GROUP;
49224c28
BV
532 for (l = cg->channels; l; l = l->next) {
533 ch = l->data;
534 if (ch->type != SR_CHANNEL_ANALOG)
535 return SR_ERR_ARG;
536 ag = g_hash_table_lookup(devc->ch_ag, ch);
537 ag->amplitude = g_variant_get_double(data);
538 }
dddabe37 539 break;
2388ae86 540 default:
bd6fbf62 541 ret = SR_ERR_NA;
6239c175
UH
542 }
543
544 return ret;
545}
546
584560f1 547static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 548 const struct sr_channel_group *cg)
a1c743fc 549{
ba7dd8bb 550 struct sr_channel *ch;
d00088ca
BV
551 GVariant *gvar;
552 GVariantBuilder gvb;
a1c743fc 553
7a1da331 554 if (key == SR_CONF_SCAN_OPTIONS) {
584560f1
BV
555 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
556 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
7a1da331
BV
557 return SR_OK;
558 }
559
390795c0
BV
560 if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
561 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
1e4a7cac 562 drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
390795c0
BV
563 return SR_OK;
564 }
565
7a1da331
BV
566 if (!sdi)
567 return SR_ERR_ARG;
568
53b4680f 569 if (!cg) {
7a1da331
BV
570 switch (key) {
571 case SR_CONF_DEVICE_OPTIONS:
584560f1 572 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
1e4a7cac 573 devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
7a1da331
BV
574 break;
575 case SR_CONF_SAMPLERATE:
576 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
577 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
578 ARRAY_SIZE(samplerates), sizeof(uint64_t));
579 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
580 *data = g_variant_builder_end(&gvb);
581 break;
582 default:
583 return SR_ERR_NA;
584 }
585 } else {
ba7dd8bb 586 ch = cg->channels->data;
7a1da331
BV
587 switch (key) {
588 case SR_CONF_DEVICE_OPTIONS:
49224c28 589 if (ch->type == SR_CHANNEL_LOGIC)
8249889d 590 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
49224c28 591 devopts_cg_logic, ARRAY_SIZE(devopts_cg_logic),
584560f1 592 sizeof(uint32_t));
e2b99f04
SA
593 else if (ch->type == SR_CHANNEL_ANALOG) {
594 if (strcmp(cg->name, "Analog") == 0)
595 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
596 devopts_cg_analog_group, ARRAY_SIZE(devopts_cg_analog_group),
597 sizeof(uint32_t));
598 else
599 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
600 devopts_cg_analog_channel, ARRAY_SIZE(devopts_cg_analog_channel),
601 sizeof(uint32_t));
602 }
49224c28
BV
603 else
604 return SR_ERR_BUG;
7a1da331
BV
605 break;
606 case SR_CONF_PATTERN_MODE:
e2b99f04
SA
607 /* The analog group (with all 4 channels) shall not have a pattern property. */
608 if (strcmp(cg->name, "Analog") == 0)
609 return SR_ERR_NA;
610
3f239f08 611 if (ch->type == SR_CHANNEL_LOGIC)
7a1da331
BV
612 *data = g_variant_new_strv(logic_pattern_str,
613 ARRAY_SIZE(logic_pattern_str));
3f239f08 614 else if (ch->type == SR_CHANNEL_ANALOG)
7a1da331
BV
615 *data = g_variant_new_strv(analog_pattern_str,
616 ARRAY_SIZE(analog_pattern_str));
2388ae86
BV
617 else
618 return SR_ERR_BUG;
7a1da331
BV
619 break;
620 default:
621 return SR_ERR_NA;
622 }
a1c743fc
BV
623 }
624
625 return SR_OK;
626}
627
c07f60e7 628static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
85b5af06 629{
61c39f54 630 struct dev_context *devc;
c07f60e7
BV
631 uint64_t i, j;
632 uint8_t pat;
85b5af06 633
61c39f54 634 devc = sdi->priv;
85b5af06 635
c07f60e7 636 switch (devc->logic_pattern) {
61c39f54 637 case PATTERN_SIGROK:
c07f60e7
BV
638 memset(devc->logic_data, 0x00, size);
639 for (i = 0; i < size; i += devc->logic_unitsize) {
640 for (j = 0; j < devc->logic_unitsize; j++) {
641 pat = pattern_sigrok[(devc->step + j) % sizeof(pattern_sigrok)] >> 1;
642 devc->logic_data[i + j] = ~pat;
643 }
644 devc->step++;
917e0e71
BV
645 }
646 break;
61c39f54 647 case PATTERN_RANDOM:
5096c6a6 648 for (i = 0; i < size; i++)
61c39f54 649 devc->logic_data[i] = (uint8_t)(rand() & 0xff);
85b5af06 650 break;
61c39f54 651 case PATTERN_INC:
c07f60e7
BV
652 for (i = 0; i < size; i++) {
653 for (j = 0; j < devc->logic_unitsize; j++) {
654 devc->logic_data[i + j] = devc->step;
655 }
656 devc->step++;
657 }
c03ed397 658 break;
61c39f54
BV
659 case PATTERN_ALL_LOW:
660 case PATTERN_ALL_HIGH:
661 /* These were set when the pattern mode was selected. */
c03ed397
UH
662 break;
663 default:
c07f60e7 664 sr_err("Unknown pattern: %d.", devc->logic_pattern);
c03ed397 665 break;
85b5af06
UH
666 }
667}
668
7a8a1aba
BG
669static void send_analog_packet(struct analog_gen *ag,
670 struct sr_dev_inst *sdi,
671 uint64_t *analog_sent,
a49a320d 672 uint64_t analog_pos,
7a8a1aba
BG
673 uint64_t analog_todo)
674{
675 struct sr_datafeed_packet packet;
676 struct dev_context *devc;
677 uint64_t sending_now, to_avg;
678 int ag_pattern_pos;
679 unsigned int i;
680
681 devc = sdi->priv;
5faebab2 682 packet.type = SR_DF_ANALOG_OLD;
7a8a1aba
BG
683 packet.payload = &ag->packet;
684
685 if (!devc->avg) {
a49a320d 686 ag_pattern_pos = analog_pos % ag->num_samples;
7a8a1aba
BG
687 sending_now = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
688 ag->packet.data = ag->pattern_data + ag_pattern_pos;
689 ag->packet.num_samples = sending_now;
690 sr_session_send(sdi, &packet);
691
692 /* Whichever channel group gets there first. */
693 *analog_sent = MAX(*analog_sent, sending_now);
694 } else {
a49a320d 695 ag_pattern_pos = analog_pos % ag->num_samples;
7a8a1aba
BG
696 to_avg = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
697
698 for (i = 0; i < to_avg; i++) {
699 ag->avg_val = (ag->avg_val +
700 *(ag->pattern_data +
701 ag_pattern_pos + i)) / 2;
702 ag->num_avgs++;
703 /* Time to send averaged data? */
704 if (devc->avg_samples > 0 &&
705 ag->num_avgs >= devc->avg_samples)
706 goto do_send;
707 }
708
709 if (devc->avg_samples == 0) {
710 /* We're averaging all the samples, so wait with
711 * sending until the very end.
712 */
713 *analog_sent = ag->num_avgs;
714 return;
715 }
716
717do_send:
718 ag->packet.data = &ag->avg_val;
719 ag->packet.num_samples = 1;
720
721 sr_session_send(sdi, &packet);
722 *analog_sent = ag->num_avgs;
723
724 ag->num_avgs = 0;
725 ag->avg_val = 0.0f;
726 }
727}
728
85b5af06 729/* Callback handling data */
61c39f54 730static int prepare_data(int fd, int revents, void *cb_data)
85b5af06 731{
61c39f54
BV
732 struct sr_dev_inst *sdi;
733 struct dev_context *devc;
b9c735a2 734 struct sr_datafeed_packet packet;
9c939c51 735 struct sr_datafeed_logic logic;
8b2d41ed 736 struct analog_gen *ag;
49224c28
BV
737 GHashTableIter iter;
738 void *value;
a49a320d
DE
739 uint64_t samples_todo, logic_done, analog_done, analog_sent, sending_now;
740 int64_t elapsed_us, limit_us, todo_us;
1924f59f 741
cb93f8a9
UH
742 (void)fd;
743 (void)revents;
1924f59f 744
61c39f54
BV
745 sdi = cb_data;
746 devc = sdi->priv;
747
a49a320d 748 /* Just in case. */
f18e0db3 749 if (devc->cur_samplerate <= 0
a49a320d
DE
750 || (devc->num_logic_channels <= 0
751 && devc->num_analog_channels <= 0)) {
695dc859 752 dev_acquisition_stop(sdi);
a49a320d
DE
753 return G_SOURCE_CONTINUE;
754 }
7f4975b4 755
a49a320d
DE
756 /* What time span should we send samples for? */
757 elapsed_us = g_get_monotonic_time() - devc->start_us;
758 limit_us = 1000 * devc->limit_msec;
759 if (limit_us > 0 && limit_us < elapsed_us)
760 todo_us = MAX(0, limit_us - devc->spent_us);
761 else
762 todo_us = MAX(0, elapsed_us - devc->spent_us);
763
764 /* How many samples are outstanding since the last round? */
36cbd69e 765 samples_todo = (todo_us * devc->cur_samplerate + G_USEC_PER_SEC - 1)
a49a320d
DE
766 / G_USEC_PER_SEC;
767 if (devc->limit_samples > 0) {
768 if (devc->limit_samples < devc->sent_samples)
769 samples_todo = 0;
770 else if (devc->limit_samples - devc->sent_samples < samples_todo)
771 samples_todo = devc->limit_samples - devc->sent_samples;
772 }
773 /* Calculate the actual time covered by this run back from the sample
774 * count, rounded towards zero. This avoids getting stuck on a too-low
775 * time delta with no samples being sent due to round-off.
776 */
777 todo_us = samples_todo * G_USEC_PER_SEC / devc->cur_samplerate;
b62bb97a 778
9dfacd87
AJ
779 logic_done = devc->num_logic_channels > 0 ? 0 : samples_todo;
780 analog_done = devc->num_analog_channels > 0 ? 0 : samples_todo;
85b5af06 781
a49a320d 782 while (logic_done < samples_todo || analog_done < samples_todo) {
c07f60e7 783 /* Logic */
a49a320d
DE
784 if (logic_done < samples_todo) {
785 sending_now = MIN(samples_todo - logic_done,
786 LOGIC_BUFSIZE / devc->logic_unitsize);
8b2d41ed
BV
787 logic_generator(sdi, sending_now * devc->logic_unitsize);
788 packet.type = SR_DF_LOGIC;
789 packet.payload = &logic;
790 logic.length = sending_now * devc->logic_unitsize;
791 logic.unitsize = devc->logic_unitsize;
792 logic.data = devc->logic_data;
793 sr_session_send(sdi, &packet);
a49a320d 794 logic_done += sending_now;
8b2d41ed
BV
795 }
796
ba7dd8bb 797 /* Analog, one channel at a time */
a49a320d 798 if (analog_done < samples_todo) {
b62bb97a 799 analog_sent = 0;
49224c28
BV
800
801 g_hash_table_iter_init(&iter, devc->ch_ag);
802 while (g_hash_table_iter_next(&iter, NULL, &value)) {
a49a320d
DE
803 send_analog_packet(value, sdi, &analog_sent,
804 devc->sent_samples + analog_done,
805 samples_todo - analog_done);
8b2d41ed 806 }
a49a320d 807 analog_done += analog_sent;
8b2d41ed 808 }
3b203673 809 }
a49a320d
DE
810 /* At this point, both logic_done and analog_done should be
811 * exactly equal to samples_todo, or else.
812 */
813 if (logic_done != samples_todo || analog_done != samples_todo) {
814 sr_err("BUG: Sample count mismatch.");
815 return G_SOURCE_REMOVE;
816 }
817 devc->sent_samples += samples_todo;
818 devc->spent_us += todo_us;
819
820 if ((devc->limit_samples > 0 && devc->sent_samples >= devc->limit_samples)
821 || (limit_us > 0 && devc->spent_us >= limit_us)) {
3b203673 822
7a8a1aba
BG
823 /* If we're averaging everything - now is the time to send data */
824 if (devc->avg_samples == 0) {
825 g_hash_table_iter_init(&iter, devc->ch_ag);
826 while (g_hash_table_iter_next(&iter, NULL, &value)) {
827 ag = value;
5faebab2 828 packet.type = SR_DF_ANALOG_OLD;
7a8a1aba
BG
829 packet.payload = &ag->packet;
830 ag->packet.data = &ag->avg_val;
831 ag->packet.num_samples = 1;
832 sr_session_send(sdi, &packet);
833 }
834 }
7f4975b4 835 sr_dbg("Requested number of samples reached.");
695dc859 836 dev_acquisition_stop(sdi);
85b5af06 837 }
1924f59f 838
a49a320d 839 return G_SOURCE_CONTINUE;
85b5af06
UH
840}
841
695dc859 842static int dev_acquisition_start(const struct sr_dev_inst *sdi)
6239c175 843{
61c39f54 844 struct dev_context *devc;
49224c28
BV
845 GHashTableIter iter;
846 void *value;
85b5af06 847
e73ffd42
BV
848 if (sdi->status != SR_ST_ACTIVE)
849 return SR_ERR_DEV_CLOSED;
850
61c39f54 851 devc = sdi->priv;
a49a320d 852 devc->sent_samples = 0;
85b5af06 853
49224c28
BV
854 g_hash_table_iter_init(&iter, devc->ch_ag);
855 while (g_hash_table_iter_next(&iter, NULL, &value))
856 generate_analog_pattern(value, devc->cur_samplerate);
4374219b 857
98c01fe1
DE
858 sr_session_source_add(sdi->session, -1, 0, 100,
859 prepare_data, (struct sr_dev_inst *)sdi);
85b5af06 860
102f1239 861 std_session_send_df_header(sdi, LOG_PREFIX);
f366e86c 862
3b203673 863 /* We use this timestamp to decide how many more samples to send. */
a49a320d
DE
864 devc->start_us = g_get_monotonic_time();
865 devc->spent_us = 0;
3b203673 866
e46b8fb1 867 return SR_OK;
6239c175
UH
868}
869
695dc859 870static int dev_acquisition_stop(struct sr_dev_inst *sdi)
6239c175 871{
a84f6ad3 872 sr_dbg("Stopping acquisition.");
027bf077 873 sr_session_source_remove(sdi->session, -1);
3be42bc2 874 std_session_send_df_end(sdi, LOG_PREFIX);
7fd3e859 875
3010f21c 876 return SR_OK;
6239c175
UH
877}
878
dd5c48a6 879static struct sr_dev_driver demo_driver_info = {
e519ba86
UH
880 .name = "demo",
881 .longname = "Demo driver and pattern generator",
882 .api_version = 1,
c2fdcc25 883 .init = std_init,
700d6b64 884 .cleanup = std_cleanup,
6078d2c9 885 .scan = scan,
c01bf34c 886 .dev_list = std_dev_list,
6ab68731 887 .dev_clear = dev_clear,
035a1078
BV
888 .config_get = config_get,
889 .config_set = config_set,
a1c743fc 890 .config_list = config_list,
6078d2c9
UH
891 .dev_open = dev_open,
892 .dev_close = dev_close,
893 .dev_acquisition_start = dev_acquisition_start,
894 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 895 .context = NULL,
6239c175 896};
dd5c48a6 897SR_REGISTER_DEV_DRIVER(demo_driver_info);