X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fsysclk-lwla%2Fapi.c;h=a4346a012329c083349fd40a80831c1e504f02c9;hb=43cd4637285833706f8a404ca027bcf0ee75b9ae;hp=5bae5d5499225e9b1d39c60641ba7b3e66a353a1;hpb=99c76642aa8d3c75bef4ef3927b4c4cf45461892;p=libsigrok.git diff --git a/hardware/sysclk-lwla/api.c b/hardware/sysclk-lwla/api.c index 5bae5d54..a4346a01 100644 --- a/hardware/sysclk-lwla/api.c +++ b/hardware/sysclk-lwla/api.c @@ -33,11 +33,21 @@ static const int32_t hwcaps[] = { SR_CONF_LOGIC_ANALYZER, SR_CONF_SAMPLERATE, SR_CONF_EXTERNAL_CLOCK, - SR_CONF_TRIGGER_TYPE, + SR_CONF_CLOCK_EDGE, + SR_CONF_TRIGGER_MATCH, + SR_CONF_TRIGGER_SOURCE, + SR_CONF_TRIGGER_SLOPE, SR_CONF_LIMIT_MSEC, SR_CONF_LIMIT_SAMPLES, }; +static const int32_t trigger_matches[] = { + SR_TRIGGER_ZERO, + SR_TRIGGER_ONE, + SR_TRIGGER_RISING, + SR_TRIGGER_FALLING, +}; + /* The hardware supports more samplerates than these, but these are the * options hardcoded into the vendor's Windows GUI. */ @@ -51,6 +61,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,39 +79,68 @@ 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; } +static struct sr_dev_inst *dev_inst_new(int device_index) +{ + struct sr_dev_inst *sdi; + struct dev_context *devc; + + /* Allocate memory for our private driver context. */ + devc = g_try_new0(struct dev_context, 1); + if (!devc) { + sr_err("Device context malloc failed."); + return NULL; + } + + /* Register the device with libsigrok. */ + sdi = sr_dev_inst_new(device_index, SR_ST_INACTIVE, + VENDOR_NAME, MODEL_NAME, NULL); + if (!sdi) { + sr_err("Failed to instantiate device."); + g_free(devc); + return NULL; + } + + /* Enable all channels to match the default channel configuration. */ + devc->channel_mask = ALL_CHANNELS_MASK; + devc->samplerate = DEFAULT_SAMPLERATE; + + sdi->priv = devc; + sdi->channels = gen_channel_list(NUM_CHANNELS); + + return sdi; +} + static GSList *scan(GSList *options) { GSList *usb_devices, *devices, *node; struct drv_context *drvc; struct sr_dev_inst *sdi; - struct dev_context *devc; struct sr_usb_dev_inst *usb; struct sr_config *src; const char *conn; int device_index; drvc = di->priv; - drvc->instances = NULL; conn = USB_VID_PID; for (node = options; node != NULL; node = node->next) { @@ -103,33 +152,22 @@ static GSList *scan(GSList *options) } usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn); devices = NULL; - device_index = 0; + device_index = g_slist_length(drvc->instances); for (node = usb_devices; node != NULL; node = node->next) { usb = node->data; - /* Allocate memory for our private driver context. */ - devc = g_try_new0(struct dev_context, 1); - if (!devc) { - sr_err("Device context malloc failed."); - sr_usb_dev_inst_free(usb); - continue; - } - /* Register the device with libsigrok. */ - sdi = sr_dev_inst_new(device_index, SR_ST_INACTIVE, - VENDOR_NAME, MODEL_NAME, NULL); + /* Create sigrok device instance. */ + sdi = dev_inst_new(device_index); if (!sdi) { - sr_err("Failed to instantiate device."); - g_free(devc); sr_usb_dev_inst_free(usb); continue; } sdi->driver = di; - sdi->priv = devc; sdi->inst_type = SR_INST_USB; sdi->conn = usb; - sdi->probes = gen_probe_list(NUM_PROBES); + /* Register device instance with driver. */ drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); } @@ -168,7 +206,6 @@ static int dev_clear(void) static int dev_open(struct sr_dev_inst *sdi) { struct drv_context *drvc; - struct dev_context *devc; struct sr_usb_dev_inst *usb; int ret; @@ -179,8 +216,7 @@ static int dev_open(struct sr_dev_inst *sdi) return SR_ERR; } - usb = sdi->conn; - devc = sdi->priv; + usb = sdi->conn; ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb); if (ret != SR_OK) @@ -195,10 +231,6 @@ static int dev_open(struct sr_dev_inst *sdi) sdi->status = SR_ST_INITIALIZING; - if (devc->samplerate == 0) - /* Apply default if the samplerate hasn't been set yet. */ - devc->samplerate = DEFAULT_SAMPLERATE; - ret = lwla_init_device(sdi); if (ret == SR_OK) @@ -210,30 +242,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; } @@ -244,11 +272,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; @@ -266,8 +295,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; @@ -276,13 +323,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) @@ -309,16 +377,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; - } - if (sdi->status == SR_ST_ACTIVE) - return lwla_set_clock_source(sdi); + 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; @@ -327,14 +408,51 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, return SR_OK; } +static int config_channel_set(const struct sr_dev_inst *sdi, + struct sr_channel *ch, unsigned int changes) +{ + uint64_t channel_bit; + struct dev_context *devc; + + devc = sdi->priv; + if (!devc) + return SR_ERR_DEV_CLOSED; + + if (ch->index < 0 || ch->index >= NUM_CHANNELS) { + sr_err("Channel index %d out of range.", ch->index); + return SR_ERR_BUG; + } + channel_bit = (uint64_t)1 << ch->index; + + 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 &= ~channel_bit; + } + + return SR_OK; +} + +static int config_commit(const struct sr_dev_inst *sdi) +{ + if (sdi->status != SR_ST_ACTIVE) { + sr_err("Device not ready (status %d).", (int)sdi->status); + return SR_ERR; + } + + 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: @@ -353,8 +471,19 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); *data = g_variant_builder_end(&gvb); break; - case SR_CONF_TRIGGER_TYPE: - *data = g_variant_new_string(TRIGGER_TYPES); + case SR_CONF_TRIGGER_MATCH: + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, + trigger_matches, ARRAY_SIZE(trigger_matches), + sizeof(int32_t)); + 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; @@ -363,61 +492,6 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, return SR_OK; } -static int configure_probes(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - const struct sr_probe *probe; - const GSList *node; - uint64_t probe_bit; - - devc = sdi->priv; - - devc->channel_mask = 0; - devc->trigger_mask = 0; - devc->trigger_edge_mask = 0; - devc->trigger_values = 0; - - for (node = sdi->probes; node != NULL; node = node->next) { - probe = node->data; - if (!probe || !probe->enabled) - continue; - - if (probe->index >= NUM_PROBES) { - sr_err("Channel index %d out of range.", probe->index); - return SR_ERR_BUG; - } - probe_bit = (uint64_t)1 << probe->index; - - /* Enable input channel for this probe. */ - devc->channel_mask |= probe_bit; - - if (!probe->trigger || probe->trigger[0] == '\0') - continue; - - if (probe->trigger[1] != '\0') { - sr_err("Only one trigger stage is supported."); - return SR_ERR; - } - /* Enable trigger for this probe. */ - devc->trigger_mask |= probe_bit; - - /* Configure edge mask and trigger value. */ - switch (probe->trigger[0]) { - case '1': devc->trigger_values |= probe_bit; - case '0': break; - - case 'r': devc->trigger_values |= probe_bit; - case 'f': devc->trigger_edge_mask |= probe_bit; - break; - default: - sr_err("Trigger type '%c' is not supported.", - probe->trigger[0]); - return SR_ERR; - } - } - return SR_OK; -} - static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct drv_context *drvc; @@ -444,19 +518,13 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) devc->stopping_in_progress = FALSE; devc->transfer_error = FALSE; - ret = configure_probes(sdi); - if (ret != SR_OK) { - sr_err("Failed to configure probes."); - lwla_free_acquisition_state(acq); - return ret; - } - sr_info("Starting acquisition."); devc->acquisition = acq; + lwla_convert_trigger(sdi); 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; @@ -464,12 +532,12 @@ 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; } - usb_source_add(drvc->sr_ctx, 100, &lwla_receive_data, + usb_source_add(sdi->session, drvc->sr_ctx, 100, &lwla_receive_data, (struct sr_dev_inst *)sdi); sr_info("Waiting for data."); @@ -505,6 +573,8 @@ SR_PRIV struct sr_dev_driver sysclk_lwla_driver_info = { .dev_clear = dev_clear, .config_get = config_get, .config_set = config_set, + .config_channel_set = config_channel_set, + .config_commit = config_commit, .config_list = config_list, .dev_open = dev_open, .dev_close = dev_close,