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