/***********************************************
*
* @file main.c
* @author Eduardo Dueñas / Daniel Quadros
* @brief Exemplo tocar musicas usando buzzer
* @version 1.0
* @date 21/04/2021
*
* última modificação: 15/05/2021
*
**********************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16500000L
#define setBit(valor,bit) (valor |= (1<<bit))
#define clearBit(valor,bit) (valor &= ~(1<<bit))
#define toogleBit(valor,bit) (valor ^= (1<<bit))
#define testBit(valor,bit) (valor & (1<<bit))
#define NumNotas 32
#define CONT(freq) ((F_CPU*10L)/(256L*freq))
enum notas{Pausa,Do, DoS, Re, ReS, Mi, Fa, FaS, Sol, SolS, La, LaS, Si, DoM, DoSM, ReM};
long f[16] = { 255L, (long)CONT(5232L), (long)CONT(5543L), (long)CONT(5873L), (long)CONT(6222L), (long)CONT(6592L), (long)CONT(6984L),
(long)CONT(7400L), (long)CONT(7840L), (long)CONT(8306L), (long)CONT(8800L), (long)CONT(9323L), (long)CONT(9877L),
(long)CONT(10465L), (long)CONT(11087L), (long)CONT(11746L)};
//{0xFF,123, 116, 110, 104, 98, 92, 87, 82, 78, 73, 69, 65, 62, 58, 54}
//Lookup table com os valores de cada nota a ser colocado na flag do timer
char Partitura[NumNotas] = {Re,Mi,Mi,Re,Sol,FaS,FaS,FaS,Re,Mi,Mi,Re,La,Sol,Sol,Sol,Re,ReM,ReM,Si,Sol,FaS,FaS,Mi,
DoM,Si,Si,Sol,La,Sol,Sol,Sol}; //partitura da música
volatile char cont = 0; //local da partitura
volatile long aux = 0;
//tratamento de interrupção
ISR (TIM0_COMPB_vect){ //vetor de comparação B
if (aux<=0xff) { //se aux menor que 8bits
OCR0B=(TCNT0+aux)&(0xff); //mandar aux para o contador
aux=f[Partitura[cont]]; //reinicia o aux
toogleBit(PORTB,PB1); //inverter o buzzer
}
else{ //se não
OCR0B=TCNT0; //mandar o tempoatual para o contador, o mesmo que esperar um overflow
aux-=0xff; //subitrair 8bits do aux
}
}
//função main
int main(){
enum notas nota;
setBit(DDRB,PB1); //configura o PortB1 como saida, pino do buzzer
//configuração do timer
TCCR0A=0x00; //configura pino de compararação desconectado
TCCR0B=0x04; //configura o prescaler como 256
setBit(TIMSK,OCIE0B); //habilita a interrupção por comparação de COMPB
sei(); //habilita interrupções globais
aux=f[Partitura[cont]]; //inicia o contador de COMPB
if (aux<=0xff) {
OCR0B=(TCNT0+aux)&(0xff);
aux=f[Partitura[cont]];
toogleBit(PORTB,PB1);
}
else{
OCR0B=TCNT0;
aux-=0xff;
}
//loop infinito
for(;;){
long i;
for(i=0;i<1000000L;i++){
asm ("nop");
//long j;
//for(j=0;j<1;j++){asm ("nop");}
} //espera um tempo (altere o valor central para acelerar ou desacelerar a música)
cont++; //avança na partitura
if (cont >= NumNotas)cont=0; //toca de novo
}
}