/*

TECLADO E MONITOR NO ARDUINO UNO (BY DANTE MEIRA)

100% construído e programado no baixo nível, em C puro, sem o 
uso de bibliotecas de terceiros (nem mesmo as funções da 
biblioteca padrão da Arduino IDE)

Um "computador" com teclado e "monitor" construído sobre um
Arduino Uno utilizando apenas botões de pressão (push buttons),
registradores de deslocamento (shift registers) e 280 LEDs

Apenas seis pinos digitais do Arduino sendo utilizados (3 para
o teclado e 3 para o "monitor")

*/

#define LATCH_TECLADO PD2
#define CLOCK_TECLADO PD3
#define DADOS_TECLADO PD4  

#define LATCH_MONITOR PB0
#define CLOCK_MONITOR PB1
#define DADOS_MONITOR PB2  

#define QUANT_TECLAS 52
#define QUANT_LINHAS 7
#define QUANT_COLUNAS 40
#define QUANT_LEDS 280

int ProgramaAtivo; // variável global que especifica o programa corrente em execução

// Macros para os códigos dos programas
#define INTRO 200
#define TXT 201

unsigned long centesimos = 0; // centésimos de segundo desde que o sistema foi iniciado
unsigned long teclSampleCont = 0; // contador de tempo para sample do teclado
int estadoteclas[QUANT_TECLAS+1]; // array para armazenar estado anterior das teclas do teclado
unsigned long ultimaVezQueMudou; // última vez que mudou estado da tecla (push button)
int delayDebounce = 2; // número de centésimos de segundo para o debounce das teclas
unsigned long RasterCont = 0; // contador de rasterização
byte keybuffer = 0; // byte para armazenar última tecla pressionada
boolean framebuffer[QUANT_LEDS]; // framebuffer para rasterização


// funções para lidar com os seis pinos digitais necessários à operação do teclado e do monitor
void LatchTecladoLow(){
   PORTD &= ~(B00000001 << LATCH_TECLADO); // colocando o LATCH do teclado em LOW direto no registrador PORTD 
}
void LatchTecladoHigh(){
   PORTD |= (B00000001 << LATCH_TECLADO); // colocando o LATCH do teclado em HIGH direto no registrador PORTD
}

void PulsaClockTeclado(){
      PORTD |= (B00000001 << CLOCK_TECLADO); // colocando o CLOCK do teclado em HIGH direto no registrador PORTD
      asm("nop \n"); // nop (ciclo sem operação) com inline assembly 
      PORTD &= ~(B00000001 << CLOCK_TECLADO); // colocando o CLOCK do teclado em LOW direto no registrador PORTD
}

void LatchMonitorLow(){
   PORTB &= ~(B00000001 << LATCH_MONITOR); // colocando o LATCH do monitor em LOW direto no registrador PORTB 
}
void LatchMonitorHigh(){
   PORTB |= (B00000001 << LATCH_MONITOR); // colocando o LATCH do monitor em HIGH direto no registrador PORTB
}

void ClockMonitorLow(){
   PORTB &= ~(B00000001 << CLOCK_MONITOR); // colocando o CLOCK do monitor em LOW direto no registrador PORTB
}
void PulsaClockMonitor(){
      PORTB |= (B00000001 << CLOCK_MONITOR); // colocando o CLOCK do monitor em HIGH direto no registrador PORTB
      asm("nop \n"); // nop (ciclo sem operação) com inline assembly 
      PORTB &= ~(B00000001 << CLOCK_MONITOR); // colocando o CLOCK do monitor em LOW direto no registrador PORTB
}

void DadosMonitorLow(){
   PORTB &= ~(B00000001 << DADOS_MONITOR); // colocando linha de dados do monitor em LOW direto no registrador PORTB 
}
void DadosMonitorHigh(){
   PORTB |= (B00000001 << DADOS_MONITOR); // colocando linha de dados do monitor em HIGH direto no registrador PORTB
}

