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