]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
ols: add swap channels feature
[libsigrok.git] / hardware / openbench-logic-sniffer / api.c
CommitLineData
0aba65da 1/*
50985c20 2 * This file is part of the libsigrok project.
0aba65da 3 *
13d8e03c 4 * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
0aba65da
UH
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "protocol.h"
21
22#define SERIALCOMM "115200/8n1"
23
e46aa4f6 24static const int32_t hwopts[] = {
1953564a
BV
25 SR_CONF_CONN,
26 SR_CONF_SERIALCOMM,
aeabd308
UH
27};
28
e46aa4f6 29static const int32_t hwcaps[] = {
1953564a
BV
30 SR_CONF_LOGIC_ANALYZER,
31 SR_CONF_SAMPLERATE,
0c05591a 32 SR_CONF_TRIGGER_TYPE,
1953564a
BV
33 SR_CONF_CAPTURE_RATIO,
34 SR_CONF_LIMIT_SAMPLES,
eb1b610b 35 SR_CONF_EXTERNAL_CLOCK,
967760a8 36 SR_CONF_PATTERN_MODE,
7b0a57fd 37 SR_CONF_SWAP,
1953564a 38 SR_CONF_RLE,
0aba65da
UH
39};
40
967760a8
MR
41#define STR_PATTERN_EXTERNAL "external"
42#define STR_PATTERN_INTERNAL "internal"
43
44/* Supported methods of test pattern outputs */
45enum {
46 /**
47 * Capture pins 31:16 (unbuffered wing) output a test pattern
48 * that can captured on pins 0:15.
49 */
50 PATTERN_EXTERNAL,
51
52 /** Route test pattern internally to capture buffer. */
53 PATTERN_INTERNAL,
54};
55
0aba65da
UH
56/* Probes are numbered 0-31 (on the PCB silkscreen). */
57SR_PRIV const char *ols_probe_names[NUM_PROBES + 1] = {
78693401
UH
58 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
59 "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
60 "24", "25", "26", "27", "28", "29", "30", "31",
0aba65da
UH
61 NULL,
62};
63
d3b38ad3 64/* Default supported samplerates, can be overridden by device metadata. */
e46aa4f6
BV
65static const uint64_t samplerates[] = {
66 SR_HZ(10),
67 SR_MHZ(200),
68 SR_HZ(1),
0aba65da
UH
69};
70
71SR_PRIV struct sr_dev_driver ols_driver_info;
72static struct sr_dev_driver *di = &ols_driver_info;
73
eea49cf1
UH
74static int dev_clear(void)
75{
76 return std_dev_clear(di, NULL);
77}
78
03f4de8c 79static int init(struct sr_context *sr_ctx)
0aba65da 80{
f6beaac5 81 return std_init(sr_ctx, di, LOG_PREFIX);
0aba65da
UH
82}
83
03f4de8c 84static GSList *scan(GSList *options)
0aba65da 85{
1987b8d6 86 struct sr_config *src;
0aba65da
UH
87 struct sr_dev_inst *sdi;
88 struct drv_context *drvc;
89 struct dev_context *devc;
90 struct sr_probe *probe;
91 struct sr_serial_dev_inst *serial;
92 GPollFD probefd;
93 GSList *l, *devices;
94 int ret, i;
95 const char *conn, *serialcomm;
96 char buf[8];
97
0aba65da 98 drvc = di->priv;
4b97c74e 99
0aba65da
UH
100 devices = NULL;
101
102 conn = serialcomm = NULL;
103 for (l = options; l; l = l->next) {
1987b8d6
BV
104 src = l->data;
105 switch (src->key) {
1953564a 106 case SR_CONF_CONN:
e46aa4f6 107 conn = g_variant_get_string(src->data, NULL);
0aba65da 108 break;
1953564a 109 case SR_CONF_SERIALCOMM:
e46aa4f6 110 serialcomm = g_variant_get_string(src->data, NULL);
0aba65da
UH
111 break;
112 }
113 }
114 if (!conn)
115 return NULL;
116
117 if (serialcomm == NULL)
118 serialcomm = SERIALCOMM;
119
120 if (!(serial = sr_serial_dev_inst_new(conn, serialcomm)))
121 return NULL;
122
123 /* The discovery procedure is like this: first send the Reset
124 * command (0x00) 5 times, since the device could be anywhere
125 * in a 5-byte command. Then send the ID command (0x02).
126 * If the device responds with 4 bytes ("OLS1" or "SLA1"), we
127 * have a match.
128 */
129 sr_info("Probing %s.", conn);
130 if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
131 return NULL;
132
133 ret = SR_OK;
134 for (i = 0; i < 5; i++) {
135 if ((ret = send_shortcommand(serial, CMD_RESET)) != SR_OK) {
136 sr_err("Port %s is not writable.", conn);
137 break;
138 }
139 }
140 if (ret != SR_OK) {
141 serial_close(serial);
142 sr_err("Could not use port %s. Quitting.", conn);
143 return NULL;
144 }
145 send_shortcommand(serial, CMD_ID);
146
147 /* Wait 10ms for a response. */
148 g_usleep(10000);
149
150 probefd.fd = serial->fd;
151 probefd.events = G_IO_IN;
152 g_poll(&probefd, 1, 1);
153
154 if (probefd.revents != G_IO_IN)
155 return NULL;
156 if (serial_read(serial, buf, 4) != 4)
157 return NULL;
158 if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4))
159 return NULL;
160
161 /* Definitely using the OLS protocol, check if it supports
162 * the metadata command.
163 */
164 send_shortcommand(serial, CMD_METADATA);
165 if (g_poll(&probefd, 1, 10) > 0) {
166 /* Got metadata. */
167 sdi = get_metadata(serial);
168 sdi->index = 0;
169 devc = sdi->priv;
170 } else {
171 /* Not an OLS -- some other board that uses the sump protocol. */
72cd99b8 172 sr_info("Device does not support metadata.");
0aba65da
UH
173 sdi = sr_dev_inst_new(0, SR_ST_INACTIVE,
174 "Sump", "Logic Analyzer", "v1.0");
175 sdi->driver = di;
0aba65da
UH
176 for (i = 0; i < 32; i++) {
177 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
178 ols_probe_names[i])))
179 return 0;
180 sdi->probes = g_slist_append(sdi->probes, probe);
181 }
bf256783 182 devc = ols_dev_new();
0aba65da
UH
183 sdi->priv = devc;
184 }
bf256783
BV
185 /* Configure samplerate and divider. */
186 if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK)
187 sr_dbg("Failed to set default samplerate (%"PRIu64").",
188 DEFAULT_SAMPLERATE);
189 /* Clear trigger masks, values and stages. */
190 ols_configure_probes(sdi);
459a0f26
BV
191 sdi->inst_type = SR_INST_SERIAL;
192 sdi->conn = serial;
bf256783 193
0aba65da
UH
194 drvc->instances = g_slist_append(drvc->instances, sdi);
195 devices = g_slist_append(devices, sdi);
196
197 serial_close(serial);
198
199 return devices;
200}
201
03f4de8c 202static GSList *dev_list(void)
0aba65da 203{
0e94d524 204 return ((struct drv_context *)(di->priv))->instances;
0aba65da
UH
205}
206
03f4de8c 207static int dev_open(struct sr_dev_inst *sdi)
0aba65da 208{
459a0f26 209 struct sr_serial_dev_inst *serial;
0aba65da 210
459a0f26
BV
211 serial = sdi->conn;
212 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
0aba65da
UH
213 return SR_ERR;
214
215 sdi->status = SR_ST_ACTIVE;
216
217 return SR_OK;
218}
219
03f4de8c 220static int dev_close(struct sr_dev_inst *sdi)
0aba65da 221{
459a0f26 222 struct sr_serial_dev_inst *serial;
0aba65da 223
459a0f26
BV
224 serial = sdi->conn;
225 if (serial && serial->fd != -1) {
226 serial_close(serial);
0aba65da
UH
227 sdi->status = SR_ST_INACTIVE;
228 }
229
230 return SR_OK;
231}
232
eea49cf1 233static int cleanup(void)
0aba65da 234{
eea49cf1 235 return dev_clear();
0aba65da
UH
236}
237
e46aa4f6 238static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
0aba65da
UH
239{
240 struct dev_context *devc;
241
0c05591a
BV
242 if (!sdi)
243 return SR_ERR_ARG;
244
245 devc = sdi->priv;
035a1078 246 switch (id) {
123e1313 247 case SR_CONF_SAMPLERATE:
0c05591a
BV
248 *data = g_variant_new_uint64(devc->cur_samplerate);
249 break;
250 case SR_CONF_CAPTURE_RATIO:
251 *data = g_variant_new_uint64(devc->capture_ratio);
252 break;
253 case SR_CONF_LIMIT_SAMPLES:
254 *data = g_variant_new_uint64(devc->limit_samples);
255 break;
967760a8
MR
256 case SR_CONF_PATTERN_MODE:
257 if (devc->flag_reg & FLAG_EXTERNAL_TEST_MODE)
258 *data = g_variant_new_string(STR_PATTERN_EXTERNAL);
259 else if (devc->flag_reg & FLAG_INTERNAL_TEST_MODE)
260 *data = g_variant_new_string(STR_PATTERN_INTERNAL);
261 break;
0c05591a
BV
262 case SR_CONF_RLE:
263 *data = g_variant_new_boolean(devc->flag_reg & FLAG_RLE ? TRUE : FALSE);
0aba65da
UH
264 break;
265 default:
bd6fbf62 266 return SR_ERR_NA;
0aba65da
UH
267 }
268
269 return SR_OK;
270}
271
e46aa4f6 272static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
0aba65da
UH
273{
274 struct dev_context *devc;
275 int ret;
e46aa4f6 276 uint64_t tmp_u64;
967760a8 277 const char *stropt;
0aba65da 278
e73ffd42
BV
279 if (sdi->status != SR_ST_ACTIVE)
280 return SR_ERR_DEV_CLOSED;
281
0aba65da
UH
282 devc = sdi->priv;
283
035a1078 284 switch (id) {
1953564a 285 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
286 tmp_u64 = g_variant_get_uint64(data);
287 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
288 return SR_ERR_SAMPLERATE;
289 ret = ols_set_samplerate(sdi, g_variant_get_uint64(data));
0aba65da 290 break;
1953564a 291 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
292 tmp_u64 = g_variant_get_uint64(data);
293 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 294 return SR_ERR;
e46aa4f6 295 devc->limit_samples = tmp_u64;
0aba65da
UH
296 ret = SR_OK;
297 break;
1953564a 298 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 299 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da
UH
300 if (devc->capture_ratio < 0 || devc->capture_ratio > 100) {
301 devc->capture_ratio = 0;
302 ret = SR_ERR;
303 } else
304 ret = SR_OK;
305 break;
eb1b610b
MR
306 case SR_CONF_EXTERNAL_CLOCK:
307 if (g_variant_get_boolean(data)) {
308 sr_info("Enabling external clock.");
309 devc->flag_reg |= FLAG_CLOCK_EXTERNAL;
310 } else {
311 sr_info("Disabled external clock.");
312 devc->flag_reg &= ~FLAG_CLOCK_EXTERNAL;
313 }
314 ret = SR_OK;
315 break;
967760a8
MR
316 case SR_CONF_PATTERN_MODE:
317 stropt = g_variant_get_string(data, NULL);
318 ret = SR_OK;
319 if (!strcmp(stropt, STR_PATTERN_INTERNAL)) {
320 sr_info("Enabling internal test mode.");
321 devc->flag_reg |= FLAG_INTERNAL_TEST_MODE;
322 } else if (!strcmp(stropt, STR_PATTERN_EXTERNAL)) {
323 sr_info("Enabling external test mode.");
324 devc->flag_reg |= FLAG_EXTERNAL_TEST_MODE;
325 } else {
326 ret = SR_ERR;
327 }
328 break;
7b0a57fd
MR
329 case SR_CONF_SWAP:
330 if (g_variant_get_boolean(data)) {
331 sr_info("Enabling channel swapping.");
332 devc->flag_reg |= FLAG_SWAP_PROBES;
333 } else {
334 sr_info("Disabling channel swapping.");
335 devc->flag_reg &= ~FLAG_SWAP_PROBES;
336 }
337 ret = SR_OK;
338 break;
339
1953564a 340 case SR_CONF_RLE:
e46aa4f6 341 if (g_variant_get_boolean(data)) {
0aba65da
UH
342 sr_info("Enabling RLE.");
343 devc->flag_reg |= FLAG_RLE;
aeea0572
BV
344 } else {
345 sr_info("Disabling RLE.");
346 devc->flag_reg &= ~FLAG_RLE;
0aba65da
UH
347 }
348 ret = SR_OK;
349 break;
350 default:
bd6fbf62 351 ret = SR_ERR_NA;
0aba65da
UH
352 }
353
354 return ret;
355}
356
e46aa4f6 357static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
a1c743fc 358{
e46aa4f6
BV
359 GVariant *gvar;
360 GVariantBuilder gvb;
a1c743fc
BV
361
362 (void)sdi;
363
364 switch (key) {
0d485e30 365 case SR_CONF_SCAN_OPTIONS:
e46aa4f6
BV
366 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
367 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
0d485e30 368 break;
9a6517d1 369 case SR_CONF_DEVICE_OPTIONS:
e46aa4f6
BV
370 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
371 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 372 break;
a1c743fc 373 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
374 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
375 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
376 ARRAY_SIZE(samplerates), sizeof(uint64_t));
377 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
378 *data = g_variant_builder_end(&gvb);
a1c743fc 379 break;
c50277a6 380 case SR_CONF_TRIGGER_TYPE:
e46aa4f6 381 *data = g_variant_new_string(TRIGGER_TYPE);
c50277a6 382 break;
a1c743fc 383 default:
bd6fbf62 384 return SR_ERR_NA;
a1c743fc
BV
385 }
386
387 return SR_OK;
388}
389
03f4de8c 390static int dev_acquisition_start(const struct sr_dev_inst *sdi,
0aba65da
UH
391 void *cb_data)
392{
0aba65da 393 struct dev_context *devc;
459a0f26 394 struct sr_serial_dev_inst *serial;
0aba65da
UH
395 uint32_t trigger_config[4];
396 uint32_t data;
397 uint16_t readcount, delaycount;
398 uint8_t changrp_mask;
399 int num_channels;
400 int i;
401
e73ffd42
BV
402 if (sdi->status != SR_ST_ACTIVE)
403 return SR_ERR_DEV_CLOSED;
404
0aba65da 405 devc = sdi->priv;
459a0f26 406 serial = sdi->conn;
0aba65da 407
0aba65da
UH
408 if (ols_configure_probes(sdi) != SR_OK) {
409 sr_err("Failed to configure probes.");
410 return SR_ERR;
411 }
412
413 /*
414 * Enable/disable channel groups in the flag register according to the
415 * probe mask. Calculate this here, because num_channels is needed
416 * to limit readcount.
417 */
418 changrp_mask = 0;
419 num_channels = 0;
420 for (i = 0; i < 4; i++) {
421 if (devc->probe_mask & (0xff << (i * 8))) {
422 changrp_mask |= (1 << i);
423 num_channels++;
424 }
425 }
426
427 /*
428 * Limit readcount to prevent reading past the end of the hardware
429 * buffer.
430 */
431 readcount = MIN(devc->max_samples / num_channels, devc->limit_samples) / 4;
432
433 memset(trigger_config, 0, 16);
2e5b73c0 434 trigger_config[devc->num_stages] |= 0x08;
0aba65da
UH
435 if (devc->trigger_mask[0]) {
436 delaycount = readcount * (1 - devc->capture_ratio / 100.0);
437 devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages;
438
459a0f26 439 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_0,
0aba65da
UH
440 reverse32(devc->trigger_mask[0])) != SR_OK)
441 return SR_ERR;
459a0f26 442 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_0,
0aba65da
UH
443 reverse32(devc->trigger_value[0])) != SR_OK)
444 return SR_ERR;
459a0f26 445 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_0,
0aba65da
UH
446 trigger_config[0]) != SR_OK)
447 return SR_ERR;
448
459a0f26 449 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_1,
0aba65da
UH
450 reverse32(devc->trigger_mask[1])) != SR_OK)
451 return SR_ERR;
459a0f26 452 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_1,
0aba65da
UH
453 reverse32(devc->trigger_value[1])) != SR_OK)
454 return SR_ERR;
459a0f26 455 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_1,
0aba65da
UH
456 trigger_config[1]) != SR_OK)
457 return SR_ERR;
458
459a0f26 459 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_2,
0aba65da
UH
460 reverse32(devc->trigger_mask[2])) != SR_OK)
461 return SR_ERR;
459a0f26 462 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_2,
0aba65da
UH
463 reverse32(devc->trigger_value[2])) != SR_OK)
464 return SR_ERR;
459a0f26 465 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_2,
0aba65da
UH
466 trigger_config[2]) != SR_OK)
467 return SR_ERR;
468
459a0f26 469 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_3,
0aba65da
UH
470 reverse32(devc->trigger_mask[3])) != SR_OK)
471 return SR_ERR;
459a0f26 472 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_3,
0aba65da
UH
473 reverse32(devc->trigger_value[3])) != SR_OK)
474 return SR_ERR;
459a0f26 475 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_3,
0aba65da
UH
476 trigger_config[3]) != SR_OK)
477 return SR_ERR;
478 } else {
459a0f26 479 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_0,
0aba65da
UH
480 devc->trigger_mask[0]) != SR_OK)
481 return SR_ERR;
459a0f26 482 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_0,
0aba65da
UH
483 devc->trigger_value[0]) != SR_OK)
484 return SR_ERR;
459a0f26 485 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_0,
0aba65da
UH
486 0x00000008) != SR_OK)
487 return SR_ERR;
488 delaycount = readcount;
489 }
490
491 sr_info("Setting samplerate to %" PRIu64 "Hz (divider %u, "
de524099
MR
492 "demux %s, noise_filter %s)", devc->cur_samplerate,
493 devc->cur_samplerate_divider,
494 devc->flag_reg & FLAG_DEMUX ? "on" : "off",
495 devc->flag_reg & FLAG_FILTER ? "on": "off");
459a0f26 496 if (send_longcommand(serial, CMD_SET_DIVIDER,
0aba65da
UH
497 reverse32(devc->cur_samplerate_divider)) != SR_OK)
498 return SR_ERR;
499
500 /* Send sample limit and pre/post-trigger capture ratio. */
501 data = ((readcount - 1) & 0xffff) << 16;
502 data |= (delaycount - 1) & 0xffff;
459a0f26 503 if (send_longcommand(serial, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK)
0aba65da
UH
504 return SR_ERR;
505
506 /* The flag register wants them here, and 1 means "disable channel". */
507 devc->flag_reg |= ~(changrp_mask << 2) & 0x3c;
508 devc->flag_reg |= FLAG_FILTER;
509 devc->rle_count = 0;
510 data = (devc->flag_reg << 24) | ((devc->flag_reg << 8) & 0xff0000);
459a0f26 511 if (send_longcommand(serial, CMD_SET_FLAGS, data) != SR_OK)
0aba65da
UH
512 return SR_ERR;
513
514 /* Start acquisition on the device. */
459a0f26 515 if (send_shortcommand(serial, CMD_RUN) != SR_OK)
0aba65da
UH
516 return SR_ERR;
517
bf256783
BV
518 /* Reset all operational states. */
519 devc->num_transfers = devc->num_samples = devc->num_bytes = 0;
abb39e6b 520 memset(devc->sample, 0, 4);
bf256783 521
4afdfd46 522 /* Send header packet to the session bus. */
29a27196 523 std_session_send_df_header(cb_data, LOG_PREFIX);
4afdfd46 524
459a0f26 525 sr_source_add(serial->fd, G_IO_IN, -1, ols_receive_data, cb_data);
0aba65da 526
0aba65da
UH
527 return SR_OK;
528}
529
03f4de8c 530static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
0aba65da 531{
0aba65da
UH
532 (void)cb_data;
533
534 abort_acquisition(sdi);
535
536 return SR_OK;
537}
538
539SR_PRIV struct sr_dev_driver ols_driver_info = {
540 .name = "ols",
541 .longname = "Openbench Logic Sniffer",
542 .api_version = 1,
03f4de8c 543 .init = init,
eea49cf1 544 .cleanup = cleanup,
03f4de8c
BV
545 .scan = scan,
546 .dev_list = dev_list,
547 .dev_clear = dev_clear,
035a1078
BV
548 .config_get = config_get,
549 .config_set = config_set,
a1c743fc 550 .config_list = config_list,
03f4de8c
BV
551 .dev_open = dev_open,
552 .dev_close = dev_close,
553 .dev_acquisition_start = dev_acquisition_start,
554 .dev_acquisition_stop = dev_acquisition_stop,
0aba65da
UH
555 .priv = NULL,
556};