]> sigrok.org Git - libsigrok.git/blame_incremental - hardware/demo/demo.c
hantek-dso: Adjust to GVariant-based sr_config_* functions
[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 int pipe_fds[2];
85 GIOChannel *channels[2];
86 uint8_t sample_generator;
87 uint64_t samples_counter;
88 void *cb_data;
89 int64_t starttime;
90};
91
92static const int hwcaps[] = {
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,
100};
101
102static const struct sr_samplerates samplerates = {
103 .low = SR_HZ(1),
104 .high = SR_GHZ(1),
105 .step = SR_HZ(1),
106 .list = NULL,
107};
108
109static const char *pattern_strings[] = {
110 "sigrok",
111 "random",
112 "incremental",
113 "all-low",
114 "all-high",
115 NULL,
116};
117
118/* We name the probes 0-7 on our demo driver. */
119static const char *probe_names[NUM_PROBES + 1] = {
120 "0", "1", "2", "3", "4", "5", "6", "7",
121 NULL,
122};
123
124static uint8_t pattern_sigrok[] = {
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
135/* Private, per-device-instance driver context. */
136/* TODO: struct context as with the other drivers. */
137
138/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
139SR_PRIV struct sr_dev_driver demo_driver_info;
140static struct sr_dev_driver *di = &demo_driver_info;
141static uint64_t cur_samplerate = SR_KHZ(200);
142static uint64_t limit_samples = 0;
143static uint64_t limit_msec = 0;
144static int default_pattern = PATTERN_SIGROK;
145
146static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
147
148static int clear_instances(void)
149{
150 /* Nothing needed so far. */
151
152 return SR_OK;
153}
154
155static int hw_init(struct sr_context *sr_ctx)
156{
157 return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
158}
159
160static GSList *hw_scan(GSList *options)
161{
162 struct sr_dev_inst *sdi;
163 struct sr_probe *probe;
164 struct drv_context *drvc;
165 GSList *devices;
166 int i;
167
168 (void)options;
169
170 drvc = di->priv;
171
172 devices = NULL;
173
174 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
175 if (!sdi) {
176 sr_err("%s: sr_dev_inst_new failed", __func__);
177 return 0;
178 }
179 sdi->driver = di;
180
181 for (i = 0; probe_names[i]; i++) {
182 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
183 probe_names[i])))
184 return NULL;
185 sdi->probes = g_slist_append(sdi->probes, probe);
186 }
187
188 devices = g_slist_append(devices, sdi);
189 drvc->instances = g_slist_append(drvc->instances, sdi);
190
191 return devices;
192}
193
194static GSList *hw_dev_list(void)
195{
196 return ((struct drv_context *)(di->priv))->instances;
197}
198
199static int hw_dev_open(struct sr_dev_inst *sdi)
200{
201 (void)sdi;
202
203 /* Nothing needed so far. */
204
205 return SR_OK;
206}
207
208static int hw_dev_close(struct sr_dev_inst *sdi)
209{
210 (void)sdi;
211
212 /* Nothing needed so far. */
213
214 return SR_OK;
215}
216
217static int hw_cleanup(void)
218{
219 /* Nothing needed so far. */
220 return SR_OK;
221}
222
223static int config_get(int id, const void **data, const struct sr_dev_inst *sdi)
224{
225 (void)sdi;
226
227 switch (id) {
228 case SR_CONF_SAMPLERATE:
229 *data = &cur_samplerate;
230 break;
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;
256 default:
257 return SR_ERR_ARG;
258 }
259
260 return SR_OK;
261}
262
263static int config_set(int id, const void *value, const struct sr_dev_inst *sdi)
264{
265 int ret;
266 const char *stropt;
267
268 (void)sdi;
269
270 if (id == SR_CONF_SAMPLERATE) {
271 cur_samplerate = *(const uint64_t *)value;
272 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
273 cur_samplerate);
274 ret = SR_OK;
275 } else if (id == SR_CONF_LIMIT_SAMPLES) {
276 limit_msec = 0;
277 limit_samples = *(const uint64_t *)value;
278 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
279 limit_samples);
280 ret = SR_OK;
281 } else if (id == SR_CONF_LIMIT_MSEC) {
282 limit_msec = *(const uint64_t *)value;
283 limit_samples = 0;
284 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
285 limit_msec);
286 ret = SR_OK;
287 } else if (id == SR_CONF_PATTERN_MODE) {
288 stropt = value;
289 ret = SR_OK;
290 if (!strcmp(stropt, STR_PATTERN_SIGROK)) {
291 default_pattern = PATTERN_SIGROK;
292 } else if (!strcmp(stropt, STR_PATTERN_RANDOM)) {
293 default_pattern = PATTERN_RANDOM;
294 } else if (!strcmp(stropt, STR_PATTERN_INC)) {
295 default_pattern = PATTERN_INC;
296 } else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) {
297 default_pattern = PATTERN_ALL_LOW;
298 } else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) {
299 default_pattern = PATTERN_ALL_HIGH;
300 } else {
301 ret = SR_ERR;
302 }
303 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
304 } else {
305 ret = SR_ERR;
306 }
307
308 return ret;
309}
310
311static int config_list(int key, const void **data, const struct sr_dev_inst *sdi)
312{
313
314 (void)sdi;
315
316 switch (key) {
317 case SR_CONF_DEVICE_OPTIONS:
318 *data = hwcaps;
319 break;
320 case SR_CONF_SAMPLERATE:
321 *data = &samplerates;
322 break;
323 case SR_CONF_PATTERN_MODE:
324 *data = &pattern_strings;
325 break;
326 default:
327 return SR_ERR_ARG;
328 }
329
330 return SR_OK;
331}
332
333static void samples_generator(uint8_t *buf, uint64_t size,
334 struct dev_context *devc)
335{
336 static uint64_t p = 0;
337 uint64_t i;
338
339 /* TODO: Needed? */
340 memset(buf, 0, size);
341
342 switch (devc->sample_generator) {
343 case PATTERN_SIGROK: /* sigrok pattern */
344 for (i = 0; i < size; i++) {
345 *(buf + i) = ~(pattern_sigrok[p] >> 1);
346 if (++p == 64)
347 p = 0;
348 }
349 break;
350 case PATTERN_RANDOM: /* Random */
351 for (i = 0; i < size; i++)
352 *(buf + i) = (uint8_t)(rand() & 0xff);
353 break;
354 case PATTERN_INC: /* Simple increment */
355 for (i = 0; i < size; i++)
356 *(buf + i) = i;
357 break;
358 case PATTERN_ALL_LOW: /* All probes are low */
359 memset(buf, 0x00, size);
360 break;
361 case PATTERN_ALL_HIGH: /* All probes are high */
362 memset(buf, 0xff, size);
363 break;
364 default:
365 sr_err("Unknown pattern: %d.", devc->sample_generator);
366 break;
367 }
368}
369
370/* Callback handling data */
371static int receive_data(int fd, int revents, void *cb_data)
372{
373 struct dev_context *devc = cb_data;
374 struct sr_datafeed_packet packet;
375 struct sr_datafeed_logic logic;
376 uint8_t buf[BUFSIZE];
377 static uint64_t samples_to_send, expected_samplenum, sending_now;
378 int64_t time, elapsed;
379
380 (void)fd;
381 (void)revents;
382
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 }
394
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;
405 sr_session_send(devc->cb_data, &packet);
406 devc->samples_counter += sending_now;
407 }
408
409 if (limit_samples && devc->samples_counter >= limit_samples) {
410 sr_info("Requested number of samples reached.");
411 hw_dev_acquisition_stop(NULL, cb_data);
412 return TRUE;
413 }
414
415 return TRUE;
416}
417
418static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
419 void *cb_data)
420{
421 struct dev_context *devc;
422
423 (void)sdi;
424
425 /* TODO: 'devc' is never g_free()'d? */
426 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
427 sr_err("%s: devc malloc failed", __func__);
428 return SR_ERR_MALLOC;
429 }
430
431 devc->sample_generator = default_pattern;
432 devc->cb_data = cb_data;
433 devc->samples_counter = 0;
434
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 */
442 if (pipe(devc->pipe_fds)) {
443 /* TODO: Better error message. */
444 sr_err("%s: pipe() failed", __func__);
445 return SR_ERR;
446 }
447
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]);
450
451 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
452
453 /* Set channel encoding to binary (default is UTF-8). */
454 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
455 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
456
457 /* Make channels to unbuffered. */
458 g_io_channel_set_buffered(devc->channels[0], FALSE);
459 g_io_channel_set_buffered(devc->channels[1], FALSE);
460
461 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
462 40, receive_data, devc);
463
464 /* Send header packet to the session bus. */
465 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
466
467 /* We use this timestamp to decide how many more samples to send. */
468 devc->starttime = g_get_monotonic_time();
469
470 return SR_OK;
471}
472
473static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
474{
475 struct dev_context *devc;
476 struct sr_datafeed_packet packet;
477
478 (void)sdi;
479
480 devc = cb_data;
481
482 sr_dbg("Stopping aquisition.");
483
484 sr_session_source_remove_channel(devc->channels[0]);
485 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
486
487 /* Send last packet. */
488 packet.type = SR_DF_END;
489 sr_session_send(devc->cb_data, &packet);
490
491 return SR_OK;
492}
493
494SR_PRIV struct sr_dev_driver demo_driver_info = {
495 .name = "demo",
496 .longname = "Demo driver and pattern generator",
497 .api_version = 1,
498 .init = hw_init,
499 .cleanup = hw_cleanup,
500 .scan = hw_scan,
501 .dev_list = hw_dev_list,
502 .dev_clear = clear_instances,
503 .config_get = config_get,
504 .config_set = config_set,
505 .config_list = config_list,
506 .dev_open = hw_dev_open,
507 .dev_close = hw_dev_close,
508 .dev_acquisition_start = hw_dev_acquisition_start,
509 .dev_acquisition_stop = hw_dev_acquisition_stop,
510 .priv = NULL,
511};