// UTS 2000 - fichier 'pio.cpp' Conversion des noms de variables UTS en n° de variables.
// V3.7d - Le 13/10/2017.
// Les noms des variables sont dans le fichier 'config.txt'
// Dans le programme, on saisit parfois le numéro de variable directement.
// Voir aussi dans le programme UTS le menu : 'Modifications > Aide TCO : Liste des variables'.
/*****************************************************************************/
/* PIO                                                                       */
/*****************************************************************************/
/*-----------------+----+----+----+----+----+----+-----+---+------+-----+----------------------------------------------------
                   | Numéro  |cart|cart|cart|cart|Nombr|Raz|Valeur|Read | 
                   |début-fin|  0 |  1 |  2 |  3 |ou xx|auto      |Write| 
-------------------+----+----+----+----+----+----+-----+---+------+---+----------------------------------------------------
det_               |    |    |00xx|01xx|02xx|03xx|4*16 |   |0-1   | R |Détections sur cantons (ex det_0, det_15, det_315)
in_                |    |    |04xx|05xx|06xx|07xx|4*80 |   |0-1   | R |Entrées matricées  et directes
can_               |    |    |08xx|09xx|10xx|11xx|4*5  |   |0-255 | R |Valeurs des entrées analogiques
out_               |    |    |12xx|13xx|14xx|15xx|4*80 |Oui|0-1   | W |Sorties
led_               |    |    |16xx|17xx|18xx|19xx|4*48 |Oui|0-1   | W |Allumage leds
led_cli_           |    |    |20xx|21xx|22xx|23xx|4*48 |Oui|0-1   | W |Leds Mode clignotement
led_phase_         |    |    |24xx|25xx|26xx|27xx|4*48 |Oui|0-1   | W |leds Inversion de la phase du clignotement
srv_pos_           |    |    |280x|290x|300x|310x|4*5  |   |0-1023| W |Position réel du servomoteur
bal_cant_p_        |    |    |32xx|33xx|34xx|35xx|4*16 |   |0-1   | R |Bloc automatique - Canton bloqué dans le sens Plus
bal_cant_m_        |    |    |36xx|37xx|38xx|39xx|4*16 |   |0-1   | R |Bloc automatique - Canton bloqué dans le sens Moins
det2_              |    |    |4000|41xx|42xx|43xx|4*16 |   |0-1   | R |Canton occupé ou détection sur le canton avec temporisation
det2p_             |    |    |4020|41xx|42xx|43xx|4*16 |   |0-1   | R |Canton occupé ou détection sur le canton avec temporisation = N° de variable det2 + 20
det2m_             |    |    |4040|41xx|42xx|43xx|4*16 |   |0-1   | R |Canton occupé ou détection sur le canton avec temporisation = N° de variable det2 + 40
                   |    |    |4400|45xx|46xx|47xx|4*16 |   |      |   |
                   |4800|4999|    |    |    |    | 200 |   |      |   |
-------------------+----+----+----+----+----+----+-----+---+------+---+----------------------------------------------------
aig_cmd            |5000|5063|    |    |    |    |  64 |Oui|0-1   | W |Commandes des aiguillages
pos0_aig_          |5100|5163|    |    |    |    |  64 |   |0-1   | R |Aiguillages en position 0 et verrouillés (pas en mouvement) 
pos1_aig_          |5200|5263|    |    |    |    |  64 |   |0-1   | R |Aiguillages en position 1 et verrouillés (pas en mouvement)
var_               |5400|5999|    |    |    |    | 600 |Oui|0-1023|R/W|Libre pour l’utilisateur
iti_start_         |6000|6049|    |    |    |    |  50 |Oui|0-1 Z*| W |Activation d’un itinéraire (*automatiquement remis à zéro)
iti_stop_          |6100|6149|    |    |    |    |  50 |Oui|0-1 Z*| W |Désactivation d’un itinéraire (*automatiquement remis à zéro)
iti_wait_          |6200|6249|    |    |    |    |  50 |   |0-1   | R |Itinéraire en attente
iti_ok             |6300|6349|    |    |    |    |  50 |   |0-1   | R |Itinéraire établit
                   |6400|6499|    |    |    |    | 100 |   |      |   |
-------------------+----+----+----+----+----+----+-----+---+------+---+----------------------------------------------------
depl_start_run_    |6500|6699|    |    |    |    | 200 |Oui|0-1 Z*|R/W|Lance un déplacement (*automatiquement remis à zéro)
depl_stop_         |6700|6899|    |    |    |    | 200 |Oui|0-1 Z*| W |Arrêt prématuré d’un déplacement (*automatiquement remis à zéro)
garage_lock_cmd_   |6900|6915|    |    |    |    |  16 |Oui|0-1   | W |Commandes de verrouillage des garages
garage_lock_status_|6950|6965|    |    |    |    |  16 |   |0-1   | R |Etats de verrouillage des garages
vib_on             |7000|    |    |    |    |    |     |   |0-1   | W |Activation du vibreur
vib_state          |7002|    |    |    |    |    |     |   |0-1   | R |Etat du vibreur
screen_mode        |7003|    |    |    |    |    |     |   |0-1   | R |Numéro d'écran affiché 
arret_urg_on       |7004|    |    |    |    |    |     |Oui|0-1   | W |Arrêt/marche de la fonction d'arrêt d'urgence (Bouton poussoir)
arret_urg_state    |7005|    |    |    |    |    |     |   |0-1   | R |Etat de la fonction d'arrêt d'urgence
depl_start_run_    |7100|7299|    |    |    |    | 200 |Oui|0-1 Z*|R/W|Lance un déplacement (*automatiquement remis à zéro) (suite si >= 200).
depl_stop_         |7300|7499|    |    |    |    | 200 |Oui|0-1 Z*| W |Arrêt prématuré d’un déplacement (*automatiquement remis à zéro) (suite si >= 200).
                   |7500|7699|    |    |    |    | 200 |   |      |   |
                   |7700|7899|    |    |    |    | 200 |   |      |   |
                   |7900|7999|    |    |    |    | 100 |   |      |   |
-------------------+----+----+----+----+----+----+-----+---+------+---+----------------------------------------------------
srv_cmd_           |    |    |800x|810x|820x|830x| 4*5 |   |0-1023| W |Consigne du servomoteur
srv_cmd_           |    |    |801x|811x|821x|831x| 4*5 |   |0-1023| W |Consigne de vitesse du servo = n° servo + 10.
exe_               |8400|8499|    |    |    |    | 100 |Oui|0-1 Z*| W |Lance un programme,utile pour les sons (*automatiquement remis à zéro)
pulse_cmd_         |8500|8531|    |    |    |    |  32 |Oui|0-1 Z*| W |Déclenchement d’une impulsion  (*automatiquement remis à zéro)
pb_capt_c_         |    |    |86xx|87xx|88xx|89xx| 4*16|   |0-1   | R |Problème de captage sur les cantons
pb_capt_t_         |9000|9015|    |    |    |    |  16 |   |0-1   | R |Problème de captage sur les trains
special_var_       |9100|9199|    |    |    |    | 100 |Non|0-1023|R/W|Variables renseignées par UTS
                   |9200|9399|    |    |    |    | 200 |   |      |   |
separe_            |9400|9499|    |    |    |    | 100 |Oui|0-1 Z*|R/W|Separe les trains en locomotives -wagons
regroupe_          |9500|9599|    |    |    |    | 100 |Oui|0-1 Z*|R/W|Regroupe les locomotives -wagons en trains
                   |9600|9799|    |    |    |    | 200 |   |      |   |
                   |9800|9999|    |    |    |    | 200 |   |      |   |
-------------------+----+----+----+----+----+----+-----+---+------+---+----------------------------------------------------
*/

