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