#include <U8g2lib.h>
#include <Wire.h>
#include <math.h>
#include <OneButton.h>

#include "myfont.h"
#define OLED_UPDATE_INTERVAL      100

U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);//这是比较常用的0.9寸的OLED显示器的驱动
OneButton btnUp(2);
OneButton btnDown(3);
OneButton btnOk(4);

u8 brightness    =  100;
float curTemp   = -8.8;
float tarTemp   = 28.0;
float rangeTemp = -3.0;
float offsetTemp = 0.0;
bool outState   = true;
bool curPower   = true;


unsigned long last_oled_update = 0;
void (*current_operation_index)();
u8 func_index = 0; //初始显示欢迎界面

typedef struct
{
	u8 current;
	u8 up;           //向上翻索引号
	u8 down;         //向下翻索引号
	u8 enter;        //确认索引号
	void (*current_operation);
} key_table;

void fun_0()
{
  u8g2.drawUTF8(10, 15, "^_^");
  u8g2.setCursor(48, 15);
  u8g2.print(curTemp, 1);
  u8g2.print("℃");
  if(outState) {
    u8g2.drawUTF8(104, 15, "on ");
  } else {
    u8g2.drawUTF8(104, 15, "off");
  }
  u8g2.drawUTF8(10, 36, "设置"); 
  u8g2.drawUTF8(10, 56, "温度"); 

  u8g2.setFont(u8g2_font_ncenR18_tn);
  u8g2.setCursor(52, 48);
  u8g2.print(tarTemp, 1);

  u8g2.setFont(u8g2_font_diy_t_myfont);
  u8g2.drawUTF8(104, 48, "℃");

}

void fun_abcd_common() {
  u8g2.drawUTF8(16, 15, "温度设置");
  u8g2.drawUTF8(16, 31, "遥控设置");
  u8g2.drawUTF8(16, 47, "亮度设置");
  u8g2.drawUTF8(16, 63, "返回上级");
}

void fun_a()   
{	
  u8g2.drawStr(0, 15, ">");
  fun_abcd_common();
}

void fun_b()   
{	
  u8g2.drawStr(0, 31, ">");
  fun_abcd_common();
}

void fun_c()   
{	
  u8g2.drawStr(0, 47, ">");
  fun_abcd_common();
}

/*********4***********/
void fun_d()   
{	
  u8g2.drawStr(0, 63, ">");
  fun_abcd_common();
}

void fun_a_common() {
  u8g2.drawUTF8(16, 15, "目标温度: "); 
  u8g2.setCursor(94, 15);
  u8g2.print(tarTemp, 1);
  u8g2.drawUTF8(16, 31, "温度回差: ");
  u8g2.setCursor(94, 31);
  u8g2.print(rangeTemp, 1);		  
  u8g2.drawUTF8(16, 47, "温度偏移: ");		
  u8g2.setCursor(94, 47);
  u8g2.print(offsetTemp, 1);		  	  
  u8g2.drawUTF8(16, 63, "返回上级");  
}

void fun_a1()    
{	
  u8g2.drawStr(0, 15, ">");
  fun_a_common();
}

void fun_a2()    
{	
  u8g2.drawStr(0, 31, ">");
  fun_a_common();
}

void fun_a3()    
{	
  u8g2.drawStr(0, 47, ">");
  fun_a_common();
}

void fun_a4()    
{	
  u8g2.drawStr(0, 63, ">");			
  fun_a_common();          														
}

void fun_b_common() {
  u8g2.drawUTF8(16, 15, "学习开启");
  u8g2.drawUTF8(16, 31, "学习关闭");
  u8g2.drawUTF8(16, 47, "测试遥控");
  u8g2.drawUTF8(16, 63, "返回上级");
}

void fun_b1()    
{	
  u8g2.drawStr(0, 15, ">");
  fun_b_common();
}

void fun_b2()    
{	
  u8g2.drawStr(0, 31, ">");			
  fun_b_common();          														
}

void fun_b3()    
{	
  u8g2.drawStr(0, 47, ">");	
  fun_b_common();
}

void fun_b4()    
{	
  u8g2.drawStr(0, 63, ">");
  fun_b_common();          														
}

void fun_c_common() {
  u8g2.drawUTF8(16, 15, "亮度调节:");
  u8g2.setCursor(94, 15);
  u8g2.print(brightness);
  u8g2.drawUTF8(16, 63, "返回上级");
}

void fun_c1() {	
  u8g2.drawStr(0, 15, ">");
  fun_c_common();
}

void fun_c2() {	
  u8g2.drawStr(0, 63, ">");
  fun_c_common();	         														
}

void fun_a1o() {
  u8g2.drawStr(0, 15, "*>");	
  fun_a_common();
}

void fun_a2o() {
  u8g2.drawStr(0, 31, "*>");	
  fun_a_common();
}

void fun_a3o() {
  u8g2.drawStr(0, 47, "*>");	
  fun_a_common();
}

