diff --git a/WouoUI/WouoUI.ino b/WouoUI/WouoUI.ino deleted file mode 100644 index 775cf88..0000000 --- a/WouoUI/WouoUI.ino +++ /dev/null @@ -1,464 +0,0 @@ -/* - 此程序用于实现稚晖君MonoUI风格的超丝滑菜单,使用0.96寸OLED显示,EC11旋转编码器控制。 - - UI示例是从我的另一个项目简化而来,只保留了列表部分,简化了添加和修改列表的操作,如需更多功能,请参考原项目:https://github.com/RQNG/Rapid-trigger-minipad - - 当前版本 v 1.0 - - 示例实现了以下功能: - - * 休眠模式扫描,同时可旋转旋钮 - * 休眠模式下点按旋钮停止扫描,进入主菜单 - * 主菜单下,旋转旋钮滚动列表,点按选择列表 - * 列表长度无限制 - * 动画速度可调,1 - 无穷大,数字越小动画速度越快,1没有动画,不支持小于1的数值 - - 推荐把返回选项放在开头,个人认为体验比较好。 - - 项目参考: - - * 旋钮功能:https://zhuanlan.zhihu.com/p/453130384 - * UI:https://www.bilibili.com/video/BV1HA411S7pv/ ; https://www.bilibili.com/video/BV1xd4y1C7BE/ - - 本项目使用Apache 2.0开源协议,如需商用或借鉴,请阅读此协议。 - - 欢迎关注我的B站账号,一个只分享osu!相关内容,很无聊的帐号。 - - 用户名:音游玩的人,B站主页:https://space.bilibili.com/9182439?spm_id_from=..0.0 -*/ - -/************************************* 旋钮相关 *************************************/ - -#define AIO PB12 -#define BIO PB13 -#define SW PB14 -#define DEBOUNCE 50 - -uint8_t btn_id = 0; -uint8_t btn_flag = 0; -bool btn_val = false; -bool btn_val_last = false; -bool btn_pressed = false; -bool CW_1 = false; -bool CW_2 = false; - -void btn_inter() -{ - bool alv = digitalRead(AIO); - bool blv = digitalRead(BIO); - if (btn_flag == 0 && alv == LOW) - { - CW_1 = blv; - btn_flag = 1; - } - if (btn_flag && alv) - { - CW_2 = !blv; - if (CW_1 && CW_2) - { - btn_id = 0; - btn_pressed = true; - } - if (CW_1 == false && CW_2 == false) - { - btn_id = 1; - btn_pressed = true; - } - btn_flag = 0; - } -} - -void btn_init() -{ - pinMode(AIO, INPUT); - pinMode(BIO, INPUT); - pinMode(SW, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(AIO), btn_inter, CHANGE); -} - -void btn_scan() -{ - btn_val = digitalRead(SW); - if (btn_val != btn_val_last) - { - delay(DEBOUNCE); - btn_val_last = btn_val; - if (btn_val == LOW) - { - btn_pressed = true; - btn_id = 2; - } - } -} - -/************************************* 屏幕和UI *************************************/ - -#include -#include - -#define SCL PB6 -#define SDA PB7 -#define RST U8X8_PIN_NONE - -U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, SCL, SDA, RST); - -//状态 -enum -{ - S_NONE, - S_DISAPPEAR, -}; - -//菜单结构体 -typedef struct MENU -{ - char *select; -} SELECT_LIST; - -//UI变量 -uint8_t ui_index; //目录变量 -uint8_t ui_state; //状态变量 -uint8_t *buf_ptr; //指向buf首地址的指针 -uint16_t buf_len; //buf的长度 -bool sleep_flag = true; //休眠标志 -uint8_t disappear_step = 1; //消失步数 - -/********************************** 需要修改的东西 ***********************************/ - -//UI参数 -#define SPEED 6 //动画速度,越小越快,1没有动画 -#define PAGES 4 //页面数量,列表类页面的总数量 - -#define ui_select 0 -#define x 1 -#define y 2 -#define y_trg 3 -#define box_width 4 -#define box_width_trg 5 -#define box_y 6 -#define box_y_trg 7 -#define num 8 -#define line_y 9 -#define line_y_trg 10 -int16_t ui_param[11][PAGES]; - -//目录 -enum -{ - M_SLEEP, - M_MAIN, - M_NUMB, - M_ALPH, -}; - -//主菜单内容 -SELECT_LIST m_main[] -{ - {"<< Sleep"}, - {"- Number"}, - {"- 1"}, - {"- 11"}, - {"- 111"}, - {"- 1111"}, - {"- 11111"}, - {"- 111111"}, - {"- 1111111"}, - {"- 11111111"}, - {"- 111111111"}, - {"- 1111111111"}, - {"- 1"}, - {"- 1111111111"}, - {"- 1"}, - {"- 1111111111"}, - {"- 1"}, - {"- 1111111111"}, - {"- 1"}, - {"- 1111111111"}, - {"- 1"}, - {"- 1111111111"}, - {"- 1"}, - {"- 1111111111"}, - {"- 1"}, -}; - -//数字菜单内容 -SELECT_LIST m_numb[] -{ - {"<< Main"}, - {"- 0"}, - {"- 1"}, - {"- 2"}, - {"- 3"}, - {"- 4"}, - {"- 5"}, - {"- 6"}, - {"- 7"}, - {"- 8"}, - {"- 9"}, -}; - -//睡眠页面处理函数 -void sleep_proc() -{ - //在这里执行功能 - while (sleep_flag) - { - //需要扫描的功能 - Serial.println("Scan"); - - //旋钮扫描 - btn_scan(); - if (btn_pressed) - { - btn_pressed = false; - switch (btn_id) - { - case 0: - //睡眠时顺时针旋转功能 - Serial.println("Clockwise"); - break; - - case 1: - //睡眠时逆时针旋转功能 - Serial.println("Anticlockwise"); - break; - - case 2: - ui_index = M_MAIN; - ui_state = S_NONE; - sleep_flag = false; - u8g2.setPowerSave(0); - break; - - default: break; - } - } - } -} - -//主菜单处理函数 -void main_proc() -{ - if (btn_pressed) - { - btn_pressed = false; - switch (btn_id) - { - case 0: - case 1: - rotate_switch(M_MAIN); - break; - - case 2: - switch (ui_param[ui_select][M_MAIN]) - { - case 0: - ui_index = M_SLEEP; - ui_state = S_NONE; - u8g2.setPowerSave(1); - sleep_flag = true; - break; - - case 1: - ui_index = M_NUMB; - ui_state = S_DISAPPEAR; - break; - - default: break; - } - - default: break; - } - ui_param[box_width_trg][M_MAIN] = u8g2.getStrWidth(m_main[ui_param[ui_select][M_MAIN]].select) + ui_param[x][M_MAIN] * 2; - } - menu_ui_show(m_main, M_MAIN); -} - -//数字菜单处理函数 -void numb_proc() -{ - if (btn_pressed) - { - btn_pressed = false; - switch (btn_id) - { - case 0: - case 1: - rotate_switch(M_NUMB); - break; - - case 2: - switch (ui_param[ui_select][M_NUMB]) - { - case 0: - ui_index = M_MAIN; - ui_state = S_DISAPPEAR; - break; - - default: break; - } - - default: break; - } - ui_param[box_width_trg][M_NUMB] = u8g2.getStrWidth(m_numb[ui_param[ui_select][M_NUMB]].select) + ui_param[x][M_NUMB] * 2; - } - menu_ui_show(m_numb, M_NUMB); -} - -//总的UI进程 -void ui_proc() -{ - switch (ui_state) - { - case S_NONE: - u8g2.clearBuffer(); - switch (ui_index) - { - //目录里所有页面都要放在这里 - - case M_SLEEP: - sleep_proc(); - break; - - case M_MAIN: - main_proc(); - break; - - case M_NUMB: - numb_proc(); - break; - - default: break; - } - break; - - case S_DISAPPEAR: - disappear(); - break; - - default: break; - } - u8g2.sendBuffer(); -} - -//ui初始化 -void ui_init() -{ - for(int i = 0 ; i < PAGES ; i++) - { - ui_param[ui_select][i] = 0; - ui_param[x][i] = 4; - ui_param[y][i] = 0; - ui_param[y_trg][i] = 0; - } - - ui_index = M_SLEEP; - ui_state = S_NONE; - - //主菜单 - ui_param[box_width][M_MAIN] = ui_param[box_width_trg][M_MAIN] = u8g2.getStrWidth(m_main[ui_param[ui_select][M_MAIN]].select) + ui_param[x][M_MAIN] * 2; - ui_param[num][M_MAIN] = sizeof(m_main) / sizeof(SELECT_LIST); - - //数字菜单 - ui_param[box_width][M_NUMB] = ui_param[box_width_trg][M_NUMB] = u8g2.getStrWidth(m_numb[ui_param[ui_select][M_NUMB]].select) + ui_param[x][M_NUMB] * 2; - ui_param[num][M_NUMB] = sizeof(m_numb) / sizeof(SELECT_LIST); -} - -/************************************* 动画函数 *************************************/ - -//移动函数 -void move(int16_t *a, int16_t *a_trg) -{ - if (*a < *a_trg) *a += ceil(fabs((float)(*a_trg - *a) / SPEED)); - else if (*a > *a_trg) *a -= ceil(fabs((float)(*a_trg - *a) / SPEED)); -} - -//消失函数 -void disappear() -{ - switch (disappear_step) - { - case 1: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 == 0) buf_ptr[i] = buf_ptr[i] & 0x55; break; - case 2: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 != 0) buf_ptr[i] = buf_ptr[i] & 0xAA; break; - case 3: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 == 0) buf_ptr[i] = buf_ptr[i] & 0x00; break; - case 4: for (uint16_t i = 0; i < buf_len; ++i) if (i % 2 != 0) buf_ptr[i] = buf_ptr[i] & 0x00; break; - - default: ui_state = S_NONE; disappear_step = 0; break; - } - disappear_step++; -} - -/************************************* 显示函数 *************************************/ - -//列表类页面通用显示函数 -void menu_ui_show(struct MENU arr[], int16_t n) -{ - for(uint8_t i = 0 ; i < ui_param[num][n] ; ++i) u8g2.drawStr(ui_param[x][n], 16 * i + ui_param[y][n] + 12, arr[i].select); - - ui_param[line_y_trg][n] = ceil((ui_param[ui_select][n]) * ((float)64 / (ui_param[num][n] - 1))); - ui_param[box_width_trg][n] = u8g2.getStrWidth(arr[ui_param[ui_select][n]].select) + 8; - - move(&ui_param[y][n], &ui_param[y_trg][n]); - move(&ui_param[box_y][n], &ui_param[box_y_trg][n]); - move(&ui_param[box_width][n], &ui_param[box_width_trg][n]); - move(&ui_param[line_y][n], &ui_param[line_y_trg][n]); - - u8g2.drawBox(125, 0, 3, ui_param[line_y][n]); - u8g2.setDrawColor(2); - u8g2.drawRBox(0, ui_param[box_y][n], ui_param[box_width][n], 16, 1); - u8g2.setDrawColor(1); -} - -/************************************* 处理函数 *************************************/ - -//列表类页面旋转时判断通用函数 -void rotate_switch(int16_t n) -{ - switch (btn_id) - { - case 0: - if (ui_param[ui_select][n] < 1) break; - ui_param[ui_select][n] -= 1; - if (ui_param[ui_select][n] < -(ui_param[y][n] / 16)) ui_param[y_trg][n] += 16; - else ui_param[box_y_trg][n] -= 16; - break; - - case 1: - if ((ui_param[ui_select][n] + 2) > ui_param[num][n]) break; - ui_param[ui_select][n] += 1; - if ((ui_param[ui_select][n] + 1) > (4 - ui_param[y][n] / 16)) ui_param[y_trg][n] -= 16; - else ui_param[box_y_trg][n] += 16; - break; - - default: break; - } -} - -/************************************ 初始化函数 ************************************/ - -//OLED初始化函数 -void oled_init() -{ - u8g2.setBusClock(800000); - u8g2.begin(); - u8g2.setFont(u8g2_font_wqy12_t_chinese1); - buf_ptr = u8g2.getBufferPtr(); - buf_len = 8 * u8g2.getBufferTileHeight() * u8g2.getBufferTileWidth(); -} - -/************************************ 主循环函数 ************************************/ - -void setup() -{ - oled_init(); - ui_init(); - btn_init(); - - Serial.begin(115200); -} - -void loop() -{ - btn_scan(); - ui_proc(); -}