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