/*-------------------------------------------------------------------------- 
FICHIER: Lit_serie_ecrit_parallele.cpp 
AUTEUR: Isabelle Castonguay 

DATE:    15/06/98 
(Dernières modifications: 7/08/98) 

DESCRIPTION: Programme qui lit un caractère à partir du port série et envoie 
            un signal équivalent au port parallèle. 
            (Application console) 

REMARQUES: Ce programme a été adapté pour les codes controlant le robot 
           uqat.  Les modifications ont été apportées par Sébastien Carle 
---------------------------------------------------------------------------*/ 



#include <iostream.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <conio.h> 
#include <string.h> 
#include <iomanip.h>
#include <windows.h>
//#include <Mmsystem.h>2

#include <commctrl.h>
//#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) 
//#pragma comment( linker, "Winmm.lib" ) 
//#include <winuser.h>
  

// Variable globale pour les ports de communications 
                   //identificateurs de port série 
#define LANCER_APP 1
#define ENVOI_MESSAGE 2
#define ENVOI_WM_KEYDOWN 3
#define ENVOI_WM_CTRL 4
#define ENVOI_WM_ALT 5
#define SHOW_WINDOW 6
#define STARTCHAR 0x33
#define STOPCHAR 0x66



struct IRCODE
{
	int T; //Taille du code (nbr octet)
	UINT Action; // Type d'action
	DWORD wParam; //Parametre sup	
	DWORD lParam; //Parametre sup
	UINT Latency;//Temps d'attente entre les actions
	char* Fonction;
	byte* Code;	 //Pointeur vers le code	
	char* AppName; //Application visée
	
};
IRCODE * pCodes_IR;
int TailleCode;
DWORD Latency;


IRCODE * ChargerTableDesCodes(void)
{
	char Ligne[128];
	int i,j,k;
	char Fonction[32];
	IRCODE * pCode;
//	HANDLE Fich;
//	Fich=CreateFile("Table.dat",GENERIC_READ,FILE_SHARE_READ,,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL)
//		ReadFile(Fich,
	FILE* Fich;
	if(	(Fich=fopen("table.dat", "r")) == NULL)

		return NULL;
	k=0;
	do{
		fgets(Ligne,sizeof(Ligne),Fich); //Taille de tableau
		k++;
	}
	while (!feof(Fich));
	fclose(Fich);
	if(	(Fich=fopen("table.dat", "r")) == NULL)

		return NULL;
	

		TailleCode=k/4;

		pCode=(IRCODE *) malloc(TailleCode*sizeof(IRCODE));

		for (i=0;i<=TailleCode-1;i++)
		{
			fgets(Ligne,sizeof(Ligne),Fich);
			
		Ligne[strlen(Ligne)-1]=NULL;

			sscanf(Ligne,"%d\t%d\t%d\t%d\t%d\t%s",&pCode->T,&pCode->Action,&pCode->wParam,&pCode->lParam,&pCode->Latency,Fonction);
			pCode->Fonction=(char*) malloc(strlen(Fonction)+1*sizeof(char));
			strcpy(pCode->Fonction,Fonction);
			pCode->Code=(byte*) malloc(pCode->T*sizeof(char));
			fgets(Ligne,sizeof(Ligne),Fich);
			
		Ligne[strlen(Ligne)-1]=NULL;
			for(j=0;j<=(pCode->T)-1;j++)
			{
				sscanf(&Ligne[2*j],"%02x",(pCode->Code+j));
			}
			fgets(Ligne,sizeof(Ligne),Fich);
			if (Ligne[strlen(Ligne)-1]=='\n')
		Ligne[strlen(Ligne)-1]=NULL;
			pCode->AppName=(char*) malloc(strlen(Ligne)*sizeof(char)+1);			
			for(j=0;j<=(int) strlen(Ligne);j++)
			{
				*(pCode->AppName+j)=(char) Ligne[j];
			}
			fgets(Ligne,sizeof(Ligne),Fich);//Ligne Vide
			pCode++;

		}
fclose(Fich);

		return pCode-i;
}

EcrireDonnes(byte* CodeT,int Taille)
{
	int Byte=1;
	int NbrChar=0;
	for (Byte;Byte<=Taille;Byte++)
	 {
	 	if (CodeT[Byte]<=0x80 && CodeT[Byte]>=0x20)
	 	NbrChar++;
	}
	//Affiche en texte
	if (NbrChar>Taille/2)
	{		printf ("Texte\t");
		//printf("(");
	  for (Byte=1;Byte<=Taille;Byte++)
 	 {
		printf("%c",(char)CodeT[Byte-1]);
		
	}
	  	//printf(")\n");
	  return TRUE;
	} else
	//Affiche en Code
	{
		printf("Code\t");
		  for (Byte=1;Byte<=Taille;Byte++)
  		{
			printf("%02x ",CodeT[Byte-1]);
		}
		return FALSE;
	}
	
	
}



