Skip to content

Commit

Permalink
Merge pull request #12 from ErikBuer/nrzi
Browse files Browse the repository at this point in the history
add NRZI encoding // decoding
  • Loading branch information
RGerzaguet committed Mar 18, 2024
2 parents 347028d + bc39152 commit 6a53033
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 1 deletion.
15 changes: 14 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
push!(LOAD_PATH, "../src/")

using Documenter, DigitalComm
using Documenter

# Running `julia --project docs/make.jl` can be very slow locally.
# To speed it up during development, one can use make_local.jl instead.
# The code below checks whether it's being called from make_local.jl or not.
const LOCAL = get(ENV, "LOCAL", "false") == "true"

if LOCAL
include("../src/DigitalComm.jl")
using .DigitalComm
else
using DigitalComm
ENV["GKSwstype"] = "100" # Prevents warnings in the doc build on github actions.
end

DocMeta.setdocmeta!(DigitalComm, :DocTestSetup, :(using DigitalComm); recursive=true)

Expand Down
9 changes: 9 additions & 0 deletions docs/make_local.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Assumes it's being run from project root.

using Pkg
Pkg.activate("docs/")
Pkg.instantiate()

ENV["LOCAL"] = "true"

include("make.jl")
10 changes: 10 additions & 0 deletions docs/src/base.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Function overview

## Common functions

```@autodocs
Expand All @@ -6,6 +8,14 @@ Pages = ["DigitalComm.jl"]
Order = [:function, :type]
```

## NRZI Encoding

```@autodocs
Modules = [DigitalComm]
Pages = ["NRZI.jl"]
Order = [:function, :type]
```

## Quadrature Amplitude Modulation

