]> sigrok.org Git - libsigrok.git/commitdiff
fx2lafw: Add support for frames
authorValentin Ochs <redacted>
Sat, 20 Jun 2020 00:04:00 +0000 (02:04 +0200)
committerSoeren Apel <redacted>
Mon, 13 Jul 2020 21:07:56 +0000 (23:07 +0200)
When using a number of frames that is not 1, the driver will read
samples up to its limit and then wait for another trigger. This will be
repeated until the configured number of frames has been finished.

src/hardware/fx2lafw/api.c
src/hardware/fx2lafw/protocol.c
src/hardware/fx2lafw/protocol.h

index 04efcf3f6abba45d47dab0a2974a8f3c56c97e90..5acb0016d0b8e6ab5ad204aea7e238f55e2f5fa8 100644 (file)
@@ -125,6 +125,7 @@ static const uint32_t drvopts[] = {
 
 static const uint32_t devopts[] = {
        SR_CONF_CONTINUOUS,
+       SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
        SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
        SR_CONF_CONN | SR_CONF_GET,
        SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
@@ -491,6 +492,9 @@ static int config_get(uint32_t key, GVariant **data,
                        return SR_ERR;
                *data = g_variant_new_printf("%d.%d", usb->bus, usb->address);
                break;
+       case SR_CONF_LIMIT_FRAMES:
+               *data = g_variant_new_uint64(devc->limit_frames);
+               break;
        case SR_CONF_LIMIT_SAMPLES:
                *data = g_variant_new_uint64(devc->limit_samples);
                break;
@@ -526,6 +530,9 @@ static int config_set(uint32_t key, GVariant *data,
                        return SR_ERR_ARG;
                devc->cur_samplerate = devc->samplerates[idx];
                break;
+       case SR_CONF_LIMIT_FRAMES:
+               devc->limit_frames = g_variant_get_uint64(data);
+               break;
        case SR_CONF_LIMIT_SAMPLES:
                devc->limit_samples = g_variant_get_uint64(data);
                break;
index 83315808d0eca129d1e37503d0375ec22de8f250..ef41f221a40ac16503f10b18ffb68aa45b0db6db 100644 (file)
@@ -414,7 +414,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
        struct dev_context *devc;
        gboolean packet_has_error = FALSE;
        unsigned int num_samples;
-       int trigger_offset, cur_sample_count, unitsize;
+       int trigger_offset, cur_sample_count, unitsize, processed_samples;
        int pre_trigger_samples;
 
        sdi = transfer->user_data;
@@ -435,6 +435,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
        /* Save incoming transfer before reusing the transfer struct. */
        unitsize = devc->sample_wide ? 2 : 1;
        cur_sample_count = transfer->actual_length / unitsize;
+       processed_samples = 0;
 
        switch (transfer->status) {
        case LIBUSB_TRANSFER_NO_DEVICE:
@@ -465,38 +466,66 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
        } else {
                devc->empty_transfer_count = 0;
        }
+
+check_trigger:
        if (devc->trigger_fired) {
                if (!devc->limit_samples || devc->sent_samples < devc->limit_samples) {
                        /* Send the incoming transfer to the session bus. */
-                       if (devc->limit_samples && devc->sent_samples + cur_sample_count > devc->limit_samples)
+                       num_samples = cur_sample_count - processed_samples;
+                       if (devc->limit_samples && devc->sent_samples + num_samples > devc->limit_samples)
                                num_samples = devc->limit_samples - devc->sent_samples;
-                       else
-                               num_samples = cur_sample_count;
 
-                       devc->send_data_proc(sdi, (uint8_t *)transfer->buffer,
+                       devc->send_data_proc(sdi, (uint8_t *)transfer->buffer + processed_samples * unitsize,
                                num_samples * unitsize, unitsize);
                        devc->sent_samples += num_samples;
+                       processed_samples += num_samples;
                }
        } else {
                trigger_offset = soft_trigger_logic_check(devc->stl,
-                       transfer->buffer, transfer->actual_length, &pre_trigger_samples);
+                       transfer->buffer + processed_samples * unitsize,
+                       transfer->actual_length - processed_samples * unitsize,
+                       &pre_trigger_samples);
                if (trigger_offset > -1) {
+                       std_session_send_df_frame_begin(sdi);
                        devc->sent_samples += pre_trigger_samples;
-                       num_samples = cur_sample_count - trigger_offset;
+                       num_samples = cur_sample_count - processed_samples - trigger_offset;
                        if (devc->limit_samples &&
-                                       num_samples > devc->limit_samples - devc->sent_samples)
+                                       devc->sent_samples + num_samples > devc->limit_samples)
                                num_samples = devc->limit_samples - devc->sent_samples;
 
                        devc->send_data_proc(sdi, (uint8_t *)transfer->buffer
+                                       + processed_samples * unitsize
                                        + trigger_offset * unitsize,
                                        num_samples * unitsize, unitsize);
                        devc->sent_samples += num_samples;
+                       processed_samples += trigger_offset + num_samples;
 
                        devc->trigger_fired = TRUE;
                }
        }
 
-       if (devc->limit_samples && devc->sent_samples >= devc->limit_samples) {
+       const int frame_ended = devc->limit_samples && (devc->sent_samples >= devc->limit_samples);
+       const int final_frame = devc->limit_frames && (devc->num_frames >= (devc->limit_frames - 1));
+       if (frame_ended) {
+               devc->num_frames++;
+               devc->sent_samples = 0;
+               devc->trigger_fired = FALSE;
+               std_session_send_df_frame_end(sdi);
+
+               /* There may be another trigger in the remaining data, go back and check for it */
+               if (processed_samples < cur_sample_count) {
+                       /* Reset the trigger stage */
+                       if (devc->stl)
+                               devc->stl->cur_stage = 0;
+                       else {
+                               std_session_send_df_frame_begin(sdi);
+                               devc->trigger_fired = TRUE;
+                       }
+                       if (!final_frame)
+                               goto check_trigger;
+               }
+       }
+       if (frame_ended && final_frame) {
                fx2lafw_abort_acquisition(devc);
                free_transfer(transfer);
        } else
@@ -621,8 +650,10 @@ static int start_transfers(const struct sr_dev_inst *sdi)
                if (!devc->stl)
                        return SR_ERR_MALLOC;
                devc->trigger_fired = FALSE;
-       } else
+       } else {
+               std_session_send_df_frame_begin(sdi);
                devc->trigger_fired = TRUE;
+       }
 
        num_transfers = get_number_of_transfers(devc);
 
index 1403c8ab09adf3a49ad53e3ff289c3877cd15f9e..3f240c590eb1bb765b991796a2c8619d45aa03f8 100644 (file)
@@ -102,6 +102,7 @@ struct dev_context {
        int num_samplerates;
 
        uint64_t cur_samplerate;
+       uint64_t limit_frames;
        uint64_t limit_samples;
        uint64_t capture_ratio;
 
@@ -110,6 +111,7 @@ struct dev_context {
        gboolean sample_wide;
        struct soft_trigger_logic *stl;
 
+       uint64_t num_frames;
        unsigned int sent_samples;
        int submitted_transfers;
        int empty_transfer_count;