void correctIQ (CXB sigbuf, IQ iq, BOOLEAN isTX, int subchan) { int i; REAL doit; if (IQdoit == 0) return; if (subchan == 0) doit = iq->mu; else doit = 0; if(!isTX) { // if (subchan == 0) // removed so that sub rx's will get IQ correction for (i = 0; i < CXBhave (sigbuf); i++) { iq->del[iq->index] = CXBdata(sigbuf,i); iq->y[iq->index] = Cadd(iq->del[iq->index],Cmul(iq->w[0],Conjg(iq->del[iq->index]))); iq->y[iq->index] = Cadd(iq->y[iq->index],Cmul(iq->w[1],Conjg(iq->y[iq->index]))); iq->w[1] = Csub(iq->w[1], Cscl(Cmul(iq->y[iq->index],iq->y[iq->index]), doit)); // this is where the adaption happens CXBdata(sigbuf,i)=iq->y[iq->index]; iq->index = (iq->index+iq->MASK)&iq->MASK; } //fprintf(stderr, "w1 real: %g, w1 imag: %g\n", iq->w[1].re, iq->w[1].im); fflush(stderr); } else { for (i = 0; i < CXBhave (sigbuf); i++) { CXBimag (sigbuf, i) += iq->phase * CXBreal (sigbuf, i); CXBreal (sigbuf, i) *= iq->gain; } } }
void CSSBDemod::demodulate() { if (m_ibuf == m_obuf) return; unsigned int n = CXBhave(m_ibuf); for (unsigned int i = 0; i < n; i++) CXBdata(m_obuf, i) = CXBdata(m_ibuf, i); CXBhave(m_obuf) = n; }
void CFMDemod::demodulate() { unsigned int n = CXBhave(m_ibuf); for (unsigned int i = 0; i < n; i++) { pll(CXBdata(m_ibuf, i)); m_afc = float(0.9999 * m_afc + 0.0001F * m_pllFreqF); CXBreal(m_obuf, i) = CXBimag(m_obuf, i) = (m_pllFreqF - m_afc) * m_cvt; } CXBhave(m_obuf) = n; }
void CLMS::processNoise() { float scl1 = 1.0F - m_adaptationRate * m_leakage; unsigned int n = CXBhave(m_signal); for (unsigned int i = 0; i < n; i++) { m_delayLine[m_delayLinePtr] = CXBreal(m_signal, i); float accum = 0.0F; float sum_sq = 0.0F; unsigned int j; for (j = 0; j < m_adaptiveFilterSize; j++) { unsigned int k = (j + m_delay + m_delayLinePtr) & m_mask; sum_sq += m_delayLine[k] * m_delayLine[k]; accum += m_adaptiveFilter[j] * m_delayLine[k]; } float error = CXBreal(m_signal, i) - accum; CXBreal(m_signal, i) = accum; CXBimag(m_signal, i) = accum; float scl2 = m_adaptationRate / (sum_sq + 1e-10); error *= scl2; for (j = 0; j < m_adaptiveFilterSize; j++) { unsigned int k = (j + m_delay + m_delayLinePtr) & m_mask; m_adaptiveFilter[j] = m_adaptiveFilter[j] * scl1 + error * m_delayLine[k]; } m_delayLinePtr = (m_delayLinePtr + m_mask) & m_mask; } }
/* ---------------------------------------------------------------------------- */ void FMDemod(FMD fm) { int i; for (i = 0; i < CXBhave(fm->ibuf); i++) { pll(fm, CXBdata(fm->ibuf, i)); fm->afc = (REAL) (0.9999 * fm->afc + 0.0001 * fm->pll.freq.f); CXBreal(fm->obuf, i) = CXBimag(fm->obuf, i) = (fm->pll.freq.f - fm->afc) * fm->cvt; } }
BOOLEAN CWTone (CWToneGen cwt) { int i, n = cwt->size; ComplexOSC (cwt->osc.gen); for (i = 0; i < n; i++) { // in an envelope stage? if (cwt->stage == CWTone_RISE) { // still going? if (cwt->rise.have++ < cwt->rise.want) { cwt->curr += cwt->rise.incr; cwt->mul = cwt->scl * (REAL) CWSIN (cwt->curr * M_PI / 2.0); } else { // no, assert steady-state, force level cwt->curr = 1.0; cwt->mul = cwt->scl; cwt->stage = CWTone_STDY; // won't come back into envelopes // until FALL asserted from outside } } else if (cwt->stage == CWTone_FALL) { // still going? if (cwt->fall.have++ < cwt->fall.want) { cwt->curr -= cwt->fall.incr; cwt->mul = cwt->scl * (REAL) CWSIN (cwt->curr * M_PI / 2.0); } else { // no, assert trailing, force level cwt->curr = 0.0; cwt->mul = 0.0; cwt->stage = CWTone_HOLD; // won't come back into envelopes hereafter } } // apply envelope // (same base as osc.gen internal buf) CXBdata (cwt->buf, i) = Cscl (CXBdata (cwt->buf, i), cwt->mul); } CXBhave(cwt->buf) = n; /* kd5tfd added - set have field of buf so correctIQ works */ // indicate whether it's turned itself off // sometime during this pass return cwt->stage != CWTone_HOLD; }
void CDCBlock::block() { unsigned int n = CXBhave(m_buf); for (unsigned int i = 0; i < n; i++) { float x = CXBreal(m_buf, i); float y = x - m_xm1 + 0.995F * m_ym1; m_xm1 = x; m_ym1 = y; CXBdata(m_buf, i) = Cmplx(y, 0.0F); } }
void blms_adapt (BLMS blms) { int sigsize = CXBhave (blms->signal); int sigidx = 0; // fputs("Inside\n",stderr),fflush(stderr); do { int j; memcpy (blms->delay_line, &blms->delay_line[128], sizeof (COMPLEX) * 128); // do overlap move memcpy (&blms->delay_line[128], &CXBdata (blms->signal, sigidx), sizeof (COMPLEX) * 128); // copy in new data fftwf_execute (blms->Xplan); // compute transform of input data for (j = 0; j < 256; j++) { blms->Yhat[j] = Cmul (blms->What[j], blms->Xhat[j]); // Filter new signal in freq. domain blms->Xhat[j] = Conjg (blms->Xhat[j]); // take input data's complex conjugate } fftwf_execute (blms->Yplan); //compute output signal transform for (j = 128; j < 256; j++) blms->y[j] = Cscl (blms->y[j], BLKSCL); memset (blms->y, 0, 128 * sizeof (COMPLEX)); for (j = 128; j < 256; j++) blms->error[j] = Csub (blms->delay_line[j], blms->y[j]); // compute error signal if (blms->filter_type) memcpy (&CXBdata (blms->signal, sigidx), &blms->y[128], 128 * sizeof (COMPLEX)); // if noise filter, output y else memcpy (&CXBdata (blms->signal, sigidx), &blms->error[128], 128 * sizeof (COMPLEX)); // if notch filter, output error fftwf_execute (blms->Errhatplan); // compute transform of the error signal for (j = 0; j < 256; j++) blms->Errhat[j] = Cmul (blms->Errhat[j], blms->Xhat[j]); // compute cross correlation transform fftwf_execute (blms->UPDplan); // compute inverse transform of cross correlation transform for (j = 0; j < 128; j++) blms->update[j] = Cscl (blms->update[j], BLKSCL); memset (&blms->update[128], 0, sizeof (COMPLEX) * 128); // zero the last block of the update, so we get // filter coefficients only at front of buffer fftwf_execute (blms->Wplan); for (j = 0; j < 256; j++) { blms->What[j] = Cadd (Cscl (blms->What[j], blms->leak_rate), // leak the W away Cscl (blms->Update[j], blms->adaptation_rate)); // update at adaptation rate } sigidx += 128; // move to next block in the signal buffer } while (sigidx < sigsize); // done? }
CXB newCXB (int size, COMPLEX * base, char *tag) { CXB p = (CXB) safealloc (1, sizeof (CXBuffer), tag); if (base) { CXBbase (p) = base; CXBmine (p) = FALSE; } else { CXBbase (p) = newvec_COMPLEX (size, "newCXB"); CXBmine (p) = TRUE; } CXBsize (p) = CXBwant (p) = size; CXBovlp (p) = CXBhave (p) = CXBdone (p) = 0; return p; }
void correctIQ (CXB sigbuf, IQ iq) { int i; // SV1EIA AIR if (CXBhave (sigbuf)!= DEFSPEC) // SV1EIA AIR { // SV1EIA AIR if (iq->buffer_counter>DEFSPEC-1) iq->buffer_counter = 0; // SV1EIA AIR iq->buffer_length[iq->buffer_counter] = CXBhave (sigbuf); // SV1EIA AIR iq->buffer_counter++; // SV1EIA AIR } // SV1EIA AIR iq->im_max_actual = 0; // SV1EIA AIR iq->im_max_test = 0; // SV1EIA AIR iq->im_min_actual = 0; // SV1EIA AIR iq->im_min_test = 0; // SV1EIA AIR iq->re_max_actual = 0; // SV1EIA AIR iq->re_max_test = 0; // SV1EIA AIR iq->re_min_actual = 0; // SV1EIA AIR iq->re_min_test = 0; // SV1EIA AIR for (i = 0; i < CXBhave (sigbuf); i++) // SV1EIA AIR { // SV1EIA AIR if (CXBimag (sigbuf, i) >= iq->im_max_actual) // SV1EIA AIR { // SV1EIA AIR iq->im_max_actual = CXBimag (sigbuf, i); // SV1EIA AIR iq->im_max_bin_actual = i; // SV1EIA AIR } // SV1EIA AIR if (CXBreal (sigbuf, i) >= iq->re_max_actual) // SV1EIA AIR { // SV1EIA AIR iq->re_max_actual = CXBreal (sigbuf, i); // SV1EIA AIR iq->re_max_bin_actual = i; // SV1EIA AIR } // SV1EIA AIR if (CXBimag (sigbuf, i) <= iq->im_min_actual) // SV1EIA AIR { // SV1EIA AIR iq->im_min_actual = CXBimag (sigbuf, i); // SV1EIA AIR iq->im_min_bin_actual = i; // SV1EIA AIR } // SV1EIA AIR if (CXBreal (sigbuf, i) <= iq->re_min_actual) // SV1EIA AIR { // SV1EIA AIR iq->re_min_actual = CXBreal (sigbuf, i); // SV1EIA AIR iq->re_min_bin_actual = i; // SV1EIA AIR } // SV1EIA AIR iq->im_actual[i] = CXBimag (sigbuf, i); // SV1EIA AIR iq->re_actual[i] = CXBreal (sigbuf, i); // SV1EIA AIR CXBimag (sigbuf, i) += iq->phase[i] * CXBreal (sigbuf, i); // SV1EIA AIR CXBreal (sigbuf, i) *= iq->gain[i]; // SV1EIA AIR iq->im_test[i] = CXBimag (sigbuf, i); // SV1EIA AIR iq->re_test[i] = CXBreal (sigbuf, i); // SV1EIA AIR if (CXBimag (sigbuf, i) >= iq->im_max_test) // SV1EIA AIR { // SV1EIA AIR iq->im_max_test = CXBimag (sigbuf, i); // SV1EIA AIR iq->im_max_bin_test = i; // SV1EIA AIR } // SV1EIA AIR if (CXBreal (sigbuf, i) >= iq->re_max_test) // SV1EIA AIR { // SV1EIA AIR iq->re_max_test = CXBreal (sigbuf, i); // SV1EIA AIR iq->re_max_bin_test = i; // SV1EIA AIR } // SV1EIA AIR if (CXBimag (sigbuf, i) <= iq->im_min_test) // SV1EIA AIR { // SV1EIA AIR iq->im_min_test = CXBimag (sigbuf, i); // SV1EIA AIR iq->im_min_bin_test = i; // SV1EIA AIR } // SV1EIA AIR if (CXBreal (sigbuf, i) <= iq->re_min_test) // SV1EIA AIR { // SV1EIA AIR iq->re_min_test = CXBreal (sigbuf, i); // SV1EIA AIR iq->re_min_bin_test = i; // SV1EIA AIR } // SV1EIA AIR } // SV1EIA AIR // if (iq->spec > 0) // { // } }
void CTX::process(float* bufi, float* bufq, unsigned int n) { for (unsigned int i = 0U; i < n; i++) { CXBreal(m_iBuf, i) = bufi[i]; CXBimag(m_iBuf, i) = bufq[i]; } CXBhave(m_iBuf) = n; CXBscl(m_iBuf, m_micGain); /* unsigned int n = CXBhave(m_iBuf); for (unsigned int i = 0; i < n; i++) CXBdata(m_iBuf, i) = Cmplx(CXBimag(m_iBuf, i), 0.0F); */ if (m_dcBlockFlag && (m_mode == USB || m_mode == LSB)) m_dcBlock->block(); spectrum(m_iBuf, SPEC_TX_MIC); meter(m_iBuf, TX_MIC); if (m_equaliserFlag && (m_mode == USB || m_mode == LSB || m_mode == AM || m_mode == SAM || m_mode == FMN)) m_equaliser->process(); if (m_speechProcFlag && (m_mode == USB || m_mode == LSB)) m_speechProc->process(); spectrum(m_iBuf, SPEC_TX_POST_COMP); meter(m_iBuf, TX_COMP); m_alc->process(); spectrum(m_iBuf, SPEC_TX_POST_ALC); meter(m_iBuf, TX_ALC); m_modulator->modulate(); if (m_tick == 0UL) m_filter->reset(); // Only active for the third method and zero-IF m_oscillator2->mix(); m_filter->filter(); CXBhave(m_oBuf) = CXBhave(m_iBuf); spectrum(m_oBuf, SPEC_TX_POST_FILT); m_oscillator1->mix(); m_iq->process(); CXBscl(m_oBuf, m_power); meter(m_oBuf, TX_PWR); n = CXBhave(m_oBuf); if (m_swapIQ) { for (unsigned int i = 0U; i < n; i++) { bufq[i] = CXBreal(m_oBuf, i); bufi[i] = CXBimag(m_oBuf, i); } } else { for (unsigned int i = 0U; i < n; i++) { bufi[i] = CXBreal(m_oBuf, i); bufq[i] = CXBimag(m_oBuf, i); } } m_tick++; }