📄 tx.m
字号:
function tx(nr_frames)
% Transmission
% Maxime Maury
% 05-04-28
if (nargin < 1)
nr_frames = 20; % number of frames to send
end
% Frame structure Type SYNC
% Antenna 1:
% +---+----------+-----+---+-----+-----------------------------+
% | G | tr_sync1 | tr1 | G | tr1 | data |
% +---+----------+-----+---+-----+-----------------------------+
% Antenna 2:
% +---+----------+-----+---+-----+-----------------------------+
% | G | tr_sync1 | tr2 | G | tr2 | data |
% +---+----------+-----+---+-----+-----------------------------+
% Antenna 1: Type REGULAR
% +---+-----+---+-----+-----------------------------+
% | G | tr1 | G | tr1 | data |
% +---+-----+---+-----+-----------------------------+
% Antenna 2:
% +---+-----+---+-----+-----------------------------+
% | G | tr2 | G | tr2 | data |
% +---+-----+---+-----+-----------------------------+
close all
disp(' ');
disp('-- Start TX --')
j = sqrt(-1);
% ---------------------------------------------------
% General parameters
% ---------------------------------------------------
Fs = 96000; % Sampling frequency (Hz)
Fc = 10000; % Carrier frequency (Hz)
L = 10; % Upsampling factor
% Simulate a Frequency offset
F_offset = 0; % In real frequency
Fc_tx = Fc + F_offset;
%nr_frames =100;
data_len = 256; % In symbolS
data_len_bits = data_len*4; % In bits
% ---------------------------------------------------
% Pulse shape
% ---------------------------------------------------
pulse = 1;
if (pulse==1)
roll_off_factor = .22;
half_filter_len = 7; % Half-Length of the RRC
pulse_shape = root_raised_cosine(L, roll_off_factor, half_filter_len);
else
pulse_shape = ones(1,L);
end
pulse_len = length(pulse_shape);
% ---------------------------------------------------
% Head & tail
% ---------------------------------------------------
% Add a zero signal for noise estimation
init_len = 500;
% Add a zero tail
tail_len = 2000;
% Sinusoid at 10kHz for frequency offset estimation
n_periods = 100;
time_end = floor(n_periods*Fs/Fc_tx) -1 ;
% Stops just before cos = 1 to avoid discontinuities in the signal
% (modulation of frames start with cos=1)
% ---------------------------------------------------
% Guard symbols
% ---------------------------------------------------
% Guard symbols
guard_symbols_I = ones(1, 1);
guard_symbols_Q = ones(1, 1);
guard_len = length(guard_symbols_I);
% ---------------------------------------------------
% Training sequence
% ---------------------------------------------------
% Training sequence
[tr_sync1_I, tr_sync1_Q, tr1_I, tr1_Q, tr2_I, tr2_Q] = training_sequence;
% Length of channel estimation training sequence
training_len = length(tr1_I);
% ---------------------------------------------------
% Framing
% ---------------------------------------------------
% Length of synchronization training sequence
training_s_len = length(tr_sync1_I);
% Length of a regular frame in symbols (before upsampling)
frame_len = guard_len + training_len + guard_len + training_len + data_len;
overhead_len = frame_len - data_len;
disp(['Overhead size (Regular): ', num2str(overhead_len/frame_len*100), '%']);
disp(['Overhead size (Sync): ', num2str((overhead_len+training_s_len)/frame_len*100), '%']);
% Synchronization every refresh_fr frames
refresh_fr = 4;
nr_sync_frames = floor((nr_frames-1)/refresh_fr) + 1;
nr_regular_frames = nr_frames - nr_sync_frames;
disp(['Number of regular frames: ', num2str(nr_regular_frames)]);
disp(['Number of sync frames: ', num2str(nr_sync_frames)]);
% Length of an upsampled frame pulse-shaped
Lf = frame_len * L + pulse_len - 1 ;
Lf_sync = Lf + training_s_len*L ;
frames_len = Lf*nr_frames + training_s_len*L*nr_sync_frames;
% Save all these parameters into tx_param for the receiver
save('tx_param');
% ---------------------------------------------------
% Data
% ---------------------------------------------------
% Generate random data stream
data_sent = random_data(data_len_bits*2*nr_frames);
% For testing, de-comment the following
% data_sent(1:2:end) = [ zeros(1,data_len*2*nr_frames), ones(1,data_len*2*nr_frames)];
% data_sent(2:2:end) = [ ones(1,data_len*2*nr_frames), zeros(1,data_len*2*nr_frames)];
% Serial To Parallel
% 1 2 3 4 5... -> [1 3 5 ...; 2 4 ...]
data_split_sent_1 = data_sent(1:2:end);
data_split_sent_2 = data_sent(2:2:end);
% channel1 sent to Antenna 1, channel2 sent to Antenna 2
channel1_block = zeros(1 , frames_len);
channel2_block = zeros(1 , frames_len);
% ---------------------------------------------------
% Frame Loop
% ---------------------------------------------------
% Proceeed frame by frame
for fr=1:nr_frames
k = 1 + (fr-1)* data_len_bits; % Position within the data bits
% Extract data
data_split_1 = data_split_sent_1(:,k:k+data_len_bits-1);
data_split_2 = data_split_sent_2(:,k:k+data_len_bits-1);
% Modulate the data in 16QAM
[data1_I,data1_Q] = qam16(data_split_1);
[data2_I,data2_Q] = qam16(data_split_2);
% Create the frame
if (mod(fr-1, refresh_fr) == 0) % Type SYNCH
frame1_I = [guard_symbols_I tr_sync1_I tr1_I guard_symbols_I tr1_I data1_I];
frame1_Q = [guard_symbols_Q tr_sync1_Q tr1_Q guard_symbols_Q tr1_Q data1_Q];
frame2_I = [guard_symbols_I tr_sync1_I tr2_I guard_symbols_I tr2_I data2_I];
frame2_Q = [guard_symbols_Q tr_sync1_Q tr2_Q guard_symbols_Q tr2_Q data2_Q];
actual_len = Lf_sync;
else % Type REGULAR
frame1_I = [guard_symbols_I tr1_I guard_symbols_I tr1_I data1_I];
frame1_Q = [guard_symbols_Q tr1_Q guard_symbols_Q tr1_Q data1_Q];
frame2_I = [guard_symbols_I tr2_I guard_symbols_I tr2_I data2_I];
frame2_Q = [guard_symbols_Q tr2_Q guard_symbols_Q tr2_Q data2_Q];
actual_len = Lf;
end
% Upsample
frame1_I_up = upsample(frame1_I,L);
frame1_Q_up = upsample(frame1_Q,L);
frame2_I_up = upsample(frame2_I,L);
frame2_Q_up = upsample(frame2_Q,L);
frame1_I_up = conv(frame1_I_up, pulse_shape);
frame1_Q_up = conv(frame1_Q_up, pulse_shape);
frame2_I_up = conv(frame2_I_up, pulse_shape);
frame2_Q_up = conv(frame2_Q_up, pulse_shape);
% Number of previous frames
n_fr_sync = floor((fr-2)/refresh_fr) + 1;
n_fr_reg = (fr-1) - n_fr_sync;
n_out = n_fr_reg * Lf + n_fr_sync * Lf_sync + 1;
s = 1;
e = s + actual_len - 1;
channel1_block(n_out:n_out+actual_len-1) = frame1_I_up(s:e) + j* frame1_Q_up(s:e);
channel2_block(n_out:n_out+actual_len-1) = frame2_I_up(s:e) + j* frame2_Q_up(s:e);
end
% Save the output of the TX
save('TXOutput','channel1_block','channel2_block');
% Save data sent
f_id = fopen('transmit.dat', 'wb');
fwrite(f_id, data_sent, 'int16');
fclose(f_id);
disp('End')
figure;
Nc = 2;
Nr = 2;
subplot(Nc,Nr,1)
plot(data1_I,data1_Q,'k*')
hold on;
plot(frame1_I(1:guard_len),frame1_Q(1:guard_len),'rs');
plot(frame1_I(guard_len+1:guard_len+training_s_len),frame1_Q(guard_len+1:guard_len+training_s_len),'g*');
plot(frame1_I(guard_len+training_s_len+1:guard_len+training_s_len+training_len),frame1_Q(guard_len+training_s_len+1:guard_len+training_s_len+training_len),'bp');
grid on;
axis([-4 4 -4 4])
axis equal
legend('Data','Guard','Sync training seq','Ch estim. trainin seq');
title('Constellation');
subplot(Nc,Nr,2)
psd(pulse_shape,2048,Fs,1024,256);
title('Pulse Shape Spectrum');
subplot(Nc,Nr,3)
plot(real(channel1_block));
hold on;
plot(imag(channel1_block),'r');
legend('I','Q');
title('Channel 1');
subplot(Nc,Nr,4)
psd(channel1_block,2048,Fs,1024,256);
title('Spectrum of Channel 1');
figure;
Nc = 2;
Nr = 1;
subplot(Nc,Nr,1)
autocorr1 = abs(xcorr(tr_sync1_I+sqrt(-1)*tr_sync1_Q));
plot( autocorr1 );
hold on;
plot(training_s_len,autocorr1(training_s_len),'*r');
title('Autocorrelation of synchronization training sequence 1');
subplot(Nc,Nr,2)
cross = abs(xcorr((tr1_I+sqrt(-1)*tr1_Q),(tr2_I+sqrt(-1)*tr2_Q)));
plot(cross);
title('Crosscorrelation of training sequence 1 and 2');
hold on;
plot(training_len,cross(training_len),'*r');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -