mirror of
https://github.com/30hours/blah2.git
synced 2024-11-18 12:33:58 +00:00
Add skeleton for USRP and add include dir
This commit is contained in:
parent
37bdf731d4
commit
27d8994914
6 changed files with 378 additions and 23 deletions
|
@ -8,13 +8,16 @@ include(CMakePrintHelpers)
|
|||
include(CTest)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(asio CONFIG REQUIRED)
|
||||
find_package(asio REQUIRED)
|
||||
find_path(RAPIDJSON_INCLUDE_DIRS "rapidjson/allocators.h")
|
||||
find_package(ryml CONFIG REQUIRED)
|
||||
find_package(httplib CONFIG REQUIRED)
|
||||
find_package(Armadillo CONFIG REQUIRED)
|
||||
find_package(Catch2 CONFIG REQUIRED)
|
||||
|
||||
set(CMAKE_PREFIX_PATH "/opt/uhd" ${CMAKE_PREFIX_PATH})
|
||||
find_package(UHD "4.6.0.0" CONFIG REQUIRED)
|
||||
|
||||
# TODO: when release CI is finished, don't use these dirs, install target should go to prod
|
||||
SET (PROJECT_ROOT "${PROJECT_SOURCE_DIR}")
|
||||
SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_ROOT}/bin")
|
||||
|
@ -27,7 +30,7 @@ MESSAGE ("Binary path: ${PROJECT_BINARY_DIR}")
|
|||
MESSAGE ("Binary test path: ${PROJECT_BINARY_TEST_DIR}")
|
||||
|
||||
# include from top-level src dir
|
||||
include_directories(src)
|
||||
include_directories(src ${UHD_INCLUDE_DIRS})
|
||||
|
||||
# TODO: create FindSdrplay.cmake for this
|
||||
add_library(sdrplay /usr/local/include/sdrplay_api.h)
|
||||
|
@ -38,6 +41,7 @@ add_executable(blah2
|
|||
src/blah2.cpp
|
||||
src/capture/Capture.cpp
|
||||
src/capture/rspduo/RspDuo.cpp
|
||||
src/capture/usrp/Usrp.cpp
|
||||
src/process/ambiguity/Ambiguity.cpp
|
||||
src/process/clutter/WienerHopf.cpp
|
||||
src/process/detection/CfarDetector1D.cpp
|
||||
|
|
64
config/radar4-usrp.yml
Normal file
64
config/radar4-usrp.yml
Normal file
|
@ -0,0 +1,64 @@
|
|||
capture:
|
||||
fs: 2000000
|
||||
fc: 204640000
|
||||
type: "Usrp"
|
||||
replay:
|
||||
state: false
|
||||
loop: true
|
||||
file: '/opt/blah2/replay/file.rspduo'
|
||||
|
||||
process:
|
||||
data:
|
||||
cpi: 0.5
|
||||
buffer: 1.5
|
||||
overlap: 0
|
||||
ambiguity:
|
||||
delayMin: -10
|
||||
delayMax: 400
|
||||
dopplerMin: -200
|
||||
dopplerMax: 200
|
||||
clutter:
|
||||
delayMin: -10
|
||||
delayMax: 400
|
||||
detection:
|
||||
pfa: 0.00001
|
||||
nGuard: 2
|
||||
nTrain: 6
|
||||
minDelay: 5
|
||||
minDoppler: 15
|
||||
nCentroid: 6
|
||||
tracker:
|
||||
initiate:
|
||||
M: 3
|
||||
N: 5
|
||||
maxAcc: 10
|
||||
delete: 10
|
||||
smooth: "none"
|
||||
|
||||
network:
|
||||
ip: 0.0.0.0
|
||||
ports:
|
||||
api: 3000
|
||||
map: 3001
|
||||
detection: 3002
|
||||
track: 3003
|
||||
timestamp: 4000
|
||||
timing: 4001
|
||||
iqdata: 4002
|
||||
|
||||
truth:
|
||||
asdb:
|
||||
enabled: false
|
||||
ip: 0.0.0.0
|
||||
port: 30000
|
||||
ais:
|
||||
enabled: false
|
||||
ip: 0.0.0.0
|
||||
port: 30001
|
||||
|
||||
save:
|
||||
iq: true
|
||||
map: false
|
||||
detection: false
|
||||
timing: false
|
||||
path: "/blah2/save/"
|
|
@ -1,11 +1,12 @@
|
|||
#include "Capture.h"
|
||||
#include "rspduo/RspDuo.h"
|
||||
#include "usrp/Usrp.h"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <httplib.h>
|
||||
|
||||
// constants
|
||||
const std::string Capture::VALID_TYPE[2] = {"RspDuo", "HackRF"};
|
||||
const std::string Capture::VALID_TYPE[2] = {"RspDuo", "Usrp"};
|
||||
|
||||
// constructor
|
||||
Capture::Capture(std::string _type, uint32_t _fs, uint32_t _fc, std::string _path)
|
||||
|
@ -19,11 +20,22 @@ Capture::Capture(std::string _type, uint32_t _fs, uint32_t _fc, std::string _pat
|
|||
|
||||
void Capture::process(IqData *buffer1, IqData *buffer2)
|
||||
{
|
||||
// case RspDuo
|
||||
if (type == Capture::VALID_TYPE[0])
|
||||
if (is_type_valid(type))
|
||||
{
|
||||
std::cout << "Setting up device " + type << std::endl;
|
||||
RspDuo *rspDuo = new RspDuo(this->fc, this->path);
|
||||
|
||||
// RspDuo device
|
||||
if (type == VALID_TYPE[0])
|
||||
{
|
||||
RspDuo *device = new RspDuo(this->fc, this->path);
|
||||
}
|
||||
|
||||
// Usrp device
|
||||
if (type == VALID_TYPE[1])
|
||||
{
|
||||
//Usrp *device = new Usrp(this->fc, this->path);
|
||||
}
|
||||
Usrp *device = new Usrp(this->fc, this->path);
|
||||
|
||||
// capture status thread
|
||||
std::thread t1([&]{
|
||||
|
@ -33,16 +45,16 @@ void Capture::process(IqData *buffer1, IqData *buffer2)
|
|||
httplib::Result res = cli.Get("/capture");
|
||||
|
||||
// if capture status changed
|
||||
if ((res->body == "true") != rspDuo->get_capture())
|
||||
if ((res->body == "true") != device->get_capture())
|
||||
{
|
||||
rspDuo->set_capture(res->body == "true");
|
||||
if (rspDuo->get_capture())
|
||||
device->set_capture(res->body == "true");
|
||||
if (device->get_capture())
|
||||
{
|
||||
rspDuo->open_file();
|
||||
device->open_file();
|
||||
}
|
||||
else
|
||||
{
|
||||
rspDuo->close_file();
|
||||
device->close_file();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,23 +64,14 @@ void Capture::process(IqData *buffer1, IqData *buffer2)
|
|||
|
||||
if (!replay)
|
||||
{
|
||||
rspDuo->start();
|
||||
rspDuo->process(buffer1, buffer2);
|
||||
device->start();
|
||||
device->process(buffer1, buffer2);
|
||||
}
|
||||
else
|
||||
{
|
||||
rspDuo->replay(buffer1, buffer2, file, loop);
|
||||
device->replay(buffer1, buffer2, file, loop);
|
||||
}
|
||||
}
|
||||
// case HackRF
|
||||
else if (type == Capture::VALID_TYPE[1])
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error: Invalid capture device" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void Capture::set_replay(bool _loop, std::string _file)
|
||||
|
@ -76,4 +79,19 @@ void Capture::set_replay(bool _loop, std::string _file)
|
|||
replay = true;
|
||||
loop = _loop;
|
||||
file = _file;
|
||||
}
|
||||
|
||||
bool Capture::is_type_valid(std::string _type)
|
||||
{
|
||||
size_t n = sizeof(Capture::VALID_TYPE) /
|
||||
sizeof(Capture::VALID_TYPE[0]);
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
if (_type == Capture::VALID_TYPE[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
std::cerr << "Invalid capture device: " << _type << std::endl;
|
||||
return false;
|
||||
}
|
|
@ -59,6 +59,11 @@ public:
|
|||
/// @param file Absolute path of file to replay.
|
||||
/// @return Void.
|
||||
void set_replay(bool loop, std::string file);
|
||||
|
||||
/// @brief Check if capture device type is valid.
|
||||
/// @param type The capture device type.
|
||||
/// @return True is capture device type is valid.
|
||||
bool is_type_valid(std::string type);
|
||||
};
|
||||
|
||||
#endif
|
181
src/capture/usrp/Usrp.cpp
Normal file
181
src/capture/usrp/Usrp.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
#include "Usrp.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <uhd/usrp/multi_usrp.hpp>
|
||||
#include <complex>
|
||||
|
||||
// constructor
|
||||
Usrp::Usrp(uint32_t _fc, std::string _path)
|
||||
{
|
||||
fc = _fc;
|
||||
path = _path;
|
||||
capture = false;
|
||||
}
|
||||
|
||||
std::string Usrp::set_file(std::string path)
|
||||
{
|
||||
char buffer[15];
|
||||
gettimeofday(&start_tm, NULL);
|
||||
strftime(buffer, 16, "%Y%m%d-%H%M%S", localtime(&start_tm.tv_sec));
|
||||
return path + buffer + ".usrp";
|
||||
}
|
||||
|
||||
void Usrp::start()
|
||||
{
|
||||
}
|
||||
|
||||
void Usrp::stop()
|
||||
{
|
||||
}
|
||||
|
||||
void Usrp::process(IqData *buffer1, IqData *buffer2)
|
||||
{
|
||||
// create a USRP object
|
||||
uhd::usrp::multi_usrp::sptr usrp =
|
||||
uhd::usrp::multi_usrp::make("localhost");
|
||||
|
||||
// Set the sample rate
|
||||
double sampleRate = 2e6; // Replace with your desired sample rate
|
||||
usrp->set_rx_rate(sampleRate);
|
||||
|
||||
// Set the center frequency
|
||||
double centerFrequency = (double)fc;
|
||||
usrp->set_rx_freq(centerFrequency);
|
||||
|
||||
// Set the gain
|
||||
double gain = 20.0; // Replace with your desired gain
|
||||
usrp->set_rx_gain(gain);
|
||||
|
||||
// Set the number of channels
|
||||
size_t numChannels = 1; // Assuming one channel for simplicity
|
||||
usrp->set_rx_antenna("RX2", 0); // Set antenna for channel 0
|
||||
|
||||
// Set the receive buffer size
|
||||
size_t bufferSize = 1024 * numChannels;
|
||||
std::vector<std::complex<float>> buffer(bufferSize);
|
||||
|
||||
// Create a receive streamer
|
||||
uhd::stream_args_t streamArgs("fc32", "sc16");
|
||||
uhd::rx_streamer::sptr rxStreamer = usrp->get_rx_stream(streamArgs);
|
||||
|
||||
// Setup streaming
|
||||
uhd::rx_metadata_t metadata;
|
||||
rxStreamer->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
|
||||
|
||||
while(true)
|
||||
{
|
||||
// Receive samples
|
||||
size_t numReceived = rxStreamer->recv(&buffer[0], buffer.size(), metadata);
|
||||
|
||||
// Stop streaming
|
||||
// rxStreamer->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
|
||||
|
||||
// Check for errors
|
||||
if (metadata.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) {
|
||||
std::cerr << "Error during reception: " << metadata.strerror() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy received samples to the output buffer
|
||||
//iqBuffer.resize(numReceived);
|
||||
//std::copy(buffer.begin(), buffer.begin() + numReceived, iqBuffer.begin());
|
||||
buffer1->lock();
|
||||
buffer2->lock();
|
||||
for (size_t i = 0; i < buffer.size(); i++)
|
||||
{
|
||||
buffer1->push_back({(double)buffer[i][0], (double)buffer[i][1]})
|
||||
}
|
||||
buffer1->unlock();
|
||||
buffer2->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void Usrp::replay(IqData *_buffer1, IqData *_buffer2, std::string _file, bool _loop)
|
||||
{
|
||||
buffer1 = _buffer1;
|
||||
buffer2 = _buffer2;
|
||||
|
||||
short i1, q1, i2, q2;
|
||||
int rv;
|
||||
file_replay = fopen(_file.c_str(), "rb");
|
||||
|
||||
while (true)
|
||||
{
|
||||
rv = fread(&i1, 1, sizeof(short), file_replay);
|
||||
rv = fread(&q1, 1, sizeof(short), file_replay);
|
||||
rv = fread(&i2, 1, sizeof(short), file_replay);
|
||||
rv = fread(&q2, 1, sizeof(short), file_replay);
|
||||
|
||||
buffer1->lock();
|
||||
buffer2->lock();
|
||||
|
||||
if (buffer1->get_length() < buffer1->get_n())
|
||||
{
|
||||
buffer1->push_back({(double)i1, (double)q1});
|
||||
buffer2->push_back({(double)i2, (double)q2});
|
||||
}
|
||||
|
||||
buffer1->unlock();
|
||||
buffer2->unlock();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Usrp::open_file()
|
||||
{
|
||||
file = set_file(path);
|
||||
|
||||
char time_tx[BUFFER_SIZE_NR];
|
||||
|
||||
// get start date and time
|
||||
gettimeofday(&start_tm, NULL);
|
||||
strftime(time_tx, sizeof(time_tx), "%d %b %Y %H:%M:%S", localtime(&start_tm.tv_sec));
|
||||
fprintf(stderr, "Info - start - start_tm: %s.%03ld\n", time_tx, start_tm.tv_usec / 1000);
|
||||
|
||||
//validate();
|
||||
|
||||
// open files
|
||||
if (chunk_time_nr == 0)
|
||||
{
|
||||
out_file_fp = fopen(file.c_str(), "wb");
|
||||
|
||||
if (out_file_fp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error - start - opening output file %s\n", file.c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Info - start - output file %s\n", file.c_str());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Usrp::close_file()
|
||||
{
|
||||
if (out_file_fp != NULL)
|
||||
{
|
||||
fclose(out_file_fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Usrp::set_capture(bool _capture)
|
||||
{
|
||||
capture = _capture;
|
||||
}
|
||||
|
||||
bool Usrp::get_capture()
|
||||
{
|
||||
return capture;
|
||||
}
|
83
src/capture/usrp/Usrp.h
Normal file
83
src/capture/usrp/Usrp.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/// @file Usrp.h
|
||||
/// @class Usrp
|
||||
/// @brief A class to capture data on the Ettus Research USRP.
|
||||
/// @details Uses the UHD C API to extract samples into the processing chain.
|
||||
///
|
||||
/// Should work on all USRP models EXCEPT discontinued (USRP1, USRP2).
|
||||
/// Networked models require an IP address in the config file.
|
||||
///
|
||||
/// @author 30hours
|
||||
|
||||
#ifndef USRP_H
|
||||
#define USRP_H
|
||||
|
||||
#include "data/IqData.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#define BUFFER_SIZE_NR 1024
|
||||
|
||||
class Usrp
|
||||
{
|
||||
private:
|
||||
/// @brief Center frequency (Hz)
|
||||
uint32_t fc;
|
||||
|
||||
/// @brief File path.
|
||||
std::string path;
|
||||
/// @brief True if capture is enabled.
|
||||
bool capture;
|
||||
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
/// @param fc Center frequency (Hz).
|
||||
/// @param path Path to save IQ data.
|
||||
/// @return The object.
|
||||
Usrp(uint32_t fc, std::string path);
|
||||
|
||||
/// @brief Get file name from path.
|
||||
/// @return String of file name based on current time.
|
||||
std::string set_file(std::string path);
|
||||
|
||||
/// @brief Call methods to start capture.
|
||||
/// @return Void.
|
||||
void start();
|
||||
|
||||
/// @brief Call methods to gracefully stop capture.
|
||||
/// @return Void.
|
||||
void stop();
|
||||
|
||||
/// @brief Implement capture function on RSPduo.
|
||||
/// @param buffer1 Pointer to reference buffer.
|
||||
/// @param buffer2 Pointer to surveillance buffer.
|
||||
/// @return Void.
|
||||
void process(IqData *buffer1, IqData *buffer2);
|
||||
|
||||
/// @brief Implement replay function on RSPduo.
|
||||
/// @param buffer1 Pointer to reference buffer.
|
||||
/// @param buffer2 Pointer to surveillance buffer.
|
||||
/// @param file Path to file to replay data from.
|
||||
/// @param loop True if samples should loop at EOF.
|
||||
/// @return Void.
|
||||
void replay(IqData *buffer1, IqData *buffer2, std::string file, bool loop);
|
||||
|
||||
/// @brief Open a new file to record IQ.
|
||||
/// @return Void.
|
||||
void open_file();
|
||||
|
||||
/// @brief Close IQ file gracefully.
|
||||
/// @return Void.
|
||||
void close_file();
|
||||
|
||||
/// @brief Setter for capture.
|
||||
/// @param capture True if capture is enabled.
|
||||
/// @return Void.
|
||||
void set_capture(bool capture);
|
||||
|
||||
/// @brief Getter for capture.
|
||||
/// @return True if capture is true.
|
||||
bool get_capture();
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue