clear;clc;
%% Declaration
%msg = 'A1B2 .?C3D4E5'; %message1
%msg = 'OK1FLZ ABCDEF'; %message2
msg = 'OK1FLZ JN79IA'; %message3
msgLength = length(msg);
if msgLength < 13
    for i=1:(13-msgLength), msg(msgLength+i) = ' '; end
    msgLength = length(msg);
elseif msgLength > 13, disp("msg too long"); return; end
alphabet = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E',...
    'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V',...
    'W','X','Y','Z',' ','+','-','.','/','?'];
alphabetLength = length(alphabet);
%% Source coding
%for every character in message we use its index in "alphabet" to encode it
msgCoded = zeros(1,msgLength);
for i=1:msgLength
    for j=1:alphabetLength
        if msg(i)==alphabet(j)
            msgCoded(i)=j-1;
        end
    end
end
clear i j alphabetLength alphabet;
%% Forming long integers
N1 = (((msgCoded(1)*42+msgCoded(2))*42+msgCoded(3))*42+msgCoded(4))*42+msgCoded(5);
N2 = (((msgCoded(6)*42+msgCoded(7))*42+msgCoded(8))*42+msgCoded(9))*42+msgCoded(10);
N3 = (msgCoded(11)*42+msgCoded(12))*42+msgCoded(13);
%% Rearanging long integers
N1 = bitset(bitshift(N1,1),1,mod(round(N3/32768),2));
N2 = bitset(bitshift(N2,1),1,mod(round(N3/65536),2));
N3 = mod(N3,32768) + 32768;
%adding 32768=2^15 is for setting bit 15 to 1, that marks message type
%as plain text for WSJT-X software
%% Bit sequence
%forming 91 bit long sequence for convolutional encoding
bitSeq = [dec2bin(N1,28),dec2bin(N2,28),dec2bin(N3,16),dec2bin(0,19)];
bitSeqLength = length(bitSeq);
data = zeros(bitSeqLength,1);
for i=1:bitSeqLength
    data(i) = str2double(bitSeq(i));
end
%% Encoding
%LDPC code (174,91) is specified by parity matrix which is stored separately
load('LDPCparity.mat');
ldpcEncoder = comm.LDPCEncoder(sparse(transpose(parity)));
bitOut = ldpcEncoder(data);
%% Convert to symbols
symbols = zeros(1,58);
j = 1;
for i=1:58
    symbols(i) = bitOut(j)*4+bitOut(j+1)*2+bitOut(j+2);
    j = j+3;
end
clear i j;
%% Gray Coding
symbolsGray = bin2gray(symbols,'fsk',8);
%% Synchronization
%specific sequence of channel symbols is included in begining, middle and
%ending of transmission, thus from 58data symbols we obtain 79
C = [3 1 4 0 6 5 2]; %Costas array
symbolsOut = [C symbolsGray(1:29) C symbolsGray(30:58) C];
%% Modulation 8-FSK
%for every channel symbol in sequence we assign waveform with corresponding
%frequency
Fs = 12000; %sampling frequency
Fc = 1000; %carrier frequency
deltaF = 6.25; %frequency separation
duration = 1920; %number of samples for which channel symbol lasts
M = 8;
t = linspace(0,1/deltaF,duration);
yMod = zeros(duration,length(symbolsOut));

for i=1:length(symbolsOut)
    yMod(:,i) = 0.5*cos(2*pi*(Fc+symbolsOut(i)*deltaF).*t);
end
y=transpose(yMod(:));
%% Pulse shaping
%raised-cosine function is used for shaping begining and ending of each
%channel symbol
T = 1/deltaF;
shapeLength = round(T/8*Fs);
A = 0.5*(1-cos(8*pi.*t(1:shapeLength)/T));
yA = yMod;
for i=1:length(symbolsOut)
    yA(1:shapeLength,i) = yMod(1:shapeLength,i).*transpose(A(1:shapeLength));
    yA(duration-shapeLength+1:duration,i) = yMod(duration-shapeLength+1:duration,i).*transpose(A(shapeLength:-1:1));
end
y=transpose(yA(:));
%% Output
%audio output for radiostation is generated
out = zeros(1,Fs*60);
out(1,1:length(y)) = y;
% out = awgn(out,-10);
audiowrite('out.wav',out,Fs)