# -*- coding: utf-8 -*-
"""
Created on Tue Apr  8 20:19:18 2025

@author: AKourgli
"""

import numpy as np
import matplotlib.pyplot as plt

# Paramètres
N_bits = 128          # Réduit pour meilleure visibilité
SNR_dB = 10
A = 1
sps = 20
fc = 2

# Génération des bits
bits = np.random.randint(0, 2, N_bits)

# Mapping 4-ASK avec Gray coding
gray_mapping = {
    (0,0): (-3*A, "00"),
    (0,1): (-1*A, "01"), 
    (1,1): (1*A, "11"),
    (1,0): (3*A, "10")
}
symbols_bits = bits.reshape(-1, 2)
symbols, gray_codes = zip(*[gray_mapping[tuple(sb)] for sb in symbols_bits])
symbols = np.array(symbols)

# Modulation
t = np.linspace(0, 1, sps)
carrier = np.cos(2*np.pi*fc*t)
modulated = np.concatenate([s*carrier for s in symbols])

# Ajout du bruit
SNR_lin = 10**(SNR_dB/10)
sigma = np.sqrt(np.mean(np.abs(modulated)**2)/(2*SNR_lin))
signal_bruite = modulated + np.random.normal(0, sigma, modulated.shape)

# Démodulation
demod = np.array([np.sum(signal_bruite[i*sps:(i+1)*sps]*carrier)*2/sps 
                for i in range(len(symbols))])

# Détection des symboles et bits
bits_recus = []
for s in demod:
    idx = np.argmin(np.abs(s - [-3*A, -1*A, 1*A, 3*A]))
    bits_recus.extend([int(b) for b in list(gray_mapping.values())[idx][1]])

# Création de la figure
plt.figure(figsize=(15, 12))

# Graphe 1: Signal modulé avec codes Gray
plt.subplot(3, 1, 1)
time_axis = np.arange(len(modulated))/sps
plt.plot(time_axis, modulated, 'b', label='Signal original')
plt.plot(time_axis, signal_bruite, 'r', alpha=0.3, label='Signal bruité')

# Ajout des codes Gray au centre de chaque symbole
for i in range(len(symbols)):
    x_pos = (i + 0.5)  # Centre du symbole en temps normalisé
    y_pos = symbols[i] + 0.5 if symbols[i] > 0 else symbols[i] - 0.5
    plt.text(x_pos, y_pos, gray_codes[i], 
             ha='center', va='center', 
             bbox=dict(facecolor='white', alpha=0.8, edgecolor='none'),
             fontsize=8)

plt.title('Signal modulé 4-ASK avec codes Gray')
plt.xlabel('Temps (symboles)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.legend()
plt.xlim(0, 20)  # Affiche les 8 premiers symboles

# Graphe 2: Diagramme de constellation
plt.subplot(3, 1, 2)
for (val, code), color in zip(gray_mapping.values(), ['red','green','blue','purple']):
    plt.scatter(val, 0, s=50, color=color, label=f'{code} : {val}A')
plt.scatter(demod, np.zeros_like(demod), c='gray', alpha=0.3, marker='x', label='Symboles reçus')
plt.title('Diagramme de constellation avec décisions')
plt.xlabel('Amplitude démodulée')
plt.yticks([])
plt.grid(True)
plt.legend()

# Graphe 3: Comparaison des bits
plt.subplot(3, 1, 3)
n_show = 32
plt.step(np.arange(n_show), bits[:n_show], 'b-', where='post', label='Émis')
plt.step(np.arange(n_show), bits_recus[:n_show], 'r--', where='post', label='Reçus', alpha=0.7)
plt.title('Comparaison des bits émis/reçus')
plt.xlabel('Index du bit')
plt.ylabel('Valeur binaire')
plt.ylim(-0.5, 1.5)
plt.grid(True)
plt.legend()

# Affichage du BER
ber = np.mean(np.array(bits) != np.array(bits_recus[:len(bits)]))
plt.figtext(0.15, 0.95, f"4-ASK - Code Gray - SNR: {SNR_dB} dB - BER: {ber:.2e}", 
            ha='left', va='center', fontsize=12, fontweight='bold')

plt.show()