X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fopenbench-logic-sniffer%2Fapi.c;h=09ef065939c22e6511775c1bc3f25fa62ea6bd3a;hb=HEAD;hp=2815a50a9861ab5d5369a0bad4a0daad288122b4;hpb=f20c39d93337e22cf3ab509be2fa54632523a592;p=libsigrok.git diff --git a/src/hardware/openbench-logic-sniffer/api.c b/src/hardware/openbench-logic-sniffer/api.c index 2815a50a..09ef0659 100644 --- a/src/hardware/openbench-logic-sniffer/api.c +++ b/src/hardware/openbench-logic-sniffer/api.c @@ -25,6 +25,7 @@ static const uint32_t scanopts[] = { SR_CONF_CONN, SR_CONF_SERIALCOMM, + SR_CONF_PROBE_NAMES, }; static const uint32_t drvopts[] = { @@ -32,11 +33,12 @@ static const uint32_t drvopts[] = { }; static const uint32_t devopts[] = { + SR_CONF_CONN | SR_CONF_GET, 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, SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET, - SR_CONF_EXTERNAL_CLOCK | SR_CONF_SET, + SR_CONF_EXTERNAL_CLOCK | SR_CONF_GET | SR_CONF_SET, SR_CONF_CLOCK_EDGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_SWAP | SR_CONF_SET, @@ -48,9 +50,9 @@ static const int32_t trigger_matches[] = { SR_TRIGGER_ONE, }; -static const char* external_clock_edges[] = { - "rising", // positive edge - "falling" // negative edge +static const char *external_clock_edges[] = { + "rising", /* positive edge */ + "falling" /* negative edge */ }; #define STR_PATTERN_NONE "None" @@ -99,10 +101,13 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) GSList *l; int num_read; unsigned int i; - const char *conn, *serialcomm; + const char *conn, *serialcomm, *probe_names; char buf[4] = { 0, 0, 0, 0 }; + struct dev_context *devc; + size_t ch_max; conn = serialcomm = NULL; + probe_names = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { @@ -112,6 +117,9 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) case SR_CONF_SERIALCOMM: serialcomm = g_variant_get_string(src->data, NULL); break; + case SR_CONF_PROBE_NAMES: + probe_names = g_variant_get_string(src->data, NULL); + break; } } if (!conn) @@ -146,7 +154,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) return NULL; } - num_read = serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4)); + num_read = + serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4)); if (num_read < 0) { sr_err("Getting ID reply failed (%d).", num_read); return NULL; @@ -159,37 +168,59 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) sr_hexdump_free(id); return NULL; + } else { + sr_dbg("Successful detection, got '%c%c%c%c' (0x%02x 0x%02x 0x%02x 0x%02x).", + buf[0], buf[1], buf[2], buf[3], + buf[0], buf[1], buf[2], buf[3]); } - /* Definitely using the OLS protocol, check if it supports - * the metadata command. + /* + * Create common data structures (sdi, devc) here in the common + * code path. These further get filled in either from metadata + * which is gathered from the device, or from open coded generic + * fallback data which is kept in the driver source code. */ - send_shortcommand(serial, CMD_METADATA); + sdi = g_malloc0(sizeof(*sdi)); + sdi->status = SR_ST_INACTIVE; + sdi->inst_type = SR_INST_SERIAL; + sdi->conn = serial; + sdi->connection_id = g_strdup(serial->port); + devc = g_malloc0(sizeof(*devc)); + sdi->priv = devc; + devc->trigger_at_smpl = OLS_NO_TRIGGER; + devc->channel_names = sr_parse_probe_names(probe_names, + ols_channel_names, ARRAY_SIZE(ols_channel_names), + ARRAY_SIZE(ols_channel_names), &ch_max); + /* + * Definitely using the OLS protocol, check if it supports + * the metadata command. Otherwise assign generic values. + * Create as many sigrok channels as was determined when + * the device was probed. + */ + send_shortcommand(serial, CMD_METADATA); g_usleep(RESPONSE_DELAY_US); - if (serial_has_receive_data(serial) != 0) { /* Got metadata. */ - sdi = get_metadata(serial); + (void)ols_get_metadata(sdi); } else { - /* Not an OLS -- some other board that uses the sump protocol. */ + /* Not an OLS -- some other board using the SUMP protocol. */ sr_info("Device does not support metadata."); - 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(); + devc->max_channels = ch_max; + } + if (devc->max_channels && ch_max > devc->max_channels) + ch_max = devc->max_channels; + for (i = 0; i < ch_max; i++) { + sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, + devc->channel_names[i]); } /* Configure samplerate and divider. */ if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK) - sr_dbg("Failed to set default samplerate (%"PRIu64").", - DEFAULT_SAMPLERATE); - sdi->inst_type = SR_INST_SERIAL; - sdi->conn = serial; + sr_dbg("Failed to set default samplerate (%" PRIu64 ").", + DEFAULT_SAMPLERATE); serial_close(serial); @@ -197,7 +228,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) } static int config_get(uint32_t key, GVariant **data, - const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) + const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) { struct dev_context *devc; @@ -209,6 +241,11 @@ static int config_get(uint32_t key, GVariant **data, devc = sdi->priv; switch (key) { + case SR_CONF_CONN: + if (!sdi->conn || !sdi->connection_id) + return SR_ERR_NA; + *data = g_variant_new_string(sdi->connection_id); + break; case SR_CONF_SAMPLERATE: *data = g_variant_new_uint64(devc->cur_samplerate); break; @@ -227,11 +264,18 @@ static int config_get(uint32_t key, GVariant **data, *data = g_variant_new_string(STR_PATTERN_NONE); break; case SR_CONF_RLE: - *data = g_variant_new_boolean(devc->capture_flags & CAPTURE_FLAG_RLE ? TRUE : FALSE); + *data = g_variant_new_boolean( + devc->capture_flags & CAPTURE_FLAG_RLE ? TRUE : FALSE); + break; + case SR_CONF_EXTERNAL_CLOCK: + *data = g_variant_new_boolean( + devc->capture_flags & CAPTURE_FLAG_CLOCK_EXTERNAL + ? TRUE : FALSE); break; case SR_CONF_CLOCK_EDGE: *data = g_variant_new_string(external_clock_edges[ - devc->capture_flags & CAPTURE_FLAG_INVERT_EXT_CLOCK ? 1 : 0]); + devc->capture_flags & CAPTURE_FLAG_INVERT_EXT_CLOCK + ? 1 : 0]); break; default: return SR_ERR_NA; @@ -241,7 +285,8 @@ static int config_get(uint32_t key, GVariant **data, } static int config_set(uint32_t key, GVariant *data, - const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) + const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) { struct dev_context *devc; uint16_t flag; @@ -330,7 +375,8 @@ static int config_set(uint32_t key, GVariant *data, } static int config_list(uint32_t key, GVariant **data, - const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) + const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) { struct dev_context *devc; int num_ols_changrp, i; @@ -338,7 +384,8 @@ static int config_list(uint32_t key, GVariant **data, switch (key) { case SR_CONF_SCAN_OPTIONS: case SR_CONF_DEVICE_OPTIONS: - return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts); + return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, + devopts); case SR_CONF_SAMPLERATE: *data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates)); break; @@ -355,8 +402,6 @@ static int config_list(uint32_t key, GVariant **data, if (!sdi) return SR_ERR_ARG; devc = sdi->priv; - if (devc->capture_flags & CAPTURE_FLAG_RLE) - return SR_ERR_NA; if (devc->max_samples == 0) /* Device didn't specify sample memory size in metadata. */ return SR_ERR_NA; @@ -364,15 +409,15 @@ static int config_list(uint32_t key, GVariant **data, * Channel groups are turned off if no channels in that group are * enabled, making more room for samples for the enabled group. */ - ols_channel_mask(sdi); + uint32_t channel_mask = ols_channel_mask(sdi); num_ols_changrp = 0; for (i = 0; i < 4; i++) { - if (devc->channel_mask & (0xff << (i * 8))) + if (channel_mask & (0xff << (i * 8))) num_ols_changrp++; } - *data = std_gvar_tuple_u64(MIN_NUM_SAMPLES, - (num_ols_changrp) ? devc->max_samples / num_ols_changrp : MIN_NUM_SAMPLES); + *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; @@ -381,163 +426,18 @@ static int config_list(uint32_t key, GVariant **data, return SR_OK; } -static int set_basic_trigger(const struct sr_dev_inst *sdi, int stage) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - uint8_t cmd, arg[4]; - - devc = sdi->priv; - serial = sdi->conn; - - cmd = CMD_SET_BASIC_TRIGGER_MASK0 + stage * 4; - arg[0] = devc->trigger_mask[stage] & 0xff; - arg[1] = (devc->trigger_mask[stage] >> 8) & 0xff; - arg[2] = (devc->trigger_mask[stage] >> 16) & 0xff; - arg[3] = (devc->trigger_mask[stage] >> 24) & 0xff; - if (send_longcommand(serial, cmd, arg) != SR_OK) - return SR_ERR; - - cmd = CMD_SET_BASIC_TRIGGER_VALUE0 + stage * 4; - arg[0] = devc->trigger_value[stage] & 0xff; - arg[1] = (devc->trigger_value[stage] >> 8) & 0xff; - arg[2] = (devc->trigger_value[stage] >> 16) & 0xff; - arg[3] = (devc->trigger_value[stage] >> 24) & 0xff; - if (send_longcommand(serial, cmd, arg) != SR_OK) - return SR_ERR; - - cmd = CMD_SET_BASIC_TRIGGER_CONFIG0 + stage * 4; - arg[0] = arg[1] = arg[3] = 0x00; - arg[2] = stage; - if (stage == devc->num_stages) - /* Last stage, fire when this one matches. */ - arg[3] |= TRIGGER_START; - if (send_longcommand(serial, cmd, arg) != SR_OK) - return SR_ERR; - - return SR_OK; -} - static int dev_acquisition_start(const struct sr_dev_inst *sdi) { + int ret; struct dev_context *devc; struct sr_serial_dev_inst *serial; - uint32_t samplecount, readcount, delaycount; - uint8_t ols_changrp_mask, arg[4]; - int num_ols_changrp; - int ret, i; devc = sdi->priv; serial = sdi->conn; - ols_channel_mask(sdi); - - num_ols_changrp = 0; - ols_changrp_mask = 0; - for (i = 0; i < 4; i++) { - if (devc->channel_mask & (0xff << (i * 8))) { - ols_changrp_mask |= (1 << i); - num_ols_changrp++; - } - } - - /* - * Limit readcount to prevent reading past the end of the hardware - * buffer. Rather read too many samples than too few. - */ - samplecount = MIN(devc->max_samples / num_ols_changrp, devc->limit_samples); - readcount = (samplecount + 3) / 4; - - /* Basic triggers. */ - if (ols_convert_trigger(sdi) != SR_OK) { - sr_err("Failed to configure channels."); - 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_smpl = (readcount - delaycount) * 4 - devc->num_stages; - for (i = 0; i <= devc->num_stages; i++) { - sr_dbg("Setting OLS stage %d trigger.", i); - if ((ret = set_basic_trigger(sdi, i)) != SR_OK) - return ret; - } - } else { - /* No triggers configured, force trigger on first stage. */ - sr_dbg("Forcing trigger at stage 0."); - if ((ret = set_basic_trigger(sdi, 0)) != SR_OK) - return ret; - delaycount = readcount; - } - - /* Samplerate. */ - sr_dbg("Setting samplerate to %" PRIu64 "Hz (divider %u)", - devc->cur_samplerate, devc->cur_samplerate_divider); - arg[0] = devc->cur_samplerate_divider & 0xff; - arg[1] = (devc->cur_samplerate_divider & 0xff00) >> 8; - arg[2] = (devc->cur_samplerate_divider & 0xff0000) >> 16; - arg[3] = 0x00; - if (send_longcommand(serial, CMD_SET_DIVIDER, arg) != SR_OK) - return SR_ERR; - - /* 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); - - 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, %s clock%s", - devc->capture_flags & CAPTURE_FLAG_INTERNAL_TEST_MODE ? "on": "off", - devc->capture_flags & CAPTURE_FLAG_EXTERNAL_TEST_MODE ? "on": "off", - devc->capture_flags & CAPTURE_FLAG_RLE ? "on" : "off", - devc->capture_flags & CAPTURE_FLAG_NOISE_FILTER ? "on": "off", - devc->capture_flags & CAPTURE_FLAG_DEMUX ? "on" : "off", - devc->capture_flags & CAPTURE_FLAG_CLOCK_EXTERNAL ? "external" : "internal", - devc->capture_flags & CAPTURE_FLAG_CLOCK_EXTERNAL ? (devc->capture_flags & CAPTURE_FLAG_INVERT_EXT_CLOCK - ? " on falling edge" : "on rising edge") : ""); - - /* - * Enable/disable OLS channel groups in the flag register according - * to the channel mask. 1 means "disable channel". - */ - devc->capture_flags &= ~0x3c; - devc->capture_flags |= ~(ols_changrp_mask << 2) & 0x3c; - - /* RLE mode is always zero, for now. */ - - arg[0] = devc->capture_flags & 0xff; - arg[1] = devc->capture_flags >> 8; - arg[2] = arg[3] = 0x00; - if (send_longcommand(serial, CMD_SET_FLAGS, arg) != SR_OK) - return SR_ERR; + ret = ols_prepare_acquisition(sdi); + if (ret != SR_OK) + return ret; /* Start acquisition on the device. */ if (send_shortcommand(serial, CMD_ARM_BASIC_TRIGGER) != SR_OK) @@ -554,10 +454,8 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) /* 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; + return serial_source_add(sdi->session, serial, G_IO_IN, 100, + ols_receive_data, (struct sr_dev_inst *)sdi); } static int dev_acquisition_stop(struct sr_dev_inst *sdi)