WouoUI/Third-party-design/PageVersion/Csource/example/LittleClock/LittleClockUI.c
2024-02-19 11:50:46 +08:00

339 lines
16 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}