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