transceiver: separate I/O portion of radio interface implementation

Move push and pull of buffers into a dedicated file. This will
allow us to swap out resampling, non-resampling, and possibly
floating point device interfaces while presenting a single
floating point abstration in the interface itself.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>

git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@2670 19bc5d8c-e614-43d4-8b26-e1612bc8e597
diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am
index 5bad45e..652663b 100644
--- a/Transceiver52M/Makefile.am
+++ b/Transceiver52M/Makefile.am
@@ -46,7 +46,8 @@
 	DummyLoad.cpp
 
 libtransceiver_la_SOURCES = \
-	$(COMMON_SOURCES)
+	$(COMMON_SOURCES) \
+	radioIO.cpp
 
 noinst_PROGRAMS = \
 	USRPping \
diff --git a/Transceiver52M/radioIO.cpp b/Transceiver52M/radioIO.cpp
new file mode 100644
index 0000000..9956e87
--- /dev/null
+++ b/Transceiver52M/radioIO.cpp
@@ -0,0 +1,91 @@
+/*
+ * Radio device I/O interface
+ * Written by Thomas Tsou <ttsou@vt.edu>
+ *
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * See the COPYING file in the main directory for details.
+ */
+
+#include <radioInterface.h>
+#include <Logger.h>
+
+/* Device side buffers */
+static short rx_buf[OUTCHUNK * 2 * 2];
+static short tx_buf[INCHUNK * 2 * 2];
+
+/* Complex float to short conversion */
+static int float_to_short(short *shrt_out, float *flt_in, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		shrt_out[2 * i + 0] = flt_in[2 * i + 0];
+		shrt_out[2 * i + 1] = flt_in[2 * i + 1];
+	}
+
+	return i;
+}
+
+/* Comlpex short to float conversion */
+static int short_to_float(float *flt_out, short *shrt_in, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		flt_out[2 * i + 0] = shrt_in[2 * i + 0];
+		flt_out[2 * i + 1] = shrt_in[2 * i + 1];
+	}
+
+	return i;
+}
+
+/* Receive a timestamped chunk from the device */ 
+void RadioInterface::pullBuffer()
+{
+	bool local_underrun;
+
+	/* Read samples. Fail if we don't get what we want. */
+	int num_rd = mRadio->readSamples(rx_buf, OUTCHUNK, &overrun,
+					    readTimestamp, &local_underrun);
+
+	LOG(DEBUG) << "Rx read " << num_rd << " samples from device";
+	assert(num_rd == OUTCHUNK);
+
+	underrun |= local_underrun;
+	readTimestamp += (TIMESTAMP) num_rd;
+
+	short_to_float(rcvBuffer + 2 * rcvCursor, rx_buf, num_rd);
+	rcvCursor += num_rd;
+}
+
+/* Send timestamped chunk to the device with arbitrary size */ 
+void RadioInterface::pushBuffer()
+{
+	if (sendCursor < INCHUNK)
+		return;
+
+	float_to_short(tx_buf, sendBuffer, sendCursor);
+
+	/* Write samples. Fail if we don't get what we want. */
+	int num_smpls = mRadio->writeSamples(tx_buf,
+					     sendCursor,
+					     &underrun,
+					     writeTimestamp);
+	assert(num_smpls == sendCursor);
+
+	writeTimestamp += (TIMESTAMP) num_smpls;
+	sendCursor = 0;
+}
diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp
index 4e261f7..1482eb6 100644
--- a/Transceiver52M/radioInterface.cpp
+++ b/Transceiver52M/radioInterface.cpp
@@ -25,6 +25,8 @@
 #include "radioInterface.h"
 #include <Logger.h>
 
+bool started = false;
+
 RadioInterface::RadioInterface(RadioDevice *wRadio,
                                int wReceiveOffset,
 			       int wRadioOversampling,
@@ -73,94 +75,40 @@
     powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0)));
 }
 
