#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
#include "HX711.h"

//--------------------------------------------------------------------------------
// OLED Globals
//--------------------------------------------------------------------------------
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiAvrI2c oled;
// GND -> GND
// VCC -> 3.3V
// SCL -> A5
// SDA -> A4

//--------------------------------------------------------------------------------
// Setup Button Globals
//--------------------------------------------------------------------------------
#define SETUP_BTN 4
// Bottom-Right -> GND
// Top-Right -> 4

//--------------------------------------------------------------------------------
// Thousands Button Globals
//--------------------------------------------------------------------------------
#define THOUSANDS_BTN 2
// Bottom-Right -> GND
// Top-Right -> 13

//--------------------------------------------------------------------------------
// Hundreds Button Globals
//--------------------------------------------------------------------------------
#define HUNDREDS_BTN 12
// Bottom-Right -> GND
// Top-Right -> 12

//--------------------------------------------------------------------------------
// Tens Button Globals
//--------------------------------------------------------------------------------
#define TENS_BTN 11
// Bottom-Right -> GND
// Top-Right -> 11

//--------------------------------------------------------------------------------
// Ones Button Globals
//--------------------------------------------------------------------------------
#define ONES_BTN 10
// Bottom-Right -> GND
// Top-Right -> 1

//--------------------------------------------------------------------------------
// Start Button Globals
//--------------------------------------------------------------------------------
#define START_BTN 9
// Bottom-Right -> GND
// Top-Right -> 9

//--------------------------------------------------------------------------------
// Relay Globals
//--------------------------------------------------------------------------------
#define RELAY 8
// Bottom-Right -> GND
// Top-Right -> 8

//--------------------------------------------------------------------------------
// Stop Button Globals
//--------------------------------------------------------------------------------
#define STOP_BTN 7
// Bottom-Right -> GND
// Top-Right -> 7

//--------------------------------------------------------------------------------
// Load Scale Globals
//--------------------------------------------------------------------------------
#define LOAD_DT A1
#define LOAD_SCK A0
HX711 scale;
float calibration_factor = 420; // this calibration factor is adjusted according to my load cell
float units;
// DT -> A1
// SCK -> A0

//--------------------------------------------------------------------------------
// LED Pump Run Globals
//--------------------------------------------------------------------------------
#define LED_PUMP_RUN 6
// STRAIGHT C -> GND
// CURVED A -> 6

//--------------------------------------------------------------------------------
// Program Globals
//--------------------------------------------------------------------------------
int weight_desired = 0;
int weight_max = 4000;
int weight_current = 0;
String spaces = "                                       ";
String line_feed = "\n";
int delay_default = 250;

void setup() {
  //--------------------------------------------------------------------------------
  // OLED Setup
  //--------------------------------------------------------------------------------
  oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
  oled.setFont(Callibri11);
  oled.clear();
  String banner_spacing = "      ";
  String msg = line_feed + banner_spacing + "Bath Bomb Xpress" + line_feed + banner_spacing + "Liquid Filling Station";
  oled.print(msg);

  //--------------------------------------------------------------------------------
  // SETUP, THOUSANDS, HUNDREDS, TENS, ONES, START Button Setup
  //-------------------------------------------------------------------------------- 
  pinMode(SETUP_BTN, INPUT_PULLUP); // setup button 
  pinMode(THOUSANDS_BTN, INPUT_PULLUP); // thousands button
  pinMode(HUNDREDS_BTN, INPUT_PULLUP); // hundreds button
  pinMode(TENS_BTN, INPUT_PULLUP); // tens button
  pinMode(ONES_BTN, INPUT_PULLUP); // ones button
  pinMode(START_BTN, INPUT_PULLUP); // start button
  pinMode(STOP_BTN, INPUT_PULLUP); // stop button

  //--------------------------------------------------------------------------------
  // Relay Setup
  //--------------------------------------------------------------------------------  
  pinMode(RELAY, OUTPUT); // Relay
  digitalWrite(RELAY, LOW);

  //--------------------------------------------------------------------------------
  // Load Scale Setup
  //--------------------------------------------------------------------------------
  scale.begin(LOAD_DT, LOAD_SCK);  
  scale.set_scale(calibration_factor); //Adjust to this calibration factor
  delay(delay_default * 12); // 3 seconds
  scale.tare();

  //--------------------------------------------------------------------------------
  // LED Setup
  //--------------------------------------------------------------------------------
  pinMode(LED_PUMP_RUN, OUTPUT);
}

void loop() {
  show_default_screen();
  if (digitalRead(SETUP_BTN) == LOW) {
    show_settings();
  }
  if (digitalRead(START_BTN) == LOW) {
    run_filler();
  }
}

void show_settings() {
  oled.clear();
  String msg = "Set Desired Weight: " + String(weight_desired);
  oled.print(msg); 
  delay(delay_default);

  while (true) {
    int adjustment = 0;
    if (digitalRead(THOUSANDS_BTN) == LOW) {
      adjustment += 1000;
    } 
    if (digitalRead(HUNDREDS_BTN) == LOW) {
      adjustment += 100;
    } 
    if (digitalRead(TENS_BTN) == LOW) {
      adjustment += 10;
    }
    if (digitalRead(ONES_BTN) == LOW) {
      adjustment += 1;
    }
    if (adjustment > 0) {
      weight_desired += adjustment;
      if (weight_desired > weight_max) {
        weight_desired = 0;
        oled.setCursor(0, 0);
        msg = "Overflow value of " + String(weight_max) + spaces + line_feed + "Setting set to zero" + spaces;
        oled.print(msg);
        delay(delay_default * 12);
      }
      oled.setCursor(0, 0);
      msg = "Set Desired Weight: " + String(weight_desired) + spaces + line_feed + spaces + spaces;
      oled.print(msg);  
      delay(delay_default);
    }

    if (digitalRead(SETUP_BTN) == LOW) {
      break;
    }
  }
  show_default_screen();
  delay(delay_default);
}

void run_filler() {
  if (weight_desired > 0) {
    digitalWrite(RELAY, HIGH);
    digitalWrite(LED_PUMP_RUN, HIGH);
    scale.tare();
    while (true) {
      if (digitalRead(STOP_BTN) == LOW) {
        break;
      }
      show_default_screen();   
      if (weight_current >= weight_desired) {
        break;
      }
    }
    digitalWrite(RELAY, LOW);
    digitalWrite(LED_PUMP_RUN, LOW);  
  }
}

void show_default_screen() {
  oled.setCursor(0,0);
  units = scale.get_units();
  weight_current = units * 1000;
  String msg = "Weight Desired: " + String(weight_desired) + spaces + "\nCurrent Weight: " + String(weight_current) + spaces + "\n" + spaces;
  oled.print(msg);  
}
NOCOMNCVCCGNDINLED1PWRRelay Module