/* 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); }
// assumes filter group delay is 0.5*(length of filter) signalVector *polyphaseResampleVector(signalVector &wVector, int P, int Q, signalVector *LPF) { bool deleteLPF = false; if (LPF==NULL) { float cutoffFreq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P); LPF = createLPF(cutoffFreq/3.0,100*POLYPHASESPAN+1,Q); deleteLPF = true; } signalVector *resampledVector = new signalVector((int) ceil(wVector.size()*(float) P / (float) Q)); resampledVector->fill(0); resampledVector->isRealOnly(wVector.isRealOnly()); signalVector::iterator newItr = resampledVector->begin(); //FIXME: need to update for real-only vectors int outputIx = (LPF->size()-1)/2/Q; //((P > Q) ? P : Q); while (newItr < resampledVector->end()) { int outputBranch = (outputIx*Q) % P; int inputOffset = (outputIx*Q - outputBranch)/P; signalVector::const_iterator inputItr = wVector.begin() + inputOffset; signalVector::const_iterator filtItr = LPF->begin() + outputBranch; while (inputItr >= wVector.end()) { inputItr--; filtItr+=P; } complex sum = 0.0; if (!LPF->isRealOnly()) { while ( (inputItr >= wVector.begin()) && (filtItr < LPF->end()) ) { sum += (*inputItr)*(*filtItr); inputItr--; filtItr += P; } } else { while ( (inputItr >= wVector.begin()) && (filtItr < LPF->end()) ) { sum += (*inputItr)*(filtItr->real()); inputItr--; filtItr += P; } } *newItr = sum; newItr++; outputIx++; } if (deleteLPF) delete LPF; return resampledVector; }
void RadioInterface::pullBuffer(void) { writingRadioLock.lock(); // These timestamps are in samples @ 400 kHz. while (readTimestamp > writeTimestamp - (TIMESTAMP) 2*OUTCHUNK) { LOG(DEEPDEBUG) << "waiting..." << readTimestamp << " " << writeTimestamp; wroteRadioSignal.wait(writingRadioLock); //wroteRadioSignal.wait(writingRadioLock,1); } writingRadioLock.unlock(); bool localUnderrun; // receive receiveVector short* shortVector = new short[OUTCHUNK*2]; int samplesRead = usrp->readSamples(shortVector,OUTCHUNK,&overrun,readTimestamp,&localUnderrun); underrun |= localUnderrun; readTimestamp += (TIMESTAMP) samplesRead; while (samplesRead < OUTCHUNK) { int oldSamplesRead = samplesRead; samplesRead += usrp->readSamples(shortVector+2*samplesRead, OUTCHUNK-samplesRead, &overrun, readTimestamp, &localUnderrun); underrun |= localUnderrun; readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead); } signalVector *receiveVector = unUSRPifyVector(shortVector,samplesRead); delete []shortVector; if (!rcvLPF) { int P = INRATE; int Q = OUTRATE; float cutoffFreq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P); rcvLPF = createLPF(cutoffFreq,961,P); } signalVector *retVector = NULL; if (!rcvHistory) { rcvHistory = new signalVector(OUTHISTORY); rcvHistory->fill(0); } // resample received data to multiple of GSM symbol rate signalVector inputVector(*rcvHistory,*receiveVector); retVector = polyphaseResampleVector(inputVector, INRATE,OUTRATE,rcvLPF); // push sampled data to back of receive buffer signalVector *tmp = retVector; retVector = new signalVector(retVector->size()-INHISTORY); tmp->segmentCopyTo(*retVector,INHISTORY,tmp->size()-INHISTORY); delete tmp; LOG(DEEPDEBUG) << "converted " << receiveVector->size() << " radio samples into " << retVector->size() << " transceiver samples "; // update history of received data receiveVector->segmentCopyTo(*rcvHistory,receiveVector->size()-OUTHISTORY,OUTHISTORY); delete receiveVector; if (rcvBuffer) { signalVector *tmp = rcvBuffer; rcvBuffer = new signalVector(*tmp,*retVector); delete tmp; delete retVector; } else rcvBuffer = retVector; }
void RadioInterface::pushBuffer(void) { if (sendBuffer->size() < INCHUNK) { return; } int numChunks = sendBuffer->size()/INCHUNK; signalVector* truncatedBuffer = new signalVector(numChunks*INCHUNK); sendBuffer->segmentCopyTo(*truncatedBuffer,0,numChunks*INCHUNK); if (!sendLPF) { int P = OUTRATE; int Q = INRATE; float cutoffFreq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P); sendLPF = createLPF(cutoffFreq,651,P); } // resample data to USRP sample rate signalVector *inputVector = new signalVector(*sendHistory,*truncatedBuffer); signalVector *resampledVector = polyphaseResampleVector(*inputVector, OUTRATE, INRATE,sendLPF); delete inputVector; // Set transmit gain and power here. scaleVector(*resampledVector, usrp->fullScaleInputValue()); short *resampledVectorShort = USRPifyVector(*resampledVector); // start the USRP when we actually have data to send to the USRP. if (!started) { started = true; LOG(INFO) << "Starting USRP"; usrp->start(); LOG(DEBUG) << "USRP started"; usrp->updateAlignment(10000); usrp->updateAlignment(10000); } // send resampleVector writingRadioLock.lock(); int samplesWritten = usrp->writeSamples(resampledVectorShort+OUTHISTORY*2, (resampledVector->size()-OUTHISTORY), &underrun, writeTimestamp); //LOG(DEEPDEBUG) << "writeTimestamp: " << writeTimestamp << ", samplesWritten: " << samplesWritten; writeTimestamp += (TIMESTAMP) samplesWritten; wroteRadioSignal.signal(); writingRadioLock.unlock(); LOG(DEEPDEBUG) << "converted " << truncatedBuffer->size() << " transceiver samples into " << samplesWritten << " radio samples "; delete resampledVector; delete []resampledVectorShort; // update the history of sent data truncatedBuffer->segmentCopyTo(*sendHistory,truncatedBuffer->size()-INHISTORY, INHISTORY); // update the buffer, i.e. keep the samples we didn't send signalVector *tmp = sendBuffer; sendBuffer = new signalVector(sendBuffer->size()-truncatedBuffer->size()); tmp->segmentCopyTo(*sendBuffer,truncatedBuffer->size(), sendBuffer->size()); delete tmp; delete truncatedBuffer; }