// Entrada e Saída (E/S) bidimensionais programadas no baixo nível
boolean aceso1 = false;
boolean aceso2 = false;
boolean aceso3 = false;
boolean aceso4 = false;
boolean aceso5 = false;
boolean aceso6 = false;
boolean aceso7 = false;
boolean aceso8 = false;
boolean aceso9 = false;
unsigned long ultimaVezQueMudouEsq = 0;
unsigned long ultimaVezQueMudouDir = 0;
unsigned long ultimaVezQueMudouCima = 0;
unsigned long ultimaVezQueMudouBaixo = 0;
unsigned long centesimos = 0; // centésimos de segundo desde que o sistema foi iniciado
int pos = 5; //posição do "cursor"
int main() {
asm("cli \n");
DDRD |= (B00000001 << DDD2); // pino 2 OUTPUT
DDRD |= (B00000001 << DDD3); // pino 3 OUTPUT
DDRD |= (B00000001 << DDD4); // pino 4 OUTPUT
DDRD |= (B00000001 << DDD5); // pino 5 OUTPUT
DDRD |= (B00000001 << DDD6); // pino 6 OUTPUT
DDRD |= (B00000001 << DDD7); // pino 7 OUTPUT
DDRB |= (B00000001 << DDB2); // pino 10 OUTPUT
DDRB |= (B00000001 << DDB3); // pino 11 OUTPUT
DDRB |= (B00000001 << DDB4); // pino 12 OUTPUT
DDRC &= ~(B00000001 << DDC0); // pino A0 input
PORTC |= (B00000001 << PORTC0); // pino A0 pullup
DDRC &= ~(B00000001 << DDC1); // pino A1 input
PORTC |= (B00000001 << PORTC1); // pino A0 pullup
DDRC &= ~(B00000001 << DDC2); // pino A2 input
PORTC |= (B00000001 << PORTC2); // pino A2 pullup
DDRC &= ~(B00000001 << DDC3); // pino A3 input
PORTC |= (B00000001 << PORTC3); // pino A3 pullup
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;
OCR1A = 2500; // um centésimo de 250 mil para o Compare-match
TIMSK1 = (1 << OCIE1A);
asm("sei \n");
while(true) {
// só se o pino A0 (pino 0 da porta C) estiver LOW
if(~(PINC) & (B00000001 << PC0)){
//debounce de 15 centésimos de segundo
if( (centesimos - ultimaVezQueMudouEsq) > 15 ){
ultimaVezQueMudouEsq = centesimos;
if( !((pos % 3)==1) ){ pos = pos-1; }
}
}
// só se o pino A1 (pino 1 da porta C) estiver LOW
if(~(PINC) & (B00000001 << PC1)){
//debounce de 15 centésimos de segundo
if( (centesimos - ultimaVezQueMudouDir) > 15 ){
ultimaVezQueMudouDir = centesimos;
if( !((pos % 3)==0) ){ pos = pos+1; }
}
}
// só se o pino A2 (pino 2 da porta C) estiver LOW
if(~(PINC) & (B00000001 << PC2)){
//debounce de 15 centésimos de segundo
if( (centesimos - ultimaVezQueMudouCima) > 15 ){
ultimaVezQueMudouCima = centesimos;
if(pos > 3){ pos = pos-3; }
}
}
// só se o pino A3 (pino 3 da porta C) estiver LOW
if(~(PINC) & (B00000001 << PC3)){
//debounce de 15 centésimos de segundo
if( (centesimos - ultimaVezQueMudouBaixo) > 15 ){
ultimaVezQueMudouBaixo = centesimos;
if(pos < 7){ pos = pos+3; }
}
}
switch(pos){
case 1:
aceso1 = true;
aceso2 = false;
aceso4 = false;
break;
case 2:
aceso1 = false;
aceso2 = true;
aceso3 = false;
aceso5 = false;
break;
case 3:
aceso2 = false;
aceso3 = true;
aceso6 = false;
break;
case 4:
aceso1 = false;
aceso4 = true;
aceso5 = false;
aceso7 = false;
break;
case 5:
aceso2 = false;
aceso4 = false;
aceso5 = true;
aceso6 = false;
aceso8 = false;
break;
case 6:
aceso3 = false;
aceso5 = false;
aceso6 = true;
aceso9 = false;
break;
case 7:
aceso4 = false;
aceso7 = true;
aceso8 = false;
break;
case 8:
aceso5 = false;
aceso7 = false;
aceso8 = true;
aceso9 = false;
break;
case 9:
aceso6 = false;
aceso8 = false;
aceso9 = true;
break;
}
if(aceso1){
PORTD |= (B00000001 << PORTD5); // coloca em HIGH
}else{
PORTD &= ~(B00000001 << PORTD5); // coloca em LOW
}
if(aceso2){
PORTD |= (B00000001 << PORTD2); // coloca em HIGH
}else{
PORTD &= ~(B00000001 << PORTD2); // coloca em LOW
}
if(aceso3){
PORTD |= (B00000001 << PORTD7); // coloca em HIGH
}else{
PORTD &= ~(B00000001 << PORTD7); // coloca em LOW
}
if(aceso4){
PORTB |= (B00000001 << PORTB4); // coloca em HIGH
}else{
PORTB &= ~(B00000001 << PORTB4); // coloca em LOW
}
if(aceso5){
PORTB |= (B00000001 << PORTB3); // coloca em HIGH
}else{
PORTB &= ~(B00000001 << PORTB3); // coloca em LOW
}
if(aceso6){
PORTB |= (B00000001 << PORTB2); // coloca em HIGH
}else{
PORTB &= ~(B00000001 << PORTB2); // coloca em LOW
}
if(aceso7){
PORTD |= (B00000001 << PORTD6); // coloca em HIGH
}else{
PORTD &= ~(B00000001 << PORTD6); // coloca em LOW
}
if(aceso8){
PORTD |= (B00000001 << PORTD4); // coloca em HIGH
}else{
PORTD &= ~(B00000001 << PORTD4); // coloca em LOW
}
if(aceso9){
PORTD |= (B00000001 << PORTD3); // coloca em HIGH
}else{
PORTD &= ~(B00000001 << PORTD3); // coloca em LOW
}
}
}
ISR(TIMER1_COMPA_vect){ // Rotina de Serviço de Interrupção (ISR) do Timer
centesimos++; // incrementa o contador de centésimos de segundo
}