diff --git a/GFSK_FixedPoint.m b/GFSK_FixedPoint.m
new file mode 100644
index 0000000000000000000000000000000000000000..bd2da8e4716bcb05216876c94847ebadb37b2255
--- /dev/null
+++ b/GFSK_FixedPoint.m
@@ -0,0 +1,380 @@
+%% GFSK Fixed-point implementation
+
+%% Transmission
+
+%%% Transmission/modulation parameters
+
+% fixed-point precision
+prec_op_TX = 32;           % precision to be used for the operations performed on the considered signal
+prec_cst = 8;           % precision for the constants
+
+f_c = 2.45e09;          % Carrier frequency
+r_symb = 1e06;          % Symbol rate
+Ts = 1/r_symb;          % Symbol period
+m = 0.5;                % Modulation index
+BTb = 0.5;              % Bandwidth - Symbol perdiod product
+
+
+N_symb = 1e04;          % Number of symbols used for the simulation
+reso = 8;               % Resolution factor (number of samples by symbol period)
+dfppm = 20;
+
+
+%%% For BER vs Eb/N0 plot and noise variance (N0) generation
+Nsnr = 16;              % Number of different values for the plot
+Eb_N0_dB = linspace(0,Nsnr-1,Nsnr);
+Eb_N0 = 10.^(Eb_N0_dB/10);
+Eb = 1;
+N0 = Eb./Eb_N0;
+
+
+%%% Generation of the preamble
+preamble = fi([1;-1;1;-1;1;-1;1;-1], 1, prec_cst, prec_cst-1);
+Lpreamble = length(preamble);
+N_symb = N_symb-Lpreamble;
+
+Lnoisestart = 92;
+N_symb = N_symb-Lnoisestart;
+
+%%% Generation of the sequence of symbols (I)
+bits = fi(round(rand(N_symb,1)), 1, prec_cst, prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',16-1,'ProductWordLength',16,'SumMode', 'SpecifyPrecision','SumFractionLength',16-1,'SumWordLength',16);
+I0 = bits-0.5;
+I1 = I0*2;
+I1(1) = fi(1, 1, prec_cst, prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',16-1,'ProductWordLength',16,'SumMode', 'SpecifyPrecision','SumFractionLength',16-1,'SumWordLength',16);
+I1(2) = fi(1, 1, prec_cst, prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',16-1,'ProductWordLength',16,'SumMode', 'SpecifyPrecision','SumFractionLength',16-1,'SumWordLength',16);
+I = fi([preamble;I1], 1, prec_cst, prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',16-1,'ProductWordLength',16,'SumMode', 'SpecifyPrecision','SumFractionLength',16-1,'SumWordLength',16);
+LI = length(I);
+
+
+%%% Gaussian pulse-shape filter (g) generation
+N_Ts = 3;                   % Number of symbol periods for the filter support
+time = -N_Ts/2*Ts : Ts/reso : N_Ts/2*Ts;    % Filter support
+Tb = Ts;                    % Here, we will always have Tb=Ts
+K = sqrt(log(2));           % Parameter for the filter amplitude
+g = g_GMSK(time,K,Tb,BTb);  % Filter generation, using my function "g_GMSK"
+Lg = length(g);
+
+% g_GMSK can be precomputed and tabled since it is constant, so it does not
+% have to be calculated in fixed-point, only the final values are
+% converted.
+gfi = fi(g,1,16,16-1,'ProductMode','SpecifyPrecision','ProductFractionLength',16-1,'ProductWordLength',16,'SumMode', 'SpecifyPrecision','SumFractionLength',16-1,'SumWordLength',16);
+
+
+%%% Convolution (convo) between the symbol sequence and the Gaussian filter
+tmin = (reso*(LI-1)+Lg+1)/2 - (reso*LI)/2;
+tmax = (reso*(LI-1)+Lg+1)/2 + (reso*LI)/2;
+Iup = upsample(I, reso);
+convfiIupgfi = convfi(Iup,gfi',16,prec_op_TX);
+convofi = convfiIupgfi(tmin:tmax);
+Lconvo = length(convofi);
+
+
+%%% Integration (integfi) of the convolution (trapezium method)
+% First, we divide everything by 256 as it is the max value the integral
+% can output considering a packet of +-300 bits. This way, saturation is
+% avoided.
+convofi = bitsra(convofi, 8);
+integfi = fi(zeros(Lconvo-1,1),1,32,32-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_TX-1,'ProductWordLength',prec_op_TX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_TX-1,'SumWordLength',prec_op_TX);
+integfi(1) = bitsra(convofi(1)+convofi(2), log2(2*reso));  % Division is performed via arithmetic shift right
+for i = 2:Lconvo-1
+    integfi(i) = integfi(i-1) + bitsra(convofi(i)+convofi(i+1), log2(2*reso));
+end
+% To avoid saturation resulting from multiplication by pi/2, the signal
+% should be divided by 2.
+integfi = bitsra(integfi, 1);
+
+
+%%% Phase (phi) generation
+fipi_2 = fi(pi/2, 1, prec_cst, prec_cst-2,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_TX-1,'ProductWordLength',prec_op_TX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_TX-1,'SumWordLength',prec_op_TX);
+phifi = fipi_2 * integfi;
+Lphifi = length(phifi);
+
+
+%%% Transmitted signal (s) generation
+s = exp(1j*double(phifi)*2^9);
+Ls = length(s);
+
+
+
+
+
+%% Reception
+
+
+% Fixed-point precision
+prec_op_RX = 16;
+precRX = 16;
+
+
+% Table of values for the CFO correction:
+ak = [-0.894221291841193;...
+      -0.823171345055248;...
+      -0.624515667660133;...
+      -0.335010157734548;...
+                       0;...
+       0.335010157734548;...
+       0.624515667660133;...
+       0.823171345055248;...
+       0.894221291841193;...
+       0.823171345055248;...
+       0.624515667660133;...
+       0.335010157734548;...
+                       0;...
+      -0.335010157734548;...
+      -0.624515667660133;...
+      -0.823171345055248];
+sinak = sin(ak);
+cosak = cos(ak);
+sinakfi = fi(sinak,1,prec_cst,prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+cosakfi = fi(cosak,1,prec_cst,prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+pow_cosak2pifi_m1 = fi(1./(cosak*2*pi),1,prec_cst,prec_cst-1);
+
+
+BERcorrfi = zeros(Nsnr,1);
+BERfi = zeros(Nsnr,1);
+df_hatfi = zeros(Nsnr,1);
+ind_trig = zeros(Nsnr,1);
+SFindi = zeros(Nsnr,1);
+% Loop for each different value of the noise variance
+% for i = 1:Nsnr
+SNR = 13;
+for i = SNR+1
+
+    
+    %%% AWGN (n) generation
+    % noise can remain in floating-point, it doesn't matter as it will be
+    % converted as soon as it will be added to the signal.
+    N = N0(i)*reso;
+    n = awgn(Lnoisestart*reso+Ls, 1, N);
+    
+    
+    %%% Received signal (r) generation
+    r = [zeros(Lnoisestart*reso, 1) ; s] + n;
+    Lr = length(r);
+
+    
+        %%% CFO        
+        df = dfppm/1e06 * f_c;
+        time = (1/(r_symb*reso) : 1/(r_symb*reso) : (Lr)/(r_symb*reso))';
+        rcfo = exp(1j*2*pi*df*time).*r;
+        rcfofi0 = fi(rcfo,1,precRX,precRX-4,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        % /!\ abs(rcfof) can go up to 13 (result from 100000 iterations 
+        % with 300 bits and SNR=13dB) => a normalization by 16 should be
+        % performed.
+        rcfofi = fi(bitsra(rcfofi0,4),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        Lrcfo = length(rcfo);
+        
+       
+        %%% Filtering of the received CFO'ed signal
+        % This is done in digital, so from now on signals must be in
+        % fixed-point. But the filter can be precomputed, so only its final
+        % coefficient values have to be converted.
+        % Moreover, as the filter coefficients are <= 1, there is no need
+        % for normalization. But one is done nonetheless as rcfo needs one.
+        fcut = 0.6e06;
+        Nper = 12;
+        h0 = LPF('Hamming', fcut, reso, Nper);
+        h0fi = fi(h0,1,prec_cst,prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        rconvfih0fi0 = convfi(rcfofi,h0fi',prec_op_RX,prec_op_RX);
+        rconvfih0fi = rconvfih0fi0(1+Nper/2*reso:end-Nper/2*reso);
+        rficfof = rconvfih0fi;
+        
+        
+
+
+        %%% Preamble detection
+        % Hermitian product
+        OSR = reso;
+        Hprodfi0 = rficfof(1+OSR:end).*conj(rficfof(1:end-OSR));
+        % IIR filter
+        IIRb = 1;
+        IIRa = zeros(OSR+1,1);
+        IIRa(1) = 1;
+        IIRa(OSR+1) = 0.875;
+        impu = eye(500,1);
+        impuresp = filter(IIRb, IIRa, impu);
+        % impuresp can be precomputed and tabled, so only the final values
+        % need to be converted into fixed-point.
+        impurespfi = fi(impuresp,1,prec_cst,prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        % /!\ abs(IIRHprod) can go up to 350 (result from 100000 iterations 
+        % with 300 bits and SNR=13dB) => a normalization by 512 should be
+        % performed, normalization of Hprodfi. But it is already 16*16 = 
+        % 256 times smaller due to the previous normalization, so it needs 
+        % an additional normalization factor of only 2 to reach 512!
+        Hprodfi = fi(bitsra(Hprodfi0,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        IIRHprodfi0 = convfi(Hprodfi,impurespfi,precRX,prec_op_RX);
+        IIRHprodfi = IIRHprodfi0(1:end-(length(impu)-1));
+        absIIRHprodfi = abs(IIRHprodfi);
+        LabsIIRHprodfi = length(absIIRHprodfi);
+
+        
+        % Search for preamble
+        if (SNR==13)
+            thresh = 37.5;
+        elseif (SNR==14)
+            thresh = 32.5;
+        end
+        % Due to the normalization, the comparison must be done wrt a
+        % threshold that has undergone the same normalization.
+        threshfi = fi(thresh/2^(4+4+1),1,prec_cst,prec_cst-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_cst-1,'ProductWordLength',prec_cst,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_cst-1,'SumWordLength',prec_cst);
+        p = 1;
+        booly = false;
+        while(booly == false)
+            if (absIIRHprodfi(p) > threshfi)
+                booly = true;
+            elseif (p >= LabsIIRHprodfi)
+                booly = true;
+                fprintf('Error, after 1000 iterations, there is still no value that has reached the threshold!');
+            else
+                p = p+1;
+            end
+        end
+        ind_trig(i) = p;
+        
+        
+        %%% Symbol timing recovery
+        Noffset = 5;
+        offset = Noffset*reso;
+        maxxtemp = absIIRHprodfi(ind_trig(i)+offset);
+        indtemp = ind_trig(i)+offset;
+        kk = 1;
+        while (kk < 1*reso)
+            if (absIIRHprodfi(ind_trig(i)+offset+kk) > maxxtemp)
+                maxxtemp = absIIRHprodfi(ind_trig(i)+offset+kk);
+                indtemp = ind_trig(i)+offset+kk;
+            end
+            kk = kk+1;
+        end
+        SFindi(i) = indtemp;
+        
+        
+        %%% CFO correction
+        df_hat_temp1 = 0;
+        Nperiod = 6;
+        b = 1;
+        counter = 1;
+        afikind = zeros(Nperiod*reso,1);
+        symbrfi = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        symbrfiold = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);        
+        hermifi_unnorm = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        hermifi = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        demodsymbrfirfiold = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        dkfi = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        dfhfi = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        dfh1fi0 = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        dfh1fi = fi(zeros(Nperiod*reso,1),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        while(b <= Nperiod*reso)
+            
+            symbrfi(b) = rficfof(b+ind_trig(i)+reso-1);
+            symbrfiold(b) = rficfof(b+ind_trig(i)+reso-1-reso);
+            
+            hermifi_unnorm(b) = symbrfi(b)*conj(symbrfiold(b));
+            % The division for the normalization is somehow problematic,
+            % as I don't know how to handle this in Matlab, I "cheat" by
+            % using a double value for the divider.
+            hermifi(b) = hermifi_unnorm(b)/double(abs(hermifi_unnorm(b)));
+            demodsymbrfirfiold(b) = imag(hermifi(b));
+
+            dkfi0 = demodsymbrfirfiold(b);
+            % Must be divided by 2 to avoid saturation when subtracting it
+            % with sinakfik
+            dkfi(b) = bitsra(dkfi0,1);
+            
+            % Simulated the index to fetch the values from the LUTs.
+            afikind(b) = mod(b,2*reso);
+            if (afikind(b) == 0)
+                afikind(b) = 2*reso;
+            end
+            
+            sinakfik0 = sinakfi(afikind(b));
+            % Must be divided by 2 to avoid saturation when subtracting it
+            % from dkfi            
+            sinakfik = bitsra(sinakfik0,1);
+
+            dfh1fi0(b) = (dkfi(b)-sinakfik)*pow_cosak2pifi_m1(afikind(b));
+            
+            % Here, I accumulate Nperiod*reso (48) values, so I have to
+            % normalize by this value beforehand (48->64).
+            dfh1fi(b) = bitsra(dfh1fi0(b),6);
+            df_hat_temp1 = df_hat_temp1+dfh1fi(b);
+            dfhfi(b) = df_hat_temp1/counter;
+            counter = counter + 1;
+                                            
+            b = b+1;
+            
+        end
+        
+
+        df_hatfi(i) = dfhfi(end);
+        normfact = 2^7/Tb;
+
+        % Correction is done in RF, and the denormalization is performed at
+        % the same time using the factor normfact.
+        rcorr = exp(-1j*2*pi*(double(df_hatfi(i))*normfact)*time((Lnoisestart+Lpreamble)*reso+1 : end)).*rcfo((Lnoisestart+Lpreamble)*reso+1 : end);
+        rcorrfi0 = fi(rcorr, 1, precRX);
+        % Looks like convfi(rcorrfi,h0fi) can go up to 10, so it seems
+        % appropriate to normalize by 16.
+        rcorrfi = fi(bitsra(rcorrfi0, 4),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+        rcorrficonvfih0fi0 = convfi(rcorrfi,h0fi',precRX,prec_op_RX);
+        rcorrficonvfih0fi = rcorrficonvfih0fi0(1+Nper/2*reso:end-Nper/2*reso);
+        rcorrfif = rcorrficonvfih0fi;
+               
+        
+    %%% Filtering of the received signal (for the CFO-free case)
+    rfi0 = fi(r, 1, precRX);
+    % Looks like convfi(rfi,h0fi) can go up to 12, so it seems appropriate
+    % to normalize by 16.
+    rfi = fi(bitsra(rfi0, 4),1,precRX,precRX-1,'ProductMode','SpecifyPrecision','ProductFractionLength',prec_op_RX-1,'ProductWordLength',prec_op_RX,'SumMode', 'SpecifyPrecision','SumFractionLength',prec_op_RX-1,'SumWordLength',prec_op_RX);
+    rficonvfih0fi0 = convfi(rfi,h0fi',precRX,prec_op_RX);
+    rficonvfih0fi = rficonvfih0fi0(1+Nper/2*reso:end-Nper/2*reso);
+    rfif = rficonvfih0fi;        
+    
+
+    %%% Demodulation
+    
+    indidown = mod(SFindi(i)+2,reso);
+    if (indidown == 0)
+        indidown = reso;
+    end       
+    
+    rcorrfifdown = downsample(rcorrfif(indidown:end),reso/2);
+    Lrcorrfifdown = length(rcorrfifdown);
+    if (mod(Lrcorrfifdown,2)==0)
+        demodficorr = imag(rcorrfifdown(2:2:end).*conj(rcorrfifdown(1:2:end-1)));
+    else
+        demodficorr = imag(rcorrfifdown(2:2:end-1).*conj(rcorrfifdown(1:2:end-2)));
+    end    
+    Ldemodficorr = length(demodficorr);
+
+
+    rfifdown = downsample(rfif(indidown:end),reso/2);
+    Lrfifdown = length(rfifdown);
+    if (mod(Lrfifdown,2)==0)
+        demodfi = imag(rfifdown(2:2:end).*conj(rfifdown(1:2:end-1)));
+    else
+        demodfi = imag(rfifdown(2:2:end-1).*conj(rfifdown(1:2:end-2)));
+    end
+    demodfi = demodfi(1+Lpreamble+Lnoisestart:end);
+    Ldemodfi = length(demodfi);
+    
+
+    %%% Decision
+    Icorrfi_hat = sign(demodficorr);
+    BERcorrfi(i) = sum(sign(I(1+Lpreamble:Lpreamble+Ldemodficorr))~=Icorrfi_hat)/N_symb;
+    Ifi_hat = sign(demodfi);
+    BERfi(i) = sum(sign(I(1+Lpreamble:Lpreamble+Ldemodfi))~=Ifi_hat)/N_symb;
+    
+
+end
+
+
+% BER vs Eb/N0 plot
+figure;
+semilogy(Eb_N0_dB,BERcorrfi,'xg','LineWidth',1.5,'MarkerSize',8);
+hold on;
+semilogy(Eb_N0_dB,BERfi,'xk','LineWidth',1.5,'MarkerSize',8);
+axis([0 Nsnr 10/N_symb 1]);
+grid;
+title( strcat('BER -- df = ', num2str(df)) );
+xlabel('E_{b}/N_{0} [dB]');
+ylabel('BER');