cf_t srslte_vec_dot_prod_ccc(cf_t *x, cf_t *y, uint32_t len) { #ifdef HAVE_VOLK_DOTPROD_FC_FUNCTION cf_t res; volk_32fc_x2_dot_prod_32fc(&res, x, y, len); return res; #else uint32_t i; cf_t res = 0; for (i=0;i<len;i++) { res += x[i]*y[i]; } return res; #endif }
void * xlate_worker_thr(void *ptr) { worker * ctx = (worker*)ptr; int32_t mypos = ctx->last_written + 1; int fir_offset = 0; /* To avoid hassle with complicated FIR evaluation, we allocate *alldata bigger * and copy the end of previous frame to the beginning of it, so we can compute * the filter simply as sum(x_{n-j}*h_{j}) and don't care about overflows. * * The interesting fact is that if SDRPACKETSIZE is not divisible by decimation, * the filtered frames will have different lengths. */ float * alldata = calloc(sizeof(float), (SDRPACKETSIZE + MAXTAPS) * COMPLEX); float * firout = calloc(1, ctx->maxoutsize); lv_32fc_t phase_inc, phase; phase = lv_cmake(1.0, 0.0); while(1) { pthread_mutex_lock(&datamutex); if(sdr_cptr <= mypos || ctx->send_cptr <= mypos - BUFSIZE) { // there are no data to process or no free space pthread_cond_wait(&datacond, &datamutex); pthread_mutex_unlock(&datamutex); continue; } pthread_mutex_unlock(&datamutex); phase_inc = lv_cmake(cos(ctx->rotate * ctx->decim), sin(ctx->rotate * ctx->decim)); memcpy(alldata, alldata+SDRPACKETSIZE*COMPLEX, MAXTAPS * COMPLEX * sizeof(float)); memcpy(alldata + MAXTAPS, sdr_inbuf[mypos % BUFSIZE].data, SDRPACKETSIZE * COMPLEX * sizeof(float)); int outsample = 0; int i; // evaluate the filter for(i = fir_offset; i<SDRPACKETSIZE; i+=ctx->decim) { lv_32fc_t* dst = (lv_32fc_t*) (firout + outsample*COMPLEX); volk_32fc_x2_dot_prod_32fc(dst, (lv_32fc_t*) (alldata+(i)*COMPLEX), // src (lv_32fc_t*)(ctx->taps), ctx->tapslen); // filter outsample++; } // rotator volk_32fc_s32fc_x2_rotator_32fc( (lv_32fc_t*) ctx->outbuf[mypos % BUFSIZE].data, // dst (lv_32fc_t*) firout, phase_inc, &phase, outsample); // save position so we know where to start evaluation the next frame fir_offset = i - SDRPACKETSIZE; ctx->outbuf[mypos % BUFSIZE].len = outsample * COMPLEX * sizeof(float); pthread_mutex_lock(&datamutex); if(ctx->newtaps != NULL) { free(ctx->taps); ctx->taps = get_complex_taps(ctx->newtaps, ctx->newtapslen, ctx->rotate); ctx->tapslen = ctx->newtapslen; ctx->maxval = calc_max_amplitude(ctx->newtaps, ctx->newtapslen); free(ctx->newtaps); ctx->newtaps = NULL; } if(!ctx->enabled) { pthread_mutex_unlock(&datamutex); break; } ctx->last_written = mypos; pthread_cond_broadcast(&datacond); pthread_mutex_unlock(&datamutex); mypos++; } // gracefully exit -- free and unlock everything... for(int i = 0; i<BUFSIZE; i++) { volk_free(ctx->outbuf[i].data); } free(ctx->taps); if(ctx->newtaps != NULL) { free(ctx->newtaps); } free(alldata); free(firout); return NULL; }