]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
Centralise duplicated logging helper defines.
[libsigrok.git] / hardware / demo / demo.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5  * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
6  * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
21  */
22
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #ifdef _WIN32
27 #include <io.h>
28 #include <fcntl.h>
29 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
30 #endif
31 #include "libsigrok.h"
32 #include "libsigrok-internal.h"
33
34 #define LOG_PREFIX "demo"
35
36 /* TODO: Number of probes should be configurable. */
37 #define NUM_PROBES           8
38
39 /* The size of chunks to send through the session bus. */
40 /* TODO: Should be configurable. */
41 #define LOGIC_BUFSIZE        4096
42
43 /* Patterns we can generate */
44 enum {
45         /**
46          * Spells "sigrok" across 8 probes using '0's (with '1's as
47          * "background") when displayed using the 'bits' output format.
48          */
49         PATTERN_SIGROK,
50
51         /** Pseudo-)random values on all probes. */
52         PATTERN_RANDOM,
53
54         /**
55          * Incrementing number across all probes.
56          */
57         PATTERN_INC,
58
59         /** All probes have a low logic state. */
60         PATTERN_ALL_LOW,
61
62         /** All probes have a high logic state. */
63         PATTERN_ALL_HIGH,
64 };
65
66 static const char *pattern_strings[] = {
67         "sigrok",
68         "random",
69         "incremental",
70         "all-low",
71         "all-high",
72 };
73
74 /* Private, per-device-instance driver context. */
75 struct dev_context {
76         int pipe_fds[2];
77         GIOChannel *channel;
78         uint64_t cur_samplerate;
79         uint64_t limit_samples;
80         uint64_t limit_msec;
81         uint8_t sample_generator;
82         uint64_t samples_counter;
83         void *cb_data;
84         int64_t starttime;
85         unsigned char logic_data[LOGIC_BUFSIZE];
86         uint64_t step;
87 };
88
89 static const int hwcaps[] = {
90         SR_CONF_LOGIC_ANALYZER,
91         SR_CONF_DEMO_DEV,
92         SR_CONF_SAMPLERATE,
93         SR_CONF_PATTERN_MODE,
94         SR_CONF_LIMIT_SAMPLES,
95         SR_CONF_LIMIT_MSEC,
96         SR_CONF_CONTINUOUS,
97 };
98
99 static const uint64_t samplerates[] = {
100         SR_HZ(1),
101         SR_GHZ(1),
102         SR_HZ(1),
103 };
104
105 static uint8_t pattern_sigrok[] = {
106         0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
107         0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
108         0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
109         0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
110         0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
111         0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
112         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113         0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 };
115
116 /* Private, per-device-instance driver context. */
117 /* TODO: struct context as with the other drivers. */
118
119 /* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
120 SR_PRIV struct sr_dev_driver demo_driver_info;
121 static struct sr_dev_driver *di = &demo_driver_info;
122
123 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
124
125 static int dev_clear(void)
126 {
127         return std_dev_clear(di, NULL);
128 }
129
130 static int init(struct sr_context *sr_ctx)
131 {
132         return std_init(sr_ctx, di, LOG_PREFIX);
133 }
134
135 static GSList *scan(GSList *options)
136 {
137         struct sr_dev_inst *sdi;
138         struct sr_probe *probe;
139         struct drv_context *drvc;
140         struct dev_context *devc;
141         GSList *devices;
142         int i;
143         char probe_name[16];
144
145         (void)options;
146
147         drvc = di->priv;
148
149         devices = NULL;
150
151         sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, "Demo device", NULL, NULL);
152         if (!sdi) {
153                 sr_err("Device instance creation failed.");
154                 return NULL;
155         }
156         sdi->driver = di;
157
158         for (i = 0; i < NUM_PROBES; i++) {
159                 sprintf(probe_name, "D%d", i);
160                 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, probe_name)))
161                         return NULL;
162                 sdi->probes = g_slist_append(sdi->probes, probe);
163         }
164
165         devices = g_slist_append(devices, sdi);
166         drvc->instances = g_slist_append(drvc->instances, sdi);
167
168         if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
169                 sr_err("Device context malloc failed.");
170                 return NULL;
171         }
172
173         devc->cur_samplerate = SR_KHZ(200);
174         devc->limit_samples = 0;
175         devc->limit_msec = 0;
176         devc->sample_generator = PATTERN_SIGROK;
177         devc->step =0;
178
179         sdi->priv = devc;
180
181         return devices;
182 }
183
184 static GSList *dev_list(void)
185 {
186         return ((struct drv_context *)(di->priv))->instances;
187 }
188
189 static int dev_open(struct sr_dev_inst *sdi)
190 {
191         sdi->status = SR_ST_ACTIVE;
192
193         return SR_OK;
194 }
195
196 static int dev_close(struct sr_dev_inst *sdi)
197 {
198         sdi->status = SR_ST_INACTIVE;
199
200         return SR_OK;
201 }
202
203 static int cleanup(void)
204 {
205         return dev_clear();
206 }
207
208 static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
209                 const struct sr_probe_group *probe_group)
210 {
211         struct dev_context *const devc = sdi->priv;
212
213         (void)probe_group;
214
215         switch (id) {
216         case SR_CONF_SAMPLERATE:
217                 *data = g_variant_new_uint64(devc->cur_samplerate);
218                 break;
219         case SR_CONF_LIMIT_SAMPLES:
220                 *data = g_variant_new_uint64(devc->limit_samples);
221                 break;
222         case SR_CONF_LIMIT_MSEC:
223                 *data = g_variant_new_uint64(devc->limit_msec);
224                 break;
225         case SR_CONF_PATTERN_MODE:
226                 *data = g_variant_new_string(pattern_strings[devc->sample_generator]);
227                 break;
228         default:
229                 return SR_ERR_NA;
230         }
231
232         return SR_OK;
233 }
234
235 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
236                 const struct sr_probe_group *probe_group)
237 {
238         unsigned int i;
239         int ret;
240         const char *stropt;
241
242         (void)probe_group;
243         struct dev_context *const devc = sdi->priv;
244
245         if (sdi->status != SR_ST_ACTIVE)
246                 return SR_ERR_DEV_CLOSED;
247
248         if (id == SR_CONF_SAMPLERATE) {
249                 devc->cur_samplerate = g_variant_get_uint64(data);
250                 sr_dbg("Setting samplerate to %" PRIu64, devc->cur_samplerate);
251                 ret = SR_OK;
252         } else if (id == SR_CONF_LIMIT_SAMPLES) {
253                 devc->limit_msec = 0;
254                 devc->limit_samples = g_variant_get_uint64(data);
255                 sr_dbg("Setting limit_samples to %" PRIu64, devc->limit_samples);
256                 ret = SR_OK;
257         } else if (id == SR_CONF_LIMIT_MSEC) {
258                 devc->limit_msec = g_variant_get_uint64(data);
259                 devc->limit_samples = 0;
260                 sr_dbg("Setting limit_msec to %" PRIu64, devc->limit_msec);
261                 ret = SR_OK;
262         } else if (id == SR_CONF_PATTERN_MODE) {
263                 stropt = g_variant_get_string(data, NULL);
264                 ret = SR_ERR;
265                 for (i = 0; i < ARRAY_SIZE(pattern_strings); i++) {
266                         if (!strcmp(stropt, pattern_strings[i])) {
267                                 devc->sample_generator = i;
268                                 ret = SR_OK;
269                                 break;
270                         }
271                 }
272                 /* Might as well do this now. */
273                 if (i == PATTERN_ALL_LOW)
274                         memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
275                 else if (i == PATTERN_ALL_HIGH)
276                         memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
277                 sr_dbg("Setting pattern to %s", pattern_strings[i]);
278         } else {
279                 ret = SR_ERR_NA;
280         }
281
282         return ret;
283 }
284
285 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
286                 const struct sr_probe_group *probe_group)
287 {
288         GVariant *gvar;
289         GVariantBuilder gvb;
290
291         (void)sdi;
292         (void)probe_group;
293
294         switch (key) {
295         case SR_CONF_DEVICE_OPTIONS:
296                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
297                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
298                 break;
299         case SR_CONF_SAMPLERATE:
300                 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
301                 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
302                                 ARRAY_SIZE(samplerates), sizeof(uint64_t));
303                 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
304                 *data = g_variant_builder_end(&gvb);
305                 break;
306         case SR_CONF_PATTERN_MODE:
307                 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
308                 break;
309         default:
310                 return SR_ERR_NA;
311         }
312
313         return SR_OK;
314 }
315
316 static void sample_generator(struct sr_dev_inst *sdi, uint64_t size)
317 {
318         struct dev_context *devc;
319         uint64_t i;
320
321         devc = sdi->priv;
322
323         switch (devc->sample_generator) {
324         case PATTERN_SIGROK:
325                 for (i = 0; i < size; i++) {
326                         devc->logic_data[i] = ~(pattern_sigrok[
327                                 devc->step++ % sizeof(pattern_sigrok)] >> 1);
328                 }
329                 break;
330         case PATTERN_RANDOM:
331                 for (i = 0; i < size; i++)
332                         devc->logic_data[i] = (uint8_t)(rand() & 0xff);
333                 break;
334         case PATTERN_INC:
335                 for (i = 0; i < size; i++)
336                         devc->logic_data[i] = devc->step++;
337                 break;
338         case PATTERN_ALL_LOW:
339         case PATTERN_ALL_HIGH:
340                 /* These were set when the pattern mode was selected. */
341                 break;
342         default:
343                 sr_err("Unknown pattern: %d.", devc->sample_generator);
344                 break;
345         }
346 }
347
348 /* Callback handling data */
349 static int prepare_data(int fd, int revents, void *cb_data)
350 {
351         struct sr_dev_inst *sdi;
352         struct dev_context *devc;
353         struct sr_datafeed_packet packet;
354         struct sr_datafeed_logic logic;
355         static uint64_t samples_to_send, expected_samplenum, sending_now;
356         int64_t time, elapsed;
357
358         (void)fd;
359         (void)revents;
360
361         sdi = cb_data;
362         devc = sdi->priv;
363
364         /* How many "virtual" samples should we have collected by now? */
365         time = g_get_monotonic_time();
366         elapsed = time - devc->starttime;
367         expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
368         /* Of those, how many do we still have to send? */
369         samples_to_send = expected_samplenum - devc->samples_counter;
370
371         if (devc->limit_samples) {
372                 samples_to_send = MIN(samples_to_send,
373                                  devc->limit_samples - devc->samples_counter);
374         }
375
376         while (samples_to_send > 0) {
377                 sending_now = MIN(samples_to_send, LOGIC_BUFSIZE);
378                 samples_to_send -= sending_now;
379                 sample_generator(sdi, sending_now);
380
381                 packet.type = SR_DF_LOGIC;
382                 packet.payload = &logic;
383                 logic.length = sending_now;
384                 logic.unitsize = 1;
385                 logic.data = devc->logic_data;
386                 sr_session_send(devc->cb_data, &packet);
387                 devc->samples_counter += sending_now;
388         }
389
390         if (devc->limit_samples &&
391                 devc->samples_counter >= devc->limit_samples) {
392                 sr_info("Requested number of samples reached.");
393                 dev_acquisition_stop(sdi, cb_data);
394                 return TRUE;
395         }
396
397         return TRUE;
398 }
399
400 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
401 {
402         struct dev_context *devc;
403
404         if (sdi->status != SR_ST_ACTIVE)
405                 return SR_ERR_DEV_CLOSED;
406
407         devc = sdi->priv;
408         devc->cb_data = cb_data;
409         devc->samples_counter = 0;
410
411         /*
412          * Setting two channels connected by a pipe is a remnant from when the
413          * demo driver generated data in a thread, and collected and sent the
414          * data in the main program loop.
415          * They are kept here because it provides a convenient way of setting
416          * up a timeout-based polling mechanism.
417          */
418         if (pipe(devc->pipe_fds)) {
419                 sr_err("%s: pipe() failed", __func__);
420                 return SR_ERR;
421         }
422
423         devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
424
425         g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
426
427         /* Set channel encoding to binary (default is UTF-8). */
428         g_io_channel_set_encoding(devc->channel, NULL, NULL);
429
430         /* Make channels to unbuffered. */
431         g_io_channel_set_buffered(devc->channel, FALSE);
432
433         sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
434                         40, prepare_data, (void *)sdi);
435
436         /* Send header packet to the session bus. */
437         std_session_send_df_header(cb_data, LOG_PREFIX);
438
439         /* We use this timestamp to decide how many more samples to send. */
440         devc->starttime = g_get_monotonic_time();
441
442         return SR_OK;
443 }
444
445 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
446 {
447         struct dev_context *const devc = sdi->priv;
448         struct sr_datafeed_packet packet;
449
450         (void)cb_data;
451
452         sr_dbg("Stopping aquisition.");
453
454         sr_session_source_remove_channel(devc->channel);
455         g_io_channel_shutdown(devc->channel, FALSE, NULL);
456         g_io_channel_unref(devc->channel);
457         devc->channel = NULL;
458
459         /* Send last packet. */
460         packet.type = SR_DF_END;
461         sr_session_send(devc->cb_data, &packet);
462
463         return SR_OK;
464 }
465
466 SR_PRIV struct sr_dev_driver demo_driver_info = {
467         .name = "demo",
468         .longname = "Demo driver and pattern generator",
469         .api_version = 1,
470         .init = init,
471         .cleanup = cleanup,
472         .scan = scan,
473         .dev_list = dev_list,
474         .dev_clear = dev_clear,
475         .config_get = config_get,
476         .config_set = config_set,
477         .config_list = config_list,
478         .dev_open = dev_open,
479         .dev_close = dev_close,
480         .dev_acquisition_start = dev_acquisition_start,
481         .dev_acquisition_stop = dev_acquisition_stop,
482         .priv = NULL,
483 };