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 "globdef.h"
25 #include "uidef.h"
26 #include "seldef.h"
27 #include "fft1def.h"
28 #include "fft2def.h"
29 #include "fft3def.h"
30 #include "screendef.h"
31 #include "sigdef.h"
32 
33 #define BWFAC 0.03  // 3% of the bandwidth for AFC 2nd/3rd order modulation.
34 
35 // The mix1 routines shift selected frequency bands to the baseband.
36 // Since we have overlapping fourier transforms already there is no
37 // need to multiply with the cos/sin table - we just select some
38 // lines in the fft and make a back transformation.
39 // We do that with a reduced transform size and get the reduced
40 // sampling rate that we want at the reduced bandwidth automatically.
41 
42 float phrot_step_save=0;
43 
do_mix1(int ss,float dfq)44 void do_mix1(int ss, float dfq)
45 {
46 int i, j, n, pa, k, mm, ia, ib, ic, id;
47 int p0, poffs;
48 float t1,t2,t3,t4,r1,r2,r3,r4,w1,w2,a1,a2;
49 float old_phrot_step,phrot_step;
50 dfq=0;
51 phrot_step=dfq*fftx_points_per_hz*2*PI_L/mix1.size;
52 old_phrot_step=phrot_step_save;
53 phrot_step_save=phrot_step;
54 mm=twice_rxchan;
55 k=mm*mix1.interleave_points/2;
56 poffs=ss*timf3_size;
57 pa=timf3_pa+poffs;
58 // There is a lot of memory in our computers but speed may be a problem
59 // Process in different loops depending on no of rx channels.
60 i=0;
61 j=mix1.size-1;
62 n=mix1.size/2-1;
63 if(sw_onechan)
64   {
65   t1=mix1_fqwin[n];
66   fftn_tmp[2*i  ]*=t1;
67   fftn_tmp[2*i+1]*=t1;
68   i++;
69   while(j>i)
70     {
71     t1=mix1_fqwin[n];
72     fftn_tmp[2*i  ]*=t1;
73     fftn_tmp[2*i+1]*=t1;
74     fftn_tmp[2*j  ]*=t1;
75     fftn_tmp[2*j+1]*=t1;
76     j--;
77     n--;
78     i++;
79     }
80   t1=mix1_fqwin[n];
81   fftn_tmp[2*i  ]*=t1;
82   fftn_tmp[2*i+1]*=t1;
83   fftback(mix1.size, mix1.n, fftn_tmp,
84                              mix1.table, mix1.permute, yieldflag_ndsp_mix1);
85 // In case there is no window the whole thing is trival.
86 // Just place the back transforms after each other.
87 
88   if(mix1.interleave_points == 0)
89     {
90     t2=mix1_phase_rot[ss];
91     t1=mix1_phase[ss];
92     j=2*mix1.size;
93     for(i=0; i<j; i+=2)
94       {
95       t3=sin(t1);
96       t4=cos(t1);
97       timf3_float[pa+i  ]=t4*fftn_tmp[i+k  ]-t3*fftn_tmp[i+k+1];
98       timf3_float[pa+i+1]=t4*fftn_tmp[i+k+1]+t3*fftn_tmp[i+k  ];
99       t1+=t2;
100       }
101     mix1_phase[ss]=t1;
102     }
103   else
104     {
105 // If a sin squared window is used, place the transforms with 50%
106 // overlap and add them together. sin squared + cos squared ==1
107     pa=timf3_pa+poffs;
108     if(mix1.interleave_points == mix1.new_points)
109       {
110       ia=mix1.size;
111       t2=mix1_phase_rot[ss];
112       t1=mix1_phase[ss];
113       r1=mix1_old_phase[ss];
114       r2=t2-2*(mix1_old_point[ss]-mix1_point[ss])*PI_L/mix1.size;
115       r2-=old_phrot_step/4;
116       t2-=phrot_step/4;
117       old_phrot_step/=mix1.size;
118       phrot_step/=mix1.size;
119       for(i=0; i<ia; i+=2)
120         {
121         t3=sin(t1);
122         t4=cos(t1);
123         r3=sin(r1);
124         r4=cos(r1);
125         a1=timf3_float[pa+i  ];
126         a2=timf3_float[pa+i+1];
127         timf3_float[pa+i  ]=r4*a1-r3*a2+t4*fftn_tmp[i  ]-t3*fftn_tmp[i+1];
128         timf3_float[pa+i+1]=r4*a2+r3*a1+t4*fftn_tmp[i+1]+t3*fftn_tmp[i  ];
129         r1+=r2;
130         t1+=t2;
131         r2-=old_phrot_step;
132         t2+=phrot_step;
133         }
134       mix1_phase[ss]=t1;
135       pa=((timf3_pa+timf3_block)&timf3_mask)+2*ss*timf3_size-timf3_block;
136       ib=2*mix1.size;
137       for(i=ia; i<ib; i+=2)
138         {
139         timf3_float[pa+i  ]=fftn_tmp[i  ];
140         timf3_float[pa+i+1]=fftn_tmp[i+1];
141         }
142       }
143     else
144       {
145       p0=timf3_pa;
146       t2=mix1_phase_rot[ss];
147       t1=mix1_phase[ss];
148       r1=mix1_old_phase[ss];
149       r2=t2-2*(mix1_old_point[ss]-mix1_point[ss])*PI_L/mix1.size;
150       r2+=old_phrot_step/4;
151       t2+=phrot_step/4;
152       old_phrot_step/=mix1.size;
153       phrot_step/=mix1.size;
154       k-=2*(mix1.crossover_points/2);
155       j=k/2+mix1.crossover_points;
156       ia=2*mix1.crossover_points;
157       for(i=0; i<ia; i+=2)
158         {
159         pa=p0+poffs;
160         t3=sin(t1);
161         t4=cos(t1);
162         r3=sin(r1);
163         r4=cos(r1);
164         w1=mix1.sin2win[i>>1];
165         w2=mix1.cos2win[i>>1];
166         a1=w2*timf3_float[pa  ];
167         a2=w2*timf3_float[pa+1];
168         timf3_float[pa  ]=r4*a1-r3*a2+
169                                (t4*fftn_tmp[i+k  ]-t3*fftn_tmp[i+k+1])*w1;
170         timf3_float[pa+1]=r4*a2+r3*a1+
171                                (t4*fftn_tmp[i+k+1]+t3*fftn_tmp[i+k  ])*w1;
172         t1+=t2;
173         r1+=r2;
174         r2+=old_phrot_step;
175         t2+=phrot_step;
176         p0=(p0+2)&timf3_mask;
177         }
178       ib=mix1.new_points+2+2*(mix1.crossover_points/2);
179       for(i=ia; i<ib; i+=2)
180         {
181         t3=sin(t1);
182         t4=cos(t1);
183         pa=p0+poffs;
184         r1=mix1.window[j];
185         timf3_float[pa  ]=(t4*fftn_tmp[i+k  ]-t3*fftn_tmp[i+k+1])*r1;
186         timf3_float[pa+1]=(t4*fftn_tmp[i+k+1]+t3*fftn_tmp[i+k  ])*r1;
187         p0=(p0+2)&timf3_mask;
188         t1+=t2;
189         t2+=phrot_step;
190         j++;
191         }
192       j--;
193       ic=2*mix1.new_points;
194       for(i=ib; i<ic; i+=2)
195         {
196         j--;
197         pa=p0+poffs;
198         t3=sin(t1);
199         t4=cos(t1);
200         r1=mix1.window[j];
201         timf3_float[pa  ]=(t4*fftn_tmp[i+k  ]-t3*fftn_tmp[i+k+1])*r1;
202         timf3_float[pa+1]=(t4*fftn_tmp[i+k+1]+t3*fftn_tmp[i+k  ])*r1;
203         t1+=t2;
204         t2+=phrot_step;
205         p0=(p0+2)&timf3_mask;
206         }
207       mix1_phase[ss]=t1;
208       id=2*(mix1.crossover_points+mix1.new_points);
209       for(i=ic; i<id; i+=2)
210         {
211         j--;
212         pa=p0+poffs;
213         timf3_float[pa  ]=fftn_tmp[i+k  ];
214         timf3_float[pa+1]=fftn_tmp[i+k+1];
215         p0=(p0+2)&timf3_mask;
216         }
217       }
218     }
219   }
220 else
221   {
222   t1=mix1_fqwin[n];
223   fftn_tmp[4*i  ]*=t1;
224   fftn_tmp[4*i+1]*=t1;
225   fftn_tmp[4*i+2]*=t1;
226   fftn_tmp[4*i+3]*=t1;
227   fftn_tmp[4*j  ]*=t1;
228   fftn_tmp[4*j+1]*=t1;
229   fftn_tmp[4*j+2]*=t1;
230   fftn_tmp[4*j+3]*=t1;
231   i++;
232   while(j>i)
233     {
234     t1=mix1_fqwin[n];
235     fftn_tmp[4*i  ]*=t1;
236     fftn_tmp[4*i+1]*=t1;
237     fftn_tmp[4*i+2]*=t1;
238     fftn_tmp[4*i+3]*=t1;
239     fftn_tmp[4*j  ]*=t1;
240     fftn_tmp[4*j+1]*=t1;
241     fftn_tmp[4*j+2]*=t1;
242     fftn_tmp[4*j+3]*=t1;
243     j--;
244     n--;
245     i++;
246     }
247   t1=mix1_fqwin[n];
248   fftn_tmp[4*i  ]*=t1;
249   fftn_tmp[4*i+1]*=t1;
250   fftn_tmp[4*i+2]*=t1;
251   fftn_tmp[4*i+3]*=t1;
252   fftn_tmp[4*j  ]*=t1;
253   fftn_tmp[4*j+1]*=t1;
254   fftn_tmp[4*j+2]*=t1;
255   fftn_tmp[4*j+3]*=t1;
256   dual_fftback(mix1.size, mix1.n, fftn_tmp,
257                                mix1.table, mix1.permute, yieldflag_ndsp_mix1);
258   if(mix1.interleave_points == 0)
259     {
260     t2=mix1_phase_rot[ss];
261     t1=mix1_phase[ss];
262     j=4*mix1.size;
263     for(i=0; i<j; i+=4)
264       {
265       t3=sin(t1);
266       t4=cos(t1);
267       timf3_float[pa+i  ]=t4*fftn_tmp[i+k  ]-t3*fftn_tmp[i+k+1];
268       timf3_float[pa+i+1]=t4*fftn_tmp[i+k+1]+t3*fftn_tmp[i+k  ];
269       timf3_float[pa+i+2]=t4*fftn_tmp[i+k+2]-t3*fftn_tmp[i+k+3];
270       timf3_float[pa+i+3]=t4*fftn_tmp[i+k+3]+t3*fftn_tmp[i+k+2];
271       t1+=t2;
272       }
273     mix1_phase[ss]=t1;
274     }
275   else
276     {
277     pa=timf3_pa+poffs;
278     if(mix1.interleave_points == mix1.new_points)
279       {
280       ia=2*mix1.size;
281       t2=mix1_phase_rot[ss];
282       t1=mix1_phase[ss];
283       r1=mix1_old_phase[ss];
284       r2=t2-2*(mix1_old_point[ss]-mix1_point[ss])*PI_L/mix1.size;
285       r2-=old_phrot_step/4;
286       t2-=phrot_step/4;
287       old_phrot_step/=mix1.size;
288       phrot_step/=mix1.size;
289       for(i=0; i<ia; i+=4)
290         {
291         t3=sin(t1);
292         t4=cos(t1);
293         r3=sin(r1);
294         r4=cos(r1);
295         a1=timf3_float[pa+i  ];
296         a2=timf3_float[pa+i+1];
297         timf3_float[pa+i  ]=r4*a1-r3*a2+t4*fftn_tmp[i  ]-t3*fftn_tmp[i+1];
298         timf3_float[pa+i+1]=r4*a2+r3*a1+t4*fftn_tmp[i+1]+t3*fftn_tmp[i  ];
299         a1=timf3_float[pa+i+2];
300         a2=timf3_float[pa+i+3];
301         timf3_float[pa+i+2]=r4*a1-r3*a2+t4*fftn_tmp[i+2]-t3*fftn_tmp[i+3];
302         timf3_float[pa+i+3]=r4*a2+r3*a1+t4*fftn_tmp[i+3]+t3*fftn_tmp[i+2];
303         r1+=r2;
304         t1+=t2;
305         r2-=old_phrot_step;
306         t2+=phrot_step;
307         }
308       mix1_phase[ss]=t1;
309       pa=((timf3_pa+timf3_block)&timf3_mask)+4*ss*timf3_size-timf3_block;
310       ib=4*mix1.size;
311       for(i=ia; i<ib; i+=4)
312         {
313         timf3_float[pa+i  ]=fftn_tmp[i  ];
314         timf3_float[pa+i+1]=fftn_tmp[i+1];
315         timf3_float[pa+i+2]=fftn_tmp[i+2];
316         timf3_float[pa+i+3]=fftn_tmp[i+3];
317         }
318       }
319     else
320       {
321       p0=timf3_pa;
322       t2=mix1_phase_rot[ss];
323       t1=mix1_phase[ss];
324       r1=mix1_old_phase[ss];
325       r2=t2-2*(mix1_old_point[ss]-mix1_point[ss])*PI_L/mix1.size;
326       r2+=old_phrot_step/4;
327       t2+=phrot_step/4;
328       old_phrot_step/=mix1.size;
329       phrot_step/=mix1.size;
330       k-=4*(mix1.crossover_points/2);
331       j=k/4+mix1.crossover_points;
332       ia=4*mix1.crossover_points;
333       for(i=0; i<ia; i+=4)
334         {
335         pa=p0+poffs;
336         t3=sin(t1);
337         t4=cos(t1);
338         r3=sin(r1);
339         r4=cos(r1);
340         w1=mix1.sin2win[i>>2];
341         w2=mix1.cos2win[i>>2];
342         a1=w2*timf3_float[pa  ];
343         a2=w2*timf3_float[pa+1];
344         timf3_float[pa  ]=r4*a1-r3*a2+
345                                (t4*fftn_tmp[i+k  ]-t3*fftn_tmp[i+k+1])*w1;
346         timf3_float[pa+1]=r4*a2+r3*a1+
347                                (t4*fftn_tmp[i+k+1]+t3*fftn_tmp[i+k  ])*w1;
348         a1=w2*timf3_float[pa+2];
349         a2=w2*timf3_float[pa+3];
350         timf3_float[pa+2]=r4*a1-r3*a2+
351                                (t4*fftn_tmp[i+k+2]-t3*fftn_tmp[i+k+3])*w1;
352         timf3_float[pa+3]=r4*a2+r3*a1+
353                                (t4*fftn_tmp[i+k+3]+t3*fftn_tmp[i+k+2])*w1;
354         t1+=t2;
355         r1+=r2;
356         r2+=old_phrot_step;
357         t2+=phrot_step;
358 
359         p0=(p0+4)&timf3_mask;
360         }
361       ib=2*mix1.new_points+4+4*(mix1.crossover_points/2);;
362       for(i=ia; i<ib; i+=4)
363         {
364         t3=sin(t1);
365         t4=cos(t1);
366         pa=p0+poffs;
367         r1=mix1.window[j];
368         timf3_float[pa  ]=(t4*fftn_tmp[i+k  ]-t3*fftn_tmp[i+k+1])*r1;
369         timf3_float[pa+1]=(t4*fftn_tmp[i+k+1]+t3*fftn_tmp[i+k  ])*r1;
370         timf3_float[pa+2]=(t4*fftn_tmp[i+k+2]-t3*fftn_tmp[i+k+3])*r1;
371         timf3_float[pa+3]=(t4*fftn_tmp[i+k+3]+t3*fftn_tmp[i+k+2])*r1;
372         p0=(p0+4)&timf3_mask;
373         t1+=t2;
374         t2+=phrot_step;
375         j++;
376         }
377       j--;
378       ic=4*mix1.new_points;
379       for(i=ib; i<ic; i+=4)
380         {
381         j--;
382         pa=p0+poffs;
383         t3=sin(t1);
384         t4=cos(t1);
385         r1=mix1.window[j];
386         timf3_float[pa  ]=(t4*fftn_tmp[i+k  ]-t3*fftn_tmp[i+k+1])*r1;
387         timf3_float[pa+1]=(t4*fftn_tmp[i+k+1]+t3*fftn_tmp[i+k  ])*r1;
388         timf3_float[pa+2]=(t4*fftn_tmp[i+k+2]-t3*fftn_tmp[i+k+3])*r1;
389         timf3_float[pa+3]=(t4*fftn_tmp[i+k+3]+t3*fftn_tmp[i+k+2])*r1;
390         t1+=t2;
391         t2+=phrot_step;
392         p0=(p0+4)&timf3_mask;
393         }
394       mix1_phase[ss]=t1;
395       id=4*(mix1.crossover_points+mix1.new_points);
396       for(i=ic; i<id; i+=4)
397         {
398         pa=p0+poffs;
399         timf3_float[pa  ]=fftn_tmp[i+k  ];
400         timf3_float[pa+1]=fftn_tmp[i+k+1];
401         timf3_float[pa+2]=fftn_tmp[i+k+2];
402         timf3_float[pa+3]=fftn_tmp[i+k+3];
403         p0=(p0+4)&timf3_mask;
404         }
405       }
406     }
407   }
408 }
409 
do_mix1_afc(int ss)410 void do_mix1_afc(int ss)
411 {
412 int k, ia, ib;
413 int na, nx, ka, kb;
414 float error;
415 float curv;
416 int kk;
417 float t1,t2,t3;
418 float *fq, *dfq, *d2fq, *fqs;
419 // The back transforms form a time function that is mixed to
420 // zero frequency by an oscillator that is stepped in frequency
421 // with a frequency value mix1_fq_mid[i] for each transform.
422 // We may be mixing from a long transform so we do not want to
423 // wait for the next one in order to step the frequency.
424 // The routine that supplied mix1_fq_mid is responsible for
425 // supplying a value for the next transform too.
426 // Based on the old frequencies we already have used we want
427 // the center frequency at the center of the next transform
428 // to be be the current frequency plus the first and second derivatives.
429 if(genparm[SECOND_FFT_ENABLE] == 0)
430   {
431   fq=&mix1_fq_mid[ss*max_fft1n];
432   dfq=&mix1_fq_slope[ss*max_fft1n];
433   d2fq=&mix1_fq_curv[ss*max_fft1n];
434   fqs=&mix1_fq_start[ss*max_fft1n];
435   ka=(fft1_nx+fft1n_mask)&fft1n_mask;
436   kb=(fft1_nx+1)&fft1n_mask;
437   nx=fft1_nx;
438   na=fft1_nb;
439   }
440 else
441   {
442   fq=&mix1_fq_mid[ss*max_fft2n];
443   dfq=&mix1_fq_slope[ss*max_fft2n];
444   d2fq=&mix1_fq_curv[ss*max_fft2n];
445   fqs=&mix1_fq_start[ss*max_fft2n];
446   ka=(fft2_nx+fft2n_mask)&fft2n_mask;
447   kb=(fft2_nx+1)&fft2n_mask;
448   nx=fft2_nx;
449   na=fft2_na;
450   }
451 t1=fq[nx]+dfq[ka];
452 t2=fq[kb];
453 // If t1 and t2 differ we may have to make a compromise.
454 // Assuming the user has selected a reasonable bandwidth for
455 // Morse code, we do not want to modulate with frequencies
456 // above BWFAC of the bandwidth in this first AFC.
457 // Later coherent processing will be at lower bandwidth and
458 // will not handle high frequency errors we introduce here.
459 // Here the signal is noisy because of the high bandwidth required
460 // to follow a drifting signal.
461 if(fabs(t2-t1) < BWFAC*baseband_bw_hz)
462   {
463 // Extrapolation of old used data fits well to our new frequency.
464 // Store new first and second derivatives.
465   dfq [nx]= fq[kb]- fq[nx];
466   d2fq[nx]=dfq[nx]-dfq[ka];
467   }
468 else
469   {
470 // Use the maximum allowed curvature to produce a frequency that
471 // goes as quickly as possible towards the desired frequency.
472   error=t2-t1;
473   curv=BWFAC*baseband_bw_hz;
474   if(error < 0)curv=-curv;
475   t3=fabs(error)/2;
476   kk=nx;
477   k=0;
478   ia=ka;
479   ib=kb;
480   while(fabs(error) > t3 && kk != na)
481     {
482     d2fq[kk]=curv;
483     dfq[kk]=dfq[ia]+curv;
484     t1=fq[kk] + dfq[kk];
485     error=fq[ib]-t1;
486     if(t1 < mix1_lowest_fq)t1=mix1_lowest_fq;
487     if(t1 > mix1_highest_fq)t1=mix1_highest_fq;
488     fq[ib]=t1;
489     ia=(ia+1)&fftxn_mask;
490     kk=(kk+1)&fftxn_mask;
491     ib=(ib+1)&fftxn_mask;
492     k++;
493     }
494   t3=error;
495   curv=-curv;
496 // The error is reduced by 50% so we reverse the sign of the curvature.
497   while(k > 0 && kk != na && t3*error>0)
498     {
499     d2fq[kk]=curv;
500     dfq[kk]=dfq[ia]+curv;
501     t1=fq[kk] + dfq[kk];
502     error=fq[ib]-t1;
503     fq[ib]=t1;
504     ia=(ia+1)&fftxn_mask;
505     kk=(kk+1)&fftxn_mask;
506     ib=(ib+1)&fftxn_mask;
507     k--;
508     }
509   }
510 // Using the data for the transform midpoints, we get the
511 // frequency for the endpoint by adding slope/2+curv/4
512 fqs[kb]=fq[nx]+0.5*dfq[nx]+0.25*d2fq[nx];
513 t1=fqs[nx]-fq[nx];
514 t2=fqs[kb]-fq[nx];
515 // The current baseband signal produced by mix1 has an error of
516 // t1 Hz at the first point and t2 Hz at the last point.
517 // **********************************************************
518 // Actually the frequency vs time function is not quite aqurate.
519 // The way the errors t1 and t1 are used below do not agree
520 // with the explanation above.
521 // The timing seems to be slightly different depending
522 // on what window was selected.
523 // The corrections below do make the AFC work well which
524 // can be verified by feeding a frequency modulated carrier
525 // into Linrad. Typically the frequency swing would be 20 Hz
526 // and the modulation frequency 0.1 Hz for a fft1/fft2
527 // bandwidth of 2 to 5 Hz.
528 // ******************************************************************
529 do_mix1(ss,t2-t1);
530 }
531 
mix1_clear(int ss)532 void mix1_clear(int ss)
533 {
534 int i, poffs, pa;
535 poffs=ss*timf3_size;
536 pa=timf3_pa+poffs;
537 for(i=0; i<timf3_block; i++)
538   {
539   timf3_float[pa+i]=0;
540   }
541 }
542 
set_mix1_phases(float fq,int ss)543 void set_mix1_phases(float fq, int ss)
544 {
545 float t1, t2;
546 int k;
547 int fftx_pnt;
548 if(fq<mix1_lowest_fq)
549   {
550   lirerr(55232);
551   return;
552   }
553 if(fq>mix1_highest_fq)
554   {
555   lirerr(55233);
556   return;
557   }
558 // Find out what point in fft1/fft2 to pick as the center
559 // frequency in the back transformation into timf3 by mix1.
560 t1=fq*fftx_points_per_hz;
561 fftx_pnt=t1+0.5;
562 // When we do the back transformation there will be a phase shift
563 // from sample to sample (frequency shift) that depends on
564 // whether the the selected point goes even in mix1_points.
565 // Our selected frequency is a fractional number, add
566 // whatever frequency shift that originates in the decimals
567 // of t1.
568 k=fftx_pnt%mix1.size;
569 t2=mix1.size*(fftx_pnt/mix1.size);
570 t2=t1-t2-k;
571 t2=t2-(int)(t2);
572 mix1_phase_rot[ss]=t2*2*PI_L/mix1.size;
573 // when we go from one transform to the next one there is a phase
574 // jump that we store in mix1_phase_step.
575 k=(k*(mix1.new_points))%mix1.size;
576 mix1_old_phase[ss]=mix1_phase[ss];
577 mix1_phase[ss]+=mix1_phase_step[ss];
578 mix1_phase_step[ss]=k*2*PI_L/mix1.size;
579 if(mix1_point[ss] != -1)
580   {
581   mix1_old_point[ss]=mix1_point[ss];
582   }
583 else
584   {
585   mix1_old_point[ss]=fftx_pnt;
586   }
587 mix1_point[ss]=fftx_pnt;
588 if(mix1_phase[ss] > PI_L)mix1_phase[ss]-=2*PI_L;
589 if(mix1_phase[ss] < PI_L)mix1_phase[ss]+=2*PI_L;
590 }
591 
fft2_mix1_afc(void)592 void fft2_mix1_afc(void)
593 {
594 // Use fft2 with a frequency shift that is different for each transform.
595 // The frequency shift is calculated by fft2_afc and stored
596 // in mix1_fq_mid
597 int i,n,n2,ss,mm;
598 float t1;
599 int nn,kk,ia,ib,ic;
600 float *z;
601 short int *zxy;
602 n=mix1.size*ui.rx_rf_channels;
603 n2=2*n;
604 mm=twice_rxchan;
605 nn=twice_rxchan*fft2_to_fft1_ratio;
606 for(ss=0; ss<genparm[MIX1_NO_OF_CHANNELS]; ss++)
607   {
608   if(mix1_selfreq[ss] >= 0)
609     {
610 // Frequency no ss is selected.
611     t1=mix1_fq_mid[ss*max_fft2n+fft2_nx];
612     set_mix1_phases(t1,ss);
613     kk=mix1_point[ss]*mm;
614 // Copy mix1.size points to fftn_tmp and make the transform
615 // This way we select a limited frequency range and reduce
616 // the sampling rate by mix1.size/fft1_size
617     ia=nn*fft1_first_point;
618     ib=n;
619     if(ib > nn*fft1_last_point-kk)ib=nn*fft1_last_point-kk;
620     if(ib < 0)ib=0;
621     ia=0;
622     if(ia < nn*fft1_first_point-kk)ia=nn*fft1_first_point-kk;
623     for(i=0; i<ia; i++)fftn_tmp[i]=0;
624     if(fft_cntrl[FFT2_CURMODE].mmx == 0)
625       {
626       z=&fft2_float[kk+mm*fft2_nx*fft2_size];
627       for(i=ia; i<ib; i++)fftn_tmp[i]=z[i];
628       }
629     else
630       {
631       zxy=&fft2_short_int[kk+mm*fft2_nx*fft2_size];
632       for(i=ia; i<ib; i++)fftn_tmp[i]=zxy[i];
633       }
634     for(i=ib; i<n+1; i++)fftn_tmp[i]=0;
635     kk-=n2;
636     ib=n;
637     if(ib < nn*fft1_first_point-kk)ib=nn*fft1_first_point-kk;
638     for(i=n+1; i<ib; i++)fftn_tmp[i]=0;
639     ic=n2;
640     if(ic > nn*fft1_last_point-kk)ic=nn*fft1_last_point-kk;
641     if(fft_cntrl[FFT2_CURMODE].mmx == 0)
642       {
643       z=&fft2_float[kk+mm*fft2_nx*fft2_size];
644       for(i=ib; i<ic; i++)fftn_tmp[i]=z[i];
645       }
646     else
647       {
648       zxy=&fft2_short_int[kk+mm*fft2_nx*fft2_size];
649       for(i=ib; i<ic; i++)fftn_tmp[i]=zxy[i];
650       }
651     for(i=ic; i<n2; i++)fftn_tmp[i]=0;
652     do_mix1_afc(ss);
653     }
654   else
655     {
656     mix1_clear(ss);
657     }
658   }
659 timf3_pa=(timf3_pa+timf3_block)&timf3_mask;
660 fft2_nx=(fft2_nx+1)&fft2n_mask;
661 }
662 
fft2_mix1_fixed(void)663 void fft2_mix1_fixed(void)
664 {
665 // Use fft2 with a constant frequency shift given by mix1_point[]
666 int ib,i,k,n,n2,ss,mm,nn;
667 float *z;
668 float t1;
669 short int *zxy;
670 n=mix1.size*ui.rx_rf_channels;
671 n2=2*n;
672 mm=twice_rxchan;
673 nn=twice_rxchan*fft2_to_fft1_ratio;
674 for(ss=0; ss<genparm[MIX1_NO_OF_CHANNELS]; ss++)
675   {
676   t1=mix1_selfreq[ss];
677   if(t1 >= 0)
678     {
679 // Frequency no ss is selected.
680     set_mix1_phases(t1,ss);
681 // Copy mix1.size points to fftn_tmp and make the transform
682 // This way we select a limited frequency range and reduce
683 // the sampling rate by mix1.size/fft1_size
684     k=mix1_point[ss]*mm;
685     ib=n;
686     if(ib > nn*fft1_last_point-k)ib=nn*fft1_last_point-k;
687     if(ib < 0) ib=0;
688     if(fft_cntrl[FFT2_CURMODE].mmx == 0)
689       {
690       z=&fft2_float[k+mm*fft2_nx*fft2_size];
691       for(i=0; i<ib; i++)fftn_tmp[i]=z[i];
692       }
693     else
694       {
695       zxy=&fft2_short_int[k+mm*fft2_nx*fft2_size];
696       for(i=0; i<ib; i++)fftn_tmp[i]=zxy[i];
697       }
698     for(i=ib; i<n; i++)fftn_tmp[i]=0;
699     k-=n2;
700     ib=n;
701     if(ib < nn*fft1_first_point-k)ib=nn*fft1_first_point-k;
702     for(i=n; i<ib; i++)fftn_tmp[i]=0;
703     if(fft_cntrl[FFT2_CURMODE].mmx == 0)
704       {
705       z=&fft2_float[k+mm*fft2_nx*fft2_size];
706       for(i=ib; i<n2; i++)fftn_tmp[i]=z[i];
707       }
708     else
709       {
710       zxy=&fft2_short_int[k+mm*fft2_nx*fft2_size];
711       for(i=ib; i<n2; i++)fftn_tmp[i]=zxy[i];
712       }
713     do_mix1(ss,0);
714     }
715   else
716     {
717     mix1_clear(ss);
718     }
719   }
720 timf3_pa=(timf3_pa+timf3_block)&timf3_mask;
721 fft2_nx=(fft2_nx+1)&fft2n_mask;
722 }
723 
fft1_mix1_fixed(void)724 void fft1_mix1_fixed(void)
725 {
726 // Use fft1 with a constant frequency shift given by mix1_point[]
727 int i,n,n2,ss,mm;
728 float *x;
729 int kk,ib;
730 float t1;
731 n=mix1.size*ui.rx_rf_channels;
732 n2=2*n;
733 mm=twice_rxchan;
734 for(ss=0; ss<genparm[MIX1_NO_OF_CHANNELS]; ss++)
735   {
736   t1=mix1_selfreq[ss];
737   if(t1 >= 0)
738     {
739 // Frequency no ss is selected.
740     if(rx_mode != MODE_TXTEST)
741       {
742       set_mix1_phases(t1,ss);
743       }
744     kk=mix1_point[ss]*mm;
745 // Copy mix1.size points to fftn_tmp and make the transform
746 // This way we select a limited frequency range and reduce
747 // the sampling rate by mix1.size/fft1_size
748     x=&fft1_float[fft1_px+kk];
749     ib=n;
750     if(ib > mm*fft1_last_point-kk)ib=mm*fft1_last_point-kk;
751     if(ib < 0) ib=0;
752     for(i=0; i<ib; i++)fftn_tmp[i]=x[i];
753     for(i=ib; i<=n; i++)fftn_tmp[i]=0;
754     kk-=n2;
755     x=&fft1_float[fft1_px+kk];
756     ib=n;
757     if(ib < mm*fft1_first_point-kk)ib=mm*fft1_first_point-kk;
758     for(i=n; i<ib; i++)fftn_tmp[i]=0;
759     for(i=ib; i<n2; i++)fftn_tmp[i]=x[i];
760     do_mix1(ss,0);
761     }
762   else
763     {
764     mix1_clear(ss);
765     }
766   }
767 timf3_pa=(timf3_pa+timf3_block)&timf3_mask;
768 fft1_nx=(fft1_nx+1)&fft1n_mask;
769 fft1_px=(fft1_px+fft1_block)&fft1_mask;
770 }
771 
772 
773 
fft1_mix1_afc(void)774 void fft1_mix1_afc(void)
775 {
776 // Use fft1 with a frequency shift that is different for each transform.
777 // The frequency shift is calculated by fft1_afc and stored
778 // in mix1_fq_mid
779 int i,n,n2,ss,mm;
780 float *x;
781 float t1;
782 int kk,ia,ib,ic;
783 n=mix1.size*ui.rx_rf_channels;
784 n2=2*n;
785 mm=twice_rxchan;
786 for(ss=0; ss<genparm[MIX1_NO_OF_CHANNELS]; ss++)
787   {
788   if(mix1_selfreq[ss] >= 0)
789     {
790 // Frequency no ss is selected.
791     t1=mix1_fq_mid[ss*max_fft1n+fft1_nx];
792     set_mix1_phases(t1,ss);
793     kk=mix1_point[ss]*mm;
794 // Copy mix1.size points to fftn_tmp and make the transform
795 // This way we select a limited frequency range and reduce
796 // the sampling rate by mix1.size/fft1_size
797     x=&fft1_float[fft1_nx*fft1_block+kk];
798     ia=mm*fft1_first_point;
799     ib=n;
800     if(ib > mm*fft1_last_point-kk)ib=mm*fft1_last_point-kk;
801     if(ib < 0)ib=0;
802     ia=0;
803     if(ia < mm*fft1_first_point-kk)ia=mm*fft1_first_point-kk;
804     for(i=0; i<ia; i++)fftn_tmp[i]=0;
805     for(i=ia; i<ib; i++)fftn_tmp[i]=x[i];
806     for(i=ib; i<n+1; i++)fftn_tmp[i]=0;
807     kk-=n2;
808     x=&fft1_float[fft1_nx*fft1_block+kk];
809     ib=n;
810     if(ib < mm*fft1_first_point-kk)ib=mm*fft1_first_point-kk;
811     for(i=n+1; i<ib; i++)fftn_tmp[i]=0;
812     ic=n2;
813     if(ic > mm*fft1_last_point-kk)ic=mm*fft1_last_point-kk;
814     for(i=ib; i<ic; i++)fftn_tmp[i]=x[i];
815     for(i=ic; i<n2; i++)fftn_tmp[i]=0;
816     do_mix1_afc(ss);
817     }
818   else
819     {
820     mix1_clear(ss);
821     }
822   }
823 timf3_pa=(timf3_pa+timf3_block)&timf3_mask;
824 fft1_nx=(fft1_nx+1)&fft1n_mask;
825 fft1_px=(fft1_px+fft1_block)&fft1_mask;
826 }
827 
828 
829 
830 
831 
832 
833 
834 
835