SDDC_Driver
Loading...
Searching...
No Matches
fft_mt_r2iq.h
1/*
2 * This file is part of SDDC_Driver.
3 *
4 * =====================
5 * MIT License
6 * =====================
7 *
8 * Copyright (C) 2020 - Oscar Steila
9 * Copyright (C) 2020 - Howard Su
10 * Copyright (C) 2021 - Hayati Ayguen
11 * Copyright (C) 2021 - Phil Ashby
12 * Copyright (C) 2025 - RenardSpark
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this software and associated documentation files (the "Software"), to deal
16 * in the Software without restriction, including without limitation the rights
17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 * copies of the Software, and to permit persons to whom the Software is
19 * furnished to do so, subject to the following conditions:
20
21 * The above copyright notice and this permission notice shall be included in all
22 * copies or substantial portions of the Software.
23
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33#pragma once
34
35// --- External dependencies --- //
36#include <thread>
37#include <mutex>
38#include <condition_variable>
39#include "fftw3.h"
40
41// --- Internal dependencies --- //
42#include "../config.h"
43#include "../dsp/ringbuffer.h"
44
45// use up to this many threads
46#define N_MAX_R2IQ_THREADS 1
47#define PRINT_INPUT_RANGE 0
48#define NDECIDX 7 // Number of decimation steps
49
50static const int BASE_FFT_SCRAP_SIZE = 2048;
51static const int BASE_FFT_USEFUL_SIZE = FFTN_R_ADC;
52static const int BASE_FFT_SIZE = BASE_FFT_USEFUL_SIZE + BASE_FFT_SCRAP_SIZE;
53static const int BASE_FFT_HALF_SIZE = BASE_FFT_SIZE / 2;
54
55struct r2iqThreadArg;
56
58{
59public:
61 virtual ~fft_mt_r2iq();
62
63 void Init(float gain, ringbuffer<int16_t>* buffers, ringbuffer<float>* obuffers);
64
65 void TurnOn();
66 void TurnOff(void);
67 bool IsOn(void);
68
69 // --- Decimation --- //
70 int getRatio();
71 bool setDecimate(uint8_t dec);
72 // --- //
73
74 void SetRand(bool v) { this->stateADCRand = v; }
75 bool getRand() const { return this->stateADCRand; }
76
77 void setSideband(bool lsb) { this->useSidebandLSB = lsb; }
78 bool getSideband() const { return this->useSidebandLSB; }
79
80 float setFreqOffset(float offset);
81
82private:
83 // --- Tools --- //
84 template<bool rand> void convert_float(const int16_t *input, float* output, int size)
85 {
86 for(int m = 0; m < size; m++)
87 {
88 int16_t val;
89 if (rand && (input[m] & 1))
90 {
91 val = input[m] ^ (-2);
92 }
93 else
94 {
95 val = input[m];
96 }
97 output[m] = float(val);
98 }
99 }
100
101 void shift_freq(fftwf_complex* dest, const fftwf_complex* source1, const fftwf_complex* source2, int start, int end)
102 {
103 for (int m = start; m < end; m++)
104 {
105 // besides circular shift, do complex multiplication with the lowpass filter's spectrum
106 // (a+ib)(c+id) = (ac - bd) + i(ad + bc)
107 dest[m][0] = source1[m][0] * source2[m][0] - source1[m][1] * source2[m][1];
108 dest[m][1] = source1[m][1] * source2[m][0] + source1[m][0] * source2[m][1];
109 }
110 }
111
112 template<bool flip> void copy(fftwf_complex* dest, const fftwf_complex* source, int count)
113 {
114 if (flip)
115 {
116 for (int i = 0; i < count; i++)
117 {
118 dest[i][0] = source[i][0];
119 dest[i][1] = -source[i][1];
120 }
121 }
122 else
123 {
124 for (int i = 0; i < count; i++)
125 {
126 dest[i][0] = source[i][0];
127 dest[i][1] = source[i][1];
128 }
129 }
130 }
131
132 bool r2iqOn; // r2iq on flag
133
134 ringbuffer<int16_t>* inputbuffer; // pointer to input buffers
135 size_t inputbuffer_block_size = 0;
136
137 ringbuffer<float>* outputbuffer; // pointer to output buffers
138
139 // --- Decimation --- //
140 int decimation = 0; // selected decimation ratio
141 // 64 Msps: 0 => 32Msps, 1=> 16Msps, 2 = 8Msps, 3 = 4Msps, 4 = 2Msps
142 // 128 Msps: 0 => 64Msps, 1 => 32Msps, 2=> 16Msps, 3 = 8Msps, 4 = 4Msps, 5 = 2Msps
143 int decimation_ratio[NDECIDX]; // ratio
144
145 // Lookup table linking the decimation level to the size of the resulting FFT
146 // Each step divides the fft size by 2
147 // Definition : fft_size_per_decimation[x] = FFT_HALF_SIZE / 2^k
148 int fft_size_per_decimation[NDECIDX];
149 // --- //
150
151 bool stateADCRand; // randomized ADC output
152 bool useSidebandLSB;
153
154 // number of ffts needed to process one block of the input buffer
155 int ffts_per_blocks = 0;
156
157 int bufIdx; // index to next buffer to be processed
158 r2iqThreadArg* lastThread;
159
160 float GainScale;
161
162 // The bin (the portion of the FFT result) in which
163 // the desired center frequency is located
164 int center_frequency_bin = 0;
165
166 void *r2iqThreadf(r2iqThreadArg *th); // thread function
167
168 void * r2iqThreadf_generic(r2iqThreadArg *th);
169 void * r2iqThreadf_avx(r2iqThreadArg *th);
170 void * r2iqThreadf_avx2(r2iqThreadArg *th);
171 void * r2iqThreadf_avx512(r2iqThreadArg *th);
172 void * r2iqThreadf_neon(r2iqThreadArg *th);
173
174 fftwf_complex **filterHw; // Hw complex to each decimation ratio
175
176 fftwf_plan plan_time2freq_r2c; // fftw plan buffers Freq to Time complex to complex per decimation ratio
177 fftwf_plan *plan_freq2time; // fftw plan buffers Time to Freq real to complex per buffer
178 fftwf_plan plan_freq2time_per_decimation[NDECIDX];
179
180 uint32_t processor_count;
181 r2iqThreadArg* threadArgs[N_MAX_R2IQ_THREADS];
182 std::mutex mutexR2iqControl; // r2iq control lock
183 std::thread r2iq_thread[N_MAX_R2IQ_THREADS]; // thread pointers
184};
185
186// assure, that ADC is not oversteered?
188
190 {
191#if PRINT_INPUT_RANGE
192 MinMaxBlockCount = 0;
193 MinValue = 0;
194 MaxValue = 0;
195#endif
196 }
197
198 uint8_t thread_id;
199 float *ADCinTime; // point to each threads input buffers [nftt][n]
200 fftwf_complex *ADCinFreq; // buffers in frequency
201 fftwf_complex *inFreqTmp; // tmp decimation output buffers (after tune shift)
202#if PRINT_INPUT_RANGE
203 int MinMaxBlockCount;
204 int16_t MinValue;
205 int16_t MaxValue;
206#endif
207};
Definition fft_mt_r2iq.h:58
Definition ringbuffer.h:49
Definition fft_mt_r2iq.h:187