#include  <windows.h>
#include  <string.h>
#include  <stdlib.h>
#include  <stdio.h>
#include "Train_UTS.h"

#define _CRT_SECURE_NO_WARNINGS  // Limite les messages de warning dans Visual C++

// Déclaration des fonctions externes
extern void log(char* sz);

// Déclaration des variables externes
extern int vio_det[NB_CARTE][NB_CANTON];
extern int vio_bal_cant_p[NB_CARTE][NB_CANTON];				// 0-1, 1 = Bloc automatique - Canton bloqué dans le sens Plus
extern int vio_bal_cant_m[NB_CARTE][NB_CANTON];				// 0-1, 1 = Bloc automatique - Canton bloqué dans le sens Moins
extern int vio_canton_vit[NB_CARTE][NB_CANTON];      //UU: n'en garder qu'un et mettre en debug total
extern int canton_pb_capt[NB_CARTE][NB_CANTON];
extern int serial_debug_canton_vit[NB_CARTE][NB_CANTON];
extern int serial_debug_select_canton_vit[NB_CARTE][NB_CANTON];

extern int vio_out[NB_CARTE][NB_OUT];
extern int serial_debug_out[NB_CARTE][NB_OUT];
extern int serial_debug_select_out[NB_CARTE][NB_OUT];

extern int vio_in[NB_CARTE][NB_IN];

extern int vio_can[NB_CARTE][NB_CAN];

extern int vio_led[NB_CARTE][NB_LED];
extern int vio_led_cli[NB_CARTE][NB_LED];
extern int vio_led_phase[NB_CARTE][NB_LED];
extern int serial_debug_led[NB_CARTE][NB_LED];
extern int serial_debug_select_led[NB_CARTE][NB_LED];
extern int serial_debug_led_cli[NB_CARTE][NB_LED];
extern int serial_debug_led_phase[NB_CARTE][NB_LED];

