#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

//Profiles 1  
  
  //Profiles
  #define t_sp 1//не міняти число!
  #define t_mp 2//не міняти число!
  #define r_off 0 // = off
  #define r_on 12 // = on
  #define get_name 20
  #define get_name_a_f 21
  #define change_letter 22
  
  
  //*prof()
  #define direct_p_sp 20
  #define direct_p_mp 21
  #define act_dir 22
  #define activate_p_sp 23
  #define activate_p_mp 24
  
  
  
  class Profiles {
    public:
      Profiles(int deZoH, byte senHor, int deZoV, byte senVer, byte st, String name, byte tape, byte na) {
      
        _deadZoneHor = deZoH;
        _sensitivityHor = senHor;
        _deadZoneVer = deZoV;
        _sensitivityVer = senVer;
        _status = st;
        _name = name; 
        _tape = tape;
        _namber = na;
      }
      int getDeZoHor() {   //get
       return _deadZoneHor;
      } 
      byte getSenHor() {
       return _sensitivityHor;
      }
      int getDeZoVer() {
       return _deadZoneVer;
      }
      byte getSenVer() {
       return _sensitivityVer;
      }
      byte getStatus() {
       return _status;
      }
      String getName() {
       return _name;
      } 
      byte getTape() {
       return _tape;
      }
      byte getNamber() {
       return _namber;
      }
      
      int setDeZoHor(int deZoH) {//set
       if (_deadZoneHor != deZoH) {_sensitivityHor = 0;}
       _deadZoneHor = deZoH; 
      } 
      byte setSenHor(byte senHor) {
       _sensitivityHor = senHor;
      }
      int setDeZoVer(int deZoV) {
        if (_deadZoneVer != deZoV) {_sensitivityVer = 0;}
        _deadZoneVer = deZoV;
      }
      byte setSenVer(byte senVer) {
       _sensitivityVer = senVer;
      }
      byte setStatus(byte st) {
       _status = st;
      }
      byte setTape(byte tape) {
       _tape = tape;
      }
      byte setNamber(byte na) {
        _namber = na;
      }
      
      String nameProfiles(byte acceptedCommand, byte index = 0, char Letter = ' '){
       
        if (_status == r_on && tmr < millis()){
         
         tmr = millis()+600;
         Flag = !Flag;
        
        }
        
        else if (_status == r_off && !Flag){
         
         Flag = 1;
         
        }
        
        switch (acceptedCommand) {
        
          case get_name: 
            
            return _name;
          
          break;
          
          case get_name_a_f: 
           
           if (Flag) {
            
            return _name;
           
           }
       
           else { 
            
            return "";
           
           }
           
           break;
          
          case change_letter: 
            
             _name[index] = Letter;
          
           break;
        
        
         return "";
        
        }
      
      
       return "";
      }
      
      
      byte centroName() {
        
        for (int i = 19; i >= 0; i--) {
         
          if (_name[i] != ' '){
           
           return 61-i*3;
           break;
          }
        
        }
        
       return 0;
      
      }
      
      byte getNamberTape(){
       
       return _tape * 10 +_namber;//логіка роботи тип може бути 1 або 2 множимо на 10 щоб не збігалася числа
      
      }
      
      void copyFrom(const Profiles& other) {//використовується для копіювання шаблона
        
        _deadZoneHor = other._deadZoneHor;
        _sensitivityHor = other._sensitivityHor;
        _deadZoneVer = other._deadZoneVer;
        _sensitivityVer = other._sensitivityVer;
        _tape = other._tape;
        _namber = other._namber;
        _status = other._status;
        _name = other._name;
      
      }
     
      bool operator!=(const Profiles& other) const { //використовується для порівняння шаблону
        
        return  (_deadZoneHor != other._deadZoneHor) ||
                (_sensitivityHor != other._sensitivityHor) ||
                (_deadZoneVer != other._deadZoneVer) ||
                (_sensitivityVer != other._sensitivityVer) ||
                (_tape != other._tape) ||
                (_namber != other._namber) ||
                (_status != other._status) ||
                (_name != other._name);
      
      }
      
      String _name;
    
    private:
      
      static uint32_t tmr;// перемінні для функціїnameProfiles(get_name_a_f) не переносити будуть глюки
      byte Flag;
      int _deadZoneHor;//(primary початкова) початок руху
      byte _sensitivityHor;
      int _deadZoneVer;
      byte _sensitivityVer;
      byte _tape;
      byte _namber;
      byte _status;
      

  };
  
  // Ініціалізуємо статичну змінну класу Profiles
  uint32_t Profiles::tmr = 0;
  
  Profiles profilSeve(0, 0, 0, 0, 0, "0", 0, 0);
  
  Profiles profilSpOne(2000, 100, 2556, 92, r_off, "CodMW", t_sp, 1);
  Profiles profilSpTwo(166, 120, 1965, 112, r_off, "Batl3", t_sp, 2);
  Profiles profilSpThree(2000, 100, 2556, 92, r_off, "SP 33", t_sp, 3);
  Profiles profilSpFour(166, 120, 1965, 112, r_off, "SP 44", t_sp, 4);
  Profiles profilSpFive(2000, 100, 2556, 92, r_off, "SP 55", t_sp, 5);
  Profiles profilSpSix(166, 120, 1965, 112, r_off, "SP 66", t_sp, 6);
  Profiles profilSpSeven(2000, 100, 2556, 92, r_off, "SP 77", t_sp, 7);
  
  Profiles profilMpOne(2000, 100, 2556, 92, r_on,  "0                   ", t_mp, 1);
  Profiles profilMpTwo(166, 120, 1965, 112, r_off, "Xmen                ", t_mp, 2);
  Profiles profilMpThree(2000, 100, 2556, 92, r_off, "Mp 3                ", t_mp, 3);
  Profiles profilMpFour(166, 120, 1965, 112, r_off, "Mp 4                ", t_mp, 4);
  Profiles profilMpFive(2000, 100, 2556, 92, r_off, "Mp 5                ", t_mp, 5);
  Profiles profilMpSix(166, 120, 1965, 112, r_off, "Mp 6                ", t_mp, 6);
  Profiles profilMpSeven(2000, 100, 2556, 92, r_off, "Mp 7                ", t_mp, 7);
 
  
  Profiles *prof(byte acceptedCommand, byte number = 0){ 
   
   static byte acting = 7+1;
  
   Profiles *prof[] = {&profilSeve, &profilSpOne, &profilSpTwo, &profilSpThree, &profilSpFour, &profilSpFive, &profilSpSix, &profilSpSeven,
                       
   &profilMpOne, &profilMpTwo, &profilMpThree, &profilMpFour, &profilMpFive, &profilMpSix, &profilMpSeven};
    
    
    
    if (acceptedCommand == act_dir) {
    
     return prof[acting];
   
    } 
    
    else if (acceptedCommand == direct_p_sp) {
    
     return prof[number];
   
    }
    
    else if (acceptedCommand == direct_p_sp) {
    
     return prof[number];
   
    }
   
    else if (acceptedCommand == direct_p_mp) {
    
     return prof[number+7];
   
    }  
   
    else if (acceptedCommand == activate_p_sp || acceptedCommand == activate_p_mp) {
      
      for (int i = 1; i < 15; i++){ 
    
       prof [i] -> setStatus(r_off);
      
      }
      
     if (acceptedCommand == activate_p_sp ) {
       
       prof[number] -> setStatus(r_on);
       acting = number;
      
     }
      
     else  {
      
       prof[number+7] -> setStatus(r_on);
       acting = number+7;
      
     }
    
    } 
     
   return 0;
  }