BOOL CodeIdentique(byte* Code1,int Taille1,byte* Code2,int Taille2)
{
	int i;
	if (Taille1==Taille2 && GetTickCount()>=Latency)
	{ 
//		printf("Taille Identic, ");
		for (i=0;i<=Taille1-1;i++)
		{
			if (Code1[i]!=Code2[i])
			{

			//	printf("Code dif : i=%d c1=%02x c2=%02x",i,Code1[i],Code2[i]);
				return FALSE;
			}
		}	
		return TRUE;
	} else
	{ 
		return FALSE;
	}
}
//--------------------------------------------------------------------------- 
BOOL ExecuteCode (byte* CodeTelecommande,int Taille)
{
	int i;
	WINDOWPLACEMENT Placement;
	HWND hWnd;
	IRCODE * pCode_en_cour=pCodes_IR;
	BYTE Extended;
	BYTE KeyLayout[256];
	
	for (i=0;i<=TailleCode-1;i++)
	{
		if ( CodeIdentique(CodeTelecommande,Taille,pCode_en_cour->Code,pCode_en_cour->T))
		{
hWnd=FindWindow(pCode_en_cour->AppName,NULL);
if (hWnd==NULL||pCode_en_cour->AppName==NULL)
hWnd=GetForegroundWindow();
//PlaySound("telecommande.wav",NULL,SND_FILENAME|SND_ASYNC|SND_NOSTOP);
		printf("Action\t%s",pCode_en_cour->Fonction);
	//	EcrireDonnes(CodeTelecommande,Taille);	
			switch (pCode_en_cour->Action)
			{
			case LANCER_APP:
				ShellExecute(NULL,NULL,pCode_en_cour->AppName,NULL,NULL, SW_SHOWNORMAL	 );
				break;	
			
			case ENVOI_MESSAGE:	

				PostMessage(hWnd,pCode_en_cour->wParam,pCode_en_cour->lParam,0);
				break;
			case ENVOI_WM_KEYDOWN:
				
GetKeyboardState(KeyLayout);

					Extended=HIBYTE(LOWORD(pCode_en_cour->wParam)) & HOTKEYF_EXT;
						
				if ( HIBYTE(LOWORD(pCode_en_cour->wParam))	& HOTKEYF_ALT !=0 )
				{
					keybd_event(VK_MENU,0,Extended,0);
					KeyLayout[VK_MENU]=1;
				}
				if ( HIBYTE(LOWORD(pCode_en_cour->wParam)) & HOTKEYF_CONTROL !=0 )
				{
					keybd_event(VK_CONTROL,0,Extended,0);
					KeyLayout[VK_CONTROL]=1;
				}
				if ( HIBYTE(LOWORD(pCode_en_cour->wParam)) & HOTKEYF_CONTROL !=0 )
				{
					keybd_event(VK_SHIFT,0,Extended,0);
					KeyLayout[VK_SHIFT]=1;
				}

				SetKeyboardState(KeyLayout);
					keybd_event((BYTE)LOWORD(pCode_en_cour->wParam),0,Extended,0);
				
					if ( HIBYTE(LOWORD(pCode_en_cour->wParam)) & HOTKEYF_ALT !=0 )
					{
							KeyLayout[VK_MENU]=0;				
					keybd_event(VK_MENU,0,KEYEVENTF_KEYUP|Extended,0);
					}
					if ( HIBYTE(LOWORD(pCode_en_cour->wParam)) & HOTKEYF_CONTROL !=0 )
						{
							KeyLayout[VK_CONTROL]=0;
					keybd_event(VK_CONTROL,0,KEYEVENTF_KEYUP|Extended,0);
					}
					if ( HIBYTE(LOWORD(pCode_en_cour->wParam)) & HOTKEYF_SHIFT !=0 )
						{
							KeyLayout[VK_SHIFT]=0;
					keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP|Extended,0);
					}
					SetKeyboardState(KeyLayout);
					keybd_event(LOBYTE(LOWORD(pCode_en_cour->wParam)),0,KEYEVENTF_KEYUP|Extended,0);
				
			/*	PostMessage(hWnd,WM_KEYDOWN,pCode_en_cour->wParam,0);
				PostMessage(hWnd,WM_KEYUP,pCode_en_cour->wParam,0x80000000);*/
				break;
			case ENVOI_WM_CTRL:
			/*	PostMessage(hWnd,WM_KEYDOWN,pCode_en_cour->lParam,0);				
				PostMessage(hWnd,WM_KEYDOWN,pCode_en_cour->wParam,0);								
				PostMessage(hWnd,WM_KEYUP,pCode_en_cour->wParam,0x80000000);
				PostMessage(hWnd,WM_KEYUP,pCode_en_cour->lParam,0x80000000);*/
/*
				keybd_event(pCode_en_cour->wParam,0,NULL,0);
				keybd_event(pCode_en_cour->lParam,0,NULL,0);
				keybd_event(pCode_en_cour->lParam,0,KEYEVENTF_KEYUP,0);
				keybd_event(pCode_en_cour->wParam,0,KEYEVENTF_KEYUP,0);*/



				
				break;
				//VK_MENU
			case SHOW_WINDOW:
				GetWindowPlacement(hWnd,&Placement);
				if (Placement.showCmd==pCode_en_cour->wParam)
				ShowWindow(hWnd,pCode_en_cour->lParam);
				else
				ShowWindow(hWnd,pCode_en_cour->wParam);			
				break;

			}


			Latency=pCode_en_cour->Latency+GetTickCount();
			return TRUE;
		}
	pCode_en_cour++;
	}
	return FALSE;
}









