⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demonstrator.c

📁 The collection of AVR source code in C.
💻 C
字号:
// Demonstrator.c Play it again Sam version

#include "PC_Comm.h"
#include "Messages.h"

#include "tunes.h"

void initializer()
{
	// Calibrate the oscillator:
    OSCCAL_calibration();   

	// Initialize the USART
	USARTinit();
	
	// Initialize timer0 to play a tune
	Timer0_Init();
	
	// initialize piezo-element
    sbi(DDRB, 5);               // set OC1A as output
    sbi(PORTB, 5);              // set OC1A high	
	
	// Display instructions on PC
	sendFString(TALKING_TO);
	sendFString(WHO_DEMO);
	sendFString(ENTER);
	sendFString(TEXT_FUR_ELISE);
	sendFString(ENTER);	
	sendFString(TEXT_TURKEY_MARCH);	
	sendFString(ENTER);	
	sendFString(TEXT_MINUET);	
	sendFString(ENTER);	
	sendFString(TEXT_AULD_LANG_SYNE);	
	sendFString(ENTER);	
	sendFString(TEXT_SIRENE1);	
	sendFString(ENTER);	
	sendFString(TEXT_SIRENE2);	
	sendFString(ENTER);	
	sendFString(TEXT_WHISTLE);	
	sendFString(ENTER);	
	sendFString(VOLUME_UP);	
	sendFString(THE_VOLUME);
	sendFString(ENTER);	
	sendFString(VOLUME_DOWN);	
	sendFString(THE_VOLUME);
	sendFString(ENTER);	
	sendFString(STOP);		


}

void parseInput(char s[])
{
	if( (s[0] <= '7') && ( s[0] >= '1') ) // 7 tunes
	{
		startTune(s[0]);
	}
	else
	{
		// parse first character	
		switch (s[0])
		{
			case '+':
				volumeUp();
				break;
			case '-':
				volumeDown();
				break;
			case 's':
				if( (s[1] == 't') && (s[2] == 'o') && (s[3] == 'p'))
				stopTune();
				break;				
			case 'd':
				if( (s[1] == 'e') && (s[2] == 'm') && (s[3] == 'o') && (s[4] == '?') )
				sendFString(TALKING_TO);
				sendFString(WHO_DEMO);
				break;
			default:
				sendFString(BAD_COMMAND1);
				sendChar(s[0]);
				sendFString(BAD_COMMAND2);

				break;
			
		}
	s[0] = '\0';
	}
}

void volumeUp()
{
    if(Volume >= 250)
        Volume = 250;
    else
        Volume += 50;
      
	OCRA1H = 0;	
    OCRA1L = Volume;

}
void volumeDown()
{
    if(Volume < 11)
        Volume = 6;
    else
        Volume -= 50;   
    
	OCRA1H = 0;
    OCRA1L = Volume;
}

void stopTune()
{
    cbi(TCCR1B, 0);    // stop Playing
    TCCR1A = 0;
    TCCR1B = 0;
    sbi(PORTB, 5);     // set OC1A high
}


void startTune(char tune)
{

	int song = atoi(&tune) - 1;
 
	stopTune();
	Tone = 0;
	Tempo = 0;
	Duration = 0;

	sendFString(TEXT_SONG_TBL[song]);     // Send the song title to the PC
	sendChar('\r');
            
	pSong=(int*)pgm_read_word(&Songs[song]); // looks too complicated..

	Sound_Init();
}


void Sound_Init(void)
{
    TCCR1A = (1<<COM1A1); 		// Set OC1A when upcounting, clear when downcounting
    TCCR1B = (1<<WGM13);       // Phase/Freq-correct PWM, top value = ICR1
    
    sbi(TCCR1B, CS10);         // start Timer1, prescaler(1)    
    
    OCRA1H = 0;					// Set a initial value in the OCR1A-register
    OCRA1L = Volume;			// This will adjust the volume on the buzzer, lower value => higher volume
}

void Play_Tune(void)
{
    int temp_hi;
    
    char loop;
    
    if(!Tone)
    {
        Duration = 0;   
		
		Tempo = (uint8_t)pgm_read_word(pSong + 0); 
		Tempo <<= 1; // compensate for using 2 MHz clock 
        Tone = 1;   //Start the song from the beginning
    }
    
    if(!Tempo)
    {
        if(Duration)        // Check if the length of the tone has "expired"
        {   
            Duration--;
        }
        else if(pgm_read_word(pSong + Tone))  // If not the end of the song
        {
            Duration = ( DURATION_SEED / pgm_read_word(pSong + Tone) );  // store the duration
			Duration <<= 1;// compensate for using 2 MHz clock
        
			Tone++;                     // point to the next tone in the Song-table        
                        
            if( (pgm_read_word(pSong + Tone) == p) | (pgm_read_word(pSong + Tone) == P) ) // if pause
                cbi(TCCR1B, CS10);             // stop Timer1, prescaler(1)    
            else 
                sbi(TCCR1B, CS10);             // start Timer1, prescaler(1)  
                
            cli(); 
            
			temp_hi = pgm_read_word(pSong + Tone);      // read out the PWM-value

            temp_hi >>= 7;// compensate for 2 MHz clock 8; // move integer 8 bits to the right
                
            TCNT1H = 0;                     // reset TCNT1H/L
            TCNT1L = 0;
            
            ICR1H = temp_hi;                // load ICR1H/L       
			ICR1L = pgm_read_word(pSong + Tone);
			ICR1L <<= 1; // compensate for using 2 MHz clock
            
            sei(); 
            
            Tone++;                     // point to the next tone in the Song-table
        }
        else    // the end of song
        {
            Tone++;         // point to the next tone in the Song-table        
            
			loop = (uint8_t)pgm_read_word(pSong + Tone); // get the byte that tells if the song should loop or not
            
            if( loop )  
            {
                Tone = 1;
            }
            else        // if not looping the song
            {
                Tone = 0;
                //gPlaying = FALSE;
                cbi(TCCR1B, 0);                     // stop Playing
                TCCR1A = 0;
                TCCR1B = 0;
                sbi(PORTB, 5);              // set OC1A high
            }
        }
        
		Tempo = (uint8_t)pgm_read_word(pSong + 0);
    }
    else
        Tempo--;
 
}  


void Timer0_Init(void)
{
 	// Initialize Timer0.
	// Used to give the correct time-delays in the song

    // Enable timer0 compare interrupt
	TIMSK0 = (1<<OCIE0A);

    // Sets the compare value
	OCR0A = 38;

	// Set Clear on Timer Compare (CTC) mode, CLK/256 prescaler
	TCCR0A = (1<<WGM01)|(0<<WGM00)|(4<<CS00);
}


SIGNAL(SIG_OUTPUT_COMPARE0)
{

	Play_Tune();

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -