Développement de SDR multicanal

Je vais vous parler de mon expérience dans le développement d'un récepteur numérique multicanal à large bande.

Depuis de nombreuses années, je travaille dans le domaine de la création de moyens de capture et de traitement des signaux des radars de navigation aérienne et côtière. Il y a environ deux ans, j'ai publié la dernière version à jour de notre carte RVAQ (Radar Video AcQuisition) et je me suis demandé quoi faire dans la vie. Je voulais quelque chose de nouveau et d'inconnu. Le choix s'est porté sur le domaine que je n'ai pas encore couvert - la radio numérique avec une entrée facile dans la région des micro-ondes.

Il s'agit du premier chapitre consacré à la formulation initiale du problème.

Par où commencer si vous n'avez jamais été professionnellement engagé dans la réception radio numérique, à l'exception du récepteur Mishutka assemblé dans l'enfance? Bien sûr, avec un rafraîchissement à la lecture de Polyakov et du modèle dans MATLAB. L'idée initiale était de créer un récepteur multicanal dans la gamme 156-162 MHz pour surveiller et enregistrer toutes les conversations actives dans la bande VHF marine. Je vais énumérer les propriétés souhaitées d'un tel récepteur:
1. La bande de réception est d'au moins 6 MHz (162-156 = 6)
2. La sensibilité n'est pas pire que -110 dBm, sinon ils riront.
3. Une large plage dynamique, car lorsque vous écoutez un navire sur le rivage en mer pendant 30 miles, quelqu'un va certainement crier à proximité avec ses 25 watts. Pour les récepteurs décents, le niveau de blocage doit être d'au moins 70 dB. Un peu en avance, je dirai qu'il s'est avéré réaliser plus de 90 dB de blocage. Bref, RTL-SDR n'a pas répondu aux attentes. Aussi étrange que cela puisse paraître, j'ai commencé par choisir l'ADC. Étant donné que, dans la nature, il n'y a pas d'ADC correspondants (du moins en théorie), cela ne vaut pas la peine d'être pris. Un tel ADC a été trouvé.

Vous devez maintenant choisir l'architecture du récepteur. Une revue des solutions pertinentes, l'étude de la base de l'élément et l'intuition ont permis de s'attarder sur le récepteur à conversion directe. Il a également été décidé de transférer la zone d'intérêt du spectre à l'aide du démodulateur en quadrature à fréquence nulle et de travailler dans la première zone de Nyquist afin de maximiser l'utilisation de toutes les qualités du CAN sélectionné.

Modèle initial d'estimation des paramètres
clear all;
k				= 1.381e-23;	% Joule/K 	- Boltzmann's Constant
T0				= 290;			% K			- temperature
% Encoding Windows-1251

% 1.     
% 1010          -       
% 1011          -    
% 1012          -     (/.)
% 1013          -      
% 1014          -      
% 1015          -    
% 1021, 1022    -     .
% 1031, 1032    -    
% 1041, 1042    -      
% 1051, 1052    -   

% 2.            

		Rrf_inp_ohm			= 50;		% Ohm	- 	 .

% 2011  -    
        BWrf_ekv_prf_hz   	= 20.0e6;   % Hz	-	    
        Lrf_max_prf_db      =  1.0;     % dB 	- 	        (insertion loss)
        
% 2012  -    
% (    Agilent MGA-71543    )
        Grf_lna_db     	    = 16.0;     % dB 	- 	   
        NFrf_lna_db         = 1.0;      % dB		- 	   
        
% 2013  -      
        BWrf_ekv_fms_hz   	=  6.0e6;   % Hz	-	     
        Lrf_max_fms_db      =  4.0;    % dB 	- 	         (insertion loss)
        
% 2014  -      
% (    Agilent MGA-71543    )
        Grf_amp_db      	=  16.0;    % dB 	- 	   
        NFrf_amp_db     	=  1.0;     % dB    - 	  
		
