// Introductory Stuff
#include <Keypad.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int ROW_NUM = 4; //four rows
const int COLUMN_NUM = 4; //four columns
const int red_button_pin = 39;
const int green_button_pin = 41;
const int blue_button_pin = 43;
const int color_switch_pin = 45;
const int enter_time_pin = 47;
const int test_strip_pin = 51;
const int expose_button_pin = 53;
const int LED_test_pin = 49;

char keys[ROW_NUM][COLUMN_NUM] = {
  {'1','2','3',},
  {'4','5','6', '.'},
  {'7','8','9', '/'},
  {'*','0','#',}
};

//LiquidCrystal_I2C lcd(0x27, 20, 4);  



byte pin_rows[ROW_NUM] = {23, 25, 27, 29}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {31, 33, 35, 37}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );

String inputString;
long inputInt;
int led_value_r;
int led_value_g;
int led_value_b;
int led_value_UV;
int old_led_r;
int old_led_g;
int old_led_b;
float base_value = 0;
int stop_1;
int stop_2;
float stop_fraction;
int stops;
float float_stops = 0;

int red_button_state = 0;
int green_button_state = 0;
int blue_button_state = 0;

int test_strip_state = 0;

int color_switch_state = 0;
int old_color_mode = 0;
int LED_test_state;
int enter_time_state = 0;

int expose_button_state = 0;

int mode = 0;
int color_mode = 1;
int data_mode = 0;
int test_strip_mode = 0;
int expose_mode = 0;

float total = 0;
float total_time[49];
float expose_time[49];
int time_set = 0;
int stops_var;
int stops_n;
int exposure_count = 0;
int stops_total;
int lights_on;
long timer;
float time_remaining;


void setup() {
  Serial.begin(57600);
  inputString.reserve(3); // maximum number of digit for a number is 10, change if needed
  //lcd.backlight();
 // lcd.init(); 
  Wire.begin();

  pinMode(red_button_pin, INPUT);
  pinMode(green_button_pin, INPUT);
  pinMode(blue_button_pin, INPUT);
  pinMode(LED_test_pin, OUTPUT);
  pinMode(color_switch_pin, INPUT);
  
 // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(500); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawRect(0, 0, 65, 11, SSD1306_WHITE);
  
  display.drawRect(0, 34, 40, 11, WHITE);
  display.drawRect(41, 34, 46, 11, WHITE);
  display.drawRect(88, 34, 40, 11, WHITE);
  display.drawRect(0, 44, 40, 20, WHITE);
  display.drawRect(41, 44, 46, 20, WHITE);
  display.drawRect(88, 44, 40, 20, WHITE);





  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();




}

