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