]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
demo: Do not use a separate thread for generating data
[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         uint64_t samples_counter;
82         void *session_dev_id;
83         int64_t starttime;
84 };
85
86 static 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
96 static const struct sr_samplerates samplerates = {
97         SR_HZ(1),
98         SR_GHZ(1),
99         SR_HZ(1),
100         NULL,
101 };
102
103 static 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. */
113 static 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
125 static 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(). */
140 SR_PRIV struct sr_dev_driver demo_driver_info;
141 static struct sr_dev_driver *ddi = &demo_driver_info;
142 static uint64_t cur_samplerate = SR_KHZ(200);
143 static uint64_t limit_samples = 0;
144 static uint64_t limit_msec = 0;
145 static int default_pattern = PATTERN_SIGROK;
146
147 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
148
149 static int hw_init(void)
150 {
151         struct drv_context *drvc;
152
153         if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
154                 sr_err("Driver context malloc failed.");
155                 return SR_ERR_MALLOC;
156         }
157         ddi->priv = drvc;
158
159         return SR_OK;
160 }
161
162 static GSList *hw_scan(GSList *options)
163 {
164         struct sr_dev_inst *sdi;
165         struct sr_probe *probe;
166         struct drv_context *drvc;
167         GSList *devices;
168         int i;
169
170         (void)options;
171
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("%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_LOGIC, 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
195 static GSList *hw_dev_list(void)
196 {
197         struct drv_context *drvc;
198
199         drvc = ddi->priv;
200
201         return drvc->instances;
202 }
203
204 static int hw_dev_open(struct sr_dev_inst *sdi)
205 {
206         (void)sdi;
207
208         /* Nothing needed so far. */
209
210         return SR_OK;
211 }
212
213 static int hw_dev_close(struct sr_dev_inst *sdi)
214 {
215         (void)sdi;
216
217         /* Nothing needed so far. */
218
219         return SR_OK;
220 }
221
222 static int hw_cleanup(void)
223 {
224         /* Nothing needed so far. */
225         return SR_OK;
226 }
227
228 static int hw_info_get(int info_id, const void **data,
229        const struct sr_dev_inst *sdi)
230 {
231         (void)sdi;
232
233         switch (info_id) {
234         case SR_DI_HWCAPS:
235                 *data = hwcaps;
236                 break;
237         case SR_DI_NUM_PROBES:
238                 *data = GINT_TO_POINTER(NUM_PROBES);
239                 break;
240         case SR_DI_PROBE_NAMES:
241                 *data = probe_names;
242                 break;
243         case SR_DI_SAMPLERATES:
244                 *data = &samplerates;
245                 break;
246         case SR_DI_CUR_SAMPLERATE:
247                 *data = &cur_samplerate;
248                 break;
249         case SR_DI_PATTERNS:
250                 *data = &pattern_strings;
251                 break;
252         default:
253                 return SR_ERR_ARG;
254         }
255
256         return SR_OK;
257 }
258
259 static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
260                 const void *value)
261 {
262         int ret;
263         const char *stropt;
264
265         (void)sdi;
266
267         if (hwcap == SR_HWCAP_SAMPLERATE) {
268                 cur_samplerate = *(const uint64_t *)value;
269                 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
270                        cur_samplerate);
271                 ret = SR_OK;
272         } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
273                 limit_msec = 0;
274                 limit_samples = *(const uint64_t *)value;
275                 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
276                        limit_samples);
277                 ret = SR_OK;
278         } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
279                 limit_msec = *(const uint64_t *)value;
280                 limit_samples = 0;
281                 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
282                        limit_msec);
283                 ret = SR_OK;
284         } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
285                 stropt = value;
286                 ret = SR_OK;
287                 if (!strcmp(stropt, "sigrok")) {
288                         default_pattern = PATTERN_SIGROK;
289                 } else if (!strcmp(stropt, "random")) {
290                         default_pattern = PATTERN_RANDOM;
291                 } else if (!strcmp(stropt, "incremental")) {
292                         default_pattern = PATTERN_INC;
293                 } else if (!strcmp(stropt, "all-low")) {
294                         default_pattern = PATTERN_ALL_LOW;
295                 } else if (!strcmp(stropt, "all-high")) {
296                         default_pattern = PATTERN_ALL_HIGH;
297                 } else {
298                         ret = SR_ERR;
299                 }
300                 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
301         } else {
302                 ret = SR_ERR;
303         }
304
305         return ret;
306 }
307
308 static void samples_generator(uint8_t *buf, uint64_t size,
309                               struct dev_context *devc)
310 {
311         static uint64_t p = 0;
312         uint64_t i;
313
314         /* TODO: Needed? */
315         memset(buf, 0, size);
316
317         switch (devc->sample_generator) {
318         case PATTERN_SIGROK: /* sigrok pattern */
319                 for (i = 0; i < size; i++) {
320                         *(buf + i) = ~(pattern_sigrok[p] >> 1);
321                         if (++p == 64)
322                                 p = 0;
323                 }
324                 break;
325         case PATTERN_RANDOM: /* Random */
326                 for (i = 0; i < size; i++)
327                         *(buf + i) = (uint8_t)(rand() & 0xff);
328                 break;
329         case PATTERN_INC: /* Simple increment */
330                 for (i = 0; i < size; i++)
331                         *(buf + i) = i;
332                 break;
333         case PATTERN_ALL_LOW: /* All probes are low */
334                 memset(buf, 0x00, size);
335                 break;
336         case PATTERN_ALL_HIGH: /* All probes are high */
337                 memset(buf, 0xff, size);
338                 break;
339         default:
340                 sr_err("Unknown pattern: %d.", devc->sample_generator);
341                 break;
342         }
343 }
344
345 /* Callback handling data */
346 static int receive_data(int fd, int revents, void *cb_data)
347 {
348         struct dev_context *devc = cb_data;
349         struct sr_datafeed_packet packet;
350         struct sr_datafeed_logic logic;
351         uint8_t buf[BUFSIZE];
352         static uint64_t samples_to_send, expected_samplenum, sending_now;
353         int64_t time, elapsed;
354
355         (void)fd;
356         (void)revents;
357
358         /* How many "virtual" samples should we have collected by now? */
359         time = g_get_monotonic_time();
360         elapsed = time - devc->starttime;
361         expected_samplenum = elapsed * cur_samplerate / 1000000;
362         /* Of those, how many do we still have to send? */
363         samples_to_send = expected_samplenum - devc->samples_counter;
364
365         if (limit_samples) {
366                 samples_to_send = MIN(samples_to_send,
367                                  limit_samples - devc->samples_counter);
368         }
369
370         while (samples_to_send > 0) {
371                 sending_now = MIN(samples_to_send, sizeof(buf));
372                 samples_to_send -= sending_now;
373                 samples_generator(buf, sending_now, devc);
374
375                 packet.type = SR_DF_LOGIC;
376                 packet.payload = &logic;
377                 logic.length = sending_now;
378                 logic.unitsize = 1;
379                 logic.data = buf;
380                 sr_session_send(devc->session_dev_id, &packet);
381                 devc->samples_counter += sending_now;
382         }
383
384
385         if (devc->samples_counter >= limit_samples) {
386                 sr_spew("We sent a total of %" PRIu64 " samples.",
387                         devc->samples_counter);
388                 /* Make sure we don't receive more packets. */
389                 hw_dev_acquisition_stop(NULL, cb_data);
390                 return TRUE;
391         }
392
393         return TRUE;
394 }
395
396 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
397                 void *cb_data)
398 {
399         struct sr_datafeed_packet *packet;
400         struct sr_datafeed_header *header;
401         struct sr_datafeed_meta_logic meta;
402         struct dev_context *devc;
403
404         (void)sdi;
405
406         sr_dbg("Starting acquisition.");
407
408         /* TODO: 'devc' is never g_free()'d? */
409         if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
410                 sr_err("%s: devc malloc failed", __func__);
411                 return SR_ERR_MALLOC;
412         }
413
414         devc->sample_generator = default_pattern;
415         devc->session_dev_id = cb_data;
416         devc->samples_counter = 0;
417
418         /*
419          * Setting two channels connected by a pipe is a remnant from when the
420          * demo driver generated data in a thread, and collected and sent the
421          * data in the main program loop.
422          * They are kept here because it provides a convenient way of setting
423          * up a timeout-based polling mechanism.
424          */
425         if (pipe(devc->pipe_fds)) {
426                 /* TODO: Better error message. */
427                 sr_err("%s: pipe() failed", __func__);
428                 return SR_ERR;
429         }
430
431         devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
432         devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
433
434         g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
435
436         /* Set channel encoding to binary (default is UTF-8). */
437         g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
438         g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
439
440         /* Make channels to unbuffered. */
441         g_io_channel_set_buffered(devc->channels[0], FALSE);
442         g_io_channel_set_buffered(devc->channels[1], FALSE);
443
444         sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
445                     40, receive_data, devc);
446
447         if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
448                 sr_err("%s: packet malloc failed", __func__);
449                 return SR_ERR_MALLOC;
450         }
451
452         if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
453                 sr_err("%s: header malloc failed", __func__);
454                 return SR_ERR_MALLOC;
455         }
456
457         packet->type = SR_DF_HEADER;
458         packet->payload = header;
459         header->feed_version = 1;
460         gettimeofday(&header->starttime, NULL);
461         sr_session_send(devc->session_dev_id, packet);
462
463         /* Send metadata about the SR_DF_LOGIC packets to come. */
464         packet->type = SR_DF_META_LOGIC;
465         packet->payload = &meta;
466         meta.samplerate = cur_samplerate;
467         meta.num_probes = NUM_PROBES;
468         sr_session_send(devc->session_dev_id, packet);
469
470         /* We use this timestamp to decide how many more samples to send. */
471         devc->starttime = g_get_monotonic_time();
472
473         g_free(header);
474         g_free(packet);
475
476         return SR_OK;
477 }
478
479 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
480 {
481         struct dev_context *devc;
482         struct sr_datafeed_packet packet;
483
484         (void)sdi;
485
486         devc = cb_data;
487
488         sr_dbg("Stopping aquisition.");
489
490         sr_session_source_remove_channel(devc->channels[0]);
491         g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
492
493         /* Send last packet. */
494         packet.type = SR_DF_END;
495         sr_session_send(devc->session_dev_id, &packet);
496
497         return SR_OK;
498 }
499
500 SR_PRIV struct sr_dev_driver demo_driver_info = {
501         .name = "demo",
502         .longname = "Demo driver and pattern generator",
503         .api_version = 1,
504         .init = hw_init,
505         .cleanup = hw_cleanup,
506         .scan = hw_scan,
507         .dev_list = hw_dev_list,
508         .dev_open = hw_dev_open,
509         .dev_close = hw_dev_close,
510         .info_get = hw_info_get,
511         .dev_config_set = hw_dev_config_set,
512         .dev_acquisition_start = hw_dev_acquisition_start,
513         .dev_acquisition_stop = hw_dev_acquisition_stop,
514         .priv = NULL,
515 };