X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=blobdiff_plain;f=src%2Fhardware%2Fopenbench-logic-sniffer%2Fapi.c;h=b0cc3978bf25e8e529f2ca4ea529e4d09679d232;hp=aaf42ab80f48d96451fc37fcb32b1500ce2ee678;hb=f6ce25ec05e8707ee3783b111ea13779f237c3b3;hpb=f4d3a4fb9ae62b4764cbb8181ab9bef95e7b6348 diff --git a/src/hardware/openbench-logic-sniffer/api.c b/src/hardware/openbench-logic-sniffer/api.c index aaf42ab8..b0cc3978 100644 --- a/src/hardware/openbench-logic-sniffer/api.c +++ b/src/hardware/openbench-logic-sniffer/api.c @@ -17,8 +17,8 @@ * along with this program. If not, see . */ +#include #include "protocol.h" -#include #define SERIALCOMM "115200/8n1" @@ -27,8 +27,11 @@ static const uint32_t scanopts[] = { SR_CONF_SERIALCOMM, }; -static const uint32_t devopts[] = { +static const uint32_t drvopts[] = { SR_CONF_LOGIC_ANALYZER, +}; + +static const uint32_t devopts[] = { SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_TRIGGER_MATCH | SR_CONF_LIST, @@ -67,11 +70,10 @@ static const char *patterns[] = { }; /* Channels are numbered 0-31 (on the PCB silkscreen). */ -SR_PRIV const char *ols_channel_names[NUM_CHANNELS + 1] = { +SR_PRIV const char *ols_channel_names[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", - NULL, }; /* Default supported samplerates, can be overridden by device metadata. */ @@ -81,32 +83,19 @@ static const uint64_t samplerates[] = { SR_HZ(1), }; -SR_PRIV struct sr_dev_driver ols_driver_info; -static struct sr_dev_driver *di = &ols_driver_info; +#define RESPONSE_DELAY_US (20 * 1000) -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options) +static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct sr_config *src; struct sr_dev_inst *sdi; - struct drv_context *drvc; - struct dev_context *devc; - struct sr_channel *ch; struct sr_serial_dev_inst *serial; - GPollFD probefd; - GSList *l, *devices; - int ret, i; + GSList *l; + int ret; + unsigned int i; const char *conn, *serialcomm; char buf[8]; - drvc = di->priv; - - devices = NULL; - conn = serialcomm = NULL; for (l = options; l; l = l->next) { src = l->data; @@ -122,11 +111,10 @@ static GSList *scan(GSList *options) if (!conn) return NULL; - if (serialcomm == NULL) + if (!serialcomm) serialcomm = SERIALCOMM; - if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) - return NULL; + serial = sr_serial_dev_inst_new(conn, serialcomm); /* The discovery procedure is like this: first send the Reset * command (0x00) 5 times, since the device could be anywhere @@ -138,56 +126,54 @@ static GSList *scan(GSList *options) if (serial_open(serial, SERIAL_RDWR) != SR_OK) return NULL; - ret = SR_OK; - for (i = 0; i < 5; i++) { - if ((ret = send_shortcommand(serial, CMD_RESET)) != SR_OK) { - sr_err("Port %s is not writable.", conn); - break; - } - } - if (ret != SR_OK) { + if (ols_send_reset(serial) != SR_OK) { serial_close(serial); sr_err("Could not use port %s. Quitting.", conn); return NULL; } send_shortcommand(serial, CMD_ID); - /* Wait 10ms for a response. */ - g_usleep(10000); + g_usleep(RESPONSE_DELAY_US); - sp_get_port_handle(serial->data, &probefd.fd); - probefd.events = G_IO_IN; - g_poll(&probefd, 1, 1); - - if (probefd.revents != G_IO_IN) + if (sp_input_waiting(serial->data) == 0) { + sr_dbg("Didn't get any reply."); return NULL; - if (serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4)) != 4) + } + + ret = serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4)); + if (ret != 4) { + sr_err("Invalid reply (expected 4 bytes, got %d).", ret); return NULL; - if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4)) + } + + if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4)) { + sr_err("Invalid reply (expected '1SLO' or '1ALS', got " + "'%c%c%c%c').", buf[0], buf[1], buf[2], buf[3]); return NULL; + } /* Definitely using the OLS protocol, check if it supports * the metadata command. */ send_shortcommand(serial, CMD_METADATA); - if (g_poll(&probefd, 1, 10) > 0) { + + g_usleep(RESPONSE_DELAY_US); + + if (sp_input_waiting(serial->data) != 0) { /* Got metadata. */ sdi = get_metadata(serial); - devc = sdi->priv; } else { /* Not an OLS -- some other board that uses the sump protocol. */ sr_info("Device does not support metadata."); - sdi = sr_dev_inst_new(SR_ST_INACTIVE, - "Sump", "Logic Analyzer", "v1.0"); - sdi->driver = di; - for (i = 0; i < 32; i++) { - if (!(ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, - ols_channel_names[i]))) - return 0; - sdi->channels = g_slist_append(sdi->channels, ch); - } - devc = ols_dev_new(); - sdi->priv = devc; + sdi = g_malloc0(sizeof(struct sr_dev_inst)); + sdi->status = SR_ST_INACTIVE; + sdi->vendor = g_strdup("Sump"); + sdi->model = g_strdup("Logic Analyzer"); + sdi->version = g_strdup("v1.0"); + for (i = 0; i < ARRAY_SIZE(ols_channel_names); i++) + sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, + ols_channel_names[i]); + sdi->priv = ols_dev_new(); } /* Configure samplerate and divider. */ if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK) @@ -196,26 +182,13 @@ static GSList *scan(GSList *options) sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - serial_close(serial); - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int cleanup(void) -{ - return std_dev_clear(di, NULL); + return std_scan_complete(di, g_slist_append(NULL, sdi)); } -static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) +static int config_get(uint32_t key, GVariant **data, + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; @@ -225,6 +198,7 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s return SR_ERR_ARG; devc = sdi->priv; + switch (key) { case SR_CONF_SAMPLERATE: *data = g_variant_new_uint64(devc->cur_samplerate); @@ -253,20 +227,16 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s return SR_OK; } -static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) +static int config_set(uint32_t key, GVariant *data, + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; uint16_t flag; uint64_t tmp_u64; - int ret; const char *stropt; (void)cg; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - devc = sdi->priv; switch (key) { @@ -274,22 +244,15 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd tmp_u64 = g_variant_get_uint64(data); if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1]) return SR_ERR_SAMPLERATE; - ret = ols_set_samplerate(sdi, g_variant_get_uint64(data)); - break; + return ols_set_samplerate(sdi, g_variant_get_uint64(data)); case SR_CONF_LIMIT_SAMPLES: tmp_u64 = g_variant_get_uint64(data); if (tmp_u64 < MIN_NUM_SAMPLES) return SR_ERR; devc->limit_samples = tmp_u64; - ret = SR_OK; break; case SR_CONF_CAPTURE_RATIO: devc->capture_ratio = g_variant_get_uint64(data); - if (devc->capture_ratio < 0 || devc->capture_ratio > 100) { - devc->capture_ratio = 0; - ret = SR_ERR; - } else - ret = SR_OK; break; case SR_CONF_EXTERNAL_CLOCK: if (g_variant_get_boolean(data)) { @@ -299,28 +262,24 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd sr_info("Disabled external clock."); devc->flag_reg &= ~FLAG_CLOCK_EXTERNAL; } - ret = SR_OK; break; case SR_CONF_PATTERN_MODE: stropt = g_variant_get_string(data, NULL); - ret = SR_OK; - flag = 0xffff; if (!strcmp(stropt, STR_PATTERN_NONE)) { sr_info("Disabling test modes."); flag = 0x0000; - }else if (!strcmp(stropt, STR_PATTERN_INTERNAL)) { + } else if (!strcmp(stropt, STR_PATTERN_INTERNAL)) { sr_info("Enabling internal test mode."); flag = FLAG_INTERNAL_TEST_MODE; } else if (!strcmp(stropt, STR_PATTERN_EXTERNAL)) { sr_info("Enabling external test mode."); flag = FLAG_EXTERNAL_TEST_MODE; } else { - ret = SR_ERR; - } - if (flag != 0xffff) { - devc->flag_reg &= ~(FLAG_INTERNAL_TEST_MODE | FLAG_EXTERNAL_TEST_MODE); - devc->flag_reg |= flag; + return SR_ERR; } + devc->flag_reg &= ~FLAG_INTERNAL_TEST_MODE; + devc->flag_reg &= ~FLAG_EXTERNAL_TEST_MODE; + devc->flag_reg |= flag; break; case SR_CONF_SWAP: if (g_variant_get_boolean(data)) { @@ -330,9 +289,7 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd sr_info("Disabling channel swapping."); devc->flag_reg &= ~FLAG_SWAP_CHANNELS; } - ret = SR_OK; break; - case SR_CONF_RLE: if (g_variant_get_boolean(data)) { sr_info("Enabling RLE."); @@ -341,48 +298,32 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd sr_info("Disabling RLE."); devc->flag_reg &= ~FLAG_RLE; } - ret = SR_OK; break; default: - ret = SR_ERR_NA; + return SR_ERR_NA; } - return ret; + return SR_OK; } -static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) +static int config_list(uint32_t key, GVariant **data, + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; - GVariant *gvar, *grange[2]; - GVariantBuilder gvb; int num_ols_changrp, i; - (void)cg; - switch (key) { case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t)); - break; case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - devopts, ARRAY_SIZE(devopts), sizeof(uint32_t)); - break; + return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts); case SR_CONF_SAMPLERATE: - g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); - gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates, - ARRAY_SIZE(samplerates), sizeof(uint64_t)); - g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar); - *data = g_variant_builder_end(&gvb); + *data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates)); break; case SR_CONF_TRIGGER_MATCH: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - trigger_matches, ARRAY_SIZE(trigger_matches), - sizeof(int32_t)); + *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches)); break; case SR_CONF_PATTERN_MODE: - *data = g_variant_new_strv(patterns, ARRAY_SIZE(patterns)); + *data = g_variant_new_strv(ARRAY_AND_SIZE(patterns)); break; case SR_CONF_LIMIT_SAMPLES: if (!sdi) @@ -403,12 +344,9 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst * if (devc->channel_mask & (0xff << (i * 8))) num_ols_changrp++; } - grange[0] = g_variant_new_uint64(MIN_NUM_SAMPLES); - if (num_ols_changrp) - grange[1] = g_variant_new_uint64(devc->max_samples / num_ols_changrp); - else - grange[1] = g_variant_new_uint64(MIN_NUM_SAMPLES); - *data = g_variant_new_tuple(grange, 2); + + *data = std_gvar_tuple_u64(MIN_NUM_SAMPLES, + (num_ols_changrp) ? devc->max_samples / num_ols_changrp : MIN_NUM_SAMPLES); break; default: return SR_ERR_NA; @@ -454,19 +392,15 @@ static int set_trigger(const struct sr_dev_inst *sdi, int stage) return SR_OK; } -static int dev_acquisition_start(const struct sr_dev_inst *sdi, - void *cb_data) +static int dev_acquisition_start(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_serial_dev_inst *serial; - uint16_t samplecount, readcount, delaycount; + uint32_t samplecount, readcount, delaycount; uint8_t ols_changrp_mask, arg[4]; int num_ols_changrp; int ret, i; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - devc = sdi->priv; serial = sdi->conn; @@ -483,14 +417,10 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, /* * Limit readcount to prevent reading past the end of the hardware - * buffer. + * buffer. Rather read too many samples than too few. */ samplecount = MIN(devc->max_samples / num_ols_changrp, devc->limit_samples); - readcount = samplecount / 4; - - /* Rather read too many samples than too few. */ - if (samplecount % 4 != 0) - readcount++; + readcount = (samplecount + 3) / 4; /* Basic triggers. */ if (ols_convert_trigger(sdi) != SR_OK) { @@ -498,6 +428,14 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, return SR_ERR; } if (devc->num_stages > 0) { + /* + * According to http://mygizmos.org/ols/Logic-Sniffer-FPGA-Spec.pdf + * reset command must be send prior each arm command + */ + sr_dbg("Send reset command before trigger configure"); + if (ols_send_reset(serial) != SR_OK) + return SR_ERR; + delaycount = readcount * (1 - devc->capture_ratio / 100.0); devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages; for (i = 0; i <= devc->num_stages; i++) { @@ -526,12 +464,28 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, /* Send sample limit and pre/post-trigger capture ratio. */ sr_dbg("Setting sample limit %d, trigger point at %d", (readcount - 1) * 4, (delaycount - 1) * 4); - arg[0] = ((readcount - 1) & 0xff); - arg[1] = ((readcount - 1) & 0xff00) >> 8; - arg[2] = ((delaycount - 1) & 0xff); - arg[3] = ((delaycount - 1) & 0xff00) >> 8; - if (send_longcommand(serial, CMD_CAPTURE_SIZE, arg) != SR_OK) - return SR_ERR; + + if (devc->max_samples > 256 * 1024) { + arg[0] = ((readcount - 1) & 0xff); + arg[1] = ((readcount - 1) & 0xff00) >> 8; + arg[2] = ((readcount - 1) & 0xff0000) >> 16; + arg[3] = ((readcount - 1) & 0xff000000) >> 24; + if (send_longcommand(serial, CMD_CAPTURE_READCOUNT, arg) != SR_OK) + return SR_ERR; + arg[0] = ((delaycount - 1) & 0xff); + arg[1] = ((delaycount - 1) & 0xff00) >> 8; + arg[2] = ((delaycount - 1) & 0xff0000) >> 16; + arg[3] = ((delaycount - 1) & 0xff000000) >> 24; + if (send_longcommand(serial, CMD_CAPTURE_DELAYCOUNT, arg) != SR_OK) + return SR_ERR; + } else { + arg[0] = ((readcount - 1) & 0xff); + arg[1] = ((readcount - 1) & 0xff00) >> 8; + arg[2] = ((delaycount - 1) & 0xff); + arg[3] = ((delaycount - 1) & 0xff00) >> 8; + if (send_longcommand(serial, CMD_CAPTURE_SIZE, arg) != SR_OK) + return SR_ERR; + } /* Flag register. */ sr_dbg("Setting intpat %s, extpat %s, RLE %s, noise_filter %s, demux %s", @@ -561,33 +515,33 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, devc->cnt_bytes = devc->cnt_samples = devc->cnt_samples_rle = 0; memset(devc->sample, 0, 4); - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); + std_session_send_df_header(sdi); - serial_source_add(sdi->session, serial, G_IO_IN, -1, - ols_receive_data, cb_data); + /* If the device stops sending for longer than it takes to send a byte, + * that means it's finished. But wait at least 100 ms to be safe. + */ + serial_source_add(sdi->session, serial, G_IO_IN, 100, + ols_receive_data, (struct sr_dev_inst *)sdi); return SR_OK; } -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) +static int dev_acquisition_stop(struct sr_dev_inst *sdi) { - (void)cb_data; - abort_acquisition(sdi); return SR_OK; } -SR_PRIV struct sr_dev_driver ols_driver_info = { +static struct sr_dev_driver ols_driver_info = { .name = "ols", - .longname = "Openbench Logic Sniffer", + .longname = "Openbench Logic Sniffer & SUMP compatibles", .api_version = 1, - .init = init, - .cleanup = cleanup, + .init = std_init, + .cleanup = std_cleanup, .scan = scan, - .dev_list = dev_list, - .dev_clear = NULL, + .dev_list = std_dev_list, + .dev_clear = std_dev_clear, .config_get = config_get, .config_set = config_set, .config_list = config_list, @@ -595,5 +549,6 @@ SR_PRIV struct sr_dev_driver ols_driver_info = { .dev_close = std_serial_dev_close, .dev_acquisition_start = dev_acquisition_start, .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, + .context = NULL, }; +SR_REGISTER_DEV_DRIVER(ols_driver_info);