import numpy as np
import matplotlib.pyplot as plt

# Séquence binaire
sequence = "011010000110000101"
#sequence = "010011101010"
time_per_bit = 1

# Temps pour chaque codage
def create_time_steps(signal_length, step_size):
    return np.arange(0, signal_length * step_size, step_size)

# 1. NRZ Unipolaire
def nrz_unipolaire(seq):
    return [1 if bit == '1' else 0 for bit in seq]

# 2. NRZ Polaire
def nrz_polaire(seq):
    return [1 if bit == '1' else -1 for bit in seq]

# 3. RZ Unipolaire
def rz_unipolaire(seq):
    signal = []
    for bit in seq:
        if bit == '1':
            signal.extend([1, 0])  # Retour à zéro
        else:
            signal.extend([0, 0])  # Zéro constant
    return signal

# 4. RZ Polaire
def rz_polaire(seq):
    signal = []
    for bit in seq:
        if bit == '1':
            signal.extend([1, 0])  # Retour à zéro
        else:
            signal.extend([0, 0])  # Zéro constant
    return signal

# 5. PAM4
def pam4(seq):
    levels = {'00': -3, '01': -1, '10': 3, '11': 1}
    signal = [levels[seq[i:i + 2]] for i in range(0, len(seq), 2)]
    return signal

# 6. PAM8
def pam8(seq):
    levels = {'000': -7, '001': -5, '011': -3, '010': -1, '110': 1, '111': 3, '101': 5, '100': 7}
    signal = [levels[seq[i:i + 3]] for i in range(0, len(seq), 3)]
    return signal

# 7. Manchester
def manchester(seq):
    signal = []
    for bit in seq:
        if bit == '1':
            signal.extend([1, -1])  # Transition de + à -
        else:
            signal.extend([-1, 1])  # Transition de - à +
    return signal

# 8. RZ Bipolaire
def rz_bipolaire(seq):
    signal = []
    last_polarity = 1
    for bit in seq:
        if bit == '1':
            signal.extend([last_polarity * 1, 0])
            last_polarity *= -1
        else:
            signal.extend([0, 0])
    return signal

# 9. AMI
def ami(seq):
    signal = []
    last_polarity = 1
    for bit in seq:
        if bit == '1':
            signal.append(last_polarity * 1)
            last_polarity *= -1
        else:
            signal.append(0)
    return signal

# 10. Miller
def miller(seq):
    signal = []
    for bit in seq:
        if bit == '1':
            signal.extend([1, -1])
        else:
            signal.append(0)
    return signal

# 11. HDB3
def hdb3(seq):
    signal = []
    violation_count = 0
    last_polarity = 1
    for i, bit in enumerate(seq):
        if bit == '1':
            signal.append(last_polarity * 1)
            last_polarity *= -1
            violation_count = 0
        else:
            violation_count += 1
            if violation_count == 4:
                violation_count = 0
                if last_polarity == 1:
                    signal.extend([-1, 1])
                else:
                    signal.extend([1, -1])
                last_polarity *= -1
            else:
                signal.append(0)
    return signal

# Création des graphiques pour chaque codage
plt.figure(1)

# Tracés
codings = [
    ("NRZ Unipolaire", nrz_unipolaire),
    ("NRZ Polaire", nrz_polaire),
    ("RZ Unipolaire", rz_unipolaire),
    ("RZ Polaire", rz_polaire),
    ("PAM4", pam4),
    ("PAM8", pam8),
    ("Manchester", manchester),
    ("RZ Bipolaire", rz_bipolaire),
    ("AMI", ami),
    ("Miller", miller),
    ("HDB3", hdb3),
]

# Pour chaque codage, ajuster le tracé
for idx, (title, func) in enumerate(codings, 1):
    signal = func(sequence)
    time_steps = create_time_steps(len(signal), 1)  # Créer un vecteur de temps adapté
    plt.subplot(3, 4, idx)
    plt.step(time_steps, signal)
    plt.title(title)
    plt.grid(True)

# Affichage de tous les tracés
plt.tight_layout()
plt.show()
