X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=hardware%2Ffx2lafw%2Ffx2lafw.c;h=ffc89c4eb110da51bb3b35ee29b51f9841f0f2ac;hb=24125e05202626c9fea3f056ecc5d008f544970b;hp=68877f1fd2a96a32725cd553b312812ba6fccb27;hpb=0ca21631dda3d948f8a67de5d48a2198b1efa425;p=libsigrok.git diff --git a/hardware/fx2lafw/fx2lafw.c b/hardware/fx2lafw/fx2lafw.c index 68877f1f..ffc89c4e 100644 --- a/hardware/fx2lafw/fx2lafw.c +++ b/hardware/fx2lafw/fx2lafw.c @@ -35,6 +35,11 @@ static const struct fx2lafw_profile supported_fx2[] = { { 0x08a9, 0x0014, "CWAV", "USBee AX", NULL, FIRMWARE_DIR "/fx2lafw-cwav-usbeeax.fw", 8 }, + /* CWAV USBee SX + */ + { 0x08a9, 0x0009, "CWAV", "USBee SX", NULL, + FIRMWARE_DIR "/fx2lafw-cwav-usbeesx.fw", 8 }, + /* Saleae Logic * EE Electronics ESLA100 * Robomotic MiniLogic @@ -155,7 +160,7 @@ static int fx2lafw_open_dev(int dev_index) struct libusb_device_descriptor des; struct sr_dev_inst *sdi; struct context *ctx; - int err, skip, i; + int ret, skip, i; if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) return SR_ERR; @@ -168,8 +173,8 @@ static int fx2lafw_open_dev(int dev_index) skip = 0; libusb_get_device_list(usb_context, &devlist); for (i = 0; devlist[i]; i++) { - if ((err = libusb_get_device_descriptor(devlist[i], &des))) { - sr_err("fx2lafw: failed to get device descriptor: %d", err); + if ((ret = libusb_get_device_descriptor(devlist[i], &des))) { + sr_err("fx2lafw: failed to get device descriptor: %d", ret); continue; } @@ -194,7 +199,7 @@ static int fx2lafw_open_dev(int dev_index) continue; } - if (!(err = libusb_open(devlist[i], &ctx->usb->devhdl))) { + if (!(ret = libusb_open(devlist[i], &ctx->usb->devhdl))) { if (ctx->usb->address == 0xff) /* * first time we touch this device after firmware upload, @@ -207,7 +212,7 @@ static int fx2lafw_open_dev(int dev_index) sdi->index, ctx->usb->bus, ctx->usb->address, USB_INTERFACE); } else { - sr_err("fx2lafw: failed to open device: %d", err); + sr_err("fx2lafw: failed to open device: %d", ret); } /* if we made it here, we handled the device one way or another */ @@ -238,6 +243,50 @@ static void close_dev(struct sr_dev_inst *sdi) sdi->status = SR_ST_INACTIVE; } +static int configure_probes(struct context *ctx, GSList *probes) +{ + struct sr_probe *probe; + GSList *l; + int probe_bit, stage, i; + char *tc; + + for (i = 0; i < NUM_TRIGGER_STAGES; i++) { + ctx->trigger_mask[i] = 0; + ctx->trigger_value[i] = 0; + } + + stage = -1; + for (l = probes; l; l = l->next) { + probe = (struct sr_probe *)l->data; + if (probe->enabled == FALSE) + continue; + probe_bit = 1 << (probe->index - 1); + if (!(probe->trigger)) + continue; + + stage = 0; + for (tc = probe->trigger; *tc; tc++) { + ctx->trigger_mask[stage] |= probe_bit; + if (*tc == '1') + ctx->trigger_value[stage] |= probe_bit; + stage++; + if (stage > NUM_TRIGGER_STAGES) + return SR_ERR; + } + } + + if (stage == -1) + /* + * We didn't configure any triggers, make sure acquisition + * doesn't wait for any. + */ + ctx->trigger_stage = TRIGGER_FIRED; + else + ctx->trigger_stage = 0; + + return SR_OK; +} + static struct context *fx2lafw_device_new(void) { struct context *ctx; @@ -247,6 +296,8 @@ static struct context *fx2lafw_device_new(void) return NULL; } + ctx->trigger_stage = TRIGGER_FIRED; + return ctx; } @@ -261,7 +312,7 @@ static int hw_init(const char *deviceinfo) const struct fx2lafw_profile *fx2lafw_prof; struct context *ctx; libusb_device **devlist; - int err; + int ret; int devcnt = 0; int i, j; @@ -277,9 +328,9 @@ static int hw_init(const char *deviceinfo) libusb_get_device_list(usb_context, &devlist); for (i = 0; devlist[i]; i++) { - if ((err = libusb_get_device_descriptor( + if ((ret = libusb_get_device_descriptor( devlist[i], &des)) != 0) { - sr_warn("failed to get device descriptor: %d", err); + sr_warn("failed to get device descriptor: %d", ret); continue; } @@ -337,7 +388,7 @@ static int hw_dev_open(int dev_index) GTimeVal cur_time; struct sr_dev_inst *sdi; struct context *ctx; - int timediff, err; + int timediff, ret; if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) return SR_ERR; @@ -347,14 +398,14 @@ static int hw_dev_open(int dev_index) * if the firmware was recently uploaded, wait up to MAX_RENUM_DELAY ms * for the FX2 to renumerate */ - err = 0; + ret = 0; if (GTV_TO_MSEC(ctx->fw_updated) > 0) { sr_info("fx2lafw: waiting for device to reset"); /* takes at least 300ms for the FX2 to be gone from the USB bus */ g_usleep(300 * 1000); timediff = 0; while (timediff < MAX_RENUM_DELAY) { - if ((err = fx2lafw_open_dev(dev_index)) == SR_OK) + if ((ret = fx2lafw_open_dev(dev_index)) == SR_OK) break; g_usleep(100 * 1000); g_get_current_time(&cur_time); @@ -362,18 +413,18 @@ static int hw_dev_open(int dev_index) } sr_info("fx2lafw: device came back after %d ms", timediff); } else { - err = fx2lafw_open_dev(dev_index); + ret = fx2lafw_open_dev(dev_index); } - if (err != SR_OK) { + if (ret != SR_OK) { sr_err("fx2lafw: unable to open device"); return SR_ERR; } ctx = sdi->priv; - err = libusb_claim_interface(ctx->usb->devhdl, USB_INTERFACE); - if (err != 0) { - sr_err("fx2lafw: Unable to claim interface: %d", err); + ret = libusb_claim_interface(ctx->usb->devhdl, USB_INTERFACE); + if (ret != 0) { + sr_err("fx2lafw: Unable to claim interface: %d", ret); return SR_ERR; } @@ -495,7 +546,7 @@ static int hw_dev_config_set(int dev_index, int hwcap, void *value) ctx->cur_samplerate = *(uint64_t *)value; ret = SR_OK; } else if (hwcap == SR_HWCAP_PROBECONFIG) { - ret = SR_OK; + ret = configure_probes(ctx, (GSList *) value); } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) { ctx->limit_samples = *(uint64_t *)value; ret = SR_OK; @@ -540,7 +591,7 @@ static void receive_transfer(struct libusb_transfer *transfer) struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; struct context *ctx = transfer->user_data; - int cur_buflen; + int cur_buflen, trigger_offset, i; unsigned char *cur_buf, *new_buf; /* @@ -559,7 +610,6 @@ static void receive_transfer(struct libusb_transfer *transfer) /* Save incoming transfer before reusing the transfer struct. */ cur_buf = transfer->buffer; cur_buflen = transfer->actual_length; - ctx = transfer->user_data; /* Fire off a new request. */ if (!(new_buf = g_try_malloc(4096))) { @@ -589,19 +639,81 @@ static void receive_transfer(struct libusb_transfer *transfer) empty_transfer_count = 0; } - /* Send the incoming transfer to the session bus. */ - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.length = cur_buflen; - logic.unitsize = 1; - logic.data = cur_buf; - sr_session_send(ctx->session_dev_id, &packet); - g_free(cur_buf); + trigger_offset = 0; + if (ctx->trigger_stage >= 0) { + for (i = 0; i < cur_buflen; i++) { + + if ((cur_buf[i] & ctx->trigger_mask[ctx->trigger_stage]) == ctx->trigger_value[ctx->trigger_stage]) { + /* Match on this trigger stage. */ + ctx->trigger_buffer[ctx->trigger_stage] = cur_buf[i]; + ctx->trigger_stage++; + + if (ctx->trigger_stage == NUM_TRIGGER_STAGES || ctx->trigger_mask[ctx->trigger_stage] == 0) { + /* Match on all trigger stages, we're done. */ + trigger_offset = i + 1; + + /* + * TODO: Send pre-trigger buffer to session bus. + * Tell the frontend we hit the trigger here. + */ + packet.type = SR_DF_TRIGGER; + packet.payload = NULL; + sr_session_send(ctx->session_dev_id, &packet); + + /* + * Send the samples that triggered it, since we're + * skipping past them. + */ + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.length = ctx->trigger_stage; + logic.unitsize = 1; + logic.data = ctx->trigger_buffer; + sr_session_send(ctx->session_dev_id, &packet); + + ctx->trigger_stage = TRIGGER_FIRED; + break; + } + return; + } - ctx->num_samples += cur_buflen; - if (ctx->limit_samples && - (unsigned int) ctx->num_samples > ctx->limit_samples) { - abort_acquisition(ctx); + /* + * We had a match before, but not in the next sample. However, we may + * have a match on this stage in the next bit -- trigger on 0001 will + * fail on seeing 00001, so we need to go back to stage 0 -- but at + * the next sample from the one that matched originally, which the + * counter increment at the end of the loop takes care of. + */ + if (ctx->trigger_stage > 0) { + i -= ctx->trigger_stage; + if (i < -1) + i = -1; /* Oops, went back past this buffer. */ + /* Reset trigger stage. */ + ctx->trigger_stage = 0; + } + } + } + + if (ctx->trigger_stage == TRIGGER_FIRED) { + /* Send the incoming transfer to the session bus. */ + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.length = cur_buflen - trigger_offset; + logic.unitsize = 1; + logic.data = cur_buf + trigger_offset; + sr_session_send(ctx->session_dev_id, &packet); + g_free(cur_buf); + + ctx->num_samples += cur_buflen; + if (ctx->limit_samples && + (unsigned int)ctx->num_samples > ctx->limit_samples) { + abort_acquisition(ctx); + } + } else { + /* + * TODO: Buffer pre-trigger data in capture + * ratio-sized buffer. + */ } } @@ -613,7 +725,7 @@ static int hw_dev_acquisition_start(int dev_index, void *cb_data) struct context *ctx; struct libusb_transfer *transfer; const struct libusb_pollfd **lupfd; - int err, size, i; + int ret, size, i; unsigned char *buf; if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) @@ -668,9 +780,9 @@ static int hw_dev_acquisition_start(int dev_index, void *cb_data) g_free(header); g_free(packet); - if ((err = command_start_acquisition (ctx->usb->devhdl, + if ((ret = command_start_acquisition (ctx->usb->devhdl, ctx->cur_samplerate)) != SR_OK) { - return err; + return ret; } return SR_OK; @@ -694,7 +806,7 @@ static int hw_dev_acquisition_stop(int dev_index, void *cb_data) SR_PRIV struct sr_dev_driver fx2lafw_driver_info = { .name = "fx2lafw", - .longname = "fx2lafw", + .longname = "fx2lafw (generic driver for FX2 based LAs)", .api_version = 1, .init = hw_init, .cleanup = hw_cleanup,