qam edits
This commit is contained in:
11730
QAM/constellation.dat
Normal file
11730
QAM/constellation.dat
Normal file
File diff suppressed because it is too large
Load Diff
16
QAM/constellation_ref.dat
Normal file
16
QAM/constellation_ref.dat
Normal file
@ -0,0 +1,16 @@
|
||||
-3.00000000 -3.00000000
|
||||
-3.00000000 -1.00000000
|
||||
-3.00000000 1.00000000
|
||||
-3.00000000 3.00000000
|
||||
-1.00000000 -3.00000000
|
||||
-1.00000000 -1.00000000
|
||||
-1.00000000 1.00000000
|
||||
-1.00000000 3.00000000
|
||||
1.00000000 -3.00000000
|
||||
1.00000000 -1.00000000
|
||||
1.00000000 1.00000000
|
||||
1.00000000 3.00000000
|
||||
3.00000000 -3.00000000
|
||||
3.00000000 -1.00000000
|
||||
3.00000000 1.00000000
|
||||
3.00000000 3.00000000
|
||||
16
QAM/plot_const.plt
Normal file
16
QAM/plot_const.plt
Normal file
@ -0,0 +1,16 @@
|
||||
set terminal qt size 600,600 title "Diagramme de constellation"
|
||||
set xlabel "I (In-phase)"
|
||||
set ylabel "Q (Quadrature)"
|
||||
set grid
|
||||
set key off
|
||||
set pointsize 1.5
|
||||
set xrange [-5:5]
|
||||
set yrange [-5:5]
|
||||
|
||||
while (1) {
|
||||
plot \
|
||||
'constellation_ref.dat' using 1:2 with points pt 7 ps 2.5 lc rgb "yellow", \
|
||||
'constellation.dat' using 1:2 with points pt 7 ps 1 lc rgb "blue"
|
||||
pause 0.15
|
||||
}
|
||||
|
||||
117
QAM/qam.c
117
QAM/qam.c
@ -4,8 +4,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <complex.h>
|
||||
#include <string.h>
|
||||
#include "../wav/wav.h"
|
||||
|
||||
#define A 1
|
||||
#define A 3000
|
||||
|
||||
struct qam_system_s {
|
||||
int M; // Nombre de symboles M-QAM
|
||||
@ -82,7 +83,7 @@ void modulate (qam_system* qam, double complex* symbols, int nb_symbols, double
|
||||
}
|
||||
|
||||
// Demodulation QAM
|
||||
void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bits_hat) {
|
||||
void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bits_hat, FILE *fp_constel) {
|
||||
for (int k = 0; k < nb_symbols; k++) {
|
||||
double complex r = 0;
|
||||
for (int n = 0; n < qam->N; n++) {
|
||||
@ -90,8 +91,12 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bit
|
||||
}
|
||||
r /= qam->N;
|
||||
|
||||
// Distance euclidien de Ir et Qr pour avoir le point le plus proche de la constellation (lent)
|
||||
if (fp_constel) {
|
||||
fprintf(fp_constel, "% .8f % .8f\n", creal(r), cimag(r));
|
||||
fflush(fp_constel);
|
||||
}
|
||||
|
||||
// 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;
|
||||
@ -106,7 +111,7 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bit
|
||||
}
|
||||
}
|
||||
|
||||
// index du symbole (id) : même mappage que dans bits_to_symbols()
|
||||
// index du symbole (id) : même mappage que dans bits_to_symbols()
|
||||
int id = i_cl * sm + j_cl;
|
||||
|
||||
for (int b = 0; b < qam->k; b++) {
|
||||
@ -131,37 +136,12 @@ double compare_bits(uint8_t* bits1, uint8_t* bits2, int nb_bits) {
|
||||
return (double)errors / nb_bits;
|
||||
}
|
||||
|
||||
void symbol_timing_recovery(double complex* r, int r_len, double complex* preamble, int preamble_len, int N_max, int* offset_est, int* N_est) {
|
||||
double max_corr = 0;
|
||||
int best_offset = 0;
|
||||
int best_N = 1;
|
||||
|
||||
for(int N_try = 1; N_try <= N_max; N_try++) {
|
||||
for(int off = 0; off <= r_len - preamble_len * N_try; off++) {
|
||||
double complex corr = 0;
|
||||
for(int k = 0; k < preamble_len; k++) {
|
||||
for(int n = 0; n < N_try; n++) {
|
||||
corr += r[off + k * N_try + n] * conj(preamble[k]);
|
||||
}
|
||||
}
|
||||
double mag = cabs(corr);
|
||||
if(mag > max_corr) {
|
||||
max_corr = mag;
|
||||
best_offset = off;
|
||||
best_N = N_try;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*offset_est = best_offset;
|
||||
*N_est = best_N;
|
||||
}
|
||||
int main () {
|
||||
qam_system qam;
|
||||
qam.M = 16;
|
||||
qam.k = (int)log2((double)(qam.M));
|
||||
qam.Fs = 44100;
|
||||
qam.Ts = 0.0003;
|
||||
qam.Ts = 0.05;
|
||||
qam.N = (int)qam.Fs * qam.Ts;
|
||||
qam.Fc = 2000;
|
||||
init_constellation(&qam);
|
||||
@ -173,7 +153,7 @@ int main () {
|
||||
//for (int i = 0; i < nb_bits; i++) {
|
||||
// input_bits[i] = rand() % 2;
|
||||
//}
|
||||
char* texte = "Bonjour tout le monde salut !!";
|
||||
char* texte = "Test du test";
|
||||
int nb_chars = strlen(texte);
|
||||
int nb_bits = nb_chars * 8;
|
||||
int nb_symbols = (nb_bits + qam.k - 1) / qam.k;
|
||||
@ -200,53 +180,27 @@ 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, 0);
|
||||
add_noise(s, total_samples, sigma + 3);
|
||||
|
||||
|
||||
FILE *fp_ref = fopen("constellation_ref.dat", "w");
|
||||
int sm = (int)sqrt(qam.M);
|
||||
for (int i = 0; i < sm; i++) {
|
||||
for (int j = 0; j < sm; j++) {
|
||||
fprintf(fp_ref, "% .8f % .8f\n",
|
||||
creal(qam.constellation[i][j]),
|
||||
cimag(qam.constellation[i][j]));
|
||||
}
|
||||
}
|
||||
fclose(fp_ref);
|
||||
FILE *fp_constel = fopen("constellation.dat", "w");
|
||||
|
||||
// Démodulation
|
||||
//uint8_t* output_bits = malloc(nb_bits * sizeof(uint8_t));
|
||||
//demodulate(&qam, s, nb_symbols, output_bits);
|
||||
uint8_t* output_bits = malloc(nb_bits * sizeof(uint8_t));
|
||||
demodulate(&qam, s, nb_symbols, output_bits, fp_constel);
|
||||
|
||||
// Calcul du taux d'erreur
|
||||
//double ber = compare_bits(input_bits, output_bits, nb_bits);
|
||||
//printf("Taux d'erreur : %.4f\n", ber * 100);
|
||||
fclose(fp_constel);
|
||||
|
||||
// Blind QAM
|
||||
int preamble_symbols = 32;
|
||||
uint8_t* preamble_bits = malloc(preamble_symbols * qam.k * sizeof(uint8_t));
|
||||
// Genere un préambule aléatoire
|
||||
for(int i = 0; i < preamble_symbols * qam.k; i++) {
|
||||
preamble_bits[i] = rand() % 2;
|
||||
}
|
||||
double complex* preamble_symbols_complex = (double complex*)malloc(sizeof(double complex) * preamble_symbols);
|
||||
bits_to_symbols(&qam, preamble_bits, preamble_symbols * qam.k, preamble_symbols_complex);
|
||||
// Ajout du préambule dans les données
|
||||
int total_symbols = preamble_symbols + nb_symbols;
|
||||
double complex* all_symbols = malloc(sizeof(double complex) * total_symbols);
|
||||
// Copier le préambule
|
||||
for(int i = 0; i < preamble_symbols; i++) {
|
||||
all_symbols[i] = preamble_symbols_complex[i];
|
||||
}
|
||||
// Copier les symboles réels
|
||||
for(int i = 0; i < nb_symbols; i++) {
|
||||
all_symbols[i + preamble_symbols] = symbols[i];
|
||||
}
|
||||
int total_samples_with_preamble = total_symbols * qam.N;
|
||||
double complex* s_with_preamble = malloc(sizeof(double complex) * total_samples_with_preamble);
|
||||
|
||||
modulate(&qam, all_symbols, total_symbols, s_with_preamble);
|
||||
|
||||
|
||||
// Symbol Timing Recovery blind
|
||||
int offset_est = 0;
|
||||
int N_est = 0;
|
||||
symbol_timing_recovery(s_with_preamble, total_samples_with_preamble, preamble_symbols_complex, preamble_symbols, qam.N*2, &offset_est, &N_est);
|
||||
|
||||
printf("Symbol Timing Recovery : offset=%d, N_est=%d (%d)\n", offset_est, N_est, qam.N);
|
||||
|
||||
/*
|
||||
// Calcul du BER
|
||||
double ber = compare_bits(input_bits, output_bits, nb_bits);
|
||||
printf("Taux d'erreur blind QAM: %.4f\n", ber * 100);
|
||||
|
||||
// Reconstruction du texte
|
||||
char* texte_recup = malloc(nb_chars + 1);
|
||||
@ -260,11 +214,22 @@ int main () {
|
||||
texte_recup[nb_chars] = '\0';
|
||||
printf("Texte original : %s\n", texte);
|
||||
printf("Texte demodulé : %s\n", texte_recup);
|
||||
*/
|
||||
|
||||
// Calcul du BER
|
||||
double ber = compare_bits(input_bits, output_bits, nb_bits);
|
||||
printf("Taux d'erreur blind QAM: %.4f\n", ber * 100);
|
||||
|
||||
// Affichage du signal dans un .wav
|
||||
double* si = (double*)malloc(sizeof(double) * total_samples);
|
||||
for (int i = 0; i < total_samples; i++) {
|
||||
si[i] = cimag(s[i]);
|
||||
}
|
||||
write_wav("output.wav", si, total_samples);
|
||||
|
||||
|
||||
// Libération mémoire
|
||||
free(input_bits);
|
||||
//free(output_bits);
|
||||
free(output_bits);
|
||||
free(symbols);
|
||||
free(s);
|
||||
free_constellation(&qam);
|
||||
|
||||
Reference in New Issue
Block a user