mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 04:50:29 -04:00 
			
		
		
		
	DATV demod: leandvb: replace custom complex by std::complex
This commit is contained in:
		
							parent
							
								
									a066e4dbc1
								
							
						
					
					
						commit
						207115bc4c
					
				| @ -115,14 +115,14 @@ template<typename T> struct datvconstellation: runnable | ||||
|     long pixels_per_frame; | ||||
|     cstln_lut<eucl_ss, 256> **cstln;  // Optional ptr to optional constellation
 | ||||
|     TVScreen *m_objDATVScreen; | ||||
|     pipereader<complex<T> > in; | ||||
|     pipereader<std::complex<T> > in; | ||||
|     unsigned long phase; | ||||
|     std::vector<int> cstln_rows; | ||||
|     std::vector<int> cstln_cols; | ||||
| 
 | ||||
|     datvconstellation( | ||||
|             scheduler *sch, | ||||
|             pipebuf<complex<T> > &_in, | ||||
|             pipebuf<std::complex<T> > &_in, | ||||
|             T _xymin, | ||||
|             T _xymax, | ||||
|             const char *_name = nullptr, | ||||
| @ -148,13 +148,13 @@ template<typename T> struct datvconstellation: runnable | ||||
|             { | ||||
|                 m_objDATVScreen->resetImage(); | ||||
| 
 | ||||
|                 complex<T> *p = in.rd(), *pend = p + pixels_per_frame; | ||||
|                 std::complex<T> *p = in.rd(), *pend = p + pixels_per_frame; | ||||
| 
 | ||||
|                 for (; p < pend; ++p) | ||||
|                 { | ||||
|                     m_objDATVScreen->selectRow(256 * (p->re - xymin) / (xymax - xymin)); | ||||
|                     m_objDATVScreen->selectRow(256 * (p->real() - xymin) / (xymax - xymin)); | ||||
|                     m_objDATVScreen->setDataColor( | ||||
|                         256 - 256 * ((p->im - xymin) / (xymax - xymin)), | ||||
|                         256 - 256 * ((p->imag() - xymin) / (xymax - xymin)), | ||||
|                         255, 0, 255); | ||||
|                 } | ||||
| 
 | ||||
| @ -197,9 +197,9 @@ template<typename T> struct datvconstellation: runnable | ||||
| 
 | ||||
|         for (int i = 0; i < (*cstln)->nsymbols; ++i) | ||||
|         { | ||||
|             complex<signed char> *p = &(*cstln)->symbols[i]; | ||||
|             int x = 256 * (p->re - xymin) / (xymax - xymin); | ||||
|             int y = 256 - 256 * (p->im - xymin) / (xymax - xymin); | ||||
|             std::complex<signed char> *p = &(*cstln)->symbols[i]; | ||||
|             int x = 256 * (p->real() - xymin) / (xymax - xymin); | ||||
|             int y = 256 - 256 * (p->imag() - xymin) / (xymax - xymin); | ||||
| 
 | ||||
|             for (int d = -4; d <= 4; ++d) | ||||
|             { | ||||
|  | ||||
| @ -1289,9 +1289,9 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample | ||||
| 
 | ||||
|         for (int intI = 0 ; intI < intRFOut; intI++) | ||||
|         { | ||||
|             objIQ.re = objRF->real(); | ||||
|             objIQ.im = objRF->imag(); | ||||
|             magSq = objIQ.re*objIQ.re + objIQ.im*objIQ.im; | ||||
|             objIQ.real(objRF->real()); | ||||
|             objIQ.imag(objRF->imag()); | ||||
|             magSq = objIQ.real() * objIQ.real() + objIQ.imag() * objIQ.imag(); | ||||
|             m_objMagSqAverage(magSq); | ||||
| 
 | ||||
|             objRF ++; | ||||
|  | ||||
| @ -119,14 +119,14 @@ template<typename T> struct datvdvbs2constellation: runnable | ||||
|     long pixels_per_frame; | ||||
|     /*cstln_lut<llr_ss, 256>*/ cstln_base **cstln;  // Optional ptr to optional constellation
 | ||||
|     TVScreen *m_objDATVScreen; | ||||
|     pipereader<complex<T> > in; | ||||
|     pipereader<std::complex<T> > in; | ||||
|     unsigned long phase; | ||||
|     std::vector<int> cstln_rows; | ||||
|     std::vector<int> cstln_cols; | ||||
| 
 | ||||
|     datvdvbs2constellation( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T> > &_in, | ||||
|         pipebuf<std::complex<T> > &_in, | ||||
|         T _xymin, | ||||
|         T _xymax, | ||||
|         const char *_name = nullptr, | ||||
| @ -154,13 +154,13 @@ template<typename T> struct datvdvbs2constellation: runnable | ||||
|             { | ||||
|                 m_objDATVScreen->resetImage(); | ||||
| 
 | ||||
|                 complex<T> *p = in.rd(), *pend = p + pixels_per_frame; | ||||
|                 std::complex<T> *p = in.rd(), *pend = p + pixels_per_frame; | ||||
| 
 | ||||
|                 for (; p < pend; ++p) | ||||
|                 { | ||||
|                     m_objDATVScreen->selectRow(256 * (p->re - xymin) / (xymax - xymin)); | ||||
|                     m_objDATVScreen->selectRow(256 * (p->real() - xymin) / (xymax - xymin)); | ||||
|                     m_objDATVScreen->setDataColor( | ||||
|                         256 - 256 * ((p->im - xymin) / (xymax - xymin)), | ||||
|                         256 - 256 * ((p->imag() - xymin) / (xymax - xymin)), | ||||
|                         255, 0, 255); | ||||
|                 } | ||||
| 
 | ||||
| @ -203,9 +203,9 @@ template<typename T> struct datvdvbs2constellation: runnable | ||||
| 
 | ||||
|         for (int i = 0; i < (*cstln)->nsymbols; ++i) | ||||
|         { | ||||
|             complex<signed char> *p = &(*cstln)->symbols[i]; | ||||
|             int x = 256 * (p->re - xymin) / (xymax - xymin); | ||||
|             int y = 256 - 256 * (p->im - xymin) / (xymax - xymin); | ||||
|             std::complex<signed char> *p = &(*cstln)->symbols[i]; | ||||
|             int x = 256 * (p->real() - xymin) / (xymax - xymin); | ||||
|             int y = 256 - 256 * (p->imag() - xymin) / (xymax - xymin); | ||||
| 
 | ||||
|             for (int d = -4; d <= 4; ++d) | ||||
|             { | ||||
|  | ||||
| @ -28,15 +28,15 @@ namespace leansdr | ||||
| // DSP blocks
 | ||||
| //////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // [cconverter] converts complex streams between numric types,
 | ||||
| // [cconverter] converts std::complex streams between numric types,
 | ||||
| // with optional ofsetting and rational scaling.
 | ||||
| template <typename Tin, int Zin, typename Tout, int Zout, int Gn, int Gd> | ||||
| struct cconverter : runnable | ||||
| { | ||||
|     cconverter( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<Tin>> &_in, | ||||
|         pipebuf<complex<Tout>> &_out | ||||
|         pipebuf<std::complex<Tin>> &_in, | ||||
|         pipebuf<std::complex<Tout>> &_out | ||||
|     ) : | ||||
|         runnable(sch, "cconverter"), | ||||
|         in(_in), | ||||
| @ -47,8 +47,8 @@ struct cconverter : runnable | ||||
|     void run() | ||||
|     { | ||||
|         unsigned long count = min(in.readable(), out.writable()); | ||||
|         complex<Tin> *pin = in.rd(), *pend = pin + count; | ||||
|         complex<Tout> *pout = out.wr(); | ||||
|         std::complex<Tin> *pin = in.rd(), *pend = pin + count; | ||||
|         std::complex<Tout> *pout = out.wr(); | ||||
| 
 | ||||
|         for (; pin < pend; ++pin, ++pout) | ||||
|         { | ||||
| @ -61,8 +61,8 @@ struct cconverter : runnable | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<complex<Tin>> in; | ||||
|     pipewriter<complex<Tout>> out; | ||||
|     pipereader<std::complex<Tin>> in; | ||||
|     pipewriter<std::complex<Tout>> out; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| @ -109,18 +109,22 @@ struct cfft_engine | ||||
|         } | ||||
| 
 | ||||
|         // Float constants
 | ||||
|         omega = new complex<T>[n]; | ||||
|         omega_rev = new complex<T>[n]; | ||||
|         omega = new std::complex<T>[n]; | ||||
|         omega_rev = new std::complex<T>[n]; | ||||
| 
 | ||||
|         for (int i = 0; i < n; ++i) | ||||
|         { | ||||
|             float a = 2.0 * M_PI * i / n; | ||||
|             omega_rev[i].re = (omega[i].re = cosf(a)); | ||||
|             omega_rev[i].im = -(omega[i].im = sinf(a)); | ||||
|             omega_rev[i].real(cosf(a)); | ||||
|             omega[i].real(cosf(a)); | ||||
|             omega_rev[i].imag(sinf(a)); | ||||
|             omega[i].imag(sinf(a)); | ||||
|             // omega_rev[i].re = (omega[i].re = cosf(a));
 | ||||
|             // omega_rev[i].im = -(omega[i].im = sinf(a));
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void inplace(complex<T> *data, bool reverse = false) | ||||
|     void inplace(std::complex<T> *data, bool reverse = false) | ||||
|     { | ||||
|         // Bit-reversal permutation
 | ||||
|         for (int i = 0; i < n; ++i) | ||||
| @ -129,13 +133,13 @@ struct cfft_engine | ||||
| 
 | ||||
|             if (r < i) | ||||
|             { | ||||
|                 complex<T> tmp = data[i]; | ||||
|                 std::complex<T> tmp = data[i]; | ||||
|                 data[i] = data[r]; | ||||
|                 data[r] = tmp; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         complex<T> *om = reverse ? omega_rev : omega; | ||||
|         std::complex<T> *om = reverse ? omega_rev : omega; | ||||
|         // Danielson-Lanczos
 | ||||
|         for (int i = 0; i < logn; ++i) | ||||
|         { | ||||
| @ -148,14 +152,14 @@ struct cfft_engine | ||||
| 
 | ||||
|                 for (int k = 0; k < hbs; ++k) | ||||
|                 { | ||||
|                     complex<T> &w = om[k * dom]; | ||||
|                     complex<T> &dqk = data[q + k]; | ||||
|                     complex<T> x(w.re * dqk.re - w.im * dqk.im, | ||||
|                                  w.re * dqk.im + w.im * dqk.re); | ||||
|                     data[q + k].re = data[p + k].re - x.re; | ||||
|                     data[q + k].im = data[p + k].im - x.im; | ||||
|                     data[p + k].re = data[p + k].re + x.re; | ||||
|                     data[p + k].im = data[p + k].im + x.im; | ||||
|                     std::complex<T> &w = om[k * dom]; | ||||
|                     std::complex<T> &dqk = data[q + k]; | ||||
|                     std::complex<T> x(w.real() * dqk.real() - w.imag() * dqk.imag(), | ||||
|                                  w.real() * dqk.imag() + w.imag() * dqk.real()); | ||||
|                     data[q + k].real(data[p + k].real() - x.real()); | ||||
|                     data[q + k].imag(data[p + k].imag() - x.imag()); | ||||
|                     data[p + k].real(data[p + k].real() + x.real()); | ||||
|                     data[p + k].imag(data[p + k].imag() + x.imag()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @ -164,10 +168,8 @@ struct cfft_engine | ||||
|         { | ||||
|             float invn = 1.0 / n; | ||||
| 
 | ||||
|             for (int i = 0; i < n; ++i) | ||||
|             { | ||||
|                 data[i].re *= invn; | ||||
|                 data[i].im *= invn; | ||||
|             for (int i = 0; i < n; ++i) { | ||||
|                 data[i] *= invn; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -187,8 +189,8 @@ struct cfft_engine | ||||
|     } | ||||
| 
 | ||||
|     int *bitrev; | ||||
|     complex<T> *omega; | ||||
|     complex<T> *omega_rev; | ||||
|     std::complex<T> *omega; | ||||
|     std::complex<T> *omega_rev; | ||||
|     int n; | ||||
|     float invsqrtn; | ||||
|     int logn; | ||||
| @ -275,14 +277,14 @@ struct scaler : runnable | ||||
|     pipewriter<Tout> out; | ||||
| }; | ||||
| 
 | ||||
| // [awgb_c] generates complex white gaussian noise.
 | ||||
| // [awgb_c] generates std::complex white gaussian noise.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct wgn_c : runnable | ||||
| { | ||||
|     wgn_c( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> | ||||
|         pipebuf<std::complex<T>> | ||||
|         &_out | ||||
|     ) : | ||||
|         runnable(sch, "awgn"), | ||||
| @ -294,7 +296,7 @@ struct wgn_c : runnable | ||||
|     void run() | ||||
|     { | ||||
|         int n = out.writable(); | ||||
|         complex<T> *pout = out.wr(), *pend = pout + n; | ||||
|         std::complex<T> *pout = out.wr(), *pend = pout + n; | ||||
| 
 | ||||
|         while (pout < pend) | ||||
|         { | ||||
| @ -319,7 +321,7 @@ struct wgn_c : runnable | ||||
|     float stddev; | ||||
| 
 | ||||
|   private: | ||||
|     pipewriter<complex<T>> out; | ||||
|     pipewriter<std::complex<T>> out; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| @ -453,9 +455,9 @@ struct fir_filter : runnable | ||||
|         { | ||||
|             float a = 2 * M_PI * f * (i - ncoeffs / 2.0); | ||||
|             float c = cosf(a), s = sinf(a); | ||||
|             // TBD Support T=complex
 | ||||
|             shifted_coeffs[i].re = coeffs[i] * c; | ||||
|             shifted_coeffs[i].im = coeffs[i] * s; | ||||
|             // TBD Support T=std::complex
 | ||||
|             shifted_coeffs[i].real(coeffs[i] * c); | ||||
|             shifted_coeffs[i].imag(coeffs[i] * s); | ||||
|         } | ||||
|         current_freq = f; | ||||
|     } | ||||
| @ -556,7 +558,7 @@ struct fir_resampler : runnable | ||||
|         { | ||||
|             float a = 2 * M_PI * f * i; | ||||
|             float c = cosf(a), s = sinf(a); | ||||
|             // TBD Support T=complex
 | ||||
|             // TBD Support T=std::complex
 | ||||
|             shifted_coeffs[i].re = coeffs[i] * c; | ||||
|             shifted_coeffs[i].im = coeffs[i] * s; | ||||
|         } | ||||
|  | ||||
| @ -1733,8 +1733,8 @@ struct viterbi_sync : runnable | ||||
| 
 | ||||
|         for (int i = 0; i < cstln->nsymbols; ++i) | ||||
|         { | ||||
|             int8_t I = cstln->symbols[i].re; | ||||
|             int8_t Q = cstln->symbols[i].im; | ||||
|             int8_t I = cstln->symbols[i].real(); | ||||
|             int8_t Q = cstln->symbols[i].imag(); | ||||
| 
 | ||||
|             if (conj) | ||||
|                 Q = -Q; | ||||
|  | ||||
| @ -81,15 +81,15 @@ struct s2_sof | ||||
|     static const uint32_t VALUE = 0x18d2e82; | ||||
|     static const uint32_t MASK = 0x3ffffff; | ||||
|     static const int LENGTH = 26; | ||||
|     complex<T> symbols[LENGTH]; | ||||
|     std::complex<T> symbols[LENGTH]; | ||||
| 
 | ||||
|     s2_sof() | ||||
|     { | ||||
|         for (int s = 0; s < LENGTH; ++s) | ||||
|         { | ||||
|             int angle = ((VALUE >> (LENGTH - 1 - s)) & 1) * 2 + (s & 1); // pi/2-BPSK
 | ||||
|             symbols[s].re = cstln_amp * cosf(M_PI / 4 + 2 * M_PI * angle / 4); | ||||
|             symbols[s].im = cstln_amp * sinf(M_PI / 4 + 2 * M_PI * angle / 4); | ||||
|             symbols[s].real(cstln_amp * cosf(M_PI / 4 + 2 * M_PI * angle / 4)); | ||||
|             symbols[s].imag(cstln_amp * sinf(M_PI / 4 + 2 * M_PI * angle / 4)); | ||||
|         } | ||||
|     } | ||||
| }; // s2_sof
 | ||||
| @ -105,7 +105,7 @@ struct s2_plscodes | ||||
|     static const int COUNT = 128; | ||||
|     static const int LENGTH = 64; | ||||
|     uint64_t codewords[COUNT]; | ||||
|     complex<T> symbols[COUNT][LENGTH]; | ||||
|     std::complex<T> symbols[COUNT][LENGTH]; | ||||
| 
 | ||||
|     s2_plscodes() | ||||
|     { | ||||
| @ -149,8 +149,8 @@ struct s2_plscodes | ||||
|             { | ||||
|                 int yi = (code >> (LENGTH - 1 - i)) & 1; | ||||
|                 int nyi = yi ^ (i & 1); | ||||
|                 symbols[index][i].re = cstln_amp * (1 - 2 * nyi) / sqrtf(2); | ||||
|                 symbols[index][i].im = cstln_amp * (1 - 2 * yi) / sqrtf(2); | ||||
|                 symbols[index][i].real(cstln_amp * (1 - 2 * nyi) / sqrtf(2)); | ||||
|                 symbols[index][i].imag(cstln_amp * (1 - 2 * yi) / sqrtf(2)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -166,10 +166,12 @@ template<typename T> | ||||
| struct s2_pilot | ||||
| { | ||||
|     static const int LENGTH = PILOT_LENGTH; | ||||
|     complex<T> symbol; | ||||
|     std::complex<T> symbol; | ||||
| 
 | ||||
|     s2_pilot() { | ||||
|         symbol.re = symbol.im = cstln_amp*0.707107; | ||||
|     s2_pilot() | ||||
|     { | ||||
|         symbol.real(cstln_amp*0.707107); | ||||
|         symbol.imag(cstln_amp*0.707107); | ||||
|     } | ||||
| };  // s2_pilot
 | ||||
| 
 | ||||
| @ -375,21 +377,21 @@ struct s2_frame_transmitter : runnable | ||||
|     s2_frame_transmitter( | ||||
|         scheduler *sch, | ||||
|         pipebuf<plslot<hard_ss>> &_in, | ||||
|         pipebuf<complex<T>> &_out | ||||
|         pipebuf<std::complex<T>> &_out | ||||
|     ) : | ||||
|         runnable(sch, "S2 frame transmitter"), | ||||
|         in(_in), | ||||
|         out(_out, modcod_info::MAX_SYMBOLS_PER_FRAME) | ||||
|     { | ||||
|         float amp = cstln_amp / sqrtf(2); | ||||
|         qsymbols[0].re = +amp; | ||||
|         qsymbols[0].im = +amp; | ||||
|         qsymbols[1].re = +amp; | ||||
|         qsymbols[1].im = -amp; | ||||
|         qsymbols[2].re = -amp; | ||||
|         qsymbols[2].im = +amp; | ||||
|         qsymbols[3].re = -amp; | ||||
|         qsymbols[3].im = -amp; | ||||
|         qsymbols[0].real() = +amp; | ||||
|         qsymbols[0].imag() = +amp; | ||||
|         qsymbols[1].real() = +amp; | ||||
|         qsymbols[1].imag() = -amp; | ||||
|         qsymbols[2].real() = -amp; | ||||
|         qsymbols[2].imag() = +amp; | ||||
|         qsymbols[3].real() = -amp; | ||||
|         qsymbols[3].imag() = -amp; | ||||
| 
 | ||||
|         // Clear the constellation cache.
 | ||||
|         for (int i = 0; i < 32; ++i) { | ||||
| @ -443,10 +445,10 @@ struct s2_frame_transmitter : runnable | ||||
|         const modcod_info *mcinfo, | ||||
|         const plslot<hard_ss> *pin, | ||||
|         int nslots, | ||||
|         complex<T> *pout | ||||
|         std::complex<T> *pout | ||||
|     ) | ||||
|     { | ||||
|         complex<T> *pout0 = pout; // For sanity check
 | ||||
|         std::complex<T> *pout0 = pout; // For sanity check
 | ||||
|         // PLHEADER: SOF AND PLSCODE
 | ||||
|         // EN 302 307-1 section 5.5.2 PL signalling
 | ||||
|         memcpy(pout, sof.symbols, sof.LENGTH * sizeof(*pout)); | ||||
| @ -454,7 +456,7 @@ struct s2_frame_transmitter : runnable | ||||
|         int pls_index = (pls->modcod << 2) | (pls->sf << 1) | pls->pilots; | ||||
|         memcpy(pout, plscodes.symbols[pls_index], plscodes.LENGTH * sizeof(*pout)); | ||||
|         pout += plscodes.LENGTH; | ||||
|         complex<T> *csymbols = get_csymbols(pls->modcod); | ||||
|         std::complex<T> *csymbols = get_csymbols(pls->modcod); | ||||
|         // Slots and pilots
 | ||||
|         int till_next_pilot = pls->pilots ? 16 : nslots; | ||||
|         uint8_t *scr = &scrambling.Rn[0]; | ||||
| @ -485,7 +487,7 @@ struct s2_frame_transmitter : runnable | ||||
|         return pout - pout0; | ||||
|     } | ||||
| 
 | ||||
|     inline void scramble(const complex<T> *src, uint8_t r, complex<T> *dst) | ||||
|     inline void scramble(const std::complex<T> *src, uint8_t r, std::complex<T> *dst) | ||||
|     { | ||||
|         switch (r) | ||||
|         { | ||||
| @ -508,10 +510,10 @@ struct s2_frame_transmitter : runnable | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<plslot<hard_ss>> in; | ||||
|     pipewriter<complex<T>> out; | ||||
|     complex<T> *pcsymbols[32];  // Constellations in use, indexed by modcod
 | ||||
|     pipewriter<std::complex<T>> out; | ||||
|     std::complex<T> *pcsymbols[32];  // Constellations in use, indexed by modcod
 | ||||
| 
 | ||||
|     complex<T> *get_csymbols(int modcod) | ||||
|     std::complex<T> *get_csymbols(int modcod) | ||||
|     { | ||||
|         if (!pcsymbols[modcod]) | ||||
|         { | ||||
| @ -536,19 +538,19 @@ struct s2_frame_transmitter : runnable | ||||
|                 mcinfo->g3 | ||||
|             ); | ||||
| 
 | ||||
|             pcsymbols[modcod] = new complex<T>[cstln.nsymbols]; | ||||
|             pcsymbols[modcod] = new std::complex<T>[cstln.nsymbols]; | ||||
| 
 | ||||
|             for ( int s=0; s<cstln.nsymbols; ++s ) | ||||
|             { | ||||
|                 pcsymbols[modcod][s].re = cstln.symbols[s].re; | ||||
|                 pcsymbols[modcod][s].im = cstln.symbols[s].im; | ||||
|                 pcsymbols[modcod][s].real() = cstln.symbols[s].real(); | ||||
|                 pcsymbols[modcod][s].imag() = cstln.symbols[s].imag(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return pcsymbols[modcod]; | ||||
|     } | ||||
| 
 | ||||
|     complex<T> qsymbols[4]; // RMS cstln_amp
 | ||||
|     std::complex<T> qsymbols[4]; // RMS cstln_amp
 | ||||
|     s2_sof<T> sof; | ||||
|     s2_plscodes<T> plscodes; | ||||
|     s2_scrambling scrambling; | ||||
| @ -577,14 +579,14 @@ struct s2_frame_receiver : runnable | ||||
|     s2_frame_receiver( | ||||
|         scheduler *sch, | ||||
|         sampler_interface<T> *_sampler, | ||||
|         pipebuf< complex<T> > &_in, | ||||
|         pipebuf< std::complex<T> > &_in, | ||||
|         pipebuf< plslot<SOFTSYMB> > &_out, | ||||
|         pipebuf<float> *_freq_out=NULL, | ||||
|         pipebuf<float> *_ss_out=NULL, | ||||
|         pipebuf<float> *_mer_out=NULL, | ||||
|         pipebuf< complex<float> > *_cstln_out=NULL, | ||||
|         pipebuf< complex<float> > *_cstln_pls_out=NULL, | ||||
|         pipebuf< complex<float> > *_symbols_out=NULL, | ||||
|         pipebuf< std::complex<float> > *_cstln_out=NULL, | ||||
|         pipebuf< std::complex<float> > *_cstln_pls_out=NULL, | ||||
|         pipebuf< std::complex<float> > *_symbols_out=NULL, | ||||
|         pipebuf<int> *_state_out=NULL | ||||
|     ) : | ||||
|         runnable(sch, "S2 frame receiver"), | ||||
| @ -662,7 +664,7 @@ struct s2_frame_receiver : runnable | ||||
|     // Useful for looking ahead (e.g. next pilots/SOF) then rewinding.
 | ||||
| 
 | ||||
|     struct sampler_state { | ||||
|         complex<T> *p;  // Pointer to samples (update when entering run())
 | ||||
|         std::complex<T> *p;  // Pointer to samples (update when entering run())
 | ||||
|         float mu;       // Time of next symbol, counted from p
 | ||||
|         float omega;    // Samples per symbol
 | ||||
|         float gain;     // Scaling factor toward cstln_amp
 | ||||
| @ -689,7 +691,7 @@ struct s2_frame_receiver : runnable | ||||
|             sprintf( | ||||
|                 buf, | ||||
|                 "%9.2lf %+6.0f ppm  %+3.0f °  %f", | ||||
|                 (double)((p-(complex<T>*)NULL)&262143)+mu,  // Arbitrary wrap
 | ||||
|                 (double)((p-(std::complex<T>*)NULL)&262143)+mu,  // Arbitrary wrap
 | ||||
|                 fw16*1e6/65536, | ||||
|                 fmodfs(ph16,65536.0f)*360/65536, | ||||
|                 gain | ||||
| @ -857,7 +859,7 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     void run_frame_probe_locked() | ||||
|     { | ||||
|         complex<float> *psampled;  // Data symbols (one per slot)
 | ||||
|         std::complex<float> *psampled;  // Data symbols (one per slot)
 | ||||
| 
 | ||||
|         if (cstln_out && cstln_out->writable()>=1024) { | ||||
|             psampled = cstln_out->wr(); | ||||
| @ -865,7 +867,7 @@ struct s2_frame_receiver : runnable | ||||
|             psampled = NULL; | ||||
|         } | ||||
| 
 | ||||
|         complex<float> *psampled_pls;  // PLHEADER symbols
 | ||||
|         std::complex<float> *psampled_pls;  // PLHEADER symbols
 | ||||
| 
 | ||||
|         if (cstln_pls_out && cstln_pls_out->writable()>=1024) { | ||||
|             psampled_pls = cstln_pls_out->wr(); | ||||
| @ -873,7 +875,7 @@ struct s2_frame_receiver : runnable | ||||
|             psampled_pls = NULL; | ||||
|         } | ||||
| #if TEST_DIVERSITY | ||||
|         complex<float> *psymbols = symbols_out ? symbols_out->wr() : NULL; | ||||
|         std::complex<float> *psymbols = symbols_out ? symbols_out->wr() : NULL; | ||||
|         float scale_symbols = 1.0 / cstln_amp; | ||||
| #endif | ||||
|         sampler_state ss = ss_cache; | ||||
| @ -886,11 +888,11 @@ struct s2_frame_receiver : runnable | ||||
|         // Interpolate PLHEADER.
 | ||||
| 
 | ||||
|         const int PLH_LENGTH = sof.LENGTH + plscodes.LENGTH; | ||||
|         complex<float> plh_symbols[PLH_LENGTH]; | ||||
|         std::complex<float> plh_symbols[PLH_LENGTH]; | ||||
| 
 | ||||
|         for (int s=0; s<PLH_LENGTH; ++s) | ||||
|         { | ||||
|             complex<float> p = interp_next(&ss) * ss.gain; | ||||
|             std::complex<float> p = interp_next(&ss) * ss.gain; | ||||
|             plh_symbols[s] = p; | ||||
| 
 | ||||
|             if (psampled_pls) { | ||||
| @ -905,10 +907,10 @@ struct s2_frame_receiver : runnable | ||||
|         // Optimization with half loop and even/odd processing in a single step
 | ||||
|         for (int i = 0; i < sof.LENGTH/2; ++i) | ||||
|         { | ||||
|             complex<float> p0 = plh_symbols[2*i]; | ||||
|             complex<float> p1 = plh_symbols[2*i+1]; | ||||
|             float d0 = p0.im + p0.re; | ||||
|             float d1 = p1.im - p1.re; | ||||
|             std::complex<float> p0 = plh_symbols[2*i]; | ||||
|             std::complex<float> p1 = plh_symbols[2*i+1]; | ||||
|             float d0 = p0.imag() + p0.real(); | ||||
|             float d1 = p1.imag() - p1.real(); | ||||
|             sof_bits = (sof_bits<<2) | ((d0<0)<<1) | (d1<0); | ||||
|         } | ||||
| 
 | ||||
| @ -934,10 +936,10 @@ struct s2_frame_receiver : runnable | ||||
|         // Optimization with half loop and even/odd processing in a single step
 | ||||
|         for (int i=0; i<plscodes.LENGTH/2; ++i) | ||||
|         { | ||||
|             complex<float> p0 = plh_symbols[sof.LENGTH+2*i]; | ||||
|             complex<float> p1 = plh_symbols[sof.LENGTH+2*i+1]; | ||||
|             float d0 = p0.im + p0.re; | ||||
|             float d1 = p1.im - p1.re; | ||||
|             std::complex<float> p0 = plh_symbols[sof.LENGTH+2*i]; | ||||
|             std::complex<float> p1 = plh_symbols[sof.LENGTH+2*i+1]; | ||||
|             float d0 = p0.imag() + p0.real(); | ||||
|             float d1 = p1.imag() - p1.real(); | ||||
|             plscode = (plscode<<2) | ((d0<0)<<1) | (d1<0); | ||||
|         } | ||||
| 
 | ||||
| @ -984,7 +986,7 @@ struct s2_frame_receiver : runnable | ||||
|         // ss now points to first data slot.
 | ||||
|         ss.scr = scrambling.Rn; | ||||
| 
 | ||||
|         complex<float> plh_expected[PLH_LENGTH]; | ||||
|         std::complex<float> plh_expected[PLH_LENGTH]; | ||||
| 
 | ||||
|         std::copy(sof.symbols, sof.symbols + sof.LENGTH, plh_expected); | ||||
|         std::copy(plscodes.symbols[plscode_index], plscodes.symbols[plscode_index] + plscodes.LENGTH, &plh_expected[sof.LENGTH]); | ||||
| @ -1254,7 +1256,7 @@ struct s2_frame_receiver : runnable | ||||
|             // Read slot.
 | ||||
|             freq_stats.add(ss.fw16); | ||||
|             pout->is_pls = false; | ||||
|             complex<float> p;  // Export last symbols for cstln_out
 | ||||
|             std::complex<float> p;  // Export last symbols for cstln_out
 | ||||
| 
 | ||||
|         	for (int s=0; s<pout->LENGTH; ++s) | ||||
|             { | ||||
| @ -1267,11 +1269,11 @@ struct s2_frame_receiver : runnable | ||||
|                     (void) track_symbol(&ss, p, dcstln);  // SLOW
 | ||||
|                 } | ||||
| 
 | ||||
| 	            complex<float> d = descramble(&ss, p); | ||||
| 	            std::complex<float> d = descramble(&ss, p); | ||||
| #if 1  // Slow
 | ||||
| 	            SOFTSYMB *symb = &dcstln->lookup(d.re, d.im)->ss; | ||||
| 	            SOFTSYMB *symb = &dcstln->lookup(d.real(), d.imag())->ss; | ||||
| #else  // Avoid scaling floats. May wrap at very low SNR.
 | ||||
| 	            SOFTSYMB *symb = &dcstln->lookup((int)d.re, (int)d.im)->ss; | ||||
| 	            SOFTSYMB *symb = &dcstln->lookup((int)d.real(), (int)d.imag())->ss; | ||||
| #endif | ||||
| 	            pout->symbols[s] = *symb; | ||||
| 	        } | ||||
| @ -1356,7 +1358,7 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     float find_plheader(sampler_state *pss, int search_range) | ||||
|     { | ||||
|         complex<T> best_corr = 0; | ||||
|         std::complex<T> best_corr = 0; | ||||
|         int best_imu = 0;  // Avoid compiler warning.
 | ||||
|         int best_pos = 0;  // Avoid compiler warning.
 | ||||
| 
 | ||||
| @ -1371,15 +1373,15 @@ struct s2_frame_receiver : runnable | ||||
|                 delete[] diffs; | ||||
|             } | ||||
| 
 | ||||
|             diffs = new complex<T>[ndiffs]; | ||||
|             diffs = new std::complex<T>[ndiffs]; | ||||
|             sampler_state ss = *pss; | ||||
|             ss.mu += imu * ss.omega / interp; | ||||
| 
 | ||||
|             // Compute rotation between consecutive symbols.
 | ||||
|             complex<T> prev = 0; | ||||
|             std::complex<T> prev = 0; | ||||
|             for (int i=0; i<ndiffs; ++i) | ||||
|             { | ||||
|                 complex<T> p = interp_next(&ss); | ||||
|                 std::complex<T> p = interp_next(&ss); | ||||
|                 diffs[i] = conjprod(prev, p); | ||||
|                 prev = p; | ||||
|             } | ||||
| @ -1388,10 +1390,10 @@ struct s2_frame_receiver : runnable | ||||
|             const int ncorrs = search_range; | ||||
|             for (int i=0; i<ncorrs; ++i) | ||||
|             { | ||||
|                 complex<T> c = correlate_plheader_diff(&diffs[i]); | ||||
|                 std::complex<T> c = correlate_plheader_diff(&diffs[i]); | ||||
|                 //if ( cnorm2(c) > cnorm2(best_corr) ) {
 | ||||
|                 // c.im>0 enforces frequency error +-Fm/4
 | ||||
|                 if (cnorm2(c)>cnorm2(best_corr) && c.im>0) | ||||
|                 // c.imag()>0 enforces frequency error +-Fm/4
 | ||||
|                 if (cnorm2(c)>cnorm2(best_corr) && c.imag()>0) | ||||
|                 { | ||||
|                     best_corr = c; | ||||
|                     best_imu = imu; | ||||
| @ -1407,14 +1409,14 @@ struct s2_frame_receiver : runnable | ||||
| #if 0 | ||||
|         // Lowpass-filter the differential correlator.
 | ||||
|         // (Does not help much.)
 | ||||
|         static complex<float> acc = 0; | ||||
|         static std::complex<float> acc = 0; | ||||
|         static const float k = 0.05; | ||||
|         acc = best_corr*k + acc*(1-k); | ||||
|         best_corr = acc; | ||||
| #endif | ||||
|         // Get rough estimate of carrier frequency from differential correlator.
 | ||||
|         // (best_corr is nominally +j).
 | ||||
|         float freqw = atan2f(-best_corr.re, best_corr.im); | ||||
|         float freqw = atan2f(-best_corr.real(), best_corr.imag()); | ||||
|         pss->fw16 += freqw * 65536 / (2*M_PI); | ||||
|         // Force refresh because correction may be large.
 | ||||
|         sampler->update_freq(pss->fw16/omega0); | ||||
| @ -1427,7 +1429,7 @@ struct s2_frame_receiver : runnable | ||||
|         { | ||||
|             sampler_state ss = *pss; | ||||
|             float power = 0; | ||||
|             complex<T> symbs[sof.LENGTH]; | ||||
|             std::complex<T> symbs[sof.LENGTH]; | ||||
| 
 | ||||
|             for (int i=0; i<sof.LENGTH; ++i) | ||||
|             { | ||||
| @ -1435,7 +1437,7 @@ struct s2_frame_receiver : runnable | ||||
|                 power += cnorm2(symbs[i]); | ||||
|             } | ||||
| 
 | ||||
|             complex<float> c = conjprod(sof.symbols, symbs, sof.LENGTH); | ||||
|             std::complex<float> c = conjprod(sof.symbols, symbs, sof.LENGTH); | ||||
|             c *= 1.0f / sof.LENGTH; | ||||
|             align_phase(pss, c); | ||||
|             float signal_amp = sqrtf(power/sof.LENGTH); | ||||
| @ -1448,22 +1450,22 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     // Correlate PLHEADER.
 | ||||
| 
 | ||||
|     complex<float> correlate_plheader_diff(complex<T> *diffs) | ||||
|     std::complex<float> correlate_plheader_diff(std::complex<T> *diffs) | ||||
|     { | ||||
|         complex<T> csof = correlate_sof_diff(diffs); | ||||
|         complex<T> cplsc = correlate_plscode_diff(&diffs[sof.LENGTH]); | ||||
|         std::complex<T> csof = correlate_sof_diff(diffs); | ||||
|         std::complex<T> cplsc = correlate_plscode_diff(&diffs[sof.LENGTH]); | ||||
|         // Use csof+cplsc or csof-cplsc, whichever maximizes likelihood.
 | ||||
|         complex<T> c0 = csof + cplsc;  // Best when b7==0 (pilots off)
 | ||||
|         complex<T> c1 = csof - cplsc;  // Best when b7==1 (pilots on)
 | ||||
|         complex<T> c = (cnorm2(c0)>cnorm2(c1)) ? c0 : c1; | ||||
|         std::complex<T> c0 = csof + cplsc;  // Best when b7==0 (pilots off)
 | ||||
|         std::complex<T> c1 = csof - cplsc;  // Best when b7==1 (pilots on)
 | ||||
|         std::complex<T> c = (cnorm2(c0)>cnorm2(c1)) ? c0 : c1; | ||||
|         return c * (1.0f/(26-1+64/2)); | ||||
|     } | ||||
| 
 | ||||
|     // Correlate 25 differential transitions in SOF.
 | ||||
| 
 | ||||
|     complex<float> correlate_sof_diff(complex<T> *diffs) | ||||
|     std::complex<float> correlate_sof_diff(std::complex<T> *diffs) | ||||
|     { | ||||
|         complex<T> c = 0; | ||||
|         std::complex<T> c = 0; | ||||
|         const uint32_t dsof = sof.VALUE ^ (sof.VALUE>>1); | ||||
| 
 | ||||
|         for (int i=0; i<sof.LENGTH; ++i) | ||||
| @ -1484,9 +1486,9 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     // Correlate 32 data-independent transitions in PLSCODE.
 | ||||
| 
 | ||||
|     complex<float> correlate_plscode_diff(complex<T> *diffs) | ||||
|     std::complex<float> correlate_plscode_diff(std::complex<T> *diffs) | ||||
|     { | ||||
|         complex<T> c = 0; | ||||
|         std::complex<T> c = 0; | ||||
|         uint64_t dscr = plscodes.SCRAMBLING ^ (plscodes.SCRAMBLING>>1); | ||||
| 
 | ||||
|         for (int i=1; i<plscodes.LENGTH; i+=2) | ||||
| @ -1534,8 +1536,8 @@ struct s2_frame_receiver : runnable | ||||
|     // spans less than 90°.
 | ||||
| 
 | ||||
|     void match_freq( | ||||
|         complex<float> *expect, | ||||
|         complex<float> *recv, | ||||
|         std::complex<float> *expect, | ||||
|         std::complex<float> *recv, | ||||
|         int ns, | ||||
| 		sampler_state *ss) | ||||
|     { | ||||
| @ -1543,16 +1545,16 @@ struct s2_frame_receiver : runnable | ||||
|             fprintf(stderr, "match_freq\n"); | ||||
|         } | ||||
| 
 | ||||
|         complex<float> diff = 0; | ||||
|         std::complex<float> diff = 0; | ||||
| 
 | ||||
|         for (int i=0; i<ns-1; ++i) | ||||
|         { | ||||
|             complex<float> de = conjprod(expect[i], expect[i+1]); | ||||
|             complex<float> dr = conjprod(recv[i], recv[i+1]); | ||||
|             std::complex<float> de = conjprod(expect[i], expect[i+1]); | ||||
|             std::complex<float> dr = conjprod(recv[i], recv[i+1]); | ||||
|             diff += conjprod(de, dr); | ||||
|         } | ||||
| 
 | ||||
|         float dfw16 = atan2f(diff.im,diff.re) * 65536 / (2*M_PI); | ||||
|         float dfw16 = atan2f(diff.imag(),diff.real()) * 65536 / (2*M_PI); | ||||
| 
 | ||||
|         // Derotate.
 | ||||
|         for (int i=0; i<ns; ++i) { | ||||
| @ -1568,15 +1570,15 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     float interp_match_pilot(sampler_state *pss) | ||||
|     { | ||||
|         complex<T> symbols[pilot.LENGTH]; | ||||
|         complex<T> expected[pilot.LENGTH]; | ||||
|         std::complex<T> symbols[pilot.LENGTH]; | ||||
|         std::complex<T> expected[pilot.LENGTH]; | ||||
| 
 | ||||
|         for (int i=0; i<pilot.LENGTH; ++i) | ||||
|         { | ||||
|             complex<float> p = interp_next(pss) * pss->gain; | ||||
|             std::complex<float> p = interp_next(pss) * pss->gain; | ||||
|             symbols[i] = descramble(pss, p); | ||||
|             expected[i] = pilot.symbol; | ||||
|             //fprintf(stderr, "%f %f\n", symbols[i].re, symbols[i].im);
 | ||||
|             //fprintf(stderr, "%f %f\n", symbols[i].real(), symbols[i].imag());
 | ||||
|         } | ||||
| 
 | ||||
|         return match_ph_amp(expected, symbols, pilot.LENGTH, pss); | ||||
| @ -1587,7 +1589,7 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     float interp_match_sof(sampler_state *pss) | ||||
|     { | ||||
|         complex<T> symbols[pilot.LENGTH]; | ||||
|         std::complex<T> symbols[pilot.LENGTH]; | ||||
| 
 | ||||
|         for (int i=0; i<sof.LENGTH; ++i) { | ||||
|             symbols[i] = interp_next(pss) * pss->gain; | ||||
| @ -1606,27 +1608,27 @@ struct s2_frame_receiver : runnable | ||||
|     // Idempotent.
 | ||||
| 
 | ||||
|     float match_ph_amp( | ||||
|         complex<float> *expect, | ||||
|         complex<float> *recv, | ||||
|         std::complex<float> *expect, | ||||
|         std::complex<float> *recv, | ||||
|         int ns, | ||||
| 		sampler_state *ss | ||||
|     ) | ||||
|     { | ||||
|         complex<float> rr = 0; | ||||
|         std::complex<float> rr = 0; | ||||
| 
 | ||||
|         for (int i=0; i<ns; ++i) { | ||||
|             rr += conjprod(expect[i], recv[i]); | ||||
|         } | ||||
| 
 | ||||
|         rr *= 1.0f / (ns*cstln_amp); | ||||
|         float dph16 = atan2f(rr.im,rr.re) * 65536 / (2*M_PI); | ||||
|         float dph16 = atan2f(rr.imag(),rr.real()) * 65536 / (2*M_PI); | ||||
|         ss->ph16 += dph16; | ||||
|         rr *= trig.expi(-dph16); | ||||
|         // rr.re is now the modulation amplitude.
 | ||||
|         float dgain = cstln_amp / rr.re; | ||||
|         // rr.real() is now the modulation amplitude.
 | ||||
|         float dgain = cstln_amp / rr.real(); | ||||
|         ss->gain *= dgain; | ||||
|         // Rotate and scale.  Compute error power.
 | ||||
|         complex<float> adj = trig.expi(-dph16) * dgain; | ||||
|         std::complex<float> adj = trig.expi(-dph16) * dgain; | ||||
|         float ev2 = 0; | ||||
| 
 | ||||
|         for (int i=0; i<ns; ++i) | ||||
| @ -1680,11 +1682,11 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|             for (int s = 0; s < ns; ++s) | ||||
|             { | ||||
|                 complex<float> p = interp_next(&ssl) * ssl.gain; | ||||
|                 std::complex<float> p = interp_next(&ssl) * ssl.gain; | ||||
|                 typename cstln_lut<SOFTSYMB,256>::result *cr = | ||||
|                     dcstln->lookup(p.re, p.im); | ||||
|                 complex<int8_t> &cp = dcstln->symbols[cr->symbol]; | ||||
|                 complex<float> ev(p.re-cp.re, p.im-cp.im); | ||||
|                     dcstln->lookup(p.real(), p.imag()); | ||||
|                 std::complex<int8_t> &cp = dcstln->symbols[cr->symbol]; | ||||
|                 std::complex<float> ev(p.real()-cp.real(), p.imag()-cp.imag()); | ||||
|                 err += cnorm2(ev); | ||||
|             } | ||||
| 
 | ||||
| @ -1718,24 +1720,24 @@ struct s2_frame_receiver : runnable | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     complex<float> descramble(sampler_state *ss, const complex<float> &p) | ||||
|     std::complex<float> descramble(sampler_state *ss, const std::complex<float> &p) | ||||
|     { | ||||
|         int r = *ss->scr++; | ||||
|         complex<float> res; | ||||
|         std::complex<float> res; | ||||
| 
 | ||||
|         switch (r) | ||||
|         { | ||||
|         case 3: | ||||
|             res.re = -p.im; | ||||
|             res.im =  p.re; | ||||
|             res.real(-p.imag()); | ||||
|             res.imag(p.real()); | ||||
|             break; | ||||
|         case 2: | ||||
|             res.re = -p.re; | ||||
|             res.im = -p.im; | ||||
|             res.real(-p.real()); | ||||
|             res.imag(-p.imag()); | ||||
|             break; | ||||
|         case 1: | ||||
|             res.re =  p.im; | ||||
|             res.im = -p.re; | ||||
|             res.real(p.imag()); | ||||
|             res.imag(-p.real()); | ||||
|             break; | ||||
|         default: | ||||
|             res = p; | ||||
| @ -1746,7 +1748,7 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     // Interpolator
 | ||||
| 
 | ||||
|     inline complex<float> interp_next(sampler_state *ss) | ||||
|     inline std::complex<float> interp_next(sampler_state *ss) | ||||
|     { | ||||
|         // Skip to next sample
 | ||||
|         while (ss->mu >= 1) | ||||
| @ -1759,16 +1761,16 @@ struct s2_frame_receiver : runnable | ||||
|         // Interpolate linearly then derotate.
 | ||||
|         // This will fail with large carrier offsets (e.g. --tune).
 | ||||
|         float cmu = 1.0f - ss->mu; | ||||
|         complex<float> s(ss->p[0].re*cmu + ss->p[1].re*ss->mu, | ||||
|                 ss->p[0].im*cmu + ss->p[1].im*ss->mu); | ||||
|         std::complex<float> s(ss->p[0].real()*cmu + ss->p[1].real()*ss->mu, | ||||
|                 ss->p[0].imag()*cmu + ss->p[1].imag()*ss->mu); | ||||
|         ss->mu += ss->omega; | ||||
|         // Derotate
 | ||||
|         const complex<float> &rot = trig.expi(-ss->ph16); | ||||
|         const std::complex<float> &rot = trig.expi(-ss->ph16); | ||||
|         ss->ph16 += ss->fw16; | ||||
|         return rot * s; | ||||
| #else | ||||
|         // Use generic interpolator
 | ||||
|         complex<float> s = sampler->interp(ss->p, ss->mu, ss->ph16); | ||||
|         std::complex<float> s = sampler->interp(ss->p, ss->mu, ss->ph16); | ||||
|         ss->mu += ss->omega; | ||||
|         ss->ph16 += ss->fw16; | ||||
|         return s; | ||||
| @ -1777,22 +1779,22 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     // Adjust phase in [ss] to cancel offset observed as [c].
 | ||||
| 
 | ||||
|     void align_phase(sampler_state *ss, const complex<float> &c) | ||||
|     void align_phase(sampler_state *ss, const std::complex<float> &c) | ||||
|     { | ||||
|         float err = atan2f(c.im,c.re) * 65536 / (2*M_PI); | ||||
|         float err = atan2f(c.imag(),c.real()) * 65536 / (2*M_PI); | ||||
|         ss->ph16 += err; | ||||
|     } | ||||
| 
 | ||||
|     inline uint8_t track_symbol( | ||||
|         sampler_state *ss, | ||||
|         const complex<float> &p, | ||||
|         const std::complex<float> &p, | ||||
| 		cstln_lut<SOFTSYMB,256> *c | ||||
|     ) | ||||
|     { | ||||
|         static const float kph = 4e-2; | ||||
|         static const float kfw = 1e-4; | ||||
|         // Decision
 | ||||
|         typename cstln_lut<SOFTSYMB,256>::result *cr = c->lookup(p.re, p.im); | ||||
|         typename cstln_lut<SOFTSYMB,256>::result *cr = c->lookup(p.real(), p.imag()); | ||||
|         // Carrier tracking
 | ||||
|         ss->ph16 += cr->phase_error * kph; | ||||
|         ss->fw16 += cr->phase_error * kfw; | ||||
| @ -1848,13 +1850,13 @@ struct s2_frame_receiver : runnable | ||||
| 
 | ||||
|     cstln_lut<SOFTSYMB,256> *cstln;  // Last seen, or NULL (legacy)
 | ||||
|     trig16 trig; | ||||
|     pipereader< complex<T> > in; | ||||
|     pipereader< std::complex<T> > in; | ||||
|     pipewriter< plslot<SOFTSYMB> > out; | ||||
|     int meas_count; | ||||
|     pipewriter<float> *freq_out, *ss_out, *mer_out; | ||||
|     pipewriter< complex<float> > *cstln_out; | ||||
|     pipewriter< complex<float> > *cstln_pls_out; | ||||
|     pipewriter< complex<float> > *symbols_out; | ||||
|     pipewriter< std::complex<float> > *cstln_out; | ||||
|     pipewriter< std::complex<float> > *cstln_pls_out; | ||||
|     pipewriter< std::complex<float> > *symbols_out; | ||||
|     pipewriter<int> *state_out; | ||||
|     bool first_run; | ||||
|     // S2 constants
 | ||||
| @ -1868,7 +1870,7 @@ struct s2_frame_receiver : runnable | ||||
|     bool m_locked; | ||||
| 
 | ||||
| private: | ||||
|     complex<T> *diffs; | ||||
|     std::complex<T> *diffs; | ||||
|     sampler_state *sspilots; | ||||
|   };  // s2_frame_receiver
 | ||||
| 
 | ||||
|  | ||||
| @ -32,7 +32,7 @@ void normalize_power(int n, T *coeffs, float gain = 1) | ||||
|     float s2 = 0; | ||||
| 
 | ||||
|     for (int i = 0; i < n; ++i) { | ||||
|         s2 = s2 + coeffs[i] * coeffs[i]; // TBD complex
 | ||||
|         s2 = s2 + coeffs[i] * coeffs[i]; // TBD std::complex
 | ||||
|     } | ||||
| 
 | ||||
|     if (s2) { | ||||
|  | ||||
| @ -260,7 +260,7 @@ struct file_printer : runnable | ||||
| 
 | ||||
| // [file_carrayprinter] writes all data available from a [pipebuf]
 | ||||
| // to a file descriptor on a single line.
 | ||||
| // Special case for complex.
 | ||||
| // Special case for std::complex.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| struct file_carrayprinter : runnable | ||||
| @ -271,7 +271,7 @@ struct file_carrayprinter : runnable | ||||
|         const char *_format, | ||||
|         const char *_sep, | ||||
|         const char *_tail, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         int _fdout | ||||
|     ) : | ||||
|         runnable(sch, _in.name), | ||||
| @ -299,7 +299,7 @@ struct file_carrayprinter : runnable | ||||
|             if (fout) | ||||
|             { | ||||
|                 fprintf(fout, head, n); | ||||
|                 complex<T> *pin = in.rd(); | ||||
|                 std::complex<T> *pin = in.rd(); | ||||
| 
 | ||||
|                 for (int i = 0; i < n; ++i) | ||||
|                 { | ||||
| @ -307,7 +307,7 @@ struct file_carrayprinter : runnable | ||||
|                         fprintf(fout, "%s", sep); | ||||
|                     } | ||||
| 
 | ||||
|                     fprintf(fout, format, pin[i].re * scale, pin[i].im * scale); | ||||
|                     fprintf(fout, format, pin[i].real() * scale, pin[i].imag() * scale); | ||||
|                 } | ||||
| 
 | ||||
|                 fprintf(fout, "%s", tail); | ||||
| @ -322,7 +322,7 @@ struct file_carrayprinter : runnable | ||||
|     int fixed_size; // Number of elements per batch, or 0.
 | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     const char *head, *format, *sep, *tail; | ||||
|     FILE *fout; | ||||
| }; | ||||
|  | ||||
| @ -182,7 +182,7 @@ struct cscope : runnable | ||||
|     unsigned long decimation; | ||||
|     unsigned long pixels_per_frame; | ||||
|     cstln_base **cstln; // Optional ptr to optional constellation
 | ||||
|     cscope(scheduler *sch, pipebuf<complex<T>> &_in, T _xymin, T _xymax, | ||||
|     cscope(scheduler *sch, pipebuf<std::complex<T>> &_in, T _xymin, T _xymax, | ||||
|            const char *_name = NULL) | ||||
|         : runnable(sch, _name ? _name : _in.name), | ||||
|           xymin(_xymin), xymax(_xymax), | ||||
| @ -199,7 +199,7 @@ struct cscope : runnable | ||||
|             { | ||||
|                 draw_begin(); | ||||
|                 g.setfg(0, 255, 0); | ||||
|                 complex<T> *p = in.rd(), *pend = p + pixels_per_frame; | ||||
|                 std::complex<T> *p = in.rd(), *pend = p + pixels_per_frame; | ||||
|                 for (; p < pend; ++p) | ||||
|                     g.point(g.w * (p->re - xymin) / (xymax - xymin), | ||||
|                             g.h - g.h * (p->im - xymin) / (xymax - xymin)); | ||||
| @ -209,7 +209,7 @@ struct cscope : runnable | ||||
|                     g.setfg(255, 255, 255); | ||||
|                     for (int i = 0; i < (*cstln)->nsymbols; ++i) | ||||
|                     { | ||||
|                         complex<signed char> *p = &(*cstln)->symbols[i]; | ||||
|                         std::complex<signed char> *p = &(*cstln)->symbols[i]; | ||||
|                         int x = g.w * (p->re - xymin) / (xymax - xymin); | ||||
|                         int y = g.h - g.h * (p->im - xymin) / (xymax - xymin); | ||||
|                         for (int d = -2; d <= 2; ++d) | ||||
| @ -228,7 +228,7 @@ struct cscope : runnable | ||||
|         } | ||||
|     } | ||||
|     //private:
 | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     unsigned long phase; | ||||
|     gfx g; | ||||
|     void draw_begin() | ||||
| @ -459,7 +459,7 @@ struct spectrumscope : runnable | ||||
|     unsigned long size; | ||||
|     float amax; | ||||
|     unsigned long decimation; | ||||
|     spectrumscope(scheduler *sch, pipebuf<complex<T>> &_in, | ||||
|     spectrumscope(scheduler *sch, pipebuf<std::complex<T>> &_in, | ||||
|                   T _max, const char *_name = NULL) | ||||
|         : runnable(sch, _name ? _name : _in.name), | ||||
|           size(4096), amax(_max / sqrtf(size)), | ||||
| @ -488,14 +488,14 @@ struct spectrumscope : runnable | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     static const int MAX_MARKERS = 4; | ||||
|     float markers[MAX_MARKERS]; | ||||
|     int nmarkers; | ||||
|     int phase; | ||||
|     gfx g; | ||||
|     cfft_engine<float> *fft; | ||||
|     void do_fft(complex<T> *input) | ||||
|     void do_fft(std::complex<T> *input) | ||||
|     { | ||||
|         draw_begin(); | ||||
|         if (!fft || fft->n != size) | ||||
| @ -504,8 +504,8 @@ struct spectrumscope : runnable | ||||
|                 delete fft; | ||||
|             fft = new cfft_engine<float>(size); | ||||
|         } | ||||
|         complex<T> *pin = input, *pend = pin + size; | ||||
|         complex<float> data[size], *pout = data; | ||||
|         std::complex<T> *pin = input, *pend = pin + size; | ||||
|         std::complex<float> data[size], *pout = data; | ||||
|         g.setfg(255, 0, 0); | ||||
|         for (int x = 0; pin < pend; ++pin, ++pout, ++x) | ||||
|         { | ||||
| @ -518,9 +518,9 @@ struct spectrumscope : runnable | ||||
|         for (int i = 0; i < size; ++i) | ||||
|         { | ||||
|             int x = ((i < size / 2) ? i + size / 2 : i - size / 2) * g.w / size; | ||||
|             complex<float> v = data[i]; | ||||
|             std::complex<float> v = data[i]; | ||||
|             ; | ||||
|             float y = hypot(v.re, v.im); | ||||
|             float y = hypot(v.real(), v.imag()); | ||||
|             g.line(x, g.h - 1, x, g.h - 1 - y * g.h / amax); | ||||
|         } | ||||
|         if (g.buttons) | ||||
| @ -559,7 +559,7 @@ struct rfscope : runnable | ||||
|     float hzoom;        // Horizontal zoom factor
 | ||||
|     float db0, dbrange; // Vertical range db0 .. db0+dbrange
 | ||||
|     float bw;           // Smoothing bandwidth
 | ||||
|     rfscope(scheduler *sch, pipebuf<complex<T>> &_in, | ||||
|     rfscope(scheduler *sch, pipebuf<std::complex<T>> &_in, | ||||
|             const char *_name = NULL) | ||||
|         : runnable(sch, _name ? _name : _in.name), | ||||
|           size(4096), decimation(DEFAULT_GUI_DECIMATION), | ||||
| @ -581,13 +581,13 @@ struct rfscope : runnable | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     int phase; | ||||
|     gfx g; | ||||
|     cfft_engine<float> *fft; | ||||
|     float *filtered; | ||||
| 
 | ||||
|     void do_fft(complex<T> *input) | ||||
|     void do_fft(std::complex<T> *input) | ||||
|     { | ||||
|         g.events(); | ||||
|         draw_begin(); | ||||
| @ -597,9 +597,9 @@ struct rfscope : runnable | ||||
|                 delete fft; | ||||
|             fft = new cfft_engine<float>(size); | ||||
|         } | ||||
|         // Convert to complex<float> and transform
 | ||||
|         complex<T> *pin = input, *pend = pin + size; | ||||
|         complex<float> data[size], *pout = data; | ||||
|         // Convert to std::complex<float> and transform
 | ||||
|         std::complex<T> *pin = input, *pend = pin + size; | ||||
|         std::complex<float> data[size], *pout = data; | ||||
|         for (int x = 0; pin < pend; ++pin, ++pout, ++x) | ||||
|         { | ||||
|             pout->re = (float)pin->re; | ||||
| @ -609,9 +609,9 @@ struct rfscope : runnable | ||||
|         float amp2[size]; | ||||
|         for (int i = 0; i < size; ++i) | ||||
|         { | ||||
|             complex<float> &v = data[i]; | ||||
|             std::complex<float> &v = data[i]; | ||||
|             ; | ||||
|             amp2[i] = (v.re * v.re + v.im * v.im) * size; | ||||
|             amp2[i] = (v.real() * v.real() + v.imag() * v.imag()) * size; | ||||
|         } | ||||
|         if (!filtered) | ||||
|         { | ||||
|  | ||||
| @ -18,76 +18,12 @@ | ||||
| #define LEANSDR_MATH_H | ||||
| 
 | ||||
| #include <cmath> | ||||
| #include <complex> | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| namespace leansdr | ||||
| { | ||||
| 
 | ||||
| template <typename T> | ||||
| struct complex | ||||
| { | ||||
|     T re, im; | ||||
| 
 | ||||
|     complex() {} | ||||
| 
 | ||||
|     complex(T x) : re(x), im(0) {} | ||||
|     complex(T x, T y) : re(x), im(y) {} | ||||
| 
 | ||||
|     inline void operator+=(const complex<T> &x) | ||||
|     { | ||||
|         re += x.re; | ||||
|         im += x.im; | ||||
|     } | ||||
| 
 | ||||
|     inline void operator*=(const complex<T> &c) | ||||
|     { | ||||
|         T tre = re * c.re - im * c.im; | ||||
|         im = re * c.im + im * c.re; | ||||
|         re = tre; | ||||
|     } | ||||
| 
 | ||||
|     inline void operator-=(const complex<T> &x) | ||||
|     { | ||||
|         re-=x.re; | ||||
|         im-=x.im; | ||||
|     } | ||||
| 
 | ||||
|     inline void operator*=(const T &k) | ||||
|     { | ||||
|         re *= k; | ||||
|         im *= k; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| complex<T> operator+(const complex<T> &a, const complex<T> &b) | ||||
| { | ||||
|     return complex<T>(a.re + b.re, a.im + b.im); | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| complex<T> operator -(const complex<T> &a, const complex<T> &b) { | ||||
|     return complex<T>(a.re - b.re, a.im - b.im); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| complex<T> operator*(const complex<T> &a, const complex<T> &b) | ||||
| { | ||||
|     return complex<T>(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| complex<T> operator*(const complex<T> &a, const T &k) | ||||
| { | ||||
|     return complex<T>(a.re * k, a.im * k); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| complex<T> operator*(const T &k, const complex<T> &a) | ||||
| { | ||||
|     return complex<T>(k * a.re, k * a.im); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| T dotprod(const T *u, const T *v, int n) | ||||
| { | ||||
| @ -101,13 +37,13 @@ T dotprod(const T *u, const T *v, int n) | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline T cnorm2(const complex<T> &u) | ||||
| inline T cnorm2(const std::complex<T> &u) | ||||
| { | ||||
|     return u.re * u.re + u.im * u.im; | ||||
|     return u.real() * u.real() + u.imag() * u.imag(); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| T cnorm2(const complex<T> *p, int n) | ||||
| T cnorm2(const std::complex<T> *p, int n) | ||||
| { | ||||
|     T res = 0; | ||||
| 
 | ||||
| @ -120,19 +56,19 @@ T cnorm2(const complex<T> *p, int n) | ||||
| 
 | ||||
| // Return conj(u)*v
 | ||||
| template <typename T> | ||||
| inline complex<T> conjprod(const complex<T> &u, const complex<T> &v) | ||||
| inline std::complex<T> conjprod(const std::complex<T> &u, const std::complex<T> &v) | ||||
| { | ||||
|     return complex<T>( | ||||
|         u.re * v.re + u.im * v.im, | ||||
|         u.re * v.im - u.im * v.re | ||||
|     return std::complex<T>( | ||||
|         u.real() * v.real() + u.imag() * v.imag(), | ||||
|         u.real() * v.imag() - u.imag() * v.real() | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| // Return sum(conj(u[i])*v[i])
 | ||||
| template <typename T> | ||||
| complex<T> conjprod(const complex<T> *u, const complex<T> *v, int n) | ||||
| std::complex<T> conjprod(const std::complex<T> *u, const std::complex<T> *v, int n) | ||||
| { | ||||
|     complex<T> acc = 0; | ||||
|     std::complex<T> acc = 0; | ||||
| 
 | ||||
|     while (n--) { | ||||
|         acc += conjprod(*u++, *v++); | ||||
| @ -156,25 +92,24 @@ int log2i(uint64_t x); | ||||
| 
 | ||||
| struct trig16 | ||||
| { | ||||
|     complex<float> lut[65536]; // TBD static and shared
 | ||||
|     std::complex<float> lut[65536]; // TBD static and shared
 | ||||
| 
 | ||||
|     trig16() | ||||
|     { | ||||
|         for (int a = 0; a < 65536; ++a) | ||||
|         { | ||||
|             float af = a * 2 * M_PI / 65536; | ||||
|             lut[a].re = cosf(af); | ||||
|             lut[a].im = sinf(af); | ||||
|             lut[a] = {cosf(af), sinf(af)}; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     inline const complex<float> &expi(uint16_t a) const | ||||
|     inline const std::complex<float> &expi(uint16_t a) const | ||||
|     { | ||||
|         return lut[a]; | ||||
|     } | ||||
| 
 | ||||
|     // a must fit in a int32_t, otherwise behaviour is undefined
 | ||||
|     inline const complex<float> &expi(float a) const | ||||
|     inline const std::complex<float> &expi(float a) const | ||||
|     { | ||||
|         return expi((uint16_t)(int16_t)(int32_t)a); | ||||
|     } | ||||
|  | ||||
| @ -18,6 +18,7 @@ | ||||
| #define LEANSDR_SDR_H | ||||
| 
 | ||||
| #include <numeric> | ||||
| #include <complex> | ||||
| 
 | ||||
| #include "leansdr/dsp.h" | ||||
| #include "leansdr/math.h" | ||||
| @ -29,11 +30,11 @@ namespace leansdr | ||||
| 
 | ||||
| typedef float f32; | ||||
| 
 | ||||
| typedef complex<u8> cu8; | ||||
| typedef complex<s8> cs8; | ||||
| typedef complex<u16> cu16; | ||||
| typedef complex<s16> cs16; | ||||
| typedef complex<f32> cf32; | ||||
| typedef std::complex<u8> cu8; | ||||
| typedef std::complex<s8> cs8; | ||||
| typedef std::complex<u16> cu16; | ||||
| typedef std::complex<s16> cs16; | ||||
| typedef std::complex<f32> cf32; | ||||
| 
 | ||||
| //////////////////////////////////////////////////////////////////////
 | ||||
| // SDR blocks
 | ||||
| @ -52,8 +53,8 @@ struct auto_notch : runnable | ||||
| 
 | ||||
|     auto_notch( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<complex<T>> &_out, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_out, | ||||
|         int _nslots, | ||||
|         T _agc_rms_setpoint | ||||
|     ) : | ||||
| @ -73,7 +74,7 @@ struct auto_notch : runnable | ||||
|         for (int s = 0; s < nslots; ++s) | ||||
|         { | ||||
|             __slots[s].i = -1; | ||||
|             __slots[s].expj = new complex<float>[fft.size()]; | ||||
|             __slots[s].expj = new std::complex<float>[fft.size()]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -106,22 +107,21 @@ struct auto_notch : runnable | ||||
| 
 | ||||
|     void detect() | ||||
|     { | ||||
|         complex<T> *pin = in.rd(); | ||||
|         complex<float> *data = new complex<float>[fft.size()]; | ||||
|         std::complex<T> *pin = in.rd(); | ||||
|         std::complex<float> *data = new std::complex<float>[fft.size()]; | ||||
|         float m0 = 0, m2 = 0; | ||||
| 
 | ||||
|         for (int i = 0; i < fft.size(); ++i) | ||||
|         { | ||||
|             data[i].re = pin[i].re; | ||||
|             data[i].im = pin[i].im; | ||||
|             m2 += (float)pin[i].re * pin[i].re + (float)pin[i].im * pin[i].im; | ||||
|             data[i] = pin[i]; | ||||
|             m2 += (float) pin[i].real() * pin[i].real() + (float) pin[i].imag() * pin[i].imag(); | ||||
| 
 | ||||
|             if (gen_abs(pin[i].re) > m0) { | ||||
|                 m0 = gen_abs(pin[i].re); | ||||
|             if (gen_abs(pin[i].real()) > m0) { | ||||
|                 m0 = gen_abs(pin[i].real()); | ||||
|             } | ||||
| 
 | ||||
|             if (gen_abs(pin[i].im) > m0) { | ||||
|                 m0 = gen_abs(pin[i].im); | ||||
|             if (gen_abs(pin[i].imag()) > m0) { | ||||
|                 m0 = gen_abs(pin[i].imag()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -141,7 +141,7 @@ struct auto_notch : runnable | ||||
|         float *amp = new float[fft.size()]; | ||||
| 
 | ||||
|         for (int i = 0; i < fft.size(); ++i) { | ||||
|             amp[i] = hypotf(data[i].re, data[i].im); | ||||
|             amp[i] = hypotf(data[i].real(), data[i].imag()); | ||||
|         } | ||||
| 
 | ||||
|         for (slot *s = __slots; s < __slots + nslots; ++s) | ||||
| @ -162,15 +162,15 @@ struct auto_notch : runnable | ||||
|                 } | ||||
| 
 | ||||
|                 s->i = iamax; | ||||
|                 s->estim.re = 0; | ||||
|                 s->estim.im = 0; | ||||
|                 s->estim.real(0); | ||||
|                 s->estim.imag(0); | ||||
|                 s->estt = 0; | ||||
| 
 | ||||
|                 for (int i = 0; i < fft.size(); ++i) | ||||
|                 { | ||||
|                     float a = 2 * M_PI * s->i * i / fft.size(); | ||||
|                     s->expj[i].re = cosf(a); | ||||
|                     s->expj[i].im = sinf(a); | ||||
|                     s->expj[i].real(cosf(a)); | ||||
|                     s->expj[i].imag(sinf(a)); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| @ -191,7 +191,7 @@ struct auto_notch : runnable | ||||
| 
 | ||||
|     void process() | ||||
|     { | ||||
|         complex<T> *pin = in.rd(), *pend = pin + fft.size(), *pout = out.wr(); | ||||
|         std::complex<T> *pin = in.rd(), *pend = pin + fft.size(), *pout = out.wr(); | ||||
| 
 | ||||
|         for (slot *s = __slots; s < __slots + nslots; ++s) { | ||||
|             s->ej = s->expj; | ||||
| @ -199,41 +199,41 @@ struct auto_notch : runnable | ||||
| 
 | ||||
|         for (; pin < pend; ++pin, ++pout) | ||||
|         { | ||||
|             complex<float> out = *pin; | ||||
|             std::complex<float> out = *pin; | ||||
|             // TODO Optimize for nslots==1 ?
 | ||||
| 
 | ||||
|             for (slot *s = __slots; s < __slots + nslots; ++s->ej, ++s) | ||||
|             { | ||||
|                 complex<float> bb( | ||||
|                     pin->re * s->ej->re + pin->im * s->ej->im, | ||||
|                     -pin->re * s->ej->im + pin->im * s->ej->re | ||||
|                 std::complex<float> bb( | ||||
|                     pin->real() * s->ej->real() + pin->imag() * s->ej->imag(), | ||||
|                     -pin->real() * s->ej->imag() + pin->imag() * s->ej->real() | ||||
|                 ); | ||||
|                 s->estim.re = bb.re * k + s->estim.re * (1 - k); | ||||
|                 s->estim.im = bb.im * k + s->estim.im * (1 - k); | ||||
|                 complex<float> sub( | ||||
|                     s->estim.re * s->ej->re - s->estim.im * s->ej->im, | ||||
|                     s->estim.re * s->ej->im + s->estim.im * s->ej->re | ||||
|                 s->estim.real(bb.real() * k + s->estim.real() * (1 - k)); | ||||
|                 s->estim.imag(bb.imag() * k + s->estim.imag() * (1 - k)); | ||||
|                 std::complex<float> sub( | ||||
|                     s->estim.real() * s->ej->real() - s->estim.imag() * s->ej->imag(), | ||||
|                     s->estim.real() * s->ej->imag() + s->estim.imag() * s->ej->real() | ||||
|                 ); | ||||
|                 out.re -= sub.re; | ||||
|                 out.im -= sub.im; | ||||
|                 out.real(out.real() - sub.real()); | ||||
|                 out.imag(out.imag() - sub.imag()); | ||||
|             } | ||||
| 
 | ||||
|             pout->re = gain * out.re; | ||||
|             pout->im = gain * out.im; | ||||
|             pout->real(gain * out.real()); | ||||
|             pout->imag(gain * out.imag()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     cfft_engine<float> fft; | ||||
|     pipereader<complex<T>> in; | ||||
|     pipewriter<complex<T>> out; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     pipewriter<std::complex<T>> out; | ||||
|     int nslots; | ||||
| 
 | ||||
|     struct slot | ||||
|     { | ||||
|         int i; | ||||
|         complex<float> estim; | ||||
|         complex<float> *expj, *ej; | ||||
|         std::complex<float> estim; | ||||
|         std::complex<float> *expj, *ej; | ||||
|         int estt; | ||||
|     }; | ||||
| 
 | ||||
| @ -255,7 +255,7 @@ struct ss_estimator : runnable | ||||
| 
 | ||||
|     ss_estimator( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<T> &_out | ||||
|     ) : | ||||
|         runnable(sch, "SS estimator"), | ||||
| @ -276,11 +276,11 @@ struct ss_estimator : runnable | ||||
|             if (phase >= decimation) | ||||
|             { | ||||
|                 phase -= decimation; | ||||
|                 complex<T> *p = in.rd(), *pend = p + window_size; | ||||
|                 std::complex<T> *p = in.rd(), *pend = p + window_size; | ||||
|                 float s = 0; | ||||
| 
 | ||||
|                 for (; p < pend; ++p) { | ||||
|                     s += (float)p->re * p->re + (float)p->im * p->im; | ||||
|                     s += (float)p->real() * p->real() + (float)p->imag() * p->imag(); | ||||
|                 } | ||||
| 
 | ||||
|                 out.write(sqrtf(s / window_size)); | ||||
| @ -291,7 +291,7 @@ struct ss_estimator : runnable | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     pipewriter<T> out; | ||||
|     unsigned long phase; | ||||
| }; | ||||
| @ -304,7 +304,7 @@ struct ss_amp_estimator : runnable | ||||
| 
 | ||||
|     ss_amp_estimator( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<T> &_out_ss, | ||||
|         pipebuf<T> &_out_ampmin, | ||||
|         pipebuf<T> &_out_ampmax | ||||
| @ -329,13 +329,13 @@ struct ss_amp_estimator : runnable | ||||
|             if (phase >= decimation) | ||||
|             { | ||||
|                 phase -= decimation; | ||||
|                 complex<T> *p = in.rd(), *pend = p + window_size; | ||||
|                 std::complex<T> *p = in.rd(), *pend = p + window_size; | ||||
|                 float s2 = 0; | ||||
|                 float amin = 1e38, amax = 0; | ||||
| 
 | ||||
|                 for (; p < pend; ++p) | ||||
|                 { | ||||
|                     float mag2 = (float)p->re * p->re + (float)p->im * p->im; | ||||
|                     float mag2 = (float)p->real() * p->real() + (float)p->imag() * p->imag(); | ||||
|                     s2 += mag2; | ||||
|                     float mag = sqrtf(mag2); | ||||
| 
 | ||||
| @ -358,7 +358,7 @@ struct ss_amp_estimator : runnable | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     pipewriter<T> out_ss, out_ampmin, out_ampmax; | ||||
|     unsigned long phase; | ||||
| }; | ||||
| @ -375,8 +375,8 @@ struct simple_agc : runnable | ||||
| 
 | ||||
|     simple_agc( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<complex<T>> &_out | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_out | ||||
|     ) : | ||||
|         runnable(sch, "AGC"), | ||||
|         out_rms(1), | ||||
| @ -388,18 +388,18 @@ struct simple_agc : runnable | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<complex<T>> in; | ||||
|     pipewriter<complex<T>> out; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     pipewriter<std::complex<T>> out; | ||||
| 
 | ||||
|     void run() | ||||
|     { | ||||
|         while (in.readable() >= chunk_size && out.writable() >= chunk_size) | ||||
|         { | ||||
|             complex<T> *pin = in.rd(), *pend = pin + chunk_size; | ||||
|             std::complex<T> *pin = in.rd(), *pend = pin + chunk_size; | ||||
|             float amp2 = 0; | ||||
| 
 | ||||
|             for (; pin < pend; ++pin) { | ||||
|                 amp2 += pin->re * pin->re + pin->im * pin->im; | ||||
|                 amp2 += pin->real() * pin->real() + pin->imag() * pin->imag(); | ||||
|             } | ||||
| 
 | ||||
|             amp2 /= chunk_size; | ||||
| @ -411,13 +411,13 @@ struct simple_agc : runnable | ||||
|             estimated = estimated * (1 - bw) + amp2 * bw; | ||||
|             float gain = estimated ? out_rms / sqrtf(estimated) : 0; | ||||
|             pin = in.rd(); | ||||
|             complex<T> *pout = out.wr(); | ||||
|             std::complex<T> *pout = out.wr(); | ||||
|             float bwcomp = 1 - bw; | ||||
| 
 | ||||
|             for (; pin < pend; ++pin, ++pout) | ||||
|             { | ||||
|                 pout->re = pin->re * gain; | ||||
|                 pout->im = pin->im * gain; | ||||
|                 pout->real() = pin->real() * gain; | ||||
|                 pout->imag() = pin->imag() * gain; | ||||
|             } | ||||
| 
 | ||||
|             in.read(chunk_size); | ||||
| @ -521,7 +521,7 @@ struct cstln_base | ||||
| 
 | ||||
|     static const char *names[]; | ||||
|     float amp_max; // Max amplitude. 1 for PSK, 0 if not applicable.
 | ||||
|     complex<int8_t> *symbols; | ||||
|     std::complex<int8_t> *symbols; | ||||
|     int nsymbols; | ||||
|     int nrotations; | ||||
| }; | ||||
| @ -546,7 +546,7 @@ struct cstln_lut : cstln_base | ||||
|             amp_max = 1; | ||||
|             nrotations = 2; | ||||
|             nsymbols = 2; | ||||
|             symbols = new complex<signed char>[nsymbols]; | ||||
|             symbols = new std::complex<signed char>[nsymbols]; | ||||
| #if 0 // BPSK at 0°
 | ||||
|             symbols[0] = polar(1, 2, 0); | ||||
|             symbols[1] = polar(1, 2, 1); | ||||
| @ -564,7 +564,7 @@ struct cstln_lut : cstln_base | ||||
|             // EN 302 307, section 5.4.1
 | ||||
|             nrotations = 4; | ||||
|             nsymbols = 4; | ||||
|             symbols = new complex<signed char>[nsymbols]; | ||||
|             symbols = new std::complex<signed char>[nsymbols]; | ||||
|             symbols[0] = polar(1, 4, 0.5); | ||||
|             symbols[1] = polar(1, 4, 3.5); | ||||
|             symbols[2] = polar(1, 4, 1.5); | ||||
| @ -577,7 +577,7 @@ struct cstln_lut : cstln_base | ||||
|             // EN 302 307, section 5.4.2
 | ||||
|             nrotations = 8; | ||||
|             nsymbols = 8; | ||||
|             symbols = new complex<signed char>[nsymbols]; | ||||
|             symbols = new std::complex<signed char>[nsymbols]; | ||||
|             symbols[0] = polar(1, 8, 1); | ||||
|             symbols[1] = polar(1, 8, 0); | ||||
|             symbols[2] = polar(1, 8, 4); | ||||
| @ -600,7 +600,7 @@ struct cstln_lut : cstln_base | ||||
|             amp_max = r2; | ||||
|             nrotations = 4; | ||||
|             nsymbols = 16; | ||||
|             symbols = new complex<signed char>[nsymbols]; | ||||
|             symbols = new std::complex<signed char>[nsymbols]; | ||||
|             symbols[0] = polar(r2, 12, 1.5); | ||||
|             symbols[1] = polar(r2, 12, 10.5); | ||||
|             symbols[2] = polar(r2, 12, 4.5); | ||||
| @ -636,7 +636,7 @@ struct cstln_lut : cstln_base | ||||
|             amp_max = r3; | ||||
|             nrotations = 4; | ||||
|             nsymbols = 32; | ||||
|             symbols = new complex<signed char>[nsymbols]; | ||||
|             symbols = new std::complex<signed char>[nsymbols]; | ||||
|             symbols[0] = polar(r2, 12, 1.5); | ||||
|             symbols[1] = polar(r2, 12, 2.5); | ||||
|             symbols[2] = polar(r2, 12, 10.5); | ||||
| @ -691,7 +691,7 @@ struct cstln_lut : cstln_base | ||||
|             amp_max = r4; | ||||
|             nrotations = 4; | ||||
|             nsymbols = 64; | ||||
|             symbols = new complex<signed char>[nsymbols]; | ||||
|             symbols = new std::complex<signed char>[nsymbols]; | ||||
|             polar2(0, r4, 1.0 / 4, 7.0 / 4, 3.0 / 4, 5.0 / 4); | ||||
|             polar2(4, r4, 13.0 / 28, 43.0 / 28, 15.0 / 28, 41.0 / 28); | ||||
|             polar2(8, r4, 1.0 / 28, 55.0 / 28, 27.0 / 28, 29.0 / 28); | ||||
| @ -770,10 +770,10 @@ struct cstln_lut : cstln_base | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     complex<signed char> polar(float r, int n, float i) | ||||
|     std::complex<signed char> polar(float r, int n, float i) | ||||
|     { | ||||
|         float a = i * 2 * M_PI / n; | ||||
|         return complex<signed char>( | ||||
|         return std::complex<signed char>( | ||||
|             r * cosf(a) * cstln_amp, | ||||
|             r * sinf(a) * cstln_amp | ||||
|         ); | ||||
| @ -787,7 +787,7 @@ struct cstln_lut : cstln_base | ||||
|         for (int j = 0; j < 4; ++j) | ||||
|         { | ||||
|             float phi = a[j] * M_PI; | ||||
|             symbols[i + j] = complex<signed char>( | ||||
|             symbols[i + j] = std::complex<signed char>( | ||||
|                 r * cosf(phi) * cstln_amp, | ||||
|                 r * sinf(phi) * cstln_amp | ||||
|             ); | ||||
| @ -798,7 +798,7 @@ struct cstln_lut : cstln_base | ||||
|     { | ||||
|         nrotations = 4; | ||||
|         nsymbols = n; | ||||
|         symbols = new complex<signed char>[nsymbols]; | ||||
|         symbols = new std::complex<signed char>[nsymbols]; | ||||
|         int m = sqrtl(n); | ||||
|         float scale; | ||||
| 
 | ||||
| @ -817,8 +817,8 @@ struct cstln_lut : cstln_base | ||||
|             { | ||||
|                 float I = x - (float)(m - 1) / 2; | ||||
|                 float Q = y - (float)(m - 1) / 2; | ||||
|                 symbols[s].re = I * scale * cstln_amp; | ||||
|                 symbols[s].im = Q * scale * cstln_amp; | ||||
|                 symbols[s].real(I * scale * cstln_amp); | ||||
|                 symbols[s].imag(Q * scale * cstln_amp); | ||||
|                 ++s; | ||||
|             } | ||||
|         } | ||||
| @ -861,7 +861,7 @@ struct cstln_lut : cstln_base | ||||
| 
 | ||||
|                 for (int s = 0; s < nsymbols; ++s) | ||||
|                 { | ||||
|                     float d2 = ((I - symbols[s].re) * (I - symbols[s].re) + (Q - symbols[s].im) * (Q - symbols[s].im)); | ||||
|                     float d2 = ((I - symbols[s].real()) * (I - symbols[s].real()) + (Q - symbols[s].imag()) * (Q - symbols[s].imag())); | ||||
| 
 | ||||
|                     if (d2 < fss.dists2[fss.nearest]) { | ||||
|                         fss.nearest = s; | ||||
| @ -893,8 +893,8 @@ struct cstln_lut : cstln_base | ||||
|                 // Always record nearest symbol and phase error for C&T.
 | ||||
|                 pr->symbol = fss.nearest; | ||||
|                 float ph_symbol = atan2f( | ||||
|                     symbols[pr->symbol].im, | ||||
|                     symbols[pr->symbol].re | ||||
|                     symbols[pr->symbol].imag(), | ||||
|                     symbols[pr->symbol].real() | ||||
|                 ); | ||||
|                 float ph_err = atan2f(Q, I) - ph_symbol; | ||||
|                 pr->phase_error = (int32_t)(ph_err * 65536 / (2 * M_PI)); // Mod 65536
 | ||||
| @ -926,7 +926,7 @@ struct cstln_lut : cstln_base | ||||
|                     // Highlight the constellation symbols.
 | ||||
|                     for (int s = 0; s < nsymbols; ++s) | ||||
|                     { | ||||
|                         if (symbols[s].re == I && symbols[s].im == Q) { | ||||
|                         if (symbols[s].real() == I && symbols[s].imag() == Q) { | ||||
|                             v ^= 128; | ||||
|                         } | ||||
|                     } | ||||
| @ -962,7 +962,7 @@ struct sampler_interface | ||||
|     virtual ~sampler_interface() { | ||||
|     } | ||||
| 
 | ||||
|     virtual complex<T> interp(const complex<T> *pin, float mu, float phase) = 0; | ||||
|     virtual std::complex<T> interp(const std::complex<T> *pin, float mu, float phase) = 0; | ||||
| 
 | ||||
|     virtual void update_freq(float freqw, int weight = 0) | ||||
|     { | ||||
| @ -983,7 +983,7 @@ struct nearest_sampler : sampler_interface<T> | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     complex<T> interp(const complex<T> *pin, float mu, float phase) | ||||
|     std::complex<T> interp(const std::complex<T> *pin, float mu, float phase) | ||||
|     { | ||||
|         (void) mu; | ||||
|         return pin[0] * trig.expi(-phase); | ||||
| @ -1003,11 +1003,11 @@ struct linear_sampler : sampler_interface<T> | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     complex<T> interp(const complex<T> *pin, float mu, float phase) | ||||
|     std::complex<T> interp(const std::complex<T> *pin, float mu, float phase) | ||||
|     { | ||||
|         // Derotate pin[0] and pin[1]
 | ||||
|         complex<T> s0 = pin[0] * trig.expi(-phase); | ||||
|         complex<T> s1 = pin[1] * trig.expi(-(phase + freqw)); | ||||
|         std::complex<T> s0 = pin[0] * trig.expi(-phase); | ||||
|         std::complex<T> s1 = pin[1] * trig.expi(-(phase + freqw)); | ||||
|         // Interpolate linearly
 | ||||
|         return s0 * (1 - mu) + s1 * mu; | ||||
|     } | ||||
| @ -1035,7 +1035,7 @@ struct fir_sampler : sampler_interface<T> | ||||
|         subsampling(_subsampling), | ||||
|         update_freq_phase(0) | ||||
|     { | ||||
|         shifted_coeffs = new complex<T>[ncoeffs]; | ||||
|         shifted_coeffs = new std::complex<T>[ncoeffs]; | ||||
|         do_update_freq(0); // In case application never calls update_freq()
 | ||||
|     } | ||||
| 
 | ||||
| @ -1048,12 +1048,12 @@ struct fir_sampler : sampler_interface<T> | ||||
|         return ncoeffs - 1; | ||||
|     } | ||||
| 
 | ||||
|     complex<T> interp(const complex<T> *pin, float mu, float phase) | ||||
|     std::complex<T> interp(const std::complex<T> *pin, float mu, float phase) | ||||
|     { | ||||
|         // Apply FIR filter with subsampling
 | ||||
|         complex<T> acc(0, 0); | ||||
|         complex<T> *pc = shifted_coeffs + (int)((1 - mu) * subsampling); | ||||
|         complex<T> *pcend = shifted_coeffs + ncoeffs; | ||||
|         std::complex<T> acc(0, 0); | ||||
|         std::complex<T> *pc = shifted_coeffs + (int)((1 - mu) * subsampling); | ||||
|         std::complex<T> *pcend = shifted_coeffs + ncoeffs; | ||||
| 
 | ||||
|         if (subsampling == 1) | ||||
|         { | ||||
| @ -1133,7 +1133,7 @@ struct cstln_receiver : runnable | ||||
|     cstln_receiver( | ||||
|         scheduler *sch, | ||||
|         sampler_interface<T> *_sampler, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<SOFTSYMB> &_out, | ||||
|         pipebuf<float> *_freq_out = nullptr, | ||||
|         pipebuf<float> *_ss_out = nullptr, | ||||
| @ -1264,13 +1264,13 @@ struct cstln_receiver : runnable | ||||
|         { | ||||
|             sampler->update_freq(freqw, chunk_size); | ||||
| 
 | ||||
|             complex<T> *pin = in.rd(), *pin0 = pin, *pend = pin + chunk_size; | ||||
|             std::complex<T> *pin = in.rd(), *pin0 = pin, *pend = pin + chunk_size; | ||||
|             SOFTSYMB *pout = out.wr(), *pout0 = pout; | ||||
| 
 | ||||
|             // These are scoped outside the loop for SS and MER estimation.
 | ||||
|             complex<float> sg{0.0f, 0.0f}; // Symbol before AGC;
 | ||||
|             complex<float> s;  // For MER estimation and constellation viewer
 | ||||
|             complex<signed char> *cstln_point = nullptr; | ||||
|             std::complex<float> sg{0.0f, 0.0f}; // Symbol before AGC;
 | ||||
|             std::complex<float> s;  // For MER estimation and constellation viewer
 | ||||
|             std::complex<signed char> *cstln_point = nullptr; | ||||
| 
 | ||||
|             while (pin < pend) | ||||
|             { | ||||
| @ -1284,7 +1284,7 @@ struct cstln_receiver : runnable | ||||
| 
 | ||||
|                     // Constellation look-up
 | ||||
|                     typename cstln_lut<SOFTSYMB, 256>::result *cr = | ||||
|                         cstln->lookup(s.re, s.im); | ||||
|                         cstln->lookup(s.real(), s.imag()); | ||||
|                     *pout = cr->ss; | ||||
|                     ++pout; | ||||
| 
 | ||||
| @ -1299,13 +1299,13 @@ struct cstln_receiver : runnable | ||||
|                     // c = decisions (constellation points)
 | ||||
|                     hist[2] = hist[1]; | ||||
|                     hist[1] = hist[0]; | ||||
|                     hist[0].p.re = s.re; | ||||
|                     hist[0].p.im = s.im; | ||||
|                     hist[0].p.real(s.real()); | ||||
|                     hist[0].p.imag(s.imag()); | ||||
|                     cstln_point = &cstln->symbols[cr->symbol]; | ||||
|                     hist[0].c.re = cstln_point->re; | ||||
|                     hist[0].c.im = cstln_point->im; | ||||
|                     float muerr = ((hist[0].p.re - hist[2].p.re) * hist[1].c.re + (hist[0].p.im - hist[2].p.im) * hist[1].c.im) | ||||
|                         - ((hist[0].c.re - hist[2].c.re) * hist[1].p.re + (hist[0].c.im - hist[2].c.im) * hist[1].p.im); | ||||
|                     hist[0].c.real(cstln_point->real()); | ||||
|                     hist[0].c.imag(cstln_point->imag()); | ||||
|                     float muerr = ((hist[0].p.real() - hist[2].p.real()) * hist[1].c.real() + (hist[0].p.imag() - hist[2].p.imag()) * hist[1].c.imag()) | ||||
|                         - ((hist[0].c.real() - hist[2].c.real()) * hist[1].p.real() + (hist[0].c.imag() - hist[2].c.imag()) * hist[1].p.imag()); | ||||
|                     float mucorr = muerr * gain_mu; | ||||
|                     const float max_mucorr = 0.1; | ||||
| 
 | ||||
| @ -1346,7 +1346,7 @@ struct cstln_receiver : runnable | ||||
|                 // AGC
 | ||||
|                 // For APSK we must do AGC on the symbols, not the whole signal.
 | ||||
|                 // TODO Use a better estimator at low SNR.
 | ||||
|                 float insp = sg.re * sg.re + sg.im * sg.im; | ||||
|                 float insp = sg.real() * sg.real() + sg.imag() * sg.imag(); | ||||
|                 est_insp = insp * kest + est_insp * (1 - kest); | ||||
| 
 | ||||
|                 if (est_insp) { | ||||
| @ -1354,9 +1354,9 @@ struct cstln_receiver : runnable | ||||
|                 } | ||||
| 
 | ||||
|                 // SS and MER
 | ||||
|                 complex<float> ev( | ||||
|                     s.re - cstln_point->re, | ||||
|                     s.im - cstln_point->im | ||||
|                 std::complex<float> ev( | ||||
|                     s.real() - cstln_point->real(), | ||||
|                     s.imag() - cstln_point->imag() | ||||
|                 ); | ||||
|                 float sig_power, ev_power; | ||||
| 
 | ||||
| @ -1364,15 +1364,15 @@ struct cstln_receiver : runnable | ||||
|                 { | ||||
|                     // Special case for BPSK: Ignore quadrature component of noise.
 | ||||
|                     // TBD Projection on I axis assumes BPSK at 45°
 | ||||
|                     float sig_real = (cstln_point->re + cstln_point->im) * 0.707; | ||||
|                     float ev_real = (ev.re + ev.im) * 0.707; | ||||
|                     float sig_real = (cstln_point->real() + cstln_point->imag()) * 0.707; | ||||
|                     float ev_real = (ev.real() + ev.imag()) * 0.707; | ||||
|                     sig_power = sig_real * sig_real; | ||||
|                     ev_power = ev_real * ev_real; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     sig_power = (int)cstln_point->re * cstln_point->re + (int)cstln_point->im * cstln_point->im; | ||||
|                     ev_power = ev.re * ev.re + ev.im * ev.im; | ||||
|                     sig_power = (int)cstln_point->real() * cstln_point->real() + (int)cstln_point->imag() * cstln_point->imag(); | ||||
|                     ev_power = ev.real() * ev.real() + ev.imag() * ev.imag(); | ||||
|                 } | ||||
| 
 | ||||
|                 est_sp = sig_power * kest + est_sp * (1 - kest); | ||||
| @ -1425,11 +1425,11 @@ struct cstln_receiver : runnable | ||||
|   private: | ||||
|     struct | ||||
|     { | ||||
|         complex<float> p; // Received symbol
 | ||||
|         complex<float> c; // Matched constellation point
 | ||||
|         std::complex<float> p; // Received symbol
 | ||||
|         std::complex<float> c; // Matched constellation point
 | ||||
|     } hist[3]; | ||||
| 
 | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     pipewriter<SOFTSYMB> out; | ||||
|     float est_insp, agc_gain; | ||||
|     float mu;    // PSK time expressed in clock ticks
 | ||||
| @ -1460,10 +1460,10 @@ struct fast_qpsk_receiver : runnable | ||||
| 
 | ||||
|     fast_qpsk_receiver( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<hardsymbol> &_out, | ||||
|         pipebuf<float> *_freq_out = nullptr, | ||||
|         pipebuf<complex<T>> *_cstln_out = nullptr | ||||
|         pipebuf<std::complex<T>> *_cstln_out = nullptr | ||||
|     ) : | ||||
|         runnable(sch, "Fast QPSK receiver"), | ||||
|         meas_decimation(1048576), | ||||
| @ -1478,7 +1478,7 @@ struct fast_qpsk_receiver : runnable | ||||
|         set_omega(1); | ||||
|         set_freq(0); | ||||
|         freq_out = _freq_out ? new pipewriter<float>(*_freq_out) : nullptr; | ||||
|         cstln_out = _cstln_out ? new pipewriter<complex<T>>(*_cstln_out) : nullptr; | ||||
|         cstln_out = _cstln_out ? new pipewriter<std::complex<T>>(*_cstln_out) : nullptr; | ||||
|         memset(hist, 0, sizeof(hist)); | ||||
|         init_lookup_tables(); | ||||
|     } | ||||
| @ -1537,7 +1537,7 @@ struct fast_qpsk_receiver : runnable | ||||
|         while (in.readable() >= chunk_size + 1 && // +1 for interpolation
 | ||||
|                out.writable() >= chunk_size && (!freq_out || freq_out->writable() >= max_meas) && (!cstln_out || cstln_out->writable() >= max_meas)) | ||||
|         { | ||||
|             complex<T> *pin = in.rd(), *pin0 = pin, *pend = pin + chunk_size; | ||||
|             std::complex<T> *pin = in.rd(), *pin0 = pin, *pend = pin + chunk_size; | ||||
|             hardsymbol *pout = out.wr(), *pout0 = pout; | ||||
| 
 | ||||
|             cu8 s; | ||||
| @ -1560,28 +1560,28 @@ struct fast_qpsk_receiver : runnable | ||||
|                     symbol_arg = a0 + (s_angle)(da*mu); | ||||
|                     s = arg_to_symbol(symbol_arg); | ||||
| #elif 1 // Linear by lookup-table. 1.2M on bench3bishs
 | ||||
|                     polar *p0 = &lut_polar[pin[0].re][pin[0].im]; | ||||
|                     polar *p0 = &lut_polar[pin[0].real()][pin[0].imag()]; | ||||
|                     u_angle a0 = (u_angle)(p0->a - phase) >> (16 - RLUT_BITS); | ||||
|                     cu8 *p0r = &lut_rect[a0][p0->r >> 1]; | ||||
|                     polar *p1 = &lut_polar[pin[1].re][pin[1].im]; | ||||
|                     polar *p1 = &lut_polar[pin[1].real()][pin[1].imag()]; | ||||
|                     u_angle a1 = (u_angle)(p1->a - (phase + freqw)) >> (16 - RLUT_BITS); | ||||
|                     cu8 *p1r = &lut_rect[a1][p1->r >> 1]; | ||||
|                     s.re = (int)(p0r->re + (p1r->re - p0r->re) * mu); | ||||
|                     s.im = (int)(p0r->im + (p1r->im - p0r->im) * mu); | ||||
|                     s.real((int)(p0r->real() + (p1r->real() - p0r->real()) * mu)); | ||||
|                     s.imag((int)(p0r->imag() + (p1r->imag() - p0r->imag()) * mu)); | ||||
|                     symbol_arg = fast_arg(s); | ||||
| #else   // Linear floating-point, for reference
 | ||||
|                     float a0 = -(int)phase * M_PI / 32768; | ||||
|                     float cosa0 = cosf(a0), sina0 = sinf(a0); | ||||
|                     complex<float> | ||||
|                         p0r(((float)pin[0].re - 128) * cosa0 - ((float)pin[0].im - 128) * sina0, | ||||
|                             ((float)pin[0].re - 128) * sina0 + ((float)pin[0].im - 128) * cosa0); | ||||
|                     std::complex<float> | ||||
|                         p0r(((float)pin[0].real() - 128) * cosa0 - ((float)pin[0].imag() - 128) * sina0, | ||||
|                             ((float)pin[0].real() - 128) * sina0 + ((float)pin[0].imag() - 128) * cosa0); | ||||
|                     float a1 = -(int)(phase + freqw) * M_PI / 32768; | ||||
|                     float cosa1 = cosf(a1), sina1 = sinf(a1); | ||||
|                     complex<float> | ||||
|                         p1r(((float)pin[1].re - 128) * cosa1 - ((float)pin[1].im - 128) * sina1, | ||||
|                             ((float)pin[1].re - 128) * sina1 + ((float)pin[1].im - 128) * cosa1); | ||||
|                     s.re = (int)(128 + p0r.re + (p1r.re - p0r.re) * mu); | ||||
|                     s.im = (int)(128 + p0r.im + (p1r.im - p0r.im) * mu); | ||||
|                     std::complex<float> | ||||
|                         p1r(((float)pin[1].real() - 128) * cosa1 - ((float)pin[1].imag() - 128) * sina1, | ||||
|                             ((float)pin[1].real() - 128) * sina1 + ((float)pin[1].imag() - 128) * cosa1); | ||||
|                     s.real() = (int)(128 + p0r.real() + (p1r.real() - p0r.real()) * mu); | ||||
|                     s.imag() = (int)(128 + p0r.imag() + (p1r.imag() - p0r.imag()) * mu); | ||||
|                     symbol_arg = fast_arg(s); | ||||
| #endif | ||||
| 
 | ||||
| @ -1604,24 +1604,24 @@ struct fast_qpsk_receiver : runnable | ||||
|                     hist[1] = hist[0]; | ||||
| #define HIST_FLOAT 0 | ||||
| #if HIST_FLOAT | ||||
|                     hist[0].p.re = (float)s.re - 128; | ||||
|                     hist[0].p.im = (float)s.im - 128; | ||||
|                     hist[0].p.real() = (float)s.real() - 128; | ||||
|                     hist[0].p.imag() = (float)s.imag() - 128; | ||||
| 
 | ||||
|                     cu8 cp = arg_to_symbol((symbol_arg & 49152) + 8192); | ||||
|                     hist[0].c.re = (float)cp.re - 128; | ||||
|                     hist[0].c.im = (float)cp.im - 128; | ||||
|                     hist[0].c.real() = (float)cp.real() - 128; | ||||
|                     hist[0].c.imag() = (float)cp.imag() - 128; | ||||
| 
 | ||||
|                     float muerr = | ||||
|                         ((hist[0].p.re - hist[2].p.re) * hist[1].c.re + | ||||
|                          (hist[0].p.im - hist[2].p.im) * hist[1].c.im) - | ||||
|                         ((hist[0].c.re - hist[2].c.re) * hist[1].p.re + | ||||
|                          (hist[0].c.im - hist[2].c.im) * hist[1].p.im); | ||||
|                         ((hist[0].p.real() - hist[2].p.real()) * hist[1].c.real() + | ||||
|                          (hist[0].p.imag() - hist[2].p.imag()) * hist[1].c.imag()) - | ||||
|                         ((hist[0].c.real() - hist[2].c.real()) * hist[1].p.real() + | ||||
|                          (hist[0].c.imag() - hist[2].c.imag()) * hist[1].p.imag()); | ||||
| #else | ||||
|                     hist[0].p = s; | ||||
|                     hist[0].c = arg_to_symbol((symbol_arg & 49152) + 8192); | ||||
| 
 | ||||
|                     int muerr = | ||||
|                         ((signed char)(hist[0].p.re - hist[2].p.re) * ((int)hist[1].c.re - 128) + (signed char)(hist[0].p.im - hist[2].p.im) * ((int)hist[1].c.im - 128)) - ((signed char)(hist[0].c.re - hist[2].c.re) * ((int)hist[1].p.re - 128) + (signed char)(hist[0].c.im - hist[2].c.im) * ((int)hist[1].p.im - 128)); | ||||
|                         ((signed char)(hist[0].p.real() - hist[2].p.real()) * ((int)hist[1].c.real() - 128) + (signed char)(hist[0].p.imag() - hist[2].p.imag()) * ((int)hist[1].c.imag() - 128)) - ((signed char)(hist[0].c.real() - hist[2].c.real()) * ((int)hist[1].p.real() - 128) + (signed char)(hist[0].c.imag() - hist[2].c.imag()) * ((int)hist[1].p.imag() - 128)); | ||||
| #endif | ||||
|                     float mucorr = muerr * gain_mu; | ||||
|                     const float max_mucorr = 0.1; | ||||
| @ -1689,7 +1689,7 @@ struct fast_qpsk_receiver : runnable | ||||
|     u_angle fast_arg(const cu8 &c) | ||||
|     { | ||||
|         // TBD read cu8 as u16 index, same endianness as in init()
 | ||||
|         return lut_polar[c.re][c.im].a; | ||||
|         return lut_polar[c.real()][c.imag()].a; | ||||
|     } | ||||
| 
 | ||||
|     cu8 lut_rect[RLUT_ANGLES][256]; | ||||
| @ -1715,16 +1715,16 @@ struct fast_qpsk_receiver : runnable | ||||
|         for (unsigned long a = 0; a < 65536; ++a) | ||||
|         { | ||||
|             float f = 2 * M_PI * a / 65536; | ||||
|             lut_sincos[a].re = 128 + cstln_amp * cosf(f); | ||||
|             lut_sincos[a].im = 128 + cstln_amp * sinf(f); | ||||
|             lut_sincos[a].real() = 128 + cstln_amp * cosf(f); | ||||
|             lut_sincos[a].imag() = 128 + cstln_amp * sinf(f); | ||||
|         } | ||||
| 
 | ||||
|         for (int a = 0; a < RLUT_ANGLES; ++a) | ||||
|         { | ||||
|             for (int r = 0; r < 256; ++r) | ||||
|             { | ||||
|                 lut_rect[a][r].re = (int)(128 + r * cos(2 * M_PI * a / RLUT_ANGLES)); | ||||
|                 lut_rect[a][r].im = (int)(128 + r * sin(2 * M_PI * a / RLUT_ANGLES)); | ||||
|                 lut_rect[a][r].real() = (int)(128 + r * cos(2 * M_PI * a / RLUT_ANGLES)); | ||||
|                 lut_rect[a][r].imag() = (int)(128 + r * sin(2 * M_PI * a / RLUT_ANGLES)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -1732,8 +1732,8 @@ struct fast_qpsk_receiver : runnable | ||||
|     struct | ||||
|     { | ||||
| #if HIST_FLOAT | ||||
|         complex<float> p; // Received symbol
 | ||||
|         complex<float> c; // Matched constellation point
 | ||||
|         std::complex<float> p; // Received symbol
 | ||||
|         std::complex<float> c; // Matched constellation point
 | ||||
| #else | ||||
|         cu8 p; // Received symbol
 | ||||
|         cu8 c; // Matched constellation point
 | ||||
| @ -1762,7 +1762,7 @@ struct cstln_transmitter : runnable | ||||
|     cstln_transmitter( | ||||
|         scheduler *sch, | ||||
|         pipebuf<u8> &_in, | ||||
|         pipebuf<complex<Tout>> &_out | ||||
|         pipebuf<std::complex<Tout>> &_out | ||||
|     ) : | ||||
|         runnable(sch, "cstln_transmitter"), | ||||
|         in(_in), | ||||
| @ -1779,13 +1779,13 @@ struct cstln_transmitter : runnable | ||||
| 
 | ||||
|         int count = min(in.readable(), out.writable()); | ||||
|         u8 *pin = in.rd(), *pend = pin + count; | ||||
|         complex<Tout> *pout = out.wr(); | ||||
|         std::complex<Tout> *pout = out.wr(); | ||||
| 
 | ||||
|         for (; pin < pend; ++pin, ++pout) | ||||
|         { | ||||
|             complex<signed char> *cp = &cstln->symbols[*pin]; | ||||
|             pout->re = Zout + cp->re; | ||||
|             pout->im = Zout + cp->im; | ||||
|             std::complex<signed char> *cp = &cstln->symbols[*pin]; | ||||
|             pout->real(Zout + cp->real()); | ||||
|             pout->imag(Zout + cp->imag()); | ||||
|         } | ||||
| 
 | ||||
|         in.read(count); | ||||
| @ -1794,7 +1794,7 @@ struct cstln_transmitter : runnable | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<u8> in; | ||||
|     pipewriter<complex<Tout>> out; | ||||
|     pipewriter<std::complex<Tout>> out; | ||||
| }; | ||||
| // cstln_transmitter
 | ||||
| 
 | ||||
| @ -1807,8 +1807,8 @@ struct rotator : runnable | ||||
| { | ||||
|     rotator( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<complex<T>> &_out, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_out, | ||||
|         float freq | ||||
|     ) : | ||||
|         runnable(sch, "rotator"), | ||||
| @ -1832,15 +1832,15 @@ struct rotator : runnable | ||||
|     void run() | ||||
|     { | ||||
|         unsigned long count = min(in.readable(), out.writable()); | ||||
|         complex<T> *pin = in.rd(), *pend = pin + count; | ||||
|         complex<T> *pout = out.wr(); | ||||
|         std::complex<T> *pin = in.rd(), *pend = pin + count; | ||||
|         std::complex<T> *pout = out.wr(); | ||||
| 
 | ||||
|         for (; pin < pend; ++pin, ++pout, ++index) | ||||
|         { | ||||
|             float c = lut_cos[index]; | ||||
|             float s = lut_sin[index]; | ||||
|             pout->re = pin->re * c - pin->im * s; | ||||
|             pout->im = pin->re * s + pin->im * c; | ||||
|             pout->real(pin->real() * c - pin->imag() * s); | ||||
|             pout->imag(pin->real() * s + pin->imag() * c); | ||||
|         } | ||||
| 
 | ||||
|         in.read(count); | ||||
| @ -1848,8 +1848,8 @@ struct rotator : runnable | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     pipereader<complex<T>> in; | ||||
|     pipewriter<complex<T>> out; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     pipewriter<std::complex<T>> out; | ||||
|     float lut_cos[65536]; | ||||
|     float lut_sin[65536]; | ||||
|     unsigned short index; // Current phase
 | ||||
| @ -1870,7 +1870,7 @@ struct cnr_fft : runnable | ||||
| { | ||||
|     cnr_fft( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<float> &_out, | ||||
|         float _bandwidth, | ||||
|         int nfft = 4096 | ||||
| @ -1944,7 +1944,7 @@ struct cnr_fft : runnable | ||||
|             sorted = new T[fft.size()]; | ||||
|         } | ||||
|         if (!data) { | ||||
|             data = new complex<T>[fft.size()]; | ||||
|             data = new std::complex<T>[fft.size()]; | ||||
|         } | ||||
|         if (!power) { | ||||
|             power = new T[fft.size()]; | ||||
| @ -1956,7 +1956,7 @@ struct cnr_fft : runnable | ||||
|         fft.inplace(data, true); | ||||
| 
 | ||||
|         for (int i = 0; i < fft.size(); ++i) | ||||
|             power[i] = data[i].re * data[i].re + data[i].im * data[i].im; | ||||
|             power[i] = data[i].real() * data[i].real() + data[i].imag() * data[i].imag(); | ||||
| 
 | ||||
|         if (!avgpower) | ||||
|         { | ||||
| @ -2039,12 +2039,12 @@ struct cnr_fft : runnable | ||||
|         // fprintf(stderr, "l: %d m: %d min: %f max: %f\n", l, m, min, max);
 | ||||
|     } | ||||
| 
 | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     pipewriter<float> out; | ||||
|     cfft_engine<T> fft; | ||||
|     T *avgpower; | ||||
|     T *sorted; | ||||
|     complex<T> *data; | ||||
|     std::complex<T> *data; | ||||
|     T *power; | ||||
|     int phase; | ||||
|     float cslots_ratio; | ||||
| @ -2062,7 +2062,7 @@ struct spectrum : runnable | ||||
| 
 | ||||
|     spectrum( | ||||
|         scheduler *sch, | ||||
|         pipebuf<complex<T>> &_in, | ||||
|         pipebuf<std::complex<T>> &_in, | ||||
|         pipebuf<float[NFFT]> &_out | ||||
|     ) : | ||||
|         runnable(sch, "spectrum"), | ||||
| @ -2102,7 +2102,7 @@ struct spectrum : runnable | ||||
|   private: | ||||
|     void do_spectrum() | ||||
|     { | ||||
|         complex<T> data[fft.n]; | ||||
|         std::complex<T> data[fft.n]; | ||||
| 
 | ||||
|         if (decim == 1) | ||||
|         { | ||||
| @ -2110,7 +2110,7 @@ struct spectrum : runnable | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             complex<T> *pin = in.rd(); | ||||
|             std::complex<T> *pin = in.rd(); | ||||
| 
 | ||||
|             for (int i = 0; i < fft.n; ++i, pin += decim) { | ||||
|                 data[i] = *pin; | ||||
| @ -2121,7 +2121,7 @@ struct spectrum : runnable | ||||
|         float power[NFFT]; | ||||
| 
 | ||||
|         for (int i = 0; i < fft.n; ++i) { | ||||
|             power[i] = (float)data[i].re * data[i].re + (float)data[i].im * data[i].im; | ||||
|             power[i] = (float)data[i].real() * data[i].real() + (float)data[i].imag() * data[i].imag(); | ||||
|         } | ||||
| 
 | ||||
|         if (!avgpower) | ||||
| @ -2146,7 +2146,7 @@ struct spectrum : runnable | ||||
|         out.written(1); | ||||
|     } | ||||
| 
 | ||||
|     pipereader<complex<T>> in; | ||||
|     pipereader<std::complex<T>> in; | ||||
|     pipewriter<float[NFFT]> out; | ||||
|     cfft_engine<T> fft; | ||||
|     T *avgpower; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user