]> sigrok.org Git - libsigrok.git/blame - src/hardware/openbench-logic-sniffer/api.c
ols: move sigrok channel creation from protocol.c to api.c
[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 };
838f0122 105 struct dev_context *devc;
fbf9e657 106 size_t ch_max;
0aba65da 107
0aba65da
UH
108 conn = serialcomm = NULL;
109 for (l = options; l; l = l->next) {
1987b8d6
BV
110 src = l->data;
111 switch (src->key) {
1953564a 112 case SR_CONF_CONN:
e46aa4f6 113 conn = g_variant_get_string(src->data, NULL);
0aba65da 114 break;
1953564a 115 case SR_CONF_SERIALCOMM:
e46aa4f6 116 serialcomm = g_variant_get_string(src->data, NULL);
0aba65da
UH
117 break;
118 }
119 }
120 if (!conn)
121 return NULL;
122
98fec29e 123 if (!serialcomm)
0aba65da
UH
124 serialcomm = SERIALCOMM;
125
91219afc 126 serial = sr_serial_dev_inst_new(conn, serialcomm);
0aba65da
UH
127
128 /* The discovery procedure is like this: first send the Reset
129 * command (0x00) 5 times, since the device could be anywhere
130 * in a 5-byte command. Then send the ID command (0x02).
131 * If the device responds with 4 bytes ("OLS1" or "SLA1"), we
132 * have a match.
133 */
134 sr_info("Probing %s.", conn);
4ded59ee 135 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
0aba65da
UH
136 return NULL;
137
244995a2 138 if (ols_send_reset(serial) != SR_OK) {
0aba65da
UH
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
1a46cc62 145 g_usleep(RESPONSE_DELAY_US);
0aba65da 146
f9921513 147 if (serial_has_receive_data(serial) == 0) {
35be304b 148 sr_dbg("Didn't get any ID reply.");
0aba65da 149 return NULL;
ed936ccc
UH
150 }
151
55eca716 152 num_read =
153 serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4));
35be304b
WS
154 if (num_read < 0) {
155 sr_err("Getting ID reply failed (%d).", num_read);
0aba65da 156 return NULL;
ed936ccc
UH
157 }
158
159 if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4)) {
35be304b
WS
160 GString *id = sr_hexdump_new((uint8_t *)buf, num_read);
161
162 sr_err("Invalid ID reply (got %s).", id->str);
163
164 sr_hexdump_free(id);
0aba65da 165 return NULL;
163da55b
GS
166 } else {
167 sr_dbg("Successful detection, got '%c%c%c%c' (0x%02x 0x%02x 0x%02x 0x%02x).",
168 buf[0], buf[1], buf[2], buf[3],
169 buf[0], buf[1], buf[2], buf[3]);
ed936ccc 170 }
0aba65da 171
838f0122
GS
172 /*
173 * Create common data structures (sdi, devc) here in the common
174 * code path. These further get filled in either from metadata
175 * which is gathered from the device, or from open coded generic
176 * fallback data which is kept in the driver source code.
177 */
178 sdi = g_malloc0(sizeof(*sdi));
179 sdi->status = SR_ST_INACTIVE;
180 sdi->inst_type = SR_INST_SERIAL;
181 sdi->conn = serial;
182 sdi->connection_id = g_strdup(serial->port);
183 devc = g_malloc0(sizeof(*devc));
184 sdi->priv = devc;
185 devc->trigger_at_smpl = OLS_NO_TRIGGER;
186
187 /*
188 * Definitely using the OLS protocol, check if it supports
fbf9e657
GS
189 * the metadata command. Otherwise assign generic values.
190 * Create as many sigrok channels as was determined when
191 * the device was probed.
0aba65da
UH
192 */
193 send_shortcommand(serial, CMD_METADATA);
1a46cc62 194 g_usleep(RESPONSE_DELAY_US);
f9921513 195 if (serial_has_receive_data(serial) != 0) {
0aba65da 196 /* Got metadata. */
838f0122 197 (void)ols_get_metadata(sdi);
0aba65da 198 } else {
fbf9e657 199 /* Not an OLS -- some other board using the SUMP protocol. */
72cd99b8 200 sr_info("Device does not support metadata.");
0af636be
UH
201 sdi->vendor = g_strdup("Sump");
202 sdi->model = g_strdup("Logic Analyzer");
203 sdi->version = g_strdup("v1.0");
fbf9e657
GS
204 devc->max_channels = ARRAY_SIZE(ols_channel_names);
205 }
206 ch_max = ARRAY_SIZE(ols_channel_names);
207 if (devc->max_channels && ch_max > devc->max_channels)
208 ch_max = devc->max_channels;
209 for (i = 0; i < ch_max; i++) {
210 sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
211 ols_channel_names[i]);
0aba65da 212 }
bf256783
BV
213 /* Configure samplerate and divider. */
214 if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK)
55eca716 215 sr_dbg("Failed to set default samplerate (%" PRIu64 ").",
216 DEFAULT_SAMPLERATE);
bf256783 217
0aba65da
UH
218 serial_close(serial);
219
43376f33 220 return std_scan_complete(di, g_slist_append(NULL, sdi));
0aba65da
UH
221}
222
dd7a72ea 223static int config_get(uint32_t key, GVariant **data,
55eca716 224 const struct sr_dev_inst *sdi,
225 const struct sr_channel_group *cg)
0aba65da
UH
226{
227 struct dev_context *devc;
228
53b4680f 229 (void)cg;
8f996b89 230
0c05591a
BV
231 if (!sdi)
232 return SR_ERR_ARG;
233
234 devc = sdi->priv;
758906aa 235
584560f1 236 switch (key) {
2f67be51
GS
237 case SR_CONF_CONN:
238 if (!sdi->conn || !sdi->connection_id)
239 return SR_ERR_NA;
240 *data = g_variant_new_string(sdi->connection_id);
241 break;
123e1313 242 case SR_CONF_SAMPLERATE:
0c05591a
BV
243 *data = g_variant_new_uint64(devc->cur_samplerate);
244 break;
245 case SR_CONF_CAPTURE_RATIO:
246 *data = g_variant_new_uint64(devc->capture_ratio);
247 break;
248 case SR_CONF_LIMIT_SAMPLES:
249 *data = g_variant_new_uint64(devc->limit_samples);
250 break;
967760a8 251 case SR_CONF_PATTERN_MODE:
a80bed76 252 if (devc->capture_flags & CAPTURE_FLAG_EXTERNAL_TEST_MODE)
967760a8 253 *data = g_variant_new_string(STR_PATTERN_EXTERNAL);
a80bed76 254 else if (devc->capture_flags & CAPTURE_FLAG_INTERNAL_TEST_MODE)
967760a8 255 *data = g_variant_new_string(STR_PATTERN_INTERNAL);
6d16fdfb
BV
256 else
257 *data = g_variant_new_string(STR_PATTERN_NONE);
967760a8 258 break;
0c05591a 259 case SR_CONF_RLE:
55eca716 260 *data = g_variant_new_boolean(
261 devc->capture_flags & CAPTURE_FLAG_RLE ? TRUE : FALSE);
7730e4f0 262 break;
50b15953 263 case SR_CONF_EXTERNAL_CLOCK:
264 *data = g_variant_new_boolean(
55eca716 265 devc->capture_flags & CAPTURE_FLAG_CLOCK_EXTERNAL
266 ? TRUE : FALSE);
50b15953 267 break;
f20c39d9 268 case SR_CONF_CLOCK_EDGE:
269 *data = g_variant_new_string(external_clock_edges[
55eca716 270 devc->capture_flags & CAPTURE_FLAG_INVERT_EXT_CLOCK
271 ? 1 : 0]);
f20c39d9 272 break;
0aba65da 273 default:
bd6fbf62 274 return SR_ERR_NA;
0aba65da
UH
275 }
276
277 return SR_OK;
278}
279
dd7a72ea 280static int config_set(uint32_t key, GVariant *data,
55eca716 281 const struct sr_dev_inst *sdi,
282 const struct sr_channel_group *cg)
0aba65da
UH
283{
284 struct dev_context *devc;
6d16fdfb 285 uint16_t flag;
e46aa4f6 286 uint64_t tmp_u64;
967760a8 287 const char *stropt;
0aba65da 288
53b4680f 289 (void)cg;
8f996b89 290
0aba65da
UH
291 devc = sdi->priv;
292
584560f1 293 switch (key) {
1953564a 294 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
295 tmp_u64 = g_variant_get_uint64(data);
296 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
297 return SR_ERR_SAMPLERATE;
758906aa 298 return ols_set_samplerate(sdi, g_variant_get_uint64(data));
1953564a 299 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
300 tmp_u64 = g_variant_get_uint64(data);
301 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 302 return SR_ERR;
e46aa4f6 303 devc->limit_samples = tmp_u64;
0aba65da 304 break;
1953564a 305 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 306 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da 307 break;
eb1b610b
MR
308 case SR_CONF_EXTERNAL_CLOCK:
309 if (g_variant_get_boolean(data)) {
310 sr_info("Enabling external clock.");
a80bed76 311 devc->capture_flags |= CAPTURE_FLAG_CLOCK_EXTERNAL;
eb1b610b
MR
312 } else {
313 sr_info("Disabled external clock.");
a80bed76 314 devc->capture_flags &= ~CAPTURE_FLAG_CLOCK_EXTERNAL;
eb1b610b 315 }
eb1b610b 316 break;
f20c39d9 317 case SR_CONF_CLOCK_EDGE:
318 stropt = g_variant_get_string(data, NULL);
319 if (!strcmp(stropt, external_clock_edges[1])) {
320 sr_info("Triggering on falling edge of external clock.");
321 devc->capture_flags |= CAPTURE_FLAG_INVERT_EXT_CLOCK;
322 } else {
323 sr_info("Triggering on rising edge of external clock.");
324 devc->capture_flags &= ~CAPTURE_FLAG_INVERT_EXT_CLOCK;
325 }
326 break;
967760a8
MR
327 case SR_CONF_PATTERN_MODE:
328 stropt = g_variant_get_string(data, NULL);
6d16fdfb
BV
329 if (!strcmp(stropt, STR_PATTERN_NONE)) {
330 sr_info("Disabling test modes.");
331 flag = 0x0000;
758906aa 332 } else if (!strcmp(stropt, STR_PATTERN_INTERNAL)) {
967760a8 333 sr_info("Enabling internal test mode.");
a80bed76 334 flag = CAPTURE_FLAG_INTERNAL_TEST_MODE;
967760a8
MR
335 } else if (!strcmp(stropt, STR_PATTERN_EXTERNAL)) {
336 sr_info("Enabling external test mode.");
a80bed76 337 flag = CAPTURE_FLAG_EXTERNAL_TEST_MODE;
967760a8 338 } else {
758906aa 339 return SR_ERR;
967760a8 340 }
a80bed76 341 devc->capture_flags &= ~CAPTURE_FLAG_INTERNAL_TEST_MODE;
342 devc->capture_flags &= ~CAPTURE_FLAG_EXTERNAL_TEST_MODE;
343 devc->capture_flags |= flag;
967760a8 344 break;
7b0a57fd
MR
345 case SR_CONF_SWAP:
346 if (g_variant_get_boolean(data)) {
347 sr_info("Enabling channel swapping.");
a80bed76 348 devc->capture_flags |= CAPTURE_FLAG_SWAP_CHANNELS;
7b0a57fd
MR
349 } else {
350 sr_info("Disabling channel swapping.");
a80bed76 351 devc->capture_flags &= ~CAPTURE_FLAG_SWAP_CHANNELS;
7b0a57fd 352 }
7b0a57fd 353 break;
1953564a 354 case SR_CONF_RLE:
e46aa4f6 355 if (g_variant_get_boolean(data)) {
0aba65da 356 sr_info("Enabling RLE.");
a80bed76 357 devc->capture_flags |= CAPTURE_FLAG_RLE;
aeea0572
BV
358 } else {
359 sr_info("Disabling RLE.");
a80bed76 360 devc->capture_flags &= ~CAPTURE_FLAG_RLE;
0aba65da 361 }
0aba65da
UH
362 break;
363 default:
758906aa 364 return SR_ERR_NA;
0aba65da
UH
365 }
366
758906aa 367 return SR_OK;
0aba65da
UH
368}
369
dd7a72ea 370static int config_list(uint32_t key, GVariant **data,
55eca716 371 const struct sr_dev_inst *sdi,
372 const struct sr_channel_group *cg)
a1c743fc 373{
f0de2dd0 374 struct dev_context *devc;
91fd0f72 375 int num_ols_changrp, i;
a1c743fc 376
a1c743fc 377 switch (key) {
0d485e30 378 case SR_CONF_SCAN_OPTIONS:
9a6517d1 379 case SR_CONF_DEVICE_OPTIONS:
55eca716 380 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts,
381 devopts);
a1c743fc 382 case SR_CONF_SAMPLERATE:
53012da6 383 *data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates));
a1c743fc 384 break;
91fd0f72 385 case SR_CONF_TRIGGER_MATCH:
53012da6 386 *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
c50277a6 387 break;
f20c39d9 388 case SR_CONF_CLOCK_EDGE:
389 *data = std_gvar_array_str(ARRAY_AND_SIZE(external_clock_edges));
390 break;
7c07a178 391 case SR_CONF_PATTERN_MODE:
53012da6 392 *data = g_variant_new_strv(ARRAY_AND_SIZE(patterns));
7c07a178 393 break;
f0de2dd0
BV
394 case SR_CONF_LIMIT_SAMPLES:
395 if (!sdi)
396 return SR_ERR_ARG;
397 devc = sdi->priv;
f0de2dd0
BV
398 if (devc->max_samples == 0)
399 /* Device didn't specify sample memory size in metadata. */
400 return SR_ERR_NA;
401 /*
ba7dd8bb 402 * Channel groups are turned off if no channels in that group are
f0de2dd0
BV
403 * enabled, making more room for samples for the enabled group.
404 */
f8fd8420 405 uint32_t channel_mask = ols_channel_mask(sdi);
91fd0f72 406 num_ols_changrp = 0;
f0de2dd0 407 for (i = 0; i < 4; i++) {
f8fd8420 408 if (channel_mask & (0xff << (i * 8)))
91fd0f72 409 num_ols_changrp++;
1e1dac0c 410 }
a162eeb2 411
55eca716 412 *data = std_gvar_tuple_u64(MIN_NUM_SAMPLES, (num_ols_changrp)
413 ? devc->max_samples / num_ols_changrp : MIN_NUM_SAMPLES);
f0de2dd0 414 break;
a1c743fc 415 default:
bd6fbf62 416 return SR_ERR_NA;
a1c743fc
BV
417 }
418
419 return SR_OK;
420}
421
695dc859 422static int dev_acquisition_start(const struct sr_dev_inst *sdi)
0aba65da 423{
f8fd8420 424 int ret;
0aba65da 425 struct dev_context *devc;
459a0f26 426 struct sr_serial_dev_inst *serial;
0aba65da
UH
427
428 devc = sdi->priv;
459a0f26 429 serial = sdi->conn;
0aba65da 430
f8fd8420 431 ret = ols_prepare_acquisition(sdi);
432 if (ret != SR_OK)
433 return ret;
0aba65da
UH
434
435 /* Start acquisition on the device. */
6f9234e6 436 if (send_shortcommand(serial, CMD_ARM_BASIC_TRIGGER) != SR_OK)
0aba65da
UH
437 return SR_ERR;
438
bf256783 439 /* Reset all operational states. */
6d16fdfb
BV
440 devc->rle_count = devc->num_transfers = 0;
441 devc->num_samples = devc->num_bytes = 0;
625763e2 442 devc->cnt_bytes = devc->cnt_samples = devc->cnt_samples_rle = 0;
abb39e6b 443 memset(devc->sample, 0, 4);
bf256783 444
bee2b016 445 std_session_send_df_header(sdi);
4afdfd46 446
8105e829
DE
447 /* If the device stops sending for longer than it takes to send a byte,
448 * that means it's finished. But wait at least 100 ms to be safe.
449 */
74e28c06 450 return serial_source_add(sdi->session, serial, G_IO_IN, 100,
451 ols_receive_data, (struct sr_dev_inst *)sdi);
0aba65da
UH
452}
453
695dc859 454static int dev_acquisition_stop(struct sr_dev_inst *sdi)
0aba65da 455{
0aba65da
UH
456 abort_acquisition(sdi);
457
458 return SR_OK;
459}
460
15a5bfe4 461static struct sr_dev_driver ols_driver_info = {
0aba65da 462 .name = "ols",
60143473 463 .longname = "Openbench Logic Sniffer & SUMP compatibles",
0aba65da 464 .api_version = 1,
c2fdcc25 465 .init = std_init,
700d6b64 466 .cleanup = std_cleanup,
03f4de8c 467 .scan = scan,
c01bf34c 468 .dev_list = std_dev_list,
f778bf02 469 .dev_clear = std_dev_clear,
035a1078
BV
470 .config_get = config_get,
471 .config_set = config_set,
a1c743fc 472 .config_list = config_list,
854434de 473 .dev_open = std_serial_dev_open,
bf2c987f 474 .dev_close = std_serial_dev_close,
03f4de8c
BV
475 .dev_acquisition_start = dev_acquisition_start,
476 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 477 .context = NULL,
0aba65da 478};
dd5c48a6 479SR_REGISTER_DEV_DRIVER(ols_driver_info);