diff --git a/src/hardware/openbench-logic-sniffer/api.c b/src/hardware/openbench-logic-sniffer/api.c index 7a5f22011..e78ff5d82 100644 --- a/src/hardware/openbench-logic-sniffer/api.c +++ b/src/hardware/openbench-logic-sniffer/api.c @@ -43,14 +43,22 @@ static const uint32_t devopts[] = { SR_CONF_RLE | SR_CONF_GET | SR_CONF_SET, }; -static const int32_t trigger_matches[] = { +static const int32_t basic_trigger_matches[] = { SR_TRIGGER_ZERO, SR_TRIGGER_ONE, }; -static const char* external_clock_edges[] = { - "rising", // positive edge - "falling" // negative edge +static const int32_t advanced_trigger_matches[] = { + SR_TRIGGER_ZERO, + SR_TRIGGER_ONE, + SR_TRIGGER_RISING, + SR_TRIGGER_FALLING, + SR_TRIGGER_EDGE, +}; + +static const char *external_clock_edges[] = { + "rising", /* positive edge */ + "falling" /* negative edge */ }; #define STR_PATTERN_NONE "None" @@ -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; @@ -181,13 +190,13 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) 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]); + ols_channel_names[i]); sdi->priv = ols_dev_new(); } /* Configure samplerate and divider. */ if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK) - sr_dbg("Failed to set default samplerate (%"PRIu64").", - DEFAULT_SAMPLERATE); + sr_dbg("Failed to set default samplerate (%" PRIu64 ").", + DEFAULT_SAMPLERATE); sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; @@ -197,7 +206,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; @@ -227,15 +237,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); + 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; @@ -245,7 +258,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; @@ -334,20 +348,27 @@ 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; + struct dev_context *devc = sdi ? sdi->priv : NULL; int num_ols_changrp, i; 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; case SR_CONF_TRIGGER_MATCH: - *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches)); + if (!devc) + return SR_ERR_ARG; + /* Advanced Triggering is only available on the Demon Core. */ + *data = devc->device_flags & DEVICE_FLAG_IS_DEMON_CORE + ? std_gvar_array_i32(ARRAY_AND_SIZE(advanced_trigger_matches)) + : std_gvar_array_i32(ARRAY_AND_SIZE(basic_trigger_matches)); break; case SR_CONF_CLOCK_EDGE: *data = std_gvar_array_str(ARRAY_AND_SIZE(external_clock_edges)); @@ -356,11 +377,8 @@ static int config_list(uint32_t key, GVariant **data, *data = g_variant_new_strv(ARRAY_AND_SIZE(patterns)); break; case SR_CONF_LIMIT_SAMPLES: - if (!sdi) + if (!devc) 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; @@ -375,8 +393,8 @@ static int config_list(uint32_t key, GVariant **data, 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; @@ -399,24 +417,27 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) return ret; /* Start acquisition on the device. */ - if (send_shortcommand(serial, CMD_ARM_BASIC_TRIGGER) != SR_OK) + if (send_shortcommand(serial, + devc->device_flags & DEVICE_FLAG_IS_DEMON_CORE ? + CMD_ARM_ADVANCED_TRIGGER : + CMD_ARM_BASIC_TRIGGER) != SR_OK) return SR_ERR; /* Reset all operational states. */ - devc->rle_count = devc->num_transfers = 0; - devc->num_samples = devc->num_bytes = 0; - devc->cnt_bytes = devc->cnt_samples = devc->cnt_samples_rle = 0; - memset(devc->sample, 0, 4); + devc->rle_count = 0; + devc->trigger_rle_at_smpl_from_end = OLS_NO_TRIGGER; + devc->cnt_samples = devc->raw_sample_size = 0; + devc->cnt_rx_bytes = devc->cnt_rx_raw_samples = 0; + memset(devc->raw_sample, 0, 4); std_session_send_df_header(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. + * that means it's finished. Since the device can be used over a slow + * network link, give it 10 seconds to reply. */ - 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, 10 * 1000, + ols_receive_data, (struct sr_dev_inst *)sdi); } static int dev_acquisition_stop(struct sr_dev_inst *sdi) diff --git a/src/hardware/openbench-logic-sniffer/protocol.c b/src/hardware/openbench-logic-sniffer/protocol.c index 9ac91982a..df34c690e 100644 --- a/src/hardware/openbench-logic-sniffer/protocol.c +++ b/src/hardware/openbench-logic-sniffer/protocol.c @@ -2,6 +2,7 @@ * This file is part of the libsigrok project. * * Copyright (C) 2013 Bert Vermeulen + * Copyright (C) 2011 Ian Davis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,8 +27,12 @@ struct ols_basic_trigger_desc { int num_stages; }; +static int +ols_convert_and_set_up_advanced_trigger(const struct sr_dev_inst *sdi, + int *num_stages); + SR_PRIV int send_shortcommand(struct sr_serial_dev_inst *serial, - uint8_t command) + uint8_t command) { char buf[1]; @@ -42,13 +47,13 @@ SR_PRIV int send_shortcommand(struct sr_serial_dev_inst *serial, return SR_OK; } -SR_PRIV int send_longcommand(struct sr_serial_dev_inst *serial, - uint8_t command, uint8_t *data) +SR_PRIV int send_longcommand(struct sr_serial_dev_inst *serial, uint8_t command, + uint8_t *data) { char buf[5]; - sr_dbg("Sending cmd 0x%.2x data 0x%.2x%.2x%.2x%.2x.", command, - data[0], data[1], data[2], data[3]); + sr_dbg("Sending cmd 0x%.2x data 0x%.2x%.2x%.2x%.2x.", command, data[0], + data[1], data[2], data[3]); buf[0] = command; buf[1] = data[0]; buf[2] = data[1]; @@ -63,8 +68,8 @@ SR_PRIV int send_longcommand(struct sr_serial_dev_inst *serial, return SR_OK; } -static int ols_send_longdata(struct sr_serial_dev_inst *serial, - uint8_t command, uint32_t value) +static int ols_send_longdata(struct sr_serial_dev_inst *serial, uint8_t command, + uint32_t value) { uint8_t data[4]; WL32(data, value); @@ -73,14 +78,28 @@ static int ols_send_longdata(struct sr_serial_dev_inst *serial, SR_PRIV int ols_send_reset(struct sr_serial_dev_inst *serial) { - unsigned int i; + int i, ret, delay_ms; + char dummy[16]; + + /* Drain all data so that the remote side is surely listening. */ + while ((ret = serial_read_nonblocking(serial, &dummy, 16)) > 0); + if (ret != SR_OK) + return ret; for (i = 0; i < 5; i++) { - if (send_shortcommand(serial, CMD_RESET) != SR_OK) - return SR_ERR; + if ((ret = send_shortcommand(serial, CMD_RESET)) != SR_OK) + return ret; } - return SR_OK; + /* + * Remove all stray output that arrived in between. + * This is likely to happen when RLE is being used because + * the device seems to return a bit more data than we request. + */ + delay_ms = serial_timeout(serial, 16); + while ((ret = serial_read_blocking(serial, &dummy, 16, delay_ms)) > 0); + + return ret; } /* Configures the channel mask based on which channels are enabled. */ @@ -96,7 +115,8 @@ SR_PRIV uint32_t ols_channel_mask(const struct sr_dev_inst *sdi) return channel_mask; } -static int convert_trigger(const struct sr_dev_inst *sdi, struct ols_basic_trigger_desc *ols_trigger) +static int ols_convert_basic_trigger(const struct sr_dev_inst *sdi, + struct ols_basic_trigger_desc *ols_trigger) { struct sr_trigger *trigger; struct sr_trigger_stage *stage; @@ -116,7 +136,7 @@ static int convert_trigger(const struct sr_dev_inst *sdi, struct ols_basic_trigg ols_trigger->num_stages = g_slist_length(trigger->stages); if (ols_trigger->num_stages > NUM_BASIC_TRIGGER_STAGES) { sr_err("This device only supports %d trigger stages.", - NUM_BASIC_TRIGGER_STAGES); + NUM_BASIC_TRIGGER_STAGES); return SR_ERR; } @@ -127,9 +147,21 @@ static int convert_trigger(const struct sr_dev_inst *sdi, struct ols_basic_trigg if (!match->channel->enabled) /* Ignore disabled channels with a trigger. */ continue; - ols_trigger->trigger_mask[stage->stage] |= 1 << match->channel->index; - if (match->match == SR_TRIGGER_ONE) - ols_trigger->trigger_value[stage->stage] |= 1 << match->channel->index; + + ols_trigger->trigger_mask[stage->stage] |= + 1 << match->channel->index; + switch (match->match) { + case SR_TRIGGER_ZERO: + break; + case SR_TRIGGER_ONE: + ols_trigger->trigger_value[stage->stage] |= + 1 << match->channel->index; + break; + default: + sr_err("Unsupported trigger type: %d", + match->match); + return SR_ERR; + } } } @@ -142,6 +174,7 @@ SR_PRIV struct dev_context *ols_dev_new(void) devc = g_malloc0(sizeof(struct dev_context)); devc->trigger_at_smpl = OLS_NO_TRIGGER; + devc->trigger_rle_at_smpl_from_end = OLS_NO_TRIGGER; return devc; } @@ -153,7 +186,7 @@ static void ols_channel_new(struct sr_dev_inst *sdi, int num_chan) for (i = 0; i < num_chan; i++) sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, - ols_channel_names[i]); + ols_channel_names[i]); devc->max_channels = num_chan; } @@ -216,13 +249,17 @@ SR_PRIV struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial) /* NULL-terminated string */ tmp_str = g_string_new(""); delay_ms = serial_timeout(serial, 1); - while (serial_read_blocking(serial, &tmp_c, 1, delay_ms) == 1 && tmp_c != '\0') + while (serial_read_blocking(serial, &tmp_c, 1, + delay_ms) == 1 && + tmp_c != '\0') g_string_append_c(tmp_str, tmp_c); - sr_dbg("Got metadata token 0x%.2x value '%s'.", key, tmp_str->str); + sr_dbg("Got metadata token 0x%.2x value '%s'.", key, + tmp_str->str); switch (key) { case METADATA_TOKEN_DEVICE_NAME: /* Device name */ - devname = g_string_append(devname, tmp_str->str); + devname = + g_string_append(devname, tmp_str->str); break; case METADATA_TOKEN_FPGA_VERSION: /* FPGA firmware version */ @@ -239,7 +276,8 @@ SR_PRIV struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial) g_string_append(version, tmp_str->str); break; default: - sr_info("ols: unknown token 0x%.2x: '%s'", key, tmp_str->str); + sr_info("ols: unknown token 0x%.2x: '%s'", key, + tmp_str->str); break; } g_string_free(tmp_str, TRUE); @@ -247,10 +285,12 @@ SR_PRIV struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial) case 1: /* 32-bit unsigned integer */ delay_ms = serial_timeout(serial, 4); - if (serial_read_blocking(serial, &tmp_int, 4, delay_ms) != 4) + if (serial_read_blocking(serial, &tmp_int, 4, + delay_ms) != 4) break; tmp_int = RB32(&tmp_int); - sr_dbg("Got metadata token 0x%.2x value 0x%.8x.", key, tmp_int); + sr_dbg("Got metadata token 0x%.2x value 0x%.8x.", key, + tmp_int); switch (key) { case METADATA_TOKEN_NUM_PROBES_LONG: /* Number of usable channels */ @@ -273,7 +313,8 @@ SR_PRIV struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial) devc->protocol_version = tmp_int; break; default: - sr_info("Unknown token 0x%.2x: 0x%.8x.", key, tmp_int); + sr_info("Unknown token 0x%.2x: 0x%.8x.", key, + tmp_int); break; } break; @@ -282,7 +323,8 @@ SR_PRIV struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial) delay_ms = serial_timeout(serial, 1); if (serial_read_blocking(serial, &tmp_c, 1, delay_ms) != 1) break; - sr_dbg("Got metadata token 0x%.2x value 0x%.2x.", key, tmp_c); + sr_dbg("Got metadata token 0x%.2x value 0x%.2x.", key, + tmp_c); switch (key) { case METADATA_TOKEN_NUM_PROBES_SHORT: /* Number of usable channels */ @@ -293,7 +335,8 @@ SR_PRIV struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial) devc->protocol_version = tmp_c; break; default: - sr_info("Unknown token 0x%.2x: 0x%.2x.", key, tmp_c); + sr_info("Unknown token 0x%.2x: 0x%.2x.", key, + tmp_c); break; } break; @@ -315,7 +358,7 @@ SR_PRIV struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial) } SR_PRIV int ols_set_samplerate(const struct sr_dev_inst *sdi, - const uint64_t samplerate) + const uint64_t samplerate) { struct dev_context *devc; @@ -327,7 +370,8 @@ SR_PRIV int ols_set_samplerate(const struct sr_dev_inst *sdi, sr_info("Enabling demux mode."); devc->capture_flags |= CAPTURE_FLAG_DEMUX; devc->capture_flags &= ~CAPTURE_FLAG_NOISE_FILTER; - devc->cur_samplerate_divider = (CLOCK_RATE * 2 / samplerate) - 1; + devc->cur_samplerate_divider = + (CLOCK_RATE * 2 / samplerate) - 1; } else { sr_info("Disabling demux mode."); devc->capture_flags &= ~CAPTURE_FLAG_DEMUX; @@ -342,22 +386,27 @@ SR_PRIV int ols_set_samplerate(const struct sr_dev_inst *sdi, if (devc->capture_flags & CAPTURE_FLAG_DEMUX) devc->cur_samplerate *= 2; if (devc->cur_samplerate != samplerate) - sr_info("Can't match samplerate %" PRIu64 ", using %" - PRIu64 ".", samplerate, devc->cur_samplerate); + sr_info("Can't match samplerate %" PRIu64 ", using %" PRIu64 + ".", + samplerate, devc->cur_samplerate); return SR_OK; } SR_PRIV void abort_acquisition(const struct sr_dev_inst *sdi) { - struct sr_serial_dev_inst *serial; + int ret; + struct sr_serial_dev_inst *serial = sdi->conn; - serial = sdi->conn; ols_send_reset(serial); - serial_source_remove(sdi->session, serial); + ret = serial_source_remove(sdi->session, serial); + if (ret != SR_OK) + sr_warn("Couldn't close serial port: %i", ret); - std_session_send_df_end(sdi); + ret = std_session_send_df_end(sdi); + if (ret != SR_OK) + sr_warn("Couldn't end session: %i", ret); } SR_PRIV int ols_receive_data(int fd, int revents, void *cb_data) @@ -368,9 +417,9 @@ SR_PRIV int ols_receive_data(int fd, int revents, void *cb_data) struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; uint32_t sample; - int num_changroups, offset, j; - unsigned int i; - unsigned char byte; + int num_bytes_read; + unsigned int num_changroups; + gboolean received_a_byte; (void)fd; @@ -378,71 +427,80 @@ SR_PRIV int ols_receive_data(int fd, int revents, void *cb_data) serial = sdi->conn; devc = sdi->priv; - if (devc->num_transfers == 0 && revents == 0) { + if (devc->cnt_rx_bytes == 0 && revents == 0) { /* Ignore timeouts as long as we haven't received anything */ return TRUE; } - if (devc->num_transfers++ == 0) { - devc->raw_sample_buf = g_try_malloc(devc->limit_samples * 4); - if (!devc->raw_sample_buf) { - sr_err("Sample buffer malloc failed."); - return FALSE; - } - /* fill with 1010... for debugging */ - memset(devc->raw_sample_buf, 0x82, devc->limit_samples * 4); - } - num_changroups = 0; - for (i = 0x20; i > 0x02; i >>= 1) { + for (uint16_t i = 0x20; i > 0x02; i >>= 1) { if ((devc->capture_flags & i) == 0) { num_changroups++; } } - if (revents == G_IO_IN && devc->num_samples < devc->limit_samples) { - if (serial_read_nonblocking(serial, &byte, 1) != 1) - return FALSE; - devc->cnt_bytes++; - - /* Ignore it if we've read enough. */ - if (devc->num_samples >= devc->limit_samples) - return TRUE; - - devc->sample[devc->num_bytes++] = byte; - sr_spew("Received byte 0x%.2x.", byte); - if (devc->num_bytes == num_changroups) { - devc->cnt_samples++; - devc->cnt_samples_rle++; + received_a_byte = FALSE; + while (revents == G_IO_IN && + (num_bytes_read = serial_read_nonblocking( + serial, devc->raw_sample + devc->raw_sample_size, + num_changroups - devc->raw_sample_size)) > 0) { + received_a_byte = TRUE; + devc->cnt_rx_bytes += num_bytes_read; + devc->raw_sample_size += num_bytes_read; + + sr_spew("Received data. Current sample: %.2x%.2x%.2x%.2x (%u bytes)", + devc->raw_sample[0], devc->raw_sample[1], + devc->raw_sample[2], devc->raw_sample[3], + devc->raw_sample_size); + + if (devc->raw_sample_size == num_changroups) { + unsigned int samples_to_write; + uint64_t new_sample_buf_size; + + devc->cnt_rx_raw_samples++; /* * Got a full sample. Convert from the OLS's little-endian * sample to the local format. */ - sample = devc->sample[0] | (devc->sample[1] << 8) \ - | (devc->sample[2] << 16) | (devc->sample[3] << 24); - sr_dbg("Received sample 0x%.*x.", devc->num_bytes * 2, sample); + sample = devc->raw_sample[0] | + (devc->raw_sample[1] << 8) | + (devc->raw_sample[2] << 16) | + (devc->raw_sample[3] << 24); + sr_dbg("Received sample 0x%.*x.", + devc->raw_sample_size * 2, sample); if (devc->capture_flags & CAPTURE_FLAG_RLE) { /* * In RLE mode the high bit of the sample is the * "count" flag, meaning this sample is the number * of times the previous sample occurred. */ - if (devc->sample[devc->num_bytes - 1] & 0x80) { + if (devc->raw_sample[devc->raw_sample_size - 1] & + 0x80) { /* Clear the high bit. */ - sample &= ~(0x80 << (devc->num_bytes - 1) * 8); - devc->rle_count = sample; - devc->cnt_samples_rle += devc->rle_count; - sr_dbg("RLE count: %u.", devc->rle_count); - devc->num_bytes = 0; - return TRUE; + sample &= ~(0x80 + << (devc->raw_sample_size - + 1) * 8); + devc->rle_count += sample; + sr_dbg("RLE count: %" PRIu64, + devc->rle_count); + devc->raw_sample_size = 0; + + if (devc->trigger_at_smpl != + OLS_NO_TRIGGER && + devc->trigger_rle_at_smpl_from_end == + OLS_NO_TRIGGER && + (unsigned int)devc->trigger_at_smpl == + devc->cnt_rx_raw_samples) + devc->trigger_rle_at_smpl_from_end = + devc->cnt_samples; + + /* + * Even on the rare occasion that the sampling ends with an RLE message, + * the acquisition should end immediately, without any timeout. + */ + goto process_and_forward; } } - devc->num_samples += devc->rle_count + 1; - if (devc->num_samples > devc->limit_samples) { - /* Save us from overrunning the buffer. */ - devc->rle_count -= devc->num_samples - devc->limit_samples; - devc->num_samples = devc->limit_samples; - } if (num_changroups < 4) { /* @@ -454,62 +512,134 @@ SR_PRIV int ols_receive_data(int fd, int revents, void *cb_data) * expecting a full 32-bit sample, based on * the number of channels. */ - j = 0; - memset(devc->tmp_sample, 0, 4); - for (i = 0; i < 4; i++) { - if (((devc->capture_flags >> 2) & (1 << i)) == 0) { + unsigned int j = 0; + uint8_t tmp_sample[4] = { 0, 0, 0, 0 }; + for (unsigned int i = 0; i < 4; i++) { + if (((devc->capture_flags >> 2) & + (1 << i)) == 0) { /* * This channel group was * enabled, copy from received * sample. */ - devc->tmp_sample[i] = devc->sample[j++]; - } else if (devc->capture_flags & CAPTURE_FLAG_DEMUX && (i > 2)) { - /* group 2 & 3 get added to 0 & 1 */ - devc->tmp_sample[i - 2] = devc->sample[j++]; + tmp_sample[i] = + devc->raw_sample[j++]; } } - memcpy(devc->sample, devc->tmp_sample, 4); + memcpy(devc->raw_sample, tmp_sample, 4); sr_spew("Expanded sample: 0x%.2hhx%.2hhx%.2hhx%.2hhx ", - devc->sample[3], devc->sample[2], devc->sample[1], devc->sample[0]); + devc->raw_sample[3], + devc->raw_sample[2], + devc->raw_sample[1], + devc->raw_sample[0]); } - /* - * the OLS sends its sample buffer backwards. - * store it in reverse order here, so we can dump - * this on the session bus later. - */ - offset = (devc->limit_samples - devc->num_samples) * 4; - for (i = 0; i <= devc->rle_count; i++) { - memcpy(devc->raw_sample_buf + offset + (i * 4), - devc->sample, 4); + samples_to_write = devc->rle_count + 1; + new_sample_buf_size = + 4 * MAX(devc->limit_samples, + devc->cnt_samples + samples_to_write); + + if (devc->sample_buf_size < new_sample_buf_size) { + uint64_t old_size = devc->sample_buf_size; + new_sample_buf_size *= 2; + devc->sample_buf = g_try_realloc( + devc->sample_buf, new_sample_buf_size); + devc->sample_buf_size = new_sample_buf_size; + + if (!devc->sample_buf) { + sr_err("Sample buffer malloc failed."); + return FALSE; + } + /* fill with 1010... for debugging */ + memset(devc->sample_buf + old_size, 0x82, + new_sample_buf_size - old_size); } - memset(devc->sample, 0, 4); - devc->num_bytes = 0; + + if (devc->capture_flags & CAPTURE_FLAG_RLE && + devc->trigger_at_smpl != OLS_NO_TRIGGER && + devc->trigger_rle_at_smpl_from_end == + OLS_NO_TRIGGER && + (unsigned int)devc->trigger_at_smpl == + devc->cnt_rx_raw_samples) + devc->trigger_rle_at_smpl_from_end = + devc->cnt_samples; + + for (uint64_t i = 0; i < samples_to_write; i++) + memcpy(devc->sample_buf + + (devc->cnt_samples + i) * 4, + devc->raw_sample, 4); + + devc->cnt_samples += samples_to_write; + + memset(devc->raw_sample, 0, 4); + devc->raw_sample_size = 0; devc->rle_count = 0; } - } else { + } + if (revents == G_IO_IN && !received_a_byte) + return FALSE; + +process_and_forward: + if (revents != G_IO_IN || + devc->cnt_rx_raw_samples == devc->limit_samples) { + unsigned int num_pre_trigger_samples; + + if (devc->cnt_rx_raw_samples != devc->limit_samples) + sr_warn("Finished with unexpected sample count. Timeout?"); + /* * This is the main loop telling us a timeout was reached, or * we've acquired all the samples we asked for -- we're done. * Send the (properly-ordered) buffer to the frontend. */ - sr_dbg("Received %d bytes, %d samples, %d decompressed samples.", - devc->cnt_bytes, devc->cnt_samples, - devc->cnt_samples_rle); + sr_dbg("Received %d bytes, %d raw samples, %" PRIu64 + " decompressed samples.", + devc->cnt_rx_bytes, devc->cnt_rx_raw_samples, + devc->cnt_samples); + + if (devc->capture_flags & CAPTURE_FLAG_RLE) { + if (devc->trigger_rle_at_smpl_from_end != + OLS_NO_TRIGGER) + devc->trigger_at_smpl = + devc->cnt_samples - + devc->trigger_rle_at_smpl_from_end; + else { + if (devc->trigger_at_smpl != OLS_NO_TRIGGER) + sr_warn("No trigger point found. Short read?"); + devc->trigger_at_smpl = OLS_NO_TRIGGER; + } + } + + /* + * The OLS sends its sample buffer backwards. + * Flip it back before sending it on the session bus. + */ + for (uint64_t i = 0; i < devc->cnt_samples / 2; i++) { + uint8_t temp[4]; + memcpy(temp, &devc->sample_buf[4 * i], 4); + memmove(&devc->sample_buf[4 * i], + &devc->sample_buf[4 * + (devc->cnt_samples - i - 1)], + 4); + memcpy(&devc->sample_buf[4 * + (devc->cnt_samples - i - 1)], + temp, 4); + } + if (devc->trigger_at_smpl != OLS_NO_TRIGGER) { /* * A trigger was set up, so we need to tell the frontend * about it. */ - if (devc->trigger_at_smpl > 0) { + if (devc->trigger_at_smpl > 0 && + (unsigned int)devc->trigger_at_smpl <= + devc->cnt_samples) { /* There are pre-trigger samples, send those first. */ packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = devc->trigger_at_smpl * 4; logic.unitsize = 4; - logic.data = devc->raw_sample_buf + - (devc->limit_samples - devc->num_samples) * 4; + logic.data = devc->sample_buf; sr_session_send(sdi, &packet); } @@ -518,17 +648,26 @@ SR_PRIV int ols_receive_data(int fd, int revents, void *cb_data) } /* Send post-trigger / all captured samples. */ - int num_pre_trigger_samples = devc->trigger_at_smpl == OLS_NO_TRIGGER - ? 0 : devc->trigger_at_smpl; - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.length = (devc->num_samples - num_pre_trigger_samples) * 4; - logic.unitsize = 4; - logic.data = devc->raw_sample_buf + (num_pre_trigger_samples + - devc->limit_samples - devc->num_samples) * 4; - sr_session_send(sdi, &packet); - - g_free(devc->raw_sample_buf); + num_pre_trigger_samples = + devc->trigger_at_smpl == OLS_NO_TRIGGER ? + 0 : + MIN((unsigned int)devc->trigger_at_smpl, + devc->cnt_samples); + if (devc->cnt_samples > num_pre_trigger_samples) { + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.length = + (devc->cnt_samples - num_pre_trigger_samples) * + 4; + logic.unitsize = 4; + logic.data = + devc->sample_buf + num_pre_trigger_samples * 4; + sr_session_send(sdi, &packet); + } + + g_free(devc->sample_buf); + devc->sample_buf = 0; + devc->sample_buf_size = 0; serial_flush(serial); abort_acquisition(sdi); @@ -537,7 +676,9 @@ SR_PRIV int ols_receive_data(int fd, int revents, void *cb_data) return TRUE; } -static int ols_set_basic_trigger_stage(const struct ols_basic_trigger_desc *trigger_desc, struct sr_serial_dev_inst *serial, int stage) +static int +ols_set_basic_trigger_stage(const struct ols_basic_trigger_desc *trigger_desc, + struct sr_serial_dev_inst *serial, int stage) { uint8_t cmd, arg[4]; @@ -552,7 +693,7 @@ static int ols_set_basic_trigger_stage(const struct ols_basic_trigger_desc *trig cmd = CMD_SET_BASIC_TRIGGER_CONFIG0 + stage * 4; arg[0] = arg[1] = arg[3] = 0x00; arg[2] = stage; - if (stage == trigger_desc->num_stages) + if (stage == trigger_desc->num_stages - 1) /* Last stage, fire when this one matches. */ arg[3] |= TRIGGER_START; if (send_longcommand(serial, cmd, arg) != SR_OK) @@ -561,12 +702,22 @@ static int ols_set_basic_trigger_stage(const struct ols_basic_trigger_desc *trig return SR_OK; } -SR_PRIV int ols_prepare_acquisition(const struct sr_dev_inst *sdi) { - int ret; +SR_PRIV int ols_prepare_acquisition(const struct sr_dev_inst *sdi) +{ + int ret, trigger_point; + uint32_t readcount, delaycount; struct dev_context *devc = sdi->priv; struct sr_serial_dev_inst *serial = sdi->conn; + /* + * 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 ((ret = ols_send_reset(serial)) != SR_OK) + return ret; + int num_changroups = 0; uint8_t changroup_mask = 0; uint32_t channel_mask = ols_channel_mask(sdi); @@ -578,76 +729,117 @@ SR_PRIV int ols_prepare_acquisition(const struct sr_dev_inst *sdi) { } /* - * Limit readcount to prevent reading past the end of the hardware - * buffer. Rather read too many samples than too few. + * Limit the number of samples to what the hardware can do. + * The sample count is always a multiple of four. */ - uint32_t samplecount = MIN(devc->max_samples / num_changroups, devc->limit_samples); - uint32_t readcount = (samplecount + 3) / 4; - uint32_t delaycount; - - /* Basic triggers. */ - struct ols_basic_trigger_desc basic_trigger_desc; - if (convert_trigger(sdi, &basic_trigger_desc) != SR_OK) { - sr_err("Failed to configure channels."); - return SR_ERR; - } - if (basic_trigger_desc.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) + devc->limit_samples = + (MIN(devc->max_samples / num_changroups, devc->limit_samples) + 3) + / 4 * 4; + readcount = devc->limit_samples / 4; + trigger_point = OLS_NO_TRIGGER; + + if (!(devc->device_flags & DEVICE_FLAG_IS_DEMON_CORE)) { + /* basic trigger only */ + struct ols_basic_trigger_desc basic_trigger_desc; + if (ols_convert_basic_trigger(sdi, &basic_trigger_desc) != + SR_OK) { + sr_err("Failed to configure channels."); return SR_ERR; - - delaycount = readcount * (1 - devc->capture_ratio / 100.0); - devc->trigger_at_smpl = (readcount - delaycount) * 4 - basic_trigger_desc.num_stages; - for (int i = 0; i <= basic_trigger_desc.num_stages; i++) { - sr_dbg("Setting OLS stage %d trigger.", i); - if ((ret = ols_set_basic_trigger_stage(&basic_trigger_desc, serial, i)) != SR_OK) + } + if (basic_trigger_desc.num_stages > 0) { + delaycount = + readcount * (1 - devc->capture_ratio / 100.0); + trigger_point = (readcount - delaycount) * 4 - 1; + for (int i = 0; i < basic_trigger_desc.num_stages; + i++) { + sr_dbg("Setting OLS stage %d trigger.", i); + ret = ols_set_basic_trigger_stage( + &basic_trigger_desc, serial, i); + if (ret != SR_OK) + return ret; + } + } else { + /* No triggers configured, force trigger on first stage. */ + sr_dbg("Forcing trigger at stage 0."); + basic_trigger_desc.num_stages = 1; + if ((ret = ols_set_basic_trigger_stage( + &basic_trigger_desc, serial, 0)) != SR_OK) return ret; + + delaycount = readcount; } } else { - /* No triggers configured, force trigger on first stage. */ - sr_dbg("Forcing trigger at stage 0."); - if ((ret = ols_set_basic_trigger_stage(&basic_trigger_desc, serial, 0)) != SR_OK) - return ret; - delaycount = readcount; + /* advanced trigger setup */ + gboolean will_trigger = FALSE; + if (ols_convert_and_set_up_advanced_trigger( + sdi, &will_trigger) != SR_OK) { + sr_err("Advanced trigger setup failed."); + return SR_ERR; + } + + if (will_trigger) { + delaycount = + readcount * (1 - devc->capture_ratio / 100.0); + trigger_point = (readcount - delaycount) * 4; + } else + delaycount = readcount; } + /* + * To determine the proper trigger sample position in RLE mode, a reverse + * lookup is needed while reading the samples. Set up the right trigger + * point in that case or the normal trigger point for non-RLE acquisitions. + */ + devc->trigger_at_smpl = + trigger_point == OLS_NO_TRIGGER ? + OLS_NO_TRIGGER : + devc->capture_flags & CAPTURE_FLAG_RLE ? + (int)devc->limit_samples - trigger_point : + trigger_point; + /* Samplerate. */ sr_dbg("Setting samplerate to %" PRIu64 "Hz (divider %u)", - devc->cur_samplerate, devc->cur_samplerate_divider); - if (ols_send_longdata(serial, CMD_SET_DIVIDER, devc->cur_samplerate_divider & 0x00FFFFFF) != SR_OK) + devc->cur_samplerate, devc->cur_samplerate_divider); + if (ols_send_longdata(serial, CMD_SET_DIVIDER, + devc->cur_samplerate_divider & 0x00FFFFFF) != 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); + (readcount - 1) * 4, (delaycount - 1) * 4); if (devc->max_samples > 256 * 1024) { - if (ols_send_longdata(serial, CMD_CAPTURE_READCOUNT, readcount-1) != SR_OK) + if (ols_send_longdata(serial, CMD_CAPTURE_READCOUNT, + readcount - 1) != SR_OK) return SR_ERR; - if (ols_send_longdata(serial, CMD_CAPTURE_DELAYCOUNT, delaycount-1) != SR_OK) + if (ols_send_longdata(serial, CMD_CAPTURE_DELAYCOUNT, + delaycount - 1) != SR_OK) return SR_ERR; } else { uint8_t arg[4]; - WL16(&arg[0], readcount-1); - WL16(&arg[2], delaycount-1); + WL16(&arg[0], readcount - 1); + WL16(&arg[2], delaycount - 1); 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") : ""); + 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 @@ -656,10 +848,554 @@ SR_PRIV int ols_prepare_acquisition(const struct sr_dev_inst *sdi) { devc->capture_flags &= ~0x3c; devc->capture_flags |= ~(changroup_mask << 2) & 0x3c; - /* RLE mode is always zero, for now. */ + /* + * Demon Core supports RLE mode 3. In this mode, an arbitrary number of + * consecutive RLE messages can occur. The value is only sent whenever + * it changes. In contrast, mode 0 repeats the value after every RLE + * message, even if it didn't change. + */ + if (devc->device_flags & DEVICE_FLAG_IS_DEMON_CORE) + devc->capture_flags |= CAPTURE_FLAG_RLEMODE0 | + CAPTURE_FLAG_RLEMODE1; + else + devc->capture_flags &= + ~(CAPTURE_FLAG_RLEMODE0 | CAPTURE_FLAG_RLEMODE1); if (ols_send_longdata(serial, CMD_SET_FLAGS, devc->capture_flags) != SR_OK) return SR_ERR; return SR_OK; } + +/* set up a level trigger stage to trigger when (input & mask) == target */ +static int ols_set_advanced_level_trigger( + struct sr_serial_dev_inst *serial, + uint8_t num_trigger_term, /* 0-9 for trigger terms a-j */ + uint32_t target, uint32_t mask) +{ + int ret; + uint32_t lutmask = 1; + uint32_t lutbits[4] = { 0, 0, 0, 0 }; + + for (uint32_t i = 0; i < 16; ++i) { + if (((i ^ ((target >> 0) & 0xF)) & ((mask >> 0) & 0xF)) == 0) + lutbits[0] |= lutmask; + if (((i ^ ((target >> 4) & 0xF)) & ((mask >> 4) & 0xF)) == 0) + lutbits[0] |= (lutmask << 16); + if (((i ^ ((target >> 8) & 0xF)) & ((mask >> 8) & 0xF)) == 0) + lutbits[1] |= lutmask; + if (((i ^ ((target >> 12) & 0xF)) & ((mask >> 12) & 0xF)) == 0) + lutbits[1] |= (lutmask << 16); + if (((i ^ ((target >> 16) & 0xF)) & ((mask >> 16) & 0xF)) == 0) + lutbits[2] |= lutmask; + if (((i ^ ((target >> 20) & 0xF)) & ((mask >> 20) & 0xF)) == 0) + lutbits[2] |= (lutmask << 16); + if (((i ^ ((target >> 24) & 0xF)) & ((mask >> 24) & 0xF)) == 0) + lutbits[3] |= lutmask; + if (((i ^ ((target >> 28) & 0xF)) & ((mask >> 28) & 0xF)) == 0) + lutbits[3] |= (lutmask << 16); + lutmask <<= 1; + } + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_SEL, 0x20 + (num_trigger_term % 10)); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, lutbits[3]); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, lutbits[2]); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, lutbits[1]); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, lutbits[0]); + if (ret != SR_OK) + return ret; + + return SR_OK; +} + +#define OLS_ADV_TRIG_EDGERISE0 0x0A0A +#define OLS_ADV_TRIG_EDGERISE1 0x00CC +#define OLS_ADV_TRIG_EDGEFALL0 0x5050 +#define OLS_ADV_TRIG_EDGEFALL1 0x3300 +#define OLS_ADV_TRIG_EDGEBOTH0 (OLS_ADV_TRIG_EDGERISE0 | OLS_ADV_TRIG_EDGEFALL0) +#define OLS_ADV_TRIG_EDGEBOTH1 (OLS_ADV_TRIG_EDGERISE1 | OLS_ADV_TRIG_EDGEFALL1) +#define OLS_ADV_TRIG_EDGENEITHER0 (~OLS_ADV_TRIG_EDGEBOTH0 & 0xFFFF) /* means neither rise nor fall: constant signal */ +#define OLS_ADV_TRIG_EDGENEITHER1 (~OLS_ADV_TRIG_EDGEBOTH1 & 0xFFFF) + +/* Set up edge trigger LUTs. + * + * All edge triggers of one unit are ORed together, not ANDed. This + * differs from level triggers, where all levels have to be met at the + * same time. This code is at least consistent in that it also ORs together + * pairs of edge triggers. + */ +static int +ols_set_advanced_edge_trigger(struct sr_serial_dev_inst *serial, + int edgesel, /* which edge trigger unit, 0 or 1 */ + uint32_t rising_edge, uint32_t falling_edge, + uint32_t neither_edge) +{ + int ret; + uint32_t lutbits = 0; + uint32_t bitmask = 0x80000000; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_SEL, + 0x34 + (edgesel & 1)); + if (ret != SR_OK) + return ret; + + for (unsigned int i = 0; i < 16; i = i + 1) { + /* Evaluate indata bit1... */ + if (neither_edge & bitmask) + lutbits |= OLS_ADV_TRIG_EDGENEITHER1; + else { + if (rising_edge & bitmask) + lutbits |= OLS_ADV_TRIG_EDGERISE1; + if (falling_edge & bitmask) + lutbits |= OLS_ADV_TRIG_EDGEFALL1; + } + bitmask >>= 1; + + /* Evaluate indata bit0... */ + if (neither_edge & bitmask) + lutbits |= OLS_ADV_TRIG_EDGENEITHER0; + else { + if (rising_edge & bitmask) + lutbits |= OLS_ADV_TRIG_EDGERISE0; + if (falling_edge & bitmask) + lutbits |= OLS_ADV_TRIG_EDGEFALL0; + } + bitmask >>= 1; + + if ((i & 1) == 0) + lutbits <<= 16; + else { + /* write total of 256 bits */ + ret = ols_send_longdata( + serial, CMD_SET_ADVANCED_TRIG_WRITE, lutbits); + if (ret != SR_OK) + return ret; + lutbits = 0; + } + } + + return SR_OK; +} + +static int ols_set_advanced_trigger_timer(struct sr_serial_dev_inst *serial, + int timersel, /* 0 or 1 */ + uint64_t count_10ns) +{ + int ret; + + ret = ols_send_longdata( + serial, CMD_SET_ADVANCED_TRIG_SEL, 0x38 + (timersel & 1) * 2); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata( + serial, CMD_SET_ADVANCED_TRIG_WRITE, count_10ns & 0xFFFFFFFF); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata( + serial, CMD_SET_ADVANCED_TRIG_SEL, 0x39 + (timersel & 1) * 2); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata( + serial, CMD_SET_ADVANCED_TRIG_WRITE, count_10ns >> 32); + if (ret != SR_OK) + return ret; + + return SR_OK; +} + +#define OLS_ADV_TRIG_STATETERM_HIT 0 +#define OLS_ADV_TRIG_STATETERM_ELSE 1 +#define OLS_ADV_TRIG_STATETERM_CAPTURE 2 + +#define OLS_ADV_TRIG_OP_NOP 0 +#define OLS_ADV_TRIG_OP_ANY 1 +#define OLS_ADV_TRIG_OP_AND 2 +#define OLS_ADV_TRIG_OP_NAND 3 +#define OLS_ADV_TRIG_OP_OR 4 +#define OLS_ADV_TRIG_OP_NOR 5 +#define OLS_ADV_TRIG_OP_XOR 6 +#define OLS_ADV_TRIG_OP_NXOR 7 +#define OLS_ADV_TRIG_OP_A 8 +#define OLS_ADV_TRIG_OP_B 9 +/* NOP ANY AND NAND OR NOR XOR NXOR A B */ +static const uint32_t pairvalue[] = {0x0000, 0xFFFF, 0x8000, 0x7FFF, 0xF888, 0x0777, 0x7888, 0x8777, 0x8888, 0xF000}; +static const uint32_t midvalue[] = {0x0000, 0xFFFF, 0x8000, 0x7FFF, 0xFFFE, 0x0001, 0x0116, 0xFEE9, 0xEEEE, 0xFFF0}; +static const uint32_t finalvalue[] = {0x0000, 0xFFFF, 0x0008, 0x0007, 0x000E, 0x0001, 0x0006, 0x0009, 0x0002, 0x0004}; + +/* + * Trigger input summing stage: Combines different inputs in arbitrary ways. + * Keep in mind that all primary inputs (a, edge etc.) output a pair of bits per + * input. That's why those LUTs have 2 inputs, whereas the mid LUTs have + * 4 inputs. Only half of the final LUT is used. + */ +static int ols_set_advanced_trigger_sum( + struct sr_serial_dev_inst *serial, + int statenum, /* 0-15 */ + int stateterm, /* 0: hit, 1: else, 2: capture */ + int op_ab, + int op_c_range1, + int op_d_edge1, + int op_e_timer1, + int op_fg, + int op_h_range2, + int op_i_edge2, + int op_j_timer2, + int op_mid1, /* sums up a, b, c, range1, d, edge1, e, timer1 */ + int op_mid2, /* sums up f, g, h, range2, i, edge2, j, timer2 */ + int op_final) /* sums up mid1, mid2 */ +{ + int ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_SEL, + 0x40 + (statenum * 4) + stateterm); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, + finalvalue[op_final]); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, + (midvalue[op_mid2] << 16) | midvalue[op_mid1]); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, + (pairvalue[op_j_timer2] << 16) | pairvalue[op_i_edge2]); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, + (pairvalue[op_h_range2] << 16) | pairvalue[op_fg]); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, + (pairvalue[op_e_timer1] << 16) | pairvalue[op_d_edge1]); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, + (pairvalue[op_c_range1] << 16) | pairvalue[op_ab]); + if (ret != SR_OK) + return ret; + + return SR_OK; +} + +#define TRIGSTATE_STATENUM_MASK 0xF +#define TRIGSTATE_OBTAIN_MASK 0x000FFFFF +#define TRIGSTATE_ELSE_BITOFS 20 +#define TRIGSTATE_STOLS_ADV_TRIG_OP_TIMER0 0x01000000 +#define TRIGSTATE_STOLS_ADV_TRIG_OP_TIMER1 0x02000000 +#define TRIGSTATE_CLEAR_TIMER0 0x04000000 +#define TRIGSTATE_CLEAR_TIMER1 0x08000000 +#define TRIGSTATE_START_TIMER0 0x10000000 +#define TRIGSTATE_START_TIMER1 0x20000000 +#define TRIGSTATE_TRIGGER_FLAG 0x40000000 +#define TRIGSTATE_LASTSTATE 0x80000000 + +static int ols_set_advanced_trigger_state( + struct sr_serial_dev_inst *serial, + uint8_t statenum, /* 0 to 15 */ + gboolean last_state, + gboolean set_trigger, + uint8_t start_timer, /* bit0=timer1, bit1=timer2 */ + uint8_t stop_timer, /* bit0=timer1, bit1=timer2 */ + uint8_t clear_timer, /* bit0=timer1, bit1=timer2 */ + uint8_t else_state, /* 0 to 15 */ + uint32_t obtain_count) +{ + int ret; + + uint32_t value = ((else_state & TRIGSTATE_STATENUM_MASK) + << TRIGSTATE_ELSE_BITOFS) | + (obtain_count & TRIGSTATE_OBTAIN_MASK); + if (last_state) value |= TRIGSTATE_LASTSTATE; + if (set_trigger) value |= TRIGSTATE_TRIGGER_FLAG; + if (start_timer & 1) value |= TRIGSTATE_START_TIMER0; + if (start_timer & 2) value |= TRIGSTATE_START_TIMER1; + if (stop_timer & 1) value |= TRIGSTATE_STOLS_ADV_TRIG_OP_TIMER0; + if (stop_timer & 2) value |= TRIGSTATE_STOLS_ADV_TRIG_OP_TIMER1; + if (clear_timer & 1) value |= TRIGSTATE_CLEAR_TIMER0; + if (clear_timer & 2) value |= TRIGSTATE_CLEAR_TIMER1; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_SEL, + statenum & TRIGSTATE_STATENUM_MASK); + if (ret != SR_OK) + return ret; + + ret = ols_send_longdata(serial, CMD_SET_ADVANCED_TRIG_WRITE, value); + if (ret != SR_OK) + return ret; + + return SR_OK; +} + +static int ols_set_advanced_trigger_sums_and_stages( + struct sr_serial_dev_inst *serial, int ols_stage, int sum_inputs[8], + gboolean is_last_stage, gboolean start_timer0) +{ + int ret; + + /* + * Hit only when all inputs are true. Always capture for pre-trigger and + * acquisition. Never execute the "Else" action, since we advance trigger + * stages implicity via hits. + */ + ret = ols_set_advanced_trigger_sum(serial, ols_stage, OLS_ADV_TRIG_STATETERM_HIT, + sum_inputs[0], sum_inputs[1], sum_inputs[2], sum_inputs[3], + sum_inputs[4], sum_inputs[5], sum_inputs[6], sum_inputs[7], + OLS_ADV_TRIG_OP_AND, OLS_ADV_TRIG_OP_AND, + OLS_ADV_TRIG_OP_AND); + if (ret != SR_OK) + return ret; + + ret = ols_set_advanced_trigger_sum(serial, ols_stage, OLS_ADV_TRIG_STATETERM_CAPTURE, + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, + OLS_ADV_TRIG_OP_AND, OLS_ADV_TRIG_OP_AND, + OLS_ADV_TRIG_OP_ANY); + if (ret != SR_OK) + return ret; + + ret = ols_set_advanced_trigger_sum(serial, ols_stage, OLS_ADV_TRIG_STATETERM_ELSE, + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, + OLS_ADV_TRIG_OP_AND, OLS_ADV_TRIG_OP_AND, + OLS_ADV_TRIG_OP_NOP); + if (ret != SR_OK) + return ret; + + /* + * Tell the state machine to move to the next stage on a hit by not + * setting the trigger flag. The last stage executes the trigger. + */ + ret = ols_set_advanced_trigger_state(serial, ols_stage, is_last_stage, + is_last_stage, + start_timer0 ? 1 : 0, 0, 0, 0, 0); + if (ret != SR_OK) + return ret; + + return SR_OK; +} + +static int +ols_convert_and_set_up_advanced_trigger(const struct sr_dev_inst *sdi, + gboolean *will_trigger) +{ + int ret; + + struct sr_serial_dev_inst *serial = sdi->conn; + struct dev_context *devc = sdi->priv; + + int ols_stage = 0; + + if (devc->capture_ratio > 0) { + /* + * We need to set up a timer to ensure enough samples are captured to + * fulfill the pre-trigger ratio. In RLE mode, this is not necessarily + * true. It would be possible to wait longer, to ensure that enough + * compressed samples are captured, but this could take ages and is + * probably not what the user wants. + */ + + uint64_t effective_divider = + devc->capture_flags & CAPTURE_FLAG_DEMUX ? + (devc->cur_samplerate_divider + 1) / 2 : + (devc->cur_samplerate_divider + 1); + uint64_t pretrigger_10ns_ticks = + devc->limit_samples * effective_divider * + devc->capture_ratio / 100 /* percent */; + sr_dbg("Inserting pre-trigger delay of %" PRIu64 "0 ns", + pretrigger_10ns_ticks); + + if ((ret = ols_set_advanced_trigger_timer( + serial, 0, pretrigger_10ns_ticks)) != SR_OK) + return ret; + + int sum_inputs[8] = { + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY + }; + + /* first stage: start timer, advance immediately to second stage */ + if ((ret = ols_set_advanced_trigger_sums_and_stages( + serial, ols_stage++, sum_inputs, FALSE, TRUE)) != SR_OK) + return ret; + + /* second stage: wait until timer expires */ + sum_inputs[3] = OLS_ADV_TRIG_OP_B; + if ((ret = ols_set_advanced_trigger_sums_and_stages( + serial, ols_stage++, sum_inputs, FALSE, TRUE)) != SR_OK) + return ret; + } + + struct sr_trigger *trigger; + if (!(trigger = sr_session_trigger_get(sdi->session))) { + *will_trigger = FALSE; + + /* Set up immediate trigger to capture and trigger regardless of any input. */ + int sum_inputs[8] = { + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY + }; + return ols_set_advanced_trigger_sums_and_stages( + serial, ols_stage, sum_inputs, TRUE, FALSE); + } + + int num_req_trigger_stages = g_slist_length(trigger->stages); + if (ols_stage + num_req_trigger_stages > NUM_ADVANCED_TRIGGER_STAGES) { + sr_err("Too many trigger stages: %d requested + %d internal > %d available", + num_req_trigger_stages, ols_stage, + NUM_ADVANCED_TRIGGER_STAGES); + return SR_ERR; + } + + sr_dbg("Setting OLS advanced trigger for %i stages", + num_req_trigger_stages); + + const int last_stage = ols_stage + num_req_trigger_stages - 1; + int num_stages_with_level_trigger = 0; + int num_stages_with_edge_trigger = 0; + for (const GSList *l = trigger->stages; l; l = l->next) { + struct sr_trigger_stage *stage = l->data; + + /* channel bit masks: */ + uint32_t level_mask = 0; + uint32_t level_value = 0; + uint32_t edge_rising = 0; + uint32_t edge_falling = 0; + + int current_level_term = -1; + int current_edge_term = -1; + + for (const GSList *m = stage->matches; m; m = m->next) { + struct sr_trigger_match *match = m->data; + if (!match->channel->enabled) + /* Ignore disabled channels with a trigger. */ + continue; + + int chan_bit = 1 << match->channel->index; + switch (match->match) { + case SR_TRIGGER_ZERO: + level_mask |= chan_bit; + break; + case SR_TRIGGER_ONE: + level_mask |= chan_bit; + level_value |= chan_bit; + break; + case SR_TRIGGER_RISING: + edge_rising |= chan_bit; + break; + case SR_TRIGGER_FALLING: + edge_falling |= chan_bit; + break; + case SR_TRIGGER_EDGE: + edge_rising |= chan_bit; + edge_falling |= chan_bit; + break; + default: + sr_err("Unsupported trigger type: %d", + match->match); + return SR_ERR; + } + } + + if (level_mask) { + if (num_stages_with_level_trigger >= + NUM_ADVANCED_LEVEL_TRIGGERS) { + sr_err("Too many level triggers, only %d supported.", + NUM_ADVANCED_LEVEL_TRIGGERS); + return SR_ERR; + } + + ols_set_advanced_level_trigger( + serial, num_stages_with_level_trigger, + level_value, level_mask); + current_level_term = num_stages_with_level_trigger; + ++num_stages_with_level_trigger; + } + + if (edge_rising | edge_falling) { + if (num_stages_with_edge_trigger >= + NUM_ADVANCED_EDGE_TRIGGERS) { + sr_err("Too many edge triggers, only %d supported.", + NUM_ADVANCED_EDGE_TRIGGERS); + return SR_ERR; + } + + ols_set_advanced_edge_trigger( + serial, num_stages_with_edge_trigger, + edge_rising, edge_falling, 0U); + current_edge_term = num_stages_with_edge_trigger; + ++num_stages_with_edge_trigger; + } + + gboolean is_last_stage = ols_stage == last_stage; + + /* map stage indices to the input pairs and pair position in the summing unit: */ + int sum_inputs[8] = { + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, + OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY, OLS_ADV_TRIG_OP_ANY + }; + #define A OLS_ADV_TRIG_OP_A + #define B OLS_ADV_TRIG_OP_B + static const int level_stage_to_input_pair[10] = {0, 0, 1, 2, 3, 4, 4, 5, 6, 7}; + static const int level_stage_to_input_ab[10] = {A, B, A, A, A, A, B, A, A, A}; + static const int edge_stage_to_input_pair[2] = {2, 6}; + #undef A + #undef B + + int level_summing_input = current_level_term >= 0 + ? level_stage_to_input_pair[current_level_term] : -1 ; + int edge_summing_input = current_edge_term >= 0 + ? edge_stage_to_input_pair[current_edge_term] : -1; + + if (level_summing_input >= 0) + sum_inputs[level_summing_input] = + level_stage_to_input_ab[current_level_term]; + if (edge_summing_input >= 0) + sum_inputs[edge_summing_input] = OLS_ADV_TRIG_OP_B; + + /* If level and edge input end up in on the same input pair, and them together: */ + if (level_summing_input >= 0 && + level_summing_input == edge_summing_input) + sum_inputs[level_summing_input] = OLS_ADV_TRIG_OP_AND; + + sr_spew(" Stage %d, lvl mask %.4x, edge %.4x, level term %d, " + "edge term %d -> " + "trigger sum %.4X %.4X %.4X %.4X %.4X %.4X %.4X %.4X", + ols_stage, level_mask, (edge_falling | edge_rising), + current_level_term, current_edge_term, sum_inputs[0], + sum_inputs[1], sum_inputs[2], sum_inputs[3], + sum_inputs[4], sum_inputs[5], sum_inputs[6], + sum_inputs[7]); + + ret = ols_set_advanced_trigger_sums_and_stages( + serial, ols_stage, sum_inputs, is_last_stage, 0); + if (ret != SR_OK) + return ret; + + ++ols_stage; + } + + *will_trigger = ols_stage > 0 ? TRUE : FALSE; + return SR_OK; +} diff --git a/src/hardware/openbench-logic-sniffer/protocol.h b/src/hardware/openbench-logic-sniffer/protocol.h index 6b8c2422b..f96afd39d 100644 --- a/src/hardware/openbench-logic-sniffer/protocol.h +++ b/src/hardware/openbench-logic-sniffer/protocol.h @@ -28,10 +28,13 @@ #define LOG_PREFIX "openbench-logic-sniffer" -#define NUM_BASIC_TRIGGER_STAGES 4 -#define CLOCK_RATE SR_MHZ(100) -#define MIN_NUM_SAMPLES 4 -#define DEFAULT_SAMPLERATE SR_KHZ(200) +#define NUM_BASIC_TRIGGER_STAGES 4 +#define NUM_ADVANCED_TRIGGER_STAGES 15 +#define NUM_ADVANCED_EDGE_TRIGGERS 2 +#define NUM_ADVANCED_LEVEL_TRIGGERS 10 +#define CLOCK_RATE SR_MHZ(100) +#define MIN_NUM_SAMPLES 4 +#define DEFAULT_SAMPLERATE SR_KHZ(200) /* Command opcodes */ #define CMD_RESET 0x00 @@ -112,34 +115,34 @@ struct dev_context { uint64_t limit_samples; uint64_t capture_ratio; int trigger_at_smpl; + int trigger_rle_at_smpl_from_end; uint16_t capture_flags; - unsigned int num_transfers; - unsigned int num_samples; - int num_bytes; - int cnt_bytes; - int cnt_samples; - int cnt_samples_rle; - - unsigned int rle_count; - unsigned char sample[4]; - unsigned char tmp_sample[4]; - unsigned char *raw_sample_buf; + unsigned int cnt_rx_bytes; /* number of bytes received */ + unsigned int raw_sample_size; /* valid bytes in sample[4] */ + unsigned char + raw_sample[4]; /* raw sample, assembled from received bytes */ + unsigned int cnt_rx_raw_samples; /* number of raw samples received */ + + uint64_t rle_count; + unsigned char *sample_buf; + unsigned int sample_buf_size; + uint64_t cnt_samples; /* number of final samples in sample_buf */ }; SR_PRIV extern const char *ols_channel_names[]; SR_PRIV int send_shortcommand(struct sr_serial_dev_inst *serial, - uint8_t command); -SR_PRIV int send_longcommand(struct sr_serial_dev_inst *serial, - uint8_t command, uint8_t *data); + uint8_t command); +SR_PRIV int send_longcommand(struct sr_serial_dev_inst *serial, uint8_t command, + uint8_t *data); SR_PRIV int ols_send_reset(struct sr_serial_dev_inst *serial); SR_PRIV int ols_prepare_acquisition(const struct sr_dev_inst *sdi); SR_PRIV uint32_t ols_channel_mask(const struct sr_dev_inst *sdi); SR_PRIV struct dev_context *ols_dev_new(void); SR_PRIV struct sr_dev_inst *get_metadata(struct sr_serial_dev_inst *serial); SR_PRIV int ols_set_samplerate(const struct sr_dev_inst *sdi, - uint64_t samplerate); + uint64_t samplerate); SR_PRIV void abort_acquisition(const struct sr_dev_inst *sdi); SR_PRIV int ols_receive_data(int fd, int revents, void *cb_data);