diff --git a/impl/src/config.h.template b/impl/src/config.h.template index b9ffc23..9a14d56 100644 --- a/impl/src/config.h.template +++ b/impl/src/config.h.template @@ -70,4 +70,14 @@ #define SDR_GAIN_RX_LNA 30.0f // RF variable gain amplifier. #define SDR_GAIN_RX_VGA 24.0f // Baseband variable gain amplifier. +// Offset compensation (these values will be subtracted from all samples). +// These generally depend on the gain settings above and need to be adjusted +// when the gain is changed. + +#define SDR_TX_OFFSET_I 0.000000f +#define SDR_TX_OFFSET_Q 0.000000f + +#define SDR_RX_OFFSET_I 0.000000f +#define SDR_RX_OFFSET_Q 0.000000f + #endif // CONFIG_H diff --git a/impl/src/sdr/sdr_sxceiver.c b/impl/src/sdr/sdr_sxceiver.c index 62beb16..994e963 100644 --- a/impl/src/sdr/sdr_sxceiver.c +++ b/impl/src/sdr/sdr_sxceiver.c @@ -198,7 +198,7 @@ result_t sdr_init(sdr_ctx_t *ctx) // set up and start RX // set gains - if(SoapySDRDevice_setGainElement(ctx->sdr, SOAPY_SDR_RX, 0, "PGA", SDR_GAIN_RX_PGA) != 0) { + /*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; } @@ -206,6 +206,11 @@ result_t sdr_init(sdr_ctx_t *ctx) 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_setGain(ctx->sdr, SOAPY_SDR_RX, 0, SDR_GAIN_RX) != 0) { + LOG(LVL_ERR, "setGain fail: %s", SoapySDRDevice_lastError()); + return ERR_SOAPY; } if(SoapySDRDevice_activateStream(ctx->sdr, ctx->rx_stream, 0, 0, 0) != 0) { @@ -292,15 +297,38 @@ result_t sdr_transmit(sdr_ctx_t *ctx, const float complex *samples, size_t nsamp flags |= SOAPY_SDR_HAS_TIME; } - void *buffs[] = {(void*)(samples)}; + const size_t BLOCK_SIZE = 4096; + float complex tx_block[BLOCK_SIZE]; - int ret = SoapySDRDevice_writeStream(ctx->sdr, ctx->tx_stream, (const void* const*)buffs, nsamples, &flags, time_ns, timeout_us); + size_t samples_transmitted = 0; - if(ret <= 0) { - LOG(LVL_ERR, "writeStream fail: %s", SoapySDRDevice_lastError()); - return ERR_SOAPY; - } else if(ret != nsamples) { - LOG(LVL_WARN, "writeStream() did not transmit all samples: %i/%zu", ret, nsamples); + while(samples_transmitted < nsamples) { + size_t samples_remaining = nsamples - samples_transmitted; + size_t block_samples = BLOCK_SIZE; + + if(samples_remaining < BLOCK_SIZE) { + block_samples = samples_remaining; + } + + const float complex *block_start = samples + samples_transmitted; + for(size_t i = 0; i < block_samples; i++) { + tx_block[i] = block_start[i] - (SDR_TX_OFFSET_I + I * SDR_TX_OFFSET_Q); + } + + void *buffs[] = {(void*)(tx_block)}; + + int64_t block_time = time_ns + samples_transmitted * 1000000000LL / SDR_TX_SAMPLING_RATE; + + int ret = SoapySDRDevice_writeStream(ctx->sdr, ctx->tx_stream, (const void* const*)buffs, block_samples, &flags, block_time, timeout_us); + + if(ret <= 0) { + LOG(LVL_ERR, "writeStream fail: %s", SoapySDRDevice_lastError()); + return ERR_SOAPY; + } else if((size_t)ret != block_samples) { + LOG(LVL_WARN, "writeStream() did not transmit all samples: %i/%zu", ret, block_samples); + } + + samples_transmitted += ret; } return OK; @@ -313,18 +341,41 @@ result_t sdr_receive(sdr_ctx_t *ctx, float complex *samples, size_t *nsamples, l return ERR_INVALID_STATE; } - void *buffs[] = {(void*)samples}; + const size_t BLOCK_SIZE = 4096; + float complex rx_block[BLOCK_SIZE]; - long long timeNs; - int flags; - int ret = SoapySDRDevice_readStream(ctx->sdr, ctx->rx_stream, (void* const*)buffs, *nsamples, &flags, &timeNs, timeout_us); + size_t samples_received = 0; - if(ret <= 0) { - LOG(LVL_ERR, "readStream fail: %s", SoapySDRDevice_lastError()); - return ERR_SOAPY; + while(samples_received < *nsamples) { + size_t samples_remaining = *nsamples - samples_received; + size_t block_samples = BLOCK_SIZE; + + if(samples_remaining < BLOCK_SIZE) { + block_samples = samples_remaining; + } + + void *buffs[] = {(void*)(rx_block)}; + + long long timeNs; + int flags; + int ret = SoapySDRDevice_readStream(ctx->sdr, ctx->rx_stream, (void* const*)buffs, block_samples, &flags, &timeNs, timeout_us); + + if(ret <= 0) { + LOG(LVL_ERR, "readStream fail: %s", SoapySDRDevice_lastError()); + return ERR_SOAPY; + } else if((size_t)ret != *nsamples) { + LOG(LVL_WARN, "readStream() did not receive all requested samples: %i/%zu", ret, block_samples); + } + + float complex *block_start = samples + samples_received; + for(size_t i = 0; i < (size_t)ret; i++) { + block_start[i] = rx_block[i] - (SDR_RX_OFFSET_I + I * SDR_RX_OFFSET_Q); + } + + samples_received += ret; } - *nsamples = ret; + *nsamples = samples_received; return OK; }