#include <Wire.h>              // Include the Wire library for I2C
#include <hd44780.h>           // Include the hd44780 LCD library
#include <hd44780_I2C.h>       // Include the hd44780 I2C library

#define STM32L0XX
#include "stm32l0xx_hal.h"
#include "stm32l0xx.h"
#include "stm32l0xx_hal_conf.h"
#include "stm32l0xx_hal_gpio.h"

// Definitions for STM32 Nucleo-L031C6 board
#define HSE_VALUE    8000000U  // Value of the External oscillator in Hz
#define VDD_VALUE    3300U      // Value of the supply voltage in mV
#define STM32L031xx    // Spécifiez ici le modèle STM32L0xx (par exemple, STM32L031xx, STM32L011xx)

// I2C handle
I2C_HandleTypeDef hi2c1;

// Initialize I2C1
#define MX_I2C1_Init() { \
  hi2c1.Instance = I2C1; \
  hi2c1.Init.ClockSpeed = 100000; \
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; \
  hi2c1.Init.OwnAddress1 = 0x00; \
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; \
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; \
  hi2c1.Init.OwnAddress2 = 0; \
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; \
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; \
  if (HAL_I2C_Init(&hi2c1) != HAL_OK) { \
    Error_Handler(); \
  } \
}

// Error handler
void Error_Handler(void) {
  while (1) {
    // Stay in loop if there is an error
  }
}

// Initialize LCD I2C
hd44780_I2C lcd(0x27); // Address 0x27, 16 columns x 2 lines

// Function to measure distance using HC-SR04 sensor
long measureDistance() {
  // Send pulse to TRIG_PIN
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Read pulse duration from ECHO_PIN
  long duration = pulseIn(ECHO_PIN, HIGH);

  // Calculate distance in cm (speed of sound = 343 m/s)
  return duration * 0.034 / 2;
}

void setup() {
  HAL_Init();  // Initialize the HAL Library
  SystemClock_Config();  // Configure the system clock
  
  MX_I2C1_Init();               // Initialize I2C1
  lcd.begin(16, 2);             // Initialize LCD 16x2
  lcd.clear();
  lcd.print("Parking System");
  delay(2000);
  lcd.clear();

  // Configure pins
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
}

void loop() {
  // Measure distance
  long distance = measureDistance();

  // Display distance on LCD
  lcd.setCursor(0, 0);
  lcd.print("Distance: ");
  lcd.print(distance);
  lcd.print(" cm");

  // LED and status management
  if (distance < 30) { // If distance is less than 30 cm
    digitalWrite(GREEN_LED, LOW);  // Turn off green LED
    digitalWrite(RED_LED, HIGH);   // Turn on red LED
    lcd.setCursor(0, 1);
    lcd.print("Parking Full!");
  } else { // If distance is 30 cm or more
    digitalWrite(GREEN_LED, HIGH); // Turn on green LED
    digitalWrite(RED_LED, LOW);    // Turn off red LED
    lcd.setCursor(0, 1);
    lcd.print("Space Available");
  }

  // Pause before next measurement
  delay(1000);
}