/******************************************************************************/
/* Files to Include                                                           */
/******************************************************************************/

/* Device header file */
#if defined(__XC16__)
#include <xc.h>
#elif defined(__C30__)
#if defined(__dsPIC33E__)
#include <p33Exxxx.h>
#elif defined(__dsPIC33F__)
#include <p33Fxxxx.h>
#endif
#endif

#include <stdint.h>                                                             /* For uint16_t definition                       */
#include <stdbool.h>                                                            /* For true/false definition                     */
#include <math.h>                                                               /* For uint16_t definition                       */
//#include "user.h"                                                             /* variables/params used by user.c               */
#include "UARTsComm.h"
#include "GenericTypeDefs.h"
#include "HardwareProfile.h"
#include "MODBUSTCPServer.h"
#include "Process.h"
#include "Pesage.h"
#include "Regul.h"
#include "AD7190.h"
#include "SPIFRAM.h"

#include "B40/abcc.h"
#include "B40/ad_obj.h"
#include "B40/user_adi.h"

//#include "PLCD/BdC.h"
//#include "PLCD/Depeseur.h"
#include "PLCD/Impression.h"

void EcritSortieAna(void);
void moyenne_glissante_poids(void);
void gestion_debit(void);
void conversion_poids(void);
void gestion_poids(void);
void verif_totaux(void);
void gestion_totalisateurs(void);
void EnvoieSerie(char num_serie, char trame[80], int nb_octets);
void gestion_vitesse(void);
void gestion_cycle_BI(void);
void gestion_defauts_BI(void);


PARAM_STRUCT        PAR;
EXPL_STRUCT         EXP;

char                sorTOR[10];
char                entTOR[10];
WORD                Cav_USR1;
WORD                Cav_CLR;

char                Demarrage1er = 1;
unsigned int        T100[50];
unsigned int        T10[10];
char                AD7190_PoidsPret;
unsigned int        Compteur;
float               NbTopTotal;
unsigned long       CompteurTot;
char                entreeTorVitesseMem;



void EcrFRAM_Param(void)
{
BYTE            *Mem;
int             AdDebut;
int             nbBytes;

AdDebut = (int)&PAR.Debut;
FRAMBeginWrite(AdDebut);
Mem = AdDebut;
nbBytes = (int)&PAR.Fin-AdDebut;

while(nbBytes--)
    FRAMWrite(*Mem++);

FRAMEndWrite();

// Ecriture des totalisateurs
//AdDebut = &EXP.TotalPartiel1;
//FRAMBeginWrite(AdDebut);
//Mem = AdDebut;
//nbBytes = 16;

//while(nbBytes--)
//    FRAMWrite(*Mem++);
}


void EcrFRAM(int adresse, int nbBytes)
{
BYTE            *Mem;
int             AdDebut;
int             AdDebut2;

AdDebut2 = (int)&PAR.Debut;
AdDebut = adresse - AdDebut2;

FRAMBeginWrite(AdDebut);
Mem = AdDebut;
//nbBytes = &PAR.Fin-AdDebut;

while(nbBytes--)
    FRAMWrite(*Mem++);
}


void LecFRAM_Param(void)
{
BYTE            *Mem;
int             AdDebut;
int             nbBytes;

AdDebut = (int)&PAR.Debut;
FRAMBeginRead(AdDebut);
Mem = AdDebut;
nbBytes = (int)&PAR.Fin-AdDebut;

while(nbBytes--)
        *Mem++ = FRAMRead();

EXP.TotalPartiel1 = PAR.TotalPartiel1;
EXP.TotalGlobal1 = PAR.TotalGlobal1;
EXP.TotalPartiel2 = PAR.TotalPartiel2;
EXP.TotalGlobal2 = PAR.TotalGlobal2;

// Lecture des totalisateurs
//AdDebut = &EXP.TotalPartiel1;
//FRAMBeginRead(AdDebut);
//Mem = AdDebut;
//nbBytes = 16;

//while(nbBytes--)
//        *Mem++ = FRAMRead();
}


void LecFRAM(int addrFram, int nbBytes)
{
BYTE            *Mem;
int             AdDebut;

Mem = addrFram;
AdDebut = (int)&PAR.Debut;
addrFram = addrFram - AdDebut;

FRAMBeginRead(addrFram);

while(nbBytes--)
        *Mem++ = FRAMRead();
}


