]> sigrok.org Git - libsigrok.git/blame - src/hardware/openbench-logic-sniffer/api.c
kingst-la2016: add support for "probe names" scan option
[libsigrok.git] / src / 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
6ec6c43b 20#include <config.h>
515ab088 21#include "protocol.h"
0aba65da
UH
22
23#define SERIALCOMM "115200/8n1"
24
a0e0bb41 25static const uint32_t scanopts[] = {
1953564a
BV
26 SR_CONF_CONN,
27 SR_CONF_SERIALCOMM,
aeabd308
UH
28};
29
55fb76b3
UH
30static const uint32_t drvopts[] = {
31 SR_CONF_LOGIC_ANALYZER,
32};
33
f254bc4b 34static const uint32_t devopts[] = {
2f67be51 35 SR_CONF_CONN | SR_CONF_GET,
5827f61b
BV
36 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
37 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
38 SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
39 SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
50b15953 40 SR_CONF_EXTERNAL_CLOCK | SR_CONF_GET | SR_CONF_SET,
f20c39d9 41 SR_CONF_CLOCK_EDGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
5827f61b
BV
42 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
43 SR_CONF_SWAP | SR_CONF_SET,
44 SR_CONF_RLE | SR_CONF_GET | SR_CONF_SET,
0aba65da
UH
45};
46
91fd0f72
BV
47static const int32_t trigger_matches[] = {
48 SR_TRIGGER_ZERO,
49 SR_TRIGGER_ONE,
50};
51
55eca716 52static const char *external_clock_edges[] = {
53 "rising", /* positive edge */
54 "falling" /* negative edge */
f20c39d9 55};
56
6d16fdfb
BV
57#define STR_PATTERN_NONE "None"
58#define STR_PATTERN_EXTERNAL "External"
59#define STR_PATTERN_INTERNAL "Internal"
967760a8
MR
60
61/* Supported methods of test pattern outputs */
62enum {
63 /**
64 * Capture pins 31:16 (unbuffered wing) output a test pattern
65 * that can captured on pins 0:15.
66 */
67 PATTERN_EXTERNAL,
68
69 /** Route test pattern internally to capture buffer. */
70 PATTERN_INTERNAL,
71};
72
7c07a178 73static const char *patterns[] = {
6d16fdfb 74 STR_PATTERN_NONE,
7c07a178
UH
75 STR_PATTERN_EXTERNAL,
76 STR_PATTERN_INTERNAL,
77};
78
ba7dd8bb 79/* Channels are numbered 0-31 (on the PCB silkscreen). */
53cda65a 80SR_PRIV const char *ols_channel_names[] = {
78693401
UH
81 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
82 "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
83 "24", "25", "26", "27", "28", "29", "30", "31",
0aba65da
UH
84};
85
d3b38ad3 86/* Default supported samplerates, can be overridden by device metadata. */
e46aa4f6
BV
87static const uint64_t samplerates[] = {
88 SR_HZ(10),
89 SR_MHZ(200),
90 SR_HZ(1),
0aba65da
UH
91};
92
ae4e6999 93#define RESPONSE_DELAY_US (20 * 1000)
1a46cc62 94
4f840ce9 95static GSList *scan(struct sr_dev_driver *di, GSList *options)
0aba65da 96{
1987b8d6 97 struct sr_config *src;
0aba65da 98 struct sr_dev_inst *sdi;
0aba65da 99 struct sr_serial_dev_inst *serial;
43376f33 100 GSList *l;
35be304b 101 int num_read;
07ffa5b3 102 unsigned int i;
0aba65da 103 const char *conn, *serialcomm;
35be304b 104 char buf[4] = { 0, 0, 0, 0 };
0aba65da 105
0aba65da
UH
106 conn = serialcomm = NULL;
107 for (l = options; l; l = l->next) {
1987b8d6
BV
108 src = l->data;
109 switch (src->key) {
1953564a 110 case SR_CONF_CONN:
e46aa4f6 111 conn = g_variant_get_string(src->data, NULL);
0aba65da 112 break;
1953564a 113 case SR_CONF_SERIALCOMM:
e46aa4f6 114 serialcomm = g_variant_get_string(src->data, NULL);
0aba65da
UH
115 break;
116 }
117 }
118 if (!conn)
119 return NULL;
120
98fec29e 121 if (!serialcomm)
0aba65da
UH
122 serialcomm = SERIALCOMM;
123
91219afc 124 serial = sr_serial_dev_inst_new(conn, serialcomm);
0aba65da
UH
125
126 /* The discovery procedure is like this: first send the Reset
127 * command (0x00) 5 times, since the device could be anywhere
128 * in a 5-byte command. Then send the ID command (0x02).
129 * If the device responds with 4 bytes ("OLS1" or "SLA1"), we
130 * have a match.
131 */
132 sr_info("Probing %s.", conn);
4ded59ee 133 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
0aba65da
UH
134 return NULL;
135
244995a2 136 if (ols_send_reset(serial) != SR_OK) {
0aba65da
UH
137 serial_close(serial);
138 sr_err("Could not use port %s. Quitting.", conn);
139 return NULL;
140 }
141 send_shortcommand(serial, CMD_ID);
142
1a46cc62 143 g_usleep(RESPONSE_DELAY_US);
0aba65da 144
f9921513 145 if (serial_has_receive_data(serial) == 0) {
35be304b 146 sr_dbg("Didn't get any ID reply.");
0aba65da 147 return NULL;
ed936ccc
UH
148 }
149
55eca716 150 num_read =
151 serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4));
35be304b
WS
152 if (num_read < 0) {
153 sr_err("Getting ID reply failed (%d).", num_read);
0aba65da 154 return NULL;
ed936ccc
UH
155 }
156
157 if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4)) {
35be304b
WS
158 GString *id = sr_hexdump_new((uint8_t *)buf, num_read);
159
160 sr_err("Invalid ID reply (got %s).", id->str);
161
162 sr_hexdump_free(id);
0aba65da 163 return NULL;
163da55b
GS
164 } else {
165 sr_dbg("Successful detection, got '%c%c%c%c' (0x%02x 0x%02x 0x%02x 0x%02x).",
166 buf[0], buf[1], buf[2], buf[3],
167 buf[0], buf[1], buf[2], buf[3]);
ed936ccc 168 }
0aba65da
UH
169
170 /* Definitely using the OLS protocol, check if it supports
171 * the metadata command.
172 */
173 send_shortcommand(serial, CMD_METADATA);
ed936ccc 174
1a46cc62 175 g_usleep(RESPONSE_DELAY_US);
ed936ccc 176
f9921513 177 if (serial_has_receive_data(serial) != 0) {
0aba65da
UH
178 /* Got metadata. */
179 sdi = get_metadata(serial);
0aba65da
UH
180 } else {
181 /* Not an OLS -- some other board that uses the sump protocol. */
72cd99b8 182 sr_info("Device does not support metadata.");
aac29cc1 183 sdi = g_malloc0(sizeof(struct sr_dev_inst));
0af636be
UH
184 sdi->status = SR_ST_INACTIVE;
185 sdi->vendor = g_strdup("Sump");
186 sdi->model = g_strdup("Logic Analyzer");
187 sdi->version = g_strdup("v1.0");
07ffa5b3 188 for (i = 0; i < ARRAY_SIZE(ols_channel_names); i++)
5e23fcab 189 sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
55eca716 190 ols_channel_names[i]);
e57057ae 191 sdi->priv = ols_dev_new();
0aba65da 192 }
bf256783
BV
193 /* Configure samplerate and divider. */
194 if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK)
55eca716 195 sr_dbg("Failed to set default samplerate (%" PRIu64 ").",
196 DEFAULT_SAMPLERATE);
459a0f26
BV
197 sdi->inst_type = SR_INST_SERIAL;
198 sdi->conn = serial;
2f67be51 199 sdi->connection_id = g_strdup(serial->port);
bf256783 200
0aba65da
UH
201 serial_close(serial);
202
43376f33 203 return std_scan_complete(di, g_slist_append(NULL, sdi));
0aba65da
UH
204}
205
dd7a72ea 206static int config_get(uint32_t key, GVariant **data,
55eca716 207 const struct sr_dev_inst *sdi,
208 const struct sr_channel_group *cg)
0aba65da
UH
209{
210 struct dev_context *devc;
211
53b4680f 212 (void)cg;
8f996b89 213
0c05591a
BV
214 if (!sdi)
215 return SR_ERR_ARG;
216
217 devc = sdi->priv;
758906aa 218
584560f1 219 switch (key) {
2f67be51
GS
220 case SR_CONF_CONN:
221 if (!sdi->conn || !sdi->connection_id)
222 return SR_ERR_NA;
223 *data = g_variant_new_string(sdi->connection_id);
224 break;
123e1313 225 case SR_CONF_SAMPLERATE:
0c05591a
BV
226 *data = g_variant_new_uint64(devc->cur_samplerate);
227 break;
228 case SR_CONF_CAPTURE_RATIO:
229 *data = g_variant_new_uint64(devc->capture_ratio);
230 break;
231 case SR_CONF_LIMIT_SAMPLES:
232 *data = g_variant_new_uint64(devc->limit_samples);
233 break;
967760a8 234 case SR_CONF_PATTERN_MODE:
a80bed76 235 if (devc->capture_flags & CAPTURE_FLAG_EXTERNAL_TEST_MODE)
967760a8 236 *data = g_variant_new_string(STR_PATTERN_EXTERNAL);
a80bed76 237 else if (devc->capture_flags & CAPTURE_FLAG_INTERNAL_TEST_MODE)
967760a8 238 *data = g_variant_new_string(STR_PATTERN_INTERNAL);
6d16fdfb
BV
239 else
240 *data = g_variant_new_string(STR_PATTERN_NONE);
967760a8 241 break;
0c05591a 242 case SR_CONF_RLE:
55eca716 243 *data = g_variant_new_boolean(
244 devc->capture_flags & CAPTURE_FLAG_RLE ? TRUE : FALSE);
7730e4f0 245 break;
50b15953 246 case SR_CONF_EXTERNAL_CLOCK:
247 *data = g_variant_new_boolean(
55eca716 248 devc->capture_flags & CAPTURE_FLAG_CLOCK_EXTERNAL
249 ? TRUE : FALSE);
50b15953 250 break;
f20c39d9 251 case SR_CONF_CLOCK_EDGE:
252 *data = g_variant_new_string(external_clock_edges[
55eca716 253 devc->capture_flags & CAPTURE_FLAG_INVERT_EXT_CLOCK
254 ? 1 : 0]);
f20c39d9 255 break;
0aba65da 256 default:
bd6fbf62 257 return SR_ERR_NA;
0aba65da
UH
258 }
259
260 return SR_OK;
261}
262
dd7a72ea 263static int config_set(uint32_t key, GVariant *data,
55eca716 264 const struct sr_dev_inst *sdi,
265 const struct sr_channel_group *cg)
0aba65da
UH
266{
267 struct dev_context *devc;
6d16fdfb 268 uint16_t flag;
e46aa4f6 269 uint64_t tmp_u64;
967760a8 270 const char *stropt;
0aba65da 271
53b4680f 272 (void)cg;
8f996b89 273
0aba65da
UH
274 devc = sdi->priv;
275
584560f1 276 switch (key) {
1953564a 277 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
278 tmp_u64 = g_variant_get_uint64(data);
279 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
280 return SR_ERR_SAMPLERATE;
758906aa 281 return ols_set_samplerate(sdi, g_variant_get_uint64(data));
1953564a 282 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
283 tmp_u64 = g_variant_get_uint64(data);
284 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 285 return SR_ERR;
e46aa4f6 286 devc->limit_samples = tmp_u64;
0aba65da 287 break;
1953564a 288 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 289 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da 290 break;
eb1b610b
MR
291 case SR_CONF_EXTERNAL_CLOCK:
292 if (g_variant_get_boolean(data)) {
293 sr_info("Enabling external clock.");
a80bed76 294 devc->capture_flags |= CAPTURE_FLAG_CLOCK_EXTERNAL;
eb1b610b
MR
295 } else {
296 sr_info("Disabled external clock.");
a80bed76 297 devc->capture_flags &= ~CAPTURE_FLAG_CLOCK_EXTERNAL;
eb1b610b 298 }
eb1b610b 299 break;
f20c39d9 300 case SR_CONF_CLOCK_EDGE:
301 stropt = g_variant_get_string(data, NULL);
302 if (!strcmp(stropt, external_clock_edges[1])) {
303 sr_info("Triggering on falling edge of external clock.");
304 devc->capture_flags |= CAPTURE_FLAG_INVERT_EXT_CLOCK;
305 } else {
306 sr_info("Triggering on rising edge of external clock.");
307 devc->capture_flags &= ~CAPTURE_FLAG_INVERT_EXT_CLOCK;
308 }
309 break;
967760a8
MR
310 case SR_CONF_PATTERN_MODE:
311 stropt = g_variant_get_string(data, NULL);
6d16fdfb
BV
312 if (!strcmp(stropt, STR_PATTERN_NONE)) {
313 sr_info("Disabling test modes.");
314 flag = 0x0000;
758906aa 315 } else if (!strcmp(stropt, STR_PATTERN_INTERNAL)) {
967760a8 316 sr_info("Enabling internal test mode.");
a80bed76 317 flag = CAPTURE_FLAG_INTERNAL_TEST_MODE;
967760a8
MR
318 } else if (!strcmp(stropt, STR_PATTERN_EXTERNAL)) {
319 sr_info("Enabling external test mode.");
a80bed76 320 flag = CAPTURE_FLAG_EXTERNAL_TEST_MODE;
967760a8 321 } else {
758906aa 322 return SR_ERR;
967760a8 323 }
a80bed76 324 devc->capture_flags &= ~CAPTURE_FLAG_INTERNAL_TEST_MODE;
325 devc->capture_flags &= ~CAPTURE_FLAG_EXTERNAL_TEST_MODE;
326 devc->capture_flags |= flag;
967760a8 327 break;
7b0a57fd
MR
328 case SR_CONF_SWAP:
329 if (g_variant_get_boolean(data)) {
330 sr_info("Enabling channel swapping.");
a80bed76 331 devc->capture_flags |= CAPTURE_FLAG_SWAP_CHANNELS;
7b0a57fd
MR
332 } else {
333 sr_info("Disabling channel swapping.");
a80bed76 334 devc->capture_flags &= ~CAPTURE_FLAG_SWAP_CHANNELS;
7b0a57fd 335 }
7b0a57fd 336 break;
1953564a 337 case SR_CONF_RLE:
e46aa4f6 338 if (g_variant_get_boolean(data)) {
0aba65da 339 sr_info("Enabling RLE.");
a80bed76 340 devc->capture_flags |= CAPTURE_FLAG_RLE;
aeea0572
BV
341 } else {
342 sr_info("Disabling RLE.");
a80bed76 343 devc->capture_flags &= ~CAPTURE_FLAG_RLE;
0aba65da 344 }
0aba65da
UH
345 break;
346 default:
758906aa 347 return SR_ERR_NA;
0aba65da
UH
348 }
349
758906aa 350 return SR_OK;
0aba65da
UH
351}
352
dd7a72ea 353static int config_list(uint32_t key, GVariant **data,
55eca716 354 const struct sr_dev_inst *sdi,
355 const struct sr_channel_group *cg)
a1c743fc 356{
f0de2dd0 357 struct dev_context *devc;
91fd0f72 358 int num_ols_changrp, i;
a1c743fc 359
a1c743fc 360 switch (key) {
0d485e30 361 case SR_CONF_SCAN_OPTIONS:
9a6517d1 362 case SR_CONF_DEVICE_OPTIONS:
55eca716 363 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts,
364 devopts);
a1c743fc 365 case SR_CONF_SAMPLERATE:
53012da6 366 *data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates));
a1c743fc 367 break;
91fd0f72 368 case SR_CONF_TRIGGER_MATCH:
53012da6 369 *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
c50277a6 370 break;
f20c39d9 371 case SR_CONF_CLOCK_EDGE:
372 *data = std_gvar_array_str(ARRAY_AND_SIZE(external_clock_edges));
373 break;
7c07a178 374 case SR_CONF_PATTERN_MODE:
53012da6 375 *data = g_variant_new_strv(ARRAY_AND_SIZE(patterns));
7c07a178 376 break;
f0de2dd0
BV
377 case SR_CONF_LIMIT_SAMPLES:
378 if (!sdi)
379 return SR_ERR_ARG;
380 devc = sdi->priv;
f0de2dd0
BV
381 if (devc->max_samples == 0)
382 /* Device didn't specify sample memory size in metadata. */
383 return SR_ERR_NA;
384 /*
ba7dd8bb 385 * Channel groups are turned off if no channels in that group are
f0de2dd0
BV
386 * enabled, making more room for samples for the enabled group.
387 */
f8fd8420 388 uint32_t channel_mask = ols_channel_mask(sdi);
91fd0f72 389 num_ols_changrp = 0;
f0de2dd0 390 for (i = 0; i < 4; i++) {
f8fd8420 391 if (channel_mask & (0xff << (i * 8)))
91fd0f72 392 num_ols_changrp++;
1e1dac0c 393 }
a162eeb2 394
55eca716 395 *data = std_gvar_tuple_u64(MIN_NUM_SAMPLES, (num_ols_changrp)
396 ? devc->max_samples / num_ols_changrp : MIN_NUM_SAMPLES);
f0de2dd0 397 break;
a1c743fc 398 default:
bd6fbf62 399 return SR_ERR_NA;
a1c743fc
BV
400 }
401
402 return SR_OK;
403}
404
695dc859 405static int dev_acquisition_start(const struct sr_dev_inst *sdi)
0aba65da 406{
f8fd8420 407 int ret;
0aba65da 408 struct dev_context *devc;
459a0f26 409 struct sr_serial_dev_inst *serial;
0aba65da
UH
410
411 devc = sdi->priv;
459a0f26 412 serial = sdi->conn;
0aba65da 413
f8fd8420 414 ret = ols_prepare_acquisition(sdi);
415 if (ret != SR_OK)
416 return ret;
0aba65da
UH
417
418 /* Start acquisition on the device. */
6f9234e6 419 if (send_shortcommand(serial, CMD_ARM_BASIC_TRIGGER) != SR_OK)
0aba65da
UH
420 return SR_ERR;
421
bf256783 422 /* Reset all operational states. */
6d16fdfb
BV
423 devc->rle_count = devc->num_transfers = 0;
424 devc->num_samples = devc->num_bytes = 0;
625763e2 425 devc->cnt_bytes = devc->cnt_samples = devc->cnt_samples_rle = 0;
abb39e6b 426 memset(devc->sample, 0, 4);
bf256783 427
bee2b016 428 std_session_send_df_header(sdi);
4afdfd46 429
8105e829
DE
430 /* If the device stops sending for longer than it takes to send a byte,
431 * that means it's finished. But wait at least 100 ms to be safe.
432 */
74e28c06 433 return serial_source_add(sdi->session, serial, G_IO_IN, 100,
434 ols_receive_data, (struct sr_dev_inst *)sdi);
0aba65da
UH
435}
436
695dc859 437static int dev_acquisition_stop(struct sr_dev_inst *sdi)
0aba65da 438{
0aba65da
UH
439 abort_acquisition(sdi);
440
441 return SR_OK;
442}
443
15a5bfe4 444static struct sr_dev_driver ols_driver_info = {
0aba65da 445 .name = "ols",
60143473 446 .longname = "Openbench Logic Sniffer & SUMP compatibles",
0aba65da 447 .api_version = 1,
c2fdcc25 448 .init = std_init,
700d6b64 449 .cleanup = std_cleanup,
03f4de8c 450 .scan = scan,
c01bf34c 451 .dev_list = std_dev_list,
f778bf02 452 .dev_clear = std_dev_clear,
035a1078
BV
453 .config_get = config_get,
454 .config_set = config_set,
a1c743fc 455 .config_list = config_list,
854434de 456 .dev_open = std_serial_dev_open,
bf2c987f 457 .dev_close = std_serial_dev_close,
03f4de8c
BV
458 .dev_acquisition_start = dev_acquisition_start,
459 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 460 .context = NULL,
0aba65da 461};
dd5c48a6 462SR_REGISTER_DEV_DRIVER(ols_driver_info);