void fun_c1o() {
  u8g2.drawStr(0, 15, "*>");	
  fun_a_common();
}

key_table table[30]=
{
	{0 ,0 ,0,1, (*fun_0)},  //主界面,短按确定进入下一级,   按上下调节温度, 长按确定开启/关闭。

	{1 ,4 ,2, 5 ,(*fun_a)}, //选择 温度设置
	{2 ,1 ,3, 9 ,(*fun_b)}, //选择 遥控设置
	{3 ,2 ,4, 13,(*fun_c)}, //选择 亮度设置
	{4 ,3 ,1, 0 ,(*fun_d)}, //选择 返回上级

	{5 ,8, 6, 15,(*fun_a1)}, //选择 温度设置->目标温度
	{6 ,5, 7, 16,(*fun_a2)}, //选择 温度设置->温度回差
	{7 ,6, 8, 17,(*fun_a3)}, //选择 温度设置->温度偏移
	{8 ,7, 5, 1 ,(*fun_a4)}, //选择 温度设置->返回上级

	{9 ,12,10, 18,(*fun_b1)}, //选择 遥控设置->学习开启
	{10,9 ,11, 19,(*fun_b2)}, //选择 遥控设置->学习关闭
	{11,10,12, 20,(*fun_b3)}, //选择 遥控设置->测试遥控
	{12,11,9 , 2 ,(*fun_b4)}, //选择 遥控设置->返回上级

	{13,14,14, 21,(*fun_c1)}, //选择 亮度设置->亮度调节
	{14,13,13, 3 ,(*fun_c2)}, //选择 亮度设置->返回上级

	{15,15,15, 5 ,(*fun_a1o)}, //设置 温度设置->目标温度
	{16,16,16, 6 ,(*fun_a2o)}, //设置 温度设置->温度回差
	{17,17,17, 7 ,(*fun_a3o)}, //设置 温度设置->温度偏移
	{18,18,18, 9 ,(*fun_b1)}, //设置 遥控设置->学习开启
	{19,19,19, 10,(*fun_b2)}, //设置 遥控设置->学习关闭
	{20,20,20, 11,(*fun_b3)}, //设置 遥控设置->测试遥控
	{21,21,21, 13,(*fun_c1o)}, //设置 亮度设置->亮度调节
};

void oled_update() {
  current_operation_index = table[func_index].current_operation;
  //u8g2.clearBuffer();
  u8g2.firstPage();
  do {
    (*current_operation_index)();//执行当前操作函数
  } while ( u8g2.nextPage() );
  //u8g2.sendBuffer();
}

void btnUpClick() {
  if (func_index == 0 || func_index == 15) {
    tarTemp += 0.1;
  } else if (func_index == 16) {
    rangeTemp += 0.1;
  } else if (func_index == 17) {
    offsetTemp += 0.1;
  } else if (func_index == 21) {
    if (brightness<100) brightness++;
  }
  func_index = table[func_index].up;    //向上翻
  last_oled_update -= OLED_UPDATE_INTERVAL;
}

void btnDownClick() {
  if (func_index == 0 || func_index == 15) {
    tarTemp -= 0.1;
  } else if (func_index == 16) {
    rangeTemp -= 0.1;
  } else if (func_index == 17) {
    offsetTemp -= 0.1;
  } else if (func_index == 21) {
    if (brightness > 10) brightness--;
  }
  func_index = table[func_index].down;  //向下翻
  last_oled_update -= OLED_UPDATE_INTERVAL;
}

void btnOkClick() {
  func_index = table[func_index].enter; //确认
  last_oled_update -= OLED_UPDATE_INTERVAL;
}


void setup(void)
{
  Serial.begin(115200);
  u8g2.begin();
  u8g2.enableUTF8Print();	
  //u8g2.setFont(u8g2_font_unifont_t_chinese2);
  u8g2.setFont(u8g2_font_diy_t_myfont);
  //u8g2.setFontMode(1);
  btnUp.attachClick(btnUpClick);
  btnDown.attachClick(btnDownClick);
  btnOk.attachClick(btnOkClick);

  btnUp.setClickTicks(100);
  btnDown.setClickTicks(100);
  btnOk.setClickTicks(100);
}


void loop(void)
{
  unsigned long cur_ms = millis();
  btnUp.tick();
  btnDown.tick();
  btnOk.tick();

  static unsigned long update_cnt = 0; 
  if ( cur_ms - last_oled_update >= OLED_UPDATE_INTERVAL) {
    oled_update();
    update_cnt++;
    last_oled_update = cur_ms;
  }

  if ( update_cnt >= 2 ) {
    outState = !outState;
    curTemp+=0.5;

    if (curTemp > 200)
      curTemp = -38.8;
    update_cnt = 0;
  }

  if (curTemp >= tarTemp) {
    if (outState != false ) {
      outState = false;
    }
  } else if (curTemp < tarTemp - rangeTemp) {
    if (outState != true ) {
      outState = true;
    }
  }

}