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