/* =====================================================================================

   Curso de Arduino e AVR WR Kits Channel
   
   Aula 282 - Menu em Lista Profissional

   https://www.youtube.com/watch?v=W2jvVSR1Kj0

   Aplicações, controle de LEDs (ou outras cargas)
   
   Autor: Eng. Wagner Rambo  
   Data: Março de 2021


===================================================================================== */
 

// =====================================================================================
// --- Mapeamento de Hardware ---
#define   db7        7
#define   db6        6
#define   db5        5
#define   db4        4
#define   db3       11
#define   db2       10
#define   db1        9
#define   db0        8

#define   rs        13
#define   en        12
#define   rw         3  //normalmente ligamos RW no GND, usar só no caso de querer ler dados do LCD.

#define   menu_bt   14
#define   ent_bt    15

#define   led1       3
#define   led2       2


// =====================================================================================
// --- Constantes do Projeto ---
#define   MENU_MAX   5


// =====================================================================================
// --- Protótipo das Funções ---
void char_pos(char row, char col);
void set_col(char address);
void send_char(char character, char row, char col);
void lcd_init();
void lcd_clear();
void send_byte(char s_byte);
char receive_byte();
void pulse_enable();

void read_bts();
void menu_main();
void menu_select();


// =====================================================================================
// --- Variáveis Globais ---
int      menu_number = 1;       
bool     sub_menu    = 0;
         

// =====================================================================================
// --- Configurações Iniciais ---
void setup()
{

  pinMode(menu_bt,  INPUT_PULLUP);
  pinMode(ent_bt,   INPUT_PULLUP);
  pinMode(led1,           OUTPUT);
  pinMode(led2,           OUTPUT);
  
  lcd_init();
  
    
    
} //end setup
 
// =====================================================================================
// --- Loop Infinito ---
void loop()
{

  menu_main();
  read_bts();
 
} //end loop


// =====================================================================================
// --- Desenvolvimento das Funções ---


void read_bts()
{
   static bool menu_flag  = 0, enter_flag = 0;
              
   if(!digitalRead(menu_bt))  menu_flag  = 0x01;
   if(!digitalRead(ent_bt))   enter_flag = 0x01;

   if(digitalRead(menu_bt) && menu_flag)
   {
       menu_flag = 0x00;
       menu_number+=1;
       if(menu_number > MENU_MAX) menu_number = 1;
       delay(150);
    
   } //end if menu

   if(digitalRead(ent_bt) && enter_flag)
   {
      enter_flag = 0x00; 
      lcd_clear();
      sub_menu = !sub_menu;
      menu_select();
      delay(150);
    
   } //end if menu
  
  
} //end read_bts


