#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "IRremote.h"
#include "RTClib.h"
#include "DHTesp.h"

#define Pin_IC_Latch 15
#define Pin_IC_Data 4
#define Pin_IC_Clock 2
#define Pin_IRRX_DAT 23
#define Pin_SDCARD_CS 27
#define Pin_SDCARD_DI 13
#define Pin_SDCARD_SCK 14
#define Pin_SDCARD_DO 12
#define Pin_DHT22_SDA 18

int Mode = 0;
int Segment[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int Data[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const uint8_t DigitBin[3][10] =
{{0b11000000, 0b11111001, 0b10100100, 0b10110000,
0b10011001, 0b10010010, 0b10000010, 0b11111000,
0b10000000, 0b10010000}, // 0123456789
{0b01000000, 0b01111001, 0b00100100, 0b00110000,
0b00011001, 0b00010010, 0b00000010, 0b01111000,
0b00000000, 0b00010000}, // 0.1.2.3.4.5.6.7.8.9.
{0b10111111, 0b10000000, 0b01000000, 0b00100000,
0b00010000, 0b00001000, 0b00000100, 0b00000010,
0b00000001, 0b11111111}}; // D0,D1,D2,D3,D4,D5,D6,D7,D8,Dall
// -,A,C,E,F,H,K,L,P,U

LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 16, 2);
IRrecv IRRX(Pin_IRRX_DAT);
decode_results IRCode;
RTC_DS1307 RTC;
DHTesp DHT22;

void setup() {
pinMode(Pin_IC_Latch, OUTPUT);
pinMode(Pin_IC_Clock, OUTPUT);
pinMode(Pin_IC_Data, OUTPUT);
Serial.begin(9600);
Wire.begin();
RTC.begin();
LCD.begin(16, 2);
LCD.init();
LCD.backlight();
LCD.clear();
print_LCD_text("Welcome IR Key", 0, 0);
print_LCD_text("Starting .....", 0, 1);
IRRX.enableIRIn();
LCD.clear();
print_LCD_text("IR Ready", 0, 0);
show_SEGMENT_data(DigitBin[2][0], DigitBin[2][0], DigitBin[2][0], DigitBin[2][0]);
set_RTC_data();
DHT22.setup(Pin_DHT22_SDA, DHTesp::DHT22);
input_IRRX_selection();
delay(500);
}

void loop() {
if (Mode == 0) {set_SEGMENT_data();} // Default
if (Mode == 1) {input_IRRX_selection();}
}

void input_IRRX_data(int j) {
LCD.setCursor(0, 1);
while (j < 16) {
if (IRRX.decode()) {
IRRX.decode(&IRCode);
set_IRRX_number(j);
LCD.setCursor(j, 1);
LCD.print(Data[j]);
j++;
IRRX.resume();
}}}

void set_RTC_data() {
LCD.clear();
IRRX.decode(&IRCode);
print_LCD_text("hr:mn|dy-mo|year", 0, 0);
input_IRRX_data(3);
int hr = 10*Data[4] + Data[5];
int mn = 10*Data[6] + Data[7];
int dy = 10*Data[8] + Data[9];
int mo = 10*Data[10] + Data[11];
int yr = 1000*Data[12] + 100*Data[13] + 10*Data[14] + Data[15];
RTC.adjust(DateTime(yr, mo, dy, hr, mn, 1));
Segment[0] = 1000*Data[4] + 100*Data[5] + 10*Data[6] + Data[7];
}

void input_IRRX_selection() {
LCD.clear();
print_LCD_text("Press the button", 0, 0);
print_LCD_text("MENU/TEST/POWER.", 0, 1);
IRRX.decode(&IRCode);
switch (IRCode.value) {
case 0x378E71F: input_IRRX_number(); break;
case 0xF0DB1AE0: input_IRRX_power(); break;
case 0x298E8724: input_IRRX_menu(); break;
}}

void input_IRRX_power() {
LCD.noDisplay();
}

void input_IRRX_menu() {
LCD.display();
print_LCD_text("Time,Date,Temp", 0, 0);
print_LCD_text("Select 1,2,3>>", 0, 1);
input_IRRX_data(14);
if (Data[15] == 1) {Mode = 1;}
if (Data[15] == 2) {Mode = 2;}
if (Data[15] == 3) {Mode = 3;}
}

void input_IRRX_number() {
print_LCD_text("Enter 4D number", 0, 0);
input_IRRX_data(11);
Segment[0] = 1000*Data[12] + 100*Data[13] + 10*Data[14] + Data[15];
}

void set_IRRX_number(int j) {
switch (IRCode.value) {
case 0xE39FAC1B: Data[j] = 0; break;
case 0x6B7832FF: Data[j] = 1; break;
case 0x3D9AE3F7: Data[j] = 2; break;
case 0x31C5DD7B: Data[j] = 3; break;
case 0x45473C1B: Data[j] = 4; break;
case 0x63CBDADB: Data[j] = 5; break;
case 0x449E79F:  Data[j] = 6; break;
case 0x32C6FDF7: Data[j] = 7; break;
case 0x3EC3FC1B: Data[j] = 8; break;
case 0x1BC0157B: Data[j] = 9; break;
}}

void set_IRRX_function(int j) {
switch (IRCode.value) {
case 0x12209C7B: Data[j] = 1; break; // +
case 0x29494F40: Data[j] = -5; break; // BACK
case 0x710E7FC0: Data[j] = -10; break; // <<
case 0xA16E9120: Data[j] = 5; break; // >
case 0x23FCB924: Data[j] = 10; break; // >>
case 0x1C506100: Data[j] = -1; break; // -
case 0x4A2DB008: Data[j] = 0; break; // C
}}

void set_SEGMENT_data() {
DateTime now = RTC.now();
TempAndHumidity data = DHT22.getTempAndHumidity();
uint8_t S1, S2, S3, S4;
int sc = now.second();
int tp = int(data.temperature);
Segment[1] = (sc/10) % 10;
Segment[2] = sc % 10;
Segment[3] = (tp/10) % 10;
Segment[4] = tp % 10;
S1 = DigitBin[0][Segment[1]];
S2 = DigitBin[0][Segment[2]];
S3 = DigitBin[0][Segment[3]];
S4 = DigitBin[0][Segment[4]];
show_SEGMENT_data(S1, S2, S3, S4);
}

void print_LCD_text(char* text, int column, int row) {
LCD.setCursor(column, row);
LCD.print(text);
}

void show_SEGMENT_data(uint8_t S1, uint8_t S2, uint8_t S3, uint8_t S4) {
digitalWrite(Pin_IC_Latch, LOW);
shiftOut(Pin_IC_Data, Pin_IC_Clock, MSBFIRST, S4);
shiftOut(Pin_IC_Data, Pin_IC_Clock, MSBFIRST, S3);
shiftOut(Pin_IC_Data, Pin_IC_Clock, MSBFIRST, S2);
shiftOut(Pin_IC_Data, Pin_IC_Clock, MSBFIRST, S1);
digitalWrite(Pin_IC_Latch, HIGH);
}
74HC595
74HC595
74HC595
74HC595
GND5VSDASCLSQWRTCDS1307+