Files
shipheart-appli/sources/entrees.c
T

885 lines
35 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//**********************************************************************************************************************************************************************************
// 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);
}
}