Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
549f03c
ols: Clean up: Prefix private function for consistency
v1ne Nov 18, 2020
fbe2bd2
ols: Display actual expanded sample instead of the raw sample
v1ne Apr 1, 2020
f793969
ols: Clear "disabled groups" flags before setting them
v1ne Mar 31, 2020
dc03fcf
ols: Add option to use the falling edge of the external clock
v1ne Mar 31, 2020
552ce33
ols: Make external clock setting queriable
v1ne Mar 31, 2020
626a33c
ols: Refactor: Extract trigger setup into private place
v1ne Apr 1, 2020
d5de503
ols: Clean up: Replace hand-rolled byte order conversion with existin…
v1ne Mar 31, 2020
535d1eb
ols: Provide sample count in RLE mode
v1ne Apr 1, 2020
1841da4
ols: Don't store temporary data in device context
v1ne Apr 1, 2020
6b7d06f
ols: Don't silently ignore error when setting up the device
v1ne Apr 1, 2020
094bd3f
ols: Forward errors to callers in a generic way
v1ne Apr 1, 2020
26177a3
ols: Fix demuxer operation
v1ne Apr 1, 2020
e984bd1
ols: Fix off-by-one when setting up trigger stages
v1ne Apr 1, 2020
566e726
ols: Adjust pre-trigger delay
v1ne Apr 1, 2020
11d03e3
ols: Flip samples after reading everything
v1ne Apr 1, 2020
83682b2
ols: Use a dynamic sample buffer
v1ne Apr 1, 2020
cdef4c4
ols: Be more robust against short reads
v1ne Apr 1, 2020
ce4e4a8
ols: Make resetting more robust, reset at the end
v1ne Apr 1, 2020
eeeceb9
ols: Clean up: Rename variables, remove misleading counter
v1ne Apr 2, 2020
04541ce
ols: Clean up: Always keep sample_buf_size up to date
v1ne Apr 2, 2020
bf3e2cf
ols: Communicate internally that the number of samples is a multiple …
v1ne Apr 2, 2020
ee81d50
ols: Immediately process data after expected sample count
v1ne Apr 2, 2020
8e33794
ols: Receive many bytes in a row
v1ne Apr 2, 2020
cecf50e
ols: Capture multiple bytes at once
v1ne Apr 2, 2020
4d22f5b
ols: Determine the right trigger point when using RLE
v1ne Apr 2, 2020
fb32bf1
ols: Support Demon Core RLE mode 3
v1ne Apr 2, 2020
789e911
ols: Add support for advanced triggers
v1ne Mar 31, 2020
b31d2ae
ols: don't set invalid number of basic trigger stages
wsakernel Jan 17, 2021
52c302d
ols: use memset instead of for-loop
wsakernel Jan 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 61 additions & 163 deletions src/hardware/openbench-logic-sniffer/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,31 @@ 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,
};

static const int32_t trigger_matches[] = {
static const int32_t basic_trigger_matches[] = {
SR_TRIGGER_ZERO,
SR_TRIGGER_ONE,
};

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"
#define STR_PATTERN_EXTERNAL "External"
#define STR_PATTERN_INTERNAL "Internal"
Expand Down Expand Up @@ -223,6 +237,14 @@ static int config_get(uint32_t key, GVariant **data,
case SR_CONF_RLE:
*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;
}
Expand Down Expand Up @@ -266,6 +288,16 @@ static int config_set(uint32_t key, GVariant *data,
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:
stropt = g_variant_get_string(data, NULL);
if (!strcmp(stropt, STR_PATTERN_NONE)) {
Expand Down Expand Up @@ -312,7 +344,7 @@ 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)
{
struct dev_context *devc;
struct dev_context *devc = sdi ? sdi->priv : NULL;
int num_ols_changrp, i;

switch (key) {
Expand All @@ -323,28 +355,33 @@ static int config_list(uint32_t key, GVariant **data,
*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));
break;
case SR_CONF_PATTERN_MODE:
*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;
/*
* 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++;
}

Expand All @@ -358,178 +395,39 @@ 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",
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");
/*
* Enable/disable OLS channel groups in the flag register according
* to the channel mask. 1 means "disable channel".
*/
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)
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,
return serial_source_add(sdi->session, serial, G_IO_IN, 10*1000,
ols_receive_data, (struct sr_dev_inst *)sdi);

return SR_OK;
}

static int dev_acquisition_stop(struct sr_dev_inst *sdi)
Expand Down
Loading