% Signal space and constellation
% Ex 5
% By: Johan Oestman
%clc; close all; clear all

% Input parameters
% For passband implemetation sampling frequency is a necessary parameter
fs = 44000; % sampling frequency [Hz]
Tsamp = 1/fs;    % Sampling time
Rb = 440; % bit rate [bit/sec]
N = 100; % number of bits to transmit
fc = 1000; % Carrier frequency
%----------------------------------------------
%       SET THIS FLAG TO CHOOSE WHAT PULSE! 
%           0 = rect, 1 = rc, 2 = rrc
pulse_flag = 2; 
%----------------------------------------------
span=6


% Constellation or bit to symbol mapping
const = [(1 + 1i), (1 - 1i), (-1 -1i), (-1 + 1i)]/sqrt(2);% Constellation 1 - QPSK/4-QAM
%const = [-1 1]/sqrt(2);% Constellation 1 - QPSK/4-QAM

scatterplot(const); grid on;                          % Constellation visualization

M = length(const);                                    % Number of symbols in the constellation
bpsymb = log2(M);                                     % Number of bits per symbol
fsymb = Rb/bpsymb;                                    % Symbol rate [symb/s]
Tsymb = 1/fsymb;                                      % symbol time
fsfd = fs/fsymb;                                      % Number of samples per symbol (choose fs such that fsfd is an integer for simplicity) [samples/symb]
a = randsrc(1,N,[0 1]);  % or "randi(2,1,N)-1"        % Information bits
m = buffer(a, bpsymb)';                               % Group bits into bits per symbol
m_idx = bi2de(m, 'left-msb')'+1;                      % Bits to symbol index, msb: the Most Significant Bit
x = const(m_idx);                                     % Look up symbols using the indices

% Pulse train using "for loop" or "Convolution"
if pulse_flag == 1 || pulse_flag == 2
    span = 6; %how many symbol times to we want of pulse (note that RC and RRC is not zero outside of symbol time!)
    [pulse, t] = rcpuls(0.35,1/fsymb,fs,span);
    figure; stem(t,pulse); legend('Pulse signal') % plot pulse signal
    figure;
    stem(eps:Tsymb:5*Tsymb,real(x(1:5))); % plot first 5 symbols
    hold on;
    s_loop = zeros(1,(5+2*span)*Tsymb*fs); 
    for i = 1:5
        t_current = t+ (i-1)*Tsymb;
        plot(t_current, real(x(i)*pulse)); % Each symbol * pulse
        idx = (i-1)*Tsymb*fs+1:ceil((i-1+2*span)*Tsymb*fs-1);
        s_loop(idx) = s_loop(idx) + x(i)*pulse;
    end
    p1 = plot([t,t(end):1/fs:t(end)+5*Tsymb], real(s_loop), 'r', 'LineWidth', 3); % Plot s using for loop
    legend(p1, 's using for loop');
    
    
    % Using convolution method
    x_upsample = upsample(x(1:5), fsfd);      % Space the symbols fsfd apart, to enable pulse shaping using conv.
    figure; stem(real(x(1:5))); hold on
    figure; stem(real(x_upsample))
    
    s = conv(pulse,x_upsample); % Convolute 'pulse' with 'x_upsample'
    figure;
    p2 = plot(Tsamp*(-floor(length(pulse)/2):length(s)-ceil(length(pulse)/2)), real(s), 'b', 'LineWidth', 3);
    legend(p2,'s using convolution')

end

x_upsample = upsample(x, fsfd);                       % Space the symbols fsfd apart, to enable pulse shaping using conv.

% Now we have a signal ready to be shaped.
switch pulse_flag
    case 0 %Rectangular
        pulse = ones(1, fsfd);                   % Generate a rectangular pulse
        pulse = pulse ./ norm(pulse);
        s = conv(pulse,x_upsample);    % Each symbol replaced by the pulse shape and added
        
    case 1 %RC
        span = 6; %how many symbol times to we want of pulse (note that RC and RRC is not zero outside of symbol time!)
        [pulse, t] = rcpuls(0.35,1/fsymb,fs,span);
        s = conv(pulse,x_upsample);
        
    case 2 %RRC
        span = 6;
        [pulse, t] = rtrcpuls(0.4,1/fsymb,fs,span);
        s = conv(pulse,x_upsample);
        
    otherwise
        disp('Unknown pulse');
        return;
end

figure; 
subplot(2,1,1); 
plot(Tsamp*(0:(length(s)-1)), real(s), 'b');

