//x_siren.c //one timeer creates the tone in freq generation mode //one timer creates an interrupt to update the setting for frequency //another timer creates the pwm signal for the volume control #include #include #include #include #define TRUE 1 #define FALSE 0 /***********************************************************************/ // 32Mhz internal RC oscillator initalization void init_32Mhzclock(void){ //setup clock for 32Mhz RC internal oscillator OSC.CTRL = OSC_RC32MEN_bm; // enable 32MHz clock while (!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for clock to be ready CCP = CCP_IOREG_gc; // enable protected register change CLK.CTRL = CLK_SCLKSEL_RC32M_gc; // switch to 32MHz clock } /***********************************************************************/ /***********************************************************************/ // Initalize TCC0 to normal mode //TCCO is used to as an interrupt source for updating the frequency of //the tone being created. Thus, it does not need to use an output pin. //Running in normal mode does not do any port override if no WGM mode //is set and CC channel is not enabled. See pg. 173 of AU manual. void init_TCC0_normal(){ //setup timer for normal mode, interrupt on overflow TCC0_CTRLA = TCC0_CTRLB = TCC0_PER = TCC0_INTCTRLA = } /***********************************************************************/ /***********************************************************************/ // Initalize TCD0 to frequency generation mode //TCDO is used to create the tone at an output pin. Period time is set by //the CCA register instead of PER. No interrupts are used. Output is //on PORTD bit 5. CCAEN must be enabled to allow waveform generation. //Frequency is defined by: clk_perif/[(2*prescaler_value)(CCA+1)] // void init_TCD0_freq_gen(){ TCD0_CTRLA = TCD0_CTRLB = TCD0_CCA = } /***********************************************************************/ /***********************************************************************/ // Initalize TCD1 to pwm, single slope mode //TCD1 is used to create the PWM signal for adjusting the volume of the //audio amplifier. No interrupts are used. Output is on pin PD4. //CCAEN must be enabled to allow waveform generation. A 30% duty cycle //is a good starting place for the volume level using 8 ohm speaker. //pwm_freq = fclk/prescale*(PER+1) // void init_TCD1_pwm(){ TCD1_CTRLA = TCD1_CTRLB = TCD1_PER = //Period of PWM signal. TOP is held here. TCD1_CCA = //Duty cycle is set here. Smaller #'s, Duty cycle goes down. } /***********************************************************************/ /***********************************************************************/ // ISR for TCC0 //Overflow will occur with TCD0_CCA match. Increases/decreases frequency //as a fraction of the frequency, not as a fixed value. // ISR(TCC0_OVF_vect){ //somewhere in your code.... TCD0_CCABUF = //Must use double buffering else, big pauses will //occur as the TCD0 has to go to old value. Tricky! } /***********************************************************************/ int main(){ init_32Mhzclock(); init_TCD0_freq_gen(); //turn on frequency generation of tone init_TCC0_normal(); //turn on interrupt source for update of frequency init_TCD1_pwm(); //turn on pwm to control volume control PORTD.DIR |= PIN0_bm; //Port D bit 0 is the output for the tone PORTD.DIR |= PIN4_bm; //Port D bit 4 is the pwm for the volume control PMIC.CTRL |= //low level interrupts enabled sei(); //global interrupts on while(1){ } //loop forever } // main