]> sigrok.org Git - libsigrok.git/blobdiff - hardware/beaglelogic/protocol.c
beaglelogic: Implementation with soft triggers
[libsigrok.git] / hardware / beaglelogic / protocol.c
index f765a957ecc3a20dbc982872cf4dfa15b8233384..1c01b64f758405955e5715d3b9a4a67998b51c9d 100644 (file)
  */
 
 #include "protocol.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 
+/* Define data packet size independent of packet (bufunitsize bytes) size
+ * from the BeagleLogic kernel module */
+#define PACKET_SIZE    (512 * 1024)
+
+/* This implementation is zero copy from the libsigrok side.
+ * It does not copy any data, just passes a pointer from the mmap'ed
+ * kernel buffers appropriately. It is up to the application which is
+ * using libsigrok to decide how to deal with the data.
+ */
 SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
 {
        const struct sr_dev_inst *sdi;
        struct dev_context *devc;
+       struct sr_datafeed_packet packet;
+       struct sr_datafeed_logic logic;
 
-       (void)fd;
+       int trigger_offset;
+       uint32_t packetsize;
+       uint64_t bytes_remaining;
 
-       if (!(sdi = cb_data))
+       if (!(sdi = cb_data) || !(devc = sdi->priv))
                return TRUE;
 
-       if (!(devc = sdi->priv))
-               return TRUE;
+       packetsize = PACKET_SIZE;
+       logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit);
 
        if (revents == G_IO_IN) {
-               /* TODO */
+               sr_info("In callback G_IO_IN, offset=%d", devc->offset);
+
+               bytes_remaining = (devc->limit_samples * logic.unitsize) -
+                               devc->bytes_read;
+
+               /* Configure data packet */
+               packet.type = SR_DF_LOGIC;
+               packet.payload = &logic;
+               logic.data = devc->sample_buf + devc->offset;
+               logic.length = MIN(packetsize, bytes_remaining);
+
+               if (devc->trigger_fired) {
+                       /* Send the incoming transfer to the session bus. */
+                       sr_session_send(devc->cb_data, &packet);
+               } else {
+                       /* Check for trigger */
+                       trigger_offset = soft_trigger_logic_check(devc->stl,
+                                               logic.data,
+                                               packetsize);
+
+                       if (trigger_offset > -1) {
+                               trigger_offset *= logic.unitsize;
+                               logic.length = MIN(packetsize - trigger_offset,
+                                               bytes_remaining);
+                               logic.data += trigger_offset;
+
+                               sr_session_send(devc->cb_data, &packet);
+
+                               devc->trigger_fired = TRUE;
+                       }
+               }
+
+               /* Move the read pointer forward */
+               lseek(fd, packetsize, SEEK_CUR);
+
+               /* Update byte count and offset (roll over if needed) */
+               devc->bytes_read += logic.length;
+               if ((devc->offset += packetsize) >= devc->buffersize) {
+                       /* One shot capture, we abort and settle with less than
+                        * the required number of samples */
+                       if (devc->triggerflags)
+                               devc->offset = 0;
+                       else
+                               packetsize = 0;
+               }
+       }
+
+       /* EOF Received or we have reached the limit */
+       if (devc->bytes_read >= devc->limit_samples * logic.unitsize ||
+                       packetsize == 0) {
+               /* Send EOA Packet, stop polling */
+               packet.type = SR_DF_END;
+               packet.payload = NULL;
+               sr_session_send(devc->cb_data, &packet);
+
+               sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
        }
 
        return TRUE;