X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fasix-sigma%2Fapi.c;h=04bc74887de3604b51bec147ba9b1ed5abdcddd8;hb=88a5f9eabe72113d70c29d45dc12eabc0add9c49;hp=15c222521aca1c7d6fd0f0ae01ec10f55a694960;hpb=9fb4c6324dc05e909387c3db44d5a43d899c8641;p=libsigrok.git diff --git a/src/hardware/asix-sigma/api.c b/src/hardware/asix-sigma/api.c index 15c22252..04bc7488 100644 --- a/src/hardware/asix-sigma/api.c +++ b/src/hardware/asix-sigma/api.c @@ -4,6 +4,7 @@ * Copyright (C) 2010-2012 Håvard Espeland , * Copyright (C) 2010 Martin Stensgård * Copyright (C) 2010 Carl Henrik Lunde + * Copyright (C) 2020 Gerhard Sittig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,7 +68,8 @@ static void clear_helper(struct dev_context *devc) static int dev_clear(const struct sr_dev_driver *di) { - return std_dev_clear_with_callback(di, (std_dev_clear_callback)clear_helper); + return std_dev_clear_with_callback(di, + (std_dev_clear_callback)clear_helper); } static gboolean bus_addr_in_devices(int bus, int addr, GSList *devs) @@ -85,9 +87,13 @@ static gboolean bus_addr_in_devices(int bus, int addr, GSList *devs) static gboolean known_vid_pid(const struct libusb_device_descriptor *des) { + gboolean is_sigma, is_omega; + if (des->idVendor != USB_VENDOR_ASIX) return FALSE; - if (des->idProduct != USB_PRODUCT_SIGMA && des->idProduct != USB_PRODUCT_OMEGA) + is_sigma = des->idProduct == USB_PRODUCT_SIGMA; + is_omega = des->idProduct == USB_PRODUCT_OMEGA; + if (!is_sigma && !is_omega) return FALSE; return TRUE; } @@ -233,12 +239,9 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) devc->id.serno = serno_num; devc->id.prefix = serno_pre; devc->id.type = dev_type; - devc->cur_samplerate = samplerates[0]; - devc->limit_msec = 0; - devc->limit_samples = 0; - devc->cur_firmware = -1; - devc->num_channels = 0; - devc->samples_per_event = 0; + devc->samplerate = samplerates[0]; + sr_sw_limits_init(&devc->cfg_limits); + devc->firmware_idx = SIGMA_FW_NONE; devc->capture_ratio = 50; devc->use_triggers = 0; } @@ -310,14 +313,11 @@ static int config_get(uint32_t key, GVariant **data, *data = g_variant_new_string(sdi->connection_id); 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_MSEC: - *data = g_variant_new_uint64(devc->limit_msec); - break; case SR_CONF_LIMIT_SAMPLES: - *data = g_variant_new_uint64(devc->limit_samples); - break; + return sr_sw_limits_config_get(&devc->cfg_limits, key, data); #if ASIX_SIGMA_WITH_TRIGGER case SR_CONF_CAPTURE_RATIO: *data = g_variant_new_uint64(devc->capture_ratio); @@ -334,6 +334,8 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; + int ret; + uint64_t want_rate, have_rate; (void)cg; @@ -341,15 +343,24 @@ static int config_set(uint32_t key, GVariant *data, switch (key) { case SR_CONF_SAMPLERATE: - return sigma_set_samplerate(sdi, g_variant_get_uint64(data)); - case SR_CONF_LIMIT_MSEC: - devc->limit_msec = g_variant_get_uint64(data); + want_rate = g_variant_get_uint64(data); + ret = sigma_normalize_samplerate(want_rate, &have_rate); + if (ret != SR_OK) + return ret; + if (have_rate != want_rate) { + char *text_want, *text_have; + text_want = sr_samplerate_string(want_rate); + text_have = sr_samplerate_string(have_rate); + sr_info("Adjusted samplerate %s to %s.", + text_want, text_have); + g_free(text_want); + g_free(text_have); + } + devc->samplerate = have_rate; break; + case SR_CONF_LIMIT_MSEC: case SR_CONF_LIMIT_SAMPLES: - devc->limit_samples = g_variant_get_uint64(data); - devc->limit_msec = sigma_limit_samples_to_msec(devc, - devc->limit_samples); - break; + return sr_sw_limits_config_set(&devc->cfg_limits, key, data); #if ASIX_SIGMA_WITH_TRIGGER case SR_CONF_CAPTURE_RATIO: devc->capture_ratio = g_variant_get_uint64(data); @@ -370,7 +381,8 @@ static int config_list(uint32_t key, GVariant **data, case SR_CONF_DEVICE_OPTIONS: if (cg) return SR_ERR_NA; - return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts); + return STD_CONFIG_LIST(key, data, sdi, cg, + scanopts, drvopts, devopts); case SR_CONF_SAMPLERATE: *data = std_gvar_samplerates(samplerates, samplerates_count); break; @@ -394,75 +406,116 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) uint8_t triggerselect; struct triggerinout triggerinout_conf; struct triggerlut lut; - uint8_t regval; - uint8_t clock_bytes[sizeof(clockselect)]; - size_t clock_idx; + uint8_t regval, trgconf_bytes[2], clock_bytes[4], *wrptr; + size_t count; devc = sdi->priv; - if (sigma_convert_trigger(sdi) != SR_OK) { - sr_err("Failed to configure triggers."); - return SR_ERR; - } - - /* If the samplerate has not been set, default to 200 kHz. */ - if (devc->cur_firmware == -1) { - if ((ret = sigma_set_samplerate(sdi, SR_KHZ(200))) != SR_OK) - return ret; + /* + * Setup the device's samplerate from the value which up to now + * just got checked and stored. As a byproduct this can pick and + * send firmware to the device, reduce the number of available + * logic channels, etc. + * + * Determine an acquisition timeout from optionally configured + * sample count or time limits. Which depends on the samplerate. + */ + ret = sigma_set_samplerate(sdi); + if (ret != SR_OK) + return ret; + ret = sigma_set_acquire_timeout(devc); + if (ret != SR_OK) + return ret; + + ret = sigma_convert_trigger(sdi); + if (ret != SR_OK) { + sr_err("Could not configure triggers."); + return ret; } /* Enter trigger programming mode. */ - sigma_set_register(WRITE_TRIGGER_SELECT2, 0x20, devc); + ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, 0x20); + if (ret != SR_OK) + return ret; triggerselect = 0; - if (devc->cur_samplerate >= SR_MHZ(100)) { + if (devc->samplerate >= SR_MHZ(100)) { /* 100 and 200 MHz mode. */ - sigma_set_register(WRITE_TRIGGER_SELECT2, 0x81, devc); + ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, 0x81); + if (ret != SR_OK) + return ret; /* Find which pin to trigger on from mask. */ - for (triggerpin = 0; triggerpin < 8; triggerpin++) - if ((devc->trigger.risingmask | devc->trigger.fallingmask) & - (1 << triggerpin)) + for (triggerpin = 0; triggerpin < 8; triggerpin++) { + if (devc->trigger.risingmask & (1 << triggerpin)) + break; + if (devc->trigger.fallingmask & (1 << triggerpin)) break; + } /* Set trigger pin and light LED on trigger. */ - triggerselect = (1 << LEDSEL1) | (triggerpin & 0x7); + triggerselect = TRGSEL2_LEDSEL1 | (triggerpin & 0x7); /* Default rising edge. */ if (devc->trigger.fallingmask) triggerselect |= 1 << 3; - } else if (devc->cur_samplerate <= SR_MHZ(50)) { + } else if (devc->samplerate <= SR_MHZ(50)) { /* All other modes. */ - sigma_build_basic_trigger(&lut, devc); + ret = sigma_build_basic_trigger(devc, &lut); + if (ret != SR_OK) + return ret; - sigma_write_trigger_lut(&lut, devc); + ret = sigma_write_trigger_lut(devc, &lut); + if (ret != SR_OK) + return ret; - triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0); + triggerselect = TRGSEL2_LEDSEL1 | TRGSEL2_LEDSEL0; } /* Setup trigger in and out pins to default values. */ - memset(&triggerinout_conf, 0, sizeof(struct triggerinout)); + memset(&triggerinout_conf, 0, sizeof(triggerinout_conf)); triggerinout_conf.trgout_bytrigger = 1; triggerinout_conf.trgout_enable = 1; - - sigma_write_register(WRITE_TRIGGER_OPTION, - (uint8_t *) &triggerinout_conf, - sizeof(struct triggerinout), devc); - - /* Go back to normal mode. */ - sigma_set_register(WRITE_TRIGGER_SELECT2, triggerselect, devc); + /* TODO + * Verify the correctness of this implementation. The previous + * version used to assign to a C language struct with bit fields + * which is highly non-portable and hard to guess the resulting + * raw memory layout or wire transfer content. The C struct's + * field names did not match the vendor documentation's names. + * Which means that I could not verify "on paper" either. Let's + * re-visit this code later during research for trigger support. + */ + wrptr = trgconf_bytes; + regval = 0; + if (triggerinout_conf.trgout_bytrigger) + regval |= TRGOPT_TRGOOUTEN; + write_u8_inc(&wrptr, regval); + regval &= ~TRGOPT_CLEAR_MASK; + if (triggerinout_conf.trgout_enable) + regval |= TRGOPT_TRGOEN; + write_u8_inc(&wrptr, regval); + count = wrptr - trgconf_bytes; + ret = sigma_write_register(devc, WRITE_TRIGGER_OPTION, + trgconf_bytes, count); + if (ret != SR_OK) + return ret; + + /* Leave trigger programming mode. */ + ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, triggerselect); + if (ret != SR_OK) + return ret; /* Set clock select register. */ clockselect.async = 0; - clockselect.fraction = 1 - 1; /* Divider 1. */ + clockselect.fraction = 1; /* Divider 1. */ clockselect.disabled_channels = 0x0000; /* All channels enabled. */ - if (devc->cur_samplerate == SR_MHZ(200)) { + if (devc->samplerate == SR_MHZ(200)) { /* Enable 4 channels. */ - clockselect.disabled_channels = 0xf0ff; - } else if (devc->cur_samplerate == SR_MHZ(100)) { + clockselect.disabled_channels = 0xfff0; + } else if (devc->samplerate == SR_MHZ(100)) { /* Enable 8 channels. */ - clockselect.disabled_channels = 0x00ff; + clockselect.disabled_channels = 0xff00; } else { /* * 50 MHz mode, or fraction thereof. The 50MHz reference @@ -471,31 +524,41 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) * (The driver lists a discrete set of sample rates, but * all of them fit the above description.) */ - clockselect.fraction = SR_MHZ(50) / devc->cur_samplerate - 1; + clockselect.fraction = SR_MHZ(50) / devc->samplerate; } - clock_idx = 0; - clock_bytes[clock_idx++] = clockselect.async; - clock_bytes[clock_idx++] = clockselect.fraction; - clock_bytes[clock_idx++] = clockselect.disabled_channels & 0xff; - clock_bytes[clock_idx++] = clockselect.disabled_channels >> 8; - sigma_write_register(WRITE_CLOCK_SELECT, clock_bytes, clock_idx, devc); + wrptr = clock_bytes; + write_u8_inc(&wrptr, clockselect.async); + write_u8_inc(&wrptr, clockselect.fraction - 1); + write_u16be_inc(&wrptr, clockselect.disabled_channels); + count = wrptr - clock_bytes; + ret = sigma_write_register(devc, WRITE_CLOCK_SELECT, clock_bytes, count); + if (ret != SR_OK) + return ret; /* Setup maximum post trigger time. */ - sigma_set_register(WRITE_POST_TRIGGER, - (devc->capture_ratio * 255) / 100, devc); + ret = sigma_set_register(devc, WRITE_POST_TRIGGER, + (devc->capture_ratio * 255) / 100); + if (ret != SR_OK) + return ret; /* Start acqusition. */ - devc->start_time = g_get_monotonic_time(); - regval = WMR_TRGRES | WMR_SDRAMWRITEEN; + regval = WMR_TRGRES | WMR_SDRAMWRITEEN; #if ASIX_SIGMA_WITH_TRIGGER regval |= WMR_TRGEN; #endif - sigma_set_register(WRITE_MODE, regval, devc); + ret = sigma_set_register(devc, WRITE_MODE, regval); + if (ret != SR_OK) + return ret; - std_session_send_df_header(sdi); + ret = std_session_send_df_header(sdi); + if (ret != SR_OK) + return ret; /* Add capture source. */ - sr_session_source_add(sdi->session, -1, 0, 10, sigma_receive_data, (void *)sdi); + ret = sr_session_source_add(sdi->session, -1, 0, 10, + sigma_receive_data, (void *)sdi); + if (ret != SR_OK) + return ret; devc->state.state = SIGMA_CAPTURE; @@ -519,7 +582,7 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi) devc->state.state = SIGMA_STOPPING; } else { devc->state.state = SIGMA_IDLE; - sr_session_source_remove(sdi->session, -1); + (void)sr_session_source_remove(sdi->session, -1); } return SR_OK;