894 lignes
32 KiB
C++
894 lignes
32 KiB
C++
|
|
/* Fichier d'implémentation de la classe DigitalModulations numériques
|
||
|
|
* - d'amplitude ;
|
||
|
|
* - de fréquence;
|
||
|
|
* - de phase ;
|
||
|
|
* - M-QAM
|
||
|
|
*
|
||
|
|
* Author : Eric Bachard 2026/01/08 18h37
|
||
|
|
* Licence GPL v2
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <cstdlib>
|
||
|
|
#include <cstdint>
|
||
|
|
#include "math.h"
|
||
|
|
#include "imgui.h"
|
||
|
|
#include "imgui_utils.h"
|
||
|
|
#include "vtoggle_button.h"
|
||
|
|
#include "gl_helpers.h"
|
||
|
|
|
||
|
|
#ifdef M_PI
|
||
|
|
#undef M_PI
|
||
|
|
#define M_PI 3.14159265358979323846f
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// FIXME image
|
||
|
|
static int my_image_width = 0;
|
||
|
|
static int my_image_height = 0;
|
||
|
|
static GLuint my_image_texture = 0;
|
||
|
|
|
||
|
|
DigitalModulation::DigitalModulation()
|
||
|
|
: mdWordSize(DEFAULT_WORD_SIZE)
|
||
|
|
{
|
||
|
|
setDigitalModulationType (Amplitude_TAB, MOD_OOK_TYPE);
|
||
|
|
setDigitalModulationType (Frequency_TAB, MOD_FSK_TYPE);
|
||
|
|
setDigitalModulationType (Phase_TAB, MOD_BPSK_TYPE);
|
||
|
|
// TODO Later
|
||
|
|
//setDigitalModulationType (M_QAM_TAB, MOD_M_QAM_TYPE);
|
||
|
|
};
|
||
|
|
|
||
|
|
DigitalModulation::~DigitalModulation()
|
||
|
|
{
|
||
|
|
};
|
||
|
|
|
||
|
|
short int DigitalModulation::AmplitudeDigitalModulation(float * carrier_freq,
|
||
|
|
int * am_bits,
|
||
|
|
DigitalModulationType * p_aType)
|
||
|
|
{
|
||
|
|
// TODO : améliorer cette partie
|
||
|
|
static DigitalModulationType amplitude_modulation_t = *p_aType;
|
||
|
|
static float c_freq = *carrier_freq;
|
||
|
|
|
||
|
|
// --------------------- LEFT : SIGNAL -----------------
|
||
|
|
ImGui::BeginChild("Signal", ImVec2(ImGui::GetContentRegionAvail().x - CHILD2_WIDTH, 0), false);
|
||
|
|
|
||
|
|
// pour 1 bit, 100 échantillons (400 pour la modulation de fréquence pour fporteuse max)
|
||
|
|
static int samples_per_bit = SAMPLES_PER_BIT_MAX;
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
ImGui::SliderFloat("Frequence porteuse ", &c_freq, 2.0f, 10.0f);
|
||
|
|
#if defined(DEBUG)
|
||
|
|
ImGui::SliderInt("Nombre de points par symbole", &samples_per_bit, DEFAULT_SAMPLES_PER_BIT, 500);
|
||
|
|
#endif
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
// Surbrillance de la trame affichée
|
||
|
|
highlightFrame(am_bits, getWordSize());
|
||
|
|
|
||
|
|
// position du curseur + dimensions du canvas.
|
||
|
|
// canvas_pos contient les coordonnées du curseur (marque l'endroit d'où l'on dessine à ce point du programme)
|
||
|
|
ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
|
||
|
|
|
||
|
|
// Dimensions du cadre dans lequel on dessine la sinusoïde
|
||
|
|
ImVec2 canvas_size(ImGui::GetContentRegionAvail().x, CANVAS_HEIGHT);
|
||
|
|
|
||
|
|
// ce qui va être dessiné
|
||
|
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||
|
|
|
||
|
|
// On dessine un fond blanc
|
||
|
|
draw_list->AddRectFilled
|
||
|
|
(
|
||
|
|
canvas_pos,
|
||
|
|
ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(255,255,255,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
// on ajoute par dessus un tour noir
|
||
|
|
draw_list->AddRect
|
||
|
|
(
|
||
|
|
canvas_pos,
|
||
|
|
ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(0,0,0,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
// calcul des coordonnées du centre de la frame
|
||
|
|
float center_y = canvas_pos.y + canvas_size.y / 2.0f;
|
||
|
|
|
||
|
|
// amplitude de la sinusoïde de base
|
||
|
|
float base_amp = SINUS_AMPLITUDE;
|
||
|
|
float total_samples = getWordSize() * samples_per_bit;
|
||
|
|
float dx = canvas_size.x / total_samples;
|
||
|
|
float x = canvas_pos.x;
|
||
|
|
|
||
|
|
ImVec2 prev(x, center_y);
|
||
|
|
|
||
|
|
for (int bit_traite = 0; bit_traite < getWordSize(); bit_traite++)
|
||
|
|
{
|
||
|
|
draw_list->AddLine
|
||
|
|
(
|
||
|
|
ImVec2(x, canvas_pos.y),
|
||
|
|
ImVec2(x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(0,120,255,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
float amplitude = 0.0f;
|
||
|
|
|
||
|
|
switch (amplitude_modulation_t)
|
||
|
|
{
|
||
|
|
case MOD_OOK_TYPE:
|
||
|
|
amplitude = am_bits[bit_traite] ? base_amp : 0.0f;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MOD_ASK_TYPE:
|
||
|
|
amplitude = am_bits[bit_traite] ? base_amp : base_amp * 0.4f;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MOD_MASK_TYPE:
|
||
|
|
if ((bit_traite % 2) == 0) // bit pair => bits 0, 2, 4 ou 6
|
||
|
|
amplitude = base_amp * (0.25 + 0.5 * am_bits[bit_traite] + 0.25 * am_bits[bit_traite+1]);
|
||
|
|
else // bit impair => bits 1, 3, 5 ou 7
|
||
|
|
amplitude = base_amp * (0.25 + 0.5 * am_bits[bit_traite-1] + 0.25 * am_bits[bit_traite]);
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
// on dessine 100 échantillons par bit de la trame
|
||
|
|
for (int i = 0; i < samples_per_bit; i++)
|
||
|
|
{
|
||
|
|
float t = (bit_traite * samples_per_bit + i) / (float)samples_per_bit;
|
||
|
|
float y = center_y - sinf(2.0f * M_PI * c_freq * t) * amplitude;
|
||
|
|
|
||
|
|
ImVec2 p(x, y);
|
||
|
|
//if (i != (samples_per_bit -1))
|
||
|
|
// Le dernier raccord peut poser problème dans certains cas
|
||
|
|
// et on ne dessine pas la ligne entre le dernier point du bit précédent
|
||
|
|
// et le premier point du bit suivant. Ceci en M_QAM pour l'instant (pour tester).
|
||
|
|
if (MOD_MASK_TYPE == *p_aType)
|
||
|
|
{
|
||
|
|
if (i != 0)
|
||
|
|
draw_list->AddLine(prev, p, IM_COL32(255,0,0,255), 2.0f);
|
||
|
|
else
|
||
|
|
draw_list->AddLine(p, p, IM_COL32(255,0,0,255), 2.0f);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
draw_list->AddLine(prev, p, IM_COL32(255,0,0,255), 2.0f);
|
||
|
|
|
||
|
|
prev = p;
|
||
|
|
x += dx;
|
||
|
|
}
|
||
|
|
|
||
|
|
// FIXME : d'où viennent ces valeurs 5 et 22 ?
|
||
|
|
draw_list->AddText ( ImVec2(x - samples_per_bit * dx + 5, canvas_pos.y + canvas_size.y - 22),
|
||
|
|
IM_COL32(0,0,255,255),
|
||
|
|
am_bits[bit_traite] ? " 1 " : " 0 "
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
ImGui::Dummy(canvas_size);
|
||
|
|
ImGui::NewLine();
|
||
|
|
ImGui::SeparatorText("Bits");
|
||
|
|
|
||
|
|
drawVToggleButtons(am_bits, getWordSize());
|
||
|
|
|
||
|
|
ImGui::EndChild();
|
||
|
|
|
||
|
|
// ----------------------------- RIGHT : OPTIONS ------------------------
|
||
|
|
ImGui::SameLine();
|
||
|
|
ImGui::BeginChild("Options", ImVec2(CHILD2_WIDTH - 8.0f /* minus the border */, 0), true);
|
||
|
|
|
||
|
|
ImGui::Text("Type de modulation");
|
||
|
|
ImGui::Separator();
|
||
|
|
|
||
|
|
ImGui::RadioButton("OOK " , (int*)&litude_modulation_t, MOD_OOK_TYPE);
|
||
|
|
ImGui::RadioButton("ASK " , (int*)&litude_modulation_t, MOD_ASK_TYPE);
|
||
|
|
ImGui::RadioButton("4-ASK ", (int*)&litude_modulation_t, MOD_MASK_TYPE);
|
||
|
|
|
||
|
|
// --- AJOUT TÉMOIN ---
|
||
|
|
ImGui::Spacing();
|
||
|
|
ImGui::Separator();
|
||
|
|
ImGui::Text("Principe :");
|
||
|
|
ImGui::Spacing();
|
||
|
|
|
||
|
|
ImVec2 ind_size(ImGui::GetContentRegionAvail().x - 10, 50);
|
||
|
|
ImU32 col = IM_COL32(0, 120, 255, 255); // Même bleu que le signal
|
||
|
|
|
||
|
|
switch(amplitude_modulation_t)
|
||
|
|
{
|
||
|
|
case MOD_OOK_TYPE:
|
||
|
|
case MOD_ASK_TYPE:
|
||
|
|
ImGui::Text("1 bit par symbole");
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator("Le bit vaut 1 :", &c_freq, &litude_modulation_t, &samples_per_bit, 1.0f, 0.0f, col, ind_size);
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator ("Le bit vaut 0 :",
|
||
|
|
&c_freq, &litude_modulation_t,
|
||
|
|
&samples_per_bit, ((MOD_ASK_TYPE == amplitude_modulation_t) ? 0.4f : 0.0f),
|
||
|
|
0.0f,
|
||
|
|
col,
|
||
|
|
ind_size
|
||
|
|
);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MOD_MASK_TYPE:
|
||
|
|
ImGui::Text("2 bits par symbole");
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator("Le symbole vaut 11 : ", &c_freq, &litude_modulation_t, &samples_per_bit, 1.0f, 0.0f, col, ind_size);
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator("Le symbole vaut 10 : ", &c_freq, &litude_modulation_t, &samples_per_bit, 0.75f, 0.0f, col, ind_size);
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator("Le symbole vaut 01 : ", &c_freq, &litude_modulation_t, &samples_per_bit, 0.4f, 0.0f, col, ind_size);
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator("Le symbole vaut 00 : ", &c_freq, &litude_modulation_t, &samples_per_bit, 0.15f, 0.0f, col, ind_size);
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
// ------- FIN AJOUT TEMOIN -------------
|
||
|
|
|
||
|
|
|
||
|
|
ImGui::EndChild();
|
||
|
|
|
||
|
|
return EXIT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
short int DigitalModulation::FrequencyDigitalModulation(float * carrier_freq, int * fm_bits, DigitalModulationType * fm_type)
|
||
|
|
{
|
||
|
|
static DigitalModulationType frequency_modulation_t = *fm_type;
|
||
|
|
static float c_freq = *carrier_freq;
|
||
|
|
|
||
|
|
// --------------------- LEFT : SIGNAL -----------------
|
||
|
|
// FIXME : LAYOUT
|
||
|
|
ImGui::BeginChild("Signal2", ImVec2(ImGui::GetContentRegionAvail().x - CHILD2_WIDTH , 0), false);
|
||
|
|
|
||
|
|
// pour 1 bit, 100 échantillons (400 donne de meilleurs résultats en MFSK)
|
||
|
|
static int samples_per_bit = SAMPLES_PER_BIT_MAX; // limite le sous-échantillonnage
|
||
|
|
static float k = 2.0f; // default
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
// affichage bruité au-delà de 4.0f
|
||
|
|
ImGui::SliderFloat("Frequence porteuse ", carrier_freq, 2.0f, 4.0f);
|
||
|
|
#ifdef DEBUG
|
||
|
|
static int k2 = 2;
|
||
|
|
ImGui::SliderInt("Nombre de points par symbole", &samples_per_bit, DEFAULT_SAMPLES_PER_BIT, 500);
|
||
|
|
ImGui::SliderInt("Rapport fréquence modulée / fréquence de base ", &k2, 4, 10);
|
||
|
|
k = (float)k2;
|
||
|
|
#else
|
||
|
|
k = 2.0f;
|
||
|
|
#endif
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
// Surbrillance
|
||
|
|
highlightFrame(fm_bits, getWordSize());
|
||
|
|
|
||
|
|
ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
|
||
|
|
ImVec2 canvas_size(ImGui::GetContentRegionAvail().x, CANVAS_HEIGHT);
|
||
|
|
|
||
|
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||
|
|
draw_list->AddRectFilled
|
||
|
|
(
|
||
|
|
canvas_pos,
|
||
|
|
ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(255,255,255,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
draw_list->AddRect
|
||
|
|
(
|
||
|
|
canvas_pos,
|
||
|
|
ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(0,0,0,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
float center_y = canvas_pos.y + canvas_size.y / 2.0f;
|
||
|
|
float base_amp = 100.0f;
|
||
|
|
float total_samples = getWordSize() * samples_per_bit;
|
||
|
|
float dx = canvas_size.x / total_samples;
|
||
|
|
float x = canvas_pos.x;
|
||
|
|
|
||
|
|
ImVec2 prev(x, center_y);
|
||
|
|
|
||
|
|
for (int bit_traite = 0; bit_traite < getWordSize(); bit_traite++)
|
||
|
|
{
|
||
|
|
draw_list->AddLine
|
||
|
|
(
|
||
|
|
ImVec2(x, canvas_pos.y),
|
||
|
|
ImVec2(x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(0,120,255,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
switch (frequency_modulation_t)
|
||
|
|
{
|
||
|
|
case MOD_FSK_TYPE:
|
||
|
|
c_freq = fm_bits[bit_traite] ? (*carrier_freq) * k : *carrier_freq ;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MOD_MFSK_TYPE:
|
||
|
|
// On doit dessiner la même amplitude pour les bits (0,1), (2,3), (4,5) et (6,7)
|
||
|
|
// => la parité de bit_traite nous donne la réponse
|
||
|
|
if ((bit_traite % 2) == 0) // bit pair => bits 0, 2, 4 ou 6
|
||
|
|
c_freq = (*carrier_freq) * ( 1 + k * (2 * fm_bits[bit_traite] + fm_bits[bit_traite+1]));
|
||
|
|
else // bit impair => bits 1, 3, 5 ou 7
|
||
|
|
c_freq = (*carrier_freq) * ( 1 + k * (2 * fm_bits[bit_traite-1] + fm_bits[bit_traite]));
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < samples_per_bit; i++)
|
||
|
|
{
|
||
|
|
float t = (bit_traite * samples_per_bit + i) / (float)samples_per_bit;
|
||
|
|
float y = center_y - sinf(2.0f * M_PI * c_freq * t) * base_amp;
|
||
|
|
|
||
|
|
ImVec2 p(x, y);
|
||
|
|
draw_list->AddLine(prev, p, IM_COL32(255,0,0,255), 2.0f);
|
||
|
|
prev = p;
|
||
|
|
x += dx;
|
||
|
|
}
|
||
|
|
|
||
|
|
draw_list->AddText ( ImVec2(x - samples_per_bit * dx + 5, canvas_pos.y + canvas_size.y - 22),
|
||
|
|
IM_COL32(0,0,255,255),
|
||
|
|
fm_bits[bit_traite] ? " 1 " : " 0 "
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
ImGui::Dummy(canvas_size);
|
||
|
|
ImGui::NewLine();
|
||
|
|
ImGui::SeparatorText("Bits");
|
||
|
|
|
||
|
|
drawVToggleButtons(fm_bits, getWordSize());
|
||
|
|
|
||
|
|
ImGui::EndChild();
|
||
|
|
|
||
|
|
// ----------------------------- RIGHT : OPTIONS ------------------------
|
||
|
|
ImGui::SameLine();
|
||
|
|
ImGui::BeginChild("Options", ImVec2(CHILD2_WIDTH - 8.0f, 0), true);
|
||
|
|
|
||
|
|
ImGui::Text("Type de modulation");
|
||
|
|
ImGui::Separator();
|
||
|
|
|
||
|
|
ImGui::RadioButton("FSK " , (int*)&frequency_modulation_t, MOD_FSK_TYPE);
|
||
|
|
ImGui::RadioButton("4-FSK " , (int*)&frequency_modulation_t, MOD_MFSK_TYPE);
|
||
|
|
|
||
|
|
// --- AJOUT TÉMOIN ---
|
||
|
|
ImGui::Spacing();
|
||
|
|
ImGui::Separator();
|
||
|
|
ImGui::Text("Principe :");
|
||
|
|
ImGui::Spacing();
|
||
|
|
|
||
|
|
ImVec2 ind_size(ImGui::GetContentRegionAvail().x - 10, 50);
|
||
|
|
ImU32 col = IM_COL32(0, 120, 255, 255); // Même bleu que le signal
|
||
|
|
|
||
|
|
switch(frequency_modulation_t)
|
||
|
|
{
|
||
|
|
case MOD_FSK_TYPE:
|
||
|
|
ImGui::Text("1 bit par symbole");
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
c_freq = (*carrier_freq) * k;
|
||
|
|
|
||
|
|
DrawIndicator("Le bit vaut 1 :", &c_freq, &frequency_modulation_t, &samples_per_bit, 1.0f, 0.0f, col, ind_size);
|
||
|
|
|
||
|
|
c_freq = *carrier_freq;
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator ("Le bit vaut 0 :",
|
||
|
|
&c_freq, &frequency_modulation_t,
|
||
|
|
&samples_per_bit,
|
||
|
|
1.0f, // amplitude
|
||
|
|
0.0f, // phase
|
||
|
|
col,
|
||
|
|
ind_size
|
||
|
|
);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MOD_MFSK_TYPE:
|
||
|
|
ImGui::Text("2 bits par symbole");
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
c_freq = (*carrier_freq) * 4.0f * k;
|
||
|
|
DrawIndicator("Le symbole vaut 11 : ", &c_freq, &frequency_modulation_t, &samples_per_bit, 1.0f, 0.0f, col, ind_size);
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
c_freq = (*carrier_freq) * 2.0f * k;
|
||
|
|
DrawIndicator("Le symbole vaut 10 : ", &c_freq, &frequency_modulation_t, &samples_per_bit, 1.0f, 0.0f, col, ind_size);
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
c_freq = (*carrier_freq) * k;
|
||
|
|
DrawIndicator("Le symbole vaut 01 : ", &c_freq, &frequency_modulation_t, &samples_per_bit, 1.0f, 0.0f, col, ind_size);
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
c_freq = (*carrier_freq) ;
|
||
|
|
DrawIndicator("Le symbole vaut 00 : ", &c_freq, &frequency_modulation_t, &samples_per_bit, 1.0f, 0.0f, col, ind_size);
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
// ------- FIN AJOUT TEMOIN -------------
|
||
|
|
|
||
|
|
|
||
|
|
ImGui::EndChild();
|
||
|
|
|
||
|
|
return EXIT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
short int DigitalModulation::PhaseDigitalModulation(float * carrier_freq, int * pm_bits, DigitalModulationType * pm_type)
|
||
|
|
{
|
||
|
|
static DigitalModulationType phase_modulation_t = *pm_type;
|
||
|
|
|
||
|
|
// --------------------- LEFT : SIGNAL -----------------
|
||
|
|
ImGui::BeginChild("Signal2", ImVec2(ImGui::GetContentRegionAvail().x - CHILD2_WIDTH , 0), false);
|
||
|
|
|
||
|
|
static int samples_per_bit = DEFAULT_SAMPLES_PER_BIT;
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
ImGui::SliderFloat("Frequence porteuse du signal", carrier_freq, 2.0f, 10.0f);
|
||
|
|
#if defined(DEBUG)
|
||
|
|
ImGui::SliderInt("Nombre de points par symbole", &samples_per_bit, DEFAULT_SAMPLES_PER_BIT, 500);
|
||
|
|
#endif
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
// Surbrillance
|
||
|
|
highlightFrame(pm_bits, getWordSize());
|
||
|
|
|
||
|
|
ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
|
||
|
|
ImVec2 canvas_size(ImGui::GetContentRegionAvail().x, CANVAS_HEIGHT);
|
||
|
|
|
||
|
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||
|
|
draw_list->AddRectFilled
|
||
|
|
(
|
||
|
|
canvas_pos,
|
||
|
|
ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(255,255,255,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
draw_list->AddRect
|
||
|
|
(
|
||
|
|
canvas_pos,
|
||
|
|
ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(0,0,0,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
float center_y = canvas_pos.y + canvas_size.y / 2.0f;
|
||
|
|
float base_amp = 100.0f;
|
||
|
|
float total_samples = getWordSize() * samples_per_bit;
|
||
|
|
float dx = canvas_size.x / total_samples;
|
||
|
|
float x = canvas_pos.x;
|
||
|
|
|
||
|
|
ImVec2 prev(x, center_y);
|
||
|
|
|
||
|
|
float phi = 0.0f;
|
||
|
|
float delta_phi = 0.0f;
|
||
|
|
|
||
|
|
for (int bit_traite = 0; bit_traite < getWordSize(); bit_traite++)
|
||
|
|
{
|
||
|
|
draw_list->AddLine
|
||
|
|
(
|
||
|
|
ImVec2(x, canvas_pos.y),
|
||
|
|
ImVec2(x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(0,120,255,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
switch (phase_modulation_t)
|
||
|
|
{
|
||
|
|
case MOD_BPSK_TYPE:
|
||
|
|
phi = pm_bits[bit_traite] ? 0.0f : M_PI;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MOD_DPSK_TYPE:
|
||
|
|
if (bit_traite < 1)
|
||
|
|
phi = pm_bits[bit_traite] ? 0.0f : M_PI;
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if ((!pm_bits[bit_traite-1] && pm_bits[bit_traite]) ||
|
||
|
|
((pm_bits[bit_traite-1]) && (pm_bits[bit_traite])))
|
||
|
|
delta_phi = M_PI;
|
||
|
|
else
|
||
|
|
delta_phi = 0.0f;
|
||
|
|
}
|
||
|
|
phi += delta_phi;
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < samples_per_bit; i++)
|
||
|
|
{
|
||
|
|
float t = (bit_traite * samples_per_bit + i) / (float)samples_per_bit;
|
||
|
|
float y = center_y - sinf(2.0f * M_PI * (*carrier_freq) * t + phi) * base_amp;
|
||
|
|
|
||
|
|
ImVec2 p(x, y);
|
||
|
|
draw_list->AddLine(prev, p, IM_COL32(255,0,0,255), 2.0f);
|
||
|
|
prev = p;
|
||
|
|
x += dx;
|
||
|
|
}
|
||
|
|
|
||
|
|
draw_list->AddText ( ImVec2(x - samples_per_bit * dx + 5, canvas_pos.y + canvas_size.y - 22),
|
||
|
|
IM_COL32(0,0,255,255),
|
||
|
|
pm_bits[bit_traite] ? " 1 " : " 0 "
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
ImGui::Dummy(canvas_size);
|
||
|
|
ImGui::NewLine();
|
||
|
|
ImGui::SeparatorText("Bits");
|
||
|
|
drawVToggleButtons(pm_bits, getWordSize());
|
||
|
|
ImGui::EndChild();
|
||
|
|
|
||
|
|
// ----------------------------- RIGHT : OPTIONS ------------------------
|
||
|
|
ImGui::SameLine();
|
||
|
|
ImGui::BeginChild("Options", ImVec2(CHILD2_WIDTH - 8.0f, 0), true);
|
||
|
|
|
||
|
|
ImGui::Text("Type de modulation");
|
||
|
|
ImGui::Separator();
|
||
|
|
|
||
|
|
ImGui::RadioButton("BPSK " , (int*)&phase_modulation_t, MOD_BPSK_TYPE);
|
||
|
|
ImGui::RadioButton("DPSK " , (int*)&phase_modulation_t, MOD_DPSK_TYPE);
|
||
|
|
|
||
|
|
// --- AJOUT TÉMOIN ---
|
||
|
|
ImGui::Spacing();
|
||
|
|
ImGui::Separator();
|
||
|
|
|
||
|
|
if (MOD_DPSK_TYPE != phase_modulation_t)
|
||
|
|
ImGui::Text("Principe :");
|
||
|
|
|
||
|
|
ImGui::Spacing();
|
||
|
|
|
||
|
|
ImVec2 ind_size(ImGui::GetContentRegionAvail().x - 10, 50);
|
||
|
|
ImU32 col = IM_COL32(0, 120, 255, 255); // Même bleu que le signal
|
||
|
|
|
||
|
|
switch(phase_modulation_t)
|
||
|
|
{
|
||
|
|
case MOD_BPSK_TYPE:
|
||
|
|
ImGui::Text("1 bit par symbole");
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
DrawIndicator("Le bit vaut 1 :",
|
||
|
|
carrier_freq,
|
||
|
|
&phase_modulation_t,
|
||
|
|
&samples_per_bit,
|
||
|
|
1.0f, // amplitude
|
||
|
|
0.0f, // phase
|
||
|
|
col,
|
||
|
|
ind_size);
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator ("Le bit vaut 0 :",
|
||
|
|
carrier_freq, &phase_modulation_t,
|
||
|
|
&samples_per_bit,
|
||
|
|
1.0f, // amplitude
|
||
|
|
M_PI, // phase
|
||
|
|
col,
|
||
|
|
ind_size
|
||
|
|
);
|
||
|
|
break;
|
||
|
|
case MOD_DPSK_TYPE:
|
||
|
|
ImGui::Text("1 bits par symbole");
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
// ------- FIN AJOUT TEMOIN -------------
|
||
|
|
|
||
|
|
ImGui::EndChild();
|
||
|
|
|
||
|
|
|
||
|
|
return EXIT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
short int DigitalModulation::M_QAM_DigitalModulation(float * carrier_freq, int * qam_bits, DigitalModulationType * qam_type)
|
||
|
|
{
|
||
|
|
// TODO : améliorer cette partie
|
||
|
|
static DigitalModulationType qam_modulation_t = *qam_type;
|
||
|
|
static float c_freq = *carrier_freq;
|
||
|
|
|
||
|
|
// --------------------- LEFT : SIGNAL -----------------
|
||
|
|
ImGui::BeginChild("Signal", ImVec2(ImGui::GetContentRegionAvail().x - CHILD2_WIDTH, 0), false);
|
||
|
|
|
||
|
|
// pour 1 bit, 100 échantillons (400 pour la modulation de fréquence pour fporteuse max)
|
||
|
|
static int samples_per_bit = SAMPLES_PER_BIT_MAX;
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
ImGui::SliderFloat("Frequence porteuse ", &c_freq, 2.0f, 10.0f);
|
||
|
|
#if defined(DEBUG)
|
||
|
|
ImGui::SliderInt("Nombre de points par symbole", &samples_per_bit, DEFAULT_SAMPLES_PER_BIT, 500);
|
||
|
|
#endif
|
||
|
|
ImGui::NewLine();
|
||
|
|
|
||
|
|
// Surbrillance de la trame affichée
|
||
|
|
highlightFrame(qam_bits, getWordSize());
|
||
|
|
|
||
|
|
// position du curseur + dimensions du canvas.
|
||
|
|
// canvas_pos contient les coordonnées du curseur (marque l'endroit d'où l'on dessine à ce point du programme)
|
||
|
|
ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
|
||
|
|
|
||
|
|
// Dimensions du cadre dans lequel on dessine la sinusoïde
|
||
|
|
ImVec2 canvas_size(ImGui::GetContentRegionAvail().x, CANVAS_HEIGHT);
|
||
|
|
|
||
|
|
// ce qui va être dessiné
|
||
|
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||
|
|
|
||
|
|
// On dessine un fond blanc
|
||
|
|
draw_list->AddRectFilled
|
||
|
|
(
|
||
|
|
canvas_pos,
|
||
|
|
ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(255,255,255,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
// on ajoute par dessus un tour noir
|
||
|
|
draw_list->AddRect
|
||
|
|
(
|
||
|
|
canvas_pos,
|
||
|
|
ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(0,0,0,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
// calcul des coordonnées du centre de la frame
|
||
|
|
float center_y = canvas_pos.y + canvas_size.y / 2.0f;
|
||
|
|
|
||
|
|
// amplitude de la sinusoïde de base
|
||
|
|
float base_amp = 100.0f;
|
||
|
|
float total_samples = getWordSize() * samples_per_bit;
|
||
|
|
float dx = canvas_size.x / total_samples;
|
||
|
|
float x = canvas_pos.x;
|
||
|
|
|
||
|
|
ImVec2 prev(x, center_y);
|
||
|
|
|
||
|
|
for (int bit_traite = 0; bit_traite < getWordSize(); bit_traite++)
|
||
|
|
{
|
||
|
|
draw_list->AddLine
|
||
|
|
(
|
||
|
|
ImVec2(x, canvas_pos.y),
|
||
|
|
ImVec2(x, canvas_pos.y + canvas_size.y),
|
||
|
|
IM_COL32(0,120,255,255)
|
||
|
|
);
|
||
|
|
|
||
|
|
float amplitude = 0.0f;
|
||
|
|
|
||
|
|
|
||
|
|
float coeff_sin = 1.0f; // terme devant le sinus (première fréquence porteuse)
|
||
|
|
float coeff_cos = 1.0f; // terme devant le cosinus (pour la seconde porteuse en quadrature)
|
||
|
|
// Pour la modulation M-QAM, on se place dans le plan complexe.
|
||
|
|
// Cas de la constellation 4-QAM (cas particulier, où elle est identique à la constellation 4-PSK)
|
||
|
|
/*
|
||
|
|
^ sin
|
||
|
|
|
|
||
|
|
01 | 11
|
||
|
|
+ | +
|
||
|
|
|
|
||
|
|
---------------------> cos
|
||
|
|
|
|
||
|
|
+ | +
|
||
|
|
00 | 10
|
||
|
|
|
|
||
|
|
|
||
|
|
*/
|
||
|
|
// /!\ LIRE d'abord sin, puis cos ci-dessous !!
|
||
|
|
// 00 -> (-1;-1) / 01 -> (1;-1) / 10 -> (-1;1) / 11 -> (1;1)
|
||
|
|
// ce qui donne les tableaux de coefficients suivants :
|
||
|
|
|
||
|
|
// tableau des valeurs de sinus
|
||
|
|
const float tab_sinus[4] = { /* 11 */ 1.0f, /* 01 */ 1.0f, /* 10 */-1.0f, /* 00 */-1.0f};
|
||
|
|
|
||
|
|
// tableau des valeurs de cosinus
|
||
|
|
const float tab_cosinus[4] = { /* 11 */ 1.0f ,/* 01 */-1.0f, /* 10 */ 1.0f, /* 00 */-1.0f};
|
||
|
|
|
||
|
|
// 16-QAM
|
||
|
|
const float tab_sin16[16] = { -3.0f, -1.0f, 3.0f, 1.0f,-3.0f,-1.0f, 3.0f, 1.0f,-3.0f,-1.0f, 3.0f, 1.0f,-3.0f,-1.0f, 3.0f, 1.0f };
|
||
|
|
const float tab_cos16[16] = { -3.0f, -3.0f,-3.0f,-3.0f,-1.0f,-1.0f,-1.0f,-1.0f, 3.0f, 3.0f, 3.0f, 3.0f, 1.0f, 1.0f, 1.0, 1.0f };
|
||
|
|
|
||
|
|
switch (qam_modulation_t)
|
||
|
|
{
|
||
|
|
case MOD_4_QAM_TYPE:
|
||
|
|
// Contraintes :
|
||
|
|
// En MODULATION M-QAM : tous les points sont équi-distants (optimisation du rapport S/(S+B))
|
||
|
|
// - on doit dessiner le même signal pour les bits (0,1), (2,3), (4,5) et (6,7)
|
||
|
|
// - si le bit testé est pair, alors il s'agit du bit 0, 2, 4 ou 6
|
||
|
|
// et il faut tester la valeur du mot binaire 2 *bit traite + bit-traite+1
|
||
|
|
// - si le bit testé est impair, il s'agit du bit 1, 3, 5 ou 7
|
||
|
|
// et il faut tester la valeur du mot 2 *bit_traite -1 + bit-traite
|
||
|
|
// - ce cas simple nous impose de diviser aussi l'amplitude de base par racine de 2
|
||
|
|
// (sinon la sinusoïde ne tient pas dans le canvas)
|
||
|
|
//
|
||
|
|
// ce premier calcul nous donne les coefficients devant le sinus ou le cosinus
|
||
|
|
// De plus n doit dessiner le même signal pour les bits (0,1), (2,3), (4,5) et (6,7)
|
||
|
|
// => la parité de bit_traite nous donne les coefficients
|
||
|
|
|
||
|
|
// Ensuite, Le calcul des coefficients est lié à la valeur des deux bits considérés
|
||
|
|
// L'expression du mot binaire sur 2 bits, nous donne les coefficients
|
||
|
|
// 4 cas sont possibles : 00, 01, 10 et 11, cf la constellation + haut.
|
||
|
|
|
||
|
|
amplitude = 0.707f * base_amp;
|
||
|
|
|
||
|
|
if ((bit_traite % 2) == 0) // bit pair => bits 0, 2, 4 ou 6
|
||
|
|
{
|
||
|
|
coeff_sin = tab_sinus[2*qam_bits[bit_traite]+qam_bits[bit_traite+1]];
|
||
|
|
coeff_cos = tab_cosinus[2*qam_bits[bit_traite]+qam_bits[bit_traite+1]];
|
||
|
|
}
|
||
|
|
else // bit impair => bits 1, 3, 5 ou 7
|
||
|
|
{
|
||
|
|
coeff_sin = tab_sinus[2*qam_bits[bit_traite-1]+qam_bits[bit_traite]];
|
||
|
|
coeff_cos = tab_cosinus[2*qam_bits[bit_traite-1]+qam_bits[bit_traite]];
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MOD_16_QAM_TYPE:
|
||
|
|
// On code cette fois chaque symbole sur 4 bits
|
||
|
|
// La constellation est la suivante
|
||
|
|
// (+ toutes les permutations circulaire et symétries possibles !!) :
|
||
|
|
//
|
||
|
|
// 0010 0110 | 1110 1010
|
||
|
|
// |
|
||
|
|
// 0011 0111 | 1111 1011
|
||
|
|
// ___-3___-1 _|__ 1____3__
|
||
|
|
// 0001 0101 | 1101 1001
|
||
|
|
// |
|
||
|
|
// 0000 0100 | 1100 1000
|
||
|
|
// |
|
||
|
|
// Horizontalement et verticalement, 4 valeurs possibles:
|
||
|
|
// -3 -1, 1 et 3 pour les 2 sinusoïdes, ce qui donne les 16 cas
|
||
|
|
// 16 coefficients pour cos et sin :
|
||
|
|
// Exemple : on codera 0011 (MSB = 0, LSB = 1 ici), avec les amplitudes -3 pour le cos et +1 pour le sin
|
||
|
|
// etc
|
||
|
|
// De plus il faudra tester le bit traité module 4
|
||
|
|
|
||
|
|
// On normalise l'amplitude : la plus grande pouvant valoir 3 x 1.414 ~ 4.24
|
||
|
|
amplitude = base_amp/4.24f;
|
||
|
|
|
||
|
|
if ((bit_traite % 4 ) == 0) // bit 0 modulo 4 (0,4,8,12,16 ...)
|
||
|
|
{
|
||
|
|
coeff_sin = tab_sin16[8*qam_bits[bit_traite]+4*qam_bits[bit_traite+1]+2*qam_bits[bit_traite+2] + qam_bits[bit_traite+3]];
|
||
|
|
coeff_cos = tab_cos16[8*qam_bits[bit_traite]+4*qam_bits[bit_traite+1]+2*qam_bits[bit_traite+2] + qam_bits[bit_traite+3]];
|
||
|
|
}
|
||
|
|
else if ((bit_traite % 4 ) == 1) // bit 1 modulo 4 (1,5,9,13,17 ...)
|
||
|
|
{
|
||
|
|
coeff_sin = tab_sin16[8*qam_bits[bit_traite-1]+4*qam_bits[bit_traite] + 2*qam_bits[bit_traite+1] + qam_bits[bit_traite+2]];
|
||
|
|
coeff_cos = tab_cos16[8*qam_bits[bit_traite-1]+4*qam_bits[bit_traite] + 2*qam_bits[bit_traite+1] + qam_bits[bit_traite+2]];
|
||
|
|
}
|
||
|
|
else if ((bit_traite % 4 ) == 2) // bit 2 modulo 4 (2,6,10,14,18 ...)
|
||
|
|
{
|
||
|
|
coeff_sin = tab_sin16[8*qam_bits[bit_traite-2]+4*qam_bits[bit_traite-1]+2*qam_bits[bit_traite] + qam_bits[bit_traite+1]];
|
||
|
|
coeff_cos = tab_cos16[8*qam_bits[bit_traite-2]+4*qam_bits[bit_traite-1]+2*qam_bits[bit_traite] + qam_bits[bit_traite+1]];
|
||
|
|
}
|
||
|
|
else if ((bit_traite % 4 ) == 3) // bit 3 [modulo 4] (3,7,11,15 ...)
|
||
|
|
{
|
||
|
|
coeff_sin = tab_sin16[8*qam_bits[bit_traite-3]+4*qam_bits[bit_traite-2]+2*qam_bits[bit_traite-1]+ qam_bits[bit_traite]];
|
||
|
|
coeff_cos = tab_cos16[8*qam_bits[bit_traite-3]+4*qam_bits[bit_traite-2]+2*qam_bits[bit_traite-1]+ qam_bits[bit_traite]];
|
||
|
|
}
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
// on dessine 100 échantillons par bit de la trame
|
||
|
|
for (int i = 0; i < samples_per_bit; i++)
|
||
|
|
{
|
||
|
|
float t = (bit_traite * samples_per_bit + i) / (float)samples_per_bit;
|
||
|
|
float y = center_y - (coeff_sin * sinf(2.0f * M_PI * c_freq * t) + coeff_cos * cosf(2.0f * M_PI * c_freq * t)) * amplitude;
|
||
|
|
|
||
|
|
ImVec2 p(x, y);
|
||
|
|
//if (i != (samples_per_bit -1))
|
||
|
|
// Le dernier raccord peut poser problème dans certains cas
|
||
|
|
// et on ne dessine pas la ligne entre le dernier point du bit précédent
|
||
|
|
// et le premier point du bit suivant. Ceci en M_QAM pour l'instant (pour tester).
|
||
|
|
if (MOD_M_QAM_TYPE == *qam_type)
|
||
|
|
{
|
||
|
|
if (i != 0)
|
||
|
|
draw_list->AddLine(prev, p, IM_COL32(255,0,0,255), 2.0f);
|
||
|
|
else
|
||
|
|
draw_list->AddLine(p, p, IM_COL32(255,0,0,255), 2.0f);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
draw_list->AddLine(prev, p, IM_COL32(255,0,0,255), 2.0f);
|
||
|
|
|
||
|
|
prev = p;
|
||
|
|
x += dx;
|
||
|
|
}
|
||
|
|
|
||
|
|
// FIXME : d'où viennent ces valeurs 5 et 22 ?
|
||
|
|
draw_list->AddText ( ImVec2(x - samples_per_bit * dx + 5, canvas_pos.y + canvas_size.y - 22),
|
||
|
|
IM_COL32(0,0,255,255),
|
||
|
|
qam_bits[bit_traite] ? " 1 " : " 0 "
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
ImGui::Dummy(canvas_size);
|
||
|
|
ImGui::NewLine();
|
||
|
|
ImGui::SeparatorText("Bits");
|
||
|
|
|
||
|
|
drawVToggleButtons(qam_bits, getWordSize());
|
||
|
|
|
||
|
|
ImGui::EndChild();
|
||
|
|
|
||
|
|
// ----------------------------- RIGHT : OPTIONS ------------------------
|
||
|
|
ImGui::SameLine();
|
||
|
|
ImGui::BeginChild("Options", ImVec2(CHILD2_WIDTH - 8.0f /* minus the border */, 0), true);
|
||
|
|
|
||
|
|
ImGui::Text("Type de modulation");
|
||
|
|
ImGui::Separator();
|
||
|
|
|
||
|
|
ImGui::RadioButton("4-QAM (= 4-PSK)" , (int*)&qam_modulation_t, MOD_4_QAM_TYPE);
|
||
|
|
ImGui::RadioButton("16-QAM " , (int*)&qam_modulation_t, MOD_16_QAM_TYPE);
|
||
|
|
|
||
|
|
// --- AJOUT TÉMOIN ---
|
||
|
|
ImGui::Spacing();
|
||
|
|
ImGui::Separator();
|
||
|
|
ImGui::Text("Principe :");
|
||
|
|
ImGui::Spacing();
|
||
|
|
|
||
|
|
ImVec2 ind_size(ImGui::GetContentRegionAvail().x - 10, 50);
|
||
|
|
ImU32 col = IM_COL32(0, 120, 255, 255); // Même bleu que le signal
|
||
|
|
|
||
|
|
switch(qam_modulation_t)
|
||
|
|
{
|
||
|
|
case MOD_4_QAM_TYPE:
|
||
|
|
ImGui::Text("2 bits par symbole");
|
||
|
|
ImGui::NewLine();
|
||
|
|
// Use 4-QAM rules
|
||
|
|
DrawIndicator("Le symbole vaut 11 : ", &c_freq, &qam_modulation_t, &samples_per_bit, 1.0f, -3.0f * M_PI/4.0f, col, ind_size);
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator("Le symbole vaut 10 : ", &c_freq, &qam_modulation_t, &samples_per_bit, 1.0f, 3.0f * M_PI/4.0f, col, ind_size);
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator("Le symbole vaut 01 : ", &c_freq, &qam_modulation_t, &samples_per_bit, 1.0f, -M_PI/4.0f, col, ind_size);
|
||
|
|
|
||
|
|
ImGui::NewLine();
|
||
|
|
DrawIndicator("Le symbole vaut 00 : ", &c_freq, &qam_modulation_t, &samples_per_bit, 1.0f, M_PI/4.0f, col, ind_size);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MOD_16_QAM_TYPE:
|
||
|
|
ImGui::Text("4 bits par symbole");
|
||
|
|
ImGui::NewLine();
|
||
|
|
ImGui::Text("Constellation 16-QAM : ");
|
||
|
|
LoadTextureFromFile("../images/Constellation_modulation_numerique_16_QAM.jpg",
|
||
|
|
&my_image_texture,
|
||
|
|
&my_image_width,
|
||
|
|
&my_image_height);
|
||
|
|
ImGui::Image((ImTextureID)(intptr_t)my_image_texture, ImVec2((float)ImGui::GetWindowSize().x - 18.0f, (float)ImGui::GetWindowSize().x - 18.0f));
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
// ------- FIN AJOUT TEMOIN -------------
|
||
|
|
|
||
|
|
|
||
|
|
ImGui::EndChild();
|
||
|
|
|
||
|
|
return EXIT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
void DigitalModulation::setDigitalModulationType(TAB_Name aTab, DigitalModulationType aType)
|
||
|
|
{
|
||
|
|
switch (aTab)
|
||
|
|
{
|
||
|
|
case Amplitude_TAB:
|
||
|
|
md_AM_DigitalModulation_t = aType;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case Frequency_TAB:
|
||
|
|
md_FM_DigitalModulation_t = aType;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case Phase_TAB:
|
||
|
|
md_PM_DigitalModulation_t = aType;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case M_QAM_TAB:
|
||
|
|
md_M_QAM_DigitalModulation_t = aType;
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|