PLL implementation

This commit is contained in:
2025-10-20 20:16:24 +02:00
parent 41fa5065a0
commit cb1328d514
24 changed files with 8778 additions and 1129 deletions

120
QAM/qam.c
View File

@ -99,7 +99,8 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bit
// Distance euclidien de Ir et Qr pour avoir le point le plus proche de la constellation (lent)
int sm = (int)sqrt(qam->M);
double min_d = INFINITY;
int i_cl, j_cl = 0;
int i_cl = 0;
int j_cl = 0;
for (int i = 0; i < sm; i++) {
for (int j = 0; j < sm; j++) {
double d = cabs(r - qam->constellation[i][j]);
@ -120,6 +121,50 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bit
}
}
// PLL pour corriger le déphasage
void pll_qam_symbol(qam_system* qam, double complex* symbols_rx, double complex* r_corr, int nb_symbols, double Kp, double Ki) {
double phase_est = 0.0;
double integrator = 0.0;
int sm = (int)sqrt(qam->M);
int N = qam->N;
for (int k = 0; k < nb_symbols; k++) {
double complex r_symbol = 0;
for (int n = 0; n < N; n++) {
int idx = k * N + n;
r_symbol += symbols_rx[idx] * cexp(2.0 * -I * M_PI * qam->Fc * ((double)idx / qam->Fs));
}
r_symbol /= N;
r_symbol *= cexp(-I * phase_est);
double min_d = INFINITY;
double complex closest = 0;
for (int i = 0; i < sm; i++) {
for (int j = 0; j < sm; j++) {
double d = cabs(r_symbol - qam->constellation[i][j]);
if (d < min_d) {
min_d = d;
closest = qam->constellation[i][j];
}
}
}
double error = carg(r_symbol * conj(closest));
integrator += Ki * error;
phase_est += Kp * error + integrator;
for (int n = 0; n < N; n++) {
int idx = k * N + n;
r_corr[idx] = symbols_rx[idx] * cexp(-I * phase_est);
}
}
}
// Libération de la mémoire
void free_constellation(qam_system* qam) {
int sm = (int)sqrt(qam->M);
@ -136,13 +181,53 @@ double compare_bits(uint8_t* bits1, uint8_t* bits2, int nb_bits) {
return (double)errors / nb_bits;
}
// Minimise le BER (si la pll s'est lockée de maniere déphasée de k*pi/2)
void demodulate2(qam_system* qam, double complex* r_corr, int nb_symbols, uint8_t* input_bits, uint8_t* output_bits, FILE* fp_constel) {
int nb_bits = nb_symbols * qam->k;
double best_ber = INFINITY;
double best_angle = 0.0;
uint8_t* temp_bits = (uint8_t*)malloc(nb_bits * sizeof(uint8_t));
for (int r = 0; r < 4; r++) {
double angle = r * M_PI/2;
double complex* rotated = (double complex*)malloc(sizeof(double complex) * nb_symbols * qam->N);
for (int i = 0; i < nb_symbols * qam->N; i++) {
rotated[i] = r_corr[i] * cexp(I * angle);
}
demodulate(qam, rotated, nb_symbols, temp_bits, fp_constel);
double ber = compare_bits(input_bits, temp_bits, nb_bits);
if (ber < best_ber) {
best_ber = ber;
best_angle = angle;
}
free(rotated);
}
for (int i = 0; i < nb_symbols * qam->N; i++) {
r_corr[i] *= cexp(I * best_angle);
}
demodulate(qam, r_corr, nb_symbols, output_bits, fp_constel);
free(temp_bits);
}
int main () {
qam_system qam;
qam.M = 16;
qam.k = (int)log2((double)(qam.M));
qam.Fs = 44100;
qam.Ts = 0.0003;
qam.N = (int)qam.Fs * qam.Ts;
//qam.Ts = 0.0003;
//qam.N = (int)qam.Fs * qam.Ts;
qam.Ts = 0.01;
qam.N = (int)(qam.Fs * qam.Ts);
qam.Fc = 2000;
init_constellation(&qam);
@ -153,7 +238,7 @@ int main () {
//for (int i = 0; i < nb_bits; i++) {
// input_bits[i] = rand() % 2;
//}
char* texte = "Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, ";
char* texte = "Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux, Vif juge, trempez ce blond whisky aqueux";
int nb_chars = strlen(texte);
int nb_bits = nb_chars * 8;
int nb_symbols = (nb_bits + qam.k - 1) / qam.k;
@ -180,7 +265,7 @@ int main () {
double snr_dB = 5; // SNR en dB
double snr_lin = pow(10.0, snr_dB / 10.0);
double sigma = sqrt(signal_power / snr_lin);
add_noise(s, total_samples, sigma);
add_noise(s, total_samples, 20);
FILE *fp_ref = fopen("constellation_ref.dat", "w");
@ -193,22 +278,32 @@ int main () {
fclose(fp_ref);
FILE *fp_constel = fopen("constellation.dat", "w");
double phase_offset = M_PI / 6.0; // 30 degrés
for (int i = 0; i < total_samples; i++) {
s[i] *= cexp(I * phase_offset);
}
double freq_offset = 0; // Hz de décalage
// Ajout de dephasage
//double phase_offset = M_PI / 6.0; // 30 degrés
//for (int i = 0; i < total_samples; i++) {
// s[i] *= cexp(I * phase_offset);
//}
// AJout de decalage de fréquence
double freq_offset = 1; // Hz de décalage
for (int i = 0; i < total_samples; i++) {
double t = (double)i / qam.Fs;
s[i] *= cexp(I * 2 * M_PI * freq_offset * t);
}
// Ajout de decalage entre les symbole
//int offset_samples = (int)(0.3 * qam.N); // décalage de 30% dun symbole
//memmove(s + offset_samples, s, (total_samples - offset_samples) * sizeof(double complex));
double complex* r_corr = malloc(sizeof(double complex) * total_samples);
double Kp = 0.25;
double Ki = 0.02;
pll_qam_symbol(&qam, s, r_corr, nb_symbols, Kp, Ki);
// Démodulation
uint8_t* output_bits = (uint8_t*)malloc(nb_bits * sizeof(uint8_t));
demodulate(&qam, s, nb_symbols, output_bits, fp_constel);
demodulate2(&qam, r_corr, nb_symbols, input_bits, output_bits, fp_constel);
//demodulate(&qam, r_corr, nb_symbols, output_bits, fp_constel);
fclose(fp_constel);
@ -222,7 +317,7 @@ int main () {
texte_recup[i] = c;
}
texte_recup[nb_chars] = '\0';
printf("Texte original : %s\n", texte);
printf("Texte original : %s\n\n", texte);
printf("Texte demodulé : %s\n", texte_recup);
// Calcul du BER
@ -233,6 +328,7 @@ int main () {
free(input_bits);
free(output_bits);
free(symbols);
free(r_corr);
free(s);
free_constellation(&qam);