2 * This file is part of the sigrok project.
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
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.
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.
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
28 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
32 #include "sigrok-internal.h"
34 /* TODO: Number of probes should be configurable. */
37 #define DEMONAME "Demo device"
39 /* The size of chunks to send through the session bus. */
40 /* TODO: Should be configurable. */
43 /* Supported patterns which we can generate */
46 * Pattern which spells "sigrok" using '0's (with '1's as "background")
47 * when displayed using the 'bits' output format.
51 /** Pattern which consists of (pseudo-)random values on all probes. */
55 * Pattern which consists of incrementing numbers.
56 * TODO: Better description.
60 /** Pattern where all probes have a low logic state. */
63 /** Pattern where all probes have a high logic state. */
67 /* FIXME: Should not be global. */
68 GIOChannel *channels[2];
72 uint8_t sample_generator;
73 uint8_t thread_running;
74 uint64_t samples_counter;
76 gpointer session_data;
80 static int capabilities[] = {
81 SR_HWCAP_LOGIC_ANALYZER,
84 SR_HWCAP_PATTERN_MODE,
85 SR_HWCAP_LIMIT_SAMPLES,
90 static struct sr_samplerates samplerates = {
97 static const char *pattern_strings[] = {
106 static const char *probe_names[NUM_PROBES + 1] = {
118 static uint8_t pattern_sigrok[] = {
119 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
120 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
121 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
122 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
123 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
124 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 /* List of struct sr_device_instance, maintained by opendev()/closedev(). */
130 static GSList *device_instances = NULL;
131 static uint64_t cur_samplerate = SR_KHZ(200);
132 static uint64_t period_ps = 5000000;
133 static uint64_t limit_samples = 0;
134 static uint64_t limit_msec = 0;
135 static int default_pattern = PATTERN_SIGROK;
136 static GThread *my_thread;
137 static int thread_running;
139 static void hw_stop_acquisition(int device_index, gpointer session_data);
141 static int hw_init(const char *deviceinfo)
143 struct sr_device_instance *sdi;
145 /* Avoid compiler warnings. */
148 sdi = sr_device_instance_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
150 sr_err("demo: %s: sr_device_instance_new failed", __func__);
154 device_instances = g_slist_append(device_instances, sdi);
159 static int hw_opendev(int device_index)
161 /* Avoid compiler warnings. */
164 /* Nothing needed so far. */
169 static int hw_closedev(int device_index)
171 /* Avoid compiler warnings. */
174 /* Nothing needed so far. */
179 static void hw_cleanup(void)
181 /* Nothing needed so far. */
184 static void *hw_get_device_info(int device_index, int device_info_id)
186 struct sr_device_instance *sdi;
189 if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
190 sr_err("demo: %s: sdi was NULL", __func__);
194 switch (device_info_id) {
198 case SR_DI_NUM_PROBES:
199 info = GINT_TO_POINTER(NUM_PROBES);
201 case SR_DI_PROBE_NAMES:
204 case SR_DI_SAMPLERATES:
207 case SR_DI_CUR_SAMPLERATE:
208 info = &cur_samplerate;
210 case SR_DI_PATTERNMODES:
211 info = &pattern_strings;
218 static int hw_get_status(int device_index)
220 /* Avoid compiler warnings. */
226 static int *hw_get_capabilities(void)
231 static int hw_set_configuration(int device_index, int capability, void *value)
236 /* Avoid compiler warnings. */
239 if (capability == SR_HWCAP_PROBECONFIG) {
240 /* Nothing to do, but must be supported */
242 } else if (capability == SR_HWCAP_SAMPLERATE) {
243 cur_samplerate = *(uint64_t *)value;
244 period_ps = 1000000000000 / cur_samplerate;
245 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
248 } else if (capability == SR_HWCAP_LIMIT_SAMPLES) {
249 limit_samples = *(uint64_t *)value;
250 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
253 } else if (capability == SR_HWCAP_LIMIT_MSEC) {
254 limit_msec = *(uint64_t *)value;
255 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
258 } else if (capability == SR_HWCAP_PATTERN_MODE) {
261 if (!strcmp(stropt, "sigrok")) {
262 default_pattern = PATTERN_SIGROK;
263 } else if (!strcmp(stropt, "random")) {
264 default_pattern = PATTERN_RANDOM;
265 } else if (!strcmp(stropt, "incremental")) {
266 default_pattern = PATTERN_INC;
267 } else if (!strcmp(stropt, "all-low")) {
268 default_pattern = PATTERN_ALL_LOW;
269 } else if (!strcmp(stropt, "all-high")) {
270 default_pattern = PATTERN_ALL_HIGH;
274 sr_dbg("demo: %s: setting pattern to %d", __func__,
283 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
285 static uint64_t p = 0;
286 struct databag *mydata = data;
290 memset(buf, 0, size);
292 switch (mydata->sample_generator) {
293 case PATTERN_SIGROK: /* sigrok pattern */
294 for (i = 0; i < size; i++) {
295 *(buf + i) = ~(pattern_sigrok[p] >> 1);
300 case PATTERN_RANDOM: /* Random */
301 for (i = 0; i < size; i++)
302 *(buf + i) = (uint8_t)(rand() & 0xff);
304 case PATTERN_INC: /* Simple increment */
305 for (i = 0; i < size; i++)
308 case PATTERN_ALL_LOW: /* All probes are low */
309 memset(buf, 0x00, size);
311 case PATTERN_ALL_HIGH: /* All probes are high */
312 memset(buf, 0xff, size);
315 /* TODO: Error handling. */
320 /* Thread function */
321 static void thread_func(void *data)
323 struct databag *mydata = data;
324 uint8_t buf[BUFSIZE];
325 uint64_t nb_to_send = 0;
327 double time_cur, time_last, time_diff;
329 time_last = g_timer_elapsed(mydata->timer, NULL);
331 while (thread_running) {
333 time_cur = g_timer_elapsed(mydata->timer, NULL);
335 time_diff = time_cur - time_last;
336 time_last = time_cur;
338 nb_to_send = cur_samplerate * time_diff;
341 nb_to_send = MIN(nb_to_send,
342 limit_samples - mydata->samples_counter);
345 /* Make sure we don't overflow. */
346 nb_to_send = MIN(nb_to_send, BUFSIZE);
349 samples_generator(buf, nb_to_send, data);
350 mydata->samples_counter += nb_to_send;
352 g_io_channel_write_chars(channels[1], (gchar *)&buf,
353 nb_to_send, (gsize *)&bytes_written, NULL);
356 /* Check if we're done. */
357 if ((limit_msec && time_cur * 1000 > limit_msec) ||
358 (limit_samples && mydata->samples_counter >= limit_samples))
360 close(mydata->pipe_fds[1]);
368 /* Callback handling data */
369 static int receive_data(int fd, int revents, void *session_data)
371 struct sr_datafeed_packet packet;
372 struct sr_datafeed_logic logic;
373 static uint64_t samples_received = 0;
374 unsigned char c[BUFSIZE];
377 /* Avoid compiler warnings. */
382 g_io_channel_read_chars(channels[0],
383 (gchar *)&c, BUFSIZE, &z, NULL);
386 packet.type = SR_DF_LOGIC;
387 packet.payload = &logic;
388 packet.timeoffset = samples_received * period_ps;
389 packet.duration = z * period_ps;
393 sr_session_bus(session_data, &packet);
394 samples_received += z;
398 if (!thread_running && z <= 0) {
399 /* Make sure we don't receive more packets. */
400 g_io_channel_close(channels[0]);
402 /* Send last packet. */
403 packet.type = SR_DF_END;
404 sr_session_bus(session_data, &packet);
412 static int hw_start_acquisition(int device_index, gpointer session_data)
414 struct sr_datafeed_packet *packet;
415 struct sr_datafeed_header *header;
416 struct databag *mydata;
418 /* TODO: 'mydata' is never g_free()'d? */
419 if (!(mydata = g_try_malloc(sizeof(struct databag)))) {
420 sr_err("demo: %s: mydata malloc failed", __func__);
421 return SR_ERR_MALLOC;
424 mydata->sample_generator = default_pattern;
425 mydata->session_data = session_data;
426 mydata->device_index = device_index;
427 mydata->samples_counter = 0;
429 if (pipe(mydata->pipe_fds)) {
430 /* TODO: Better error message. */
431 sr_err("demo: %s: pipe() failed", __func__);
435 channels[0] = g_io_channel_unix_new(mydata->pipe_fds[0]);
436 channels[1] = g_io_channel_unix_new(mydata->pipe_fds[1]);
438 /* Set channel encoding to binary (default is UTF-8). */
439 g_io_channel_set_encoding(channels[0], NULL, NULL);
440 g_io_channel_set_encoding(channels[1], NULL, NULL);
442 /* Make channels to unbuffered. */
443 g_io_channel_set_buffered(channels[0], FALSE);
444 g_io_channel_set_buffered(channels[1], FALSE);
446 sr_source_add(mydata->pipe_fds[0], G_IO_IN | G_IO_ERR, 40,
447 receive_data, session_data);
449 /* Run the demo thread. */
451 /* This must to be done between g_thread_init() & g_thread_create(). */
452 mydata->timer = g_timer_new();
455 g_thread_create((GThreadFunc)thread_func, mydata, TRUE, NULL);
457 sr_err("demo: %s: g_thread_create failed", __func__);
458 return SR_ERR; /* TODO */
461 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
462 sr_err("demo: %s: packet malloc failed", __func__);
463 return SR_ERR_MALLOC;
466 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
467 sr_err("demo: %s: header malloc failed", __func__);
468 return SR_ERR_MALLOC;
471 packet->type = SR_DF_HEADER;
472 packet->payload = header;
473 packet->timeoffset = 0;
474 packet->duration = 0;
475 header->feed_version = 1;
476 gettimeofday(&header->starttime, NULL);
477 header->samplerate = cur_samplerate;
478 header->num_logic_probes = NUM_PROBES;
479 header->num_analog_probes = 0;
480 sr_session_bus(session_data, packet);
487 static void hw_stop_acquisition(int device_index, gpointer session_data)
489 /* Avoid compiler warnings. */
493 /* Stop generate thread. */
497 struct sr_device_plugin demo_plugin_info = {
499 .longname = "Demo driver and pattern generator",
502 .cleanup = hw_cleanup,
503 .opendev = hw_opendev,
504 .closedev = hw_closedev,
505 .get_device_info = hw_get_device_info,
506 .get_status = hw_get_status,
507 .get_capabilities = hw_get_capabilities,
508 .set_configuration = hw_set_configuration,
509 .start_acquisition = hw_start_acquisition,
510 .stop_acquisition = hw_stop_acquisition,