Browse Source

first upload

master
iansun2 4 years ago
commit
f4a2c4a797
  1. 204
      lcd_menu.cpp
  2. 360
      lcd_menu.h

204
lcd_menu.cpp

@ -0,0 +1,204 @@
#ifndef LCD_MENU_C
#define LCD_MENU_C
#include "lcd_menu.h"
Menu menu;
LiquidCrystal_I2C lcd(0x27,16, 2);
//init menu//
void Menu::init(uint8_t width, uint8_t height){
//Serial.println("=============[init:start]==============");
menu_data_head = new menu_data;
menu_data_end = menu_data_head;
menu_data_head->next_data = NULL;
setDataValue(menu_data_head, NULL, NULL, 0, 0);
setDataIndex(menu_data_head, NULL, 255);
lcd_width = width;
lcd_height = height;
lcd.init();
lcd.backlight();
//Serial.print("[init]first data index: "); Serial.println(first_data_idx);
//Serial.println("=============[init:end]==============");
}
//add element//
void Menu::add(uint8_t new_gid, uint8_t new_id, const __FlashStringHelper* new_title){
//Serial.println("=============[add:start]==============");
//Serial.print("[add]static: "); Serial.println(new_title);
menu_data* new_data = getInsertDataAddress(new_gid, new_id);
//Serial.print("[add]: "); Serial.println(unsigned(new_data));
setDataValue(new_data, new_title, NULL, new_gid, new_id);
//debugPrint(new_data);
updateScreen();
//Serial.println("=============[add:end]==============\n");
}
//add element//
void Menu::add(uint8_t new_gid, uint8_t new_id, const char* new_title){
//Serial.println("=============[add:start]==============");
//Serial.print("[add]dynamic: "); Serial.println(new_title);
menu_data* new_data = getInsertDataAddress(new_gid, new_id);
//Serial.print("[add]: "); Serial.println(unsigned(new_data));
setDataValue(new_data, NULL , new_title, new_gid, new_id);
//debugPrint(new_data);
updateScreen();
//Serial.println("=============[add:end]==============\n");
}
//link element to group//
void Menu::link(uint8_t src_gid, uint8_t src_id, uint8_t dst_gid){
//Serial.println("=======================");
menu_data* data_src = getDataAddress(src_gid, src_id);
data_src->sub_group = dst_gid;
getDataAddress(data_src->sub_group,0)->parent = data_src;
menu_data* finder = getDataAddress(data_src->sub_group,0);
//Serial.print("[link]src gid: "); //Serial.print(src_gid); //Serial.print(" id: "); //Serial.println(src_id);
//debugPrint(data_src);
//Serial.print("[link]dst gid: "); //Serial.println(dst_gid);
//debugPrint(data_src->sub_group);
do{
finder->parent = data_src;
finder = getNextMemberAddress(finder);
}while(finder != NULL);
//Serial.println("=======================");
}
//remove element//
void Menu::remove(uint8_t del_gid, uint8_t del_id){
//Serial.println("=============[remove:start]==============");
menu_data* group_head = getDataAddress(del_gid, 0);
menu_data* del_data = getDataAddress(del_gid, del_id);
menu_data* next_del_data = del_data;
//if del all group, show parent
if(del_data == group_head && screen_select_line->gid == del_data->gid){
//Serial.println("[Remove]del group");
back();
}
//if del screen top line or screen select line
if(screen_top_line == del_data){
//Serial.println("[Remove]change top line");
//show pre data
if(getPreMemberAddress(screen_top_line) != NULL){
screen_top_line = getPreMemberAddress(screen_top_line);
//show next data
}else if(getNextMemberAddress(screen_top_line) != NULL){
screen_top_line = getNextMemberAddress(screen_top_line);
}
}
if(screen_select_line == del_data){
//Serial.println("[Remove]change select line");
//show pre data
if(getPreMemberAddress(screen_select_line) != NULL){
screen_select_line = getPreMemberAddress(screen_select_line);
//show next data
}else if(getNextMemberAddress(screen_select_line) != NULL){
screen_select_line = getNextMemberAddress(screen_select_line);
}
}
//Serial.print("[Remove]: "); Serial.println((unsigned)del_data);
//if del group head, del this group
if(del_data == group_head){
//Serial.println("[Remove]del group");
do{
del_data = next_del_data;
next_del_data = getNextMemberAddress(next_del_data);
//Serial.print("[Remove]: "); Serial.println((unsigned)del_data);
deleteData(del_data);
}while(next_del_data != NULL);
}else{
deleteData(del_data);
}
updateScreen();
//Serial.println("=============[remove:end]==============");
}
//start menu//
void Menu::start(){
//Serial.println("[start]start");
menu_started = 1;
initScreenHead(0);
}
//rollup//
void Menu::rollUp(){
//Serial.println("[rollup]start");
//if can rollup
if(getPreMemberAddress(screen_select_line) != NULL){
screen_select_line = getPreMemberAddress(screen_select_line);
//Serial.print("[rollup]select_line: "); Serial.println((unsigned)screen_select_line);
}
updateScreen();
//printf("[rollup] end\n");
}
//rolldown//
void Menu::rollDown(){
//Serial.println("[rolldown]start");
//if only one member
if(getNextMemberAddress(screen_select_line) != NULL){
screen_select_line = getNextMemberAddress(screen_select_line);
}
updateScreen();
}
//back to parent element//
void Menu::back(){
screen_select_line = screen_select_line->parent;
screen_top_line = screen_select_line;
updateScreen();
}
//enter select element//
void Menu::enter(){
//Serial.println("[enter]start");
//soft back
String buffer;
if(screen_select_line->dynamic_title != NULL){
buffer = screen_select_line->dynamic_title;
}else if(screen_select_line->static_title != NULL){
buffer = screen_select_line->static_title;
}
menu_select_gid = screen_select_line->gid;
menu_select_id = screen_select_line->id;
if(soft_back){
if(!buffer.compareTo("...")){
back();
onSelect();
return;
}
}
if(screen_select_line->sub_group != 255){
screen_select_line = getDataAddress(screen_select_line->sub_group,0);
screen_top_line = screen_select_line;
}
updateScreen();
onSelect();
}
//check select element//
bool Menu::checkSelect(uint8_t dst_gid, uint8_t dst_id){
if(dst_gid == menu_select_gid && dst_id == menu_select_id){
return 1;
}else{
return 0;
}
}
//jump to group//
void Menu::jump(uint8_t dst_gid, uint8_t dst_id){
screen_top_line = getDataAddress(dst_gid, dst_id);
screen_select_line = screen_top_line;
updateScreen();
}
#endif

