#include "classmae.h"
////////////////////////////////////////////////////////////////////
//! Un programme pour tester notre composant (logiciel)
void programmeDeTest1(){
//! Le composant à tester
CStateMachine mae;  
Serial.print("Test lancé le "); 
Serial.print(__DATE__ );
Serial.print(" à "); 
Serial.println(__TIME__ );
Serial.print("Fonction de test: ");
Serial.println(__func__);
//boucle pour gérer les différents cas à tester
for (unsigned int ntest=0;ntest<8;ntest++){
Serial.print("début du test numéro: ");
Serial.println(ntest);
 
mae.reset();
mae.setEntree(0);
/*
mae.setEntreeBit(0,1);
mae.setEntreeBit(1,1);
mae.setEntreeBit(2,1);
mae.setEntreeBit(3,1);
mae.setEntreeBit(0,0);
mae.setEntreeBit(2,0);
mae.setEntreeBit(1,0);
mae.setEntreeBit(3,0);
*/
//test du maintien dans l'état 0
mae.clock(); //ici on teste la mae sans considération de timing, donc clock() n'est pas conditionné à un timer
mae.clock();
//la MAE doit être dans l'état 0
if (mae.getEtat()!=0)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
mae.setEntreeBit(0,1); //équivalent ici à mae.setEntree(1);
mae.clock();  //transition de 0 à 1
if (mae.getEtat()!=1)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
if (mae.getSortieBit(2)!=0)  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
mae.reset(); //ici pour faire le test en fonction des 2 valeurs de entree2 je reset la mae
//on verra plus bas une manière plus générale de tester 2 cas
if (mae.getEtat()!=0)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
mae.setEntreeBit(2,1); //met entree2 à 1 pour tester la mémorisation d'un 1 sur sortie2
mae.clock();  //transition de 0 à 1
if (mae.getSortieBit(2)!=1)  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
//test du maintien dans l'état 1
//bloqué dans l'état 1 tant que entree2 est à 1
//verifie si sortie1 recopie bien entree1
mae.setEntreeBit(1,1); 
mae.clock();  
if (mae.getSortieBit(1)!=1)  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
mae.setEntreeBit(1,0); 
mae.clock();  
if (mae.getSortieBit(1)!=0)  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
//transition de etat 1 vers état 2
// avec mémorisation de entree0 qui vaut 0 ou 1 dans sortie3, 
//il faut faire 2 tests, donc j'utilise le bit 0 de ntest pour cela
mae.setEntreeBit(0,((ntest>>0)&1));  //pour régler la valeur à mémoriser
mae.setEntreeBit(2,0); //pour déclencher la transition
mae.clock();  
if (mae.getSortieBit(3)!=((ntest>>0)&1))  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
 
//test du maintien dans l'état 2
mae.setEntreeBit(2,0);
mae.setEntreeBit(0,0);
mae.clock();  
mae.clock();  
if (mae.getEtat()!=2)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
//transition de etat 2 vers etat3
mae.setEntreeBit(0,1);
mae.clock();  
if (mae.getEtat()!=3)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
//vérifie si sortie0 recopie bien entree1
//il faut faire 2 tests, donc j'utilise le bit 1 de ntest pour cela
mae.setEntreeBit(1,((ntest>>1)&1));  
mae.clock();
//test du maintien dans l'état 3  
//la mae doit être maintenue dans l'état 3 et sortie0 doit être égale à entree1
if (mae.getEtat()!=3)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
if (mae.getSortieBit(0)!=((ntest>>1)&1))  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
//transition de etat 3 vers etat 0, on teste les 2 cas de recopie de sortie1 , avec entree2= bit 2 de ntest
mae.setEntreeBit(0,0);
mae.setEntreeBit(2,((ntest>>2)&1));  
mae.clock();  
if (mae.getEtat()!=0)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
if (mae.getSortieBit(1)!=((ntest>>2)&1))  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
mae.clock(); 
//sortie1 est une AMZI, elle doit revenir à 0
if (mae.getSortieBit(1)!=0)  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
//revenons à l'état 2 pour tester la transition vers l'état 0,
//durant cette transition, il faut remettre à 0 la sortie3, donc on va s'arranger pour la mémoriser à 1 dans la 
//transition de 1 vers 2
mae.setEntreeBit(0,1);
mae.setEntreeBit(1,0);
mae.clock(); 
mae.setEntreeBit(2,0);
mae.setEntreeBit(0,1); //on mémorise un 1 dans sortie 3
mae.clock(); 
if (mae.getEtat()!=2)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
mae.setEntreeBit(0,0);
mae.setEntreeBit(2,1);
mae.clock(); 
if (mae.getEtat()!=0)  debugMessage("Erreur: La MAE n'est pas dans l\'état prévu", __FILE__,  __LINE__);
if (mae.getSortieBit(3)!=0)  debugMessage("Erreur: La sortie n'est pas à la valeur prévue", __FILE__,  __LINE__);
 
//Ce test n'est même pas exhaustif car nous n'avons pas testé si les AMZI reviennent bien toutes à 0
//et si les AMZE mémorisent bien
//et si les entrées autres que celle écrites sur le modèle n'ont pas un impact (par exemple que fait l'entree1 dans l'état 2)
}
Serial.println("fin du test");
//vidage de la FIFO d'affichage:
//flush(std::cout);
}
////////////////////////////////////////////////////////////////////
 
////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
//Normalement le programme de test est un programme à part
programmeDeTest1();
}
////////////////////////////////////////////////////////////////////
//! fonction d'affichage d'un message de debug bien pratique, 
//! qui affiche un message texte, le nom du fichier et le numéro de la ligne 
//! depuis où la fonction a été appelée
void debugMessage(const char * chaineMsg,const char * chaineFile,const unsigned int line){
Serial.print("DEBUG ");  
Serial.print(chaineFile);  
Serial.print(" : l ");   
Serial.print(line);  
Serial.print(" : ");   
Serial.print(chaineMsg);  
Serial.println();
}
////////////////////////////////////////////////////////////////////
void loop() {
}