```@autodocs
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Currently, the package support the following elements
- Bit manipulation
- Generation of random binary sequence
- Conversion between binary sequences and octal sequences
- Non Return to Zero Inverted (NRZI) encoding and decoding
- Modulation // demodulation
- Quadrature Amplitude Modulation (QAM) with 4-QAM (QPSK), 16-QAM, 64-QAM and 256-QAM.
- Hard demapper for the x-QAM formats
Expand Down
4 changes: 4 additions & 0 deletions src/DigitalComm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export genByteSequence! , genByteSequence;
include("bitMapping.jl");
export bitMappingQAM! , bitMappingQAM;

include("NRZI.jl");
export encodeNRZI , decodeNRZI;
export encodeNRZI! , decodeNRZI!;

# --- QAM Hard demapper
include("bitDeMapping.jl");
export bitDemappingQAM! , bitDemappingQAM;
Expand Down
113 changes: 113 additions & 0 deletions src/NRZI.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""
encodeNRZI(bits::AbstractVector, transitions::Symbol=:low)::AbstractVector
Map a bit sequence to Non-Return-to-Zero Inverted (NRZI) encoded bits.
Expects a vector of bits, e.g. `[0, 1, 1, 0, 0, 1, 0, 1, 0, 1]`.
# Arguments
- `bits::AbstractVector`: Vector of bits to encode.
- `transitions::Symbol`: Symbol indicating the symbol to transition on (`:low`/`:high`). Defaults to `:low`.
# Returns
- `encoded_bits::AbstractVector`: Vector of encoded bits.
# Examples
```jldoctest
julia> encoded_bits = encodeNRZI(Int32[0, 1, 1, 0, 0, 1], :low);
julia> transpose(encoded_bits)
1×6 transpose(::Vector{Int32}) with eltype Int32:
1 1 1 0 1 1
```
The example below shows how the `transitions` argument affects the encoded bit sequence.
```jldoctest
julia> encoded_bits = encodeNRZI(Int32[0, 1, 1, 0, 0, 1], :high);
julia> transpose(encoded_bits)
1×6 transpose(::Vector{Int32}) with eltype Int32:
0 1 0 0 0 1
```
"""
function encodeNRZI(bits::AbstractVector, transitions::Symbol=:low)::AbstractVector
encoded_bits = similar(bits)
encodeNRZI!(encoded_bits,bits,transitions)
return encoded_bits
end

function encodeNRZI!(encoded_bits::AbstractVector,bits::AbstractVector,transitions::Symbol=:low)
@assert size(encoded_bits) == size(bits) "With NRZI encoding, input and output should have same size ($(size(encoded_bits)) ≂̸ $(size(bits))"
last_bit = 0
transition_bit = (transitions == :high) ? 1 : 0
for n eachindex(bits)
if bits[n] == transition_bit
last_bit = last_bit 1
end
encoded_bits[n] = last_bit
end
return nothing
end

"""
decodeNRZI(bits::AbstractVector, transitions::Symbol=:low)::AbstractVector
Decode a Non-Return-to-Zero Inverted (NRZI) encoded bit sequence.
Expects a vector of bits, e.g. `[0, 1, 1, 0, 0, 1, 0, 1, 0, 1]`.
# Arguments
- `bits::AbstractVector`: Vector of bits to encode.
- `transitions::Symbol`: Symbol represented by a transition in the NRZI coded sequence (`:low`/`:high`). Defaults to `:low`.
# Returns
- `decoded_bits::AbstractVector`: Vector of decoded bits. The first bit of the output depends on a value of a memory bit in the decoder.
this value is set to `0`.
# Examples
```jldoctest
julia> decoded_bits = decodeNRZI(Int32[1, 1, 1, 0, 1, 1], :low);
julia> transpose(decoded_bits)
1×6 transpose(::Vector{Int32}) with eltype Int32:
0 1 1 0 0 1
```
The example below shows how the `transitions` argument affects the decoded bit sequence.
```jldoctest
julia> decoded_bits = decodeNRZI(Int32[0, 1, 0, 0, 0, 1], :high);
julia> transpose(decoded_bits)
1×6 transpose(::Vector{Int32}) with eltype Int32:
0 1 1 0 0 1
```
"""
function decodeNRZI(encoded_bits::AbstractVector, transitions::Symbol=:low)::AbstractVector
decoded_bits = similar(encoded_bits)
decodeNRZI!(decoded_bits,encoded_bits,transitions)
return decoded_bits
end


function decodeNRZI!(decoded_bits::AbstractVector,encoded_bits::AbstractVector, transitions::Symbol=:low)
@assert size(encoded_bits) == size(decoded_bits) "With NRZI encoding, input and output should have same size ($(size(decoded_bits)) ≂̸ $(size(encoded_bits))"
last_bit = 0
transition_bit = (transitions == :high) ? 1 : 0
for n eachindex(encoded_bits)
current_bit = encoded_bits[n]
if current_bit != last_bit
decoded_bit = transition_bit
else
decoded_bit = 1 - transition_bit
end
last_bit = current_bit
decoded_bits[n] = decoded_bit
end
return nothing
end
3 changes: 3 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ include("test_bitMapping.jl");
include("test_bitDemapping.jl");
include("test_hardConstellation.jl");

# NRZI Mapping
include("test_nrzi.jl");

# Symbol demapper
include("test_symbolDemapper.jl");

Expand Down
29 changes: 29 additions & 0 deletions test/test_nrzi.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ----------------------------------------------------
# --- Import modules
# ----------------------------------------------------
using DigitalComm
using Test
# ----------------------------------------------------
# --- Tests
# ----------------------------------------------------
# Note --> The mapping system is described in bitMapping.jl
println("Tests for symbol mapper with NRZI sequences");

@testset "NRZI" begin
# Create a bit squence (already tested)
nbBits = 2 * 2048;
bitSeq = genBitSequence(nbBits);
# Pass trough the function
buff = zeros(Complex{Float64},nbBits)
# Call
encodeNRZI!(buff,bitSeq);
buff2 = encodeNRZI(bitSeq);
@test all( buff .== buff2)
# Ensure Tx // Rx is Ok
@test all(bitSeq .== decodeNRZI(encodeNRZI(bitSeq)))
@test all(bitSeq .== decodeNRZI(encodeNRZI(bitSeq,:high),:high))
# Some manual check for both transitions
buff = [0x01;0x00;0x00;0x01;0x00;0x00;0x00;0x01 ];
@test all( encodeNRZI(buff,:low) .== [0;1;0;0;1;0;1;1]) # Transitions on 0
@test all( encodeNRZI(buff,:high) .== [1;1;1;0;0;0;0;1]) # Transitions on 1
end

0 comments on commit 6a53033

Please sign in to comment.