summaryrefslogtreecommitdiff
path: root/Radio/HW/BladeRF/src/streaming/sync.h
diff options
context:
space:
mode:
Diffstat (limited to 'Radio/HW/BladeRF/src/streaming/sync.h')
-rw-r--r--Radio/HW/BladeRF/src/streaming/sync.h193
1 files changed, 193 insertions, 0 deletions
diff --git a/Radio/HW/BladeRF/src/streaming/sync.h b/Radio/HW/BladeRF/src/streaming/sync.h
new file mode 100644
index 0000000..8977791
--- /dev/null
+++ b/Radio/HW/BladeRF/src/streaming/sync.h
@@ -0,0 +1,193 @@
+/*
+ * This file is part of the bladeRF project:
+ * http://www.github.com/nuand/bladeRF
+ *
+ * Copyright (C) 2014 Nuand LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef STREAMING_SYNC_H_
+#define STREAMING_SYNC_H_
+
+#include <limits.h>
+#include <pthread.h>
+
+#include <libbladeRF.h>
+
+#include "thread.h"
+
+/* These parameters are only written during sync_init */
+struct stream_config {
+ bladerf_format format;
+ bladerf_channel_layout layout;
+
+ unsigned int samples_per_buffer;
+ unsigned int num_xfers;
+ unsigned int timeout_ms;
+
+ size_t bytes_per_sample;
+};
+
+typedef enum {
+ SYNC_BUFFER_EMPTY = 0, /**< Buffer contains no data */
+ SYNC_BUFFER_PARTIAL, /**< sync_rx/tx is currently emptying/filling */
+ SYNC_BUFFER_FULL, /**< Buffer is full of data */
+ SYNC_BUFFER_IN_FLIGHT, /**< Currently being transferred */
+} sync_buffer_status;
+
+typedef enum {
+ SYNC_META_STATE_HEADER, /**< Extract the metadata header */
+ SYNC_META_STATE_SAMPLES, /**< Process samples */
+} sync_meta_state;
+
+typedef enum {
+ /** Invalid selection */
+ SYNC_TX_SUBMITTER_INVALID = -1,
+
+ /** sync_tx() is repsonsible for submitting buffers for async transfer */
+ SYNC_TX_SUBMITTER_FN,
+
+ /** The TX worker callbacks should be returning buffers for submission */
+ SYNC_TX_SUBMITTER_CALLBACK
+} sync_tx_submitter;
+
+#define BUFFER_MGMT_INVALID_INDEX (UINT_MAX)
+
+struct buffer_mgmt {
+ sync_buffer_status *status;
+ size_t *actual_lengths;
+
+ void **buffers;
+ unsigned int num_buffers;
+
+ unsigned int prod_i; /**< Producer index - next buffer to fill */
+ unsigned int cons_i; /**< Consumer index - next buffer to empty */
+ unsigned int partial_off; /**< Current index into partial buffer */
+
+ /* In the event of a SW RX overrun, this count is used to determine
+ * how many more transfers should be considered invalid and require
+ * resubmission */
+ unsigned int resubmit_count;
+
+ /* Applicable to TX only. Denotes which context is responsible for
+ * submitting full buffers to the underlying async system */
+ sync_tx_submitter submitter;
+
+
+ MUTEX lock;
+ pthread_cond_t buf_ready; /**< Buffer produced by RX callback, or
+ * buffer emptied by TX callback */
+};
+
+/* State of API-side sync interface */
+typedef enum {
+ SYNC_STATE_CHECK_WORKER,
+ SYNC_STATE_RESET_BUF_MGMT,
+ SYNC_STATE_START_WORKER,
+ SYNC_STATE_WAIT_FOR_BUFFER,
+ SYNC_STATE_BUFFER_READY,
+ SYNC_STATE_USING_BUFFER,
+ SYNC_STATE_USING_PACKET_META,
+ SYNC_STATE_USING_BUFFER_META
+} sync_state;
+
+struct sync_meta {
+ sync_meta_state state; /* State of metadata processing */
+
+ uint8_t *curr_msg; /* Points to current message in the buffer */
+ size_t curr_msg_off; /* Offset into current message (samples),
+ * ignoring the 4-samples worth of metadata */
+ size_t msg_size; /* Size of data message */
+ unsigned int msg_per_buf; /* Number of data messages per buffer */
+ unsigned int msg_num; /* Which message within the buffer are we in?
+ * Range is: 0 to msg_per_buf */
+ unsigned int samples_per_msg; /* Number of samples within a message */
+ unsigned int samples_per_ts; /* Number of samples within a timestamp */
+
+ union {
+ /* Used only for RX */
+ struct {
+ uint64_t
+ msg_timestamp; /* Timestamp contained in the current message */
+ uint32_t msg_flags; /* Flags for the current message */
+ };
+
+ /* Used only for TX */
+ struct {
+ bool in_burst;
+ bool now;
+ };
+ };
+
+ uint64_t curr_timestamp; /* Timestamp at the sample we've
+ * consumed up to */
+};
+
+struct bladerf_sync {
+ MUTEX lock;
+ struct bladerf *dev;
+ bool initialized;
+ sync_state state;
+ struct buffer_mgmt buf_mgmt;
+ struct stream_config stream_config;
+ struct sync_worker *worker;
+ struct sync_meta meta;
+};
+
+/**
+ * Create and initialize as synchronous interface handle for the specified
+ * device and direction. If the synchronous handle is already initialized, this
+ * call will first deinitialize it.
+ *
+ * The associated stream will be started at the first RX or TX call
+ *
+ * @return 0 or BLADERF_ERR_* value on failure
+ */
+int sync_init(struct bladerf_sync *sync,
+ struct bladerf *dev,
+ bladerf_channel_layout layout,
+ bladerf_format format,
+ unsigned int num_buffers,
+ size_t buffer_size,
+ size_t msg_size,
+ unsigned int num_transfers,
+ unsigned int stream_timeout);
+
+/**
+ * Deinitialize the sync handle. This tears down and deallocates the underlying
+ * asynchronous stream.
+ *
+ * @param[inout] sync Handle to deinitialize.
+ */
+void sync_deinit(struct bladerf_sync *sync);
+
+int sync_rx(struct bladerf_sync *sync,
+ void *samples,
+ unsigned int num_samples,
+ struct bladerf_metadata *metadata,
+ unsigned int timeout_ms);
+
+int sync_tx(struct bladerf_sync *sync,
+ void const *samples,
+ unsigned int num_samples,
+ struct bladerf_metadata *metadata,
+ unsigned int timeout_ms);
+
+unsigned int sync_buf2idx(struct buffer_mgmt *b, void *addr);
+
+void *sync_idx2buf(struct buffer_mgmt *b, unsigned int idx);
+
+#endif