aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2018-04-30 20:12:42 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2018-05-20 19:45:38 +0200
commiteb11e68412b49b0945ab6bb332ac9486f1ebeb9e (patch)
tree768091baf5dd8150d33b3f8275316bb92d31608e
parent16b102efcdae6c33b1761e4f2da8c507eed03bb4 (diff)
downloadosmo-fl2k-eb11e68412b49b0945ab6bb332ac9486f1ebeb9e.tar.gz
osmo-fl2k-eb11e68412b49b0945ab6bb332ac9486f1ebeb9e.tar.bz2
osmo-fl2k-eb11e68412b49b0945ab6bb332ac9486f1ebeb9e.zip
Add support for interleaved R/G samples
This is useful for transmitting complex I/Q data on the red and green DACs
-rw-r--r--include/osmo-fl2k.h3
-rw-r--r--src/fl2k_file.c23
-rw-r--r--src/libosmo-fl2k.c51
3 files changed, 64 insertions, 13 deletions
diff --git a/include/osmo-fl2k.h b/include/osmo-fl2k.h
index 8d3cc3b..6a1b3ee 100644
--- a/include/osmo-fl2k.h
+++ b/include/osmo-fl2k.h
@@ -50,6 +50,9 @@ typedef struct fl2k_data_info {
/* filled in by application */
int sampletype_signed; /* are samples signed or unsigned? */
+ /* Either iq_buf or (r_buf, g_buf and b_buf) must be non-null */
+ char *iq_buf; /* pointer to data containing interleaved r and g
+ data */
char *r_buf; /* pointer to red buffer */
char *g_buf; /* pointer to green buffer */
char *b_buf; /* pointer to blue buffer */
diff --git a/src/fl2k_file.c b/src/fl2k_file.c
index 1d3697d..0da1cbc 100644
--- a/src/fl2k_file.c
+++ b/src/fl2k_file.c
@@ -40,7 +40,8 @@
static fl2k_dev_t *dev = NULL;
static volatile int do_exit = 0;
-static volatile int repeat = 1;
+static int repeat = 1;
+static int interleaved = 1;
FILE *file;
char *txbuf = NULL;
@@ -52,6 +53,7 @@ void usage(void)
"\t[-d device_index (default: 0)]\n"
"\t[-r repeat file (default: 1)]\n"
"\t[-s samplerate (default: 100 MS/s)]\n"
+ "\t[-i interleave (input samples are interleaved Red/Green values, useful for I/Q data, default: 0)]\n"
"\tfilename (use '-' to read from stdin)\n\n"
);
exit(1);
@@ -80,14 +82,20 @@ static void sighandler(int signum)
void fl2k_callback(fl2k_data_info_t *data_info)
{
- int r, left = FL2K_BUF_LEN;
+ int r;
+ const int required_samples = FL2K_BUF_LEN * (interleaved ? 2 : 1);
+ int left = required_samples;
static uint32_t repeat_cnt = 0;
data_info->sampletype_signed = 1;
- data_info->r_buf = txbuf;
+ if (interleaved) {
+ data_info->iq_buf = txbuf;
+ } else {
+ data_info->r_buf = txbuf;
+ }
while (!do_exit && (left > 0)) {
- r = fread(txbuf + (FL2K_BUF_LEN - left), 1, left, file);
+ r = fread(txbuf + (required_samples - left), 1, left, file);
if (ferror(file))
fprintf(stderr, "File Error\n");
@@ -120,11 +128,14 @@ int main(int argc, char **argv)
void *status;
char *filename = NULL;
- while ((opt = getopt(argc, argv, "d:r:s:")) != -1) {
+ while ((opt = getopt(argc, argv, "d:i:r:s:")) != -1) {
switch (opt) {
case 'd':
dev_index = (uint32_t)atoi(optarg);
break;
+ case 'i':
+ interleaved = (int)atoi(optarg);
+ break;
case 'r':
repeat = (int)atoi(optarg);
break;
@@ -151,7 +162,7 @@ int main(int argc, char **argv)
goto out;
}
- txbuf = malloc(FL2K_BUF_LEN);
+ txbuf = malloc(FL2K_BUF_LEN * (interleaved ? 2 : 1));
if (!txbuf) {
fprintf(stderr, "malloc error!\n");
goto out;
diff --git a/src/libosmo-fl2k.c b/src/libosmo-fl2k.c
index 0285f9a..09380b6 100644
--- a/src/libosmo-fl2k.c
+++ b/src/libosmo-fl2k.c
@@ -767,6 +767,37 @@ static void *fl2k_usb_worker(void *arg)
}
/* Buffer format conversion functions for R, G, B DACs */
+static inline void fl2k_convert_rg_interleaved(
+ char *out,
+ char *in,
+ uint32_t len,
+ uint8_t offset)
+{
+ unsigned int i, j = 0;
+
+ if (!in || !out)
+ return;
+
+ for (i = 0; i < len; i += 24) {
+ out[i+ 6] = in[j++] + offset;
+ out[i+ 5] = in[j++] + offset;
+ out[i+ 1] = in[j++] + offset;
+ out[i+ 0] = in[j++] + offset;
+ out[i+12] = in[j++] + offset;
+ out[i+ 3] = in[j++] + offset;
+ out[i+15] = in[j++] + offset;
+ out[i+14] = in[j++] + offset;
+ out[i+10] = in[j++] + offset;
+ out[i+ 9] = in[j++] + offset;
+ out[i+21] = in[j++] + offset;
+ out[i+20] = in[j++] + offset;
+ out[i+16] = in[j++] + offset;
+ out[i+23] = in[j++] + offset;
+ out[i+19] = in[j++] + offset;
+ out[i+18] = in[j++] + offset;
+ }
+}
+
static inline void fl2k_convert_r(char *out,
char *in,
uint32_t len,
@@ -882,15 +913,21 @@ static void *fl2k_sample_worker(void *arg)
xfer_info = (fl2k_xfer_info_t *)xfer->user_data;
out_buf = (char *)xfer->buffer;
- /* Re-arrange and copy bytes in buffer for DACs */
- fl2k_convert_r(out_buf, data_info.r_buf, dev->xfer_buf_len,
- data_info.sampletype_signed ? 128 : 0);
+ if (data_info.iq_buf) {
+ /* Re-arrange interleaved samples and copy bytes in buffer for DACs */
+ fl2k_convert_rg_interleaved(out_buf, data_info.iq_buf,
+ dev->xfer_buf_len, data_info.sampletype_signed ? 128 : 0);
+ } else {
+ /* Re-arrange and copy bytes in buffer for DACs */
+ fl2k_convert_r(out_buf, data_info.r_buf, dev->xfer_buf_len,
+ data_info.sampletype_signed ? 128 : 0);
- fl2k_convert_g(out_buf, data_info.g_buf, dev->xfer_buf_len,
- data_info.sampletype_signed ? 128 : 0);
+ fl2k_convert_g(out_buf, data_info.g_buf, dev->xfer_buf_len,
+ data_info.sampletype_signed ? 128 : 0);
- fl2k_convert_b(out_buf, data_info.b_buf, dev->xfer_buf_len,
- data_info.sampletype_signed ? 128 : 0);
+ fl2k_convert_b(out_buf, data_info.b_buf, dev->xfer_buf_len,
+ data_info.sampletype_signed ? 128 : 0);
+ }
xfer_info->seq = buf_cnt++;
xfer_info->state = BUF_FILLED;