]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
demo: sync get/set options
[libsigrok.git] / hardware / demo / demo.c
CommitLineData
6239c175
UH
1/*
2 * This file is part of the sigrok project.
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
92bcedf6
UH
34/* Message logging helpers with driver-specific prefix string. */
35#define DRIVER_LOG_DOMAIN "demo: "
36#define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args)
37#define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args)
38#define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args)
39#define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args)
40#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args)
41#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args)
42
c03ed397 43/* TODO: Number of probes should be configurable. */
e15f48c2 44#define NUM_PROBES 8
c03ed397 45
e15f48c2 46#define DEMONAME "Demo device"
c03ed397
UH
47
48/* The size of chunks to send through the session bus. */
49/* TODO: Should be configurable. */
e15f48c2 50#define BUFSIZE 4096
85b5af06 51
2474d87e
BV
52#define STR_PATTERN_SIGROK "sigrok"
53#define STR_PATTERN_RANDOM "random"
54#define STR_PATTERN_INC "incremental"
55#define STR_PATTERN_ALL_LOW "all-low"
56#define STR_PATTERN_ALL_HIGH "all-high"
57
0d31276b 58/* Supported patterns which we can generate */
e15f48c2 59enum {
0d31276b
UH
60 /**
61 * Pattern which spells "sigrok" using '0's (with '1's as "background")
62 * when displayed using the 'bits' output format.
63 */
c8f4624d 64 PATTERN_SIGROK,
0d31276b 65
c03ed397 66 /** Pattern which consists of (pseudo-)random values on all probes. */
c8f4624d 67 PATTERN_RANDOM,
0d31276b
UH
68
69 /**
70 * Pattern which consists of incrementing numbers.
71 * TODO: Better description.
72 */
c8f4624d 73 PATTERN_INC,
c03ed397
UH
74
75 /** Pattern where all probes have a low logic state. */
76 PATTERN_ALL_LOW,
77
78 /** Pattern where all probes have a high logic state. */
79 PATTERN_ALL_HIGH,
e15f48c2 80};
85b5af06 81
b4750a3a
BV
82/* Private, per-device-instance driver context. */
83struct dev_context {
e15f48c2 84 int pipe_fds[2];
249ae2be 85 GIOChannel *channels[2];
e15f48c2 86 uint8_t sample_generator;
e15f48c2 87 uint64_t samples_counter;
3e9b7f9c 88 void *cb_data;
3b203673 89 int64_t starttime;
e15f48c2 90};
85b5af06 91
915f7cc8 92static const int hwcaps[] = {
1953564a
BV
93 SR_CONF_LOGIC_ANALYZER,
94 SR_CONF_DEMO_DEV,
95 SR_CONF_SAMPLERATE,
96 SR_CONF_PATTERN_MODE,
97 SR_CONF_LIMIT_SAMPLES,
98 SR_CONF_LIMIT_MSEC,
99 SR_CONF_CONTINUOUS,
6239c175
UH
100};
101
a533743d 102static const struct sr_samplerates samplerates = {
d3b38ad3
UH
103 .low = SR_HZ(1),
104 .high = SR_GHZ(1),
105 .step = SR_HZ(1),
106 .list = NULL,
4bfbf9fc
BV
107};
108
c8f4624d 109static const char *pattern_strings[] = {
c03ed397 110 "sigrok",
e15f48c2
BV
111 "random",
112 "incremental",
c03ed397
UH
113 "all-low",
114 "all-high",
02440dd8 115 NULL,
85b5af06
UH
116};
117
d261dbbf 118/* We name the probes 0-7 on our demo driver. */
464d12c7 119static const char *probe_names[NUM_PROBES + 1] = {
78693401 120 "0", "1", "2", "3", "4", "5", "6", "7",
464d12c7
KS
121 NULL,
122};
123
c8f4624d 124static uint8_t pattern_sigrok[] = {
917e0e71
BV
125 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
126 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
127 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
128 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
129 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
130 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133};
134
ea9cfed7
UH
135/* Private, per-device-instance driver context. */
136/* TODO: struct context as with the other drivers. */
137
e7eb703f 138/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
dcf03d6d 139SR_PRIV struct sr_dev_driver demo_driver_info;
a873c594 140static struct sr_dev_driver *di = &demo_driver_info;
59df0c77 141static uint64_t cur_samplerate = SR_KHZ(200);
b9cc3629
BV
142static uint64_t limit_samples = 0;
143static uint64_t limit_msec = 0;
c8f4624d 144static int default_pattern = PATTERN_SIGROK;
6239c175 145
69b07d14 146static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 147
eebb6067
UH
148static int clear_instances(void)
149{
150 /* Nothing needed so far. */
151
152 return SR_OK;
153}
154
34f06b90 155static int hw_init(struct sr_context *sr_ctx)
61136ea6 156{
063e7aef 157 return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
61136ea6
BV
158}
159
067d0716 160static GSList *hw_scan(GSList *options)
6239c175 161{
d68e2d1a 162 struct sr_dev_inst *sdi;
87ca93c5 163 struct sr_probe *probe;
b4750a3a 164 struct drv_context *drvc;
067d0716 165 GSList *devices;
87ca93c5 166 int i;
067d0716
BV
167
168 (void)options;
64d33dc2 169
a873c594 170 drvc = di->priv;
4b97c74e 171
067d0716 172 devices = NULL;
85b5af06 173
d3683c42 174 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 175 if (!sdi) {
92bcedf6 176 sr_err("%s: sr_dev_inst_new failed", __func__);
85b5af06 177 return 0;
c03ed397 178 }
a873c594 179 sdi->driver = di;
e15f48c2 180
87ca93c5 181 for (i = 0; probe_names[i]; i++) {
de6e0eca 182 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
87ca93c5
BV
183 probe_names[i])))
184 return NULL;
185 sdi->probes = g_slist_append(sdi->probes, probe);
186 }
187
067d0716 188 devices = g_slist_append(devices, sdi);
b4750a3a 189 drvc->instances = g_slist_append(drvc->instances, sdi);
85b5af06 190
067d0716 191 return devices;
6239c175
UH
192}
193
811deee4
BV
194static GSList *hw_dev_list(void)
195{
0e94d524 196 return ((struct drv_context *)(di->priv))->instances;
811deee4
BV
197}
198
25a0f108 199static int hw_dev_open(struct sr_dev_inst *sdi)
6239c175 200{
25a0f108 201 (void)sdi;
6239c175
UH
202
203 /* Nothing needed so far. */
697785d1 204
e46b8fb1 205 return SR_OK;
6239c175
UH
206}
207
25a0f108 208static int hw_dev_close(struct sr_dev_inst *sdi)
6239c175 209{
25a0f108 210 (void)sdi;
6239c175
UH
211
212 /* Nothing needed so far. */
697785d1
UH
213
214 return SR_OK;
6239c175
UH
215}
216
57ab7d9f 217static int hw_cleanup(void)
6239c175
UH
218{
219 /* Nothing needed so far. */
57ab7d9f 220 return SR_OK;
6239c175
UH
221}
222
035a1078 223static int config_get(int id, const void **data, const struct sr_dev_inst *sdi)
6239c175 224{
6f57fd96
BV
225 (void)sdi;
226
035a1078 227 switch (id) {
123e1313 228 case SR_CONF_SAMPLERATE:
dfb0fa1a 229 *data = &cur_samplerate;
6239c175 230 break;
2474d87e
BV
231 case SR_CONF_LIMIT_SAMPLES:
232 *data = &limit_samples;
233 break;
234 case SR_CONF_LIMIT_MSEC:
235 *data = &limit_msec;
236 break;
237 case SR_CONF_PATTERN_MODE:
238 switch (default_pattern) {
239 case PATTERN_SIGROK:
240 *data = STR_PATTERN_SIGROK;
241 break;
242 case PATTERN_RANDOM:
243 *data = STR_PATTERN_RANDOM;
244 break;
245 case PATTERN_INC:
246 *data = STR_PATTERN_INC;
247 break;
248 case PATTERN_ALL_LOW:
249 *data = STR_PATTERN_ALL_LOW;
250 break;
251 case PATTERN_ALL_HIGH:
252 *data = STR_PATTERN_ALL_HIGH;
253 break;
254 }
255 break;
7dfcf010
BV
256 default:
257 return SR_ERR_ARG;
6239c175
UH
258 }
259
dfb0fa1a 260 return SR_OK;
6239c175
UH
261}
262
035a1078 263static int config_set(int id, const void *value, const struct sr_dev_inst *sdi)
6239c175
UH
264{
265 int ret;
1b79df2f 266 const char *stropt;
6239c175 267
6f4b1868 268 (void)sdi;
6239c175 269
035a1078 270 if (id == SR_CONF_SAMPLERATE) {
1b79df2f 271 cur_samplerate = *(const uint64_t *)value;
92bcedf6 272 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
6f422264 273 cur_samplerate);
e46b8fb1 274 ret = SR_OK;
035a1078 275 } else if (id == SR_CONF_LIMIT_SAMPLES) {
8489264f 276 limit_msec = 0;
1b79df2f 277 limit_samples = *(const uint64_t *)value;
92bcedf6 278 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
6f422264 279 limit_samples);
e46b8fb1 280 ret = SR_OK;
035a1078 281 } else if (id == SR_CONF_LIMIT_MSEC) {
1b79df2f 282 limit_msec = *(const uint64_t *)value;
8489264f 283 limit_samples = 0;
92bcedf6 284 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
6f422264 285 limit_msec);
e46b8fb1 286 ret = SR_OK;
035a1078 287 } else if (id == SR_CONF_PATTERN_MODE) {
e15f48c2 288 stropt = value;
c03ed397 289 ret = SR_OK;
2474d87e 290 if (!strcmp(stropt, STR_PATTERN_SIGROK)) {
c03ed397 291 default_pattern = PATTERN_SIGROK;
2474d87e 292 } else if (!strcmp(stropt, STR_PATTERN_RANDOM)) {
c8f4624d 293 default_pattern = PATTERN_RANDOM;
2474d87e 294 } else if (!strcmp(stropt, STR_PATTERN_INC)) {
c8f4624d 295 default_pattern = PATTERN_INC;
2474d87e 296 } else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) {
c03ed397 297 default_pattern = PATTERN_ALL_LOW;
2474d87e 298 } else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) {
c03ed397 299 default_pattern = PATTERN_ALL_HIGH;
e15f48c2 300 } else {
e46b8fb1 301 ret = SR_ERR;
e15f48c2 302 }
92bcedf6 303 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
6239c175 304 } else {
e46b8fb1 305 ret = SR_ERR;
6239c175
UH
306 }
307
308 return ret;
309}
310
a1c743fc
BV
311static int config_list(int key, const void **data, const struct sr_dev_inst *sdi)
312{
313
314 (void)sdi;
315
316 switch (key) {
9a6517d1
BV
317 case SR_CONF_DEVICE_OPTIONS:
318 *data = hwcaps;
319 break;
a1c743fc
BV
320 case SR_CONF_SAMPLERATE:
321 *data = &samplerates;
322 break;
dd96ea98
BV
323 case SR_CONF_PATTERN_MODE:
324 *data = &pattern_strings;
325 break;
a1c743fc
BV
326 default:
327 return SR_ERR_ARG;
328 }
329
330 return SR_OK;
331}
332
3b203673
AG
333static void samples_generator(uint8_t *buf, uint64_t size,
334 struct dev_context *devc)
85b5af06 335{
cddd1c5f 336 static uint64_t p = 0;
cddd1c5f 337 uint64_t i;
85b5af06 338
c03ed397 339 /* TODO: Needed? */
5096c6a6 340 memset(buf, 0, size);
85b5af06 341
b4750a3a 342 switch (devc->sample_generator) {
c03ed397 343 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 344 for (i = 0; i < size; i++) {
c8f4624d 345 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
346 if (++p == 64)
347 p = 0;
348 }
349 break;
c8f4624d 350 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
351 for (i = 0; i < size; i++)
352 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 353 break;
c8f4624d 354 case PATTERN_INC: /* Simple increment */
5096c6a6 355 for (i = 0; i < size; i++)
85b5af06
UH
356 *(buf + i) = i;
357 break;
c03ed397 358 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 359 memset(buf, 0x00, size);
c03ed397
UH
360 break;
361 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 362 memset(buf, 0xff, size);
c03ed397
UH
363 break;
364 default:
92bcedf6 365 sr_err("Unknown pattern: %d.", devc->sample_generator);
c03ed397 366 break;
85b5af06
UH
367 }
368}
369
85b5af06 370/* Callback handling data */
1f9813eb 371static int receive_data(int fd, int revents, void *cb_data)
85b5af06 372{
b4750a3a 373 struct dev_context *devc = cb_data;
b9c735a2 374 struct sr_datafeed_packet packet;
9c939c51 375 struct sr_datafeed_logic logic;
3b203673
AG
376 uint8_t buf[BUFSIZE];
377 static uint64_t samples_to_send, expected_samplenum, sending_now;
378 int64_t time, elapsed;
1924f59f 379
cb93f8a9
UH
380 (void)fd;
381 (void)revents;
1924f59f 382
3b203673
AG
383 /* How many "virtual" samples should we have collected by now? */
384 time = g_get_monotonic_time();
385 elapsed = time - devc->starttime;
386 expected_samplenum = elapsed * cur_samplerate / 1000000;
387 /* Of those, how many do we still have to send? */
388 samples_to_send = expected_samplenum - devc->samples_counter;
389
390 if (limit_samples) {
391 samples_to_send = MIN(samples_to_send,
392 limit_samples - devc->samples_counter);
393 }
85b5af06 394
3b203673
AG
395 while (samples_to_send > 0) {
396 sending_now = MIN(samples_to_send, sizeof(buf));
397 samples_to_send -= sending_now;
398 samples_generator(buf, sending_now, devc);
399
400 packet.type = SR_DF_LOGIC;
401 packet.payload = &logic;
402 logic.length = sending_now;
403 logic.unitsize = 1;
404 logic.data = buf;
3e9b7f9c 405 sr_session_send(devc->cb_data, &packet);
3b203673
AG
406 devc->samples_counter += sending_now;
407 }
408
35e199da
UH
409 if (limit_samples && devc->samples_counter >= limit_samples) {
410 sr_info("Requested number of samples reached.");
c216d623
AG
411 hw_dev_acquisition_stop(NULL, cb_data);
412 return TRUE;
85b5af06 413 }
1924f59f 414
85b5af06
UH
415 return TRUE;
416}
417
3ffb6964
BV
418static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
419 void *cb_data)
6239c175 420{
b4750a3a 421 struct dev_context *devc;
6239c175 422
3ffb6964
BV
423 (void)sdi;
424
b4750a3a
BV
425 /* TODO: 'devc' is never g_free()'d? */
426 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
92bcedf6 427 sr_err("%s: devc malloc failed", __func__);
e46b8fb1 428 return SR_ERR_MALLOC;
27a3a6fe 429 }
85b5af06 430
b4750a3a 431 devc->sample_generator = default_pattern;
3e9b7f9c 432 devc->cb_data = cb_data;
b4750a3a 433 devc->samples_counter = 0;
85b5af06 434
3b203673
AG
435 /*
436 * Setting two channels connected by a pipe is a remnant from when the
437 * demo driver generated data in a thread, and collected and sent the
438 * data in the main program loop.
439 * They are kept here because it provides a convenient way of setting
440 * up a timeout-based polling mechanism.
441 */
b4750a3a 442 if (pipe(devc->pipe_fds)) {
c03ed397 443 /* TODO: Better error message. */
92bcedf6 444 sr_err("%s: pipe() failed", __func__);
e46b8fb1 445 return SR_ERR;
c03ed397 446 }
85b5af06 447
b4750a3a
BV
448 devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
449 devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
d35aaf02 450
b4750a3a 451 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 452
d35aaf02 453 /* Set channel encoding to binary (default is UTF-8). */
b4750a3a
BV
454 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
455 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
d35aaf02
UH
456
457 /* Make channels to unbuffered. */
b4750a3a
BV
458 g_io_channel_set_buffered(devc->channels[0], FALSE);
459 g_io_channel_set_buffered(devc->channels[1], FALSE);
d35aaf02 460
b4750a3a
BV
461 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
462 40, receive_data, devc);
85b5af06 463
4afdfd46
UH
464 /* Send header packet to the session bus. */
465 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
f366e86c 466
3b203673
AG
467 /* We use this timestamp to decide how many more samples to send. */
468 devc->starttime = g_get_monotonic_time();
469
e46b8fb1 470 return SR_OK;
6239c175
UH
471}
472
69b07d14 473static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 474{
7fd3e859 475 struct dev_context *devc;
c216d623 476 struct sr_datafeed_packet packet;
7fd3e859 477
c216d623 478 (void)sdi;
6239c175 479
c216d623 480 devc = cb_data;
7fd3e859 481
49145a63
AG
482 sr_dbg("Stopping aquisition.");
483
7fd3e859 484 sr_session_source_remove_channel(devc->channels[0]);
c216d623
AG
485 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
486
487 /* Send last packet. */
488 packet.type = SR_DF_END;
3e9b7f9c 489 sr_session_send(devc->cb_data, &packet);
7fd3e859 490
3010f21c 491 return SR_OK;
6239c175
UH
492}
493
c09f0b57 494SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
495 .name = "demo",
496 .longname = "Demo driver and pattern generator",
497 .api_version = 1,
498 .init = hw_init,
499 .cleanup = hw_cleanup,
61136ea6 500 .scan = hw_scan,
811deee4 501 .dev_list = hw_dev_list,
eebb6067 502 .dev_clear = clear_instances,
035a1078
BV
503 .config_get = config_get,
504 .config_set = config_set,
a1c743fc 505 .config_list = config_list,
e7eb703f
UH
506 .dev_open = hw_dev_open,
507 .dev_close = hw_dev_close,
69040b7c
UH
508 .dev_acquisition_start = hw_dev_acquisition_start,
509 .dev_acquisition_stop = hw_dev_acquisition_stop,
b4750a3a 510 .priv = NULL,
6239c175 511};