X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fsysclk-lwla%2Fprotocol.c;h=f1ae8b3d5d1fe1c1b146fa5d41ddb3eeb0f7ad50;hb=102f12396660e0784134bccce5cc0679db325751;hp=4c89ea2480db4d759841c0fb0333edaab89ba466;hpb=43db343618e81d03aa8531b4a4ed96c250a29991;p=libsigrok.git diff --git a/hardware/sysclk-lwla/protocol.c b/hardware/sysclk-lwla/protocol.c index 4c89ea24..f1ae8b3d 100644 --- a/hardware/sysclk-lwla/protocol.c +++ b/hardware/sysclk-lwla/protocol.c @@ -29,13 +29,13 @@ /* Number of 64-bit words read from the capture status memory. */ #define CAP_STAT_LEN 5 -/* The bitstream filenames are indexed by the clock source enumeration. +/* The bitstream filenames are indexed by the clock_config enumeration. */ -static const char *const bitstream_map[] = { - FIRMWARE_DIR "/sysclk-lwla1034-off.bitstream", - FIRMWARE_DIR "/sysclk-lwla1034-int.bitstream", - FIRMWARE_DIR "/sysclk-lwla1034-extpos.bitstream", - FIRMWARE_DIR "/sysclk-lwla1034-extneg.bitstream", +static const char bitstream_map[][32] = { + "sysclk-lwla1034-off.rbf", + "sysclk-lwla1034-int.rbf", + "sysclk-lwla1034-extpos.rbf", + "sysclk-lwla1034-extneg.rbf", }; /* Submit an already filled-in USB transfer. @@ -63,6 +63,7 @@ static int capture_setup(const struct sr_dev_inst *sdi) struct dev_context *devc; struct acquisition_state *acq; uint64_t divider_count; + uint64_t trigger_mask; uint64_t memory_limit; uint16_t command[3 + 10*4]; @@ -102,10 +103,18 @@ static int capture_setup(const struct sr_dev_inst *sdi) command[17] = LWLA_WORD_2(devc->trigger_edge_mask); command[18] = LWLA_WORD_3(devc->trigger_edge_mask); - command[19] = LWLA_WORD_0(devc->trigger_mask); - command[20] = LWLA_WORD_1(devc->trigger_mask); - command[21] = LWLA_WORD_2(devc->trigger_mask); - command[22] = LWLA_WORD_3(devc->trigger_mask); + trigger_mask = devc->trigger_mask; + /* Set bits to select external TRG input edge. */ + if (devc->cfg_trigger_source == TRIGGER_EXT_TRG) + switch (devc->cfg_trigger_slope) { + case EDGE_POSITIVE: trigger_mask |= (uint64_t)1 << 35; break; + case EDGE_NEGATIVE: trigger_mask |= (uint64_t)1 << 34; break; + } + + command[19] = LWLA_WORD_0(trigger_mask); + command[20] = LWLA_WORD_1(trigger_mask); + command[21] = LWLA_WORD_2(trigger_mask); + command[22] = LWLA_WORD_3(trigger_mask); /* Set the capture memory full threshold. This is slightly less * than the actual maximum, most likely in order to compensate for @@ -287,7 +296,7 @@ static void process_capture_length(const struct sr_dev_inst *sdi) devc->transfer_error = TRUE; return; } - acq->mem_addr_fill = LWLA_READ32(acq->xfer_buf_in); + acq->mem_addr_fill = LWLA_TO_UINT32(acq->xfer_buf_in[0]); sr_dbg("%zu words in capture buffer.", acq->mem_addr_fill); @@ -362,9 +371,9 @@ static void process_capture_status(const struct sr_dev_inst *sdi) * in the FPGA. These fields are definitely less than 64 bit wide * internally, and the unused bits occasionally even contain garbage. */ - mem_fill = LWLA_READ32(&acq->xfer_buf_in[0]); - duration = LWLA_READ32(&acq->xfer_buf_in[8]); - flags = LWLA_READ32(&acq->xfer_buf_in[16]) & STATUS_FLAG_MASK; + mem_fill = LWLA_TO_UINT32(acq->xfer_buf_in[0]); + duration = LWLA_TO_UINT32(acq->xfer_buf_in[4]); + flags = LWLA_TO_UINT32(acq->xfer_buf_in[8]) & STATUS_FLAG_MASK; /* The LWLA1034 runs at 125 MHz if the clock divider is bypassed. * However, the time base used for the duration is apparently not @@ -452,7 +461,7 @@ static int process_sample_data(const struct sr_dev_inst *sdi) struct dev_context *devc; struct acquisition_state *acq; uint8_t *out_p; - uint16_t *slice; + uint32_t *slice; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; size_t expect_len; @@ -472,7 +481,7 @@ static int process_sample_data(const struct sr_dev_inst *sdi) in_words_left = MIN(acq->mem_addr_stop - acq->mem_addr_done, READ_CHUNK_LEN); - expect_len = LWLA1034_MEMBUF_LEN(in_words_left) * sizeof(uint16_t); + expect_len = LWLA1034_MEMBUF_LEN(in_words_left) * sizeof(uint32_t); actual_len = acq->xfer_in->actual_length; if (actual_len != expect_len) { @@ -530,13 +539,13 @@ static int process_sample_data(const struct sr_dev_inst *sdi) break; /* done with current chunk */ /* Now work on the current slice. */ - high_nibbles = LWLA_READ32(&slice[8 * 2]); - word = LWLA_READ32(&slice[si * 2]); + high_nibbles = LWLA_TO_UINT32(slice[8]); + word = LWLA_TO_UINT32(slice[si]); word |= (high_nibbles << (4 * si + 4)) & ((uint64_t)0xF << 32); if (acq->rle == RLE_STATE_DATA) { acq->sample = word & ALL_CHANNELS_MASK; - acq->run_len = ((word >> NUM_PROBES) & 1) + 1; + acq->run_len = ((word >> NUM_CHANNELS) & 1) + 1; if (word & RLE_FLAG_LEN_FOLLOWS) acq->rle = RLE_STATE_LEN; } else { @@ -545,10 +554,9 @@ static int process_sample_data(const struct sr_dev_inst *sdi) } /* Move to next word. */ - if (++si >= 8) { - si = 0; - slice += 9 * 2; - } + si = (si + 1) % 8; + if (si == 0) + slice += 9; --in_words_left; } @@ -579,7 +587,7 @@ static void end_acquisition(struct sr_dev_inst *sdi) devc->state = STATE_IDLE; /* Remove USB file descriptors from polling. */ - usb_source_remove(drvc->sr_ctx); + usb_source_remove(sdi->session, drvc->sr_ctx); packet.type = SR_DF_END; sr_session_send(sdi, &packet); @@ -694,14 +702,10 @@ SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi) devc = sdi->priv; - /* Select internal clock if it hasn't been set yet */ - if (devc->selected_clock_source == CLOCK_SOURCE_NONE) - devc->selected_clock_source = CLOCK_SOURCE_INT; - /* Force reload of bitstream */ - devc->cur_clock_source = CLOCK_SOURCE_NONE; + devc->cur_clock_config = CONF_CLOCK_NONE; - ret = lwla_set_clock_source(sdi); + ret = lwla_set_clock_config(sdi); if (ret != SR_OK) return ret; @@ -734,29 +738,80 @@ SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi) return ret; } -/* Select the LWLA clock source. If the clock source changed from the - * previous setting, this will download a new bitstream to the FPGA. +SR_PRIV int lwla_convert_trigger(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + struct sr_trigger *trigger; + struct sr_trigger_stage *stage; + struct sr_trigger_match *match; + const GSList *l, *m; + uint64_t channel_index; + + devc = sdi->priv; + + devc->trigger_mask = 0; + devc->trigger_values = 0; + devc->trigger_edge_mask = 0; + + if (!(trigger = sr_session_trigger_get(sdi->session))) + return SR_OK; + + if (g_slist_length(trigger->stages) > 1) { + sr_err("This device only supports 1 trigger stage."); + return SR_ERR; + } + + for (l = trigger->stages; l; l = l->next) { + stage = l->data; + for (m = stage->matches; m; m = m->next) { + match = m->data; + if (!match->channel->enabled) + /* Ignore disabled channels with a trigger. */ + continue; + channel_index = 1 << match->channel->index; + devc->trigger_mask |= channel_index; + switch (match->match) { + case SR_TRIGGER_ONE: + devc->trigger_values |= channel_index; + break; + case SR_TRIGGER_RISING: + devc->trigger_values |= channel_index; + /* Fall through for edge mask. */ + case SR_TRIGGER_FALLING: + devc->trigger_edge_mask |= channel_index; + break; + } + } + } + + return SR_OK; +} + +/* Select the LWLA clock configuration. If the clock source changed from + * the previous setting, this will download a new bitstream to the FPGA. */ -SR_PRIV int lwla_set_clock_source(const struct sr_dev_inst *sdi) +SR_PRIV int lwla_set_clock_config(const struct sr_dev_inst *sdi) { struct dev_context *devc; int ret; - enum clock_source selected; - size_t idx; + enum clock_config choice; devc = sdi->priv; - selected = devc->selected_clock_source; - if (devc->cur_clock_source != selected) { - devc->cur_clock_source = CLOCK_SOURCE_NONE; - idx = selected; - if (idx >= G_N_ELEMENTS(bitstream_map)) { - sr_err("Clock source (%d) out of range", selected); - return SR_ERR_BUG; - } - ret = lwla_send_bitstream(sdi->conn, bitstream_map[idx]); + if (sdi->status == SR_ST_INACTIVE) + choice = CONF_CLOCK_NONE; + else if (devc->cfg_clock_source == CLOCK_INTERNAL) + choice = CONF_CLOCK_INT; + else if (devc->cfg_clock_edge == EDGE_POSITIVE) + choice = CONF_CLOCK_EXT_RISE; + else + choice = CONF_CLOCK_EXT_FALL; + + if (choice != devc->cur_clock_config) { + devc->cur_clock_config = CONF_CLOCK_NONE; + ret = lwla_send_bitstream(sdi->conn, bitstream_map[choice]); if (ret == SR_OK) - devc->cur_clock_source = selected; + devc->cur_clock_config = choice; return ret; } return SR_OK; @@ -790,8 +845,7 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi) } else acq->samples_max = MAX_LIMIT_SAMPLES; - switch (devc->cur_clock_source) { - case CLOCK_SOURCE_INT: + if (devc->cfg_clock_source == CLOCK_INTERNAL) { sr_info("Internal clock, samplerate %" PRIu64 ".", devc->samplerate); if (devc->samplerate == 0) @@ -806,18 +860,13 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi) else if (devc->limit_samples == 0 && devc->limit_msec > 0) acq->samples_max = devc->limit_msec * devc->samplerate / 1000; - break; - case CLOCK_SOURCE_EXT_FALL: - sr_info("External clock, falling edge."); - acq->bypass_clockdiv = TRUE; - break; - case CLOCK_SOURCE_EXT_RISE: - sr_info("External clock, rising edge."); + } else { acq->bypass_clockdiv = TRUE; - break; - default: - sr_err("No valid clock source has been configured."); - return SR_ERR; + + if (devc->cfg_clock_edge == EDGE_NEGATIVE) + sr_info("External clock, falling edge."); + else + sr_info("External clock, rising edge."); } regvals[0].reg = REG_MEM_CTRL2;