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