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