void loop() {

  //get data from pins

  int red_button_state;
  red_button_state = digitalRead(red_button_pin);
  int green_button_state;
  green_button_state = digitalRead(green_button_pin); 
  int blue_button_state;
  blue_button_state = digitalRead(blue_button_pin); 

  int color_switch_state;
  color_switch_state = digitalRead(color_switch_pin);

  int enter_time_state;
  enter_time_state = digitalRead(enter_time_pin);

  int test_strip_state;
  test_strip_state = digitalRead(test_strip_pin);

  int expose_button_state;
  expose_button_state = digitalRead(expose_button_pin);

  // set timer mode from switch
      
  display.setCursor(2, 2);
  display.setTextColor(WHITE,BLACK);
  display.setTextSize(1);
  display.print("F-STOP    ");
  display.drawRect(66, 0, 62, 11, WHITE);
  display.drawRect(0, 12, 33, 11, WHITE);
  display.drawRect(32, 12, 33, 11, WHITE);
  display.drawRect(0, 22, 33, 11, WHITE);
  display.drawRect(32, 22, 33, 11, WHITE);
        
  display.setTextColor(WHITE,BLACK);
  display.setTextSize(1);
  display.setCursor(2, 14);
  display.print("BASE");
  display.setCursor(34, 14);
  display.print("STOP"); 
  display.display();

  if (enter_time_state == HIGH) {
    data_mode = 1;
    expose_mode = 1;
    display.setCursor(68, 2);
    display.setTextColor(WHITE,BLACK);
    display.setTextSize(1);
    display.print("STOPS    ");
    base_value = 0;
    display.setCursor (2, 24);
    display.print (base_value);
    stop_1 = 0;
    stop_2 = 0;
    display.setCursor (34, 24);
    display.print (stop_1);
    display.print ("/");
    display.print (stop_2);
    display.print ("  ");
    stops = 0;
    display.setTextSize (2);
    display.setCursor (66, 12);
    display.print (stops);
    display.print ("    ");
    display.drawRect(41, 34, 46, 11, WHITE);
    display.drawRect(88, 34, 40, 11, WHITE);
    time_set = 0;
    display.display();
  } 
  if (test_strip_state == HIGH) {
    data_mode = 1;
    expose_mode = 2;
    display.setTextColor(WHITE,BLACK);
    display.setTextSize(1);
    display.setCursor(68, 2);
    display.print("STOPS    ");
    base_value = 0;
    display.setCursor(2,2);
    display.print("TEST STRIP");
    display.setCursor (2, 24);
    display.print (base_value);
    stop_1 = 0;
    stop_2 = 0;
    display.setCursor (34, 24);
    display.print (stop_1);
    display.print ("/");
    display.print (stop_2);
    display.print ("  ");
    stops = 0;
    display.setTextSize (2);
    display.setCursor (66, 12);
    display.print (stops);
    display.print ("    ");
    display.drawRect(41, 34, 46, 11, WHITE);
    display.drawRect(88, 34, 40, 11, WHITE);
    time_set = 0;
    display.display();
  }        

  
            
            
            
  //input F-Stop mode data          
  while (data_mode == 1){
    time_set = 0;
    display.fillRect(66, 28, 28, 4,  BLACK);
    display.display();
    char key = keypad.getKey();
      
    if (key) {
      Serial.println(key);

      if (key != '#' & key != '*' & key != '/') {
      inputString += key;
      display.setCursor(2, 24);
      display.setTextColor(WHITE,BLACK);
      display.setTextSize(1);
      display.print("     ");
      display.setCursor(2, 24);
      display.print(inputString);
      display.display();
      }
      if (key == '#') {
        if (inputString.length() > 0) {
        base_value = inputString.toFloat(); // YOU GOT A FLOAT NUMBER
        inputString = "";
        display.setCursor(2, 24);
        display.setTextColor(WHITE,BLACK);
        display.setTextSize(1);
        display.print(base_value);
        display.display();
        data_mode = 2;
        }
      }else if (key == '*') {
        inputString = "";
        data_mode = 0;
      }
    }
  } 

  while (data_mode == 2){
           
    char key = keypad.getKey();
      
    if (key) {
      Serial.println(key);
      if (key != '/' & key != '*' & key !='#' & key != '.') {
        inputString += key;
        display.setCursor(34, 24);
        display.setTextColor(WHITE,BLACK);
        display.setTextSize(1);
        display.print("     ");
        display.setCursor(34, 24);
        display.print(inputString);
        display.display();
      }
      if (key == '/' ) {
        if (inputString.length() > 0) {
          stop_1 = inputString.toInt();
          inputString = "";
          if (stop_1 > 1) {
            stop_1 = 1;
          }
          display.setCursor(34, 24);
          display.setTextColor(WHITE,BLACK);
          display.setTextSize(1);
          display.print(stop_1);
          display.print("/");
          display.display();
          data_mode = 3;
        }
      } else if (key == '*') {
        inputString = "";
        data_mode = 0;
      }
    }
  } 

  while (data_mode == 3){
            
    char key = keypad.getKey();
      
    if (key) {
      Serial.println(key);
      if (key != '/' & key != '*' & key !='#' & key != '.') {
        inputString += key;
        display.setCursor(34, 24);
        display.setTextColor(WHITE,BLACK);
        display.setTextSize(1);
        display.print(stop_1);
        display.print("/");
        display.print(inputString);
        display.display();
      }
      if (key == '#') {
        if (inputString.length() > 0) {
          stop_2 = inputString.toInt();
          inputString = "";
          display.setCursor(34, 24);
          display.setTextColor(WHITE,BLACK);
          display.setTextSize(1);
          display.print(stop_1);
          display.print("/");
          display.print(stop_2);
          display.display();
          data_mode = 4;
        }
      }else if (key == '*') {
        inputString = "";
        data_mode = 0;
      }
    }
          
  } 

  while (data_mode == 4) {
    char key = keypad.getKey();
      
      if (key) {
        Serial.println(key);
        if (key != '/' & key != '*' & key !='#' & key != '.') {
          inputString += key;
          display.setCursor(66, 12);
          display.setTextColor(WHITE,BLACK);
          display.setTextSize(2);
          display.print("   ");
          display.setCursor(66, 12);
          display.print(inputString);
          display.drawRect(41, 34, 46, 11, WHITE);
          display.drawRect(88, 34, 40, 11, WHITE);
          display.display();
        }
        if (key == '#' && expose_mode == 1) {
          if (inputString.length() > 0) {
            if (stops > 48) {
              stops = 48;
            }
            stops = inputString.toInt();
            inputString = "";
            display.setCursor(68, 2);
            display.setTextColor(WHITE,BLACK);
            display.setTextSize(1);
            display.print("TOTAL    ");
            time_set = 1;
            display.display();
            data_mode = 0;
          }
        }else if (key == '*') {
          inputString = "";
          data_mode = 0;
        }
        if (key == '#' && expose_mode == 2) {
          if (inputString.length() > 0) {
            stops = inputString.toInt();
            stops_total = stops;
            if (stops > 48) {
              stops = 48;
            }
            inputString = "";
            display.setCursor(68, 2);
            display.setTextColor(WHITE,BLACK);
            display.setTextSize(1);
            display.print("EXP   /  ");
            time_set = 1;
            display.display();
            data_mode = 0;
            
          }
        }else if (key == '*') {
          inputString = "";
          data_mode = 0;
        }
      }
  }   
 
  if (time_set == 1) {
    display.fillRect(66, 28, 28, 4,  WHITE);
    display.display();
  } else {
    display.fillRect(66, 28, 28, 4,  BLACK);
    display.display();
  }

  if (time_set == 1 && expose_mode == 2) {
    
    stop_fraction = (float) stop_1 / stop_2;
    stops_var = stops;
    for (data_mode == 0 && expose_mode ==2; stops_var > 0; stops_var--) {
      total_time[stops_var] = base_value * pow (2, stop_fraction*(stops_var - 1));
    }
    total_time[0] = 0;
    while (stops > 0) {
      char key = keypad.getKey();
      expose_button_state = digitalRead(expose_button_pin);
      display.setCursor(92, 2);
      display.setTextColor(WHITE,BLACK);
      display.setTextSize(1);
      display.print(abs(stops - (stops_total + 1)));
      display.print("/");
      display.print(stops_total);
      stops_n = stops - 1;
      expose_time[stops] = total_time[stops] - total_time[stops_n];
      display.fillRect(66, 12, 63, 14, BLACK);
      display.setTextSize (2);
      display.setCursor (66, 12);
      display.drawRect(41, 34, 46, 11, WHITE);
      display.drawRect(88, 34, 40, 11, WHITE);
      if (100 > expose_time[stops]) {
        display.print(expose_time[stops], 2);
      } else if (1000 > expose_time[stops] > 100) {
        display.print(expose_time[stops], 1);   
      } else {
        display.print (expose_time[stops], 0);
      }
      display.display();
      if (expose_button_state == HIGH) {
        lights_on = 1;
        digitalWrite(LED_test_pin, HIGH);
        timer = millis() + (expose_time[stops] * 1000);    
        while (timer > millis()) {
          display.fillRect(66, 12, 63, 14, BLACK);
          display.setTextSize (2);
          display.setCursor (66, 12);
          time_remaining = (float) (timer - millis()) / 1000;
          if (time_remaining > 0) {
            if (999.9 < time_remaining) {
              display.print(time_remaining, 0);
            } 
            if (999.9 > time_remaining && 99.99 < time_remaining) {
              display.print(time_remaining, 1);
            } 
            if (99.99 > time_remaining) {
              display.print(time_remaining, 2);
            }
          }
        display.drawRect(41, 34, 46, 11, WHITE);
        display.drawRect(88, 34, 40, 11, WHITE);
        display.display();
      }
      lights_on = 0;
      digitalWrite(LED_test_pin, LOW);
      stops = stops - 1;
      }
      if (key == '*') {
        inputString = "";
        stops = 0;
      }
    }
    display.setCursor(68, 2);
    display.setTextColor(WHITE, BLACK);
    display.setTextSize(1);
    display.print("TEST DONE");
    time_set = 0;
    }

  if (time_set == 1 && expose_mode == 1) {
    stop_fraction = (float) stop_1 / stop_2;
    total = base_value * pow (2, stop_fraction*(stops - 1));
    display.fillRect(66, 12, 63, 14, BLACK);
    display.setTextSize (2);
    display.setCursor (66, 12);
    display.drawRect(41, 34, 46, 11, WHITE);
    display.drawRect(88, 34, 40, 11, WHITE);
    if (100 > total) {
      display.print(total, 2);
    } else if (1000 > total > 100) {
      display.print(total, 1);   
    } else {
      display.print (total, 0);
    }
    display.display();
    if (expose_button_state == HIGH) {
      digitalWrite(LED_test_pin, HIGH);
      timer = millis() + (total * 1000); 
      while (timer > millis()) {
        display.fillRect(66, 12, 63, 14, BLACK);
        display.setTextSize (2);
        display.setCursor (66, 12);
        time_remaining = (float) (timer - millis())/1000;
        if (time_remaining > 0) {
          if (999.9 < time_remaining) {
            display.print(time_remaining, 0);
          } 
          if (999.9 > time_remaining && 99.99 < time_remaining) {
            display.print(time_remaining, 1);
          } 
          if (99.99 > time_remaining) {
            display.print(time_remaining, 2);
          }
        }
        display.drawRect(41, 34, 46, 11, WHITE);
        display.drawRect(88, 34, 40, 11, WHITE);
        display.display();
      }
      lights_on = 0;
      digitalWrite(LED_test_pin, LOW);
      display.fillRect(66, 12, 63, 14, BLACK);
      display.setTextSize (2);
      display.setCursor (66, 12);
      if (100 > total) {
        display.print(total, 2); 
      } else if (1000 > total > 100) {
        display.print(total, 1);
      } else {
        display.print(total, 0);
      }
      display.drawRect(41, 34, 46, 11, WHITE);
      display.drawRect(88, 34, 40, 11, WHITE);
    }
  }
   
  


// set color mode from switch

  if (color_switch_state == HIGH){
    color_mode = 1;
    if (color_mode == old_color_mode) {
      display.clearDisplay();
      display.drawRect(0, 0, 65, 11, SSD1306_WHITE);
      display.drawRect(0, 34, 40, 11, WHITE);
      display.drawRect(41, 34, 46, 11, WHITE);
      display.drawRect(88, 34, 40, 11, WHITE);
      display.drawRect(0, 44, 40, 20, WHITE);
      display.drawRect(41, 44, 46, 20, WHITE);
      display.drawRect(88, 44, 40, 20, WHITE);
    }
    old_color_mode = 2;

  } else if (color_switch_state == LOW) {
    color_mode = 2;
    if (color_mode == old_color_mode) {
      display.clearDisplay();
      display.drawRect(0, 0, 65, 11, SSD1306_WHITE);
      display.drawRect(0, 34, 40, 11, WHITE);
      display.drawRect(41, 34, 46, 11, WHITE);
      display.drawRect(88, 34, 40, 11, WHITE);
      display.drawRect(0, 44, 40, 20, WHITE);
      display.drawRect(41, 44, 46, 20, WHITE);
      display.drawRect(88, 44, 40, 20, WHITE);
    }
    old_color_mode = 1;

  }



// set color values from keypad and color buttons

  if (color_mode == 1) {
    display.setTextColor(WHITE,BLACK);
    display.setTextSize(1);
    display.setCursor (2, 36);
    display.print ("RED");
    display.setCursor (43, 36);
    display.print ("GREEN");
    display.setCursor (90, 36);
    display.print ("BLUE");
    led_value_UV = 0;

    display.setTextSize(2);
    display.setCursor (2, 47);
    display.print (led_value_r);
    display.setTextSize(1); 

    display.setTextSize(2);
    display.setCursor (43, 47);
    display.print (led_value_g);
    display.setTextSize(1);

    display.setTextSize(2);
    display.setCursor (90, 47);
    display.print (led_value_b);
    display.setTextSize(1);

    if (red_button_state == HIGH) {
      mode = 1;
    }

    if (green_button_state == HIGH) {
        mode = 2;
    }

    if (blue_button_state == HIGH) {
      mode = 3;
    }

    if (mode == 0) {
      display.fillRect(96, 28, 28, 4,  WHITE);
      display.display();
    } else {
      display.fillRect(96, 28, 28, 4,  BLACK);
      display.display();
    }

    while (mode == 1) {
        
      char key = keypad.getKey();
    
      if (key) {
        Serial.println(key);

        if (key >= '0' && key <= '9') {     // only act on numeric keys
          inputString += key;               // append new character to input string
          if (inputString.length() <= 3) {
            display.setCursor(2, 47);
            display.setTextColor(WHITE,BLACK);
            display.setTextSize(2);
            display.print("   ");
            display.setCursor(2, 47);
            display.print(inputString);
            display.display();
          }
            
        } else if (key == '#') {
          if (inputString.length() > 0) {
            led_value_r = inputString.toInt(); // YOU GOT AN INTEGER NUMBER
            inputString = "";               // clear input
            mode = 0;
          }
        } else if (key == '*') {
            inputString = "";                 // clear input
            mode = 0;
        }

      } 
        
      if (led_value_r > 255) {
        led_value_r = 255;

      } if (led_value_r < 0) {
        led_value_r = 0;
      }

      if (led_value_r != old_led_r) {

        display.setTextSize(2);
        display.setCursor (2, 47);
        display.print ("   ");
          
      }

      display.setTextSize(2);
      display.setCursor (2, 47);
      display.print (led_value_r);
      display.setTextSize(1);

      old_led_r = led_value_r;        
        
    }

    while (mode == 2) {
    
      char key = keypad.getKey();
      
      if (key) {
        Serial.println(key);

        if (key >= '0' && key <= '9') {     // only act on numeric keys
          inputString += key;               // append new character to input string
          if (inputString.length() <= 3) {
            display.setCursor(43, 47);
            display.setTextColor(WHITE,BLACK);
            display.setTextSize(2);
            display.print("   ");
            display.setCursor(43, 47);
            display.print(inputString);
            display.display();
          }
            
        } else if (key == '#') {
          if (inputString.length() > 0) {
            led_value_g = inputString.toInt(); // YOU GOT AN INTEGER NUMBER
            inputString = ""; 
            mode = 0;              // clear input 
          }

        } else if (key == '*') {
            inputString = "";    
            mode = 0;             // clear input
        } 

      } 
      
      if (led_value_g > 255) {
        led_value_g = 255;
        
      } if (led_value_g < 0) {
        led_value_g = 0;
      }

      if (led_value_g != old_led_g) {
        display.setTextSize(2);
        display.setCursor (43, 47);
        display.print ("   ");
      }
      
      display.setTextSize(2);
      display.setCursor (43, 47);
      display.print (led_value_g);
      display.setTextSize(1);

      old_led_g = led_value_g;
    }
    
    while (mode == 3) {
    
      char key = keypad.getKey();
    
      if (key) {
        Serial.println(key);

        if (key >= '0' && key <= '9') {     // only act on numeric keys
          inputString += key;               // append new character to input string
          if (inputString.length() <= 3) {
           display.setCursor(90, 47);
            display.setTextColor(WHITE,BLACK);
            display.setTextSize(2);
            display.print("   ");
            display.setCursor(90, 47);
            display.print(inputString);
            display.display();
          }
            
        } else if (key == '#') {
          if (inputString.length() > 0) {
            led_value_b = inputString.toInt(); // YOU GOT AN INTEGER NUMBER
          inputString = "";               // clear input
          mode = 0;
          }   
      
        } else if (key == '*') {
          inputString = "";                 // clear input
          mode = 0;
        }

      } 
        
      if (led_value_b > 255) {
        led_value_b = 255;
      } 
        
      if (led_value_b < 0) {
        led_value_b = 0;
      }

      if (led_value_b != old_led_b) {
        display.setTextSize(2);
        display.setCursor (90, 47);
        display.print ("   ");
      }
   
      display.setTextSize(2);
      display.setCursor (90, 47);
      display.print (led_value_b);
      display.setTextSize(1);

      old_led_b = led_value_b;

    }

  } else if (color_mode == 2){
    display.setTextColor(WHITE,BLACK);
    display.setTextSize(1);
    display.setCursor (2, 36);
    display.print ("   ");
    display.setCursor (43, 36);
    display.print ("      ");
    display.setCursor (90, 36);
    display.print ("    ");
    led_value_r = 0;
    led_value_g = 0;
    led_value_b = 0;
    led_value_UV = 255;

    display.setTextSize(2);
    display.setCursor (2, 47);
    display.print ("UV ");
    display.setCursor (43, 47);
    display.print ("UV ");
    display.setCursor (90, 47);
    display.print ("UV ");
    display.setTextSize(1);

  }

}