1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22
23
24 #include <unistd.h>
25
26 #include "globdef.h"
27 #include "uidef.h"
28 #include "fft1def.h"
29 #include "fft2def.h"
30 #include "fft3def.h"
31 #include "sigdef.h"
32 #include "screendef.h"
33 #include "seldef.h"
34 #include "rusage.h"
35 #include "thrdef.h"
36
37 extern int wg_old_y1;
38 extern int wg_old_y2;
39 extern int wg_old_x1;
40 extern int wg_old_x2;
41
42
43
txtest_init(void)44 void txtest_init(void)
45 {
46 int i, j, k;
47 float t1;
48 int pnts_per_seg;
49 txtest_decayfac1=fft1_blocktime;
50 txtest_decayfac2=1-txtest_decayfac1;
51 txtest_no_of_segs=(int)((fft1_last_point-fft1_first_point)*
52 fft1_hz_per_point/600);
53 if(txtest_no_of_segs >= screen_width)
54 {
55 lirerr(1159);
56 return;
57 }
58 for(i=0; i<screen_width; i++)
59 {
60 txtest_ypeak[i]=wg.ybottom-1;
61 txtest_ypeak_decay[i]=wg.ybottom-1;
62 txtest_yavg[i]=wg.ybottom-1;
63 fft1_spectrum[i]=wg.ybottom-1;
64 }
65 mix1_selfreq[0]=2400;
66 // Set up a rectangular filter with 2400Hz bandwidth
67 pnts_per_seg=2400/fft1_hz_per_point;
68 j=(mix1.size-pnts_per_seg)/2;
69 k=mix1.size/2;
70 i=0;
71 for(i=0; i<j; i++)
72 {
73 mix1_fqwin[i]=0;
74 }
75 for(i=j; i<=(int)mix1.size/2; i++)
76 {
77 mix1_fqwin[i]=1;
78 }
79 j=(mix1.size-mix1.new_points)/2;
80 k=j;
81 for(i=0; i<(int)mix1.crossover_points; i++)
82 {
83 mix1.cos2win[i]=mix1.window[k];
84 mix1.sin2win[i]=mix1.window[j];
85 k--;
86 j++;
87 }
88 if(txtest_no_of_segs <=0)txtest_no_of_segs=1;
89 txtest_pntinc=(fft1_last_point-fft1_first_point)/txtest_no_of_segs;
90 t1=pnts_per_seg/2+1;
91 txtest_first_point=fft1_first_point+t1;
92 txtest_pixinc=txtest_pntinc;
93 if(wg.xpoints_per_pixel == 0)
94 {
95 txtest_pixinc=txtest_pntinc*wg.pixels_per_xpoint;
96 t1*=wg.pixels_per_xpoint;
97 }
98 else
99 {
100 txtest_pixinc=(float)(txtest_pntinc)/wg.xpoints_per_pixel;
101 t1/=wg.xpoints_per_pixel;
102 if(txtest_pixinc < 1)
103 {
104 lirerr(1160);
105 return;
106 }
107 }
108 t1+=wg_first_xpixel;
109 txtest_spek_no=0;
110 txtest_spek_p0=0;
111 while(txtest_first_point-(int)mix1.size/2 < fft1_first_point)
112 {
113 txtest_first_point+=txtest_pntinc;
114 t1+=txtest_pixinc;
115 }
116 txtest_first_xpix=t1+0.5;
117 while(txtest_no_of_segs*txtest_pntinc+(int)mix1.size/2+
118 txtest_first_point > fft1_last_point) txtest_no_of_segs--;
119 if(txtest_no_of_segs < 0)
120 {
121 txtest_no_of_segs=0;
122 }
123 else
124 {
125 if( txtest_first_xpix+(txtest_no_of_segs-1)*txtest_pixinc >= wg.xright)
126 {
127 txtest_no_of_segs=0;
128 }
129 }
130 txtest_yfac=wg_yfac_power*wg.spek_avgnum;
131 if(genparm[FIRST_FFT_SINPOW] != 0)
132 {
133 t1=0;
134 for(i=0; i<fft1_size/2; i++)t1+=fft1_window[i];
135 t1/=fft1_size;
136 txtest_yfac/=t1*t1;
137 }
138 txtest_peak_redraw=0;
139 txtest_saturated=(float)BIG;
140 }
141
make_txtest_wide_spectra(void)142 void make_txtest_wide_spectra(void)
143 {
144 int i, j, k;
145 float t1;
146 // Make the average spectrum.
147 for(i=0; i<txtest_no_of_segs; i++)
148 {
149 t1=0;
150 k=0;
151 for(j=0; j<wg.spek_avgnum; j++)
152 {
153 t1+=txtest_power[k+i];
154 k+=txtest_no_of_segs;
155 }
156 txtest_powersum[i]=t1/wg.spek_avgnum;
157 }
158 }
159
160
txtest(void)161 void txtest(void)
162 {
163 int i, j, k;
164 int ia, ib;
165 int mix1_flag;
166 int local_workload_reset;
167 int old_fft1_nx, old_fft1_px;
168 float pwr1, pwr2;
169 float t1;
170 restart:;
171 local_workload_reset=workload_reset_flag;
172 for(i=0; i<txtest_no_of_segs*wg.spek_avgnum; i++)txtest_power[i]=0;
173 mix1_flag=0;
174 if(thread_command_flag[THREAD_SCREEN]!=THRFLAG_NOT_ACTIVE)
175 {
176 while(thread_status_flag[THREAD_SCREEN]!=THRFLAG_ACTIVE &&
177 thread_status_flag[THREAD_SCREEN]!=THRFLAG_IDLE &&
178 thread_status_flag[THREAD_SCREEN]!=THRFLAG_SEM_WAIT)
179 {
180 if(thread_command_flag[THREAD_TXTEST] == THRFLAG_KILL)goto txtest_exit;
181 lir_sleep(10000);
182 }
183 }
184 thread_status_flag[THREAD_TXTEST]=THRFLAG_ACTIVE;
185 while(thread_command_flag[THREAD_TXTEST] == THRFLAG_ACTIVE)
186 {
187 if(local_workload_reset!=workload_reset_flag)
188 {
189 local_workload_reset=workload_reset_flag;
190 if(txtest_saturated < 0.1)
191 {
192 txtest_saturated=BIG;
193 }
194 for(i=0; i<txtest_no_of_segs; i++)
195 {
196 txtest_peak_power_decay[i]=txtest_peak_power[i];
197 txtest_peak_power[i]=0;
198 }
199 for(i=wg_first_xpixel; i<wg_last_xpixel; i++)
200 {
201 txtest_ypeak[i]=wg.ybottom-1;
202 }
203 // Just clear the entire window and make a new graph.
204 // Quick fix when going from single-threaded to multi-threaded structure.
205 wg_old_x1=wg.xleft;
206 wg_old_x2=wg.xright;
207 wg_old_y1=wg.ytop;
208 wg_old_y2=wg.ybottom;
209 make_wide_graph(TRUE);
210 memcheck(197,fft1mem,&fft1_handle);
211 if(kill_all_flag) goto txtest_exit;
212 }
213 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
214 // mix1_flag signals to us that there is work to do on previous
215 // transforms so do not wait for a new fft1/fft2 if it is nonzero.
216 if(mix1_flag == 0) lir_await_event(EVENT_FFT1_READY);
217 if(txtest_no_of_segs < 1)fft1_px=(fft1_px+1)&fft1_mask;
218 mix1_flag=0;
219 // ###########################################################
220 // Third processing block.
221 // evaluate peak voltage in 2.4kHz bandwidth.
222 // ###########################################################
223 i=(fft1_pb-fft1_px+fft1_mask+1)&fft1_mask;
224 if(i>2*(int)mix1.size)
225 {
226 mix1_flag=1;
227 old_fft1_nx=fft1_nx;
228 old_fft1_px=fft1_px;
229 mix1_point[0]=txtest_first_point;
230 for(i=0; i<txtest_no_of_segs; i++)
231 {
232 fft1_nx=old_fft1_nx;
233 fft1_px=old_fft1_px;
234 for(j=0; j<2*timf3_block; j++)
235 {
236 timf3_float[j]=0;
237 }
238 timf3_pa=0;
239 fft1_mix1_fixed();
240 // In case the window is sine squared, we have to divide by it.
241 // because the standard routine we use does not divide for us.
242 ia=(mix1.interleave_points+mix1.crossover_points)/2;
243 if(mix1.interleave_points == mix1.new_points)
244 {
245 ia=mix1.size/4;
246 ib=3*mix1.size/4;
247 j=mix1.size/2+1;
248 k=mix1.size/2-1;
249 while(k >= (int)mix1.size/5)
250 {
251 timf3_float[2*k]*=mix1.window[k];
252 timf3_float[2*k+1]*=mix1.window[k];
253 timf3_float[2*j]*=mix1.window[k];
254 timf3_float[2*j+1]*=mix1.window[k];
255 j++;
256 k--;
257 }
258 }
259 else
260 {
261 if(mix1.interleave_points == 0)
262 {
263 ia=0;
264 ib=mix1.size;
265 }
266 else
267 {
268 ia=0;
269 ib=mix1.new_points+1;
270 }
271 }
272 pwr2=0;
273 pwr1=0;
274 for(j=ia; j<ib; j++)
275 {
276 t1=timf3_float[2*j ]*timf3_float[2*j ]+
277 timf3_float[2*j+1]*timf3_float[2*j+1];
278 pwr1+=t1;
279 if(pwr2 < t1)pwr2=t1;
280 }
281 pwr1*=txtest_yfac;
282 pwr2*=txtest_yfac;
283 txtest_power[txtest_spek_p0+i]=pwr1/(ib-ia);
284 txtest_peak_power[i]=pwr2;
285 txtest_peak_power_decay[i]=txtest_peak_power_decay[i]*txtest_decayfac2+
286 txtest_peak_power[i]*txtest_decayfac1;
287 mix1_point[0]+=txtest_pntinc;
288 lir_sched_yield();
289 }
290 txtest_show_p0=txtest_spek_p0;
291 txtest_spek_no++;
292 txtest_spek_p0+=txtest_no_of_segs;
293 if(txtest_spek_no >=wg.spek_avgnum)
294 {
295 txtest_spek_no=0;
296 txtest_spek_p0=0;
297 }
298 make_txtest_wide_spectra();
299 }
300 // Here we do the mouse actions that affect the wide graph.
301 // Currently only the waterfall memory area may become re-allocated
302 if(mouse_task!=-1)
303 {
304 k=mouse_task&GRAPH_MASK;
305 if( k > MAX_WIDEBAND_GRAPHS)
306 {
307 set_button_states();
308 if(mouse_active_flag == 0)
309 {
310 switch (k)
311 {
312 case FREQ_GRAPH:
313 mouse_on_freq_graph();
314 break;
315 }
316 if(mouse_active_flag == 0)lirerr(18877);
317 }
318 if(numinput_flag==0)current_mouse_activity();
319 if( (numinput_flag&DATA_READY_PARM) != 0)
320 {
321 par_from_keyboard_routine();
322 par_from_keyboard_routine=NULL;
323 mouse_active_flag=0;
324 numinput_flag=0;
325 leftpressed=BUTTON_IDLE;
326 }
327 if(mouse_active_flag == 0)
328 {
329 mouse_task=-1;
330 }
331 }
332 }
333 }
334 if(thread_command_flag[THREAD_TXTEST]==THRFLAG_IDLE)
335 {
336 // The wideband dsp thread is running and it puts out
337 // the waterfall graph. Stop it now.
338 thread_command_flag[THREAD_WIDEBAND_DSP]=THRFLAG_IDLE;
339 while(thread_status_flag[THREAD_WIDEBAND_DSP]!=THRFLAG_IDLE)
340 {
341 lir_sleep(25000);
342 }
343 thread_status_flag[THREAD_TXTEST]=THRFLAG_IDLE;
344 while(thread_command_flag[THREAD_TXTEST] == THRFLAG_IDLE)
345 {
346 lir_sleep(10000);
347 fft1_px = fft1_pb;
348 }
349 thread_command_flag[THREAD_WIDEBAND_DSP]=THRFLAG_ACTIVE;
350 lir_sleep(1000);
351 wg_old_x1=wg.xleft;
352 wg_old_x2=wg.xright;
353 wg_old_y1=wg.ytop;
354 wg_old_y2=wg.ybottom;
355 make_wide_graph(TRUE);
356 if(kill_all_flag) goto txtest_exit;
357 goto restart;
358 }
359 txtest_exit:;
360 lir_sleep(10000);
361 thread_status_flag[THREAD_TXTEST]=THRFLAG_RETURNED;
362 while(thread_command_flag[THREAD_TXTEST] != THRFLAG_NOT_ACTIVE)
363 {
364 lir_sleep(1000);
365 }
366 }
367