extern int vio_aig_res[NB_AIG];
extern int vio_aig_cmd[NB_AIG];
extern int vio_aig_pos0[NB_AIG];
extern int vio_aig_pos1[NB_AIG];
extern int iti_tab[ITI_TAB_NB][ITI_TAB_IND_TAILLE];

extern int depl_tab[DEPL_TAB_NB][DEPL_TAB_IND_TAILLE];
extern int vib_on;      //dans pio
extern int vib_state;   //dans pio
extern int screen_mode;
extern int arret_urg_on;      //dans pio
extern int cmd_divers[CMD_DIVERS_TAILLE]; // Tableau pour commander directement les déplacements par clic sur les cases du TCO

extern int pio_pulse_cmd[NB_PULSE];

extern int vio_srv[NB_CARTE][NB_SERVO];
extern int vio_srv_res[NB_CARTE][NB_SERVO];
extern int serial_debug_srv[NB_CARTE][NB_SERVO];
extern int serial_debug_select_srv[NB_CARTE][NB_SERVO];

extern int vio_srv_cmd[NB_CARTE][NB_SERVO+NB_SERVO_VIT];

extern int vio_garage_lock_res[NB_GARAGE]; // 0 ou 1, 1 => Garage réservé.
extern int vio_garage_lock_cmd[NB_GARAGE]; // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
extern int vio_garage_lock_status[NB_GARAGE]; // 0 ou 1, 1 => Le garage est isolé du canton (état réel).

extern int pio_exe[NB_EXE];
extern int cfg_enable_leds[NB_CARTE];

extern int train_pb_capt[NB_TRAIN];  // 0 ou 1, 1 => Le train n'est pas détecté sur les cantons.
extern int separe_tab[SEPARE_TAB_NB][SEPARE_TAB_IND_TAILLE];
extern int regroupe_tab[REGROUPE_TAB_NB][REGROUPE_TAB_IND_TAILLE];
extern char gszErr[1024];
extern int det_elabore[NB_CARTE][NB_CANTON]; // 0-1, 1 = canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore.
extern int det_elaborep[NB_CARTE][NB_CANTON]; // 0-1, 1 = canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore. Vitesse train > 0.
extern int det_elaborem[NB_CARTE][NB_CANTON]; // 0-1, 1 = canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore. Vitesse train < 0.


#ifndef VERSION_UTS_V3 // Ne pas toucher à cette ligne !!!
extern int cfg_enable_servos[NB_CARTE][NB_SERVO];
#endif


int pio_var[NB_VAR];             // Tableau des variables utilisateur.
int special_var[NB_SPECIAL_VAR]; // Tableau des variables spéciales.
int pio_tdv_ind[NB_TDV+1];         // Validité d'une table de vérité. -1 = invalide ou indicateur d'offset de cette table dans 'pio_tab[]'.
int pio_tdv_on_off[NB_TDV];      // Table de vérité en fonction si =1.

int pio_pulse_cmd[NB_PULSE];
int pio_var_add_indice; //remplacer var par tab

int pio_define_convert(char ch_user[],char ch_syst[])
{
//    int i;
//    for(i=0;i<pio_define_next_entry;i++) {
//        if(!strcmp(ch_user,&pio_define_string_tab[pio_define_index[i][0]])) {
//            strcpy(ch_syst,&pio_define_string_tab[pio_define_index[i][1]]);
//            return 1;
//        }
//    }
    return 0;
}


/*void pio_define_list(void)
{
    FILE* pf;
    int i;
    pf=fopen("debug_define","wt");
    for(i=0;i<pio_define_next_entry;i++) fprintf(pf,"\n%d: %s --> %s",i,&pio_define_string_tab[pio_define_index[i][0]],&pio_define_string_tab[pio_define_index[i][1]]);
    fclose(pf);
}*/


