#include <MD_MAX72xx.h>
#include <SPI.h>

// ===== LED Matrix Setup =====
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 1

#define DATA_PIN D7
#define CS_PIN   D8
#define CLK_PIN  D0

MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// ===== Ultrasonic Pins =====
#define TRIG_PIN D5
#define ECHO_PIN D6

long duration;
float distance;

// 👉 Set tank height (cm)
float tankHeight = 15.0;

// ===== Setup =====
void setup()
{
  Serial.begin(9600);

  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);

  mx.begin();
  mx.control(MD_MAX72XX::INTENSITY, 5);
  mx.clear();

  Serial.println("Water Level System Started...");
}

// ===== Distance Function =====
float getDistance()
{
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);

  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  duration = pulseIn(ECHO_PIN, HIGH);

  float dist = duration * 0.034 / 2;
  return dist;
}

// ===== Display RIGHT SIDE (COLUMN STEP) =====
void showLevel(int level)
{
  mx.clear();

  // Convert % → columns (0–8)
  int cols = map(level, 0, 100, 0, 8);

  // Fill from RIGHT side (column 7 → 0)
  for (int j = 0; j < cols; j++)
  {
    for (int i = 0; i < 8; i++)
    {
      mx.setPoint(i, 7 - j, true);
    }
  }
}

// ===== Loop =====
void loop()
{
  float dist = getDistance();

  Serial.print("Distance: ");
  Serial.print(dist);
  Serial.println(" cm");

  // Sensor safety
  if (dist <= 0 || dist > tankHeight)
  {
    Serial.println("Sensor Error!");
    delay(1000);
    return;
  }

  // Calculate level %
  float level = ((tankHeight - dist) / tankHeight) * 100;
  level = constrain(level, 0, 100);

  Serial.print("Water Level: ");
  Serial.print(level);
  Serial.println(" %");

  // Show on matrix
  showLevel((int)level);

  delay(1000);
}