X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fasix-sigma%2Fasix-sigma.c;h=59acdcb1dcaa657d8822c0db5e91eb4a1e649777;hb=46641facd4ad8de4a93910d7089c7b289b412443;hp=06373d61a574074cfebef04465af2b2a2b273bf7;hpb=64fe661b87c119079516b9ba7b395bdd8af14994;p=libsigrok.git diff --git a/hardware/asix-sigma/asix-sigma.c b/hardware/asix-sigma/asix-sigma.c index 06373d61..59acdcb1 100644 --- a/hardware/asix-sigma/asix-sigma.c +++ b/hardware/asix-sigma/asix-sigma.c @@ -455,8 +455,22 @@ static int sigma_fpga_init_la(struct dev_context *devc) { /* Initialize the logic analyzer mode. */ uint8_t logic_mode_start[] = { - 0x00, 0x40, 0x0f, 0x25, 0x35, 0x40, - 0x2a, 0x3a, 0x40, 0x03, 0x20, 0x38, + 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]; @@ -465,7 +479,7 @@ static int sigma_fpga_init_la(struct dev_context *devc) /* Initialize the logic analyzer mode. */ sigma_write(logic_mode_start, sizeof(logic_mode_start), devc); - /* Expect a 3 byte reply. */ + /* Expect a 3 byte reply since we issued three READ requests. */ ret = sigma_read(result, 3, devc); if (ret != 3) goto err; @@ -915,6 +929,15 @@ static int get_trigger_offset(uint16_t *samples, uint16_t last_sample, return i & 0x7; } + +/* + * Return the timestamp of "DRAM cluster". + */ +static uint16_t sigma_dram_cluster_ts(struct sigma_dram_cluster *cluster) +{ + return (cluster->timestamp_hi << 8) | cluster->timestamp_lo; +} + /* * Decode chunk of 1024 bytes, 64 clusters, 7 events per cluster. * Each event is 20ns apart, and can contain multiple samples. @@ -924,10 +947,12 @@ static int get_trigger_offset(uint16_t *samples, uint16_t last_sample, * For 50 MHz and below, events contain one sample for each channel, * spread 20 ns apart. */ -static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts, +static int decode_chunk_ts(struct sigma_dram_line *dram_line, uint16_t *lastts, uint16_t *lastsample, int triggerpos, - uint16_t limit_chunk, void *cb_data) + uint16_t events_in_line, void *cb_data) { + uint8_t *buf = (uint8_t *)dram_line; + struct sigma_dram_cluster *dram_cluster; struct sr_dev_inst *sdi = cb_data; struct dev_context *devc = sdi->priv; uint16_t tsdiff, ts; @@ -954,15 +979,12 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts, } /* For each ts. */ - for (i = 0; i < 64; ++i) { - ts = *(uint16_t *) &buf[i * 16]; + for (i = 0; i < (events_in_line / 7); i++) { + dram_cluster = &dram_line->cluster[i]; + ts = sigma_dram_cluster_ts(dram_cluster); tsdiff = ts - *lastts; *lastts = ts; - /* Decode partial chunk. */ - if (limit_chunk && ts > limit_chunk) - return SR_OK; - /* Pad last sample up to current point. */ numpad = tsdiff * devc->samples_per_event - clustersize; if (numpad > 0) { @@ -1055,66 +1077,133 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts, 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; + 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_events_in_line = 64 * 7; + uint32_t trg_line = ~0; + + dram_line = g_try_malloc0(chunks_per_read * sizeof(*dram_line)); + if (!dram_line) + return FALSE; 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); - /* Decode chunks and send them to sigrok. */ - for (i = 0; i < newchunks; ++i) { - int limit_chunk = 0; + /* Set SDRAM Read Enable. */ + sigma_set_register(WRITE_MODE, 0x02, devc); + + /* Get the current position. */ + sigma_read_pos(&stoppos, &triggerpos, devc); - /* 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; + /* 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_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); + + bufsz = sigma_read_dram(dl_lines_done, dl_lines_curr, + (uint8_t *)dram_line, devc); + /* TODO: Check bufsz. For now, just avoid compiler warnings. */ + (void)bufsz; + + /* This is the first DRAM line, so find the initial timestamp. */ + if (dl_lines_done == 0) { + devc->state.lastts = + sigma_dram_cluster_ts(&dram_line[0].cluster[0]); + 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 - decode_chunk_ts(buf + (i * CHUNK_SIZE), + for (i = 0; i < dl_lines_curr; i++) { + int trigger_line = -1; + /* The last "DRAM line" can be only partially full. */ + if (dl_lines_done + i == dl_lines_total - 1) + dl_events_in_line = stoppos & 0x1ff; + + /* Test if the trigger happened on this line. */ + if (dl_lines_done + i == trg_line) + trigger_line = trg_line; + + decode_chunk_ts(dram_line + i, &devc->state.lastts, &devc->state.lastsample, - -1, limit_chunk, sdi); + trigger_line, + dl_events_in_line, 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; @@ -1122,49 +1211,11 @@ static int receive_data(int fd, int revents, void *cb_data) 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; }