/* Général */
// permet représenter une variable par un nombre (plus facile à manipuler qu'une chaine)
// Général.
// Dans la fenêtre d'édition, affiche un texte quand on a saisi un numéro de variable.
char* pio_var_ch[]=
{ //                               "xxxx" = obligatoirement un nombre sur 4 chiffres.  
	"det2p_"             ,"4x16"  ,"4020",	// Canton occupé ou détection sur le canton avec temporisation. Vitesse > 0
	"det2m_"             ,"4x16"  ,"4040",	// Canton occupé ou détection sur le canton avec temporisation. Vitesse < 0
	"det2_"              ,"4x16"  ,"4000",	// Canton occupé ou détection sur le canton avec temporisation. Mettre en dernier sinon det2 sort à chaque fois.
	"det_"               ,"4x16"  ,"0000",     // Détection des trains par canton.
	"can_"               ,"4x5"   ,"0800" ,	// Valeur des entrées analogiques.
    "in_"                ,"4x80"  ,"0400" ,  // Valeur des entrées numériques, passe de 4x36 à 4x80 en V3.3
    "out_"               ,"4x80"  ,"1200",	// Valeur des sorties numériques, passe de 4x40 à 4x80 en V3.3
    "led_phase_"         ,"4x48"  ,"2400",	// !!! Mettre "led_phase" et "led_cli" en premier pour le test 
    "led_cli_"           ,"4x48"  ,"2000",	// !!! sinon "led_" sort à chaque fois pour les 3 lignes sur les leds.
    "led_"               ,"4x48"  ,"1600",	// !!!
    "srv_pos_"           ,"4x5"   ,"2800",	// V3.3
    "bal_cant_p_"        ,"4x16"  ,"3200",	// Bloc automatique - Canton bloqué dans le sens Plus.
    "bal_cant_m_"        ,"4x16"  ,"3600",	// Bloc automatique - Canton bloqué dans le sens Moins.
    "aig_cmd_"           ,"64"    ,"5000",	// Change de position un aiguillage.
    "pos0_aig_"          ,"64"    ,"5100",	// Demande si un aiguillage est en position 0.
    "pos1_aig_"          ,"64"    ,"5200",	// Demande si un aiguillage est en position 1.
    "var_"               ,"600"   ,"5400",
    "iti_start_"         ,"50"    ,"6000",  // Variable uniquement en écriture.
    "iti_stop_"          ,"50"    ,"6100",  // Variable uniquement en écriture.
    "iti_wait_"          ,"50"    ,"6200",
    "iti_ok_"            ,"50"    ,"6300",
    "iti_step_"          ,"50"    ,"6400",  // Variable uniquement en lecture.
    "depl_start_run_"    ,"200"   ,"6500",	// Variable uniquement en écriture.
    "depl_stop_"         ,"200"   ,"6700",  // Variable uniquement en écriture, Modifié en V3.3  6600 --> 6700  (pour 200 déplacements max).
    "garage_lock_cmd_"   ,"49"    ,"6900",  // Modifié en V3.3  6800 --> 6900.
    "garage_lock_status_","49"    ,"6950",  // Variable uniquement en lecture, Modifié en V3.3  6900 --> 6950.
    "vib_on"             ,"1"     ,"7000",
    "vib_state"          ,"1"     ,"7002",
    "screen_mode"        ,"1"     ,"7003",
    "arret_urg_on"       ,"1"     ,"7004",
    "arret_urg_state"    ,"1"     ,"7005",
	"srv_cmd_"           ,"4x15"  ,"8000",	// Consigne + Vitesse à la suite = 4x(NB_SERVO+NB_SERVO_VIT).
	"exe_"               ,"100"   ,"8400",  // Lance un executable
	"pulse_cmd_"         ,"32"    ,"8500",  // Pour commander des sélénoïde, genre dételeurs.
    "pb_capt_c_"         ,"4x16"  ,"8600",	// Problème capteur au niveau du canton.
    "pb_capt_t_"         ,"16"    ,"9000",	// Problème capteur au niveau du train.
	"special_var_"       ,"100"   ,"9100",	// Variables pour les feux tricolores, les clignotants, les automatismes.
	"separe_"            ,"100"   ,"9400",	// Separe un train en une locomotive sur le premier canton et des wagons sur le deuxième canton.
	"regroupe_"          ,"100"   ,"9500",	// Regroupe une locomotive et des wagons sur les deux cantons.
	"EOL",									// "EOL" = texte de fin de tableau.
};



