Adaptador PPI-MEGA8 |
char Keymap[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
ISR (PCINT1_vect, ISR_NAKED) {
asm volatile ( // 7 até aqui
"in __tmp_reg__,__SREG__ \n\t" // 1 Salva registrador de Status
"ldi r26,lo8(Keymap) \n\t" // 1 Ponteiro X = endereço de Keymap
"ldi r27,hi8(Keymap)\n\t" // 1
"in r19,%0 \n\t" // 1 Amostra bits da porta C da PPI (PC0..PC3)
"andi r19,0x0f \n\t" // 1 limpa bits 4..7
"add r26,r19 \n\t" // 1 soma com ponteiro
"ld r19,X \n\t" // 1 lê coluna correspondente do mapa de teclas
"out %1,r19 \n\t" // 1 escreve na porta B da PPI
// até aqui 15 instruções
"out __SREG__,__tmp_reg__ \n\t" // restaura registrador de Status
"reti \n\t"
:: "I" (_SFR_IO_ADDR(PINC)), "I" (_SFR_IO_ADDR(PORTB)) );
}
Porém algumas considerações permitem reduzir este tempo em alguns ciclos:
Já que apenas os primeiros 4 pinos da Porta C estão conectados, podemos deixar os pinos restantes como saídas e escrever o valor ZERO nos bits PORTC.5 e PORTC.6. Desta maneira, ao se ler o estado da porta C os bits 4 a 8 serão sempre zero, o que significa que podemos economizar um ciclo da instrução andi r19,0x0f
Como o início da RAM dos ATMega88 é em 0x100, podemos declarar a variável Keymap antes de qualquer outra e assim economizamos as instruções ldi r26,lo8(Keymap) e add r26,r19 . Em vez disso, bastar ler a porta C diretamente em r26.
Se reservarmos o registro r27 para ser usado como uma variável, o compilador não deve usar esse registro e assim podemos economizar mais outra instrução: ldi r27,hi8(Keymap) (fazendo é claro a inicialização de r27 em outro trecho de código).
Assim a contagem de ciclos fica igual a 15-1-1-1-1 =11 ciclos.
A 8MHz ou seja, com clock interno isso consome 1,375us
A 16Mhz que é o clock padrão do Arduino são 687,5ns
A 20MHz velocidade máxima oficial são 550ns
A 27MHz em overclock são 407ns
Uma última otimização é colocar o código diretamente no vetor de interrupção e assim economizar mais 3 ciclos.
Assim a contagem de ciclos fica igual a 11-3 =8 ciclos!!
Em termos de tempo isso significa
A 8MHz ou seja, com clock interno isso consome 1,0 us
A 16Mhz que é o clock padrão do Arduino são 500ns
A 20MHz velocidade máxima oficial são 400ns
A 27MHz em overclock são apenas 296,3 ns
Se reservarmos o registro r27 para ser usado como uma variável, o compilador não deve usar esse registro e assim podemos economizar mais outra instrução: ldi r27,hi8(Keymap) (fazendo é claro a inicialização de r27 em outro trecho de código).
Assim a contagem de ciclos fica igual a 15-1-1-1-1 =11 ciclos.
A 8MHz ou seja, com clock interno isso consome 1,375us
A 16Mhz que é o clock padrão do Arduino são 687,5ns
A 20MHz velocidade máxima oficial são 550ns
A 27MHz em overclock são 407ns
Uma última otimização é colocar o código diretamente no vetor de interrupção e assim economizar mais 3 ciclos.
Assim a contagem de ciclos fica igual a 11-3 =8 ciclos!!
Em termos de tempo isso significa
A 8MHz ou seja, com clock interno isso consome 1,0 us
A 16Mhz que é o clock padrão do Arduino são 500ns
A 20MHz velocidade máxima oficial são 400ns
A 27MHz em overclock são apenas 296,3 ns
Nenhum comentário:
Postar um comentário