samples = s(span*fsfd:fsfd:end-span*fsfd);
hold on;
t = span*fsfd:fsfd:(span*fsfd + fsfd*(length(samples)-1));
hold on;
stem(t*Tsamp, real(samples),'r');
legend('s', 'sampled s');
title('real')
xlabel('seconds')
subplot(2,1,2); 
plot(Tsamp*(0:(length(s)-1)), imag(s), 'b');
hold on;
stem(t*Tsamp, imag(samples),'r');
legend('s', 'sampled s');
title('imag')
xlabel('seconds')


if pulse_flag > 0
    tx_signal = s.*exp(-1i*2*pi*fc*(0:length(s)-1)*Tsamp); % Carrier Modulation/Upconversion 
    tx_signal = real(tx_signal);                        % send real part, information is in amplitude and phase
    tx_signal = tx_signal/max(abs(tx_signal));          % Limit the max amplitude to 1 to prevent clipping of waveforms

    subplot(121)
    plot(tx_signal)

    
    
    %% MINE
    % Baseband
    subplot(241)
    plot(Tsamp*(0:(length(s)-1)), real(s))
    title('In-phase baseband')
    
    subplot(245)
    plot_fft(real(s), fs)
    title('In-phase baseband spectrum')
    
    % Passband
    subplot(242)
    tx_signal_alt = real(s).*cos(2*pi*fc*(0:length(s)-1)*Tsamp) - imag(s).*sin(2*pi*fc*(0:length(s)-1)*Tsamp);
    plot(Tsamp*(0:(length(s)-1)), tx_signal_alt)
    title('Carrier modulated TX signal')
    
    subplot(246)
    plot_fft(tx_signal_alt, fs)
    title('Frequency spectrum of carrier modulated TX signal')
    grid on;
    xlabel('f');
    
    % Receiver, pre-filter
    subplot(243)
    rx_signal = tx_signal_alt.*cos(2*pi*fc*(0:length(s)-1)*Tsamp);
    plot(Tsamp*(0:(length(s)-1)), rx_signal)
    title('Unfiltered Received In-Phase component (ie. multiplied by cos(\omega_0t))');
          
    subplot(247)
    plot_fft(rx_signal, fs)
    grid on;
            
    % Receiver, post-filter
    subplot(244)
    rx_filt = lowpass(rx_signal, 500, fs, 'ImpulseResponse','iir','Steepness',0.85);
    plot(Tsamp*(0:(length(s)-1)),real(rx_filt))
    title('Filtered I-comp'); grid on;
    
    subplot(248)
    plot_fft(rx_filt, fs);
    grid on; 
    

    
    N = 256;
    P_bb = fftshift(fft(s, N)); % baseband signal
    P_bp = fftshift(fft(tx_signal, N)); % passband signal
    df = fs/N;                  % sampling frequency is split into N bins
    fvec = df*(-floor(N/2):1:ceil(N/2)-1); % Truncated, has wide bandwidth
    figure; plot(fvec, 20*log10(abs(P_bb/N))); hold on
    plot(fvec, 20*log10(abs(P_bp/N))); legend('Baseband signal', 'Passband signal')
    
    N = 256;
    P_bb = fftshift(fft(s, N)); % baseband signal
    P_bp = fftshift(fft(tx_signal_alt, N)); % passband signal
    df = fs/N;                  % sampling frequency is split into N bins
    fvec = df*(-floor(N/2):1:ceil(N/2)-1); % Truncated, has wide bandwidth
    figure; plot(fvec, 20*log10(abs(P_bb/N))); hold on
    plot(fvec, 20*log10(abs(P_bp/N))); legend('Baseband signal', 'Passband signal')
end


%% My stuff

%     tx_signal_alt = s.*(cos(2*pi*fc*(0:length(s)-1)*Tsamp) + sin(2*pi*fc*(0:length(s)-1)*Tsamp));
%     tx_signal_alt = tx_signal_alt.*cos(2*pi*fc*(0:length(s)-1)*Tsamp);
%     
%     tx_filt = lowpass(real(tx_signal_alt), 0.1);
%  figure
%     plot(Tsamp*(0:(length(s)-1)),real(tx_filt))
%     hold on
%     %plot(Tsamp*(0:(length(s)-1)), real(s));
%     %stem(t*Tsamp, real(samples),'r');
%     
%     figure
%     plot(t*Tsamp, downsample(real(tx_filt), fsfd))
%     

