diff --git a/src/Channel/addCFO.jl b/src/Channel/addCFO.jl new file mode 100644 index 0000000..a5cddbe --- /dev/null +++ b/src/Channel/addCFO.jl @@ -0,0 +1,30 @@ +""" +Adding Carrier Frequency Offset δ in Hz to the input signal x sampled at frequency samplingRate (In Hz) with initial phase ϕ (default 0) +This function does not mutate the input signal. See addCFO! for mutating function. +In case you want to add normalized CFO, set the samplingRate to 1. +# --- Syntax +y = addCFO(x,delta,samplingRate) +# --- Input parameters +- x : Input signal +- δ : Carrier frequency offset [Hz] +- samplingRate : Sampling rate [Hz] +# --- Output parameters +- y : Signal with CFO +""" +function addCFO(x::Union{AbstractVector{Complex{T}},AbstractVector{T}},δ,samplingRate,ϕ=0) where T + y = zeros(Complex{T},length(x)) + addCFO!(y,x,δ,samplingRate,ϕ) + return y +end + +function addCFO!(y::AbstractVector{Complex{T}},x::AbstractVector,δ::Number,samplingRate::Number,ϕ=0) where T + # --- Basic array check + @assert length(x) == length(y) "Input and output should have same length (here input x is $(length(x)) and pre-allocated output has size $(length(y))" + # --- CFO pulsation + ω = δ / samplingRate + # --- Adding CFO + @inbounds @simd for n ∈ eachindex(x) + y[n] = x[n] * Complex{T}(exp(2im*π*ω*( (n-1) + ϕ))) + end +end + diff --git a/src/DigitalComm.jl b/src/DigitalComm.jl index 6622569..6038c51 100644 --- a/src/DigitalComm.jl +++ b/src/DigitalComm.jl @@ -49,7 +49,9 @@ export initChannel export getChannel export getFIRResponse export applyChannel - +include("Channel/addCFO.jl") +export addCFO +export addCFO! # ---------------------------------------------------- diff --git a/test/test_addNoise.jl b/test/test_addNoise.jl index cf4ec93..04db06e 100644 --- a/test/test_addNoise.jl +++ b/test/test_addNoise.jl @@ -32,10 +32,31 @@ println("Tests for noise addition"); addNoise!(mem,qamSeq,snrVise); snr = -10*log10(mean(abs2.(qamSeq .- mem))); @test abs2(snr - snrVise) < 0.1 - - - - +end + +@testset "Testing addCFO.jl..." begin + # We check with array of ones, to be sure rotation is Ok + x = ones(2048) + y = addCFO(x,0,1,0) + @test length(x) == length(y) + @test all(x .== y) + addCFO!(y,x,0,1,0) + @test all(x .== y) + + # Check it works with complex input + x = randn(ComplexF64,1024) + y = addCFO(x,0,1,0) + + # Check that F32 is not promoted to F64 + x2 = randn(ComplexF32,1024) + y = addCFO(x2,100,1e3,0) + @test y isa Vector{ComplexF32} + + + # Check that CFO is applied + y = addCFO(x,100,1e3) + @test y[1] == x[1] + @test y[2] == x[2] * exp(2im*π*100/1e3) + @test y[1024] == x[1024] * exp(2im*π*1023*100/1e3) end -