X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fasix-sigma%2Fprotocol.c;h=25bfc2bf86aadfe8b3e6846612362bbaf1a3dfda;hb=e686119cc287164b0043c44857ab4cf2faedde53;hp=5fa7b2d015a1080d442e8b12ec162131e9f00eff;hpb=bee2b0168c087676c1b365861d8c2d4714afa9b9;p=libsigrok.git diff --git a/src/hardware/asix-sigma/protocol.c b/src/hardware/asix-sigma/protocol.c index 5fa7b2d0..25bfc2bf 100644 --- a/src/hardware/asix-sigma/protocol.c +++ b/src/hardware/asix-sigma/protocol.c @@ -26,12 +26,6 @@ #include #include "protocol.h" -#define USB_VENDOR 0xa600 -#define USB_PRODUCT 0xa000 -#define USB_DESCRIPTION "ASIX SIGMA" -#define USB_VENDOR_NAME "ASIX" -#define USB_MODEL_NAME "SIGMA" - /* * The ASIX Sigma supports arbitrary integer frequency divider in * the 50MHz mode. The divider is in range 1...256 , allowing for @@ -51,7 +45,7 @@ SR_PRIV const uint64_t samplerates[] = { SR_MHZ(200), /* Special FW needed */ }; -SR_PRIV const int SAMPLERATES_COUNT = ARRAY_SIZE(samplerates); +SR_PRIV const size_t samplerates_count = ARRAY_SIZE(samplerates); static const char sigma_firmware_files[][24] = { /* 50 MHz, supports 8 bit fractions */ @@ -105,9 +99,9 @@ SR_PRIV int sigma_write_register(uint8_t reg, uint8_t *data, size_t len, uint8_t buf[80]; int idx = 0; - if ((len + 2) > sizeof(buf)) { + if ((2 * len + 2) > sizeof(buf)) { sr_err("Attempted to write %zu bytes, but buffer is too small.", - len + 2); + len); return SR_ERR_BUG; } @@ -388,12 +382,13 @@ static int sigma_fw_2_bitbang(struct sr_context *ctx, const char *name, int bit, v; int ret = SR_OK; + /* Retrieve the on-disk firmware file content. */ firmware = sr_resource_load(ctx, SR_RESOURCE_FIRMWARE, name, &file_size, 256 * 1024); if (!firmware) return SR_ERR; - /* Weird magic transformation below, I have no idea what it does. */ + /* Unscramble the file content (XOR with "random" sequence). */ imm = 0x3f6df2ab; for (i = 0; i < file_size; i++) { imm = (imm + 0xa853753) % 177 + (imm * 0x8034052); @@ -401,13 +396,20 @@ static int sigma_fw_2_bitbang(struct sr_context *ctx, const char *name, } /* - * Now that the firmware is "transformed", we will transcribe the - * firmware blob into a sequence of toggles of the Dx wires. This - * sequence will be fed directly into the Sigma, which must be in - * the FPGA bitbang programming mode. + * Generate a sequence of bitbang samples. With two samples per + * FPGA configuration bit, providing the level for the DIN signal + * as well as two edges for CCLK. See Xilinx UG332 for details + * ("slave serial" mode). + * + * Note that CCLK is inverted in hardware. That's why the + * respective bit is first set and then cleared in the bitbang + * sample sets. So that the DIN level will be stable when the + * data gets sampled at the rising CCLK edge, and the signals' + * setup time constraint will be met. + * + * The caller will put the FPGA into download mode, will send + * the bitbang samples, and release the allocated memory. */ - - /* Each bit of firmware is transcribed as two toggles of Dx wires. */ bb_size = file_size * 8 * 2; bb_stream = (uint8_t *)g_try_malloc(bb_size); if (!bb_stream) { @@ -415,7 +417,6 @@ static int sigma_fw_2_bitbang(struct sr_context *ctx, const char *name, ret = SR_ERR_MALLOC; goto exit; } - bbs = bb_stream; for (i = 0; i < file_size; i++) { for (bit = 7; bit >= 0; bit--) { @@ -512,24 +513,54 @@ static int upload_firmware(struct sr_context *ctx, return SR_OK; } +/* + * Sigma doesn't support limiting the number of samples, so we have to + * translate the number and the samplerate to an elapsed time. + * + * In addition we need to ensure that the last data cluster has passed + * the hardware pipeline, and became available to the PC side. With RLE + * compression up to 327ms could pass before another cluster accumulates + * at 200kHz samplerate when input pins don't change. + */ +SR_PRIV uint64_t sigma_limit_samples_to_msec(const struct dev_context *devc, + uint64_t limit_samples) +{ + uint64_t limit_msec; + uint64_t worst_cluster_time_ms; + + limit_msec = limit_samples * 1000 / devc->cur_samplerate; + worst_cluster_time_ms = 65536 * 1000 / devc->cur_samplerate; + /* + * One cluster time is not enough to flush pipeline when sampling + * grounded pins with 1 sample limit at 200kHz. Hence the 2* fix. + */ + return limit_msec + 2 * worst_cluster_time_ms; +} + SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) { struct dev_context *devc; struct drv_context *drvc; - unsigned int i; + size_t i; int ret; devc = sdi->priv; drvc = sdi->driver->context; ret = SR_OK; - for (i = 0; i < ARRAY_SIZE(samplerates); i++) { + /* Reject rates that are not in the list of supported rates. */ + for (i = 0; i < samplerates_count; i++) { if (samplerates[i] == samplerate) break; } - if (samplerates[i] == 0) + if (i >= samplerates_count || samplerates[i] == 0) return SR_ERR_SAMPLERATE; + /* + * Depending on the samplerates of 200/100/50- MHz, specific + * firmware is required and higher rates might limit the set + * of available channels. + */ if (samplerate <= SR_MHZ(50)) { ret = upload_firmware(drvc->sr_ctx, 0, devc); devc->num_channels = 16; @@ -541,6 +572,11 @@ SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi, uint64_t sampler devc->num_channels = 4; } + /* + * Derive the sample period from the sample rate as well as the + * number of samples that the device will communicate within + * an "event" (memory organization internal to the device). + */ if (ret == SR_OK) { devc->cur_samplerate = samplerate; devc->period_ps = 1000000000000ULL / samplerate; @@ -548,6 +584,18 @@ SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi, uint64_t sampler devc->state.state = SIGMA_IDLE; } + /* + * Support for "limit_samples" is implemented by stopping + * acquisition after a corresponding period of time. + * Re-calculate that period of time, in case the limit is + * set first and the samplerate gets (re-)configured later. + */ + if (ret == SR_OK && devc->limit_samples) { + uint64_t msecs; + msecs = sigma_limit_samples_to_msec(devc, devc->limit_samples); + devc->limit_msec = msecs; + } + return ret; } @@ -693,7 +741,7 @@ static void sigma_decode_dram_cluster(struct sigma_dram_cluster *dram_cluster, ts = sigma_dram_cluster_ts(dram_cluster); tsdiff = ts - ss->lastts; - ss->lastts = ts; + ss->lastts = ts + EVENTS_PER_CLUSTER; packet.type = SR_DF_LOGIC; packet.payload = &logic; @@ -711,7 +759,7 @@ static void sigma_decode_dram_cluster(struct sigma_dram_cluster *dram_cluster, * sample in the cluster happens at the time of the timestamp * and the remaining samples happen at timestamp +1...+6 . */ - for (ts = 0; ts < tsdiff - (EVENTS_PER_CLUSTER - 1); ts++) { + for (ts = 0; ts < tsdiff; ts++) { i = ts % 1024; samples[2 * i + 0] = ss->lastsample & 0xff; samples[2 * i + 1] = ss->lastsample >> 8; @@ -721,7 +769,7 @@ static void sigma_decode_dram_cluster(struct sigma_dram_cluster *dram_cluster, * end of submitting the padding samples, submit * the packet to Sigrok. */ - if ((i == 1023) || (ts == (tsdiff - EVENTS_PER_CLUSTER))) { + if ((i == 1023) || (ts == tsdiff - 1)) { logic.length = (i + 1) * logic.unitsize; sr_session_send(sdi, &packet); }