X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fsysclk-lwla%2Fapi.c;h=12a1e08696764c20d9d365d0eafb21caf7e57f4b;hb=f3ca73edd29a48f8cc19755df629ab2bc9478eea;hp=d17408d92343eec298de5558691369a9b7c18c42;hpb=ee38c8ba3e49fa3b8af6d2fd83396b3dd4b109a7;p=libsigrok.git diff --git a/hardware/sysclk-lwla/api.c b/hardware/sysclk-lwla/api.c index d17408d9..12a1e086 100644 --- a/hardware/sysclk-lwla/api.c +++ b/hardware/sysclk-lwla/api.c @@ -33,7 +33,10 @@ 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, SR_CONF_LIMIT_MSEC, SR_CONF_LIMIT_SAMPLES, }; @@ -51,6 +54,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 the signal_edge enum values. + */ +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; @@ -59,21 +72,21 @@ static int init(struct sr_context *sr_ctx) return std_init(sr_ctx, di, LOG_PREFIX); } -static GSList *gen_probe_list(int num_probes) +static GSList *gen_channel_list(int num_channels) { GSList *list; - struct sr_probe *probe; + struct sr_channel *ch; int i; char name[8]; list = NULL; - for (i = num_probes; i > 0; --i) { - /* The LWLA series simply number probes from CH1 to CHxx. */ + for (i = num_channels; i > 0; --i) { + /* The LWLA series simply number channels from CH1 to CHxx. */ g_snprintf(name, sizeof(name), "CH%d", i); - probe = sr_probe_new(i - 1, SR_PROBE_LOGIC, TRUE, name); - list = g_slist_prepend(list, probe); + ch = sr_channel_new(i - 1, SR_CHANNEL_LOGIC, TRUE, name); + list = g_slist_prepend(list, ch); } return list; @@ -100,12 +113,12 @@ static struct sr_dev_inst *dev_inst_new(int device_index) return NULL; } - /* Enable all channels to match the default probe configuration. */ + /* Enable all channels to match the default channel configuration. */ devc->channel_mask = ALL_CHANNELS_MASK; devc->samplerate = DEFAULT_SAMPLERATE; sdi->priv = devc; - sdi->probes = gen_probe_list(NUM_PROBES); + sdi->channels = gen_channel_list(NUM_CHANNELS); return sdi; } @@ -222,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; } @@ -256,11 +265,12 @@ static int cleanup(void) } static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_probe_group *probe_group) + const struct sr_channel_group *cg) { struct dev_context *devc; + size_t idx; - (void)probe_group; + (void)cg; if (!sdi) return SR_ERR_ARG; @@ -278,8 +288,26 @@ 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; + 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(signal_edge_names)) + return SR_ERR_BUG; + *data = g_variant_new_string(signal_edge_names[idx]); break; default: return SR_ERR_NA; @@ -288,13 +316,34 @@ 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) + const struct sr_channel_group *cg) { uint64_t value; struct dev_context *devc; + int idx; - (void)probe_group; + (void)cg; devc = sdi->priv; if (!devc) @@ -321,14 +370,29 @@ 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, + 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, signal_edge_names, + G_N_ELEMENTS(signal_edge_names)); + if (idx < 0) + return SR_ERR_ARG; + devc->cfg_trigger_slope = idx; break; default: return SR_ERR_NA; @@ -337,10 +401,10 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, return SR_OK; } -static int config_probe_set(const struct sr_dev_inst *sdi, - struct sr_probe *probe, unsigned int changes) +static int config_channel_set(const struct sr_dev_inst *sdi, + struct sr_channel *ch, unsigned int changes) { - uint64_t probe_bit; + uint64_t channel_bit; uint64_t trigger_mask; uint64_t trigger_values; uint64_t trigger_edge_mask; @@ -350,46 +414,46 @@ static int config_probe_set(const struct sr_dev_inst *sdi, if (!devc) return SR_ERR_DEV_CLOSED; - if (probe->index < 0 || probe->index >= NUM_PROBES) { - sr_err("Probe index %d out of range.", probe->index); + if (ch->index < 0 || ch->index >= NUM_CHANNELS) { + sr_err("Channel index %d out of range.", ch->index); return SR_ERR_BUG; } - probe_bit = (uint64_t)1 << probe->index; + channel_bit = (uint64_t)1 << ch->index; - if ((changes & SR_PROBE_SET_ENABLED) != 0) { - /* Enable or disable input channel for this probe. */ - if (probe->enabled) - devc->channel_mask |= probe_bit; + if ((changes & SR_CHANNEL_SET_ENABLED) != 0) { + /* Enable or disable input channel for this channel. */ + if (ch->enabled) + devc->channel_mask |= channel_bit; else - devc->channel_mask &= ~probe_bit; + devc->channel_mask &= ~channel_bit; } - if ((changes & SR_PROBE_SET_TRIGGER) != 0) { - trigger_mask = devc->trigger_mask & ~probe_bit; - trigger_values = devc->trigger_values & ~probe_bit; - trigger_edge_mask = devc->trigger_edge_mask & ~probe_bit; + if ((changes & SR_CHANNEL_SET_TRIGGER) != 0) { + trigger_mask = devc->trigger_mask & ~channel_bit; + trigger_values = devc->trigger_values & ~channel_bit; + trigger_edge_mask = devc->trigger_edge_mask & ~channel_bit; - if (probe->trigger && probe->trigger[0] != '\0') { - if (probe->trigger[1] != '\0') { + if (ch->trigger && ch->trigger[0] != '\0') { + if (ch->trigger[1] != '\0') { sr_warn("Trigger configuration \"%s\" with " "multiple stages is not supported.", - probe->trigger); + ch->trigger); return SR_ERR_ARG; } - /* Enable trigger for this probe. */ - trigger_mask |= probe_bit; + /* Enable trigger for this channel. */ + trigger_mask |= channel_bit; /* Configure edge mask and trigger value. */ - switch (probe->trigger[0]) { - case '1': trigger_values |= probe_bit; + switch (ch->trigger[0]) { + case '1': trigger_values |= channel_bit; case '0': break; - case 'r': trigger_values |= probe_bit; - case 'f': trigger_edge_mask |= probe_bit; + case 'r': trigger_values |= channel_bit; + case 'f': trigger_edge_mask |= channel_bit; break; default: sr_warn("Trigger type '%c' is not supported.", - probe->trigger[0]); + ch->trigger[0]); return SR_ERR_ARG; } } @@ -409,17 +473,17 @@ 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, - const struct sr_probe_group *probe_group) + const struct sr_channel_group *cg) { GVariant *gvar; GVariantBuilder gvb; (void)sdi; - (void)probe_group; + (void)cg; switch (key) { case SR_CONF_SCAN_OPTIONS: @@ -441,6 +505,15 @@ 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: + 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; } @@ -479,7 +552,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) devc->acquisition = acq; ret = lwla_setup_acquisition(sdi); if (ret != SR_OK) { - sr_err("Failed to set up aquisition."); + sr_err("Failed to set up acquisition."); devc->acquisition = NULL; lwla_free_acquisition_state(acq); return ret; @@ -487,7 +560,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) ret = lwla_start_acquisition(sdi); if (ret != SR_OK) { - sr_err("Failed to start aquisition."); + sr_err("Failed to start acquisition."); devc->acquisition = NULL; lwla_free_acquisition_state(acq); return ret; @@ -528,7 +601,7 @@ SR_PRIV struct sr_dev_driver sysclk_lwla_driver_info = { .dev_clear = dev_clear, .config_get = config_get, .config_set = config_set, - .config_probe_set = config_probe_set, + .config_channel_set = config_channel_set, .config_commit = config_commit, .config_list = config_list, .dev_open = dev_open,