]> sigrok.org Git - libsigrok.git/blame_incremental - hardware/demo/demo.c
serial-dmm: Add Digitek DT4000ZC support.
[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/* Supported patterns which we can generate */
53enum {
54 /**
55 * Pattern which spells "sigrok" using '0's (with '1's as "background")
56 * when displayed using the 'bits' output format.
57 */
58 PATTERN_SIGROK,
59
60 /** Pattern which consists of (pseudo-)random values on all probes. */
61 PATTERN_RANDOM,
62
63 /**
64 * Pattern which consists of incrementing numbers.
65 * TODO: Better description.
66 */
67 PATTERN_INC,
68
69 /** Pattern where all probes have a low logic state. */
70 PATTERN_ALL_LOW,
71
72 /** Pattern where all probes have a high logic state. */
73 PATTERN_ALL_HIGH,
74};
75
76/* Private, per-device-instance driver context. */
77struct dev_context {
78 int pipe_fds[2];
79 GIOChannel *channels[2];
80 uint8_t sample_generator;
81 uint8_t thread_running;
82 uint64_t samples_counter;
83 void *session_dev_id;
84 GTimer *timer;
85};
86
87static const int hwcaps[] = {
88 SR_HWCAP_LOGIC_ANALYZER,
89 SR_HWCAP_DEMO_DEV,
90 SR_HWCAP_SAMPLERATE,
91 SR_HWCAP_PATTERN_MODE,
92 SR_HWCAP_LIMIT_SAMPLES,
93 SR_HWCAP_LIMIT_MSEC,
94 SR_HWCAP_CONTINUOUS,
95};
96
97static const struct sr_samplerates samplerates = {
98 SR_HZ(1),
99 SR_GHZ(1),
100 SR_HZ(1),
101 NULL,
102};
103
104static const char *pattern_strings[] = {
105 "sigrok",
106 "random",
107 "incremental",
108 "all-low",
109 "all-high",
110 NULL,
111};
112
113/* We name the probes 0-7 on our demo driver. */
114static const char *probe_names[NUM_PROBES + 1] = {
115 "0",
116 "1",
117 "2",
118 "3",
119 "4",
120 "5",
121 "6",
122 "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 *ddi = &demo_driver_info;
143static uint64_t cur_samplerate = SR_KHZ(200);
144static uint64_t limit_samples = 0;
145static uint64_t limit_msec = 0;
146static int default_pattern = PATTERN_SIGROK;
147static GThread *my_thread;
148static int thread_running;
149
150static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
151
152static int hw_init(void)
153{
154 struct drv_context *drvc;
155
156 if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
157 sr_err("Driver context malloc failed.");
158 return SR_ERR_MALLOC;
159 }
160 ddi->priv = drvc;
161
162 return SR_OK;
163}
164
165static GSList *hw_scan(GSList *options)
166{
167 struct sr_dev_inst *sdi;
168 struct sr_probe *probe;
169 struct drv_context *drvc;
170 GSList *devices;
171 int i;
172
173 (void)options;
174
175 drvc = ddi->priv;
176 devices = NULL;
177
178 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
179 if (!sdi) {
180 sr_err("%s: sr_dev_inst_new failed", __func__);
181 return 0;
182 }
183 sdi->driver = ddi;
184
185 for (i = 0; probe_names[i]; i++) {
186 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
187 probe_names[i])))
188 return NULL;
189 sdi->probes = g_slist_append(sdi->probes, probe);
190 }
191
192 devices = g_slist_append(devices, sdi);
193 drvc->instances = g_slist_append(drvc->instances, sdi);
194
195 return devices;
196}
197
198static GSList *hw_dev_list(void)
199{
200 struct drv_context *drvc;
201
202 drvc = ddi->priv;
203
204 return drvc->instances;
205}
206
207static int hw_dev_open(struct sr_dev_inst *sdi)
208{
209 (void)sdi;
210
211 /* Nothing needed so far. */
212
213 return SR_OK;
214}
215
216static int hw_dev_close(struct sr_dev_inst *sdi)
217{
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 (void)sdi;
235
236 switch (info_id) {
237 case SR_DI_HWCAPS:
238 *data = hwcaps;
239 break;
240 case SR_DI_NUM_PROBES:
241 *data = GINT_TO_POINTER(NUM_PROBES);
242 break;
243 case SR_DI_PROBE_NAMES:
244 *data = probe_names;
245 break;
246 case SR_DI_SAMPLERATES:
247 *data = &samplerates;
248 break;
249 case SR_DI_CUR_SAMPLERATE:
250 *data = &cur_samplerate;
251 break;
252 case SR_DI_PATTERNS:
253 *data = &pattern_strings;
254 break;
255 default:
256 return SR_ERR_ARG;
257 }
258
259 return SR_OK;
260}
261
262static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
263 const void *value)
264{
265 int ret;
266 const char *stropt;
267
268 (void)sdi;
269
270 if (hwcap == SR_HWCAP_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 (hwcap == SR_HWCAP_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 (hwcap == SR_HWCAP_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 (hwcap == SR_HWCAP_PATTERN_MODE) {
288 stropt = value;
289 ret = SR_OK;
290 if (!strcmp(stropt, "sigrok")) {
291 default_pattern = PATTERN_SIGROK;
292 } else if (!strcmp(stropt, "random")) {
293 default_pattern = PATTERN_RANDOM;
294 } else if (!strcmp(stropt, "incremental")) {
295 default_pattern = PATTERN_INC;
296 } else if (!strcmp(stropt, "all-low")) {
297 default_pattern = PATTERN_ALL_LOW;
298 } else if (!strcmp(stropt, "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 void samples_generator(uint8_t *buf, uint64_t size, void *data)
312{
313 static uint64_t p = 0;
314 struct dev_context *devc = data;
315 uint64_t i;
316
317 /* TODO: Needed? */
318 memset(buf, 0, size);
319
320 switch (devc->sample_generator) {
321 case PATTERN_SIGROK: /* sigrok pattern */
322 for (i = 0; i < size; i++) {
323 *(buf + i) = ~(pattern_sigrok[p] >> 1);
324 if (++p == 64)
325 p = 0;
326 }
327 break;
328 case PATTERN_RANDOM: /* Random */
329 for (i = 0; i < size; i++)
330 *(buf + i) = (uint8_t)(rand() & 0xff);
331 break;
332 case PATTERN_INC: /* Simple increment */
333 for (i = 0; i < size; i++)
334 *(buf + i) = i;
335 break;
336 case PATTERN_ALL_LOW: /* All probes are low */
337 memset(buf, 0x00, size);
338 break;
339 case PATTERN_ALL_HIGH: /* All probes are high */
340 memset(buf, 0xff, size);
341 break;
342 default:
343 sr_err("Unknown pattern: %d.", devc->sample_generator);
344 break;
345 }
346}
347
348/* Thread function */
349static void thread_func(void *data)
350{
351 struct dev_context *devc = data;
352 uint8_t buf[BUFSIZE];
353 uint64_t nb_to_send = 0;
354 int bytes_written;
355 double time_cur, time_last, time_diff;
356
357 time_last = g_timer_elapsed(devc->timer, NULL);
358
359 while (thread_running) {
360 /* Rate control */
361 time_cur = g_timer_elapsed(devc->timer, NULL);
362
363 time_diff = time_cur - time_last;
364 time_last = time_cur;
365
366 nb_to_send = cur_samplerate * time_diff;
367
368 if (limit_samples) {
369 nb_to_send = MIN(nb_to_send,
370 limit_samples - devc->samples_counter);
371 }
372
373 /* Make sure we don't overflow. */
374 nb_to_send = MIN(nb_to_send, BUFSIZE);
375
376 if (nb_to_send) {
377 samples_generator(buf, nb_to_send, data);
378 devc->samples_counter += nb_to_send;
379
380 g_io_channel_write_chars(devc->channels[1], (gchar *)&buf,
381 nb_to_send, (gsize *)&bytes_written, NULL);
382 }
383
384 /* Check if we're done. */
385 if ((limit_msec && time_cur * 1000 > limit_msec) ||
386 (limit_samples && devc->samples_counter >= limit_samples))
387 {
388 close(devc->pipe_fds[1]);
389 thread_running = 0;
390 }
391
392 g_usleep(10);
393 }
394}
395
396/* Callback handling data */
397static int receive_data(int fd, int revents, void *cb_data)
398{
399 struct dev_context *devc = cb_data;
400 struct sr_datafeed_packet packet;
401 struct sr_datafeed_logic logic;
402 static uint64_t samples_received = 0;
403 unsigned char c[BUFSIZE];
404 gsize z;
405
406 (void)fd;
407 (void)revents;
408
409 do {
410 g_io_channel_read_chars(devc->channels[0],
411 (gchar *)&c, BUFSIZE, &z, NULL);
412
413 if (z > 0) {
414 packet.type = SR_DF_LOGIC;
415 packet.payload = &logic;
416 logic.length = z;
417 logic.unitsize = 1;
418 logic.data = c;
419 sr_session_send(devc->session_dev_id, &packet);
420 samples_received += z;
421 }
422 } while (z > 0);
423
424 if (!thread_running && z <= 0) {
425 /* Make sure we don't receive more packets. */
426 hw_dev_acquisition_stop(NULL, cb_data);
427 return TRUE;
428 }
429
430 return TRUE;
431}
432
433static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
434 void *cb_data)
435{
436 struct sr_datafeed_packet *packet;
437 struct sr_datafeed_header *header;
438 struct sr_datafeed_meta_logic meta;
439 struct dev_context *devc;
440
441 (void)sdi;
442
443 sr_dbg("Starting acquisition.");
444
445 /* TODO: 'devc' is never g_free()'d? */
446 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
447 sr_err("%s: devc malloc failed", __func__);
448 return SR_ERR_MALLOC;
449 }
450
451 devc->sample_generator = default_pattern;
452 devc->session_dev_id = cb_data;
453 devc->samples_counter = 0;
454
455 if (pipe(devc->pipe_fds)) {
456 /* TODO: Better error message. */
457 sr_err("%s: pipe() failed", __func__);
458 return SR_ERR;
459 }
460
461 devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
462 devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
463
464 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
465
466 /* Set channel encoding to binary (default is UTF-8). */
467 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
468 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
469
470 /* Make channels to unbuffered. */
471 g_io_channel_set_buffered(devc->channels[0], FALSE);
472 g_io_channel_set_buffered(devc->channels[1], FALSE);
473
474 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
475 40, receive_data, devc);
476
477 /* Run the demo thread. */
478 devc->timer = g_timer_new();
479 thread_running = 1;
480 my_thread = g_thread_try_new("sigrok demo generator",
481 (GThreadFunc)thread_func, devc, NULL);
482 if (!my_thread) {
483 sr_err("%s: g_thread_try_new failed", __func__);
484 return SR_ERR; /* TODO */
485 }
486
487 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
488 sr_err("%s: packet malloc failed", __func__);
489 return SR_ERR_MALLOC;
490 }
491
492 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
493 sr_err("%s: header malloc failed", __func__);
494 return SR_ERR_MALLOC;
495 }
496
497 packet->type = SR_DF_HEADER;
498 packet->payload = header;
499 header->feed_version = 1;
500 gettimeofday(&header->starttime, NULL);
501 sr_session_send(devc->session_dev_id, packet);
502
503 /* Send metadata about the SR_DF_LOGIC packets to come. */
504 packet->type = SR_DF_META_LOGIC;
505 packet->payload = &meta;
506 meta.samplerate = cur_samplerate;
507 meta.num_probes = NUM_PROBES;
508 sr_session_send(devc->session_dev_id, packet);
509
510 g_free(header);
511 g_free(packet);
512
513 return SR_OK;
514}
515
516static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
517{
518 struct dev_context *devc;
519 struct sr_datafeed_packet packet;
520
521 (void)sdi;
522
523 devc = cb_data;
524
525 sr_dbg("Stopping aquisition.");
526
527 /* Stop generate thread. */
528 thread_running = 0;
529
530 sr_session_source_remove_channel(devc->channels[0]);
531 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
532
533 /* Send last packet. */
534 packet.type = SR_DF_END;
535 sr_session_send(devc->session_dev_id, &packet);
536
537 return SR_OK;
538}
539
540SR_PRIV struct sr_dev_driver demo_driver_info = {
541 .name = "demo",
542 .longname = "Demo driver and pattern generator",
543 .api_version = 1,
544 .init = hw_init,
545 .cleanup = hw_cleanup,
546 .scan = hw_scan,
547 .dev_list = hw_dev_list,
548 .dev_open = hw_dev_open,
549 .dev_close = hw_dev_close,
550 .info_get = hw_info_get,
551 .dev_config_set = hw_dev_config_set,
552 .dev_acquisition_start = hw_dev_acquisition_start,
553 .dev_acquisition_stop = hw_dev_acquisition_stop,
554 .priv = NULL,
555};