Merge pull request #136 from osqzss/develop

Update players
This commit is contained in:
OSQZSS 2018-03-07 16:15:06 +09:00 committed by GitHub
commit 4733b8a42d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1050 additions and 693 deletions

3
.gitignore vendored
View File

@ -38,3 +38,6 @@ gps-sdr-sim-lut
# Temporary files
*.swp
# Netbeans project folder
nbproject/*

View File

@ -2,7 +2,7 @@
GPS-SDR-SIM generates GPS baseband signal data streams, which can be converted
to RF using software-defined radio (SDR) platforms, such as
[bladeRF](http://nuand.com/), [HackRF](https://github.com/mossmann/hackrf/wiki), and [USRP](http://www.ettus.com/).
[ADALM-Pluto](https://wiki.analog.com/university/tools/pluto), [bladeRF](http://nuand.com/), [HackRF](https://github.com/mossmann/hackrf/wiki), and [USRP](http://www.ettus.com/).
### Windows build instructions
@ -35,11 +35,11 @@ These files are then used to generate the simulated pseudorange and
Doppler for the GPS satellites in view. This simulated range data is
then used to generate the digitized I/Q samples for the GPS signal.
The bladeRF command line interface requires I/Q pairs stored as signed
The bladeRF and ADALM-Pluto command line interface requires I/Q pairs stored as signed
16-bit integers, while the hackrf_transfer and gps-sdr-sim-uhd.py
support signed bytes.
HackRF and bladeRF require 2.6 MHz sample rate, while the USRP2 requires
HackRF, bladeRF and ADALM-Pluto require 2.6 MHz sample rate, while the USRP2 requires
2.5 MHz (an even integral decimator of 100 MHz).
The simulation start time can be specified if the corresponding set of ephemerides
@ -91,6 +91,8 @@ The user motion can be specified in either dynamic or static mode:
The TX port of a particular SDR platform is connected to the GPS receiver
under test through a DC block and a fixed 50-60dB attenuator.
#### BladeRF:
The simulated GPS signal file, named "gpssim.bin", can be loaded
into the bladeRF for playback as shown below:
@ -106,30 +108,50 @@ tx start
```
You can also execute these commands via the `bladeRF-cli` script option as below:
```
> bladeRF-cli -s bladerf.script
```
For the HackRF:
#### HackRF:
```
> hackrf_transfer -t gpssim.bin -f 1575420000 -s 2600000 -a 1 -x 0
```
For UHD supported devices (tested with USRP2 only):
#### UHD supported devices (tested with USRP2 only):
```
> gps-sdr-sim-uhd.py -t gpssim.bin -s 2500000 -x 0
```
For LimeSDR (in case of 1 Msps 1-bit file, to get full BaseBand dynamic and low RF power):
#### LimeSDR (in case of 1 Msps 1-bit file, to get full BaseBand dynamic and low RF power):
```
> limeplayer -s 1000000 -b 1 -d 2047 -g 0.1 < ../circle.1b.1M.bin
```
#### ADALM-Pluto (PlutoSDR):
The ADALM-Pluto device is expected to have its network interface up and running and is accessible
via "pluto.local" by default.
Default settings:
```
> plutoplayer -t gpssim.bin
```
Set TX attenuation:
```
> plutoplayer -t gpssim.bin -a -30.0
```
Default -20.0dB. Applicable range 0.0dB to -80.0dB in 0.25dB steps.
Set RF bandwidth:
```
> plutoplayer -t gpssim.bin -b 3.0
```
Default 3.0MHz. Applicable range 1.0MHz to 5.0MHz.
### License
Copyright &copy; 2015 Takuji Ebinuma
Copyright &copy; 2015-2018 Takuji Ebinuma
Distributed under the [MIT License](http://www.opensource.org/licenses/mit-license.php).

View File

@ -1,5 +1,28 @@
CC=gcc -O2 -Wall
DIALECT = -std=c11
CFLAGS += $(DIALECT) -O3 -g -W -Wall
LIBS = -lm
CFLAGS += $(shell pkg-config --cflags libbladeRF)
CFLAGS += $(shell pkg-config --cflags libhackrf)
CFLAGS += $(shell pkg-config --cflags libiio libad9361)
.PHONY: all bladeplayer hackplayer limeplayer plutoplayer clean
all: bladeplayer hackplayer limeplayer plutoplayer
%.o: %.c *.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
bladeplayer: bladeplayer.o $(SDR_OBJ) $(COMPAT)
$(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) $(shell pkg-config --libs libbladeRF)
hackplayer: hackplayer.o $(COMPAT)
$(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) $(shell pkg-config --libs libhackrf)
limeplayer: limeplayer.c
$(CC) -o limeplayer limeplayer.c -lLimeSuite
gcc -O2 -Wall -o limeplayer limeplayer.c -lLimeSuite
plutoplayer: plutoplayer.o $(COMPAT)
$(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) $(shell pkg-config --libs libiio libad9361)
clean:
rm -f *.o bladeplayer hackplayer limeplayer plutoplayer

59
player/README.md Normal file
View File

@ -0,0 +1,59 @@
## How to build the player software on Linux
### bladeRF
#### Build and install libbladeRF
https://github.com/Nuand/bladeRF/wiki/Getting-Started:-Linux
#### Build bladeplayer
```
$ make bladeplayer
```
### HackRF One
#### Build and install libhackrf
https://github.com/mossmann/hackrf/tree/master/host
#### Build hackplayer
```
$ make hackplayer
```
### LimeSDR
#### Build and install libLimeSuite
http://wiki.myriadrf.org/Lime_Suite
#### Build limeplayer
```
$ make limeplayer
```
### ADALM-Pluto
#### Build and install libiio
https://wiki.analog.com/resources/tools-software/linux-software/libiio
#### Build and insatall libad9361
```
$ git clone https://github.com/analogdevicesinc/libad9361-iio.git
$ cd libad9361-iio
$ cmake ./
$ make all
$ sudo make install
```
#### Build plutoplayer
```
$ make plutoplayer
```

View File

@ -7,7 +7,9 @@
#ifdef _WIN32
#include "getopt.h"
#else
#include <getopt.h>
#include <unistd.h>
#include <errno.h>
#endif
#define TX_FREQUENCY 1575420000
@ -49,7 +51,7 @@ int main(int argc, char *argv[])
size_t samples_read;
int16_t lut[256][8];
int16_t amp = AMPLITUDE;
int i,k;
uint32_t i,k;
int gain = TX_VGA1;
int result;

View File

@ -1,22 +1,25 @@
#define _CRT_SECURE_NO_WARNINGS
#include <hackrf.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#ifdef _WIN32
#include <windows.h>
#ifdef _WIN64
typedef int64_t ssize_t;
#else
typedef int32_t ssize_t;
#endif
typedef int bool;
#define true 1
#define false 0
#include "getopt.h"
#else
#include <stdbool.h>
#include <sys/types.h>
#include <getopt.h>
#include <signal.h>
#endif
#include <libhackrf/hackrf.h>
static hackrf_device* device = NULL;
@ -25,11 +28,12 @@ volatile uint32_t byte_count = 0;
volatile bool do_exit = false;
static transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_TX;
//static transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_TX;
#define FD_BUFFER_SIZE (8*1024)
#define FREQ_ONE_MHZ (1000000ull)
#ifdef _WIN32
BOOL WINAPI sighandler(int signum)
{
if(CTRL_C_EVENT == signum) {
@ -39,6 +43,12 @@ BOOL WINAPI sighandler(int signum)
}
return FALSE;
}
#else
static void sighandler(int signum) {
fprintf(stdout, "Caught signal %d\n", signum);
do_exit = true;
}
#endif
int tx_callback(hackrf_transfer* transfer) {
size_t bytes_to_read;
@ -136,7 +146,11 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
#ifdef _WIN32
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
#else
signal(SIGINT, sighandler);
#endif
printf("call hackrf_sample_rate_set(%.03f MHz)\n", ((float)sample_rate_hz/(float)FREQ_ONE_MHZ));
result = hackrf_set_sample_rate_manual(device, sample_rate_hz, 1);

234
player/plutoplayer.c Normal file
View File

@ -0,0 +1,234 @@
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <iio.h>
#include <ad9361.h>
#define NOTUSED(V) ((void) V)
#define MHZ(x) ((long long)(x*1000000.0 + .5))
#define GHZ(x) ((long long)(x*1000000000.0 + .5))
#define NUM_SAMPLES 2600000
#define BUFFER_SIZE (NUM_SAMPLES * 2 * sizeof(int16_t))
struct stream_cfg {
long long bw_hz; // Analog banwidth in Hz
long long fs_hz; // Baseband sample rate in Hz
long long lo_hz; // Local oscillator frequency in Hz
const char* rfport; // Port name
double gain_db; // Hardware gain
};
static void usage() {
fprintf(stderr, "Usage: plutoplayer [options]\n"
" -t <filename> Transmit data from file (required)\n"
" -a <attenuation> Set TX attenuation [dB] (default -20.0)\n"
" -b <bw> Set RF bandwidth [MHz] (default 5.0)\n");
return;
}
static bool stop = false;
static void handle_sig(int sig)
{
NOTUSED(sig);
stop = true;
}
static char* readable_fs(double size, char *buf, size_t buf_size) {
int i = 0;
const char* units[] = {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
while (size > 1024) {
size /= 1024;
i++;
}
snprintf(buf, buf_size, "%.*f %s", i, size, units[i]);
return buf;
}
/*
*
*/
int main(int argc, char** argv) {
char buf[1024];
int opt;
const char* path = NULL;
struct stream_cfg txcfg;
FILE *fp = NULL;
enum state {INIT, READ_FILE, PAD_TRAILING, DONE};
// TX stream default config
txcfg.bw_hz = MHZ(3.0); // 3.0 MHz RF bandwidth
txcfg.fs_hz = MHZ(2.6); // 2.6 MS/s TX sample rate
txcfg.lo_hz = GHZ(1.575420); // 1.57542 GHz RF frequency
txcfg.rfport = "A";
txcfg.gain_db = -20.0;
struct iio_context *ctx = NULL;
struct iio_device *tx = NULL;
struct iio_device *phydev = NULL;
struct iio_channel *tx0_i = NULL;
struct iio_channel *tx0_q = NULL;
struct iio_buffer *tx_buffer = NULL;
while ((opt = getopt(argc, argv, "t:a:b:")) != EOF) {
switch (opt) {
case 't':
path = optarg;
break;
case 'a':
txcfg.gain_db = atof(optarg);
if(txcfg.gain_db > 0.0) txcfg.gain_db = 0.0;
if(txcfg.gain_db < -80.0) txcfg.gain_db = -80.0;
break;
case 'b':
txcfg.bw_hz = MHZ(atof(optarg));
if(txcfg.bw_hz > MHZ(5.0)) txcfg.bw_hz = MHZ(5.0);
if(txcfg.bw_hz < MHZ(1.0)) txcfg.bw_hz = MHZ(1.0);
break;
default:
printf("Unknown argument '-%c %s'\n", opt, optarg);
usage();
return EXIT_FAILURE;
}
}
signal(SIGINT, handle_sig);
if( path == NULL ) {
printf("Specify a path to a file to transmit\n");
usage();
return EXIT_FAILURE;
}
fp = fopen(path, "rb");
if (fp==NULL) {
fprintf(stderr, "ERROR: Failed to open TX file: %s\n", path);
return EXIT_FAILURE;
}
fseek(fp, 0L, SEEK_END);
size_t sz = ftell(fp);
fseek(fp, 0L, SEEK_SET);
readable_fs((double)sz, buf, sizeof(buf));
printf("* Transmit file size: %s\n", buf);
printf("* Acquiring IIO context\n");
ctx = iio_create_default_context();
if (ctx == NULL) {
ctx = iio_create_network_context("pluto.local");
}
if (ctx == NULL) {
iio_strerror(errno, buf, sizeof(buf));
fprintf(stderr, "Failed creating IIO context: %s\n", buf);
return false;
}
struct iio_scan_context *scan_ctx;
struct iio_context_info **info;
scan_ctx = iio_create_scan_context(NULL, 0);
if (scan_ctx) {
int info_count = iio_scan_context_get_info_list(scan_ctx, &info);
if(info_count > 0) {
printf("* Found %s\n", iio_context_info_get_description(info[0]));
iio_context_info_list_free(info);
}
iio_scan_context_destroy(scan_ctx);
}
printf("* Acquiring devices\n");
int device_count = iio_context_get_devices_count(ctx);
if (!device_count) {
fprintf(stderr, "No supported PLUTOSDR devices found.\n");
goto error_exit;
}
fprintf(stderr, "* Context has %d device(s).\n", device_count);
printf("* Acquiring TX device\n");
tx = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc");
if (tx == NULL) {
iio_strerror(errno, buf, sizeof(buf));
fprintf(stderr, "Error opening PLUTOSDR TX device: %s\n", buf);
goto error_exit;
}
iio_device_set_kernel_buffers_count(tx, 8);
phydev = iio_context_find_device(ctx, "ad9361-phy");
struct iio_channel* phy_chn = iio_device_find_channel(phydev, "voltage0", true);
iio_channel_attr_write(phy_chn, "rf_port_select", txcfg.rfport);
iio_channel_attr_write_longlong(phy_chn, "rf_bandwidth", txcfg.bw_hz);
iio_channel_attr_write_longlong(phy_chn, "sampling_frequency", txcfg.fs_hz);
iio_channel_attr_write_double(phy_chn, "hardwaregain", txcfg.gain_db);
iio_channel_attr_write_bool(
iio_device_find_channel(phydev, "altvoltage0", true)
, "powerdown", true); // Turn OFF RX LO
iio_channel_attr_write_longlong(
iio_device_find_channel(phydev, "altvoltage1", true)
, "frequency", txcfg.lo_hz); // Set TX LO frequency
iio_channel_attr_write_longlong(
iio_device_find_channel(phydev, "altvoltage1", true)
, "frequency", txcfg.lo_hz); // Set TX LO frequency
printf("* Initializing streaming channels\n");
tx0_i = iio_device_find_channel(tx, "voltage0", true);
if (!tx0_i)
tx0_i = iio_device_find_channel(tx, "altvoltage0", true);
tx0_q = iio_device_find_channel(tx, "voltage1", true);
if (!tx0_q)
tx0_q = iio_device_find_channel(tx, "altvoltage1", true);
printf("* Enabling IIO streaming channels\n");
iio_channel_enable(tx0_i);
iio_channel_enable(tx0_q);
ad9361_set_bb_rate(iio_context_find_device(ctx, "ad9361-phy"), txcfg.fs_hz);
printf("* Creating TX buffer\n");
tx_buffer = iio_device_create_buffer(tx, NUM_SAMPLES, false);
if (!tx_buffer) {
fprintf(stderr, "Could not create TX buffer.\n");
goto error_exit;
}
iio_channel_attr_write_bool(
iio_device_find_channel(iio_context_find_device(ctx, "ad9361-phy"), "altvoltage1", true)
, "powerdown", false); // Turn ON TX LO
int32_t ntx = 0;
char *ptx_buffer = (char *)iio_buffer_start(tx_buffer);
printf("* Transmit starts...\n");
// Keep writing samples while there is more data to send and no failures have occurred.
while (!feof(fp) && !stop) {
fread(ptx_buffer, 1, BUFFER_SIZE,fp);
// Schedule TX buffer
ntx = iio_buffer_push(tx_buffer);
if (ntx < 0) {
printf("Error pushing buf %d\n", (int) ntx);
goto error_exit;
}
}
printf("Done.\n");
error_exit:
fclose(fp);
iio_channel_attr_write_bool(
iio_device_find_channel(iio_context_find_device(ctx, "ad9361-phy"), "altvoltage1", true)
, "powerdown", true); // Turn OFF TX LO
if (tx_buffer) { iio_buffer_destroy(tx_buffer); }
if (tx0_i) { iio_channel_disable(tx0_i); }
if (tx0_q) { iio_channel_disable(tx0_q); }
if (ctx) { iio_context_destroy(ctx); }
return EXIT_SUCCESS;
}