USRP_Server  2.0
A flexible, GPU-accelerated radio-frequency readout software.
USRP_buffer_generator.cpp
Go to the documentation of this file.
1 /* @file USRP_buffer_generator.cpp
2  * @brief Signal generation methods for the TX_buffer_generator class.
3  *
4  * Contains the definitions of the methods used to generates the buffer.
5  * Most of the methods used to generate the transmission buffer will call some cuda kernel wrapper.
6  *
7 */
9 
10 TX_buffer_generator::TX_buffer_generator(param* init_parameters){
11 
12 
14 
18  parameters = init_parameters;
19  buffer_len = parameters->buffer_len;
20 
21  //check what kind of function to use with the requested buffer
22  w_type last_w_type = parameters->wave_type[0];
23  mixed_buffer_type = false;
24  int chirp_counter = 0;
25  for(size_t i = 0; i < parameters->wave_type.size(); i++){
26  if(parameters->wave_type[i]!=last_w_type)mixed_buffer_type = true;
27  if(parameters->wave_type[i]==CHIRP)chirp_counter++;
28  }
29  if(chirp_counter>1){
30  print_error("Multiple chirp TX buffer generation has been requested. This feature is not implemented yet.");
31  exit(-1);
32  }
33  if(mixed_buffer_type){
34  print_error("Mixed TX buffer generation has been requested. This feature is not implemented yet.");
35  exit(-1);
36  }
37 
38  //assign the function pointer to the correct generator and initialize the buffer
39  switch(last_w_type){
40  case NODSP:
41  print_error("NODSP CASE NOT IMPLEMENTED.");
42  exit(-1);
43 
44  case SWONLY:
45  print_error("NODSP CASE NOT IMPLEMENTED.");
46  exit(-1);
47 
48  case RAMP:
49  print_error("RAMP CASE NOT IMPLEMENTED.");
50  exit(-1);
51 
52  case DIRECT:
53  print_error("RAMP CASE NOT IMPLEMENTED.");
54  exit(-1);
55 
56  case NOISE:
57  get_ptr = &TX_buffer_generator::get_from_noise;
58  clr_ptr = &TX_buffer_generator::close_noise;
59 
60  case TONES:
61 
62  //assign the get() and close() function pointers
63  get_ptr = &TX_buffer_generator::get_from_tones;
64  clr_ptr = &TX_buffer_generator::close_host;
65 
66  //initialize variables used in the get() method
67  TONES_buffer_len = parameters->rate;
68  TONES_last_sample = 0;
69 
70  //wrap tone information in the apposite struct
71  tone_parameters info;
72  info.tones_number = parameters->wave_type.size();
73  info.tone_frquencies = parameters->freq.data();
74  info.tones_amplitudes = parameters->ampl.data();
75 
76  //generate the buffer
77  base_buffer = tone_gen(&info,parameters->rate);
78 
79  //correct the situation if the buffer length is bigger than the sampling rate
80  if(buffer_len > parameters->rate){
81 
82  //take the biggest number of base buffer length that contains the transmission buffer
83  int buffer_ratio = std::ceil((float)buffer_len/(float)parameters->rate);
84  TONES_buffer_len = buffer_ratio*parameters->rate;
85 
86  //expand the buffer and replicate the first chunk
87  base_buffer = (float2*)realloc(base_buffer, (TONES_buffer_len)*sizeof(float2));
88  for(int j = 1; j < buffer_ratio; j++){
89  memcpy(base_buffer + j*parameters->rate, base_buffer, parameters->rate * sizeof(float2));
90  }
91  }
92 
93  //extend the base buffer so to compensate a possible buffer/buffer irrationality
94  base_buffer = (float2*)realloc(base_buffer, (TONES_buffer_len + buffer_len)*sizeof(float2));
95 
96  //copy the first pice of the buffer on the last pice.
97  memcpy(base_buffer + TONES_buffer_len, base_buffer, buffer_len * sizeof(float2));
98 
99  break;
100 
101  case CHIRP:
102 
103  //set the correct function pointers for get() and close() methods
104  get_ptr = &TX_buffer_generator::get_from_chirp;
105  clr_ptr = &TX_buffer_generator::close_device_chirp;
106 
107  //create an high priority stream (allow to overlap TX and RX operation on same GPU)
108  int low_p,high_p;
109  cudaDeviceGetStreamPriorityRange ( &low_p, &high_p );
110  cudaStreamCreateWithPriority(&internal_stream,cudaStreamNonBlocking, high_p);
111 
112  //wrap TX signal information in the apposite struct
113 
114  h_parameter.num_steps = parameters->swipe_s[0];
115  if(h_parameter.num_steps<1){
116  print_warning("Number of frequency steps of the chirp signal is not set. Setting it to maximum (chirp time * sampling rate).");
117  h_parameter.num_steps = parameters->chirp_t[0] * parameters->rate;
118  }
119  if(h_parameter.num_steps<2){
120  print_warning("Number of frequency steps of the chirp signal is less than 2. This may result in single tone generation.");
121  }
122 
123  //how long each tone is in samples
124  h_parameter.length = parameters->chirp_t[0] * parameters->rate / h_parameter.num_steps;
125  if(h_parameter.length<1){
126  print_warning("Duration of each frequency in chirp signal cannot be less than one sample. Setting duration of each tone to 1.");
127  h_parameter.length = 1;
128  h_parameter.num_steps = parameters->chirp_t[0] * parameters->rate;
129  }
130 
131  //the chirpness is expressed as double this expression somewhere
132  h_parameter.chirpness = ((std::pow(2,32)-1)*(parameters->chirp_f[0]-parameters->freq[0])/((double)h_parameter.num_steps-1.))/(double)parameters->rate;
133 
134  //the algorithm used for chirp generation use this value as frequency offset
135  //h_parameter.f0 = (std::pow(2,64)-1) * ((double)parameters->freq[0]/(double)parameters->rate);
136  h_parameter.f0 = (std::pow(2,32)-1) * ((double)parameters->freq[0]/(double)parameters->rate);
137 
138  //bookeeping of the last sample generated. Countrary to the single tone version this value is updated in the kernel call
139  last_index = 0;
140 
141  //this variable is now deprecated.
142  h_parameter.freq_norm = 0;
143 
144 
145  //set the chirp signal amplitude
146  scale = parameters->ampl[0];
147  if(scale == 0)print_warning("Chirp signal amplitude is 0");
148 
149  //upload the parameter struct to the gpu
150  cudaMalloc((void **)&d_parameter,sizeof(chirp_parameter));
151  cudaMemcpy(d_parameter, &h_parameter, sizeof(chirp_parameter),cudaMemcpyHostToDevice);
152 
153  //allocte memory for the kernel operations
154  cudaMalloc((void **)&base_buffer,sizeof(float2)*buffer_len);
155  //print_chirp_params("TX",h_parameter);
156 
157  break;
158 
159  }
160 }
161 
162 //wrapper to the correct get function
163 void TX_buffer_generator::get(float2** __restrict__ in){
165 
168  (this->*get_ptr)(in);
169 }
170 
171 //wrapper to the correct cleaning function
172 void TX_buffer_generator::close(){
174 
176  (this->*clr_ptr)();
177 }
178 
179 //pre-fill the queue with some packets. WARNING: for some reason it doesn't update the index parameter inside the called function
180 //causing the waveform to restart when get() method is called outside the class (why?)
181 int TX_buffer_generator::prefill_queue(tx_queue* queue, preallocator<float2>* memory, param* parameter_tx){
183 
189  bool filling = true;
190  // how many packets have been produced
191  int filled = 0;
192  float2* tmp;
193  bool dynamic = parameter_tx->dynamic_buffer();
194  //print_debug("preffiler is using dynamic allocation? ",dynamic);
195  while(filling){
196  if(dynamic)tmp = memory->get();
197  get(&tmp);
198  filling = queue->push(tmp);
199  std::this_thread::sleep_for(std::chrono::microseconds(200));
200  if(filling)filled++;
201  }
202 
203  return filled;
204 }
205 
206 
207 //effective function to get the chirp buffer
208 void TX_buffer_generator::get_from_chirp(float2** __restrict__ target){
209 
210  //generate the chirp signal on gpu
211  chirp_gen_wrapper(base_buffer,buffer_len,d_parameter,last_index,internal_stream,scale);
212 
213  //update index
214  last_index = (last_index + parameters->buffer_len) % (h_parameter.num_steps * h_parameter.length);
215 
216  //download it to the host
217  cudaMemcpyAsync(*target,base_buffer,sizeof(float2)*buffer_len,cudaMemcpyDeviceToHost,internal_stream);
218 
219  //wait for operation to be completed before returning
220  cudaStreamSynchronize(internal_stream);
221 }
222 
223 void TX_buffer_generator::get_from_noise(float2** __restrict__ target){}
224 
225 //effective function to get the tone buffer
226 void TX_buffer_generator::get_from_tones(float2** __restrict__ target){
227  *target = base_buffer + TONES_last_sample;
228  TONES_last_sample = (TONES_last_sample + buffer_len) % TONES_buffer_len;
229 }
230 
231 void TX_buffer_generator::get_from_noise(){}
232 
233 //versions of the cleaning function
234 void TX_buffer_generator::close_host(){
235  free(base_buffer);
236 }
237 
238 void TX_buffer_generator::close_device_chirp(){
239  cudaFree(base_buffer);
240  cudaFree(d_parameter);
241  cudaStreamDestroy(internal_stream);
242 }
243 
244 void TX_buffer_generator::close_noise(){}
int * tone_frquencies
Definition: kernels.cuh:69
Descriptor of the mutitone generation.
Definition: kernels.cuh:67
void print_error(std::string text)
float2 * tone_gen(tone_parameters *info, int sampling_rate, float scale, bool device)
Definition: kernels.cu:611
float * tones_amplitudes
Definition: kernels.cuh:70
void chirp_gen_wrapper(float2 *__restrict__ output, unsigned int output_size, chirp_parameter *__restrict__ info, unsigned long int last_index, cudaStream_t internal_stream, float scale=1)
Definition: kernels.cu:395
void print_warning(std::string text)