Skip to content

Commit

Permalink
Merge pull request #26 from IQTLabs/sf
Browse files Browse the repository at this point in the history
write sigmf file.
  • Loading branch information
anarkiwi authored Apr 3, 2024
2 parents 42e8c7f + 96b1745 commit dd8439f
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 8 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@

build/
sigpack*
json.hpp
flatbuffers
json
libsigmf
VkFFT
SPIRV-Tools
*~
Expand Down
4 changes: 3 additions & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.16)
project(uhd_sample_recorder)
set(CMAKE_BUILD_TYPE Release)
set(SRC_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/..")
set(CMAKE_CXX_STANDARD 20)
include(FindPkgConfig)
include(CTest)

Expand All @@ -11,6 +12,7 @@ find_package(Vulkan REQUIRED)
find_package(Armadillo REQUIRED)
find_package(UHD 3.15.0 REQUIRED)
find_package(nlohmann_json 3.11.2 REQUIRED)
find_package(libsigmf REQUIRED)

find_package(
Boost ${Boost_Version}
Expand Down Expand Up @@ -51,4 +53,4 @@ add_test(NAME sample_pipeline_test COMMAND sample_pipeline_test)

add_executable(uhd_sample_recorder uhd_sample_recorder.cpp)
target_link_libraries(uhd_sample_recorder sample_pipeline sample_writer
${Boost_LIBRARIES} ${UHD_LIBRARIES})
${Boost_LIBRARIES} ${UHD_LIBRARIES} libsigmf::libsigmf)
6 changes: 5 additions & 1 deletion lib/sample_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,15 @@ void sample_pipeline_start(const std::string &file, const std::string &fft_file,
writer_threads->add_thread(new boost::thread(fft_out_worker));
}

void sample_pipeline_stop(size_t overflows) {
void sample_pipeline_stop(size_t overflows, const std::string &file,
size_t rate, size_t freq, double timestamp,
double gain, const std::string &sigmf_format) {
samples_input_done = true;
writer_threads->join_all();
sample_writer->close(overflows);
fft_sample_writer->close(overflows);
sample_writer->write_sigmf(file + ".sigmf-meta", timestamp, sigmf_format,
rate, freq, gain);
if (useVkFFT) {
free_vkfft();
}
Expand Down
4 changes: 3 additions & 1 deletion lib/sample_pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ void sample_pipeline_start(const std::string &file, const std::string &fft_file,
size_t nfft_ds_, size_t rate, size_t batches,
size_t sample_id);
size_t get_samp_size();
void sample_pipeline_stop(size_t overflows);
void sample_pipeline_stop(size_t overflows, const std::string &file,
size_t rate, size_t freq, double timestamp,
double gain, const std::string &sigmf_format);
void set_sample_pipeline_types(const std::string &type,
std::string &cpu_format);
4 changes: 2 additions & 2 deletions lib/sample_pipeline_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ BOOST_AUTO_TEST_CASE(SmokeTest) {
set_sample_pipeline_types("short", cpu_format);
BOOST_TEST(cpu_format == "sc16");
sample_pipeline_start("", "", 1e6, 1, false, 0, 0, 1, 1, 1e6, 0, 0);
sample_pipeline_stop(0);
sample_pipeline_stop(0, "", 1e6, 1e6, 1.1, -1, "ci16_le");
}

BOOST_AUTO_TEST_CASE(RandomFFTTest) {
Expand All @@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(RandomFFTTest) {
memcpy(buffer_p, samples.memptr(),
samples.size() * sizeof(std::complex<float>));
enqueue_samples(write_ptr);
sample_pipeline_stop(0);
sample_pipeline_stop(0, file, 1e3 * 1024, 100e6, 1.1, -1, "cf32_le");
arma::Col<std::complex<float>> disk_samples;
disk_samples.copy_size(samples);
FILE *samples_fp = fopen(file.c_str(), "rb");
Expand Down
31 changes: 31 additions & 0 deletions lib/sample_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filter/zstd.hpp>
#include <iostream>
#include <sigmf/sigmf.h>

std::string get_prefix_file(const std::string &file,
const std::string &prefix) {
Expand Down Expand Up @@ -63,3 +64,33 @@ void SampleWriter::close(size_t overflows) {
}
}
}

void SampleWriter::write_sigmf(const std::string &filename, double timestamp,
const std::string &datatype, double sample_rate,
double frequency, double gain) {
sigmf::SigMF<
sigmf::Global<sigmf::core::DescrT>,
sigmf::Capture<sigmf::core::DescrT, sigmf::capture_details::DescrT>,
sigmf::Annotation<sigmf::core::DescrT>>
record;
record.global.access<sigmf::core::GlobalT>().datatype = datatype;
record.global.access<sigmf::core::GlobalT>().sample_rate = sample_rate;
auto capture =
sigmf::Capture<sigmf::core::DescrT, sigmf::capture_details::DescrT>();
capture.get<sigmf::core::DescrT>().sample_start = 0;
capture.get<sigmf::core::DescrT>().global_index = 0;
capture.get<sigmf::core::DescrT>().frequency = frequency;
std::ostringstream ts_ss;
time_t timestamp_t = static_cast<time_t>(timestamp);
ts_ss << std::put_time(gmtime(&timestamp_t), "%FT%TZ");
capture.get<sigmf::core::DescrT>().datetime = ts_ss.str();
capture.get<sigmf::capture_details::DescrT>().source_file =
basename(file_.c_str());
capture.get<sigmf::capture_details::DescrT>().gain = gain;
record.captures.emplace_back(capture);
std::string dotfilename = get_dotfile(filename);
std::ofstream jsonfile(dotfilename);
jsonfile << record.to_json();
jsonfile.close();
rename(dotfilename.c_str(), filename.c_str());
}
3 changes: 3 additions & 0 deletions lib/sample_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class SampleWriter {
void open(const std::string &file, size_t zlevel);
void close(size_t overflows);
void write(const char *data, size_t len);
void write_sigmf(const std::string &filename, double timestamp,
const std::string &datatype, double sample_rate,
double frequency, double gain);

private:
boost::scoped_ptr<boost::iostreams::filtering_ostream> outbuf_p;
Expand Down
16 changes: 14 additions & 2 deletions lib/uhd_sample_recorder.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <bit>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/program_options.hpp>
#include <chrono>
Expand Down Expand Up @@ -176,6 +177,11 @@ void sample_record(uhd::usrp::multi_usrp::sptr usrp, const std::string &type,
std::cerr << "max_samps_per_packet from stream: " << max_samps_per_packet
<< std::endl;

const std::string endian_str =
std::endian::native == std::endian::little ? "_le" : "_be";
const std::string sigmf_format =
type == "short" ? "ci16" + endian_str : "cf32" + endian_str;

if (nfft) {
std::cerr << "using FFT point size " << nfft << std::endl;

Expand All @@ -200,10 +206,16 @@ void sample_record(uhd::usrp::multi_usrp::sptr usrp, const std::string &type,
bool overflows =
run_stream(rx_stream, time_requested, max_samples, num_requested_samples);

double timestamp =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())
.count() /
1e3;
stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
rx_stream->issue_stream_cmd(stream_cmd);
std::cerr << "stream stopped" << std::endl;
sample_pipeline_stop(overflows);
sample_pipeline_stop(overflows, file, rate, freq, timestamp, gain,
sigmf_format);
std::cerr << "pipeline stopped" << std::endl;
}

Expand All @@ -216,7 +228,7 @@ int parse_args(int argc, char *argv[]) {
"file", po::value<std::string>(&file)->default_value(""),
"name of the file to write binary samples to")(
"type", po::value<std::string>(&type)->default_value("short"),
"sample type: double, float, or short")(
"sample type: float, or short")(
"nsamps", po::value<size_t>(&total_num_samps)->default_value(0),
"total number of samples to receive")(
"duration", po::value<double>(&total_time)->default_value(0),
Expand Down

0 comments on commit dd8439f

Please sign in to comment.