void InitParams(void)
{
PAR.Init = 0;

PAR.LongueurPesage = 0.8;
PAR.BandeFiltrePoids = 100;

PAR.TypeProgramme[0] = 0x30;
PAR.TypeProgramme[1] = 0x36;
PAR.Version[0] = 0x30;
PAR.Version[1] = 0x31;
PAR.Metrologie = 0x30;
PAR.Options = 0;
PAR.OP_Doseur = 0;

memcpy(PAR.InfosClient, "PLCD SAS                                                                                            ", 100);
memcpy(PAR.TechnicienPLCD, "Philippe ROUSSEL    ", 20);
memcpy(PAR.TechnicienClient, "Nom contact client  ", 20);
memcpy(PAR.TypeCapteurs, "3 capteurs TEDEA 500kg                            ", 50);
memcpy(PAR.ProduitPese, "Farine                                 ", 40);
memcpy(PAR.DateMiseEnService, "20130801", 8);
memcpy(PAR.DateVerification, "20140902", 8);

memcpy(PAR.NumSerie, "150801", 6);
memcpy(PAR.CodeBalancier, "0001", 4);

memcpy(PAR.Impr_EnteteLigne1, "PLCD SAS", 8);
PAR.Impr_EnteteLigne2[0] = 0;
PAR.Impr_EnteteLigne3[0] = 0;
PAR.Impr_PiedPageLigne1[0] = 0;
PAR.Impr_PiedPageLigne2[0] = 0;
PAR.Impr_NbLignesVides = 0;
PAR.Impr_NumTicket = 0;

PAR.UnitePoids = 2;
PAR.PoidsMax = 500000;
PAR.NbChiffreVirgPoids = 1;
PAR.EchelonPoids = 7;
PAR.EchelonPoidsVal = 0.1;
PAR.FiltrePoids = 10;
PAR.FrequencePoids = 6;                                                         // 200m/s
PAR.TareMetrologie = 960644;
PAR.TareInc = 960644;
PAR.ToleranceTarage = 10.0;
PAR.NbPointsEtalonnage = 1;
PAR.RapportEtalonnage = 1000;

PAR.Pente[1] = 0.477;
PAR.SeuilPente[1] = 100.0;
PAR.Pente[2] = 2.0;
PAR.SeuilPente[2] = 200.0;
PAR.Pente[3] = 3.0;
PAR.SeuilPente[3] = 300.0;
PAR.Pente[4] = 4.0;
PAR.SeuilPente[4] = 400.0;
PAR.Pente[5] = 5.0;
PAR.SeuilPente[5] = 500.0;
PAR.SensibiliteMoyCapteurs = 2000000;
PAR.SensibiliteCapteur[1]  = 2000001;
PAR.SensibiliteCapteur[2]  = 2000002;
PAR.SensibiliteCapteur[3]  = 2000003;
PAR.SensibiliteCapteur[4]  = 2000004;
PAR.SensibiliteCapteur[5]  = 2000005;
PAR.SensibiliteCapteur[6]  = 2000006;
PAR.SensibiliteCapteur[7]  = 2000007;
PAR.SensibiliteCapteur[8]  = 2000008;
PAR.SensibiliteCapteur[9]  = 2000009;
PAR.SensibiliteCapteur[10] = 2000010;
PAR.DefautCapteurMoins = 100;
PAR.DefautCapteurPlus = 10000000;
PAR.NbEchelonsStabilite = 2;
PAR.TempsStabilite = 10;

PAR.Correction1 = 100.0;
PAR.Correction2 = 100.0;
PAR.Correction3 = 100.0;
PAR.Correction4 = 100.0;
PAR.FiltreDebit = 3;
PAR.LongPulseSortie = 200;
PAR.LimZeroAuto = 2;
PAR.ZoneMorte = 0;

PAR.TotalPartiel1 = 0;
PAR.TotalGlobal1 = 0;
PAR.TotalPartiel2 = 0;
PAR.TotalGlobal2 = 0;

// Paramètres généraux bascule sur bande
PAR.EchelonTotalisation = 4;
PAR.EchelonTotalisationVal = 10;
PAR.EchelonSortieTot = 10;
PAR.EchelonSortieTotVal = 1000;
PAR.UniteTotalisation = 2;
PAR.NbChiffreDecimaleVitesse = 3;
PAR.VitesseMax = 2.0;
PAR.NbChiffreDecimaleDebit = 2;
PAR.DebitMax = 100.0;
PAR.DebitMin = 0.0;
PAR.DebitNominal = 20.0;
PAR.VitesseMin = 0.5;
PAR.Correction1 = 100.0;
PAR.Correction2 = 100.0;
PAR.Correction3 = 100.0;
PAR.Correction4 = 100.0;
PAR.LongueurBande = 3.0;
PAR.LongueurPesage = 1.0;
PAR.CirconfTambMene = 1.020;
PAR.CirconfTambMenant = 1.020;
PAR.ImpTambMene = 8;
PAR.ImpTambMenant = 8;
PAR.NbPulsesAvantReglage = 16;
PAR.NbTourBandesReglage = 1;
PAR.LimiteTotalisation = 5.0;
PAR.FiltreDebit = 0;
PAR.LargeurBande = 800;
PAR.TempsArret = 0;
PAR.TempsMarcheTotalisation = 0;
PAR.TempsMarche = 0;
PAR.TempsMarcheVide = 0;
PAR.DebitMaxLot = 0;
PAR.TotDebitMoyen = 0;
PAR.NbTotDebitMoyen = 0;
EXP.DebitMoyenLot = 0;
PAR.CorrectionTimer = 10000;

PAR.EntreeTOR[1]  = DI_DCY;
PAR.EntreeTOR[2]  = DI_AutorisationReglage;
PAR.EntreeTOR[3]  = DI_ModeDistant;
PAR.EntreeTOR[4]  = DI_VitesseMene;
PAR.EntreeTOR[5]  = 0;
PAR.EntreeTOR[6]  = DI_ImpressionTotPartiel;
PAR.EntreeTOR[7]  = 0;
PAR.EntreeTOR[8]  = 0;
PAR.EntreeTOR[9]  = 0;
PAR.EntreeTOR[10] = 0;
PAR.InversionSortiesTOR = 0;
PAR.InversionSortieTOR[1] = 0;
PAR.InversionSortieTOR[2] = 0;
PAR.InversionSortieTOR[3] = 0;
PAR.InversionSortieTOR[4] = 0;
PAR.InversionSortieTOR[5] = 0;
PAR.InversionSortieTOR[6] = 0;
PAR.InversionSortieTOR[7] = 0;
PAR.InversionSortieTOR[8] = 0;
PAR.InversionSortieTOR[9] = 0;
PAR.InversionSortieTOR[10] = 0;

PAR.SortieTOR[1] = 0;
PAR.SortieTOR[2] = DO_DefGeneral;
PAR.SortieTOR[3] = DO_CommandeBande;
PAR.SortieTOR[4] = DO_Totalisateur;
PAR.SortieTOR[5] = 0;
PAR.SortieTOR[6] = 0;
PAR.SortieTOR[7] = DO_SimulateurVitesse;
PAR.SortieTOR[8] = 0;

PAR.EntreeANA[1]  = 0;
PAR.EntreeANA[2]  = 0;
PAR.ValSortieANA[1]  = 0;
PAR.ValSortieANA[2]  = 0;
PAR.TypeSortieANA[1] = 1;
PAR.TypeSortieANA[2] = 1;
PAR.OrigineSortieANA[1] = 2;
PAR.OrigineSortieANA[2] = 2;
PAR.CoeffSortieAna[1] = 10000;
PAR.CoeffSortieAna[2] = 10000;
PAR.OrigineEntreeANA[1] = 10;
PAR.OrigineEntreeANA[2] = 10;
PAR.CoeffEntreeAna[1] = 10000;
PAR.CoeffEntreeAna[2] = 10000;
PAR.TypeEntreeANA[1] = 2;
PAR.TypeEntreeANA[2] = 2;
        
PAR.AdresseIP[0] = 192;
PAR.AdresseIP[1] = 168;
PAR.AdresseIP[2] = 0;
PAR.AdresseIP[3] = 100;
PAR.MasqueIP[0] = 255;
PAR.MasqueIP[1] = 255;
PAR.MasqueIP[2] = 255;
PAR.MasqueIP[3] = 0;
PAR.PortIP = 502;

PAR.CommVitesse[COM_RS232] = 10;                                                // BR57600
PAR.CommParite[COM_RS232] = 1;
PAR.CommNbBits[COM_RS232] = 1;
PAR.CommNbbitsStop[COM_RS232] = 1;
PAR.CommCtrlFlux[COM_RS232] = 0;
PAR.CommMode[COM_RS232] = 1;
PAR.CommNumEsclave[COM_RS232] = 1;
PAR.CommType[COM_RS232] = COMM_IMPRIMANTE;
PAR.CommVitesse[COM_UART2] = 10;                                                // BR57600
PAR.CommParite[COM_UART2] = 1;
PAR.CommNbBits[COM_UART2] = 1;
PAR.CommNbbitsStop[COM_UART2] = 1;
PAR.CommCtrlFlux[COM_UART2] = 0;
PAR.CommMode[COM_UART2] = 1;
PAR.CommNumEsclave[COM_UART2] = 1;
PAR.CommType[COM_UART2] = COMM_PC;
PAR.CommVitesse[COM_RS485_1] = 10;                                              // BR57600
PAR.CommParite[COM_RS485_1] = 1;
PAR.CommNbBits[COM_RS485_1] = 2;
PAR.CommNbbitsStop[COM_RS485_1] = 1;
PAR.CommCtrlFlux[COM_RS485_1] = 0;
PAR.CommMode[COM_RS485_1] = 1;
PAR.CommNumEsclave[COM_RS485_1] = 1;
PAR.CommType[COM_RS485_1] = COMM_AFFICHEUR_BASIA4;
PAR.CommVitesse[COM_RS485_2] = 10;                                              // BR57600
PAR.CommParite[COM_RS485_2] = 1;
PAR.CommNbBits[COM_RS485_2] = 2;
PAR.CommNbbitsStop[COM_RS485_2] = 1;
PAR.CommCtrlFlux[COM_RS485_2] = 0;
PAR.CommMode[COM_RS485_2] = 1;
PAR.CommNumEsclave[COM_RS485_2] = 1;
PAR.CommType[COM_RS485_2] = COMM_ANA_BASIA4;
PAR.CommVitesse[COM_PROFIBUS] = 3;
PAR.CommNumEsclave[COM_PROFIBUS] = 0;
PAR.CommVitesse[COM_CAN] = 35;
PAR.CommNumEsclave[COM_CAN] = 36;

PAR.TempoDefaut = 10;
PAR.AffectTempoDefaut1 = 0xE7FF;
PAR.AffectTempoDefaut2 = 0xFFFF;
PAR.AffectDefautDefautGeneral1 = 0xF9FF;
PAR.AffectDefautDefautGeneral2 = 0xFFFF;
PAR.ActivationDefaut1 = 0xFFFF;
PAR.ActivationDefaut2 = 0xFFFF;
memcpy(PAR.DateDerniereRAZ, "20160101100000", 14);
        
PAR.TypeCommande = 0x00;
PAR.CommandeTOR = 1;
PAR.CommandeSerie = 0;

PAR.PID_Ki = 500.0;
PAR.PID_Kp = 500.0;

// Imprimante
PAR.Impr_TypeTicket = 1;
memcpy(PAR.Impr_Produit, "                    ", 20);
memcpy(PAR.Impr_Client, "                    ", 20);
memcpy(PAR.Impr_Destination, "                    ", 20);
memcpy(PAR.Impr_Camion, "                    ", 20);
        
// Doseur
PAR.SeuilHautRegul = 1000;
PAR.SeuilBasRegul = 1000;
PAR.ModeRegul = 1;
PAR.ValeurMaxRegul = 10000;
PAR.ConsigneAnaMax = 10000;
PAR.MemorisationSortieAna = 0;
PAR.LimiteConsigneNulle = 0;

// Dépesée
PAR.Dep_CalculErreurJeteeAuto = 0;

// Pese essieu
PAR.PEs_SeuilDeclenchement = 500000;
PAR.PEs_TempoHorsCycle = 100;
PAR.PEs_TempoApresStabilite = 20;
PAR.PEs_ModeStatique = 1;
PAR.PEs_LargeurPlateforme = 100;
PAR.PEs_TolMaxVariationVitesse = 100;
PAR.PEs_VitesseMax = 5;
PAR.PEs_TempsAcquisitionPoids = 20;

PAR.VitesseManu = 0.0;
//PAR.LongueurPesage = 0.8;
//PAR.CirconfTambMene = 0.5;
//PAR.CirconfTambMenant = 0.2;
//PAR.ImpTambMene = 4;
//PAR.ImpTambMenant = 4;
PAR.Correction1 = 100;

PAR.CategorieProgramme = TY_BI;

ModifieVitesseComm(0);
ModifieVitesseComm(1);
ModifieVitesseComm(2);
ModifieVitesseComm(3);

EcrFRAM_Param();
}


void gestion_profibus(void)
{
float               interf;
unsigned long       interul;

// Mise à jour des variables Profibus DB
ADI_DebitInstan = EXP.DebitTR * 1000;
if (EXP.PoidsMoyen >= 0)
    ADI_PoidsInstan = EXP.PoidsMoyen * 1000;
else
{
    ADI_PoidsInstan = (-EXP.PoidsMoyen) * 1000;
    ADI_PoidsInstan = 0xFFFFFFFF - ADI_PoidsInstan;
}

if (EXP.PoidsMetre >= 0)
    ADI_PoidsMetre = EXP.PoidsMetre * 1000;
else
{
    ADI_PoidsMetre = (-EXP.PoidsMetre) * 1000;
    ADI_PoidsMetre = 0xFFFFFFFF - ADI_PoidsMetre;
}
interf = PAR.TareInc;
interf = interf * PAR.Pente[1] / 100;
PAR.TarePoids = interf;
ADI_Tare = PAR.TarePoids;
ADI_Vitesse = EXP.Vitesse * 1000;
interul = EXP.TotalPartiel2; interul *= 10000; interul += EXP.TotalPartiel1 * 1000;
ADI_TotalPartiel = interul;
interul = EXP.TotalGlobal2; interul *= 10000; interul += EXP.TotalGlobal1 * 1000;
ADI_TotalGlobal = interul;
ADI_EtatBascule = (unsigned long)EXP.Defaut1 * 65536 + EXP.Etat1;

EXP.Profibus_Command = ADI_CmdsBascule;
if (EXP.ModeLocal)
    EXP.Profibus_Command = 0;

AD_NewWrPd();
}


