From 31d48a7a83a6b7abb1bd29b78dabb9961e3ab890 Mon Sep 17 00:00:00 2001 From: Robin Gerzaguet Date: Tue, 2 Nov 2021 19:28:33 +0100 Subject: [PATCH] Adding raised cosine and sqrt raised cosine filter templates --- src/DigitalComm.jl | 5 +++ src/raisedCosine.jl | 73 ++++++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 4 ++- test/test_filters.jl | 44 ++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/raisedCosine.jl create mode 100644 test/test_filters.jl diff --git a/src/DigitalComm.jl b/src/DigitalComm.jl index 6038c51..62da9c8 100644 --- a/src/DigitalComm.jl +++ b/src/DigitalComm.jl @@ -53,6 +53,11 @@ include("Channel/addCFO.jl") export addCFO export addCFO! +# --- Raised cosine filters +include("raisedCosine.jl") +export raisedCosine +export sqrtRaisedCosine + # ---------------------------------------------------- # --- Function definition diff --git a/src/raisedCosine.jl b/src/raisedCosine.jl new file mode 100644 index 0000000..76474b4 --- /dev/null +++ b/src/raisedCosine.jl @@ -0,0 +1,73 @@ +""" +Returns the Finite Impulse Response of a Raised Cosine (RC) filter. The filter is defined by its span (evaluated in number of symbol N), its Roll-Off factor and its oversampling factor. The span corresponds to the number of symbol affected by filter before and after the center point.\n +Output is a Vector{Float64} array of size L= 2KN+1 \n +SRRC definition is based on [1] \n +[1] 3GPP TS 25.104 V6.8.0 (2004-12). http://www.3gpp.org/ftp/Specs/archive/25_series/25.104/25104-680.zip \n + Syntax \n + h = raisedCosine(N,beta,ovS) +Input parameters \n +- N : Symbol span (Int16) +- beta : Roll-off factor (Float64) +- ovS : Oversampling rate (Int16) +""" +function raisedCosine(N,beta,ovS) + # --- Final size of filter + nbTaps = 2 * N * ovS + 1; + # --- Init output + h = zeros(Float64,nbTaps); + counter = 0; + # --- Iterative SRRC definition + for k = -N*ovS : 1 : N*ovS + counter = counter + 1; + if k == 0 + ## First singular point at t=0 + h[counter] = 1;#(1-beta) + 3*beta/pi; + elseif abs(k) == ovS / (2*beta); + ## Second possible singular point + h[counter] = pi/4*sin(pi/(2beta))/(pi/(2beta)); + else + ## Classic SRRC formulation (see [1]) + h[counter] = sin(pi*k/ovS)/(pi*k/ovS) * cos(pi*beta*k/ovS)/(1- 4beta^2*(k/ovS)^2); + end + end + return h +end + + +""" +Returns the Finite Impulse Response of a Square Root Raised Cosine (SRRC) filter. \n +The filter is defined by its span (evaluated in number of symbol N), its Roll-Off factor and its oversampling factor. The span corresponds to the number of symbol affected by filter before and after the center point.\n +Output is a Vector{Float64} array of size L= 2KN+1\n +SRRC definition is based on [1]\n +[1] 3GPP TS 25.104 V6.8.0 (2004-12). http://www.3gpp.org/ftp/ Specs/archive/25_series/25.104/25104-680.zip\n +Syntax\n +h = sqrtRaisedCosine(N,beta,ovS) \n +Input parameters \n +- N : Symbol span (Int16) +- beta : Roll-off factor (Float64) +- ovS : Oversampling rate (Int16) +""" +function sqrtRaisedCosine(N,beta,ovS) + # --- Final size of filter + nbTaps = 2 * N * ovS + 1; + # --- Init output + h = zeros(Float64,nbTaps); + counter = 0; + # --- Iterative SRRC definition + for k = -N*ovS : 1 : N*ovS + counter = counter + 1; + if k == 0 + ## First singular point at t=0 + h[counter] = (1-beta) + 4*beta/pi; + elseif abs(k) == ovS / (4*beta); + ## Second possible singular point + h[counter] = beta/sqrt(2)*( (1+2/pi)sin(pi/(4beta))+(1-2/pi)cos(pi/(4beta))); + else + ## Classic SRRC formulation (see [1]) + h[counter] = ( sin(pi*k/ovS*(1-beta)) + 4beta*k/ovS*cos(pi*k/ovS*(1+beta))) / (pi*k/ovS*(1- (4beta*k/ovS)^2) ); + end + end + # --- Max @ h[0] + h = h ./ maximum(h) + return h +end diff --git a/test/runtests.jl b/test/runtests.jl index feca978..58faab4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -18,9 +18,11 @@ include("test_hardConstellation.jl"); # Symbol demapper include("test_symbolDemapper.jl"); - # AWGN include("test_addNoise.jl"); # Test Waveforms include("test_waveforms.jl"); + +# Test filters +include("test_filters.jl") diff --git a/test/test_filters.jl b/test/test_filters.jl new file mode 100644 index 0000000..705627a --- /dev/null +++ b/test/test_filters.jl @@ -0,0 +1,44 @@ +# ---------------------------------------------------- +# --- Import modules +# ---------------------------------------------------- +using DigitalComm +using DSP +using Test +# ---------------------------------------------------- +# --- Tests +# ---------------------------------------------------- +println("Tests for filters"); +@testset "Raised Cosine filter test" begin + # Create the vector + h = raisedCosine(12,0.5,16) + # Check type + @test h isa Vector{Float64} + # Check size + sH = 12*16*2+1 + @test length(h)== sH + # Check it is 1 in the middle + @test h[1+ (sH-1)÷2] == 1 + # Check Nyquist criterion + for n ∈ 0 : 11 + @test ≈(h[1 + n*16],0,atol=1e-8) + end +end + +@testset "Raised Cosine filter test" begin + # Create the vector + h = sqrtRaisedCosine(12,0.5,16) + # Check type + @test h isa Vector{Float64} + # Check size + sH = 12*16*2+1 + @test length(h)== sH + # Check it is 1 in the middle + @test h[1+ (sH-1)÷2] == 1 + # Check Nyquist criterion + # sqrt is not a Nyquist filter but h*h is ! + p = conv(h,h) + p = p /maximum(p) + for n ∈ 0 : 2*11 + @test ≈(p[1 + n*16],0,atol=1e-4) + end +end