diff --git a/Makefile.am b/Makefile.am index 660b0fc9..cd21a688 100644 --- a/Makefile.am +++ b/Makefile.am @@ -174,8 +174,9 @@ libsigrok_la_SOURCES += \ endif if HW_ASIX_SIGMA libsigrok_la_SOURCES += \ - src/hardware/asix-sigma/asix-sigma.h \ - src/hardware/asix-sigma/asix-sigma.c + src/hardware/asix-sigma/protocol.h \ + src/hardware/asix-sigma/protocol.c \ + src/hardware/asix-sigma/api.c endif if HW_ATTEN_PPS3XXX libsigrok_la_SOURCES += \ diff --git a/src/hardware/asix-sigma/api.c b/src/hardware/asix-sigma/api.c new file mode 100644 index 00000000..8b798d4e --- /dev/null +++ b/src/hardware/asix-sigma/api.c @@ -0,0 +1,445 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2010-2012 Håvard Espeland , + * Copyright (C) 2010 Martin Stensgård + * Copyright (C) 2010 Carl Henrik Lunde + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * ASIX SIGMA/SIGMA2 logic analyzer driver + */ + +#include +#include "protocol.h" + +SR_PRIV struct sr_dev_driver asix_sigma_driver_info; + +/* + * Channel numbers seem to go from 1-16, according to this image: + * http://tools.asix.net/img/sigma_sigmacab_pins_720.jpg + * (the cable has two additional GND pins, and a TI and TO pin) + */ +static const char *channel_names[] = { + "1", "2", "3", "4", "5", "6", "7", "8", + "9", "10", "11", "12", "13", "14", "15", "16", +}; + +static const uint32_t drvopts[] = { + SR_CONF_LOGIC_ANALYZER, +}; + +static const uint32_t devopts[] = { + SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET, + SR_CONF_LIMIT_SAMPLES | SR_CONF_SET, + SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_TRIGGER_MATCH | SR_CONF_LIST, + SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET, +}; + +static const int32_t trigger_matches[] = { + SR_TRIGGER_ZERO, + SR_TRIGGER_ONE, + SR_TRIGGER_RISING, + SR_TRIGGER_FALLING, +}; + + +static int dev_clear(const struct sr_dev_driver *di) +{ + return std_dev_clear(di, sigma_clear_helper); +} + +static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx) +{ + return std_init(sr_ctx, di, LOG_PREFIX); +} + +static GSList *scan(struct sr_dev_driver *di, GSList *options) +{ + struct sr_dev_inst *sdi; + struct drv_context *drvc; + struct dev_context *devc; + GSList *devices; + struct ftdi_device_list *devlist; + char serial_txt[10]; + uint32_t serial; + int ret; + unsigned int i; + + (void)options; + + drvc = di->context; + + devices = NULL; + + devc = g_malloc0(sizeof(struct dev_context)); + + ftdi_init(&devc->ftdic); + + /* Look for SIGMAs. */ + + if ((ret = ftdi_usb_find_all(&devc->ftdic, &devlist, + USB_VENDOR, USB_PRODUCT)) <= 0) { + if (ret < 0) + sr_err("ftdi_usb_find_all(): %d", ret); + goto free; + } + + /* Make sure it's a version 1 or 2 SIGMA. */ + ftdi_usb_get_strings(&devc->ftdic, devlist->dev, NULL, 0, NULL, 0, + serial_txt, sizeof(serial_txt)); + sscanf(serial_txt, "%x", &serial); + + if (serial < 0xa6010000 || serial > 0xa602ffff) { + sr_err("Only SIGMA and SIGMA2 are supported " + "in this version of libsigrok."); + goto free; + } + + sr_info("Found ASIX SIGMA - Serial: %s", serial_txt); + + devc->cur_samplerate = samplerates[0]; + devc->period_ps = 0; + devc->limit_msec = 0; + devc->cur_firmware = -1; + devc->num_channels = 0; + devc->samples_per_event = 0; + devc->capture_ratio = 50; + devc->use_triggers = 0; + + /* Register SIGMA device. */ + sdi = g_malloc0(sizeof(struct sr_dev_inst)); + sdi->status = SR_ST_INITIALIZING; + sdi->vendor = g_strdup(USB_VENDOR_NAME); + sdi->model = g_strdup(USB_MODEL_NAME); + sdi->driver = di; + + for (i = 0; i < ARRAY_SIZE(channel_names); i++) + sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_names[i]); + + devices = g_slist_append(devices, sdi); + drvc->instances = g_slist_append(drvc->instances, sdi); + sdi->priv = devc; + + /* We will open the device again when we need it. */ + ftdi_list_free(&devlist); + + return devices; + +free: + ftdi_deinit(&devc->ftdic); + g_free(devc); + return NULL; +} + +static GSList *dev_list(const struct sr_dev_driver *di) +{ + return ((struct drv_context *)(di->context))->instances; +} + +static int dev_open(struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + int ret; + + devc = sdi->priv; + + /* Make sure it's an ASIX SIGMA. */ + if ((ret = ftdi_usb_open_desc(&devc->ftdic, + USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) { + + sr_err("ftdi_usb_open failed: %s", + ftdi_get_error_string(&devc->ftdic)); + + return 0; + } + + sdi->status = SR_ST_ACTIVE; + + return SR_OK; +} + +static int dev_close(struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + + devc = sdi->priv; + + /* TODO */ + if (sdi->status == SR_ST_ACTIVE) + ftdi_usb_close(&devc->ftdic); + + sdi->status = SR_ST_INACTIVE; + + return SR_OK; +} + +static int cleanup(const struct sr_dev_driver *di) +{ + return dev_clear(di); +} + +static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) +{ + struct dev_context *devc; + + (void)cg; + + if (!sdi) + return SR_ERR; + devc = sdi->priv; + + switch (key) { + case SR_CONF_SAMPLERATE: + *data = g_variant_new_uint64(devc->cur_samplerate); + break; + case SR_CONF_LIMIT_MSEC: + *data = g_variant_new_uint64(devc->limit_msec); + break; + case SR_CONF_CAPTURE_RATIO: + *data = g_variant_new_uint64(devc->capture_ratio); + break; + default: + return SR_ERR_NA; + } + + return SR_OK; +} + +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; + uint64_t tmp; + int ret; + + (void)cg; + + if (sdi->status != SR_ST_ACTIVE) + return SR_ERR_DEV_CLOSED; + + devc = sdi->priv; + + ret = SR_OK; + switch (key) { + case SR_CONF_SAMPLERATE: + ret = sigma_set_samplerate(sdi, g_variant_get_uint64(data)); + break; + case SR_CONF_LIMIT_MSEC: + tmp = g_variant_get_uint64(data); + if (tmp > 0) + devc->limit_msec = g_variant_get_uint64(data); + else + ret = SR_ERR; + break; + case SR_CONF_LIMIT_SAMPLES: + tmp = g_variant_get_uint64(data); + devc->limit_msec = tmp * 1000 / devc->cur_samplerate; + break; + case SR_CONF_CAPTURE_RATIO: + tmp = g_variant_get_uint64(data); + if (tmp <= 100) + devc->capture_ratio = tmp; + else + ret = SR_ERR; + break; + default: + ret = SR_ERR_NA; + } + + return ret; +} + +static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) +{ + GVariant *gvar; + GVariantBuilder gvb; + + (void)cg; + + switch (key) { + case SR_CONF_DEVICE_OPTIONS: + if (!sdi) + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t)); + else + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + devopts, ARRAY_SIZE(devopts), sizeof(uint32_t)); + break; + case SR_CONF_SAMPLERATE: + g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); + gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates, + SAMPLERATES_COUNT, sizeof(uint64_t)); + g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); + *data = g_variant_builder_end(&gvb); + break; + 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; + default: + return SR_ERR_NA; + } + + return SR_OK; +} + +static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) +{ + struct dev_context *devc; + struct clockselect_50 clockselect; + int frac, triggerpin, ret; + uint8_t triggerselect = 0; + struct triggerinout triggerinout_conf; + struct triggerlut lut; + + if (sdi->status != SR_ST_ACTIVE) + return SR_ERR_DEV_CLOSED; + + 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; + } + + /* Enter trigger programming mode. */ + sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20, devc); + + /* 100 and 200 MHz mode. */ + if (devc->cur_samplerate >= SR_MHZ(100)) { + sigma_set_register(WRITE_TRIGGER_SELECT1, 0x81, devc); + + /* Find which pin to trigger on from mask. */ + for (triggerpin = 0; triggerpin < 8; ++triggerpin) + if ((devc->trigger.risingmask | devc->trigger.fallingmask) & + (1 << triggerpin)) + break; + + /* Set trigger pin and light LED on trigger. */ + triggerselect = (1 << LEDSEL1) | (triggerpin & 0x7); + + /* Default rising edge. */ + if (devc->trigger.fallingmask) + triggerselect |= 1 << 3; + + /* All other modes. */ + } else if (devc->cur_samplerate <= SR_MHZ(50)) { + sigma_build_basic_trigger(&lut, devc); + + sigma_write_trigger_lut(&lut, devc); + + triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0); + } + + /* Setup trigger in and out pins to default values. */ + memset(&triggerinout_conf, 0, sizeof(struct triggerinout)); + 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_SELECT1, triggerselect, devc); + + /* Set clock select register. */ + if (devc->cur_samplerate == SR_MHZ(200)) + /* Enable 4 channels. */ + sigma_set_register(WRITE_CLOCK_SELECT, 0xf0, devc); + else if (devc->cur_samplerate == SR_MHZ(100)) + /* Enable 8 channels. */ + sigma_set_register(WRITE_CLOCK_SELECT, 0x00, devc); + else { + /* + * 50 MHz mode (or fraction thereof). Any fraction down to + * 50 MHz / 256 can be used, but is not supported by sigrok API. + */ + frac = SR_MHZ(50) / devc->cur_samplerate - 1; + + clockselect.async = 0; + clockselect.fraction = frac; + clockselect.disabled_channels = 0; + + sigma_write_register(WRITE_CLOCK_SELECT, + (uint8_t *) &clockselect, + sizeof(clockselect), devc); + } + + /* Setup maximum post trigger time. */ + sigma_set_register(WRITE_POST_TRIGGER, + (devc->capture_ratio * 255) / 100, devc); + + /* Start acqusition. */ + gettimeofday(&devc->start_tv, 0); + sigma_set_register(WRITE_MODE, 0x0d, devc); + + devc->cb_data = cb_data; + + /* Send header packet to the session bus. */ + std_session_send_df_header(sdi, LOG_PREFIX); + + /* Add capture source. */ + sr_session_source_add(sdi->session, -1, 0, 10, sigma_receive_data, (void *)sdi); + + devc->state.state = SIGMA_CAPTURE; + + return SR_OK; +} + +static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) +{ + struct dev_context *devc; + + (void)cb_data; + + devc = sdi->priv; + devc->state.state = SIGMA_IDLE; + + sr_session_source_remove(sdi->session, -1); + + return SR_OK; +} + +SR_PRIV struct sr_dev_driver asix_sigma_driver_info = { + .name = "asix-sigma", + .longname = "ASIX SIGMA/SIGMA2", + .api_version = 1, + .init = init, + .cleanup = cleanup, + .scan = scan, + .dev_list = dev_list, + .dev_clear = dev_clear, + .config_get = config_get, + .config_set = config_set, + .config_list = config_list, + .dev_open = dev_open, + .dev_close = dev_close, + .dev_acquisition_start = dev_acquisition_start, + .dev_acquisition_stop = dev_acquisition_stop, + .context = NULL, +}; diff --git a/src/hardware/asix-sigma/asix-sigma.c b/src/hardware/asix-sigma/protocol.c similarity index 72% rename from src/hardware/asix-sigma/asix-sigma.c rename to src/hardware/asix-sigma/protocol.c index 9db557b3..8f07a0d8 100644 --- a/src/hardware/asix-sigma/asix-sigma.c +++ b/src/hardware/asix-sigma/protocol.c @@ -24,14 +24,7 @@ */ #include -#include -#include -#include -#include -#include -#include -#include "libsigrok-internal.h" -#include "asix-sigma.h" +#include "protocol.h" #define USB_VENDOR 0xa600 #define USB_PRODUCT 0xa000 @@ -40,7 +33,6 @@ #define USB_MODEL_NAME "SIGMA" SR_PRIV struct sr_dev_driver asix_sigma_driver_info; -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data); /* * The ASIX Sigma supports arbitrary integer frequency divider in @@ -48,7 +40,7 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data); * very precise sampling rate selection. This driver supports only * a subset of the sampling rates. */ -static const uint64_t samplerates[] = { +SR_PRIV const uint64_t samplerates[] = { SR_KHZ(200), /* div=250 */ SR_KHZ(250), /* div=200 */ SR_KHZ(500), /* div=100 */ @@ -61,34 +53,7 @@ static const uint64_t samplerates[] = { SR_MHZ(200), /* Special FW needed */ }; -/* - * Channel numbers seem to go from 1-16, according to this image: - * http://tools.asix.net/img/sigma_sigmacab_pins_720.jpg - * (the cable has two additional GND pins, and a TI and TO pin) - */ -static const char *channel_names[] = { - "1", "2", "3", "4", "5", "6", "7", "8", - "9", "10", "11", "12", "13", "14", "15", "16", -}; - -static const uint32_t drvopts[] = { - SR_CONF_LOGIC_ANALYZER, -}; - -static const uint32_t devopts[] = { - SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET, - SR_CONF_LIMIT_SAMPLES | SR_CONF_SET, - SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, - SR_CONF_TRIGGER_MATCH | SR_CONF_LIST, - SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET, -}; - -static const int32_t trigger_matches[] = { - SR_TRIGGER_ZERO, - SR_TRIGGER_ONE, - SR_TRIGGER_RISING, - SR_TRIGGER_FALLING, -}; +SR_PRIV const int SAMPLERATES_COUNT = ARRAY_SIZE(samplerates); static const char sigma_firmware_files[][24] = { /* 50 MHz, supports 8 bit fractions */ @@ -135,8 +100,8 @@ static int sigma_write(void *buf, size_t size, struct dev_context *devc) * NOTE: We chose the buffer size to be large enough to hold any write to the * device. We still print a message just in case. */ -static int sigma_write_register(uint8_t reg, uint8_t *data, size_t len, - struct dev_context *devc) +SR_PRIV int sigma_write_register(uint8_t reg, uint8_t *data, size_t len, + struct dev_context *devc) { size_t i; uint8_t buf[80]; @@ -159,7 +124,7 @@ static int sigma_write_register(uint8_t reg, uint8_t *data, size_t len, return sigma_write(buf, idx, devc); } -static int sigma_set_register(uint8_t reg, uint8_t value, struct dev_context *devc) +SR_PRIV int sigma_set_register(uint8_t reg, uint8_t value, struct dev_context *devc) { return sigma_write_register(reg, &value, 1, devc); } @@ -255,7 +220,7 @@ static int sigma_read_dram(uint16_t startchunk, size_t numchunks, } /* Upload trigger look-up tables to Sigma. */ -static int sigma_write_trigger_lut(struct triggerlut *lut, struct dev_context *devc) +SR_PRIV int sigma_write_trigger_lut(struct triggerlut *lut, struct dev_context *devc) { int i; uint8_t tmp[2]; @@ -313,7 +278,7 @@ static int sigma_write_trigger_lut(struct triggerlut *lut, struct dev_context *d return SR_OK; } -static void clear_helper(void *priv) +SR_PRIV void sigma_clear_helper(void *priv) { struct dev_context *devc; @@ -322,99 +287,6 @@ static void clear_helper(void *priv) ftdi_deinit(&devc->ftdic); } -static int dev_clear(const struct sr_dev_driver *di) -{ - return std_dev_clear(di, clear_helper); -} - -static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(struct sr_dev_driver *di, GSList *options) -{ - struct sr_dev_inst *sdi; - struct drv_context *drvc; - struct dev_context *devc; - GSList *devices; - struct ftdi_device_list *devlist; - char serial_txt[10]; - uint32_t serial; - int ret; - unsigned int i; - - (void)options; - - drvc = di->context; - - devices = NULL; - - devc = g_malloc0(sizeof(struct dev_context)); - - ftdi_init(&devc->ftdic); - - /* Look for SIGMAs. */ - - if ((ret = ftdi_usb_find_all(&devc->ftdic, &devlist, - USB_VENDOR, USB_PRODUCT)) <= 0) { - if (ret < 0) - sr_err("ftdi_usb_find_all(): %d", ret); - goto free; - } - - /* Make sure it's a version 1 or 2 SIGMA. */ - ftdi_usb_get_strings(&devc->ftdic, devlist->dev, NULL, 0, NULL, 0, - serial_txt, sizeof(serial_txt)); - sscanf(serial_txt, "%x", &serial); - - if (serial < 0xa6010000 || serial > 0xa602ffff) { - sr_err("Only SIGMA and SIGMA2 are supported " - "in this version of libsigrok."); - goto free; - } - - sr_info("Found ASIX SIGMA - Serial: %s", serial_txt); - - devc->cur_samplerate = samplerates[0]; - devc->period_ps = 0; - devc->limit_msec = 0; - devc->cur_firmware = -1; - devc->num_channels = 0; - devc->samples_per_event = 0; - devc->capture_ratio = 50; - devc->use_triggers = 0; - - /* Register SIGMA device. */ - sdi = g_malloc0(sizeof(struct sr_dev_inst)); - sdi->status = SR_ST_INITIALIZING; - sdi->vendor = g_strdup(USB_VENDOR_NAME); - sdi->model = g_strdup(USB_MODEL_NAME); - sdi->driver = di; - - for (i = 0; i < ARRAY_SIZE(channel_names); i++) - sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_names[i]); - - devices = g_slist_append(devices, sdi); - drvc->instances = g_slist_append(drvc->instances, sdi); - sdi->priv = devc; - - /* We will open the device again when we need it. */ - ftdi_list_free(&devlist); - - return devices; - -free: - ftdi_deinit(&devc->ftdic); - g_free(devc); - return NULL; -} - -static GSList *dev_list(const struct sr_dev_driver *di) -{ - return ((struct drv_context *)(di->context))->instances; -} - /* * Configure the FPGA for bitbang mode. * This sequence is documented in section 2. of the ASIX Sigma programming @@ -642,29 +514,7 @@ static int upload_firmware(struct sr_context *ctx, return SR_OK; } -static int dev_open(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - int ret; - - devc = sdi->priv; - - /* Make sure it's an ASIX SIGMA. */ - if ((ret = ftdi_usb_open_desc(&devc->ftdic, - USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) { - - sr_err("ftdi_usb_open failed: %s", - ftdi_get_error_string(&devc->ftdic)); - - return 0; - } - - sdi->status = SR_ST_ACTIVE; - - return SR_OK; -} - -static int set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) +SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) { struct dev_context *devc; struct drv_context *drvc; @@ -711,7 +561,7 @@ static int set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) * The Sigma supports complex triggers using boolean expressions, but this * has not been implemented yet. */ -static int convert_trigger(const struct sr_dev_inst *sdi) +SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_trigger *trigger; @@ -788,133 +638,6 @@ static int convert_trigger(const struct sr_dev_inst *sdi) return SR_OK; } -static int dev_close(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - - devc = sdi->priv; - - /* TODO */ - if (sdi->status == SR_ST_ACTIVE) - ftdi_usb_close(&devc->ftdic); - - sdi->status = SR_ST_INACTIVE; - - return SR_OK; -} - -static int cleanup(const struct sr_dev_driver *di) -{ - return dev_clear(di); -} - -static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - if (!sdi) - return SR_ERR; - devc = sdi->priv; - - switch (key) { - case SR_CONF_SAMPLERATE: - *data = g_variant_new_uint64(devc->cur_samplerate); - break; - case SR_CONF_LIMIT_MSEC: - *data = g_variant_new_uint64(devc->limit_msec); - break; - case SR_CONF_CAPTURE_RATIO: - *data = g_variant_new_uint64(devc->capture_ratio); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -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; - uint64_t tmp; - int ret; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - - ret = SR_OK; - switch (key) { - case SR_CONF_SAMPLERATE: - ret = set_samplerate(sdi, g_variant_get_uint64(data)); - break; - case SR_CONF_LIMIT_MSEC: - tmp = g_variant_get_uint64(data); - if (tmp > 0) - devc->limit_msec = g_variant_get_uint64(data); - else - ret = SR_ERR; - break; - case SR_CONF_LIMIT_SAMPLES: - tmp = g_variant_get_uint64(data); - devc->limit_msec = tmp * 1000 / devc->cur_samplerate; - break; - case SR_CONF_CAPTURE_RATIO: - tmp = g_variant_get_uint64(data); - if (tmp <= 100) - devc->capture_ratio = tmp; - else - ret = SR_ERR; - break; - default: - ret = SR_ERR_NA; - } - - return ret; -} - -static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - GVariant *gvar; - GVariantBuilder gvb; - - (void)cg; - - switch (key) { - case SR_CONF_DEVICE_OPTIONS: - if (!sdi) - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t)); - else - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - devopts, ARRAY_SIZE(devopts), sizeof(uint32_t)); - break; - case SR_CONF_SAMPLERATE: - g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); - gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates, - ARRAY_SIZE(samplerates), sizeof(uint64_t)); - g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); - *data = g_variant_builder_end(&gvb); - break; - 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; - default: - return SR_ERR_NA; - } - - return SR_OK; -} /* Software trigger to determine exact trigger position. */ static int get_trigger_offset(uint8_t *samples, uint16_t last_sample, @@ -1190,7 +913,7 @@ static int download_capture(struct sr_dev_inst *sdi) packet.type = SR_DF_END; sr_session_send(sdi, &packet); - dev_acquisition_stop(sdi, sdi); + sdi->driver->dev_acquisition_stop(sdi, sdi); g_free(dram_line); @@ -1229,7 +952,7 @@ static int sigma_capture_mode(struct sr_dev_inst *sdi) return TRUE; } -static int receive_data(int fd, int revents, void *cb_data) +SR_PRIV int sigma_receive_data(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct dev_context *devc; @@ -1361,7 +1084,7 @@ static void add_trigger_function(enum triggerop oper, enum triggerfunc func, * simple pin change and state triggers. Only two transitions (rise/fall) can be * set at any time, but a full mask and value can be set (0/1). */ -static int build_basic_trigger(struct triggerlut *lut, struct dev_context *devc) +SR_PRIV int sigma_build_basic_trigger(struct triggerlut *lut, struct dev_context *devc) { int i,j; uint16_t masks[2] = { 0, 0 }; @@ -1406,146 +1129,3 @@ static int build_basic_trigger(struct triggerlut *lut, struct dev_context *devc) return SR_OK; } - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - struct clockselect_50 clockselect; - int frac, triggerpin, ret; - uint8_t triggerselect = 0; - struct triggerinout triggerinout_conf; - struct triggerlut lut; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - - if (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 = set_samplerate(sdi, SR_KHZ(200))) != SR_OK) - return ret; - } - - /* Enter trigger programming mode. */ - sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20, devc); - - /* 100 and 200 MHz mode. */ - if (devc->cur_samplerate >= SR_MHZ(100)) { - sigma_set_register(WRITE_TRIGGER_SELECT1, 0x81, devc); - - /* Find which pin to trigger on from mask. */ - for (triggerpin = 0; triggerpin < 8; ++triggerpin) - if ((devc->trigger.risingmask | devc->trigger.fallingmask) & - (1 << triggerpin)) - break; - - /* Set trigger pin and light LED on trigger. */ - triggerselect = (1 << LEDSEL1) | (triggerpin & 0x7); - - /* Default rising edge. */ - if (devc->trigger.fallingmask) - triggerselect |= 1 << 3; - - /* All other modes. */ - } else if (devc->cur_samplerate <= SR_MHZ(50)) { - build_basic_trigger(&lut, devc); - - sigma_write_trigger_lut(&lut, devc); - - triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0); - } - - /* Setup trigger in and out pins to default values. */ - memset(&triggerinout_conf, 0, sizeof(struct triggerinout)); - 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_SELECT1, triggerselect, devc); - - /* Set clock select register. */ - if (devc->cur_samplerate == SR_MHZ(200)) - /* Enable 4 channels. */ - sigma_set_register(WRITE_CLOCK_SELECT, 0xf0, devc); - else if (devc->cur_samplerate == SR_MHZ(100)) - /* Enable 8 channels. */ - sigma_set_register(WRITE_CLOCK_SELECT, 0x00, devc); - else { - /* - * 50 MHz mode (or fraction thereof). Any fraction down to - * 50 MHz / 256 can be used, but is not supported by sigrok API. - */ - frac = SR_MHZ(50) / devc->cur_samplerate - 1; - - clockselect.async = 0; - clockselect.fraction = frac; - clockselect.disabled_channels = 0; - - sigma_write_register(WRITE_CLOCK_SELECT, - (uint8_t *) &clockselect, - sizeof(clockselect), devc); - } - - /* Setup maximum post trigger time. */ - sigma_set_register(WRITE_POST_TRIGGER, - (devc->capture_ratio * 255) / 100, devc); - - /* Start acqusition. */ - gettimeofday(&devc->start_tv, 0); - sigma_set_register(WRITE_MODE, 0x0d, devc); - - devc->cb_data = cb_data; - - /* Send header packet to the session bus. */ - std_session_send_df_header(sdi, LOG_PREFIX); - - /* Add capture source. */ - sr_session_source_add(sdi->session, -1, 0, 10, receive_data, (void *)sdi); - - devc->state.state = SIGMA_CAPTURE; - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - - (void)cb_data; - - devc = sdi->priv; - devc->state.state = SIGMA_IDLE; - - sr_session_source_remove(sdi->session, -1); - - return SR_OK; -} - -SR_PRIV struct sr_dev_driver asix_sigma_driver_info = { - .name = "asix-sigma", - .longname = "ASIX SIGMA/SIGMA2", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = dev_clear, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .context = NULL, -}; diff --git a/src/hardware/asix-sigma/asix-sigma.h b/src/hardware/asix-sigma/protocol.h similarity index 79% rename from src/hardware/asix-sigma/asix-sigma.h rename to src/hardware/asix-sigma/protocol.h index 44935743..d654e609 100644 --- a/src/hardware/asix-sigma/asix-sigma.h +++ b/src/hardware/asix-sigma/protocol.h @@ -1,7 +1,7 @@ /* * This file is part of the libsigrok project. * - * Copyright (C) 2010 Håvard Espeland , + * Copyright (C) 2010-2012 Håvard Espeland , * Copyright (C) 2010 Martin Stensgård * Copyright (C) 2010 Carl Henrik Lunde * @@ -19,11 +19,24 @@ * along with this program. If not, see . */ -#ifndef LIBSIGROK_HARDWARE_ASIX_SIGMA_ASIX_SIGMA_H -#define LIBSIGROK_HARDWARE_ASIX_SIGMA_ASIX_SIGMA_H +#ifndef LIBSIGROK_HARDWARE_ASIX_SIGMA_PROTOCOL_H +#define LIBSIGROK_HARDWARE_ASIX_SIGMA_PROTOCOL_H + +#include +#include +#include +#include +#include +#include "libsigrok-internal.h" #define LOG_PREFIX "asix-sigma" +#define USB_VENDOR 0xa600 +#define USB_PRODUCT 0xa000 +#define USB_DESCRIPTION "ASIX SIGMA" +#define USB_VENDOR_NAME "ASIX" +#define USB_MODEL_NAME "SIGMA" + enum sigma_write_register { WRITE_CLOCK_SELECT = 0, WRITE_TRIGGER_SELECT0 = 1, @@ -208,4 +221,17 @@ struct dev_context { void *cb_data; }; +extern SR_PRIV const uint64_t samplerates[]; +extern SR_PRIV const int SAMPLERATES_COUNT; + +SR_PRIV int sigma_write_register(uint8_t reg, uint8_t *data, size_t len, + struct dev_context *devc); +SR_PRIV int sigma_set_register(uint8_t reg, uint8_t value, struct dev_context *devc); +SR_PRIV int sigma_write_trigger_lut(struct triggerlut *lut, struct dev_context *devc); +SR_PRIV void sigma_clear_helper(void *priv); +SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate); +SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi); +SR_PRIV int sigma_receive_data(int fd, int revents, void *cb_data); +SR_PRIV int sigma_build_basic_trigger(struct triggerlut *lut, struct dev_context *devc); + #endif