Skip to content

Commit 6a53033

Browse files
authored
Merge pull request #12 from ErikBuer/nrzi
add NRZI encoding // decoding
2 parents 347028d + bc39152 commit 6a53033

8 files changed

Lines changed: 183 additions & 1 deletion

File tree

docs/make.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
push!(LOAD_PATH, "../src/")
22

3-
using Documenter, DigitalComm
3+
using Documenter
4+
5+
# Running `julia --project docs/make.jl` can be very slow locally.
6+
# To speed it up during development, one can use make_local.jl instead.
7+
# The code below checks whether it's being called from make_local.jl or not.
8+
const LOCAL = get(ENV, "LOCAL", "false") == "true"
9+
10+
if LOCAL
11+
include("../src/DigitalComm.jl")
12+
using .DigitalComm
13+
else
14+
using DigitalComm
15+
ENV["GKSwstype"] = "100" # Prevents warnings in the doc build on github actions.
16+
end
417

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

docs/make_local.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Assumes it's being run from project root.
2+
3+
using Pkg
4+
Pkg.activate("docs/")
5+
Pkg.instantiate()
6+
7+
ENV["LOCAL"] = "true"
8+
9+
include("make.jl")

docs/src/base.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Function overview
2+
13
## Common functions
24

35
```@autodocs
@@ -6,6 +8,14 @@ Pages = ["DigitalComm.jl"]
68
Order = [:function, :type]
79
```
810

11+
## NRZI Encoding
12+
13+
```@autodocs
14+
Modules = [DigitalComm]
15+
Pages = ["NRZI.jl"]
16+
Order = [:function, :type]
17+
```
18+
919
## Quadrature Amplitude Modulation
1020

