]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
probe_groups: API changes required to implement probe groups.
[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                 const struct sr_probe_group *probe_group)
230 {
231         struct dev_context *const devc = sdi->priv;
232
233         (void)probe_group;
234
235         switch (id) {
236         case SR_CONF_SAMPLERATE:
237                 *data = g_variant_new_uint64(devc->cur_samplerate);
238                 break;
239         case SR_CONF_LIMIT_SAMPLES:
240                 *data = g_variant_new_uint64(devc->limit_samples);
241                 break;
242         case SR_CONF_LIMIT_MSEC:
243                 *data = g_variant_new_uint64(devc->limit_msec);
244                 break;
245         case SR_CONF_PATTERN_MODE:
246                 switch (devc->sample_generator) {
247                 case PATTERN_SIGROK:
248                         *data = g_variant_new_string(STR_PATTERN_SIGROK);
249                         break;
250                 case PATTERN_RANDOM:
251                         *data = g_variant_new_string(STR_PATTERN_RANDOM);
252                         break;
253                 case PATTERN_INC:
254                         *data = g_variant_new_string(STR_PATTERN_INC);
255                         break;
256                 case PATTERN_ALL_LOW:
257                         *data = g_variant_new_string(STR_PATTERN_ALL_LOW);
258                         break;
259                 case PATTERN_ALL_HIGH:
260                         *data = g_variant_new_string(STR_PATTERN_ALL_HIGH);
261                         break;
262                 }
263                 break;
264         default:
265                 return SR_ERR_NA;
266         }
267
268         return SR_OK;
269 }
270
271 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
272                 const struct sr_probe_group *probe_group)
273 {
274         int ret;
275         const char *stropt;
276
277         (void)probe_group;
278         struct dev_context *const devc = sdi->priv;
279
280         if (sdi->status != SR_ST_ACTIVE)
281                 return SR_ERR_DEV_CLOSED;
282
283         if (id == SR_CONF_SAMPLERATE) {
284                 devc->cur_samplerate = g_variant_get_uint64(data);
285                 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
286                        devc->cur_samplerate);
287                 ret = SR_OK;
288         } else if (id == SR_CONF_LIMIT_SAMPLES) {
289                 devc->limit_msec = 0;
290                 devc->limit_samples = g_variant_get_uint64(data);
291                 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
292                        devc->limit_samples);
293                 ret = SR_OK;
294         } else if (id == SR_CONF_LIMIT_MSEC) {
295                 devc->limit_msec = g_variant_get_uint64(data);
296                 devc->limit_samples = 0;
297                 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
298                        devc->limit_msec);
299                 ret = SR_OK;
300         } else if (id == SR_CONF_PATTERN_MODE) {
301                 stropt = g_variant_get_string(data, NULL);
302                 ret = SR_OK;
303                 if (!strcmp(stropt, STR_PATTERN_SIGROK)) {
304                         devc->sample_generator = PATTERN_SIGROK;
305                 } else if (!strcmp(stropt, STR_PATTERN_RANDOM)) {
306                         devc->sample_generator = PATTERN_RANDOM;
307                 } else if (!strcmp(stropt, STR_PATTERN_INC)) {
308                         devc->sample_generator = PATTERN_INC;
309                 } else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) {
310                         devc->sample_generator = PATTERN_ALL_LOW;
311                 } else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) {
312                         devc->sample_generator = PATTERN_ALL_HIGH;
313                 } else {
314                         ret = SR_ERR;
315                 }
316                 sr_dbg("%s: setting pattern to %d",
317                         __func__, devc->sample_generator);
318         } else {
319                 ret = SR_ERR_NA;
320         }
321
322         return ret;
323 }
324
325 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
326                 const struct sr_probe_group *probe_group)
327 {
328         GVariant *gvar;
329         GVariantBuilder gvb;
330
331         (void)sdi;
332         (void)probe_group;
333
334         switch (key) {
335         case SR_CONF_DEVICE_OPTIONS:
336                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
337                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
338                 break;
339         case SR_CONF_SAMPLERATE:
340                 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
341                 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
342                                 ARRAY_SIZE(samplerates), sizeof(uint64_t));
343                 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
344                 *data = g_variant_builder_end(&gvb);
345                 break;
346         case SR_CONF_PATTERN_MODE:
347                 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
348                 break;
349         default:
350                 return SR_ERR_NA;
351         }
352
353         return SR_OK;
354 }
355
356 static void samples_generator(uint8_t *buf, uint64_t size,
357                               struct dev_context *devc)
358 {
359         static uint64_t p = 0;
360         uint64_t i;
361
362         /* TODO: Needed? */
363         memset(buf, 0, size);
364
365         switch (devc->sample_generator) {
366         case PATTERN_SIGROK: /* sigrok pattern */
367                 for (i = 0; i < size; i++) {
368                         *(buf + i) = ~(pattern_sigrok[
369                                 p++ % sizeof(pattern_sigrok)] >> 1);
370                 }
371                 break;
372         case PATTERN_RANDOM: /* Random */
373                 for (i = 0; i < size; i++)
374                         *(buf + i) = (uint8_t)(rand() & 0xff);
375                 break;
376         case PATTERN_INC: /* Simple increment */
377                 for (i = 0; i < size; i++)
378                         *(buf + i) = p++;
379                 break;
380         case PATTERN_ALL_LOW: /* All probes are low */
381                 memset(buf, 0x00, size);
382                 break;
383         case PATTERN_ALL_HIGH: /* All probes are high */
384                 memset(buf, 0xff, size);
385                 break;
386         default:
387                 sr_err("Unknown pattern: %d.", devc->sample_generator);
388                 break;
389         }
390 }
391
392 /* Callback handling data */
393 static int receive_data(int fd, int revents, void *cb_data)
394 {
395         struct dev_context *devc = cb_data;
396         struct sr_datafeed_packet packet;
397         struct sr_datafeed_logic logic;
398         uint8_t buf[BUFSIZE];
399         static uint64_t samples_to_send, expected_samplenum, sending_now;
400         int64_t time, elapsed;
401
402         (void)fd;
403         (void)revents;
404
405         /* How many "virtual" samples should we have collected by now? */
406         time = g_get_monotonic_time();
407         elapsed = time - devc->starttime;
408         expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
409         /* Of those, how many do we still have to send? */
410         samples_to_send = expected_samplenum - devc->samples_counter;
411
412         if (devc->limit_samples) {
413                 samples_to_send = MIN(samples_to_send,
414                                  devc->limit_samples - devc->samples_counter);
415         }
416
417         while (samples_to_send > 0) {
418                 sending_now = MIN(samples_to_send, sizeof(buf));
419                 samples_to_send -= sending_now;
420                 samples_generator(buf, sending_now, devc);
421
422                 packet.type = SR_DF_LOGIC;
423                 packet.payload = &logic;
424                 logic.length = sending_now;
425                 logic.unitsize = 1;
426                 logic.data = buf;
427                 sr_session_send(devc->cb_data, &packet);
428                 devc->samples_counter += sending_now;
429         }
430
431         if (devc->limit_samples &&
432                 devc->samples_counter >= devc->limit_samples) {
433                 sr_info("Requested number of samples reached.");
434                 dev_acquisition_stop(devc->sdi, cb_data);
435                 return TRUE;
436         }
437
438         return TRUE;
439 }
440
441 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
442 {
443         struct dev_context *const devc = sdi->priv;
444
445         if (sdi->status != SR_ST_ACTIVE)
446                 return SR_ERR_DEV_CLOSED;
447
448         devc->cb_data = cb_data;
449         devc->samples_counter = 0;
450
451         /*
452          * Setting two channels connected by a pipe is a remnant from when the
453          * demo driver generated data in a thread, and collected and sent the
454          * data in the main program loop.
455          * They are kept here because it provides a convenient way of setting
456          * up a timeout-based polling mechanism.
457          */
458         if (pipe(devc->pipe_fds)) {
459                 /* TODO: Better error message. */
460                 sr_err("%s: pipe() failed", __func__);
461                 return SR_ERR;
462         }
463
464         devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
465
466         g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
467
468         /* Set channel encoding to binary (default is UTF-8). */
469         g_io_channel_set_encoding(devc->channel, NULL, NULL);
470
471         /* Make channels to unbuffered. */
472         g_io_channel_set_buffered(devc->channel, FALSE);
473
474         sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
475                     40, receive_data, devc);
476
477         /* Send header packet to the session bus. */
478         std_session_send_df_header(cb_data, LOG_PREFIX);
479
480         /* We use this timestamp to decide how many more samples to send. */
481         devc->starttime = g_get_monotonic_time();
482
483         return SR_OK;
484 }
485
486 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
487 {
488         struct dev_context *const devc = sdi->priv;
489         struct sr_datafeed_packet packet;
490
491         (void)cb_data;
492
493         sr_dbg("Stopping aquisition.");
494
495         sr_session_source_remove_channel(devc->channel);
496         g_io_channel_shutdown(devc->channel, FALSE, NULL);
497         g_io_channel_unref(devc->channel);
498         devc->channel = NULL;
499
500         /* Send last packet. */
501         packet.type = SR_DF_END;
502         sr_session_send(devc->cb_data, &packet);
503
504         return SR_OK;
505 }
506
507 SR_PRIV struct sr_dev_driver demo_driver_info = {
508         .name = "demo",
509         .longname = "Demo driver and pattern generator",
510         .api_version = 1,
511         .init = init,
512         .cleanup = cleanup,
513         .scan = scan,
514         .dev_list = dev_list,
515         .dev_clear = dev_clear,
516         .config_get = config_get,
517         .config_set = config_set,
518         .config_list = config_list,
519         .dev_open = dev_open,
520         .dev_close = dev_close,
521         .dev_acquisition_start = dev_acquisition_start,
522         .dev_acquisition_stop = dev_acquisition_stop,
523         .priv = NULL,
524 };