sdr/sx: implement timed transmission
This commit is contained in:
parent
5aa9eeb18b
commit
a520b3232d
|
@ -50,6 +50,8 @@
|
||||||
static int m_tunfd = -1;
|
static int m_tunfd = -1;
|
||||||
static bool m_running = true;
|
static bool m_running = true;
|
||||||
|
|
||||||
|
static double m_tstart = 0.0;
|
||||||
|
|
||||||
static double next_tx_switch_time = 0.0;
|
static double next_tx_switch_time = 0.0;
|
||||||
|
|
||||||
static rx_stats_t m_rx_stats;
|
static rx_stats_t m_rx_stats;
|
||||||
|
@ -149,7 +151,8 @@ void cb_rx(rx_evt_t evt, const struct layer1_rx_s *rx, uint8_t *packet_data, siz
|
||||||
|
|
||||||
static result_t transmit(sdr_ctx_t *sdr, const float complex *samples, size_t len)
|
static result_t transmit(sdr_ctx_t *sdr, const float complex *samples, size_t len)
|
||||||
{
|
{
|
||||||
result_t result = sdr_transmit(sdr, samples, len, 100000);
|
int64_t tx_time_ns = (int64_t)((get_hires_time() - m_tstart + 0.1) * 1e9);
|
||||||
|
result_t result = sdr_transmit(sdr, samples, len, tx_time_ns, 100000);
|
||||||
|
|
||||||
fprintf(stderr, "t");
|
fprintf(stderr, "t");
|
||||||
return result;
|
return result;
|
||||||
|
@ -223,10 +226,11 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
// start in TX mode to work around SoapyHackRF not setting the correct frequency.
|
// start in TX mode to work around SoapyHackRF not setting the correct frequency.
|
||||||
RESULT_CHECK(sdr_start_tx(&sdr, 1));
|
RESULT_CHECK(sdr_start_tx(&sdr, 1));
|
||||||
|
m_tstart = get_hires_time();
|
||||||
|
|
||||||
unsigned rx_retries = 0;
|
unsigned rx_retries = 0;
|
||||||
|
|
||||||
double old = get_hires_time();
|
double old = m_tstart;
|
||||||
size_t total_samples = 0;
|
size_t total_samples = 0;
|
||||||
double next_stats_print_time = old + 0.5;
|
double next_stats_print_time = old + 0.5;
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,43 @@
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "results.h"
|
||||||
|
|
||||||
#include "sdr_sxceiver.h"
|
#include "sdr_sxceiver.h"
|
||||||
|
|
||||||
void soapy_log_handler(const SoapySDRLogLevel logLevel, const char *message)
|
void soapy_log_handler(const SoapySDRLogLevel logLevel, const char *message)
|
||||||
{
|
{
|
||||||
LOG(LVL_ERR, "soapy [%d]: %s", logLevel, message);
|
int level;
|
||||||
|
|
||||||
|
switch(logLevel) {
|
||||||
|
case SOAPY_SDR_CRITICAL:
|
||||||
|
case SOAPY_SDR_FATAL:
|
||||||
|
level = LVL_FATAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOAPY_SDR_ERROR:
|
||||||
|
level = LVL_ERR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOAPY_SDR_WARNING:
|
||||||
|
level = LVL_WARN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOAPY_SDR_INFO:
|
||||||
|
level = LVL_INFO;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOAPY_SDR_DEBUG:
|
||||||
|
level = LVL_DEBUG;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
level = LVL_DUMP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(level, "soapy [%d]: %s", logLevel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_streams(sdr_ctx_t *ctx)
|
static void close_streams(sdr_ctx_t *ctx)
|
||||||
|
@ -49,6 +80,7 @@ result_t sdr_init(sdr_ctx_t *ctx)
|
||||||
|
|
||||||
// set up logging
|
// set up logging
|
||||||
SoapySDR_registerLogHandler(soapy_log_handler);
|
SoapySDR_registerLogHandler(soapy_log_handler);
|
||||||
|
//SoapySDR_setLogLevel(SOAPY_SDR_DEBUG);
|
||||||
|
|
||||||
//enumerate devices
|
//enumerate devices
|
||||||
SoapySDRKwargs *results = SoapySDRDevice_enumerate(NULL, &length);
|
SoapySDRKwargs *results = SoapySDRDevice_enumerate(NULL, &length);
|
||||||
|
@ -155,6 +187,55 @@ result_t sdr_init(sdr_ctx_t *ctx)
|
||||||
return ERR_SOAPY;
|
return ERR_SOAPY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// PA always on
|
||||||
|
if (SoapySDRDevice_writeSetting(ctx->sdr, "PA", "ON") != 0) {
|
||||||
|
LOG(LVL_ERR, "writeSetting fail: %s", SoapySDRDevice_lastError());
|
||||||
|
return ERR_SOAPY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// set up and start RX
|
||||||
|
|
||||||
|
// set gains
|
||||||
|
if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_RX, 0, "PGA", SDR_GAIN_RX_PGA) != 0) {
|
||||||
|
LOG(LVL_ERR, "setGainElement fail: %s", SoapySDRDevice_lastError());
|
||||||
|
return ERR_SOAPY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_RX, 0, "LNA", SDR_GAIN_RX_LNA) != 0) {
|
||||||
|
LOG(LVL_ERR, "setGainElement fail: %s", SoapySDRDevice_lastError());
|
||||||
|
return ERR_SOAPY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SoapySDRDevice_activateStream(ctx->sdr, ctx->rx_stream, 0, 0, 0) != 0) {
|
||||||
|
LOG(LVL_ERR, "activateStream fail: %s", SoapySDRDevice_lastError());
|
||||||
|
return ERR_SOAPY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up and start TX
|
||||||
|
|
||||||
|
// set gain
|
||||||
|
/*if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_TX, 0, "DAC", SDR_GAIN_TX_DAC) != 0) {
|
||||||
|
LOG(LVL_ERR, "setGainElement fail: %s", SoapySDRDevice_lastError());
|
||||||
|
return ERR_SOAPY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_TX, 0, "MIXER", SDR_GAIN_TX_MIXER) != 0) {
|
||||||
|
LOG(LVL_ERR, "setGainElement fail: %s", SoapySDRDevice_lastError());
|
||||||
|
return ERR_SOAPY;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if(SoapySDRDevice_setGain(ctx->sdr, SOAPY_SDR_TX, 0, SDR_GAIN_TX) != 0) {
|
||||||
|
LOG(LVL_ERR, "setGain fail: %s", SoapySDRDevice_lastError());
|
||||||
|
return ERR_SOAPY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SoapySDRDevice_activateStream(ctx->sdr, ctx->tx_stream, 0, 0, 0) != 0) {
|
||||||
|
LOG(LVL_ERR, "activateStream fail: %s", SoapySDRDevice_lastError());
|
||||||
|
return ERR_SOAPY;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,21 +257,6 @@ result_t sdr_destroy(sdr_ctx_t *ctx)
|
||||||
|
|
||||||
result_t sdr_start_rx(sdr_ctx_t *ctx)
|
result_t sdr_start_rx(sdr_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
// set gains
|
|
||||||
if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_RX, 0, "PGA", SDR_GAIN_RX_PGA) != 0) {
|
|
||||||
LOG(LVL_ERR, "setGainElement fail: %s", SoapySDRDevice_lastError());
|
|
||||||
return ERR_SOAPY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_RX, 0, "LNA", SDR_GAIN_RX_LNA) != 0) {
|
|
||||||
LOG(LVL_ERR, "setGainElement fail: %s", SoapySDRDevice_lastError());
|
|
||||||
return ERR_SOAPY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SoapySDRDevice_activateStream(ctx->sdr, ctx->rx_stream, 0, 0, 0) != 0) {
|
|
||||||
LOG(LVL_ERR, "activateStream fail: %s", SoapySDRDevice_lastError());
|
|
||||||
return ERR_SOAPY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -198,21 +264,6 @@ result_t sdr_start_rx(sdr_ctx_t *ctx)
|
||||||
|
|
||||||
result_t sdr_start_tx(sdr_ctx_t *ctx, size_t burst_size)
|
result_t sdr_start_tx(sdr_ctx_t *ctx, size_t burst_size)
|
||||||
{
|
{
|
||||||
// set gain
|
|
||||||
if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_TX, 0, "DAC", SDR_GAIN_TX_DAC) != 0) {
|
|
||||||
LOG(LVL_ERR, "setGainElement fail: %s", SoapySDRDevice_lastError());
|
|
||||||
return ERR_SOAPY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_TX, 0, "MIXER", SDR_GAIN_TX_MIXER) != 0) {
|
|
||||||
LOG(LVL_ERR, "setGainElement fail: %s", SoapySDRDevice_lastError());
|
|
||||||
return ERR_SOAPY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SoapySDRDevice_activateStream(ctx->sdr, ctx->tx_stream, 0, 0, burst_size) != 0) {
|
|
||||||
LOG(LVL_ERR, "activateStream fail: %s", SoapySDRDevice_lastError());
|
|
||||||
return ERR_SOAPY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -220,40 +271,36 @@ result_t sdr_start_tx(sdr_ctx_t *ctx, size_t burst_size)
|
||||||
|
|
||||||
result_t sdr_stop_rx(sdr_ctx_t *ctx)
|
result_t sdr_stop_rx(sdr_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
if(SoapySDRDevice_deactivateStream(ctx->sdr, ctx->rx_stream, 0, 0) != 0) {
|
|
||||||
LOG(LVL_ERR, "activateStream fail: %s", SoapySDRDevice_lastError());
|
|
||||||
return ERR_SOAPY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result_t sdr_stop_tx(sdr_ctx_t *ctx)
|
result_t sdr_stop_tx(sdr_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
if(SoapySDRDevice_deactivateStream(ctx->sdr, ctx->tx_stream, 0, 0) != 0) {
|
|
||||||
LOG(LVL_ERR, "activateStream fail: %s", SoapySDRDevice_lastError());
|
|
||||||
return ERR_SOAPY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result_t sdr_transmit(sdr_ctx_t *ctx, const float complex *samples, size_t nsamples, long timeout_us)
|
result_t sdr_transmit(sdr_ctx_t *ctx, const float complex *samples, size_t nsamples, int64_t time_ns, long timeout_us)
|
||||||
{
|
{
|
||||||
if(ctx->tx_stream == NULL) {
|
if(ctx->tx_stream == NULL) {
|
||||||
return ERR_INVALID_STATE;
|
return ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *buffs[] = {(void*)samples};
|
|
||||||
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
int ret = SoapySDRDevice_writeStream(ctx->sdr, ctx->tx_stream, (const void* const*)buffs, nsamples, &flags, 0, timeout_us);
|
if(time_ns != 0) {
|
||||||
|
flags |= SOAPY_SDR_HAS_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *buffs[] = {(void*)(samples)};
|
||||||
|
|
||||||
|
int ret = SoapySDRDevice_writeStream(ctx->sdr, ctx->tx_stream, (const void* const*)buffs, nsamples, &flags, time_ns, timeout_us);
|
||||||
|
|
||||||
if(ret <= 0) {
|
if(ret <= 0) {
|
||||||
LOG(LVL_ERR, "writeStream fail: %s", SoapySDRDevice_lastError());
|
LOG(LVL_ERR, "writeStream fail: %s", SoapySDRDevice_lastError());
|
||||||
return ERR_SOAPY;
|
return ERR_SOAPY;
|
||||||
|
} else if(ret != nsamples) {
|
||||||
|
LOG(LVL_WARN, "writeStream() did not transmit all samples: %i/%zu", ret, nsamples);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -28,7 +28,7 @@ result_t sdr_start_tx(sdr_ctx_t *ctx, size_t burst_size);
|
||||||
result_t sdr_stop_rx(sdr_ctx_t *ctx);
|
result_t sdr_stop_rx(sdr_ctx_t *ctx);
|
||||||
result_t sdr_stop_tx(sdr_ctx_t *ctx);
|
result_t sdr_stop_tx(sdr_ctx_t *ctx);
|
||||||
|
|
||||||
result_t sdr_transmit(sdr_ctx_t *ctx, const float complex *samples, size_t nsamples, long timeout_us);
|
result_t sdr_transmit(sdr_ctx_t *ctx, const float complex *samples, size_t nsamples, int64_t time_ns, long timeout_us);
|
||||||
result_t sdr_receive(sdr_ctx_t *ctx, float complex *samples, size_t *nsamples, long timeout_us);
|
result_t sdr_receive(sdr_ctx_t *ctx, float complex *samples, size_t *nsamples, long timeout_us);
|
||||||
|
|
||||||
#endif // SDR_SDR_H
|
#endif // SDR_SDR_H
|
||||||
|
|
Loading…
Reference in a new issue