]> sigrok.org Git - libsigrok.git/blame_incremental - hardware/demo/demo.c
victor-dmm: Cosmetics.
[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 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdlib.h>
23#include <unistd.h>
24#include <string.h>
25#ifdef _WIN32
26#include <io.h>
27#include <fcntl.h>
28#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
29#endif
30#include "libsigrok.h"
31#include "libsigrok-internal.h"
32
33/* Message logging helpers with driver-specific prefix string. */
34#define DRIVER_LOG_DOMAIN "demo: "
35#define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args)
36#define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args)
37#define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args)
38#define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args)
39#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args)
40#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args)
41
42/* TODO: Number of probes should be configurable. */
43#define NUM_PROBES 8
44
45#define DEMONAME "Demo device"
46
47/* The size of chunks to send through the session bus. */
48/* TODO: Should be configurable. */
49#define BUFSIZE 4096
50
51/* Supported patterns which we can generate */
52enum {
53 /**
54 * Pattern which spells "sigrok" using '0's (with '1's as "background")
55 * when displayed using the 'bits' output format.
56 */
57 PATTERN_SIGROK,
58
59 /** Pattern which consists of (pseudo-)random values on all probes. */
60 PATTERN_RANDOM,
61
62 /**
63 * Pattern which consists of incrementing numbers.
64 * TODO: Better description.
65 */
66 PATTERN_INC,
67
68 /** Pattern where all probes have a low logic state. */
69 PATTERN_ALL_LOW,
70
71 /** Pattern where all probes have a high logic state. */
72 PATTERN_ALL_HIGH,
73};
74
75/* Private, per-device-instance driver context. */
76struct dev_context {
77 int pipe_fds[2];
78 GIOChannel *channels[2];
79 uint8_t sample_generator;
80 uint8_t thread_running;
81 uint64_t samples_counter;
82 void *session_dev_id;
83 GTimer *timer;
84};
85
86static const int hwcaps[] = {
87 SR_HWCAP_LOGIC_ANALYZER,
88 SR_HWCAP_DEMO_DEV,
89 SR_HWCAP_SAMPLERATE,
90 SR_HWCAP_PATTERN_MODE,
91 SR_HWCAP_LIMIT_SAMPLES,
92 SR_HWCAP_LIMIT_MSEC,
93 SR_HWCAP_CONTINUOUS,
94};
95
96static const struct sr_samplerates samplerates = {
97 SR_HZ(1),
98 SR_GHZ(1),
99 SR_HZ(1),
100 NULL,
101};
102
103static const char *pattern_strings[] = {
104 "sigrok",
105 "random",
106 "incremental",
107 "all-low",
108 "all-high",
109 NULL,
110};
111
112/* We name the probes 0-7 on our demo driver. */
113static const char *probe_names[NUM_PROBES + 1] = {
114 "0",
115 "1",
116 "2",
117 "3",
118 "4",
119 "5",
120 "6",
121 "7",
122 NULL,
123};
124
125static uint8_t pattern_sigrok[] = {
126 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
127 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
128 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
129 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
130 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
131 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134};
135
136/* Private, per-device-instance driver context. */
137/* TODO: struct context as with the other drivers. */
138
139/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
140SR_PRIV struct sr_dev_driver demo_driver_info;
141static struct sr_dev_driver *ddi = &demo_driver_info;
142static uint64_t cur_samplerate = SR_KHZ(200);
143static uint64_t limit_samples = 0;
144static uint64_t limit_msec = 0;
145static int default_pattern = PATTERN_SIGROK;
146static GThread *my_thread;
147static int thread_running;
148
149static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
150
151static int hw_init(void)
152{
153 struct drv_context *drvc;
154
155 if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
156 sr_err("Driver context malloc failed.");
157 return SR_ERR_MALLOC;
158 }
159 ddi->priv = drvc;
160
161 return SR_OK;
162}
163
164static GSList *hw_scan(GSList *options)
165{
166 struct sr_dev_inst *sdi;
167 struct sr_probe *probe;
168 struct drv_context *drvc;
169 GSList *devices;
170 int i;
171
172 (void)options;
173 drvc = ddi->priv;
174 devices = NULL;
175
176 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
177 if (!sdi) {
178 sr_err("%s: sr_dev_inst_new failed", __func__);
179 return 0;
180 }
181 sdi->driver = ddi;
182
183 for (i = 0; probe_names[i]; i++) {
184 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
185 probe_names[i])))
186 return NULL;
187 sdi->probes = g_slist_append(sdi->probes, probe);
188 }
189
190 devices = g_slist_append(devices, sdi);
191 drvc->instances = g_slist_append(drvc->instances, sdi);
192
193 return devices;
194}
195
196static GSList *hw_dev_list(void)
197{
198 struct drv_context *drvc;
199
200 drvc = ddi->priv;
201
202 return drvc->instances;
203}
204
205static int hw_dev_open(struct sr_dev_inst *sdi)
206{
207 /* Avoid compiler warnings. */
208 (void)sdi;
209
210 /* Nothing needed so far. */
211
212 return SR_OK;
213}
214
215static int hw_dev_close(struct sr_dev_inst *sdi)
216{
217 /* Avoid compiler warnings. */
218 (void)sdi;
219
220 /* Nothing needed so far. */
221
222 return SR_OK;
223}
224
225static int hw_cleanup(void)
226{
227 /* Nothing needed so far. */
228 return SR_OK;
229}
230
231static int hw_info_get(int info_id, const void **data,
232 const struct sr_dev_inst *sdi)
233{
234
235 (void)sdi;
236
237 switch (info_id) {
238 case SR_DI_HWCAPS:
239 *data = hwcaps;
240 break;
241 case SR_DI_NUM_PROBES:
242 *data = GINT_TO_POINTER(NUM_PROBES);
243 break;
244 case SR_DI_PROBE_NAMES:
245 *data = probe_names;
246 break;
247 case SR_DI_SAMPLERATES:
248 *data = &samplerates;
249 break;
250 case SR_DI_CUR_SAMPLERATE:
251 *data = &cur_samplerate;
252 break;
253 case SR_DI_PATTERNS:
254 *data = &pattern_strings;
255 break;
256 default:
257 return SR_ERR_ARG;
258 }
259
260 return SR_OK;
261}
262
263static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
264 const void *value)
265{
266 int ret;
267 const char *stropt;
268
269 (void)sdi;
270
271 if (hwcap == SR_HWCAP_SAMPLERATE) {
272 cur_samplerate = *(const uint64_t *)value;
273 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
274 cur_samplerate);
275 ret = SR_OK;
276 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
277 limit_msec = 0;
278 limit_samples = *(const uint64_t *)value;
279 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
280 limit_samples);
281 ret = SR_OK;
282 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
283 limit_msec = *(const uint64_t *)value;
284 limit_samples = 0;
285 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
286 limit_msec);
287 ret = SR_OK;
288 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
289 stropt = value;
290 ret = SR_OK;
291 if (!strcmp(stropt, "sigrok")) {
292 default_pattern = PATTERN_SIGROK;
293 } else if (!strcmp(stropt, "random")) {
294 default_pattern = PATTERN_RANDOM;
295 } else if (!strcmp(stropt, "incremental")) {
296 default_pattern = PATTERN_INC;
297 } else if (!strcmp(stropt, "all-low")) {
298 default_pattern = PATTERN_ALL_LOW;
299 } else if (!strcmp(stropt, "all-high")) {
300 default_pattern = PATTERN_ALL_HIGH;
301 } else {
302 ret = SR_ERR;
303 }
304 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
305 } else {
306 ret = SR_ERR;
307 }
308
309 return ret;
310}
311
312static void samples_generator(uint8_t *buf, uint64_t size, void *data)
313{
314 static uint64_t p = 0;
315 struct dev_context *devc = data;
316 uint64_t i;
317
318 /* TODO: Needed? */
319 memset(buf, 0, size);
320
321 switch (devc->sample_generator) {
322 case PATTERN_SIGROK: /* sigrok pattern */
323 for (i = 0; i < size; i++) {
324 *(buf + i) = ~(pattern_sigrok[p] >> 1);
325 if (++p == 64)
326 p = 0;
327 }
328 break;
329 case PATTERN_RANDOM: /* Random */
330 for (i = 0; i < size; i++)
331 *(buf + i) = (uint8_t)(rand() & 0xff);
332 break;
333 case PATTERN_INC: /* Simple increment */
334 for (i = 0; i < size; i++)
335 *(buf + i) = i;
336 break;
337 case PATTERN_ALL_LOW: /* All probes are low */
338 memset(buf, 0x00, size);
339 break;
340 case PATTERN_ALL_HIGH: /* All probes are high */
341 memset(buf, 0xff, size);
342 break;
343 default:
344 sr_err("Unknown pattern: %d.", devc->sample_generator);
345 break;
346 }
347}
348
349/* Thread function */
350static void thread_func(void *data)
351{
352 struct dev_context *devc = data;
353 uint8_t buf[BUFSIZE];
354 uint64_t nb_to_send = 0;
355 int bytes_written;
356 double time_cur, time_last, time_diff;
357
358 time_last = g_timer_elapsed(devc->timer, NULL);
359
360 while (thread_running) {
361 /* Rate control */
362 time_cur = g_timer_elapsed(devc->timer, NULL);
363
364 time_diff = time_cur - time_last;
365 time_last = time_cur;
366
367 nb_to_send = cur_samplerate * time_diff;
368
369 if (limit_samples) {
370 nb_to_send = MIN(nb_to_send,
371 limit_samples - devc->samples_counter);
372 }
373
374 /* Make sure we don't overflow. */
375 nb_to_send = MIN(nb_to_send, BUFSIZE);
376
377 if (nb_to_send) {
378 samples_generator(buf, nb_to_send, data);
379 devc->samples_counter += nb_to_send;
380
381 g_io_channel_write_chars(devc->channels[1], (gchar *)&buf,
382 nb_to_send, (gsize *)&bytes_written, NULL);
383 }
384
385 /* Check if we're done. */
386 if ((limit_msec && time_cur * 1000 > limit_msec) ||
387 (limit_samples && devc->samples_counter >= limit_samples))
388 {
389 close(devc->pipe_fds[1]);
390 thread_running = 0;
391 }
392
393 g_usleep(10);
394 }
395}
396
397/* Callback handling data */
398static int receive_data(int fd, int revents, void *cb_data)
399{
400 struct dev_context *devc = cb_data;
401 struct sr_datafeed_packet packet;
402 struct sr_datafeed_logic logic;
403 static uint64_t samples_received = 0;
404 unsigned char c[BUFSIZE];
405 gsize z;
406
407 /* Avoid compiler warnings. */
408 (void)fd;
409 (void)revents;
410
411 do {
412 g_io_channel_read_chars(devc->channels[0],
413 (gchar *)&c, BUFSIZE, &z, NULL);
414
415 if (z > 0) {
416 packet.type = SR_DF_LOGIC;
417 packet.payload = &logic;
418 logic.length = z;
419 logic.unitsize = 1;
420 logic.data = c;
421 sr_session_send(devc->session_dev_id, &packet);
422 samples_received += z;
423 }
424 } while (z > 0);
425
426 if (!thread_running && z <= 0) {
427 /* Make sure we don't receive more packets. */
428 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
429
430 /* Send last packet. */
431 packet.type = SR_DF_END;
432 sr_session_send(devc->session_dev_id, &packet);
433
434 return FALSE;
435 }
436
437 return TRUE;
438}
439
440static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
441 void *cb_data)
442{
443 struct sr_datafeed_packet *packet;
444 struct sr_datafeed_header *header;
445 struct sr_datafeed_meta_logic meta;
446 struct dev_context *devc;
447
448 (void)sdi;
449
450 /* TODO: 'devc' is never g_free()'d? */
451 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
452 sr_err("%s: devc malloc failed", __func__);
453 return SR_ERR_MALLOC;
454 }
455
456 devc->sample_generator = default_pattern;
457 devc->session_dev_id = cb_data;
458 devc->samples_counter = 0;
459
460 if (pipe(devc->pipe_fds)) {
461 /* TODO: Better error message. */
462 sr_err("%s: pipe() failed", __func__);
463 return SR_ERR;
464 }
465
466 devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
467 devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
468
469 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
470
471 /* Set channel encoding to binary (default is UTF-8). */
472 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
473 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
474
475 /* Make channels to unbuffered. */
476 g_io_channel_set_buffered(devc->channels[0], FALSE);
477 g_io_channel_set_buffered(devc->channels[1], FALSE);
478
479 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
480 40, receive_data, devc);
481
482 /* Run the demo thread. */
483 devc->timer = g_timer_new();
484 thread_running = 1;
485 my_thread = g_thread_try_new("sigrok demo generator",
486 (GThreadFunc)thread_func, devc, NULL);
487 if (!my_thread) {
488 sr_err("%s: g_thread_try_new failed", __func__);
489 return SR_ERR; /* TODO */
490 }
491
492 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
493 sr_err("%s: packet malloc failed", __func__);
494 return SR_ERR_MALLOC;
495 }
496
497 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
498 sr_err("%s: header malloc failed", __func__);
499 return SR_ERR_MALLOC;
500 }
501
502 packet->type = SR_DF_HEADER;
503 packet->payload = header;
504 header->feed_version = 1;
505 gettimeofday(&header->starttime, NULL);
506 sr_session_send(devc->session_dev_id, packet);
507
508 /* Send metadata about the SR_DF_LOGIC packets to come. */
509 packet->type = SR_DF_META_LOGIC;
510 packet->payload = &meta;
511 meta.samplerate = cur_samplerate;
512 meta.num_probes = NUM_PROBES;
513 sr_session_send(devc->session_dev_id, packet);
514
515 g_free(header);
516 g_free(packet);
517
518 return SR_OK;
519}
520
521static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
522{
523 struct dev_context *devc;
524
525 /* Avoid compiler warnings. */
526 (void)cb_data;
527
528 devc = sdi->priv;
529
530 /* Stop generate thread. */
531 thread_running = 0;
532
533 sr_session_source_remove_channel(devc->channels[0]);
534
535 return SR_OK;
536}
537
538SR_PRIV struct sr_dev_driver demo_driver_info = {
539 .name = "demo",
540 .longname = "Demo driver and pattern generator",
541 .api_version = 1,
542 .init = hw_init,
543 .cleanup = hw_cleanup,
544 .scan = hw_scan,
545 .dev_list = hw_dev_list,
546 .dev_open = hw_dev_open,
547 .dev_close = hw_dev_close,
548 .info_get = hw_info_get,
549 .dev_config_set = hw_dev_config_set,
550 .dev_acquisition_start = hw_dev_acquisition_start,
551 .dev_acquisition_stop = hw_dev_acquisition_stop,
552 .priv = NULL,
553};