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