int main(int argc, char **argv) 
    { 
	UINT i;
HANDLE Port_s; 
	DWORD Event;
    char Entete[2];          //Tampon où vont être placé les données lus 
    byte Donnes_temp;
	byte Donnes[50];//sur le port série 
    DWORD nbytestoread=32;     //nombre de bits lus 
   

    /*ouverture du port série, mode lecture,ne crée pas de fichier s'il n'existe pas, 
                                       attribut normal...*/ 

    Port_s= CreateFile("\\COM2:",GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL); 
    cout<<"Ouverture du port serie"<<endl; 

    unsigned long ulsize=sizeof(COMMCONFIG); 
    COMMCONFIG tR; 


    GetCommConfig(Port_s, &tR,&ulsize);    //Obtenir la configuration du port série 
    
	pCodes_IR=ChargerTableDesCodes();
  printf("ulsize= %ld", ulsize); 
    printf("\n DCB:\n BaudRate(%ld), Parite(%ld), \n ByteSize(%d)  Parity(%d)  Stop(%d) \n XonChar(%x)  XoffChar(%x)ErrorChar(%x) EofChar(%x)  EvtChar(%x)\n", 
    tR.dcb.BaudRate,tR.dcb.fParity, tR.dcb.ByteSize, tR.dcb.StopBits, 
    tR.dcb.XonChar, tR.dcb.XoffChar, tR.dcb.ErrorChar, tR.dcb.EofChar, 
    tR.dcb.EvtChar); 
	tR.dcb.fParity=NOPARITY;
	tR.dcb.ByteSize=8;
	tR.dcb.StopBits=ONESTOPBIT	;
    tR.dcb.fInX=0;                 //désactive les Xon-Xoff 
    tR.dcb.BaudRate= CBR_9600;     //Configuration du BaudRate
	tR.dcb.EvtChar=STARTCHAR;

    //Enregistrer les modifications apportées au paramètres Xon-Xoff 
    SetCommConfig(Port_s, &tR, ulsize); 
	if (
EscapeCommFunction(Port_s,SETRTS))
printf ("Alimentation du montage OK !\n");


     COMMTIMEOUTS tMyTimeOuts =  { 
       100,//MAXDWORD,// MAXDWORD, //  DWORD ReadIntervalTimeout;      (voir texte ci-dessus) 
        0, //  DWORD ReadTotalTimeoutMultiplier;      (voir texte ci-dessus) 
        0,    //  DWORD ReadTotalTimeoutConstant;     (10 secondes) 
        1000,     //  DWORD WriteTotalTimeoutMultiplier;   (1 seconde) 
        1000     //  DWORD WriteTotalTimeoutConstant;      (1 seconde) 
        }; 
  
    //Enregistrer les modifications concernant le CommTimeouts 
    SetCommTimeouts(Port_s, &tMyTimeOuts);  // Ajuste les temps d'attente 
  
  
  
  
  

    /*----------------------------------------------------------------------- 
    ///////////////////////TEMPORAIRE: À VÉRIFIER//////////////////////////// 
  

    Commande du robot sur 4 bits.  Règle la marche avant, arrière et les virages 
    à gauche et à droite et l'arrêt du robot. 
  

    Bit 0 => Ref + pour le moteur gauche; 
    Bit 1 => Ref + pour le moteur droit; 
    Bit 2 => Ref - pour le moteur gauche; 
    Bit 3 => Ref - pour le moteur droit. */ 
SetCommMask(Port_s,EV_RXCHAR);


    do                        //boucle de lecture et de transmission du caractère 

        { 
  //LECTURE
			PurgeComm(Port_s,PURGE_RXCLEAR);
		WaitCommEvent(Port_s,&Event,NULL);
		ReadFile(Port_s, Entete, 2, &nbytestoread,NULL);     //STARTCHAR


	//	Sleep(20);

		ReadFile(Port_s, Donnes, Entete[1], &nbytestoread,NULL);
		
		if (!ExecuteCode(Donnes,Entete[1]))
			EcrireDonnes(Donnes,Entete[1]);
			
		printf("\n");
  
  
             }      //fin du do 

     while (1 );    //Réaliser la boucle tant que l'usager n'entre 
                                    //pas le caractère d'arrêt du programme 
  

   ///////////////-----------Procédures de fermeture------------/////////////// 

  
    CloseHandle(Port_s);    //fermeture du port série 
   
    return 0; 
    }   //fin du programme 
  
  
  
  
  
  
  
  
  
 
 
  
  
  
  
  