// Sous-programme pour convertir le numéro interne d'une variable en une chaine de caractères du nom d'une variable.
// Exemple : pio_var_int2ch(902,ch) retourne "in_102" dans la chaine de caractères 'ch'.
// V3.4 on vérifie entièrement le n° des variables.
//
int pio_var_int2ch(int num,char szVarName[])
{
	int ind=0,min,max;

	if ((num >= 4000 && num <= 4015) || (num >= 4100 && num <= 4115) || (num >= 4200 && num <= 4215) || (num >= 4300 && num <= 4315)) {
		sprintf(szVarName, "det2_%d", num - 4000); // Série de variable de type det2_xxx  !
		return 1; 
	}
	if ((num >= 4020 && num <= 4035) || (num >= 4120 && num <= 4135) || (num >= 4220 && num <= 4235) || (num >= 4320 && num <= 4335)) {
		sprintf(szVarName, "det2p_%d", num - 4020); // Série de variable de type det2p_xxx  !
		return 1; 
	}
	if ((num >= 4040 && num <= 4055) || (num >= 4140 && num <= 4155) || (num >= 4240 && num <= 4255) || (num >= 4340 && num <= 4355)) {
		sprintf(szVarName, "det2m_%d", num - 4040); // Série de variable de type det2m_xxx  !
		return 1;
	}

	while(strcmp(pio_var_ch[ind],"EOL")) {
		min=atoi(pio_var_ch[ind+2]); // min = Premier n° interne du type de variable. (400 => in_0 ou 4000 => det2_0)
		if (strlen(pio_var_ch[ind+1]) >= 2 && pio_var_ch[ind+1][1]=='x') max=min+100*(atoi(pio_var_ch[ind+1])-1)+atoi(&pio_var_ch[ind+1][2])-1; // Exemple = "4x16".
		else                           max=min+atoi(pio_var_ch[ind+1])-1; // max = Dernier n° interne du type de variable. (779 => in_379).
		if (num>=min && num<=max) {
			if ((strlen(pio_var_ch[ind+1])<=2) || (pio_var_ch[ind+1][1]!='x')) { // Retour de  strcmp (ch1,ch2) = 0 si chaines identiques.
				if (strcmp(pio_var_ch[ind+1],"1")) sprintf(szVarName,"%s%d",pio_var_ch[ind],num-min); // Série de variable simple mais multiple. Ex = "det_xxx".
				else sprintf(szVarName,"%s",pio_var_ch[ind]); // Série de variable simple et unique. Retour sans chiffre. Ex = "etat_vib_on".
				return 1;
			}
			else {
				if ((num-min)%100<(atoi(&pio_var_ch[ind+1][2]))) {     // N° de variable < N° de variable par canton ?
					sprintf(szVarName,"%s%d",pio_var_ch[ind],num-min); // Série de variable de type "4x16" (série par canton) !
					return 1;
				}
				else {
					sprintf(szVarName,"INVALIDE HORS-LIMITE");
					sprintf(gszErr, "\n-Erreur2 : Conversion N° variable interne => Libellé : Numéro var hors limite = %d", num); log(gszErr);
					return 0;
				}
			}
		}
		ind=ind+3;
	}
	sprintf(szVarName,"INVALIDE N° INCONNU");
	sprintf(gszErr,"\n-Erreur1 : Conversion N° variable interne => Libellé : Numéro var inconnue    = %d",num); log(gszErr);
	return 0;
}

// Sous-programme pour convertir le nom d'une variable en son numéro interne au programme
// Exemple   pio_var_ch2int_("in_102") retourne 902 = 800+100+2 = Base + 100*n°carte + N° d'entrée
//
//
int pio_var_ch2int_(char szVarName[])
{
    int i,l1,l2;
    char ch[200];

    // 1. si le nom de la variable est défini par l'utilisateur alors la remplacer par son non système.
    if(pio_define_convert(szVarName,ch)==0) strcpy(ch,szVarName);
    // 2. chercher le numéro de la variable en fonction de son nom
    i=0;
    while(STR_DIFF stricmp(PIO_VAR_NAME,"EOL")) {
        if(STR_SAME strnicmp( ch,PIO_VAR_NAME,strlen(PIO_VAR_NAME)) ) { // +1 au 26/02/2012
            if(atoi(PIO_VAR_NB)==1) return atoi(PIO_VAR_BASE);
            else if(PIO_VAR_NB[0]=='4' && PIO_VAR_NB[1]=='x') {
                l1=atoi(&ch[strlen(PIO_VAR_NAME)]);
                l2=atoi(&PIO_VAR_NB[2]);  //skip 4x
                if((l1%100)<l2) return atoi(PIO_VAR_BASE)+l1;
            }
            else {
                l1=atoi(&ch[strlen(PIO_VAR_NAME)]);
                l2=atoi(PIO_VAR_NB);
                if(l1<l2) return atoi(PIO_VAR_BASE)+l1;
            }
        }
        i++;
    }
	sprintf_s(gszErr,"\n-Erreur3 : Conversion Libellé => N° variable interne : Var inconnue = %s",ch); log(gszErr);
    return -1;
}

//
//
//
int pio_var_ch2int(char szVarName[])
{
    int ret;
    ret=pio_var_ch2int_(szVarName);
    //sprintf_s(gszErr,"\n-DBG-0000- adr: %s = %d",szVarName,ret); log(gszErr);
    return ret;
}

// pas besoin de vérifier que l'interval existe (ex: 25: vio_det_25)
// car la fonction pio_var_ch2int aura déjà signalé l'erreur