//P

//Additional_elements 2
  
  bool Vibrgyro;
  // СПІЛЬНІ КОНСТАНТИ ПІД ХОД ДЛЯ БАГ ФУНК
  #define no_action 0 // НЕМА ДІЇ
  #define no_data 0 // немає даних
  #define no_indication 0   // немає вказівки
  #define no 0 
  #define off 0 
  #define get_status 1               // получити настройки
  #define yes 1
  #define save_settings 4           // зберехти настройки
  #define reset 11
  #define on 12
  #define click 13
  #define execute_code 14// execution without comman - виконання без команди
  #define gyro 15
  #define profil 16
  
  #define melody_start 1
  #define melody_off_power 2

  #define x_axis_hor 1
  #define y_axis_ver 2
  #define z_axis_ver 3


  #define get_y 2
  #define get_z 3
  #define get_vibr 4
  
   //Піни карта
  //#define b_mein 25
  #define b_triger 33
  #define b_analog 32
  #define b_on_off 14
  #define b_emul_dpad 26
  #define b_sw 4
  #define p_dt 3
  #define p_clk 2
 
  #define thandle_touch_button 27

  //Mf_EncoderButton();
   
   //#define click 13
   #define press 20
   #define hol_but 21
   #define released 22
   #define released_const 23
   #define press_const 24
   #define hol_const 25
   #define hol_released 26
   #define status_button 27
  
  //Md_Display(byte Receiving) {
    
    #define info_display 20
    #define menu 21 
    #define confirm_selection 22 

    #define lang_eng 25
    #define lang_ukr 26 
    #define click_in_dis_on 27
  
   //Md_MainDisplayENG();
    
    #define menu_off 21
    #define menu_start 22
   
    //byte Md_addres();
    
    //#define click 13
    #define back 20
    #define address_entered 21
    #define get_add 22
    #define int_add 23
    #define int_add_ban 24
    #define int_add_last 25
    #define address_deleted 26
    //int Md_cursor();
    
    //#define reset 11
    #define selection_inversion 21
    #define freeze_position 22
    #define get_pos 23
    #define return_pos 24
    byte noData[1];
    byte posOne[] = {1};
    byte posTwo[] = {2};
    byte posThree[] = {3};
    byte posFour[] = {4};
    byte posFive[] = {5};
    byte posSix[] = {6};
    byte posEight[] = {7};
   
    //Ae_InterruptReadPinDtEncoder()
    //Mf_Encoder();
     #define rotated_rights 20
     #define rotated_left 21
    
    
    //MdAf_consenDisplay()
     #define choice_yes 20
     #define choice_no 21
    
    
    //MdAf_profileStorage()
    #define copy_profile 20
    #define return_save 21
    #define check_changes 22
    #define recorded_changes 23//зафіксовані зміни
    
    //Mf_Buttons()
    
    #define animation_one 20
    #define animation_two 21
    #define animation_stope_one 22
    #define animation_stope_two 23
    #define cancel_actions 24
    
    int8_t Md_addres(int8_t AddNumb, int8_t acceptedCommand, int8_t acceptedDataOne = 0);
    byte Md_p_Buttons(byte receivedData = 0, byte selectedButton = 0);
    byte buttonArray[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
    int8_t Ae_Countdown(int8_t acceptedCommand){

   static uint32_t tmr;
   
   if (!tmr) {tmr = (acceptedCommand+1) * 1000 + millis();}
   
   else if (acceptedCommand == reset) { tmr = 0;}
   acceptedCommand = ((tmr - millis()) / 1200) - 1;
   //Serial.println(acceptedCommand);
   
   return acceptedCommand;
  }
 
  byte Ae_BatR(byte Taking) {
   return !digitalRead(Taking);
  }
 
  void Ae_InterruptReadPinDtEncoder() {  //дивитися на початку в void setup працюэ разом з attachInterrupt(digitalPinToInterrupt(p_dt), Ae_InterruptReadPinDtEncoder, CHANGE);

   static int8_t clkStateCurrent;
   static int8_t clkStateLast;

   clkStateCurrent = digitalRead(p_clk);

    if ((clkStateLast == LOW) && (clkStateCurrent == HIGH)) {

      if (digitalRead(p_dt) == HIGH) {      
        Mf_encoderActionStorage(rotated_rights);
                  
      } else {
         Mf_encoderActionStorage(rotated_left);
                  
      }
    }

    clkStateLast = clkStateCurrent;       

  }

  
//Ae

//Main_display 3
  
  // add1-----------------------------------------------------------------------------------------------------------
    
    byte Md_MainDisplay() {// головна фунція виклик решта функцій дисплея
     
     display.clearDisplay();
      
      switch (Md_addres(1, int_add)) {
        case no_action: 
         
         MdAf_BluetoothPrint(); MdAf_typeNumberPrint(); MdAf_batteryPrint();

         Md_ItemOne();
        
         break;//1
        case 1:
          
          Md_Profile();
         
         break;//a2
        //case 2: Md_Additional_effectsENG(); break;
        //case 3: Md_SettingsENG(); break;
        //case 4: Md_InstructionENG(); break;
        
        case address_entered:
          
            if (Md_addres(1, get_add) == 5) {
             
             Md_Display(info_display);
             Md_cursor(no_data, reset);
             Md_addres(1, back);         
            
            }
            
            else{
            
             Md_cursor(no_data, reset);
            
            } 
          
          break;
        
         
      }
     
     display.display();
    
    }
    
    void Md_ItemOne(){
      
        byte Lines[] = {16, 24, 32, 40, 48 };
        Md_cursor(Lines, sizeof(Lines));
        
        display.setCursor(0, 16);
        display.println(" Profile");
        display.println(" Additional effects");
        display.println(" Settings ");
        display.println(" Instruction ");
        display.println(" Close menu ");
    
    }
  //
  // add2-----------------------------------------------------------------------------------------------------------
    
    void Md_Profile() {
      
      if (prof(act_dir)->getTape() == t_sp) {//в залежності від типу профілю вид меню міняється
      
        switch (Md_addres(2, int_add)) {
          
          case no_action: 
            
            Md_p_Profile();
           
           break;
          
          case 1:
           
            Md_ProfileSettings();
          
           break;//a3
          
          case 2: break;// QR code
          
          case 3:
            
            Md_SelectProfile();
           
           break;//a3 
          
          case address_entered:
          
            if (Md_addres(2, get_add) == 4) {
            
             Md_cursor(posOne, return_pos);
             Md_addres(1, back);           
            
            }
            
            else{
             
             MdAf_profileStorage(copy_profile);////копіюємо профіль при доході в настройки p1 для подальшої перевірки на зміни при виході 
             Md_cursor(no_data, reset);
            
            } 
          
          break;
          
        }
      }   
      
      else {
    
        switch (Md_addres(2, int_add)) {
          case no_action: 
           
            Md_p_Profile();
          
           break;
          
          case 1://a3
            
            Md_ProfileSettings();
           
           break;
          
          case 2: //a3 
            
            Md_SelectProfile();
          
           break;
          
          case address_entered: 
          
            if (Md_addres(2, get_add) == 3) {
            
              Md_cursor(posOne, return_pos);
              Md_addres(1, back);
            
            }
            
            else{
             
             MdAf_profileStorage(copy_profile);
             Md_cursor(no_data, reset);
            
            } 
        
           break;
            
        }
      }   
    } 
   
    void Md_p_Profile() {
        
         byte LinesSp[] = {31, 39, 49, 57};
         byte LinesMp[] = {35, 49, 57};
        
        if (prof(act_dir)->getTape() == t_sp) {      
         Md_cursor(LinesSp, sizeof( LinesSp));
        } 
        else {
         Md_cursor(LinesMp, sizeof(LinesMp));
        }
        
      display.setCursor(3, 1);//стрілки по боках активний профіль
      display.write(25);
      display.setCursor(118, 1);
      display.write(25);
      
      display.drawRoundRect(0, 0, 127, 10, 2, WHITE);// РАМКА АКТИВ ПРОФ НАЗВА ГРИ
      display.drawRect(0, 9, 127, 19, WHITE);
      display.drawRect(10, 29, 51, 19, WHITE);// РАМКА НАСТРОЙКИ КЮАР КОД
      
      display.setCursor(21, 1);
      display.print("Active profile");
      
      display.setCursor(98, 36);       //РИСКА В лыво РАЗОМ ПОЛУЧАЭТСЯ КРИВА СТРЫЛКА
      display.println("_" );
      display.setCursor(93, 36);
      display.println("_" );
      display.setCursor(91, 36);// СТРЫЛКА ВВЕРХ РАЗОМ ПОЛУЧАЭТСЯ КРИВА СТРЫЛКА
      display.write(24);
      display.setCursor(91, 34);
      display.write(30);
      
      display.drawCircle(113, 42, 11, WHITE);// КРУГ НАВК Sp
      
      display.setCursor(105, 39);
      
      if (prof(act_dir)->getTape() == t_sp) { 
       
       display.print("Sp");
       display.println(prof(act_dir)->getNamber());
      }
      else {
       
       display.print("Mp");
       display.println(prof(act_dir)->getNamber());
      }
      
      display.setCursor(prof(act_dir)->centroName(), 15);//функція centroName() в залежності від кількості ім'я вранці
      display.println(prof(act_dir)->nameProfiles(get_name));
      
      display.setCursor(0, 32);       //РИСКА В ПРАВО РАЗОМ ПОЛУЧАЭТСЯ КРИВА СТРЫЛКА
      display.println("          _" );
      display.setCursor(4, 32);
      display.println("          _" );
      
      display.setCursor(66, 32);// СТРЫЛКА ВВЕРХ РАЗОМ ПОЛУЧАЭТСЯ КРИВА СТРЫЛКА
      display.write(24);
      display.setCursor(66, 30);
      display.write(30);
      
      
      
      if (prof(act_dir)->getTape() == t_sp) {      
        display.setCursor(0, 31);
        display.println("  Settings   " );
        display.println("  QR code");
        } 
        else { 
        display.setCursor(0, 35);
        display.println("  Settings   " );
        }
      
      display.setCursor(0, 49);
      display.println(" Select profile ");
      display.println(" Back" );
      
    }
  
  //        
  // add3-----------------------------------------------------------------------------------------------------------

    void Md_SelectProfile() {
    
      switch (Md_addres(3, int_add)) {
        case no_action: 
          
          Md_p_SelectProfile();
         
         break;
        case 1: 
          
          Md_StandardProfiles();
         
         break;
        case 2: 
         
          Md_MyProfiles();
         
         break;
        
        case address_entered: 
         
          if (Md_addres(3, get_add) == 3) {
           
           if (prof(act_dir)->getTape() == t_sp) {  
            
            Md_cursor(posThree, return_pos);
           
           }
           
           else{
            
            Md_cursor(posTwo, return_pos);
           
           }
           
           Md_addres(2, back); 
          
          }
           
          else{ 

           Md_cursor(no_data, reset);
          
          } 
         
         break;
      
      }
    }
    
    void Md_p_SelectProfile() {
      
      byte Lines[] = {16, 24, 32};
      Md_cursor(Lines, sizeof(Lines));
    
      display.setCursor(0, 16);
      display.println(" Standard profiles" );
      display.println(" My profiles");
      display.println(" Back" );
    
    }
  
    void Md_ProfileSettings() {
      
      if (prof(act_dir)->getTape() == t_sp) { //вид пунктiv меню якщо профіль стандартний
        
        switch (Md_addres(3, int_add)) {
          
          case no_action: 
            
            Md_p_ProfileSettings();
           
           break;
          
          case 1:
            
            Md_Buttons();
           
           break;//Buttons
          
          case address_entered: 
         
            if (Md_addres(3, get_add) == 2) {
            
             Md_cursor(posOne, return_pos);
             Md_addres(2, back); 
            
            }
            
            else{

             Md_cursor(no_data, reset);
            
            } 
         
           break;
        }
      }
        
      else { // вид пунктів якщо вибрано власний профіль
        
        if (!Md_addres(3, get_add) && MdAf_profileStorage(check_changes) == recorded_changes) {//перевірка на наявність змін
           
          switch (MdAf_consenDisplay()) {//якщо є зміни запуститься дисплей підтвердження при виході з настройок
            
            case choice_yes:
            
              MdAf_profileStorage(copy_profile);//якщо виберемо так профіль повторно скопірується і функція MdAf_profileStorage  перестане видавати recorded_changes
            
             break;
            
            case choice_no:
            
              MdAf_profileStorage(return_save);//якщо виберемо Ні функція dAf_profileStorage перестане видавати recorded_changes і  умова перестане  виконуватися
              
             break;
          
          }
        }
        
        else{
        
          switch (Md_addres(3, int_add)) {
            
            case no_action: //a2

              Md_p_ProfileSettings();//відображення пунктів настройки
    
             break;
            
            case 2://Gyroscope //a4
              
              Md_gyroscopeSettings();
              
             break;
            
            case 1://Buttons
             
              Md_Buttons();
             
             break;
            
            case 3://Name
            
              Md_changeNameProfile();
            
             break;
            
            case 4://Reset
            
             break;
            
            case address_entered: 
              
              if (Md_addres(3, get_add) == 5) {
              
              Md_cursor(posOne, return_pos); //копіюємо профіль при доході в настройки для подальшої перевірки на зміни при виході 
              Md_addres(2, back);
              
              }
              
              else{
              
               Md_cursor(no_data, reset);
              
              } 
          
            break;
            
          }
        }
      }
    }
       
    void  Md_p_ProfileSettings() {
      
      byte LinesSp[] = {16, 24};
      byte LinesMp[] = {8, 16, 24, 38, 50};
      
      if (prof(act_dir)->getTape() == t_sp) {      
        Md_cursor(LinesSp, sizeof(LinesSp));
        display.setCursor(0, 16);
        display.println(" Buttons" );//не добавляти пункт reset не потрібно
        display.println(" Back" );
      
      } 
      else {
        Md_cursor(LinesMp, sizeof(LinesMp));

        display.drawRoundRect(9, 6, 59, 28, 0, WHITE);
        display.setCursor(0, 8);
        display.println("  Gyroscope" );
        display.println("  Buttons" );
        display.println("  Name" );
        
        if(Md_cursor(noData, get_pos) == 4){
          display.setCursor(38, 35);// КРИВА СТРЫЛКА ВВЕРХ СТРЫЛКА
          display.println("_" );
          display.setCursor(40, 35);
          display.write(24);
        }
        
        display.setCursor(0, 38);
        display.println(" Reset" );
        
        display.setCursor(0, 50);
        display.println(" Back" );
      }

    }
  //                
  // add4-----------------------------------------------------------------------------------------------------------
    
    void Md_StandardProfiles() {
    
      
      switch (Md_addres(4, int_add)) {
        
        case no_action: 
        
          Md_p_StandardProfiles();//відображення списку профілів вибір
        
         break;
        
        case address_entered: 
         
          if (Md_addres(4, get_add) == 8) {
          
            Md_cursor(posOne, return_pos);
            Md_addres(3, back);
          
          }
          
          else{

           
            if (prof(act_dir)->getNamberTape() != prof(direct_p_sp, Md_addres(4, get_add))->getNamberTape()) {
           
             prof(activate_p_sp, Md_addres(4, get_add));
             Md_cursor(posOne, return_pos);
             Md_addres(2, back); 
            
            }
          
            else{Md_addres(4, back); }
          
          }

         break;
 
      }
    }
    
    void  Md_p_StandardProfiles(){
      
      byte Lines[] = {0, 8, 16, 24, 32, 40, 48, 56};
      Md_cursor(Lines, sizeof(Lines));
    
      for (int i = 0; i < 7; i++) {//виводим імена профілів діючий профіль мигає
      
       display.setCursor(6, i*8);
       display.print(prof(direct_p_sp, i+1)->nameProfiles(get_name_a_f));
      
      }
      
      display.setCursor(0, 56);
      display.println(" Back" );
    
    }
    
    void Md_MyProfiles(){
     
      switch (Md_addres(4, int_add)){//третій параметр забороняє вибирати діючий профіль
        
        case no_action: 
           
           Md_p_MyProfiles();
          
          break;
        
        case address_entered: 
         
          if (Md_addres(4, get_add) == 8) {//повертаємося в передній пункт
          
            Md_cursor(posOne, return_pos);
            Md_addres(3, back);
          
          }
          
           else{

           
            if (prof(act_dir)->getNamberTape() != prof(direct_p_mp, Md_addres(4, get_add))->getNamberTape()) {
           
             prof(activate_p_mp, Md_addres(4, get_add));
             Md_cursor(posOne, return_pos);
             Md_addres(2, back); 
            
            }
          
            else{Md_addres(4, back); }
          
          }

         break;
        
      }
    }
    
    void  Md_p_MyProfiles() {
      
      byte Lines[] = {0, 8, 16, 24, 32, 40, 48, 56};
      Md_cursor(Lines, sizeof(Lines));
    
      for (int i = 0; i < 7; i++) {
      
       display.setCursor(6, i*8);
       display.print(prof(direct_p_mp, i+1)->nameProfiles(get_name_a_f));
      
      }
      
      display.setCursor(6, 56);
      display.println("Back" );
    
    }
   
    void Md_gyroscopeSettings(){//a3
      
      int seveData;//використовую щоб було більш зрозуміліше

      if (Md_addres(4, get_add) != 5){Md_p_gyroscopeSettings();}
      
      switch (Md_addres(4, int_add_last, 5)) {//4
        
        case no_action:break;
        
        case 1:
          
          seveData = Mf_Magnifier(prof(act_dir)->getDeZoHor(), 0, 9999, 100);
          prof(act_dir)->setDeZoHor(seveData);
         
         break;
        case 2:
          
          seveData = Mf_Magnifier(prof(act_dir)->getSenHor(), 0, 100, 100);
          prof(act_dir)->setSenHor(seveData);
         
         break;
        case 3:
          
          seveData = Mf_Magnifier(prof(act_dir)->getDeZoVer(), 0, 9999, 100);
          prof(act_dir)->setDeZoVer(seveData);
        
         break;
        
        case 4:
          
          seveData = Mf_Magnifier(prof(act_dir)->getSenVer(), 0, 100, 100);
          prof(act_dir)->setSenVer(seveData);        
         
         break;
        
        case 5:
          
          Md_cursor(posOne, return_pos);
          Md_addres(3, back);   
         
         break;
      
      }
    }
  
    void Md_p_gyroscopeSettings() {
      
      static uint32_t tmr;
      static byte dashFlag;//прапорець м'ягання
      
      if (tmr < millis()) {
        
        tmr = millis() + 500;
        dashFlag = ! dashFlag;
      
      }
     
      byte Lines[] = {5, 15, 34, 44, 55};
      Md_cursor(Lines, sizeof(Lines));
    
      display.setCursor(8, 5);
      display.println("Dead zone ");
      display.setCursor(8, 15);
      display.println("Sensitivity");
      display.setCursor(8, 34);
      display.println("Dead zone ");
      display.setCursor(8, 44);
      display.println("Sensitivity");
      display.setCursor(8, 55);
      display.println("Back");
      
      display.setCursor(84, 10);
      display.println("H");
    
      display.setCursor(84, 39);
      display.println("V");
      
      display.setCursor(102, 4);
      display.println(prof(act_dir)->getDeZoHor());
    
      display.setCursor(104, 17);
      display.println(prof(act_dir)->getSenHor());
      
      display.setCursor(102, 33);
      display.println(prof(act_dir)->getDeZoVer());
      
      display.setCursor(104, 46);
      display.println(prof(act_dir)->getSenVer());
      
      
      display.drawRoundRect(6, 2, 69, 23, 3, WHITE); //РАМКА НАВКОЛО Dead zone Sensitivity H
      display.drawRoundRect(6, 31, 69, 23, 0, WHITE);//РАМКА НАВКОЛО Dead zone Sensitivity V
      
      //H
      if((Md_cursor(noData, get_pos) == 1 || Md_cursor(noData, get_pos) == 2) && !Md_addres(4, get_add)){// РАМКА  НВКОЛО H
       
       if(dashFlag){display.drawRoundRect(79, 6, 15, 15, 0, WHITE);}
      
      }
      
      else{display.drawRoundRect(79, 6, 15, 15, 0, WHITE);}
      
      //V
      if((Md_cursor(noData, get_pos) == 3 || Md_cursor(noData, get_pos) == 4) && !Md_addres(4, get_add)){// РАМКА  НВКОЛО V
       
       if(dashFlag){display.drawCircle(86, 42, 7, WHITE);}
      
      }
      
      else{display.drawCircle(86, 42, 7, WHITE);}   
      
      
      if(Md_addres(4, get_add) == 1){ // число рамка DZ H
       
       if(dashFlag){display.drawRoundRect(99, 2, 29, 11, 4, WHITE);}
      
      }
      
      else{display.drawRoundRect(99, 2, 29, 11, 4, WHITE);}
      
      if(Md_addres(4, get_add) == 2){ // число рамка S H
      
       if(dashFlag){display.drawRect(101, 15, 23, 11, WHITE);}
      
      }
      
      else{display.drawRect(101, 15, 23, 11, WHITE);}
      
      if(Md_addres(4, get_add) == 3){ // число рамка DZ V
      
       if(dashFlag){display.drawRect(99, 31, 29, 11, WHITE);}
      
      }
      
      else{display.drawRect(99, 31, 29, 11, WHITE);}

      if(Md_addres(4, get_add) == 4){ // число рамка S V
       
       if(dashFlag){display.drawRoundRect(101, 44, 23, 11, 4, WHITE);}
      
      }
      
      else{display.drawRoundRect(101, 44, 23, 11, 4, WHITE);} 
       
    }
    
    void Md_Buttons() {
  
      static unsigned long tmr;
      static byte currenState;
      static byte saveButton;
      static byte butFlag;
      
      Md_p_Buttons();
      
      switch (Md_addres(4, int_add_last, 3)) {
        
        case no_action:
          
          break;
        
        case 1:
          
          if(!butFlag){
            
            for (int i = 0; i <= 1; i++) {
            
              if(!digitalRead(buttonArray[i])){
                      
                butFlag = 1;
                
                if(!saveButton){
                  
                  Md_p_Buttons(animation_two, i);
                  butFlag = 1;
                  saveButton = buttonArray[i];
                  break;
                
                }
                
                else {
                  
                  Md_p_Buttons(animation_stope_one, i);
                  buttonArray[i] = saveButton;
                  saveButton = 0;
                  Md_cursor(posOne, return_pos);
                  Md_addres(4, back);
                  break;
                
                }
                
                
                
                break;
              
              }   
            }   
          }
          
          else if(butFlag){
            
            for (int i = 0; i <= 1; i++) {
            
              if(digitalRead(buttonArray[i])){
                
                break;
              
              }   
              
              butFlag = 0;
            
            }   
          }

          break;

        
        case 3:
           
           Md_cursor(posTwo, return_pos);
           Md_addres(3, back);
         
         break;
        
        case address_entered:
          
          if(Md_addres(4, get_add) == 1){
          
           Md_p_Buttons(animation_one);
          
          }
          
         break;
        
        case address_deleted:
          
          Serial.println("111111111");
          Md_p_Buttons(cancel_actions);
          
          if(saveButton){
              
           saveButton = 0;
          
          }
        
         break;
      
      }
      
    }
    
    byte Md_p_Buttons(byte receivedData = 0, byte selectedButton = 0){
      
      static byte runningArrow;
      static byte questionMarkFlag;
      static byte animation;
      static byte buttonOne;
      static byte buttonTwo;
      static byte accumulationL;  
      static byte accumulationR;
      static unsigned long tmr;  

      const char *buttonNames[] = {
        "A",
        "B",
        "X",
        "Y",
        "LB",
        "RB",
        "LT",
        "RT",
        "LA",
        "RA",
      };
      
      if (receivedData == animation_two) {
         
        buttonOne = selectedButton;
        
      }
        
      else if (receivedData == animation_stope_one){
          
        buttonTwo = selectedButton;
        
      }
      
      if (receivedData) {
        
        if (cancel_actions == receivedData) {
         
         accumulationL = accumulationR = questionMarkFlag = runningArrow = buttonOne = buttonTwo = animation = 0;
        
        }
        
        else {
        
         animation = receivedData;
        
        }
      
      }
      
      if (animation && tmr < millis()) {
        
        if (animation == animation_stope_two) {
          
         accumulationL = accumulationR = questionMarkFlag = runningArrow = buttonOne = buttonTwo = animation = 0;

        }
        
        else{
          
         tmr = millis()+400; 
        
        }
        
        if (runningArrow < 7) {
          
          runningArrow++;
        
        } 
        
        else{
        
         runningArrow = !runningArrow;
        
        }
        
        
        if ( questionMarkFlag < 2) { 
          
          questionMarkFlag++;
        
        } 
        
        else{
        
         questionMarkFlag = !questionMarkFlag;
        
        }
        
        if (animation == animation_one && accumulationL < 3) {
          
          accumulationL++;
        
        } 
        
        else if (accumulationL) {
        
        accumulationL = 0;
        
        }
        
        
        if (animation == animation_two && accumulationR < 3) {
          
          accumulationR++;
        
        } 
        
        else if (accumulationR) {
        
        accumulationR = 0;
        
        } 
        
      }

      //display.drawRect(0, 0, 127, 63, WHITE);// test ramka

      display.drawRect(6, 5, 31, 31, WHITE); // квадрат L
      display.drawRect(90, 5, 31, 31, WHITE);// квадрат R
      
    
      if (accumulationL) {
      
       display.setCursor(19, 13);
      
      }
      
      else if (accumulationR) {
      
       display.setCursor(103, 13);

      }
      
      if (questionMarkFlag) {
      
       display.println('?');
      
      }
      
      if (animation == animation_two) {
      
        display.setCursor(22-strlen(buttonNames[buttonOne])*3, 13);
        display.println(buttonNames[buttonOne]);
      
        for (int i = 0; i < 8; ++i) {
        
        display.setCursor(40+i*6, 13);
        display.write(62);
      
        }
      
        display.setCursor(40+runningArrow*6, 13);
        display.write(16);
      
      }
      
      else if (animation == animation_stope_one || animation == animation_stope_two) {
        
      
        if (animation == animation_stope_one) {
          
          accumulationL = accumulationR = questionMarkFlag = runningArrow = 0;

          animation = animation_stope_two;
          tmr = millis()+1000; 
        
        }
        
        display.setCursor(22-strlen(buttonNames[buttonOne])*3, 13);
        display.println(buttonNames[buttonOne]);
      
        
        display.setCursor(106-strlen(buttonNames[buttonTwo])*3, 13);
        display.println(buttonNames[buttonTwo]);
        
      }

      display.drawCircle(21, 16, 8, WHITE);//кружки над кнопками
      display.drawCircle(105, 16, 8, WHITE);
      
      display.drawRect(12, 26+accumulationL, 19, 5, WHITE);//ліва кнопка
      display.fillRect(9, 30, 25, 4, WHITE);
      
      display.drawRect(96, 26+accumulationR, 19, 5, WHITE);//права кнопка
      display.fillRect(93, 30, 25, 4, WHITE);

      byte Lines[] = {40, 48, 56};
      Md_cursor(Lines, sizeof(Lines));
      
      display.setCursor(0, 40);
      display.println(" Move buttons");
      display.println(" Reset");      
      display.println(" Back");


      return 0; 

    }         
    
    void Md_changeNameProfile(){
      
      static int8_t AxisX, AxisY, storedAction, inputIndicator, axisChange;
      static uint32_t tmr;
    
     char letterBig[5][10] = {
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
        {'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'},
        {'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '-'},
        {'!', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '.', '<'},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>'}
      };
      
      char letterSmall[5][10] = {
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
        {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'},
        {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '-'},
        {'!', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '.', '<'},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>'}
      };
    
     static char (*ptrLetter)[10] = letterSmall;//вказівник вказує в залежності від настройки на великі або малі букви
      
      if (!inputIndicator && ptrLetter == letterSmall && !storedAction) {//якщо видаляється остання буква одноразово всі букви робляться великими
        
        storedAction = 1;
        
        for (int i = 19; i >= 0; i--) {
         
          if (prof(act_dir)->nameProfiles(get_name)[i] != ' '){
           
           inputIndicator = i+1;
          
           break;
          }
          
          else if (!i){
           
           ptrLetter = letterBig;
           inputIndicator = 0;
          
           break;
          
          }
        
        }
      }
      
      else if (inputIndicator && storedAction) {
        
        storedAction = 0;
      
      }
      
      switch (Mf_EncoderButton(200)) {
        
        case click:
          
          switch (ptrLetter[AxisY][AxisX]) {
            
            case '!': //міняємо величину букв
              
              if (ptrLetter == letterBig) {
                
                ptrLetter = letterSmall;
              
              }
              
              else {
                
                ptrLetter = letterBig;
              
              }
              
             break;
            
            case '>'://вихыд
              
              AxisX = AxisY = inputIndicator = 0;
              Md_cursor(posThree, return_pos);
              Md_addres(3, back);
  
             break;
            
            case '<': //видаляємо букви
               
              if (inputIndicator ) {
              
               inputIndicator--;
               prof(act_dir)->nameProfiles(change_letter, inputIndicator, ' ');
              
              }
              
             break;
            
            default://введення вибраної букви
              
              if (inputIndicator <= 19) {
               
                prof(act_dir)->nameProfiles(change_letter, inputIndicator, ptrLetter [AxisY][AxisX]);
                
                if (inputIndicator == 0) {
                 
                 ptrLetter = letterSmall;
                
                }
                
                inputIndicator++;
              
              }        
          
          }   
          break;
        
        case hol_const://якщо кнопка зажата курсор переміщається по вертикалі
          
          if (!axisChange) {
            
            axisChange = !axisChange;
          
          }
        
         break;
        
        case hol_released://повертаємо звичайний режим роботи
          
          if (axisChange) {
            axisChange = !axisChange;
          }
          
          if (AxisY == 4 ){//переміщаємо курсор для коректної роботи якщо останній масив
          
          if (AxisX <= 7){
            AxisX = 0;
          }
          
          else{AxisX = 9;}
          
          }
         break;
      
      }
      
      switch (Mf_encoderActionStorage(get_status)) {
        
        case 0: 
        
        break;
        
        case rotated_rights: 
          
          if (!axisChange) {AxisX--;}//\переміщення в залежності від режиму
          else {AxisY--;}  
          
          if (AxisY == 4 && AxisX == 8) {//корекція курсора якщо попали на останній масив костильі)
            AxisX = 0;
          }
          if (AxisX < 0) {
          AxisX = 9;
          AxisY--;
          }
          if (AxisY < 0) {AxisY = 4;}
        
        break;
        
        case rotated_left: 
          
          if (!axisChange) {AxisX++;}
          else {AxisY++;}  
          
          if (AxisY == 4 && AxisX == 1) {
          AxisX = 9;
          }
          if (AxisX > 9) {
          AxisX = 0;
          AxisY++;
          } 
          if (AxisY > 4 ) {AxisY = 0;} 
        
        break;   
      }
      
      Md_p_changeNameProfile(ptrLetter, inputIndicator, AxisX, AxisY);

    }
    
    byte Md_p_changeNameProfile(char letter[][10], byte inputIndicator, byte AxisX, byte AxisY){
      
      static char tracking;//використовується для відслідковування позиції рамки
      char str[] = {'!', '<', ' ', '>'};//маси використовується для мигання необхідної рамки
      static byte flagBlink[5];
      static uint32_t tmr, tmrInd;
      
      display.setCursor(6, 44);///набір різних стрілок
      
      if(letter[1][1] == 'W'){//якщо в масиві є великі букви значить стрілочка вниз
        
        display.write(25);//стрілочка вниз малі букви
      
      }
      else{display.write(24);}//стрілочка вверх великі букви
      
      display.setCursor(114, 54);//back
      display.print('s'); 
      display.drawPixel(120, 60, WHITE); //крапка
      
      if(!flagBlink[0]){//кружок стрілка вниз вверх
       
       display.drawCircle(8, 47, 5, WHITE);
      
      }
      
      if(!flagBlink[1]){// видалення
        
        display.setCursor(114, 43);
        display.print('x'); 
        display.drawCircle(116, 47, 4, WHITE);
      
      }
      
      display.fillRect(36, 54, 54, 6, WHITE);//пробіл
      
      if(letter[AxisY][AxisX] == ' '){//додаткова рамка якщо навели на пробіл
       
       display.drawRect(34, 52, 58, 10, WHITE);
      
      }
      
      if(!flagBlink[3]){//рамка s.
       
       display.drawRoundRect(112, 54, 9, 9, 0, WHITE);
      
      }
      
      for (int i = 0; i < 4; i++) {
        
        if(tracking != letter[AxisY][AxisX]){//можливі розрив захист від зникнення рамки
          
          flagBlink[0] = flagBlink[1] = flagBlink[2] = flagBlink[3] = tmr = 0;//якщо було переміщення обнуляємо всі переміни 
          tracking = letter[AxisY][AxisX];//перезаписуємо перемінно новими даними
        
        }

        if(letter[AxisY][AxisX] == str[i]){

         if(tmr < millis()){
          
          tmr = millis()+400;
          flagBlink[i] = !flagBlink[i];
         
         }
         
         break;
        }
        
        else if(i == 3 ){//
          
          display.drawRect(4+AxisX*12, 12+AxisY*10, 9, 11, WHITE);//рамка курса 10 вверх вниз, вліво вправо 12 
          break;
        
        }
      }
        
      if(inputIndicator != 20){//вертикальна риска біля букви мигання 
        
        if(tmrInd < millis()){
          
          tmrInd = millis()+400;
          flagBlink[4] = !flagBlink[4];
        
        }        
      }
      
      if(flagBlink[4] || inputIndicator == 20){//перестає мигати якщо 20 символів
       
        display.drawRect(2+6*inputIndicator, 0, 1, 9, WHITE);
      
      }
      
      display.setCursor(2, 1);//виводив ім'я профіля
      display.print(prof(act_dir)->getName());
      
      for (int i = 0; i < 4; i++) {//виводим масив букв на дисплей
        
        for (int j = 0; j < 10; j++) {
          
          display.setCursor(6+j*12, 14+i*10);
          
          if(letter[i][j] != '!' && letter[i][j] != '<'){//ці знаки не можна виводити використовується для виконання дій
           
           display.print(letter[i][j]);
          
          }
        }
      }
      
      return 0; 
    }
  
  //
  // Additional functions-------------------------------------------------------------------------------------------
    
    byte MdAf_consenDisplay(){ //викликається для підтвердження вибору
      
      static int8_t flagChoice;
      
      switch (Mf_encoderActionStorage(get_status)) {//керування рамкою вліво вправо
       
        case no_action: 
          
          break;
        
        case rotated_rights: 
          
          if (flagChoice > -2) {
           
           flagChoice--;
          
          }
          
         break;
        
        case rotated_left: 
          
          if (flagChoice < 2) {
           
           flagChoice++;
          
          } 
          
         break;
      }
      
      if ((flagChoice == -2 || flagChoice == 2) && Mf_EncoderButton(500) == click) {// V1 якщо відбувся Клік виконується дії в залежності від вибору
        
        if (flagChoice == -2) {//якщо вибрали ні виконуються дії//вихід виконується в любому випадку з збереженими настройками або ні
           
          flagChoice = 0;
          return choice_no;
        
        }
        
        else if (flagChoice == 2) {
           
          flagChoice = 0;
          return choice_yes;
        
        }
        
      }
            
      MdAf_consenDisplayPrint(flagChoice);//візуальна частина коду
    
     return 0;
    
    }
      
    int8_t MdAf_consenDisplayPrint(int8_t acceptedFlag){
      
      static uint32_t tmr;
      static int8_t  FlagFrame;
      
      if (tmr < millis()) {
        
        tmr = millis() + 400;
        FlagFrame = !FlagFrame;
      
      }
      
      display.drawRoundRect(20, 8, 87, 22, 0, WHITE); //рамка навколо слова зверху
      
      display.setCursor(28, 15); 
      display.println("Confirm save");
      
      if (FlagFrame) {
       
       display.drawRect(52+acceptedFlag*18, 39, 21, 13, WHITE);
      
      }
      
      for (int i=39; i <= 75; i+=18){
       
       display.setCursor(i,42);
       display.write(27);display.write(26); 
      
      }
      
      display.setCursor(21, 42);
      display.println("NO");
      display.setCursor(18, 42);
      display.println("            YES");
      
      return 0;
    
    }
    
    byte MdAf_profileStorage(byte acceptedCommand) {//функція викликається якщо Md_addres(3, get_add) == 1
     
      switch (acceptedCommand) {//false якщо повертаємо збережені настройки
        
        case return_save:
           
           prof(act_dir)->copyFrom(profilSeve);//це означає що ми вибрали ні і повертаємо настройки
          
          break;
       
        case copy_profile:
           
           profilSeve.copyFrom(*prof(act_dir));//копіювання діючий профіль перед доходом в настройки
          
          break;
        
        case check_changes:
  
           if (profilSeve != *prof(act_dir)) {return recorded_changes;}
          
          break;
      }
      return 0;
    }
      
    byte MdAf_reminderDisplay(byte acceptedCommand) {

      static uint32_t tmr;

      display.clearDisplay();

      display.drawRect(0, 14, 127, 30, WHITE);// РАМКА НАВКОЛО НАЗВИ

      if (acceptedCommand == reset) {
        tmr = 0;
      }
      else if (!tmr) {
        tmr = millis() + 2000;
      }
      else if (tmr < millis()) {
        tmr = 0;
        Md_Display(info_display);
      }

      display.setCursor(0, 16);

      display.println("  Read instruction");// НАГАДУВАННЯ
      display.println("   " );//27
      display.println(" Make game settings " );//27

      display.setCursor(60, 50);
      display.print("b");

      display.drawCircle(62, 53, 6, WHITE);//кружок

      display.display();
    }

    void MdAf_infoDisplay() {

      display.clearDisplay();//не забути доробити періодичне виведення

      MdAf_BluetoothPrint(); MdAf_typeNumberPrint(); MdAf_batteryPrint();

      display.drawRect(0, 14, 127, 19, WHITE);// РАМКА НАВКОЛО НАЗВИ

      display.setCursor(prof(act_dir)->centroName(), 20);// функція centroName() в залежності від кількості ім'я вранці
      display.print(prof(act_dir)->nameProfiles(get_name));
      
      display.setCursor(44,44);
      display.write(26);
      
      display.drawRect(50, 42, 27, 11, WHITE);
      display.setCursor(52,44);
      display.print("Menu");
      
      display.display();
    }

    void MdAf_BluetoothPrint() {

      static uint32_t tmr;
      static byte FlagPriS;
      static byte BluTest;

      display.setCursor(4, 3);
      //display.write(127 + 47);
      display.print("b");

      if (!BluTest) {
        display.drawCircle(6, 6, 6, WHITE);//кружок
      }

      if (BluTest) {
        display.drawCircle(6, 6, 6, WHITE);//кружок
      }

      if (FlagPriS != 3 && tmr < millis()) {
        FlagPriS++;
        tmr = millis() + 1000;
      }
    }

    void MdAf_batteryPrint() {

      display.setCursor(17 * 6, 0);
      display.print("123");

    }

    void MdAf_typeNumberPrint() {
      
      display.setCursor(49, 0);
      if (prof(act_dir)->getTape() == t_sp) { 
       
       display.print("(Sp");
       display.print(prof(act_dir)->getNamber());
       
      }
      else {
       
       display.print("(Mp");
       display.print(prof(act_dir)->getNamber());
      }
      display.print(")");
    }

  //Af
//Md

//Display 4
  byte Md_Display(byte Receiving) { 
     
    //static byte Regime = info_display; 
    static byte Regime = menu;
      
      switch (Receiving) {
        
        case get_status: 
          
           return Regime;
          
          break;
        
        case menu: 

          Regime = menu;
          
          break;
        
        case info_display: 
          
          Regime = info_display;
        
          break;
        
      }
    
   return Regime;
  } 

//D

//Menu_functions 5 
 
  byte Md_cursor(byte* arr, byte acceptedCommand) { 
    
    static int8_t Arrow, Point = 1;
        
    switch (acceptedCommand) {
      case return_pos: 
          Point = arr[0];
          Arrow = 0;
        break;
      case reset: 
          Arrow = 0;
          Point = 1;
        break;
      case selection_inversion: 
          Arrow = !Arrow;
        break;
      case get_pos: 
         return Point; 
        break;
      default:
        switch (Mf_encoderActionStorage(get_status)) {
          case no_action: 
            break;
          case rotated_left: 
            if (!Arrow) {Point--;}
            if (Point == 0) {Point = acceptedCommand;}
            break;
          case rotated_rights: 
            if (!Arrow) {Point++;}
            if (acceptedCommand < Point) {Point = 1;}
            break;
        }
        if (!Arrow) {
          display.setCursor(0, arr[Point-1]);  //21,8 максимум символів
          display.write(26);
          }
        else if (Arrow) {
          display.setCursor(0, arr[Point-1]);  //21,8 максимум символів
          display.write(16);
        }   
      } 
   return 0;
  } 
    
  int8_t Md_addres(int8_t AddNumb, int8_t acceptedCommand, int8_t acceptedData = 0) {

    static byte Adr[19], modeSwitch, namb = 1;

    switch (acceptedCommand) {
      
      case back:
          
        modeSwitch = 0;
        
        for (int i=18; i >= 1; i--){
          
          Adr[i] = 0;
          
          if (i == AddNumb) {
            
            namb = AddNumb;
            break;
          
          }
        
        }
       
       break;
      
      case get_add:
        
        return Adr[AddNumb];
       
       break;
              
      default://int_add
       
        if (!modeSwitch && !Adr[AddNumb] && Mf_EncoderButton(500) == click){
          
          Adr[namb] = Md_cursor(noData, get_pos);
          
          if (acceptedCommand == int_add_last && acceptedData != Md_cursor(noData, get_pos)){ 
          
           Md_cursor(noData, selection_inversion);
           modeSwitch = !modeSwitch;
          
          }
          
          else {
            
            namb++;
          
          }
          
          return address_entered;
        
        }
        
        else if (modeSwitch && Mf_EncoderButton(500) == click){
         
         Adr[namb] = modeSwitch = 0;
         Md_cursor(noData, selection_inversion);
         
         return address_deleted;
        
        }      
    
    }
    
    return Adr[AddNumb];

  }
  
  int8_t Mf_encoderActionStorage(int8_t acceptedCommand) {

   static int8_t operationRetention;//збереження спрацювання
  
    if (acceptedCommand == rotated_left || acceptedCommand == rotated_rights) {
    operationRetention = acceptedCommand;
    }
    else if (acceptedCommand == get_status ) {
      acceptedCommand = operationRetention;
      operationRetention = 0;
      return acceptedCommand;
    }
    return 0;
  }
  
  int Mf_EncoderButton(int retentionAfter) {

    static byte buttonState = released_const;
    static uint32_t tmr;

    if (Ae_BatR(b_sw)){
      
      if (buttonState == released_const) {
        buttonState = press_const; 
        tmr = millis() + retentionAfter; 
        return press;
      }
      else if (tmr && tmr < millis()) {
        buttonState = hol_const; 
        tmr = 0; 
        return hol_but;
      }
    }

    else if (!Ae_BatR(b_sw)){
      if (buttonState == hol_const) {buttonState = released_const; return hol_released;}
      else if (buttonState == press_const) {buttonState = released_const; return click;}
    }
      
    return buttonState;
      
  }
 
  int Mf_Magnifier(int Numeric, int Min, int Max, int Speed) {
   
   static uint32_t tmr;
   static int counter = 1;
   
    switch (Mf_encoderActionStorage(get_status)) {
      case rotated_rights:
         tmr = millis()+500;
         Numeric += counter;
         if (Speed > counter) {
          counter++;
         }
        break;
      case rotated_left:
         tmr = millis()+500;
         Numeric += -counter;
         if (Speed > counter) {
          counter++;
         }
        break;
    }
    if (counter != 1 && tmr < millis()) {        
      tmr = millis()+counter/2;
      counter--;
    }
    
    if (Numeric > Max) {
      Numeric = Min;
    } else if (Numeric < Min) {
      Numeric = Max;
    }
   return Numeric;
  }

//Mf

//Gamepad_function 6
//Gf

void setup() {
  
  Serial.begin(9600);// В ФЫНАЛЫ НЕЗАБУТИ ЗАКОМЕНТУВАТИ!!!
  Wire.begin();
  
  //pin 34 35 обережно глюки здаєтся немож зроб INPUT_PULLUP, pin 2 дыод! esp 32

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  
  pinMode(b_sw, INPUT_PULLUP);  //енкодер кнопка SW
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  //Ae_InterruptReadPinDtEncoder()
  attachInterrupt(digitalPinToInterrupt(p_dt), Ae_InterruptReadPinDtEncoder, CHANGE);


  //----------Display--------------
  //display.cp437(true);  //rus текст
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setTextWrap(false);
  display.clearDisplay();
  display.display();

}

void loop() {
  
 
  switch (Md_Display(get_status)) {
    
    case info_display: 
        
        if (Mf_EncoderButton(500) == click) {

         Md_Display(menu);
        
        }
        
        MdAf_infoDisplay();
        
        /*
        if (bleGamepad.isConnected()) {
        Gf_ModifiedButtonInput();
        Gf_AnLeftAxisX();//H
        Gf_AnLeftAxisY();//V
        Gf_AnRightZ(get_status);//H G
        Gf_AnRightRZ(get_status);//V G
        bleGamepad.sendReport();
        }
      */
      
      break;
   
   case menu:
       
       Md_MainDisplay();
    
      break;
   
  }  
    
    
    
    
     
    
  
  

}  //void loop()