]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
demo: Properly stop acquisition after reaching our sample quota
[libsigrok.git] / hardware / demo / demo.c
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 */
53 enum {
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. */
77 struct 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
87 static 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
97 static const struct sr_samplerates samplerates = {
98         SR_HZ(1),
99         SR_GHZ(1),
100         SR_HZ(1),
101         NULL,
102 };
103
104 static 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. */
114 static 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
126 static 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(). */
141 SR_PRIV struct sr_dev_driver demo_driver_info;
142 static struct sr_dev_driver *ddi = &demo_driver_info;
143 static uint64_t cur_samplerate = SR_KHZ(200);
144 static uint64_t limit_samples = 0;
145 static uint64_t limit_msec = 0;
146 static int default_pattern = PATTERN_SIGROK;
147 static GThread *my_thread;
148 static int thread_running;
149
150 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
151
152 static 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
165 static 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
198 static GSList *hw_dev_list(void)
199 {
200         struct drv_context *drvc;
201
202         drvc = ddi->priv;
203
204         return drvc->instances;
205 }
206
207 static 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
216 static 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
225 static int hw_cleanup(void)
226 {
227         /* Nothing needed so far. */
228         return SR_OK;
229 }
230
231 static 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
262 static 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
311 static 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 */
349 static 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 */
397 static 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
433 static 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
516 static 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
540 SR_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 };