void process_plcd(void)
{
static DWORD        t100 = 0;
static DWORD        t10 = 0;
int                 i;
float               interf;
char                reponse[80] = {0};
unsigned long       interul;
int                 echelon;

lecture_entrees_TOR();

if (!Cav_USR1)
    InitParams();

if (!Cav_CLR)                                                                   // Paramètres d'usine sur RS485-2 Afficheur
{
    PAR.CommVitesse[COM_RS485_2] = 10;                                          // BR57600
    PAR.CommParite[COM_RS485_2] = 1;
    PAR.CommNbBits[COM_RS485_2] = 8;
    PAR.CommNbbitsStop[COM_RS485_2] = 1;
    PAR.CommCtrlFlux[COM_RS485_2] = 0;
    PAR.CommMode[COM_RS485_2] = 0;
    PAR.CommNumEsclave[COM_RS485_2] = 1;
    PAR.CommType[COM_RS485_2] = COMM_AFFICHEUR_BASIA4;
}

if (Demarrage1er)
{
    LecFRAM_Param();
    Demarrage1er = 0;
    Compteur = 0;

    PAR.TypeProgramme[0] = 0x30;
    PAR.TypeProgramme[1] = 0x32;
    PAR.TypeProgramme[2] = '6';
    PAR.TypeProgramme[3] = '0';

    AppConfig.MyIPAddr.Val = PAR.AdresseIP[0] | PAR.AdresseIP[1]<<8ul | PAR.AdresseIP[2]<<16ul | PAR.AdresseIP[3]<<24ul;
    AppConfig.MyMask.Val = PAR.MasqueIP[0] | PAR.MasqueIP[1]<<8ul | PAR.MasqueIP[2]<<16ul | PAR.MasqueIP[3]<<24ul;

    T100[timer_VitesseManu] = 3;

    T100[timer_DefautPoidsMax]   = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0100) == 0x0100);
    T100[timer_DefautDebitMax]   = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0200) == 0x0200);
    T100[timer_DefautDebitMin]   = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0400) == 0x0400);
    T100[timer_DefautVitesseMin] = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0800) == 0x0800);
    T100[timer_DefautCapteur]    = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x1000) == 0x1000);

    PAR.CommVitesse[COM_UART2] = 10;                                            // BR57600
    PAR.CommParite[COM_UART2] = 1;
    PAR.CommNbBits[COM_UART2] = 1;
    PAR.CommNbbitsStop[COM_UART2] = 1;
    PAR.CommCtrlFlux[COM_UART2] = 0;
    PAR.CommMode[COM_UART2] = 1;
    PAR.CommNumEsclave[COM_UART2] = 1;
    PAR.CommType[COM_UART2] = COMM_PC;
    ModifieVitesseComm(COM_UART2);

    EXP.Debug = 0;
    EXP.Etat1 = 0x0001;                                                         // Bascule à l'arrêt
    EXP.Etat2 = 0x0000;
    EXP.Etat3 = 0x0000;
    EXP.Etat4 = 0x0000;

    EXP.ReglEnCours = 0;
    EXP.posMesureTempsTourBande = 0;

    T100[timer_TempsMarche] = 10;
            
    memcpy(EXP.Date, "01012016", 8);
    memcpy(EXP.Heure, "080000", 6);
            
    // Bascule de circuit
    EXP.BdC_pos_cycle = 0;
  
    // Depeseur
    EXP.Dep_PosCycle = 0;

    // Perte de poids
    EXP.PdP_IndiceTabPoids = 0;
    
            AD7190_StartContinuousRead(PAR.FrequencePoids);

    // Recopie du compteur de sortie sur le totalisateur partiel
    echelon = 1000 / PAR.EchelonSortieTotVal;
    EXP.CptTotalPartiel2 = EXP.TotalPartiel2;
    while ((EXP.TotalPartiel1 * echelon) >= (EXP.CptTotalPartiel1 + 1))
        EXP.CptTotalPartiel1++;
}

// Choix du programme
if (((PAR.Version[0] == 0x30) && (PAR.Version[1] == 0x31))                      // Bascule intégratrice
        && ((PAR.Options & 0xFFFF) == 0x0000))
    PAR.CategorieProgramme = TY_BI;

if (((PAR.Version[0] == 0x30) && (PAR.Version[1] == 0x31))                      // Doseur
        && ((PAR.Options & 0x0001) == 0x0001))
    PAR.CategorieProgramme = TY_Doseur;

if ((PAR.Version[0] == 0x30) && (PAR.Version[1] == 0x32))                       // Vide BigBag
    PAR.CategorieProgramme = TY_Depeseur;

if ((PAR.Version[0] == 0x30) && (PAR.Version[1] == 0x33))                       // Bascule de circuit
    PAR.CategorieProgramme = TY_BasculeCircuit;

if ((PAR.Version[0] == 0x30) && (PAR.Version[1] == 0x34))                       // Pèse essieux
    PAR.CategorieProgramme = TY_PeseEssieux;

if ((PAR.Version[0] == 0x30) && (PAR.Version[1] == 0x35))                       // Vis pesée
    PAR.CategorieProgramme = TY_BI;

if ((PAR.Version[0] == 0x30) && (PAR.Version[1] == 0x36))                       // Perte de poids
    PAR.CategorieProgramme = TY_PerteDePoids;

// Envoie du poids rapidement
//sprintf(reponse,"%c%08lu%c",0x02,EXP.PoidsPoints,0x03);
//EnvoieSerie(COM_UART2, reponse);
//return;

gestion_profibus();

if (Compteur < 50000) Compteur++;
else Compteur = 0;

// Gestion des timers 100ms
if (TickGet() - t100 >= TICK_SECOND / 10ul)
{
    for (i = 0; i < 50; i++)
        if (T100[i]) T100[i]--;
    t100 = TickGet();
}

// Gestion des timers 10ms
if (TickGet() - t10 >= TICK_SECOND / 100ul)
{
    for (i = 0; i < 10; i++)
        if (T10[i]) T10[i]--;
    t10 = TickGet();
}

// Sauvegarde FRAM des paramètres
if (EXP.Command1 & 0x8000)                                                      // Sauvegarde FRAM
{
    EcrFRAM_Param();
    EXP.Etat1 = EXP.Etat1 | 0x8000;                                             // Sauvegarde FRAM effectuée
    T100[timer_SauvegardeFRAM] = 20;
}
if (!T100[timer_SauvegardeFRAM])
    EXP.Etat1 = EXP.Etat1 & 0x7FFF;                                             // Sauvegarde FRAM effectuée

if (!T100[timer_SauveFRamCycle])
{
    PAR.TotalPartiel1 = EXP.TotalPartiel1;
    PAR.TotalGlobal1 = EXP.TotalGlobal1;
    PAR.TotalPartiel2 = EXP.TotalPartiel2;
    PAR.TotalGlobal2 = EXP.TotalGlobal2;

    EcrFRAM_Param();
    T100[timer_SauveFRamCycle] = 20;
}

// Simulation vitesse
if (!T10[timer_SimulateurVitesse])
{
    T10[timer_SimulateurVitesse] = 20;
    sortiesTOR(DO_SimulateurVitesse, 3);
}

// Calcul stabilite poids
interf = PAR.EchelonPoidsVal * PAR.NbEchelonsStabilite;
if ((EXP.PoidsMoyen > EXP.PoidsMemStabilite + interf)
        || (EXP.PoidsMoyen < EXP.PoidsMemStabilite - interf))
{
    sortiesTOR(DO_DefAfficheur, 0);
    T100[timer_stabilite] = PAR.TempsStabilite;
    EXP.Etat2 = EXP.Etat2 & 0xFFFE;                                             // Stabilité
    EXP.PoidsStable = 0;
    EXP.PoidsMemStabilite = EXP.PoidsMoyen;
}
else
{
    if (!T100[timer_stabilite])
    {
        sortiesTOR(DO_DefAfficheur, 1);
        EXP.Etat2 = EXP.Etat2 | 0x0001;                                         // Stabilité
        EXP.PoidsStable = 1;
    }
}

// Gestion du mode local/distant
if (ValEntTOR(DI_ModeDistant, 0))                                               // Mode local
{
    EXP.ModeLocal = 0;
    EXP.Etat1 = EXP.Etat1 & 0xEFFF;                                             // Mode local
}
else
{
    EXP.ModeLocal = 1;
    EXP.Etat1 = EXP.Etat1 | 0x1000;                                             // Mode local
}

// Clignotement des leds
if (!T100[timer_LED1])
{
    T100[timer_LED1] = 5;
    LED0_IO ^= 1;
}

if (!T10[timer_EcritSortieAna])
    EcritSortieAna();

