Gray Mapping
This commit is contained in:
60
QAM/qam.c
60
QAM/qam.c
@ -14,27 +14,23 @@ struct qam_system_s {
|
|||||||
double Ts; // Temps d'échantillionage
|
double Ts; // Temps d'échantillionage
|
||||||
int N; // Nombre d'échantillions
|
int N; // Nombre d'échantillions
|
||||||
double Fc; // Fréquence de la porteuse
|
double Fc; // Fréquence de la porteuse
|
||||||
double complex** constellation; // Tableau de symboles I + j Q
|
double complex* constellation; // Tableau de symboles I + j Q 1D
|
||||||
};
|
};
|
||||||
typedef struct qam_system_s qam_system;
|
typedef struct qam_system_s qam_system;
|
||||||
|
|
||||||
// Initialisation de la constellation (double tableau de taille sqrt(M)),
|
// Initialisation de la constellation (double tableau de taille sqrt(M)),
|
||||||
// ToDo : changer à un tableau à 1 dimension pour éviter de calculer sqrt(M)
|
|
||||||
void init_constellation (qam_system* qam) {
|
void init_constellation (qam_system* qam) {
|
||||||
int sm = (int)sqrt(qam->M);
|
int sm = (int)sqrt(qam->M);
|
||||||
qam->constellation = (double complex**)malloc(sizeof(double complex*) * sm);
|
qam->constellation = (double complex*)malloc(sizeof(double complex) * qam->M);
|
||||||
|
|
||||||
for (int i = 0; i < sm; i++) {
|
|
||||||
qam->constellation[i] = (double complex*)malloc(sizeof(double complex) * sm);
|
|
||||||
}
|
|
||||||
|
|
||||||
double norm_factor = sqrt((double)(qam->M - 1) / 3.0); // Pour puissance unitaire
|
double norm_factor = sqrt((double)(qam->M - 1) / 3.0); // Pour puissance unitaire
|
||||||
|
|
||||||
for (int i = 0; i < sm; i++) {
|
for (int i = 0; i < sm; i++) {
|
||||||
double complex ip = -(sm - 1) + 2 * i;
|
double ip = -(sm - 1) + 2 * i;
|
||||||
for (int j = 0; j < sm; j++) {
|
for (int j = 0; j < sm; j++) {
|
||||||
double complex qp = -(sm - 1) + 2 * j;
|
double qp = -(sm - 1) + 2 * j;
|
||||||
qam->constellation[i][j] = (ip + I * qp) / norm_factor;
|
int idx = i * sm + j;
|
||||||
|
qam->constellation[idx] = (ip + I * qp) / norm_factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,27 +77,15 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bit
|
|||||||
double min_d = INFINITY;
|
double min_d = INFINITY;
|
||||||
int i_cl = 0;
|
int i_cl = 0;
|
||||||
int j_cl = 0;
|
int j_cl = 0;
|
||||||
for (int i = 0; i < sm; i++) {
|
for (int idx = 0; idx < qam->M; idx++) {
|
||||||
for (int j = 0; j < sm; j++) {
|
double d = cabs(r - qam->constellation[idx]);
|
||||||
double d = cabs(r - qam->constellation[i][j]);
|
if (d < min_d) {
|
||||||
if (d < min_d) {
|
min_d = d;
|
||||||
min_d = d;
|
i_cl = idx / sm;
|
||||||
i_cl = i;
|
j_cl = idx % sm;
|
||||||
j_cl = j;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Ancienne methode (non gray)
|
|
||||||
// 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++) {
|
|
||||||
bits_hat[k * qam->k + b] = (id >> (qam->k - 1 - b)) & 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Gray mapping
|
// Gray mapping
|
||||||
if (qam->k % 2 != 0) {
|
if (qam->k % 2 != 0) {
|
||||||
printf("demodulate : k pair (k = %d)\n", qam->k);
|
printf("demodulate : k pair (k = %d)\n", qam->k);
|
||||||
@ -141,20 +125,6 @@ void add_noise (double complex* s, int len, double sigma) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Changer le tableau de bits en boolen ou alors la represenation binaire et shifter pour extraire les bits (pas bien si M plus grand)
|
// Changer le tableau de bits en boolen ou alors la represenation binaire et shifter pour extraire les bits (pas bien si M plus grand)
|
||||||
/*void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double complex* symbols) {
|
|
||||||
int nb_symbols = nb_bits / qam->k;
|
|
||||||
int sm = sqrt(qam->M);
|
|
||||||
for (int k = 0; k < nb_symbols; k++) {
|
|
||||||
int id = 0;
|
|
||||||
for (int b = 0 ; b < qam->k; b++) {
|
|
||||||
id = id * 2 + bits[k * qam->k + b];
|
|
||||||
}
|
|
||||||
int i = id / sm;
|
|
||||||
int j = id % sm;
|
|
||||||
symbols[k] = qam->constellation[i][j];
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double complex* symbols) {
|
void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double complex* symbols) {
|
||||||
int nb_symbols = nb_bits / qam->k;
|
int nb_symbols = nb_bits / qam->k;
|
||||||
int sm = (int)sqrt(qam->M);
|
int sm = (int)sqrt(qam->M);
|
||||||
@ -182,7 +152,7 @@ void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double comple
|
|||||||
printf("bits_to_symbols : IOOR i_gray = %d j_gray = %d sm = %d \n", i_gray, j_gray, sm);
|
printf("bits_to_symbols : IOOR i_gray = %d j_gray = %d sm = %d \n", i_gray, j_gray, sm);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
symbols[sym] = qam->constellation[i_gray][j_gray];
|
symbols[sym] = qam->constellation[i_gray * sm + j_gray];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +181,8 @@ void fill_constellation_data(qam_system* qam, FILE *fp_ref) {
|
|||||||
int sm = (int)sqrt(qam->M);
|
int sm = (int)sqrt(qam->M);
|
||||||
for (int i = 0; i < sm; i++) {
|
for (int i = 0; i < sm; i++) {
|
||||||
for (int j = 0; j < sm; j++) {
|
for (int j = 0; j < sm; j++) {
|
||||||
fprintf(fp_ref, "% .8f % .8f\n", creal(qam->constellation[i][j]), cimag(qam->constellation[i][j]));
|
int idx = i * sm + j;
|
||||||
|
fprintf(fp_ref, "% .8f % .8f\n", creal(qam->constellation[idx]), cimag(qam->constellation[idx]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,6 +212,7 @@ void free_constellation(qam_system* qam) {
|
|||||||
for (int i = 0; i < sm; i++)
|
for (int i = 0; i < sm; i++)
|
||||||
free(qam->constellation[i]);
|
free(qam->constellation[i]);
|
||||||
free(qam->constellation);
|
free(qam->constellation);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main () {
|
int main () {
|
||||||
|
|||||||
104
QAM/save/2/debug.py
Normal file
104
QAM/save/2/debug.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import pyqtgraph as pg
|
||||||
|
from pyqtgraph.Qt import QtWidgets, QtCore
|
||||||
|
import numpy as np
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
# -------------------- Fichiers de données --------------------
|
||||||
|
REF_FILE = "constellation_ref.dat"
|
||||||
|
RX_FILE = "constellation.dat"
|
||||||
|
ERROR_FILE = "pll_error.dat"
|
||||||
|
|
||||||
|
# -------------------- Fonctions de chargement --------------------
|
||||||
|
def load_points(filename):
|
||||||
|
if os.path.exists(filename):
|
||||||
|
return np.loadtxt(filename)
|
||||||
|
else:
|
||||||
|
return np.zeros((0,2))
|
||||||
|
|
||||||
|
def load_error(filename):
|
||||||
|
if os.path.exists(filename):
|
||||||
|
return np.loadtxt(filename)
|
||||||
|
else:
|
||||||
|
return np.zeros((0,2))
|
||||||
|
|
||||||
|
# -------------------- Application --------------------
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
win = pg.GraphicsLayoutWidget(show=True, title="Constellation")
|
||||||
|
win.resize(900, 900)
|
||||||
|
win.setBackground('#0a0a0a') # fond noir profond
|
||||||
|
|
||||||
|
plot = win.addPlot()
|
||||||
|
plot.setAspectLocked(True) # axes égaux
|
||||||
|
|
||||||
|
# -------------------- Axes stylés --------------------
|
||||||
|
plot.getAxis('left').setPen(pg.mkPen('#AAA', width=2))
|
||||||
|
plot.getAxis('bottom').setPen(pg.mkPen('#AAA', width=2))
|
||||||
|
plot.getAxis('left').setTextPen(pg.mkPen('#EEE'))
|
||||||
|
plot.getAxis('bottom').setTextPen(pg.mkPen('#EEE'))
|
||||||
|
plot.setLabel('left', 'Quadrature (Q)', color='#EEE', size='12pt')
|
||||||
|
plot.setLabel('bottom', 'In-phase (I)', color='#EEE', size='12pt')
|
||||||
|
|
||||||
|
# -------------------- Grille subtile --------------------
|
||||||
|
grid = pg.GridItem()
|
||||||
|
grid.setPen(pg.mkPen('#444', width=1, style=QtCore.Qt.DotLine))
|
||||||
|
plot.addItem(grid)
|
||||||
|
|
||||||
|
# -------------------- Chargement initial --------------------
|
||||||
|
ref_data = load_points(REF_FILE)
|
||||||
|
rx_data = load_points(RX_FILE)
|
||||||
|
error_data = load_error(ERROR_FILE)
|
||||||
|
|
||||||
|
# Points référence
|
||||||
|
ref_plot = plot.plot(ref_data[:,0], ref_data[:,1],
|
||||||
|
pen=None,
|
||||||
|
symbol='o',
|
||||||
|
symbolSize=10,
|
||||||
|
symbolBrush=pg.mkBrush('#1E90FF'), # bleu vif
|
||||||
|
symbolPen=None,
|
||||||
|
name='Référence')
|
||||||
|
|
||||||
|
# Points reçus
|
||||||
|
rx_plot = plot.plot(rx_data[:,0], rx_data[:,1],
|
||||||
|
pen=None,
|
||||||
|
symbol='x',
|
||||||
|
symbolSize=6,
|
||||||
|
symbolBrush=pg.mkBrush('#FF4500'), # orange vif
|
||||||
|
symbolPen=None,
|
||||||
|
name='Reçu')
|
||||||
|
|
||||||
|
# PLL error en vert
|
||||||
|
error_plot = plot.plot(error_data[:,0], error_data[:,1],
|
||||||
|
pen=pg.mkPen('#00FF00', width=2),
|
||||||
|
symbol=None,
|
||||||
|
name='PLL error')
|
||||||
|
|
||||||
|
# -------------------- Légende stylée --------------------
|
||||||
|
legend = plot.addLegend()
|
||||||
|
for item in legend.items:
|
||||||
|
item[1].setPen(pg.mkPen('#FFF', width=2))
|
||||||
|
|
||||||
|
# -------------------- Timer pour mise à jour dynamique --------------------
|
||||||
|
def update():
|
||||||
|
ref_data = load_points(REF_FILE)
|
||||||
|
rx_data = load_points(RX_FILE)
|
||||||
|
error_data = load_error(ERROR_FILE)
|
||||||
|
|
||||||
|
if ref_data.size > 0:
|
||||||
|
ref_plot.setData(ref_data[:,0], ref_data[:,1])
|
||||||
|
if rx_data.size > 0:
|
||||||
|
rx_plot.setData(rx_data[:,0], rx_data[:,1])
|
||||||
|
if error_data.size > 0:
|
||||||
|
error_plot.setData(error_data[:,0], error_data[:,1])
|
||||||
|
|
||||||
|
timer = QtCore.QTimer()
|
||||||
|
timer.timeout.connect(update)
|
||||||
|
timer.start(500) # ms
|
||||||
|
|
||||||
|
# -------------------- Anti-aliasing --------------------
|
||||||
|
pg.setConfigOptions(antialias=True)
|
||||||
|
|
||||||
|
# -------------------- Exécution --------------------
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(app.exec_())
|
||||||
|
|
||||||
@ -39,36 +39,16 @@ void init_constellation (qam_system* qam) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcul du bruit gaussien pour un sigma donné
|
int bin_to_gray (int x) {
|
||||||
// Formule de Box-Muller
|
return x ^ (x >> 1);
|
||||||
double gaussian_noise (double sigma) {
|
|
||||||
double u1 = (rand() + 1) / ((double)RAND_MAX + 2);
|
|
||||||
double u2 = (rand() + 1) / ((double)RAND_MAX + 2);
|
|
||||||
return sigma * sqrt(-2 * log(u1)) * cos(2 * M_PI * u2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajout du bruit
|
// Iteration de XOR
|
||||||
void add_noise (double complex* s, int len, double sigma) {
|
int gray_to_bin(int g) {
|
||||||
for (int i = 0; i < len; i++) {
|
int b = g;
|
||||||
double nr = gaussian_noise(sigma);
|
while (g >>= 1)
|
||||||
double ni = gaussian_noise(sigma);
|
b ^= g;
|
||||||
s[i] += nr + I * ni;
|
return b;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Changer le tableau de bits en boolen ou alors la represenation binaire et shifter pour extraire les bits (pas bien si M plus grand)
|
|
||||||
void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double complex* symbols) {
|
|
||||||
int nb_symbols = nb_bits / qam->k;
|
|
||||||
int sm = sqrt(qam->M);
|
|
||||||
for (int k = 0; k < nb_symbols; k++) {
|
|
||||||
int id = 0;
|
|
||||||
for (int b = 0 ; b < qam->k; b++) {
|
|
||||||
id = id * 2 + bits[k * qam->k + b];
|
|
||||||
}
|
|
||||||
int i = id / sm;
|
|
||||||
int j = id % sm;
|
|
||||||
symbols[k] = qam->constellation[i][j];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modulation QAM
|
// Modulation QAM
|
||||||
@ -112,12 +92,146 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Ancienne methode (non gray)
|
||||||
// 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;
|
int id = i_cl * sm + j_cl;
|
||||||
|
|
||||||
for (int b = 0; b < qam->k; b++) {
|
for (int b = 0; b < qam->k; b++) {
|
||||||
bits_hat[k * qam->k + b] = (id >> (qam->k - 1 - b)) & 1;
|
bits_hat[k * qam->k + b] = (id >> (qam->k - 1 - b)) & 1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Gray mapping
|
||||||
|
if (qam->k % 2 != 0) {
|
||||||
|
printf("demodulate : k pair (k = %d)\n", qam->k);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
int bits_per_axis = qam->k / 2;
|
||||||
|
|
||||||
|
int i_bin = gray_to_bin(i_cl);
|
||||||
|
int j_bin = gray_to_bin(j_cl);
|
||||||
|
|
||||||
|
for (int b = 0; b < bits_per_axis; b++) {
|
||||||
|
bits_hat[k * qam->k + b] = (i_bin >> (bits_per_axis - 1 - b)) & 1;
|
||||||
|
bits_hat[k * qam->k + bits_per_axis + b] = (j_bin >> (bits_per_axis - 1 - b)) & 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcul du bruit gaussien pour un sigma donné
|
||||||
|
// Formule de Box-Muller
|
||||||
|
double gaussian_noise (double sigma) {
|
||||||
|
double u1 = (rand() + 1) / ((double)RAND_MAX + 2);
|
||||||
|
double u2 = (rand() + 1) / ((double)RAND_MAX + 2);
|
||||||
|
return sigma * sqrt(-2 * log(u1)) * cos(2 * M_PI * u2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajout du bruit
|
||||||
|
void add_noise (double complex* s, int len, double sigma) {
|
||||||
|
//double signal_power = (2.0/3.0)*(qam.M-1);
|
||||||
|
//double snr_dB = 5; // SNR en dB
|
||||||
|
//double snr_lin = pow(10.0, snr_dB / 10.0);
|
||||||
|
//double sigma = sqrt(signal_power / snr_lin);
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
double nr = gaussian_noise(sigma);
|
||||||
|
double ni = gaussian_noise(sigma);
|
||||||
|
s[i] += nr + I * ni;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changer le tableau de bits en boolen ou alors la represenation binaire et shifter pour extraire les bits (pas bien si M plus grand)
|
||||||
|
/*void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double complex* symbols) {
|
||||||
|
int nb_symbols = nb_bits / qam->k;
|
||||||
|
int sm = sqrt(qam->M);
|
||||||
|
for (int k = 0; k < nb_symbols; k++) {
|
||||||
|
int id = 0;
|
||||||
|
for (int b = 0 ; b < qam->k; b++) {
|
||||||
|
id = id * 2 + bits[k * qam->k + b];
|
||||||
|
}
|
||||||
|
int i = id / sm;
|
||||||
|
int j = id % sm;
|
||||||
|
symbols[k] = qam->constellation[i][j];
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double complex* symbols) {
|
||||||
|
int nb_symbols = nb_bits / qam->k;
|
||||||
|
int sm = (int)sqrt(qam->M);
|
||||||
|
|
||||||
|
// k pair
|
||||||
|
if (qam->k % 2 != 0) {
|
||||||
|
printf("bits_to_symbols : k doit être pair (k = %d) \n", qam->k);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
int bits_per_axis = qam->k / 2;
|
||||||
|
|
||||||
|
for (int sym = 0; sym < nb_symbols; sym++) {
|
||||||
|
// Construire les indices binaires i_bin (MSB...) et j_bin (LSB...)
|
||||||
|
int i_bin = 0;
|
||||||
|
int j_bin = 0;
|
||||||
|
for (int b = 0; b < bits_per_axis; b++) {
|
||||||
|
i_bin = (i_bin << 1) | bits[sym * qam->k + b];
|
||||||
|
j_bin = (j_bin << 1) | bits[sym * qam->k + bits_per_axis + b];
|
||||||
|
}
|
||||||
|
|
||||||
|
int i_gray = bin_to_gray(i_bin);
|
||||||
|
int j_gray = bin_to_gray(j_bin);
|
||||||
|
|
||||||
|
if (i_gray < 0 || i_gray >= sm || j_gray < 0 || j_gray >= sm) {
|
||||||
|
printf("bits_to_symbols : IOOR i_gray = %d j_gray = %d sm = %d \n", i_gray, j_gray, sm);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
symbols[sym] = qam->constellation[i_gray][j_gray];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double compare_bits(uint8_t* bits1, uint8_t* bits2, int nb_bits) {
|
||||||
|
int errors = 0;
|
||||||
|
for (int i = 0; i < nb_bits; i++) {
|
||||||
|
if (bits1[i] != bits2[i]) errors++;
|
||||||
|
}
|
||||||
|
return (double)errors / nb_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_dephasage(double complex* s, double phi_offset, int total_samples) {
|
||||||
|
for (int i = 0; i < total_samples; i++) {
|
||||||
|
s[i] *= cexp(I * phi_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_freq(qam_system* qam, double complex* s, double freq_offset, int total_samples) {
|
||||||
|
for (int i = 0; i < total_samples; i++) {
|
||||||
|
double t = (double)i / qam->Fs;
|
||||||
|
s[i] *= cexp(I * 2 * M_PI * freq_offset * t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fill_constellation_data(qam_system* qam, FILE *fp_ref) {
|
||||||
|
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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reconstruction_text(int nb_chars, uint8_t* output_bits, char* texte_recup) {
|
||||||
|
for(int i = 0; i < nb_chars; i++){
|
||||||
|
char c = 0;
|
||||||
|
for(int b = 0; b < 8; b++){
|
||||||
|
c |= output_bits[i*8 + b] << (7-b);
|
||||||
|
}
|
||||||
|
texte_recup[i] = c;
|
||||||
|
}
|
||||||
|
texte_recup[nb_chars] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void text_to_bits(int nb_chars, int nb_bits, char* texte, uint8_t* input_bits) {
|
||||||
|
for(int i = 0; i < nb_chars; i++){
|
||||||
|
for(int b = 0; b < 8; b++){
|
||||||
|
input_bits[i*8 + b] = (texte[i] >> (7-b)) & 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,45 +243,24 @@ void free_constellation(qam_system* qam) {
|
|||||||
free(qam->constellation);
|
free(qam->constellation);
|
||||||
}
|
}
|
||||||
|
|
||||||
double compare_bits(uint8_t* bits1, uint8_t* bits2, int nb_bits) {
|
|
||||||
int errors = 0;
|
|
||||||
for (int i = 0; i < nb_bits; i++) {
|
|
||||||
if (bits1[i] != bits2[i]) errors++;
|
|
||||||
}
|
|
||||||
return (double)errors / nb_bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main () {
|
int main () {
|
||||||
|
// Initialisation du system qam
|
||||||
qam_system qam;
|
qam_system qam;
|
||||||
qam.M = 16;
|
qam.M = 16;
|
||||||
qam.k = (int)log2((double)(qam.M));
|
qam.k = (int)log2((double)(qam.M));
|
||||||
qam.Fs = 44100;
|
qam.Fs = 44100;
|
||||||
//qam.Ts = 0.0003;
|
|
||||||
//qam.N = (int)qam.Fs * qam.Ts;
|
|
||||||
qam.Ts = 0.01;
|
qam.Ts = 0.01;
|
||||||
qam.N = (int)(qam.Fs * qam.Ts);
|
qam.N = (int)(qam.Fs * qam.Ts);
|
||||||
qam.Fc = 2000;
|
qam.Fc = 2000;
|
||||||
init_constellation(&qam);
|
init_constellation(&qam);
|
||||||
|
|
||||||
//int nb_bits = 1000;
|
// Conversion du texte en bits
|
||||||
//int nb_symbols = nb_bits / qam.k;
|
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";
|
||||||
|
|
||||||
//uint8_t* input_bits = malloc(nb_bits * sizeof(uint8_t));
|
|
||||||
//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, 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_chars = strlen(texte);
|
||||||
int nb_bits = nb_chars * 8;
|
int nb_bits = nb_chars * 8;
|
||||||
int nb_symbols = (nb_bits + qam.k - 1) / qam.k;
|
int nb_symbols = (nb_bits + qam.k - 1) / qam.k;
|
||||||
|
|
||||||
// Conversion du texte en bits
|
|
||||||
uint8_t* input_bits = malloc(nb_bits * sizeof(uint8_t));
|
uint8_t* input_bits = malloc(nb_bits * sizeof(uint8_t));
|
||||||
for(int i = 0; i < nb_chars; i++){
|
text_to_bits(nb_chars, nb_bits, texte, input_bits);
|
||||||
for(int b = 0; b < 8; b++){
|
|
||||||
input_bits[i*8 + b] = (texte[i] >> (7-b)) & 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conversion en symboles
|
// Conversion en symboles
|
||||||
double complex* symbols = malloc(sizeof(double complex) * nb_symbols);
|
double complex* symbols = malloc(sizeof(double complex) * nb_symbols);
|
||||||
@ -179,65 +272,28 @@ int main () {
|
|||||||
modulate(&qam, symbols, nb_symbols, s);
|
modulate(&qam, symbols, nb_symbols, s);
|
||||||
|
|
||||||
// Ajout du bruit
|
// Ajout du bruit
|
||||||
double signal_power = (2.0/3.0)*(qam.M-1); // puissance moyenne
|
|
||||||
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, 0);
|
||||||
|
|
||||||
|
|
||||||
FILE *fp_ref = fopen("constellation_ref.dat", "w");
|
FILE *fp_ref = fopen("constellation_ref.dat", "w");
|
||||||
int sm = (int)sqrt(qam.M);
|
fill_constellation_data(&qam, fp_ref);
|
||||||
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);
|
fclose(fp_ref);
|
||||||
|
|
||||||
FILE *fp_constel = fopen("constellation.dat", "w");
|
|
||||||
|
|
||||||
// Ajout de dephasage
|
// Ajout de dephasage
|
||||||
//double phase_offset = M_PI / 6.0; // 30 degrés
|
//add_dephasage(s, M_PI / 6.0, total_samples);
|
||||||
//for (int i = 0; i < total_samples; i++) {
|
|
||||||
// s[i] *= cexp(I * phase_offset);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// AJout de decalage de fréquence
|
// AJout de decalage de fréquence
|
||||||
//double freq_offset = 1; // Hz de décalage
|
//add_freq(&qam, s, 1, total_samples);
|
||||||
//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% d’un 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.2;
|
|
||||||
//double Ki = 0.02;
|
|
||||||
//double alpha = 0.1;
|
|
||||||
//FILE* fp_error = fopen("pll_error.dat", "w");
|
|
||||||
//pll_qam_symbol(&qam, s, r_corr, nb_symbols, Kp, Ki, alpha, fp_error);
|
|
||||||
//fclose(fp_error);
|
|
||||||
|
|
||||||
// Démodulation
|
// Démodulation
|
||||||
|
FILE *fp_constel = fopen("constellation.dat", "w");
|
||||||
uint8_t* output_bits = (uint8_t*)malloc(nb_bits * sizeof(uint8_t));
|
uint8_t* output_bits = (uint8_t*)malloc(nb_bits * sizeof(uint8_t));
|
||||||
demodulate(&qam, s, nb_symbols, output_bits, fp_constel);
|
demodulate(&qam, s, nb_symbols, output_bits, fp_constel);
|
||||||
|
|
||||||
fclose(fp_constel);
|
fclose(fp_constel);
|
||||||
|
|
||||||
// Reconstruction du texte
|
// Reconstruction du texte
|
||||||
char* texte_recup = malloc(nb_chars + 1);
|
char* texte_recup = malloc(nb_chars + 1);
|
||||||
for(int i = 0; i < nb_chars; i++){
|
reconstruction_text(nb_chars, output_bits, texte_recup);
|
||||||
char c = 0;
|
|
||||||
for(int b = 0; b < 8; b++){
|
|
||||||
c |= output_bits[i*8 + b] << (7-b);
|
|
||||||
}
|
|
||||||
texte_recup[i] = c;
|
|
||||||
}
|
|
||||||
texte_recup[nb_chars] = '\0';
|
|
||||||
printf("Texte original : %s\n\n", texte);
|
printf("Texte original : %s\n\n", texte);
|
||||||
printf("Texte demodulé : %s\n", texte_recup);
|
printf("Texte demodulé : %s\n", texte_recup);
|
||||||
|
|
||||||
Reference in New Issue
Block a user