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