SDDC_Driver
Loading...
Searching...
No Matches
fft_mt_r2iq.h
1#pragma once
2
3#include "fftw3.h"
4#include "../config.h"
5#include <algorithm>
6#include <string.h>
7#include <thread>
8#include <mutex>
9#include <condition_variable>
10#include <atomic>
11#include <vector>
12
13#include "../dsp/ringbuffer.h"
14
15// use up to this many threads
16#define N_MAX_R2IQ_THREADS 1
17#define PRINT_INPUT_RANGE 0
18#define NDECIDX 7 // Number of decimation steps
19
20static const int BASE_FFT_SCRAP_SIZE = 2048;
21static const int BASE_FFT_SIZE = FFTN_R_ADC + BASE_FFT_SCRAP_SIZE;
22static const int BASE_FFT_HALF_SIZE = BASE_FFT_SIZE / 2;
23
24struct r2iqThreadArg;
25
27{
28public:
30 virtual ~fft_mt_r2iq();
31
32 void Init(float gain, ringbuffer<int16_t>* buffers, ringbuffer<float>* obuffers);
33
34 void TurnOn();
35 void TurnOff(void);
36 bool IsOn(void);
37
38 // --- Decimation --- //
39 int getRatio()
40 {
41 return decimation_ratio[decimation];
42 }
43 bool setDecimate(uint8_t dec)
44 {
45 if(dec >= NDECIDX) return false;
46 this->decimation = dec;
47 return true;
48 }
49 // --- //
50
51 void SetRand(bool v) { this->stateADCRand = v; }
52 bool getRand() const { return this->stateADCRand; }
53
54 void setSideband(bool lsb) { this->useSidebandLSB = lsb; }
55 bool getSideband() const { return this->useSidebandLSB; }
56
57 float setFreqOffset(float offset);
58
59protected:
60
61 template<bool rand> void convert_float(const int16_t *input, float* output, int size)
62 {
63 for(int m = 0; m < size; m++)
64 {
65 int16_t val;
66 if (rand && (input[m] & 1))
67 {
68 val = input[m] ^ (-2);
69 }
70 else
71 {
72 val = input[m];
73 }
74 output[m] = float(val);
75 }
76 }
77
78 void shift_freq(fftwf_complex* dest, const fftwf_complex* source1, const fftwf_complex* source2, int start, int end)
79 {
80 for (int m = start; m < end; m++)
81 {
82 // besides circular shift, do complex multiplication with the lowpass filter's spectrum
83 // (a+ib)(c+id) = (ac - bd) + i(ad + bc)
84 dest[m][0] = source1[m][0] * source2[m][0] - source1[m][1] * source2[m][1];
85 dest[m][1] = source1[m][1] * source2[m][0] + source1[m][0] * source2[m][1];
86 }
87 }
88
89 template<bool flip> void copy(fftwf_complex* dest, const fftwf_complex* source, int count)
90 {
91 if (flip)
92 {
93 for (int i = 0; i < count; i++)
94 {
95 dest[i][0] = source[i][0];
96 dest[i][1] = -source[i][1];
97 }
98 }
99 else
100 {
101 for (int i = 0; i < count; i++)
102 {
103 dest[i][0] = source[i][0];
104 dest[i][1] = source[i][1];
105 }
106 }
107 }
108
109private:
110 bool r2iqOn; // r2iq on flag
111
112 ringbuffer<int16_t>* inputbuffer; // pointer to input buffers
113 size_t inputbuffer_block_size = 0;
114
115 ringbuffer<float>* outputbuffer; // pointer to output buffers
116
117 // --- Decimation --- //
118 int decimation = 0; // selected decimation ratio
119 // 64 Msps: 0 => 32Msps, 1=> 16Msps, 2 = 8Msps, 3 = 4Msps, 4 = 2Msps
120 // 128 Msps: 0 => 64Msps, 1 => 32Msps, 2=> 16Msps, 3 = 8Msps, 4 = 4Msps, 5 = 2Msps
121 int decimation_ratio[NDECIDX]; // ratio
122
123 // Lookup table linking the decimation level to the size of the resulting FFT
124 // Each step divides the fft size by 2
125 // Definition : fft_size_per_decimation[x] = FFT_HALF_SIZE / 2^k
126 int fft_size_per_decimation[NDECIDX];
127 // --- //
128
129 bool stateADCRand; // randomized ADC output
130 bool useSidebandLSB;
131
132 // number of ffts needed to process one block of the input buffer
133 int ffts_per_blocks = 0;
134
135 int bufIdx; // index to next buffer to be processed
136 r2iqThreadArg* lastThread;
137
138 float GainScale;
139
140 // The bin (the portion of the FFT result) in which
141 // the desired center frequency is located
142 int center_frequency_bin = 0;
143
144 void *r2iqThreadf(r2iqThreadArg *th); // thread function
145
146 void * r2iqThreadf_generic(r2iqThreadArg *th);
147 void * r2iqThreadf_avx(r2iqThreadArg *th);
148 void * r2iqThreadf_avx2(r2iqThreadArg *th);
149 void * r2iqThreadf_avx512(r2iqThreadArg *th);
150 void * r2iqThreadf_neon(r2iqThreadArg *th);
151
152 fftwf_complex **filterHw; // Hw complex to each decimation ratio
153
154 fftwf_plan plan_time2freq_r2c; // fftw plan buffers Freq to Time complex to complex per decimation ratio
155 fftwf_plan *plan_freq2time; // fftw plan buffers Time to Freq real to complex per buffer
156 fftwf_plan plan_freq2time_per_decimation[NDECIDX];
157
158 uint32_t processor_count;
159 r2iqThreadArg* threadArgs[N_MAX_R2IQ_THREADS];
160 std::mutex mutexR2iqControl; // r2iq control lock
161 std::thread r2iq_thread[N_MAX_R2IQ_THREADS]; // thread pointers
162};
163
164// assure, that ADC is not oversteered?
166
168 {
169#if PRINT_INPUT_RANGE
170 MinMaxBlockCount = 0;
171 MinValue = 0;
172 MaxValue = 0;
173#endif
174 }
175
176 uint8_t thread_id;
177 float *ADCinTime; // point to each threads input buffers [nftt][n]
178 fftwf_complex *ADCinFreq; // buffers in frequency
179 fftwf_complex *inFreqTmp; // tmp decimation output buffers (after tune shift)
180#if PRINT_INPUT_RANGE
181 int MinMaxBlockCount;
182 int16_t MinValue;
183 int16_t MaxValue;
184#endif
185};
Definition fft_mt_r2iq.h:27
Definition ringbuffer.h:18
Definition fft_mt_r2iq.h:165