2 * This file is part of the libsigrok project.
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>
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.
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.
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
29 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
31 #include "libsigrok.h"
32 #include "libsigrok-internal.h"
34 #define LOG_PREFIX "demo"
36 /* TODO: Number of probes should be configurable. */
39 /* The size of chunks to send through the session bus. */
40 /* TODO: Should be configurable. */
41 #define LOGIC_BUFSIZE 4096
43 /* Patterns we can generate */
46 * Spells "sigrok" across 8 probes using '0's (with '1's as
47 * "background") when displayed using the 'bits' output format.
51 /** Pseudo-)random values on all probes. */
55 * Incrementing number across all probes.
59 /** All probes have a low logic state. */
62 /** All probes have a high logic state. */
66 static const char *pattern_strings[] = {
74 /* Private, per-device-instance driver context. */
78 uint64_t cur_samplerate;
79 uint64_t limit_samples;
81 uint8_t sample_generator;
82 uint64_t samples_counter;
85 unsigned char logic_data[LOGIC_BUFSIZE];
89 static const int hwcaps[] = {
90 SR_CONF_LOGIC_ANALYZER,
94 SR_CONF_LIMIT_SAMPLES,
99 static const uint64_t samplerates[] = {
105 static uint8_t pattern_sigrok[] = {
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,
116 /* Private, per-device-instance driver context. */
117 /* TODO: struct context as with the other drivers. */
119 /* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
120 SR_PRIV struct sr_dev_driver demo_driver_info;
121 static struct sr_dev_driver *di = &demo_driver_info;
123 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
125 static int dev_clear(void)
127 return std_dev_clear(di, NULL);
130 static int init(struct sr_context *sr_ctx)
132 return std_init(sr_ctx, di, LOG_PREFIX);
135 static GSList *scan(GSList *options)
137 struct sr_dev_inst *sdi;
138 struct sr_probe *probe;
139 struct drv_context *drvc;
140 struct dev_context *devc;
151 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, "Demo device", NULL, NULL);
153 sr_err("Device instance creation failed.");
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)))
162 sdi->probes = g_slist_append(sdi->probes, probe);
165 devices = g_slist_append(devices, sdi);
166 drvc->instances = g_slist_append(drvc->instances, sdi);
168 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
169 sr_err("Device context malloc failed.");
173 devc->cur_samplerate = SR_KHZ(200);
174 devc->limit_samples = 0;
175 devc->limit_msec = 0;
176 devc->sample_generator = PATTERN_SIGROK;
184 static GSList *dev_list(void)
186 return ((struct drv_context *)(di->priv))->instances;
189 static int dev_open(struct sr_dev_inst *sdi)
191 sdi->status = SR_ST_ACTIVE;
196 static int dev_close(struct sr_dev_inst *sdi)
198 sdi->status = SR_ST_INACTIVE;
203 static int cleanup(void)
208 static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
209 const struct sr_probe_group *probe_group)
211 struct dev_context *const devc = sdi->priv;
216 case SR_CONF_SAMPLERATE:
217 *data = g_variant_new_uint64(devc->cur_samplerate);
219 case SR_CONF_LIMIT_SAMPLES:
220 *data = g_variant_new_uint64(devc->limit_samples);
222 case SR_CONF_LIMIT_MSEC:
223 *data = g_variant_new_uint64(devc->limit_msec);
225 case SR_CONF_PATTERN_MODE:
226 *data = g_variant_new_string(pattern_strings[devc->sample_generator]);
235 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
236 const struct sr_probe_group *probe_group)
243 struct dev_context *const devc = sdi->priv;
245 if (sdi->status != SR_ST_ACTIVE)
246 return SR_ERR_DEV_CLOSED;
248 if (id == SR_CONF_SAMPLERATE) {
249 devc->cur_samplerate = g_variant_get_uint64(data);
250 sr_dbg("Setting samplerate to %" PRIu64, devc->cur_samplerate);
252 } else if (id == SR_CONF_LIMIT_SAMPLES) {
253 devc->limit_msec = 0;
254 devc->limit_samples = g_variant_get_uint64(data);
255 sr_dbg("Setting limit_samples to %" PRIu64, devc->limit_samples);
257 } else if (id == SR_CONF_LIMIT_MSEC) {
258 devc->limit_msec = g_variant_get_uint64(data);
259 devc->limit_samples = 0;
260 sr_dbg("Setting limit_msec to %" PRIu64, devc->limit_msec);
262 } else if (id == SR_CONF_PATTERN_MODE) {
263 stropt = g_variant_get_string(data, NULL);
265 for (i = 0; i < ARRAY_SIZE(pattern_strings); i++) {
266 if (!strcmp(stropt, pattern_strings[i])) {
267 devc->sample_generator = i;
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]);
285 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
286 const struct sr_probe_group *probe_group)
295 case SR_CONF_DEVICE_OPTIONS:
296 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
297 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
299 case SR_CONF_SAMPLERATE:
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);
306 case SR_CONF_PATTERN_MODE:
307 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
316 static void sample_generator(struct sr_dev_inst *sdi, uint64_t size)
318 struct dev_context *devc;
323 switch (devc->sample_generator) {
325 for (i = 0; i < size; i++) {
326 devc->logic_data[i] = ~(pattern_sigrok[
327 devc->step++ % sizeof(pattern_sigrok)] >> 1);
331 for (i = 0; i < size; i++)
332 devc->logic_data[i] = (uint8_t)(rand() & 0xff);
335 for (i = 0; i < size; i++)
336 devc->logic_data[i] = devc->step++;
338 case PATTERN_ALL_LOW:
339 case PATTERN_ALL_HIGH:
340 /* These were set when the pattern mode was selected. */
343 sr_err("Unknown pattern: %d.", devc->sample_generator);
348 /* Callback handling data */
349 static int prepare_data(int fd, int revents, void *cb_data)
351 struct sr_dev_inst *sdi;
352 struct dev_context *devc;
353 struct sr_datafeed_packet packet;
354 struct sr_datafeed_logic logic;
355 static uint64_t samples_to_send, expected_samplenum, sending_now;
356 int64_t time, elapsed;
364 /* How many "virtual" samples should we have collected by now? */
365 time = g_get_monotonic_time();
366 elapsed = time - devc->starttime;
367 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
368 /* Of those, how many do we still have to send? */
369 samples_to_send = expected_samplenum - devc->samples_counter;
371 if (devc->limit_samples) {
372 samples_to_send = MIN(samples_to_send,
373 devc->limit_samples - devc->samples_counter);
376 while (samples_to_send > 0) {
377 sending_now = MIN(samples_to_send, LOGIC_BUFSIZE);
378 samples_to_send -= sending_now;
379 sample_generator(sdi, sending_now);
381 packet.type = SR_DF_LOGIC;
382 packet.payload = &logic;
383 logic.length = sending_now;
385 logic.data = devc->logic_data;
386 sr_session_send(devc->cb_data, &packet);
387 devc->samples_counter += sending_now;
390 if (devc->limit_samples &&
391 devc->samples_counter >= devc->limit_samples) {
392 sr_info("Requested number of samples reached.");
393 dev_acquisition_stop(sdi, cb_data);
400 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
402 struct dev_context *devc;
404 if (sdi->status != SR_ST_ACTIVE)
405 return SR_ERR_DEV_CLOSED;
408 devc->cb_data = cb_data;
409 devc->samples_counter = 0;
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.
418 if (pipe(devc->pipe_fds)) {
419 sr_err("%s: pipe() failed", __func__);
423 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
425 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
427 /* Set channel encoding to binary (default is UTF-8). */
428 g_io_channel_set_encoding(devc->channel, NULL, NULL);
430 /* Make channels to unbuffered. */
431 g_io_channel_set_buffered(devc->channel, FALSE);
433 sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
434 40, prepare_data, (void *)sdi);
436 /* Send header packet to the session bus. */
437 std_session_send_df_header(cb_data, LOG_PREFIX);
439 /* We use this timestamp to decide how many more samples to send. */
440 devc->starttime = g_get_monotonic_time();
445 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
447 struct dev_context *const devc = sdi->priv;
448 struct sr_datafeed_packet packet;
452 sr_dbg("Stopping aquisition.");
454 sr_session_source_remove_channel(devc->channel);
455 g_io_channel_shutdown(devc->channel, FALSE, NULL);
456 g_io_channel_unref(devc->channel);
457 devc->channel = NULL;
459 /* Send last packet. */
460 packet.type = SR_DF_END;
461 sr_session_send(devc->cb_data, &packet);
466 SR_PRIV struct sr_dev_driver demo_driver_info = {
468 .longname = "Demo driver and pattern generator",
473 .dev_list = dev_list,
474 .dev_clear = dev_clear,
475 .config_get = config_get,
476 .config_set = config_set,
477 .config_list = config_list,
478 .dev_open = dev_open,
479 .dev_close = dev_close,
480 .dev_acquisition_start = dev_acquisition_start,
481 .dev_acquisition_stop = dev_acquisition_stop,