X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=blobdiff_plain;f=src%2Fhardware%2Fopenbench-logic-sniffer%2Fapi.c;h=7a5f22011caed4fed85701036af512b12dcfa5e0;hp=4f9ee04f2dcf7d9b0d1d127af604be412083155c;hb=f8fd84208d5cb2788ef0288ddb87da3581467a96;hpb=f992151332f79569feaa175f51cc4debabd271dd diff --git a/src/hardware/openbench-logic-sniffer/api.c b/src/hardware/openbench-logic-sniffer/api.c index 4f9ee04f..7a5f2201 100644 --- a/src/hardware/openbench-logic-sniffer/api.c +++ b/src/hardware/openbench-logic-sniffer/api.c @@ -36,7 +36,8 @@ static const uint32_t devopts[] = { 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, SR_CONF_RLE | SR_CONF_GET | SR_CONF_SET, @@ -47,6 +48,11 @@ static const int32_t trigger_matches[] = { SR_TRIGGER_ONE, }; +static const char* external_clock_edges[] = { + "rising", // positive edge + "falling" // negative edge +}; + #define STR_PATTERN_NONE "None" #define STR_PATTERN_EXTERNAL "External" #define STR_PATTERN_INTERNAL "Internal" @@ -91,10 +97,10 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) struct sr_dev_inst *sdi; struct sr_serial_dev_inst *serial; GSList *l; - int ret; + int num_read; unsigned int i; const char *conn, *serialcomm; - char buf[8]; + char buf[4] = { 0, 0, 0, 0 }; conn = serialcomm = NULL; for (l = options; l; l = l->next) { @@ -136,19 +142,22 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) g_usleep(RESPONSE_DELAY_US); if (serial_has_receive_data(serial) == 0) { - sr_dbg("Didn't get any reply."); + sr_dbg("Didn't get any ID reply."); return NULL; } - ret = serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4)); - if (ret != 4) { - sr_err("Invalid reply (expected 4 bytes, got %d).", ret); + 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; } 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]); + GString *id = sr_hexdump_new((uint8_t *)buf, num_read); + + sr_err("Invalid ID reply (got %s).", id->str); + + sr_hexdump_free(id); return NULL; } @@ -210,15 +219,23 @@ static int config_get(uint32_t key, GVariant **data, *data = g_variant_new_uint64(devc->limit_samples); break; case SR_CONF_PATTERN_MODE: - if (devc->flag_reg & FLAG_EXTERNAL_TEST_MODE) + if (devc->capture_flags & CAPTURE_FLAG_EXTERNAL_TEST_MODE) *data = g_variant_new_string(STR_PATTERN_EXTERNAL); - else if (devc->flag_reg & FLAG_INTERNAL_TEST_MODE) + else if (devc->capture_flags & CAPTURE_FLAG_INTERNAL_TEST_MODE) *data = g_variant_new_string(STR_PATTERN_INTERNAL); else *data = g_variant_new_string(STR_PATTERN_NONE); break; case SR_CONF_RLE: - *data = g_variant_new_boolean(devc->flag_reg & 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]); break; default: return SR_ERR_NA; @@ -257,10 +274,20 @@ static int config_set(uint32_t key, GVariant *data, case SR_CONF_EXTERNAL_CLOCK: if (g_variant_get_boolean(data)) { sr_info("Enabling external clock."); - devc->flag_reg |= FLAG_CLOCK_EXTERNAL; + devc->capture_flags |= CAPTURE_FLAG_CLOCK_EXTERNAL; } else { sr_info("Disabled external clock."); - devc->flag_reg &= ~FLAG_CLOCK_EXTERNAL; + devc->capture_flags &= ~CAPTURE_FLAG_CLOCK_EXTERNAL; + } + break; + case SR_CONF_CLOCK_EDGE: + stropt = g_variant_get_string(data, NULL); + if (!strcmp(stropt, external_clock_edges[1])) { + sr_info("Triggering on falling edge of external clock."); + devc->capture_flags |= CAPTURE_FLAG_INVERT_EXT_CLOCK; + } else { + sr_info("Triggering on rising edge of external clock."); + devc->capture_flags &= ~CAPTURE_FLAG_INVERT_EXT_CLOCK; } break; case SR_CONF_PATTERN_MODE: @@ -270,33 +297,33 @@ static int config_set(uint32_t key, GVariant *data, flag = 0x0000; } else if (!strcmp(stropt, STR_PATTERN_INTERNAL)) { sr_info("Enabling internal test mode."); - flag = FLAG_INTERNAL_TEST_MODE; + flag = CAPTURE_FLAG_INTERNAL_TEST_MODE; } else if (!strcmp(stropt, STR_PATTERN_EXTERNAL)) { sr_info("Enabling external test mode."); - flag = FLAG_EXTERNAL_TEST_MODE; + flag = CAPTURE_FLAG_EXTERNAL_TEST_MODE; } else { return SR_ERR; } - devc->flag_reg &= ~FLAG_INTERNAL_TEST_MODE; - devc->flag_reg &= ~FLAG_EXTERNAL_TEST_MODE; - devc->flag_reg |= flag; + devc->capture_flags &= ~CAPTURE_FLAG_INTERNAL_TEST_MODE; + devc->capture_flags &= ~CAPTURE_FLAG_EXTERNAL_TEST_MODE; + devc->capture_flags |= flag; break; case SR_CONF_SWAP: if (g_variant_get_boolean(data)) { sr_info("Enabling channel swapping."); - devc->flag_reg |= FLAG_SWAP_CHANNELS; + devc->capture_flags |= CAPTURE_FLAG_SWAP_CHANNELS; } else { sr_info("Disabling channel swapping."); - devc->flag_reg &= ~FLAG_SWAP_CHANNELS; + devc->capture_flags &= ~CAPTURE_FLAG_SWAP_CHANNELS; } break; case SR_CONF_RLE: if (g_variant_get_boolean(data)) { sr_info("Enabling RLE."); - devc->flag_reg |= FLAG_RLE; + devc->capture_flags |= CAPTURE_FLAG_RLE; } else { sr_info("Disabling RLE."); - devc->flag_reg &= ~FLAG_RLE; + devc->capture_flags &= ~CAPTURE_FLAG_RLE; } break; default: @@ -322,6 +349,9 @@ static int config_list(uint32_t key, GVariant **data, case SR_CONF_TRIGGER_MATCH: *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches)); break; + case SR_CONF_CLOCK_EDGE: + *data = std_gvar_array_str(ARRAY_AND_SIZE(external_clock_edges)); + break; case SR_CONF_PATTERN_MODE: *data = g_variant_new_strv(ARRAY_AND_SIZE(patterns)); break; @@ -329,7 +359,7 @@ static int config_list(uint32_t key, GVariant **data, if (!sdi) return SR_ERR_ARG; devc = sdi->priv; - if (devc->flag_reg & FLAG_RLE) + 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. */ @@ -338,10 +368,10 @@ 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++; } @@ -355,158 +385,21 @@ static int config_list(uint32_t key, GVariant **data, return SR_OK; } -static int set_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_TRIGGER_MASK + 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_TRIGGER_VALUE + 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_TRIGGER_CONFIG + 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 = (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_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_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", - devc->flag_reg & FLAG_INTERNAL_TEST_MODE ? "on": "off", - devc->flag_reg & FLAG_EXTERNAL_TEST_MODE ? "on": "off", - devc->flag_reg & FLAG_RLE ? "on" : "off", - devc->flag_reg & FLAG_FILTER ? "on": "off", - devc->flag_reg & FLAG_DEMUX ? "on" : "off"); - /* - * Enable/disable OLS channel groups in the flag register according - * to the channel mask. 1 means "disable channel". - */ - devc->flag_reg |= ~(ols_changrp_mask << 2) & 0x3c; - arg[0] = devc->flag_reg & 0xff; - arg[1] = devc->flag_reg >> 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_RUN) != SR_OK) + if (send_shortcommand(serial, CMD_ARM_BASIC_TRIGGER) != SR_OK) return SR_ERR; /* Reset all operational states. */