#include <U8g2lib.h>
#include <Wire.h>
#include <Arduino.h>
#include "Freenove_WS2812_Lib_for_ESP32.h"
#include <INA226.h>
#define EEPROM_SIZE 128
/************************************* INA 电流电压功率 ******************************/
INA226 INA(0x45); // A0=GND,A1=GND 对应地址0x40
struct
{
float current;
float voltage;
float power;
float current_coeffA;
float current_coeffB;
float voltage_coeffA;
float voltage_coeffB;
} ina;
void ina226_init()
{
Wire.begin();
if (!INA.begin() )
{
Serial.println("could not connect. Fix and Reboot");
}
else
{
INA.setAverage(10);
delay(100);
INA.setMaxCurrentShunt(0.7, 0.1);
}
ina.current_coeffA=2;
ina.current_coeffB=0;
ina.voltage_coeffA=1;
ina.voltage_coeffB=0;
}
void ina226_read()
{
ina.voltage = INA.getBusVoltage()*ina.voltage_coeffA+ina.voltage_coeffB;
//ina.voltage = INA.getBusVoltage();
ina.current = INA.getCurrent_mA()/1000.0*ina.current_coeffA+ina.current_coeffB;
if (ina.current<0)
{
ina.current=0.00;
}
//ina.power = INA.getPower();
ina.power=ina.current*ina.voltage;
}
/************************************* 屏幕驱动 *************************************/
// #define SCL 22
// #define SDA 21
// #define RST U8X8_PIN_NONE
// 分辨率:128*64 驱动:SSD1306 接口:IIC(硬件)
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0,SCL,SDA,U8X8_PIN_NONE);
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
/************************************* 函数声明 *************************************/
void print_time(uint8_t hour,uint8_t minute,uint8_t second);
void ui_proc();
/************************************* LED Halo *************************************/
#define LEDS_COUNT 16
#define LEDS_PIN 27
#define LED_BAR_PIN 15
#define CHANNEL 0
#define LED_SHOW_DELAY 10
#define WAVE_COUNT 300
#define LED_BAR_INTERVAL 1000
#define CHG_R_PIN 25
#define CHG_G_PIN 26
Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(LEDS_COUNT, LEDS_PIN, CHANNEL, TYPE_GRB);
Freenove_ESP32_WS2812 ledBar = Freenove_ESP32_WS2812(1, LED_BAR_PIN, CHANNEL, TYPE_GRB);
struct
{
bool loop_flag;
uint32_t loop_count;
uint32_t set_count;
uint16_t loop_interval;
uint8_t color[LEDS_COUNT][3];
uint8_t index;
bool need_update;
bool breath_flag;
uint8_t breath_min;
uint8_t breath_max;
uint32_t breath_count;
uint16_t breath_interval;
uint8_t bar_r;
uint8_t bar_g;
uint8_t bar_b;
bool bar_flicker;
bool bar_update_flag;
bool bar_flicker_inverse;
long bar_flicker_count;
} volatile led;
// Length 300, max 255
PROGMEM const uint8_t index_wave255[WAVE_COUNT] =
{
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4,
4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12,
13, 13, 14, 14, 15, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23, 24, 25, 25, 26, 27, 28, 30, 31, 32, 33,
34, 36, 37, 38, 40, 41, 43, 45, 46, 48, 50, 52, 54, 56, 58, 60, 62, 65, 67, 70, 72, 75, 78, 81, 84, 87, 90,
94, 97, 101, 105, 109, 113, 117, 122, 126, 131, 136, 141, 146, 152, 158, 164, 170, 176, 183, 190, 197, 205,
213, 221, 229, 238, 247, 255, 255, 247, 238, 229, 221, 213, 205, 197, 190, 183, 176, 170, 164, 158, 152, 146,
141, 136, 131, 126, 122, 117, 113, 109, 105, 101, 97, 94, 90, 87, 84, 81, 78, 75, 72, 70, 67, 65, 62, 60, 58,
56, 54, 52, 50, 48, 46, 45, 43, 41, 40, 38, 37, 36, 34, 33, 32, 31, 30, 28, 27, 26, 25, 25, 24, 23, 22, 21, 20,
20, 19, 18, 18, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7,
6,6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
uint8_t brightness_sub=1;
uint8_t brightness_current=0;
uint8_t m_nCenterIndex=0;
uint16_t m_ledColorV[LEDS_COUNT];
uint16_t m_ledColorH[LEDS_COUNT];
uint16_t m_nDescH=30;
uint16_t m_nTargH = 100;
uint16_t m_nBreathCount = 0;
void ws2812_param_init()
{
led.need_update=false;
led.breath_count=0;
led.breath_interval=10;
led.loop_interval=500;
led.breath_max=240;
led.breath_min=1;
for (uint8_t i = 0; i < LEDS_COUNT; i++)
{
led.color[i][0]=255;
led.color[i][1]=0;
led.color[i][2]=0;
m_ledColorV[i]=100;
m_ledColorH[i]=50;
}
}
uint16_t index_wave=0;
void ws2812_pro()
{
if (!led.loop_flag && millis()-led.loop_count>led.loop_interval)
{
led.loop_count = millis();
led.loop_flag = true;
}
if (led.loop_flag && !led.breath_flag)
{
for (uint8_t i = 0; i < LEDS_COUNT; i++)
{
strip.setLedColorData(i, led.color[i][0], led.color[i][1], led.color[i][2]);
}
strip.show();
led.loop_flag=false;
}
if (millis()-led.breath_count>led.breath_interval && led.breath_flag)
{
led.breath_count=millis();
index_wave = index_wave%WAVE_COUNT;
for (uint8_t i = 0; i < LEDS_COUNT; i++)
{
// strip.setLedColorData(i, led.color[i][0], led.color[i][1], led.color[i][2]);
uint32_t red_value = led.color[i][0] * index_wave255[index_wave] / 255;
uint32_t green_value = led.color[i][1] * index_wave255[index_wave] / 255;
uint32_t blue_value = led.color[i][2] * index_wave255[index_wave] / 255;
strip.setLedColorData(i, red_value, green_value, blue_value);
}
index_wave++;
strip.show();
}
}
void set_led_color(uint8_t r,uint8_t g, uint8_t b)
{
for (uint8_t i = 0; i < LEDS_COUNT; i++)
{
led.color[i][0]=r;
led.color[i][1]=g;
led.color[i][2]=b;
}
led.need_update=true;
}
void update_led_color_index(uint8_t index)
{
led.breath_flag=false;
switch (index)
{
case 0: set_led_color(255,0,0); break;
case 1: set_led_color(0,255,0); break;
case 2: set_led_color(0,0,255); break;
case 3: set_led_color(255,255,255); break;
case 4: set_led_color(0,0,0); break;
case 5: set_led_color(0,255,0); led.breath_flag=true;break;
case 6: set_led_color(0,0,255); led.breath_flag=true;break;
default: break;
}
}
void show_led_bar_color()
{
ledBar.setLedColorData(0, led.bar_r, led.bar_g, led.bar_b);
ledBar.show();
}
void update_led_bar_color(uint8_t r,uint8_t g,uint8_t b,bool flicker)
{
led.bar_r=r;
led.bar_g=g;
led.bar_b=b;
led.bar_flicker=flicker;
led.bar_update_flag=true;
}
void led_bar_pro()
{
if(led.bar_update_flag)
{
led.bar_update_flag=false;
show_led_bar_color();
}
if(led.bar_flicker)
{
if(millis()-led.bar_flicker_count>LED_BAR_INTERVAL)
{
led.bar_flicker_count=millis();
led.bar_flicker_inverse=!led.bar_flicker_inverse;
if(led.bar_flicker_inverse)
{
ledBar.setLedColorData(0, 0, 0, 0);
}
else
{
show_led_bar_color();
}
ledBar.show();
}
}
}
void charge_red_inter()
{
update_led_bar_color(255,0,0,false);
show_led_bar_color();
Serial.println("Charge Power Off");
}
void charge_green_inter()
{
update_led_bar_color(0,255,0,false);
show_led_bar_color();
Serial.println("Charge Power On");
}
/************************************* 定义页面 *************************************/
//总目录,缩进表示页面层级
enum
{
M_WINDOW,
M_SLEEP,
M_MAIN,
M_HALO,
M_PERIOD,
M_STT,
M_ENT,
M_TIME,
M_CHARGE,
M_SETTING,
M_SYSTEM,
M_WIFI,
M_WIFI_USR,
M_WIFI_PSW,
M_ABOUT,
};
//状态,初始化标签
enum
{
S_FADE, //转场动画
S_WINDOW, //弹窗初始化
S_LAYER_IN, //层级初始化
S_LAYER_OUT, //层级初始化
S_NONE, //直接选择页面
};
//菜单结构体
typedef struct MENU
{
const char *m_select;
} M_SELECT;
/************************************* 定义内容 *************************************/
/************************************* 文字内容 *************************************/
M_SELECT main_menu[]
{
{"< Sleep >"},
{"< Halo >"},
{"< Time >"},
{"< Charge >"},
{"< Setting >"},
};
M_SELECT halo_menu[]
{
{"[ Halo ]"},
{"- Brightness"},
{"--------------------------"},
{"= Function 1"},
{"= Function 2"},
{"= Function 3"},
{"= Function 4"},
{"= Function 5"},
{"= Function 6"},
{"= Function 7"},
{"--------------------------"},
{"- [ Period ]"},
};
M_SELECT period_menu[]
{
{"[ Period ]"},
{"- Specific time"},
{"> Start"},
{"< End"},
};
M_SELECT stt_menu[]
{
{"[ Start Time ]"},
{"~ Hour"},
{"~ Minute"},
{"~ Second"},
};
M_SELECT ent_menu[]
{
{"[ End Time ]"},
{"~ Hour"},
{"~ Minute"},
{"~ Second"},
};
M_SELECT time_menu[]
{
{"time"},
};
M_SELECT charge_menu[]
{
{"A"},
{"V"},
{"I"},
{"P"},
};
M_SELECT setting_menu[]
{
{"[ Setting ]"},
{"- System"},
{"- Wifi"},
{"- About"},
};
M_SELECT system_menu[]
{
{"[ System ]"},
{"~ Disp Bri"},
{"~ Tile Ani"},
{"~ List Ani"},
{"~ Win Ani"},
{"~ Spot Ani"},
{"~ Tag Ani"},
{"~ Fade Ani"},
{"~ Auto Time"},
{"~ Btn LPT"},
{"+ T Ufd Fm Scr"},
{"+ L Ufd Fm Scr"},
{"+ T Loop Mode"},
{"+ L Loop Mode"},
{"+ Win Bokeh Bg"},
{"+ Knob Rot Dir"},
{"+ Dark Mode"},
};
M_SELECT wifi_menu[]
{
{"[ WIFI ]"},
{"- User"},
{"- Password"},
};
M_SELECT about_menu[]
{
{"[ About ]"},
{"- Version: v1.0"},
{"- Board: ESP32"},
{"- Ram: 4M"},
{"- Flash: 64k"},
{"- Freq: 72Mhz"},
{"- Creator: RS"},
};
/************************************* 图片内容 *************************************/
PROGMEM const uint8_t main_icon_pic_40x40[][200]
{
{
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0x7f,0xfc,0xff,0xff,0xff,0x1f,0xfc,0xff,0xff,0xff,0x07,0xfe,0x00,0xfe,0xff,0x03,0xfe,0x00,0xfc,
0xff,0x01,0xff,0x3f,0xfe,0xff,0x00,0xff,0x1f,0xff,0x7f,0x00,0xff,0x87,0xff,0x3f,0x80,0xff,0xe3,0xff,
0x3f,0x80,0xff,0xf1,0xff,0x1f,0x80,0xff,0xf8,0xff,0x1f,0x80,0x7f,0x00,0xfe,0x1f,0x80,0xff,0x00,0xfe,
0x0f,0x00,0xff,0xff,0xff,0x0f,0x00,0xff,0xff,0xff,0x0f,0x00,0xfe,0xff,0xff,0x0f,0x00,0xfe,0xff,0xff,
0x0f,0x00,0xfc,0xff,0xff,0x0f,0x00,0xf8,0xff,0xff,0x0f,0x00,0xf0,0xff,0xf1,0x1f,0x00,0xc0,0xff,0xf0,
0x1f,0x00,0x00,0x04,0xf8,0x1f,0x00,0x00,0x00,0xf8,0x3f,0x00,0x00,0x00,0xf8,0x3f,0x00,0x00,0x00,0xfc,
0x7f,0x00,0x00,0x00,0xfe,0x7f,0x00,0x00,0x00,0xfe,0xff,0x00,0x00,0x00,0xff,0xff,0x01,0x00,0x80,0xff,
0xff,0x07,0x00,0xc0,0xff,0xff,0x0f,0x00,0xf0,0xff,0xff,0x3f,0x00,0xfc,0xff,0xff,0xff,0x81,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
},
{
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3c,0xfc,0xff,0xff,0x1f,0x3c,0xf8,0xff,
0xff,0x07,0x3c,0xe0,0xff,0xff,0x03,0x3c,0xc0,0xff,0xff,0x01,0x3c,0x80,0xff,0xff,0x00,0xff,0x00,0xff,
0xff,0x80,0xff,0x01,0xff,0x7f,0xc0,0xff,0x03,0xfe,0xff,0xe1,0xff,0x87,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfc,0xff,0x7f,0xf8,0x1f,0xf8,0xff,0x1f,0xf8,
0x1f,0xf8,0xff,0x1f,0xf8,0x3f,0xf8,0xff,0x1f,0xf8,0x3f,0xf8,0xff,0x1f,0xfc,0x3f,0xf0,0xff,0x1f,0xfc,
0x3f,0xf0,0xff,0x0f,0xfc,0x7f,0xe0,0xff,0x07,0xfe,0x7f,0xe0,0xff,0x07,0xfe,0xff,0xf0,0xff,0x0f,0xff,
0xff,0xf0,0x7e,0x1f,0xff,0xff,0x79,0x00,0x9e,0xff,0xff,0x7f,0x00,0xfe,0xff,0xff,0x3f,0x00,0xfc,0xff,
0xff,0x1f,0x00,0xf8,0xff,0xff,0x7f,0x00,0xfe,0xff,0xff,0xff,0xe7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
},
{
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xfc,
0x1f,0x00,0x00,0x00,0xf8,0x1f,0xff,0xff,0xff,0xf8,0x8f,0xff,0xff,0xff,0xf1,0x8f,0xff,0xff,0xff,0xf1,
0x8f,0xff,0xf7,0xff,0xf1,0x8f,0xff,0xf3,0xff,0xf1,0x8f,0xff,0xf3,0xff,0xf1,0x8f,0xff,0xf3,0xff,0xf1,
0x8f,0xff,0xf3,0xff,0xf1,0x8f,0xff,0xf3,0xff,0xf1,0x8f,0xff,0xf3,0xff,0xf1,0x8f,0xff,0xf3,0xff,0xf1,
0x8f,0xff,0x83,0xff,0xf1,0x8f,0xff,0x03,0xfc,0xf1,0x8f,0xff,0x1f,0xfc,0xf1,0x8f,0xff,0xff,0xff,0xf1,
0x8f,0xff,0xff,0xff,0xf1,0x8f,0xff,0xff,0xff,0xf1,0x8f,0xff,0xff,0xff,0xf1,0x8f,0xff,0xff,0xff,0xf1,
0x8f,0xff,0xff,0xff,0xf1,0x8f,0xff,0xff,0xff,0xf1,0x1f,0xff,0xff,0xff,0xf8,0x1f,0x00,0x00,0x00,0xf8,
0x3f,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
},
{
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xf3,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xf8,0xff,
0xff,0xff,0x7f,0xf8,0xff,0xff,0xff,0x3f,0xfc,0xff,0xff,0xff,0x1f,0xfe,0xff,0xff,0xff,0x0f,0xfe,0xff,
0xff,0xff,0x07,0xff,0xff,0xff,0xff,0x83,0xff,0xff,0xff,0xff,0x81,0xff,0xff,0xff,0xff,0xc0,0xff,0xff,
0xff,0x7f,0xe0,0xff,0xff,0xff,0x3f,0x00,0x00,0xff,0xff,0x1f,0x00,0x00,0xff,0xff,0x0f,0x00,0x80,0xff,
0xff,0x0f,0x00,0xc0,0xff,0xff,0xff,0x1f,0xe0,0xff,0xff,0xff,0x0f,0xf0,0xff,0xff,0xff,0x0f,0xf8,0xff,
0xff,0xff,0x07,0xfc,0xff,0xff,0xff,0x07,0xfe,0xff,0xff,0xff,0x03,0xff,0xff,0xff,0xff,0x81,0xff,0xff,
0xff,0xff,0xc1,0xff,0xff,0xff,0xff,0xe0,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0x7f,0xf8,0xff,0xff,
0xff,0x3f,0xfc,0xff,0xff,0xff,0x3f,0xfe,0xff,0xff,0xff,0x1f,0xff,0xff,0xff,0xff,0x8f,0xff,0xff,0xff,
0xff,0xc7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
},
{
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x81,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x3f,0x18,0xfc,0xff,
0xff,0x0f,0x3c,0xf0,0xff,0xff,0x03,0xff,0xc0,0xff,0xff,0xc1,0xff,0x83,0xff,0x7f,0xe0,0xff,0x07,0xfe,
0x3f,0xf8,0xff,0x1f,0xfc,0x3f,0xfe,0xff,0x7f,0xfc,0x3f,0xfe,0xe7,0x7f,0xfc,0x3f,0xfe,0x81,0x7f,0xfc,
0x3f,0xfe,0x00,0x7f,0xfc,0x3f,0x7e,0x18,0x7e,0xfc,0x3f,0x7e,0x3c,0x7e,0xfc,0x3f,0x3e,0x7e,0x7c,0xfc,
0x3f,0x3e,0x7e,0x7c,0xfc,0x3f,0x7e,0x3c,0x7e,0xfc,0x3f,0x7e,0x18,0x7e,0xfc,0x3f,0xfe,0x00,0x7f,0xfc,
0x3f,0xfe,0x81,0x7f,0xfc,0x3f,0xfe,0xe7,0x7f,0xfc,0x3f,0xfe,0xff,0x7f,0xfc,0x3f,0xf8,0xff,0x1f,0xfc,
0x7f,0xe0,0xff,0x07,0xfe,0xff,0xc1,0xff,0x83,0xff,0xff,0x03,0xff,0xc0,0xff,0xff,0x0f,0x3c,0xf0,0xff,
0xff,0x3f,0x18,0xfc,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x81,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
},
};
PROGMEM const uint8_t main_icon_pic_30x30[][120]
{
{
0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xe7,0xff,0x3f,0xff,0xe1,0x03,0x3f,
0xff,0xe0,0x03,0x3e,0x3f,0xf0,0x3f,0x3e,0x3f,0xf0,0x9f,0x3f,0x1f,0xf0,0xcf,0x3f,0x0f,0xf8,0xe7,0x3f,
0x0f,0xf8,0x03,0x3f,0x0f,0xf0,0x03,0x3e,0x07,0xf0,0xff,0x3f,0x07,0xf0,0xff,0x3f,0x07,0xe0,0xff,0x3f,
0x07,0xc0,0xff,0x3f,0x07,0x80,0xff,0x3f,0x07,0x00,0xff,0x38,0x0f,0x00,0x00,0x3c,0x0f,0x00,0x00,0x3c,
0x1f,0x00,0x00,0x3c,0x1f,0x00,0x00,0x3e,0x3f,0x00,0x00,0x3f,0x7f,0x00,0x80,0x3f,0xff,0x00,0xc0,0x3f,
0xff,0x03,0xe0,0x3f,0xff,0x1f,0xfc,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f
},
{
0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xcf,0xfc,0x3f,
0xff,0xc3,0xf0,0x3f,0xff,0xc0,0xc0,0x3f,0x7f,0xc0,0x80,0x3f,0x3f,0xe0,0x01,0x3f,0x3f,0xf8,0x07,0x3f,
0x3f,0xfc,0x0f,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xcf,0xff,0xff,0x3c,0x0f,0xff,0x3f,0x3c,
0x0f,0xff,0x3f,0x3c,0x0f,0xff,0x3f,0x3c,0x1f,0xfe,0x1f,0x3c,0x1f,0xfe,0x1f,0x3e,0x1f,0xfc,0x0f,0x3e,
0x3f,0xfe,0x1f,0x3f,0x3f,0xee,0x3d,0x3f,0x7f,0x07,0xb8,0x3f,0xff,0x07,0xf8,0x3f,0xff,0x03,0xf0,0x3f,
0xff,0x1f,0xfe,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f
},
{
0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,
0x1f,0x00,0x00,0x3e,0x0f,0x00,0x00,0x3c,0xe7,0xff,0xff,0x39,0xe7,0xff,0xff,0x39,0xe7,0xbf,0xff,0x39,
0xe7,0xbf,0xff,0x39,0xe7,0xbf,0xff,0x39,0xe7,0xbf,0xff,0x39,0xe7,0xbf,0xff,0x39,0xe7,0xbf,0xff,0x39,
0xe7,0x3f,0xfc,0x39,0xe7,0x3f,0xf0,0x39,0xe7,0xff,0xfb,0x39,0xe7,0xff,0xff,0x39,0xe7,0xff,0xff,0x39,
0xe7,0xff,0xff,0x39,0xe7,0xff,0xff,0x39,0xe7,0xff,0xff,0x39,0x0f,0x00,0x00,0x3c,0x1f,0x00,0x00,0x3e,
0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f
},
{
0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xef,0x3f,0xff,0xff,0xe7,0x3f,
0xff,0xff,0xf3,0x3f,0xff,0xff,0xf1,0x3f,0xff,0xff,0xf8,0x3f,0xff,0x7f,0xf8,0x3f,0xff,0x3f,0xfc,0x3f,
0xff,0x1f,0xfe,0x3f,0xff,0x0f,0xfe,0x3f,0xff,0x07,0xff,0x3f,0xff,0x03,0x00,0x3f,0xff,0x01,0x80,0x3f,
0xff,0x01,0xc0,0x3f,0xff,0xff,0xe0,0x3f,0xff,0x7f,0xf0,0x3f,0xff,0x3f,0xf8,0x3f,0xff,0x3f,0xfc,0x3f,
0xff,0x1f,0xfe,0x3f,0xff,0x0f,0xff,0x3f,0xff,0x8f,0xff,0x3f,0xff,0xc7,0xff,0x3f,0xff,0xe3,0xff,0x3f,
0xff,0xf3,0xff,0x3f,0xff,0xf9,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f
},
{
0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0x3f,0xff,0x3f,0xff,0x0f,0xfc,0x3f,
0xff,0x07,0xf8,0x3f,0xff,0xe1,0xe1,0x3f,0x7f,0xf8,0x87,0x3f,0x1f,0xfc,0x0f,0x3e,0x1f,0xff,0x3f,0x3e,
0x9f,0xff,0x7f,0x3e,0x9f,0x1f,0x7e,0x3e,0x9f,0x0f,0x7c,0x3e,0x9f,0xe7,0x79,0x3e,0x9f,0xe7,0x79,0x3e,
0x9f,0xe7,0x79,0x3e,0x9f,0xe7,0x79,0x3e,0x9f,0x0f,0x7c,0x3e,0x9f,0x1f,0x7e,0x3e,0x9f,0xff,0x7f,0x3e,
0x1f,0xff,0x3f,0x3e,0x1f,0xfc,0x0f,0x3e,0x7f,0xf8,0x87,0x3f,0xff,0xe1,0xe1,0x3f,0xff,0x07,0xf8,0x3f,
0xff,0x0f,0xfc,0x3f,0xff,0x3f,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f
},
};
PROGMEM const uint8_t show_icon_pic[][20]
{
// Wifi
{
0x60,0x00,0x98,0x01,0x04,0x02,0x62,0x04,0x98,0x01,
0x04,0x02,0x60,0x00,0x90,0x00,0x00,0x00,0x60,0x00
},
// Bluetooth
{
0x30,0x00,0x50,0x00,0x94,0x00,0x58,0x00,0x30,0x00,
0x30,0x00,0x58,0x00,0x94,0x00,0x50,0x00,0x30,0x00
},
};
/************************************* 页面变量 *************************************/
//OLED变量
#define DISP_H 64 //屏幕高度
#define DISP_W 128 //屏幕宽度
uint8_t *buf_ptr; //指向屏幕缓冲的指针
uint16_t buf_len; //缓冲长度
//UI变量
#define UI_DEPTH 20 //最深层级数
#define UI_MNUMB 100 //菜单数量
#define UI_PARAM 16 //参数数量
#define BTN_SP_TIME 25
enum
{
DISP_BRI, //屏幕亮度
TILE_ANI, //磁贴动画速度
LIST_ANI, //列表动画速度
WIN_ANI, //弹窗动画速度
SPOT_ANI, //聚光动画速度
TAG_ANI, //标签动画速度
FADE_ANI, //消失动画速度
AUT_TM, //自动屏保时长
BTN_LPT, //按键长按时长
TILE_UFD, //磁贴图标从头展开开关
LIST_UFD, //菜单列表从头展开开关
TILE_LOOP, //磁贴图标循环模式开关
LIST_LOOP, //菜单列表循环模式开关
WIN_BOK, //弹窗背景虚化开关
KNOB_DIR, //旋钮方向切换开关
DARK_MODE, //黑暗模式开关
};
struct
{
bool init;
uint8_t num[UI_MNUMB];
uint8_t select[UI_DEPTH];
uint8_t layer = 1;
uint8_t index = M_TIME;
uint8_t state = S_NONE;
bool sleep = false;
uint8_t fade = 1;
uint8_t param[UI_PARAM];
} ui;
void start_sleep()
{
ui.index=M_SLEEP;
ui.state=S_NONE;
ui.layer=0;
ui.sleep=true;
}
void start_time()
{
ui.init=false;
ui.index=M_TIME;
ui.state=S_NONE;
ui.layer=1;
ui.sleep=true;
}
#define TIME_B_FONT u8g2_font_timB24_tf
//磁贴变量
//所有磁贴页面都使用同一套参数
#define TILE_B_FONT u8g2_font_ncenB14_tr //u8g2_font_ncenB12_tr //u8g2_font_helvB18_tr //磁贴大标题字体
#define TILE_B_TITLE_H 14 //磁贴大标题字体高度
#define TILE_ICON_H 30 //磁贴图标高度
#define TILE_ICON_W 30 //磁贴图标宽度
#define TILE_ICON_S 42 //磁贴图标间距
#define TILE_INDI_H 27 //磁贴大标题指示器高度
#define TILE_INDI_W 7 //磁贴大标题指示器宽度
#define TILE_INDI_S 39 //磁贴大标题指示器上边距
struct
{
float title_y_calc = TILE_INDI_S + (TILE_INDI_H - TILE_B_TITLE_H) / 2 + TILE_B_TITLE_H * 2;
float title_y_trg_calc = TILE_INDI_S + (TILE_INDI_H - TILE_B_TITLE_H) / 2 + TILE_B_TITLE_H;
int16_t temp;
bool select_flag;
float icon_x;
float icon_x_trg;
float icon_y;
float icon_y_trg;
float indi_x;
float indi_x_trg;
float title_y;
float title_y_trg;
} tile;
//列表变量
//默认参数
#define LIST_FONT u8g2_font_HelvetiPixel_tr //列表字体
#define LIST_TEXT_H 8 //列表每行文字字体的高度
#define LIST_LINE_H 16 //列表单行高度
#define LIST_TEXT_S 4 //列表每行文字的上边距,左边距和右边距,下边距由它和字体高度和行高度决定
#define LIST_BAR_W 5 //列表进度条宽度,需要是奇数,因为正中间有1像素宽度的线
#define LIST_BOX_R 0.5f //列表选择框圆角
/*
//超窄行高度测试
#define LIST_FONT u8g2_font_4x6_tr //列表字体
#define LIST_TEXT_H 5 //列表每行文字字体的高度
#define LIST_LINE_H 7 //列表单行高度
#define LIST_TEXT_S 1 //列表每行文字的上边距,左边距和右边距,下边距由它和字体高度和行高度决定
#define LIST_BAR_W 7 //列表进度条宽度,需要是奇数,因为正中间有1像素宽度的线
#define LIST_BOX_R 0.5f //列表选择框圆角
*/
struct
{
uint8_t line_n = DISP_H / LIST_LINE_H;
int16_t temp;
bool loop;
float y;
float y_trg;
float box_x;
float box_x_trg;
float box_y;
float box_y_trg[UI_DEPTH];
float bar_y;
float bar_y_trg;
} list;
//电压测量页面变量
//开发板模拟引脚
// uint8_t analog_pin[10] = { };
//曲线相关
#define WAVE_SAMPLE 23 //采集倍数
#define WAVE_W 94 //波形宽度
#define WAVE_L 24 //波形左边距
#define WAVE_U 0 //波形上边距
#define WAVE_MAX 27 //最大值
#define WAVE_MIN 4 //最小值
#define WAVE_BOX_H 32 //波形边框高度
#define WAVE_BOX_W 94 //波形边框宽度
#define WAVE_BOX_L_S 24 //波形边框左边距
//列表和文字背景框相关
#define VOLT_FONT u8g2_font_helvB18_tr //电压数字字体
#define VOLT_FONT_S u8g2_font_ncenB14_tr //电压数字字体
#define VOLT_TEXT_BG_L_S 24 //文字背景框左边距
#define VOLT_TEXT_BG_W 94 //文字背景框宽度
#define VOLT_TEXT_BG_H 29 //文字背景框高度
struct
{
int ch0_adc[WAVE_SAMPLE * WAVE_W];
int ch0_wave[WAVE_W];
float val_v[WAVE_SAMPLE];
float val_i[WAVE_SAMPLE];
float val_w[WAVE_SAMPLE];
float val_v_min;
float val_v_max;
float val_i_min;
float val_i_max;
float val_w_min;
float val_w_max;
int val_min;
int val_max;
float val;
float val1;
float val2;
float val3;
float text_bg_r;
float text_bg_r_trg;
long refresh_count;
} volt;
//选择框变量
//默认参数
#define CHECK_BOX_L_S 95 //选择框在每行的左边距
#define CHECK_BOX_L_S_T 75 //选择框在每行的左边距-时间字符
#define CHECK_BOX_U_S 2 //选择框在每行的上边距
#define CHECK_BOX_F_W 12 //选择框外框宽度
#define CHECK_BOX_F_H 12 //选择框外框高度
#define CHECK_BOX_D_S 2 //选择框里面的点距离外框的边距
struct
{
uint8_t *v;
uint8_t *m;
uint8_t *s;
uint8_t *s_p;
} check_box;
//弹窗变量
#define WIN_FONT u8g2_font_HelvetiPixel_tr //弹窗字体
#define WIN_H 32 //弹窗高度
#define WIN_W 102 //弹窗宽度
#define WIN_BAR_W 92 //弹窗进度条宽度
#define WIN_BAR_H 7 //弹窗进度条高度
#define WIN_Y - WIN_H - 2 //弹窗竖直方向出场起始位置
#define WIN_Y_TRG - WIN_H - 2 //弹窗竖直方向退场终止位置
struct
{
//uint8_t
uint8_t *value;
uint8_t max;
uint8_t min;
uint8_t step;
MENU *bg;
uint8_t index;
char title[20];
uint8_t select;
uint8_t l = (DISP_W - WIN_W) / 2;
uint8_t u = (DISP_H - WIN_H) / 2;
float bar;
float bar_trg;
float y;
float y_trg;
} win;
//聚光灯变量
struct
{
float l;
float l_trg;
float r;
float r_trg;
float u;
float u_trg;
float d;
float d_trg;
} spot;
/********************************** 自定义功能变量 **********************************/
//Halo功能变量
#define PERIOD_PARAM 6
#define FUNCS_PARAM 2
enum
{
START_HOUR, //开始时
START_MINUTE, //开始分
START_SECOND, //开始秒
END_HOUR, //结束时
END_MINUTE, //结束分
END_SECOND, //结束秒
};
struct
{
uint8_t param[PERIOD_PARAM] = { 0, 0, 0, 23,59,59 }; //开始:时,分,秒;结束:时,分,秒
} period;
struct
{
uint8_t param[FUNCS_PARAM] = {3,3}; // 功能开始index为3对应 function1
} funcs;
/************************************* 断电保存 *************************************/
#include <EEPROM.h>
//EEPROM变量
#define EEPROM_CHECK 11
struct
{
bool init;
bool change;
int address;
uint8_t check;
uint8_t check_param[EEPROM_CHECK] = { 'a', 'b', 'c', 'd', 'e', 'f','g', 'h', 'i', 'j', 'k' };
} eeprom;
//EEPROM写数据,回到睡眠时执行一遍
void eeprom_write_all_data()
{
Serial.println("eeprom write all data.");
eeprom.address = 0;
for (uint8_t i = 0; i < EEPROM_CHECK; ++i)
{
EEPROM.write(eeprom.address + i, eeprom.check_param[i]);
EEPROM.commit();
delay(10);
}
eeprom.address += EEPROM_CHECK;
for (uint8_t i = 0; i < UI_PARAM; ++i)
{
EEPROM.write(eeprom.address + i, ui.param[i]);
EEPROM.commit();
delay(10);
}
eeprom.address += UI_PARAM;
for (uint8_t i = 0; i < PERIOD_PARAM; ++i)
{
EEPROM.write(eeprom.address + i, period.param[i]);
EEPROM.commit();
delay(10);
}
eeprom.address += PERIOD_PARAM;
for (uint8_t i = 0; i < FUNCS_PARAM; ++i)
{
EEPROM.write(eeprom.address + i, funcs.param[i]);
EEPROM.commit();
delay(10);
}
eeprom.address += FUNCS_PARAM;
}
//EEPROM读数据,开机初始化时执行一遍
void eeprom_read_all_data()
{
eeprom.address = EEPROM_CHECK;
for (uint8_t i = 0; i < UI_PARAM; ++i) ui.param[i] = EEPROM.read(eeprom.address + i); eeprom.address += UI_PARAM;
for (uint8_t i = 0; i < PERIOD_PARAM; ++i) period.param[i] = EEPROM.read(eeprom.address + i); eeprom.address += PERIOD_PARAM;
for (uint8_t i = 0; i < FUNCS_PARAM; ++i) funcs.param[i] = EEPROM.read(eeprom.address + i); eeprom.address += FUNCS_PARAM;
}
void ui_param_init();
//开机检查是否已经修改过,没修改过则跳过读配置步骤,用默认设置
void eeprom_init()
{
EEPROM.begin(EEPROM_SIZE);
eeprom.check = 0;
eeprom.address = 0; for (uint8_t i = 0; i < EEPROM_CHECK; ++i) if (EEPROM.read(eeprom.address + i) != eeprom.check_param[i]) eeprom.check ++;
Serial.print("eeprom check:");
Serial.println(eeprom.check);
//eeprom_read_all_data();
if (eeprom.check <= 1) eeprom_read_all_data(); //允许一位误码
else ui_param_init();
for (uint8_t i = 0; i < PERIOD_PARAM; ++i)
{
if (period.param[i]>59) period.param[i]=59;
}
if (period.param[0]>23) period.param[0]=23;
if (period.param[3]>23) period.param[3]=23;
if (funcs.param[0]>9) funcs.param[0]=3;
if (funcs.param[1]>9) funcs.param[1]=3;
}
/************************************* 时间相关 *************************************/
#define TIM_Y_START 62
#define TIM_Y_TRG 44
#define TIM_HEIGHT 30
struct
{
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t wday;
char time_arr[9];
char last_time_arr[9];
bool time_changed_flag;
bool time_changing_flag;
float time_y;
float time_y_trg;
} dateTime;
PROGMEM const String WDAY_NAMES[] = {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
uint32_t auto_time_count;
hw_timer_t *tim0 = NULL;
void Init_timer();
void time_init()
{
dateTime.year=2024;
dateTime.month=4;
dateTime.day=18;
dateTime.hour=17;
dateTime.minute=4;
dateTime.second=0;
dateTime.wday=4;
strcpy(dateTime.time_arr, "17:04:00");
strcpy(dateTime.last_time_arr, "17:04:00");
Init_timer();
}
void time_show_update()
{
dateTime.time_changed_flag = false;
for(uint8_t i=0;i<8;i++)
{
if(dateTime.time_arr[i]!=dateTime.last_time_arr[i])
{
dateTime.time_changed_flag = true;
break;
}
}
if(dateTime.time_changed_flag && !dateTime.time_changing_flag)
{
dateTime.time_y = TIM_Y_START;
dateTime.time_y_trg = TIM_Y_TRG;
dateTime.time_changing_flag = true;
}
}
void time_update()
{
auto_time_count++;
dateTime.second++;
if(dateTime.second>59)
{
dateTime.second=0;
dateTime.minute++;
}
if(dateTime.minute>59)
{
dateTime.minute=0;
dateTime.hour++;
}
if(dateTime.hour>23)
{
dateTime.hour=0;
dateTime.day++;
dateTime.wday++;
}
if(dateTime.wday>6)
{
dateTime.wday=0;
}
uint8_t fulldays=30;
switch(dateTime.month)
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
fulldays=31;
break;
case 4:case 6: case 9: case 11:
fulldays=30;
break;
case 2:
if(dateTime.year%4==0) fulldays=29; else fulldays=28;
break;
}
if(dateTime.day>fulldays)
{
dateTime.day=1;
dateTime.month++;
}
if(dateTime.month>12)
{
dateTime.month=1;
dateTime.year++;
}
sprintf(dateTime.time_arr,"%02d:%02d:%02d",dateTime.hour,dateTime.minute,dateTime.second);
time_show_update();
}
void Init_timer()
{
tim0 = timerBegin(0, 80, true);
timerAttachInterrupt(tim0, time_update, true);
timerAlarmWrite(tim0, 1000000, true);
timerAlarmEnable(tim0);
}
/************************************* 按键相关 *************************************/
//按键引脚
#define BTN_UP 4
#define BTN_DOWN 18
#define BTN_MID 16
#define BTN_LEF 17
#define BTN_RIG 5
#define AIO 17
#define BIO 5
//按键ID
#define BTN_ID_UP 0 //上
#define BTN_ID_DOWN 1 //下
#define BTN_ID_MID_SP 2 //短按
#define BTN_ID_MID_LP 3 //长按
#define BTN_ID_LEF 4 //左
#define BTN_ID_RIG 5 //右
#define BTN_ID_CC 6
#define BTN_ID_CW 7
//按键变量
#define BTN_PARAM_TIMES 2 //由于uint8_t最大值可能不够,但它存储起来方便,这里放大两倍使用
struct
{
uint8_t id;
bool flag;
bool pressed;
bool val_up;
bool val_down;
bool val_middle;
bool val_left;
bool val_right;
bool val_last_up;
bool val_last_down;
bool val_last_middle;
bool val_last_left;
bool val_last_right;
bool CW_1;
bool CW_2;
bool alv;
bool blv;
long count;
} volatile btn;
void knob_inter()
{
btn.alv = digitalRead(AIO);
btn.blv = digitalRead(BIO);
if (!btn.flag && btn.alv == LOW)
{
btn.CW_1 = btn.blv;
btn.flag = true;
}
if (btn.flag && btn.alv)
{
btn.CW_2 = !btn.blv;
if (btn.CW_1 && btn.CW_2)
{
btn.id = BTN_ID_UP; //BTN_ID_CC; //BTN_ID_UP
btn.pressed = true;
}
if (btn.CW_1 == false && btn.CW_2 == false)
{
btn.id = BTN_ID_DOWN; //BTN_ID_CW; //BTN_ID_DOWN
btn.pressed = true;
}
btn.flag = false;
}
}
void btn_scan()
{
// knob_inter();
// Middle Button
if (!btn.pressed)
{
btn.val_middle = digitalRead(BTN_MID);
if (btn.val_middle != btn.val_last_middle)
{
btn.val_last_middle = btn.val_middle;
delay(BTN_SP_TIME * BTN_PARAM_TIMES);
btn.val_middle = digitalRead(BTN_MID);
if (btn.val_middle == LOW)
{
btn.pressed = true;
btn.count = 0;
while (!digitalRead(BTN_MID))
{
btn.count++;
delay(1);
}
if (btn.count < ui.param[BTN_LPT] * BTN_PARAM_TIMES) btn.id = BTN_ID_MID_SP;
else btn.id = BTN_ID_MID_LP;
}
}
}
/*
// Up Button
if (!btn.pressed)
{
btn.val_up = digitalRead(BTN_UP);
if (btn.val_up != btn.val_last_up)
{
btn.val_last_up = btn.val_up;
delay(BTN_SP_TIME * BTN_PARAM_TIMES);
btn.val_up = digitalRead(BTN_UP);
if (btn.val_up == HIGH)
{
btn.pressed = true;
btn.id = BTN_ID_UP;
long count = 0;
while (digitalRead(BTN_UP))
{
count++;
delay(1);
if (count > ui.param[BTN_LPT] * BTN_PARAM_TIMES)
{
btn.pressed = true;
btn.id = BTN_ID_UP;
ui_proc();
}
}
}
}
}
// Down Button
if (!btn.pressed)
{
btn.val_down = digitalRead(BTN_DOWN);
if (btn.val_down != btn.val_last_down)
{
btn.val_last_down = btn.val_down;
delay(BTN_SP_TIME * BTN_PARAM_TIMES);
btn.val_down = digitalRead(BTN_DOWN);
if (btn.val_down == HIGH)
{
btn.pressed = true;
btn.id = BTN_ID_DOWN;
long count = 0;
while (digitalRead(BTN_DOWN))
{
count++;
delay(1);
if (count > ui.param[BTN_LPT] * BTN_PARAM_TIMES)
{
btn.pressed = true;
btn.id = BTN_ID_DOWN;
ui_proc();
}
}
}
}
}
// Left Button
if (!btn.pressed)
{
btn.val_left = digitalRead(BTN_LEF);
if (btn.val_left != btn.val_last_left)
{
btn.val_last_left = btn.val_left;
delay(BTN_SP_TIME * BTN_PARAM_TIMES);
btn.val_left = digitalRead(BTN_LEF);
if (btn.val_left == HIGH)
{
btn.pressed = true;
btn.id = BTN_ID_LEF;
}
}
}
// Right Button
if (!btn.pressed)
{
btn.val_right = digitalRead(BTN_RIG);
if (btn.val_right != btn.val_last_right)
{
btn.val_last_right = btn.val_right;
delay(BTN_SP_TIME * BTN_PARAM_TIMES);
btn.val_right = digitalRead(BTN_RIG);
if (btn.val_right == HIGH)
{
btn.pressed = true;
btn.id = BTN_ID_RIG;
}
}
}
*/
if(btn.pressed)
{
auto_time_count=0;
}
}
void btn_init()
{
pinMode(BTN_MID, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLDOWN);
pinMode(BTN_DOWN, INPUT_PULLDOWN);
pinMode(BTN_LEF, INPUT_PULLDOWN);
pinMode(BTN_RIG, INPUT_PULLDOWN);
pinMode(AIO, INPUT_PULLUP);
pinMode(BIO, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(AIO), knob_inter, CHANGE);
pinMode(CHG_R_PIN, INPUT_PULLDOWN);
pinMode(CHG_G_PIN, INPUT_PULLDOWN);
attachInterrupt(digitalPinToInterrupt(CHG_R_PIN), charge_green_inter, RISING);
attachInterrupt(digitalPinToInterrupt(CHG_G_PIN), charge_red_inter, RISING);
}
/************************************* Text Edit *************************************/
#define TEXT_STR_LEN 20
#define BLINK_SPEED 18
struct
{
char wifi_user[TEXT_STR_LEN];
char wifi_psw[TEXT_STR_LEN]="asdgasdg";
uint8_t edit_index;
bool edit_flag = false;
uint16_t blink_count;
} text;
void str_text_edit(char* textArr, bool dir,uint8_t index)
{
if(!dir)
{
if(textArr[index]>='A' && textArr[index]<='Z')
{
if(textArr[index]=='A')
{
textArr[index]='z';
}
else
{
textArr[index]-=1;
}
}
else if(textArr[index]>='a' && textArr[index]<='z')
{
if(textArr[index]=='a')
{
textArr[index]='9';
}
else
{
textArr[index]-=1;
}
}
else if(textArr[index]>='0' && textArr[index]<='9')
{
if(textArr[index]=='0')
{
textArr[index]=' ';
}
else
{
textArr[index]-=1;
}
}
else
{
textArr[index]='Z';
}
}
else
{
if(textArr[index]>='A' && textArr[index]<='Z')
{
if(textArr[index]=='Z')
{
textArr[index]=' ';
}
else
{
textArr[index]+=1;
}
}
else if(textArr[index]>='a' && textArr[index]<='z')
{
if(textArr[index]=='z')
{
textArr[index]='A';
}
else
{
textArr[index]+=1;
}
}
else if(textArr[index]>='0' && textArr[index]<='9')
{
if(textArr[index]=='9')
{
textArr[index]='a';
}
else
{
textArr[index]+=1;
}
}
else
{
textArr[index]='0';
}
}
}
void chr_text_edit(char* textArr, bool dir,uint8_t index)
{
if(!dir)
{
if(textArr[index]>=' ' && textArr[index]<='z')
{
if(textArr[index]==' ')
{
textArr[index]='z';
}
else
{
textArr[index]-=1;
}
}
else
{
textArr[index]=' ';
}
}
else
{
if(textArr[index]>=' ' && textArr[index]<='z')
{
if(textArr[index]=='z')
{
textArr[index]=' ';
}
else
{
textArr[index]+=1;
}
}
else
{
textArr[index]='z';
}
}
}
void user_text_edit_show()
{
u8g2.drawRFrame(4,6,120,52,8);
u8g2.drawStr((128-u8g2.getStrWidth("--User Name--"))/2,20,"--User Name--");
u8g2.drawStr(10,38,text.wifi_user);
u8g2.drawStr(80,50,"-Return");
uint8_t box_x = 9;
if(text.edit_index<TEXT_STR_LEN)
{
if(text.blink_count<BLINK_SPEED/2)
{
for(uint8_t i=0;i<text.edit_index;++i)
{
char temp[2] = {text.wifi_user[i],'\0'};
box_x += u8g2.getStrWidth(temp);
if(text.wifi_user[i]!=' ')
{
box_x++;
}
}
char temp[2]={text.wifi_user[text.edit_index],'\0'};
u8g2.setDrawColor(2);
u8g2.drawBox(box_x,26,u8g2.getStrWidth(temp)+2,16);
u8g2.setDrawColor(1);
}
else
{
u8g2.setDrawColor(2);
u8g2.drawRBox(78,38,u8g2.getStrWidth("-Return")+4,16,1);
u8g2.setDrawColor(1);
}
}
if(text.edit_flag)
{
if(text.blink_count<BLINK_SPEED)
{
text.blink_count+=1;
}
else
{
text.blink_count=0;
}
}
else
{
text.blink_count=0;
}
}
void psw_text_edit_show()
{
u8g2.drawRFrame(4,6,120,52,8);
u8g2.drawStr((128-u8g2.getStrWidth("--Password--"))/2,20,"--Password--");
u8g2.drawStr(10,38,text.wifi_psw);
u8g2.drawStr(80,50,"-Return");
uint8_t box_x = 9;
if(text.edit_index<TEXT_STR_LEN)
{
if(text.blink_count<BLINK_SPEED/2)
{
for(uint8_t i=0;i<text.edit_index;++i)
{
char temp[2] = {text.wifi_psw[i],'\0'};
box_x += u8g2.getStrWidth(temp);
if(text.wifi_psw[i]!=' ')
{
box_x++;
}
}
char temp[2]={text.wifi_psw[text.edit_index],'\0'};
u8g2.setDrawColor(2);
u8g2.drawBox(box_x,26,u8g2.getStrWidth(temp)+2,16);
u8g2.setDrawColor(1);
}
else
{
// u8g2.setDrawColor(2);
// u8g2.drawRBox(78,38,u8g2.getStrWidth("-Return")+4,16,1);
// u8g2.setDrawColor(1);
}
}
if(text.edit_flag)
{
if(text.blink_count<BLINK_SPEED)
{
text.blink_count+=1;
}
else
{
text.blink_count=0;
}
}
else
{
text.blink_count=0;
}
}
void text_str_edit_proc()
{
psw_text_edit_show();
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
if(text.edit_flag)
{
chr_text_edit(text.wifi_psw,false,text.edit_index);
}
else
{
if(text.edit_index==0)
{
text.edit_index=TEXT_STR_LEN;
}
else
{
text.edit_index-=1;
}
}
break;
case BTN_ID_UP:
if(text.edit_flag)
{
chr_text_edit(text.wifi_psw,true,text.edit_index);
}
else
{
if(text.edit_index==TEXT_STR_LEN)
{
text.edit_index=0;
}
else
{
text.edit_index+=1;
}
}
break;
case BTN_ID_MID_SP:
if(text.edit_index==TEXT_STR_LEN)
{
ui.index = M_WIFI;
ui.state = S_LAYER_OUT;
text.edit_index=0;
}
else
{
text.edit_flag=!text.edit_flag;
}
break;
case BTN_ID_MID_LP:
ui.index = M_WIFI;
ui.state = S_LAYER_OUT;
text.edit_index=0;
break;
}
}
}
/************************************ 初始化函数 ***********************************/
/********************************* 初始化数据处理函数 *******************************/
//显示数值的初始化
void check_box_v_init(uint8_t *param)
{
check_box.v = param;
}
//多选框的初始化
void check_box_m_init(uint8_t *param)
{
check_box.m = param;
}
//单选框时的初始化
void check_box_s_init(uint8_t *param, uint8_t *param_p)
{
check_box.s = param;
check_box.s_p = param_p;
}
//多选框处理函数
void check_box_m_select(uint8_t param)
{
check_box.m[param] = !check_box.m[param];
eeprom.change = true;
}
//单选框处理函数
void check_box_s_select(uint8_t val, uint8_t pos)
{
*check_box.s = val;
*check_box.s_p = pos;
eeprom.change = true;
}
//弹窗数值初始化
void window_value_init(const char title[], uint8_t select, uint8_t *value, uint8_t max, uint8_t min, uint8_t step, MENU *bg, uint8_t index)
{
strcpy(win.title, title);
win.select = select;
win.value = value;
win.max = max;
win.min = min;
win.step = step;
win.bg = bg;
win.index = index;
ui.index = M_WINDOW;
ui.state = S_WINDOW;
}
/*********************************** UI 初始化函数 *********************************/
//在初始化EEPROM时,选择性初始化的默认设置
void ui_param_init()
{
ui.param[DISP_BRI] = 255; //屏幕亮度
ui.param[TILE_ANI] = 10; //磁贴动画速度
ui.param[LIST_ANI] = 10; //列表动画速度
ui.param[WIN_ANI] = 10; //弹窗动画速度
ui.param[SPOT_ANI] = 10; //聚光动画速度
ui.param[TAG_ANI] = 10; //标签动画速度
ui.param[FADE_ANI] = 20; //消失动画速度
ui.param[AUT_TM] = 25; //自动时间时长
ui.param[BTN_LPT] = 100; //按键长按时长
ui.param[TILE_UFD] = 1; //磁贴图标从头展开开关
ui.param[LIST_UFD] = 1; //菜单列表从头展开开关
ui.param[TILE_LOOP] = 0; //磁贴图标循环模式开关
ui.param[LIST_LOOP] = 0; //菜单列表循环模式开关
ui.param[WIN_BOK] = 0; //弹窗背景虚化开关
ui.param[KNOB_DIR] = 0; //旋钮方向切换开关
ui.param[DARK_MODE] = 1; //黑暗模式开关
}
//列表类页面列表行数初始化,必须初始化的参数
void ui_init()
{
ui.num[M_MAIN] = sizeof( main_menu ) / sizeof(M_SELECT);
ui.num[M_HALO] = sizeof( halo_menu ) / sizeof(M_SELECT);
ui.num[M_PERIOD] = sizeof( period_menu ) / sizeof(M_SELECT);
ui.num[M_TIME] = sizeof( time_menu ) / sizeof(M_SELECT);
ui.num[M_STT] = sizeof( stt_menu ) / sizeof(M_SELECT);
ui.num[M_ENT] = sizeof( ent_menu ) / sizeof(M_SELECT);
ui.num[M_CHARGE] = sizeof( charge_menu ) / sizeof(M_SELECT);
ui.num[M_SETTING] = sizeof( setting_menu ) / sizeof(M_SELECT);
ui.num[M_SYSTEM] = sizeof( system_menu ) / sizeof(M_SELECT);
ui.num[M_WIFI] = sizeof( wifi_menu ) / sizeof(M_SELECT);
ui.num[M_ABOUT] = sizeof( about_menu ) / sizeof(M_SELECT);
}
/********************************* 分页面初始化函数 ********************************/
//进入磁贴类时的初始化
void tile_param_init()
{
ui.init = false;
tile.icon_x = 0;
tile.icon_x_trg = TILE_ICON_S;
tile.icon_y = -TILE_ICON_H;
tile.icon_y_trg = 0;
tile.indi_x = 0;
tile.indi_x_trg = TILE_INDI_W;
tile.title_y = tile.title_y_calc;
tile.title_y_trg = tile.title_y_trg_calc;
}
//进入睡眠时的初始化
void sleep_param_init()
{
u8g2.setDrawColor(0);
u8g2.drawBox(0, 0, DISP_W, DISP_H);
u8g2.setPowerSave(1);
ui.state = S_NONE;
ui.sleep = true;
if (eeprom.change)
{
eeprom_write_all_data();
eeprom.change = false;
}
}
//旋钮设置页初始化
void funcs_param_init() { check_box_s_init(&funcs.param[0],&funcs.param[1]); }
//开始时间页初始化
void stt_param_init() { check_box_v_init(&period.param[0]); }
//结束时间页初始化
void ent_param_init() { check_box_v_init(&period.param[3]); }
//电压测量页初始化
void volt_param_init()
{
volt.text_bg_r = 0;
volt.text_bg_r_trg = VOLT_TEXT_BG_W;
}
//电压测量页初始化
void time_param_init()
{
if (eeprom.change)
{
eeprom_write_all_data();
eeprom.change = false;
}
}
//设置页初始化
void setting_param_init()
{
// check_box_v_init(ui.param);
// check_box_m_init(ui.param);
}
void system_param_init()
{
check_box_v_init(ui.param);
check_box_m_init(ui.param);
}
/********************************** 通用初始化函数 *********************************/
/*
页面层级管理逻辑是,把所有页面都先当作列表类初始化,不是列表类按需求再初始化对应函数
这样做会浪费一些资源,但跳转页面时只需要考虑页面层级,逻辑上更清晰,减少出错
*/
//弹窗动画初始化
void window_param_init()
{
win.bar = 0;
win.y = WIN_Y;
win.y_trg = win.u;
ui.state = S_NONE;
}
//进入更深层级时的初始化
void layer_init_in()
{
ui.layer ++;
ui.init = 0;
list.y = 0;
list.y_trg = LIST_LINE_H;
list.box_x = 0;
list.box_y = 0;
list.bar_y = 0;
ui.state = S_FADE;
switch (ui.index)
{
case M_MAIN: tile_param_init(); break; //睡眠进入主菜单,动画初始化
case M_PERIOD: funcs_param_init(); break; //旋钮设置页,行末尾文字初始化
case M_STT: stt_param_init(); break; //旋钮旋转页,单选框初始化
case M_ENT: ent_param_init(); break; //旋钮点按页,单选框初始化
case M_TIME: time_param_init(); break; //主菜单进入时间页,动画初始化
case M_CHARGE: volt_param_init(); break; //主菜单进入电压测量页,动画初始化
case M_SETTING: setting_param_init(); break; //主菜单进入设置页,单选框初始化
case M_SYSTEM: system_param_init(); break; //主菜单进入设置页,单选框初始化
}
}
//进入更浅层级时的初始化
void layer_init_out()
{
ui.select[ui.layer] = 0;
list.box_y_trg[ui.layer] = 0;
ui.layer --;
ui.init = 0;
list.y = 0;
list.y_trg = LIST_LINE_H;
list.bar_y = 0;
ui.state = S_FADE;
switch (ui.index)
{
case M_SLEEP: sleep_param_init(); break; //主菜单进入睡眠页,检查是否需要写EEPROM
case M_MAIN: tile_param_init(); break; //不管什么页面进入主菜单时,动画初始化
}
}
/************************************* 动画函数 *************************************/
//动画函数
void animation(float *a, float *a_trg, uint8_t n)
{
if (*a != *a_trg)
{
if (fabs(*a - *a_trg) < 0.15f) *a = *a_trg;
else *a += (*a_trg - *a) / (ui.param[n] / 10.0f);
if (fabs(*a - *a_trg) < 0.15f) *a = *a_trg;
}
}
void animationA(float *a, float *a_trg, float n)
{
if (*a != *a_trg)
{
if (fabs(*a - *a_trg) < 0.15f) *a = *a_trg;
else *a += n;
if (fabs(*a - *a_trg) < 0.15f) *a = *a_trg;
}
}
//消失函数
void fade()
{
delay(ui.param[FADE_ANI]);
if (ui.param[DARK_MODE])
{
switch (ui.fade)
{
case 1: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 != 0) buf_ptr[i] = buf_ptr[i] & 0xAA; break;
case 2: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 != 0) buf_ptr[i] = buf_ptr[i] & 0x00; break;
case 3: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 == 0) buf_ptr[i] = buf_ptr[i] & 0x55; break;
case 4: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 == 0) buf_ptr[i] = buf_ptr[i] & 0x00; break;
default: ui.state = S_NONE; ui.fade = 0; break;
}
}
else
{
switch (ui.fade)
{
case 1: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 != 0) buf_ptr[i] = buf_ptr[i] | 0xAA; break;
case 2: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 != 0) buf_ptr[i] = buf_ptr[i] | 0x00; break;
case 3: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 == 0) buf_ptr[i] = buf_ptr[i] | 0x55; break;
case 4: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 == 0) buf_ptr[i] = buf_ptr[i] | 0x00; break;
default: ui.state = S_NONE; ui.fade = 0; break;
}
}
ui.fade++;
}
/************************************* 显示函数 *************************************/
//磁贴类页面通用显示函数
void tile_show(struct MENU arr_1[])
{
//计算动画过渡值
animation(&tile.icon_x, &tile.icon_x_trg, TILE_ANI);
animation(&tile.icon_y, &tile.icon_y_trg, TILE_ANI);
animation(&tile.indi_x, &tile.indi_x_trg, TILE_ANI);
animation(&tile.title_y, &tile.title_y_trg, TILE_ANI);
//设置大标题的颜色,0透显,1实显,2反色, 这里用实显
u8g2.setDrawColor(1);
//绘制大标题
u8g2.setFont(TILE_B_FONT);
u8g2.drawStr(((DISP_W - TILE_INDI_W) - u8g2.getStrWidth(arr_1[ui.select[ui.layer]].m_select)) / 2 + TILE_INDI_W, tile.title_y, arr_1[ui.select[ui.layer]].m_select);
int16_t sub=5;
//绘制图标
if (!ui.init)
{
for (uint8_t i = 0; i < ui.num[ui.index]; ++i)
{
if (ui.param[TILE_UFD]) tile.temp = (DISP_W - TILE_ICON_W) / 2 + i * tile.icon_x - TILE_ICON_S * ui.select[ui.layer];
else tile.temp = (DISP_W - TILE_ICON_W) / 2 + (i - ui.select[ui.layer]) * tile.icon_x;
int16_t target_x= (DISP_W - TILE_ICON_W) / 2 + (int16_t)(- ui.select[ui.layer] * TILE_ICON_S) + i * TILE_ICON_S;
int16_t curren_x = tile.temp;
if(i==ui.select[ui.layer])
{
u8g2.drawXBMP(curren_x - sub, (int16_t)tile.icon_y, TILE_ICON_W+10, TILE_ICON_H+10, main_icon_pic_40x40[i]);
}
else
{
u8g2.drawXBMP(curren_x, (int16_t)tile.icon_y+sub, TILE_ICON_W, TILE_ICON_H, main_icon_pic_30x30[i]);
}
}
if ((int16_t)tile.icon_x == (int16_t)tile.icon_x_trg)
{
ui.init = true;
tile.icon_x = tile.icon_x_trg = - ui.select[ui.layer] * TILE_ICON_S;
}
}
else
{
for (uint8_t i = 0; i < ui.num[ui.index]; ++i)
{
if(i==ui.select[ui.layer])
{
u8g2.drawXBMP((DISP_W - TILE_ICON_W) / 2 + (int16_t)tile.icon_x + i * TILE_ICON_S-sub, 0, TILE_ICON_W+10, TILE_ICON_H+10, main_icon_pic_40x40[i]);
}
else
{
u8g2.drawXBMP((DISP_W - TILE_ICON_W) / 2 + (int16_t)tile.icon_x + i * TILE_ICON_S, sub, TILE_ICON_W, TILE_ICON_H, main_icon_pic_30x30[i]);
}
}
}
//反转屏幕内元素颜色,白天模式遮罩
u8g2.setDrawColor(2);
if (!ui.param[DARK_MODE]) u8g2.drawBox(0, 0, DISP_W, DISP_H);
}
/*************** 根据列表每行开头符号,判断每行尾部是否绘制以及绘制什么内容 *************/
//列表显示数值
void list_draw_value(int n) { u8g2.print(check_box.v[n - 1]); }
//绘制外框
void list_draw_check_box_frame() { u8g2.drawRFrame(CHECK_BOX_L_S, list.temp + CHECK_BOX_U_S, CHECK_BOX_F_W, CHECK_BOX_F_H, 1); }
//绘制框里面的点
void list_draw_check_box_dot() { u8g2.drawBox(CHECK_BOX_L_S + CHECK_BOX_D_S + 1, list.temp + CHECK_BOX_U_S + CHECK_BOX_D_S + 1, CHECK_BOX_F_W - (CHECK_BOX_D_S + 1) * 2, CHECK_BOX_F_H - (CHECK_BOX_D_S + 1) * 2); }
//判断列表尾部内容
void list_draw_text_and_check_box(struct MENU arr[], int i)
{
u8g2.drawStr(LIST_TEXT_S, list.temp + LIST_TEXT_H + LIST_TEXT_S, arr[i].m_select);
u8g2.setCursor(CHECK_BOX_L_S, list.temp + LIST_TEXT_H + LIST_TEXT_S);
switch (arr[i].m_select[0])
{
case '~': list_draw_value(i); break;
case '+': list_draw_check_box_frame(); if (check_box.m[i - 1] == 1) list_draw_check_box_dot(); break;
case '=': list_draw_check_box_frame(); if (funcs.param[1] == i) list_draw_check_box_dot();
break;
case '>':
{
u8g2.setCursor(CHECK_BOX_L_S_T, list.temp + LIST_TEXT_H + LIST_TEXT_S);
print_time(period.param[0],period.param[1],period.param[2]);
break;
}
case '<':
{
u8g2.setCursor(CHECK_BOX_L_S_T, list.temp + LIST_TEXT_H + LIST_TEXT_S);
print_time(period.param[3],period.param[4],period.param[5]);
break;
}
}
}
/******************************** 列表显示函数 **************************************/
//列表类页面通用显示函数
void list_show(struct MENU arr[], uint8_t ui_index)
{
//更新动画目标值
u8g2.setFont(LIST_FONT);
list.box_x_trg = u8g2.getStrWidth(arr[ui.select[ui.layer]].m_select) + LIST_TEXT_S * 2;
list.bar_y_trg = ceil((ui.select[ui.layer]) * ((float)DISP_H / (ui.num[ui_index] - 1)));
//计算动画过渡值
animation(&list.y, &list.y_trg, LIST_ANI);
animation(&list.box_x, &list.box_x_trg, LIST_ANI);
animation(&list.box_y, &list.box_y_trg[ui.layer], LIST_ANI);
animation(&list.bar_y, &list.bar_y_trg, LIST_ANI);
//检查循环动画是否结束
if (list.loop && list.box_y == list.box_y_trg[ui.layer]) list.loop = false;
//设置文字和进度条颜色,0透显,1实显,2反色,这里都用实显
u8g2.setDrawColor(1);
//绘制进度条
u8g2.drawHLine(DISP_W - LIST_BAR_W, 0, LIST_BAR_W);
u8g2.drawHLine(DISP_W - LIST_BAR_W, DISP_H - 1, LIST_BAR_W);
u8g2.drawVLine(DISP_W - ceil((float)LIST_BAR_W / 2), 0, DISP_H);
u8g2.drawBox(DISP_W - LIST_BAR_W, 0, LIST_BAR_W, list.bar_y);
//绘制列表文字
if (!ui.init)
{
for (int i = 0; i < ui.num[ui_index]; ++ i)
{
if (ui.param[LIST_UFD]) list.temp = i * list.y - LIST_LINE_H * ui.select[ui.layer] + list.box_y_trg[ui.layer];
else list.temp = (i - ui.select[ui.layer]) * list.y + list.box_y_trg[ui.layer];
list_draw_text_and_check_box(arr, i);
}
if (list.y == list.y_trg)
{
ui.init = true;
list.y = list.y_trg = - LIST_LINE_H * ui.select[ui.layer] + list.box_y_trg[ui.layer];
}
}
else for (int i = 0; i < ui.num[ui_index]; ++ i)
{
list.temp = LIST_LINE_H * i + list.y;
list_draw_text_and_check_box(arr, i);
}
//绘制文字选择框,0透显,1实显,2反色,这里用反色
u8g2.setDrawColor(2);
u8g2.drawRBox(0, list.box_y, list.box_x, LIST_LINE_H, LIST_BOX_R);
//反转屏幕内元素颜色,白天模式遮罩,在这里屏蔽有列表参与的页面,使遮罩作用在那个页面上
if (!ui.param[DARK_MODE])
{
u8g2.drawBox(0, 0, DISP_W, DISP_H);
switch(ui.index)
{
case M_WINDOW:
case M_TIME:
u8g2.drawBox(0, 0, DISP_W, DISP_H);
}
}
}
void print_time(uint8_t hour,uint8_t minute,uint8_t second)
{
if(hour<10) u8g2.print("0");
u8g2.print(hour);
if(minute<10) u8g2.print(":0"); else u8g2.print(":");
u8g2.print(minute);
if(second<10) u8g2.print(":0"); else u8g2.print(":");
u8g2.print(second);
}
void time_show()
{
//设置曲线颜色,0透显,1实显,2反色,这里用实显
u8g2.setDrawColor(1);
animationA(&dateTime.time_y, &dateTime.time_y_trg, -1);
//绘制时间值
u8g2.setFont(TIME_B_FONT);
int16_t temp_x = 0;
if(dateTime.time_y==dateTime.time_y_trg)
{
if(dateTime.time_changing_flag)
{
for(uint8_t i=0;i<8;i++)
{
dateTime.last_time_arr[i]=dateTime.time_arr[i];
}
dateTime.time_changed_flag = false;
dateTime.time_changing_flag = false;
}
for(uint8_t i=0;i<8;i++)
{
char temp[2]={dateTime.time_arr[i],'\0'};
u8g2.drawStr(temp_x,(int16_t)dateTime.time_y_trg,temp);
temp_x+=u8g2.getStrWidth(temp);
}
}
else
{
for(uint8_t i=0;i<8;i++)
{
char temp[2]={dateTime.time_arr[i],'\0'};
if(dateTime.time_arr[i]!=dateTime.last_time_arr[i])
{
u8g2.drawStr(temp_x,(int16_t)dateTime.time_y,temp);
char temp_last[2]={dateTime.last_time_arr[i],'\0'};
u8g2.drawStr(temp_x,(int16_t)dateTime.time_y-TIM_HEIGHT-1,temp_last);
}
else
{
u8g2.drawStr(temp_x,(int16_t)dateTime.time_y_trg,temp);
}
temp_x+=u8g2.getStrWidth(temp);
}
u8g2.setDrawColor(0);
u8g2.drawBox(0, 0, DISP_W, TIM_HEIGHT-10);
u8g2.drawBox(0, TIM_Y_TRG+1, DISP_W, TIM_HEIGHT-10);
}
u8g2.setDrawColor(1);
//绘制日期值
u8g2.setFont(LIST_FONT);
u8g2.setCursor(1, 10);
u8g2.print(dateTime.year);
if(dateTime.month<10) u8g2.print("-0"); else u8g2.print("-");
u8g2.print(dateTime.month);
if(dateTime.day<10) u8g2.print("-0"); else u8g2.print("-");
u8g2.print(dateTime.day);
u8g2.setCursor(1, DISP_H - 2);
u8g2.print(WDAY_NAMES[dateTime.wday]);
// u8g2.print(" 26 C");
u8g2.drawXBMP(DISP_W-26, 0, 10, 10, show_icon_pic[1]);
u8g2.drawXBMP(DISP_W-13, 0, 12, 10, show_icon_pic[0]);
//反转屏幕内元素颜色,白天模式遮罩
if (!ui.param[DARK_MODE]) u8g2.drawBox(0, 0, DISP_W, DISP_H);
}
long volt_count;
void calculate_chart_point(int* value,float fValue,float minValue,float maxValue)
{
if (minValue==maxValue)
{
*value = (WAVE_MIN + WAVE_MAX)/2;
}
else
{
float percent = (fValue-minValue)/(maxValue-minValue);
*value = WAVE_MAX + 1 - (int)(percent*(WAVE_MAX-WAVE_MIN));
}
}
//电压页面显示函数
void volt_show()
{
//使用列表类显示选项
list_show(charge_menu, M_CHARGE);
//计算动画过渡值
animation(&volt.text_bg_r, &volt.text_bg_r_trg, TAG_ANI);
//设置曲线颜色,0透显,1实显,2反色,这里用实显
u8g2.setDrawColor(1);
bool update_flag=false;
if (millis()-volt.refresh_count>200)
{
volt.refresh_count=millis();
// Read INA226 data
volt.val_v[WAVE_SAMPLE-1] = ina.voltage;
volt.val_i[WAVE_SAMPLE-1] = ina.current;
volt.val_w[WAVE_SAMPLE-1] = ina.power;
volt.val1=ina.voltage;
volt.val2=ina.current;
volt.val3=ina.power;
update_flag=true;
}
if(ui.select[ui.layer]>0)
{
//绘制电压曲线和外框
volt.val = 0;
u8g2.drawFrame(WAVE_BOX_L_S, 0, WAVE_BOX_W, WAVE_BOX_H);
u8g2.drawFrame(WAVE_BOX_L_S + 1, 1, WAVE_BOX_W - 2, WAVE_BOX_H - 2);
if (list.box_y == list.box_y_trg[ui.layer] && list.y == list.y_trg)
{
if ( update_flag )
{
for (int i = 0; i < WAVE_SAMPLE - 1; i++)
{
volt.val_v[i] = volt.val_v[i+1];
volt.val_i[i] = volt.val_i[i+1];
volt.val_w[i] = volt.val_w[i+1];
}
volt.val_v_min=volt.val_v[0];
volt.val_i_min=volt.val_i[0];
volt.val_w_min=volt.val_w[0];
volt.val_v_max=volt.val_v[0];
volt.val_i_max=volt.val_i[0];
volt.val_w_max=volt.val_w[0];
for (int i = 0; i < WAVE_SAMPLE; i++)
{
if(volt.val_v[i]<volt.val_v_min)volt.val_v_min=volt.val_v[i];
if(volt.val_i[i]<volt.val_i_min)volt.val_i_min=volt.val_i[i];
if(volt.val_w[i]<volt.val_w_min)volt.val_w_min=volt.val_w[i];
if(volt.val_v[i]>volt.val_v_max)volt.val_v_max=volt.val_v[i];
if(volt.val_i[i]>volt.val_i_max)volt.val_i_max=volt.val_i[i];
if(volt.val_w[i]>volt.val_w_max)volt.val_w_max=volt.val_w[i];
}
}
switch(ui.select[ui.layer])
{
case 1:
volt.val=volt.val_v[WAVE_SAMPLE-1];
for (int i = 1; i < WAVE_SAMPLE - 0; i++)
{
int val1,val2;
calculate_chart_point(&val1,volt.val_v[i],volt.val_v_min,volt.val_v_max);
calculate_chart_point(&val2,volt.val_v[i-1],volt.val_v_min,volt.val_v_max);
u8g2.drawLine(WAVE_L + i*4, WAVE_U + val1, WAVE_L + (i-1)*4, WAVE_U + val2);
}
break;
case 2:
volt.val=volt.val_i[WAVE_SAMPLE-1];
for (int i = 1; i < WAVE_SAMPLE - 0; i++)
{
int val1,val2;
calculate_chart_point(&val1,volt.val_i[i],volt.val_i_min,volt.val_i_max);
calculate_chart_point(&val2,volt.val_i[i-1],volt.val_i_min,volt.val_i_max);
u8g2.drawLine(WAVE_L + i*4, WAVE_U + val1, WAVE_L + (i-1)*4, WAVE_U + val2);
}
break;
case 3:
volt.val=volt.val_w[WAVE_SAMPLE-1];
for (int i = 1; i < WAVE_SAMPLE - 0; i++)
{
int val1,val2;
calculate_chart_point(&val1,volt.val_w[i],volt.val_w_min,volt.val_w_max);
calculate_chart_point(&val2,volt.val_w[i-1],volt.val_w_min,volt.val_w_max);
u8g2.drawLine(WAVE_L + i*4, WAVE_U + val1, WAVE_L + (i-1)*4, WAVE_U + val2);
}
break;
}
}
//绘制电压值
u8g2.setFontDirection(0);
u8g2.setFont(VOLT_FONT);
u8g2.setCursor(39, DISP_H - 6);
u8g2.print(volt.val);
switch(ui.select[ui.layer])
{
case 1: u8g2.print("V"); break;
case 2: u8g2.print("A"); break;
case 3: u8g2.print("w"); break;
}
//绘制列表选择框和电压文字背景
u8g2.setDrawColor(2);
u8g2.drawBox(VOLT_TEXT_BG_L_S, DISP_H - VOLT_TEXT_BG_H, volt.text_bg_r, VOLT_TEXT_BG_H);
}
else
{
u8g2.setFontDirection(0);
u8g2.setFont(VOLT_FONT_S);
uint8_t dis=60;
u8g2.setCursor(32, DISP_H - 42);
u8g2.print(volt.val1);
u8g2.setCursor(32+dis+3, DISP_H - 42);
u8g2.print("V");
u8g2.setCursor(32, DISP_H - 24);
u8g2.print(volt.val2);
u8g2.setCursor(32+dis+3, DISP_H - 24);
u8g2.print("A");
u8g2.setCursor(32, DISP_H - 6);
u8g2.print(volt.val3);
u8g2.setCursor(32+dis, DISP_H - 6);
u8g2.print("W");
//u8g2.setDrawColor(2);
//u8g2.drawBox(WAVE_BOX_L_S, 0, WAVE_BOX_W, 64);
u8g2.drawFrame(WAVE_BOX_L_S, 0, WAVE_BOX_W, 64);
u8g2.drawFrame(WAVE_BOX_L_S+1, 0+1, WAVE_BOX_W-2, 64-2);
}
//反转屏幕内元素颜色,白天模式遮罩
if (!ui.param[DARK_MODE]) u8g2.drawBox(0, 0, DISP_W, DISP_H);
}
//弹窗通用显示函数
void window_show()
{
//绘制背景列表,根据开关判断背景是否要虚化
list_show(win.bg, win.index);
if (ui.param[WIN_BOK]) for (uint16_t i = 0; i < buf_len; ++i) buf_ptr[i] = buf_ptr[i] & (i % 2 == 0 ? 0x55 : 0xAA);
//更新动画目标值
u8g2.setFont(WIN_FONT);
win.bar_trg = (float)(*win.value - win.min) / (float)(win.max - win.min) * (WIN_BAR_W - 4);
//计算动画过渡值
animation(&win.bar, &win.bar_trg, WIN_ANI);
animation(&win.y, &win.y_trg, WIN_ANI);
//绘制窗口
u8g2.setDrawColor(0); u8g2.drawRBox(win.l, (int16_t)win.y, WIN_W, WIN_H, 2); //绘制外框背景
u8g2.setDrawColor(1); u8g2.drawRFrame(win.l, (int16_t)win.y, WIN_W, WIN_H, 2); //绘制外框描边
u8g2.drawRFrame(win.l + 5, (int16_t)win.y + 20, WIN_BAR_W, WIN_BAR_H, 1); //绘制进度条外框
u8g2.drawBox(win.l + 7, (int16_t)win.y + 22, win.bar, WIN_BAR_H - 4); //绘制进度条
u8g2.setCursor(win.l + 5, (int16_t)win.y + 14); u8g2.print(win.title); //绘制标题
u8g2.setCursor(win.l + 78, (int16_t)win.y + 14); u8g2.print(*win.value); //绘制当前值
//需要在窗口修改参数时立即见效的函数
if (!strcmp(win.title, "Disp Bri"))
{
u8g2.setContrast(ui.param[DISP_BRI]);
strip.setBrightness(ui.param[DISP_BRI]);
}
//反转屏幕内元素颜色,白天模式遮罩
u8g2.setDrawColor(2);
if (!ui.param[DARK_MODE]) u8g2.drawBox(0, 0, DISP_W, DISP_H);
}
/************************************* 处理函数 *************************************/
/*********************************** 通用处理函数 ***********************************/
//磁贴类页面旋转时判断通用函数
void tile_rotate_switch()
{
switch (btn.id)
{
case BTN_ID_UP:
if (ui.init)
{
if (ui.select[ui.layer] > 0)
{
ui.select[ui.layer] -= 1;
tile.icon_x_trg += TILE_ICON_S;
tile.select_flag = false;
}
else
{
if (ui.param[TILE_LOOP])
{
ui.select[ui.layer] = ui.num[ui.index] - 1;
tile.icon_x_trg = - TILE_ICON_S * (ui.num[ui.index] - 1);
break;
}
else tile.select_flag = true;
}
}
break;
case BTN_ID_DOWN:
if (ui.init)
{
if (ui.select[ui.layer] < (ui.num[ui.index] - 1))
{
ui.select[ui.layer] += 1;
tile.icon_x_trg -= TILE_ICON_S;
tile.select_flag = false;
}
else
{
if (ui.param[TILE_LOOP])
{
ui.select[ui.layer] = 0;
tile.icon_x_trg = 0;
break;
}
else tile.select_flag = true;
}
}
break;
}
}
//列表类页面旋转时判断通用函数
void list_rotate_switch()
{
if (!list.loop)
{
switch (btn.id)
{
case BTN_ID_UP:
if (ui.select[ui.layer] == 0)
{
if (ui.param[LIST_LOOP] && ui.init)
{
list.loop = true;
ui.select[ui.layer] = ui.num[ui.index] - 1;
if (ui.num[ui.index] > list.line_n)
{
list.box_y_trg[ui.layer] = DISP_H - LIST_LINE_H;
list.y_trg = DISP_H - ui.num[ui.index] * LIST_LINE_H;
}
else list.box_y_trg[ui.layer] = (ui.num[ui.index] - 1) * LIST_LINE_H;
break;
}
else break;
}
if (ui.init)
{
ui.select[ui.layer] -= 1;
if (ui.select[ui.layer] < - (list.y_trg / LIST_LINE_H))
{
if (!(DISP_H % LIST_LINE_H)) list.y_trg += LIST_LINE_H;
else
{
if (list.box_y_trg[ui.layer] == DISP_H - LIST_LINE_H * list.line_n)
{
list.y_trg += (list.line_n + 1) * LIST_LINE_H - DISP_H;
list.box_y_trg[ui.layer] = 0;
}
else if (list.box_y_trg[ui.layer] == LIST_LINE_H)
{
list.box_y_trg[ui.layer] = 0;
}
else list.y_trg += LIST_LINE_H;
}
}
else list.box_y_trg[ui.layer] -= LIST_LINE_H;
break;
}
case BTN_ID_DOWN:
if (ui.select[ui.layer] == (ui.num[ui.index] - 1))
{
if (ui.param[LIST_LOOP] && ui.init)
{
list.loop = true;
ui.select[ui.layer] = 0;
list.y_trg = 0;
list.box_y_trg[ui.layer] = 0;
break;
}
else break;
}
if (ui.init)
{
ui.select[ui.layer] += 1;
if ((ui.select[ui.layer] + 1) > (list.line_n - list.y_trg / LIST_LINE_H))
{
if (!(DISP_H % LIST_LINE_H)) list.y_trg -= LIST_LINE_H;
else
{
if (list.box_y_trg[ui.layer] == LIST_LINE_H * (list.line_n - 1))
{
list.y_trg -= (list.line_n + 1) * LIST_LINE_H - DISP_H;
list.box_y_trg[ui.layer] = DISP_H - LIST_LINE_H;
}
else if (list.box_y_trg[ui.layer] == DISP_H - LIST_LINE_H * 2)
{
list.box_y_trg[ui.layer] = DISP_H - LIST_LINE_H;
}
else list.y_trg -= LIST_LINE_H;
}
}
else list.box_y_trg[ui.layer] += LIST_LINE_H;
break;
}
break;
}
}
}
//弹窗通用处理函数
void window_proc()
{
window_show();
if (win.y == WIN_Y_TRG) ui.index = win.index;
if (btn.pressed && win.y == win.y_trg && win.y != WIN_Y_TRG)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_UP: if (*win.value < win.max) *win.value += win.step; eeprom.change = true; break;
case BTN_ID_DOWN: if (*win.value > win.min) *win.value -= win.step; eeprom.change = true; break;
case BTN_ID_MID_SP: case BTN_ID_MID_LP: win.y_trg = WIN_Y_TRG; break;
}
}
}
/********************************** 分页面处理函数 **********************************/
//睡眠页面处理函数
void sleep_proc()
{
while (ui.sleep)
{
//睡眠时循环执行的函数
//time_show();
//睡眠时需要扫描旋钮才能退出睡眠
btn_scan();
//当旋钮有动作时
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
//睡眠时上键执行的函数
case BTN_ID_DOWN:
break;
//睡眠时下键执行的函数
case BTN_ID_UP:
break;
//睡眠时短按执行的函数
// case BTN_ID_SP: break;
//睡眠时长按执行的函数
case BTN_ID_MID_LP: ui.index = M_MAIN; ui.state = S_LAYER_IN; u8g2.setPowerSave(0); ui.sleep = false; break;
}
}
}
}
//主菜单处理函数,磁贴类模板
void main_proc()
{
tile_show(main_menu);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
case BTN_ID_LEF:
case BTN_ID_RIG:
tile_rotate_switch();
break;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
case 0: ui.index = M_SLEEP; ui.state = S_LAYER_OUT; break;
case 1: ui.index = M_HALO; ui.state = S_LAYER_IN; break;
case 2: ui.index = M_TIME; ui.state = S_LAYER_IN; break;
case 3: ui.index = M_CHARGE; ui.state = S_LAYER_IN; break;
case 4: ui.index = M_SETTING; ui.state = S_LAYER_IN; break;
}
}
if (!tile.select_flag && ui.init) { tile.indi_x = 0; tile.title_y = tile.title_y_calc; }
}
}
//编辑器菜单处理函数
void halo_proc()
{
list_show(halo_menu, M_HALO);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
ui.select[ui.layer] = 0;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
case 0: ui.index = M_MAIN; ui.state = S_LAYER_OUT; break;
case 1:
case 2: break;
case 3:case 4:case 5:case 6:case 7:case 8:case 9:
funcs_param_init();
check_box_s_select(ui.select[ui.layer], ui.select[ui.layer]);
update_led_color_index(ui.select[ui.layer]-3);
break;
case 11: ui.index = M_PERIOD; ui.state = S_LAYER_IN; break;
}
}
}
}
//旋钮编辑菜单处理函数
void period_proc()
{
list_show(period_menu, M_PERIOD);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
ui.select[ui.layer] = 0;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
case 0: ui.index = M_HALO; ui.state = S_LAYER_OUT; break;
case 2: ui.index = M_STT; ui.state = S_LAYER_IN; check_box_v_init(&period.param[0]); break;
case 3: ui.index = M_ENT; ui.state = S_LAYER_IN; check_box_v_init(&period.param[3]); break;
}
}
}
}
//显示时间信息
void time_proc()
{
time_show();
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
list_rotate_switch();
break;
case BTN_ID_MID_SP:
case BTN_ID_MID_LP:
ui.index = M_MAIN;
ui.state = S_LAYER_OUT;
break;
}
}
}
//旋钮旋转功能菜单处理函数
void stt_proc()
{
list_show(stt_menu, M_STT);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_UP:
case BTN_ID_DOWN:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
ui.select[ui.layer] = 0;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
case 0: ui.index = M_PERIOD; ui.state = S_LAYER_OUT; break;
case 1: window_value_init("Hour", START_HOUR, &period.param[0], 23, 0, 1, stt_menu, M_STT); break;
case 2: window_value_init("Minute", START_MINUTE, &period.param[1], 59, 0, 1, stt_menu, M_STT); break;
case 3: window_value_init("Second", START_SECOND, &period.param[2], 59, 0, 1, stt_menu, M_STT); break;
}
}
}
}
void ent_proc()
{
list_show(ent_menu, M_ENT);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_UP:
case BTN_ID_DOWN:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
ui.select[ui.layer] = 0;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
case 0: ui.index = M_PERIOD; ui.state = S_LAYER_OUT; break;
case 1: window_value_init("Hour", END_HOUR, &period.param[3], 23, 0, 1, ent_menu, M_ENT); break;
case 2: window_value_init("Minute", END_MINUTE, &period.param[4], 59, 0, 1, ent_menu, M_ENT); break;
case 3: window_value_init("Second", END_SECOND, &period.param[5], 59, 0, 1, ent_menu, M_ENT); break;
}
}
}
}
//设置菜单处理函数,多选框列表类模板,弹窗模板
void setting_proc()
{
list_show(setting_menu, M_SETTING);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
ui.select[ui.layer] = 0;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
//返回更浅层级,长按被当作选择这一项,也是执行这一行
case 0: ui.index = M_MAIN; ui.state = S_LAYER_OUT; break;
//系统参数
case 1: ui.index = M_SYSTEM; ui.state = S_LAYER_IN; break;
//WIFI
case 2: ui.index = M_WIFI; ui.state = S_LAYER_IN; break;
//关于本机
case 3: ui.index = M_ABOUT; ui.state = S_LAYER_IN; break;
}
}
}
}
//电压测量页处理函数
void volt_proc()
{
volt_show();
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
case BTN_ID_MID_SP:
ui.index = M_MAIN;
ui.state = S_LAYER_OUT;
break;
}
}
}
//设置菜单处理函数,多选框列表类模板,弹窗模板
void system_proc()
{
list_show(system_menu, M_SYSTEM);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
ui.select[ui.layer] = 0;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
//返回更浅层级,长按被当作选择这一项,也是执行这一行
case 0: ui.index = M_SETTING; ui.state = S_LAYER_OUT; break;
//弹出窗口,参数初始化:标题,参数名,参数值,最大值,最小值,步长,背景列表名,背景列表标签
case 1: window_value_init("Disp Bri", DISP_BRI, &ui.param[DISP_BRI], 255, 0, 5, system_menu, M_SETTING); break;
case 2: window_value_init("Tile Ani", TILE_ANI, &ui.param[TILE_ANI], 100, 10, 1, system_menu, M_SETTING); break;
case 3: window_value_init("List Ani", LIST_ANI, &ui.param[LIST_ANI], 100, 10, 1, system_menu, M_SETTING); break;
case 4: window_value_init("Win Ani", WIN_ANI, &ui.param[WIN_ANI], 100, 10, 1, system_menu, M_SETTING); break;
case 5: window_value_init("Spot Ani", SPOT_ANI, &ui.param[SPOT_ANI], 100, 10, 1, system_menu, M_SETTING); break;
case 6: window_value_init("Tag Ani", TAG_ANI, &ui.param[TAG_ANI], 100, 10, 1, system_menu, M_SETTING); break;
case 7: window_value_init("Fade Ani", FADE_ANI, &ui.param[FADE_ANI], 255, 0, 1, system_menu, M_SETTING); break;
case 8: window_value_init("Auto Time", AUT_TM, &ui.param[AUT_TM], 255, 0, 1, system_menu, M_SETTING); break;
case 9: window_value_init("Btn LPT", BTN_LPT, &ui.param[BTN_LPT], 255, 0, 1, system_menu, M_SETTING); break;
//多选框
case 10: check_box_m_select( TILE_UFD ); break;
case 11: check_box_m_select( LIST_UFD ); break;
case 12: check_box_m_select( TILE_LOOP ); break;
case 13: check_box_m_select( LIST_LOOP ); break;
case 14: check_box_m_select( WIN_BOK ); break;
case 15: check_box_m_select( KNOB_DIR ); break;
case 16: check_box_m_select( DARK_MODE ); break;
}
}
}
}
//Wifi配置页面
void wifi_proc()
{
list_show(wifi_menu, M_WIFI);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
ui.select[ui.layer] = 0;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
case 0: ui.index = M_SETTING; ui.state = S_LAYER_OUT; break;
case 1: ui.index = M_WIFI_USR; ui.state = S_LAYER_IN; break;
case 2: ui.index = M_WIFI_PSW; ui.state = S_LAYER_IN; break;
}
}
}
}
//关于本机页
void about_proc()
{
list_show(about_menu, M_ABOUT);
if (btn.pressed)
{
btn.pressed = false;
switch (btn.id)
{
case BTN_ID_DOWN:
case BTN_ID_UP:
list_rotate_switch();
break;
case BTN_ID_MID_LP:
ui.select[ui.layer] = 0;
case BTN_ID_MID_SP:
switch (ui.select[ui.layer])
{
case 0: ui.index = M_SETTING; ui.state = S_LAYER_OUT; break;
}
}
}
}
void auto_time_proc()
{
if (auto_time_count>ui.param[AUT_TM])
{
if (!ui.sleep)
{
Serial.println("auto time");
start_time();
}
auto_time_count=0;
}
}
//总的UI进程
void ui_proc()
{
u8g2.sendBuffer();
switch (ui.state)
{
case S_FADE: fade(); break; //转场动画
case S_WINDOW: window_param_init(); break; //弹窗初始化
case S_LAYER_IN: layer_init_in(); break; //层级初始化
case S_LAYER_OUT: layer_init_out(); break; //层级初始化
case S_NONE: u8g2.clearBuffer(); switch (ui.index) //直接选择页面
{
case M_WINDOW: window_proc(); break;
case M_SLEEP: sleep_proc(); break;
case M_MAIN: main_proc(); break;
case M_HALO: halo_proc(); break;
case M_PERIOD: period_proc(); break;
case M_STT: stt_proc(); break;
case M_ENT: ent_proc(); break;
case M_TIME: time_proc(); break;
case M_CHARGE: volt_proc(); break;
case M_SETTING: setting_proc(); break;
case M_SYSTEM: system_proc(); break;
case M_WIFI: wifi_proc(); break;
case M_WIFI_USR: text_str_edit_proc(); break;
case M_WIFI_PSW: text_str_edit_proc(); break;
case M_ABOUT: about_proc(); break;
}
}
}
//OLED初始化函数
void oled_init()
{
u8g2.setBusClock(4000000); //硬件IIC接口使用
u8g2.begin();
u8g2.setContrast(ui.param[DISP_BRI]);
buf_ptr = u8g2.getBufferPtr();
buf_len = 8 * u8g2.getBufferTileHeight() * u8g2.getBufferTileWidth();
}
void setup()
{
Serial.begin(115200);
strip.begin();
strip.setBrightness(255);
ledBar.begin();
ledBar.setBrightness(200);
ledBar.setLedColorData(0, led.bar_r, led.bar_g, led.bar_b);
ledBar.show();
charge_green_inter();
eeprom_init();
ui_init();
oled_init();
btn_init();
time_init();
ui.sleep=false;
start_time();
ws2812_param_init();
ina226_init();
strip.setBrightness(ui.param[DISP_BRI]);
}
long print_count=0;
void loop()
{
btn_scan();
ui_proc();
auto_time_proc();
ws2812_pro();
ina226_read();
//ws2812_loop();
// if (millis()-print_count>1000)
// {
// print_count=millis();
// Serial.print(ina.voltage);
// Serial.print(",");
// Serial.print(ina.current);
// Serial.print(",");
// Serial.print(ina.power);
// Serial.println();
// }
}