sysclk-lwla: Implement SR_CONF_CLOCK_EDGE setting.
This commit is contained in:
parent
860bc59b0f
commit
6358f0a956
|
@ -33,6 +33,7 @@ static const int32_t hwcaps[] = {
|
||||||
SR_CONF_LOGIC_ANALYZER,
|
SR_CONF_LOGIC_ANALYZER,
|
||||||
SR_CONF_SAMPLERATE,
|
SR_CONF_SAMPLERATE,
|
||||||
SR_CONF_EXTERNAL_CLOCK,
|
SR_CONF_EXTERNAL_CLOCK,
|
||||||
|
SR_CONF_CLOCK_EDGE,
|
||||||
SR_CONF_TRIGGER_TYPE,
|
SR_CONF_TRIGGER_TYPE,
|
||||||
SR_CONF_TRIGGER_SOURCE,
|
SR_CONF_TRIGGER_SOURCE,
|
||||||
SR_CONF_TRIGGER_SLOPE,
|
SR_CONF_TRIGGER_SLOPE,
|
||||||
|
@ -59,9 +60,9 @@ static const uint64_t samplerates[] = {
|
||||||
static const char *const trigger_source_names[] = { "CH", "TRG" };
|
static const char *const trigger_source_names[] = { "CH", "TRG" };
|
||||||
|
|
||||||
/* Names assigned to available trigger slope choices. Indices must
|
/* Names assigned to available trigger slope choices. Indices must
|
||||||
* match trigger_slope enum values.
|
* match the signal_edge enum values.
|
||||||
*/
|
*/
|
||||||
static const char *const trigger_slope_names[] = { "r", "f" };
|
static const char *const signal_edge_names[] = { "r", "f" };
|
||||||
|
|
||||||
SR_PRIV struct sr_dev_driver sysclk_lwla_driver_info;
|
SR_PRIV struct sr_dev_driver sysclk_lwla_driver_info;
|
||||||
static struct sr_dev_driver *const di = &sysclk_lwla_driver_info;
|
static struct sr_dev_driver *const di = &sysclk_lwla_driver_info;
|
||||||
|
@ -234,7 +235,6 @@ static int dev_open(struct sr_dev_inst *sdi)
|
||||||
static int dev_close(struct sr_dev_inst *sdi)
|
static int dev_close(struct sr_dev_inst *sdi)
|
||||||
{
|
{
|
||||||
struct sr_usb_dev_inst *usb;
|
struct sr_usb_dev_inst *usb;
|
||||||
struct dev_context *devc;
|
|
||||||
|
|
||||||
if (!di->priv) {
|
if (!di->priv) {
|
||||||
sr_err("Driver was not initialized.");
|
sr_err("Driver was not initialized.");
|
||||||
|
@ -242,22 +242,19 @@ static int dev_close(struct sr_dev_inst *sdi)
|
||||||
}
|
}
|
||||||
|
|
||||||
usb = sdi->conn;
|
usb = sdi->conn;
|
||||||
devc = sdi->priv;
|
|
||||||
|
|
||||||
if (!usb->devhdl)
|
if (!usb->devhdl)
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
|
|
||||||
/* Trigger download of the shutdown bitstream. */
|
sdi->status = SR_ST_INACTIVE;
|
||||||
devc->selected_clock_source = CLOCK_SOURCE_NONE;
|
|
||||||
|
|
||||||
if (lwla_set_clock_source(sdi) != SR_OK)
|
/* Trigger download of the shutdown bitstream. */
|
||||||
|
if (lwla_set_clock_config(sdi) != SR_OK)
|
||||||
sr_err("Unable to shut down device.");
|
sr_err("Unable to shut down device.");
|
||||||
|
|
||||||
libusb_release_interface(usb->devhdl, USB_INTERFACE);
|
libusb_release_interface(usb->devhdl, USB_INTERFACE);
|
||||||
libusb_close(usb->devhdl);
|
libusb_close(usb->devhdl);
|
||||||
|
|
||||||
usb->devhdl = NULL;
|
usb->devhdl = NULL;
|
||||||
sdi->status = SR_ST_INACTIVE;
|
|
||||||
|
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
}
|
}
|
||||||
|
@ -291,8 +288,14 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
|
||||||
*data = g_variant_new_uint64(devc->limit_samples);
|
*data = g_variant_new_uint64(devc->limit_samples);
|
||||||
break;
|
break;
|
||||||
case SR_CONF_EXTERNAL_CLOCK:
|
case SR_CONF_EXTERNAL_CLOCK:
|
||||||
*data = g_variant_new_boolean(devc->selected_clock_source
|
*data = g_variant_new_boolean(devc->cfg_clock_source
|
||||||
>= CLOCK_SOURCE_EXT_RISE);
|
== CLOCK_EXT_CLK);
|
||||||
|
break;
|
||||||
|
case SR_CONF_CLOCK_EDGE:
|
||||||
|
idx = devc->cfg_clock_edge;
|
||||||
|
if (idx >= G_N_ELEMENTS(signal_edge_names))
|
||||||
|
return SR_ERR_BUG;
|
||||||
|
*data = g_variant_new_string(signal_edge_names[idx]);
|
||||||
break;
|
break;
|
||||||
case SR_CONF_TRIGGER_SOURCE:
|
case SR_CONF_TRIGGER_SOURCE:
|
||||||
idx = devc->cfg_trigger_source;
|
idx = devc->cfg_trigger_source;
|
||||||
|
@ -302,9 +305,9 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
|
||||||
break;
|
break;
|
||||||
case SR_CONF_TRIGGER_SLOPE:
|
case SR_CONF_TRIGGER_SLOPE:
|
||||||
idx = devc->cfg_trigger_slope;
|
idx = devc->cfg_trigger_slope;
|
||||||
if (idx >= G_N_ELEMENTS(trigger_slope_names))
|
if (idx >= G_N_ELEMENTS(signal_edge_names))
|
||||||
return SR_ERR_BUG;
|
return SR_ERR_BUG;
|
||||||
*data = g_variant_new_string(trigger_slope_names[idx]);
|
*data = g_variant_new_string(signal_edge_names[idx]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SR_ERR_NA;
|
return SR_ERR_NA;
|
||||||
|
@ -367,14 +370,15 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
|
||||||
devc->limit_samples = value;
|
devc->limit_samples = value;
|
||||||
break;
|
break;
|
||||||
case SR_CONF_EXTERNAL_CLOCK:
|
case SR_CONF_EXTERNAL_CLOCK:
|
||||||
if (g_variant_get_boolean(data)) {
|
devc->cfg_clock_source = (g_variant_get_boolean(data))
|
||||||
sr_info("Enabling external clock.");
|
? CLOCK_EXT_CLK : CLOCK_INTERNAL;
|
||||||
/* TODO: Allow the external clock to be inverted */
|
break;
|
||||||
devc->selected_clock_source = CLOCK_SOURCE_EXT_RISE;
|
case SR_CONF_CLOCK_EDGE:
|
||||||
} else {
|
idx = lookup_index(data, signal_edge_names,
|
||||||
sr_info("Disabling external clock.");
|
G_N_ELEMENTS(signal_edge_names));
|
||||||
devc->selected_clock_source = CLOCK_SOURCE_INT;
|
if (idx < 0)
|
||||||
}
|
return SR_ERR_ARG;
|
||||||
|
devc->cfg_clock_edge = idx;
|
||||||
break;
|
break;
|
||||||
case SR_CONF_TRIGGER_SOURCE:
|
case SR_CONF_TRIGGER_SOURCE:
|
||||||
idx = lookup_index(data, trigger_source_names,
|
idx = lookup_index(data, trigger_source_names,
|
||||||
|
@ -384,8 +388,8 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
|
||||||
devc->cfg_trigger_source = idx;
|
devc->cfg_trigger_source = idx;
|
||||||
break;
|
break;
|
||||||
case SR_CONF_TRIGGER_SLOPE:
|
case SR_CONF_TRIGGER_SLOPE:
|
||||||
idx = lookup_index(data, trigger_slope_names,
|
idx = lookup_index(data, signal_edge_names,
|
||||||
G_N_ELEMENTS(trigger_slope_names));
|
G_N_ELEMENTS(signal_edge_names));
|
||||||
if (idx < 0)
|
if (idx < 0)
|
||||||
return SR_ERR_ARG;
|
return SR_ERR_ARG;
|
||||||
devc->cfg_trigger_slope = idx;
|
devc->cfg_trigger_slope = idx;
|
||||||
|
@ -469,7 +473,7 @@ static int config_commit(const struct sr_dev_inst *sdi)
|
||||||
return SR_ERR;
|
return SR_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lwla_set_clock_source(sdi);
|
return lwla_set_clock_config(sdi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
|
static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
|
||||||
|
@ -506,8 +510,9 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
|
||||||
G_N_ELEMENTS(trigger_source_names));
|
G_N_ELEMENTS(trigger_source_names));
|
||||||
break;
|
break;
|
||||||
case SR_CONF_TRIGGER_SLOPE:
|
case SR_CONF_TRIGGER_SLOPE:
|
||||||
*data = g_variant_new_strv(trigger_slope_names,
|
case SR_CONF_CLOCK_EDGE:
|
||||||
G_N_ELEMENTS(trigger_slope_names));
|
*data = g_variant_new_strv(signal_edge_names,
|
||||||
|
G_N_ELEMENTS(signal_edge_names));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SR_ERR_NA;
|
return SR_ERR_NA;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
/* Number of 64-bit words read from the capture status memory. */
|
/* Number of 64-bit words read from the capture status memory. */
|
||||||
#define CAP_STAT_LEN 5
|
#define CAP_STAT_LEN 5
|
||||||
|
|
||||||
/* The bitstream filenames are indexed by the clock source enumeration.
|
/* The bitstream filenames are indexed by the clock_config enumeration.
|
||||||
*/
|
*/
|
||||||
static const char bitstream_map[][32] = {
|
static const char bitstream_map[][32] = {
|
||||||
"sysclk-lwla1034-off.rbf",
|
"sysclk-lwla1034-off.rbf",
|
||||||
|
@ -107,8 +107,8 @@ static int capture_setup(const struct sr_dev_inst *sdi)
|
||||||
/* Set bits to select external TRG input edge. */
|
/* Set bits to select external TRG input edge. */
|
||||||
if (devc->cfg_trigger_source == TRIGGER_EXT_TRG)
|
if (devc->cfg_trigger_source == TRIGGER_EXT_TRG)
|
||||||
switch (devc->cfg_trigger_slope) {
|
switch (devc->cfg_trigger_slope) {
|
||||||
case SLOPE_POSITIVE: trigger_mask |= (uint64_t)1 << 35; break;
|
case EDGE_POSITIVE: trigger_mask |= (uint64_t)1 << 35; break;
|
||||||
case SLOPE_NEGATIVE: trigger_mask |= (uint64_t)1 << 34; break;
|
case EDGE_NEGATIVE: trigger_mask |= (uint64_t)1 << 34; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
command[19] = LWLA_WORD_0(trigger_mask);
|
command[19] = LWLA_WORD_0(trigger_mask);
|
||||||
|
@ -702,14 +702,10 @@ SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi)
|
||||||
|
|
||||||
devc = sdi->priv;
|
devc = sdi->priv;
|
||||||
|
|
||||||
/* Select internal clock if it hasn't been set yet */
|
|
||||||
if (devc->selected_clock_source == CLOCK_SOURCE_NONE)
|
|
||||||
devc->selected_clock_source = CLOCK_SOURCE_INT;
|
|
||||||
|
|
||||||
/* Force reload of bitstream */
|
/* Force reload of bitstream */
|
||||||
devc->cur_clock_source = CLOCK_SOURCE_NONE;
|
devc->cur_clock_config = CONF_CLOCK_NONE;
|
||||||
|
|
||||||
ret = lwla_set_clock_source(sdi);
|
ret = lwla_set_clock_config(sdi);
|
||||||
|
|
||||||
if (ret != SR_OK)
|
if (ret != SR_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -742,29 +738,31 @@ SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select the LWLA clock source. If the clock source changed from the
|
/* Select the LWLA clock configuration. If the clock source changed from
|
||||||
* previous setting, this will download a new bitstream to the FPGA.
|
* the previous setting, this will download a new bitstream to the FPGA.
|
||||||
*/
|
*/
|
||||||
SR_PRIV int lwla_set_clock_source(const struct sr_dev_inst *sdi)
|
SR_PRIV int lwla_set_clock_config(const struct sr_dev_inst *sdi)
|
||||||
{
|
{
|
||||||
struct dev_context *devc;
|
struct dev_context *devc;
|
||||||
int ret;
|
int ret;
|
||||||
enum clock_source selected;
|
enum clock_config choice;
|
||||||
size_t idx;
|
|
||||||
|
|
||||||
devc = sdi->priv;
|
devc = sdi->priv;
|
||||||
selected = devc->selected_clock_source;
|
|
||||||
|
|
||||||
if (devc->cur_clock_source != selected) {
|
if (sdi->status == SR_ST_INACTIVE)
|
||||||
devc->cur_clock_source = CLOCK_SOURCE_NONE;
|
choice = CONF_CLOCK_NONE;
|
||||||
idx = selected;
|
else if (devc->cfg_clock_source == CLOCK_INTERNAL)
|
||||||
if (idx >= G_N_ELEMENTS(bitstream_map)) {
|
choice = CONF_CLOCK_INT;
|
||||||
sr_err("Clock source (%d) out of range", selected);
|
else if (devc->cfg_clock_edge == EDGE_POSITIVE)
|
||||||
return SR_ERR_BUG;
|
choice = CONF_CLOCK_EXT_RISE;
|
||||||
}
|
else
|
||||||
ret = lwla_send_bitstream(sdi->conn, bitstream_map[idx]);
|
choice = CONF_CLOCK_EXT_FALL;
|
||||||
|
|
||||||
|
if (choice != devc->cur_clock_config) {
|
||||||
|
devc->cur_clock_config = CONF_CLOCK_NONE;
|
||||||
|
ret = lwla_send_bitstream(sdi->conn, bitstream_map[choice]);
|
||||||
if (ret == SR_OK)
|
if (ret == SR_OK)
|
||||||
devc->cur_clock_source = selected;
|
devc->cur_clock_config = choice;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
|
@ -798,8 +796,7 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi)
|
||||||
} else
|
} else
|
||||||
acq->samples_max = MAX_LIMIT_SAMPLES;
|
acq->samples_max = MAX_LIMIT_SAMPLES;
|
||||||
|
|
||||||
switch (devc->cur_clock_source) {
|
if (devc->cfg_clock_source == CLOCK_INTERNAL) {
|
||||||
case CLOCK_SOURCE_INT:
|
|
||||||
sr_info("Internal clock, samplerate %" PRIu64 ".",
|
sr_info("Internal clock, samplerate %" PRIu64 ".",
|
||||||
devc->samplerate);
|
devc->samplerate);
|
||||||
if (devc->samplerate == 0)
|
if (devc->samplerate == 0)
|
||||||
|
@ -814,18 +811,13 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi)
|
||||||
else if (devc->limit_samples == 0 && devc->limit_msec > 0)
|
else if (devc->limit_samples == 0 && devc->limit_msec > 0)
|
||||||
acq->samples_max = devc->limit_msec
|
acq->samples_max = devc->limit_msec
|
||||||
* devc->samplerate / 1000;
|
* devc->samplerate / 1000;
|
||||||
break;
|
} else {
|
||||||
case CLOCK_SOURCE_EXT_FALL:
|
acq->bypass_clockdiv = TRUE;
|
||||||
|
|
||||||
|
if (devc->cfg_clock_edge == EDGE_NEGATIVE)
|
||||||
sr_info("External clock, falling edge.");
|
sr_info("External clock, falling edge.");
|
||||||
acq->bypass_clockdiv = TRUE;
|
else
|
||||||
break;
|
|
||||||
case CLOCK_SOURCE_EXT_RISE:
|
|
||||||
sr_info("External clock, rising edge.");
|
sr_info("External clock, rising edge.");
|
||||||
acq->bypass_clockdiv = TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sr_err("No valid clock source has been configured.");
|
|
||||||
return SR_ERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
regvals[0].reg = REG_MEM_CTRL2;
|
regvals[0].reg = REG_MEM_CTRL2;
|
||||||
|
|
|
@ -101,13 +101,20 @@
|
||||||
*/
|
*/
|
||||||
#define MAX_LIMIT_MSEC (UINT64_C(1) << 32)
|
#define MAX_LIMIT_MSEC (UINT64_C(1) << 32)
|
||||||
|
|
||||||
/** LWLA clock sources.
|
/** LWLA1034 FPGA clock configurations.
|
||||||
|
*/
|
||||||
|
enum clock_config {
|
||||||
|
CONF_CLOCK_NONE,
|
||||||
|
CONF_CLOCK_INT,
|
||||||
|
CONF_CLOCK_EXT_RISE,
|
||||||
|
CONF_CLOCK_EXT_FALL,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Available clock sources.
|
||||||
*/
|
*/
|
||||||
enum clock_source {
|
enum clock_source {
|
||||||
CLOCK_SOURCE_NONE,
|
CLOCK_INTERNAL,
|
||||||
CLOCK_SOURCE_INT,
|
CLOCK_EXT_CLK,
|
||||||
CLOCK_SOURCE_EXT_RISE,
|
|
||||||
CLOCK_SOURCE_EXT_FALL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Available trigger sources.
|
/** Available trigger sources.
|
||||||
|
@ -117,11 +124,11 @@ enum trigger_source {
|
||||||
TRIGGER_EXT_TRG,
|
TRIGGER_EXT_TRG,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Available edge choices for the external trigger.
|
/** Available edge choices for the external clock and trigger inputs.
|
||||||
*/
|
*/
|
||||||
enum trigger_slope {
|
enum signal_edge {
|
||||||
SLOPE_POSITIVE = 0,
|
EDGE_POSITIVE = 0,
|
||||||
SLOPE_NEGATIVE,
|
EDGE_NEGATIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** LWLA device states.
|
/** LWLA device states.
|
||||||
|
@ -223,15 +230,18 @@ struct dev_context {
|
||||||
|
|
||||||
enum device_state state;
|
enum device_state state;
|
||||||
|
|
||||||
/** The currently configured clock source of the device. */
|
/** The currently active clock configuration of the device. */
|
||||||
enum clock_source cur_clock_source;
|
enum clock_config cur_clock_config;
|
||||||
/** The clock source selected by the user. */
|
|
||||||
enum clock_source selected_clock_source;
|
/** Clock source configuration setting. */
|
||||||
|
enum clock_source cfg_clock_source;
|
||||||
|
/** Clock edge configuration setting. */
|
||||||
|
enum signal_edge cfg_clock_edge;
|
||||||
|
|
||||||
/** Trigger source configuration setting. */
|
/** Trigger source configuration setting. */
|
||||||
enum trigger_source cfg_trigger_source;
|
enum trigger_source cfg_trigger_source;
|
||||||
/** Trigger slope configuration setting. */
|
/** Trigger slope configuration setting. */
|
||||||
enum trigger_slope cfg_trigger_slope;
|
enum signal_edge cfg_trigger_slope;
|
||||||
|
|
||||||
/* Indicates that stopping the acquisition is currently in progress. */
|
/* Indicates that stopping the acquisition is currently in progress. */
|
||||||
gboolean stopping_in_progress;
|
gboolean stopping_in_progress;
|
||||||
|
@ -244,7 +254,7 @@ SR_PRIV struct acquisition_state *lwla_alloc_acquisition_state(void);
|
||||||
SR_PRIV void lwla_free_acquisition_state(struct acquisition_state *acq);
|
SR_PRIV void lwla_free_acquisition_state(struct acquisition_state *acq);
|
||||||
|
|
||||||
SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi);
|
SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi);
|
||||||
SR_PRIV int lwla_set_clock_source(const struct sr_dev_inst *sdi);
|
SR_PRIV int lwla_set_clock_config(const struct sr_dev_inst *sdi);
|
||||||
SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi);
|
SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi);
|
||||||
SR_PRIV int lwla_start_acquisition(const struct sr_dev_inst *sdi);
|
SR_PRIV int lwla_start_acquisition(const struct sr_dev_inst *sdi);
|
||||||
SR_PRIV int lwla_abort_acquisition(const struct sr_dev_inst *sdi);
|
SR_PRIV int lwla_abort_acquisition(const struct sr_dev_inst *sdi);
|
||||||
|
|
Loading…
Reference in New Issue