if ((!T100[timer_Debug]) && EXP.Debug)
{
    T100[timer_Debug] = 20;
    
//  if (debugUart2 || debugUart3)
    {
//        sprintf(reponse,"Etat1=%04X    Etat2=%04X    Défaut1=%04X    Défaut2=%04X    Init=%i    CLR=%i\r\n",EXP.Etat1,EXP.Etat2,EXP.Defaut1,EXP.Defaut2,Cav_USR1,Cav_CLR);
//        EnvoieSerie(COMM_DEBUG, reponse, 40);
//        sprintf(reponse,"Poids points=%08lu   Poids = %04.3f    Poids/mètre = %4.3f\r\n",EXP.PoidsPoints,EXP.PoidsMoyen,EXP.PoidsMetre);
//        EnvoieSerie(COMM_DEBUG, reponse, 40);
//        sprintf(reponse,"Vitesse=%04.3f   DébitTR=%04.3f    Débit moyen=%04.3f\r\n",EXP.Vitesse,EXP.DebitTR,EXP.DebitMoyen);
//        EnvoieSerie(COMM_DEBUG, reponse, 40);
//        sprintf(reponse,"Total partiel=%5lu%4.3f    Total global =%5lu%4.3f    Total reglage=%6lu\r\n",EXP.TotalPartiel2,EXP.TotalPartiel1,EXP.TotalGlobal2,EXP.TotalGlobal1,EXP.TotalReglage);
//        EnvoieSerie(COMM_DEBUG, reponse, 40);
//        sprintf(reponse,"Type commande=%02i    Mode doseur=%1i    Consigne=%4.3f    Regulation PID=%6i\r\n",PAR.TypeCommande,PAR.OP_Doseur,EXP.Consigne,EXP.SortieAna);
//        EnvoieSerie(COMM_DEBUG, reponse, 40);
//        interul = EXP.SortieAna; interf = interul;
//        interf=interf/1000.0;
//        sprintf(reponse,"ADAM=#00C1%+07.3f\r\n\n",interf);
//        EnvoieSerie(COMM_DEBUG, reponse, 20);

        sprintf(reponse,"Empl1:%03i Cpt=%04i    Empl2:%03i Cpt=%04i    Empl3:%03i Cpt=%04i\r\n",EXP.EtatSocket[0],T100[timer_CloseSocket1],EXP.EtatSocket[1],T100[timer_CloseSocket2],EXP.EtatSocket[2],T100[timer_CloseSocket3]);
//        EnvoieSerie(2, reponse, 64);
    }
}

if ((PAR.CategorieProgramme == TY_BI)
        || (PAR.CategorieProgramme == TY_Doseur))
{
    gestion_poids();
    gestion_debit();
    gestion_vitesse();
    gestion_totalisateurs();
    gestion_defauts_BI();
    gestion_cycle_BI();
}

if (PAR.CategorieProgramme == TY_Depeseur)
{
    gestion_poids();
    gestion_defauts_Depeseur();
    gestion_cycle_Depeseur();
}

if (PAR.CategorieProgramme == TY_BasculeCircuit)
{
    gestion_poids();
    gestion_cycle_BdC();
}

if (PAR.CategorieProgramme == TY_PeseEssieux)
{
    gestion_poids();
    gestion_cycle_PeseEssieu();
}

if (PAR.CategorieProgramme == TY_PerteDePoids)
{
//    gestion_poids();
    gestion_cycle_PerteDePoids();
}

forcageSortiesTOR();

if (!T100[timer_Donnees_LS])
    T100[timer_Donnees_LS] = 2; 
}


void gestion_defauts_BI(void)
{
unsigned long   interL;
int             defautGeneral;
char            reponse[80];

interL = EXP.PoidsMoyen*1000;
if ((interL > (PAR.PoidsMax/10))                                                // Défaut Poids > Poids Max
        && (PAR.ActivationDefaut1 & 0x0100))
{
    if (!T100[timer_DefautPoidsMax])
        EXP.Defaut1 = EXP.Defaut1 | 0x0100;
}
else
{
    if (PAR.AcqAutoDefauts)
    {
        T100[timer_DefautPoidsMax] = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0100) == 0x0100);
        EXP.Defaut1 = EXP.Defaut1 & 0xFEFF;
    }
}

if ((EXP.DebitMoyen > PAR.DebitMax)                                             // Défaut Débit > Débit Max
        && (PAR.ActivationDefaut1 & 0x0200))
{
    if (!T100[timer_DefautDebitMax])
        EXP.Defaut1 = EXP.Defaut1 | 0x0200;
}
else
{
    if (PAR.AcqAutoDefauts)
    {
        T100[timer_DefautDebitMax] = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0200) == 0x0200);
        EXP.Defaut1 = EXP.Defaut1 & 0xFDFF;
    }
}

if ((EXP.DebitMoyen < PAR.DebitMin)                                             // Défaut Débit < Débit Min
        && (PAR.ActivationDefaut1 & 0x0400)
        && (PAR.DebitMin > 0)                                                   //
        && (EXP.Etat1 & 0x0002))                                                // Bascule en marche
{
    if (!T100[timer_DefautDebitMin])
        EXP.Defaut1 = EXP.Defaut1 | 0x0400;
}
else
{
    if (PAR.AcqAutoDefauts)
    {
        T100[timer_DefautDebitMin] = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0400) == 0x0400);
        EXP.Defaut1 = EXP.Defaut1 & 0xFBFF;
    }
}

if ((EXP.Vitesse < PAR.VitesseMin)                                              // Défaut Vitesse < Vitesse Min
        && (PAR.ActivationDefaut1 & 0x0800)
        && (EXP.Etat1 & 0x0002))                                                // Bascule en marche
{
    if (!T100[timer_DefautVitesseMin])
        EXP.Defaut1 = EXP.Defaut1 | 0x0800;
}
else
{
    if (PAR.AcqAutoDefauts)
    {
        T100[timer_DefautVitesseMin] = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0800) == 0x0800);
        EXP.Defaut1 = EXP.Defaut1 & 0xF7FF;
    }
}

if (((EXP.PoidsPoints < PAR.DefautCapteurMoins) || (EXP.PoidsPoints > PAR.DefautCapteurPlus))  // Défaut Capteur
        && (PAR.ActivationDefaut1 & 0x1000))
{
    if (!T100[timer_DefautCapteur])
        EXP.Defaut1 = EXP.Defaut1 | 0x1000;
}
else
{
    if (PAR.AcqAutoDefauts)
    {
        T100[timer_DefautCapteur] = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x1000) == 0x1000);
        EXP.Defaut1 = EXP.Defaut1 & 0xEFFF;
    }
}

// Gestion des défauts doseur
if (PAR.OP_Doseur)
{
    
}

defautGeneral = calculDefautGeneral();
if (defautGeneral > 0)                                                          
{
    EXP.Defaut1 = EXP.Defaut1 | 0x0004;                                         // Défaut général
    sortiesTOR(DO_DefGeneral, 1);
} else
{
    EXP.Defaut1 = EXP.Defaut1 & 0xFFFB;                                         // Défaut général
    sortiesTOR(DO_DefGeneral, 0);
}
}


int calculDefautGeneral(void)
{
int     defautGeneral;

defautGeneral = 0;                                                              // Gestion du défaut général
defautGeneral = ((EXP.Defaut1 & 0x0100) & (PAR.AffectDefautDefautGeneral1 & 0x0100))    // Poids > poids max
        || ((EXP.Defaut1 & 0x0200) & (PAR.AffectDefautDefautGeneral1 & 0x0200))         // Débit > débit max
        || ((EXP.Defaut1 & 0x0400) & (PAR.AffectDefautDefautGeneral1 & 0x0400))         // Débit < débit min
        || ((EXP.Defaut1 & 0x0800) & (PAR.AffectDefautDefautGeneral1 & 0x0800))         // Vitesse < vitesse min
        || ((EXP.Defaut1 & 0x1000) & (PAR.AffectDefautDefautGeneral1 & 0x1000))         // Défaut capteur

        || ((EXP.Defaut2 & 0x0001) & (PAR.AffectDefautDefautGeneral2 & 0x0001))         // Défaut tolérance -
        || ((EXP.Defaut2 & 0x0002) & (PAR.AffectDefautDefautGeneral2 & 0x0002))         // Défaut tolérance +
        || ((EXP.Defaut2 & 0x0004) & (PAR.AffectDefautDefautGeneral2 & 0x0004))         // Consigne hors tolérances
        || ((EXP.Defaut2 & 0x0008) & (PAR.AffectDefautDefautGeneral2 & 0x0008))         // Défaut ouverture vanne supérieure
        || ((EXP.Defaut2 & 0x0010) & (PAR.AffectDefautDefautGeneral2 & 0x0010))         // Défaut fermeture vanne supérieure
        || ((EXP.Defaut2 & 0x0020) & (PAR.AffectDefautDefautGeneral2 & 0x0020))         // Défaut ouverture vanne inférieure
        || ((EXP.Defaut2 & 0x0040) & (PAR.AffectDefautDefautGeneral2 & 0x0040))         // Défaut fermeture vanne inférieure
        || ((EXP.Defaut2 & 0x0080) & (PAR.AffectDefautDefautGeneral2 & 0x0080))         // Défaut retour marche moteur/vis
        || ((EXP.Defaut2 & 0x0100) & (PAR.AffectDefautDefautGeneral2 & 0x0100));        // BigBag vide (pas d'évolution de poids)
}


