diff --git a/Third-party-design/PageVersion/Csource/README.md b/Third-party-design/PageVersion/Csource/README.md new file mode 100644 index 0000000..0f47163 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/README.md @@ -0,0 +1,11 @@ +# 本文件夹的一些小说明 + +## 文件目录 + +```c +|---example(使用接口函数构建的例子,需要使用接口函数构建的,可以参考这个文件夹下的例子,共有2个) + |---LittleClock(一个用air001的小时钟) + |---UITest(页面展示的例子,基本上所有页面类型都有用到) +|---src(主要的源代码文件,7个文件,不包含oled_port.c) +``` + diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/LittleClockUI.c b/Third-party-design/PageVersion/Csource/example/LittleClock/LittleClockUI.c new file mode 100644 index 0000000..d5526d3 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/example/LittleClock/LittleClockUI.c @@ -0,0 +1,338 @@ +#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,}, //默认值为0,close +}; + +//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; +} diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/LittleClockUI.h b/Third-party-design/PageVersion/Csource/example/LittleClock/LittleClockUI.h new file mode 100644 index 0000000..3700410 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/example/LittleClock/LittleClockUI.h @@ -0,0 +1,33 @@ +#ifndef __LITTLECLOCKUI_H__ +#define __LITTLECLOCKUI_H__ + +#include "oled_ui.h" +#include "oled_g.h" +#include "oled_port.h" + +void LittleClockUI_Init(void); +void LittleClockUI_Proc(void); + +#define DATE_UPDATE_MSK 0x01 +#define TIME_UPDATE_MSK 0x02 +#define ALARM1_UPDATE_MSK 0x04 +#define ALARM2_UPDATE_MSK 0x08 //用于检测update flag的置位 +#define ALARM1_ENABLE_MSK 0x10 +#define ALARM2_ENABLE_MSK 0x20 //用于检测update flag的置位 + +#define ALARM1_RING_MSK 0x40 +#define ALARM2_RING_MSK 0x80 //主函数中置位,在响铃页面检测 + + +#define SET_FLAG(flag, msk) (flag|=msk) +#define FLAG_IS_SET(flag, msk) (flag&msk) +#define CLEAR_FLAG(flag, msk) (flag&= (~msk)) + +extern uint16_t fps; // 外界需要提供一个变量,统计一秒内UIproc能刷新几次,粗略估计帧率' +extern uint8_t update_flag; //用于主函数中判断是否需要更新rtc芯片的数据 +extern DigitalPage calendar_page; +extern DigitalPage clock_page; //用于主函数中,1秒更新一次时间 +extern DigitalPage alarm1_page; +extern DigitalPage alarm2_page; +extern RaderPicPage ring_page; +#endif diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/icon/BiliBili Air001模块视频码15.bmp b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/BiliBili Air001模块视频码15.bmp new file mode 100644 index 0000000..03d6051 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/BiliBili Air001模块视频码15.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/icon/日历.bmp b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/日历.bmp new file mode 100644 index 0000000..1b849b7 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/日历.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/icon/时钟.bmp b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/时钟.bmp new file mode 100644 index 0000000..3524c1c Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/时钟.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/icon/时钟2.bmp b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/时钟2.bmp new file mode 100644 index 0000000..17c059e Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/时钟2.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/icon/更多.bmp b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/更多.bmp new file mode 100644 index 0000000..d7a9fe9 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/更多.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/icon/电池,电量.bmp b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/电池,电量.bmp new file mode 100644 index 0000000..8195f3f Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/电池,电量.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/LittleClock/icon/电池,电量.png b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/电池,电量.png new file mode 100644 index 0000000..a4b944d Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/LittleClock/icon/电池,电量.png differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/TestUI.c b/Third-party-design/PageVersion/Csource/example/UITest/TestUI.c new file mode 100644 index 0000000..fdc96ef --- /dev/null +++ b/Third-party-design/PageVersion/Csource/example/UITest/TestUI.c @@ -0,0 +1,332 @@ +#include "TestUI.h" +#include "string.h" +#include "math.h" +#include "System.h" + +//-------枚举id,唯一标识一个页面,防止有两个页面使用同一id +enum +{ + main_page_id = 0x00, + logo_page_id, + setting_page_id, + curve_page_id, + lock_page_id, + about_page_id, + about_wououi_page_id, + about_page_version_id, +}; +//--------定义页面对象 +TitlePage main_page; +RaderPicPage logo_page; +ListPage setting_page; +WavePage curve_page; +DigitalPage lock_page; +ListPage about_page; +RadioPage about_wououi_page; //这两个相关页使用单选项RadioPage类型只是为了展示单选项页面而已 +RadioPage about_page_version_page; +//--------定义每个页面需要的一些参数 +//部分页面内选项个数 +#define MAIN_PAGE_NUM 5 +#define LOGO_PAGE_NUM 4 +#define SETTING_PAGE_NUM 13 +#define CURVE_PAGE_NUM 2 +#define LOCK_PAGE_LABEL_NUM 2 +#define ABOUT_PAGE_NUM 3 +#define ABOUT_WOUOUI_PAGE_NUM 9 +#define ABOUT_PAGEVERSION_NUM 8 + +//定义部分页面选项 +//********main页面的选项 +Option mian_option_array[MAIN_PAGE_NUM] = +{///{ order,max,min,step,int_val,text,} //option的成员顺序,但对单纯title的页面来说,只有text需要赋值 + {.text = "- Logo"}, //前两个字符是前缀,不显示,用于标识一般选项(-),二值选项(+),数值弹窗(~),确认弹窗($) + {.text = "- Setting"}, + {.text = "- Curve"}, + {.text = "- DigLock"}, + {.text = "- Aoubt"}, +}; +//main页面的图标 +Icon main_icon_array[MAIN_PAGE_NUM] = +{ + [0] = {0xFC,0xFE,0xFF,0x3F,0x1F,0x0F,0x07,0x03,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x03,0x07,0x07,0x0F,0x1F,0x3F,0xFF,0xFE,0xFC,0xFF,0x01, + 0x00,0x00,0x00,0x00,0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0xFC, + 0x00,0x00,0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xF0,0xC0,0x00, + 0x00,0x00,0x03,0x07,0x0F,0x1F,0x3E,0x3C,0x3C,0x3C,0x1E,0x1F,0x0F,0x03,0x00,0x00, + 0x1F,0x3F,0x3F,0x1F,0x00,0x00,0x00,0xC0,0xF0,0xFF,0xCF,0xDF,0xFF,0xFF,0xFE,0xFC, + 0xF8,0xF8,0xF0,0xF0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xF0, + 0xF8,0xF8,0xFC,0xFE,0xFF,0xFF,0xDF,0xCF}, //logo + [1] = {0xFC,0xFE,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x83,0x81,0x01,0x01,0x81,0xE1,0xE1,0xE1, + 0xE1,0x81,0x01,0x81,0x81,0x83,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFE,0xFC,0xFF,0x01, + 0x00,0x00,0x00,0xE0,0xE0,0xF3,0xFF,0xFF,0x3F,0x0F,0x07,0x07,0x03,0x03,0x07,0x07, + 0x0F,0x3F,0xFF,0xFF,0xF7,0xE0,0xE0,0x00,0x00,0x00,0x01,0xFF,0xFF,0xE0,0x80,0x00, + 0x00,0x01,0x01,0x3B,0x7F,0x7F,0x7F,0x3C,0x78,0xF8,0xF0,0xF0,0xF8,0x78,0x3C,0x3F, + 0x7F,0x7F,0x33,0x01,0x01,0x00,0x00,0x80,0xE0,0xFF,0xCF,0xDF,0xFF,0xFF,0xFE,0xFC, + 0xF8,0xF0,0xF0,0xE0,0xE0,0xE0,0xE0,0xE1,0xE1,0xE1,0xE1,0xE0,0xE0,0xE0,0xE0,0xF0, + 0xF0,0xF8,0xFC,0xFC,0xFF,0xFF,0xDF,0xCF}, // Setting + [2] = {0xFC,0xFE,0x07,0xF3,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0x03,0x03, + 0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xF3,0x07,0xFE,0xFC,0xFF,0xFF, + 0x00,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0xBF,0x3F,0x7F,0x20,0x08,0x8F,0x07, + 0x61,0x30,0x36,0x38,0x39,0x39,0x39,0x39,0x39,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0xE7, + 0xE7,0xE7,0xE7,0xE7,0xC7,0xDB,0xC3,0xE1,0xF8,0xFC,0x04,0x01,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0xCF,0xDF,0xF8,0xF3,0xF7,0xF7, + 0xF7,0xF7,0xF7,0xF7,0xF7,0xF7,0xF7,0xF7,0xF0,0xF0,0xF7,0xF7,0xF7,0xF7,0xF7,0xF7, + 0xF7,0xF7,0xF7,0xF7,0xF3,0xF8,0xDF,0xCF}, //Curve + [3] = {0xFC,0xFE,0x1F,0x07,0x07,0xC3,0xE3,0xE3,0xE3,0xE3,0xE3,0xE3,0xE3,0x63,0x63,0x63, + 0x63,0xE3,0xE3,0xE3,0xE3,0xE3,0xE3,0xE3,0xC3,0x07,0x07,0x1F,0xFE,0xFC,0xFF,0xFF, + 0x00,0x00,0x00,0xFF,0xFF,0xFF,0x3F,0x3F,0x3F,0x01,0x00,0x00,0x3C,0x3C,0x00,0x00, + 0x01,0x3F,0x3F,0x3F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00, + 0x00,0xFF,0xFF,0xFF,0xC0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0xC0,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xCF,0xDF,0xFE,0xF8,0xF8,0xF0, + 0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1, + 0xF1,0xF1,0xF0,0xF8,0xF8,0xFE,0xDF,0xCF}, //DigitalLock + [4] = {0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x3F,0x1F,0x0F,0x0F,0x0F,0x07,0x07,0x07, + 0x07,0x0F,0x0F,0x0F,0x1F,0x3F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xFF,0xFF, + 0xFF,0x3F,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xEE,0xE6,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1F,0x1F,0x08,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x60,0xF0,0xFF,0xFF,0xFF,0xFF,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFE,0xFC,0xFC,0xFC,0xFC,0xFC,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8, + 0xF8,0xF8,0xF8,0xF8,0xFF,0xFF,0xDF,0xCF} //about +}; + +//LOGO页面的参数 +const uint8_t logo_wouo_pic[] = {0x00,0x00,0xF8,0xF0,0x80,0x00,0x00,0x00,0xE0,0xFC,0xE0,0x00,0x00,0x00,0x00,0xF0, + 0xFC,0x04,0x18,0x30,0x70,0xE0,0xC0,0xE0,0xF0,0xF8,0x38,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x70,0x70,0xE0,0xC0,0xE0,0xF0,0x78,0x18,0x00, + 0x00,0x00,0x00,0x00,0x1F,0xFF,0xF0,0xF8,0x3F,0x03,0x01,0x1F,0x7E,0xF0,0xE0,0xFE, + 0x7F,0x01,0x00,0x00,0xF8,0x8E,0x83,0x81,0xC1,0x41,0x71,0x3F,0x00,0x00,0x7F,0xC0, + 0xC0,0xC0,0x60,0x30,0x7E,0xFF,0x00,0x00,0xFC,0x8E,0x83,0x81,0xC1,0x61,0x3B,0x1F, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00}; //49*20 +const uint8_t logo_ui_pic[] = {0x00,0x00,0x00,0xF0,0xFC,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFE, + 0xFC,0x00,0x00,0x0C,0x0C,0xFC,0xFC,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x7F, + 0xC0,0x80,0x80,0x80,0xC0,0xE0,0x70,0x38,0x1C,0xFF,0xFF,0xF8,0x00,0x00,0x80,0xC0, + 0xFF,0x9F,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00, + 0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, + 0x00}; // 27*20 +const uint8_t logo_page_pic[] = {0x00,0x00,0x00,0xF0,0xFC,0x0C,0x0C,0x0C,0x98,0xF0,0x00,0x00,0x00,0x00,0x80,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x80,0x80,0x80, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xCF,0x0C,0x0E,0x06,0x03,0x03,0x00,0x18, + 0x2E,0x21,0x21,0x31,0x1E,0x3C,0x20,0x0C,0x1F,0x11,0x10,0x90,0xFF,0x00,0x1C,0x3E, + 0x65,0x65,0x62,0x21,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x03, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //36*20 +const uint8_t logo_version_pic[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xDC,0x9C, + 0xD8,0xC0,0xC0,0xE8,0xFC,0xDC,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x01,0x01,0x00,0x0F,0x1F,0x1F,0x0F,0x0F,0x0F,0x07,0x83,0x80,0x80,0x00,0xC0,0xC0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00, + 0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x83,0x83, + 0xBB,0xBC,0xFC,0xFC,0xFC,0xB8,0x83,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xFF,0xFF,0xC0,0xC0,0xC0,0xFF,0xFF,0xC0,0xC0,0x00,0x00,0xFE,0xFF,0xC3,0xC1, + 0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xFF,0x7F,0x60,0x60,0x60,0x60,0xE0,0xC0,0x00,0x00,0x00, + 0xFF,0xFF,0x0F,0x1C,0x38,0x70,0xE0,0x80,0x00,0x00,0x80,0xE0,0x7C,0x1F,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF, + 0xFF,0xFF,0x00,0xE0,0xFF,0x07,0x00,0x00,0x80,0xC0,0xE1,0x73,0x3F,0x1E,0x3F,0x71, + 0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x00,0x00, + 0x00,0x00,0x00,0x07,0x07,0x03,0x00,0x07,0x07,0x00,0x00,0x07,0x33,0x79,0x78,0x78, + 0x30,0x80,0xC0,0xE0,0xC0,0x03,0x07,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02, + 0x02,0x03,0x03,0x03,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //36*60 版 +//镭射图片对象 +RaderPic logo_rpp_array[LOGO_PAGE_NUM] = +{//{pic,x,y,w,h,rd} //镭射图片的成员参数 + {logo_wouo_pic, 4, 8, 49, 20, RD_RIGHT_DOWN}, + {logo_ui_pic, 53, 8, 27, 20, RD_RIGHT_DOWN}, + {logo_page_pic, 20, 36, 36, 20, RD_RIGHT_DOWN}, + {logo_version_pic, 84, 2, 36, 60, RD_RIGHT_DOWN} +}; + +//设置的列表选项数组 +Option setting_option_array[SETTING_PAGE_NUM] = +{///{ order,max,min,step,int_val,text,} //option的成员顺序 + {.text = "- Setting"}, //第一个做说明标签,没有功能 + {0, 255, 0, 1, 0, "~ Tile Ani"}, + {0, 255, 0, 1, 0, "~ List Ani"}, //对于数值弹窗,需要给定最大最小值和步长 + {.text = "+ T Ufd Fm Scr", .step = 1,}, + {.text = "+ L Ufd Fm Scr", .step = 1,}, + {.text = "+ T Loop Mode", .step = 1,}, + {.text = "+ L Loop Mode", .step = 1,}, + {.text = "+ ValWin Bok", .step = 1,}, + {.text = "+ ConWin Bok", .step = 1,}, + {.text = "$ Dig Ripple", .step = 1,}, + {.text = "+ RaderPicMode", .step = 1,}, //step为1,能够使用clcik控制取反,为0,则失能取反(通常用于需要外部接管这个变量的情况) + {0, 10, 1, 1, 0, "~ RP_S_Rate"}, + {0, 100, 0, 1, 0, "~ RP_M_Rate"}, //因为没有办法给初始化的全局变量使用变量值进行初始化,所以int_val暂时先设为0 +}; + +//curve页面的选项数组 +Option curve_option_array[CURVE_PAGE_NUM] = +{//{ order,max,min,step,int_val,text,} //option的成员顺序 + {.item_max = 50, .item_min = -50, .step = 0, .val = 0, .text = "sin" }, + {.item_max = 50, .item_min = -50, .step = 0, .val = 0, .text = "tri" }, //wave页面的option中text不需要前缀 +}; +int16_t n = 0; //曲线横坐标自增变量 + +//Lock页面参数 +Option lock_option_array[3] = //由于Digital页面有三个数字选项,所以,digital页面选项数组大小必须为3 +{//{ order,max,min,step,int_val,text,} //option的成员顺序 + {.item_max = 99 , .item_min = 0, .step = 1, .val = 0, .text = NULL}, + {.item_max = 99 , .item_min = 0, .step = 1, .val = 0, .text = NULL}, + {.item_max = 99 , .item_min = 0, .step = 1, .val = 0, .text = NULL}, //设置每一个数字的上限值和步长 +} ; +String lock_label_array[LOCK_PAGE_LABEL_NUM] = {"Confirm", "Clear All"}; +// uint8_t lock_password[3] = {56,34, 12}; //3个两位数字组成的密码(注意三个数字从0-2是从右到左)(两种形式的初始化均可) +uint8_t lock_password[3] = {[Digital_Pos_IndexLeft] = 12, [Digital_Pos_IndexMid] = 34, [Digital_Pos_IndexRight] = 56}; //3个两位数字组成的密码(注意三个数字从0-2是从右到左) +uint8_t lcok_page_state = 0; //0表示正常情况,1表示密码正确(Confirm后密码正确),2表示清除所有位(ClearALL) + +//about页面的选项数组 +Option about_option_array[ABOUT_PAGE_NUM] = +{ + {.text = "- About wouo"}, //第一项只是说明 + {.text = "- WouoUI origin"}, //原wououi的说明 + {.text = "- Page version"}, //Page version的说明 +}; + +//about wououi页面的数组 +Option about_wououi_option_array[ABOUT_WOUOUI_PAGE_NUM] = +{ //单选项需要以“=”开头 + {.text = "- From WouoUI1.2"}, + {.text = "- Thanks for the "}, + {.text = " original author"}, + {.text = "- Bilibili UID:"}, + {.text = "= 9182439"}, + {.text = "- Github URL: "}, + {.text = "= https://"}, + {.text = " github.com/"}, + {.text = " RQNG/WouoUI"} +}; +Option about_pageversion_array[ABOUT_PAGEVERSION_NUM] = +{ + {.text = "- Page Version"}, + {.text = "- MyBilili UID:"}, + {.text = "= 679703519"}, + {.text = "- Github URL:"}, + {.text = "= https://"}, + {.text = " github.com/"}, + {.text = " Sheep118/WouoUI"}, + {.text = " -PageVersion"}, +}; +//--------定义每个页面的回调函数 + +void MainPage_CallBack(uint8_t self_page_id,Option* select_item) +{ + switch (select_item->order) + { + case 0: OLED_UIJumpToPage(self_page_id,&logo_page); break; + case 1: OLED_UIJumpToPage(self_page_id,&setting_page); break; + case 2: OLED_UIJumpToPage(self_page_id,&curve_page); break; + case 3: OLED_UIJumpToPage(self_page_id,&lock_page); break; + case 4: OLED_UIJumpToPage(self_page_id,&about_page); break; + default: break; + } +} + +void SettingPage_CallBack(uint8_t self_page_id,Option* select_item) +{ + switch (select_item->order) //对选中项的真实参数值赋值 + { //由于第0项是说明文字“Setting” + case 1: ui_para.ani_param[TILE_ANI] = select_item->val;break;//ani_tile + case 2: ui_para.ani_param[LIST_ANI] = select_item->val;break;//ani_list + case 3: ui_para.ufd_param[TILE_UFD] = select_item->val;break;//ani_tile + case 4: ui_para.ufd_param[LIST_UFD] = select_item->val;break;//ani_list + case 5: ui_para.loop_param[TILE_UFD] = select_item->val;break;//loop_tile + case 6: ui_para.loop_param[LIST_UFD] = select_item->val;break;//loop_list + case 7: ui_para.valwin_broken = select_item->val;break;//ValWin Broken + case 8: ui_para.conwin_broken = select_item->val;break;//ConWin Broken + case 9: ui_para.digital_ripple = select_item->val;break;//Digital Ripple Enable/not + case 10: ui_para.raderpic_scan_mode = select_item->val;break;//RaderPic scan mode + case 11: ui_para.raderpic_scan_rate = select_item->val;break;//RaderPic scan rate + case 12: ui_para.raderpic_move_rate = select_item->val;break;//RaderPic move rate + default: + break; + } +} + +void LockPage_CallBack(uint8_t self_page_id,Option* select_item) +{ + switch (select_item->order) + { + case Digital_Pos_IndexLabel: //选中label项,并单击click的话 + if(strcmp(select_item->text, lock_label_array[0]) == 0) //“confirm” + { + if(lock_option_array[0].val == lock_password[0] && lock_option_array[1].val == lock_password[1] && lock_option_array[2].val == lock_password[2]) + //密码正确的话,转到logopage + OLED_UIChangeCurrentPage(&logo_page); + } + else if(strcmp(select_item->text, lock_label_array[1]) == 0) //“Clear All” + OLED_DigitalPage_UpdateDigitalNumAnimation(&lock_page, 0, 0, 0, Digital_Direct_Increase); + break; + default: + break; + } +} + +void About_CallBack(uint8_t self_page_id,Option* select_item) +{ + switch (select_item->order) + {//第0项是说明文字 + case 1: OLED_UIJumpToPage(self_page_id,&about_wououi_page); break; + case 2: OLED_UIJumpToPage(self_page_id,&about_page_version_page); break; + default: break; + } +} + + +//-------------一些需要用的内部函数 +//生成三角波的函数 +int16_t Triangle_Func(int16_t x) +{ + static int16_t ret = 0; + if(x%20 != 0) ret+= (curve_option_array[1].item_max - curve_option_array[1].item_min)/2/19; + else ret = curve_option_array[1].item_min/2 ; + return ret; +} + +//--------------给主函数调用的接口函数 + +void TestUI_Init(void) +{ + OLED_Init(); //硬件的初始化 + LL_mDelay(100); + OLED_ClearBuff(); //清空缓存 + OLED_RefreshBuff(); //刷新屏幕(清空屏幕) + OLED_SetPointColor(1); //设置绘制颜色 + OLED_UiInit(); //必要的ui参数初始化 + //补充列表页面的初值 + setting_option_array[1].val = ui_para.ani_param[TILE_ANI]; + setting_option_array[2].val = ui_para.ani_param[LIST_ANI]; + setting_option_array[3].val = ui_para.ani_param[TILE_UFD]; + setting_option_array[4].val = ui_para.ani_param[LIST_UFD]; + setting_option_array[5].val = ui_para.ani_param[TILE_LOOP]; + setting_option_array[6].val = ui_para.ani_param[LIST_LOOP]; + setting_option_array[7].val = ui_para.valwin_broken; + setting_option_array[8].val = ui_para.conwin_broken; + setting_option_array[9].val = ui_para.digital_ripple; + setting_option_array[10].val = ui_para.raderpic_scan_mode; + setting_option_array[11].val = ui_para.raderpic_scan_rate; + setting_option_array[12].val = ui_para.raderpic_move_rate; + //设置界面选项 + OLED_TitlePageInit(&main_page, main_page_id, MAIN_PAGE_NUM, mian_option_array, main_icon_array, MainPage_CallBack); + OLED_RaderPicPageInit(&logo_page, logo_page_id, LOGO_PAGE_NUM, logo_rpp_array,Rader_Pic_Mode_Loop, NULL); + OLED_ListPageInit(&setting_page, setting_page_id, SETTING_PAGE_NUM, setting_option_array, SettingPage_CallBack); + OLED_WavePageInit(&curve_page, curve_page_id, CURVE_PAGE_NUM, curve_option_array, NULL); + OLED_DigitalPageInit(&lock_page, lock_page_id, lock_option_array, LOCK_PAGE_LABEL_NUM, lock_label_array, '-', 0, 50, LockPage_CallBack); + OLED_ListPageInit(&about_page, about_page_id, ABOUT_PAGE_NUM, about_option_array, About_CallBack); + OLED_RadioPageInit(&about_wououi_page, about_wououi_page_id, ABOUT_WOUOUI_PAGE_NUM, about_wououi_option_array, NULL); + OLED_RadioPageInit(&about_page_version_page,about_page_version_id, ABOUT_PAGEVERSION_NUM, about_pageversion_array, NULL); +} + + +void TestUI_Proc(void) +{ + OLED_UIProc(); + OLED_UIWaveUpdateVal(&(curve_option_array[0]), sin(0.1*n)*(curve_option_array[0].item_max)*0.75); + OLED_UIWaveUpdateVal(&(curve_option_array[1]), Triangle_Func(n)); + n++; +} + diff --git a/Third-party-design/PageVersion/Csource/example/UITest/TestUI.h b/Third-party-design/PageVersion/Csource/example/UITest/TestUI.h new file mode 100644 index 0000000..74fc637 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/example/UITest/TestUI.h @@ -0,0 +1,12 @@ +#ifndef __TEST_UI_H__ +#define __TEST_UI_H__ + +#include "oled_port.h" +#include "oled_g.h" +#include "oled_ui.h" + + +void TestUI_Init(void); +void TestUI_Proc(void); + +#endif diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/Curves.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/Curves.bmp new file mode 100644 index 0000000..d25a391 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/Curves.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/Page.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/Page.bmp new file mode 100644 index 0000000..00d84dc Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/Page.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/UI.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/UI.bmp new file mode 100644 index 0000000..826cc5a Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/UI.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/Wouo.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/Wouo.bmp new file mode 100644 index 0000000..77c2fa9 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/Wouo.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/f-about.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/f-about.bmp new file mode 100644 index 0000000..8be8b34 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/f-about.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/lock.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/lock.bmp new file mode 100644 index 0000000..00dffa1 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/lock.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/uicn.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/uicn.bmp new file mode 100644 index 0000000..81a56a1 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/uicn.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/version.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/version.bmp new file mode 100644 index 0000000..84cfed5 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/version.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/版.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/版.bmp new file mode 100644 index 0000000..f9edb69 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/版.bmp differ diff --git a/Third-party-design/PageVersion/Csource/example/UITest/icon/设置.bmp b/Third-party-design/PageVersion/Csource/example/UITest/icon/设置.bmp new file mode 100644 index 0000000..3d42066 Binary files /dev/null and b/Third-party-design/PageVersion/Csource/example/UITest/icon/设置.bmp differ diff --git a/Third-party-design/PageVersion/Csource/src/oled_conf.h b/Third-party-design/PageVersion/Csource/src/oled_conf.h new file mode 100644 index 0000000..bb9b094 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/src/oled_conf.h @@ -0,0 +1,14 @@ +#ifndef __OLED_CONF_H__ +#define __OLED_CONF_H__ + +#define UI_CONWIN_ENABLE 1 //是否使能 以"$ " 为开头的选项使用确认弹窗 +#define UI_MAX_PAGE_NUM 32 //页面的最大数量,这个数字需要大于所有页面的page_id +#define UI_INPUT_MSG_QUNEE_SIZE 4 //ui内部消息对列的大小(至少需要是2) + +//页面类型使能宏,使用对应的页面类型,则需要开启该宏,将宏置为1,默认都开启 +#define PAGE_WAVE_ENABLE 1 +#define PAGE_RADIO_ENABLE 1 +#define PAGE_RADERPIC_ENABLE 1 +#define PAGE_DIGITAL_ENABLE 1 + +#endif diff --git a/Third-party-design/PageVersion/Csource/src/oled_g.c b/Third-party-design/PageVersion/Csource/src/oled_g.c new file mode 100644 index 0000000..8c0d1c8 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/src/oled_g.c @@ -0,0 +1,471 @@ +#include "oled_g.h" +#include "string.h" +#include "oledfont.h" +#include "math.h" + +#define OLED_BUFF_SIZE (OLED_HEIGHT/8*OLED_WIDTH) + +uint8_t oled_buff[OLED_HEIGHT/8][OLED_WIDTH] = {0}; //全局buff,对应oled中的GRAM +uint8_t oled_color = '|'; //默认| 表示白色,'&'表示黑色 + +/** +* @brief : void OLED_ClearBuff(void) +* @param : Nonw +* @attention : 清空整个buff +* @author : Sheep +* @date : 23/10/04 +*/ +void OLED_ClearBuff(void) +{ + memset(oled_buff,0,1024); +} + +/** +* @brief : void OLED_SetPointColor(uint8_t color) +* @param : 设置画笔颜色,color:1=亮,0=灭,2=反色 +* @attention : None +* @author : Sheep +* @date : 23/10/04 +*/ +void OLED_SetPointColor(uint8_t color) +{ + switch (color) + { + case 0: oled_color = '&';break; + case 1: oled_color = '|';break; + case 2: oled_color = '^';break; + default:break; + } + // oled_color = (color != 0 )?'|':'&'; +} + + +/** +* @brief : void OLED_RefreshBUff(void) +* @param : 更新整个buff到oledGRAM +* @attention : 返回oled_ok表示成功 +* @author : Sheep +* @date : 23/10/04 +*/ +void OLED_RefreshBuff(void) +{ + OLED_SendBuff(oled_buff); +} + + +/* +函数:void OLED_BuffWriteByte(uint8_t x, uint8_t y , uint8_t val) +参数:x y 写入buff的位置,一整个字节的起始位置 coverORadd 对应的字节与\或还是直接覆盖 +注意'='是直接将输入赋值给buff,'|'是将输入为1的位在buff中置1(写白点),'&'内部会自动取反的,及将输入的val中为1的位在buff中置0(写黑点) +返回值:无 +说明:主要是用于数组写入时防止越界 +作者:Sheep +日期:23/09/27 +*/ +static void OLED_BuffWriteByte(int16_t x, int16_t y ,uint8_t coverORaddORclear, uint8_t val) +{ + if( x > (OLED_WIDTH-1) || y>(OLED_HEIGHT/8-1) || x<0 || y<0) return; + switch (coverORaddORclear) + { + case '|':oled_buff[y][x] |= val;break; + case '&':oled_buff[y][x] &= (~val);break; + case '^':oled_buff[y][x] ^= val;break; + default: + break; + } +} + +/** +* @brief : static void OLED_WinWriteByte(window * win ,int16_t x, int16_t y, uint8_t val) +* @param : win 画图窗口,x相对于画图原点的横坐标,y相对于画图原点的纵坐标,写入的一个字节 +* @attention : OLED_OK/OUT/ERR +* @author : Sheep +* @date : 23/10/03 +*/ +static void OLED_WinWriteByte(window * win ,int16_t x, int16_t y, uint8_t val) +{ + uint8_t n = 0,m = 0,temp1 = 0,temp2 = 0; + if(x > win->w || y > win->h || x < 0 || y <= -7) return ; //超出窗口大小 + if(y+7 > (win->h -1) ) val &= (~(0xFF<<(win->h - y))); //超过窗口的部分不显示 + if(y > -7 && y < 0) + { + val >>=(-1*y); + n = win->start_y/8; + m = win->start_y%8; + } + else + { + n = (win->start_y + y)/8; m = (win->start_y + y)%8; + } + temp1 = val<>(8-m)); + //在全局buff中第几个字节的第几位 ,取出低字节的位,取出高字节的位 + if(m==0) OLED_BuffWriteByte(win->start_x+x,n,oled_color,val); //恰好是整字节 + else if(m != 0) + { + OLED_BuffWriteByte(win->start_x+x,n,oled_color,temp1); + OLED_BuffWriteByte(win->start_x+x,n+1,oled_color,temp2); + } +} + + +/* +函数:void OLED_WinDrawASCII(window *win,int16_t x, int16_t y ,uint8_t size, char c) +参数:[in] win, x,y ,size(12,16,24) c +返回值:目前递增到的x的位置 +说明:绘制单个字符 +作者:Sheep +日期:24/01/30 +*/ +int16_t OLED_WinDrawASCII(window *win,int16_t x, int16_t y ,uint8_t size, char c) +{ + c = c - ' '; //得到偏移值 + switch (size) + { + case 16://16号字8x16 + for(uint8_t i=0;i<8;i++) + { + OLED_WinWriteByte(win,x,y,F8X16[c*2][i]); + OLED_WinWriteByte(win,x,y+8,F8X16[c*2+1][i]); + x++;if(x > win->w)break; //已经超出边框没必要再写了 + } + break; + case 24://24号字12*24 + for(uint8_t i=0;i<12;i++) + { + OLED_WinWriteByte(win,x,y,F12X24[c*3][i]); + OLED_WinWriteByte(win,x,y+8,F12X24[c*3+1][i]); + OLED_WinWriteByte(win,x,y+16,F12X24[c*3+2][i]); + x++;if(x > win->w)break; //已经超出边框没必要再写了 + } + break; + case 8://12号字6*8 + for(uint8_t i=0;i<6;i++) + { + OLED_WinWriteByte(win,x,y,F6x8[c][i]); + x++;if(x > win->w)break; //已经超出边框没必要再写了 + } + break; + default: + break; + } + return x; +} + + +/** +* @brief : void OLED_WinDrawStr(window *win,int16_t x, int16_t y ,uint8_t size, uint8_t* str) +* @param : win指定窗口,x,y相对于窗口的恒重坐标,str 字符串 +* @attention : None +* @author : Sheep +* @date : 23/10/03 +*/ +void OLED_WinDrawStr(window *win,int16_t x, int16_t y ,uint8_t size, uint8_t* str) +{ + int16_t cur_x = x; //由于绘制时x的递增在drawAscii中完成,所以利用返回值将X位置返回出来,下次传入 + while(*str != '\0') + { + cur_x = OLED_WinDrawASCII(win, cur_x, y, size, *str); + str++; + if(x > win->w) break; //已经到边了没必要再写了 + } +} + + + +/** +* @brief : void OLED_WinDrawVLine(window *win,int16_t x, int16_t y_start, int16_t y_end) +* @param : 往指定窗口中画线,注意,y_end 必须大于y_start +* @attention : None +* @author : Sheep +* @date : 23/10/03 +*/ +void OLED_WinDrawVLine(window *win,int16_t x, int16_t y_start, int16_t y_end) +{ + uint8_t n = 0, m = 0; + if(y_start < 0 && y_end < 0)return; + if(y_start < 0) y_start = 0; + if(y_end > win->h )y_end = win->h; + if(x > win->w || x < 0)return ; + if((y_end - y_start) < 7) OLED_WinWriteByte(win,x,y_start, ~(0xFF<<(y_end - y_start))); + else + { + uint8_t i = 0; + n = (y_end - y_start)/8; + m = (y_end - y_start)%8; + for(i = 0; i < n; i++)OLED_WinWriteByte(win,x,y_start+i*8,0xFF); + OLED_WinWriteByte(win,x,y_start+i*8,~(0xFF< x_start +* @attention : 错误代码 +* @author : Sheep +* @date : 23/10/04 +*/ +void OLED_WinDrawHLine(window * win, int16_t x_start, int16_t x_end, int16_t y) +{ + if(x_start < 0) x_start = 0; + if(x_end > win->w ) x_start = win->w; + if(y > win->h || y < 0)return ; + for(uint8_t i = 0; i < (x_end - x_start); i++) + OLED_WinWriteByte(win,x_start+i,y,0x01); +} + + +/** +* @brief : void OLED_WinDrawRBox(window *win, int16_t x_start, int16_t y_start, int16_t width, int16_t height, uint8_t r) +* @param : r 倒角像素的大小 +* @attention : 绘制倒角矩形,注意倒角不能大于宽或高的1/2 +* @author : Sheep +* @date : 23/10/04 +*/ +void OLED_WinDrawRBox(window *win, int16_t x_start, int16_t y_start, int16_t width, int16_t height, uint8_t r) +{ + uint8_t cir_r = r; // + if((2*r > width) || (2*r > height))return; + for(uint8_t i = 0; i < width; i++) + { + OLED_WinDrawVLine(win,x_start+i,y_start+r,y_start+height-r); + if(i < cir_r)r--; + if(i >= (width - cir_r-1))r++; + } +} + +/** +* @brief : void OLED_WinDrawRBoxEmpty(window *win, int16_t x_start, int16_t y_start, int16_t width, int16_t height, uint8_t r) +* @param : 在窗口内绘制空心的倒角矩形,r 倒角像素的大小 +* @attention : 绘制倒角矩形,注意倒角不能大于宽或高的1/2 +* @author : Sheep +* @date : 23/10/04 +*/ +void OLED_WinDrawRBoxEmpty(window *win, int16_t x_start, int16_t y_start, int16_t width, int16_t height, uint8_t r) +{ + uint8_t cir_r = r; //默认倒角为2 + if((2*r > width) || (2*r > height))return; + for(uint8_t i = 0; i < height ; i++) + { + if(i == 0 || i == (height-1))OLED_WinDrawHLine(win,x_start+r,x_start+width-r+1,y_start+i); + else + { + OLED_WinWriteByte(win,x_start+r,y_start+i,0x01); + OLED_WinWriteByte(win,x_start+width-r,y_start+i,0x01); + } + if(i < cir_r)r--; + if(i>= (height -cir_r -1) )r++; + } +} + +/** +* @brief : void OLED_WinDrawBMP(window * win, int16_t x, int16_t y, int16_t width, int16_t height,const uint8_t * BMP, uint8_t color) +* @param : heigh must be a total times of 8, the color is convenient for draw inverse-color BMP +* @attention : None +* @author : Sheep +* @date : 23/10/06 +*/ +void OLED_WinDrawBMP(window * win, int16_t x, int16_t y, int16_t width, int16_t height,const uint8_t * BMP, uint8_t color) +{ + if(BMP == NULL) return; //如果是NULL,直接返回 + uint8_t n = height/8, m = height%8; + for(uint8_t i = 0; i < n; i++) + { + for(uint8_t j = 0; j < width; j++) + { + if(x+j > win->w)break; + if(y+i*8 > win->h)return; + if(color == 1) OLED_WinWriteByte(win,x+j,y+i*8,(BMP[i*width+j])); + else OLED_WinWriteByte(win,x+j,y+i*8,~(BMP[i*width+j])); + } + } + if(m!=0) + { + for(uint8_t j = 0; j < width; j++) + { + if(x+j > win->w)return; + if(color == 1) OLED_WinWriteByte(win,x+j,y+n*8,(BMP[n*width+j] & (~(0xFF<0)?p:(-p); //求斜率的绝对值,后面作误差变量使用 + if(p < 1) //p>0 && p<1 + { + if(x2 > x1){x_small = x1; x_big = x2; } + else{x_small = x2; x_big = x1; temp = y1; y1 = y2; y2 = temp;} //默认与 xsmall对应的y是y1 + dx = x_big - x_small; + dy = ((y1 - y2)>0)?(y1-y2):(y2-y1); + p = (dy<<1) - dx; + while (x_small <= x_big) + { + OLED_WinWriteByte(win, x_small, y1, 0x01); + if(p > 0) + { + if(y1 < y2)y1++; + else y1--; + p = p+(dy<<1)-(dx<<1); + } + else {p = p+(dy<<1);} + x_small++; + } + } + else //p>=1 + { + if(y2 > y1){y_small = y1; y_big = y2;} + else {y_small = y2; y_big = y1; temp = x1; x1 = x2; x2 = temp;} //默认与y_small对应的是x1; + dx = (x1>x2)?(x1-x2):(x2-x1); + dy = y_big - y_small; + p = (dx<<1) - dy; + while (y_small <= y_big) + { + OLED_WinWriteByte(win, x1, y_small, 0x01); + if(p > 0) + { + if(x1 < x2)x1++; + else x1--; + p = p+(dx<<1)-(dy<<1); + } + else {p = p+(dx<<1);} + y_small++; + } + } +} + +/** +* @brief : uint8_t OLED_WinDrawRaderPic(window * win,const uint8_t* pic,int16_t start_x, uint16_t start_y, uint8_t width, uint8_t height, RaderDirection direct, uint8_t enable_all_point_scan) +* @param : [in] win 显示的窗口对象 +* @param : [in] pic 显示的图片对象 +* @param : [in] start_x,start_y,width,height,图片的左上角(x,y) 和宽高 +* @param : [in] direct 射线方向,枚举类型RaderDirection +* @param : [in] enable_all_point_scan true/Fasle,Fasle的话,只有图片亮的点才会生成射线扫描 +* @param : [in] scan_rate 扫描的速度,值越大越快 +* @return : 若整体图像绘制完成时,返回1,否则返回0 +* @attention : None +* @author : Sheep +* @date : 23/11/15 +*/ +uint8_t OLED_WinDrawRaderPic(window * win,const uint8_t* pic,int16_t start_x, uint16_t start_y, uint8_t width, uint8_t height, RaderDirection direct, uint8_t enable_all_point_scan, uint8_t scan_rate) +{ + static uint16_t now_end_point = 1; //静态计数变量(允许在描文字的过程中被打断) + uint8_t mask = 1, horizon_line_flag = 0, ret = 0; + int16_t x = 0, y = 0; + uint16_t i = 0,array_index = 0; + if(pic == NULL) return 0; //如果图像为null,直接返回0,表示未完成 + //绘制前面绘制好的图形 + for(i = 0; i < now_end_point; i++) + { + if((i % width == 0) && (i!=0)) + if(mask == 0x80){mask = 1;} + else {mask <<= 1;array_index-=width;} + if(pic[array_index]&mask) + OLED_WinDrawPoint(win,start_x + i%width, start_y + i/width); + array_index++; + } + //绘制镭射那根线 + if((pic[array_index]&mask) || enable_all_point_scan) + { + switch (direct) //确定端点 + { + case RD_LEFT_UP: x = win->start_x; y = win->start_y; break; + case RD_LEFT_DOWN: x = win->start_x; y = win->start_y+win->h-1; break; + case RD_RIGHT_UP: x = win->start_x + win->w-1; y = win->start_y; break; + case RD_RIGHT_DOWN: x = win->start_x+win->w-1; y = win->start_y+win->h-1; break; + case RD_LEFT: horizon_line_flag = 1;x = win->start_x;break; + case RD_RIGHT: horizon_line_flag = 1;x = win->start_x+win->w;break; + default: + break; + } + if(horizon_line_flag) + if(start_x + i%width < x)OLED_WinDrawHLine(win,start_x + i%width,x,start_y + i/width); + else OLED_WinDrawHLine(win,x , start_x + i%width,start_y + i/width); + else + if(i%width != x){OLED_WinDrawLine(win,start_x + i%width,start_y + i/width,x,y);} + else + if(start_y + i/width < y )OLED_WinDrawVLine(win,x,start_y + i/width,y); + else OLED_WinDrawVLine(win,x,y,start_y+i/width); + } + //终点自增 + if(now_end_point < (width*height-1)){now_end_point+=scan_rate;ret = 0;} + else {now_end_point = 1;ret= 1;} //图像绘制结束 + return ret; +} + diff --git a/Third-party-design/PageVersion/Csource/src/oled_g.h b/Third-party-design/PageVersion/Csource/src/oled_g.h new file mode 100644 index 0000000..47d4e43 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/src/oled_g.h @@ -0,0 +1,48 @@ +#ifndef __OLED_G_H__ +#define __OLED_G_H__ + + +#include "oled_port.h" + +#define OLED_WIDTH 128 +#define OLED_HEIGHT 64 + +typedef struct +{ + int16_t start_x; + int16_t start_y; + int16_t w; + int16_t h; +} window; + + +typedef enum +{ + RD_LEFT_UP = 0x00, //射线从左上角出发 + RD_LEFT_DOWN, //射线从左下角出发 + RD_RIGHT_UP, //射线从右上角出发 + RD_RIGHT_DOWN, //射线从右下角出发 + RD_RIGHT, //射线从水平向右 + RD_LEFT, //射线从水平向左 +} RaderDirection; + + +void OLED_ClearBuff(void); +void OLED_SetPointColor(uint8_t color); +void OLED_RefreshBuff(void); + + +int16_t OLED_WinDrawASCII(window *win,int16_t x, int16_t y ,uint8_t size, char c); +void OLED_WinDrawStr(window *win,int16_t x, int16_t y ,uint8_t size, uint8_t* str); +void OLED_WinDrawVLine(window *win,int16_t x, int16_t y_start, int16_t y_end); +void OLED_WinDrawHLine(window * win, int16_t x_start, int16_t x_end, int16_t y); +void OLED_WinDrawRBox(window *win, int16_t x_start, int16_t y_start, int16_t width, int16_t height, uint8_t r); +void OLED_WinDrawRBoxEmpty(window *win, int16_t x_start, int16_t y_start, int16_t width, int16_t height, uint8_t r); +void OLED_WinDrawBMP(window * win, int16_t x, int16_t y, int16_t width, int16_t height,const uint8_t * BMP, uint8_t color); +void OLED_WinDrawPoint(window * win, int16_t x, int16_t y); +void OLED_WinDrawLine(window* win,int16_t x1, int16_t y1, int16_t x2, int16_t y2); +uint8_t OLED_GetStrWidth(const char * str, uint8_t size); +void OLED_Animation(float *a, float *a_trg, float n); +void OLED_AllSrcFade(uint8_t Odd0OrEven1,uint8_t byte); +uint8_t OLED_WinDrawRaderPic(window * win,const uint8_t* pic,int16_t start_x, uint16_t start_y, uint8_t width, uint8_t height, RaderDirection direct, uint8_t enable_all_point_scan, uint8_t scan_rate); +#endif diff --git a/Third-party-design/PageVersion/Csource/src/oled_port.h b/Third-party-design/PageVersion/Csource/src/oled_port.h new file mode 100644 index 0000000..0ca8546 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/src/oled_port.h @@ -0,0 +1,14 @@ +#ifndef __OLED_PORT_H__ +#define __OLED_PORT_H__ + +#include "stdio.h" +#include "stdint.h" + +#define OLED_LOG (void) + +//对应要实现的接口函数 +void OLED_Init(void); //初始化驱动 +void OLED_SendBuff(uint8_t buff[8][128]); //将8*128字节的buff一次性全部发送的函数 + +#endif + diff --git a/Third-party-design/PageVersion/Csource/src/oled_ui.c b/Third-party-design/PageVersion/Csource/src/oled_ui.c new file mode 100644 index 0000000..a3d2d7e --- /dev/null +++ b/Third-party-design/PageVersion/Csource/src/oled_ui.c @@ -0,0 +1,1578 @@ +#include "oled_ui.h" +#include "string.h" +#include "stdio.h" +//===============================类型声明(和一次性变量定义)=================================== + +typedef struct +{ + uint8_t state:2; //弹窗的状态 不再弹窗内0,参数初始化1,弹窗动画轮询2 + uint8_t l; // = (DISP_W - WIN_W) / 2; + uint8_t u; // = (DISP_H - WIN_H) / 2; + float bar; //进度条长度值(按键位置x值)btn_x + float bar_trg; //进度条目标值(按键位置x值目标)btn_x_trg + float y; //弹窗y值 + float y_trg; //弹窗y植目标值 + PageAniInit anim_init; //动画初始化方法 + void (*show)(Option * select_item); //展示方法(函数指针,参数为选中项) + void (*react)(PageAddr bg,Option * select_item); //响应方法(函数指针,参数为背景页面和选中项) +} Win; //数值(确认)弹窗类型 +//有一个全局数值弹窗变量vwin在ui结构体中,用于每次弹窗使用(对于数值弹窗来说,不论是上下、还是确认,都会调用一次回调,方便数值实时更新) +//有一个全局确认弹窗变量cwin在ui结构体中,用于每次确认弹窗使用(对于确认弹窗来说,只有按下确认键,才会触发回调,确认的意义所在) + +#if PAGE_WAVE_ENABLE +struct +{ + int16_t data_que[WAVE_W-1]; //用于记录波形全程队列 + uint8_t p_head; //队列头部指针,表征队列最起始的位置 + uint8_t p_rear; //出队列指针 + uint8_t p_font; //入队列指针 + uint8_t change_flag; // 切换过的标志 + float text_bg_r; + float text_bg_r_trg; +} wave_tag; //波形曲线标签全局变量,用于记录波形页面中标签的移动 +#endif + +#if PAGE_RADIO_ENABLE +uint8_t radio_click_flag = False; //标志位,用于标记在单选项页面内是否单击了Click +#endif + +#if PAGE_DIGITAL_ENABLE +//6个单位数字的横坐标存储数组 +uint8_t digital_num_xindex[DIGITAL_NUM_INDEX_MAX] = {12+24+12+24+12, 12+24+12+24, 12+24+12, 12+24, 12, 0}; +// uint8_t digital_num_pos = 0; //0表示没有选中位置,1-7bit每一位置1表示该位被选中 +// uint8_t temp_ripple_index = 0; //用于在ripple时记录选中位置(选中最低位位置开始,慢慢往上增) +static uint8_t Gap_shine_time = 0 ; //全局闪烁时间递减变量 +static uint8_t Uline_shine_time = 0 ; //全局闪烁时间递减变量 +typedef struct +{ + uint8_t num:4; //只有单个位的数据,用于存储单个位的数据 +} SingleBit; +SingleBit num_array[6]; //显示的6个单个位数据 +uint8_t last_or_next_label_index = 0; //用来记录上次显示的label的index +#endif + + +//===================================全局变量================================== +UiPara ui_para; //全局UI参数集合变量,这个UI的相关参数都在这个集合中定义 +struct +{ + uint8_t init_finish_flag ; //页面是否正在初始化完成的标志位,即是否完成过度页面的初始化 + uint8_t current_page_id ; //当前页面id + UIState state ; //ui状态变量 + UiPara* upara; //ui参数集合 + Win vwin; //数值弹窗插件 +#if UI_CONWIN_ENABLE + Win cwin; //确认弹窗插件 +#endif +} ui; //整个ui对象 + +PageAddr page_array[UI_MAX_PAGE_NUM] = {NULL}; //页面地址的数组,方便记录不同页面用于切换 + +window w_all = {0,0,OLED_WIDTH,OLED_HEIGHT}; //全局窗口变量,所有的绘制都在这个窗口内进行 + +InputMsg msg_queue[INPUT_MSG_QUNEE_SIZE] = {msg_none}; +uint8_t msg_que_font = 0, msg_que_rear = 0; //消息队列的头尾指针 + + +//===================================对应函数================================== + +//--------通用页面函数 +#define UNUSED_PARAMETER(x) ((void)x) //对未使用参数的处理,防止警告 +//通用的页面返回上一个页面函数 +static void OLED_PageReturn(PageAddr page_addr) +{ + Page* p = (Page*)page_addr; + ui.current_page_id = p->last_page_id; + ui.state = ui_layer_in; //将状态机置为页面初始化状态 + ui.init_finish_flag = False; //启用过度页面动画 +} + +//最基本的页面成员初始化,并加入到页面队列中,注意,没有进行页面类型初始化,因为这个由各自初始化函数执行 +static void OLED_PageInit(PageAddr page_addr, uint8_t page_id, CallBackFunc call_back) +{ + Page* p = (Page*)page_addr; + p->page_id = page_id; + p->last_page_id = 0; //没有确认上一个id时,默认返回page_id为0的页面,即默认把0页面当作主(home)页面 + p->cb = call_back; + page_array[p->page_id] = page_addr; //加入页面数组 +} + +/** + * @brief OLED_WinFSM函数用于处理窗口的状态机 + * + * @param w 指向窗口结构体的指针 + * @param bg 页面地址 + * @param select_item 指向选项结构体的指针 + */ +static void OLED_WinFSM(Win * w, PageAddr bg, Option * select_item) +{ + switch (w->state) + { + case 1: w->anim_init(bg); w->state = 2; break; // 初始化只用在弹窗最开始时做—次弹窗参数初始化 + case 2: w->show(select_item); w->react(bg, select_item); break; // 弹窗动画和交互 + default: break; + } +} +//检查页面类型,返回PageType类型 +#define OLED_CheckPageType(page_addr) (((Page*)page_addr)->page_type) +/** + * @brief 将无符号32位整数转换为字符串 + * + * @param num 要转换的无符号32位整数 + * @return char* 转换后的字符串 + */ +char * itoa(uint32_t num) +{ + static char str[10] = {0}; // 定义一个静态字符数组,用于存储转换后的字符串 + memset(str, 0, sizeof(str)); // 将字符数组清零 + sprintf(str, "%d", num); // 将无符号32位整数转换为字符串 + return str; // 返回转换后的字符串 +} +/** + * @brief 将浮点数转换为字符串 + * + * @param num 要转换的浮点数 + * @return char* 转换后的字符串 + */ +char * ftoa(float num) +{ + static char str[10] = {0}; // 定义一个静态字符数组,用于存储转换后的字符串 + memset(str, 0, sizeof(str)); // 将字符数组清零 + sprintf(str, "%.2f", num); // 将浮点数转换为字符串,并保留两位小数 + return str; // 返回转换后的字符串 +} + + +//--------msg_que处理相关函数 +#define OLED_MsgQueIsEmpty (msg_que_font == msg_que_rear) //队列空 +#define OLED_MsgQueIsFull ((msg_que_rear + 1)%INPUT_MSG_QUNEE_SIZE == msg_que_font) //队列满 +//向msg队列发送消息和读msg队列函数,参数和返回值均是InputMsg类型 +void OLED_MsgQueSend(InputMsg msg) +{ + if(!OLED_MsgQueIsFull) + { + msg_queue[msg_que_rear] = msg; + msg_que_rear++; + if(msg_que_rear == INPUT_MSG_QUNEE_SIZE )msg_que_rear = 0; + } +} +InputMsg OLED_MsgQueRead(void) +{ + InputMsg msg = msg_none; + if(!OLED_MsgQueIsEmpty) + { + msg = msg_queue[msg_que_font]; + msg_que_font++; + if(msg_que_font == INPUT_MSG_QUNEE_SIZE)msg_que_font = 0; + } + return msg; +} + + +//**********************每个以Page为基类的类都有对应的AnimInit、show、React方法 +//--------Title页面相关函数 + +static void OLED_TitlePageAnimInit(PageAddr page_addr) +{ + TitlePage * title_page = (TitlePage *)page_addr; + title_page->icon_x = 0; + title_page->icon_x_trg = TILE_ICON_S; + title_page->icon_y = -TILE_ICON_H; + title_page->icon_y_trg = 0; + title_page->indi_x = 0; + title_page->indi_x_trg = TILE_INDI_W; + title_page->title_y = TILE_INDI_S + (TILE_INDI_H - TILE_B_TITLE_H) / 2 + TILE_B_TITLE_H; + title_page->title_y_trg = TILE_INDI_S + (TILE_INDI_H - TILE_B_TITLE_H) / 2; +} + +static void OLED_TitlePageShow(PageAddr page_addr) +{ + TitlePage * tp = (TitlePage *)page_addr; + float temp = 0; //用于存放临时的icon的x坐标 + //计算动画参数 + OLED_Animation(&tp->icon_x,&tp->icon_x_trg,ui.upara->ani_param[TILE_ANI]); + OLED_Animation(&tp->icon_y,&tp->icon_y_trg,ui.upara->ani_param[TILE_ANI]); + OLED_Animation(&tp->indi_x,&tp->indi_x_trg,ui.upara->ani_param[TILE_ANI]); + OLED_Animation(&tp->title_y,&tp->title_y_trg,ui.upara->ani_param[TILE_ANI]); + String show_str = tp->option_array[tp->select_item].text; + //绘制title + OLED_WinDrawStr(&w_all, ((OLED_WIDTH - TILE_INDI_W) - OLED_GetStrWidth(&(show_str[2]),TILE_B_TITLE_H)) / 2 + TILE_INDI_W, + tp->title_y,TILE_B_TITLE_H,(uint8_t*)&(show_str[2])); + //绘制title指示器 + OLED_WinDrawRBox(&w_all,0,TILE_ICON_S,tp->indi_x,TILE_INDI_H,0); + //绘制图标 + if(!ui.init_finish_flag) //过度动画尚未完成 + { + for (uint8_t i = 0; i < tp->item_num; i++) + { + if(ui.upara->ufd_param[TILE_UFD]) + temp = (OLED_WIDTH - TILE_ICON_W) / 2 + i * tp->icon_x - TILE_ICON_S * tp->select_item; + //从第一个选项开始展开,最终保持选中在中间 + else + temp = (OLED_WIDTH - TILE_ICON_W) / 2 + (i - tp->select_item) * tp->icon_x; + //保证选中的选项在中间,向两侧展开 + OLED_WinDrawBMP(&w_all,(int16_t)temp,(int16_t)(tp->icon_y),TILE_ICON_W,TILE_ICON_H,tp->icon_array[i],1); + } + if(tp->icon_x == tp->icon_x_trg) + { + ui.init_finish_flag = True; //设置过度动画已经结束 + tp->icon_x = tp->icon_x_trg = -1*tp->select_item * TILE_ICON_S; + } + } + else + for(uint8_t i = 0; i < tp->item_num; i++) //过度动画完成后一般选择时的切换动画 + OLED_WinDrawBMP(&w_all,(OLED_WIDTH - TILE_ICON_W)/2 + (int16_t)(tp->icon_x) + i*TILE_ICON_S, + 0,TILE_ICON_W,TILE_ICON_H,tp->icon_array[i],1); +} + + +static void OLED_TitlePageReact(PageAddr page_addr) +{ + TitlePage * tp = (TitlePage *)page_addr; + String selcet_string = NULL; + InputMsg msg = OLED_MsgQueRead(); //空时读出msg_none + switch (msg) + { + case msg_up: + if(ui.init_finish_flag) //已经完成过渡动画了 + { + if(tp->select_item > 0) + { + //第一个icon与中心的距离减小S + tp->select_item --; + tp->icon_x_trg += TILE_ICON_S; + //切换动画动作,动indi 和title + tp->indi_x = 0; + tp->title_y = TILE_INDI_S + (TILE_INDI_H - TILE_B_TITLE_H) / 2 + TILE_B_TITLE_H; + } + else + { + if(ui.upara->loop_param[TILE_LOOP]) //开启循环的话 + { + tp->select_item = tp->item_num -1; + tp->icon_x_trg = -1*TILE_ICON_S*(tp->item_num -1); + //切换动画动作,动indi 和title + tp->indi_x = 0; + tp->title_y = TILE_INDI_S + (TILE_INDI_H - TILE_B_TITLE_H) / 2 + TILE_B_TITLE_H; + } + } + } + break; + case msg_down: + if(ui.init_finish_flag) + { + if(tp->select_item < (tp->item_num - 1)) + { + tp->select_item ++; + tp->icon_x_trg -= TILE_ICON_S; + //切换动画动作,动indi 和title + tp->indi_x = 0; + tp->title_y = TILE_INDI_S + (TILE_INDI_H - TILE_B_TITLE_H) / 2 + TILE_B_TITLE_H; + } + else + { + if(ui.upara->loop_param[TILE_LOOP]) + { + tp->select_item = 0; + tp->icon_x_trg = 0; + //切换动画动作,动indi 和title + tp->indi_x = 0; + tp->title_y = TILE_INDI_S + (TILE_INDI_H - TILE_B_TITLE_H) / 2 + TILE_B_TITLE_H; + } + } + } + break; + case msg_return: OLED_PageReturn(page_addr);break; + case msg_home : break; + case msg_click: + selcet_string = tp->option_array[tp->select_item].text; + if(selcet_string[0] == '~') + {//数值弹窗的话,进入数值弹窗这个动作不触发回调,但弹窗内不论点击什么都会实时触发回调 + //当数值弹窗step设为0为只读是,进入数值弹窗前会调用一次回调,以便外界更改val值 + ui.vwin.state = 1; //进入弹窗初始化 + if((tp->option_array[tp->select_item].step == 0) && (tp->page.cb != NULL)) + tp->page.cb(tp->page.page_id, &(tp->option_array[tp->select_item])); + } +#if UI_CONWIN_ENABLE + else if(selcet_string[0] == '$') ui.cwin.state = 1; //进入确认弹窗初始化 + //确认弹窗内只有确认弹窗内的click才会触发回调 +#endif + else if(tp->page.cb !=NULL)tp->page.cb(tp->page.page_id,&(tp->option_array[tp->select_item])); + //当前页面id和确认选中项的指针传入 + break; + default: + break; + } +} + +void OLED_TitlePageInit( + TitlePage * title_page, //磁贴页面对象 + uint8_t page_id, //为该页面分配一个唯一的id + uint8_t item_num, //选项个数,需与title数组大小,icon数组大小一致 + Option *option_array, //整个页面的选项数组(数组大小需与item_num一致) + Icon *icon_array, //整个页面的icon数组(数组大小需与item_num一致) + CallBackFunc call_back) //回调函数,参数为确认选中项index(1-256)0表示未确认哪个选项 +{ + //缺少选项个数检查,Icon个数检查, + title_page->page.page_type = type_title; + OLED_PageInit((PageAddr)title_page, page_id, call_back); + title_page->page.ani_init = OLED_TitlePageAnimInit; + title_page->page.show = OLED_TitlePageShow; + title_page->page.react = OLED_TitlePageReact; //关联处理函数(方法) + title_page->select_item = 0; + title_page->item_num = item_num; + title_page->option_array = option_array; + title_page->icon_array = icon_array; + for (uint8_t i = 0; i < title_page->item_num; i++) + title_page->option_array[i].order = i;//选项序号标号 +} + + + + +//------------数值弹窗相关函数 + +static void OLED_ValWinAnimInit(PageAddr bg) +{ + UNUSED_PARAMETER(bg); + ui.vwin.bar = 0; + ui.vwin.y = WIN_Y; + ui.vwin.y_trg = ui.vwin.u; +} + +static void OLED_ValWinShow(Option* win) +{ + if(ui.upara->valwin_broken) //如果要背景虚化的话 + { + OLED_SetPointColor(0); + OLED_AllSrcFade(0,0x55); + OLED_AllSrcFade(1,0xAA); + OLED_SetPointColor(1); + } + ui.vwin.bar_trg = (float)(win->val - win->item_min)/(float)(win->item_max - win->item_min)*(WIN_BAR_W - 4); + + OLED_Animation(&ui.vwin.bar, &ui.vwin.bar_trg,ui.upara->ani_param[WIN_ANI]); + OLED_Animation(&ui.vwin.y, &ui.vwin.y_trg,ui.upara->ani_param[WIN_ANI]); + + OLED_SetPointColor(0); + OLED_WinDrawRBox(&w_all, ui.vwin.l, (int16_t)ui.vwin.y, WIN_W, WIN_H, 2); //弹窗背景黑边 + OLED_SetPointColor(1); + OLED_WinDrawRBoxEmpty(&w_all, ui.vwin.l, (int16_t)ui.vwin.y, WIN_W, WIN_H, 2); //弹窗外框 + OLED_WinDrawRBoxEmpty(&w_all, ui.vwin.l + 5, (int16_t)ui.vwin.y + 20,WIN_BAR_W, WIN_BAR_H, 1); //进度条外框 + OLED_WinDrawRBox(&w_all, ui.vwin.l+7, (int16_t)ui.vwin.y+22, ui.vwin.bar, WIN_BAR_H - 4,1); //绘制进度条 + OLED_WinDrawStr(&w_all, ui.vwin.l + 5,(int16_t)ui.vwin.y+2, WIN_FNOT_H, (uint8_t*)&(win->text[2])); //提示文本跳过“~ ” + OLED_WinDrawStr(&w_all, ui.vwin.l + 6 + OLED_GetStrWidth((char*)&(win->text[2]),WIN_FNOT_H), + (int16_t)ui.vwin.y+2,WIN_FNOT_H, (uint8_t*)(itoa(win->val))); //数值 +} + +static void OLED_ValWinReact(PageAddr bg, Option* select_win) +{ + if(ui.vwin.y == ui.vwin.y_trg && ui.vwin.y != WIN_Y_TRG) //弹窗进场动画结束时 + { + InputMsg msg = OLED_MsgQueRead(); + switch (msg) + { + case msg_up: + if(select_win->val < select_win->item_max) + select_win->val += select_win->step; + break; + case msg_down: + if(select_win->val > select_win->item_min) + select_win->val -= select_win->step; + break; + case msg_click: //点击确认也会退出弹窗,不过,点击确认是会触发一次回调,点击返回则不会 + case msg_return: + ui.vwin.y_trg = WIN_Y_TRG; //弹窗退场 + ui.vwin.state = 0; //状态标志,退出弹窗 + break; + default:break; + } + if (msg != msg_none && msg != msg_return) //只有弹窗内有动作,就会实时触发回调 + { + Page * p = (Page*)bg; + if(p->cb != NULL)p->cb(p->page_id, select_win); + } + } +} + +//----------确认弹窗相关函数 +#if UI_CONWIN_ENABLE + +static void OLED_ConWinAnimInit(PageAddr bg) +{ + UNUSED_PARAMETER(bg); + ui.cwin.y = CON_WIN_Y; + ui.cwin.y_trg = ui.cwin.u; + ui.cwin.bar = ui.cwin.l; +} + +static void OLED_ConWinShow(Option* win) +{ + if(ui.upara->conwin_broken) //如果要背景虚化的话 + { + OLED_SetPointColor(0); + OLED_AllSrcFade(0,0x55); + OLED_AllSrcFade(1,0xAA); + OLED_SetPointColor(1); + } + //对应的动画 + OLED_Animation(&ui.cwin.y, &ui.cwin.y_trg,ui.upara->ani_param[WIN_ANI]); + // OLED_Animation(&ui.cwin.bar, &ui.cwin.bar_trg,ui.upara->ani_param[WIN_ANI]); //ConWin的选项不用横向移动 + + OLED_SetPointColor(0);//绘制外围黑框 + OLED_WinDrawRBox(&w_all, ui.cwin.l, (int16_t)ui.cwin.y, CON_WIN_W, CON_WIN_H, CON_WIN_R); //弹窗背景黑边 + OLED_SetPointColor(1); + //绘制外框 + OLED_WinDrawRBoxEmpty(&w_all, ui.cwin.l, (int16_t)ui.cwin.y, CON_WIN_W,CON_WIN_H,CON_WIN_R); + OLED_WinDrawStr(&w_all, (OLED_WIDTH - OLED_GetStrWidth((const char*)&(win->text[2]),CON_WIN_FONT_H) )>>1, (int16_t)ui.cwin.y, + CON_WIN_FONT_H,(uint8_t*)&(win->text[2]));// 《/2》 + OLED_WinDrawStr(&w_all, ui.cwin.l+15, (int16_t)ui.cwin.y+20,CON_WIN_FONT_H,(uint8_t*)"Yes"); + OLED_WinDrawStr(&w_all, OLED_WIDTH-ui.cwin.l-30, (int16_t)ui.cwin.y+20,CON_WIN_FONT_H,(uint8_t*)"No"); + OLED_WinDrawRBoxEmpty(&w_all, ui.cwin.l, (int16_t)ui.cwin.y+18, CON_WIN_W/2,CON_WIN_BTN_H,CON_WIN_R); //绘制选项框《/2》 + OLED_WinDrawRBoxEmpty(&w_all, ui.cwin.l+CON_WIN_W/2, (int16_t)ui.cwin.y+18, CON_WIN_W/2,CON_WIN_BTN_H,CON_WIN_R); //《/2》 + OLED_SetPointColor(2); //反色绘制 + if(win->val == True) //选中的话 + OLED_WinDrawRBox(&w_all, ui.cwin.bar, (int16_t)ui.cwin.y+18, CON_WIN_W/2, CON_WIN_BTN_H, CON_WIN_R);//绘制选中背景 《/2》 + else + OLED_WinDrawRBox(&w_all, ui.cwin.bar+CON_WIN_W/2, (int16_t)ui.cwin.y+18, CON_WIN_W/2, CON_WIN_BTN_H, CON_WIN_R); //《/2》 + OLED_SetPointColor(1);//改回实色绘制 +} + +static void OLED_ConWinReact(PageAddr bg,Option* win) +{ + if(ui.cwin.y == ui.cwin.y_trg && ui.cwin.y != CON_WIN_Y_TRG) //弹窗进场动画结束 + { + InputMsg msg = OLED_MsgQueRead(); + Page* p = (Page*)bg; + switch (msg) + { + case msg_up: + case msg_down: //上下键在确认弹窗时用于切换 + win->val = !(win->val); + ui.cwin.bar_trg = ui.cwin.l; //触发选项移动动画 + break; + case msg_click: //对于确认弹窗来说,只有按下确认键,才会触发回调 + if((p->cb) != NULL)p->cb(p->page_id, win); + //这儿不用break;因为确认结束,直接退出弹窗 + case msg_return: + ui.cwin.y_trg = CON_WIN_Y_TRG; //弹窗退场 + ui.cwin.state = 0; //标志退出弹窗状态 + break; + default: + break; + } + } +} + +#endif + +//-------List页面相关函数 + +//绘制列表项文字和对应的行末数字或选框 +static void OLED_ListDrawText_CheckBox(float start_y ,Option* item) +{ + //绘制文字 + OLED_WinDrawStr(&w_all,LIST_TEXT_S,start_y + LIST_TEXT_S,LIST_TEXT_H,(uint8_t *)(item->text)); + //绘制表尾 + switch (item->text[0]) + { + case '~': //数值弹窗的话 // 画行结尾的数值 + OLED_WinDrawStr(&w_all,CHECK_BOX_L_S, start_y + LIST_TEXT_S, LIST_TEXT_H,(uint8_t*)(itoa(item->val))); + break; + case '+': //二值选择框的话 //画结尾外框 + case '=': //如果是单选框页面内的单选选项的话 + case '$': //如果是确认弹窗的话 + OLED_WinDrawRBoxEmpty(&w_all, CHECK_BOX_L_S, start_y + CHECK_BOX_U_S, CHECK_BOX_F_W, CHECK_BOX_F_H, 2); + if(item->val != 0)//非0即是选中,画框内的点 + OLED_WinDrawRBox(&w_all,CHECK_BOX_L_S+CHECK_BOX_D_S+1, start_y+CHECK_BOX_U_S+CHECK_BOX_D_S+1, + CHECK_BOX_F_W - (CHECK_BOX_D_S +1) * 2 +1, CHECK_BOX_F_H - (CHECK_BOX_D_S + 1) * 2 , 1); + break; + default: + break; + } +} + +static void OLED_ListPageAnimInit(PageAddr page_addr) +{ + ListPage * lp = (ListPage *)page_addr; + lp->y = 0; + lp->y_trg = LIST_LINE_H; + lp->box_x = 0; + lp->box_y = 0; + lp->bar_y = 0; +// ui.vwin.state = 0; //刚进入列表时默认关闭弹窗 +// #if UI_CONWIN_ENABLE +// ui.cwin.state = 0; //刚进入列表时默认关闭弹窗 +// #endif +} +static void OLED_ListPageShow(PageAddr page_addr) +{ + ListPage * lp = (ListPage *)page_addr; + static float temp = 0; //用于临时存放列表每一项的y坐标 + //计算选中框目标值和进度条y值目标 + lp->box_x_trg = OLED_GetStrWidth(lp->option_array[lp->select_item].text,LIST_TEXT_H) + LIST_TEXT_S * 2; + lp->bar_y_trg = (int16_t)(lp->select_item * OLED_HEIGHT/(lp->item_num-1))+1; + + //计算动画过渡值 + OLED_Animation(&(lp->y), &(lp->y_trg), ui.upara->ani_param[LIST_ANI]); + OLED_Animation(&(lp->box_x), &(lp->box_x_trg), ui.upara->ani_param[LIST_ANI]); + OLED_Animation(&(lp->box_y), &(lp->box_y_trg), ui.upara->ani_param[LIST_ANI]); + OLED_Animation(&(lp->bar_y), &(lp->bar_y_trg), ui.upara->ani_param[LIST_ANI]); + + //绘制进度条 + OLED_WinDrawHLine(&w_all,OLED_WIDTH - LIST_BAR_W,0,LIST_BAR_W); + OLED_WinDrawHLine(&w_all,OLED_WIDTH - LIST_BAR_W,OLED_HEIGHT-1,LIST_BAR_W); + OLED_WinDrawVLine(&w_all,OLED_WIDTH - ((LIST_BAR_W/2)+1),0,OLED_HEIGHT); + OLED_WinDrawRBox(&w_all,OLED_WIDTH - LIST_BAR_W,0,LIST_BAR_W,lp->bar_y,0); + + if(lp->slip_flag && lp->box_y == lp->box_y_trg) lp->slip_flag = False; + //该标志位是为了防止 切换动画导致的box_y移动对过度动画造成影响 + if(!ui.init_finish_flag) //过度动画 + { + for (uint8_t i = 0; i < (lp->item_num); i++) + { + if(ui.upara->ufd_param[LIST_UFD]) //从头展开 + temp = i*(lp->y) - LIST_LINE_H*(lp->select_item) + (lp->box_y_trg); + else //选中项展开 + temp = (i - (lp->select_item))*(lp->y) + lp->box_y_trg; + OLED_ListDrawText_CheckBox(temp, &(lp->option_array[i])); + } + if(lp->y == lp->y_trg) //动画抵达目标位置 + { + ui.init_finish_flag = True;//过度动画完成 + lp->y = lp->y_trg = -LIST_LINE_H * (lp->select_item) + (lp->box_y_trg); + //第一个选项到光标(盒子)所在的距离确定下来 + } + } + else //过度后,一般上下切换选项时的动画,但目标参数不在这儿设置 + for (uint8_t i = 0; i < (lp->item_num); i++) + { + temp = LIST_LINE_H *i + (lp->y); + OLED_ListDrawText_CheckBox(temp, &(lp->option_array[i])); + } + //绘制文字选中框,框需要在文字前绘制,否则文字无法显色 + OLED_SetPointColor(2);//反色绘制 + OLED_WinDrawRBox(&w_all, 0, lp->box_y, lp->box_x, LIST_LINE_H, LIST_BOX_R); + OLED_SetPointColor(1);//实色绘制 +} + + +static void OLED_ListPageReact(PageAddr page_addr) +{ + ListPage * lp = (ListPage *)page_addr; + String selcet_string = NULL; + int16_t select_val = 0; + //int16_t contorl_flip = 0; //控制取反信号(这儿不能使用取反信号进行异或,对数组参数的赋值无法实现??) + InputMsg msg = OLED_MsgQueRead(); + switch (msg) + { + case msg_up: //上一个 + if(ui.init_finish_flag && !(lp->slip_flag)) //初始化动画已完成 + { +#if PAGE_WAVE_ENABLE + if(OLED_CheckPageType(lp) == type_wave) wave_tag.change_flag = True;//如果是波形页面的话,标志波形切换 +#endif + if(lp->select_item == 0) //选中第一个的话 + { + if(ui.upara->loop_param[LIST_LOOP]) //同时loop参数开的话 + { + lp->slip_flag = True; + lp->select_item = lp->item_num - 1; //选中最后一个 + if(lp->item_num > lp->line_n) //数目超出一页的最大数目 + {//更改box到最底 + lp->box_y_trg = OLED_HEIGHT - LIST_LINE_H; + //同时更改文字到最底 + lp->y_trg = OLED_HEIGHT - (lp->item_num)*LIST_LINE_H; + } + else // 没有超出数目则是到最后一个 + lp->box_y_trg = (lp->item_num - 1)*LIST_LINE_H; + } + } + else //没有选中第一个 + { + lp->select_item -= 1; //选中减1 + if(lp->select_item < -((lp->y_trg) / LIST_LINE_H))//光标盒子到页面顶了???? + { + if(!(OLED_HEIGHT % LIST_LINE_H)) //上面剩余完整的行 + lp->y_trg += LIST_LINE_H; //文字下移 + else //上面的行不完整(LIST_LINE_H该项用于页面和行高非整除时) + { + if(lp->box_y_trg == OLED_HEIGHT-LIST_LINE_H*lp->line_n) + {//文字往下走一行,且光标盒子置于0处,把上面的非整行去掉 + lp->y_trg += (lp->line_n+1)*LIST_LINE_H - OLED_HEIGHT; + lp->box_y_trg = 0; + } + else if(lp->box_y_trg == LIST_LINE_H) + lp->box_y_trg = 0; //上面整行直接移动光标盒子 + else lp->y_trg += LIST_LINE_H; //顶页整行,文字直接往下走 + } + } + else //光标盒子没到页面顶 + lp->box_y_trg -= LIST_LINE_H; //直接光标盒子往上走即可。 + } + } + break; + case msg_down: //下一个 + if(ui.init_finish_flag && !(lp->slip_flag)) //初始化动作已完成 + { +#if PAGE_WAVE_ENABLE + if(OLED_CheckPageType(lp) == type_wave) wave_tag.change_flag = True;//如果是波形页面的话,标志波形切换 +#endif + if(lp->select_item == (lp->item_num) -1) //到最后一个选项了 + { + if(ui.upara->loop_param[LIST_LOOP]) //loop开关开 + {//全部回到顶部 + lp->slip_flag = True; + lp->select_item = 0; + lp->y_trg = 0; + lp->box_y_trg = 0; + } + } + else //不是最后一个选项 + { + lp->select_item += 1; + if((lp->select_item+1) > ((lp->line_n) - (lp->y_trg)/LIST_LINE_H)) + {//光标到页面底 + if(!(OLED_HEIGHT % LIST_LINE_H)) lp->y_trg -= LIST_LINE_H; + else //非整行的情况 + { + if(lp->box_y_trg == LIST_LINE_H*(lp->line_n-1)) + { + lp->y_trg -= (lp->line_n+1)*LIST_LINE_H - OLED_HEIGHT; + lp->box_y_trg = OLED_HEIGHT - LIST_LINE_H; + } + else if(lp->box_y_trg == OLED_HEIGHT - LIST_LINE_H*2) + lp->box_y_trg = OLED_HEIGHT - LIST_LINE_H; + else + lp->y_trg -= LIST_LINE_H; + } + } + else lp->box_y_trg += LIST_LINE_H; + } + } + break; + + case msg_return: OLED_PageReturn((PageAddr)lp); break; + + case msg_click : + selcet_string = lp->option_array[lp->select_item].text; + select_val = lp->option_array[lp->select_item].val; + //contorl_flip = (!!(lp->option_array[lp->select_item].step)); //使用step作为是否取反的信号 + if(selcet_string[0] == '+' || selcet_string[0] == '=') ////二值选框或者单选框 + { + if(lp->option_array[lp->select_item].step)lp->option_array[lp->select_item].val = !select_val; //将对应值取反 + //lp->option_array[lp->select_item].val ^= contorl_flip; + //将对应值取反(用step的是否非0控制val是否取反) +#if PAGE_RADIO_ENABLE + if(selcet_string[0] == '=')radio_click_flag = True; //标记为1,用于OLED_RadioReact进行轮询判断单选 +#endif + } + +//为没有使能确认弹窗的宏定义时,打个补丁,$标识的确认弹窗和一般的二值选择框一样,将值取反,并调用回调 +#if !UI_CONWIN_ENABLE + if(selcet_string[0] == '$') + if(lp->option_array[lp->select_item].step)lp->option_array[lp->select_item].val = !select_val; //将对应值取反 + //lp->option_array[lp->select_item].val ^= contorl_flip; + //将对应值取反(用step的是否非0控制val是否取反) +#endif + //回调函数和状态机部分 + if(selcet_string[0] == '~') + {//数值弹窗的话,进入数值弹窗这个动作不触发回调,但弹窗内不论点击什么都会实时触发回调 + //当数值弹窗step设为0为只读是,进入数值弹窗前会调用一次回调,以便外界更改val值 + ui.vwin.state = 1; //进入弹窗初始化 + if((lp->option_array[lp->select_item].step == 0) && (lp->page.cb != NULL)) + lp->page.cb(lp->page.page_id, &(lp->option_array[lp->select_item])); + } +#if UI_CONWIN_ENABLE + else if(selcet_string[0] == '$') ui.cwin.state = 1; //进入确认弹窗初始化 + //确认弹窗内只有确认弹窗内的click才会触发回调 +#endif + else if(lp->page.cb != NULL)lp->page.cb(lp->page.page_id, &(lp->option_array[lp->select_item])); + break; + default:break; + } +} + +void OLED_ListPageInit( + ListPage * lp, //列表页面对象 + uint8_t page_id, //为该页面分配一个唯一的id + uint8_t item_num, //选项个数,需与title数组大小,icon数组大小一致 + Option *option_array, //整个页面的选项数组(数组大小需与item_num一致) + CallBackFunc call_back) //回调函数,参数为确认选中项index(1-256)0表示未确认哪个选项 +{ + //缺少选项个数检查,检查, + lp->page.page_type = type_list; + OLED_PageInit((PageAddr)lp, page_id, call_back); + lp->page.ani_init = OLED_ListPageAnimInit; + lp->page.show = OLED_ListPageShow; + lp->page.react = OLED_ListPageReact;//关联相关处理函数 + lp->select_item = 0; + lp->item_num = item_num; + lp->option_array = option_array; + lp->line_n = OLED_HEIGHT/LIST_LINE_H; + for (uint8_t i = 0; i < lp->item_num; i++) + lp->option_array[i].order = i;//选项序号标号 +} + + +// // ------终端波形页面 +#if PAGE_WAVE_ENABLE + +void OLED_WavePageAnimInit(PageAddr page_addr) +{ + WavePage * wp = (WavePage *)page_addr; + OLED_ListPageAnimInit(wp); + wave_tag.text_bg_r = 0; + wave_tag.text_bg_r_trg = WAVE_TEXT_BG_W; +} + +void OLED_WavePageShow(PageAddr page_addr) +{ + WavePage * wp = (WavePage *)page_addr; + int16_t temp; //临时变量用于存放波形的点,暂时显示 + String temp_str = NULL; + OLED_ListPageShow(wp); + OLED_Animation(&wave_tag.text_bg_r, &wave_tag.text_bg_r_trg, ui.upara->ani_param[TAG_ANI]); + + OLED_WinDrawRBoxEmpty(&w_all, WAVE_BOX_L_S, 0 ,WAVE_BOX_W , WAVE_BOX_H,0); + OLED_WinDrawRBoxEmpty(&w_all, WAVE_BOX_L_S+1, 1 ,WAVE_BOX_W -2, WAVE_BOX_H-2,0); + + //数据入队列 + wave_tag.data_que[wave_tag.p_rear] = wp->option_array[wp->select_item].val; //放入数据 + wave_tag.p_rear++; wave_tag.p_rear %= (WAVE_W-1); + if((wave_tag.p_rear)%(WAVE_W-1) == wave_tag.p_head) //队列满了 + wave_tag.p_head++; wave_tag.p_head %= (WAVE_W-1); //环状前进 + wave_tag.p_font = wave_tag.p_head; //获取起始地址 + if(wp->box_y == wp->box_y_trg && wp->y == wp->y_trg)//完成过度动画 + { + for (uint8_t i = 1; i < WAVE_W -1; i++) + { + if(wave_tag.p_rear != wave_tag.p_font) //队列非空 + { + temp = wave_tag.data_que[wave_tag.p_font]; + wave_tag.p_font++;wave_tag.p_font %= (WAVE_W -1); //出队指针前移 + //画点或者差值画斜线函数 + OLED_WinDrawPoint(&w_all,WAVE_L + i , + WAVE_BOX_H - (temp - wp->option_array[wp->select_item].item_min)*WAVE_BOX_H/(wp->option_array[wp->select_item].item_max - wp->option_array[wp->select_item].item_min)); + } + else break; + } + //绘制文字 + temp_str = itoa(wp->option_array[wp->select_item].val); + OLED_WinDrawStr(&w_all, WAVE_TEXT_BG_L_S + (WAVE_TEXT_BG_W - OLED_GetStrWidth(temp_str,WAVE_FONT_H))/2, + OLED_HEIGHT-28, WAVE_FONT_H, (uint8_t*)temp_str); + //绘制选框 + OLED_SetPointColor(2); //反色选框 + OLED_WinDrawRBox(&w_all, WAVE_TEXT_BG_L_S, OLED_HEIGHT - WAVE_TEXT_BG_H, wave_tag.text_bg_r, WAVE_TEXT_BG_H, 0); + OLED_SetPointColor(1); //恢复实色 + } +} + +void OLED_WavePageReact(PageAddr page_addr) +{ + WavePage * wp = (WavePage *)page_addr; + OLED_ListPageReact(wp); + if(wave_tag.change_flag) + { + wave_tag.p_rear = 0; + wave_tag.p_head = 0; //切换选项时,重新开始显示波形 + wave_tag.change_flag = False; + } +} + +void OLED_WavePageInit( + WavePage * wp, //波形页面对象 + uint8_t page_id, //为该页面分配一个唯一的id + uint8_t item_num, //选项个数,需与option_array数组大小,icon数组大小一致 + Option *option_array, //整个页面的选项数组(数组大小需与item_num一致) + CallBackFunc call_back) //回调函数,参数为 self_id 和 选中项option指针 +{ + OLED_ListPageInit(wp,page_id,item_num,option_array,call_back); //先初始化为list + wp->page.page_type = type_wave; //指定为波形页面 + wp->page.ani_init = OLED_WavePageAnimInit; + wp->page.show = OLED_WavePageShow; + wp->page.react = OLED_WavePageReact; +} + +//更新波形选项的显示值(后期会加上断言),以防止输入NULL +void OLED_UIWaveUpdateVal(Option * op, int16_t val) +{ + //这里可以添加断言 + op->val = val; +} + +#endif + +// // -------单选框页面 +#if PAGE_RADIO_ENABLE +//单选框的AnimInit 和show页面与list页面一致 +void OLED_RadioPageReact(PageAddr page_addr) +{ + RadioPage * rp = (RadioPage *)page_addr; + OLED_ListPageReact(rp); + if(radio_click_flag) + { + for(uint8_t i = 0; i < rp->item_num; i++) + { + if(rp->option_array[i].text[0] == '=') //确保这个选项是单选项 + { + if(i != rp->select_item)rp->option_array[i].val = False; + else rp->option_array[i].val = True; //确保单选 + } + } + radio_click_flag = False; + } +} + +void OLED_RadioPageInit( + RadioPage * rp, //Radio单选页面对象 + uint8_t page_id, //为该页面分配一个唯一的id + uint8_t item_num, //选项个数,option_array 大小一致 + Option *option_array, //整个页面的选项数组(数组大小需与item_num一致),需要注意单选项 的 text 需要以“= ”开头,一般标识符则不需要 + CallBackFunc call_back) //回调函数,参数为 self_id 和 选中项option指针 +{ + OLED_ListPageInit(rp, page_id, item_num, option_array, call_back); + rp->page.page_type = type_radio; //标记为单选终端页面 + rp->page.react = OLED_RadioPageReact; //只有单选的react函数不一样,其他处理函数和list的一样 +} + +#endif + + +//-----镭射文字界面相关函数 +#if PAGE_RADERPIC_ENABLE + +void OLED_RaderPicAnimInit(PageAddr page_addr) +{ + RaderPicPage* rpp = (RaderPicPage*)page_addr; + if(rpp->cur_pic_index == rpp->pic_num) //所有的图片已经绘制完成,且从pic页面退出重新进入(因为在layIn中调用该函数) + rpp->cur_pic_index = 0; //重新开始绘制图片页面的绘制 + rpp->move_x = -1.0; + rpp->move_y = -1.0; +} + +void OLED_RaderPicShow(PageAddr page_addr) +{ + RaderPicPage* rpp = (RaderPicPage*)page_addr; + RaderPic *cur_pic = NULL; + Option temp_op; + float target = 0; + OLED_Animation(&(rpp->move_x), &target, ui.upara->raderpic_move_rate); + OLED_Animation(&(rpp->move_y), &target, ui.upara->raderpic_move_rate); + if(rpp->cur_pic_index < rpp->pic_num) //当前序号在数组大小内的话 + { + uint8_t pic_finish_flag = 0; + cur_pic = &(rpp->pic_array[rpp->cur_pic_index]); + if(rpp->cur_pic_index > 0) //将已经绘制完成的pic快速绘制完 + for(uint8_t i = 0; i < rpp->cur_pic_index ; i++) + { + RaderPic * temp_pic = &(rpp->pic_array[i]); + OLED_WinDrawBMP(&w_all, temp_pic->start_x*(1+rpp->move_x), temp_pic->start_y*(1+rpp->move_y), temp_pic->w, temp_pic->h, temp_pic->pic,1);//实色显示 + } + pic_finish_flag = OLED_WinDrawRaderPic(&w_all,cur_pic->pic, cur_pic->start_x*(1+rpp->move_x), cur_pic->start_y*(1+rpp->move_y), + cur_pic->w,cur_pic->h,cur_pic->rd,ui.upara->raderpic_scan_mode,ui.upara->raderpic_scan_rate); + if(pic_finish_flag) //一张图片绘制完成切换下一张 + { + rpp->cur_pic_index++; //默认自增(1 ~ pic_num) + if(rpp->page.cb != NULL) + { + temp_op.order = rpp->cur_pic_index; + rpp->page.cb(rpp->page.page_id,&temp_op); //传入回调函数第i(1 ~ pic_num)张图像已经绘制完成 + } + } + } + else //全部图片绘制完成 + { + switch (rpp->rader_pic_mode) + { + case Rader_Pic_Mode_Loop: rpp->cur_pic_index = 0; break; + case Rader_Pic_Mode_Hold: + for(uint8_t i = 0; i < rpp->pic_num ; i++) + { + RaderPic * temp_pic = &(rpp->pic_array[i]); + OLED_WinDrawBMP(&w_all, temp_pic->start_x, temp_pic->start_y, temp_pic->w, temp_pic->h, temp_pic->pic,1);//实色显示 + } + //hold保持模式的话,在所有图像绘制完成后会持续调用回调 + if(rpp->page.cb != NULL) + { + temp_op.order = rpp->cur_pic_index; + rpp->page.cb(rpp->page.page_id,&temp_op); //传入回调函数第i(0 ~ pic_num-1)张图像已经绘制完成 + } + break; + default: break; + } + } +} +void OLED_RaderPicReact(PageAddr page_addr) +{ + RaderPicPage* rpp = (RaderPicPage*)page_addr; + InputMsg msg = OLED_MsgQueRead(); + switch (msg) + { + case msg_click : + case msg_return : //镭射文字页面内上up下down键没有用,按下click,或return均是返回 + OLED_PageReturn((PageAddr)rpp); + break; + default:break; + } +} + +void OLED_RaderPicPageInit( + RaderPicPage* rpp, //镭射页面对象 + uint8_t page_id, //该页面的id + uint8_t pic_num, //页面内的图片数量,pic_array的数组大小 + RaderPic * pic_array, //镭射图片数组 + RaderPicMode mode, //所有图片播放完后的操作模式选择(clear,hold,loop) + CallBackFunc cb) //回调函数,在每绘制完一个图片前会调用一次 +{ + rpp->page.page_type = type_rader_pic; + OLED_PageInit((PageAddr)rpp, page_id, cb); + rpp->pic_num = pic_num; + rpp->pic_array = pic_array; + rpp->cur_pic_index = 0;//默认第一张显示的序号为数组下标为0的图片 + rpp->rader_pic_mode = mode; + rpp->page.ani_init = OLED_RaderPicAnimInit; + rpp->page.show = OLED_RaderPicShow; + rpp->page.react = OLED_RaderPicReact; +} + + +#endif + + +#if PAGE_DIGITAL_ENABLE + +/** + * @brief 在数字标签上绘制下划线(光标) + * + * @param dp 数字页面指针 + * @param color 颜色值 + */ +static void OLED_DigitalDrawUline(DigitalPage *dp, uint8_t color) +{ + //标签的下划线偏移值不同 + uint8_t end_x = 0, start_y = 0, start_x = 0; + if(dp->select_index == Digital_Pos_IndexLabel) + { + start_x = (OLED_WIDTH-OLED_GetStrWidth(dp->label_array[dp->select_label_index],DIGITAL_Label_SIZE))>>1; + end_x = start_x + OLED_GetStrWidth(dp->label_array[dp->select_label_index],DIGITAL_Label_SIZE); + start_y = dp->w_digtal[1].start_y + DIGITAL_Label_SIZE; + } else if(dp->select_index < Digital_Pos_IndexLabel) //是数字的话 + { + start_y = dp->w_digtal[0].start_y + DIGITAL_NUM_SIZE+2; + start_x = 16 + digital_num_xindex[(dp->select_index)*2+1]; //012->135 《*2》 + end_x = start_x + DIGITAL_NUM_SIZE; //两个字符宽 + } + if(dp->select_index != Digital_Pos_Complete) + { + if(color == 0) + { + OLED_SetPointColor(0); //更改颜色 + OLED_WinDrawHLine(&w_all, start_x, end_x, start_y); //如果在python中,应该是套个装饰器 + OLED_SetPointColor(1); + } + else + OLED_WinDrawHLine(&w_all, start_x, end_x, start_y); + } +} + +/* +函数:static void OLED_DigitalDirChangey(DigitalPage *dp, DigitalDirect dir) +参数:dp 数字页面指针 , dir方向枚举类型 +返回值:None +说明:根据输入的方向,设置数字运动的目标值 +作者:Sheep +日期:24/02/10 +*/ +static void OLED_DigitalDirChangey(DigitalPage *dp, DigitalDirect dir) +{ + dp->num_y = 0; + switch (dir) + { + case Digital_Direct_Increase : dp->num_y_trg = -24; break; + case Digital_Direct_Decrease : dp->num_y_trg = 24; break; + default:break; + } +} +//创建过度动画使用的string +static char* OLED_DigitalCreateText(DigitalPage * dp) +{ + static char str[10] = {0}; + memset(str, 0, sizeof(str)); + sprintf(str, "%02d%c%02d%c%02d", dp->option_array[Digital_Pos_IndexLeft].val, dp->gap_char, + dp->option_array[Digital_Pos_IndexMid].val, dp->gap_char, + dp->option_array[Digital_Pos_IndexRight].val); + return str; +} + +/** +* @brief : static void OLED_DigitalSetSingleBit(DigitalPage* dp, uint8_t index, SingleBit sbit_array[6]) + 将设置的数字写入到显示在屏幕上6个单个位的数组中 +* @param : dp 数字页面指针, index 下标,sbit_array 十位和个位的数组(共6个位) +* @attention : None +* @author : Sheep +* @date : 24/02/10 +*/ +static void OLED_DigitalSetSingleBit(DigitalPage* dp, uint8_t index, SingleBit sbit_array[6]) +{ + if(index > 5)return ; //防止数组越界 + if(index%2) //个位 + sbit_array[index].num = ((dp->option_array[index>>1].val)%100)/10; //取出十位 + else + sbit_array[index].num = (dp->option_array[index>>1].val)%10 ; //取出个位 +} + +/** +* @brief : static void OLED_DigitalSetValAnim(DigitalPage * dp, DigitalPosIndex bit, uint8_t val, DigitalDirect dir) +* @param : dp 数字页面指针, bit 下标,val 更新的值,dir 方向枚举类型 +* @attention : 这个函数将更新的值设置在选项中,并触发一次更新动画,让show函数中按模式要求更新显示 +* @todo : 后期有一处细节可以更新,将根据输入方向,决定先更新十位还是个位,这样,可以使上下的ripple动画有区分。 +* @author : Sheep +* @date : 24/02/10 +*/ +// 建议可以判断两个位更新时再等待运动结束 +static void OLED_DigitalSetValAnim(DigitalPage * dp, DigitalPosIndex bit, uint8_t val, DigitalDirect dir) +{ + uint8_t last_val = dp->option_array[bit].val; + if((val >= dp->option_array[bit].item_min) && (val <= dp->option_array[bit].item_max) && (last_val != val)) //更新的数据符合要求 + { + dp->option_array[bit].val = val; + dp->dir = dir; + if((val%100)/10 != (last_val%100)/10) //十位发生变化 + { + dp->digital_num_pos |= (1<<(bit*2+1)); //012->135 + dp->temp_ripple_index = (bit*2+1); //记下这个十位 + } + if(val%10 != (last_val%10)) //个位发生变化 + { + dp->digital_num_pos |= (1<<(bit*2)); //012->024 + dp->temp_ripple_index = (bit*2); //记下这个个位(个位在十位后,所以最低位会被记录) + } + } +} + + +/** + * @brief 在数字页面上绘制标签 + * + * @param dp 数字页面指针 + * @param y 标签的纵坐标 + * @param label 标签的文本 + * @brief 为了减少代码量而专门为digital[1] 绘制标签设置的函数 + */ +static void OLED_DigitalDrawLabel(DigitalPage * dp, int16_t y , String label) +{ + int16_t x = (OLED_WIDTH-OLED_GetStrWidth(label,DIGITAL_Label_SIZE))>>1; // 计算起始横坐标 + OLED_WinDrawStr(&(dp->w_digtal[1]), x, y, DIGITAL_Label_SIZE, (uint8_t*)(label)); // 绘制标签 +} + +static uint8_t temp_num_pos = 0; //用于在show函数内暂时装载num_pos变量,实现同时运动动画和ripple动画的切换 +static DigitalDirect temp_dir = Digital_Direct_None; //记录下运动方向 + +static void OLED_DigitalShow(PageAddr page_addr) +{ + DigitalPage* dp = (DigitalPage*)page_addr; + if(!ui.init_finish_flag) //绘制过度动画 + { + OLED_Animation(&(dp->rect_y), &(dp->rect_y_trg), ui.upara->ani_param[WIN_ANI]); //使用弹窗的速度 + OLED_Animation(&(dp->label_y), &(dp->label_y_trg), ui.upara->ani_param[WIN_ANI]); //使用弹窗的速度 + OLED_WinDrawRBoxEmpty(&w_all,DIGITAL_RECT_X, dp->rect_y, DIGITAL_RECT_W, DIGITAL_RECT_H, DIGITAL_RECT_R); + dp->w_digtal[0].start_y = dp->rect_y + DIGITAL_NUM_T_S; + OLED_WinDrawStr(&(dp->w_digtal[0]), 0, 0, DIGITAL_NUM_SIZE,(uint8_t*)OLED_DigitalCreateText(dp)); + //这儿可以将label的移动改为label窗口的移动,再将label绘制在label窗口中 + dp->w_digtal[1].start_y = dp->label_y; //更新label窗口的纵坐标 + OLED_DigitalDrawLabel(dp, 0, dp->label_array[dp->select_label_index]); + if(dp->rect_y == dp->rect_y_trg && dp->label_y == dp->label_y_trg) ui.init_finish_flag = True; + } + else //绘制切换动画 + { + //绘制不需要移动的框 + OLED_WinDrawRBoxEmpty(&w_all,DIGITAL_RECT_X, DIGITAL_RECT_Y, DIGITAL_RECT_W, DIGITAL_RECT_H, DIGITAL_RECT_R); + //闪烁 + if(Gap_shine_time <= ((dp->gap_shine_time)>>1)) //恒定为0是显示的内容 + { + OLED_WinDrawASCII(&w_all, digital_num_xindex[4]+28, dp->w_digtal[0].start_y, DIGITAL_NUM_SIZE, dp->gap_char); + OLED_WinDrawASCII(&w_all, digital_num_xindex[2]+28, dp->w_digtal[0].start_y, DIGITAL_NUM_SIZE, dp->gap_char); + } + else + { + OLED_WinDrawASCII(&w_all, digital_num_xindex[4]+28, dp->w_digtal[0].start_y, DIGITAL_NUM_SIZE, ' '); + OLED_WinDrawASCII(&w_all, digital_num_xindex[2]+28, dp->w_digtal[0].start_y, DIGITAL_NUM_SIZE, ' '); + } + if(Gap_shine_time == dp->gap_shine_time)Gap_shine_time = 0; + else Gap_shine_time++; + //根据模式横杠闪烁提示 + switch(dp->mod) + { + case Digital_Mode_Edit: + if(Uline_shine_time <= ((dp->uline_shine_time)>>1)) //恒定为0是显示的内容 + OLED_DigitalDrawUline(dp,0); + else + OLED_DigitalDrawUline(dp,1); + if(Uline_shine_time == dp->uline_shine_time)Uline_shine_time = 0; + else Uline_shine_time++; + break; + case Digital_Mode_Observe: //未进入编辑模式时,没有横杠 + OLED_DigitalDrawUline(dp,0); + break; + case Digital_Mode_Singlebit: //编辑单个位时,常亮 + OLED_DigitalDrawUline(dp,1); + break; + default:break; + } + //数字上下移动 + if(dp->dir != Digital_Direct_None) + { + temp_dir = dp->dir; //记录传入的方向,并清零传入的消息(label移动,也将方向读出) + if((dp->digital_num_pos & 0x3F) && !(dp->digital_num_pos & 0x40)) + //ripple模式和一起滚动模式的区别只对数字移动有效(对标签滚动无效) + //排除标签是为了防止在数字运动是标签运动重复进入 + if(ui.upara->digital_ripple) //第一次接收到运动消息时, + { + OLED_DigitalDirChangey(dp,temp_dir); + temp_num_pos = (dp->digital_num_pos & 0x3F) & (1<temp_ripple_index); + OLED_DigitalSetSingleBit(dp , dp->temp_ripple_index, num_array); //更新第一个需要运动的位的数据 + (dp->temp_ripple_index)++; + } + else //一起滚动的话 + { + temp_num_pos = (dp->digital_num_pos & 0x3F); //设置需要滚动的位 + for(uint8_t i = 0; i < 6; i++)OLED_DigitalSetSingleBit(dp ,i , num_array); + //更新选中位的值 + OLED_DigitalDirChangey(dp,temp_dir); + } + dp->dir = Digital_Direct_None; //保证只有接收到运动消息的第一次进来 + } + if(temp_dir != Digital_Direct_None) //持续运动 + if(dp->digital_num_pos & 0x3F) //移动的是数字 + OLED_Animation(&(dp->num_y),&(dp->num_y_trg),ui.upara->ani_param[DIGI_ANI]); //从0-24 + else if(dp->digital_num_pos & 0x40) //移动的是标签 + OLED_Animation(&(dp->label_y),&(dp->label_y_trg),ui.upara->ani_param[DIGI_ANI]); + for(uint8_t i = 0; i < DIGITAL_NUM_INDEX_MAX; i++) //绘制每个数字win的位置 + { + if((temp_num_pos & (1<w_digtal[0]), digital_num_xindex[i],dp->num_y - DIGITAL_NUM_SIZE,DIGITAL_NUM_SIZE,((num_array[i].num)%10)+'0'); //上一个数字 + OLED_WinDrawASCII(&(dp->w_digtal[0]), digital_num_xindex[i],dp->num_y,DIGITAL_NUM_SIZE,((num_array[i].num+1)%10)+'0'); //这个数字 + } + else if((temp_num_pos & (1<w_digtal[0]), digital_num_xindex[i],dp->num_y + DIGITAL_NUM_SIZE,DIGITAL_NUM_SIZE,((num_array[i].num)%10)+'0'); //下一个数字 + OLED_WinDrawASCII(&(dp->w_digtal[0]), digital_num_xindex[i],dp->num_y,DIGITAL_NUM_SIZE,((num_array[i].num-1)%10)+'0'); //这个 + } + else //直接绘制这个数字就可以 + { OLED_WinDrawASCII(&(dp->w_digtal[0]), digital_num_xindex[i],0,DIGITAL_NUM_SIZE,(num_array[i].num%10)+'0'); //因为只有单位数字 + } + } + if(dp->num_y == dp->num_y_trg && (dp->digital_num_pos&0x3F)) //单次字符运动结束时 + { + if(ui.upara->digital_ripple) + { + do{ + temp_num_pos = (dp->digital_num_pos &0x3F) & (1<temp_ripple_index); + if(temp_num_pos) + { + OLED_DigitalDirChangey(dp,temp_dir); //设置运动坐标 + OLED_DigitalSetSingleBit(dp, dp->temp_ripple_index ,num_array);//更新下一位数据 + (dp->temp_ripple_index)++; //准备检测下一位 + break; + } + dp->temp_ripple_index++; //准备检测下一位 + if(dp->temp_ripple_index >= 6)//所有位到扫描完,才完全退出 + { + temp_dir = Digital_Direct_None;dp->digital_num_pos &= 0xC0; + temp_num_pos = 0; //全部数字运动完清零 + break;//所有位检测完了break; + } + }while(1); //不需要运动继续往下检测 + } + else + {temp_dir = Digital_Direct_None; dp->digital_num_pos &= 0xC0;} + } + //标签上下移动 + //绘制移动标签 + if((dp->digital_num_pos&0x40) && temp_dir == Digital_Direct_Increase) + { + OLED_DigitalDrawLabel(dp, dp->label_y + DIGITAL_Label_SIZE, dp->label_array[dp->select_label_index]); + OLED_DigitalDrawLabel(dp, dp->label_y, dp->label_array[last_or_next_label_index]); + } + else if (((dp->digital_num_pos)&0x40) && temp_dir == Digital_Direct_Decrease) + { + OLED_DigitalDrawLabel(dp, dp->label_y - DIGITAL_Label_SIZE, dp->label_array[dp->select_label_index]); + OLED_DigitalDrawLabel(dp, dp->label_y, dp->label_array[last_or_next_label_index]); + } + else + OLED_DigitalDrawLabel(dp, 0, dp->label_array[dp->select_label_index]); + //运动完成 + if(dp->label_y == dp->label_y_trg && ((dp->digital_num_pos)&0x40)) + { temp_dir = Digital_Direct_None; dp->digital_num_pos &= 0x3F;} + } +} + +static void OLED_DigitalAnimInit(PageAddr page_addr) +{ + DigitalPage* dp = (DigitalPage*)page_addr; + dp->rect_y = - DIGITAL_RECT_Y - DIGITAL_RECT_H; + dp->rect_y_trg = DIGITAL_RECT_Y ; + dp->label_y = OLED_HEIGHT; + dp->label_y_trg = OLED_HEIGHT- DIGITAL_Label_SIZE-4; + dp->dir = Digital_Direct_None; //默认进入页面没有动作 + dp->mod = Digital_Mode_Observe; //默认观察模式 + dp->digital_num_pos = 0; //默认没有选中数字 + dp->temp_ripple_index = 0; //默认没有开始滚动 + dp->select_index = Digital_Pos_Complete; //默认光标位置为完成状态(即没有选中任何位) + for(uint8_t i = 0; i < 6; i++) + OLED_DigitalSetSingleBit(dp, i, num_array); //设置显示数字 +} + + +/** + * @brief 设置数字页面选项和回调函数 + * + * @param dp 数字页面指针 + * @param op 选项指针 + */ +static void OLED_DigitalSetOptionAndCallback(DigitalPage *dp, Option *op) +{ + // 如果选择索引小于标签索引,则设置选项为选项数组中的值 + if(dp->select_index < Digital_Pos_IndexLabel) + *op = dp->option_array[dp->select_index]; + else + { + // 设置选项的顺序和文本为标签数组中的值 + op->order = dp->select_index; + op->text = dp->label_array[dp->select_label_index]; + } + // 如果页面回调函数不为空,则调用回调函数并传入页面ID和选项指针 + if (dp->page.cb != NULL) + dp->page.cb(dp->page.page_id, op); +} + + + +//Digital页面仅在每一位(数字/标签)发生变化并单击click或者返回到observe模式时,才调用回调,其他情况下不会调用回调 +static void OLED_DigitalReact(PageAddr page_addr) +{ + DigitalPage* dp = (DigitalPage*)page_addr; + InputMsg msg = OLED_MsgQueRead(); + Option output_option = {0}; + switch (dp->mod) + { + case Digital_Mode_Observe: + if(msg == msg_up || msg == msg_click) + { + dp->mod = Digital_Mode_Edit; dp->select_index = Digital_Pos_IndexRight; + } + else if(msg == msg_down) + { + dp->mod = Digital_Mode_Edit; dp->select_index = Digital_Pos_IndexLabel; + } + else if(msg == msg_return) + { + temp_dir = Digital_Direct_None; + temp_num_pos = 0; //退出时将临时变量全部清零,防止动画运行一半退出时,在其他DigitalPage页面造成影响。 + OLED_PageReturn((PageAddr)dp); + } + break; + + case Digital_Mode_Edit: + if(msg == msg_return) + { + dp->select_index = Digital_Pos_Complete; + OLED_DigitalSetOptionAndCallback(dp, &output_option); //要退回到观察模式时会有一次complete回调 + dp->mod = Digital_Mode_Observe; + } + else if(msg == msg_click) {dp->mod = Digital_Mode_Singlebit;} + else if(msg == msg_up){dp->select_index++; if(dp->select_index > Digital_Pos_IndexLabel) dp->select_index = Digital_Pos_IndexRight;} + else if(msg == msg_down) + { + if(dp->select_index == Digital_Pos_IndexRight) dp->select_index = Digital_Pos_IndexLabel; + else dp->select_index--; + } + break; + + case Digital_Mode_Singlebit: + if(msg == msg_click)dp->mod = Digital_Mode_Edit; + if(msg == msg_return) + { + dp->select_index = Digital_Pos_Complete; + OLED_DigitalSetOptionAndCallback(dp, &output_option); //要退回到观察模式时会有一次complete回调 + dp->mod = Digital_Mode_Observe; + } + else if (msg == msg_up) + { + if(dp->select_index < Digital_Pos_IndexLabel) //数字的话 + OLED_DigitalSetValAnim(dp, dp->select_index, + dp->option_array[dp->select_index].val + dp->option_array[dp->select_index].step, Digital_Direct_Increase); + else //在eidt页面做了selcet_index的上限限制,输入这边一定是index_label + { + OLED_DigitalPage_UpdateLabelAnimation(dp, (dp->select_label_index)+1, Digital_Direct_Increase); + } + } + else if (msg == msg_down) + { + if(dp->select_index < Digital_Pos_IndexLabel) //数字的话 + OLED_DigitalSetValAnim(dp, dp->select_index, + dp->option_array[dp->select_index].val - dp->option_array[dp->select_index].step, Digital_Direct_Decrease); + else //在eidt页面做了selcet_index的上限限制,输入这边一定是index_label + { + OLED_DigitalPage_UpdateLabelAnimation(dp, (dp->select_label_index)-1, Digital_Direct_Decrease); + } + } + if(msg == msg_click) //编辑值完成后click时会调用回调,将对应选项的值输出给回调 + OLED_DigitalSetOptionAndCallback(dp, &output_option); + break; + default: + break; + } +} + +void OLED_DigitalPageInit( + DigitalPage* dp, //数字显示页面 + uint8_t page_id, //当前页面id + Option * option_array, //选项数组,必须包含3个选项,因为要显示3个数字 + uint8_t label_array_num, //标签数组的大小 + String * label_array, //标签数组,方便标签滚动,数组大小必须和label_array_num一致 + char gap_char, //间隔字符 + uint8_t gap_shine_time, //间隔字符闪烁时间间隔 + uint8_t uline_shine_time, //下划线标识符闪烁时间间隔 + CallBackFunc cb //回调函数 +) +{ + dp->page.page_type = type_digital; //赋值页面类型 + OLED_PageInit((PageAddr)dp, page_id, cb); + //对方法赋值 + dp->page.ani_init = OLED_DigitalAnimInit; + dp->page.show = OLED_DigitalShow; + dp->page.react = OLED_DigitalReact; + + dp->option_array = option_array; + dp->label_array_num = label_array_num; + dp->select_label_index = 0; //默认选中第一个标签 + dp->select_index = Digital_Pos_Complete; //默认没有选中任何一个数字/标签,即是选择完成状态。 + dp->label_array = label_array; + dp->gap_char = gap_char; + dp->gap_shine_time = gap_shine_time; + dp->uline_shine_time = uline_shine_time; + //数字控件的横坐标 + dp->w_digtal[0].start_x = 16; //确定数字窗口的x坐标 + dp->w_digtal[0].h = 24; + dp->w_digtal[0].w = 96; //数字窗口的一些参数 + dp->w_digtal[1].start_x = 0; + dp->w_digtal[1].h = 16; + dp->w_digtal[1].w = 128; //标签窗口的一些参数 +} + + +/** + * @brief 更新数字页面标签动画 + * + * @param dp 数字页面指针 + * @param label_index 标签索引 + * @param dir 运动方向 + */ +void OLED_DigitalPage_UpdateLabelAnimation(DigitalPage * dp, uint8_t label_index, DigitalDirect dir) +{ + if(label_index == 255) label_index = dp->label_array_num -1; // 如果标签索引为255,则设置为最后一个标签索引 + else if(label_index >= dp->label_array_num)label_index = 0; // 如果标签索引大于等于标签数组长度,则设置为第一个标签索引 + if(dp->page.page_id == ui.current_page_id) //只有当前页面是要更新的页面时,才需要更新动画,否则直接更新值就可以 + { + // 这里需要考虑下,给外界调用需不需要等待运动完成??????if(digital_num_pos == 0) + dp->dir = dir; // 确定方向 + dp->label_y = 0; // 设置标签的初始位置 + dp->digital_num_pos |= 0x40; // 设置数字位置标志位 + if(dir == Digital_Direct_Increase)dp->label_y_trg = - DIGITAL_Label_SIZE; // 如果方向为增加,则设置运动目标值为负数 + else dp->label_y_trg = DIGITAL_Label_SIZE; // 如果方向为减少,则设置运动目标值为正数 + } + dp->select_label_index = label_index; // 更新选中项 + last_or_next_label_index = dp->select_label_index; // 存储上一次的值 +} + + + +/** + * @brief 更新数字页面的数字动画 + * + * @param dp 数字页面指针 + * @param leftval 左侧数字值 + * @param midval 中间数字值 + * @param rightval 右侧数字值 + * @param dir 数字方向 + */ +void OLED_DigitalPage_UpdateDigitalNumAnimation(DigitalPage * dp, uint8_t leftval, uint8_t midval, uint8_t rightval, DigitalDirect dir) +{ + uint8_t val_array[3] = {rightval, midval, leftval}; + if(dp->page.page_id == ui.current_page_id)//当当前页面是要更新的页面时,才触发动画更新,否则直接更新数据就可以 + { + if((dp->digital_num_pos&0x3F) == 0) //数字运动完成就可以更新 + //运动结束赋值发生变化,才能从外部更新数据,(是否需要处于obeserve模式由外界自己决定,这样就可以在回调函数中使用这个函数了) + { + //触发数字的动画(调用时倒着循环调用)(保证能让temp_ripplr_index记录到最低需要滚动的位) + for (int8_t i = Digital_Pos_IndexLeft ; i >= Digital_Pos_IndexRight; i--) //从高到低更新,这样ripple才能从低到高 + if(val_array[i] != dp->option_array[i].val) + OLED_DigitalSetValAnim(dp, (DigitalPosIndex)i, val_array[i], dir); + } + } + else + { + for (int8_t i = Digital_Pos_IndexLeft ; i >= Digital_Pos_IndexRight; i--) //从高到低更新,这样ripple才能从低到高 + dp->option_array[i].val = val_array[i]; //直接更新值没有触发动画 + } +} + +#endif + + + + +//-------UI相关函数 +static void OLED_UIParaInit(void) +{ + ui_para.ani_param[TILE_ANI] = 120; // 磁贴动画速度 + ui_para.ani_param[LIST_ANI] = 120; // 列表动画速度 + ui_para.ani_param[WIN_ANI] = 120; // 弹窗动画速度 +// ui_para.ani_param[SPOT_ANI] = 50; // 聚光动画速度 +// ui_para.ani_param[FADE_ANI] = 30; // 消失动画速度 + ui_para.ani_param[TAG_ANI] = 60; // 标签动画速度 + ui_para.ani_param[DIGI_ANI] = 100; // 数字动画滚动速度 + ui_para.ufd_param[TILE_UFD] = True; // 磁贴图标从头展开开关 + ui_para.ufd_param[LIST_UFD] = True; // 菜单列表从头展开开关 + ui_para.loop_param[TILE_LOOP] = True; // 磁贴图标循环模式开关 + ui_para.loop_param[LIST_LOOP] = True; // 菜单列表循环模式开关 + ui_para.valwin_broken = True; //弹窗背景虚化开关 + ui_para.conwin_broken = True; //确认弹窗背景虚化开关 + ui_para.digital_ripple = True; //digital页面波纹递增动画开关 + ui_para.raderpic_scan_mode = False; //镭射文字只扫描亮处 + ui_para.raderpic_scan_rate = 4; //镭射文字扫描速度 + ui_para.raderpic_move_rate = 50; //镭射文字移动速度 +} + + +void OLED_UiInit(void) +{ + ui.init_finish_flag = False; //初始时需要先开启过度动画 + ui.current_page_id = 0; //默认0页面为主页面(开始页面) + ui.state = ui_layer_in; //从没页面进入主页面,所以是lay_in + ui.vwin.l = (OLED_WIDTH - WIN_W)/2;//《/2》 + ui.vwin.u = (OLED_HEIGHT - WIN_H)/2;//弹窗里的默认参数《/2》 + ui.vwin.state = 0 ; //默认弹窗是关闭的 + ui.vwin.anim_init = OLED_ValWinAnimInit; + ui.vwin.show = OLED_ValWinShow; + ui.vwin.react = OLED_ValWinReact; //关联相关的处理函数 +#if UI_CONWIN_ENABLE + ui.cwin.l = (OLED_WIDTH - CON_WIN_W)/2; //不管选框宽度,以字体宽度为准《/2》 + ui.cwin.u = (OLED_HEIGHT - CON_WIN_H)/2; //确认弹窗里的默认参数 + ui.cwin.state = 0 ; //默认弹窗是关闭的 + ui.cwin.anim_init = OLED_ConWinAnimInit; + ui.cwin.show = OLED_ConWinShow; + ui.cwin.react = OLED_ConWinReact; //关联相关的处理函数 +#endif + OLED_UIParaInit(); + ui.upara = &ui_para; //将设置好的参数赋值给ui +} + +static void OLED_UILayerInProc(void) +{ + if(page_array[ui.current_page_id] != NULL)//检查该页面地址存在 + { + Page* p = (Page*)(page_array[ui.current_page_id]); //把当前页面转为page读取 + p->ani_init(page_array[ui.current_page_id]); + } +} + + +static void OLED_UIPageProc(void) //页面处理任务 +{ + if(page_array[ui.current_page_id] != NULL) //该页面地址存在 + { + Option *op = NULL; + Page * p = NULL; + TitlePage * cur_tile = NULL; + ListPage * cur_list = NULL; + PageType pt = OLED_CheckPageType(page_array[ui.current_page_id]); + switch (pt) + { + case type_title: + cur_tile = (TitlePage *)page_array[ui.current_page_id]; + op = &(cur_tile->option_array[cur_tile->select_item]); + break; + case type_list: + cur_list = (ListPage *)page_array[ui.current_page_id]; + op = &(cur_list->option_array[cur_list->select_item]); + break; + default:break; + } + p = (Page *)(page_array[ui.current_page_id]);//把当前页面转为page读取 + p->show(page_array[ui.current_page_id]); + if(pt == type_list || pt == type_title) + {//valwin和conwin不会同时出现 +#if UI_CONWIN_ENABLE + if(ui.vwin.state == 0 && ui.cwin.state == 0)p->react(page_array[ui.current_page_id]); + OLED_WinFSM(&(ui.cwin), page_array[ui.current_page_id], op); +#else + if(ui.vwin.state == 0)p->react(page_array[ui.current_page_id]); +#endif + OLED_WinFSM(&(ui.vwin), page_array[ui.current_page_id], op); + } + else p->react(page_array[ui.current_page_id]); + } +} + +void OLED_UIProc(void) //UI总任务(FSM) +{ + OLED_RefreshBuff(); + switch (ui.state) //ui状态机轮询 + { + case ui_layer_in://主要是对页面动画在切换时做一次参数的赋值 + OLED_UILayerInProc(); + ui.state = ui_page_proc; + break; + case ui_page_proc://因为主要的绘制图像都在这儿完成,所以进入前需清空一次buff + OLED_ClearBuff(); + OLED_UIPageProc(); //在处理过程中读取输入队列,确定状态转换 + break; + default: + break; + } +} + + +/** + * @brief 跳转到指定页面(跳转是会将当前页面id输入,用于关联确认上下级页面关系) + * + * @param self_page_id 当前页面ID + * @param terminate_page 目标页面地址 + */ +void OLED_UIJumpToPage(uint8_t self_page_id,PageAddr terminate_page) +{ + // 关联上级页面并跳转页面 + if(terminate_page != NULL) + { + Page * p = (Page*)terminate_page; + p->last_page_id = self_page_id; + ui.current_page_id = p->page_id; + ui.init_finish_flag = False; // 开启过度动画 + ui.state = ui_layer_in; // 开始层级渲染 + } +} + +/** + * @brief 改变当前页面(不会关联上下级页面关系,只是单纯将当前页面更改为这个页面) + * + * @param terminate_page The address of the page to change to. + */ +void OLED_UIChangeCurrentPage(PageAddr terminate_page) +{ + if(terminate_page != NULL) + { + Page * p = (Page*)terminate_page; + ui.current_page_id = p->page_id; // Set the current page ID to the page ID of the specified page. + ui.init_finish_flag = False; // Enable the transition animation. + ui.state = ui_layer_in; // Start rendering the layers. + } +} + +uint8_t OLED_UIGetCurrentPageID(void) +{ + return ui.current_page_id; +} diff --git a/Third-party-design/PageVersion/Csource/src/oled_ui.h b/Third-party-design/PageVersion/Csource/src/oled_ui.h new file mode 100644 index 0000000..341ec25 --- /dev/null +++ b/Third-party-design/PageVersion/Csource/src/oled_ui.h @@ -0,0 +1,376 @@ +#ifndef __OLED_UI_H__ +#define __OLED_UI_H__ + +#include "oled_g.h" +#include "oled_conf.h" +/*============================================常量定义=========================================*/ +#define True 1 +#define False 0 + + +// 输入消息缓冲队列的大小(至少为2) +#define INPUT_MSG_QUNEE_SIZE UI_INPUT_MSG_QUNEE_SIZE + +//磁贴默认参数 +//所有磁贴页面都使用同一套参数 +#define TILE_B_TITLE_H 24 //磁贴大标题字体高度 +#define TILE_ICON_H 30 //磁贴图标高度 +#define TILE_ICON_W 30 //磁贴图标宽度 +#define TILE_ICON_S 36 //磁贴图标间距 +#define TILE_INDI_H 27 //磁贴大标题指示器高度 +#define TILE_INDI_W 8 //磁贴大标题指示器宽度 +#define TILE_INDI_S 36 //磁贴大标题指示器上边距 +#define ICON_BUFFSIZE (TILE_ICON_W*(TILE_ICON_H/8+1)) + +// 列表默认参数 +//所有列表使用同一套参数 +#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 2 // 列表选择框倒角 + +// 列表行尾选择选项参数 +#define CHECK_BOX_L_S 95 // 选择框在每行的左边距 +#define CHECK_BOX_U_S 2 // 选择框在每行的上边距 +#define CHECK_BOX_F_W 12 // 选择框外框宽度 +#define CHECK_BOX_F_H 12 // 选择框外框高度 +#define CHECK_BOX_D_S 2 // 选择框里面的点距离外框的边距 + +// 弹窗参数 +#define WIN_FNOT_H 16 // 弹窗字体高度 +#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) // 弹窗竖直方向退场终止位置 + +// 确认弹窗变量 +#define CON_WIN_FONT_H 16 // 弹窗字体高度 +#define CON_WIN_H 38 // 弹窗高度 +#define CON_WIN_W 102 // 弹窗宽度 +#define CON_WIN_BTN_H 20 +#define CON_WIN_R 3 +#define CON_WIN_Y (-CON_WIN_H - 2) // 弹窗竖直方向出场起始位置 +#define CON_WIN_Y_TRG (-CON_WIN_H - 2) // 弹窗竖直方向退场终止位置 + +//曲线相关参数 +#define WAVE_SAMPLE 1 //采集倍数 +#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 WAVE_FONT_H 24 //电压数字字体 +#define WAVE_TEXT_BG_L_S 24 //文字背景框左边距 +#define WAVE_TEXT_BG_W 94 //文字背景框宽度 +#define WAVE_TEXT_BG_H 29 +//数字控件页面相关参数 +#define DIGITAL_RECT_X 8 //外框的横坐标 +#define DIGITAL_RECT_Y 4 //外框的纵坐标 +#define DIGITAL_RECT_H 40 //外框的高度 +#define DIGITAL_RECT_W 112 //外框的宽度 +#define DIGITAL_RECT_R 3 //外框的倒角 +#define DIGITAL_NUM_T_S 8 //数字到外框的边距 +#define DIGITAL_NUM_SIZE 24 //数字的尺寸 +#define DIGITAL_Label_SIZE 16 //数字的尺寸 +#define DIGITAL_NUM_INDEX_MAX 6 //digital页面共有6个数字 + +/*============================================类型声明=========================================*/ +//--------页面类型枚举 +typedef enum +{ + //选择框类页面 + type_title = 0x00, //磁贴类 + type_list, //列表类 + //终端类页面 + type_radio, //单选框类 + type_digital, //数字控件类 + type_wave, //波形显示类 + type_rader_pic, //镭射图片类 +} PageType; //页面类型,用于标志传入的每个页面类型,方便调用对应的proc函数 + +//-------页面成员类型 +typedef char* String; // 定义字符串类型 +typedef struct +{ + uint8_t order; //该选项在列表/磁贴中的排序(0-255) + int16_t item_max; //列表项对应变量可取的最大值(若是单选/多选框,该值无意义,可为0) + int16_t item_min; //列表项对应变量可取的最小值(若是单选/多选框,该值无意义,可为0) + int16_t step;//列表项对应变量的步长变化,只对数值弹窗有效(若是单选/多选框,该值无意义,可为0) + int16_t val; //这个列表项关联的显示的值(可以用于设置初值) + String text; + //这个列表项显示的字符串 + //(通过选项的第一个字符判断为数值弹窗(~)/确认弹窗($)/其他项(-)/二值选项框(+)) + //其中二值选项框由于二值项只能在列表中展示,因此只在列表选择页面中有效,在磁帖页面中如果出现+开头的字串默认为其他项 + //其实单选列表项,需使用其他项在应用层关联跳转单选终端页面实现(单选列表项必须使用=做字符串开头)。 +} Option; //通用选项类,其中item_max,item_min,entity与列表选项(单选/多选/弹窗项)相关,磁贴选项可不管 +//选择类界面的回调函数类型定义,参数为确认选中项的指针。 +typedef void (*CallBackFunc)(uint8_t self_page_id,Option* select_item); + +typedef const uint8_t Icon[ICON_BUFFSIZE]; //定义图标类型 +//页面地址类型,用于声明全局页面数组存放页面使用 +#define PageAddr void* +//每个页面都有的三种方法 +typedef void (*PageAniInit)(PageAddr); //页面的动画初始化函数 +typedef void (*PageShow)(PageAddr); //页面的展示函数 +typedef void (*PageReact)(PageAddr); //页面的响应函数 + +typedef struct +{ + PageType page_type; //页面类型,以便在处理时调用不同函数绘制 + uint8_t page_id; //页面的序号,每个页面唯一一个,用于指示在数组中的位置,方便跳转 + uint8_t last_page_id; //上一个页面的id,用于返回时使用 + CallBackFunc cb; //页面的回调函数 + PageAniInit ani_init; + PageShow show; + PageReact react; +} Page; //最基本的页面类型(所有页面类型的基类和结构体的**第一个成员**) + +//----------5种页面类 +typedef struct +{ + Page page; //基础页面信息 + uint8_t item_num ; //页面选项个数,option_array和icon_array个数需与此一致 + Option *option_array; //选项类型的数组(由于数组大小不确定,使用指针代替) + Icon *icon_array ; //图标数组(由于数组大小不确定,使用指针代替) + uint8_t select_item; //选中选项 + + float icon_x; //图标的x坐标距选中目标的间距的变量 + float icon_x_trg;//图标的x坐标距选中目标的间距的变量目标 + float icon_y;//图标的y坐标 + float icon_y_trg;//图标的y坐标目标 + float indi_x; //指示器的x坐标 + float indi_x_trg;//指示器的x坐标目标值 + float title_y;//标题的y坐标 + float title_y_trg;//标题的y坐标目标值 +} TitlePage; //磁帖页面类型(所有类型页面,类型成员为第一个,方便查看) + +typedef struct +{ + Page page; //基础页面信息 + uint8_t item_num ; //页面选项个数,title和icon个数需与此一致 + uint8_t select_item; //选中选项 + Option *option_array; //选项类型的数组(由于数组大小不确定,使用指针代替) + + uint8_t slip_flag; //切换动画是否完成的标志位 + uint8_t line_n; // = DISP_H / LIST_LINE_H; 屏幕内有多少行选项 + float y; //列表中每个选项的间隔值 + float y_trg; //列表中每个选项间隔的目标值 + float box_x; //选中框x + float box_x_trg; //选中框x的目标值 + float box_y; //选中框y + float box_y_trg; //选中框y的目标值 + float bar_y; //进度条的y值 + float bar_y_trg; //进度条的y目标值 +} ListPage; //列表页面类型(所有类型页面,类型成员为第一个,方便查看) + +#if PAGE_WAVE_ENABLE +typedef ListPage WavePage; //定义波形页面类型 +#endif + +#if PAGE_RADIO_ENABLE +typedef ListPage RadioPage; //定义单选项页面类型 +#endif + +#if PAGE_RADERPIC_ENABLE +typedef struct +{ + const uint8_t * pic; //图片指针 + int16_t start_x; //起始x + int16_t start_y; //起始y + uint8_t w; //width of pic + uint8_t h; //height of pic + RaderDirection rd; //射线方向选择,枚举类型 +} RaderPic; //镭射图片对象 +typedef struct +{ + Page page; //基类 +//镭射界面回调函数,传入已经绘制完成的pic序号 +//为了方便在镭射图片界面,绘制自己想要的其他元素(如文字提示,在模式为Rader_Pic_Mode_Hold是,会不断绘制已完成的图片并不断调用回调函数) + uint8_t pic_num ; //页面pic个数,pic_array数组大小需与此一致 + uint8_t rader_pic_mode:2; //结束之后的操作 + RaderPic* pic_array; //镭射图片数组 + + uint8_t cur_pic_index; //当前正在绘制完成的pic序号(0~pic_num-1) + float move_x; + float move_y; +} RaderPicPage; //镭射图片页面对象 + +typedef enum +{ + // Rader_Pic_Mode_Clear = 0x00, //显示完所有图片后不操作,直接清空(这个模式暂时没有使用到) + Rader_Pic_Mode_Loop = 0x01, //显示完所有图片后不操作,再从第一张开始显示 + Rader_Pic_Mode_Hold = 0x02, //显示完所有图片后不操作,保持原图 + Rader_Pic_Mode_Num, +} RaderPicMode; +#endif + +#if PAGE_DIGITAL_ENABLE + +typedef enum +{ + Digital_Direct_None = 0x00, + Digital_Direct_Increase = 0x01, + Digital_Direct_Decrease = 0x02, +} DigitalDirect; //用于Digital Show和React函数间传递信号 + +typedef enum +{ + Digital_Mode_Observe = 0x00, //观察模式没有光标 + Digital_Mode_Edit = 0x01, //对编辑位置的编辑 + Digital_Mode_Singlebit = 0x02, //对单位数字的编辑 +} DigitalMode; //digital页面的模式 + + + +typedef enum //Digital页面从右往左 +{ + Digital_Pos_IndexRight = 0x00, //用于指示当前光标或者编辑的位置 + Digital_Pos_IndexMid, + Digital_Pos_IndexLeft, + Digital_Pos_IndexLabel, //在标签处 + Digital_Pos_Complete, //编辑完成 +}DigitalPosIndex; //用于在回调函数中检验选中项的op->order值,表示选中哪个数字位还是标签 + +typedef struct +{ + Page page; //页面的基本信息 + char gap_char; //3个digital数字间的间隔字符 + uint8_t gap_shine_time; //间隔字符闪烁的时间参数 + uint8_t uline_shine_time; //下划线闪烁的时间参数 + Option * option_array; //选项数组,数组大小必须为3 ,用于显示三个数字 + uint8_t label_array_num; // 标签数组的大小 + String * label_array; //标签数组,方便标签滚动 + + DigitalPosIndex select_index:4; //选中项的index + uint8_t digital_num_pos; //0表示没有选中位置,1-7bit每一位置1表示该位被选中 + uint8_t temp_ripple_index; //用于在ripple时记录选中位置(选中最低位位置开始,慢慢往上增) + DigitalDirect dir:2; //用于Digital Show和React函数间传递信号 + DigitalMode mod:2; //digital页面的模式 + uint8_t select_label_index; //在标签数组中选中的标签的index + window w_digtal[2]; //用限制数字时钟的窗口(1个数字窗口+1个label窗口) 2个窗口 + float rect_y; //移动外框的顶点坐标 + float rect_y_trg; //移动外框的顶点坐标目标 + float label_y; //移动外框的顶点坐标 + float label_y_trg; //移动外框的顶点坐标目标 + float num_y; //移动数字的顶点坐标 + float num_y_trg; //移动数字的顶点坐标目标 +} DigitalPage; //时间页面 + +#endif + + + +//---------输入消息枚举类型 +typedef enum +{ + msg_none = 0x00, //none表示没有操作 + msg_up, //上,或者last消息,表上一个 + msg_down, //下,或者next消息,表下一个 + msg_return, //返回消息,表示返回,从一个页面退出 + msg_click, //点击消息,表确认,确认某一选项,回调用一次回调 + msg_home, //home消息,表回主界面(尚未设计,目前还没有设计对应的功能,默认以page_id为0的页面为主页面) +} InputMsg; //输入消息类型,UI设计只供输入5种消息 + + + +//------类别下标声明。用于UI参数数组中做索引 +enum _ani_kind //动画速度类别(数组中的下标) +{ + TILE_ANI = 0x00, //磁贴动画速度 + LIST_ANI, //列表动画速度 + WIN_ANI, //弹窗动画速度 + // SPOT_ANI, //聚光动画速度 + // FADE_ANI, //消失动画速度 + TAG_ANI, //标签动画速度 + DIGI_ANI, //数字动画滚动速度 + AIN_ALL_NUM, //动画速度参数的数目,用于数组初始化 +}; +enum _ufd_kind //展开方式类别(数组中的下标) +{ + TILE_UFD = 0x00, //磁贴图标从头展开开关 + LIST_UFD, //菜单列表从头展开开关 + UFD_ALL_NUM, //展开方式类别数目 +} ; +enum _loop_kind //循环模式类别(数组中的下标) +{ + TILE_LOOP = 0x00, //磁贴图标循环模式开关 + LIST_LOOP, //菜单列表循环模式开关 + LOOP_ALL_NUM, //循环模式类别数目 +}; + +typedef enum +{ + ui_layer_in = 0x00, //ui层级深入时 + ui_page_proc , //ui页面处理时 +} UIState; //UI状态机 + + +//============================================全局变量的外界声明================================ + +typedef struct +{ + uint8_t valwin_broken:1; //数值弹窗背景虚化开关 + uint8_t conwin_broken:1; //数值弹窗背景虚化开关 + uint8_t digital_ripple:1; //digital页面多位数值递增时是否使用ripple模式还是同时运动递增 + uint8_t raderpic_scan_mode:1; //raderpic扫描方式的开关 + uint8_t raderpic_scan_rate; //raderpic扫描的速度 + uint8_t raderpic_move_rate; //raderpic过度动画的移动速度 + uint8_t ani_param[AIN_ALL_NUM]; //动画参数数组 + uint8_t ufd_param[UFD_ALL_NUM]; //展开参数数组 + uint8_t loop_param[LOOP_ALL_NUM]; //循环参数数组 +} UiPara; //UI参数集合类型 +extern UiPara ui_para; //共外部使用的全局UI参数变量 + +extern window w_all; //这个窗口是ui绘制时的全局窗口,可供外界自由绘制 + +/*============================================接口函数=========================================*/ +void OLED_TitlePageInit(TitlePage * title_page, uint8_t page_id,uint8_t item_num,Option* option_array,Icon *icon_array,CallBackFunc call_back); +void OLED_ListPageInit(ListPage * lp,uint8_t page_id,uint8_t item_num,Option *option_array,CallBackFunc call_back); +//用于向UI传递一个消息Msg(msg_click/msg_up/msg_down/msg_return) +void OLED_MsgQueSend(InputMsg msg); +//UI必要的一些参数和变量的初始化 +void OLED_UiInit(void); +//UI运行任务,需要放在主循环中循环调用,而且尽量不要阻塞 +void OLED_UIProc(void); +/* +* 从一个页面跳转到另一个页面,常用于回调函数中调用,并确定页面的上下级关系(这样,在terminate_page页面收到return消息时,会返回self_page_id所代表的页面) +@param self_page_id 是当前页面的id(回调函数中有这个参数) +@param terminate_page 要跳转的那个页面的地址(不需要理会是那种类型的页面,直接将页面地址作为参数传入即可) +*/ +void OLED_UIJumpToPage(uint8_t self_page_id,PageAddr terminate_page); +/* +* 切换当前页面的函数,与Jump函数不同的时,这个函数不会绑定上下级页面关系,terminate_page 页面收到return 消息不会返回当前页面(常用于临时的画面切换) +@param terminate_page 要跳转的那个页面的地址(不需要理会是那种类型的页面,直接将页面地址作为参数传入即可) +*/ +void OLED_UIChangeCurrentPage(PageAddr terminate_page); +/*获取当前页面的id*/ +uint8_t OLED_UIGetCurrentPageID(void); + + +#if PAGE_WAVE_ENABLE +void OLED_WavePageInit(WavePage * wp, uint8_t page_id, uint8_t item_num, Option *option_array, CallBackFunc call_back); +void OLED_UIWaveUpdateVal(Option * op, int16_t val); +#endif + +#if PAGE_RADIO_ENABLE +void OLED_RadioPageInit(RadioPage * rp, uint8_t page_id, uint8_t item_num,Option *option_array,CallBackFunc call_back); +#endif + +#if PAGE_RADERPIC_ENABLE +void OLED_RaderPicPageInit(RaderPicPage* rpp,uint8_t page_id,uint8_t pic_num,RaderPic * pic_array,RaderPicMode mode,CallBackFunc cb) ; +#endif + +#if PAGE_DIGITAL_ENABLE +void OLED_DigitalPageInit(DigitalPage* dp, uint8_t page_id, Option * option_array, uint8_t label_array_num, String * label_array, char gap_char, uint8_t gap_shine_time, uint8_t uline_shine_time,CallBackFunc cb); +void OLED_DigitalPage_UpdateDigitalNumAnimation(DigitalPage * dp, uint8_t leftval, uint8_t midval, uint8_t rightval, DigitalDirect dir); +void OLED_DigitalPage_UpdateLabelAnimation(DigitalPage * dp, uint8_t label_index, DigitalDirect dir); +#endif + +#endif diff --git a/Third-party-design/PageVersion/Csource/src/oledfont.h b/Third-party-design/PageVersion/Csource/src/oledfont.h new file mode 100644 index 0000000..2d5df9e --- /dev/null +++ b/Third-party-design/PageVersion/Csource/src/oledfont.h @@ -0,0 +1,595 @@ +#ifndef __OLEDFONT_H +#define __OLEDFONT_H +//常用ASCII表 +//偏移量32 +//ASCII字符集 +//偏移量32 +//大小:12*6 +/************************************6*8的点阵************************************/ +const unsigned char F6x8[][6] = +{ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp +0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// ! +0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// " +0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// # +0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $ +0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// % +0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// & +0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// ' +0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// ( +0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// ) +0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// * +0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// + +0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// , +0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// - +0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// . +0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// / +0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0 +0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1 +0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2 +0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3 +0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4 +0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5 +0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6 +0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7 +0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8 +0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9 +0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// : +0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ; +0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// < +0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// = +0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// > +0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ? +0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @ +0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A +0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B +0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C +0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D +0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E +0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F +0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G +0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H +0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I +0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J +0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K +0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L +0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M +0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N +0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O +0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P +0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q +0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R +0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S +0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T +0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U +0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V +0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W +0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X +0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y +0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z +0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [ +0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55 +0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ] +0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^ +0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _ +0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// ' +0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a +0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b +0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c +0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d +0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e +0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f +0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g +0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h +0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i +0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j +0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k +0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l +0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m +0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n +0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o +0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p +0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q +0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r +0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s +0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t +0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u +0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v +0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w +0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x +0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y +0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z +0x00, 0x00, 0x00, 0x7E, 0x80, 0x00,/*"{",0*/ +0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, /*"|",1*/ +0x00, 0x80, 0x7E, 0x00, 0x00, 0x00, /*"}",2*/ +0x00, 0x08, 0x08, 0x10, 0x10, 0x00, /*"~",0*/ +}; +/****************************************8*16的点阵************************************/ +const unsigned char F8X16[][8] = +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",32*/ + {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00},/*"!",33*/ + {0x00,0x10,0x0C,0x02,0x10,0x0C,0x02,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",34*/ + {0x00,0x40,0xC0,0x78,0x40,0xC0,0x78,0x00}, + {0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x00},/*"#",35*/ + {0x00,0x70,0x88,0x88,0xFC,0x08,0x30,0x00}, + {0x00,0x18,0x20,0x20,0xFF,0x21,0x1E,0x00},/*"$",36*/ + {0xF0,0x08,0xF0,0x80,0x60,0x18,0x00,0x00}, + {0x00,0x31,0x0C,0x03,0x1E,0x21,0x1E,0x00},/*"%",37*/ + {0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00}, + {0x1E,0x21,0x23,0x2C,0x19,0x27,0x21,0x10},/*"&",38*/ + {0x00,0x12,0x0E,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",39*/ + {0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00}, + {0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00},/*"(",40*/ + {0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00}, + {0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00},/*")",41*/ + {0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00}, + {0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00},/*"*",42*/ + {0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00}, + {0x00,0x01,0x01,0x01,0x0F,0x01,0x01,0x01},/*"+",43*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x90,0x70,0x00,0x00,0x00,0x00,0x00},/*",",44*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x00},/*"-",45*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},/*".",46*/ + {0x00,0x00,0x00,0x00,0xC0,0x38,0x04,0x00}, + {0x00,0x60,0x18,0x07,0x00,0x00,0x00,0x00},/*"/",47*/ + {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00}, + {0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},/*"0",48*/ + {0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00}, + {0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00},/*"1",49*/ + {0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00}, + {0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},/*"2",50*/ + {0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00}, + {0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00},/*"3",51*/ + {0x00,0x00,0x80,0x40,0x30,0xF8,0x00,0x00}, + {0x00,0x06,0x05,0x24,0x24,0x3F,0x24,0x24},/*"4",52*/ + {0x00,0xF8,0x88,0x88,0x88,0x08,0x08,0x00}, + {0x00,0x19,0x20,0x20,0x20,0x11,0x0E,0x00},/*"5",53*/ + {0x00,0xE0,0x10,0x88,0x88,0x90,0x00,0x00}, + {0x00,0x0F,0x11,0x20,0x20,0x20,0x1F,0x00},/*"6",54*/ + {0x00,0x18,0x08,0x08,0x88,0x68,0x18,0x00}, + {0x00,0x00,0x00,0x3E,0x01,0x00,0x00,0x00},/*"7",55*/ + {0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00}, + {0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},/*"8",56*/ + {0x00,0xF0,0x08,0x08,0x08,0x10,0xE0,0x00}, + {0x00,0x01,0x12,0x22,0x22,0x11,0x0F,0x00},/*"9",57*/ + {0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00},/*":",58*/ + {0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00},/*";",59*/ + {0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00}, + {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00},/*"<",60*/ + {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x00}, + {0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x00},/*"=",61*/ + {0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00}, + {0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00},/*">",62*/ + {0x00,0x70,0x48,0x08,0x08,0x88,0x70,0x00}, + {0x00,0x00,0x00,0x30,0x37,0x00,0x00,0x00},/*"?",63*/ + {0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00}, + {0x07,0x18,0x27,0x28,0x2F,0x28,0x17,0x00},/*"@",64*/ + {0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00}, + {0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20},/*"A",65*/ + {0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00}, + {0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},/*"B",66*/ + {0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00}, + {0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},/*"C",67*/ + {0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00}, + {0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},/*"D",68*/ + {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00}, + {0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},/*"E",69*/ + {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00}, + {0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},/*"F",70*/ + {0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00}, + {0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},/*"G",71*/ + {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08}, + {0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},/*"H",72*/ + {0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00}, + {0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"I",73*/ + {0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00}, + {0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},/*"J",74*/ + {0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00}, + {0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},/*"K",75*/ + {0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00}, + {0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},/*"L",76*/ + {0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00}, + {0x20,0x3F,0x01,0x3E,0x01,0x3F,0x20,0x00},/*"M",77*/ + {0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08}, + {0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},/*"N",78*/ + {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00}, + {0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},/*"O",79*/ + {0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00}, + {0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},/*"P",80*/ + {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00}, + {0x0F,0x10,0x28,0x28,0x30,0x50,0x4F,0x00},/*"Q",81*/ + {0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00}, + {0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},/*"R",82*/ + {0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00}, + {0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},/*"S",83*/ + {0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00}, + {0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"T",84*/ + {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08}, + {0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"U",85*/ + {0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08}, + {0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},/*"V",86*/ + {0x08,0xF8,0x00,0xF8,0x00,0xF8,0x08,0x00}, + {0x00,0x03,0x3E,0x01,0x3E,0x03,0x00,0x00},/*"W",87*/ + {0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08}, + {0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},/*"X",88*/ + {0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00}, + {0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"Y",89*/ + {0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00}, + {0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},/*"Z",90*/ + {0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00}, + {0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00},/*"[",91*/ + {0x00,0x04,0x38,0xC0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00},/*"\",92*/ + {0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00}, + {0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00},/*"]",93*/ + {0x00,0x00,0x04,0x02,0x02,0x04,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",94*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},/*"_",95*/ + {0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",96*/ + {0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00}, + {0x00,0x19,0x24,0x24,0x12,0x3F,0x20,0x00},/*"a",97*/ + {0x10,0xF0,0x00,0x80,0x80,0x00,0x00,0x00}, + {0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},/*"b",98*/ + {0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00}, + {0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},/*"c",99*/ + {0x00,0x00,0x80,0x80,0x80,0x90,0xF0,0x00}, + {0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},/*"d",100*/ + {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00}, + {0x00,0x1F,0x24,0x24,0x24,0x24,0x17,0x00},/*"e",101*/ + {0x00,0x80,0x80,0xE0,0x90,0x90,0x20,0x00}, + {0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"f",102*/ + {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00}, + {0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},/*"g",103*/ + {0x10,0xF0,0x00,0x80,0x80,0x80,0x00,0x00}, + {0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"h",104*/ + {0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00}, + {0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"i",105*/ + {0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00}, + {0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},/*"j",106*/ + {0x10,0xF0,0x00,0x00,0x80,0x80,0x80,0x00}, + {0x20,0x3F,0x24,0x06,0x29,0x30,0x20,0x00},/*"k",107*/ + {0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00}, + {0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"l",108*/ + {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00}, + {0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},/*"m",109*/ + {0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00}, + {0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"n",110*/ + {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00}, + {0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"o",111*/ + {0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00}, + {0x80,0xFF,0x91,0x20,0x20,0x11,0x0E,0x00},/*"p",112*/ + {0x00,0x00,0x00,0x80,0x80,0x00,0x80,0x00}, + {0x00,0x0E,0x11,0x20,0x20,0x91,0xFF,0x80},/*"q",113*/ + {0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00}, + {0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},/*"r",114*/ + {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00}, + {0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},/*"s",115*/ + {0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00}, + {0x00,0x00,0x00,0x1F,0x20,0x20,0x10,0x00},/*"t",116*/ + {0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00}, + {0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},/*"u",117*/ + {0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00}, + {0x00,0x03,0x0C,0x30,0x0C,0x03,0x00,0x00},/*"v",118*/ + {0x80,0x80,0x00,0x80,0x80,0x00,0x80,0x80}, + {0x01,0x0E,0x30,0x0C,0x07,0x38,0x06,0x01},/*"w",119*/ + {0x00,0x80,0x80,0x80,0x00,0x80,0x80,0x00}, + {0x00,0x20,0x31,0x0E,0x2E,0x31,0x20,0x00},/*"x",120*/ + {0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80}, + {0x00,0x81,0x86,0x78,0x18,0x06,0x01,0x00},/*"y",121*/ + {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00}, + {0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},/*"z",122*/ + {0x00,0x00,0x00,0x00,0x00,0xFC,0x02,0x02}, + {0x00,0x00,0x00,0x00,0x01,0x3E,0x40,0x40},/*"{",123*/ + {0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00},/*"|",124*/ + {0x02,0x02,0xFC,0x00,0x00,0x00,0x00,0x00}, + {0x40,0x40,0x3E,0x01,0x00,0x00,0x00,0x00},/*"}",125*/ + {0x00,0x02,0x01,0x02,0x02,0x04,0x02,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",126*/ +}; + + +const unsigned char F12X24 [][12]= +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",32*/ + {0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x00,0x00,0x00,0x00,0x00},/*"!",33*/ + {0x00,0x00,0x00,0xF0,0xF0,0x00,0x00,0xF0,0xF0,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",34*/ + {0x00,0x00,0x00,0x80,0xF0,0x00,0x00,0x00,0xF0,0xF0,0x00,0x00}, + {0xC6,0xC6,0xC6,0xFF,0xC7,0xC6,0xC6,0xF6,0xFF,0xC6,0xC6,0x00}, + {0x00,0x00,0x1F,0x07,0x00,0x00,0x10,0x1F,0x00,0x00,0x00,0x00},/*"#",35*/ + {0x00,0x00,0xC0,0xE0,0x30,0xF8,0x30,0x70,0xE0,0xC0,0x00,0x00}, + {0x00,0x80,0x87,0x0F,0x0C,0xFF,0x38,0x70,0xE1,0xC1,0x00,0x00}, + {0x00,0x03,0x0F,0x0E,0x18,0x7F,0x18,0x1C,0x0F,0x07,0x00,0x00},/*"$",36*/ + {0x00,0xE0,0x30,0x30,0xE0,0x00,0x00,0x00,0xE0,0x10,0x00,0x00}, + {0x00,0x0F,0x18,0x18,0xCF,0x30,0x0C,0xE3,0x30,0x30,0xE0,0x00}, + {0x00,0x00,0x18,0x06,0x01,0x00,0x01,0x0F,0x18,0x18,0x0F,0x00},/*"%",37*/ + {0x00,0x00,0xC0,0xE0,0x30,0x30,0x30,0xE0,0x80,0x00,0x00,0x00}, + {0x00,0xE0,0xF3,0x3F,0x3C,0xFC,0xC6,0x83,0x00,0xE0,0x60,0x00}, + {0x00,0x07,0x0F,0x0C,0x18,0x18,0x19,0x0F,0x07,0x0F,0x0C,0x00},/*"&",38*/ + {0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",39*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0x30,0x18,0x08,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x38,0xFF,0x01,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0E,0x18,0x30,0x20,0x00},/*"(",40*/ + {0x00,0x0C,0x18,0x70,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x60,0x30,0x1C,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*")",41*/ + {0x00,0xC0,0x80,0x00,0x00,0xF0,0xF0,0x00,0x00,0x80,0xC0,0x00}, + {0x00,0x31,0x19,0x1B,0x0F,0xFF,0xFF,0x0F,0x1B,0x19,0x31,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"*",42*/ + {0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00}, + {0x10,0x10,0x10,0x10,0x10,0xFF,0xFF,0x10,0x10,0x10,0x10,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x00,0x00,0x00},/*"+",43*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x5C,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",44*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",45*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x1C,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",46*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x00}, + {0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x07,0x01,0x00,0x00,0x00}, + {0x00,0x18,0x0E,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"/",47*/ + {0x00,0x00,0xC0,0xE0,0x70,0x30,0x30,0x60,0xE0,0xC0,0x00,0x00}, + {0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFE,0x00}, + {0x00,0x01,0x07,0x0E,0x0C,0x18,0x18,0x0C,0x0F,0x07,0x00,0x00},/*"0",48*/ + {0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x03,0x01,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00},/*"1",49*/ + {0x00,0x80,0xE0,0x60,0x30,0x30,0x30,0x70,0xE0,0xC0,0x00,0x00}, + {0x00,0x01,0x01,0x00,0x80,0xC0,0xE0,0x38,0x1F,0x07,0x00,0x00}, + {0x00,0x08,0x0E,0x0F,0x0B,0x09,0x08,0x08,0x08,0x08,0x08,0x00},/*"2",50*/ + {0x00,0x80,0xC0,0x60,0x30,0x30,0x30,0x30,0xE0,0xC0,0x00,0x00}, + {0x00,0x01,0x01,0x00,0x00,0x18,0x18,0x38,0x7F,0xE7,0x80,0x00}, + {0x00,0x03,0x07,0x0C,0x18,0x18,0x18,0x0C,0x0E,0x07,0x01,0x00},/*"3",51*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0x00,0x00,0x00}, + {0x80,0xC0,0xF0,0xB8,0x8E,0x87,0x81,0xFF,0xFF,0x80,0x80,0x80}, + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0F,0x0F,0x01,0x01,0x01},/*"4",52*/ + {0x00,0x00,0xE0,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00}, + {0x00,0x1C,0x1F,0x0D,0x04,0x04,0x0C,0x0C,0x3C,0xF8,0xC0,0x00}, + {0x01,0x07,0x0E,0x08,0x18,0x18,0x18,0x0C,0x0F,0x07,0x00,0x00},/*"5",53*/ + {0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0x30,0x10,0x00,0x00,0x00}, + {0x00,0xE0,0xF8,0x1E,0x0F,0x0D,0x0C,0x0C,0x18,0xF8,0xF0,0x00}, + {0x00,0x03,0x07,0x0C,0x18,0x18,0x18,0x18,0x0C,0x0F,0x03,0x00},/*"6",54*/ + {0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xA0,0xE0,0x60,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0x1E,0x07,0x01,0x00,0x00}, + {0x00,0x00,0x00,0x08,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"7",55*/ + {0x00,0x80,0xE0,0x60,0x30,0x30,0x30,0x20,0xE0,0xC0,0x00,0x00}, + {0x00,0xE3,0xFF,0x3C,0x18,0x18,0x18,0x3C,0x3F,0xE7,0xC0,0x00}, + {0x00,0x07,0x0F,0x0C,0x18,0x18,0x18,0x18,0x0C,0x07,0x03,0x00},/*"8",56*/ + {0x00,0xC0,0xE0,0x60,0x30,0x30,0x30,0x60,0xE0,0xC0,0x00,0x00}, + {0x02,0x1F,0x3D,0x30,0x60,0x60,0xE0,0xF0,0x7F,0x1F,0x03,0x00}, + {0x00,0x00,0x00,0x10,0x1C,0x0F,0x03,0x01,0x00,0x00,0x00,0x00},/*"9",57*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x00,0x00,0x00,0x00,0x00},/*":",58*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0x1C,0x00,0x00,0x00,0x00,0x00},/*";",59*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0x20,0x10,0x00}, + {0x00,0x10,0x38,0x6C,0xC6,0x83,0x01,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x06,0x0C,0x08,0x10,0x00},/*"<",60*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xC2,0xC2,0xC2,0xC2,0xC2,0xC2,0xC2,0xC2,0xC2,0xC2,0xC2,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"=",61*/ + {0x00,0x30,0x20,0x40,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x01,0x83,0xC6,0x6C,0x38,0x10,0x00}, + {0x00,0x18,0x08,0x04,0x02,0x03,0x01,0x00,0x00,0x00,0x00,0x00},/*">",62*/ + {0x00,0x00,0xC0,0xE0,0x70,0x30,0x30,0x60,0xE0,0xC0,0x00,0x00}, + {0x00,0x01,0x01,0x00,0x00,0xE0,0x78,0x1C,0x0F,0x07,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x00,0x00,0x00,0x00,0x00},/*"?",63*/ + {0x00,0x00,0xC0,0x20,0x20,0x10,0x10,0x10,0x20,0x40,0x80,0x00}, + {0x78,0x87,0x00,0xFC,0x0E,0x01,0xC1,0xFF,0x07,0x80,0x7F,0x00}, + {0x00,0x03,0x04,0x09,0x11,0x11,0x10,0x11,0x09,0x01,0x00,0x00},/*"@",64*/ + {0x00,0x00,0x00,0x00,0xC0,0xF0,0xF0,0x80,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xE0,0xFE,0xDF,0xC1,0xC3,0xFF,0xFC,0xC0,0x00,0x00}, + {0x10,0x1F,0x1F,0x01,0x00,0x00,0x00,0x00,0x03,0x1F,0x1E,0x10},/*"A",65*/ + {0x00,0xF0,0xF0,0x30,0x30,0x30,0x20,0x60,0xE0,0xC0,0x00,0x00}, + {0x00,0xFF,0xFF,0x18,0x18,0x18,0x18,0x18,0x3F,0xE7,0xC3,0x00}, + {0x00,0x1F,0x1F,0x18,0x18,0x18,0x18,0x0C,0x0E,0x0F,0x03,0x00},/*"B",66*/ + {0x00,0x00,0xC0,0xE0,0x60,0x30,0x30,0x30,0x60,0xC0,0x80,0x00}, + {0x00,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0xC3,0xC3,0x00}, + {0x00,0x01,0x07,0x0F,0x0C,0x18,0x18,0x18,0x0E,0x07,0x03,0x00},/*"C",67*/ + {0x00,0xF0,0xF0,0x30,0x20,0x20,0x60,0xE0,0xC0,0x80,0x00,0x00}, + {0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x83,0xFF,0xFE,0x00}, + {0x00,0x1F,0x1F,0x18,0x18,0x08,0x0C,0x0E,0x07,0x03,0x00,0x00},/*"D",68*/ + {0x00,0xF0,0xF0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00}, + {0x00,0xFF,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00}, + {0x00,0x1F,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00},/*"E",69*/ + {0x00,0xF0,0xF0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00}, + {0x00,0xFF,0xFF,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00}, + {0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"F",70*/ + {0x00,0x00,0xC0,0xE0,0x60,0x30,0x30,0x60,0xE0,0xC0,0x00,0x00}, + {0x00,0xFF,0xFF,0x01,0x00,0x00,0x30,0x30,0x31,0xF3,0xF3,0x00}, + {0x00,0x01,0x07,0x0F,0x0C,0x18,0x18,0x08,0x0E,0x1F,0x1F,0x00},/*"G",71*/ + {0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00}, + {0x00,0xFF,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xFF,0x00}, + {0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00},/*"H",72*/ + {0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00},/*"I",73*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0x00}, + {0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x7F,0x00}, + {0x00,0x03,0x07,0x0E,0x1C,0x18,0x18,0x0C,0x0F,0x07,0x00,0x00},/*"J",74*/ + {0x00,0xF0,0xF0,0x00,0x00,0x00,0x80,0xC0,0xE0,0x30,0x10,0x00}, + {0x00,0xFF,0xFF,0x38,0x1C,0x3F,0xF3,0xE1,0x80,0x00,0x00,0x00}, + {0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x03,0x0F,0x1E,0x18,0x00},/*"K",75*/ + {0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x1F,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00},/*"L",76*/ + {0x00,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x80,0xF0,0xF0,0xF0,0x00}, + {0x00,0xFF,0xFF,0x0F,0xFF,0xE0,0xE0,0xFF,0x07,0xFF,0xFF,0x00}, + {0x00,0x1F,0x1F,0x00,0x01,0x1F,0x1F,0x00,0x00,0x1F,0x1F,0x00},/*"M",77*/ + {0x00,0xF0,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00}, + {0x00,0xFF,0xFF,0x03,0x0F,0x3C,0xF0,0xC0,0x00,0xFF,0xFF,0x00}, + {0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x07,0x1F,0x1F,0x1F,0x00},/*"N",78*/ + {0x00,0x80,0xC0,0xE0,0x70,0x30,0x30,0x60,0xE0,0xC0,0x00,0x00}, + {0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00}, + {0x00,0x03,0x07,0x0E,0x1C,0x18,0x18,0x0C,0x0F,0x07,0x01,0x00},/*"O",79*/ + {0x00,0xF0,0xF0,0x30,0x30,0x30,0x20,0x60,0x60,0xC0,0x80,0x00}, + {0x00,0xFF,0xFF,0x30,0x30,0x30,0x30,0x30,0x38,0x1F,0x0F,0x00}, + {0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"P",80*/ + {0x00,0x80,0xC0,0xE0,0x70,0x30,0x30,0x60,0xE0,0xC0,0x00,0x00}, + {0x00,0xFF,0xFF,0x00,0x00,0x00,0x80,0x80,0x01,0xFF,0xFF,0x00}, + {0x00,0x03,0x07,0x0E,0x1C,0x18,0x19,0x0F,0x1F,0x1F,0x01,0x00},/*"Q",81*/ + {0x00,0xF0,0xF0,0x30,0x30,0x30,0x20,0x60,0xE0,0xC0,0x80,0x00}, + {0x00,0xFF,0xFF,0x30,0x30,0x30,0x70,0xF8,0x9C,0x0F,0x07,0x00}, + {0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x01,0x0F,0x1E,0x18,0x00},/*"R",82*/ + {0x00,0x80,0xC0,0xE0,0x30,0x30,0x30,0x60,0xE0,0xC0,0x00,0x00}, + {0x00,0x83,0x87,0x0E,0x1C,0x18,0x38,0x30,0x71,0xE1,0xC0,0x00}, + {0x00,0x07,0x0F,0x0C,0x18,0x18,0x18,0x18,0x0E,0x07,0x03,0x00},/*"S",83*/ + {0x00,0x30,0x30,0x30,0x30,0xF0,0xF0,0x30,0x30,0x30,0x30,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00},/*"T",84*/ + {0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00}, + {0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00}, + {0x00,0x03,0x0F,0x0C,0x18,0x18,0x18,0x1C,0x0E,0x0F,0x03,0x00},/*"U",85*/ + {0x30,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xF0,0x00}, + {0x00,0x01,0x1F,0xFF,0xF0,0x00,0x80,0xF8,0x7F,0x07,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x07,0x1F,0x1F,0x03,0x00,0x00,0x00,0x00},/*"V",86*/ + {0xF0,0xF0,0x00,0x00,0x80,0xF0,0xF0,0x00,0x00,0xF0,0xF0,0x10}, + {0x00,0xFF,0xFF,0xC0,0xFF,0x03,0x1F,0xFE,0xC0,0xFF,0x1F,0x00}, + {0x00,0x00,0x1F,0x1F,0x01,0x00,0x00,0x0F,0x1F,0x0F,0x00,0x00},/*"W",87*/ + {0x00,0x30,0xF0,0xE0,0x00,0x00,0x00,0x80,0xE0,0x70,0x10,0x00}, + {0x00,0x00,0x00,0x83,0xEF,0x7C,0x7E,0xE7,0x81,0x00,0x00,0x00}, + {0x10,0x1C,0x1F,0x07,0x01,0x00,0x00,0x01,0x0F,0x1E,0x18,0x00},/*"X",88*/ + {0x10,0x70,0xF0,0x80,0x00,0x00,0x00,0x00,0xC0,0xF0,0x30,0x00}, + {0x00,0x00,0x01,0x07,0x1E,0xF8,0xFC,0x0F,0x03,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00},/*"Y",89*/ + {0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xF0,0xF0,0x30,0x00}, + {0x00,0x00,0x00,0xC0,0xE0,0x78,0x1E,0x07,0x03,0x00,0x00,0x00}, + {0x00,0x1C,0x1F,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00},/*"Z",90*/ + {0x00,0x00,0x00,0x00,0x00,0xFC,0x0C,0x0C,0x0C,0x0C,0x0C,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7F,0x60,0x60,0x60,0x60,0x60,0x00},/*"[",91*/ + {0x00,0x10,0x70,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x03,0x0F,0x78,0xE0,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x3C,0x60,0x00,0x00},/*"\",92*/ + {0x00,0x0C,0x0C,0x0C,0x0C,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x60,0x60,0x60,0x60,0x7F,0x7F,0x00,0x00,0x00,0x00,0x00},/*"]",93*/ + {0x00,0x20,0x30,0x18,0x0C,0x04,0x0C,0x1C,0x18,0x20,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",94*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},/*"_",95*/ + {0x00,0x00,0x00,0x00,0x04,0x0C,0x38,0x30,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",96*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x98,0x9C,0xCC,0xCC,0xCC,0x4C,0xFC,0xF8,0x00,0x00}, + {0x00,0x07,0x0F,0x19,0x18,0x18,0x08,0x0C,0x0F,0x1F,0x10,0x00},/*"a",97*/ + {0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xFF,0xFF,0x18,0x0C,0x04,0x0C,0x0C,0x7C,0xF8,0xC0,0x00}, + {0x00,0x1F,0x1F,0x0C,0x08,0x18,0x18,0x1C,0x0F,0x07,0x01,0x00},/*"b",98*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xF0,0xF8,0x1C,0x0C,0x0C,0x0C,0x0C,0x3C,0x38,0x00,0x00}, + {0x00,0x03,0x07,0x0C,0x18,0x18,0x18,0x18,0x0E,0x07,0x03,0x00},/*"c",99*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x00}, + {0x00,0xF0,0xF8,0x1C,0x0C,0x04,0x0C,0x0C,0xFF,0xFF,0x00,0x00}, + {0x00,0x03,0x0F,0x0C,0x18,0x18,0x18,0x0C,0x1F,0x1F,0x00,0x00},/*"d",100*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xE0,0xF8,0x5C,0x4C,0x44,0x44,0x4C,0x7C,0x78,0x40,0x00}, + {0x00,0x03,0x07,0x0C,0x18,0x18,0x18,0x18,0x0E,0x06,0x02,0x00},/*"e",101*/ + {0x00,0x00,0x00,0x00,0xC0,0xE0,0x20,0x30,0x30,0x30,0x60,0x00}, + {0x00,0x0C,0x0C,0x0C,0xFF,0xFF,0x0C,0x0C,0x0C,0x0C,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00},/*"f",102*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xF8,0xFC,0x8C,0x04,0x8C,0xFC,0xFC,0x04,0x04,0x00}, + {0x00,0x72,0xF7,0xCD,0x8D,0x8D,0x8D,0x89,0xC8,0x78,0x30,0x00},/*"g",103*/ + {0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xFF,0xFF,0x30,0x08,0x0C,0x04,0x0C,0x1C,0xF8,0xE0,0x00}, + {0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00},/*"h",104*/ + {0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00},/*"i",105*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x00,0x00,0x00}, + {0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0x7F,0x3F,0x00,0x00,0x00},/*"j",106*/ + {0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xFF,0xFF,0xC0,0xE0,0x70,0xF8,0x9C,0x0C,0x04,0x00,0x00}, + {0x00,0x1F,0x1F,0x01,0x00,0x00,0x01,0x03,0x0E,0x1C,0x10,0x00},/*"k",107*/ + {0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00},/*"l",108*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xFC,0xFC,0x18,0x0C,0x0C,0xFC,0xF8,0x08,0x0C,0x0C,0xFC,0x00}, + {0x1F,0x1F,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x1F,0x00},/*"m",109*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xFC,0xFC,0x30,0x08,0x0C,0x04,0x0C,0x1C,0xF8,0xE0,0x00}, + {0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00},/*"n",110*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xF0,0xF8,0x1C,0x0C,0x0C,0x0C,0x0C,0x18,0xF8,0xE0,0x00}, + {0x00,0x03,0x07,0x0C,0x18,0x18,0x18,0x0C,0x0E,0x07,0x03,0x00},/*"o",111*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xFC,0xFC,0x18,0x0C,0x0C,0x0C,0x0C,0x78,0xF8,0xC0,0x00}, + {0x00,0xFF,0xFF,0x0C,0x08,0x18,0x18,0x1C,0x0F,0x07,0x01,0x00},/*"p",112*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xF0,0xF8,0x1C,0x0C,0x0C,0x0C,0x0C,0xFC,0xFC,0x00,0x00}, + {0x00,0x03,0x0F,0x0C,0x18,0x18,0x18,0x0C,0xFF,0xFF,0x00,0x00},/*"q",113*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFC,0xFC,0x70,0x18,0x08,0x0C,0x0C,0x00,0x00,0x00}, + {0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"r",114*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x78,0x7C,0xCC,0xC4,0xC4,0x8C,0x9C,0x18,0x00,0x00}, + {0x00,0x00,0x0E,0x0C,0x18,0x18,0x18,0x18,0x0F,0x0F,0x00,0x00},/*"s",115*/ + {0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x0C,0x0C,0x0C,0xFF,0xFF,0x0C,0x0C,0x0C,0x0C,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x07,0x0F,0x18,0x18,0x18,0x18,0x00,0x00},/*"t",116*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x00}, + {0x00,0x07,0x0F,0x1C,0x18,0x18,0x08,0x0C,0x07,0x1F,0x1F,0x00},/*"u",117*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x0C,0x7C,0xF0,0x80,0x00,0x00,0xC0,0xF8,0x3C,0x04,0x00}, + {0x00,0x00,0x00,0x01,0x0F,0x1C,0x1E,0x07,0x00,0x00,0x00,0x00},/*"v",118*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x0C,0xFC,0xE0,0x00,0xF0,0x3C,0xFC,0xC0,0x00,0xFC,0x7C,0x00}, + {0x00,0x00,0x1F,0x1E,0x07,0x00,0x00,0x1F,0x1F,0x07,0x00,0x00},/*"w",119*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x04,0x0C,0x1C,0xF0,0xE0,0xE0,0x38,0x1C,0x04,0x00,0x00}, + {0x00,0x10,0x1C,0x0E,0x03,0x01,0x03,0x07,0x0E,0x18,0x10,0x00},/*"x",120*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x0C,0x7C,0xF0,0x80,0x00,0x00,0xC0,0xF8,0x3C,0x04,0x00}, + {0x00,0x00,0xC0,0xC1,0xCF,0x7E,0x3E,0x07,0x00,0x00,0x00,0x00},/*"y",121*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x0C,0x0C,0x8C,0xCC,0xEC,0x3C,0x1C,0x0C,0x00,0x00}, + {0x00,0x18,0x1C,0x1F,0x1B,0x19,0x18,0x18,0x18,0x18,0x00,0x00},/*"z",122*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0C,0x04,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x38,0xFF,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x60,0x40,0x00,0x00},/*"{",123*/ + {0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00},/*"|",124*/ + {0x00,0x04,0x04,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0xCF,0xFF,0x30,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x40,0x40,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",125*/ + {0x00,0x08,0x0C,0x06,0x06,0x06,0x0C,0x18,0x18,0x0C,0x06,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",126*/ +}; + + +#endif + + diff --git a/Third-party-design/PageVersion/ProjectExamples/Air001/Air001_Demo.zip b/Third-party-design/PageVersion/ProjectExamples/Air001/Air001_Demo.zip new file mode 100644 index 0000000..b745ae2 Binary files /dev/null and b/Third-party-design/PageVersion/ProjectExamples/Air001/Air001_Demo.zip differ diff --git a/Third-party-design/PageVersion/ProjectExamples/Air001/Port_C_SPI/oled_port.c b/Third-party-design/PageVersion/ProjectExamples/Air001/Port_C_SPI/oled_port.c new file mode 100644 index 0000000..4e9e016 --- /dev/null +++ b/Third-party-design/PageVersion/ProjectExamples/Air001/Port_C_SPI/oled_port.c @@ -0,0 +1,142 @@ +#include "oled_port.h" +#include "string.h" +#include "air001xx.h" +#include "air001xx_ll_spi.h" +#include "air001xx_ll_bus.h" +#include "air001xx_ll_gpio.h" +#include "air001xx_ll_utils.h" + +#define OLED_CMD 0 +#define OLED_DATA 1 + +#define RES_PORT GPIOA +#define RES_PIN LL_GPIO_PIN_4 +#define DC_PORT GPIOA +#define DC_PIN LL_GPIO_PIN_6 +#define SCK_PORT GPIOA +#define SCK_PIN LL_GPIO_PIN_5 +#define SDI_PORT GPIOA +#define SDI_PIN LL_GPIO_PIN_7 + +__STATIC_INLINE void OLED_RES_Set(void) +{ + WRITE_REG(RES_PORT->BSRR, READ_REG(RES_PORT->BSRR) | RES_PIN); +} +__STATIC_INLINE void OLED_DC_Set(void) +{ + WRITE_REG(DC_PORT->BSRR, READ_REG(DC_PORT->BSRR) | DC_PIN); +} +__STATIC_INLINE void OLED_RES_Clr(void) +{ + WRITE_REG(RES_PORT->BRR, READ_REG(RES_PORT->BRR) | RES_PIN); +} +__STATIC_INLINE void OLED_DC_Clr(void) +{ + WRITE_REG(DC_PORT->BRR, READ_REG(DC_PORT->BRR) | DC_PIN); +} + + +static void OLED_SPIRstDCPinInit(void) +{ + LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); //使能GPIOA的时钟 + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = RES_PIN|DC_PIN; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + // GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; + // GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; //输出推挽就可以 + LL_GPIO_Init(RES_PORT,&GPIO_InitStruct); + + GPIO_InitStruct.Pin = SCK_PIN|SDI_PIN; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + // GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; //默认初始化为0,就是NO + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(SCK_PORT,&GPIO_InitStruct); +} + + +static void OLED_WriteByte(uint8_t dat, uint8_t cORd) +{ + if(cORd) OLED_DC_Set(); + else OLED_DC_Clr(); + LL_SPI_TransmitData8(SPI1,dat); + while(!LL_SPI_IsActiveFlag_TXE(SPI1))OLED_LOG("hw spi send fail!"); + OLED_DC_Set(); +} + +static void OLED_WriteByteArrayData(uint8_t * data_array,uint16_t len) +{ + OLED_DC_Set(); + for(uint8_t i = 0; i < len; i++) + { + LL_SPI_TransmitData8(SPI1,data_array[i]); + while(!LL_SPI_IsActiveFlag_TXE(SPI1))OLED_LOG("HW SPI SEND FAIL"); + } +} + + +void OLED_Init(void) +{ + LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SPI1); + LL_SPI_InitTypeDef SPI_InitStruct = {0}; + // LL_SPI_StructInit(&SPI_InitStruct); //默认初始化 + // //全双工、从机、8bit、时钟极性低、第一个时钟边沿采数据、硬件NSS、波特率2分频、MSB、normal speed + // SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; //全双工 + // SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT; //8bit + // SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; //MSB //这三个参数在初始化是就是0,设置也是0,因此不需要重复设置 + SPI_InitStruct.Mode = LL_SPI_MODE_MASTER; //主机 + SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH; //极性高 + SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; //第2个时钟延采样 + SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; //软件NSS + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4; //4分频 + LL_SPI_Init(SPI1,&SPI_InitStruct); + LL_SPI_Enable(SPI1); + + OLED_SPIRstDCPinInit(); + LL_mDelay(300); + OLED_RES_Clr(); + LL_mDelay(300); + OLED_RES_Set(); + + OLED_WriteByte(0xAE,OLED_CMD);//--turn off oled panel + OLED_WriteByte(0x00,OLED_CMD);//---set low column address + OLED_WriteByte(0x10,OLED_CMD);//---set high column address + OLED_WriteByte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) + OLED_WriteByte(0x81,OLED_CMD);//--set contrast control register + OLED_WriteByte(0xCF,OLED_CMD);// Set SEG Output Current Brightness + OLED_WriteByte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 + OLED_WriteByte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 + OLED_WriteByte(0xA6,OLED_CMD);//--set normal display + OLED_WriteByte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64) + OLED_WriteByte(0x3f,OLED_CMD);//--1/64 duty + OLED_WriteByte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) + OLED_WriteByte(0x00,OLED_CMD);//-not offset + OLED_WriteByte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency + OLED_WriteByte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec + OLED_WriteByte(0xD9,OLED_CMD);//--set pre-charge period + OLED_WriteByte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock + OLED_WriteByte(0xDA,OLED_CMD);//--set com pins hardware configuration + OLED_WriteByte(0x12,OLED_CMD); + OLED_WriteByte(0xDB,OLED_CMD);//--set vcomh + OLED_WriteByte(0x40,OLED_CMD);//Set VCOM Deselect Level + OLED_WriteByte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02) + OLED_WriteByte(0x02,OLED_CMD);// + OLED_WriteByte(0x8D,OLED_CMD);//--set Charge Pump enable/disable + OLED_WriteByte(0x14,OLED_CMD);//--set(0x10) disable + OLED_WriteByte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5) + OLED_WriteByte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) + //OLED_SPIFill(0x00); + OLED_WriteByte(0xAF,OLED_CMD); +} + + +void OLED_SendBuff(uint8_t buff[8][128]) +{ + for(uint8_t i=0;i<8;i++) + { + OLED_WriteByte (0xb0+i,OLED_CMD); //设置页地址(0~7)(b0-b7) + OLED_WriteByte (0x00,OLED_CMD); //设置显示位置—列低地址 + OLED_WriteByte (0x10,OLED_CMD); //设置显示位置—列高地址 + OLED_WriteByteArrayData(buff[i],128); //写一页128个字符 + } //更新显示 +} diff --git a/Third-party-design/PageVersion/ProjectExamples/README.md b/Third-party-design/PageVersion/ProjectExamples/README.md new file mode 100644 index 0000000..52c08d4 --- /dev/null +++ b/Third-party-design/PageVersion/ProjectExamples/README.md @@ -0,0 +1,13 @@ +# 本文件夹的一些小说明 + +## 文件目录 + +```c +|---Air001(使用air001作为主控,SSD1306为OLED驱动器的 WouoUIPage版工程) + |---Port_C_SPI(SPI驱动的底层代码文件`oled_port.c`) + |---Air001_Demo.zip(完整工程文件的压缩包,包含TestUI和LittleClok两个例子) +|---Stm32(使用Stm32作为主控,SSD1306为OLED驱动器的 WouoUIPage版工程) + |---STM32_HWSPI_TestUI.zip(完整工程文件的压缩包,固件库,TestUI例子,使用硬件SPI) + |---Port_C_SPI_STD(Stm32标准固件库硬件spi的底层驱动文件`oled_port.c`) +``` + diff --git a/Third-party-design/PageVersion/ProjectExamples/Stm32/Port_C_SPI_STD/oled_port.c b/Third-party-design/PageVersion/ProjectExamples/Stm32/Port_C_SPI_STD/oled_port.c new file mode 100644 index 0000000..022b565 --- /dev/null +++ b/Third-party-design/PageVersion/ProjectExamples/Stm32/Port_C_SPI_STD/oled_port.c @@ -0,0 +1,150 @@ +#include "oled_port.h" +#include "string.h" +#include "stm32f10x.h" +#include "main.h" + +#define SCL_PORT GPIOA +#define SCL_PIN GPIO_Pin_5 +#define SDA_PORT GPIOA +#define SDA_PIN GPIO_Pin_7 +#define RES_PORT GPIOB +#define RES_PIN GPIO_Pin_0 +#define DC_PORT GPIOB +#define DC_PIN GPIO_Pin_1 + +#define OLED_CMD 0 +#define OLED_DATA 1 + +void delay(uint8_t i) +{ + i = i*5; + while(i--){} +} + +static void OLED_RES_Set(void) +{ + GPIO_WriteBit(RES_PORT, RES_PIN, Bit_SET); +} +static void OLED_DC_Set(void) +{ + GPIO_WriteBit(DC_PORT , DC_PIN, Bit_SET); +} +static void OLED_RES_Clr(void) +{ + GPIO_WriteBit(RES_PORT, RES_PIN, Bit_RESET); +} +static void OLED_DC_Clr(void) +{ + GPIO_WriteBit(DC_PORT, DC_PIN, Bit_RESET); +} + + +static void OLED_SPIRstDCPinInit(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//GPIOB + GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Pin= DC_PIN|RES_PIN; + GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; + GPIO_Init(DC_PORT, &GPIO_InitStructure); + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIOA + GPIO_InitStructure.GPIO_Pin = SCL_PIN | SDA_PIN ; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(SCL_PORT, &GPIO_InitStructure); +} + + +static void OLED_WriteByte(uint8_t dat, uint8_t cORd) +{ + if(cORd) OLED_DC_Set(); + else OLED_DC_Clr(); + /* Loop while DR register in not emplty */ + while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); + /* Send byte through the SPI1 peripheral */ + SPI_I2S_SendData(SPI1, dat); + delay(5); + OLED_DC_Set(); +} + +static void OLED_WriteByteArrayData(uint8_t * data_array,uint16_t len) +{ + OLED_DC_Set(); + for(uint8_t i = 0; i < len; i++) + { + /* Loop while DR register in not emplty */ + while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); + /* Send byte through the SPI1 peripheral */ + SPI_I2S_SendData(SPI1, data_array[i]); + delay(5); + } +} + + +void OLED_Init(void) +{ + OLED_SPIRstDCPinInit(); + + RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE); + SPI_InitTypeDef SPI_InitStructure; + SPI_SSOutputCmd(SPI1, ENABLE); + SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; + SPI_InitStructure.SPI_Mode = SPI_Mode_Master; + SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; + SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; + SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; + SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; + SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; + SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; + SPI_InitStructure.SPI_CRCPolynomial = 7; + SPI_Init(SPI1, &SPI_InitStructure); + SPI_Cmd(SPI1, ENABLE); + + delay_ms(300); + OLED_RES_Clr(); + delay_ms(300); + OLED_RES_Set(); + + OLED_WriteByte(0xAE,OLED_CMD);//--turn off oled panel + OLED_WriteByte(0x00,OLED_CMD);//---set low column address + OLED_WriteByte(0x10,OLED_CMD);//---set high column address + OLED_WriteByte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) + OLED_WriteByte(0x81,OLED_CMD);//--set contrast control register + OLED_WriteByte(0xCF,OLED_CMD);// Set SEG Output Current Brightness + OLED_WriteByte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 + OLED_WriteByte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 + OLED_WriteByte(0xA6,OLED_CMD);//--set normal display + OLED_WriteByte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64) + OLED_WriteByte(0x3f,OLED_CMD);//--1/64 duty + OLED_WriteByte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) + OLED_WriteByte(0x00,OLED_CMD);//-not offset + OLED_WriteByte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency + OLED_WriteByte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec + OLED_WriteByte(0xD9,OLED_CMD);//--set pre-charge period + OLED_WriteByte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock + OLED_WriteByte(0xDA,OLED_CMD);//--set com pins hardware configuration + OLED_WriteByte(0x12,OLED_CMD); + OLED_WriteByte(0xDB,OLED_CMD);//--set vcomh + OLED_WriteByte(0x40,OLED_CMD);//Set VCOM Deselect Level + OLED_WriteByte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02) + OLED_WriteByte(0x02,OLED_CMD);// + OLED_WriteByte(0x8D,OLED_CMD);//--set Charge Pump enable/disable + OLED_WriteByte(0x14,OLED_CMD);//--set(0x10) disable + OLED_WriteByte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5) + OLED_WriteByte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) + //OLED_SPIFill(0x00); + OLED_WriteByte(0xAF,OLED_CMD); +} + + +void OLED_SendBuff(uint8_t buff[8][128]) +{ + for(uint8_t i=0;i<8;i++) + { + OLED_WriteByte (0xb0+i,OLED_CMD); //设置页地址(0~7)(b0-b7) + OLED_WriteByte (0x00,OLED_CMD); //设置显示位置—列低地址 + OLED_WriteByte (0x10,OLED_CMD); //设置显示位置—列高地址 + OLED_WriteByteArrayData(buff[i],128); //写一页128个字符 + } //更新显示 +} diff --git a/Third-party-design/PageVersion/ProjectExamples/Stm32/STM32_HWSPI_TestUI.zip b/Third-party-design/PageVersion/ProjectExamples/Stm32/STM32_HWSPI_TestUI.zip new file mode 100644 index 0000000..87ea151 Binary files /dev/null and b/Third-party-design/PageVersion/ProjectExamples/Stm32/STM32_HWSPI_TestUI.zip differ diff --git a/Third-party-design/PageVersion/README.md b/Third-party-design/PageVersion/README.md new file mode 100644 index 0000000..96b6dad --- /dev/null +++ b/Third-party-design/PageVersion/README.md @@ -0,0 +1,27 @@ +# WouoUI Page 版 + +## 作者 + +Sheep118 + +## 说明 +这是一个改动自WouoUI的纯C语言,无依赖库,只适用于128*64OLED的代码框架,将WouoUI抽象出一部分统一的接口,以方便快速构建一个具有类似WouoUI风格的OLEDUI。只需要使用简单的初始化函数便可以创建一个具有WouoUI风格的丝滑OLED动画的UI。 + +具体的接口函数说明请参考下面仓库里的README文件 + +[https://github.com/Sheep118/WouoUI-PageVersion](https://github.com/Sheep118/WouoUI-PageVersion) + +## 本文件夹结构 + +```c +|---Csource + |---src (这个文件夹是WouoUIPage最主要的源代码文件,移植时主要用这里面的几个文件) + |---example (这个是使用WouoUIPage所提供的接口构建的一些应用的例子,只有对应.c.h文件) +|---ProjectExamples (这个文件夹内放着使用WouoUIPage的工程的参考,按主控的类型划分,为移植时提供一些参考,所有工程文件均以zip压缩包上传到对应文件夹中) + |---Air001(Air001的工程压缩包和底层的接口文件示例) + |---Stm32(Stm32的工程压缩包和底层的接口文件示例) +``` + +## 开源协议 + +本项目(WouoUI Page版)遵循 MPL2.0开源协议,使用者可以在遵守MPL2.0开源协议的情况下,自由使用、修改本项目的开源代码。