Transceiver52M: Setup dual sample rate transceiver
This patch applies oversampling, when selected with 4 sps,
to the downlink only, while running the receiver with
minimal sampling at 1 sps. These split sample rates allow
us to run a highly accurate downlink signal with minimal
distortion, while keeping receive path channel filtering
on the FPGA.
Without this patch, we oversample the receive path and
require a steep receive filter to get similar adjacent
channel suppression as the FPGA halfband / CIC filter
combination, which comes with a high computational cost.
Signed-off-by: Thomas Tsou <tom@tsou.cc>
diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp
index f39a470..e9fcd49 100644
--- a/Transceiver52M/radioInterface.cpp
+++ b/Transceiver52M/radioInterface.cpp
@@ -23,13 +23,15 @@
*/
#include "radioInterface.h"
+#include "Resampler.h"
#include <Logger.h>
extern "C" {
#include "convert.h"
}
-bool started = false;
+#define INCHUNK (625 * SAMPSPERSYM)
+#define OUTCHUNK (625 * SAMPSPERSYM)
RadioInterface::RadioInterface(RadioDevice *wRadio,
int wReceiveOffset,
@@ -37,7 +39,7 @@
GSM::Time wStartTime)
: underrun(false), sendCursor(0), recvCursor(0), mOn(false),
mRadio(wRadio), receiveOffset(wReceiveOffset),
- sps(wSPS), powerScaling(1.0),
+ mSPSTx(wSPS), mSPSRx(1), powerScaling(1.0),
loadTest(false), sendBuffer(NULL), recvBuffer(NULL),
convertRecvBuffer(NULL), convertSendBuffer(NULL)
{
@@ -209,8 +211,8 @@
// while there's enough data in receive buffer, form received
// GSM bursts and pass up to Transceiver
// Using the 157-156-156-156 symbols per timeslot format.
- while (rcvSz > (symbolsPerSlot + (tN % 4 == 0)) * sps) {
- signalVector rxVector((symbolsPerSlot + (tN % 4 == 0)) * sps);
+ while (rcvSz > (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx) {
+ signalVector rxVector((symbolsPerSlot + (tN % 4 == 0)) * mSPSRx);
unRadioifyVector((float *) (recvBuffer->begin() + readSz), rxVector);
GSM::Time tmpTime = rcvClock;
if (rcvClock.FN() >= 0) {
@@ -228,8 +230,8 @@
}
mClock.incTN();
rcvClock.incTN();
- readSz += (symbolsPerSlot+(tN % 4 == 0)) * sps;
- rcvSz -= (symbolsPerSlot+(tN % 4 == 0)) * sps;
+ readSz += (symbolsPerSlot+(tN % 4 == 0)) * mSPSRx;
+ rcvSz -= (symbolsPerSlot+(tN % 4 == 0)) * mSPSRx;
tN = rcvClock.TN();
}
@@ -267,33 +269,35 @@
return -1;
}
-/* Receive a timestamped chunk from the device */
+/* Receive a timestamped chunk from the device */
void RadioInterface::pullBuffer()
{
bool local_underrun;
- int num_recv;
+ int num_recv, len = OUTCHUNK / mSPSTx;
+ float *output;
- /* Outer buffer access size is fixed */
+ /* Outer buffer access size is fixed */
num_recv = mRadio->readSamples(convertRecvBuffer,
- OUTCHUNK,
+ len,
&overrun,
readTimestamp,
&local_underrun);
- if (num_recv != OUTCHUNK) {
+ if (num_recv != len) {
LOG(ALERT) << "Receive error " << num_recv;
return;
}
- convert_short_float((float *) (recvBuffer->begin() + recvCursor),
- convertRecvBuffer, 2 * OUTCHUNK);
+ output = (float *) (recvBuffer->begin() + recvCursor);
+
+ convert_short_float(output, convertRecvBuffer, 2 * len);
underrun |= local_underrun;
- readTimestamp += num_recv;
+ readTimestamp += num_recv;
recvCursor += num_recv;
}
-/* Send timestamped chunk to the device with arbitrary size */
+/* Send timestamped chunk to the device with arbitrary size */
void RadioInterface::pushBuffer()
{
int num_sent;