X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fkingst-la2016%2Fapi.c;h=742f3e3ae6a0a3155e2516e32903894db4770c84;hb=90ed86aa1737fd30bac4cbbeaae91d87b4c22682;hp=044b728fa5f6164213c34c4f7ccc2b96a8f087c8;hpb=7de0f6c1ffc52f6f96e2733d66d8d85cf3526000;p=libsigrok.git diff --git a/src/hardware/kingst-la2016/api.c b/src/hardware/kingst-la2016/api.c index 044b728f..742f3e3a 100644 --- a/src/hardware/kingst-la2016/api.c +++ b/src/hardware/kingst-la2016/api.c @@ -1,6 +1,7 @@ /* * This file is part of the libsigrok project. * + * Copyright (C) 2022 Gerhard Sittig * Copyright (C) 2020 Florian Schmidt * Copyright (C) 2013 Marcus Comstedt * Copyright (C) 2013 Bert Vermeulen @@ -35,6 +36,7 @@ static const uint32_t scanopts[] = { SR_CONF_CONN, + SR_CONF_PROBE_NAMES, }; static const uint32_t drvopts[] = { @@ -43,20 +45,16 @@ static const uint32_t drvopts[] = { }; static const uint32_t devopts[] = { - /* TODO: SR_CONF_CONTINUOUS, */ SR_CONF_CONN | SR_CONF_GET, SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET, #if WITH_THRESHOLD_DEVCFG SR_CONF_VOLTAGE_THRESHOLD | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, -#if !WITH_THRESHOLD_SIMPLE - SR_CONF_LOGIC_THRESHOLD | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, - SR_CONF_LOGIC_THRESHOLD_CUSTOM | SR_CONF_GET | SR_CONF_SET, -#endif #endif SR_CONF_TRIGGER_MATCH | SR_CONF_LIST, SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET, + SR_CONF_CONTINUOUS | SR_CONF_GET | SR_CONF_SET, }; static const uint32_t devopts_cg_logic[] = { @@ -90,20 +88,23 @@ static const char *channel_names_pwm[] = { }; /* - * The hardware uses a 100/200/500MHz base clock (model dependent) and - * a 16bit divider (common across all models). The range from 10kHz to - * 100/200/500MHz should be applicable to all devices. High rates may - * suffer from coarse resolution (e.g. in the "500MHz div 2" case) and - * may not provide the desired 1/2/5 steps. Fortunately this exclusively - * affects the 500MHz model where 250MHz is used instead of 200MHz and - * the 166MHz and 125MHz rates are not presented to users. Deep memory - * of these models and hardware compression reduce the necessity to let - * users pick from a huge list of possible rates. + * The devices have an upper samplerate limit of 100/200/500 MHz each. + * But their hardware uses different base clocks (100/200/800MHz, this + * is _not_ a typo) and a 16bit divider. Which results in per-model ranges + * of supported rates which not only differ in the upper boundary, but + * also at the lower boundary. It's assumed that the 10kHz rate is not + * useful enough to provide by all means. Starting at 20kHz for all models + * simplfies the implementation of the config API routines, and eliminates + * redundancy in these samplerates tables. * + * Streaming mode is constrained by the channel count and samplerate + * product (the bits per second which need to travel the USB connection + * while the acquisition is executing). Because streaming mode does not + * compress the capture data, a later implementation may desire a finer + * resolution. For now let's just stick with the 1/2/5 steps. */ static const uint64_t rates_500mhz[] = { - SR_KHZ(10), SR_KHZ(20), SR_KHZ(50), SR_KHZ(100), @@ -116,12 +117,11 @@ static const uint64_t rates_500mhz[] = { SR_MHZ(20), SR_MHZ(50), SR_MHZ(100), - SR_MHZ(250), + SR_MHZ(200), SR_MHZ(500), }; static const uint64_t rates_200mhz[] = { - SR_KHZ(10), SR_KHZ(20), SR_KHZ(50), SR_KHZ(100), @@ -138,7 +138,6 @@ static const uint64_t rates_200mhz[] = { }; static const uint64_t rates_100mhz[] = { - SR_KHZ(10), SR_KHZ(20), SR_KHZ(50), SR_KHZ(100), @@ -153,8 +152,6 @@ static const uint64_t rates_100mhz[] = { SR_MHZ(100), }; -#if WITH_THRESHOLD_SIMPLE - /* * Only list a few discrete voltages, to form a useful set which covers * most logic families. Too many choices can make some applications use @@ -188,55 +185,6 @@ static double threshold_voltage(const struct sr_dev_inst *sdi, double *high) return voltage; } -#else /* WITH_THRESHOLD_SIMPLE */ - -static const float logic_threshold_value[] = { - 1.58, - 2.5, - 1.165, - 1.5, - 1.25, - 0.9, - 0.75, - 0.60, - 0.45, -}; - -static const char *logic_threshold[] = { - "TTL 5V", - "CMOS 5V", - "CMOS 3.3V", - "CMOS 3.0V", - "CMOS 2.5V", - "CMOS 1.8V", - "CMOS 1.5V", - "CMOS 1.2V", - "CMOS 0.9V", - "USER", -}; - -#define LOGIC_THRESHOLD_IDX_USER (ARRAY_SIZE(logic_threshold) - 1) - -static double threshold_voltage(const struct sr_dev_inst *sdi, double *high) -{ - struct dev_context *devc; - size_t idx; - double voltage; - - devc = sdi->priv; - idx = devc->threshold_voltage_idx; - if (idx == LOGIC_THRESHOLD_IDX_USER) - voltage = devc->threshold_voltage; - else - voltage = logic_threshold_value[idx]; - if (high) - *high = voltage; - - return voltage; -} - -#endif /* WITH_THRESHOLD_SIMPLE */ - /* Convenience. Release an allocated devc from error paths. */ static void kingst_la2016_free_devc(struct dev_context *devc) { @@ -483,6 +431,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) uint8_t bus, addr; uint16_t pid; const char *conn; + const char *probe_names; char conn_id[64]; int ret; size_t ch_off, ch_max; @@ -494,12 +443,16 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) conn = NULL; conn_devices = NULL; + probe_names = NULL; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_CONN: conn = g_variant_get_string(src->data, NULL); break; + case SR_CONF_PROBE_NAMES: + probe_names = g_variant_get_string(src->data, NULL); + break; } } if (conn) @@ -572,9 +525,10 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) * this device. */ devc->fw_uploaded = 0; + devc->usb_pid = pid; if (des.iProduct != LA2016_IPRODUCT_INDEX) { sr_info("Uploading MCU firmware to '%s'.", conn_id); - ret = la2016_upload_firmware(sdi, ctx, dev, pid); + ret = la2016_upload_firmware(sdi, ctx, dev, FALSE); if (ret != SR_OK) { sr_err("MCU firmware upload failed."); kingst_la2016_free_sdi(sdi); @@ -584,6 +538,13 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) usb->address = 0xff; renum_devices = g_slist_append(renum_devices, sdi); continue; + } else { + ret = la2016_upload_firmware(sdi, NULL, NULL, TRUE); + if (ret != SR_OK) { + sr_err("MCU firmware filename check failed."); + kingst_la2016_free_sdi(sdi); + continue; + } } /* @@ -640,12 +601,14 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) ch_max = ARRAY_SIZE(channel_names_logic); if (ch_max > devc->model->channel_count) ch_max = devc->model->channel_count; + devc->channel_names_logic = sr_parse_probe_names(probe_names, + channel_names_logic, ch_max, ch_max, &ch_max); cg = sr_channel_group_new(sdi, "Logic", NULL); devc->cg_logic = cg; for (ch_idx = 0; ch_idx < ch_max; ch_idx++) { ch = sr_channel_new(sdi, ch_off, SR_CHANNEL_LOGIC, TRUE, - channel_names_logic[ch_idx]); + devc->channel_names_logic[ch_idx]); ch_off++; cg->channels = g_slist_append(cg->channels, ch); } @@ -672,13 +635,10 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) sr_sw_limits_init(&devc->sw_limits); devc->sw_limits.limit_samples = 0; devc->capture_ratio = 50; - devc->cur_samplerate = devc->model->samplerate; -#if WITH_THRESHOLD_SIMPLE + devc->samplerate = devc->model->samplerate; + if (!devc->model->memory_bits) + devc->continuous = TRUE; devc->threshold_voltage_idx = LOGIC_THRESHOLD_IDX_DFLT; -#else /* WITH_THRESHOLD_SIMPLE */ - devc->threshold_voltage_idx = 0; - devc->threshold_voltage = logic_threshold_value[devc->threshold_voltage_idx]; -#endif /* WITH_THRESHOLD_SIMPLE */ if (ARRAY_SIZE(devc->pwm_setting) >= 1) { devc->pwm_setting[0].enabled = FALSE; devc->pwm_setting[0].freq = SR_KHZ(1); @@ -731,7 +691,10 @@ static int dev_close(struct sr_dev_inst *sdi) if (!usb->devhdl) return SR_ERR_BUG; - la2016_deinit_hardware(sdi); + la2016_release_resources(sdi); + + if (WITH_DEINIT_IN_CLOSE) + la2016_deinit_hardware(sdi); sr_info("Closing device on %d.%d (logical) / %s (physical) interface %d.", usb->bus, usb->address, sdi->connection_id, USB_INTERFACE); @@ -803,7 +766,6 @@ static int config_get(uint32_t key, GVariant **data, struct pwm_setting *pwm; struct sr_usb_dev_inst *usb; double voltage, rounded; - const char *label; (void)rounded; (void)voltage; @@ -821,12 +783,10 @@ static int config_get(uint32_t key, GVariant **data, if (cg && cg_type == SR_CHANNEL_LOGIC) { switch (key) { #if !WITH_THRESHOLD_DEVCFG -#if WITH_THRESHOLD_SIMPLE case SR_CONF_VOLTAGE_THRESHOLD: voltage = threshold_voltage(sdi, NULL); *data = std_gvar_tuple_double(voltage, voltage); break; -#endif /* WITH_THRESHOLD_SIMPLE */ #endif /* WITH_THRESHOLD_DEVCFG */ default: return SR_ERR_NA; @@ -859,7 +819,7 @@ static int config_get(uint32_t key, GVariant **data, *data = g_variant_new_printf("%d.%d", usb->bus, usb->address); break; case SR_CONF_SAMPLERATE: - *data = g_variant_new_uint64(devc->cur_samplerate); + *data = g_variant_new_uint64(devc->samplerate); break; case SR_CONF_LIMIT_SAMPLES: case SR_CONF_LIMIT_MSEC: @@ -868,25 +828,14 @@ static int config_get(uint32_t key, GVariant **data, *data = g_variant_new_uint64(devc->capture_ratio); break; #if WITH_THRESHOLD_DEVCFG -#if WITH_THRESHOLD_SIMPLE case SR_CONF_VOLTAGE_THRESHOLD: voltage = threshold_voltage(sdi, NULL); *data = std_gvar_tuple_double(voltage, voltage); break; -#else /* WITH_THRESHOLD_SIMPLE */ - case SR_CONF_VOLTAGE_THRESHOLD: - rounded = (int)(devc->threshold_voltage / 0.1) * 0.1; - *data = std_gvar_tuple_double(rounded, rounded + 0.1); - break; - case SR_CONF_LOGIC_THRESHOLD: - label = logic_threshold[devc->threshold_voltage_idx]; - *data = g_variant_new_string(label); - break; - case SR_CONF_LOGIC_THRESHOLD_CUSTOM: - *data = g_variant_new_double(devc->threshold_voltage); - break; -#endif /* WITH_THRESHOLD_SIMPLE */ #endif /* WITH_THRESHOLD_DEVCFG */ + case SR_CONF_CONTINUOUS: + *data = g_variant_new_boolean(devc->continuous); + break; default: return SR_ERR_NA; } @@ -902,8 +851,8 @@ static int config_set(uint32_t key, GVariant *data, size_t logic_idx, analog_idx; struct pwm_setting *pwm; double value_f; - double low, high, voltage; int idx; + gboolean on; devc = sdi->priv; @@ -916,7 +865,6 @@ static int config_set(uint32_t key, GVariant *data, if (cg && cg_type == SR_CHANNEL_LOGIC) { switch (key) { #if !WITH_THRESHOLD_DEVCFG -#if WITH_THRESHOLD_SIMPLE case SR_CONF_LOGIC_THRESHOLD: idx = std_double_tuple_idx(data, ARRAY_AND_SIZE(threshold_ranges)); @@ -924,7 +872,6 @@ static int config_set(uint32_t key, GVariant *data, return SR_ERR_ARG; devc->threshold_voltage_idx = idx; break; -#endif /* WITH_THRESHOLD_SIMPLE */ #endif /* WITH_THRESHOLD_DEVCFG */ default: return SR_ERR_NA; @@ -968,7 +915,7 @@ static int config_set(uint32_t key, GVariant *data, switch (key) { case SR_CONF_SAMPLERATE: - devc->cur_samplerate = g_variant_get_uint64(data); + devc->samplerate = g_variant_get_uint64(data); break; case SR_CONF_LIMIT_SAMPLES: case SR_CONF_LIMIT_MSEC: @@ -977,7 +924,6 @@ static int config_set(uint32_t key, GVariant *data, devc->capture_ratio = g_variant_get_uint64(data); break; #if WITH_THRESHOLD_DEVCFG -#if WITH_THRESHOLD_SIMPLE case SR_CONF_VOLTAGE_THRESHOLD: idx = std_double_tuple_idx(data, ARRAY_AND_SIZE(threshold_ranges)); @@ -985,27 +931,13 @@ static int config_set(uint32_t key, GVariant *data, return SR_ERR_ARG; devc->threshold_voltage_idx = idx; break; -#else /* WITH_THRESHOLD_SIMPLE */ - case SR_CONF_VOLTAGE_THRESHOLD: - g_variant_get(data, "(dd)", &low, &high); - devc->threshold_voltage = (low + high) / 2.0; - devc->threshold_voltage_idx = LOGIC_THRESHOLD_IDX_USER; - break; - case SR_CONF_LOGIC_THRESHOLD: { - idx = std_str_idx(data, ARRAY_AND_SIZE(logic_threshold)); - if (idx < 0) +#endif /* WITH_THRESHOLD_DEVCFG */ + case SR_CONF_CONTINUOUS: + on = g_variant_get_boolean(data); + if (!devc->model->memory_bits && !on) return SR_ERR_ARG; - if (idx != LOGIC_THRESHOLD_IDX_USER) { - devc->threshold_voltage = logic_threshold_value[idx]; - } - devc->threshold_voltage_idx = idx; - break; - } - case SR_CONF_LOGIC_THRESHOLD_CUSTOM: - devc->threshold_voltage = g_variant_get_double(data); + devc->continuous = on; break; -#endif /* WITH_THRESHOLD_SIMPLE */ -#endif /* WITH_THRESHOLD_DEVCFG */ default: return SR_ERR_NA; } @@ -1038,11 +970,9 @@ static int config_list(uint32_t key, GVariant **data, sizeof(devopts_cg_logic[0])); break; #if !WITH_THRESHOLD_DEVCFG -#if WITH_THRESHOLD_SIMPLE case SR_CONF_VOLTAGE_THRESHOLD: *data = std_gvar_thresholds(ARRAY_AND_SIZE(threshold_ranges)); break; -#endif /* WITH_THRESHOLD_SIMPLE */ #endif /* WITH_THRESHOLD_DEVCFG */ default: return SR_ERR_NA; @@ -1076,27 +1006,18 @@ static int config_list(uint32_t key, GVariant **data, *data = std_gvar_samplerates(ARRAY_AND_SIZE(rates_500mhz)); else if (devc->model->samplerate == SR_MHZ(200)) *data = std_gvar_samplerates(ARRAY_AND_SIZE(rates_200mhz)); - else + else if (devc->model->samplerate == SR_MHZ(100)) *data = std_gvar_samplerates(ARRAY_AND_SIZE(rates_100mhz)); + else + return SR_ERR_BUG; break; case SR_CONF_LIMIT_SAMPLES: *data = std_gvar_tuple_u64(0, LA2016_NUM_SAMPLES_MAX); break; #if WITH_THRESHOLD_DEVCFG -#if WITH_THRESHOLD_SIMPLE case SR_CONF_VOLTAGE_THRESHOLD: *data = std_gvar_thresholds(ARRAY_AND_SIZE(threshold_ranges)); break; -#else /* WITH_THRESHOLD_SIMPLE */ - case SR_CONF_VOLTAGE_THRESHOLD: - *data = std_gvar_min_max_step_thresholds( - LA2016_THR_VOLTAGE_MIN, - LA2016_THR_VOLTAGE_MAX, 0.1); - break; - case SR_CONF_LOGIC_THRESHOLD: - *data = g_variant_new_strv(ARRAY_AND_SIZE(logic_threshold)); - break; -#endif /* WITH_THRESHOLD_SIMPLE */ #endif /* WITH_THRESHOLD_DEVCFG */ case SR_CONF_TRIGGER_MATCH: *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches)); @@ -1114,6 +1035,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) struct drv_context *drvc; struct sr_context *ctx; struct dev_context *devc; + size_t unitsize; double voltage; int ret; @@ -1123,12 +1045,21 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) devc = sdi->priv; if (!devc->feed_queue) { + if (devc->model->channel_count == 32) + unitsize = sizeof(uint32_t); + else if (devc->model->channel_count == 16) + unitsize = sizeof(uint16_t); + else + return SR_ERR_ARG; devc->feed_queue = feed_queue_logic_alloc(sdi, - LA2016_CONVBUFFER_SIZE, sizeof(uint16_t)); + LA2016_CONVBUFFER_SIZE, unitsize); if (!devc->feed_queue) { sr_err("Cannot allocate buffer for session feed."); return SR_ERR_MALLOC; } + devc->packets_per_chunk = TRANSFER_PACKET_LENGTH; + devc->packets_per_chunk--; + devc->packets_per_chunk /= unitsize + sizeof(uint8_t); } sr_sw_limits_acquisition_start(&devc->sw_limits);