// função main
int main(){
   asm( "cli \n"); // desabilita interrupts com inline assembly  

    // configurando o timer
     TCCR1A = 0;  // limpando registrador TCCR1A
     // colocando o timer no modo CTC (Clear Timer on Compare-match)
     TCCR1B &= ~(B00000001 << WGM13);
     TCCR1B |= (B00000001 << WGM12);
     // setando prescaler do timer para 64 (16 mHz / 64 = 250 kHz)
     TCCR1B &= ~(B00000001 << CS12);
     TCCR1B |= (B00000001 << CS11);
     TCCR1B |= (B00000001 << CS10);
     TCNT1 = 0;  // carregando contador do timer com 0   
     OCR1A = 2500; // um centésimo de 250 mil para o Compare-match
     TIMSK1 = (B00000001 << OCIE1A);

   // configurando pinos
    DDRD |= (B00000001 << PORTD2); //  pino 2 em OUTPUT
    DDRD |= (B00000001 << PORTD3); //  pino 3 em OUTPUT
    DDRD &= ~(B00000001 << PORTD4); //  pino 4 em INPUT

    DDRB |= (B00000001 << PORTB0); //  pino 8 em OUTPUT
    DDRB |= (B00000001 << PORTB1); //  pino 9 em OUTPUT
    DDRB |= (B00000001 << PORTB2); //  pino 10 em OUTPUT

    asm( "sei \n"); // habilita interrupts com inline assembly  

    LatchTecladoHigh(); // Linha latch do teclado fica HIGH enquanto não estiver fazendo o sample

    //inicializando o array de estados das teclas com zeros
      for(int i=0; i < QUANT_TECLAS+1; i++){
         estadoteclas[i] = 0;
      }     
     
   //define o primeiro programa a ser executado na inicialização
    ProgramaAtivo = INTRO;

    // loop infinito
    while(true) {
            // checa o teclado a cada centésimo de segundo
            if( (centesimos - teclSampleCont) > 1 ){          
                  teclSampleCont = centesimos; 
                  ChecaTeclado();
            }

         ExecutaPrograma(ProgramaAtivo); // executa o programa ativo

          // rasterização a cada 4 centésimos (25 fps)
          if( (centesimos - RasterCont) > 4 ){
                 RasterCont =  centesimos; 
                 Rasterizar();  
          }
    }   
} // fim da função main


// Rotina de Serviço de Interrupção (ISR) do Timer
ISR(TIMER1_COMPA_vect){ 
    centesimos++; // incrementa o contador de centésimos de segundo
}


int LerPinoDadosTeclado(){
     // função que lê o pino de dados do teclado e retorna um inteiro
      if(PIND & (B00000001 << DADOS_TECLADO)){ // lendo o estado do pino
        return 1; // pino de dados está HIGH
      }else{
        return 0; // pino de dados está LOW
      }
}


void ChecaTeclado(){    
     // função que verifica o estado das teclas do teclado

       int estado =  0; // variável local para armazenar o estado do pino de dados

       //fazendo o sample em todos os registradores de deslocamento PISO
       LatchTecladoLow();
       asm("nop \n"); // nop (ciclo sem operação) com inline assembly 
       LatchTecladoHigh();

      // verifica cada tecla individualmente (começando de 1 e não de 0)
      for(int i=1; i < QUANT_TECLAS+1; i++){
               estado = LerPinoDadosTeclado(); // lendo estado da tecla 
              //debounce da tecla
              if (estado != estadoteclas[i]){ // verifica se mudou o estado desta tecla
                  ultimaVezQueMudou = centesimos; 
                }
                // só faz algo se já estiver sem mudar de estado por mais tempo do que o delay de debounce
                if( (centesimos - ultimaVezQueMudou) > delayDebounce ){ 
                        if(estado == 1){ // se a tecla estiver HIGH
                            keybuffer = i; // número sequencial da tecla vai para o keybuffer                              
                            return; // sai da função ChecaTeclado()   
                            }
                }
                estadoteclas[i] = estado;    
            
              PulsaClockTeclado(); // próxima tecla  
      }
}


void Rasterizar(){
    LatchMonitorLow();
    ClockMonitorLow();

    for(int i=QUANT_LEDS-1; i > -1; i--){
        if(framebuffer[i]){ // se true (aceso)
            DadosMonitorHigh();
            PulsaClockMonitor();
        }else{ // se false (apagado)
            DadosMonitorLow();
            PulsaClockMonitor();       
        }
    }

   //pulsa o LATCH do monitor
   LatchMonitorHigh();
   asm("nop \n"); // nop (ciclo sem operação) com inline assembly 
   LatchMonitorLow();  
}


#define ACESO true
#define APAGADO false


// função para definir estado do pixel (aceso ou apagado)
void DefinePixel(int pixel, boolean estado){
    framebuffer[pixel] = estado;
}


