]> sigrok.org Git - libsigrok.git/blame - src/hardware/openbench-logic-sniffer/api.c
ols: Refactor: Extract trigger setup into private place
[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
f20c39d9 51static const char* external_clock_edges[] = {
52 "rising", // positive edge
53 "falling" // negative edge
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
35be304b
WS
149 num_read = serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4));
150 if (num_read < 0) {
151 sr_err("Getting ID reply failed (%d).", num_read);
0aba65da 152 return NULL;
ed936ccc
UH
153 }
154
155 if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4)) {
35be304b
WS
156 GString *id = sr_hexdump_new((uint8_t *)buf, num_read);
157
158 sr_err("Invalid ID reply (got %s).", id->str);
159
160 sr_hexdump_free(id);
0aba65da 161 return NULL;
ed936ccc 162 }
0aba65da
UH
163
164 /* Definitely using the OLS protocol, check if it supports
165 * the metadata command.
166 */
167 send_shortcommand(serial, CMD_METADATA);
ed936ccc 168
1a46cc62 169 g_usleep(RESPONSE_DELAY_US);
ed936ccc 170
f9921513 171 if (serial_has_receive_data(serial) != 0) {
0aba65da
UH
172 /* Got metadata. */
173 sdi = get_metadata(serial);
0aba65da
UH
174 } else {
175 /* Not an OLS -- some other board that uses the sump protocol. */
72cd99b8 176 sr_info("Device does not support metadata.");
aac29cc1 177 sdi = g_malloc0(sizeof(struct sr_dev_inst));
0af636be
UH
178 sdi->status = SR_ST_INACTIVE;
179 sdi->vendor = g_strdup("Sump");
180 sdi->model = g_strdup("Logic Analyzer");
181 sdi->version = g_strdup("v1.0");
07ffa5b3 182 for (i = 0; i < ARRAY_SIZE(ols_channel_names); i++)
5e23fcab 183 sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
c368e6f3 184 ols_channel_names[i]);
e57057ae 185 sdi->priv = ols_dev_new();
0aba65da 186 }
bf256783
BV
187 /* Configure samplerate and divider. */
188 if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK)
189 sr_dbg("Failed to set default samplerate (%"PRIu64").",
190 DEFAULT_SAMPLERATE);
459a0f26
BV
191 sdi->inst_type = SR_INST_SERIAL;
192 sdi->conn = serial;
bf256783 193
0aba65da
UH
194 serial_close(serial);
195
43376f33 196 return std_scan_complete(di, g_slist_append(NULL, sdi));
0aba65da
UH
197}
198
dd7a72ea
UH
199static int config_get(uint32_t key, GVariant **data,
200 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
0aba65da
UH
201{
202 struct dev_context *devc;
203
53b4680f 204 (void)cg;
8f996b89 205
0c05591a
BV
206 if (!sdi)
207 return SR_ERR_ARG;
208
209 devc = sdi->priv;
758906aa 210
584560f1 211 switch (key) {
123e1313 212 case SR_CONF_SAMPLERATE:
0c05591a
BV
213 *data = g_variant_new_uint64(devc->cur_samplerate);
214 break;
215 case SR_CONF_CAPTURE_RATIO:
216 *data = g_variant_new_uint64(devc->capture_ratio);
217 break;
218 case SR_CONF_LIMIT_SAMPLES:
219 *data = g_variant_new_uint64(devc->limit_samples);
220 break;
967760a8 221 case SR_CONF_PATTERN_MODE:
a80bed76 222 if (devc->capture_flags & CAPTURE_FLAG_EXTERNAL_TEST_MODE)
967760a8 223 *data = g_variant_new_string(STR_PATTERN_EXTERNAL);
a80bed76 224 else if (devc->capture_flags & CAPTURE_FLAG_INTERNAL_TEST_MODE)
967760a8 225 *data = g_variant_new_string(STR_PATTERN_INTERNAL);
6d16fdfb
BV
226 else
227 *data = g_variant_new_string(STR_PATTERN_NONE);
967760a8 228 break;
0c05591a 229 case SR_CONF_RLE:
a80bed76 230 *data = g_variant_new_boolean(devc->capture_flags & CAPTURE_FLAG_RLE ? TRUE : FALSE);
7730e4f0 231 break;
50b15953 232 case SR_CONF_EXTERNAL_CLOCK:
233 *data = g_variant_new_boolean(
234 devc->capture_flags & CAPTURE_FLAG_CLOCK_EXTERNAL ? TRUE : FALSE);
235 break;
f20c39d9 236 case SR_CONF_CLOCK_EDGE:
237 *data = g_variant_new_string(external_clock_edges[
238 devc->capture_flags & CAPTURE_FLAG_INVERT_EXT_CLOCK ? 1 : 0]);
239 break;
0aba65da 240 default:
bd6fbf62 241 return SR_ERR_NA;
0aba65da
UH
242 }
243
244 return SR_OK;
245}
246
dd7a72ea
UH
247static int config_set(uint32_t key, GVariant *data,
248 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
0aba65da
UH
249{
250 struct dev_context *devc;
6d16fdfb 251 uint16_t flag;
e46aa4f6 252 uint64_t tmp_u64;
967760a8 253 const char *stropt;
0aba65da 254
53b4680f 255 (void)cg;
8f996b89 256
0aba65da
UH
257 devc = sdi->priv;
258
584560f1 259 switch (key) {
1953564a 260 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
261 tmp_u64 = g_variant_get_uint64(data);
262 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
263 return SR_ERR_SAMPLERATE;
758906aa 264 return ols_set_samplerate(sdi, g_variant_get_uint64(data));
1953564a 265 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
266 tmp_u64 = g_variant_get_uint64(data);
267 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 268 return SR_ERR;
e46aa4f6 269 devc->limit_samples = tmp_u64;
0aba65da 270 break;
1953564a 271 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 272 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da 273 break;
eb1b610b
MR
274 case SR_CONF_EXTERNAL_CLOCK:
275 if (g_variant_get_boolean(data)) {
276 sr_info("Enabling external clock.");
a80bed76 277 devc->capture_flags |= CAPTURE_FLAG_CLOCK_EXTERNAL;
eb1b610b
MR
278 } else {
279 sr_info("Disabled external clock.");
a80bed76 280 devc->capture_flags &= ~CAPTURE_FLAG_CLOCK_EXTERNAL;
eb1b610b 281 }
eb1b610b 282 break;
f20c39d9 283 case SR_CONF_CLOCK_EDGE:
284 stropt = g_variant_get_string(data, NULL);
285 if (!strcmp(stropt, external_clock_edges[1])) {
286 sr_info("Triggering on falling edge of external clock.");
287 devc->capture_flags |= CAPTURE_FLAG_INVERT_EXT_CLOCK;
288 } else {
289 sr_info("Triggering on rising edge of external clock.");
290 devc->capture_flags &= ~CAPTURE_FLAG_INVERT_EXT_CLOCK;
291 }
292 break;
967760a8
MR
293 case SR_CONF_PATTERN_MODE:
294 stropt = g_variant_get_string(data, NULL);
6d16fdfb
BV
295 if (!strcmp(stropt, STR_PATTERN_NONE)) {
296 sr_info("Disabling test modes.");
297 flag = 0x0000;
758906aa 298 } else if (!strcmp(stropt, STR_PATTERN_INTERNAL)) {
967760a8 299 sr_info("Enabling internal test mode.");
a80bed76 300 flag = CAPTURE_FLAG_INTERNAL_TEST_MODE;
967760a8
MR
301 } else if (!strcmp(stropt, STR_PATTERN_EXTERNAL)) {
302 sr_info("Enabling external test mode.");
a80bed76 303 flag = CAPTURE_FLAG_EXTERNAL_TEST_MODE;
967760a8 304 } else {
758906aa 305 return SR_ERR;
967760a8 306 }
a80bed76 307 devc->capture_flags &= ~CAPTURE_FLAG_INTERNAL_TEST_MODE;
308 devc->capture_flags &= ~CAPTURE_FLAG_EXTERNAL_TEST_MODE;
309 devc->capture_flags |= flag;
967760a8 310 break;
7b0a57fd
MR
311 case SR_CONF_SWAP:
312 if (g_variant_get_boolean(data)) {
313 sr_info("Enabling channel swapping.");
a80bed76 314 devc->capture_flags |= CAPTURE_FLAG_SWAP_CHANNELS;
7b0a57fd
MR
315 } else {
316 sr_info("Disabling channel swapping.");
a80bed76 317 devc->capture_flags &= ~CAPTURE_FLAG_SWAP_CHANNELS;
7b0a57fd 318 }
7b0a57fd 319 break;
1953564a 320 case SR_CONF_RLE:
e46aa4f6 321 if (g_variant_get_boolean(data)) {
0aba65da 322 sr_info("Enabling RLE.");
a80bed76 323 devc->capture_flags |= CAPTURE_FLAG_RLE;
aeea0572
BV
324 } else {
325 sr_info("Disabling RLE.");
a80bed76 326 devc->capture_flags &= ~CAPTURE_FLAG_RLE;
0aba65da 327 }
0aba65da
UH
328 break;
329 default:
758906aa 330 return SR_ERR_NA;
0aba65da
UH
331 }
332
758906aa 333 return SR_OK;
0aba65da
UH
334}
335
dd7a72ea
UH
336static int config_list(uint32_t key, GVariant **data,
337 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
a1c743fc 338{
f0de2dd0 339 struct dev_context *devc;
91fd0f72 340 int num_ols_changrp, i;
a1c743fc 341
a1c743fc 342 switch (key) {
0d485e30 343 case SR_CONF_SCAN_OPTIONS:
9a6517d1 344 case SR_CONF_DEVICE_OPTIONS:
e66d1892 345 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
a1c743fc 346 case SR_CONF_SAMPLERATE:
53012da6 347 *data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates));
a1c743fc 348 break;
91fd0f72 349 case SR_CONF_TRIGGER_MATCH:
53012da6 350 *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
c50277a6 351 break;
f20c39d9 352 case SR_CONF_CLOCK_EDGE:
353 *data = std_gvar_array_str(ARRAY_AND_SIZE(external_clock_edges));
354 break;
7c07a178 355 case SR_CONF_PATTERN_MODE:
53012da6 356 *data = g_variant_new_strv(ARRAY_AND_SIZE(patterns));
7c07a178 357 break;
f0de2dd0
BV
358 case SR_CONF_LIMIT_SAMPLES:
359 if (!sdi)
360 return SR_ERR_ARG;
361 devc = sdi->priv;
a80bed76 362 if (devc->capture_flags & CAPTURE_FLAG_RLE)
f0de2dd0
BV
363 return SR_ERR_NA;
364 if (devc->max_samples == 0)
365 /* Device didn't specify sample memory size in metadata. */
366 return SR_ERR_NA;
367 /*
ba7dd8bb 368 * Channel groups are turned off if no channels in that group are
f0de2dd0
BV
369 * enabled, making more room for samples for the enabled group.
370 */
f8fd8420 371 uint32_t channel_mask = ols_channel_mask(sdi);
91fd0f72 372 num_ols_changrp = 0;
f0de2dd0 373 for (i = 0; i < 4; i++) {
f8fd8420 374 if (channel_mask & (0xff << (i * 8)))
91fd0f72 375 num_ols_changrp++;
1e1dac0c 376 }
a162eeb2
UH
377
378 *data = std_gvar_tuple_u64(MIN_NUM_SAMPLES,
379 (num_ols_changrp) ? devc->max_samples / num_ols_changrp : MIN_NUM_SAMPLES);
f0de2dd0 380 break;
a1c743fc 381 default:
bd6fbf62 382 return SR_ERR_NA;
a1c743fc
BV
383 }
384
385 return SR_OK;
386}
387
695dc859 388static int dev_acquisition_start(const struct sr_dev_inst *sdi)
0aba65da 389{
f8fd8420 390 int ret;
0aba65da 391 struct dev_context *devc;
459a0f26 392 struct sr_serial_dev_inst *serial;
0aba65da
UH
393
394 devc = sdi->priv;
459a0f26 395 serial = sdi->conn;
0aba65da 396
f8fd8420 397 ret = ols_prepare_acquisition(sdi);
398 if (ret != SR_OK)
399 return ret;
0aba65da
UH
400
401 /* Start acquisition on the device. */
6f9234e6 402 if (send_shortcommand(serial, CMD_ARM_BASIC_TRIGGER) != SR_OK)
0aba65da
UH
403 return SR_ERR;
404
bf256783 405 /* Reset all operational states. */
6d16fdfb
BV
406 devc->rle_count = devc->num_transfers = 0;
407 devc->num_samples = devc->num_bytes = 0;
625763e2 408 devc->cnt_bytes = devc->cnt_samples = devc->cnt_samples_rle = 0;
abb39e6b 409 memset(devc->sample, 0, 4);
bf256783 410
bee2b016 411 std_session_send_df_header(sdi);
4afdfd46 412
8105e829
DE
413 /* If the device stops sending for longer than it takes to send a byte,
414 * that means it's finished. But wait at least 100 ms to be safe.
415 */
416 serial_source_add(sdi->session, serial, G_IO_IN, 100,
695dc859 417 ols_receive_data, (struct sr_dev_inst *)sdi);
0aba65da 418
0aba65da
UH
419 return SR_OK;
420}
421
695dc859 422static int dev_acquisition_stop(struct sr_dev_inst *sdi)
0aba65da 423{
0aba65da
UH
424 abort_acquisition(sdi);
425
426 return SR_OK;
427}
428
15a5bfe4 429static struct sr_dev_driver ols_driver_info = {
0aba65da 430 .name = "ols",
60143473 431 .longname = "Openbench Logic Sniffer & SUMP compatibles",
0aba65da 432 .api_version = 1,
c2fdcc25 433 .init = std_init,
700d6b64 434 .cleanup = std_cleanup,
03f4de8c 435 .scan = scan,
c01bf34c 436 .dev_list = std_dev_list,
f778bf02 437 .dev_clear = std_dev_clear,
035a1078
BV
438 .config_get = config_get,
439 .config_set = config_set,
a1c743fc 440 .config_list = config_list,
854434de 441 .dev_open = std_serial_dev_open,
bf2c987f 442 .dev_close = std_serial_dev_close,
03f4de8c
BV
443 .dev_acquisition_start = dev_acquisition_start,
444 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 445 .context = NULL,
0aba65da 446};
dd5c48a6 447SR_REGISTER_DEV_DRIVER(ols_driver_info);