From: Daniel Elstner Date: Sun, 26 Jan 2014 20:42:22 +0000 (+0100) Subject: sysclk-lwla: Add support for external trigger input. X-Git-Tag: libsigrok-0.3.0~178 X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=e6e54bd2537ac423977f5574292f2cb987ce8629 sysclk-lwla: Add support for external trigger input. Implement the configuration setting TRIGGER_SOURCE with the choices CH (logic channels) and TRG (external trigger input). Also implement the TRIGGER_SLOPE setting for selecting the edge to trigger on (rising or falling). --- diff --git a/hardware/sysclk-lwla/api.c b/hardware/sysclk-lwla/api.c index d17408d9..f94edcd6 100644 --- a/hardware/sysclk-lwla/api.c +++ b/hardware/sysclk-lwla/api.c @@ -34,6 +34,8 @@ static const int32_t hwcaps[] = { SR_CONF_SAMPLERATE, SR_CONF_EXTERNAL_CLOCK, SR_CONF_TRIGGER_TYPE, + SR_CONF_TRIGGER_SOURCE, + SR_CONF_TRIGGER_SLOPE, SR_CONF_LIMIT_MSEC, SR_CONF_LIMIT_SAMPLES, }; @@ -51,6 +53,16 @@ static const uint64_t samplerates[] = { SR_HZ(500), SR_HZ(200), SR_HZ(100), }; +/* Names assigned to available trigger sources. Indices must match + * trigger_source enum values. + */ +static const char *const trigger_source_names[] = { "CH", "TRG" }; + +/* Names assigned to available trigger slope choices. Indices must + * match trigger_slope enum values. + */ +static const char *const trigger_slope_names[] = { "r", "f" }; + SR_PRIV struct sr_dev_driver sysclk_lwla_driver_info; static struct sr_dev_driver *const di = &sysclk_lwla_driver_info; @@ -259,6 +271,7 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_probe_group *probe_group) { struct dev_context *devc; + size_t idx; (void)probe_group; @@ -281,6 +294,18 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, *data = g_variant_new_boolean(devc->selected_clock_source >= CLOCK_SOURCE_EXT_RISE); break; + case SR_CONF_TRIGGER_SOURCE: + idx = devc->cfg_trigger_source; + if (idx >= G_N_ELEMENTS(trigger_source_names)) + return SR_ERR_BUG; + *data = g_variant_new_string(trigger_source_names[idx]); + break; + case SR_CONF_TRIGGER_SLOPE: + idx = devc->cfg_trigger_slope; + if (idx >= G_N_ELEMENTS(trigger_slope_names)) + return SR_ERR_BUG; + *data = g_variant_new_string(trigger_slope_names[idx]); + break; default: return SR_ERR_NA; } @@ -288,11 +313,32 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, return SR_OK; } +/* Helper for mapping a string-typed configuration value to an index + * within a table of possible values. + */ +static int lookup_index(GVariant *value, const char *const *table, int len) +{ + const char *entry; + int i; + + entry = g_variant_get_string(value, NULL); + if (!entry) + return -1; + + /* Linear search is fine for very small tables. */ + for (i = 0; i < len; ++i) { + if (strcmp(entry, table[i]) == 0) + return i; + } + return -1; +} + static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_probe_group *probe_group) { uint64_t value; struct dev_context *devc; + int idx; (void)probe_group; @@ -330,6 +376,20 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, devc->selected_clock_source = CLOCK_SOURCE_INT; } break; + case SR_CONF_TRIGGER_SOURCE: + idx = lookup_index(data, trigger_source_names, + G_N_ELEMENTS(trigger_source_names)); + if (idx < 0) + return SR_ERR_ARG; + devc->cfg_trigger_source = idx; + break; + case SR_CONF_TRIGGER_SLOPE: + idx = lookup_index(data, trigger_slope_names, + G_N_ELEMENTS(trigger_slope_names)); + if (idx < 0) + return SR_ERR_ARG; + devc->cfg_trigger_slope = idx; + break; default: return SR_ERR_NA; } @@ -441,6 +501,14 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, case SR_CONF_TRIGGER_TYPE: *data = g_variant_new_string(TRIGGER_TYPES); break; + case SR_CONF_TRIGGER_SOURCE: + *data = g_variant_new_strv(trigger_source_names, + 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)); + break; default: return SR_ERR_NA; } diff --git a/hardware/sysclk-lwla/protocol.c b/hardware/sysclk-lwla/protocol.c index 5b1f2483..c4d99d82 100644 --- a/hardware/sysclk-lwla/protocol.c +++ b/hardware/sysclk-lwla/protocol.c @@ -63,6 +63,7 @@ static int capture_setup(const struct sr_dev_inst *sdi) struct dev_context *devc; struct acquisition_state *acq; uint64_t divider_count; + uint64_t trigger_mask; uint64_t memory_limit; uint16_t command[3 + 10*4]; @@ -102,10 +103,18 @@ static int capture_setup(const struct sr_dev_inst *sdi) command[17] = LWLA_WORD_2(devc->trigger_edge_mask); command[18] = LWLA_WORD_3(devc->trigger_edge_mask); - command[19] = LWLA_WORD_0(devc->trigger_mask); - command[20] = LWLA_WORD_1(devc->trigger_mask); - command[21] = LWLA_WORD_2(devc->trigger_mask); - command[22] = LWLA_WORD_3(devc->trigger_mask); + trigger_mask = devc->trigger_mask; + /* 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; + } + + command[19] = LWLA_WORD_0(trigger_mask); + command[20] = LWLA_WORD_1(trigger_mask); + command[21] = LWLA_WORD_2(trigger_mask); + command[22] = LWLA_WORD_3(trigger_mask); /* Set the capture memory full threshold. This is slightly less * than the actual maximum, most likely in order to compensate for diff --git a/hardware/sysclk-lwla/protocol.h b/hardware/sysclk-lwla/protocol.h index 762a17b5..c410e60b 100644 --- a/hardware/sysclk-lwla/protocol.h +++ b/hardware/sysclk-lwla/protocol.h @@ -110,6 +110,20 @@ enum clock_source { CLOCK_SOURCE_EXT_FALL, }; +/** Available trigger sources. + */ +enum trigger_source { + TRIGGER_CHANNELS = 0, + TRIGGER_EXT_TRG, +}; + +/** Available edge choices for the external trigger. + */ +enum trigger_slope { + SLOPE_POSITIVE = 0, + SLOPE_NEGATIVE, +}; + /** LWLA device states. */ enum device_state { @@ -214,6 +228,11 @@ struct dev_context { /** The clock source selected by the user. */ enum clock_source selected_clock_source; + /** Trigger source configuration setting. */ + enum trigger_source cfg_trigger_source; + /** Trigger slope configuration setting. */ + enum trigger_slope cfg_trigger_slope; + /* Indicates that stopping the acquisition is currently in progress. */ gboolean stopping_in_progress;