void gestion_cycle_BI(void)
{
float               interf;

// Gestion des timers
if (!T100[timer_TempsMarche])
{
    if ((EXP.Etat1 & 0x0002) == 0x0002)                                           // Bit installation en marche
        PAR.TempsMarche++;
    else
        PAR.TempsArret++;
        
    if ((EXP.DebitMoyen >= PAR.LimiteTotalisation * PAR.DebitMax / 100)
            && ((EXP.Etat1 & 0x0002) == 0x0002))                                // Bit installation en marche
        PAR.TempsMarcheTotalisation++;
    else
        if ((EXP.Etat1 & 0x0002) == 0x0002)                                     // Bit installation en marche
            PAR.TempsMarcheVide++;    
        
    PAR.TotDebitMoyen = PAR.TotDebitMoyen + EXP.DebitMoyen;
    PAR.NbTotDebitMoyen++;
    EXP.DebitMoyenLot = (PAR.TotDebitMoyen*10000) / PAR.NbTotDebitMoyen;

    EXP.CorrectionTimersMoyenneLot++;                                           // Correction de la dérive du timer
    interf = PAR.CorrectionTimer; interf = interf/10000;
    if (EXP.CorrectionTimersMoyenneLot >= 130*interf)
    {
        EXP.CorrectionTimersMoyenneLot = 0;
        T100[timer_TempsMarche] = 1;
    }
    else
        T100[timer_TempsMarche] = 10;
}   

// Gestion Commandes
// Gestion DCY
if ((PAR.CommandeSerie && (!PAR.OP_Doseur) && ((EXP.Command1 & 0x0001)          // DCY
            || (EXP.Profibus_Command & 0x0001)))                                // DCY
        || ((PAR.CommandeTOR) && (ValEntTOR(DI_DCY, 0)) && (EXP.PosCycleRegulation == 0))
        || ((PAR.CommandeTOR) && (!ValEntTOR(DI_ModeDistant,0)) && (ValEntTOR(DI_BdC_RMarcheMoteurVis, 0)) && (PAR.OP_Doseur) && (EXP.PosCycleRegulation == 0))
        || ((PAR.CommandeSerie) && (ValEntTOR(DI_ModeDistant,0)) && (EXP.Command1 & 0x4000) && (PAR.OP_Doseur) && (EXP.PosCycleRegulation == 0)))
{
    if ((PAR.OP_Doseur) && ((PAR.CommandeTOR) && (ValEntTOR(DI_DCY, 0))
                || (PAR.CommandeSerie) && (EXP.Command1 & 0x0001)))
    {
        EXP.PosCycleRegulation = 10;
        T100[timer_Volumetrique] = PAR.TempsFonctVolumetrique;
    }

//    EXP.Command1 = EXP.Command1 & 0xFFFE;
    EXP.Profibus_Command = EXP.Profibus_Command & 0xFFFE;
    EXP.Etat1 = EXP.Etat1 & 0xFFFE;                                             // Bit installation à l'arrêt
    EXP.Etat1 = EXP.Etat1 & 0xFFFB;                                             // Bit installation suspendu
    EXP.Etat1 = EXP.Etat1 | 0x0002;                                             // Bit installation en marche
    sortiesTOR(DO_CommandeBande, 1);                                            // Commande marche bande
}

// Suspension
if (PAR.CommandeSerie && (EXP.Command1 & 0x0002))                               // Suspension
{
    EXP.Command1 = EXP.Command1 & 0xFFFD;
    EXP.Etat1 = EXP.Etat1 & 0xFFFD;                                             // Bit installation en marche
    EXP.Etat1 = EXP.Etat1 | 0x0001;                                             // Bit installation à l'arrêt
    sortiesTOR(DO_CommandeBande, 0);                                            // Commande arrêt bande
}

// Abandon
if ((PAR.CommandeSerie && ((EXP.Command1 & 0x0004)                              // Abandon
            || (EXP.Profibus_Command & 0x0004)))                                // Abandon
        || ((PAR.CommandeTOR) && (!ValEntTOR(DI_DCY, 0))))
{
    EXP.Command1 = EXP.Command1 & 0xFFFB;
    EXP.Profibus_Command = EXP.Profibus_Command & 0xFFFD;
    EXP.Etat1 = EXP.Etat1 & 0xFFFD;                                             // Bit installation en marche
    EXP.Etat1 = EXP.Etat1 & 0xFFFB;                                             // Bit installation suspendu
    EXP.Etat1 = EXP.Etat1 | 0x0001;                                             // Bit installation à l'arrêt
    sortiesTOR(DO_CommandeBande, 0);                                            // Commande arrêt bande

    if (PAR.OP_Doseur)
    {
        EXP.PosCycleRegulation = 0;
    }
}

// Gestion des sorties défauts
sortiesTOR(DO_DefPoidsMax,       ((EXP.Defaut1 & 0x0100) == 0x0100));           // Poids > poids max
sortiesTOR(DO_DefDebitMax,       ((EXP.Defaut1 & 0x0200) == 0x0200));           // Débit > débit max
sortiesTOR(DO_DefDebitMin,       ((EXP.Defaut1 & 0x0400) == 0x0400));           // Débit < débit min
sortiesTOR(DO_DefVitesseMin,     ((EXP.Defaut1 & 0x0800) == 0x0800));           // Vitesse < vitesse min
sortiesTOR(DO_DefautCapteur,     ((EXP.Defaut1 & 0x1000) == 0x1000));           // Défaut capteur

sortiesTOR(DO_DefDeviationMoins, ((EXP.Defaut2 & 0x0001) == 0x0001));           // Défaut tolérance -
sortiesTOR(DO_DefDeviationPlus,  ((EXP.Defaut2 & 0x0002) == 0x0002));           // Défaut tolérance +

// Acquittement défauts
if ((EXP.Command1 & 0x0008)                                                     // Acquittement défauts
        || (EXP.Profibus_Command & 0x0008)                                      // Acquittement défauts
        || (ValEntTOR(DI_AcqDefauts, 0)))                                       // Acquittement défauts
{
    EXP.Command1 = EXP.Command1 & 0xFFF7;
    EXP.Profibus_Command = EXP.Profibus_Command & 0xFFF7;

    T100[timer_DefautPoidsMax]       = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0100) == 0x0100);
    T100[timer_DefautDebitMax]       = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0200) == 0x0200);
    T100[timer_DefautDebitMin]       = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0400) == 0x0400);
    T100[timer_DefautVitesseMin]     = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x0800) == 0x0800);
    T100[timer_DefautCapteur]        = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut1&0x1000) == 0x1000);
    T100[timer_DefautDeviationMoins] = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut2&0x0001) == 0x0001);
    T100[timer_DefautDeviationPlus]  = PAR.TempoDefaut*10*((PAR.AffectTempoDefaut2&0x0002) == 0x0002);

    EXP.Defaut1 = 0;
    EXP.Defaut2 = 0;
}

// RAZ moyenne débit
if (EXP.Command2 & 0x0004)                                                      // RAZ moyenne débit
{
    EXP.Command2 = EXP.Command2 & 0xFFFB;

    PAR.DateDerniereRAZ[0] = EXP.Date[6]; PAR.DateDerniereRAZ[1] = EXP.Date[7]; PAR.DateDerniereRAZ[2] = '/';
    PAR.DateDerniereRAZ[3] = EXP.Date[4]; PAR.DateDerniereRAZ[4] = EXP.Date[5]; PAR.DateDerniereRAZ[5] = '/';
    PAR.DateDerniereRAZ[6] = EXP.Date[0]; PAR.DateDerniereRAZ[7] = EXP.Date[1];
    PAR.DateDerniereRAZ[8] = EXP.Date[2]; PAR.DateDerniereRAZ[9] = EXP.Date[3];
    PAR.DateDerniereRAZ[10] = 0x20;
    PAR.DateDerniereRAZ[11] = EXP.Heure[0]; PAR.DateDerniereRAZ[12] = EXP.Heure[1]; PAR.DateDerniereRAZ[13] = ':';
    PAR.DateDerniereRAZ[14] = EXP.Heure[2]; PAR.DateDerniereRAZ[15] = EXP.Heure[3];

    PAR.TempsArret = 0;
    PAR.TempsMarcheTotalisation = 0;
    PAR.TempsMarche = 0;
    PAR.TempsMarcheVide = 0;

    PAR.DebitMaxLot = 0;
    PAR.TotDebitMoyen = 0;
    PAR.NbTotDebitMoyen = 0;
    EXP.DebitMoyenLot = 0;
}

// RAZ totalisateur partiel
if (((EXP.Command1 & 0x0010)                                                    // RAZ totalisateur partiel
        || (EXP.Profibus_Command & 0x0020))                                     // RAZ totalisateur partiel
        || ((ValEntTOR(DI_RAZ_TotPartiel, 0))))                                 // RAZ totalisateur partiel
{
    EXP.Command1 = EXP.Command1 & 0xFFEF;
    EXP.Profibus_Command = EXP.Profibus_Command & 0xFFDF;
    EXP.TotalPartiel1 = 0;
    EXP.TotalPartiel2 = 0;
    EXP.CptTotalPartiel1 = 0;
    EXP.CptTotalPartiel2 = 0;
    EXP.CptTotalPartiel = 0;

    EXP.CptTotalPartiel1B = 0;
    EXP.CptTotalPartiel2B = 0;
    EXP.CptTotalPartielB = 0;
    CompteurTot++;
}

// RAZ totalisateur global
if (((EXP.Command1 & 0x0020)                                                    // RAZ totalisateur global
        || (EXP.Profibus_Command & 0x0040))                                     // RAZ totalisateur global
        || (ValEntTOR(DI_RAZ_TotGlobal, 0)))                                    // RAZ totalisateur partiel
{
    EXP.Command1 = EXP.Command1 & 0xFFDF;
    EXP.Profibus_Command = EXP.Profibus_Command & 0xFFBF;
    EXP.TotalGlobal1 = 0;
    EXP.TotalGlobal2 = 0;
    EXP.CptTotalGlobal1 = 0;
    EXP.CptTotalGlobal2 = 0;
}

