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