diff options
Diffstat (limited to 'Transceiver52M/radioInterfaceResamp.cpp')
-rw-r--r-- | Transceiver52M/radioInterfaceResamp.cpp | 332 |
1 files changed, 0 insertions, 332 deletions
diff --git a/Transceiver52M/radioInterfaceResamp.cpp b/Transceiver52M/radioInterfaceResamp.cpp deleted file mode 100644 index c7f17ea..0000000 --- a/Transceiver52M/radioInterfaceResamp.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Radio device interface with sample rate conversion - * 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> - -/* New chunk sizes for resampled rate */ -#ifdef INCHUNK - #undef INCHUNK -#endif -#ifdef OUTCHUNK - #undef OUTCHUNK -#endif - -/* Resampling parameters */ -#define INRATE 65 * SAMPSPERSYM -#define INHISTORY INRATE * 2 -#define INCHUNK INRATE * 9 - -#define OUTRATE 96 * SAMPSPERSYM -#define OUTHISTORY OUTRATE * 2 -#define OUTCHUNK OUTRATE * 9 - -/* Resampler low pass filters */ -signalVector *tx_lpf = 0; -signalVector *rx_lpf = 0; - -/* Resampler history */ -signalVector *tx_hist = 0; -signalVector *rx_hist = 0; - -/* Resampler input buffer */ -signalVector *tx_vec = 0; -signalVector *rx_vec = 0; - -/* - * High rate (device facing) buffers - * - * Transmit side samples are pushed after each burst so accomodate - * a resampled burst plus up to a chunk left over from the previous - * resampling operation. - * - * Receive side samples always pulled with a fixed size. - */ -short tx_buf[INCHUNK * 2 * 4]; -short rx_buf[OUTCHUNK * 2 * 2]; - -/* - * Utilities and Conversions - * - * Manipulate signal vectors dynamically for two reasons. For one, - * it's simpler. And two, it doesn't make any reasonable difference - * relative to the high overhead generated by the resampling. - */ - -/* Concatenate signal vectors. Deallocate input vectors. */ -signalVector *concat(signalVector *a, signalVector *b) -{ - signalVector *vec = new signalVector(*a, *b); - delete a; - delete b; - - return vec; -} - -/* Segment a signal vector. Deallocate the input vector. */ -signalVector *segment(signalVector *a, int indx, int sz) -{ - signalVector *vec = new signalVector(sz); - a->segmentCopyTo(*vec, indx, sz); - delete a; - - return vec; -} - -/* Create a new signal vector from a short array. */ -signalVector *short_to_sigvec(short *smpls, size_t sz) -{ - int i; - signalVector *vec = new signalVector(sz); - signalVector::iterator itr = vec->begin(); - - for (i = 0; i < sz; i++) { - *itr++ = Complex<float>(smpls[2 * i + 0], smpls[2 * i + 1]); - } - - return vec; -} - -/* Convert and deallocate a signal vector into a short array. */ -int sigvec_to_short(signalVector *vec, short *smpls) -{ - int i; - signalVector::iterator itr = vec->begin(); - - for (i = 0; i < vec->size(); i++) { - smpls[2 * i + 0] = itr->real(); - smpls[2 * i + 1] = itr->imag(); - itr++; - } - delete vec; - - return i; -} - -/* Create a new signal vector from a float array. */ -signalVector *float_to_sigvec(float *smpls, int sz) -{ - int i; - signalVector *vec = new signalVector(sz); - signalVector::iterator itr = vec->begin(); - - for (i = 0; i < sz; i++) { - *itr++ = Complex<float>(smpls[2 * i + 0], smpls[2 * i + 1]); - } - - return vec; -} - -/* Convert and deallocate a signal vector into a float array. */ -int sigvec_to_float(signalVector *vec, float *smpls) -{ - int i; - signalVector::iterator itr = vec->begin(); - - for (i = 0; i < vec->size(); i++) { - smpls[2 * i + 0] = itr->real(); - smpls[2 * i + 1] = itr->imag(); - itr++; - } - delete vec; - - return i; -} - -/* Initialize resampling signal vectors */ -void init_resampler(signalVector **lpf, - signalVector **buf, - signalVector **hist, - int tx) -{ - int P, Q, taps, hist_len; - float cutoff_freq; - - if (tx) { - LOG(INFO) << "Initializing Tx resampler"; - P = OUTRATE; - Q = INRATE; - taps = 651; - hist_len = INHISTORY; - } else { - LOG(INFO) << "Initializing Rx resampler"; - P = INRATE; - Q = OUTRATE; - taps = 961; - hist_len = OUTHISTORY; - } - - if (!*lpf) { - cutoff_freq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P); - *lpf = createLPF(cutoff_freq, taps, P); - } - - if (!*buf) { - *buf = new signalVector(); - } - - if (!*hist); - *hist = new signalVector(hist_len); -} - -/* Resample a signal vector - * - * The input vector is deallocated and the pointer returned with a vector - * of any unconverted samples. - */ -signalVector *resmpl_sigvec(signalVector *hist, signalVector **vec, - signalVector *lpf, double in_rate, - double out_rate, int chunk_sz) -{ - signalVector *resamp_vec; - int num_chunks = (*vec)->size() / chunk_sz; - - /* Truncate to a chunk multiple */ - signalVector trunc_vec(num_chunks * chunk_sz); - (*vec)->segmentCopyTo(trunc_vec, 0, num_chunks * chunk_sz); - - /* Update sample buffer with remainder */ - *vec = segment(*vec, trunc_vec.size(), (*vec)->size() - trunc_vec.size()); - - /* Add history and resample */ - signalVector input_vec(*hist, trunc_vec); - resamp_vec = polyphaseResampleVector(input_vec, in_rate, - out_rate, lpf); - - /* Update history */ - trunc_vec.segmentCopyTo(*hist, trunc_vec.size() - hist->size(), - hist->size()); - return resamp_vec; -} - -/* Wrapper for receive-side integer-to-float array resampling */ - int rx_resmpl_int_flt(float *smpls_out, short *smpls_in, int num_smpls) -{ - int num_resmpld, num_chunks; - signalVector *convert_vec, *resamp_vec, *trunc_vec; - - if (!rx_lpf || !rx_vec || !rx_hist) - init_resampler(&rx_lpf, &rx_vec, &rx_hist, false); - - /* Convert and add samples to the receive buffer */ - convert_vec = short_to_sigvec(smpls_in, num_smpls); - rx_vec = concat(rx_vec, convert_vec); - - num_chunks = rx_vec->size() / OUTCHUNK; - if (num_chunks < 1) - return 0; - - /* Resample */ - resamp_vec = resmpl_sigvec(rx_hist, &rx_vec, rx_lpf, - INRATE, OUTRATE, OUTCHUNK); - /* Truncate */ - trunc_vec = segment(resamp_vec, INHISTORY, - resamp_vec->size() - INHISTORY); - /* Convert */ - num_resmpld = sigvec_to_float(trunc_vec, smpls_out); - - return num_resmpld; -} - -/* Wrapper for transmit-side float-to-int array resampling */ -int tx_resmpl_flt_int(short *smpls_out, float *smpls_in, int num_smpls) -{ - int num_resmpl, num_chunks; - signalVector *convert_vec, *resamp_vec; - - if (!tx_lpf || !tx_vec || !tx_hist) - init_resampler(&tx_lpf, &tx_vec, &tx_hist, true); - - /* Convert and add samples to the transmit buffer */ - convert_vec = float_to_sigvec(smpls_in, num_smpls); - tx_vec = concat(tx_vec, convert_vec); - - num_chunks = tx_vec->size() / INCHUNK; - if (num_chunks < 1) - return 0; - - /* Resample and convert to an integer array */ - resamp_vec = resmpl_sigvec(tx_hist, &tx_vec, tx_lpf, - OUTRATE, INRATE, INCHUNK); - num_resmpl = sigvec_to_short(resamp_vec, smpls_out); - - return num_resmpl; -} - -RadioInterfaceResamp::RadioInterfaceResamp(RadioDevice *wRadio, - int wReceiveOffset, - int wSPS, - GSM::Time wStartTime) - : RadioInterface(wRadio, wReceiveOffset, wSPS, wStartTime) -{ -} - -/* Receive a timestamped chunk from the device */ -void RadioInterfaceResamp::pullBuffer() -{ - int num_cv, num_rd; - bool local_underrun; - - /* Read samples. Fail if we don't get what we want. */ - 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; - - /* Convert and resample */ - num_cv = rx_resmpl_int_flt(rcvBuffer + 2 * rcvCursor, - rx_buf, num_rd); - - LOG(DEBUG) << "Rx read " << num_cv << " samples from resampler"; - - rcvCursor += num_cv; -} - -/* Send a timestamped chunk to the device */ -void RadioInterfaceResamp::pushBuffer() -{ - int num_cv, num_wr; - - if (sendCursor < INCHUNK) - return; - - LOG(DEBUG) << "Tx wrote " << sendCursor << " samples to resampler"; - - /* Resample and convert */ - num_cv = tx_resmpl_flt_int(tx_buf, sendBuffer, sendCursor); - assert(num_cv > sendCursor); - - /* Write samples. Fail if we don't get what we want. */ - num_wr = mRadio->writeSamples(tx_buf + OUTHISTORY * 2, - num_cv - OUTHISTORY, - &underrun, - writeTimestamp); - - LOG(DEBUG) << "Tx wrote " << num_wr << " samples to device"; - assert(num_wr == num_wr); - - writeTimestamp += (TIMESTAMP) num_wr; - sendCursor = 0; -} |