// Impression totalisateur partiel
if (((EXP.Command1 & 0x0040)                                                    // Impression totalisateur partiel
        || (ValEntTOR(DI_ImpressionTotPartiel, 0)))
        && (!EXP.DI_ImpressionTotPartielMem))
{
    if (PAR.Impr_NumTicket < 60000)
        PAR.Impr_NumTicket++;
    else
        PAR.Impr_NumTicket = 1;
    ImpressionTotalisateur(EXP.TotalPartiel2, EXP.TotalPartiel1, 1);
}
EXP.DI_ImpressionTotPartielMem = ((EXP.Command1 & 0x0040) || ValEntTOR(DI_ImpressionTotPartiel, 0));
EXP.Command1 = EXP.Command1 & 0xFFBF;

// Impression totalisateur global
if (((EXP.Command1 & 0x0080)                                                    // Impression totalisateur global
        || (ValEntTOR(DI_ImpressionTotGlobal, 0)))
        && (!EXP.DI_ImpressionTotGlobalMem))
{
    if (PAR.Impr_NumTicket < 60000)
        PAR.Impr_NumTicket++;
    else
        PAR.Impr_NumTicket = 1;
    ImpressionTotalisateur(EXP.TotalGlobal2, EXP.TotalGlobal1, 2);
}
EXP.DI_ImpressionTotGlobalMem = ((EXP.Command1 & 0x0080) || ValEntTOR(DI_ImpressionTotGlobal, 0));
EXP.Command1 = EXP.Command1 & 0xFF7F;

// Impression ticket
if (EXP.Command2 & 0x0002)                                                     // Impression ticket
{
    if (PAR.Impr_NumTicket < 60000)
        PAR.Impr_NumTicket++;
    else
        PAR.Impr_NumTicket = 1;
    ImpressionTotalisateur(0, 0, 1);
}
EXP.Command2 = EXP.Command2 & 0xFFFD;

GestionCyclePesage();
if (PAR.OP_Doseur)
    RegulationDoseur();
}


int ValEntTOR(int numFonction, int etatDefaut)
{
int         indice;

for (indice=1; indice<=9; indice++)
{
    if (PAR.EntreeTOR[indice] == numFonction)
        return(entTOR[indice-1]);
}
return(etatDefaut);
}


void gestion_vitesse(void)
{
float           interf;
float           interf2;
int             Cpt;

if (!T100[timer_VitesseNulle])
{
    EXP.Vitesse = 0;
    EXP.TotPulseReglage = 0;
//    ResetCounterMillis();
}

// Gestion des 2 entrée sous interruption
if ((PAR.EntreeTOR[8] == DI_VitesseMene)
        || (PAR.EntreeTOR[9] == DI_VitesseMene))
{
    if (PAR.EntreeTOR[9] == DI_VitesseMene)
    {
        EXP.TempsVitesse = EXP.TempsVitesse1;
        Cpt = EXP.CptInt1;
    }
    else
    {
        EXP.TempsVitesse = EXP.TempsVitesse2;
        Cpt = EXP.CptInt2;
    }

    if (((EXP.TempsVitesse >= 400) && (Cpt >= 2))
        || ((EXP.TempsVitesse >= 100) && (Cpt >= 100)))
    {
        interf = EXP.TempsVitesse;
        
        if (PAR.EntreeTOR[9] == DI_VitesseMene)
        {
            interf2 = 1.025 * Cpt * (PAR.CirconfTambMene/(float)PAR.ImpTambMene)/(interf/1000);
            EXP.CptInt1 = -1;
        }
        if (PAR.EntreeTOR[10] == DI_VitesseMene)
        {
            interf2 = 1.025 * Cpt * (PAR.CirconfTambMene/(float)PAR.ImpTambMene)/(interf/1000);
            EXP.CptInt2 = -1;
        }
        EXP.Vitesse = (EXP.Vitesse + interf2) / 2;
//        EXP.Vitesse = interf2;
    }
    EXP.TempsMemVitesse = 0;
}
else
{
    if ((ValEntTOR(DI_VitesseMene, 0)) && (!entreeTorVitesseMem))
    {
        if (EXP.AttenteCalculVitesse)
        {
            ResetCounterMillis();
            EXP.AttenteCalculVitesse = 0;
        }
        else
            EXP.TotPulseVitesse++;
    
        EXP.TotPulseReglage++;
        T100[timer_VitesseNulle] = 30;                                          // 3s
        EXP.PulseTotal++;
        
        EXP.TempsVitesse = GetCounterMillis();

        if ((EXP.TempsVitesse >= 1000) && (EXP.TotPulseVitesse >= 20))
        {
            interf = EXP.TempsVitesse;
            interf2 = EXP.TotPulseVitesse * (PAR.CirconfTambMene/(float)PAR.ImpTambMene)/(interf/1000);
            EXP.Vitesse = (2*EXP.Vitesse + interf2) / 3;
            
            EXP.AttenteCalculVitesse = 1;
            EXP.TotPulseVitesse = 0;
        }
        EXP.TempsMemVitesse = EXP.TempsVitesse;
    }

    entreeTorVitesseMem = ValEntTOR(DI_VitesseMene, 0);
}

if (PAR.VitesseManu > 0.0)
{
    if (EXP.Etat1 & 0x0001)
        EXP.Vitesse = 0;
    else
        EXP.Vitesse = PAR.VitesseManu;
}
}

void EnvoieSerie1(char type_serie, char trame[80], int nb_octets)
{
int             indice;
char            num_serie;

// Recherche du port série définie
num_serie = -1;
for (indice=0; indice<=5; indice++)
    if (PAR.CommType[indice] == type_serie)
        num_serie = indice;

if (num_serie >= 0)
    EnvoieSerie(num_serie+1, trame, nb_octets);
}


void EnvoieSerie(char num_serie, char trame[80], int nb_octets)
{
int             indice;

switch (num_serie)
{
    case 3 : UART3TXEN_IO = 1; Delay10us(1); break;
    case 4 : UART4TXEN_IO = 1; Delay10us(1); break;
}

indice = 0;
while(indice < nb_octets)
{
    switch (num_serie)
    {
        case 1 :    while(U1STAbits.UTXBF);                                     /* wait if the buffer is full */
                    U1TXREG = trame[indice++]; break;                           /* transfer data word to TX reg */
        case 2 :    while(U2STAbits.UTXBF);                                     /* wait if the buffer is full */
                    U2TXREG = trame[indice++]; break;                           /* transfer data word to TX reg */
        case 3 :    while(U3STAbits.UTXBF);                                     /* wait if the buffer is full */
                    U3TXREG = trame[indice++];                                  /* transfer data word to TX reg */
                    while(BusyUART3()); break;                                  // Attente de la fin de la transmission
        case 4 :    while(U4STAbits.UTXBF);                                     /* wait if the buffer is full */
                    U4TXREG = trame[indice++];                                  /* transfer data word to TX reg */
                    while(BusyUART4()); break;                                  // Attente de la fin de la transmission
    }
}

switch (num_serie)
{
    case 3 : Delay10us(1); UART3TXEN_IO = 0; break;
    case 4 : Delay10us(1); UART4TXEN_IO = 0; break;
}
    
/*
if (num_serie == COM_RS232)
{
    putsUART2(trame);
    while(BusyUART2());
}

if (num_serie == COM_RS485_1)
{
    SendStrUART3(trame);
}

if (num_serie == COM_RS485_2)
{
    SendStrUART4(trame);
}
*/
}


void gestion_totalisateurs(void)
{
float totalPartiel;

// Gestion des totalisateurs
if (((EXP.DebitMoyen >= PAR.LimiteTotalisation * PAR.DebitMax / 100)
        && ((EXP.Etat1 & 0x0002) == 0x0002))                                    // Bit installation en marche
            || ((EXP.ControlEnCours == 1) && ((EXP.Etat1 & 0x0200) == 0x0200))) // Controle en cours
{
    if (PAR.VitesseManu == 0.0)
    {
        if (EXP.ReglEnCours == 0)
        {
            EXP.TotalPartiel1 += 1.025 * PAR.Correction1 * EXP.PoidsMoyen * PAR.CirconfTambMene
                    * (EXP.PulseTotal) / PAR.ImpTambMene / PAR.LongueurPesage / 100000;
            EXP.TotalGlobal1 += 1.025 * PAR.Correction1 * EXP.PoidsMoyen * PAR.CirconfTambMene
                    * (EXP.PulseTotal) / PAR.ImpTambMene / PAR.LongueurPesage / 100000;
        }
        if (EXP.Etat1 & 0x0080)                                                 // Etalonnage en cours
            EXP.TotalReglageFloat += 1.025 * PAR.Correction1 * EXP.PoidsMoyen * PAR.CirconfTambMene
                    * (EXP.PulseTotal) / PAR.ImpTambMene / PAR.LongueurPesage / 100000;

        if ((EXP.DebitMoyen >= PAR.LimiteTotalisation * PAR.DebitMax / 100)
                && (EXP.Etat1 & 0x0200))                                        // Controle en cours
            EXP.TotalReglageFloat += 1.025 * PAR.Correction1 * EXP.PoidsMoyen * PAR.CirconfTambMene
                    * (EXP.PulseTotal) / PAR.ImpTambMene / PAR.LongueurPesage / 100000;

        EXP.TotalReglage = 1000.0 * EXP.TotalReglageFloat;
        EXP.PulseTotal = 0;
    }
    else
    {
        if (!T100[timer_VitesseManu])
        {
            NbTopTotal = NbTopTotal + 1;
            totalPartiel = (PAR.Correction1 / 100) * EXP.PoidsMoyen * PAR.VitesseManu / PAR.LongueurPesage / 1000;

            if (EXP.ReglEnCours == 0)
            {
                EXP.TotalPartiel1 += totalPartiel;
                EXP.TotalGlobal1 += totalPartiel;
            }
            if (EXP.Etat1 & 0x0080)                                             // Etalonnage en cours
                EXP.TotalReglageFloat += totalPartiel;

            if ((EXP.DebitMoyen >= PAR.LimiteTotalisation * PAR.DebitMax / 100)
                    && (EXP.Etat1 & 0x0200))                                    // Controle en cours
                EXP.TotalReglageFloat += totalPartiel;
            
            EXP.TotalReglage = 1000.0 * EXP.TotalReglageFloat;

            T100[timer_VitesseManu] = 10;
        }
    }
}
else
    EXP.PulseTotal = 0;

verif_totaux();

/*
    if (regl_en_cours>=2)
            {
            if (P_vitesse_man==0.0)
                    {
                    if (control)
                            tot_reg+=P_correction*poids_moyen_aff*P_c_tamb_mene*(pulse_total)/P_imp_tamb_mene/P_long_pesage/1000;
                    else
                            tot_reg+=poids_moyen_aff*P_c_tamb_mene*(pulse_total)/P_imp_tamb_mene/P_long_pesage/1000;
                    }
            else
                    {
                    if (PULSE_TOT3)
                            {
                            if (control)
                                    tot_reg+=P_correction*poids_moyen_aff*P_vitesse_man/P_long_pesage/1000/2;
                            else
                                    tot_reg+=poids_moyen_aff*P_vitesse_man/P_long_pesage/1000/2;
                            }
                    }
            }
     */
}