1121
```@autodocs

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Currently, the package support the following elements
1616
- Bit manipulation
1717
- Generation of random binary sequence
1818
- Conversion between binary sequences and octal sequences
19+
- Non Return to Zero Inverted (NRZI) encoding and decoding
1920
- Modulation // demodulation
2021
- Quadrature Amplitude Modulation (QAM) with 4-QAM (QPSK), 16-QAM, 64-QAM and 256-QAM.
2122
- Hard demapper for the x-QAM formats

src/DigitalComm.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ export genByteSequence! , genByteSequence;
2727
include("bitMapping.jl");
2828
export bitMappingQAM! , bitMappingQAM;
2929

30+
include("NRZI.jl");
31+
export encodeNRZI , decodeNRZI;
32+
export encodeNRZI! , decodeNRZI!;
33+
3034
# --- QAM Hard demapper
3135
include("bitDeMapping.jl");
3236
export bitDemappingQAM! , bitDemappingQAM;

src/NRZI.jl

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""
2+
encodeNRZI(bits::AbstractVector, transitions::Symbol=:low)::AbstractVector
3+
4+
Map a bit sequence to Non-Return-to-Zero Inverted (NRZI) encoded bits.
5+
Expects a vector of bits, e.g. `[0, 1, 1, 0, 0, 1, 0, 1, 0, 1]`.
6+
7+
# Arguments
8+
9+
- `bits::AbstractVector`: Vector of bits to encode.
10+
- `transitions::Symbol`: Symbol indicating the symbol to transition on (`:low`/`:high`). Defaults to `:low`.
11+
12+
# Returns
13+
14+
- `encoded_bits::AbstractVector`: Vector of encoded bits.
15+
16+
# Examples
17+
18+
```jldoctest
19+
julia> encoded_bits = encodeNRZI(Int32[0, 1, 1, 0, 0, 1], :low);
20+
21+
julia> transpose(encoded_bits)
22+
1×6 transpose(::Vector{Int32}) with eltype Int32:
23+
1 1 1 0 1 1
24+
```
25+
26+
The example below shows how the `transitions` argument affects the encoded bit sequence.
27+
28+
```jldoctest
29+
julia> encoded_bits = encodeNRZI(Int32[0, 1, 1, 0, 0, 1], :high);
30+
31+
julia> transpose(encoded_bits)
32+
1×6 transpose(::Vector{Int32}) with eltype Int32:
33+
0 1 0 0 0 1
34+
```
35+
"""
36+
function encodeNRZI(bits::AbstractVector, transitions::Symbol=:low)::AbstractVector
37+
encoded_bits = similar(bits)
38+
encodeNRZI!(encoded_bits,bits,transitions)
39+
return encoded_bits
40+
end
41+
42+
function encodeNRZI!(encoded_bits::AbstractVector,bits::AbstractVector,transitions::Symbol=:low)
43+
@assert size(encoded_bits) == size(bits) "With NRZI encoding, input and output should have same size ($(size(encoded_bits)) ≂̸ $(size(bits))"
44+
last_bit = 0
45+
transition_bit = (transitions == :high) ? 1 : 0
46+
for n eachindex(bits)
47+
if bits[n] == transition_bit
48+
last_bit = last_bit 1
49+
end
50+
encoded_bits[n] = last_bit
51+
end
52+
return nothing
53+
end
54+
55+
"""
56+
decodeNRZI(bits::AbstractVector, transitions::Symbol=:low)::AbstractVector
57+
58+
Decode a Non-Return-to-Zero Inverted (NRZI) encoded bit sequence.
59+
Expects a vector of bits, e.g. `[0, 1, 1, 0, 0, 1, 0, 1, 0, 1]`.
60+
61+
# Arguments
62+
63+
- `bits::AbstractVector`: Vector of bits to encode.
64+
- `transitions::Symbol`: Symbol represented by a transition in the NRZI coded sequence (`:low`/`:high`). Defaults to `:low`.
65+
66+
# Returns
67+
68+
- `decoded_bits::AbstractVector`: Vector of decoded bits. The first bit of the output depends on a value of a memory bit in the decoder.
69+
this value is set to `0`.
70+
71+
# Examples
72+
73+
```jldoctest
74+
julia> decoded_bits = decodeNRZI(Int32[1, 1, 1, 0, 1, 1], :low);
75+
76+
julia> transpose(decoded_bits)
77+
1×6 transpose(::Vector{Int32}) with eltype Int32:
78+
0 1 1 0 0 1
79+
```
80+
81+
The example below shows how the `transitions` argument affects the decoded bit sequence.
82+
83+
```jldoctest
84+
julia> decoded_bits = decodeNRZI(Int32[0, 1, 0, 0, 0, 1], :high);
85+
86+
julia> transpose(decoded_bits)
87+
1×6 transpose(::Vector{Int32}) with eltype Int32:
88+
0 1 1 0 0 1
89+
```
90+
"""
91+
function decodeNRZI(encoded_bits::AbstractVector, transitions::Symbol=:low)::AbstractVector
92+
decoded_bits = similar(encoded_bits)
93+
decodeNRZI!(decoded_bits,encoded_bits,transitions)
94+
return decoded_bits
95+
end
96+
97+
98+
function decodeNRZI!(decoded_bits::AbstractVector,encoded_bits::AbstractVector, transitions::Symbol=:low)
99+
@assert size(encoded_bits) == size(decoded_bits) "With NRZI encoding, input and output should have same size ($(size(decoded_bits)) ≂̸ $(size(encoded_bits))"
100+
last_bit = 0
101+
transition_bit = (transitions == :high) ? 1 : 0
102+
for n eachindex(encoded_bits)
103+
current_bit = encoded_bits[n]
104+
if current_bit != last_bit
105+
decoded_bit = transition_bit
106+
else
107+
decoded_bit = 1 - transition_bit
108+
end
109+
last_bit = current_bit
110+
decoded_bits[n] = decoded_bit
111+
end
112+
return nothing
113+
end

test/runtests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ include("test_bitMapping.jl");
1616
include("test_bitDemapping.jl");
1717
include("test_hardConstellation.jl");
1818

19+
# NRZI Mapping
20+
include("test_nrzi.jl");
21+
1922
# Symbol demapper
2023
include("test_symbolDemapper.jl");
2124

test/test_nrzi.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# ----------------------------------------------------
2+
# --- Import modules
3+
# ----------------------------------------------------
4+
using DigitalComm
5+
using Test
6+
# ----------------------------------------------------
7+
# --- Tests
8+
# ----------------------------------------------------
9+
# Note --> The mapping system is described in bitMapping.jl
10+
println("Tests for symbol mapper with NRZI sequences");
11+
12+
@testset "NRZI" begin
13+
# Create a bit squence (already tested)
14+
nbBits = 2 * 2048;
15+
bitSeq = genBitSequence(nbBits);
16+
# Pass trough the function
17+
buff = zeros(Complex{Float64},nbBits)
18+
# Call
19+
encodeNRZI!(buff,bitSeq);
20+
buff2 = encodeNRZI(bitSeq);
21+
@test all( buff .== buff2)
22+
# Ensure Tx // Rx is Ok
23+
@test all(bitSeq .== decodeNRZI(encodeNRZI(bitSeq)))
24+
@test all(bitSeq .== decodeNRZI(encodeNRZI(bitSeq,:high),:high))
25+
# Some manual check for both transitions
26+
buff = [0x01;0x00;0x00;0x01;0x00;0x00;0x00;0x01 ];
27+
@test all( encodeNRZI(buff,:low) .== [0;1;0;0;1;0;1;1]) # Transitions on 0
28+
@test all( encodeNRZI(buff,:high) .== [1;1;1;0;0;0;0;1]) # Transitions on 1
29+
end

0 commit comments

Comments
 (0)