% 2015  -    
% (    Analog Devices ADL5387)
        Grf_mix_db      	=   4.5;    	% dB 	- 	    
        NFrf_mix_db     	=  15.0;    	% dB    - 	   
		IP1dBrf_mix_dbw		=  13.0 - 30.0; % dBW	- 	Input P1dB (IP1dB)

% 3.                
% 3011	-	
%    (db)
        NFrf_sys_db = pow2db( ( db2pow(  Lrf_max_prf_db )       ) + ...                   
                              ( db2pow( NFrf_lna_db     ) + 1 ) / ( db2pow( -Lrf_max_prf_db )) + ...
                              ( db2pow(  Lrf_max_fms_db ) + 1 ) / ( db2pow( -Lrf_max_prf_db ) * db2pow(  Grf_lna_db )) + ...
                              ( db2pow( NFrf_amp_db     ) + 1 ) / ( db2pow( -Lrf_max_prf_db ) * db2pow(  Grf_lna_db ) * db2pow( -Lrf_max_fms_db )) + ...
							  ( db2pow( NFrf_mix_db     ) + 1 ) / ( db2pow( -Lrf_max_prf_db ) * db2pow(  Grf_lna_db ) * db2pow( -Lrf_max_fms_db ) * db2pow(  Grf_amp_db )) ...
                            );

%    (dB)
		Grf_sys_db	= ( Grf_lna_db + Grf_amp_db + Grf_mix_db ) - ( Lrf_max_prf_db + Lrf_max_fms_db );
		
%      (Hz)
		BWrf_sys_hz = BWrf_ekv_fms_hz;

% 3012	-	Baseband LPF
		Lbb_lpf_db		= 9;		% dB			-	   Baseband LPF    (insertion loss)
		
% 3013	-	Baseband  (LTC6400-14)
		Gbb_opa_db		= 0;		% dB			-	  
		NFbb_opa_db     = 0;      % dB			-	  	

%    ,      (dB)
		Gbb_lfa_db		= Gbb_opa_db - Lbb_lpf_db;
		
%         (dB) -   . 
		NFbb_sys_db     = pow2db( ( db2pow( NFrf_sys_db         )     ) + ...                   
                                  ( db2pow( NFbb_opa_db         ) + 1 ) / ( db2pow( Grf_sys_db )) ...
					    		);
							
%         (dB)
		Gbb_sys_db	    = Grf_sys_db + Gbb_lfa_db; 

%       (Hz) -  
		BWbb_sys_hz		= BWrf_sys_hz;
		
%         (dBW)		
		PNbb_out_dbw	= pow2db( k * T0 * BWrf_sys_hz ) + NFbb_sys_db + Gbb_sys_db;	

% 3014	-	 
% (    1  Linear Technology LTC2271)
		FSadc_hz		= 20.0e6;	% Hz	-	Sampling rate		
		SNadc_fs_db		= 84;		% dB	-	SNR 
		NBadc_fs_bits	= 16;		% bits 	-	Full scale bits
		Vadc_fs_v		= 2;		% V		-	Full scale voltage
		Radc_inp_ohm	= 1000;		% Ohm	-	Input ADC resistance	

%            (dBW)			
		PFSadc_inp_dbw	= pow2db( 2.0 * (( Vadc_fs_v * 0.5 * sqrt( 0.5 )) ^ 2 ) / Radc_inp_ohm );  
		
%      (dBW)			
		PNadc_snr_dbw	= PFSadc_inp_dbw - SNadc_fs_db;
		
%      (dBW)
		PNadc_qan_dbw	= PFSadc_inp_dbw - ( NBadc_fs_bits * mag2db( 2 ) + mag2db( sqrt( 6 ) / 2 )); % adding correction factor for sinusoidal signal			
					
% 3015	-	     
        SNfm_min_db		= 12.0;		% dB  		-   -       
		BWfm_max_hz		= 25.0e3;	% Hz 		-    ,    		
		BWfm_min_hz		= 6.25e3;	% Hz 		-      ,    

%   (dBW)         (     )	
		Pfm_min_dbw		= pow2db( k * T0 * BWfm_max_hz ) + NFbb_sys_db + SNfm_min_db;		
		
%         ,      (dBW)
		Pfm_min_bb_sys_dbw 	= Pfm_min_dbw + Gbb_sys_db;		

%     .        
%        (dBW)
		PFSmix_inp_dbw = PFSadc_inp_dbw - Gbb_lfa_db - Grf_mix_db;		

%       ( )
		deltaPmix_inp_lin = IP1dBrf_mix_dbw - PFSmix_inp_dbw; 
		



Maintenant je veux des photos
%       
Nfft = 2 * (( FSadc_hz / 2 ) / BWfm_min_hz ); 
Nsmp = Nfft;

tmp_fft_buf = zeros( 1, Nfft );
tmp_acc_buf = zeros( 1, Nfft );
tmp_smp_buf = zeros( 1, Nsmp );

max_acc = 30;

for acc = 1:max_acc
%   1 
%     -      
%    -       

  PS1 = db2pow( Pfm_min_bb_sys_dbw );
  WS1 = 25.0e3;
  FS1 =  1.0e6;
  
  Fstart = FS1;
  Fstop  = Fstart + WS1 - BWfm_min_hz;
  Pstep  = PS1 / ( WS1 / BWfm_min_hz ); 
  PS1_smp_buf = zeros( 1, Nsmp );
  
  for f = Fstart:BWfm_min_hz:Fstop
      phi_acc = 2.0 * pi * rand( 1 ); % random phase
      phi_stp =       pi * ( f / ( FSadc_hz / 2 ));
      
      for k = 1:Nsmp
          PS1_smp_buf( k ) = PS1_smp_buf( k ) + sqrt( Pstep ) * exp( j * phi_acc );
          phi_acc = phi_acc + phi_stp;
          
          if( phi_acc > (  2.0 * pi ))
              phi_acc = phi_acc - 2.0 * pi;
          else
              if( phi_acc < ( -2.0 * pi ))
                  phi_acc = phi_acc + 2.0 * pi;
              end
          end
      end
  end

%   2 
%     -       
%    -       

  PS2 = db2pow( PFSadc_inp_dbw - 1.0 ); % -1 dB back off 
  WS2 = 25.0e3;
  FS2 = -2.0e6;
  
  Fstart = FS2;
  Fstop  = Fstart + WS2 - BWfm_min_hz;
  Pstep  = PS2; 
  PS2_smp_buf = zeros( 1, Nsmp );
  
  for f = Fstart:BWfm_min_hz:Fstop
      phi_acc = 2.0 * pi * rand( 1 ); % random phase
      phi_stp =       pi * ( f / ( FSadc_hz / 2 ));
      
      for k = 1:Nsmp
          PS2_smp_buf( k ) = PS2_smp_buf( k ) + sqrt( Pstep ) * exp( j * phi_acc );
          phi_acc = phi_acc + phi_stp;
          
          if( phi_acc > (  2.0 * pi ))
              phi_acc = phi_acc - 2.0 * pi;
          else
              if( phi_acc < ( -2.0 * pi ))
                  phi_acc = phi_acc + 2.0 * pi;
              end
          end
      end
  end

%      
  PN1 = db2pow( PNbb_out_dbw );
  WN1 = BWbb_sys_hz;
  
  Pfull_bw = PN1 * ( FSadc_hz / WN1 );
  
  PN1_smp_buf = sqrt( 0.5 * Pfull_bw ) * complex( randn( 1, Nsmp ), randn( 1, Nsmp ));
  tmp_fft_buf = fftshift( fft( PN1_smp_buf ));
  tmp_msk_buf = zeros( 1, Nfft );
  tmp_msk_buf((( Nfft / 2 ) - (( WN1 / FSadc_hz ) * ( Nfft / 2 )) + 1 ) : (( Nfft / 2 ) + (( WN1 / FSadc_hz ) * ( Nfft / 2 )))) = ... 
              ones( 1, (( WN1 / FSadc_hz ) * Nfft ));
  
  tmp_fft_buf = tmp_fft_buf .* tmp_msk_buf;
  PN1_smp_buf = ifft( fftshift( tmp_fft_buf ));

%    
  PN2 = db2pow( PNadc_snr_dbw ) - db2pow( PNadc_qan_dbw );
  %PN2 = db2pow( PNadc_snr_dbw );
  
  Pfull_bw = PN2;
  
  PN2_smp_buf = sqrt( 0.5 * Pfull_bw ) * complex( randn( 1, Nsmp ), randn( 1, Nsmp ));

%    
  QAN_smp_buf = PS1_smp_buf + PS2_smp_buf + PN1_smp_buf + PN2_smp_buf;
  
  QAN_delta = Vadc_fs_v / ( 2 ^ NBadc_fs_bits );
  
  QAN_smp_buf = round( QAN_smp_buf ./ QAN_delta ) .* QAN_delta;
  
  QAN_smp_buf_re = real( QAN_smp_buf );
  QAN_smp_buf_re( find( QAN_smp_buf_re > (  Vadc_fs_v / 2.0 ))) =  Vadc_fs_v / 2.0;
  QAN_smp_buf_re( find( QAN_smp_buf_re < ( -Vadc_fs_v / 2.0 ))) = -Vadc_fs_v / 2.0;
  
  QAN_smp_buf_im = imag( QAN_smp_buf );
  QAN_smp_buf_im( find( QAN_smp_buf_im > (  Vadc_fs_v / 2.0 ))) =  Vadc_fs_v / 2.0;
  QAN_smp_buf_im( find( QAN_smp_buf_im < ( -Vadc_fs_v / 2.0 ))) = -Vadc_fs_v / 2.0;
  
  QAN_smp_buf = complex( QAN_smp_buf_re, QAN_smp_buf_im );

%   ADC

  tmp_smp_buf = QAN_smp_buf;
  %tmp_smp_buf = PS1_smp_buf + PS2_smp_buf + PN1_smp_buf + PN2_smp_buf;
  
  tmp_fft_buf = fft( tmp_smp_buf ) / Nfft;
  tmp_acc_buf = tmp_acc_buf + ( tmp_fft_buf .* conj( tmp_fft_buf ));
end  

tmp_acc_buf = tmp_acc_buf ./ max_acc;

f = linspace(( -FSadc_hz / 2 ) + BWfm_min_hz, FSadc_hz / 2, Nfft );

plot( f, pow2db( fftshift( tmp_acc_buf ))); 
xlim( [( -FSadc_hz / 2 ), ( FSadc_hz / 2 )] ); 
ylim( [-150.0, -20.0] ); 
title('Power Spectrum')
xlabel('Frequency (Hz)')
ylabel('P(f) dBW')
drawnow;



Eh bien, le modèle a montré la viabilité de l'idée - sensibilité -115dBm, blocage sous 90dB.

De plus, dans le FPGA, en utilisant le bloc de normalisation des signaux en quadrature, nous supprimons la composante constante, gérons le canal miroir et appliquons le signal à l'entrée DDC . Après la dérive de la fréquence d'intérêt vers zéro, le signal ira à une chaîne de filtres numériques CIC et FIR , formant une bande de canaux. Bien sûr, si nous voulons recevoir simultanément plus d'un canal, nous devons avoir un tas de DDC et de filtres.

Dans le prochain article, si le public est intéressé, je parlerai des prochaines étapes de la modélisation et de l'évaluation des ressources matérielles FPGA.

Source: https://habr.com/ru/post/fr395853/


All Articles