void verif_totaux(void)
{
int                 echelon;
float               inter;
float               total_diffAB;

while (EXP.TotalPartiel1 >= 10)
{
    EXP.TotalPartiel1 = EXP.TotalPartiel1 - 10;
    EXP.TotalPartiel2++;
    if (EXP.TotalPartiel2 >= 400000)
        EXP.TotalPartiel2 = 0;
}

while (EXP.TotalGlobal1 >= 10)
{
    EXP.TotalGlobal1 = EXP.TotalGlobal1 - 10;
    EXP.TotalGlobal2++;
    if (EXP.TotalGlobal2 >= 400000)
        EXP.TotalGlobal2 = 0;
}

echelon = 1000 / PAR.EchelonSortieTotVal;

// Totalisateur partiel
if (EXP.CptTotalPartiel2 != EXP.TotalPartiel2)
{
    inter = EXP.TotalPartiel2 - EXP.CptTotalPartiel2;
    inter = inter * 10.0 * echelon;
    EXP.CptTotalPartiel2 = EXP.TotalPartiel2;
    
    while ((inter + EXP.TotalPartiel1 * echelon) >= (EXP.CptTotalPartiel1 + 1))
    {
        CompteurTot++;
        EXP.CptTotalPartiel1++;
        EXP.CptTotalPartiel++;
    }
    //EXP.CptTotalPartiel1 = EXP.TotalPartiel1 * echelon;
    EXP.CptTotalPartiel1 = 0;
}
else
{
    while ((EXP.TotalPartiel1 * echelon) >= (EXP.CptTotalPartiel1 + 1))
    {
        CompteurTot++;
        EXP.CptTotalPartiel1++;
        EXP.CptTotalPartiel++;
    }
}

if ((EXP.CptTotalPartiel > 0) && (T10[timer_NivBasTot] == 0) && (etatSortieTOR(DO_Totalisateur) == 0))
{
    sortiesTOR(DO_Totalisateur, 1);
    T10[timer_NivHautTot] = PAR.LongPulseSortie/10;
    EXP.CptTotalPartiel--;
}
if ((T10[timer_NivHautTot] == 0) && (etatSortieTOR(DO_Totalisateur) == 1))
{
    sortiesTOR(DO_Totalisateur, 0);
    T10[timer_NivBasTot] = PAR.LongPulseSortie/10;
}

// Totalisateur différence
EXP.TotalPartiel2B = EXP.TotalPartiel2;
EXP.TotalPartiel1B = EXP.TotalPartiel1;

inter = EXP.TotalPartielB; inter /= 1000;
total_diffAB = EXP.TotalPartiel2 * 10 + EXP.TotalPartiel1 - inter;

while ((total_diffAB * echelon) >= (EXP.CptTotalPartiel1B + 1))
{
    EXP.CptTotalPartiel1B++;
    EXP.CptTotalPartielB++;
}

if ((EXP.CptTotalPartielB > 0) && (T10[timer_NivBasTotB] == 0) && (etatSortieTOR(DO_TotalisateurBA) == 0))
{
    sortiesTOR(DO_TotalisateurBA, 1);
    T10[timer_NivHautTotB] = PAR.LongPulseSortie/10;
    EXP.CptTotalPartielB--;
}
if ((T10[timer_NivHautTotB] == 0) && (etatSortieTOR(DO_TotalisateurBA) == 1))
{
    sortiesTOR(DO_TotalisateurBA, 0);
    T10[timer_NivBasTotB] = PAR.LongPulseSortie/10;
}
 
}


int etatSortieTOR(int numFonction)
{
int         indice;

for (indice=1; indice<=8; indice++)
    if (PAR.SortieTOR[indice] == numFonction)
        return(sorTOR[indice]);
return(0);
}


void forcageSortiesTOR(void)
{
int         indice;
char        etat1;

for (indice=1; indice<=8; indice++)
{
    if (EXP.Forcage1SortieTOR[indice])
        etat1 = !PAR.InversionSortieTOR[indice];
    else
    {
        if (EXP.Forcage0SortieTOR[indice])
            etat1 = PAR.InversionSortieTOR[indice];
        else
        {
            if (PAR.InversionSortieTOR[indice])
                etat1 = !sorTOR[indice];
            else
                etat1 = sorTOR[indice];
        }
    }
    
    switch (indice)
    {
        case 1: OUT1_IO = etat1; break;
        case 2: OUT0_IO = etat1; break;
        case 3: OUT2_IO = etat1; break;
        case 4: OUT3_IO = etat1; break;
        case 5: OUT4_IO = etat1; break;
        case 6: OUT5_IO = etat1; break;
        case 7: OUT6_IO = etat1; break;
        case 8: OUT7_IO = etat1; break;
    }
}
}


void sortiesTOR(char numFonction, char etat)
{
int         indice;

for (indice=1; indice<=8; indice++)
    if (PAR.SortieTOR[indice] == numFonction)
    {
        if (etat != 3)
            sorTOR[indice] = etat;
        else
            sorTOR[indice] = !sorTOR[indice];
    }
}


void gestion_poids(void)
{
float           poidsAff;
long            interL;

if (EXP.NouveauPoids)
{
    conversion_poids();
    moyenne_glissante_poids();
    EXP.NouveauPoids = 0;
}

// Création poids afficheur
if (EXP.PoidsMoyen > 0)
    poidsAff = EXP.PoidsMoyen + (PAR.EchelonPoidsVal/2);
else
    poidsAff = EXP.PoidsMoyen - (PAR.EchelonPoidsVal/2);
poidsAff = poidsAff / PAR.EchelonPoidsVal;
interL = poidsAff;
poidsAff = interL * PAR.EchelonPoidsVal;
EXP.PoidsMoyenAff = poidsAff;

// Création du poids au mètre
EXP.PoidsMetre = EXP.PoidsMoyen / PAR.LongueurPesage;

// Création du poids au mètre carre
EXP.PoidsMetreCarre = (EXP.PoidsMetre*10000*1000 / PAR.LargeurBande);
}


void gestion_debit(void)
{
float           interF;

EXP.DebitTR = (PAR.Correction1 / 100) * EXP.Vitesse * EXP.PoidsMoyen * 3.6 / PAR.LongueurPesage;

if (EXP.DebitTR < 0)
    EXP.DebitTR = 0;

if (PAR.FiltreDebit == 0)
    EXP.DebitMoyen = EXP.DebitTR;
else
//    EXP.DebitMoyen += ((PAR.Correction1 / 100) * EXP.Vitesse * EXP.PoidsMoyen
//        * 3.6 / PAR.LongueurPesage - EXP.DebitMoyen) / PAR.FiltreDebit;
    EXP.DebitMoyen = (EXP.DebitMoyen * PAR.FiltreDebit + EXP.DebitTR) / (PAR.FiltreDebit+1);

interF = PAR.DebitMax*PAR.ZoneMorte/100;                                        // Débit = 0 si on est dans bande morte
if ((EXP.DebitTR <= interF) && (EXP.DebitTR >= -interF))
{
    EXP.DebitTR = 0;
    EXP.DebitMoyen = 0;
}

if (EXP.DebitMoyen*10000 > PAR.DebitMaxLot)
    PAR.DebitMaxLot = EXP.DebitMoyen*10000;
}


void envoyer_reel(float valeur, char nb_chiffre, char nb_chiffre_apv, char signe, char zero)
{
char strRes[20];
char format[10];
int indice = 0;

format[indice++] = '%';
if (signe) format[indice++] = '+';
if (zero) format[indice++] = '0';
if (nb_chiffre >= 10)
{
    format[indice++] = 0x30 + ((int) nb_chiffre / 10);
    format[indice++] = 0x30 + (nb_chiffre - ((int) nb_chiffre / 10)*10);
}
else
    format[indice++] = 0x30 + nb_chiffre;
format[indice++] = '.';
format[indice++] = 0x30 + nb_chiffre_apv;
format[indice++] = 'f';
format[indice++] = '\0';

sprintf(strRes, format, valeur);
putsUART2(strRes);
}

