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