// função para limpar a tela toda
void LimpaTela(){
    for(int i=0; i < QUANT_LEDS; i++){
            DefinePixel(i, APAGADO);
        }
}

 //função principal, que executa o programa especificado pela variável global ProgramaAtivo
void ExecutaPrograma(int codprog){
    switch(codprog){
         case 200:
            Intro();
         break;
         case 201:
            programaEditorDeTexto();
         break;         
    }
}

unsigned long inicioIntro = 0; // variável de tempo para programa Intro
//programa de Introdução
void Intro(){
   if(centesimos - inicioIntro > 5){
       EscreveCaractere('C', QUANT_COLUNAS+1); 
       EscreveCaractere('R', QUANT_COLUNAS+9);    
       EscreveCaractere('I', QUANT_COLUNAS+14); 
       EscreveCaractere('A', QUANT_COLUNAS+20); 
       EscreveCaractere('D', QUANT_COLUNAS+27); 
       EscreveCaractere('O', QUANT_COLUNAS+34);                         
   }
   if(centesimos - inicioIntro > 150){
       LimpaTela();
   } 
   if(centesimos - inicioIntro > 190){
       EscreveCaractere('P', QUANT_COLUNAS+10); 
       EscreveCaractere('O', QUANT_COLUNAS+18);    
       EscreveCaractere('R', QUANT_COLUNAS+26); 
   }
   if(centesimos - inicioIntro > 300){
       LimpaTela();
   } 
   if(centesimos - inicioIntro > 340){
       EscreveCaractere('D', QUANT_COLUNAS+1); 
       EscreveCaractere('A', QUANT_COLUNAS+9);    
       EscreveCaractere('N', QUANT_COLUNAS+17); 
       EscreveCaractere('T', QUANT_COLUNAS+25); 
       EscreveCaractere('E', QUANT_COLUNAS+33);                          
   } 
   if(centesimos - inicioIntro > 500){
       LimpaTela();
   } 
   if(centesimos - inicioIntro > 540){
       EscreveCaractere('M', QUANT_COLUNAS+1); 
       EscreveCaractere('E', QUANT_COLUNAS+9);    
       EscreveCaractere('I', QUANT_COLUNAS+17); 
       EscreveCaractere('R', QUANT_COLUNAS+25); 
       EscreveCaractere('A', QUANT_COLUNAS+33);                          
   }
   if(centesimos - inicioIntro > 750){
      LimpaTela();
   }  
   if(centesimos - inicioIntro > 760){
      ProgramaAtivo = TXT;
   }                  
}

#define  TECLA_ZERO 10
#define  TECLA_BACK 11
#define  TECLA_MAIS 12
#define  TECLA_MENOS 13
#define  TECLA_Q 14
#define  TECLA_W 15
#define  TECLA_E 16
#define  TECLA_R 17
#define  TECLA_T 18
#define  TECLA_Y 19
#define  TECLA_U 20
#define  TECLA_I 21
#define  TECLA_O 22
#define  TECLA_P 23
#define  TECLA_VEZES 24
#define  TECLA_DIV 25
#define  TECLA_A 26
#define  TECLA_S 27
#define  TECLA_D 28
#define  TECLA_F 29
#define  TECLA_G 30
#define  TECLA_H 31
#define  TECLA_J 32
#define  TECLA_K 33
#define  TECLA_L 34
#define  TECLA_CEDILHA 35
#define  TECLA_ENTER 36
#define  TECLA_Z 37
#define  TECLA_X 38
#define  TECLA_C 39
#define  TECLA_V 40
#define  TECLA_B 41
#define  TECLA_N 42
#define  TECLA_M 43
#define  TECLA_PONTO 44
#define  TECLA_AGUDO 45
#define  TECLA_CIRCUNFLEXO 46
#define  TECLA_TIL 47
#define  TECLA_ESPACO 48
#define  TECLA_CIMA 49
#define  TECLA_BAIXO 50
#define  TECLA_ESQUERDA 51
#define  TECLA_DIREITA 52


int poscursor = 1; // posição do cursor (editor de texto)
#define MAX_CURSOR 5 //valor válido máximo de posição do cursor
unsigned long TempoRepetTecla = 0; // variável de tempo para controlar a repetição de tecla
int delayRepetTecla = 25; // intervalo em centésimos de segundo para delay de repetição de tecla
byte teclaanterior = 127; // variável para controle de repetição de tecla
unsigned long TempoCursorInterm = 0; // variável de tempo para indicador de cursor intermitente
boolean cursorBool = false; // variável booleana para fazer indicador de cursor piscar