void moyenne_glissante_debit()
{
EXP.DebitTR = EXP.PoidsMoyen * EXP.Vitesse;

if (PAR.FiltreDebit == 0)
    EXP.DebitMoyen = EXP.DebitTR;
else
    EXP.DebitMoyen = (EXP.DebitMoyen * PAR.FiltreDebit + EXP.DebitTR) / (PAR.FiltreDebit +1);
}


void moyenne_glissante_poids()
{
int             i;
float           v;
int             valFrequence;
long            valNbMoyenne;
float           poidsMoyen;
long            indiceMaxFiltrePoids;
unsigned int    filtrePoids;
long            nbMesures;

filtrePoids = PAR.FiltrePoids & 0x00FF; 
filtrePoids = filtrePoids*2;
if (filtrePoids == 0)
{
    EXP.PoidsMoyen = EXP.PoidsTR;
    return;
}

switch (PAR.FrequencePoids)
{
    case 1 : valFrequence = 1200/4.3; break;
    case 2 : valFrequence = 1000/3.5; break;
    case 3 : valFrequence = 800/3; break;
    case 4 : valFrequence = 600/2.2; break;
    case 5 : valFrequence = 400/1.5; break;
    case 6 : valFrequence = 200*1.25; break;
    case 7 : valFrequence = 100*2; break;
    case 8 : valFrequence = 50*5; break;
}

nbMesures = filtrePoids;
nbMesures = (nbMesures * valFrequence)/10;
if (nbMesures >= 200)
{
    valNbMoyenne = nbMesures / 200;
    EXP.TotalValMoyenne += EXP.PoidsTR;
    EXP.indiceNbValMoyenne++;
    indiceMaxFiltrePoids = 200;
    
    if (EXP.indiceNbValMoyenne > valNbMoyenne)
    {
        poidsMoyen = EXP.TotalValMoyenne / EXP.indiceNbValMoyenne;
        EXP.indiceNbValMoyenne = 0;
        EXP.TotalValMoyenne = 0.0;
    }
    else
        return;
}
else
{
    poidsMoyen = EXP.PoidsTR;
    indiceMaxFiltrePoids = nbMesures;
}

if (EXP.indiceFiltrePoids >= indiceMaxFiltrePoids)
{
    EXP.indiceFiltrePoids = 1;
    EXP.tableauFiltrePoidsPlein = 1;
}
else
    EXP.indiceFiltrePoids++;
EXP.T_FiltrePoids[EXP.indiceFiltrePoids] = poidsMoyen;
    
if ((abs(poidsMoyen - EXP.PoidsMoyen) > (float)PAR.BandeFiltrePoids/10000.0)
        && (PAR.BandeFiltrePoids > 0))
{
    EXP.tableauFiltrePoidsPlein = 0;
    EXP.indiceFiltrePoids = 1;
    EXP.T_FiltrePoids[1] = poidsMoyen;
    EXP.PoidsMoyen = poidsMoyen;
    return;
}

v = 0;
if (EXP.tableauFiltrePoidsPlein)
{
    for (i = 1; i <= indiceMaxFiltrePoids; i++)
        v += EXP.T_FiltrePoids[i];
    EXP.PoidsMoyen = v / (float)indiceMaxFiltrePoids;
}
else
{
    for (i = 1; i <= EXP.indiceFiltrePoids; i++)
        v += EXP.T_FiltrePoids[i];
    EXP.PoidsMoyen = v / (float)EXP.indiceFiltrePoids;
}
}


void conversion_poids(void)
{
EXP.PoidsTR = (float) EXP.PoidsPoints;
EXP.PoidsTR = (EXP.PoidsTR - PAR.TareInc) * PAR.Pente[1] / 100000;

if (EXP.ReglEnCours)                                                            //Réglage en cours
{
    EXP.TotIncReglageFloat += EXP.PoidsPoints;
    EXP.NbMesureReglage++;
}
}


void lecture_entrees_TOR(void)
{
entTOR[0] = (PAR.InversionEntreeTOR[1] ^ (!IN0_IO));
entTOR[1] = (PAR.InversionEntreeTOR[2] ^ (!IN1_IO));
entTOR[2] = (PAR.InversionEntreeTOR[3] ^ (!IN2_IO));
entTOR[3] = (PAR.InversionEntreeTOR[4] ^ (!IN3_IO));
entTOR[4] = (PAR.InversionEntreeTOR[5] ^ (!IN4_IO));
entTOR[5] = (PAR.InversionEntreeTOR[6] ^ (!IN5_IO));
entTOR[6] = (PAR.InversionEntreeTOR[7] ^ (!IN6_IO));
entTOR[7] = (PAR.InversionEntreeTOR[8] ^ (!IN7_IO));

Cav_USR1 = C1_IO;
Cav_CLR = C2_IO;
}


void EcritSortieAna(void)
{
int             indice;
unsigned long   interul;
float           interf;
float           interf2;
float           interf3;
char            reponse[80];
int             interi;
float           corrPenteAna;

T10[timer_EcritSortieAna] = 20;

for (indice=COM_RS232; indice<=COM_RS485_2; indice++)
{
    if ((PAR.CommType[indice] == COMM_ADAM_4021)
            || (PAR.CommType[indice] == COMM_ADAM_4024)
            || (PAR.CommType[indice] == COMM_ANA_BASIA4))
    {
        EXP.PourcSortieAna[(int)EXP.NumSortieAna] = 0;
        EXP.SortieAna[(int)EXP.NumSortieAna] = 0;
    
        switch (PAR.ValSortieANA[(int)EXP.NumSortieAna])
        {
            case AO_DEBIT :
                interf = (EXP.DebitMoyen/PAR.DebitMax)*4096;
                break;
            case AO_POIDS :
                interf = (EXP.PoidsMoyen/PAR.PoidsMax)*10000*4096;
                break;
            case AO_REGUL :
            case AO_REGUL_AB :
            case AO_REGUL_BA :
                interf = EXP.SortieRegul;
                break;
            case AO_DIFFERENCE_AB :
                interf = EXP.DebitMoyen-EXP.DebitBascule2/1000;
                interf = (interf/PAR.ConsigneAnaMax)*4096*1000;
                break;
            case AO_DIFFERENCE_BA :
                interf = EXP.DebitBascule2/1000-EXP.DebitMoyen;
                interf = (interf/PAR.ConsigneAnaMax)*4096*1000;
                break;
            case AO_POIDS_METRE_CARRE :
                interf = EXP.PoidsMetreCarre; interf = interf/10000.0;
                interf2 = PAR.PoidsMax; interf2 = interf2/10000;
                interf3 = PAR.LargeurBande; interf3 = interf3/1000;
                interf = ((interf/(interf2/interf3)))*4096;
                break;
        }
        if (interf < 0.0) interf = 0.0;
        if (interf > 4096.0) interf = 4096.0;
        
        corrPenteAna = PAR.CoeffSortieAna[(int)EXP.NumSortieAna]; corrPenteAna /= 10000;
        interf = interf * corrPenteAna;
        
        if (PAR.TypeSortieANA[(int)EXP.NumSortieAna] == 2)                      // Si 4-20mA
            interf = interf/1.25 + 819 + PAR.OrigineSortieANA[(int)EXP.NumSortieAna];
    
        // Calcul des pourcentages
        interul = interf;
        interi = interul;
        EXP.SortieAna[(int)EXP.NumSortieAna] = interi;
        if (PAR.TypeSortieANA[(int)EXP.NumSortieAna] == 2)                      // Si 4-20mA
            EXP.PourcSortieAna[(int)EXP.NumSortieAna] = (EXP.SortieAna[(int)EXP.NumSortieAna]-819-PAR.OrigineSortieANA[(int)EXP.NumSortieAna])
                    *1.25*100*10/4096;
        else
            EXP.PourcSortieAna[(int)EXP.NumSortieAna] = EXP.SortieAna[(int)EXP.NumSortieAna]*100*10/4096;
        if (EXP.PourcSortieAna[(int)EXP.NumSortieAna] == 999)
            EXP.PourcSortieAna[(int)EXP.NumSortieAna] = 1000;
        
        if (PAR.CommType[indice] == COMM_ADAM_4021)
        {
            interf = interi;
            interf = (interf / 4096) * 20;
            sprintf(reponse,"#01%06.3f%c",(double)interf,0x0D);
            EXP.NumSortieAna = 1;
            EnvoieSerie(indice+1, reponse, 10);
        }
        
        if (PAR.CommType[indice] == COMM_ADAM_4024)
        {
            interf = interi;
            interf = (interf / 4096) * 20;
            if (EXP.NumSortieAna == 1)
            {
                sprintf(reponse,"#00C0%+07.3f\r",(double)interf);
                EXP.NumSortieAna = 2;
            }
            else
            {
                sprintf(reponse,"#00C1%+07.3f\r",(double)interf);
                EXP.NumSortieAna = 1;
            }
            EnvoieSerie(indice+1, reponse, 13);
        }
        
        if (PAR.CommType[indice] == COMM_ANA_BASIA4)
        {
            if (EXP.NumSortieAna == 1)
            {
                sprintf(reponse,"%cDAC A 1 %04i%c",0x3A,interi,0x00);
                EXP.NumSortieAna = 2;
            }
            else
            {
                sprintf(reponse,"%cDAC B 1 %04i%c",0x3A,interi,0x00);
                EXP.NumSortieAna = 1;
            }
            EnvoieSerie(indice+1, reponse, 14);
        }
    }
}
}
