//e
int menu_array[(menu_option_lines*2)+1];
int eeprom_current_integers[(menu_option_lines)+1]; //loads the integers from eeprom, and then is edited while running to be saved later
int eeprom_integer_min_max[menu_option_lines*2]; //stores min/max values for integers //todo change to min/max of current line when going to editing mode
int eeprom_decimal_values[menu_option_lines+1];//todo
int loaded_eeprom_min; //todo not done yet, when editing an integer, the min value is loaded into this int
int loaded_eeprom_max; //todo not done yet, when editing an integer, the max value is loaded into this int
bool display_clearDisplay = false;
bool display_update_cursor = false;
bool display_update_integers = false;
bool display_update_menu_text = false;
boolean in_navigate_state;
uint8_t previous_total_offset; //todo when writing the integer on the screen, if the offset is larger than before, write blanking line on screen
int font_width;
int font_hight;
int menu_shown_min_max[2]; //min and maximum line that is displayed on screen, gets reset on menu change
int menu_shown_min_max_prev[2]; //old min and maximum line that was displayed on previously, to efficiently clear display
int cursor_selected_menu_option = 1;
int cursor_position_on_screen = 0;
class SSD1306_Menu
{
public:
//EEPROM
void update_eeprom_integers(int bank_number, int new_int_value){ //update running config, used when editing an integer
int n = 0;
while(1)
{
if(n > menu_option_lines){break;}
if(line_variable_number(n) == bank_number){
if(line_type_mapper(line_type(n)) == 'E'){break;}
}
n=n+1; //check the next line
}
eeprom_current_integers[n] = new_int_value;
}
int load_running_eeprom_integers(int bank_number){ //reads int from running config (ussualy to apply the change in real time)
int n = 0;
//while(eeprom_current_integers[n] != bank_number && line_type_mapper(lenght_of_integer_and_menu_line_type[n+1]) != 'E')
while(1)
{
if(n > menu_option_lines){break;}
if(line_variable_number(n) == bank_number){
if(line_type_mapper(line_type(n)) == 'E'){break; Serial.println("OK");}
}
n=n+1; //check the next line
}
Serial.print("loaded from running: "); Serial.print(line_type_mapper(line_type(n/2))); Serial.println(eeprom_current_integers[n]);
return eeprom_current_integers[n];
}
void save_eeprom_integers(){ //write the current running config integers to eeprom
int n = 0;
while(n < menu_option_lines)
{
save_to_EEPROM(line_variable_number(n),eeprom_current_integers[n]);
n=n+1;
}
}
//
void Setup(int menu_options, char menu_option_text[]){ //set variables to default
//lenght_of_integer_and_menu_line_type[(cursor_selected_menu_option*2)+1] = '0';
//font_width = 1;
//font_hight = 1;
cursor_selected_menu_option = 0;
display_clearDisplay = false;
display_update_cursor = true;
display_update_integers = true;
display_update_menu_text = true;
int menu_options_lenght[menu_options];
int i = 0;
int a = 0;
int n = 0;
do
{
a = menu_option_text[i]+1;
//---------------
if(menu_option_text[i]=='['){ //if there is eeprom read mark
//lenght_of_integer_and_menu_line_type[n-1] = menu_option_text[i+1]; //save line type
//Serial.print(n); Serial.print(" line_type"); Serial.println(lenght_of_integer_and_menu_line_type[n+1]);
if(menu_option_text[i+1]!='R'){
eeprom_current_integers[(n/2)-1] = load_from_eeprom(menu_option_text[i+2]);
//Serial.print("x:"); Serial.println(menu_option_text[i+2]); //save int location in eeprom
//Serial.print("l:"); Serial.println(eeprom_current_integers[n+1]); //loaded value from eeprom
}
while(menu_option_text[i-1]!=']'){i++;}//skip the "[**]" (eeprom readmark)
//i=i+4;
a = 0;
a = menu_option_text[i]+1;
}
Serial.print("spacing:"); Serial.println(i);
menu_array[n] = i;
Serial.print("lenght:"); Serial.println(a);
menu_array[n+1] = a;
i = i + a;
n = n + 2;
}
while (n < (menu_option_lines*2)+1);
in_navigate_state = true;
}
int get_decimal_multipl(uint8_t dec_places){
int i = 1;
int dec = 1;
while(i<=dec_places){i++, dec = dec*10;}
return dec;
}
char line_type_mapper(char input_line_type = 0){ //decides what line type the current line is
if (input_line_type == 'E'){return 'E';} //E integer refresh
if (input_line_type == 'F'){return 'E';} //F full refresh
if (input_line_type == 'R'){return 'H';} //R redirrect
if (input_line_type == 'I'){return 'E';} //I integer refresh
if (input_line_type == 'D'){return 'E';} //I integer refresh
return 'H';
}
char line_type(int input_line = cursor_selected_menu_option){
if(main_menu_option_text[line_text_end(input_line)+1] == '['){
return main_menu_option_text[line_text_end(input_line)+2];
}
return 0;
}
int line_get_min_value(int input_line = cursor_selected_menu_option){
return eeprom_integer_min_max[input_line*2];;
}
int line_get_max_value(int input_line = cursor_selected_menu_option){
return eeprom_integer_min_max[input_line*2+1];
}
int line_variable_number(int input_line = cursor_selected_menu_option){
if(main_menu_option_text[line_text_end(input_line)+1] == '['){
return main_menu_option_text[line_text_end(input_line)+3];
}
return 0;
}
int line_variable_decimal_palce(int input_line = cursor_selected_menu_option){
if(main_menu_option_text[line_text_end(input_line)+1] == '[' && line_type_mapper(line_type(input_line)) == 'E'){
return main_menu_option_text[line_text_end(input_line)+4];
}
return 0;
}
int line_variable_value(int input_line = cursor_selected_menu_option){
return eeprom_current_integers[input_line];
}
int line_variable_value_lenght(int input_line = cursor_selected_menu_option){ //lenght in characters
int value = line_variable_value(input_line);// --> load integer
if(line_type_mapper(line_type(input_line)) != 'E'){return 0;}
int lenght = 0;
// if(line_variable_decimal_palce(input_line) > 0 && ){
// lenght = lenght - line_variable_decimal_palce(input_line);
// }
if (line_type(input_line) == 'D'){ //decimal
lenght = lenght + 4;
if(value<0){lenght = lenght + 1; value = value*(-1);}
if(value >= 1000){lenght = lenght +1;}
if(value >= 10000){lenght = lenght +2;}
if(value >= 100000){lenght = lenght +3;}
return lenght;
}
if (value<0){lenght = lenght + 1; value = value*(-1);}
if (value>=0 && value<10){lenght = lenght + 1;}
if (value>=10 && value<100){lenght = lenght + 2;}
if (value>=100 && value<1000){lenght = lenght + 3;}
if (value>=1000 && value<10000){lenght = lenght + 4;}
return lenght;
}
int line_text_start(int input_line = cursor_selected_menu_option){
return menu_array[input_line*2]+1;
}
int line_text_end(int input_line = cursor_selected_menu_option){
return line_text_start(input_line)+menu_array[input_line*2+1]-2;
}
int page_max_lines_on_screen(){
return (8/font_hight)-1;
}
int page_line_start(uint8_t page = menu_number){
int c=0;
int n=0;
if(page != 0)
{
do{n=n+menu_options_section_lenght[c]; c++;}while(c!=page);
};
return n;
}
int page_line_end(uint8_t page = menu_number){
int c=0;
int n=0;
do{n=n+menu_options_section_lenght[c]; c++;}while(c!=page+1);
return n-1;
}
void reset_menu_shown_min_max(){
Serial.print("page_max_lines_on_screen(): "); Serial.println(page_max_lines_on_screen());
menu_shown_min_max[0]=page_line_start();
menu_shown_min_max[1]=page_line_end();
if(menu_shown_min_max[1]>page_max_lines_on_screen()+page_line_start()){
menu_shown_min_max[1]=page_max_lines_on_screen()+page_line_start();
}
}
void set_cursor_position_on_screen(int position = 0){
cursor_position_on_screen = position;
}
void move_menu_shown_min_max(char direction){
Serial.print("page_line_end()"); Serial.print(page_line_end()); Serial.print(" menu_shown_min_max[1]: "); Serial.println(menu_shown_min_max[1]);
if(cursor_position_on_screen > menu_shown_min_max[1]-menu_shown_min_max[0]){
Serial.println("EEE");
if(direction == '+' && page_line_end() > menu_shown_min_max[1]){
menu_shown_min_max_prev[0]=menu_shown_min_max[0];
menu_shown_min_max_prev[1]=menu_shown_min_max[1];
menu_shown_min_max[0]++;
menu_shown_min_max[1]++;
cursor_position_on_screen = page_max_lines_on_screen();
display_update_menu_text = true;
display_update('i', 'm');
}
}
Serial.print("HERE on_screen: "); Serial.print(cursor_position_on_screen); Serial.print(" min_max0: "); Serial.println(menu_shown_min_max[1]-page_max_lines_on_screen()-1);
if(cursor_position_on_screen == (menu_shown_min_max[1]-page_max_lines_on_screen()-1)-(menu_shown_min_max[0])){
Serial.println("OOO");
if(direction == '-' && menu_shown_min_max[0]>page_line_start()){
menu_shown_min_max_prev[0]=menu_shown_min_max[0];
menu_shown_min_max_prev[1]=menu_shown_min_max[1];
menu_shown_min_max[0]--;
menu_shown_min_max[1]--;
cursor_position_on_screen = 0;
display_update_menu_text = true;
display_update('i', 'm');
//display_clearDisplay = true;
}
}
}
int last_writable_line(int first_line){
int last_line;
last_line = first_line+page_max_lines_on_screen();
if(last_line > first_line+page_max_lines_on_screen()){last_line = first_line+page_max_lines_on_screen();}
return last_line;
}
void cursor_move_up(){
if(cursor_position_on_screen < (page_line_end()-page_line_start())){cursor_position_on_screen++;}
else{return;}
//Serial.println(line_text_end()-line_text_start());
cursor_selected_menu_option = cursor_position_on_screen+page_line_start()+(menu_shown_min_max[0]-page_line_start());
display_update_cursor = true;
move_menu_shown_min_max('+');
if(cursor_position_on_screen>page_max_lines_on_screen()){cursor_position_on_screen = page_max_lines_on_screen();}
if(cursor_selected_menu_option>page_line_end()){cursor_selected_menu_option = page_line_end();}
}
void cursor_move_down(){
cursor_position_on_screen--;
cursor_selected_menu_option = cursor_position_on_screen+page_line_start()+(menu_shown_min_max[0]-page_line_start());
display_update_cursor = true;
move_menu_shown_min_max('-');
if(cursor_position_on_screen<0){cursor_position_on_screen = 0;}
if(cursor_selected_menu_option<page_line_start()){cursor_selected_menu_option = page_line_start();}
}
void write_out_cursor(){
if(display_update_cursor == false){return;}
//page_max_lines_on_screen(), cursor_position_on_screen display.setCursor(0,i)
int i = 0;
int spacing = 0;
int m = menu_shown_min_max[1]-menu_shown_min_max[0]+1;
//if(m>menu_shown_min_max[1]+1){m=menu_shown_min_max[1]+1;}
Serial.println(m);
while(i<m){
display.setCursor(0,spacing);
if(i==cursor_position_on_screen){display.print(">");}
else(display.print(" "));
if(i>=menu_shown_min_max[1]+1){break;}
i++;
spacing=spacing+font_hight;
}
display_update_cursor = false;
}
void write_out_integer_range(int first_line, int last_line = -1){
#define prev_lenght_offset (menu_shown_min_max[0]-menu_shown_min_max_prev[0])
if(display_update_integers == false){return;}
//int c = 0;
int line_selected = first_line;
if(last_line == -1){last_line=last_writable_line(first_line);}
if(last_line > page_line_end()-page_line_start()){last_line = page_line_end();}
Serial.print("last: "); Serial.println(last_line-first_line);
Serial.println("---------");
do{
#define old_lenght line_variable_value_lenght((line_selected)-prev_lenght_offset)
#define current_lenght line_variable_value_lenght(line_selected)
#define maximum_display_position display.getCols()- (font_width*1)-1
#define integer_line line_selected-menu_shown_min_max[0]
Serial.print("c: "); Serial.println(integer_line);
//Serial.print(" line_variable_value: "); Serial.print(line_variable_value(line_selected));
//Serial.print(" current_lenght: "); Serial.print(current_lenght);
//Serial.print(" old_lenght: "); Serial.println(old_lenght);
//Serial.print("maximum_display_position: "); Serial.println(maximum_display_position);
if(current_lenght < old_lenght){
int n = 0;
while(current_lenght+n<old_lenght+0){ //+2 for the '[]'
display.setCursor(display.getCols()-old_lenght+n-0, integer_line); //-2 for the '[]'
display.print('#');
//Serial.println(n);
n++;
}
}
if(line_variable_number()!=0 && line_type_mapper(line_type(line_selected)) == 'E'){ //if there is a EEPROM stored variable
Serial.print("writing int on screen to line: "); Serial.println(line_selected);
//lenght_of_integer_and_menu_line_type[line_selected+1] = 'E'; //E is EEPROM type of current selected line
//fix the offset if the character was changed
int value = line_variable_value(line_selected);// --> loaded integer
uint8_t total_offset = maximum_display_position - (line_variable_value_lenght(line_selected)*(font_width))+2; //lenght_of_integer_and_menu_line_type[b/2] is the number of characters that have to he shifted for int to not go off the screen; 104 is the offset of the last character (]); 12 is the width of each character
//Serial.println(total_offset);
//Serial.println(previous_total_offset);
if(previous_total_offset<total_offset){
//Serial.println("CLEAR!!");
display.setCursor(previous_total_offset,integer_line);
display.print("#");
}
previous_total_offset = total_offset;
//display.setCursor(f, c-16);
display.setCursor(total_offset, integer_line);
//Serial.println(c-(8*font_width));
int g=0;
//int dec=100;
float gf = value;
float value_f;
if(line_type(line_selected)== 'D'){
float gf = value;
float value_f;
value_f = gf/get_decimal_multipl(line_variable_decimal_palce(line_selected));
display.print(value_f);
}else(display.print(value));
Serial.println("font_hight++");
}
line_selected++;
Serial.println("line_selected++");
}while(line_selected < last_line+1);
//while(line_selected/2 < 11);
display_update_integers = false;
}
void write_out_text_range(int first_line, int last_line = -1, int offset = 0){
#define prev_line_offset (menu_shown_min_max[0]-menu_shown_min_max_prev[0])
if(display_update_menu_text == false){return;}
int line_selected = first_line;
if(last_line == -1){last_line=last_writable_line(first_line);}
while(line_selected <= last_line){
#define old_lenght line_text_end(line_selected-prev_line_offset)-line_text_start(line_selected-prev_line_offset)
#define current_lenght line_text_end(line_selected)-line_text_start(line_selected)
if(old_lenght>current_lenght){Serial.print("Clean line: "); Serial.print(line_selected);}
else{Serial.print(" Do NOT clean line: "); Serial.print(line_selected);}
//Serial.print(" current_lenght: "); Serial.print(current_lenght);
//Serial.print(" old_lenght: "); Serial.println(old_lenght);
display.setCursor(1, offset);
offset=offset+font_hight;
int i = 0;
while(line_text_start(line_selected)+i <= line_text_end(line_selected)){ //print text
char c = main_menu_option_text[line_text_start(line_selected)+i];
display.print(c);
i++;
}
while(line_text_start(line_selected)+i <= line_text_start(line_selected)+old_lenght){ //print blank to clear previous test
display.print(" ");
i++;
}
line_selected++;
}
display_update_menu_text = false;
}
void Up(){ //if in_navigate_state == ture, move cursor
if(in_navigate_state == true){
cursor_move_up();
return;
}
if(in_navigate_state == false && line_type() == 'E'){
eeprom_current_integers[cursor_selected_menu_option]++;
Serial.println(line_get_max_value());
display_update_integers = true;
//return; //'E'
}
if(in_navigate_state == false && line_type() == 'D'){
eeprom_current_integers[cursor_selected_menu_option]++;
Serial.println(line_get_max_value());
display_update_integers = true;
//return; //'E'
}
if(in_navigate_state == false && line_type() == 'F'){
int i=line_variable_value()+1;
Serial.print("up");
Serial.println(i);
update_eeprom_integers(line_variable_number(), i);
display_clearDisplay = true;
//return;
}
if(line_variable_value() > line_get_max_value()){ //if its larger than maximum allowed value, reset to maximum allowed value
eeprom_current_integers[cursor_selected_menu_option] = line_get_max_value();
}
}
void Down(){ //if in_navigate_state == true, move cursor
if(in_navigate_state == true){
cursor_move_down();
return;
}
if(in_navigate_state == false && line_type() == 'E'){
if(eeprom_integer_min_max[(cursor_selected_menu_option*2)+0] < eeprom_current_integers[cursor_selected_menu_option]){
eeprom_current_integers[cursor_selected_menu_option]--;
//Serial.println((cursor_selected_menu_option*2)+1);
if(eeprom_current_integers[cursor_selected_menu_option] > eeprom_integer_min_max[(cursor_selected_menu_option*2)+1]){ //if its larger than maximum allowed value, reset to maximum allowed value
eeprom_current_integers[cursor_selected_menu_option] = eeprom_integer_min_max[(cursor_selected_menu_option*2)+1];
}
}
display_update_integers = true;
//return;
}
if(in_navigate_state == false && line_type() == 'D'){
if(eeprom_integer_min_max[(cursor_selected_menu_option*2)+0] < eeprom_current_integers[cursor_selected_menu_option]){
eeprom_current_integers[cursor_selected_menu_option]--;
//Serial.println((cursor_selected_menu_option*2)+1);
if(eeprom_current_integers[cursor_selected_menu_option] > eeprom_integer_min_max[(cursor_selected_menu_option*2)+1]){ //if its larger than maximum allowed value, reset to maximum allowed value
eeprom_current_integers[cursor_selected_menu_option] = eeprom_integer_min_max[(cursor_selected_menu_option*2)+1];
}
}
display_update_integers = true;
//return;
}
if(in_navigate_state == false && line_type() == 'F'){
Serial.println("F");
if(eeprom_integer_min_max[(cursor_selected_menu_option*2)+0] < eeprom_current_integers[cursor_selected_menu_option]){
eeprom_current_integers[cursor_selected_menu_option]--;
Serial.print("modifying: "); Serial.println((cursor_selected_menu_option*2)+1);
if(eeprom_current_integers[cursor_selected_menu_option] > eeprom_integer_min_max[(cursor_selected_menu_option*2)+1]){ //if its larger than maximum allowed value, reset to maximum allowed value
eeprom_current_integers[cursor_selected_menu_option] = eeprom_integer_min_max[(cursor_selected_menu_option*2)+1];
}
}
display_clearDisplay = true;
//return;
}
if(line_variable_value() > line_get_max_value()){ //if its larger than maximum allowed value, reset to maximum allowed value
eeprom_current_integers[cursor_selected_menu_option] = line_get_max_value();
}
}
void Ok(){ //get state of variables
Serial.print("line_type()"); Serial.println(line_type());
if(line_type() == 'R'){
redirect();
return;
}
if(in_navigate_state == false){
//Serial.println("e");
in_navigate_state = true;
return;
}
Serial.print("state "); Serial.println(in_navigate_state);
Serial.print("type" ); Serial.println(line_type());
if(in_navigate_state == true && line_type() != '0'){ //E is EEPROM type of current selected line
in_navigate_state = false;
return;
}
}
void set_int_limit(int integer_ID, int MIN = -32768, int MAX = 32767){ //assigned eeprom number, min, max -saves to eeprom_integer_min_max[]
//; //eeprom_integer_min_max[1,2] gets saved based on on what line integer_ID relative on the eeprom_current_integers
int line_selected = 0;
while(line_selected<menu_option_lines*2){
if(line_variable_number(line_selected/2) == integer_ID && line_type_mapper(line_type(line_selected/2)) == 'E'){
Serial.println("found");
eeprom_integer_min_max[line_selected] = MIN;
eeprom_integer_min_max[line_selected+1] = MAX;
Serial.println("assigned MIN, MAX to line: ");Serial.println(line_selected/2);
}else(Serial.println("Sadge"));
line_selected=line_selected+2;
}
}
void display_update(char a = 0, char b = 0, char c = 0){
if(a+b+c == 0){
a='m';
b='c';
c='i';
}
if(a == 'm' || b == 'm' || c == 'm'){
display_update_menu_text = true;
}
if(a == 'c' || b == 'c' || c == 'c'){
display_update_cursor = true;
}
if(a == 'i' || b == 'i' || c == 'i'){
display_update_integers = true;
}
}
void redirect(int input_line = cursor_selected_menu_option){
menu_number = line_variable_number(input_line); //redirect to submenu of the currently selected line
reset_menu_shown_min_max();
set_cursor_position_on_screen(0);
cursor_selected_menu_option = page_line_start();
//Serial.println(cursor_selected_menu_option*2);
display_clearDisplay = true;
}
};