]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
demo: User-configurable number of probes.
[libsigrok.git] / 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>
d35aaf02
UH
26#ifdef _WIN32
27#include <io.h>
28#include <fcntl.h>
29#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
30#endif
45c59c8b
BV
31#include "libsigrok.h"
32#include "libsigrok-internal.h"
6239c175 33
3544f848 34#define LOG_PREFIX "demo"
92bcedf6 35
c07f60e7
BV
36#define DEFAULT_NUM_LOGIC_PROBES 8
37#define DEFAULT_NUM_ANALOG_PROBES 4
c03ed397
UH
38
39/* The size of chunks to send through the session bus. */
61c39f54 40#define LOGIC_BUFSIZE 4096
2474d87e 41
61c39f54 42/* Patterns we can generate */
e15f48c2 43enum {
0d31276b 44 /**
61c39f54
BV
45 * Spells "sigrok" across 8 probes using '0's (with '1's as
46 * "background") when displayed using the 'bits' output format.
c07f60e7
BV
47 * The pattern is repeasted every 8 probes, shifted to the right
48 * in time by one bit.
0d31276b 49 */
c8f4624d 50 PATTERN_SIGROK,
0d31276b 51
c07f60e7 52 /** Pseudo-random values on all probes. */
c8f4624d 53 PATTERN_RANDOM,
0d31276b
UH
54
55 /**
c07f60e7
BV
56 * Incrementing number across 8 probes. The pattern is repeasted
57 * every 8 probes, shifted to the right in time by one bit.
0d31276b 58 */
c8f4624d 59 PATTERN_INC,
c03ed397 60
61c39f54 61 /** All probes have a low logic state. */
c03ed397
UH
62 PATTERN_ALL_LOW,
63
61c39f54 64 /** All probes have a high logic state. */
c03ed397 65 PATTERN_ALL_HIGH,
e15f48c2 66};
85b5af06 67
61c39f54
BV
68static const char *pattern_strings[] = {
69 "sigrok",
70 "random",
71 "incremental",
72 "all-low",
73 "all-high",
74};
75
b4750a3a
BV
76/* Private, per-device-instance driver context. */
77struct dev_context {
e15f48c2 78 int pipe_fds[2];
e0532047 79 GIOChannel *channel;
a7684294
JH
80 uint64_t cur_samplerate;
81 uint64_t limit_samples;
82 uint64_t limit_msec;
e15f48c2 83 uint64_t samples_counter;
3b203673 84 int64_t starttime;
61c39f54 85 uint64_t step;
c07f60e7
BV
86 int32_t num_logic_probes;
87 unsigned int logic_unitsize;
88 uint8_t logic_pattern;
89 unsigned char logic_data[LOGIC_BUFSIZE];
90 int32_t num_analog_probes;
91};
92
93static const int32_t hwopts[] = {
94 SR_CONF_NUM_LOGIC_PROBES,
95 SR_CONF_NUM_ANALOG_PROBES,
e15f48c2 96};
85b5af06 97
915f7cc8 98static const int hwcaps[] = {
1953564a
BV
99 SR_CONF_LOGIC_ANALYZER,
100 SR_CONF_DEMO_DEV,
101 SR_CONF_SAMPLERATE,
102 SR_CONF_PATTERN_MODE,
103 SR_CONF_LIMIT_SAMPLES,
104 SR_CONF_LIMIT_MSEC,
105 SR_CONF_CONTINUOUS,
6239c175
UH
106};
107
d00088ca
BV
108static const uint64_t samplerates[] = {
109 SR_HZ(1),
110 SR_GHZ(1),
111 SR_HZ(1),
4bfbf9fc
BV
112};
113
c8f4624d 114static uint8_t pattern_sigrok[] = {
917e0e71
BV
115 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
116 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
117 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
118 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
119 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
120 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123};
124
dcf03d6d 125SR_PRIV struct sr_dev_driver demo_driver_info;
a873c594 126static struct sr_dev_driver *di = &demo_driver_info;
6239c175 127
6078d2c9 128static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 129
c07f60e7 130
3b412e3a 131static int dev_clear(void)
eebb6067 132{
1c2d542d 133 return std_dev_clear(di, NULL);
eebb6067
UH
134}
135
6078d2c9 136static int init(struct sr_context *sr_ctx)
61136ea6 137{
f6beaac5 138 return std_init(sr_ctx, di, LOG_PREFIX);
61136ea6
BV
139}
140
6078d2c9 141static GSList *scan(GSList *options)
6239c175 142{
b4750a3a 143 struct drv_context *drvc;
33ef7573 144 struct dev_context *devc;
c07f60e7
BV
145 struct sr_dev_inst *sdi;
146 struct sr_probe *probe;
147 struct sr_config *src;
148 GSList *devices, *l;
149 int num_logic_probes, num_analog_probes, i;
61c39f54 150 char probe_name[16];
067d0716 151
a873c594 152 drvc = di->priv;
4b97c74e 153
c07f60e7
BV
154 num_logic_probes = DEFAULT_NUM_LOGIC_PROBES;
155 num_analog_probes = DEFAULT_NUM_ANALOG_PROBES;
156 for (l = options; l; l = l->next) {
157 src = l->data;
158 switch (src->key) {
159 case SR_CONF_NUM_LOGIC_PROBES:
160 num_logic_probes = g_variant_get_int32(src->data);
161 break;
162 case SR_CONF_NUM_ANALOG_PROBES:
163 num_analog_probes = g_variant_get_int32(src->data);
164 break;
165 }
166 }
85b5af06 167
c07f60e7 168 devices = NULL;
61c39f54 169 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, "Demo device", NULL, NULL);
c03ed397 170 if (!sdi) {
e45ad6e2
UH
171 sr_err("Device instance creation failed.");
172 return NULL;
c03ed397 173 }
a873c594 174 sdi->driver = di;
e15f48c2 175
c07f60e7 176 for (i = 0; i < num_logic_probes; i++) {
61c39f54
BV
177 sprintf(probe_name, "D%d", i);
178 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, probe_name)))
87ca93c5
BV
179 return NULL;
180 sdi->probes = g_slist_append(sdi->probes, probe);
181 }
182
c07f60e7
BV
183 for (i = 0; i < num_analog_probes; i++) {
184 sprintf(probe_name, "A%d", i);
185 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, probe_name)))
186 return NULL;
187 sdi->probes = g_slist_append(sdi->probes, probe);
188 }
189
067d0716 190 devices = g_slist_append(devices, sdi);
b4750a3a 191 drvc->instances = g_slist_append(drvc->instances, sdi);
85b5af06 192
33ef7573 193 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
e45ad6e2
UH
194 sr_err("Device context malloc failed.");
195 return NULL;
33ef7573 196 }
a7684294
JH
197 devc->cur_samplerate = SR_KHZ(200);
198 devc->limit_samples = 0;
199 devc->limit_msec = 0;
c07f60e7
BV
200 devc->step = 0;
201 devc->num_logic_probes = num_logic_probes;
202 devc->logic_unitsize = (devc->num_logic_probes + 7) / 8;
203 devc->logic_pattern = PATTERN_SIGROK;
204 devc->num_analog_probes = num_analog_probes;
33ef7573
JH
205
206 sdi->priv = devc;
207
067d0716 208 return devices;
6239c175
UH
209}
210
6078d2c9 211static GSList *dev_list(void)
811deee4 212{
0e94d524 213 return ((struct drv_context *)(di->priv))->instances;
811deee4
BV
214}
215
6078d2c9 216static int dev_open(struct sr_dev_inst *sdi)
6239c175 217{
e73ffd42 218 sdi->status = SR_ST_ACTIVE;
697785d1 219
e46b8fb1 220 return SR_OK;
6239c175
UH
221}
222
6078d2c9 223static int dev_close(struct sr_dev_inst *sdi)
6239c175 224{
decfe89d 225 sdi->status = SR_ST_INACTIVE;
697785d1
UH
226
227 return SR_OK;
6239c175
UH
228}
229
6078d2c9 230static int cleanup(void)
6239c175 231{
1c2d542d 232 return dev_clear();
6239c175
UH
233}
234
8f996b89
ML
235static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
236 const struct sr_probe_group *probe_group)
6239c175 237{
c07f60e7 238 struct dev_context *devc;
6f57fd96 239
8f996b89
ML
240 (void)probe_group;
241
c07f60e7 242 devc = sdi->priv;
035a1078 243 switch (id) {
123e1313 244 case SR_CONF_SAMPLERATE:
a7684294 245 *data = g_variant_new_uint64(devc->cur_samplerate);
6239c175 246 break;
2474d87e 247 case SR_CONF_LIMIT_SAMPLES:
a7684294 248 *data = g_variant_new_uint64(devc->limit_samples);
2474d87e
BV
249 break;
250 case SR_CONF_LIMIT_MSEC:
a7684294 251 *data = g_variant_new_uint64(devc->limit_msec);
2474d87e
BV
252 break;
253 case SR_CONF_PATTERN_MODE:
c07f60e7
BV
254 *data = g_variant_new_string(pattern_strings[devc->logic_pattern]);
255 break;
256 case SR_CONF_NUM_LOGIC_PROBES:
257 *data = g_variant_new_int32(devc->num_logic_probes);
258 break;
259 case SR_CONF_NUM_ANALOG_PROBES:
260 *data = g_variant_new_int32(devc->num_analog_probes);
2474d87e 261 break;
7dfcf010 262 default:
bd6fbf62 263 return SR_ERR_NA;
6239c175
UH
264 }
265
dfb0fa1a 266 return SR_OK;
6239c175
UH
267}
268
8f996b89
ML
269static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
270 const struct sr_probe_group *probe_group)
6239c175 271{
61c39f54 272 unsigned int i;
6239c175 273 int ret;
1b79df2f 274 const char *stropt;
6239c175 275
8f996b89 276 (void)probe_group;
a7684294 277 struct dev_context *const devc = sdi->priv;
6239c175 278
e73ffd42
BV
279 if (sdi->status != SR_ST_ACTIVE)
280 return SR_ERR_DEV_CLOSED;
281
035a1078 282 if (id == SR_CONF_SAMPLERATE) {
a7684294 283 devc->cur_samplerate = g_variant_get_uint64(data);
61c39f54 284 sr_dbg("Setting samplerate to %" PRIu64, devc->cur_samplerate);
e46b8fb1 285 ret = SR_OK;
035a1078 286 } else if (id == SR_CONF_LIMIT_SAMPLES) {
a7684294
JH
287 devc->limit_msec = 0;
288 devc->limit_samples = g_variant_get_uint64(data);
61c39f54 289 sr_dbg("Setting limit_samples to %" PRIu64, devc->limit_samples);
e46b8fb1 290 ret = SR_OK;
035a1078 291 } else if (id == SR_CONF_LIMIT_MSEC) {
a7684294
JH
292 devc->limit_msec = g_variant_get_uint64(data);
293 devc->limit_samples = 0;
61c39f54 294 sr_dbg("Setting limit_msec to %" PRIu64, devc->limit_msec);
e46b8fb1 295 ret = SR_OK;
035a1078 296 } else if (id == SR_CONF_PATTERN_MODE) {
d00088ca 297 stropt = g_variant_get_string(data, NULL);
61c39f54
BV
298 ret = SR_ERR;
299 for (i = 0; i < ARRAY_SIZE(pattern_strings); i++) {
300 if (!strcmp(stropt, pattern_strings[i])) {
c07f60e7 301 devc->logic_pattern = i;
61c39f54
BV
302 ret = SR_OK;
303 break;
304 }
e15f48c2 305 }
61c39f54
BV
306 /* Might as well do this now. */
307 if (i == PATTERN_ALL_LOW)
308 memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
309 else if (i == PATTERN_ALL_HIGH)
310 memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
311 sr_dbg("Setting pattern to %s", pattern_strings[i]);
6239c175 312 } else {
bd6fbf62 313 ret = SR_ERR_NA;
6239c175
UH
314 }
315
316 return ret;
317}
318
8f996b89
ML
319static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
320 const struct sr_probe_group *probe_group)
a1c743fc 321{
d00088ca
BV
322 GVariant *gvar;
323 GVariantBuilder gvb;
a1c743fc
BV
324
325 (void)sdi;
8f996b89 326 (void)probe_group;
a1c743fc
BV
327
328 switch (key) {
c07f60e7
BV
329 case SR_CONF_SCAN_OPTIONS:
330 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
331 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
332 break;
9a6517d1 333 case SR_CONF_DEVICE_OPTIONS:
d00088ca
BV
334 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
335 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 336 break;
a1c743fc 337 case SR_CONF_SAMPLERATE:
d00088ca
BV
338 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
339 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
340 ARRAY_SIZE(samplerates), sizeof(uint64_t));
341 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
342 *data = g_variant_builder_end(&gvb);
a1c743fc 343 break;
dd96ea98 344 case SR_CONF_PATTERN_MODE:
d00088ca 345 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
dd96ea98 346 break;
a1c743fc 347 default:
bd6fbf62 348 return SR_ERR_NA;
a1c743fc
BV
349 }
350
351 return SR_OK;
352}
353
c07f60e7 354static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
85b5af06 355{
61c39f54 356 struct dev_context *devc;
c07f60e7
BV
357 uint64_t i, j;
358 uint8_t pat;
85b5af06 359
61c39f54 360 devc = sdi->priv;
85b5af06 361
c07f60e7 362 switch (devc->logic_pattern) {
61c39f54 363 case PATTERN_SIGROK:
c07f60e7
BV
364 memset(devc->logic_data, 0x00, size);
365 for (i = 0; i < size; i += devc->logic_unitsize) {
366 for (j = 0; j < devc->logic_unitsize; j++) {
367 pat = pattern_sigrok[(devc->step + j) % sizeof(pattern_sigrok)] >> 1;
368 devc->logic_data[i + j] = ~pat;
369 }
370 devc->step++;
917e0e71
BV
371 }
372 break;
61c39f54 373 case PATTERN_RANDOM:
5096c6a6 374 for (i = 0; i < size; i++)
61c39f54 375 devc->logic_data[i] = (uint8_t)(rand() & 0xff);
85b5af06 376 break;
61c39f54 377 case PATTERN_INC:
c07f60e7
BV
378 for (i = 0; i < size; i++) {
379 for (j = 0; j < devc->logic_unitsize; j++) {
380 devc->logic_data[i + j] = devc->step;
381 }
382 devc->step++;
383 }
c03ed397 384 break;
61c39f54
BV
385 case PATTERN_ALL_LOW:
386 case PATTERN_ALL_HIGH:
387 /* These were set when the pattern mode was selected. */
c03ed397
UH
388 break;
389 default:
c07f60e7 390 sr_err("Unknown pattern: %d.", devc->logic_pattern);
c03ed397 391 break;
85b5af06
UH
392 }
393}
394
85b5af06 395/* Callback handling data */
61c39f54 396static int prepare_data(int fd, int revents, void *cb_data)
85b5af06 397{
61c39f54
BV
398 struct sr_dev_inst *sdi;
399 struct dev_context *devc;
b9c735a2 400 struct sr_datafeed_packet packet;
9c939c51 401 struct sr_datafeed_logic logic;
c07f60e7 402 uint64_t samples_to_send, expected_samplenum, sending_now;
3b203673 403 int64_t time, elapsed;
1924f59f 404
cb93f8a9
UH
405 (void)fd;
406 (void)revents;
1924f59f 407
61c39f54
BV
408 sdi = cb_data;
409 devc = sdi->priv;
410
3b203673
AG
411 /* How many "virtual" samples should we have collected by now? */
412 time = g_get_monotonic_time();
413 elapsed = time - devc->starttime;
a7684294 414 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
3b203673
AG
415 /* Of those, how many do we still have to send? */
416 samples_to_send = expected_samplenum - devc->samples_counter;
417
a7684294 418 if (devc->limit_samples) {
3b203673 419 samples_to_send = MIN(samples_to_send,
c07f60e7 420 devc->limit_samples - devc->samples_counter);
3b203673 421 }
85b5af06 422
3b203673 423 while (samples_to_send > 0) {
c07f60e7 424 sending_now = MIN(samples_to_send, LOGIC_BUFSIZE / devc->logic_unitsize);
3b203673 425 samples_to_send -= sending_now;
3b203673 426
c07f60e7
BV
427 /* Logic */
428 logic_generator(sdi, sending_now * devc->logic_unitsize);
3b203673
AG
429 packet.type = SR_DF_LOGIC;
430 packet.payload = &logic;
c07f60e7
BV
431 logic.length = sending_now * devc->logic_unitsize;
432 logic.unitsize = devc->logic_unitsize;
61c39f54 433 logic.data = devc->logic_data;
c07f60e7 434 sr_session_send(sdi, &packet);
3b203673
AG
435 devc->samples_counter += sending_now;
436 }
437
a7684294
JH
438 if (devc->limit_samples &&
439 devc->samples_counter >= devc->limit_samples) {
35e199da 440 sr_info("Requested number of samples reached.");
61c39f54 441 dev_acquisition_stop(sdi, cb_data);
c216d623 442 return TRUE;
85b5af06 443 }
1924f59f 444
85b5af06
UH
445 return TRUE;
446}
447
6078d2c9 448static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
6239c175 449{
61c39f54 450 struct dev_context *devc;
85b5af06 451
e73ffd42
BV
452 if (sdi->status != SR_ST_ACTIVE)
453 return SR_ERR_DEV_CLOSED;
454
61c39f54 455 devc = sdi->priv;
b4750a3a 456 devc->samples_counter = 0;
85b5af06 457
3b203673
AG
458 /*
459 * Setting two channels connected by a pipe is a remnant from when the
460 * demo driver generated data in a thread, and collected and sent the
461 * data in the main program loop.
462 * They are kept here because it provides a convenient way of setting
463 * up a timeout-based polling mechanism.
464 */
b4750a3a 465 if (pipe(devc->pipe_fds)) {
92bcedf6 466 sr_err("%s: pipe() failed", __func__);
e46b8fb1 467 return SR_ERR;
c03ed397 468 }
85b5af06 469
e0532047 470 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
d35aaf02 471
e0532047 472 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 473
d35aaf02 474 /* Set channel encoding to binary (default is UTF-8). */
e0532047 475 g_io_channel_set_encoding(devc->channel, NULL, NULL);
d35aaf02
UH
476
477 /* Make channels to unbuffered. */
e0532047 478 g_io_channel_set_buffered(devc->channel, FALSE);
d35aaf02 479
e0532047 480 sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
61c39f54 481 40, prepare_data, (void *)sdi);
85b5af06 482
4afdfd46 483 /* Send header packet to the session bus. */
29a27196 484 std_session_send_df_header(cb_data, LOG_PREFIX);
f366e86c 485
3b203673
AG
486 /* We use this timestamp to decide how many more samples to send. */
487 devc->starttime = g_get_monotonic_time();
488
e46b8fb1 489 return SR_OK;
6239c175
UH
490}
491
6078d2c9 492static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 493{
33ef7573 494 struct dev_context *const devc = sdi->priv;
c216d623 495 struct sr_datafeed_packet packet;
7fd3e859 496
33ef7573 497 (void)cb_data;
7fd3e859 498
49145a63
AG
499 sr_dbg("Stopping aquisition.");
500
e0532047
JH
501 sr_session_source_remove_channel(devc->channel);
502 g_io_channel_shutdown(devc->channel, FALSE, NULL);
2150a69b
JH
503 g_io_channel_unref(devc->channel);
504 devc->channel = NULL;
c216d623
AG
505
506 /* Send last packet. */
507 packet.type = SR_DF_END;
c07f60e7 508 sr_session_send(sdi, &packet);
7fd3e859 509
3010f21c 510 return SR_OK;
6239c175
UH
511}
512
c09f0b57 513SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
514 .name = "demo",
515 .longname = "Demo driver and pattern generator",
516 .api_version = 1,
6078d2c9
UH
517 .init = init,
518 .cleanup = cleanup,
519 .scan = scan,
520 .dev_list = dev_list,
3b412e3a 521 .dev_clear = dev_clear,
035a1078
BV
522 .config_get = config_get,
523 .config_set = config_set,
a1c743fc 524 .config_list = config_list,
6078d2c9
UH
525 .dev_open = dev_open,
526 .dev_close = dev_close,
527 .dev_acquisition_start = dev_acquisition_start,
528 .dev_acquisition_stop = dev_acquisition_stop,
b4750a3a 529 .priv = NULL,
6239c175 530};