SR_CONF_LIMIT_SAMPLES,
};
-/* Initialize the logic analyzer mode. */
-static uint8_t logic_mode_start[] = {
- 0x00, 0x40, 0x0f, 0x25, 0x35, 0x40,
- 0x2a, 0x3a, 0x40, 0x03, 0x20, 0x38,
-};
-
static const char *sigma_firmware_files[] = {
/* 50 MHz, supports 8 bit fractions */
FIRMWARE_DIR "/asix-sigma-50.fw",
return SR_OK;
}
-/*
- * Read the firmware from a file and transform it into a series of bitbang
- * pulses used to program the FPGA. Note that the *bb_cmd must be free()'d
- * by the caller of this function.
- */
-static int sigma_fw_2_bitbang(const char *filename,
- uint8_t **bb_cmd, gsize *bb_cmd_size)
-{
- GMappedFile *file;
- GError *error;
- gsize i, file_size, bb_size;
- gchar *firmware;
- uint8_t *bb_stream, *bbs;
- uint32_t imm;
- int bit, v;
- int ret = SR_OK;
-
- /*
- * Map the file and make the mapped buffer writable.
- * NOTE: Using writable=TRUE does _NOT_ mean that file that is mapped
- * will be modified. It will not be modified until someone uses
- * g_file_set_contents() on it.
- */
- error = NULL;
- file = g_mapped_file_new(filename, TRUE, &error);
- g_assert_no_error(error);
-
- file_size = g_mapped_file_get_length(file);
- firmware = g_mapped_file_get_contents(file);
- g_assert(firmware);
-
- /* Weird magic transformation below, I have no idea what it does. */
- imm = 0x3f6df2ab;
- for (i = 0; i < file_size; i++) {
- imm = (imm + 0xa853753) % 177 + (imm * 0x8034052);
- firmware[i] ^= imm & 0xff;
- }
-
- /*
- * 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.
- */
-
- /* 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) {
- sr_err("%s: Failed to allocate bitbang stream", __func__);
- ret = SR_ERR_MALLOC;
- goto exit;
- }
-
- bbs = bb_stream;
- for (i = 0; i < file_size; i++) {
- for (bit = 7; bit >= 0; bit--) {
- v = (firmware[i] & (1 << bit)) ? 0x40 : 0x00;
- *bbs++ = v | 0x01;
- *bbs++ = v;
- }
- }
-
- /* The transformation completed successfully, return the result. */
- *bb_cmd = bb_stream;
- *bb_cmd_size = bb_size;
-
-exit:
- g_mapped_file_unref(file);
- return ret;
-}
-
static void clear_helper(void *priv)
{
struct dev_context *devc;
return SR_ERR_TIMEOUT;
}
+/*
+ * Configure the FPGA for logic-analyzer mode.
+ */
+static int sigma_fpga_init_la(struct dev_context *devc)
+{
+ /* Initialize the logic analyzer mode. */
+ uint8_t logic_mode_start[] = {
+ REG_ADDR_LOW | (READ_ID & 0xf),
+ REG_ADDR_HIGH | (READ_ID >> 8),
+ REG_READ_ADDR, /* Read ID register. */
+
+ REG_ADDR_LOW | (WRITE_TEST & 0xf),
+ REG_DATA_LOW | 0x5,
+ REG_DATA_HIGH_WRITE | 0x5,
+ REG_READ_ADDR, /* Read scratch register. */
+
+ REG_DATA_LOW | 0xa,
+ REG_DATA_HIGH_WRITE | 0xa,
+ REG_READ_ADDR, /* Read scratch register. */
+
+ REG_ADDR_LOW | (WRITE_MODE & 0xf),
+ REG_DATA_LOW | 0x0,
+ REG_DATA_HIGH_WRITE | 0x8,
+ };
+
+ uint8_t result[3];
+ int ret;
+
+ /* Initialize the logic analyzer mode. */
+ sigma_write(logic_mode_start, sizeof(logic_mode_start), devc);
+
+ /* Expect a 3 byte reply since we issued three READ requests. */
+ ret = sigma_read(result, 3, devc);
+ if (ret != 3)
+ goto err;
+
+ if (result[0] != 0xa6 || result[1] != 0x55 || result[2] != 0xaa)
+ goto err;
+
+ return SR_OK;
+err:
+ sr_err("Configuration failed. Invalid reply received.");
+ return SR_ERR;
+}
+
+/*
+ * Read the firmware from a file and transform it into a series of bitbang
+ * pulses used to program the FPGA. Note that the *bb_cmd must be free()'d
+ * by the caller of this function.
+ */
+static int sigma_fw_2_bitbang(const char *filename,
+ uint8_t **bb_cmd, gsize *bb_cmd_size)
+{
+ GMappedFile *file;
+ GError *error;
+ gsize i, file_size, bb_size;
+ gchar *firmware;
+ uint8_t *bb_stream, *bbs;
+ uint32_t imm;
+ int bit, v;
+ int ret = SR_OK;
+
+ /*
+ * Map the file and make the mapped buffer writable.
+ * NOTE: Using writable=TRUE does _NOT_ mean that file that is mapped
+ * will be modified. It will not be modified until someone uses
+ * g_file_set_contents() on it.
+ */
+ error = NULL;
+ file = g_mapped_file_new(filename, TRUE, &error);
+ g_assert_no_error(error);
+
+ file_size = g_mapped_file_get_length(file);
+ firmware = g_mapped_file_get_contents(file);
+ g_assert(firmware);
+
+ /* Weird magic transformation below, I have no idea what it does. */
+ imm = 0x3f6df2ab;
+ for (i = 0; i < file_size; i++) {
+ imm = (imm + 0xa853753) % 177 + (imm * 0x8034052);
+ firmware[i] ^= imm & 0xff;
+ }
+
+ /*
+ * 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.
+ */
+
+ /* 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) {
+ sr_err("%s: Failed to allocate bitbang stream", __func__);
+ ret = SR_ERR_MALLOC;
+ goto exit;
+ }
+
+ bbs = bb_stream;
+ for (i = 0; i < file_size; i++) {
+ for (bit = 7; bit >= 0; bit--) {
+ v = (firmware[i] & (1 << bit)) ? 0x40 : 0x00;
+ *bbs++ = v | 0x01;
+ *bbs++ = v;
+ }
+ }
+
+ /* The transformation completed successfully, return the result. */
+ *bb_cmd = bb_stream;
+ *bb_cmd_size = bb_size;
+
+exit:
+ g_mapped_file_unref(file);
+ return ret;
+}
+
static int upload_firmware(int firmware_idx, struct dev_context *devc)
{
int ret;
unsigned char *buf;
unsigned char pins;
size_t buf_size;
- unsigned char result[32];
const char *firmware = sigma_firmware_files[firmware_idx];
struct ftdi_context *ftdic = &devc->ftdic;
ftdi_usb_purge_buffers(ftdic);
/* Discard garbage. */
- while (1 == sigma_read(&pins, 1, devc))
+ while (sigma_read(&pins, 1, devc) == 1)
;
- /* Initialize the logic analyzer mode. */
- sigma_write(logic_mode_start, sizeof(logic_mode_start), devc);
-
- /* Expect a 3 byte reply. */
- ret = sigma_read(result, 3, devc);
- if (ret != 3 ||
- result[0] != 0xa6 || result[1] != 0x55 || result[2] != 0xaa) {
- sr_err("Configuration failed. Invalid reply received.");
- return SR_ERR;
- }
+ /* Initialize the FPGA for logic-analyzer mode. */
+ ret = sigma_fpga_init_la(devc);
+ if (ret != SR_OK)
+ return ret;
devc->cur_firmware = firmware_idx;
return SR_OK;
}
-static void download_capture(struct sr_dev_inst *sdi)
+static int download_capture(struct sr_dev_inst *sdi)
{
- struct dev_context *devc;
+ struct dev_context *devc = sdi->priv;
const int chunks_per_read = 32;
- unsigned char buf[chunks_per_read * CHUNK_SIZE];
- int bufsz, i, numchunks, newchunks;
+ struct sigma_dram_line *dram_line;
+ unsigned char *buf;
+ int bufsz;
+ uint32_t stoppos, triggerpos;
+ struct sr_datafeed_packet packet;
+ uint8_t modestatus;
+
+ uint32_t i;
+ uint32_t dl_lines_total, dl_lines_curr, dl_lines_done;
+ uint32_t dl_trailing_events;
+ uint32_t trg_line = ~0;
+
+ dram_line = g_try_malloc0(chunks_per_read * sizeof(*dram_line));
+ if (!dram_line)
+ return FALSE;
+
+ buf = (unsigned char *)dram_line;
sr_info("Downloading sample data.");
- devc = sdi->priv;
- devc->state.chunks_downloaded = 0;
- numchunks = (devc->state.stoppos + 511) / 512;
- newchunks = MIN(chunks_per_read, numchunks - devc->state.chunks_downloaded);
-
- bufsz = sigma_read_dram(devc->state.chunks_downloaded, newchunks, buf, devc);
- /* TODO: Check bufsz. For now, just avoid compiler warnings. */
- (void)bufsz;
-
- /* Find first ts. */
- if (devc->state.chunks_downloaded == 0) {
- devc->state.lastts = RL16(buf) - 1;
- devc->state.lastsample = 0;
- }
+ /* Stop acquisition. */
+ sigma_set_register(WRITE_MODE, 0x11, devc);
+
+ /* Set SDRAM Read Enable. */
+ sigma_set_register(WRITE_MODE, 0x02, devc);
+
+ /* Get the current position. */
+ sigma_read_pos(&stoppos, &triggerpos, devc);
+
+ /* Check if trigger has fired. */
+ modestatus = sigma_get_register(READ_MODE, devc);
+ if (modestatus & 0x20)
+ trg_line = triggerpos >> 9;
+
+ /*
+ * Determine how many 1024b "DRAM lines" do we need to read from the
+ * Sigma so we have a complete set of samples. Note that the last
+ * line can be only partial, containing less than 64 clusters.
+ */
+ dl_lines_total = (stoppos >> 9) + 1;
+ dl_trailing_events = stoppos & 0x1ff;
+
+ dl_lines_done = 0;
+
+ while (dl_lines_total > dl_lines_done) {
+ /* We can download only up-to 32 DRAM lines in one go! */
+ dl_lines_curr = MIN(chunks_per_read, dl_lines_total);
- /* Decode chunks and send them to sigrok. */
- for (i = 0; i < newchunks; ++i) {
- int limit_chunk = 0;
+ bufsz = sigma_read_dram(dl_lines_done, dl_lines_curr, buf, devc);
+ /* TODO: Check bufsz. For now, just avoid compiler warnings. */
+ (void)bufsz;
- /* The last chunk may potentially be only in part. */
- if (devc->state.chunks_downloaded == numchunks - 1) {
- /* Find the last valid timestamp */
- limit_chunk = devc->state.stoppos % 512 + devc->state.lastts;
+ /* This is the first DRAM line, so find the initial timestamp. */
+ if (dl_lines_done == 0) {
+ devc->state.lastts = RL16(buf) - 1;
+ devc->state.lastsample = 0;
}
- if (devc->state.chunks_downloaded + i == devc->state.triggerchunk)
- decode_chunk_ts(buf + (i * CHUNK_SIZE),
- &devc->state.lastts,
- &devc->state.lastsample,
- devc->state.triggerpos & 0x1ff,
- limit_chunk, sdi);
- else
+ for (i = 0; i < dl_lines_curr; i++) {
+ uint32_t dl_limit = 0;
+ int trigger_line = -1;
+ /* The last "DRAM line" can be only partially full. */
+ if (dl_lines_done + i == dl_lines_total - 1)
+ dl_limit = dl_trailing_events;
+
+ /* Test if the trigger happened on this line. */
+ if (dl_lines_done + i == trg_line)
+ trigger_line = trg_line;
+
decode_chunk_ts(buf + (i * CHUNK_SIZE),
&devc->state.lastts,
&devc->state.lastsample,
- -1, limit_chunk, sdi);
+ trigger_line, dl_limit, sdi);
+ }
- ++devc->state.chunks_downloaded;
+ dl_lines_done += dl_lines_curr;
}
+ /* All done. */
+ packet.type = SR_DF_END;
+ sr_session_send(sdi, &packet);
+
+ dev_acquisition_stop(sdi, sdi);
+
+ g_free(dram_line);
+
+ return TRUE;
+}
+
+/*
+ * Handle the Sigma when in CAPTURE mode. This function checks:
+ * - Sampling time ended
+ * - DRAM capacity overflow
+ * This function triggers download of the samples from Sigma
+ * in case either of the above conditions is true.
+ */
+static int sigma_capture_mode(struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc = sdi->priv;
+
+ uint64_t running_msec;
+ struct timeval tv;
+
+ uint32_t stoppos, triggerpos;
+
+ /* Check if the selected sampling duration passed. */
+ gettimeofday(&tv, 0);
+ running_msec = (tv.tv_sec - devc->start_tv.tv_sec) * 1000 +
+ (tv.tv_usec - devc->start_tv.tv_usec) / 1000;
+ if (running_msec >= devc->limit_msec)
+ return download_capture(sdi);
+
+ /* Get the position in DRAM to which the FPGA is writing now. */
+ sigma_read_pos(&stoppos, &triggerpos, devc);
+ /* Test if DRAM is full and if so, download the data. */
+ if ((stoppos >> 9) == 32767)
+ return download_capture(sdi);
+
+ return TRUE;
}
static int receive_data(int fd, int revents, void *cb_data)
{
struct sr_dev_inst *sdi;
struct dev_context *devc;
- struct sr_datafeed_packet packet;
- uint64_t running_msec;
- struct timeval tv;
- int numchunks;
- uint8_t modestatus;
(void)fd;
(void)revents;
sdi = cb_data;
devc = sdi->priv;
- /* Get the current position. */
- sigma_read_pos(&devc->state.stoppos, &devc->state.triggerpos, devc);
-
if (devc->state.state == SIGMA_IDLE)
return TRUE;
- if (devc->state.state == SIGMA_CAPTURE) {
- numchunks = (devc->state.stoppos + 511) / 512;
-
- /* Check if the timer has expired, or memory is full. */
- gettimeofday(&tv, 0);
- running_msec = (tv.tv_sec - devc->start_tv.tv_sec) * 1000 +
- (tv.tv_usec - devc->start_tv.tv_usec) / 1000;
-
- if (running_msec < devc->limit_msec && numchunks < 32767)
- /* Still capturing. */
- return TRUE;
-
- /* Stop acquisition. */
- sigma_set_register(WRITE_MODE, 0x11, devc);
-
- /* Set SDRAM Read Enable. */
- sigma_set_register(WRITE_MODE, 0x02, devc);
-
- /* Get the current position. */
- sigma_read_pos(&devc->state.stoppos, &devc->state.triggerpos, devc);
-
- /* Check if trigger has fired. */
- modestatus = sigma_get_register(READ_MODE, devc);
- if (modestatus & 0x20)
- devc->state.triggerchunk = devc->state.triggerpos / 512;
- else
- devc->state.triggerchunk = -1;
-
- /* Transfer captured data from device. */
- download_capture(sdi);
-
- /* All done. */
- packet.type = SR_DF_END;
- sr_session_send(sdi, &packet);
-
- dev_acquisition_stop(sdi, sdi);
- }
+ if (devc->state.state == SIGMA_CAPTURE)
+ return sigma_capture_mode(sdi);
return TRUE;
}