885 lines
35 KiB
C
885 lines
35 KiB
C
//**********************************************************************************************************************************************************************************
|
||
// Fichier ENTREES.C
|
||
//
|
||
// Contient toutes les fonctions liées à la lecture de l'état des entrées
|
||
//**********************************************************************************************************************************************************************************/
|
||
|
||
// Includes :
|
||
#include "main.h"
|
||
|
||
// Prototypes :
|
||
void gestion_entrees(void);
|
||
void gestion_entrees_aux(void);
|
||
void gestion_entrees_level_sensor(void);
|
||
void gestion_entrees_volt(void);
|
||
void gestion_entrees_nmea(void);
|
||
void gestion_entrees_ow(void);
|
||
void gestion_entrees_predefinies(void);
|
||
void gestion_entrees_core(void);
|
||
void gestion_entrees_gpio(void);
|
||
int8_t init_entrees(void);
|
||
int8_t init_entrees_aux(void);
|
||
int8_t init_entrees_level_sensor(void);
|
||
int8_t init_entrees_volt(void);
|
||
int8_t init_entrees_nmea(void);
|
||
int8_t init_entrees_ow(void);
|
||
int8_t init_entrees_predefinies(void);
|
||
int8_t init_entrees_core(void);
|
||
int8_t init_entrees_gpio(void);
|
||
float lecture_entree(uint8_t type, uint8_t module, uint8_t no, bool flag_immediat);
|
||
int16_t entree_no(uint8_t type, uint8_t module, uint8_t no);
|
||
uint8_t lecture_entree_gpio(uint8_t no, int8_t logique);
|
||
|
||
|
||
// Variables globales :
|
||
struct Struct_entrees entrees;
|
||
struct gpiod_chip *gpiod_chip0; // Nécessaire pour CM5
|
||
struct gpiod_line_request *gpiod_entrees_request; // Nécessaire pour CM5
|
||
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction LECTURE_ENTREE
|
||
|
||
Fonction utilisée pour connaitre l'état d'une entrée, quel que soit sont type.
|
||
Reçoit en paramètre : le Type d'entrée, le module comportant l'entrée, le n° sur le module et un flag permettant de forcer la lecture immédiate (pour GPIO)
|
||
Retourne : l'état de l'entrée
|
||
NB : Dans le cas où le flag est 'faux', l'appel à cette fonction remontera le dernier état connu, mis à jour par le gestionnaire correspondant au type.
|
||
NB2 : L'utilisation du flag n'est possible que pour les entrées de type GPIO (pour les autres, il est ignoré...). Ce flag est à utiliser avec modération...
|
||
**********************************************************************************************************************************************************************************/
|
||
float lecture_entree(uint8_t type, uint8_t module, uint8_t no, bool flag_immediat)
|
||
{
|
||
int16_t x;
|
||
|
||
x = entree_no(type, module, no);
|
||
|
||
switch(type)
|
||
{
|
||
//-----------------------------
|
||
case TYPE_ENTREES_AUXILIAIRES :
|
||
{
|
||
return(entrees.aux.entrees[x].valeur);
|
||
break;
|
||
}
|
||
//-----------------------------
|
||
case TYPE_ENTREES_LEVEL_SENSOR :
|
||
{
|
||
return(entrees.level_sensor.entrees[x].valeur);
|
||
break;
|
||
}
|
||
//-----------------------------
|
||
case TYPE_ENTREES_VOLTAGE :
|
||
{
|
||
return(entrees.volt.entrees[x].valeur);
|
||
break;
|
||
}
|
||
//-----------------------------
|
||
case TYPE_ENTREES_NMEA :
|
||
{
|
||
return(entrees.nmea.entrees[x].valeur);
|
||
break;
|
||
}
|
||
//-----------------------------
|
||
case TYPE_ENTREES_OW :
|
||
{
|
||
return(entrees.ow.entrees[x].valeur);
|
||
break;
|
||
}
|
||
//-----------------------------
|
||
case TYPE_ENTREES_PREDEFINIES :
|
||
{
|
||
return(entrees.predefinies.entrees[x].valeur);
|
||
break;
|
||
}
|
||
//-----------------------------
|
||
case TYPE_ENTREES_CORE :
|
||
{
|
||
return(entrees.core.entrees[x].valeur);
|
||
break;
|
||
}
|
||
//-----------------------------
|
||
case TYPE_ENTREES_GPIO :
|
||
{
|
||
if (flag_immediat) entrees.gpio.entrees[x].valeur = lecture_entree_gpio(no, entrees.gpio.entrees[x].logique);
|
||
return(entrees.gpio.entrees[x].valeur);
|
||
break;
|
||
}
|
||
//-----------------------------
|
||
default: ;
|
||
}
|
||
|
||
return (0xFFFFFFFF); // Cas d'erreur
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES
|
||
|
||
Lance le traitement régulier du gestionnaire de chaque type d'entrée
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees(void)
|
||
{
|
||
|
||
gestion_entrees_aux();
|
||
gestion_entrees_level_sensor();
|
||
gestion_entrees_volt();
|
||
gestion_entrees_nmea();
|
||
gestion_entrees_ow();
|
||
gestion_entrees_predefinies();
|
||
gestion_entrees_core();
|
||
gestion_entrees_gpio();
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES_AUX
|
||
|
||
Fonction utilisée pour mettre à jour toutes les sorties GPIO de façon synchrones
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees_aux(void)
|
||
{
|
||
// Il n'y a rien à faire car l'état des entrées AUX est remonté automatiquement par le Compagnon via une commande UP.
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES_LEVEL_SENSOR
|
||
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees_level_sensor(void)
|
||
{
|
||
|
||
switch(entrees.level_sensor.sequenceur.etat)
|
||
{
|
||
case ETAT_SEQUENCEUR_ENTREES_LEVEL_SENSOR_INIT:
|
||
{
|
||
if ((entrees.level_sensor.sequenceur.compteur == 0) && (systeme.flag_cm3p_ready))
|
||
{
|
||
c_bus_down_commande_config_level_sensors(); // Commande de config des entrées Level Sensor vers le Compagnon sur C-Bus
|
||
|
||
entrees.level_sensor.sequenceur.etat = ETAT_SEQUENCEUR_ENTREES_LEVEL_SENSOR_REPOS;
|
||
}
|
||
break;
|
||
}
|
||
|
||
case ETAT_SEQUENCEUR_ENTREES_LEVEL_SENSOR_REPOS:
|
||
{
|
||
break;
|
||
}
|
||
|
||
default : entrees.level_sensor.sequenceur.etat = ETAT_SEQUENCEUR_ENTREES_LEVEL_SENSOR_REPOS;
|
||
}
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES_VOLT
|
||
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees_volt(void)
|
||
{
|
||
// Il n'y a rien à faire car l'état des entrées VOLTAGE est remonté automatiquement par le Compagnon via une commande UP.
|
||
}
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES_NMEA
|
||
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees_nmea(void)
|
||
{
|
||
// Il n'y a rien à faire car l'état des entrées NMEA est remonté automatiquement par le Compagnon via une commande UP.
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES_OW
|
||
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees_ow(void)
|
||
{
|
||
// Il n'y a rien à faire car l'état des entrées OW est remonté automatiquement par le Compagnon via une commande UP.
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES_PREDEFINIES
|
||
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees_predefinies(void)
|
||
{
|
||
// Il n'y a rien à faire car l'état des entrées PREDEFINIES est remonté automatiquement par le Compagnon via les commandes UP.
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES_CORE
|
||
|
||
Séquenceur permettant la lecture des trames reçues sur la ligne Téléinfo du compteur EDF
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees_core(void)
|
||
{
|
||
int i;
|
||
char commande[MAX_TAILLE_COMMANDE_SHELL];
|
||
char chaine[300];
|
||
|
||
if (entrees.core.sequenceur.compteur == 0)
|
||
{
|
||
entrees.core.sequenceur.compteur = PERIODE_LECTURE_ENTREES_CORE; // Réarmement du timer périodique
|
||
|
||
strcpy(commande, "{ "); // Attention, l'espace après le '{' est obligatoire !
|
||
for (i=0; i<MAX_NOMBRE_ENTREES_CORE; i++)
|
||
{
|
||
if (!entrees.core.entrees[i].flag_validite) continue;
|
||
|
||
if (strstr(entrees.core.entrees[i].nom, "TEMPERATURE_CORE") != NULL) strcat(commande, "vcgencmd measure_temp; ");
|
||
else if (strstr(entrees.core.entrees[i].nom, "TENSION_CORE") != NULL) strcat(commande, "vcgencmd measure_volts core; ");
|
||
else if (strstr(entrees.core.entrees[i].nom, "FREQUENCE_CORE") != NULL) strcat(commande, "vcgencmd measure_clock core; ");
|
||
else if (strstr(entrees.core.entrees[i].nom, "FREQUENCE_UART") != NULL) strcat(commande, "vcgencmd measure_clock uart; ");
|
||
else if (strstr(entrees.core.entrees[i].nom, "VITESSE_BOUCLE_PRINCIPALE") != NULL)
|
||
{
|
||
if (supervision_boucle_principale.nb_secondes > 0) // Dans le cas où on n'a pas effectué un comptage sur 1 seconde au moins, on ne traite pas la mesure de l'entrée :
|
||
{
|
||
// printf("Vitesse boucle principale = %i boucles/seconde\n", (supervision_boucle_principale.nb_boucles / supervision_boucle_principale.nb_secondes));
|
||
supervision_boucle_principale.nb_boucles = 0;
|
||
supervision_boucle_principale.nb_secondes = 0;
|
||
}
|
||
}
|
||
}
|
||
strcat(commande, " }"); // Attention, l'espace avant le '{' est obligatoire !
|
||
sprintf(chaine, " > %s/%s &", REPERTOIRE_TMP_CORE, NOM_FICHIER_ETAT_ENTREES_CORE);
|
||
strcat(commande, chaine);
|
||
//printf("Commande Shell = [%s]\n", commande);
|
||
commande_shell(commande);
|
||
}
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction ENTREES_GPIO
|
||
|
||
Fonction utilisée pour rendre la lecture des entrées GPIO synchrones (tous les états lus d'un coup)
|
||
**********************************************************************************************************************************************************************************/
|
||
void gestion_entrees_gpio(void)
|
||
{
|
||
int i;
|
||
|
||
if (entrees.gpio.sequenceur.compteur == 0)
|
||
{
|
||
entrees.gpio.sequenceur.compteur = PERIODE_LECTURE_ENTREES_GPIO; // Réarmement du timer périodique
|
||
|
||
for (i=0; i<MAX_NOMBRE_ENTREES_GPIO; i++)
|
||
{
|
||
if (!entrees.gpio.entrees[i].flag_validite) continue;
|
||
|
||
entrees.gpio.entrees[i].valeur = lecture_entree_gpio(entrees.gpio.entrees[i].no, entrees.gpio.entrees[i].logique);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES
|
||
|
||
Intitialisation des entrées, quel que soit leur type.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees(void)
|
||
{
|
||
|
||
|
||
// Init des entrées AUX :
|
||
if (init_entrees_aux() == -1) return(-1);
|
||
|
||
// Init des entrées Level Sensor :
|
||
if (init_entrees_level_sensor() == -1) return(-1);
|
||
|
||
// Init des entrées VOLT :
|
||
if (init_entrees_volt() == -1) return(-1);
|
||
|
||
// Init des entrées NMEA :
|
||
if (init_entrees_nmea() == -1) return(-1);
|
||
|
||
// Init des entrées OW :
|
||
if (init_entrees_ow() == -1) return(-1);
|
||
|
||
// Init des entrées PREDEFINIES :
|
||
if (init_entrees_predefinies() == -1) return(-1);
|
||
|
||
// Init des entrées CORE :
|
||
if (init_entrees_core() == -1) return(-1);
|
||
|
||
// Init des entrées GPIO :
|
||
if (init_entrees_gpio() == -1) return(-1);
|
||
|
||
return(0);
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES_AUX
|
||
|
||
Configure les entrées qui sont configurées dans la table 'TB_Entrées_aux'
|
||
Renvoi -1 en cas d'erreur lors de l'initialisation.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees_aux(void)
|
||
{
|
||
// Rien à faire car la remontée de l'état des entrées AUX est faite automatiquement par le Compagnon via des commandes UP.
|
||
return(0);
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES_LEVEL_SENSOR
|
||
|
||
Configure les entrées qui sont configurées dans la table 'TB_Entrées_level_sensor'
|
||
Renvoi -1 en cas d'erreur lors de l'initialisation.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees_level_sensor(void)
|
||
{
|
||
|
||
entrees.level_sensor.sequenceur.etat = ETAT_SEQUENCEUR_ENTREES_LEVEL_SENSOR_INIT;
|
||
entrees.level_sensor.sequenceur.compteur = TEMPO_INIT_ENTREES_LEVEL_SENSOR;
|
||
|
||
return(0);
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES_VOLT
|
||
|
||
Renvoi -1 en cas d'erreur lors de l'initialisation.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees_volt(void)
|
||
{
|
||
// Rien à faire car la remontée de l'état des entrées VOLT est faite automatiquementpar le Compagnon via des commandes UP.
|
||
return(0);
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES_NMEA
|
||
|
||
Renvoi -1 en cas d'erreur lors de l'initialisation.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees_nmea(void)
|
||
{
|
||
// Rien à faire car la remontée de l'état des entrées NMEA est faite automatiquementpar le Compagnon via des commandes UP.
|
||
return(0);
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES_OW
|
||
|
||
Configure les entrées qui sont configurées dans la table 'TB_One_wire'
|
||
Renvoi -1 en cas d'erreur lors de l'initialisation.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees_ow(void)
|
||
{
|
||
// Rien à faire car la remontée de l'état des entrées OW est faite automatiquementpar le Compagnon via des commandes UP.
|
||
return(0);
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES_PREDEFINIES
|
||
|
||
Configure les entrées qui sont configurées dans la table 'TB_Entrées_predefinies'
|
||
Renvoi -1 en cas d'erreur lors de l'initialisation.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees_predefinies(void)
|
||
{
|
||
// Rien à faire car la remontée de l'état des entrées PREDEFINIES est faite automatiquementpar le Compagnon via des commandes UP.
|
||
return(0);
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES_CORE
|
||
|
||
+--------------+----------+---------------------------+-----------------+-----------------------------------------------------------------+---------------------+
|
||
| Cle_primaire | Validite | Nom | Unite | Description | Date_maj |
|
||
+--------------+----------+---------------------------+-----------------+-----------------------------------------------------------------+---------------------+
|
||
| 1 | 1 | TEMPERATURE_CORE | °C | Température interne du processeur. | 2020-01-01 00:00:00 |
|
||
| 2 | 1 | TENSION_CORE | V | Tension d'alimentation du processeur | 2020-01-01 00:00:00 |
|
||
| 3 | 1 | FREQUENCE_CORE | Hz | Fréquence d'horloge du Core | 2020-01-01 00:00:00 |
|
||
| 4 | 1 | FREQUENCE_UART | HZ | Fréquence d'horloge de l'UART | 2020-01-01 00:00:00 |
|
||
| 5 | 1 | VITESSE_BOUCLE_PRINCIPALE | Boucles/seconde | Indique le nombre de boucle principale exécutée par secondes. | 2020-01-01 00:00:00 |
|
||
+--------------+----------+---------------------------+-----------------+-----------------------------------------------------------------+---------------------+
|
||
|
||
Configure les entrées 'Core'
|
||
Renvoi -1 en cas d'erreur lors de l'initialisation.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees_core(void)
|
||
{
|
||
uint8_t i;
|
||
|
||
|
||
i = 0;
|
||
|
||
entrees.core.entrees[i].flag_validite = TRUE;
|
||
strcpy(entrees.core.entrees[i].nom, "TEMPERATURE_CORE"); // Température interne du processeur (en °C)
|
||
entrees.core.entrees[i].no = i; // Définition arbitraire pour garder la comptabilité avec les autres entrées...
|
||
i++;
|
||
|
||
entrees.core.entrees[i].flag_validite = TRUE;
|
||
strcpy(entrees.core.entrees[i].nom, "TENSION_CORE"); // Tension d'alimentation du processeur (en V)
|
||
entrees.core.entrees[i].no = i; // Définition arbitraire pour garder la comptabilité avec les autres entrées...
|
||
i++;
|
||
|
||
entrees.core.entrees[i].flag_validite = TRUE;
|
||
strcpy(entrees.core.entrees[i].nom, "FREQUENCE_CORE"); // Fréquence d'horloge du Core (en Hz)
|
||
entrees.core.entrees[i].no = i; // Définition arbitraire pour garder la comptabilité avec les autres entrées...
|
||
i++;
|
||
|
||
entrees.core.entrees[i].flag_validite = TRUE;
|
||
strcpy(entrees.core.entrees[i].nom, "FREQUENCE_UART"); // Fréquence d'horloge de l'UART (en Hz)
|
||
entrees.core.entrees[i].no = i; // Définition arbitraire pour garder la comptabilité avec les autres entrées...
|
||
i++;
|
||
|
||
entrees.core.entrees[i].flag_validite = TRUE;
|
||
strcpy(entrees.core.entrees[i].nom, "VITESSE_BOUCLE_PRINCIPALE"); // Indique le nombre de boucle principale exécutée par secondes (en boucles/secondes)
|
||
entrees.core.entrees[i].no = i; // Définition arbitraire pour garder la comptabilité avec les autres entrées...
|
||
i++;
|
||
|
||
|
||
entrees.core.sequenceur.compteur = TEMPO_INIT_ENTREES_CORE;
|
||
|
||
return(0);
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction INIT_ENTREES_GPIO
|
||
|
||
Configure les I/O du GPIO
|
||
Renvoi -1 en cas d'erreur lors de l'initialisation.
|
||
**********************************************************************************************************************************************************************************/
|
||
int8_t init_entrees_gpio(void)
|
||
{
|
||
bool flag_erreur;
|
||
uint8_t groupe;
|
||
uint8_t position_groupe;
|
||
uint8_t i;
|
||
uint8_t val;
|
||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||
|
||
|
||
i = 0;
|
||
|
||
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1)
|
||
{
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_MOD_RI;
|
||
entrees.gpio.entrees[i].pull = PULL_DOWN;
|
||
entrees.gpio.entrees[i].logique = 1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_LIGHT_MOD;
|
||
entrees.gpio.entrees[i].pull = PULL_DOWN;
|
||
entrees.gpio.entrees[i].logique = 1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_STATUS_MOD;
|
||
entrees.gpio.entrees[i].pull = PULL_DOWN;
|
||
entrees.gpio.entrees[i].logique = 1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_USB1_ALERT_N;
|
||
entrees.gpio.entrees[i].pull = PULL_UP;
|
||
entrees.gpio.entrees[i].logique = -1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_USB2_ALERT_N;
|
||
entrees.gpio.entrees[i].pull = PULL_UP;
|
||
entrees.gpio.entrees[i].logique = -1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_USB3_ALERT_N;
|
||
entrees.gpio.entrees[i].pull = PULL_UP;
|
||
entrees.gpio.entrees[i].logique = -1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_FROM_UC;
|
||
entrees.gpio.entrees[i].pull = PULL_DOWN;
|
||
entrees.gpio.entrees[i].logique = 1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_LOW_12V;
|
||
entrees.gpio.entrees[i].pull = NO_PUP_PDN;
|
||
entrees.gpio.entrees[i].logique = 1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM3P_DI_SIM_SW;
|
||
entrees.gpio.entrees[i].pull = PULL_UP;
|
||
entrees.gpio.entrees[i].logique = -1;
|
||
i++;
|
||
}
|
||
else // Concerne V2 & V3
|
||
{
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM4_DI_USB_BAS_ALERT_N;
|
||
entrees.gpio.entrees[i].pull = PULL_UP;
|
||
entrees.gpio.entrees[i].logique = -1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM4_DI_USB_MILIEU_ALERT_N;
|
||
entrees.gpio.entrees[i].pull = PULL_UP;
|
||
entrees.gpio.entrees[i].logique = -1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM4_DI_USB_HAUT_ALERT_N;
|
||
entrees.gpio.entrees[i].pull = PULL_UP;
|
||
entrees.gpio.entrees[i].logique = -1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM4_LOW_32V_INPUT;
|
||
entrees.gpio.entrees[i].pull = NO_PUP_PDN;
|
||
entrees.gpio.entrees[i].logique = 1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM4_DI_USB_ARRIERE_ALERT_N;
|
||
entrees.gpio.entrees[i].pull = PULL_UP;
|
||
entrees.gpio.entrees[i].logique = -1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM4_DI_JACK_DETECT;
|
||
entrees.gpio.entrees[i].pull = PULL_UP; // SDIR #232
|
||
entrees.gpio.entrees[i].logique = 1;
|
||
i++;
|
||
|
||
entrees.gpio.entrees[i].flag_validite = TRUE;
|
||
entrees.gpio.entrees[i].no = CM4_DI_FROM_UC;
|
||
entrees.gpio.entrees[i].pull = PULL_DOWN;
|
||
entrees.gpio.entrees[i].logique = 1;
|
||
i++;
|
||
}
|
||
|
||
|
||
flag_erreur = FALSE;
|
||
|
||
//====================================================================================================
|
||
// V3 (CM5) : réservation groupée des lignes GPIO via libgpiod.
|
||
//====================================================================================================
|
||
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V3)
|
||
{
|
||
unsigned int offsets[MAX_NOMBRE_ENTREES_GPIO];
|
||
uint8_t nb_lignes = 0;
|
||
|
||
struct gpiod_line_settings *settings = gpiod_line_settings_new();
|
||
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
||
|
||
struct gpiod_line_config *line_cfg = gpiod_line_config_new();
|
||
|
||
struct gpiod_request_config *req_cfg = gpiod_request_config_new();
|
||
gpiod_request_config_set_consumer(req_cfg, "shipheart_entrees");
|
||
|
||
gpiod_chip0 = gpiod_chip_open("/dev/gpiochip0");
|
||
if (gpiod_chip0 == NULL)
|
||
{
|
||
sprintf(tmp, "Ouverture de /dev/gpiochip0 impossible...");
|
||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||
return(-1);
|
||
}
|
||
|
||
for (i=0; i<MAX_NOMBRE_ENTREES_GPIO; i++)
|
||
{
|
||
if (!entrees.gpio.entrees[i].flag_validite) continue;
|
||
|
||
switch (entrees.gpio.entrees[i].pull)
|
||
{
|
||
case PULL_UP : gpiod_line_settings_set_bias(settings, GPIOD_LINE_BIAS_PULL_UP); break;
|
||
case PULL_DOWN : gpiod_line_settings_set_bias(settings, GPIOD_LINE_BIAS_PULL_DOWN); break;
|
||
default : gpiod_line_settings_set_bias(settings, GPIOD_LINE_BIAS_DISABLED); break;
|
||
}
|
||
|
||
offsets[nb_lignes] = entrees.gpio.entrees[i].no;
|
||
gpiod_line_config_add_line_settings(line_cfg, &offsets[nb_lignes], 1, settings);
|
||
nb_lignes++;
|
||
|
||
sprintf(tmp, "GPIO #%2i configurée en ENTREE (via libgpiod)", entrees.gpio.entrees[i].no);
|
||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
|
||
}
|
||
|
||
gpiod_entrees_request = gpiod_chip_request_lines(gpiod_chip0, req_cfg, line_cfg);
|
||
|
||
gpiod_request_config_free(req_cfg);
|
||
gpiod_line_config_free(line_cfg);
|
||
gpiod_line_settings_free(settings);
|
||
|
||
if (gpiod_entrees_request == NULL)
|
||
{
|
||
sprintf(tmp, "Réservation des lignes GPIO d'entrée impossible...");
|
||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||
return(-1);
|
||
}
|
||
|
||
entrees.gpio.sequenceur.compteur = TEMPO_INIT_ENTREES_GPIO;
|
||
return(0); // On sort ici : la boucle V1/V2 ci-dessous ne doit pas s'exécuter pour V3
|
||
}
|
||
|
||
|
||
//====================================================================================================
|
||
// V1 et V2 :
|
||
//====================================================================================================
|
||
for (i=0; i<MAX_NOMBRE_ENTREES_GPIO; i++)
|
||
{
|
||
if (!entrees.gpio.entrees[i].flag_validite) continue;
|
||
|
||
groupe = entrees.gpio.entrees[i].no / 10;
|
||
position_groupe = entrees.gpio.entrees[i].no % 10;
|
||
|
||
// Configuration en Entrée de l'E/S GPIO :
|
||
*(hardware.gpio_base + groupe) &= ~(7<<(position_groupe*3)); // Mets à 0 les 3 bits correspondant à N0
|
||
sprintf(tmp, "GPIO #%2i configurée en ENTREE", entrees.gpio.entrees[i].no);
|
||
|
||
// Configuration des résitances de pull-up/down :
|
||
switch (entrees.gpio.entrees[i].pull)
|
||
{
|
||
case NO_PUP_PDN :
|
||
{
|
||
strcat(tmp, " ");
|
||
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1) val = CM3P_NO_PUP_PDN;
|
||
else val = CM4_NO_PUP_PDN;
|
||
break;
|
||
}
|
||
case PULL_UP :
|
||
{
|
||
strcat(tmp, " avec résistance de pull-up");
|
||
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1) val = CM3P_PULL_UP;
|
||
else val = CM4_PULL_UP;
|
||
break;
|
||
}
|
||
case PULL_DOWN :
|
||
{
|
||
strcat(tmp, " avec résistance de pull-down");
|
||
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1) val = CM3P_PULL_DOWN;
|
||
else val = CM4_PULL_DOWN;
|
||
break;
|
||
}
|
||
default :
|
||
{
|
||
strcat(tmp, " avec un type de résistance de pull-up/down inconnu !!! ");
|
||
flag_erreur = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!flag_erreur)
|
||
{
|
||
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1)
|
||
{
|
||
if (entrees.gpio.entrees[i].pull != NO_PUP_PDN)
|
||
{
|
||
// Séquence de configuration pour l'E/S en cours (cf page 101 de la doc du BCM2835-ARM-Peripherals) :
|
||
*(hardware.gpio_base + CM3P_OFFSET_GPIO_PIN_PULL_UP_DOWN_ENABLE) = (uint32_t) val;
|
||
|
||
delai_nano_sec(200); // Wait 150 cycles – this provides the required set-up time for the control signal
|
||
|
||
if (entrees.gpio.entrees[i].no < 32) *(hardware.gpio_base + CM3P_OFFSET_GPIO_PIN_PULL_UP_DOWN_ENABLE_CLOCK_0) |= (1 << entrees.gpio.entrees[i].no); // 0 = no effect, 1 = Assert Clock on line (n)
|
||
else *(hardware.gpio_base + CM3P_OFFSET_GPIO_PIN_PULL_UP_DOWN_ENABLE_CLOCK_1) |= (1 << (entrees.gpio.entrees[i].no - 32)); // 0 = no effect, 1 = Assert Clock on line (n)
|
||
|
||
delai_nano_sec(200); // Wait 150 cycles – this provides the required set-up time for the control signal
|
||
|
||
*(hardware.gpio_base + CM3P_OFFSET_GPIO_PIN_PULL_UP_DOWN_ENABLE) = (uint32_t) 0x00; // 00 = Off – disable pull-up/down
|
||
if (entrees.gpio.entrees[i].no < 32) *(hardware.gpio_base + CM3P_OFFSET_GPIO_PIN_PULL_UP_DOWN_ENABLE_CLOCK_0) = 0; // Write to GPPUDCLK0/1 to remove the clock
|
||
else *(hardware.gpio_base + CM3P_OFFSET_GPIO_PIN_PULL_UP_DOWN_ENABLE_CLOCK_1) = 0;
|
||
}
|
||
}
|
||
else // CM4 (NB : dans ce cas, on met à jour les registre même si la demande est NO_PUP-DWN) :
|
||
{
|
||
groupe = entrees.gpio.entrees[i].no / 16;
|
||
position_groupe = entrees.gpio.entrees[i].no % 16;
|
||
|
||
*(hardware.gpio_base + CM4_OFFSET_GPIO_PUP_PDN_CNTRL_REG0 + groupe) &= ~(3<<(position_groupe*2)); // Mets à 0 les 2 bits correspondant à l'entrée
|
||
*(hardware.gpio_base + CM4_OFFSET_GPIO_PUP_PDN_CNTRL_REG0 + groupe) |= (val<<(position_groupe*2)); // Ecrit la valeur demandée dans les 2 bits correspondant à l'entrée
|
||
}
|
||
}
|
||
|
||
|
||
// Affichage du message de débug :
|
||
if (!flag_erreur) affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
|
||
else affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||
|
||
// Arrêt de l'intitialisation si erreur :
|
||
if (flag_erreur) return(-1);
|
||
}
|
||
|
||
entrees.gpio.sequenceur.compteur = TEMPO_INIT_ENTREES_GPIO;
|
||
|
||
return(0);
|
||
}
|
||
|
||
|
||
/***********************************************************************************************************************************************************************************
|
||
Fonction ENTREE_NO
|
||
Reçoit en paramètre :
|
||
- le type d'entrée concerné
|
||
- le module (adresse_k_bus) sur lequel l'entrée se situe
|
||
- Le n° de l'entrée sur le module
|
||
Retourne :
|
||
- le numéro d'entrée correspondant (ou -1 si aucune entrée valide ne correspond). La numérotation allant de 0 à MAX_ENTREES_xxxx (fonction du type).
|
||
**********************************************************************************************************************************************************************************/
|
||
int16_t entree_no(uint8_t type, uint8_t module, uint8_t no)
|
||
{
|
||
int i;
|
||
|
||
switch(type)
|
||
{
|
||
//------------------------------------
|
||
case TYPE_ENTREES_AUXILIAIRES:
|
||
{
|
||
for (i=0; i<entrees.aux.nb; i++)
|
||
{
|
||
if ((entrees.aux.entrees[i].flag_validite) &&
|
||
(entrees.aux.entrees[i].module == module) &&
|
||
(entrees.aux.entrees[i].no == no)) return(i);
|
||
}
|
||
break;
|
||
}
|
||
|
||
//------------------------------------
|
||
case TYPE_ENTREES_LEVEL_SENSOR :
|
||
{
|
||
for (i=0; i<entrees.level_sensor.nb; i++)
|
||
{
|
||
if ((entrees.level_sensor.entrees[i].flag_validite) &&
|
||
(entrees.level_sensor.entrees[i].module == module) &&
|
||
(entrees.level_sensor.entrees[i].no == no)) return(i);
|
||
}
|
||
break;
|
||
}
|
||
|
||
//------------------------------------
|
||
case TYPE_ENTREES_VOLTAGE:
|
||
{
|
||
for (i=0; i<entrees.volt.nb; i++)
|
||
{
|
||
if ((entrees.volt.entrees[i].flag_validite) &&
|
||
(entrees.volt.entrees[i].module == module) &&
|
||
(entrees.volt.entrees[i].no == no)) return(i);
|
||
}
|
||
break;
|
||
}
|
||
|
||
/* //------------------------------------
|
||
case TYPE_ENTREES_NMEA:
|
||
{
|
||
for (i=0; i<entrees.nmea.nb; i++)
|
||
{
|
||
if ((entrees.nmea.entrees[i].flag_validite) &&
|
||
(entrees.nmea.entrees[i].module == module) &&
|
||
(entrees.nmea.entrees[i].no == no)) return(i); // ATTENTION : pour les entrées NMEA, on n'a pas de no mais pgn et field.
|
||
}
|
||
break;
|
||
}
|
||
*/
|
||
/* //------------------------------------
|
||
case TYPE_ENTREES_OW :
|
||
{
|
||
for (i=0; i<MAX_NOMBRE_ENTREES_OW; i++)
|
||
{
|
||
if ((entrees.ow.entrees[i].flag_validite) &&
|
||
(entrees.ow.entrees[i].cle_primaire == no)) return(i); // ATTENTION : ici, c'est la clé primaire !
|
||
}
|
||
break;
|
||
}
|
||
*/
|
||
//------------------------------------
|
||
case TYPE_ENTREES_PREDEFINIES:
|
||
{
|
||
for (i=0; i<entrees.predefinies.nb; i++)
|
||
{
|
||
if ((entrees.predefinies.entrees[i].flag_validite) &&
|
||
(entrees.predefinies.entrees[i].module == module) &&
|
||
(entrees.predefinies.entrees[i].no == no)) return(i);
|
||
}
|
||
break;
|
||
}
|
||
|
||
//------------------------------------
|
||
case TYPE_ENTREES_CORE:
|
||
{
|
||
for (i=0; i<MAX_NOMBRE_ENTREES_CORE; i++)
|
||
{
|
||
if ((entrees.core.entrees[i].flag_validite) &&
|
||
(entrees.core.entrees[i].no == no)) return(i);
|
||
}
|
||
break;
|
||
}
|
||
|
||
//------------------------------------
|
||
case TYPE_ENTREES_GPIO:
|
||
{
|
||
for (i=0; i<MAX_NOMBRE_ENTREES_GPIO; i++)
|
||
{
|
||
if ((entrees.gpio.entrees[i].flag_validite) &&
|
||
(entrees.gpio.entrees[i].no == no)) return(i);
|
||
}
|
||
break;
|
||
}
|
||
|
||
//------------------------------------
|
||
default: ;
|
||
}
|
||
|
||
return (-1); // Si on est arrivé au bout de la boucle, on renvoi le code de 'non trouvé'.
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************************************************************************************
|
||
Fonction LECTURE_ENTREE_GPIO
|
||
|
||
Fonction utilisée pour lire l'état de l'entrée dans les registres du BCM283x en fonction du N° d'entrée GPIO (0 à 53) et de la logique (-1 = logique inversée)
|
||
NB : cette fonction ne doit PAS être appelée en direct mais passer par la fonction 'lecture_entree' (cette fonction ne mets pas à jour l'état de l'entrée qui n'est donc pas mémorisé après la lecture)
|
||
**********************************************************************************************************************************************************************************/
|
||
uint8_t lecture_entree_gpio(uint8_t no, int8_t logique)
|
||
{
|
||
uint8_t x;
|
||
|
||
|
||
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V3)
|
||
{
|
||
enum gpiod_line_value val = gpiod_line_request_get_value(gpiod_entrees_request, no);
|
||
x = (val == GPIOD_LINE_VALUE_ACTIVE) ? ON : OFF;
|
||
}
|
||
else // Pour V1 & V2 : accès direct aux registres
|
||
{
|
||
// Lecture dans les registres du BCM2836 :
|
||
if (no < 32) // Entrées 0 à 31 :
|
||
{
|
||
if (((*(hardware.gpio_base + hardware.offset_gpio_pin_level_0)) & (1 << no)) != 0) x = ON;
|
||
else x = OFF;
|
||
}
|
||
else // Entrées 32 à 53 :
|
||
{
|
||
if (((*(hardware.gpio_base + hardware.offset_gpio_pin_level_1)) & (1 << (no - 32))) != 0) x = ON;
|
||
else x = OFF;
|
||
}
|
||
}
|
||
|
||
|
||
// Cas d'une sortie à logique inversée :
|
||
if (logique == -1)
|
||
{
|
||
if (x == ON) return(0);
|
||
else return(1);
|
||
}
|
||
else
|
||
{
|
||
if (x == ON) return(1);
|
||
else return(0);
|
||
}
|
||
}
|