]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
sr: fx2lafw: Consistent #include guard naming.
[libsigrok.git] / hardware / demo / demo.c
CommitLineData
6239c175
UH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
fc96e6f8 5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
6239c175
UH
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>
85b5af06 23#include <unistd.h>
6239c175 24#include <string.h>
d35aaf02
UH
25#ifdef _WIN32
26#include <io.h>
27#include <fcntl.h>
28#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
29#endif
b7f09cf8
UH
30#include "sigrok.h"
31#include "sigrok-internal.h"
6239c175 32
c03ed397 33/* TODO: Number of probes should be configurable. */
e15f48c2 34#define NUM_PROBES 8
c03ed397 35
e15f48c2 36#define DEMONAME "Demo device"
c03ed397
UH
37
38/* The size of chunks to send through the session bus. */
39/* TODO: Should be configurable. */
e15f48c2 40#define BUFSIZE 4096
85b5af06 41
0d31276b 42/* Supported patterns which we can generate */
e15f48c2 43enum {
0d31276b
UH
44 /**
45 * Pattern which spells "sigrok" using '0's (with '1's as "background")
46 * when displayed using the 'bits' output format.
47 */
c8f4624d 48 PATTERN_SIGROK,
0d31276b 49
c03ed397 50 /** Pattern which consists of (pseudo-)random values on all probes. */
c8f4624d 51 PATTERN_RANDOM,
0d31276b
UH
52
53 /**
54 * Pattern which consists of incrementing numbers.
55 * TODO: Better description.
56 */
c8f4624d 57 PATTERN_INC,
c03ed397
UH
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,
e15f48c2 64};
85b5af06 65
29cbfeaf 66/* FIXME: Should not be global. */
3d2efd7d 67SR_PRIV GIOChannel *channels[2];
d35aaf02 68
e15f48c2
BV
69struct databag {
70 int pipe_fds[2];
71 uint8_t sample_generator;
72 uint8_t thread_running;
73 uint64_t samples_counter;
bb7ef793 74 int dev_index;
9c939c51 75 gpointer session_data;
b9cc3629 76 GTimer *timer;
e15f48c2 77};
85b5af06 78
ffedd0bf 79static int hwcaps[] = {
5a2326a7 80 SR_HWCAP_LOGIC_ANALYZER,
bb7ef793 81 SR_HWCAP_DEMO_DEV,
4bfbf9fc 82 SR_HWCAP_SAMPLERATE,
5a2326a7
UH
83 SR_HWCAP_PATTERN_MODE,
84 SR_HWCAP_LIMIT_SAMPLES,
85 SR_HWCAP_LIMIT_MSEC,
86 SR_HWCAP_CONTINUOUS,
6239c175
UH
87};
88
4bfbf9fc 89static struct sr_samplerates samplerates = {
c9140419 90 SR_HZ(1),
59df0c77 91 SR_GHZ(1),
c9140419 92 SR_HZ(1),
4bfbf9fc
BV
93 NULL,
94};
95
c8f4624d 96static const char *pattern_strings[] = {
c03ed397 97 "sigrok",
e15f48c2
BV
98 "random",
99 "incremental",
c03ed397
UH
100 "all-low",
101 "all-high",
02440dd8 102 NULL,
85b5af06
UH
103};
104
464d12c7
KS
105static 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
c8f4624d 117static uint8_t pattern_sigrok[] = {
917e0e71
BV
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
ea9cfed7
UH
128/* Private, per-device-instance driver context. */
129/* TODO: struct context as with the other drivers. */
130
e7eb703f 131/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
d68e2d1a 132static GSList *dev_insts = NULL;
59df0c77 133static uint64_t cur_samplerate = SR_KHZ(200);
b9cc3629
BV
134static uint64_t limit_samples = 0;
135static uint64_t limit_msec = 0;
c8f4624d 136static int default_pattern = PATTERN_SIGROK;
b9cc3629
BV
137static GThread *my_thread;
138static int thread_running;
6239c175 139
69040b7c 140static int hw_dev_acquisition_stop(int dev_index, gpointer session_data);
6239c175 141
bb7ef793 142static int hw_init(const char *devinfo)
6239c175 143{
d68e2d1a 144 struct sr_dev_inst *sdi;
85b5af06 145
e15f48c2 146 /* Avoid compiler warnings. */
bb7ef793 147 (void)devinfo;
85b5af06 148
d3683c42 149 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 150 if (!sdi) {
d68e2d1a 151 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
85b5af06 152 return 0;
c03ed397 153 }
e15f48c2 154
d68e2d1a 155 dev_insts = g_slist_append(dev_insts, sdi);
85b5af06
UH
156
157 return 1;
6239c175
UH
158}
159
e7eb703f 160static int hw_dev_open(int dev_index)
6239c175 161{
17e1afcb 162 /* Avoid compiler warnings. */
bb7ef793 163 (void)dev_index;
6239c175
UH
164
165 /* Nothing needed so far. */
697785d1 166
e46b8fb1 167 return SR_OK;
6239c175
UH
168}
169
e7eb703f 170static int hw_dev_close(int dev_index)
6239c175 171{
17e1afcb 172 /* Avoid compiler warnings. */
bb7ef793 173 (void)dev_index;
6239c175
UH
174
175 /* Nothing needed so far. */
697785d1
UH
176
177 return SR_OK;
6239c175
UH
178}
179
57ab7d9f 180static int hw_cleanup(void)
6239c175
UH
181{
182 /* Nothing needed so far. */
57ab7d9f 183 return SR_OK;
6239c175
UH
184}
185
5097b0d0 186static void *hw_dev_info_get(int dev_index, int dev_info_id)
6239c175 187{
d68e2d1a 188 struct sr_dev_inst *sdi;
85b5af06
UH
189 void *info = NULL;
190
bb7ef793 191 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
c03ed397 192 sr_err("demo: %s: sdi was NULL", __func__);
85b5af06 193 return NULL;
c03ed397 194 }
85b5af06 195
bb7ef793 196 switch (dev_info_id) {
1d9a8a5f 197 case SR_DI_INST:
85b5af06 198 info = sdi;
6239c175 199 break;
5a2326a7 200 case SR_DI_NUM_PROBES:
6239c175
UH
201 info = GINT_TO_POINTER(NUM_PROBES);
202 break;
464d12c7
KS
203 case SR_DI_PROBE_NAMES:
204 info = probe_names;
205 break;
4bfbf9fc
BV
206 case SR_DI_SAMPLERATES:
207 info = &samplerates;
208 break;
5a2326a7 209 case SR_DI_CUR_SAMPLERATE:
6239c175
UH
210 info = &cur_samplerate;
211 break;
5a2326a7 212 case SR_DI_PATTERNMODES:
c8f4624d 213 info = &pattern_strings;
e15f48c2 214 break;
6239c175
UH
215 }
216
217 return info;
218}
219
e7eb703f 220static int hw_dev_status_get(int dev_index)
6239c175 221{
17e1afcb 222 /* Avoid compiler warnings. */
bb7ef793 223 (void)dev_index;
5096c6a6 224
5a2326a7 225 return SR_ST_ACTIVE;
6239c175
UH
226}
227
ffedd0bf 228static int *hw_hwcap_get_all(void)
6239c175 229{
ffedd0bf 230 return hwcaps;
6239c175
UH
231}
232
a9a245b4 233static int hw_dev_config_set(int dev_index, int hwcap, void *value)
6239c175
UH
234{
235 int ret;
e15f48c2 236 char *stropt;
6239c175 237
17e1afcb 238 /* Avoid compiler warnings. */
bb7ef793 239 (void)dev_index;
6239c175 240
ffedd0bf 241 if (hwcap == SR_HWCAP_PROBECONFIG) {
d81d2933
BV
242 /* Nothing to do, but must be supported */
243 ret = SR_OK;
ffedd0bf 244 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
68c12597 245 cur_samplerate = *(uint64_t *)value;
6f422264
UH
246 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
247 cur_samplerate);
e46b8fb1 248 ret = SR_OK;
ffedd0bf 249 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
68c12597 250 limit_samples = *(uint64_t *)value;
6f422264
UH
251 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
252 limit_samples);
e46b8fb1 253 ret = SR_OK;
ffedd0bf 254 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
68c12597 255 limit_msec = *(uint64_t *)value;
6f422264
UH
256 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
257 limit_msec);
e46b8fb1 258 ret = SR_OK;
ffedd0bf 259 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
e15f48c2 260 stropt = value;
c03ed397
UH
261 ret = SR_OK;
262 if (!strcmp(stropt, "sigrok")) {
263 default_pattern = PATTERN_SIGROK;
264 } else if (!strcmp(stropt, "random")) {
c8f4624d 265 default_pattern = PATTERN_RANDOM;
e15f48c2 266 } else if (!strcmp(stropt, "incremental")) {
c8f4624d 267 default_pattern = PATTERN_INC;
c03ed397
UH
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;
e15f48c2 272 } else {
e46b8fb1 273 ret = SR_ERR;
e15f48c2 274 }
c8f4624d
UH
275 sr_dbg("demo: %s: setting pattern to %d", __func__,
276 default_pattern);
6239c175 277 } else {
e46b8fb1 278 ret = SR_ERR;
6239c175
UH
279 }
280
281 return ret;
282}
283
5096c6a6 284static void samples_generator(uint8_t *buf, uint64_t size, void *data)
85b5af06 285{
cddd1c5f 286 static uint64_t p = 0;
85b5af06 287 struct databag *mydata = data;
cddd1c5f 288 uint64_t i;
85b5af06 289
c03ed397 290 /* TODO: Needed? */
5096c6a6 291 memset(buf, 0, size);
85b5af06
UH
292
293 switch (mydata->sample_generator) {
c03ed397 294 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 295 for (i = 0; i < size; i++) {
c8f4624d 296 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
297 if (++p == 64)
298 p = 0;
299 }
300 break;
c8f4624d 301 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
302 for (i = 0; i < size; i++)
303 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 304 break;
c8f4624d 305 case PATTERN_INC: /* Simple increment */
5096c6a6 306 for (i = 0; i < size; i++)
85b5af06
UH
307 *(buf + i) = i;
308 break;
c03ed397 309 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 310 memset(buf, 0x00, size);
c03ed397
UH
311 break;
312 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 313 memset(buf, 0xff, size);
c03ed397
UH
314 break;
315 default:
316 /* TODO: Error handling. */
317 break;
85b5af06
UH
318 }
319}
320
321/* Thread function */
322static void thread_func(void *data)
323{
324 struct databag *mydata = data;
325 uint8_t buf[BUFSIZE];
326 uint64_t nb_to_send = 0;
d35aaf02 327 int bytes_written;
1924f59f
HE
328 double time_cur, time_last, time_diff;
329
330 time_last = g_timer_elapsed(mydata->timer, NULL);
85b5af06
UH
331
332 while (thread_running) {
1924f59f
HE
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
c03ed397 341 if (limit_samples) {
1924f59f 342 nb_to_send = MIN(nb_to_send,
c03ed397
UH
343 limit_samples - mydata->samples_counter);
344 }
1924f59f
HE
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;
070befcd
BV
352
353 g_io_channel_write_chars(channels[1], (gchar *)&buf,
c03ed397 354 nb_to_send, (gsize *)&bytes_written, NULL);
b9cc3629
BV
355 }
356
1924f59f
HE
357 /* Check if we're done. */
358 if ((limit_msec && time_cur * 1000 > limit_msec) ||
359 (limit_samples && mydata->samples_counter >= limit_samples))
360 {
85b5af06
UH
361 close(mydata->pipe_fds[1]);
362 thread_running = 0;
85b5af06
UH
363 }
364
1924f59f 365 g_usleep(10);
85b5af06
UH
366 }
367}
368
369/* Callback handling data */
9c939c51 370static int receive_data(int fd, int revents, void *session_data)
85b5af06 371{
b9c735a2 372 struct sr_datafeed_packet packet;
9c939c51
BV
373 struct sr_datafeed_logic logic;
374 static uint64_t samples_received = 0;
375 unsigned char c[BUFSIZE];
108a5bfb 376 gsize z;
1924f59f 377
26ce0bbf 378 /* Avoid compiler warnings. */
cb93f8a9
UH
379 (void)fd;
380 (void)revents;
1924f59f
HE
381
382 do {
383 g_io_channel_read_chars(channels[0],
070befcd 384 (gchar *)&c, BUFSIZE, &z, NULL);
1924f59f
HE
385
386 if (z > 0) {
5a2326a7 387 packet.type = SR_DF_LOGIC;
9c939c51 388 packet.payload = &logic;
9c939c51
BV
389 logic.length = z;
390 logic.unitsize = 1;
391 logic.data = c;
392 sr_session_bus(session_data, &packet);
393 samples_received += z;
1924f59f
HE
394 }
395 } while (z > 0);
85b5af06 396
c03ed397
UH
397 if (!thread_running && z <= 0) {
398 /* Make sure we don't receive more packets. */
1924f59f 399 g_io_channel_close(channels[0]);
d35aaf02 400
1924f59f 401 /* Send last packet. */
5a2326a7 402 packet.type = SR_DF_END;
9c939c51 403 sr_session_bus(session_data, &packet);
1924f59f
HE
404
405 return FALSE;
85b5af06 406 }
1924f59f 407
85b5af06
UH
408 return TRUE;
409}
410
69040b7c 411static int hw_dev_acquisition_start(int dev_index, gpointer session_data)
6239c175 412{
b9c735a2
UH
413 struct sr_datafeed_packet *packet;
414 struct sr_datafeed_header *header;
85b5af06 415 struct databag *mydata;
6239c175 416
27a3a6fe
UH
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__);
e46b8fb1 420 return SR_ERR_MALLOC;
27a3a6fe 421 }
85b5af06 422
c8f4624d 423 mydata->sample_generator = default_pattern;
9c939c51 424 mydata->session_data = session_data;
bb7ef793 425 mydata->dev_index = dev_index;
85b5af06 426 mydata->samples_counter = 0;
85b5af06 427
c03ed397
UH
428 if (pipe(mydata->pipe_fds)) {
429 /* TODO: Better error message. */
430 sr_err("demo: %s: pipe() failed", __func__);
e46b8fb1 431 return SR_ERR;
c03ed397 432 }
85b5af06 433
d35aaf02
UH
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
6f1be0a2 445 sr_source_add(mydata->pipe_fds[0], G_IO_IN | G_IO_ERR, 40,
9c939c51 446 receive_data, session_data);
85b5af06
UH
447
448 /* Run the demo thread. */
449 g_thread_init(NULL);
c03ed397 450 /* This must to be done between g_thread_init() & g_thread_create(). */
1924f59f 451 mydata->timer = g_timer_new();
85b5af06
UH
452 thread_running = 1;
453 my_thread =
454 g_thread_create((GThreadFunc)thread_func, mydata, TRUE, NULL);
c03ed397
UH
455 if (!my_thread) {
456 sr_err("demo: %s: g_thread_create failed", __func__);
457 return SR_ERR; /* TODO */
458 }
6239c175 459
27a3a6fe
UH
460 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
461 sr_err("demo: %s: packet malloc failed", __func__);
e46b8fb1 462 return SR_ERR_MALLOC;
27a3a6fe
UH
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 }
6239c175 469
5a2326a7 470 packet->type = SR_DF_HEADER;
9c939c51 471 packet->payload = header;
6239c175
UH
472 header->feed_version = 1;
473 gettimeofday(&header->starttime, NULL);
474 header->samplerate = cur_samplerate;
c2616fb9 475 header->num_logic_probes = NUM_PROBES;
9c939c51 476 sr_session_bus(session_data, packet);
27a3a6fe
UH
477 g_free(header);
478 g_free(packet);
6239c175 479
e46b8fb1 480 return SR_OK;
6239c175
UH
481}
482
69040b7c 483static int hw_dev_acquisition_stop(int dev_index, gpointer session_data)
6239c175 484{
17e1afcb 485 /* Avoid compiler warnings. */
bb7ef793 486 (void)dev_index;
cb93f8a9 487 (void)session_data;
6239c175 488
1924f59f
HE
489 /* Stop generate thread. */
490 thread_running = 0;
3010f21c
UH
491
492 return SR_OK;
6239c175
UH
493}
494
bb7ef793 495SR_PRIV struct sr_dev_plugin demo_plugin_info = {
e519ba86
UH
496 .name = "demo",
497 .longname = "Demo driver and pattern generator",
498 .api_version = 1,
499 .init = hw_init,
500 .cleanup = hw_cleanup,
e7eb703f
UH
501 .dev_open = hw_dev_open,
502 .dev_close = hw_dev_close,
5097b0d0 503 .dev_info_get = hw_dev_info_get,
e7eb703f 504 .dev_status_get = hw_dev_status_get,
ffedd0bf 505 .hwcap_get_all = hw_hwcap_get_all,
a9a245b4 506 .dev_config_set = hw_dev_config_set,
69040b7c
UH
507 .dev_acquisition_start = hw_dev_acquisition_start,
508 .dev_acquisition_stop = hw_dev_acquisition_stop,
6239c175 509};