void menu_main()
{
  char titles[][16]=
       { '1',' ','L','E','D',' ','1',' ','P','W','M',' ',' ',' ',' ',' ',
         '2',' ','L','E','D',' ','2',' ','O','N',' ',' ',' ',' ',' ',' ',
         '3',' ','L','E','D',' ','2',' ','T','O','G','G','L','E',' ',' ',
         '4',' ','O','F','F',' ','A','L','L',' ',' ',' ',' ',' ',' ',' ',
         '5',' ','H','E','L','P',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', };
  
  send_char('>',1,1); 
  
  if(!sub_menu)
  {
    switch(menu_number)
    {
      case 1: 
              for(int i=0,j=2;i<16,j<16;i++,j++)
              { 
                send_char(titles[0][i],1,j);
                send_char(titles[1][i],2,j);
              } //end for
              break;
      case 2: 
              for(int i=0,j=2;i<16,j<16;i++,j++)
              { 
                send_char(titles[1][i],1,j);
                send_char(titles[2][i],2,j);
              } //end for
              break;      
      case 3: 
              for(int i=0,j=2;i<16,j<16;i++,j++)
              { 
                send_char(titles[2][i],1,j);
                send_char(titles[3][i],2,j);
              } //end for
              break;
      case 4: 
              for(int i=0,j=2;i<16,j<16;i++,j++)
              { 
                send_char(titles[3][i],1,j);
                send_char(titles[4][i],2,j);
              } //end for
              break;
      case 5: 
              for(int i=0,j=2;i<16,j<16;i++,j++)
              { 
                send_char(titles[4][i],1,j);
                send_char(titles[0][i],2,j);
              } //end for
              break;
      
      
    } //end switch
    
  } //end if !sub_menu
  
  
} //end manu_main


void menu_select()
{

    switch(menu_number)
    {
       case 1: 
               send_char('A',1,2);
               send_char(' ',2,2);
               analogWrite(led1, 55);
               break;
       case 2: 
               send_char('B',1,2);
               send_char(' ',2,2);
               digitalWrite(led2, HIGH);
               break;
       case 3: 
               send_char('C',1,2);
               send_char(' ',2,2);
               digitalWrite(led2, HIGH);
               delay(100);
               digitalWrite(led2,  LOW);
               break;
       case 4: 
               send_char('D',1,2);
               send_char(' ',2,2);
               digitalWrite(led1, LOW);
               digitalWrite(led2, LOW);
               break;
       case 5: 
               send_char('.',1,2);
               send_char('.',2,2);
               break;
   
    } //end switch
  
 
} //end menu_select





void char_pos(char row, char col)
{
   col -= 1;

   switch(row)
   {
      case 1: set_col(col);      break; 
      case 2: set_col(col+0x40); break;
    
   } //end switch
  
} //end char_pos


// =====================================================================================
// --- Função para Envio de Caracteres ---
void set_col(char address)
{
   digitalWrite(rs,   LOW);
   send_byte(address);
   digitalWrite(db7, (address >> 7) | 0x01);
   pulse_enable();
   
} //end set_col


void send_char(char character, char row, char col)
{

   char_pos(row, col);
   send_byte(character); 
   digitalWrite(rs,  HIGH);
   delayMicroseconds(200);
   pulse_enable();
   digitalWrite(rs,  LOW);
  
} //end send_char


// =====================================================================================
// --- Função para Inicializar LCD ---
void lcd_init()
{

   //configura saídas
   pinMode(db0, OUTPUT);
   pinMode(db1, OUTPUT);
   pinMode(db2, OUTPUT);
   pinMode(db3, OUTPUT);
   pinMode(db4, OUTPUT);
   pinMode(db5, OUTPUT);
   pinMode(db6, OUTPUT);
   pinMode(db7, OUTPUT);
   pinMode(rs,  OUTPUT);
   pinMode(en,  OUTPUT);
   pinMode(rw,  OUTPUT);

   //inicializa saídas
   digitalWrite(rw,   LOW);
   digitalWrite(en,   LOW);
   digitalWrite(rs,   LOW);
   send_byte(0x00);
   delayMicroseconds(200);
   
   // LIMPA LCD
   send_byte(0x01);
   pulse_enable();

   // MODO DE 8 BITS
   send_byte(0x38);
   pulse_enable();

   // LIGA LCD, DESLIGA CURSOR, DESLIGA BLINK
   send_byte(0x0C); //desliga cursor
  // send_byte(0x0E); //liga cursor
   pulse_enable();

   // HABILITA INCREMENTO, DESLIGA SCROLL
   send_byte(0x06);
   pulse_enable();
  
} //end lcd_init


void lcd_clear()
{

   // LIMPA LCD
   digitalWrite(rs,   LOW);
   send_byte(0x01);
   pulse_enable();

} //end lcd_clear


void send_byte(char s_byte)
{
   digitalWrite(db7, (s_byte >> 7) & 0x01);
   digitalWrite(db6, (s_byte >> 6) & 0x01);
   digitalWrite(db5, (s_byte >> 5) & 0x01);
   digitalWrite(db4, (s_byte >> 4) & 0x01);
   digitalWrite(db3, (s_byte >> 3) & 0x01);
   digitalWrite(db2, (s_byte >> 2) & 0x01);
   digitalWrite(db1, (s_byte >> 1) & 0x01);
   digitalWrite(db0, (s_byte >> 0) & 0x01);  

  
} //end send_byte


void pulse_enable()
{
   digitalWrite(en,   LOW);
   delayMicroseconds(800);
   digitalWrite(en,  HIGH);
   delayMicroseconds(200);
   digitalWrite(en,   LOW);
   delayMicroseconds(800);  
  
} //end pulse_enable


// =====================================================================================
// --- Final do Programa ---