void programaEditorDeTexto(){
   // inteiro para armazenar pixel do canto superior esquerdo, de acordo com posição do cursor
    int canto_sup_esquerdo;

      if(keybuffer == teclaanterior){ // esta condição só é atendida quando ChecaTeclado() tira keybuffer de zero (no máximo uma vez a cada centésimo de segundo)
            if( (centesimos - TempoRepetTecla) < delayRepetTecla){
              keybuffer = 0;
              return;
            }
      }

   if(keybuffer != 0){ // na grande maioria das vezes em que a função chega até aqui keybuffer será zero
          teclaanterior = keybuffer;   
          TempoRepetTecla = centesimos;      
      } // atualiza as variáveis se keybuffer não for zero


   if(keybuffer == TECLA_BACK){
             if(poscursor > 1){
                     poscursor-- ;  // volta o cursor
                     canto_sup_esquerdo =  ( (poscursor-1)*8 ) + 1 + QUANT_COLUNAS;
                     for(int linha = 0; linha < 5; linha++){
                           for(int i = canto_sup_esquerdo + (linha*QUANT_COLUNAS); i < (canto_sup_esquerdo + (linha*QUANT_COLUNAS))+5 ; i++){
                              DefinePixel(i, APAGADO); //apaga último caractere
                           } 
                        }    
                     }
             keybuffer = 0;
             return;
    }  


   if(keybuffer == TECLA_ESQUERDA){
               if(poscursor > 1){
                        poscursor-- ;  // volta o cursor sem apagar nada
                        }       
                  keybuffer = 0;
                return;
    } 

   if(keybuffer == TECLA_DIREITA){
               if(poscursor <= MAX_CURSOR){
                        poscursor++ ;  //incrementa posição do cursor         
                        }       
                  keybuffer = 0;
                return;
    }     

   canto_sup_esquerdo =  ( (poscursor-1)*8 ) + 1 + QUANT_COLUNAS;

   //indicador intermitente do cursor
   if( (centesimos - TempoCursorInterm) > 25){ // intervalo de 25 centésimos
            TempoCursorInterm = centesimos;
            if(cursorBool){  cursorBool = false;  }else{  cursorBool = true; }
   }

   if(cursorBool){
                  for(int i = 6*QUANT_COLUNAS; i < 7*QUANT_COLUNAS; i++){
                                    DefinePixel(i, APAGADO);
                  }  
                  for(int i = canto_sup_esquerdo+(5*QUANT_COLUNAS)-1; i < (canto_sup_esquerdo+(5*QUANT_COLUNAS))+6; i++){
                                    DefinePixel(i, ACESO);
                  }  
   }else{
                  for(int i = canto_sup_esquerdo+(5*QUANT_COLUNAS)-1; i < (canto_sup_esquerdo+(5*QUANT_COLUNAS))+6; i++){
                                    DefinePixel(i, APAGADO);
                  }  
   }
   

   if(poscursor <= MAX_CURSOR){ //apenas se a posição do cursor já não ultrapassou o máximo
      switch(keybuffer){ 
         case 0:   
                asm("nop \n"); // nop (ciclo sem operação) com inline assembly 
         break;
         case 1:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('1', canto_sup_esquerdo);
                  poscursor++ ; //incrementa posição do cursor                  
                  keybuffer = 0;
         break;
         case 2:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('2', canto_sup_esquerdo); 
                  poscursor++ ; //incrementa posição do cursor                  
                  keybuffer = 0;
         break;   
         case 3:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('3', canto_sup_esquerdo); 
                  poscursor++ ; //incrementa posição do cursor                  
                  keybuffer = 0;
         break;  
         case 4:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('4', canto_sup_esquerdo); 
                  poscursor++ ; //incrementa posição do cursor                   
                  keybuffer = 0;
         break;   
         case 5:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('5', canto_sup_esquerdo);    
                  poscursor++ ; //incrementa posição do cursor                  
                  keybuffer = 0;
         break;   
         case 6:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('6', canto_sup_esquerdo);        
                  poscursor++ ; //incrementa posição do cursor  
                  keybuffer = 0;
         break;   
         case 7:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('7', canto_sup_esquerdo);                              
                  poscursor++ ; //incrementa posição do cursor         
                  keybuffer = 0;
         break;  
         case 8:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('8', canto_sup_esquerdo);
                  poscursor++ ; //incrementa posição do cursor  
                  keybuffer = 0;
         break;
         case 9:
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('9', canto_sup_esquerdo);
                 poscursor++ ; //incrementa posição do cursor  
                 keybuffer = 0;
         break;                                                         
         case TECLA_ZERO:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('0', canto_sup_esquerdo);
                  poscursor++ ; //incrementa posição do cursor     
                  keybuffer = 0;                
         break; 
         case TECLA_MAIS:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('+', canto_sup_esquerdo);
                  poscursor++ ; //incrementa posição do cursor          
                  keybuffer = 0;
         break; 
         case TECLA_MENOS:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('-', canto_sup_esquerdo);
                  poscursor++ ; //incrementa posição do cursor    
                  keybuffer = 0;
         break; 
         case TECLA_Q:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('Q', canto_sup_esquerdo);      
                  poscursor++ ; //incrementa posição do cursor    
                  keybuffer = 0;
         break; 
         case TECLA_W:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('W', canto_sup_esquerdo);   
                  poscursor++ ; //incrementa posição do cursor    
                  keybuffer = 0;
         break; 
         case TECLA_E:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('E', canto_sup_esquerdo);       
                  poscursor++ ; //incrementa posição do cursor    
                  keybuffer = 0;
         break; 
         case TECLA_R:
                  EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                  EscreveCaractere('R', canto_sup_esquerdo);                                
                  poscursor++ ; //incrementa posição do cursor    
                  keybuffer = 0;
         break;   
         case TECLA_T:
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área   
                 EscreveCaractere('T', canto_sup_esquerdo);            
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;     
         case TECLA_Y: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('Y', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;   
         case TECLA_U: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('U', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;       
         case TECLA_I: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('I', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;    
         case TECLA_O: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('O', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;    
         case TECLA_P: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('P', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;    
         case TECLA_VEZES: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('*', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;
         case TECLA_DIV: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('/', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break; 
         case TECLA_A: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('A', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;   
         case TECLA_S: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('S', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;     
         case TECLA_D: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('D', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;    
         case TECLA_F: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('F', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;       
         case TECLA_G: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('G', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;                                                                                                                                                                  
         case TECLA_H: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('H', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;      
         case TECLA_J: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('J', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;
         case TECLA_K: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('K', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;        
         case TECLA_L: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('L', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;    
         case TECLA_CEDILHA: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('#', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;       
         case TECLA_Z: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('Z', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;    
         case TECLA_X: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('X', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;                                       
         case TECLA_C: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('C', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;
         case TECLA_V: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('V', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;
         case TECLA_B: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('B', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;
         case TECLA_N: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('N', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;   
         case TECLA_M: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('M', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;    
         case TECLA_PONTO: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('.', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;  
         case TECLA_AGUDO: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('@', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break; 
         case TECLA_CIRCUNFLEXO: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('%', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;       
         case TECLA_TIL: 
                 EscreveCaractere(' ', canto_sup_esquerdo); //primeiro limpa a área
                 EscreveCaractere('&', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;                        
         case TECLA_ESPACO: 
                 EscreveCaractere(' ', canto_sup_esquerdo);   
                 poscursor++ ; //incrementa posição do cursor          
                 keybuffer = 0;
         break;                                                                                                                                                                      
      }      
      
   }

}



// função de desenho de caracteres, relativamente ao canto superior esquerdo informado
void EscreveCaractere(char caractere, uint8_t canto_sup_esquerdo){
   switch(caractere){
         case '1': 
                for(int i = canto_sup_esquerdo + 3; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+4; i = i+QUANT_COLUNAS){
                           DefinePixel(i, ACESO);
                        }  
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 2, ACESO); 
                  DefinePixel(canto_sup_esquerdo + (2*QUANT_COLUNAS) + 1, ACESO);           
         break;        
         case '2': 
                for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+4; i++){
                           DefinePixel(i, ACESO);
                        }  
               for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+4; i++){
                           DefinePixel(i, ACESO);
                        }  
               for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS); i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+4; i++){
                           DefinePixel(i, ACESO);
                        }    
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 3, ACESO);         
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);              
         break;         
         case '3': 
               for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+4; i++){
                           DefinePixel(i, ACESO);
                        }  
               for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+4; i++){
                           DefinePixel(i, ACESO);
                        }  
               for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS); i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+4; i++){
                           DefinePixel(i, ACESO);
                        }    
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 3, ACESO);         
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS) + 3, ACESO);                
         break;       
         case '4': 
                for(int i = canto_sup_esquerdo + 3; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+4; i = i+QUANT_COLUNAS){
                           DefinePixel(i, ACESO);
                        } 
                  DefinePixel(canto_sup_esquerdo, ACESO);       
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);  
               for(int i = canto_sup_esquerdo + (2*QUANT_COLUNAS); i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+4; i++){
                           DefinePixel(i, ACESO);
                        }              
         break;         
         case '5': 
                for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+4; i++){
                        DefinePixel(i, ACESO);
                        }  
               for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+4; i++){
                           DefinePixel(i, ACESO);
                        }  
               for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS); i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+4; i++){
                           DefinePixel(i, ACESO);
                        }    
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);         
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS) + 3, ACESO);                 
         break;       
         case '6': 
                  for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }   
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);        
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);  
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+4, ACESO);            
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < (canto_sup_esquerdo+(2*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                                    
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                   
         break;       
         case '7': 
                for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+5; i++){
                           DefinePixel(i, ACESO);
                        }         
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 4, ACESO);   
                  DefinePixel(canto_sup_esquerdo + (2*QUANT_COLUNAS) + 3, ACESO);       
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS) + 2, ACESO);    
                  DefinePixel(canto_sup_esquerdo + (4*QUANT_COLUNAS) + 1, ACESO);                      
         break;       
         case '8': 
                  for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }   
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);        
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);  
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS+4, ACESO);
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+4, ACESO);            
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(2*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                                    
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                      
         break;       
         case '9': 
                  for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }   
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);                      
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS+4; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }     
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(2*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                                    
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                    
         break;        
         case '0': 
                   for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }    
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }         
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS+4; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }                         
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                  
         break;         
         case '+': 
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+5; i++){
                     DefinePixel(i, ACESO);
                  }    
                  for(int i = canto_sup_esquerdo+2; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+3; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }                      
         break;          
         case '-': 
                   for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+5; i++){
                     DefinePixel(i, ACESO);
                  }                     
         break;      
         case 'Q': 
                  for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }    
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }         
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS+4; i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }    
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS)+2,ACESO);  
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+3, ACESO);                                                        
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS)+1, ACESO);
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS)+2, ACESO);                  
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS)+4, ACESO);                       
         break;          
         case 'W': 
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }           
                  for(int i = canto_sup_esquerdo+4; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }  
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS)+2, ACESO);      
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+1, ACESO); 
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+3, ACESO);       
         break;        
         case 'E': 
                   for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+5; i++){
                     DefinePixel(i, ACESO);
                  }    
                  DefinePixel(canto_sup_esquerdo+QUANT_COLUNAS, ACESO);       
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+4; i++){
                     DefinePixel(i, ACESO);
                  }
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS), ACESO);
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS); i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+5; i++){
                     DefinePixel(i, ACESO);
                  }         
         break;        
         case 'R': 
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  } 
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS)+1; i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+4; i++){
                     DefinePixel(i, ACESO);
                  }                      
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }       
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+4, ACESO);                        
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+2, ACESO);
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS)+3, ACESO);                    
         break;       
         case 'T': 
                   for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+5; i++){
                     DefinePixel(i, ACESO);
                  }    
                  for(int i = canto_sup_esquerdo+2; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+3; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }       
         break;      
         case 'Y': 
                  DefinePixel(canto_sup_esquerdo, ACESO);
                  DefinePixel(canto_sup_esquerdo+4, ACESO);
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+1, ACESO);
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+3, ACESO);
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS)+2; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+3; i = i+QUANT_COLUNAS){
                      DefinePixel(i, ACESO);
                  }     
         break;        
         case 'U':   
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }         
                  for(int i = canto_sup_esquerdo + 4; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }                         
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                  
         break;  
         case 'I': 
                  for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }    
                  for(int i = canto_sup_esquerdo+2; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+3; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }  
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+4; i++){
                     DefinePixel(i, ACESO);
                  }                                     
         break;    
         case 'O': 
                   for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }    
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }         
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS+4; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }                         
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                  
         break; 
         case 'P': 
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  } 
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS)+1; i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+4; i++){
                     DefinePixel(i, ACESO);
                  }                      
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }       
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+4, ACESO);                                          
         break; 
         case '*':    
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+1, ACESO);  
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+3, ACESO);    
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS)+2, ACESO); 
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+1, ACESO);
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+3, ACESO);                                         
         break;   
         case '/':    
                  DefinePixel(canto_sup_esquerdo+4, ACESO);  
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+3, ACESO);    
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS)+2, ACESO); 
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+1, ACESO);
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS), ACESO);                                         
         break;        
         case 'A':    
                  for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }   
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);    
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 4, ACESO);                            
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);  
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+4, ACESO);   
                  DefinePixel(canto_sup_esquerdo + (4*QUANT_COLUNAS), ACESO);  
                  DefinePixel(canto_sup_esquerdo + (4*QUANT_COLUNAS)+4, ACESO);                            
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < (canto_sup_esquerdo+(2*QUANT_COLUNAS))+5; i++){
                     DefinePixel(i, ACESO);
                  }                                                                          
         break;      
         case 'S':    
                  for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+5; i++){
                     DefinePixel(i, ACESO);
                  }   
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);                              
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+4, ACESO);                  
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(2*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }   
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS); i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                                                                                           
         break;  
         case 'D':    
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }   
                   for(int i = canto_sup_esquerdo+QUANT_COLUNAS+4; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }  
                   for(int i = canto_sup_esquerdo+QUANT_COLUNAS+1; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+2; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }                                                 
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+4, ACESO);                  
  
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS); i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                                                                                           
         break;     
         case 'F':    
                   for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+5; i++){
                     DefinePixel(i, ACESO);
                  }    
                  DefinePixel(canto_sup_esquerdo+QUANT_COLUNAS, ACESO);       
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+4; i++){
                     DefinePixel(i, ACESO);
                  }
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS), ACESO);
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS), ACESO);                                                                                           
         break;            
         case 'G': 
                  for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+5; i++){
                     DefinePixel(i, ACESO);
                  }   
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO); 
                  DefinePixel(canto_sup_esquerdo + (2*QUANT_COLUNAS), ACESO);       
                  DefinePixel(canto_sup_esquerdo + (2*QUANT_COLUNAS)+3, ACESO);      
                  DefinePixel(canto_sup_esquerdo + (2*QUANT_COLUNAS)+4, ACESO);                                                      
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);  
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+4, ACESO);                                  
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+5; i++){
                     DefinePixel(i, ACESO);
                  }                   
         break; 
         case 'H':    
                  DefinePixel(canto_sup_esquerdo, ACESO);    
                  DefinePixel(canto_sup_esquerdo + 4, ACESO);                    
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);    
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 4, ACESO);                            
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);  
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+4, ACESO);   
                  DefinePixel(canto_sup_esquerdo + (4*QUANT_COLUNAS), ACESO);  
                  DefinePixel(canto_sup_esquerdo + (4*QUANT_COLUNAS)+4, ACESO);                            
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < (canto_sup_esquerdo+(2*QUANT_COLUNAS))+5; i++){
                     DefinePixel(i, ACESO);
                  }                                                                          
         break; 
         case 'J': 
                  DefinePixel(canto_sup_esquerdo + 4, ACESO);    
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);         
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS+4; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }                         
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                  
         break;   
         case 'K':    
                  DefinePixel(canto_sup_esquerdo, ACESO);   
                  DefinePixel(canto_sup_esquerdo+3, ACESO);                                                      
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO); 
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS+2, ACESO);         
                  DefinePixel(canto_sup_esquerdo + (2*QUANT_COLUNAS), ACESO);      
                  DefinePixel(canto_sup_esquerdo + (2*QUANT_COLUNAS)+1, ACESO);                                                      
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);   
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+2, ACESO);                    
                  DefinePixel(canto_sup_esquerdo + (4*QUANT_COLUNAS), ACESO);      
                  DefinePixel(canto_sup_esquerdo + (4*QUANT_COLUNAS) + 3, ACESO);                                                                                                               
         break; 
         case 'L':    
                  DefinePixel(canto_sup_esquerdo, ACESO);     
                  DefinePixel(canto_sup_esquerdo+QUANT_COLUNAS, ACESO);       
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS), ACESO);
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS), ACESO);
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS); i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+5; i++){
                     DefinePixel(i, ACESO);
                  }                                                                                                             
         break; 
         case '#': 
                   for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+5; i++){
                     DefinePixel(i, ACESO);
                  }    
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS; i < canto_sup_esquerdo+(2*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }                               
                  for(int i = canto_sup_esquerdo+(3*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(3*QUANT_COLUNAS))+5; i++){
                     DefinePixel(i, ACESO);
                  } 
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS)+3, ACESO);        
         break;
         case 'Z': 
                for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+5; i++){
                           DefinePixel(i, ACESO);
                        }         
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 3, ACESO);   
                  DefinePixel(canto_sup_esquerdo + (2*QUANT_COLUNAS) + 2, ACESO);       
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS) + 1, ACESO);    
                for(int i = canto_sup_esquerdo + (4*QUANT_COLUNAS); i < canto_sup_esquerdo + (4*QUANT_COLUNAS) + 5; i++){
                           DefinePixel(i, ACESO);
                        }                     
         break;   
         case 'X':  
                  DefinePixel(canto_sup_esquerdo, ACESO);  
                  DefinePixel(canto_sup_esquerdo+4, ACESO);             
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+1, ACESO);  
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+3, ACESO);    
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS)+2, ACESO); 
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+1, ACESO);
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+3, ACESO);    
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS), ACESO);
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS)+4, ACESO);                                                         
         break;   
         case 'C': 
                   for(int i = canto_sup_esquerdo+1; i < canto_sup_esquerdo+5; i++){
                     DefinePixel(i, ACESO);
                  }    
                  for(int i = canto_sup_esquerdo + QUANT_COLUNAS; i < canto_sup_esquerdo+(3*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }                               
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+5; i++){
                     DefinePixel(i, ACESO);
                  }     
         break;
         case 'V': 
                  DefinePixel(canto_sup_esquerdo, ACESO);
                  DefinePixel(canto_sup_esquerdo+4, ACESO);
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS), ACESO);
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+4, ACESO);
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS), ACESO);
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS)+4, ACESO);   
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+1, ACESO);
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+3, ACESO);        
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS)+2, ACESO);                                 
         break; 
         case 'B': 
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+4; i++){
                     DefinePixel(i, ACESO);
                  }   
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS, ACESO);        
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS), ACESO);  
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS+4, ACESO);
                  DefinePixel(canto_sup_esquerdo + (3*QUANT_COLUNAS)+4, ACESO);            
                  for(int i = canto_sup_esquerdo+(2*QUANT_COLUNAS); i < (canto_sup_esquerdo+(2*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                                    
                  for(int i = canto_sup_esquerdo+(4*QUANT_COLUNAS); i < (canto_sup_esquerdo+(4*QUANT_COLUNAS))+4; i++){
                     DefinePixel(i, ACESO);
                  }                      
         break;  
         case 'N': 
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }           
                  for(int i = canto_sup_esquerdo+4; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }  
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS)+2, ACESO);      
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 1, ACESO); 
                  DefinePixel(canto_sup_esquerdo+(3*QUANT_COLUNAS)+3, ACESO);       
         break;   
         case 'M': 
                  for(int i = canto_sup_esquerdo; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+1; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }           
                  for(int i = canto_sup_esquerdo+4; i < canto_sup_esquerdo+(4*QUANT_COLUNAS)+5; i = i+QUANT_COLUNAS){
                     DefinePixel(i, ACESO);
                  }  
                  DefinePixel(canto_sup_esquerdo+(2*QUANT_COLUNAS)+2, ACESO);      
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 1, ACESO); 
                  DefinePixel(canto_sup_esquerdo + QUANT_COLUNAS + 3, ACESO);       
         break; 
         case '.': 
                  DefinePixel(canto_sup_esquerdo+(4*QUANT_COLUNAS), ACESO);          
         break; 
         case '@': 
                  DefinePixel(canto_sup_esquerdo+3, ACESO);             
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+2, ACESO);        
         break;       
         case '%': 
                  DefinePixel(canto_sup_esquerdo+2, ACESO);             
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+1, ACESO);     
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+3, ACESO);     
         break;       
         case '&': 
                  DefinePixel(canto_sup_esquerdo+2, ACESO);         
                  DefinePixel(canto_sup_esquerdo+4, ACESO);       
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+1, ACESO);     
                  DefinePixel(canto_sup_esquerdo+(QUANT_COLUNAS)+3, ACESO);     
         break;                 
         case ' ': 
                     for(int linha = 0; linha < 5; linha++){
                           for(int i = canto_sup_esquerdo + (linha*QUANT_COLUNAS); i < (canto_sup_esquerdo + (linha*QUANT_COLUNAS))+5 ; i++){
                              DefinePixel(i, APAGADO); //todos os LEDs da área de caractere apagados
                           } 
                        }                       
         break;                                                                                 
   }
}
74HC165
74HC165
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC165
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC165
74HC165
74HC165
74HC165