sysclk-lwla: Implement SR_CONF_CLOCK_EDGE setting.

This commit is contained in:
Daniel Elstner 2014-01-30 00:31:42 +01:00 committed by Bert Vermeulen
parent 860bc59b0f
commit 6358f0a956
3 changed files with 86 additions and 79 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);