From 6358f0a9568848be734a8a94ad7f510e04a4503f Mon Sep 17 00:00:00 2001 From: Daniel Elstner Date: Thu, 30 Jan 2014 00:31:42 +0100 Subject: [PATCH] sysclk-lwla: Implement SR_CONF_CLOCK_EDGE setting. --- hardware/sysclk-lwla/api.c | 59 +++++++++++++++-------------- hardware/sysclk-lwla/protocol.c | 66 +++++++++++++++------------------ hardware/sysclk-lwla/protocol.h | 40 ++++++++++++-------- 3 files changed, 86 insertions(+), 79 deletions(-) diff --git a/hardware/sysclk-lwla/api.c b/hardware/sysclk-lwla/api.c index f94edcd6..d6c6267a 100644 --- a/hardware/sysclk-lwla/api.c +++ b/hardware/sysclk-lwla/api.c @@ -33,6 +33,7 @@ static const int32_t hwcaps[] = { SR_CONF_LOGIC_ANALYZER, SR_CONF_SAMPLERATE, SR_CONF_EXTERNAL_CLOCK, + SR_CONF_CLOCK_EDGE, SR_CONF_TRIGGER_TYPE, SR_CONF_TRIGGER_SOURCE, SR_CONF_TRIGGER_SLOPE, @@ -59,9 +60,9 @@ static const uint64_t samplerates[] = { static const char *const trigger_source_names[] = { "CH", "TRG" }; /* 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; static struct sr_dev_driver *const di = &sysclk_lwla_driver_info; @@ -234,30 +235,26 @@ static int dev_open(struct sr_dev_inst *sdi) static int dev_close(struct sr_dev_inst *sdi) { struct sr_usb_dev_inst *usb; - struct dev_context *devc; if (!di->priv) { sr_err("Driver was not initialized."); return SR_ERR; } - usb = sdi->conn; - devc = sdi->priv; - + usb = sdi->conn; if (!usb->devhdl) return SR_OK; - /* Trigger download of the shutdown bitstream. */ - devc->selected_clock_source = CLOCK_SOURCE_NONE; + sdi->status = SR_ST_INACTIVE; - 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."); libusb_release_interface(usb->devhdl, USB_INTERFACE); libusb_close(usb->devhdl); usb->devhdl = NULL; - sdi->status = SR_ST_INACTIVE; 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); break; case SR_CONF_EXTERNAL_CLOCK: - *data = g_variant_new_boolean(devc->selected_clock_source - >= CLOCK_SOURCE_EXT_RISE); + *data = g_variant_new_boolean(devc->cfg_clock_source + == 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; case SR_CONF_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; case SR_CONF_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; - *data = g_variant_new_string(trigger_slope_names[idx]); + *data = g_variant_new_string(signal_edge_names[idx]); break; default: 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; break; case SR_CONF_EXTERNAL_CLOCK: - if (g_variant_get_boolean(data)) { - sr_info("Enabling external clock."); - /* TODO: Allow the external clock to be inverted */ - devc->selected_clock_source = CLOCK_SOURCE_EXT_RISE; - } else { - sr_info("Disabling external clock."); - devc->selected_clock_source = CLOCK_SOURCE_INT; - } + devc->cfg_clock_source = (g_variant_get_boolean(data)) + ? CLOCK_EXT_CLK : CLOCK_INTERNAL; + break; + case SR_CONF_CLOCK_EDGE: + idx = lookup_index(data, signal_edge_names, + G_N_ELEMENTS(signal_edge_names)); + if (idx < 0) + return SR_ERR_ARG; + devc->cfg_clock_edge = idx; break; case SR_CONF_TRIGGER_SOURCE: 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; break; case SR_CONF_TRIGGER_SLOPE: - idx = lookup_index(data, trigger_slope_names, - G_N_ELEMENTS(trigger_slope_names)); + idx = lookup_index(data, signal_edge_names, + G_N_ELEMENTS(signal_edge_names)); if (idx < 0) return SR_ERR_ARG; devc->cfg_trigger_slope = idx; @@ -469,7 +473,7 @@ static int config_commit(const struct sr_dev_inst *sdi) 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, @@ -506,8 +510,9 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, G_N_ELEMENTS(trigger_source_names)); break; case SR_CONF_TRIGGER_SLOPE: - *data = g_variant_new_strv(trigger_slope_names, - G_N_ELEMENTS(trigger_slope_names)); + case SR_CONF_CLOCK_EDGE: + *data = g_variant_new_strv(signal_edge_names, + G_N_ELEMENTS(signal_edge_names)); break; default: return SR_ERR_NA; diff --git a/hardware/sysclk-lwla/protocol.c b/hardware/sysclk-lwla/protocol.c index c4d99d82..75b38063 100644 --- a/hardware/sysclk-lwla/protocol.c +++ b/hardware/sysclk-lwla/protocol.c @@ -29,7 +29,7 @@ /* Number of 64-bit words read from the capture status memory. */ #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] = { "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. */ if (devc->cfg_trigger_source == TRIGGER_EXT_TRG) switch (devc->cfg_trigger_slope) { - case SLOPE_POSITIVE: trigger_mask |= (uint64_t)1 << 35; break; - case SLOPE_NEGATIVE: trigger_mask |= (uint64_t)1 << 34; break; + case EDGE_POSITIVE: trigger_mask |= (uint64_t)1 << 35; break; + case EDGE_NEGATIVE: trigger_mask |= (uint64_t)1 << 34; break; } 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; - /* 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 */ - 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) return ret; @@ -742,29 +738,31 @@ SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi) return ret; } -/* Select the LWLA clock source. If the clock source changed from the - * previous setting, this will download a new bitstream to the FPGA. +/* Select the LWLA clock configuration. If the clock source changed from + * 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; int ret; - enum clock_source selected; - size_t idx; + enum clock_config choice; devc = sdi->priv; - selected = devc->selected_clock_source; - if (devc->cur_clock_source != selected) { - devc->cur_clock_source = CLOCK_SOURCE_NONE; - idx = selected; - if (idx >= G_N_ELEMENTS(bitstream_map)) { - sr_err("Clock source (%d) out of range", selected); - return SR_ERR_BUG; - } - ret = lwla_send_bitstream(sdi->conn, bitstream_map[idx]); + if (sdi->status == SR_ST_INACTIVE) + choice = CONF_CLOCK_NONE; + else if (devc->cfg_clock_source == CLOCK_INTERNAL) + choice = CONF_CLOCK_INT; + else if (devc->cfg_clock_edge == EDGE_POSITIVE) + choice = CONF_CLOCK_EXT_RISE; + else + 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) - devc->cur_clock_source = selected; + devc->cur_clock_config = choice; return ret; } return SR_OK; @@ -798,8 +796,7 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi) } else acq->samples_max = MAX_LIMIT_SAMPLES; - switch (devc->cur_clock_source) { - case CLOCK_SOURCE_INT: + if (devc->cfg_clock_source == CLOCK_INTERNAL) { sr_info("Internal clock, samplerate %" PRIu64 ".", devc->samplerate); 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) acq->samples_max = devc->limit_msec * devc->samplerate / 1000; - break; - case CLOCK_SOURCE_EXT_FALL: - sr_info("External clock, falling edge."); + } else { acq->bypass_clockdiv = TRUE; - break; - case CLOCK_SOURCE_EXT_RISE: - sr_info("External clock, rising edge."); - acq->bypass_clockdiv = TRUE; - break; - default: - sr_err("No valid clock source has been configured."); - return SR_ERR; + + if (devc->cfg_clock_edge == EDGE_NEGATIVE) + sr_info("External clock, falling edge."); + else + sr_info("External clock, rising edge."); } regvals[0].reg = REG_MEM_CTRL2; diff --git a/hardware/sysclk-lwla/protocol.h b/hardware/sysclk-lwla/protocol.h index c410e60b..61940be6 100644 --- a/hardware/sysclk-lwla/protocol.h +++ b/hardware/sysclk-lwla/protocol.h @@ -101,13 +101,20 @@ */ #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 { - CLOCK_SOURCE_NONE, - CLOCK_SOURCE_INT, - CLOCK_SOURCE_EXT_RISE, - CLOCK_SOURCE_EXT_FALL, + CLOCK_INTERNAL, + CLOCK_EXT_CLK, }; /** Available trigger sources. @@ -117,11 +124,11 @@ enum trigger_source { TRIGGER_EXT_TRG, }; -/** Available edge choices for the external trigger. +/** Available edge choices for the external clock and trigger inputs. */ -enum trigger_slope { - SLOPE_POSITIVE = 0, - SLOPE_NEGATIVE, +enum signal_edge { + EDGE_POSITIVE = 0, + EDGE_NEGATIVE, }; /** LWLA device states. @@ -223,15 +230,18 @@ struct dev_context { enum device_state state; - /** The currently configured clock source of the device. */ - enum clock_source cur_clock_source; - /** The clock source selected by the user. */ - enum clock_source selected_clock_source; + /** The currently active clock configuration of the device. */ + enum clock_config cur_clock_config; + + /** Clock source configuration setting. */ + enum clock_source cfg_clock_source; + /** Clock edge configuration setting. */ + enum signal_edge cfg_clock_edge; /** Trigger source configuration setting. */ enum trigger_source cfg_trigger_source; /** 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. */ 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 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_start_acquisition(const struct sr_dev_inst *sdi); SR_PRIV int lwla_abort_acquisition(const struct sr_dev_inst *sdi);