// Sous-programme pour retourner l'état de la variable passé en paramètre. 
//   Exemple : i=pio_get_val(401) => retourne la valeur de l'entrée n°1 de la carte n°0.
//
//
int pio_get_val_(int no_var)
{
    int base;
    base=0   ; if(no_var>=base && no_var<=(base+400-1)) return vio_det         [(no_var-base)/100][(no_var-base)%100];
    base=400 ; if(no_var>=base && no_var<=(base+400-1)) return vio_in          [(no_var-base)/100][(no_var-base)%100];
    base=800 ; if(no_var>=base && no_var<=(base+400-1)) return vio_can         [(no_var-base)/100][(no_var-base)%100];
    base=1200; if(no_var>=base && no_var<=(base+400-1)) return vio_out         [(no_var-base)/100][(no_var-base)%100];
    base=1600; if(no_var>=base && no_var<=(base+400-1)) return vio_led         [(no_var-base)/100][(no_var-base)%100];
    base=2000; if(no_var>=base && no_var<=(base+400-1)) return vio_led_cli     [(no_var-base)/100][(no_var-base)%100];
    base=2400; if(no_var>=base && no_var<=(base+400-1)) return vio_led_phase   [(no_var-base)/100][(no_var-base)%100];
    base=2800; if(no_var>=base && no_var<=(base+400-1)) return vio_srv         [(no_var-base)/100][(no_var-base)%100];
    base=3200; if(no_var>=base && no_var<=(base+400-1)) return vio_bal_cant_p  [(no_var-base)/100][(no_var-base)%100];
    base=3600; if(no_var>=base && no_var<=(base+400-1)) return vio_bal_cant_m  [(no_var-base)/100][(no_var-base)%100];
    base=4000; if((no_var>=4000 && no_var<=4015) || (no_var>=4100 && no_var<=4115) || (no_var>=4200 && no_var<=4215)  || (no_var>=4300 && no_var<=4315))   return det_elabore[(no_var-base)/100][(no_var-base)%100];
    base=4020; if((no_var>=4020 && no_var<=4035) || (no_var>=4120 && no_var<=4135) || (no_var>=4220 && no_var<=4235)  || (no_var>=4320 && no_var<=4335))   return det_elaborep[(no_var-base)/100][(no_var-base)%100];
    base=4040; if((no_var>=4040 && no_var<=4055) || (no_var>=4140 && no_var<=4155) || (no_var>=4240 && no_var<=4255)  || (no_var>=4340 && no_var<=4355))   return det_elaborem[(no_var-base)/100][(no_var-base)%100];
	base=5000; if(no_var>=base && no_var<=(base+100-1)) return vio_aig_cmd     [no_var-base];
    base=5100; if(no_var>=base && no_var<=(base+100-1)) return vio_aig_pos0    [no_var-base];
    base=5200; if(no_var>=base && no_var<=(base+100-1)) return vio_aig_pos1    [no_var-base];
    base=5400; if(no_var>=base && no_var<=(base+600-1)) return pio_var         [no_var-base];
    base=6200; if(no_var>=base && no_var<=(base+ITI_TAB_NB-1)) return iti_tab  [no_var-base][ITI_TAB_IND_WAIT];
    base=6300; if(no_var>=base && no_var<=(base+ITI_TAB_NB-1)) return iti_tab  [no_var-base][ITI_TAB_IND_OK];
    base=6400; if(no_var>=base && no_var<=(base+ITI_TAB_NB-1)) return iti_tab  [no_var-base][ITI_TAB_IND_STEP];       // Variable en lecture seulement
    base=6500; if(no_var>=base && no_var<=(base+DEPL_TAB_NB-1)) return depl_tab[no_var-base][DEPL_TAB_IND_START_RUN];
//	base=6700; if(no_var>=base && no_var<=(base+DEPL_TAB_NB-1)) return depl_tab[no_var-base][DEPL_TAB_IND_STEP];      // Variable en lecture seulement
    base=6900; if(no_var>=base && no_var<=(base+NB_GARAGE_REEL-1)) return vio_garage_lock_cmd[no_var-base];
    base=6950; if(no_var>=base && no_var<=(base+NB_GARAGE_REEL-1)) return vio_garage_lock_status[no_var-base];
    if(no_var==7000) return vib_on;
    if(no_var==7002) return vib_state;
    if(no_var==7003) return screen_mode;
    if(no_var==7004) return arret_urg_on;
    if(no_var==7005) return cmd_divers[CMD_DIVERS_OPT4_ARRET];
    base=8000; if(no_var>=base && no_var<=(base+400-1)) return vio_srv_cmd     [(no_var-base)/100][(no_var-base)%100];
    base=8400; if(no_var>=base && no_var<=(base+100-1)) return pio_exe         [no_var-base];
    base=8500; if(no_var>=base && no_var<=(base+100-1)) return pio_pulse_cmd   [no_var-base];
    base=8600; if(no_var>=base && no_var<=(base+400-1)) return canton_pb_capt  [(no_var-base)/100][(no_var-base)%100];
    base=9000; if(no_var>=base && no_var<=(base+ 16-1)) return train_pb_capt   [no_var-base];
    base=9100; if(no_var>=base && no_var<=(base+100-1)) return special_var     [no_var-base];
    base=9400; if(no_var>=base && no_var<=(base+SEPARE_TAB_NB-1))   return   separe_tab[no_var-base][SEPARE_TAB_IND_EXIST];
    base=9500; if(no_var>=base && no_var<=(base+REGROUPE_TAB_NB-1)) return regroupe_tab[no_var-base][REGROUPE_TAB_IND_EXIST];
	sprintf_s(gszErr,"\n-Erreur4 : Lecture N° variable interne : Var inconnue = %d",no_var); log(gszErr);
    return -1;
}
int pio_get_val(int no_var)
{
    int ret;
    ret=pio_get_val_(no_var);
    //sprintf_s(gszErr,"\n-DBG-0001- getadr: %d = %d",no_var,ret); log(gszErr);
    return ret;
}


