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).
This commit is contained in:
Daniel Elstner 2014-01-26 21:42:22 +01:00
parent e0df15d436
commit e6e54bd253
3 changed files with 100 additions and 4 deletions

View File

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

View File

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

View File

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