/*

 ____  ____  __  __  _____  ____  __  __  __   
(  _ \( ___)(  \/  )(  _  )(  _ \(  )(  )(  )  
 )(_) ))__)  )    (  )(_)(  )(_) ))(__)(  )(__ 
(____/(____)(_/\/\_)(_____)(____/(______)(____)


AUTEURS	    : Aymeric & Samira
DATE        : 10/06/2003
FICHIER     : demodul.cpp
DESCRIPTION : demodule un signal
	      donnees prises dans signal.dat

*/

#include <iostream.h>
#include <fstream.h>
#include <math.h>
#include <stdlib.h>

/* ---------------------------------------------- */
/* ------ declaration des parametres connus ----- */
/* ---------------------------------------------- */

// taille maximale d'un message
#define LONGUEUR 256
// rapidite de modulation (en bauds)
const int rapidite=75;
// frequence d'echantillonnage (en Hz)
const int Fe=16000;
// frequence de modulation d'un bit 0 (en Hz)
const float f0=390;
// frequence de modulation d'un bit 1 (en Hz)
const float f1=450;
// amplitude (en V)
const float amplitude=20;
// fanion de debut de trame = 10101011
const int code_depart[8]={1,1,0,1,0,1,0,1};
// nombre de points par bit
const int nbpoint=Fe/rapidite+1;


/* ---------------------------------------------- */
/* ---------- declaration des fonctions --------- */
/* ---------------------------------------------- */

bool debut_message(short*,int);
int compare (short*,int,int);
int diff(short*,int,float,int);
int bin2dec(int[]);
int cherchetaille(short*,int);


/* ---------------------------------------------- */
/* --------- fonction main du programme --------- */
/* ---------------------------------------------- */

int main(void)
{
	const int taille_init=8*nbpoint;
	// tab_init represente les 8 bits contenant la taille du message envoye
	short tab_init[taille_init];
	short *tab;
	short *tmp_tab;
	tmp_tab = new short[taille_init*LONGUEUR];
	
	// ouverture du flux vers le fichier en lecture
	fstream f("signal.dat",ios::in);

	// on se place au debut du fichier
	f.seekp(ios::beg);

	// on copie chaque ligne du fichier dans un tableau
	if (!f)
	{
		cout << "\nErreur : signal.dat n'existe pas !" << endl;
		return(0);
	}
	
	int indice=0;
	int ind=0;
	int taille;
	int position=1;
	bool ok=true;
	
	while (!f.eof())
	{
	
		// tant qu'on a pas trouve le fanion de debut de message, on stocke les informations
		// dans tmp_tab
		if ( (ok == true) && (debut_message(tmp_tab,ind) == false) )
			f >> tmp_tab[ind++];
	
		// on rentre dans le 'else' lorsqu'on a trouve le fanion de debut
		else
		{
			ok=false;
			
			// on enregistre dans le tableau tab_init l'octet contenant la taille du message
			if (indice < taille_init)
				f >> tab_init[indice++];
			else if (indice == taille_init)
			{
				taille=cherchetaille(tab_init,taille_init);
				// on recupere la taille du message
				tab=new short[taille*nbpoint*8];
				f >> tab[0];
				indice++;
			}
			// on rentre le message dans le tableau tab
			else
				f >> tab[position++];
		}
	}

	f.close();
	
	cout << endl << (ind+indice+position-2)/214 << " bits detectes dont " << taille*8 << " pour le message" << endl;
	
	int t=0;
	int resultat[8];
	
	cout << endl << "Message recu : \n";
	for (int i=0; i < taille; i++)
	{
		for (int j=0; j < 8; j++)
		{
			// la fonction compare retourne la valeur du bit correspondant au signal
			resultat[j]=compare(tab,t,position);
			// on se decale du nombre de points par bit pour acceder au bit suivant
			t+=nbpoint;
		}
		// on affiche le message trouve
		cout << (char)bin2dec(resultat);
	}
	
	cout << endl;
	
	delete []tmp_tab;
	delete []tab;
	
	return(0);
}


/* ---------------------------------------------- */
/* -------------- fonctions utiles -------------- */
/* ---------------------------------------------- */

// cette fonction retourne true si elle trouve le fanion de debut
bool debut_message(short *tab, int indice)
{
	if ( (indice % nbpoint == 0) && (indice / nbpoint > 7) )
	{
		int j=0;
		int bit;
		for (int i=indice-8*nbpoint; i < indice; i+=nbpoint)
		{
			bit=compare(tab,i,indice);
			if (bit != code_depart[j++]) return(false);
		}
		return(true);
	}
	else return(false);
}

// cette fonction retourne la taille du message trouve dans les 8 bits correspondant
int cherchetaille(short *tab_init, int taille)
{
	int resultat[8];
	int t=0;
	for (int k=0; k < 8; k++)
	{
		resultat[k]=compare(tab_init,t,taille);
		t+=nbpoint;
	}
	
	return(bin2dec(resultat));
}

// cette fonction retourne la valeur du bit trouve selon le signal
int compare (short *tableau, int curseur, int max)
{
	int i;
	int resultat_f0=0,resultat_f1=0;
	
	for (i=curseur; i < (int)(f0/rapidite)+curseur; i++)
		resultat_f0+=diff(tableau,max,f0,i);
	for (i=curseur; i < (int)(f1/rapidite)+curseur; i++)
		resultat_f1+=diff(tableau,max,f1,i);

	resultat_f0/=(int)f0/rapidite;
	resultat_f1/=(int)f1/rapidite;
	
	if ( resultat_f0 <= resultat_f1 ) return(0);
	else return(1);
}

// cette fonction retourne la valeur absolue de la difference entres 2 points du signal
int diff(short *tab, int max, float frequence, int t)
{
	if ( (t+(Fe/frequence)) <= max )
		return( abs( tab[t]-tab[t+(Fe/(int)frequence)]) );
	else return(0);
}

// cette fonction retourne le code ascii d'un caractere code en binaire
int bin2dec(int *resultat)
{
	int retour=0;
	int coef=1;
	for (int i=0; i < 8; i++)
	{
		retour+=resultat[i]*coef;
		coef*=2;
	}
	return(retour);
}

