]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
3e3150afc6663156f0aaac25aeeb0f7505bbb269
[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_SAMPLERATE) {
262                 cur_samplerate = *(const uint64_t *)value;
263                 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
264                        cur_samplerate);
265                 ret = SR_OK;
266         } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
267                 limit_msec = 0;
268                 limit_samples = *(const uint64_t *)value;
269                 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
270                        limit_samples);
271                 ret = SR_OK;
272         } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
273                 limit_msec = *(const uint64_t *)value;
274                 limit_samples = 0;
275                 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
276                        limit_msec);
277                 ret = SR_OK;
278         } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
279                 stropt = value;
280                 ret = SR_OK;
281                 if (!strcmp(stropt, "sigrok")) {
282                         default_pattern = PATTERN_SIGROK;
283                 } else if (!strcmp(stropt, "random")) {
284                         default_pattern = PATTERN_RANDOM;
285                 } else if (!strcmp(stropt, "incremental")) {
286                         default_pattern = PATTERN_INC;
287                 } else if (!strcmp(stropt, "all-low")) {
288                         default_pattern = PATTERN_ALL_LOW;
289                 } else if (!strcmp(stropt, "all-high")) {
290                         default_pattern = PATTERN_ALL_HIGH;
291                 } else {
292                         ret = SR_ERR;
293                 }
294                 sr_dbg("demo: %s: setting pattern to %d", __func__,
295                        default_pattern);
296         } else {
297                 ret = SR_ERR;
298         }
299
300         return ret;
301 }
302
303 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
304 {
305         static uint64_t p = 0;
306         struct dev_context *devc = data;
307         uint64_t i;
308
309         /* TODO: Needed? */
310         memset(buf, 0, size);
311
312         switch (devc->sample_generator) {
313         case PATTERN_SIGROK: /* sigrok pattern */
314                 for (i = 0; i < size; i++) {
315                         *(buf + i) = ~(pattern_sigrok[p] >> 1);
316                         if (++p == 64)
317                                 p = 0;
318                 }
319                 break;
320         case PATTERN_RANDOM: /* Random */
321                 for (i = 0; i < size; i++)
322                         *(buf + i) = (uint8_t)(rand() & 0xff);
323                 break;
324         case PATTERN_INC: /* Simple increment */
325                 for (i = 0; i < size; i++)
326                         *(buf + i) = i;
327                 break;
328         case PATTERN_ALL_LOW: /* All probes are low */
329                 memset(buf, 0x00, size);
330                 break;
331         case PATTERN_ALL_HIGH: /* All probes are high */
332                 memset(buf, 0xff, size);
333                 break;
334         default:
335                 sr_err("demo: %s: unknown pattern %d", __func__,
336                        devc->sample_generator);
337                 break;
338         }
339 }
340
341 /* Thread function */
342 static void thread_func(void *data)
343 {
344         struct dev_context *devc = data;
345         uint8_t buf[BUFSIZE];
346         uint64_t nb_to_send = 0;
347         int bytes_written;
348         double time_cur, time_last, time_diff;
349
350         time_last = g_timer_elapsed(devc->timer, NULL);
351
352         while (thread_running) {
353                 /* Rate control */
354                 time_cur = g_timer_elapsed(devc->timer, NULL);
355
356                 time_diff = time_cur - time_last;
357                 time_last = time_cur;
358
359                 nb_to_send = cur_samplerate * time_diff;
360
361                 if (limit_samples) {
362                         nb_to_send = MIN(nb_to_send,
363                                       limit_samples - devc->samples_counter);
364                 }
365
366                 /* Make sure we don't overflow. */
367                 nb_to_send = MIN(nb_to_send, BUFSIZE);
368
369                 if (nb_to_send) {
370                         samples_generator(buf, nb_to_send, data);
371                         devc->samples_counter += nb_to_send;
372
373                         g_io_channel_write_chars(devc->channels[1], (gchar *)&buf,
374                                 nb_to_send, (gsize *)&bytes_written, NULL);
375                 }
376
377                 /* Check if we're done. */
378                 if ((limit_msec && time_cur * 1000 > limit_msec) ||
379                     (limit_samples && devc->samples_counter >= limit_samples))
380                 {
381                         close(devc->pipe_fds[1]);
382                         thread_running = 0;
383                 }
384
385                 g_usleep(10);
386         }
387 }
388
389 /* Callback handling data */
390 static int receive_data(int fd, int revents, void *cb_data)
391 {
392         struct dev_context *devc = cb_data;
393         struct sr_datafeed_packet packet;
394         struct sr_datafeed_logic logic;
395         static uint64_t samples_received = 0;
396         unsigned char c[BUFSIZE];
397         gsize z;
398
399         /* Avoid compiler warnings. */
400         (void)fd;
401         (void)revents;
402
403         do {
404                 g_io_channel_read_chars(devc->channels[0],
405                                         (gchar *)&c, BUFSIZE, &z, NULL);
406
407                 if (z > 0) {
408                         packet.type = SR_DF_LOGIC;
409                         packet.payload = &logic;
410                         logic.length = z;
411                         logic.unitsize = 1;
412                         logic.data = c;
413                         sr_session_send(devc->session_dev_id, &packet);
414                         samples_received += z;
415                 }
416         } while (z > 0);
417
418         if (!thread_running && z <= 0) {
419                 /* Make sure we don't receive more packets. */
420                 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
421
422                 /* Send last packet. */
423                 packet.type = SR_DF_END;
424                 sr_session_send(devc->session_dev_id, &packet);
425
426                 return FALSE;
427         }
428
429         return TRUE;
430 }
431
432 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
433                 void *cb_data)
434 {
435         struct sr_datafeed_packet *packet;
436         struct sr_datafeed_header *header;
437         struct sr_datafeed_meta_logic meta;
438         struct dev_context *devc;
439
440         (void)sdi;
441
442         /* TODO: 'devc' is never g_free()'d? */
443         if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
444                 sr_err("demo: %s: devc malloc failed", __func__);
445                 return SR_ERR_MALLOC;
446         }
447
448         devc->sample_generator = default_pattern;
449         devc->session_dev_id = cb_data;
450         devc->samples_counter = 0;
451
452         if (pipe(devc->pipe_fds)) {
453                 /* TODO: Better error message. */
454                 sr_err("demo: %s: pipe() failed", __func__);
455                 return SR_ERR;
456         }
457
458         devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
459         devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
460
461         g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
462
463         /* Set channel encoding to binary (default is UTF-8). */
464         g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
465         g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
466
467         /* Make channels to unbuffered. */
468         g_io_channel_set_buffered(devc->channels[0], FALSE);
469         g_io_channel_set_buffered(devc->channels[1], FALSE);
470
471         sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
472                     40, receive_data, devc);
473
474         /* Run the demo thread. */
475         g_thread_init(NULL);
476         /* This must to be done between g_thread_init() & g_thread_create(). */
477         devc->timer = g_timer_new();
478         thread_running = 1;
479         my_thread =
480             g_thread_create((GThreadFunc)thread_func, devc, TRUE, NULL);
481         if (!my_thread) {
482                 sr_err("demo: %s: g_thread_create 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_open = hw_dev_open,
541         .dev_close = hw_dev_close,
542         .info_get = hw_info_get,
543         .dev_config_set = hw_dev_config_set,
544         .dev_acquisition_start = hw_dev_acquisition_start,
545         .dev_acquisition_stop = hw_dev_acquisition_stop,
546         .priv = NULL,
547 };