sdr_sxceiver: add DC offset correction support
The samples are now split into blocks. The offset is corrected on each block before it is given to SoapySX for transmission or corrected after reception of a block from SoapySX. This ensures there are no huge spikes in CPU usage and therefore delays when a lot of samples should be transferred at once.
This commit is contained in:
parent
42e0b319b7
commit
052f5d4612
2 changed files with 77 additions and 16 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue