Código fuente de demodulación Ofdm
Manteniendo el canal estimado. Hay una curva de tasa de error de bits
Borrar todo;
Cerrar todo;
Fprintf( '\n simulación OFDM\ n \ n '); p >
-
Definición de parámetros
-
IFFT_bin_length = 1024
Recuento de portadores = 200;
Número de bits por símbolo = 2;
Símbolos por portadora = 50
Número de subportadoras 200
Números/símbolos 2
p>
Símbolos/portadora 50
Número de símbolos de entrenamiento 10
Longitud del prefijo cíclico T/4 (nota del autor) CP todo cero
Modo de modulación QDPSK
Porcentaje de canales multitrayecto 2, 3 y 4 (predeterminado)
Retraso máximo del canal 7 (símbolos de datos unitarios)
Condicional simulado transmitir y recibir Sincronización estricta entre
SNR = entrada ('SNR =' parámetros de relación señal-ruido de entrada
Relación señal-ruido = 3:14; rango de relación señal-ruido
BER = cero (1, longitud (SNR));
Longitud de salida de la banda base = recuento de portadoras * símbolo por portadora * bits por símbolo calcular el longitud de la secuencia binaria transmitida
carriers =(1: carrier _ count) (floor(IFFT _ bin _length/4)-floor(carrier _ count/2)); 156, 157-356
Conjugate_carrier = IFFT_bin_length-carrier2; coordenadas: 1024-(157:356) 2 = 1026-(157:356)=(869:670)
Construcción * * *matriz portadora de tiempo yugo, aplicando así el llamado RCC, reduciendo la complejidad computacional del algoritmo, es decir, el resultado después de ifft es un número real.
Defina la matriz portadora de tiempo conjugada
También puede utilizar la función flipdim para construir una matriz de yugo * * * simétrica.
-
Emisión de señal
-
out = rand(1, baseband_out_length);
baseband _ salida 1 = ronda(salida);
banda base _ salida 2 = piso(salida * 2
banda base _ salida 3 = techo(salida * 2)- 1; p>
baseband_out4 = randint(1, baseband _ out _ length);
Cuatro formas de generar la secuencia binaria a enviar, elija cualquiera para generar la secuencia binaria a enviar.
if(salida de banda base 1 == amplificador de salida de banda base baseband_out1 == baseband_out3)
fprintf('Se ha generado la secuencia de transmisión \ n \ n '); > baseband _ out = baseband _ out 1;
En caso contrario
fprintf('¡¡¡Compruebe el código!!!!!!!!!!!!!!!!!!!! ! ! ! \n\n');
Fin
Cuatro formas de generar una secuencia binaria enviada.
Baseband_out=round( rand(1, baseband_out_length));
convert_matrix = forma(baseband_out, bits_per_symbol, length(baseband_out) /bits_per_symbol);
Para k = 1 longitud (salida de banda base)/bits por símbolo),
modulo_baseband(k) = 0;
Para i = 1: bits por símbolo
módulo_baseband(k) = módulo_baseband(k) transform_matrix(I,k)*2^(bits_per_symbol-I
Fin
Fin
Convertir cada 2); bits en un número entero de 0 a 3.
Usa el modo "msb izquierdo".
-
Porcentaje de pruebas realizadas por lavabin
Una función incorporada que convierte directamente bits binarios a números decimales
-
p>convert_matrix 1 = 0(longitud(baseband_out)/bits_per_symbol,bits_per_symbol);
convert_matrix 1 = convert_matrix ';
Prueba _ convert_ matriz 1 = bi2de(convertir _ matriz 1, bits_per_symbol, ' left-msb ');
Prueba _ convert _ matriz 2 = bi2de(convertir _ matriz 1, bits_per_symbol, 'right-msb');
Descripción de la función:
BI2DE convierte un vector binario en un número decimal.
D = BI2DE(B) convierte el vector binario B en un valor decimal D. Cuando B es una matriz, la transformación se realiza por filas y la salida D es un vector de columna de valores decimales. La orientación predeterminada para la entrada de archivos binarios
es derecha-MSB; el primer elemento en B representa el bit menos significativo.
if(modulo_baseband==Prueba_convert_matriz 1')
fprintf('modulo_baseband=Prueba_convert_matriz 1\n\n'); /p>
else if(módulo _ baseband = = Prueba _ convertir _ matriz 2')
fprintf(' módulo _ baseband = Prueba _ convertir _ matriz 2 \ n \ n '); /p>
De lo contrario
fprintf(' módulo _ baseband ~ = cualquier Prueba _ convert _ matriz \ n \ n ');
Fin
Fin
Obtenemos el resultado "modulo_baseband = Test_convert_matrix 1".
-
carrier_matrix = shape(modulo_baseband, carrier_count, simbolos_per_carrier)';
Generar matriz de portadoras de tiempo
-
Modulación QDPSK
-
carrier_matrix = [zeros(1, Carrier_count); Carrier_matrix]; agrega inicialización para la fase de modulación diferencial, que es 0.
Para i = símbolos por portadora 1)
carrier_matrix(i, = rem(carrier_matrix(i, carrier_matrix (i-1,, 2^bits_per_symbol)); Modulación diferencial p >
Fin
Carrier_matrix = carrier_matrix*((2*pi)/(2^bits_per_symbol)); generar fase diferencial
[X, Y]=pol2cart. carrier_matrix, ones(size(carrier_matrix, 1), size(carrier_matrix, 2)); desde coordenadas polares hasta coordenadas complejas, el primer parámetro es la fase y el segundo parámetro es la amplitud.
Carrier_matrix contiene todo información de fase y todas las amplitudes son iguales "1".
Complex_carrier_matrix=complex(X,Y);
Añadir secuencia de entrenamiento` 2
training _ símbolos =[1j j 1-1j j j 1j j 1j j 1j j 1j j 1j j 1j j 1j...
-j-j-1 1j j-1-j-1j-j-1j-1j-j-1j-1j-1j- 1j-1j- 1j-1j-j-1...
1j j 1-1-j-j-1j j 1j j 1j j 1j j 1j j 1-1j-j 1-j 1-j 1j 1j 1j 1j 1...
-1-j-j-1j j 1j j 1j-j-1j j 1-j-j-1j-j-1j-j-1j 1j j 1j 1j 1-j -1j-j -65438...
-1 1j j 1-j-j-1j j 1j j 1j-j-1j j j 1j j 1j j 1j 1j 25 veces " 1 j j 1 ", 25 veces "-1 - j -j -1 ", un total de 200 símbolos en una línea
training_symbols = cat(1, Training_symbols, Training_symbols);
training_symbols = cat(1, Training_symbols, Training_symbols) ; generar 4 filas de símbolos de entrenamiento
Complex_carrier_matrix = cat(1, Training_symbols, complex_carrier_matrix); fusionar secuencia de entrenamiento con datos
Símbolos piloto de tipo bloque
IFFT_modulation= cero (4 símbolos por portador, IFFT_bin_length);
Aquí, el vector de fila de ceros se encuentra entre los símbolos de entrenamiento y ¡Entre los símbolos de datos! ! !
4 símbolos de entrenamiento y 1 símbolo cero
Cada símbolo OFDM ocupa una fila de "modulación IFFT"
IFFT_modulation(:, portadora) = número complejo _carrier_matrix;
IFFT _modulation(:, conjugate_carrier) = conj(complex_carrier_matrix);
-
Probado por lavabin - índice de ceros encontrado
index_of_zeros = zeros(símbolos por operador, IFFT_bin_length-2 * recuento de operadores);
IFFT_modulation1 = zeros(4 símbolos_ 1 por operador, IFFT_bin_length);
IFFT_modulation2=zero (4 símbolos por portadora, IFFT_bin_length);
IFFT_modulation1( 6: símbolos_5 por portadora, = IFFT_modulation(6: símbolos_5 por portadora, = = 0;
Porcentaje de i = 1: símbolos por portadora
index_of_zeros (i, = buscar(IFFT_modulation1(i 5, = = 1);
Fin
-
Time_Wave_Matrix = IFFT( IFFT_modulation'); utilizado para operaciones IFFT
Matriz de onda de tiempo = matriz de onda de tiempo'; Si X es una matriz, ift devuelve la transformada de Fourier inversa de cada columna de la matriz.
Para i = 1: 4 símbolos por portadora 1
windowed_time_wave_matrix( i,) = real(time_wave_matrix( i,));
End
p>Obtener la parte real del resultado IFFT
Este paso se puede omitir porque los resultados IFFT son todos números reales.
Se puede ver que solo se toman los puntos del operador después de IFFT, sin copiar CP ni agregar final.
OFDM_modulation = reshape(windowed_time_wave_matrix',1,IFFT_bin_length*(4 símbolos_1 por portadora));
Operación P2S
-
Porcentaje de pruebas realizadas por lavabin
Otra forma de conversión matricial
ofdm_modulation_tmp = windowed_time_waveform_matrix. ;
OFDM _ modulación _ prueba = OFDM _ modulación _ tmp(';
if (prueba de modulación ofdm == modulación ofdm)
fprintf(' OFDM _ modulación _ prueba = = OFDM _ modulación \ n \ n ');
En caso contrario
fprintf(' OFDM _ modulación _ prueba ~ = OFDM _ modulación \ n \ n ') ;
Fin
Obtenemos el resultado "OFDM_modulation_test == OFDM_modulation".
-
Tx_datos = ofdm_modulación
-
Simulación de canal
-
d 1 = 4; a 1 = 0,2; D2 = 5; a2 = 0,3D3 = 6; a3 = 0,4D4 = 7; a4 = 0,5 simulación de canal
copiar1 = cero ( Tx_data));
Para i = 1 d1: longitud(Tx_data)
copia 1(I)= a 1 * Tx_data(I-d 1);
Fin
copia2 = cero(tamaño(Tx_data));
Para i = 1 d2: longitud(Tx_data)
copia 2 (I)= a2 * Tx_data(I-D2);
Fin
copiar3 = cero(tamaño(Tx_data));
Para i = 1 d3: longitud (Tx_data )
copia 3(I)= a3 * Tx _ data(I-D3);
Fin
copia4 = cero(tamaño(Tx_data));
Para i = 1 d4: longitud(Tx_data)
copiar 4(I)= a4 * Tx_data(I-D4);
Fin
Tx_datos = Tx_datos copia 1 copia 2 copia 3 copia 4 multirutas
Tx_señal_potencia = var (Tx_data);
Para IDX = 1: Longitud (Relación señal-ruido) Simulación Monte Carlo
linear_SNR = 10^(Relación señal-ruido (idx)/10
ruido _σ= Tx _ señal _ potencia); /linear _ SNR;
Noise_scale_factor = sqrt(noise_sigma);
ruido = randn (1, longitud (Tx _ data)) * ruido _ escala _ factor
Rx_Data = Ruido Tx_data
-
Recepción de señal
-
Rx _ Data _ matriz = forma(Rx _ Datos, IFFT_bin_length, 4 símbolos _ por _ portadora 1);
Rx _ espectro = FFT(Rx _ Data _ matriz);
Asume una sincronización precisa entre Tx y Rx
Rx _ portadoras = Rx _ espectro(portadoras,)';
Rx _ entrenamiento _ símbolos = Rx_portadoras((1:4),:);
Rx_carrier = Rx_carriers((5:55),:);
-
Estimación de canal
-
Rx_training_symbols = Rx_training_symbols.
/símbolos_entrenamiento;
Rx_training_symbols_deno = Rx_training_symbols. ^2;
Rx_training_symbols_deno = Rx_training_symbols_deno(1, Rx_training_symbols_deno(2, Rx_training_symbols_deno(3, Rx_training_symbols_deno(4,);
Rx_training_symbols_nume = Rx_training_symbols(1,) ing_symbols(2,) Rx_training_symbols(3,) Rx_training_symbols(4,);
Rx_training_symbols_nume = conj(Rx_training_symbols_nume);
Tome los símbolos piloto de 4 vectores para una optimización promedio
Operación en el "vector de línea", es decir, un único símbolo OFDM
< El principio de p>: encontrar 1/H para realizar una compensación en el dominio de la frecuencia en los datos después de FFT1/H = conj(H)/H^2 porque H^2 = H * conj(H)
Rx_training_symbols = Rx_training_symbols_nume /Rx_training_symbols_deno; Rx_training_symbols_nume.
/Rx_training_symbols_deno;
Rx_training_symbols_2 = cat(1, Rx_training_symbols, Rx_training_symbols);
Rx_training_symbols_ 4 = cat(1,Rx_training_symbols_2,Rx_training_symbols_2);
Rx_training_symbols _8 = gato (1,Rx_training_symbols_4,Rx_training_symbols_4);
Rx_training_symbols_16 = cat(1,Rx_training_symbols_8,Rx_training_symbols_8);
Rx_training_symbols_32 = cat(1,Rx_training_symbols_16,Rx_ bols_16);
Rx_training_symbols_48 = cat(1,Rx_training_symbols_32,Rx_training_symbols_16);
Rx_training_symbols_ 50 = cat(1,Rx_training_symbols_48,Rx_training_symbols_2);
Rx_training_symbols = cat(1,Rx_train ing_symbols_50,Rx_training_symbols);
Rx_carriers = Rx_training_symbols. * Los Rx_carriers se utilizan para la ecualización de un solo toque en el dominio de la frecuencia.
Rx_phase = ángulo(Rx_carriers)*(180/pi);
phase_negative = find(Rx_phase lt;0);
-Prueba usando "rem" -
Fase_Rx 1 = Fase_Rx;
Fase_Rx2 = Fase_Rx
Fase_Rx 1(fase_negativa)= rem(Fase_Rx 1(fase_negativa) 360, 360); p>
Rx_fase 2(fase_negativa)= Rx_fase 2(fase_negativa) 360;
si Rx_fase 2(fase_negativa)= = Rx_fase 1(fase_negativa)
fprintf('\nNo es necesario usar rem en la transición de fase negativa.\n n ')
De lo contrario
fprintf('\nNecesitamos usar rem en la transición de fase negativa .
\n ')
Fin
-
Rx _ fase(fase _ negativa)= rem(Rx _ fase(fase _ negativa) 360, 360) ;Convertir fase negativa en fase positiva
Rx _ decodificado _ fase = diff(Rx _ fase
Es por eso que la fase inicial se agrega delante.
"¡¡¡El vector fila de ceros aquí está entre los símbolos de entrenamiento y los símbolos de datos!!!"
phase _ negativo = find(Rx _ decode _ fase lt; 0);
Rx_decoded_phase(phase_negative)= rem(Rx_decoded_phase(phase_negative) 360, 360); Convierte la fase negativa en fase positiva nuevamente.
-
Demodulación QDPSK
-
base _ fase = 360 /2^bits_per_symbol
δ_phase; = base_phase/2;
Rx_decoded_symbols = zero(size(Rx_decoded_phase, 1), size(Rx_decoded_phase, 2));
Para I = 1: (2^ bits_per_symbol-1)
fase_centro = fase_base * I;
plus_delta = fase_centro fase_delta; umbral de decisión 1
menos_delta = fase central - fase_delta 2
decodificado = find((Rx _ decodificado _ fase lt; = plus _ delta) amp; (Rx _ decodificado _ fase gtMINUS _ delta));
Rx_decoded_symbols = I;
Fin
Solo se evaluaron tres áreas.
El área restante es espacio de fase cero.
Al definir la matriz de demodulación, esta área se ha definido como cero.
Rx_serial_symbols = reshape(Rx_decoded_symbols',1,size(Rx_decoded_symbols,1)* size(Rx_decoded_symbols,2));
para i = bits por símbolo: -1: 1
si i ~= 1
Rx_binary_matrix(i,) = rem(Rx_serial_symbols, 2);
Rx_serial_symbols = piso(Rx_serial_symbols/2);
Otro
Rx_binary_matrix(i,)= Rx_serial_symbols
Fin
Fin
Entero versus binario
baseband _ in = shape(Rx_binary_matrix, 1, size(Rx_binary_matrix, 1)* size(Rx_binary_matrix, 2));
-
Cálculo de la tasa de errores
-
bit _ errores(idx)= buscar( baseband _ in ~ = baseband _ out);
Cada elemento del resultado de la búsqueda es la etiqueta del vector de entrada que satisface la condición lógica, y su longitud vectorial también es un número diferente de bits enviados y recibidos.
bit_error_count(idx)= tamaño(bit_error,2);
total_bits = tamaño(baseband_output,2);
Tasa de error de bits = recuento de errores de bits/ número total de bits;
fprintf ( 'f \n ', bit _ error _ rate
[number_err(idx), BER(idx )] = biterr(baseband_out, baseband_in);
Fin
Semilog(SNR, BER, ' r * ');
Legend(' OFDM BER-SNR ');
xlabel(' SNR(dB)'); y label(' BER ');
Título("OFDM");
Se abre la cuadrícula;
-
Fin
-
1. Este programa realiza una estimación simple del canal LMS sin aumentar la comparación con otros algoritmos de estimación de canales, como MMSE;
2. La condición de simulación es que el sistema esté en un estado de sincronización ideal.