]> sigrok.org Git - libsigrok.git/blame_incremental - hardware/demo/demo.c
demo: Moved demo configuration variables into dev_context
[libsigrok.git] / hardware / demo / demo.c
... / ...
CommitLineData
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
6 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
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>
24#include <unistd.h>
25#include <string.h>
26#ifdef _WIN32
27#include <io.h>
28#include <fcntl.h>
29#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
30#endif
31#include "libsigrok.h"
32#include "libsigrok-internal.h"
33
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
43/* TODO: Number of probes should be configurable. */
44#define NUM_PROBES 8
45
46#define DEMONAME "Demo device"
47
48/* The size of chunks to send through the session bus. */
49/* TODO: Should be configurable. */
50#define BUFSIZE 4096
51
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
58/* Supported patterns which we can generate */
59enum {
60 /**
61 * Pattern which spells "sigrok" using '0's (with '1's as "background")
62 * when displayed using the 'bits' output format.
63 */
64 PATTERN_SIGROK,
65
66 /** Pattern which consists of (pseudo-)random values on all probes. */
67 PATTERN_RANDOM,
68
69 /**
70 * Pattern which consists of incrementing numbers.
71 * TODO: Better description.
72 */
73 PATTERN_INC,
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,
80};
81
82/* Private, per-device-instance driver context. */
83struct dev_context {
84 struct sr_dev_inst *sdi;
85 int pipe_fds[2];
86 GIOChannel *channel;
87 uint64_t cur_samplerate;
88 uint64_t limit_samples;
89 uint64_t limit_msec;
90 uint8_t sample_generator;
91 uint64_t samples_counter;
92 void *cb_data;
93 int64_t starttime;
94};
95
96static const int hwcaps[] = {
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,
104};
105
106static const uint64_t samplerates[] = {
107 SR_HZ(1),
108 SR_GHZ(1),
109 SR_HZ(1),
110};
111
112static const char *pattern_strings[] = {
113 "sigrok",
114 "random",
115 "incremental",
116 "all-low",
117 "all-high",
118};
119
120/* We name the probes 0-7 on our demo driver. */
121static const char *probe_names[NUM_PROBES + 1] = {
122 "0", "1", "2", "3", "4", "5", "6", "7",
123 NULL,
124};
125
126static uint8_t pattern_sigrok[] = {
127 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
128 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
129 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
130 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
131 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
132 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135};
136
137/* Private, per-device-instance driver context. */
138/* TODO: struct context as with the other drivers. */
139
140/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
141SR_PRIV struct sr_dev_driver demo_driver_info;
142static struct sr_dev_driver *di = &demo_driver_info;
143
144static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
145
146static int clear_instances(void)
147{
148 /* Nothing needed so far. */
149
150 return SR_OK;
151}
152
153static int hw_init(struct sr_context *sr_ctx)
154{
155 return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
156}
157
158static GSList *hw_scan(GSList *options)
159{
160 struct sr_dev_inst *sdi;
161 struct sr_probe *probe;
162 struct drv_context *drvc;
163 struct dev_context *devc;
164 GSList *devices;
165 int i;
166
167 (void)options;
168
169 drvc = di->priv;
170
171 devices = NULL;
172
173 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
174 if (!sdi) {
175 sr_err("%s: sr_dev_inst_new failed", __func__);
176 return 0;
177 }
178 sdi->driver = di;
179
180 for (i = 0; probe_names[i]; i++) {
181 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
182 probe_names[i])))
183 return NULL;
184 sdi->probes = g_slist_append(sdi->probes, probe);
185 }
186
187 devices = g_slist_append(devices, sdi);
188 drvc->instances = g_slist_append(drvc->instances, sdi);
189
190 /* TODO: 'devc' is never g_free()'d? */
191 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
192 sr_err("%s: devc malloc failed", __func__);
193 return SR_ERR_MALLOC;
194 }
195
196 devc->sdi = sdi;
197 devc->cur_samplerate = SR_KHZ(200);
198 devc->limit_samples = 0;
199 devc->limit_msec = 0;
200 devc->sample_generator = PATTERN_SIGROK;
201
202 sdi->priv = devc;
203
204 return devices;
205}
206
207static GSList *hw_dev_list(void)
208{
209 return ((struct drv_context *)(di->priv))->instances;
210}
211
212static int hw_dev_open(struct sr_dev_inst *sdi)
213{
214 (void)sdi;
215
216 /* Nothing needed so far. */
217
218 return SR_OK;
219}
220
221static int hw_dev_close(struct sr_dev_inst *sdi)
222{
223 (void)sdi;
224
225 /* Nothing needed so far. */
226
227 return SR_OK;
228}
229
230static int hw_cleanup(void)
231{
232 /* Nothing needed so far. */
233 return SR_OK;
234}
235
236static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
237{
238 struct dev_context *const devc = sdi->priv;
239
240 switch (id) {
241 case SR_CONF_SAMPLERATE:
242 *data = g_variant_new_uint64(devc->cur_samplerate);
243 break;
244 case SR_CONF_LIMIT_SAMPLES:
245 *data = g_variant_new_uint64(devc->limit_samples);
246 break;
247 case SR_CONF_LIMIT_MSEC:
248 *data = g_variant_new_uint64(devc->limit_msec);
249 break;
250 case SR_CONF_PATTERN_MODE:
251 switch (devc->sample_generator) {
252 case PATTERN_SIGROK:
253 *data = g_variant_new_string(STR_PATTERN_SIGROK);
254 break;
255 case PATTERN_RANDOM:
256 *data = g_variant_new_string(STR_PATTERN_RANDOM);
257 break;
258 case PATTERN_INC:
259 *data = g_variant_new_string(STR_PATTERN_INC);
260 break;
261 case PATTERN_ALL_LOW:
262 *data = g_variant_new_string(STR_PATTERN_ALL_LOW);
263 break;
264 case PATTERN_ALL_HIGH:
265 *data = g_variant_new_string(STR_PATTERN_ALL_HIGH);
266 break;
267 }
268 break;
269 default:
270 return SR_ERR_ARG;
271 }
272
273 return SR_OK;
274}
275
276static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
277{
278 int ret;
279 const char *stropt;
280
281 struct dev_context *const devc = sdi->priv;
282
283 if (id == SR_CONF_SAMPLERATE) {
284 devc->cur_samplerate = g_variant_get_uint64(data);
285 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
286 devc->cur_samplerate);
287 ret = SR_OK;
288 } else if (id == SR_CONF_LIMIT_SAMPLES) {
289 devc->limit_msec = 0;
290 devc->limit_samples = g_variant_get_uint64(data);
291 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
292 devc->limit_samples);
293 ret = SR_OK;
294 } else if (id == SR_CONF_LIMIT_MSEC) {
295 devc->limit_msec = g_variant_get_uint64(data);
296 devc->limit_samples = 0;
297 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
298 devc->limit_msec);
299 ret = SR_OK;
300 } else if (id == SR_CONF_PATTERN_MODE) {
301 stropt = g_variant_get_string(data, NULL);
302 ret = SR_OK;
303 if (!strcmp(stropt, STR_PATTERN_SIGROK)) {
304 devc->sample_generator = PATTERN_SIGROK;
305 } else if (!strcmp(stropt, STR_PATTERN_RANDOM)) {
306 devc->sample_generator = PATTERN_RANDOM;
307 } else if (!strcmp(stropt, STR_PATTERN_INC)) {
308 devc->sample_generator = PATTERN_INC;
309 } else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) {
310 devc->sample_generator = PATTERN_ALL_LOW;
311 } else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) {
312 devc->sample_generator = PATTERN_ALL_HIGH;
313 } else {
314 ret = SR_ERR;
315 }
316 sr_dbg("%s: setting pattern to %d",
317 __func__, devc->sample_generator);
318 } else {
319 ret = SR_ERR;
320 }
321
322 return ret;
323}
324
325static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
326{
327 GVariant *gvar;
328 GVariantBuilder gvb;
329
330 (void)sdi;
331
332 switch (key) {
333 case SR_CONF_DEVICE_OPTIONS:
334 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
335 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
336 break;
337 case SR_CONF_SAMPLERATE:
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);
343 break;
344 case SR_CONF_PATTERN_MODE:
345 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
346 break;
347 default:
348 return SR_ERR_ARG;
349 }
350
351 return SR_OK;
352}
353
354static void samples_generator(uint8_t *buf, uint64_t size,
355 struct dev_context *devc)
356{
357 static uint64_t p = 0;
358 uint64_t i;
359
360 /* TODO: Needed? */
361 memset(buf, 0, size);
362
363 switch (devc->sample_generator) {
364 case PATTERN_SIGROK: /* sigrok pattern */
365 for (i = 0; i < size; i++) {
366 *(buf + i) = ~(pattern_sigrok[
367 p++ % sizeof(pattern_sigrok)] >> 1);
368 }
369 break;
370 case PATTERN_RANDOM: /* Random */
371 for (i = 0; i < size; i++)
372 *(buf + i) = (uint8_t)(rand() & 0xff);
373 break;
374 case PATTERN_INC: /* Simple increment */
375 for (i = 0; i < size; i++)
376 *(buf + i) = p++;
377 break;
378 case PATTERN_ALL_LOW: /* All probes are low */
379 memset(buf, 0x00, size);
380 break;
381 case PATTERN_ALL_HIGH: /* All probes are high */
382 memset(buf, 0xff, size);
383 break;
384 default:
385 sr_err("Unknown pattern: %d.", devc->sample_generator);
386 break;
387 }
388}
389
390/* Callback handling data */
391static int receive_data(int fd, int revents, void *cb_data)
392{
393 struct dev_context *devc = cb_data;
394 struct sr_datafeed_packet packet;
395 struct sr_datafeed_logic logic;
396 uint8_t buf[BUFSIZE];
397 static uint64_t samples_to_send, expected_samplenum, sending_now;
398 int64_t time, elapsed;
399
400 (void)fd;
401 (void)revents;
402
403 /* How many "virtual" samples should we have collected by now? */
404 time = g_get_monotonic_time();
405 elapsed = time - devc->starttime;
406 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
407 /* Of those, how many do we still have to send? */
408 samples_to_send = expected_samplenum - devc->samples_counter;
409
410 if (devc->limit_samples) {
411 samples_to_send = MIN(samples_to_send,
412 devc->limit_samples - devc->samples_counter);
413 }
414
415 while (samples_to_send > 0) {
416 sending_now = MIN(samples_to_send, sizeof(buf));
417 samples_to_send -= sending_now;
418 samples_generator(buf, sending_now, devc);
419
420 packet.type = SR_DF_LOGIC;
421 packet.payload = &logic;
422 logic.length = sending_now;
423 logic.unitsize = 1;
424 logic.data = buf;
425 sr_session_send(devc->cb_data, &packet);
426 devc->samples_counter += sending_now;
427 }
428
429 if (devc->limit_samples &&
430 devc->samples_counter >= devc->limit_samples) {
431 sr_info("Requested number of samples reached.");
432 hw_dev_acquisition_stop(devc->sdi, cb_data);
433 return TRUE;
434 }
435
436 return TRUE;
437}
438
439static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
440 void *cb_data)
441{
442 struct dev_context *const devc = sdi->priv;
443
444 devc->cb_data = cb_data;
445 devc->samples_counter = 0;
446
447 /*
448 * Setting two channels connected by a pipe is a remnant from when the
449 * demo driver generated data in a thread, and collected and sent the
450 * data in the main program loop.
451 * They are kept here because it provides a convenient way of setting
452 * up a timeout-based polling mechanism.
453 */
454 if (pipe(devc->pipe_fds)) {
455 /* TODO: Better error message. */
456 sr_err("%s: pipe() failed", __func__);
457 return SR_ERR;
458 }
459
460 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
461
462 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
463
464 /* Set channel encoding to binary (default is UTF-8). */
465 g_io_channel_set_encoding(devc->channel, NULL, NULL);
466
467 /* Make channels to unbuffered. */
468 g_io_channel_set_buffered(devc->channel, FALSE);
469
470 sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
471 40, receive_data, devc);
472
473 /* Send header packet to the session bus. */
474 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
475
476 /* We use this timestamp to decide how many more samples to send. */
477 devc->starttime = g_get_monotonic_time();
478
479 return SR_OK;
480}
481
482static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
483{
484 struct dev_context *const devc = sdi->priv;
485 struct sr_datafeed_packet packet;
486
487 (void)cb_data;
488
489 sr_dbg("Stopping aquisition.");
490
491 sr_session_source_remove_channel(devc->channel);
492 g_io_channel_shutdown(devc->channel, FALSE, NULL);
493
494 /* Send last packet. */
495 packet.type = SR_DF_END;
496 sr_session_send(devc->cb_data, &packet);
497
498 return SR_OK;
499}
500
501SR_PRIV struct sr_dev_driver demo_driver_info = {
502 .name = "demo",
503 .longname = "Demo driver and pattern generator",
504 .api_version = 1,
505 .init = hw_init,
506 .cleanup = hw_cleanup,
507 .scan = hw_scan,
508 .dev_list = hw_dev_list,
509 .dev_clear = clear_instances,
510 .config_get = config_get,
511 .config_set = config_set,
512 .config_list = config_list,
513 .dev_open = hw_dev_open,
514 .dev_close = hw_dev_close,
515 .dev_acquisition_start = hw_dev_acquisition_start,
516 .dev_acquisition_stop = hw_dev_acquisition_stop,
517 .priv = NULL,
518};