]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
68bd4115b5fd60cf60126626d07df1a4f9c7a8b8
[libsigrok.git] / hardware / demo / demo.c
1 /*
2  * This file is part of the libsigrok 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 subsystem-specific prefix string. */
35 #define LOG_PREFIX "demo: "
36 #define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
37 #define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
38 #define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
39 #define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
40 #define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
41 #define sr_err(s, args...) sr_err(LOG_PREFIX 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 #define STR_PATTERN_SIGROK   "sigrok"
53 #define STR_PATTERN_RANDOM   "random"
54 #define STR_PATTERN_INC      "incremental"
55 #define STR_PATTERN_ALL_LOW  "all-low"
56 #define STR_PATTERN_ALL_HIGH "all-high"
57
58 /* Supported patterns which we can generate */
59 enum {
60         /**
61          * Pattern which spells "sigrok" using '0's (with '1's as "background")
62          * when displayed using the 'bits' output format.
63          */
64         PATTERN_SIGROK,
65
66         /** Pattern which consists of (pseudo-)random values on all probes. */
67         PATTERN_RANDOM,
68
69         /**
70          * Pattern which consists of incrementing numbers.
71          * TODO: Better description.
72          */
73         PATTERN_INC,
74
75         /** Pattern where all probes have a low logic state. */
76         PATTERN_ALL_LOW,
77
78         /** Pattern where all probes have a high logic state. */
79         PATTERN_ALL_HIGH,
80 };
81
82 /* Private, per-device-instance driver context. */
83 struct dev_context {
84         struct sr_dev_inst *sdi;
85         int pipe_fds[2];
86         GIOChannel *channel;
87         uint64_t cur_samplerate;
88         uint64_t limit_samples;
89         uint64_t limit_msec;
90         uint8_t sample_generator;
91         uint64_t samples_counter;
92         void *cb_data;
93         int64_t starttime;
94 };
95
96 static const int hwcaps[] = {
97         SR_CONF_LOGIC_ANALYZER,
98         SR_CONF_DEMO_DEV,
99         SR_CONF_SAMPLERATE,
100         SR_CONF_PATTERN_MODE,
101         SR_CONF_LIMIT_SAMPLES,
102         SR_CONF_LIMIT_MSEC,
103         SR_CONF_CONTINUOUS,
104 };
105
106 static const uint64_t samplerates[] = {
107         SR_HZ(1),
108         SR_GHZ(1),
109         SR_HZ(1),
110 };
111
112 static const char *pattern_strings[] = {
113         "sigrok",
114         "random",
115         "incremental",
116         "all-low",
117         "all-high",
118 };
119
120 /* We name the probes 0-7 on our demo driver. */
121 static const char *probe_names[NUM_PROBES + 1] = {
122         "0", "1", "2", "3", "4", "5", "6", "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 *di = &demo_driver_info;
143
144 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
145
146 static int dev_clear(void)
147 {
148         return std_dev_clear(di, NULL);
149 }
150
151 static int init(struct sr_context *sr_ctx)
152 {
153         return std_init(sr_ctx, di, LOG_PREFIX);
154 }
155
156 static GSList *scan(GSList *options)
157 {
158         struct sr_dev_inst *sdi;
159         struct sr_probe *probe;
160         struct drv_context *drvc;
161         struct dev_context *devc;
162         GSList *devices;
163         int i;
164
165         (void)options;
166
167         drvc = di->priv;
168
169         devices = NULL;
170
171         sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
172         if (!sdi) {
173                 sr_err("Device instance creation failed.");
174                 return NULL;
175         }
176         sdi->driver = di;
177
178         for (i = 0; probe_names[i]; i++) {
179                 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
180                                 probe_names[i])))
181                         return NULL;
182                 sdi->probes = g_slist_append(sdi->probes, probe);
183         }
184
185         devices = g_slist_append(devices, sdi);
186         drvc->instances = g_slist_append(drvc->instances, sdi);
187
188         if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
189                 sr_err("Device context malloc failed.");
190                 return NULL;
191         }
192
193         devc->sdi = sdi;
194         devc->cur_samplerate = SR_KHZ(200);
195         devc->limit_samples = 0;
196         devc->limit_msec = 0;
197         devc->sample_generator = PATTERN_SIGROK;
198
199         sdi->priv = devc;
200
201         return devices;
202 }
203
204 static GSList *dev_list(void)
205 {
206         return ((struct drv_context *)(di->priv))->instances;
207 }
208
209 static int dev_open(struct sr_dev_inst *sdi)
210 {
211         sdi->status = SR_ST_ACTIVE;
212
213         return SR_OK;
214 }
215
216 static int dev_close(struct sr_dev_inst *sdi)
217 {
218         sdi->status = SR_ST_INACTIVE;
219
220         return SR_OK;
221 }
222
223 static int cleanup(void)
224 {
225         return dev_clear();
226 }
227
228 static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
229 {
230         struct dev_context *const devc = sdi->priv;
231
232         switch (id) {
233         case SR_CONF_SAMPLERATE:
234                 *data = g_variant_new_uint64(devc->cur_samplerate);
235                 break;
236         case SR_CONF_LIMIT_SAMPLES:
237                 *data = g_variant_new_uint64(devc->limit_samples);
238                 break;
239         case SR_CONF_LIMIT_MSEC:
240                 *data = g_variant_new_uint64(devc->limit_msec);
241                 break;
242         case SR_CONF_PATTERN_MODE:
243                 switch (devc->sample_generator) {
244                 case PATTERN_SIGROK:
245                         *data = g_variant_new_string(STR_PATTERN_SIGROK);
246                         break;
247                 case PATTERN_RANDOM:
248                         *data = g_variant_new_string(STR_PATTERN_RANDOM);
249                         break;
250                 case PATTERN_INC:
251                         *data = g_variant_new_string(STR_PATTERN_INC);
252                         break;
253                 case PATTERN_ALL_LOW:
254                         *data = g_variant_new_string(STR_PATTERN_ALL_LOW);
255                         break;
256                 case PATTERN_ALL_HIGH:
257                         *data = g_variant_new_string(STR_PATTERN_ALL_HIGH);
258                         break;
259                 }
260                 break;
261         default:
262                 return SR_ERR_NA;
263         }
264
265         return SR_OK;
266 }
267
268 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
269 {
270         int ret;
271         const char *stropt;
272
273         struct dev_context *const devc = sdi->priv;
274
275         if (sdi->status != SR_ST_ACTIVE)
276                 return SR_ERR_DEV_CLOSED;
277
278         if (id == SR_CONF_SAMPLERATE) {
279                 devc->cur_samplerate = g_variant_get_uint64(data);
280                 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
281                        devc->cur_samplerate);
282                 ret = SR_OK;
283         } else if (id == SR_CONF_LIMIT_SAMPLES) {
284                 devc->limit_msec = 0;
285                 devc->limit_samples = g_variant_get_uint64(data);
286                 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
287                        devc->limit_samples);
288                 ret = SR_OK;
289         } else if (id == SR_CONF_LIMIT_MSEC) {
290                 devc->limit_msec = g_variant_get_uint64(data);
291                 devc->limit_samples = 0;
292                 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
293                        devc->limit_msec);
294                 ret = SR_OK;
295         } else if (id == SR_CONF_PATTERN_MODE) {
296                 stropt = g_variant_get_string(data, NULL);
297                 ret = SR_OK;
298                 if (!strcmp(stropt, STR_PATTERN_SIGROK)) {
299                         devc->sample_generator = PATTERN_SIGROK;
300                 } else if (!strcmp(stropt, STR_PATTERN_RANDOM)) {
301                         devc->sample_generator = PATTERN_RANDOM;
302                 } else if (!strcmp(stropt, STR_PATTERN_INC)) {
303                         devc->sample_generator = PATTERN_INC;
304                 } else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) {
305                         devc->sample_generator = PATTERN_ALL_LOW;
306                 } else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) {
307                         devc->sample_generator = PATTERN_ALL_HIGH;
308                 } else {
309                         ret = SR_ERR;
310                 }
311                 sr_dbg("%s: setting pattern to %d",
312                         __func__, devc->sample_generator);
313         } else {
314                 ret = SR_ERR_NA;
315         }
316
317         return ret;
318 }
319
320 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
321 {
322         GVariant *gvar;
323         GVariantBuilder gvb;
324
325         (void)sdi;
326
327         switch (key) {
328         case SR_CONF_DEVICE_OPTIONS:
329                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
330                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
331                 break;
332         case SR_CONF_SAMPLERATE:
333                 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
334                 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
335                                 ARRAY_SIZE(samplerates), sizeof(uint64_t));
336                 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
337                 *data = g_variant_builder_end(&gvb);
338                 break;
339         case SR_CONF_PATTERN_MODE:
340                 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
341                 break;
342         default:
343                 return SR_ERR_NA;
344         }
345
346         return SR_OK;
347 }
348
349 static void samples_generator(uint8_t *buf, uint64_t size,
350                               struct dev_context *devc)
351 {
352         static uint64_t p = 0;
353         uint64_t i;
354
355         /* TODO: Needed? */
356         memset(buf, 0, size);
357
358         switch (devc->sample_generator) {
359         case PATTERN_SIGROK: /* sigrok pattern */
360                 for (i = 0; i < size; i++) {
361                         *(buf + i) = ~(pattern_sigrok[
362                                 p++ % sizeof(pattern_sigrok)] >> 1);
363                 }
364                 break;
365         case PATTERN_RANDOM: /* Random */
366                 for (i = 0; i < size; i++)
367                         *(buf + i) = (uint8_t)(rand() & 0xff);
368                 break;
369         case PATTERN_INC: /* Simple increment */
370                 for (i = 0; i < size; i++)
371                         *(buf + i) = p++;
372                 break;
373         case PATTERN_ALL_LOW: /* All probes are low */
374                 memset(buf, 0x00, size);
375                 break;
376         case PATTERN_ALL_HIGH: /* All probes are high */
377                 memset(buf, 0xff, size);
378                 break;
379         default:
380                 sr_err("Unknown pattern: %d.", devc->sample_generator);
381                 break;
382         }
383 }
384
385 /* Callback handling data */
386 static int receive_data(int fd, int revents, void *cb_data)
387 {
388         struct dev_context *devc = cb_data;
389         struct sr_datafeed_packet packet;
390         struct sr_datafeed_logic logic;
391         uint8_t buf[BUFSIZE];
392         static uint64_t samples_to_send, expected_samplenum, sending_now;
393         int64_t time, elapsed;
394
395         (void)fd;
396         (void)revents;
397
398         /* How many "virtual" samples should we have collected by now? */
399         time = g_get_monotonic_time();
400         elapsed = time - devc->starttime;
401         expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
402         /* Of those, how many do we still have to send? */
403         samples_to_send = expected_samplenum - devc->samples_counter;
404
405         if (devc->limit_samples) {
406                 samples_to_send = MIN(samples_to_send,
407                                  devc->limit_samples - devc->samples_counter);
408         }
409
410         while (samples_to_send > 0) {
411                 sending_now = MIN(samples_to_send, sizeof(buf));
412                 samples_to_send -= sending_now;
413                 samples_generator(buf, sending_now, devc);
414
415                 packet.type = SR_DF_LOGIC;
416                 packet.payload = &logic;
417                 logic.length = sending_now;
418                 logic.unitsize = 1;
419                 logic.data = buf;
420                 sr_session_send(devc->cb_data, &packet);
421                 devc->samples_counter += sending_now;
422         }
423
424         if (devc->limit_samples &&
425                 devc->samples_counter >= devc->limit_samples) {
426                 sr_info("Requested number of samples reached.");
427                 dev_acquisition_stop(devc->sdi, cb_data);
428                 return TRUE;
429         }
430
431         return TRUE;
432 }
433
434 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
435 {
436         struct dev_context *const devc = sdi->priv;
437
438         if (sdi->status != SR_ST_ACTIVE)
439                 return SR_ERR_DEV_CLOSED;
440
441         devc->cb_data = cb_data;
442         devc->samples_counter = 0;
443
444         /*
445          * Setting two channels connected by a pipe is a remnant from when the
446          * demo driver generated data in a thread, and collected and sent the
447          * data in the main program loop.
448          * They are kept here because it provides a convenient way of setting
449          * up a timeout-based polling mechanism.
450          */
451         if (pipe(devc->pipe_fds)) {
452                 /* TODO: Better error message. */
453                 sr_err("%s: pipe() failed", __func__);
454                 return SR_ERR;
455         }
456
457         devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
458
459         g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
460
461         /* Set channel encoding to binary (default is UTF-8). */
462         g_io_channel_set_encoding(devc->channel, NULL, NULL);
463
464         /* Make channels to unbuffered. */
465         g_io_channel_set_buffered(devc->channel, FALSE);
466
467         sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
468                     40, receive_data, devc);
469
470         /* Send header packet to the session bus. */
471         std_session_send_df_header(cb_data, LOG_PREFIX);
472
473         /* We use this timestamp to decide how many more samples to send. */
474         devc->starttime = g_get_monotonic_time();
475
476         return SR_OK;
477 }
478
479 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
480 {
481         struct dev_context *const devc = sdi->priv;
482         struct sr_datafeed_packet packet;
483
484         (void)cb_data;
485
486         sr_dbg("Stopping aquisition.");
487
488         sr_session_source_remove_channel(devc->channel);
489         g_io_channel_shutdown(devc->channel, FALSE, NULL);
490         g_io_channel_unref(devc->channel);
491         devc->channel = NULL;
492
493         /* Send last packet. */
494         packet.type = SR_DF_END;
495         sr_session_send(devc->cb_data, &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 = init,
505         .cleanup = cleanup,
506         .scan = scan,
507         .dev_list = dev_list,
508         .dev_clear = dev_clear,
509         .config_get = config_get,
510         .config_set = config_set,
511         .config_list = config_list,
512         .dev_open = dev_open,
513         .dev_close = dev_close,
514         .dev_acquisition_start = dev_acquisition_start,
515         .dev_acquisition_stop = dev_acquisition_stop,
516         .priv = NULL,
517 };