360
lcd_menu.h

@ -0,0 +1,360 @@
#ifndef LCD_MENU_H
#define LCD_MENU_H
#include <LiquidCrystal_I2C.h>
#include <Arduino.h>
extern LiquidCrystal_I2C lcd;
class Menu{
public:
//init
void init(uint8_t width, uint8_t height);
//add
void add(uint8_t new_gid, uint8_t new_id, const __FlashStringHelper* new_title);
void add(uint8_t new_gid, uint8_t new_id, const char* new_title);
//link
void link(uint8_t src_gid, uint8_t src_id, uint8_t dst_gid);
//remove
void remove(uint8_t del_gid, uint8_t del_id);
//onSelect
void onSelect();
//start
void start();
//rollUp
void rollUp();
//rollDown
void rollDown();
//back
void back();
//enter
void enter();
//checkSelect
bool checkSelect(uint8_t check_gid, uint8_t check_id);
//jump
void jump(uint8_t dst_gid, uint8_t dst_id);
//softBack
//if set to 1, title = "..." be selected will call back() function
bool soft_back = 0;
private:
//if menu start() function have be called, set to 1
bool menu_started = 0;
//now select gid
uint8_t menu_select_gid = 0;
//now select id
uint8_t menu_select_id = 0;
//lcd size
uint8_t lcd_height = 0;
uint8_t lcd_width = 0;
//data struct
struct menu_data{
const __FlashStringHelper* static_title;
const char* dynamic_title;
uint8_t gid;
uint8_t id;
menu_data* parent;
uint8_t sub_group;
menu_data* next_data;
};
menu_data* menu_data_head;
menu_data* menu_data_end;
menu_data* screen_top_line = 0;
menu_data* screen_select_line = 0;
//function//
//set data value
//input data addr & new value
//no return
void setDataValue(menu_data* dst_data, const __FlashStringHelper* static_title, const char* dynamic_title, uint8_t new_gid, uint8_t new_id){
dst_data->static_title = static_title;
dst_data->dynamic_title = dynamic_title;
dst_data->gid = new_gid;
dst_data->id = new_id;
}
//set data index
//input data addr & new index
//no return
void setDataIndex(menu_data* dst_data, menu_data* new_parent, uint8_t new_sub_group){
dst_data->parent = new_parent;
dst_data->sub_group = new_sub_group;
}
//add new data
//no input
//return new data address
menu_data* addData(){
//Serial.print("[add_data]old menu_end: "); Serial.println((unsigned)menu_data_end);
menu_data* new_data = new menu_data;
menu_data_end->next_data = new_data;
new_data->next_data = NULL;
menu_data_end = new_data;
//Serial.print("[add_data]new data: "); Serial.println((unsigned)new_data);
//Serial.print("[add_data]new menu_end: "); Serial.println((unsigned)menu_data_end);
return new_data;
}
//get data address
//input gid
//return data address which gid & id match
menu_data* getDataAddress(uint8_t dst_gid, uint8_t dst_id){
//find match data
menu_data* finder = menu_data_head;
while(finder != NULL){
if(finder->gid == dst_gid && finder->id == dst_id){
return finder;
}
finder = finder->next_data;
}
//cannot find group
return NULL;
}
//get data pre address
//input data address
//return data pre address
menu_data* getPreMemberAddress(menu_data* dst_data){
menu_data* finder = menu_data_head;
menu_data* pre_data = NULL;
uint8_t pre_data_id = 0;
do{
//if finder->gid match && pre_data_id < finder->id < dst_data->id
//Serial.print("[gpma]finder: "); Serial.println((unsigned)finder);
//Serial.print("[gpma]q1 "); Serial.println((unsigned)finder->gid == dst_data->gid);
//Serial.print("[gpma]q2 "); Serial.println((unsigned)finder->id < dst_data->id);
//Serial.print("[gpma]q3 "); Serial.println((unsigned)finder->id >= pre_data_id);
if(finder->gid == dst_data->gid && finder->id < dst_data->id && finder->id >= pre_data_id){
pre_data = finder;
pre_data_id = finder->id;
}
finder = finder->next_data;
}while(finder != NULL);
return pre_data;
}
//get data pre address
//input data address
//return data pre address
menu_data* getNextMemberAddress(menu_data* dst_data){
menu_data* finder = menu_data_head;
menu_data* next_data = NULL;
uint8_t next_data_id = 255;
do{
//if finder->gid match && pre_data_id < finder->id < dst_data->id
//Serial.print("[gnma]finder: "); Serial.println((unsigned)finder);
//Serial.print("[gnma]q1 "); Serial.println((unsigned)finder->gid == dst_data->gid);
//Serial.print("[gnma]q2 "); Serial.println((unsigned)finder->id > dst_data->id);
//Serial.print("[gnma]q3 "); Serial.println((unsigned)finder->id < next_data_id);
if(finder->gid == dst_data->gid && finder->id > dst_data->id && finder->id <= next_data_id){
next_data = finder;
next_data_id = finder->id;
}
finder = finder->next_data;
}while(finder != NULL);
return next_data;
}
//delete data
//input del data address
//no return
void deleteData(menu_data* del_data){
//if del group, clear parent's sub group
if(del_data->parent != NULL && del_data->id == 0){
//Serial.println("[delD]del_group");
del_data->parent->sub_group = 255;
}
menu_data* finder = menu_data_head;
//loop until finder->next_data = del_data
while(finder->next_data != del_data){
finder = finder->next_data;
}
//set finder->next_data to del_data->next_data
finder->next_data = del_data->next_data;
if(finder->next_data == NULL){
menu_data_end = finder;
}
delete del_data;
}
//get insert data addr
//input gid, id
//return new data address
menu_data* getInsertDataAddress(uint8_t new_gid, uint8_t new_id){
//Serial.print("[gida]start: "); Serial.print(new_gid); Serial.print(" "); Serial.println(new_id);
menu_data* finder = getDataAddress(new_gid, 0);
menu_data* new_data;
//Serial.print("[gida]group_head: "); Serial.println((unsigned)finder);
//group not exist
if(finder == NULL){
//Serial.println("[gida]not exist");
//add at data end
new_data = addData();
setDataIndex(new_data, NULL, 255);
return new_data;
//normal
}else{
do{
//Serial.print("[gida]finder: "); Serial.println((unsigned)finder);
//insert at exist data
if(finder->id == new_id){
//Serial.println("[gida]exist");
return finder;
}
//insert at group end
if(finder->next_data == NULL){
//Serial.println("[gida]at end");
new_data = addData();
setDataIndex(new_data, finder->parent, 255);
return new_data;
//insert between two data
}else if(new_id < finder->id){
//Serial.println("[gida]between");
//set new data
new_data = addData();
setDataIndex(new_data, finder->parent, 255);
return new_data;
//go to next memeber
}else{
finder = getNextMemberAddress(finder);
//Serial.print("[gida]new_finder: "); Serial.println((unsigned)finder);
}
}while(finder != NULL);
}
//Serial.println("[gida]error");
return NULL;
}
//update screen function
//no input
//no return
void updateScreen(){
//if menu doesn't start
if(!menu_started){
//Serial.println("[updsc]not start");
return;
}
//Serial.println("[updsc]start");
lcd.clear();
menu_data* finder = getDataAddress(screen_top_line->gid, 0);
uint8_t members = 0;
uint8_t top_line_order = 0;
uint8_t select_line_order = 0;
//count group element quantity
while(finder != NULL){
members ++;
if(finder == screen_top_line){
top_line_order = (members - 1);
}
if(finder == screen_select_line){
select_line_order = (members - 1);
}
finder = getNextMemberAddress(finder);
}
if((top_line_order + lcd_height - 1) < select_line_order){
screen_top_line = getNextMemberAddress(screen_top_line);
top_line_order ++;
}
if(top_line_order > select_line_order){
screen_top_line = getPreMemberAddress(screen_top_line);
top_line_order --;
}
//Serial.print("[updsc]quantity: "); Serial.println(member_quantity);
//Serial.print("[updsc]top line order: "); Serial.println(top_line_order);
//Serial.print("[updsc]select: "); Serial.println(menu_select);
finder = screen_top_line;
for(uint8_t now_line = 0; now_line < lcd_height; now_line++){
if(finder != NULL){
//debugPrint(line_data);
//Serial.print("[updsc]show: "); Serial.println(line_data->dynamic_title);
//Serial.print("[updsc]now line: "); Serial.println(now_line);
if((now_line + top_line_order) == select_line_order){
//Serial.println("[updsc]select");
lcd.setCursor(0,now_line);
lcd.print(">");
}
lcd.setCursor(1,now_line);
if(finder->dynamic_title != NULL){
lcd.print(finder->dynamic_title);
}else if(finder->static_title != NULL){
lcd.print(finder->static_title);
}else{
lcd.print("");
}
}else{
break;
}
//Serial.println((unsigned)line_data->next_member);
finder = getNextMemberAddress(finder);
}
}
//init screen head function
//input gid
//no return
void initScreenHead(uint8_t dst_gid){
screen_top_line = getDataAddress(dst_gid, 0);
screen_select_line = screen_top_line;
////Serial.println(menu_line_0->title);
////Serial.println(menu_line_1->title);
updateScreen();
}
void debugPrint(menu_data* dst_data){
//Serial.println("=============[debug:start]==============");
//Serial.print("[debug]addr: "); Serial.println(unsigned(dst_data));
//Serial.print("[debug]sub_group: "); Serial.println((unsigned)dst_data->sub_group);
//Serial.print("[debug]parent: "); Serial.println((unsigned)dst_data->parent);
//Serial.print("[debug]pre_member: "); Serial.println((unsigned)getPreMemberAddress(dst_data));
//Serial.print("[debug]next_member: "); Serial.println((unsigned)getNextMemberAddress(dst_data));
//Serial.print("[debug]next_data: "); Serial.println((unsigned)dst_data->next_data);
//Serial.println("=============[debug:end]==============");
}
};
extern Menu menu;
#endif
Loading…
Cancel
Save