-short *RadioInterface::radioifyVector(signalVector &wVector,
-                                      short *retVector,
-                                      float scale,
-                                      bool zeroOut)
+int RadioInterface::radioifyVector(signalVector &wVector,
+				   float *retVector,
+				   float scale,
+				   bool zero)
 {
+  int i;
   signalVector::iterator itr = wVector.begin();
-  short *shortItr = retVector;
-  if (zeroOut) {
-    while (itr < wVector.end()) {
-      *shortItr++ = 0;
-      *shortItr++ = 0;
-      itr++;
-    }
-  } else if (scale != 1.0) { 
-    while (itr < wVector.end()) {
-      *shortItr++ = (short) (itr->real() * scale);
-      *shortItr++ = (short) (itr->imag() * scale);
-      itr++;
-    }
-  } else {
-    while (itr < wVector.end()) {
-      *shortItr++ = (short) (itr->real());
-      *shortItr++ = (short) (itr->imag());
-      itr++;
-    }
+
+  if (zero) {
+    memset(retVector, 0, wVector.size() * 2 * sizeof(float));
+    return wVector.size();
   }
 
-  return retVector;
+  for (i = 0; i < wVector.size(); i++) {
+    retVector[2 * i + 0] = itr->real() * scale;
+    retVector[2 * i + 1] = itr->imag() * scale;
+    itr++;
+  }
+
+  return wVector.size();
 }
 
-void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector)
+int RadioInterface::unRadioifyVector(float *floatVector,
+				     signalVector& newVector)
 {
-  
+  int i;
   signalVector::iterator itr = newVector.begin();
-  short *shortItr = shortVector;
-  while (itr < newVector.end()) {
-    *itr++ = Complex<float>(*shortItr,*(shortItr+1));
-    shortItr += 2;
+
+  for (i = 0; i < newVector.size(); i++) {
+    *itr++ = Complex<float>(floatVector[2 * i + 0],
+			    floatVector[2 * i + 1]);
   }
 
-}
-
-
-bool started = false;
-
-void RadioInterface::pushBuffer(void) {
-
-  if (sendCursor < 2*INCHUNK*samplesPerSymbol) return;
-
-  // send resampleVector
-  int samplesWritten = mRadio->writeSamples(sendBuffer,
-					  INCHUNK*samplesPerSymbol,
-					  &underrun,
-					  writeTimestamp); 
-   
-  writeTimestamp += (TIMESTAMP) samplesWritten;
-
-  if (sendCursor > 2*samplesWritten) 
-    memcpy(sendBuffer,sendBuffer+samplesWritten*2,sizeof(short)*2*(sendCursor-2*samplesWritten));
-  sendCursor = sendCursor - 2*samplesWritten;
-}
-
-
-void RadioInterface::pullBuffer(void)
-{
-   
-  bool localUnderrun;
-
-   // receive receiveVector
-  short* shortVector = rcvBuffer+rcvCursor;  
-  //LOG(DEBUG) << "Reading USRP samples at timestamp " << readTimestamp;
-  int samplesRead = mRadio->readSamples(shortVector,OUTCHUNK*samplesPerSymbol,&overrun,readTimestamp,&localUnderrun);
-  underrun |= localUnderrun;
-  readTimestamp += (TIMESTAMP) samplesRead;
-  while (samplesRead < OUTCHUNK*samplesPerSymbol) {
-    int oldSamplesRead = samplesRead;
-    samplesRead += mRadio->readSamples(shortVector+2*samplesRead,
-				     OUTCHUNK*samplesPerSymbol-samplesRead,
-				     &overrun,
-				     readTimestamp,
-				     &localUnderrun);
-    underrun |= localUnderrun;
-    readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead);
-  }
-  //LOG(DEBUG) << "samplesRead " << samplesRead;
-
-  rcvCursor += samplesRead*2;
-
+  return newVector.size();
 }
 
 bool RadioInterface::tuneTx(double freq)
@@ -186,8 +134,8 @@
   mRadio->updateAlignment(writeTimestamp-10000); 
   mRadio->updateAlignment(writeTimestamp-10000);
 
-  sendBuffer = new short[2*2*INCHUNK*samplesPerSymbol];
-  rcvBuffer = new short[2*2*OUTCHUNK*samplesPerSymbol];
+  sendBuffer = new float[2*2*INCHUNK*samplesPerSymbol];
+  rcvBuffer = new float[2*2*OUTCHUNK*samplesPerSymbol];
  
   mOn = true;
 
@@ -211,9 +159,9 @@
 
   if (!mOn) return;
 
-  radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst);
+  radioifyVector(radioBurst, sendBuffer + 2 * sendCursor, powerScaling, zeroBurst);
 
-  sendCursor += (radioBurst.size()*2);
+  sendCursor += radioBurst.size();
 
   pushBuffer();
 }
@@ -229,7 +177,7 @@
   GSM::Time rcvClock = mClock.get();
   rcvClock.decTN(receiveOffset);
   unsigned tN = rcvClock.TN();
-  int rcvSz = rcvCursor/2;
+  int rcvSz = rcvCursor;
   int readSz = 0;
   const int symbolsPerSlot = gSlotLen + 8;
 
@@ -263,9 +211,9 @@
     tN = rcvClock.TN();
   }
 
-  if (readSz > 0) { 
-    memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor-readSz));
-    rcvCursor = rcvCursor-2*readSz;
+  if (readSz > 0) {
+    rcvCursor -= readSz;
+    memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(float) * 2 * rcvCursor);
   }
 } 
   
diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h
index 8fb9f27..9b5c2b1 100644
--- a/Transceiver52M/radioInterface.h
+++ b/Transceiver52M/radioInterface.h
@@ -37,10 +37,10 @@
 
   RadioDevice *mRadio;			      ///< the USRP object
  
-  short *sendBuffer; //[2*2*INCHUNK];
+  float *sendBuffer;
   unsigned sendCursor;
 
-  short *rcvBuffer; //[2*2*OUTCHUNK];
+  float *rcvBuffer;
   unsigned rcvCursor;
  
   bool underrun;			      ///< indicates writes to USRP are too slow
@@ -64,13 +64,13 @@
   signalVector *finalVec, *finalVec9;
 
   /** format samples to USRP */ 
-  short *radioifyVector(signalVector &wVector,
-                        short *shortVector,
-                        float scale,
-                        bool zeroOut);
+  int radioifyVector(signalVector &wVector,
+                     float *floatVector,
+                     float scale,
+                     bool zero);
 
   /** format samples from USRP */
-  void unRadioifyVector(short *shortVector, signalVector &wVector);
+  int unRadioifyVector(float *floatVector, signalVector &wVector);
 
   /** push GSM bursts into the transmit buffer */
   void pushBuffer(void);