// Sous-programme pour modifier l'état de la variable passé en paramètre. 
//   Exemple : i=pio_set_val(1201,1) => Met la valeur de la sortie n°1 de la carte n°0 à 1.
//
//
int pio_set_val(int no_var,int val_var)
{
    int base;
    //sprintf_s(gszErr,"\n-DBG-0002- setadr: %d = %d",no_var,val_var); log(gszErr);
    base=1200; if(no_var>=base && no_var<=(base+400-1)) { vio_out[(no_var-base)/100][(no_var-base)%100]=val_var; return 0; }
    base=1600; if(no_var>=base && no_var<=(base+400-1)) { vio_led[(no_var-base)/100][(no_var-base)%100]=val_var; return 0; }
    base=2000; if(no_var>=base && no_var<=(base+400-1)) { vio_led_cli[(no_var-base)/100][(no_var-base)%100]=val_var; return 0; }
    base=2400; if(no_var>=base && no_var<=(base+400-1)) { vio_led_phase[(no_var-base)/100][(no_var-base)%100]=val_var; return 0; }
    base=5000; if(no_var>=base && no_var<=(base+100-1))
               if(vio_aig_res[no_var-base]==0)          { vio_aig_cmd[no_var-base]=val_var; return 0; }  // if(vio_aig_mode[no_var-1000]=='p') ... else return -2;
    base=5400; if(no_var>=base && no_var<=(base+600-1)) { pio_var[no_var-base]=val_var; return 0; }
	base=6000; if(no_var>=base && no_var<=(base+ITI_TAB_NB-1)) {
		if (iti_tab[no_var-base][ITI_TAB_IND_EXIST]!=0 && iti_tab[no_var-base][ITI_TAB_IND_STEP]==ITI_CST_STATE_IDLE) iti_tab[no_var-base][ITI_TAB_IND_START]=val_var; // variable en écriture seulement.
		return 0;
		}
    base=6100; if(no_var>=base && no_var<=(base+ITI_TAB_NB-1)) {
		if (iti_tab[no_var-base][ITI_TAB_IND_EXIST]!=0 && iti_tab[no_var-base][ITI_TAB_IND_STEP]!=ITI_CST_STATE_IDLE) iti_tab[no_var-base][ITI_TAB_IND_STOP]=val_var; // variable en écriture seulement.
		return 0;
	} 
	base=6500; if(no_var>=base && no_var<=(base+DEPL_TAB_NB-1)) {
		if (depl_tab[no_var-base][DEPL_TAB_IND_CANT_START]!=-1)   depl_tab[no_var-base][DEPL_TAB_IND_START_RUN]=val_var;
		return 0;
	}
	base=6700; if(no_var>=base && no_var<=(base+DEPL_TAB_NB-1)) {
		if (depl_tab[no_var-base][DEPL_TAB_IND_CANT_START]!=-1)   depl_tab[no_var-base][DEPL_TAB_IND_STOP]=val_var;   // variable en écriture seulement.
		return 0; 
	}
	base=6900; if(no_var>=base && no_var<=(base+NB_GARAGE_REEL-1)) {
		if(vio_garage_lock_res[no_var-base]==0)                   vio_garage_lock_cmd[no_var-base]=val_var; 
		return 0;
	}
    if(no_var==7000) {vib_on       =val_var; return 0;}
    // if(no_var==7002) {vib_state =val_var; return 0;}  Variable non modifiable. lecture uniquement.
    if(no_var==7003) {screen_mode  =val_var; return 0;}
    if(no_var==7004) {arret_urg_on =val_var; return 0;}
    // if(no_var==7005) {cmd_divers[CMD_DIVERS_TAILLE]=val_var; return 0;}  Variable non modifiable. lecture uniquement.
    base=8400; if(no_var>=base && no_var<=(base+100-1)) { pio_exe[no_var-base]=val_var; return 0; }
    base=8500; if(no_var>=base && no_var<=(base+100-1)) { pio_pulse_cmd[no_var-base]=val_var; return 0; }
    base=9100; if(no_var>=base && no_var<=(base+100-1)) { special_var[no_var-base]=val_var; return 0; }
	base=8000; if(no_var>=base && no_var<=(base+400-1)) {
		if 	((no_var-base)%100>=NB_SERVO_VIT ) { // SERV_XXX+NB_SERVO_VIT" = Vitesse du servo XXX, mais on vérifie que le servo n'est pas réservé (XXX-NB_SERVO_VIT).
			if(vio_srv_res[(no_var-base)/100][(no_var-NB_SERVO_VIT-base)%100]==0) { vio_srv_cmd[(no_var-base)/100][(no_var-base)%100]=val_var; return 0; }
		}
		else {									// "SRV_XXX" = Consigne du servo XXX.
			if(vio_srv_res[(no_var-base)/100][(no_var-base)%100]==0) { vio_srv_cmd[(no_var-base)/100][(no_var-base)%100]=val_var; return 0; }
		}
	}
	base=9400; 
	if (no_var>=base && no_var<=(base+SEPARE_TAB_NB-1)) {
		separe_tab[no_var-base][SEPARE_TAB_IND_EXIST]=val_var;
		return 0;
	}
	base=9500; 
	if (no_var>=base && no_var<=(base+REGROUPE_TAB_NB-1)) {
	    regroupe_tab[no_var-base][REGROUPE_TAB_IND_EXIST]=val_var;
		return 0;
	}

	sprintf_s(gszErr,"\n-Erreur5 : Ecriture N° variable interne : Var inconnue = %d",no_var); log(gszErr);
    return -1;
}



