/* USER CODE BEGIN 4 */
// Fonction qui transmet un caractère via UART et le renvoie.Utilisé pour la sortie standard (printf).
int __io_putchar(int ch) {
    HAL_UART_Transmit(&huart2, (uint8_t*) &ch10xFFFF); // Pour Envoyer le caractère via UART
    // ITM_SendChar(ch);                 // Option alternative pour envoyer le caractère via ITM
    return ch;
}
// Fonction d'écriture d'une nibble (moitié d'octet) sur l'écran LCD.
// Arguments : nibble - les 4 bits à écrire, rs - le bit registre (0 pour commande, 1 pour données)
void lcd_write_nibble(uint8_t nibbleuint8_t rs) {
    uint8_t data nibble << D4_BIT;                                // Déplace la nibble aux bits appropriés
    data |= rs << RS_BIT;                                           // Configure le bit registre
    data |= backlight_state << BL_BIT;                              // Inclut l'état du rétroéclairage dans les données
    data |= << EN_BIT;                                            // Configure le bit enable
    HAL_I2C_Master_Transmit(&hi2c1I2C_ADDR << 1, &data1100);  // Transmet les données à l'écran via I2C
    HAL_Delay(1);                                                   // Attente après la transmission
    data &= ~(<< EN_BIT);                                         // Désactive le bit enable
    HAL_I2C_Master_Transmit(&hi2c1I2C_ADDR << 1, &data1100);  // Retransmet les données sans l'activation
}
// Fonction d'envoi de commande à l'écran LCD.
void lcd_send_cmd(uint8_t cmd) {
    uint8_t upper_nibble cmd >> 4;    // Extrait les 4 bits supérieurs de la commande
    uint8_t lower_nibble cmd 0x0F;  // Extrait les 4 bits inférieurs de la commande
    lcd_write_nibble(upper_nibble0);  // Écrit la moitié supérieure de la commande
    lcd_write_nibble(lower_nibble0);  // Écrit la moitié inférieure de la commande
    if (cmd == 0x01 || cmd == 0x02) {   // Si le CMD est un reset ou un retour à la maison
        HAL_Delay(2);                   // Attente de 2ms pour compléter la commande
    }
}
// Fonction d'envoi d'un octet de données à l'écran LCD.
// Les données sont envoyées en deux parties: le nibble supérieur et le nibble inférieur.
void lcd_send_data(uint8_t data) {
    uint8_t upper_nibble data >> 4;     // Extraire les 4 bits supérieurs (le nibble supérieur)
    uint8_t lower_nibble data 0x0F;   // Extraire les 4 bits inférieurs (le nibble inférieur)
    lcd_write_nibble(upper_nibble1);    // Envoyer le nibble supérieur à l'écran LCD avec RS fixé à 1 pour indiquer que ce sont des données
    lcd_write_nibble(lower_nibble1);    // Envoyer le nibble inférieur à l'écran LCD avec RS fixé à 1 pour indiquer que ce sont des données
}
// Fonction d'initialisation de l'écran LCD.
// Ce processus comprend une série de commandes pour configurer l'écran correctement.
void lcd_init() {
    HAL_Delay(50);                // Attendre 50 ms pour permettre à l'écran de s'allumer
    lcd_write_nibble(0x030);    // Envoyer la commande d'initialisation 0x03 pour démarrer en mode 4 bits
    HAL_Delay(5);                 // Attendre 5 ms
    lcd_write_nibble(0x030);    // Répéter la commande d'initialisation 0x03
    HAL_Delay(1);                 // Attendre 1 ms
    lcd_write_nibble(0x030);    // Répéter à nouveau la commande d'initialisation 0x03 pour assurer la mise en mode 4 bits
    HAL_Delay(1);                 // Attendre 1 ms
    lcd_write_nibble(0x020);    // Envoyer la commande pour passer en mode 4 bits
    lcd_send_cmd(0x28);           // Configurer le LCD en mode 4 bits, 2 lignes, 5x7 dots
    lcd_send_cmd(0x0C);           // Activer l'affichage et désactiver le curseur
    lcd_send_cmd(0x06);           // Définir le mode d'entrée à incrémentation sans décalage d'affichage
    lcd_send_cmd(0x01);           // Effacer l'écran
    HAL_Delay(2);                 // Attendre 2 ms pour s'assurer que l'écran est bien effacé
}
// Fonction d'écriture de chaîne de caractères sur l'écran LCD.
// On utilise la fonction lcd_send_data pour envoyer chaque caractère.
void lcd_write_string(char *str) {
    while (*str) {
        lcd_send_data(*str++); // Envoyer chaque caractère de la chaîne
    }
}
// Fonction de positionnement du curseur de l'écran LCD sur la ligne et la colonne spécifiées.
void lcd_set_cursor(uint8_t rowuint8_t column) {
    uint8_t address;
    switch (row) {
    case 0:
        address 0x00;         // Adresse de mémoire de la première ligne
        break;
    case 1:
        address 0x40;         // Adresse de mémoire de la deuxième ligne
        break;
    default:
        address 0x00;         // Par défaut : première ligne
    }
    address += column;              // Ajouter la colonne à l'adresse de base
    lcd_send_cmd(0x80 address);   // Envoyer la commande de positionnement de curseur
}
// Fonction d'effacement de l'écran LCD.
void lcd_clear(void) {
    lcd_send_cmd(0x01); // Envoyer la commande d'effacement de l'écran
    HAL_Delay(2);       // Attendre 2 ms pour s'assurer que l'effacement est complet
}
// Fonction de contrôle d'état du rétroéclairage de l'écran LCD.
void lcd_backlight(uint8_t state) {
    if (state) {
        backlight_state 1// Allumer le rétroéclairage
    else {
        backlight_state 0// Éteindre le rétroéclairage
    }
}
/* USER CODE END 4 */