#include "STM32_I2C_LCD.h"  // Inclusion de l'en-tête pour la gestion de l'écran LCD via I2C
#include <string.h>         // Inclusion de la bibliothèque standard pour les fonctions de manipulation de chaînes de caractères

// Variables internes
static I2C_HandleTypeDef *lcd_hi2c;  // Pointeur pour la structure de gestion I2C
static uint8_t backlight_state 1;  // État initial du rétroéclairage (activé)

// Fonctions internes
static void lcd_write_nibble(uint8_t nibbleuint8_t rs);   // Fonction pour écrire un demi-octet sur le bus I2C
static void lcd_send_cmd(uint8_t cmd);                      // Fonction pour envoyer une commande à l'écran LCD
static void lcd_send_data(uint8_t data);                    // Fonction pour envoyer des données à l'écran LCD

// Fonction d'initialisation de l'écran LCD
void lcd_init(I2C_HandleTypeDef *hi2c) {
    lcd_hi2c hi2c;            // Initialisation du pointeur I2C
    HAL_Delay(50);              // Délai d'attente pour la stabilisation
    lcd_write_nibble(0x030);  // Séquence d'initialisation en mode 8 bits
    HAL_Delay(5);
    lcd_write_nibble(0x030);
    HAL_Delay(1);
    lcd_write_nibble(0x030);
    HAL_Delay(1);
    lcd_write_nibble(0x020);  // Passage en mode 4 bits
    lcd_send_cmd(0x28);         // Configuration de l'écran en mode 4 bits, 2 lignes, police 5x8
    lcd_send_cmd(0x0C);         // Activation de l'affichage, désactivation du curseur
    lcd_send_cmd(0x06);         // Configuration pour l'incrémentation automatique du curseur
    lcd_send_cmd(0x01);         // Effacement de l'écran
    HAL_Delay(2);
}

// Fonction d'écriture de chaîne de caractères sur l'écran LCD
void lcd_write_string(char *str) {
    while (*str) {
        lcd_send_data(*str++);  // Envoie chaque caractère de la chaîne à l'écran
    }
}

// Fonction de positionnement du curseur de l'écran LCD
void lcd_set_cursor(uint8_t rowuint8_t column) {
    uint8_t address;
    switch (row) {
        case 0address 0x00break;      // Adresse de début pour la première ligne
        case 1address 0x40break;      // Adresse de début pour la deuxième ligne
        defaultaddress 0x00break;     // Valeur par défaut (première ligne)
    }
    address += column;              // Ajoute le décalage de colonne à l'adresse de début de la ligne
    lcd_send_cmd(0x80 address);   // Envoie la commande pour placer le curseur à la position souhaitée
}

// Fonction d'effacement de l'écran LCD
void lcd_clear(void) {
    lcd_send_cmd(0x01);     // Envoie la commande d'effacement
    HAL_Delay(2);           // Temps d'attente pour l'effacement
}

// Fonction de contrôle d'état du rétroéclairage de l'écran LCD
void lcd_backlight(uint8_t state) {
    backlight_state state 0;  // Modifie l'état du rétroéclairage selon l'argument passé
}

// Fonctions internes
static void lcd_write_nibble(uint8_t nibbleuint8_t rs) {
    uint8_t data nibble << D4_BIT;        // Déplace le demi-octet vers les bits de données
    data |= rs << RS_BIT;                   // Ajoute le bit de registre de sélection (RS)
    data |= backlight_state << BL_BIT;      // Ajoute l'état du rétroéclairage
    data |= << EN_BIT;                    // Ajoute le bit enable (EN)
    HAL_I2C_Master_Transmit(lcd_hi2cI2C_ADDR << 1, &data1100);  // Transmet les données via I2C
    HAL_Delay(1);                           // Délai pour stabilisation
    data &= ~(<< EN_BIT);                 // Désactive le bit enable (EN)
    HAL_I2C_Master_Transmit(lcd_hi2cI2C_ADDR << 1, &data1100);  // Transmet les données via I2C
}

static void lcd_send_cmd(uint8_t cmd) {
    uint8_t upper_nibble cmd >> 4;    // Extrait les 4 bits de poids fort de la commande
    uint8_t lower_nibble cmd 0x0F;  // Extrait les 4 bits de poids faible de la commande
    lcd_write_nibble(upper_nibble0);  // Envoie les bits de poids fort
    lcd_write_nibble(lower_nibble0);  // Envoie les bits de poids faible
    if (cmd == 0x01 || cmd == 0x02) {
        HAL_Delay(2);                   // Temps d'attente pour les commandes d'effacement et de retour à la maison
    }
}

static void lcd_send_data(uint8_t data) {
    uint8_t upper_nibble data >> 4;       // Extrait les 4 bits de poids fort des données
    uint8_t lower_nibble data 0x0F;     // Extrait les 4 bits de poids faible des données
    lcd_write_nibble(upper_nibble1);      // Envoie les bits de poids fort avec RS = 1 (données)
    lcd_write_nibble(lower_nibble1);      // Envoie les bits de poids faible avec RS = 1 (données)
}
// Fonction pour faire défiler le texte à droite
void lcd_scroll_right(void) {
    lcd_send_cmd(0x1E);                     // Envoie la commande pour le défilement à droite
}

// Fonction pour faire défiler le texte à gauche
void lcd_scroll_left(void) {
    lcd_send_cmd(0x18);                     // Envoie la commande pour le défilement à gauche
}