diff --git a/hardware/sysclk-lwla/protocol.c b/hardware/sysclk-lwla/protocol.c index 7c8cc80a..b154de66 100644 --- a/hardware/sysclk-lwla/protocol.c +++ b/hardware/sysclk-lwla/protocol.c @@ -238,8 +238,8 @@ static void issue_read_start(const struct sr_dev_inst *sdi) acq->mem_addr_next = 4; acq->mem_addr_stop = acq->mem_addr_fill; - /* Byte offset into the packet output buffer. */ - acq->out_offset = 0; + /* Sample position in the packet output buffer. */ + acq->out_index = 0; regvals = devc->reg_write_seq; @@ -434,49 +434,6 @@ static void request_read_mem(const struct sr_dev_inst *sdi) } } -/* Send a packet of logic samples to the session bus. The payload is taken - * from the acquisition state. The return value indicates whether to stop - * reading more samples. - */ -static gboolean send_logic_packet(const struct sr_dev_inst *sdi) -{ - uint64_t samples; - struct dev_context *devc; - struct acquisition_state *acq; - struct sr_datafeed_packet packet; - struct sr_datafeed_logic logic; - int last; - - devc = sdi->priv; - acq = devc->acquisition; - - if (acq->samples_done >= acq->samples_max) - return TRUE; - - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.unitsize = UNIT_SIZE; - logic.data = acq->out_packet; - logic.length = acq->out_offset; - - samples = acq->out_offset / UNIT_SIZE; - last = FALSE; - - /* Cut the packet short if necessary. */ - if (acq->samples_done + samples >= acq->samples_max) { - samples = acq->samples_max - acq->samples_done; - logic.length = samples * UNIT_SIZE; - last = TRUE; - } - acq->samples_done += samples; - acq->out_offset = 0; - - /* Send off logic datafeed packet. */ - sr_session_send(sdi, &packet); - - return last; -} - /* Demangle and decompress incoming sample data from the capture buffer. * The data chunk is taken from the acquisition state, and is expected to * contain a multiple of 8 device words. @@ -487,15 +444,19 @@ static gboolean send_logic_packet(const struct sr_dev_inst *sdi) static int process_sample_data(const struct sr_dev_inst *sdi) { uint64_t sample; - uint64_t run_len; uint64_t high_nibbles; uint64_t word; struct dev_context *devc; struct acquisition_state *acq; uint8_t *out_p; uint16_t *slice; + struct sr_datafeed_packet packet; + struct sr_datafeed_logic logic; size_t expect_len; size_t actual_len; + size_t out_max_samples; + size_t out_run_samples; + size_t ri; size_t in_words_left; size_t si; @@ -518,27 +479,49 @@ static int process_sample_data(const struct sr_dev_inst *sdi) return SR_ERR; } acq->mem_addr_done += in_words_left; + + /* Prepare session packet. */ + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.unitsize = UNIT_SIZE; + logic.data = acq->out_packet; + slice = acq->xfer_buf_in; si = 0; /* word index within slice */ for (;;) { - sample = acq->sample; + /* Calculate number of samples to write into packet. */ + out_max_samples = MIN(acq->samples_max - acq->samples_done, + PACKET_LENGTH - acq->out_index); + out_run_samples = MIN(acq->run_len, out_max_samples); + /* Expand run-length samples into session packet. */ - for (run_len = acq->run_len; run_len > 0; --run_len) { - out_p = &acq->out_packet[acq->out_offset]; + sample = acq->sample; + out_p = &acq->out_packet[acq->out_index * UNIT_SIZE]; + + for (ri = 0; ri < out_run_samples; ++ri) { out_p[0] = sample & 0xFF; out_p[1] = (sample >> 8) & 0xFF; out_p[2] = (sample >> 16) & 0xFF; out_p[3] = (sample >> 24) & 0xFF; out_p[4] = (sample >> 32) & 0xFF; - acq->out_offset += UNIT_SIZE; - - /* Send out packet if it is full. */ - if (acq->out_offset > PACKET_SIZE - UNIT_SIZE) - if (send_logic_packet(sdi)) - return SR_OK; /* sample limit reached */ + out_p += UNIT_SIZE; + } + acq->run_len -= out_run_samples; + acq->out_index += out_run_samples; + acq->samples_done += out_run_samples; + + /* Packet full or sample count limit reached? */ + if (out_run_samples == out_max_samples) { + logic.length = acq->out_index * UNIT_SIZE; + sr_session_send(sdi, &packet); + acq->out_index = 0; + + if (acq->samples_done >= acq->samples_max) + return SR_OK; /* sample limit reached */ + if (acq->run_len > 0) + continue; /* need another packet */ } - acq->run_len = 0; if (in_words_left == 0) break; /* done with current chunk */ @@ -566,10 +549,12 @@ static int process_sample_data(const struct sr_dev_inst *sdi) --in_words_left; } - /* Send out partially filled packet if it is the last one. */ - if (acq->mem_addr_done >= acq->mem_addr_stop && acq->out_offset > 0) - send_logic_packet(sdi); - + /* Send out partially filled packet if this was the last chunk. */ + if (acq->mem_addr_done >= acq->mem_addr_stop && acq->out_index > 0) { + logic.length = acq->out_index * UNIT_SIZE; + sr_session_send(sdi, &packet); + acq->out_index = 0; + } return SR_OK; } diff --git a/hardware/sysclk-lwla/protocol.h b/hardware/sysclk-lwla/protocol.h index d177836e..f8b64ac6 100644 --- a/hardware/sysclk-lwla/protocol.h +++ b/hardware/sysclk-lwla/protocol.h @@ -44,7 +44,7 @@ /** Unit and packet size for the sigrok logic datafeed. */ #define UNIT_SIZE ((NUM_PROBES + 7) / 8) -#define PACKET_SIZE (10000 * UNIT_SIZE) /* bytes */ +#define PACKET_LENGTH 10000 /* units */ /** Size of the acquisition buffer in device memory units. */ @@ -158,7 +158,7 @@ struct acquisition_state { size_t mem_addr_next; size_t mem_addr_stop; - size_t out_offset; + size_t out_index; struct libusb_transfer *xfer_in; struct libusb_transfer *xfer_out; @@ -175,7 +175,7 @@ struct acquisition_state { uint16_t xfer_buf_in[MAX_ACQ_RECV_WORDS]; /* Payload buffer for sigrok logic packets. */ - uint8_t out_packet[PACKET_SIZE]; + uint8_t out_packet[PACKET_LENGTH * UNIT_SIZE]; }; /** Private, per-device-instance driver context.