]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
zeroplus-logic-cube: init and scan fixes
[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
45c59c8b
BV
30#include "libsigrok.h"
31#include "libsigrok-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. */
d35aaf02 67
455b26ed 68struct context {
e15f48c2 69 int pipe_fds[2];
249ae2be 70 GIOChannel *channels[2];
e15f48c2
BV
71 uint8_t sample_generator;
72 uint8_t thread_running;
73 uint64_t samples_counter;
bb7ef793 74 int dev_index;
3cd3a20b 75 void *session_dev_id;
b9cc3629 76 GTimer *timer;
e15f48c2 77};
85b5af06 78
915f7cc8 79static const 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
a533743d 89static const 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
d261dbbf 105/* We name the probes 0-7 on our demo driver. */
464d12c7
KS
106static const char *probe_names[NUM_PROBES + 1] = {
107 "0",
108 "1",
109 "2",
110 "3",
111 "4",
112 "5",
113 "6",
114 "7",
115 NULL,
116};
117
c8f4624d 118static uint8_t pattern_sigrok[] = {
917e0e71
BV
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,
127};
128
ea9cfed7
UH
129/* Private, per-device-instance driver context. */
130/* TODO: struct context as with the other drivers. */
131
e7eb703f 132/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
dcf03d6d
BV
133SR_PRIV struct sr_dev_driver demo_driver_info;
134static struct sr_dev_driver *ddi = &demo_driver_info;
59df0c77 135static uint64_t cur_samplerate = SR_KHZ(200);
b9cc3629
BV
136static uint64_t limit_samples = 0;
137static uint64_t limit_msec = 0;
c8f4624d 138static int default_pattern = PATTERN_SIGROK;
b9cc3629
BV
139static GThread *my_thread;
140static int thread_running;
6239c175 141
3cd3a20b 142static int hw_dev_acquisition_stop(int dev_index, void *cb_data);
6239c175 143
40dda2c3 144static int hw_init(void)
61136ea6
BV
145{
146
147 /* Nothing to do. */
148
149 return SR_OK;
150}
151
152static int hw_scan(void)
6239c175 153{
d68e2d1a 154 struct sr_dev_inst *sdi;
85b5af06 155
d3683c42 156 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 157 if (!sdi) {
d68e2d1a 158 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
85b5af06 159 return 0;
c03ed397 160 }
e15f48c2 161
dcf03d6d 162 ddi->instances = g_slist_append(ddi->instances, sdi);
85b5af06
UH
163
164 return 1;
6239c175
UH
165}
166
e7eb703f 167static int hw_dev_open(int dev_index)
6239c175 168{
17e1afcb 169 /* Avoid compiler warnings. */
bb7ef793 170 (void)dev_index;
6239c175
UH
171
172 /* Nothing needed so far. */
697785d1 173
e46b8fb1 174 return SR_OK;
6239c175
UH
175}
176
e7eb703f 177static int hw_dev_close(int dev_index)
6239c175 178{
17e1afcb 179 /* Avoid compiler warnings. */
bb7ef793 180 (void)dev_index;
6239c175
UH
181
182 /* Nothing needed so far. */
697785d1
UH
183
184 return SR_OK;
6239c175
UH
185}
186
57ab7d9f 187static int hw_cleanup(void)
6239c175
UH
188{
189 /* Nothing needed so far. */
57ab7d9f 190 return SR_OK;
6239c175
UH
191}
192
b7f578be 193static const void *hw_dev_info_get(int dev_index, int dev_info_id)
6239c175 194{
d68e2d1a 195 struct sr_dev_inst *sdi;
b7f578be 196 const void *info = NULL;
85b5af06 197
dcf03d6d 198 if (!(sdi = sr_dev_inst_get(ddi->instances, dev_index))) {
c03ed397 199 sr_err("demo: %s: sdi was NULL", __func__);
85b5af06 200 return NULL;
c03ed397 201 }
85b5af06 202
bb7ef793 203 switch (dev_info_id) {
1d9a8a5f 204 case SR_DI_INST:
85b5af06 205 info = sdi;
6239c175 206 break;
5a2326a7 207 case SR_DI_NUM_PROBES:
6239c175
UH
208 info = GINT_TO_POINTER(NUM_PROBES);
209 break;
464d12c7
KS
210 case SR_DI_PROBE_NAMES:
211 info = probe_names;
212 break;
4bfbf9fc
BV
213 case SR_DI_SAMPLERATES:
214 info = &samplerates;
215 break;
5a2326a7 216 case SR_DI_CUR_SAMPLERATE:
6239c175
UH
217 info = &cur_samplerate;
218 break;
eb0a3731 219 case SR_DI_PATTERNS:
c8f4624d 220 info = &pattern_strings;
e15f48c2 221 break;
6239c175
UH
222 }
223
224 return info;
225}
226
e7eb703f 227static int hw_dev_status_get(int dev_index)
6239c175 228{
17e1afcb 229 /* Avoid compiler warnings. */
bb7ef793 230 (void)dev_index;
5096c6a6 231
5a2326a7 232 return SR_ST_ACTIVE;
6239c175
UH
233}
234
915f7cc8 235static const int *hw_hwcap_get_all(void)
6239c175 236{
ffedd0bf 237 return hwcaps;
6239c175
UH
238}
239
1b79df2f 240static int hw_dev_config_set(int dev_index, int hwcap, const void *value)
6239c175
UH
241{
242 int ret;
1b79df2f 243 const char *stropt;
6239c175 244
17e1afcb 245 /* Avoid compiler warnings. */
bb7ef793 246 (void)dev_index;
6239c175 247
ffedd0bf 248 if (hwcap == SR_HWCAP_PROBECONFIG) {
d81d2933
BV
249 /* Nothing to do, but must be supported */
250 ret = SR_OK;
ffedd0bf 251 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
1b79df2f 252 cur_samplerate = *(const uint64_t *)value;
6f422264
UH
253 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
254 cur_samplerate);
e46b8fb1 255 ret = SR_OK;
ffedd0bf 256 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
8489264f 257 limit_msec = 0;
1b79df2f 258 limit_samples = *(const uint64_t *)value;
6f422264
UH
259 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
260 limit_samples);
e46b8fb1 261 ret = SR_OK;
ffedd0bf 262 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
1b79df2f 263 limit_msec = *(const uint64_t *)value;
8489264f 264 limit_samples = 0;
6f422264
UH
265 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
266 limit_msec);
e46b8fb1 267 ret = SR_OK;
ffedd0bf 268 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
e15f48c2 269 stropt = value;
c03ed397
UH
270 ret = SR_OK;
271 if (!strcmp(stropt, "sigrok")) {
272 default_pattern = PATTERN_SIGROK;
273 } else if (!strcmp(stropt, "random")) {
c8f4624d 274 default_pattern = PATTERN_RANDOM;
e15f48c2 275 } else if (!strcmp(stropt, "incremental")) {
c8f4624d 276 default_pattern = PATTERN_INC;
c03ed397
UH
277 } else if (!strcmp(stropt, "all-low")) {
278 default_pattern = PATTERN_ALL_LOW;
279 } else if (!strcmp(stropt, "all-high")) {
280 default_pattern = PATTERN_ALL_HIGH;
e15f48c2 281 } else {
e46b8fb1 282 ret = SR_ERR;
e15f48c2 283 }
c8f4624d
UH
284 sr_dbg("demo: %s: setting pattern to %d", __func__,
285 default_pattern);
6239c175 286 } else {
e46b8fb1 287 ret = SR_ERR;
6239c175
UH
288 }
289
290 return ret;
291}
292
5096c6a6 293static void samples_generator(uint8_t *buf, uint64_t size, void *data)
85b5af06 294{
cddd1c5f 295 static uint64_t p = 0;
455b26ed 296 struct context *ctx = data;
cddd1c5f 297 uint64_t i;
85b5af06 298
c03ed397 299 /* TODO: Needed? */
5096c6a6 300 memset(buf, 0, size);
85b5af06 301
ab331b67 302 switch (ctx->sample_generator) {
c03ed397 303 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 304 for (i = 0; i < size; i++) {
c8f4624d 305 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
306 if (++p == 64)
307 p = 0;
308 }
309 break;
c8f4624d 310 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
311 for (i = 0; i < size; i++)
312 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 313 break;
c8f4624d 314 case PATTERN_INC: /* Simple increment */
5096c6a6 315 for (i = 0; i < size; i++)
85b5af06
UH
316 *(buf + i) = i;
317 break;
c03ed397 318 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 319 memset(buf, 0x00, size);
c03ed397
UH
320 break;
321 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 322 memset(buf, 0xff, size);
c03ed397
UH
323 break;
324 default:
0abee507 325 sr_err("demo: %s: unknown pattern %d", __func__,
ab331b67 326 ctx->sample_generator);
c03ed397 327 break;
85b5af06
UH
328 }
329}
330
331/* Thread function */
332static void thread_func(void *data)
333{
455b26ed 334 struct context *ctx = data;
85b5af06
UH
335 uint8_t buf[BUFSIZE];
336 uint64_t nb_to_send = 0;
d35aaf02 337 int bytes_written;
1924f59f
HE
338 double time_cur, time_last, time_diff;
339
ab331b67 340 time_last = g_timer_elapsed(ctx->timer, NULL);
85b5af06
UH
341
342 while (thread_running) {
1924f59f 343 /* Rate control */
ab331b67 344 time_cur = g_timer_elapsed(ctx->timer, NULL);
1924f59f
HE
345
346 time_diff = time_cur - time_last;
347 time_last = time_cur;
348
349 nb_to_send = cur_samplerate * time_diff;
350
c03ed397 351 if (limit_samples) {
1924f59f 352 nb_to_send = MIN(nb_to_send,
ab331b67 353 limit_samples - ctx->samples_counter);
c03ed397 354 }
1924f59f
HE
355
356 /* Make sure we don't overflow. */
357 nb_to_send = MIN(nb_to_send, BUFSIZE);
358
359 if (nb_to_send) {
360 samples_generator(buf, nb_to_send, data);
ab331b67 361 ctx->samples_counter += nb_to_send;
070befcd 362
249ae2be 363 g_io_channel_write_chars(ctx->channels[1], (gchar *)&buf,
c03ed397 364 nb_to_send, (gsize *)&bytes_written, NULL);
b9cc3629
BV
365 }
366
1924f59f
HE
367 /* Check if we're done. */
368 if ((limit_msec && time_cur * 1000 > limit_msec) ||
ab331b67 369 (limit_samples && ctx->samples_counter >= limit_samples))
1924f59f 370 {
ab331b67 371 close(ctx->pipe_fds[1]);
85b5af06 372 thread_running = 0;
85b5af06
UH
373 }
374
1924f59f 375 g_usleep(10);
85b5af06
UH
376 }
377}
378
379/* Callback handling data */
1f9813eb 380static int receive_data(int fd, int revents, void *cb_data)
85b5af06 381{
249ae2be 382 struct context *ctx = cb_data;
b9c735a2 383 struct sr_datafeed_packet packet;
9c939c51
BV
384 struct sr_datafeed_logic logic;
385 static uint64_t samples_received = 0;
386 unsigned char c[BUFSIZE];
108a5bfb 387 gsize z;
1924f59f 388
26ce0bbf 389 /* Avoid compiler warnings. */
cb93f8a9
UH
390 (void)fd;
391 (void)revents;
1924f59f
HE
392
393 do {
249ae2be 394 g_io_channel_read_chars(ctx->channels[0],
070befcd 395 (gchar *)&c, BUFSIZE, &z, NULL);
1924f59f
HE
396
397 if (z > 0) {
5a2326a7 398 packet.type = SR_DF_LOGIC;
9c939c51 399 packet.payload = &logic;
9c939c51
BV
400 logic.length = z;
401 logic.unitsize = 1;
402 logic.data = c;
249ae2be 403 sr_session_send(ctx->session_dev_id, &packet);
9c939c51 404 samples_received += z;
1924f59f
HE
405 }
406 } while (z > 0);
85b5af06 407
c03ed397
UH
408 if (!thread_running && z <= 0) {
409 /* Make sure we don't receive more packets. */
249ae2be 410 g_io_channel_shutdown(ctx->channels[0], FALSE, NULL);
d35aaf02 411
1924f59f 412 /* Send last packet. */
5a2326a7 413 packet.type = SR_DF_END;
249ae2be 414 sr_session_send(ctx->session_dev_id, &packet);
1924f59f
HE
415
416 return FALSE;
85b5af06 417 }
1924f59f 418
85b5af06
UH
419 return TRUE;
420}
421
3cd3a20b 422static int hw_dev_acquisition_start(int dev_index, void *cb_data)
6239c175 423{
b9c735a2
UH
424 struct sr_datafeed_packet *packet;
425 struct sr_datafeed_header *header;
f366e86c 426 struct sr_datafeed_meta_logic meta;
455b26ed 427 struct context *ctx;
6239c175 428
ab331b67 429 /* TODO: 'ctx' is never g_free()'d? */
455b26ed 430 if (!(ctx = g_try_malloc(sizeof(struct context)))) {
ab331b67 431 sr_err("demo: %s: ctx malloc failed", __func__);
e46b8fb1 432 return SR_ERR_MALLOC;
27a3a6fe 433 }
85b5af06 434
ab331b67
UH
435 ctx->sample_generator = default_pattern;
436 ctx->session_dev_id = cb_data;
437 ctx->dev_index = dev_index;
438 ctx->samples_counter = 0;
85b5af06 439
ab331b67 440 if (pipe(ctx->pipe_fds)) {
c03ed397
UH
441 /* TODO: Better error message. */
442 sr_err("demo: %s: pipe() failed", __func__);
e46b8fb1 443 return SR_ERR;
c03ed397 444 }
85b5af06 445
249ae2be
LPC
446 ctx->channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
447 ctx->channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
d35aaf02 448
e6e8f8e0
LPC
449 g_io_channel_set_flags(ctx->channels[0], G_IO_FLAG_NONBLOCK, NULL);
450
d35aaf02 451 /* Set channel encoding to binary (default is UTF-8). */
249ae2be
LPC
452 g_io_channel_set_encoding(ctx->channels[0], NULL, NULL);
453 g_io_channel_set_encoding(ctx->channels[1], NULL, NULL);
d35aaf02
UH
454
455 /* Make channels to unbuffered. */
249ae2be
LPC
456 g_io_channel_set_buffered(ctx->channels[0], FALSE);
457 g_io_channel_set_buffered(ctx->channels[1], FALSE);
d35aaf02 458
249ae2be
LPC
459 sr_session_source_add_channel(ctx->channels[0], G_IO_IN | G_IO_ERR,
460 40, receive_data, ctx);
85b5af06
UH
461
462 /* Run the demo thread. */
463 g_thread_init(NULL);
c03ed397 464 /* This must to be done between g_thread_init() & g_thread_create(). */
ab331b67 465 ctx->timer = g_timer_new();
85b5af06
UH
466 thread_running = 1;
467 my_thread =
ab331b67 468 g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
c03ed397
UH
469 if (!my_thread) {
470 sr_err("demo: %s: g_thread_create failed", __func__);
471 return SR_ERR; /* TODO */
472 }
6239c175 473
27a3a6fe
UH
474 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
475 sr_err("demo: %s: packet malloc failed", __func__);
e46b8fb1 476 return SR_ERR_MALLOC;
27a3a6fe
UH
477 }
478
479 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
480 sr_err("demo: %s: header malloc failed", __func__);
481 return SR_ERR_MALLOC;
482 }
6239c175 483
5a2326a7 484 packet->type = SR_DF_HEADER;
9c939c51 485 packet->payload = header;
6239c175
UH
486 header->feed_version = 1;
487 gettimeofday(&header->starttime, NULL);
ab331b67 488 sr_session_send(ctx->session_dev_id, packet);
f366e86c
BV
489
490 /* Send metadata about the SR_DF_LOGIC packets to come. */
491 packet->type = SR_DF_META_LOGIC;
492 packet->payload = &meta;
493 meta.samplerate = cur_samplerate;
494 meta.num_probes = NUM_PROBES;
495 sr_session_send(ctx->session_dev_id, packet);
496
27a3a6fe
UH
497 g_free(header);
498 g_free(packet);
6239c175 499
e46b8fb1 500 return SR_OK;
6239c175
UH
501}
502
3cd3a20b
UH
503/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
504static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
6239c175 505{
17e1afcb 506 /* Avoid compiler warnings. */
bb7ef793 507 (void)dev_index;
3cd3a20b 508 (void)cb_data;
6239c175 509
1924f59f
HE
510 /* Stop generate thread. */
511 thread_running = 0;
3010f21c
UH
512
513 return SR_OK;
6239c175
UH
514}
515
c09f0b57 516SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
517 .name = "demo",
518 .longname = "Demo driver and pattern generator",
519 .api_version = 1,
520 .init = hw_init,
521 .cleanup = hw_cleanup,
61136ea6 522 .scan = hw_scan,
e7eb703f
UH
523 .dev_open = hw_dev_open,
524 .dev_close = hw_dev_close,
5097b0d0 525 .dev_info_get = hw_dev_info_get,
e7eb703f 526 .dev_status_get = hw_dev_status_get,
ffedd0bf 527 .hwcap_get_all = hw_hwcap_get_all,
a9a245b4 528 .dev_config_set = hw_dev_config_set,
69040b7c
UH
529 .dev_acquisition_start = hw_dev_acquisition_start,
530 .dev_acquisition_stop = hw_dev_acquisition_stop,
dcf03d6d 531 .instances = NULL,
6239c175 532};