# -*- coding: utf-8 -*-
"""
Created on Fri Feb 14 14:29:56 2025

@author: AKourgli
"""

import numpy as np
import matplotlib.pyplot as plt

# Définitions des DSP analytiques pour différents codes
def psd_nrz_unipolar(f, Tb):
    return (Tb/4) * (np.sinc(f*Tb)**2) + (1/4)*np.where(f == 0, 1, 0)  # DC component

def psd_nrz_polar(f, Tb):
    return Tb * (np.sinc(f*Tb)**2)

def psd_rz_unipolar(f, Tb):
    return (Tb/16) * (np.sinc(f*Tb/2)**2) + (1/16)*np.where(f == 0, 1, 0)

def psd_rz_polar(f, Tb):
    return (Tb/4) * (np.sinc(f*Tb/2)**2)

def psd_manchester(f, Tb):
    return Tb * (np.sinc(f*Tb/2)**2) * (np.sin(np.pi*f*Tb/2)**2)

def psd_4level(f, Tb):
    Ts=Tb* np.log2(4)
    return Ts/5 * (np.sinc(f*Ts)**2)  # Pour 4 niveaux équiprobables

def psd_8level(f, Tb):
    Ts=Tb* np.log2(8)
    return Ts/21 * (np.sinc(f*Ts)**2)  # Pour 8 niveaux équiprobables

def psd_ami(f, Tb):
    return (Tb/4) * (1 - np.cos(2*np.pi*f*Tb)) * (np.sinc(f*Tb)**2)

def psd_rz_bipolar(f, Tb):  # <-- Nouvelle fonction ajoutée
    return (Tb/4) * (1 - np.cos(2*np.pi*f*Tb)) * (np.sinc(f*Tb/2)**2)

def psd_miller(f, Tb):
    #return (2*(1 - np.cos(np.pi*f*Tb))**2)/((np.pi*f*Tb)**2 * (1 + np.cos(np.pi*f*Tb)**2)) * Tb
    return 1/Tb * (np.sinc(f * Tb))**2 * (1 - np.sinc(2 * f * Tb))

# Configuration des paramètres
Tb = 1       # Durée bit
f = np.linspace(0, 3, 1000)  # Fréquences normalisées

# Calcul des DSP
psd_functions_ind = [
    ('NRZ Unipolaire', psd_nrz_unipolar(f, Tb)),
    ('NRZ Polaire', psd_nrz_polar(f, Tb)),
    ('RZ Unipolaire', psd_rz_unipolar(f, Tb)),
    ('RZ Polaire', psd_rz_polar(f, Tb)),
    ('Manchester', psd_manchester(f, Tb)),
    ('4-Aires', psd_4level(f, Tb)),
    ('8-Aires', psd_8level(f, Tb)),
]

psd_functions_dpd = [
    ('AMI', psd_ami(f, Tb)),
    ('RZ Bipolaire', psd_rz_bipolar(f, Tb)),  
    ('Miller', psd_miller(f, Tb)),
]
# Affichage des résultats
plt.close('all'); 
plt.figure(1)
plt.subplot(1,2,1)
for label, spectrum in psd_functions_ind:
    plt.plot(f, spectrum, label=label)

plt.title('DSP Analytique des Codes de Ligne indépendants')
plt.xlabel('Fréquence normalisée (f*Tb)') ; plt.ylabel('Densité Spectrale de Puissance')
plt.legend(); plt.grid(True)

plt.subplot(1,2,2)
for label, spectrum in psd_functions_ind:
    plt.plot(f, 10 * np.log10(spectrum + 1e-12), label=label)
    
plt.title('DSP Analytique des Codes de Ligne indépendants en db')
plt.xlabel('Fréquence normalisée (f*Tb)'); plt.ylabel('Densité Spectrale de Puissance')
plt.legend(); plt.grid(True)

plt.figure(2)
plt.subplot(1,2,1)
for label, spectrum in psd_functions_dpd:
    plt.plot(f, spectrum, label=label)

plt.title('DSP Analytique des Codes de Ligne dépendants')
plt.xlabel('Fréquence normalisée (f*Tb)');plt.ylabel('Densité Spectrale de Puissance')
plt.legend(); plt.grid(True)

plt.subplot(1,2,2)
for label, spectrum in psd_functions_dpd:
    plt.plot(f, 10 * np.log10(spectrum + 1e-12), label=label)
    
plt.title('DSP Analytique des Codes de Ligne dépendants en db')
plt.xlabel('Fréquence normalisée (f*Tb)'); plt.ylabel('Densité Spectrale de Puissance')
plt.legend(); plt.grid(True)