// Au lancement d'UTS, initialise les variables.
//
void pio_init(void)
{
    int j,i;
    // 1. Initialisation des variables des cartes (en sortie).
    for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_CANTON;i++) {
										vio_canton_vit[j][i]                 =0;
										vio_bal_cant_p[j][i]                 =0;
										vio_bal_cant_m[j][i]                 =0;
										serial_debug_select_canton_vit[j][i] =0;
										serial_debug_canton_vit[j][i]        =0;
										}
    for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_OUT;i++) { 
										vio_out[j][i]                 =0;
										serial_debug_select_out[j][i] =0;
										serial_debug_out[j][i]        =0;
										}
    for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_LED;i++) { 
										vio_led[j][i]                 =0;
										vio_led_cli[j][i]             =0;
										vio_led_phase[j][i]           =0;
										serial_debug_select_led[j][i] =0;
										serial_debug_led[j][i]        =0;
										serial_debug_led_cli[j][i]    =0;
										serial_debug_led_phase[j][i]  =0;
										}
    for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_SERVO;i++)  { 
										vio_srv_cmd[j][i]             =512;		// Valeur = 512 = position centrale de consigne
										vio_srv[j][i]                 =512;		// Valeur = 512 = position centrale de position réel du servo.
										serial_debug_select_srv[j][i] =0;
										serial_debug_srv[j][i]        =128;		// Valeur = 128 = position centrale pour l'affichage sur l'écran 'RS232-Debug'.
										vio_srv_cmd[j][i+NB_SERVO_VIT]=0;		// Vitesse de déplacement des servo, nulle.
										}


    for(j=0;j<NB_CARTE;j++) cfg_enable_leds[j] =1;		// Par défaut des sorties sont utilisées pour alimenter 48 leds.

	#ifndef VERSION_UTS_V3 // Ne pas toucher à cette ligne !!!
	for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_SERVO;i++) cfg_enable_servos[j][i] =0;
	#endif

	for(i=0;i<NB_AIG;i++) {
		vio_aig_cmd[i]  =0;
		vio_aig_pos0[i] =0;
		vio_aig_pos1[i] =0;
	}

    // 2. Initialisation des variables des cartes (en entrée).
    for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_CAN;i++)    vio_can[j][i] =0;
    for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_IN;i++)     vio_in[j][i]  =0;
    for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_CANTON;i++) vio_det[j][i] =0;

    // 3. Initialisation des variables internes.
    for(i=0;i<NB_AIG;i++)    vio_aig_res[i]            =0;
    for(i=0;i<NB_GARAGE;i++) vio_garage_lock_cmd[i]    =0; // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
    for(i=0;i<NB_GARAGE;i++) vio_garage_lock_status[i] =0; // 0 ou 1, 1 => Le garage est isolé du canton (état réel).
    for(i=0;i<NB_GARAGE;i++) vio_garage_lock_res[i]    =0; // 0 ou 1, 1 => Garage réservé.

    for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_SERVO;i++) vio_srv_res[j][i] =0;

    // 4. Initialisation des variables internes.
    for(i=0;i<NB_VAR ;i++)         pio_var[i]     =0;			// Toutes les variables utilisateur à zéro.
    for(i=0;i<NB_SPECIAL_VAR ;i++) special_var[i] =0;			// Toutes les variables spéciales à zéro.

}


void pio_maj(void)
{}
