WouoUI/Third-party-design/PageVersion/Csource/example/LittleClock/LittleClockUI.c

339 lines
16 KiB
C
Raw Normal View History

#include "LittleClockUI.h"
#include "string.h"
#include "System.h"
#include "BATADC.h"
//定义的跨文件的全局变量
uint16_t fps = 0; //帧率
uint8_t update_flag = 0;
//-------枚举id唯一标识一个页面防止有两个页面使用同一id
enum
{
main_page_id = 0x00,
calendar_page_id,
clock_page_id,
alarm_list_page_id,
alarm1_page_id,
alarm2_page_id,
about_page_id,
ring_page_id, //这个页面是单独游离的,只有闹钟时才会调出来
};
//--------定义页面对象
TitlePage main_page;
DigitalPage calendar_page;
DigitalPage clock_page;
ListPage alarm_list_page;
DigitalPage alarm1_page;
DigitalPage alarm2_page;
RaderPicPage about_page;
RaderPicPage ring_page; //闹钟响起时的界面(空的RaderPicPage页面用于自己绘制)
//--------定义每个页面需要的一些参数
//部分页面内选项个数
#define MAIN_PAGE_NUM 5
#define CALENDAR_LABEL_NUM 7
#define ALARM_LIST_PAGE_NUM 3
#define ALARM12_LABEL_NUM 3
#define ABOUT_PAGE_NUM 1
//定义部分页面选项
//********main页面的选项
Option mian_option_array[MAIN_PAGE_NUM] =
{///{ order,max,min,step,int_val,text,} //option的成员顺序但对单纯title的页面来说只有text需要赋值
{.text = "- Calendar"}, //前两个字符是前缀,不显示,用于标识一般选项(-),二值选项(+),数值弹窗(~),确认弹窗($)
{.text = "- Clock"},
{.text = "- Alarm"},
{.text = "~ BATLevel", .item_max = 100, .item_min = 0, .step = 0,.val = 50,},
//数值弹窗电压显示(step = 0则为只读无法使用按键编辑(其实就是使操作+-0无效))
{.text = "- Aoubt"},
};
//main页面的图标
Icon main_icon_array[MAIN_PAGE_NUM] =
{
[0] = {0xF0,0xF8,0x38,0x38,0x38,0x38,0x7F,0xFF,0x7F,0x38,0x38,0x38,0x38,0x38,0x38,0x38,
0x38,0x38,0x38,0x38,0x38,0x7F,0xFF,0xFF,0x38,0x38,0x38,0x38,0xF8,0xF0,0xFF,0xFF,
0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x8E,0x8E,0xCE,0xCE,0x0E,0x0E,
0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0xFF,0xFF,0xFF,0xFF,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x1F,0x3F,0x38,0x38,0x38,0x38,
0x38,0x38,0x38,0x38,0x38,0x39,0x3B,0x3B,0x39,0x39,0x3B,0x3B,0x39,0x38,0x38,0x38,
0x38,0x38,0x38,0x38,0x38,0x38,0x3F,0x1F}, //Canlendar
[1] = {0x00,0x00,0xC0,0xE0,0xF0,0x38,0x1C,0x1C,0x0E,0x06,0x07,0x07,0x07,0x03,0xE3,0xE3,
0x03,0x07,0x07,0x07,0x06,0x0E,0x1C,0x1C,0x38,0xF0,0xE0,0xC0,0x00,0x00,0xFC,0xFF,
0x1F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x1F,0xFF,0xFC,0x0F,0x3F,0xFE,0xE0,
0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x07,
0x07,0x07,0x07,0x06,0x0E,0xCE,0xE2,0xFE,0x3F,0x0F,0x00,0x00,0x00,0x01,0x03,0x07,
0x0E,0x0E,0x1C,0x18,0x38,0x38,0x38,0x30,0x30,0x30,0x30,0x38,0x38,0x38,0x18,0x1C,
0x0E,0x0E,0x07,0x03,0x01,0x00,0x00,0x00}, //clock
[2] = {0xF0,0xF8,0x9C,0xCE,0xEE,0x76,0xBE,0xDC,0xEC,0x60,0x70,0x30,0x38,0x38,0xF8,0xF8,
0x38,0x38,0x30,0x30,0x70,0xEC,0xDC,0xFE,0xF6,0xEE,0xCE,0x9C,0xFC,0xF0,0x01,0x03,
0xE7,0xFB,0xFF,0x0F,0x03,0x01,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x03,0x0F,0xFE,0xFD,0xE7,0x03,0x01,0x00,0x00,0x01,0x1F,
0x7F,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x80,0xC0,0xF0,0x7F,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x0C,0x1E,0x0F,
0x07,0x03,0x07,0x07,0x0E,0x0E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0E,0x0E,0x07,0x07,
0x03,0x03,0x07,0x0E,0x1C,0x08,0x00,0x00}, //alarm
[3] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,
0x30,0x18,0x18,0x10,0x30,0x70,0xD8,0x98,0x18,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x80,0xC0,0xE0,0x30,0x18,0x4C,0x26,0x13,0x03,0x01,0x00,0x00,0x00,0x00,
0x0A,0x04,0x0A,0x00,0x00,0x81,0xC2,0x6F,0x39,0x00,0x00,0x00,0x00,0x00,0x1E,0x33,
0x41,0x81,0x00,0x10,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0x30,0x18,
0x0C,0x06,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x06,0x0C,0x08,0x08,0x0C,0x06,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //Bat level
[4] = {0x00,0x00,0xC0,0xE0,0xF0,0x38,0x1C,0x1C,0x0E,0x06,0x07,0x07,0x07,0x03,0x03,0x03,
0x03,0x03,0x07,0x07,0x06,0x0E,0x1C,0x1C,0x38,0xF0,0xE0,0xC0,0x00,0x00,0xFC,0xFF,
0x1F,0x01,0x00,0xC0,0xE0,0xE0,0xC0,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xC0,0x00,
0x00,0x00,0x00,0xC0,0xE0,0xE0,0xC0,0x00,0x01,0x1F,0xFF,0xF8,0x0F,0x3F,0xFE,0xE0,
0xC0,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x01,0x00,0xC0,0xF0,0xFE,0x3F,0x0F,0x00,0x00,0x00,0x01,0x03,0x07,
0x0E,0x0E,0x1C,0x18,0x38,0x38,0x38,0x30,0x30,0x30,0x30,0x38,0x38,0x38,0x18,0x1C,
0x0E,0x0E,0x07,0x03,0x01,0x00,0x00,0x00}, //more
};
//Calendar 页面的选项
Option calendar_option_array[3] =
{///{ order,max,min,step,int_val,text,}
[Digital_Pos_IndexLeft] = { .item_max = 99, .item_min = 0, .step = 1, .text = "Year"},
[Digital_Pos_IndexMid] = { .item_max = 12, .item_min = 1, .step = 1, .text = "Month"},
[Digital_Pos_IndexRight] = { .item_max = 31, .item_min = 1, .step = 1, .text = "day"},
};
//标签数组
String week_str[CALENDAR_LABEL_NUM] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
//Clock页面选项
Option clock_option_array[3]=
{
[Digital_Pos_IndexLeft] = { .item_max = 23, .item_min = 0, .step = 1, .text = "Hour"},
[Digital_Pos_IndexMid] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Minute"},
[Digital_Pos_IndexRight] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Second"},
};
//alarm页面选项
Option alarm_list_option_array[3]=
{
{.text = " alarm list"},
{.text = "+ Alarm1", .val = 0,}, //为二值选项单选项值由Alarm12页面控制(读全局update_flag中enable_msk位可以设置)
{.text = "+ Alarm2", .val = 0,}, //默认值为0close
};
//alarm1页面选项
Option alarm1_option_array[3]=
{
[Digital_Pos_IndexLeft] = { .item_max = 23, .item_min = 0, .step = 1, .text = "Hour"},
[Digital_Pos_IndexMid] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Minute"},
[Digital_Pos_IndexRight] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Second"},
};
Option alarm2_option_array[3]=
{
[Digital_Pos_IndexLeft] = { .item_max = 23, .item_min = 0, .step = 1, .text = "Hour"},
[Digital_Pos_IndexMid] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Minute"},
[Digital_Pos_IndexRight] = { .item_max = 59, .item_min = 0, .step = 0, .text = "Second"},
//DS3231只有两个闹钟且闹钟2的秒无效所以alarm2的step为0,为不可编辑模式
//(因为air001的内存不够也不想做软件闹钟了)
};
String alarm12_label_array[3] = { "Close", "Open", "Delete"};
//About页面
const uint8_t QRCode[] = {
0xFF,0xFF,0xFF,0x07,0x07,0xE7,0x27,0x27,0x27,0x27,0x27,0x27,0xE7,0x07,0x07,0xFF,
0xFF,0xDF,0x1F,0x1F,0x27,0x27,0x27,0x27,0xFF,0xC7,0xC7,0x27,0x27,0x1F,0x1F,0xFF,
0xFF,0xFF,0x07,0x07,0xE7,0x27,0x27,0x27,0x27,0x27,0x27,0xE7,0x07,0x07,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x80,0x9F,0x90,0x90,0x90,0x90,0x90,0x90,0x9F,0x80,
0x80,0xFF,0xFF,0x93,0xF0,0xF0,0x90,0x90,0xF3,0xF3,0x90,0x6F,0x6F,0x9F,0x9F,0xEC,
0xEC,0x0F,0xFF,0xFF,0x80,0x80,0x9F,0x90,0x90,0x90,0x90,0x90,0x90,0x9F,0x80,0x80,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x3F,0x31,0x31,0x3F,0x3F,0xF1,0xF1,
0x3F,0xCD,0xCD,0xC3,0xC3,0xCF,0x0F,0x0F,0xFF,0xFF,0x03,0x03,0x3F,0x00,0x00,0xCF,
0xCF,0xFD,0xFD,0x0C,0x3F,0x3F,0x03,0x03,0x0F,0xCD,0xCD,0xFF,0xFF,0xCF,0xCF,0x0D,
0xC3,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x66,0x9E,0x86,0x86,0x9F,0x9F,
0x07,0x07,0x80,0x66,0x66,0x66,0x66,0xFE,0x86,0x86,0xE0,0xE0,0x98,0x98,0x7F,0x87,
0x87,0xE7,0xE7,0xFE,0xFE,0x78,0x1F,0x1F,0x60,0x60,0x66,0x1F,0x1F,0x78,0x78,0xE7,
0xE7,0x86,0xE0,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x03,0xF3,0x13,0x13,
0x13,0x13,0x13,0x13,0xF3,0x03,0x03,0xFF,0xFF,0x9C,0x00,0x00,0x73,0x73,0x10,0x10,
0xE0,0xEF,0xEF,0x80,0x80,0x70,0x70,0x00,0x1F,0x1F,0x93,0x93,0x1F,0x00,0x00,0x00,
0x00,0x7F,0x7F,0x80,0x80,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xCF,
0xC8,0xC8,0xC8,0xC8,0xC8,0xC8,0xCF,0xC0,0xC0,0xFF,0xFF,0xC9,0xC0,0xC0,0xFE,0xFE,
0xF6,0xF6,0xCF,0xF9,0xF9,0xFF,0xFF,0xF0,0xF0,0xC6,0xC8,0xC8,0xFF,0xFF,0xCE,0xF0,
0xF0,0xF6,0xF6,0xFE,0xFE,0xC7,0xC9,0xC9,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,
}; //Qrcode
RaderPic qrcode_raderpic[ABOUT_PAGE_NUM] =
{
{.pic = QRCode, .start_x = 7, .start_y = 7, .w = 50, .h = 50, .rd = RD_RIGHT_DOWN},
};
//--------定义每个页面的回调函数
void MainPage_CallBack(uint8_t self_page_id,Option* select_item)
{
switch (select_item->order)
{
case 0: OLED_UIJumpToPage(self_page_id,&calendar_page); break;
case 1: OLED_UIJumpToPage(self_page_id,&clock_page); break;
case 2: OLED_UIJumpToPage(self_page_id,&alarm_list_page); break;
case 3: //更新电量
select_item->val = BATADC_Read();
break;
case 4: OLED_UIJumpToPage(self_page_id,&about_page); break;
default: break;
}
}
void CalendarPage_CallBack(uint8_t self_page_id,Option* select_item)
{
uint8_t month_days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
switch (select_item->order)
{
case Digital_Pos_Complete : //全部数据设置完成后,也会检测一次数据
SET_FLAG(update_flag,DATE_UPDATE_MSK); //同时会通知main函数设置rtc芯片
case Digital_Pos_IndexRight: //更正日期数据
if( calendar_page.option_array[Digital_Pos_IndexRight].val > //大于每个月的最大月数,更正日期
month_days[calendar_page.option_array[Digital_Pos_IndexMid].val -1])
OLED_DigitalPage_UpdateDigitalNumAnimation(&calendar_page,
calendar_page.option_array[Digital_Pos_IndexLeft].val,
calendar_page.option_array[Digital_Pos_IndexMid].val,
month_days[calendar_page.option_array[Digital_Pos_IndexMid].val -1], Digital_Direct_Decrease);
break;
default:break;
}
}
void ClockPage_CallBack(uint8_t self_page_id,Option* select_item)
{
if(select_item->order == Digital_Pos_Complete) //时间设置完成
SET_FLAG(update_flag,TIME_UPDATE_MSK); //通知主函数更新时间
}
void AlarmList_CallBack(uint8_t self_page_id,Option* select_item)
{
switch (select_item->order)
{
// case 0:
// OLED_UIJumpToPage(self_page_id, &ring_page); //只是作为绘制页面的跳转测试
// break;
case 1:
OLED_UIJumpToPage(self_page_id, &alarm1_page);
//设置其标签
alarm1_page.select_label_index = (!!FLAG_IS_SET(update_flag, ALARM1_ENABLE_MSK)); //将数值变量转为逻辑
break;
case 2:
OLED_UIJumpToPage(self_page_id, &alarm2_page);
alarm2_page.select_label_index = (!!FLAG_IS_SET(update_flag, ALARM2_ENABLE_MSK)); //将数值变量转为逻辑
break;
default :break;
}
}
void Alarm12_CallBack(uint8_t self_page_id,Option* select_item)
{
uint8_t update_msk = 0;
uint8_t enable_msk = 0;
if(self_page_id == alarm1_page_id){update_msk = ALARM1_UPDATE_MSK;enable_msk = ALARM1_ENABLE_MSK;}
else if(self_page_id == alarm2_page_id){update_msk = ALARM2_UPDATE_MSK;enable_msk = ALARM2_ENABLE_MSK;}
switch (select_item->order)
{
case Digital_Pos_Complete: //编辑完成
SET_FLAG(update_flag, update_msk);
break;
case Digital_Pos_IndexLabel: //click标签时
if(strcmp(select_item->text, alarm12_label_array[0]) == 0) //close
CLEAR_FLAG(update_flag,enable_msk);
else if(strcmp(select_item->text, alarm12_label_array[1]) == 0) //open
SET_FLAG(update_flag,enable_msk);
else if(strcmp(select_item->text, alarm12_label_array[2]) == 0) //Delete
{
CLEAR_FLAG(update_flag,enable_msk); //闹钟标志位关闭
if(self_page_id == alarm1_page_id)
OLED_DigitalPage_UpdateDigitalNumAnimation(&alarm1_page, 0,0,0,Digital_Direct_Decrease);
else if(self_page_id == alarm2_page_id)
OLED_DigitalPage_UpdateDigitalNumAnimation(&alarm2_page, 0,0,0,Digital_Direct_Decrease);
}
default:
break;
}
}
void About_CallBack(uint8_t self_page_id,Option* select_item)
{
uint8_t buff[10] = {0};
sprintf((char*)buff, "fps:%d",fps);
if(select_item->order == ABOUT_PAGE_NUM) //图像绘制完成后
{
OLED_WinDrawStr(&w_all, 64, 7, 16, buff);
OLED_WinDrawStr(&w_all, 64, 24, 16, "Scan");
OLED_WinDrawStr(&w_all, 64, 40, 16, "QrCode");
}
}
void Ring_CallBack(uint8_t self_page_id,Option* select_item)
{
static float x = 2;
static float x_trg = 12;
static uint8_t color = 1;
OLED_Animation(&x, &x_trg, 200);
OLED_WinDrawBMP(&w_all, 15, 15 , 30, 30 , main_icon_array[2], color); // 实色绘制闹钟图标
OLED_SetPointColor(2); //反色绘制
int16_t len = 62-2*x;
OLED_WinDrawRBox(&w_all, x, x, len, len,2);
OLED_SetPointColor(1); //恢复正常颜色
if(x == x_trg)
{
if(x_trg == 12){x_trg = 2;color =! color;}
else if(x_trg == 2){x_trg = 12;color =! color;}
}
if(FLAG_IS_SET(update_flag, ALARM1_RING_MSK))
OLED_WinDrawStr(&w_all, 60, 8, 16, "Alarm1");
else if((FLAG_IS_SET(update_flag, ALARM2_RING_MSK)))
OLED_WinDrawStr(&w_all, 60, 8, 16, "Alarm2");
OLED_WinDrawStr(&w_all, 60, 34, 8, "Press Any");
OLED_WinDrawStr(&w_all, 60, 44, 8, "Key to exit!");
}
//-------------一些需要用的内部函数
//--------------给主函数调用的接口函数
void LittleClockUI_Init(void)
{
OLED_Init(); //硬件的初始化
LL_mDelay(100);
OLED_ClearBuff(); //清空缓存
OLED_RefreshBuff(); //刷新屏幕(清空屏幕)
OLED_SetPointColor(1); //设置绘制颜色
OLED_UiInit(); //必要的ui参数初始化
OLED_TitlePageInit(&main_page, main_page_id, MAIN_PAGE_NUM, mian_option_array, main_icon_array, MainPage_CallBack);
OLED_DigitalPageInit(&calendar_page, calendar_page_id, calendar_option_array, CALENDAR_LABEL_NUM, week_str, '-', 0, 100, CalendarPage_CallBack);
OLED_DigitalPageInit(&clock_page, clock_page_id, clock_option_array, CALENDAR_LABEL_NUM, week_str, ':', 50, 100, ClockPage_CallBack); //时钟页面的标签也显示周
OLED_ListPageInit(&alarm_list_page, alarm_list_page_id, ALARM_LIST_PAGE_NUM, alarm_list_option_array, AlarmList_CallBack);
OLED_DigitalPageInit(&alarm1_page, alarm1_page_id, alarm1_option_array, ALARM12_LABEL_NUM, alarm12_label_array, ':', 50, 100, Alarm12_CallBack);
OLED_DigitalPageInit(&alarm2_page, alarm2_page_id, alarm2_option_array, ALARM12_LABEL_NUM, alarm12_label_array, ':', 50, 100, Alarm12_CallBack);
OLED_RaderPicPageInit(&about_page, about_page_id, ABOUT_PAGE_NUM, qrcode_raderpic, Rader_Pic_Mode_Hold, About_CallBack);
OLED_RaderPicPageInit(&ring_page, ring_page_id, 0, NULL, Rader_Pic_Mode_Hold, Ring_CallBack); //相当于一个空的页面可以自由绘制
}
void LittleClockUI_Proc(void)
{
OLED_UIProc();
//由updataflag接管 alarmlist中两个选框的选中与否
if(FLAG_IS_SET(update_flag,ALARM1_ENABLE_MSK))alarm_list_option_array[1].val = 1;
else alarm_list_option_array[1].val = 0;
if(FLAG_IS_SET(update_flag,ALARM2_ENABLE_MSK))alarm_list_option_array[2].val = 1;
else alarm_list_option_array[2].val = 0;
}