All pastes #2098131 Raw Edit

full code

public c v1 · immutable
#2098131 ·published 2012-01-02 11:37 UTC
rendered paste body
// Sergio Campama 2011// http://kaipi.me//// Adapted for internal oscillator, added random sound and delay by jonathan schemoul//// Made for the TI MSP430 LaunchPad// http://ti.com/launchpadwiki//// Heavily based on http://www.43oh.com/forum/viewtopic.php?f=10&t=1159#include <msp430.h>#include <inttypes.h>//In uniarch there is no more signal.h to sugar coat the interrupts definition, so we do it here#define interrupt(x) void __attribute__((interrupt (x))) //Defines to help understand what is attached to each port#define LED_DIR P1DIR#define LED_OUT P1OUT//P1.0 is the red LED#define LED_RED BIT0//Piezo defines//Here it is defined as BIT6 to see the results on the LED, but should be changed to the bit where it is //connected the piezo#define PIEZO BIT6#define PIEZO_DIR P1DIR#define PIEZO_SEL P1SEL#define PIEZO_OUT P1OUTvoid timer_init(){    BCSCTL3 |= LFXT1S_2;	//Set DCO to 1 MHz	BCSCTL1 = CALBC1_1MHZ;	DCOCTL = CALDCO_1MHZ;		//Select ACLK, TimerA counter divisor in 1	TACTL |= TASSEL_1 + ID_0; 	//Enables the CCR0 interrupt	TACCTL0 |= CCIE; }void piezo_init(){	//Set the direction as output	PIEZO_DIR |= PIEZO; 		//Set the piezo bit to PWM output of TA1, which coincides with the green	//LED in the Launchpad	PIEZO_SEL |= PIEZO;	}void led_init(){	//Set the direction as output	LED_DIR |= LED_RED; 		//Red led starts off	LED_OUT &= ~LED_RED;	}void init(){	//Stop the watchdog	WDTCTL = WDTPW + WDTHOLD; 	//Inits the different parts	led_init();	piezo_init();	timer_init();	//Enable global interrupts	_BIS_SR(GIE);}void timer_start(){	//Since the crystal attached to LFXT is 32.768 kHz, 	//when the counter reaches this value, exactly 1 second should have passed	//The clock skew is 20 ppm, which at this frequency, should be +-.65 Hz	//TACCR0 = 32767;	TACCR0 = 12000;		//Sets the TimerA count mode in UP, and thus starting the Timer	TACTL |= TASSEL_1 | MC_1;	}int main(){	init();	timer_start();		//We enter the LPM3 Low Power Mode, which only leaves ACLK running	//This way, the CPU will be off for 1 second, toggle the LED, and turn off for another second	_BIS_SR(LPM3_bits);		return 0;}//This function delivers a uniform random variable between 20 and 899uint64_t random_seed = 65738265;uint16_t random_uniform(){	random_seed = (4000*random_seed) % (2147483647LLU);	return random_seed % 600 + 10;	//return 3;}//This function delivers a uniform random variable between 20 and 899uint64_t brandom_seed = 6008264;uint16_t brandom_uniform(){	brandom_seed = (4000*brandom_seed) % (2147483647LLU);	return brandom_seed % 38 + 10;	//return 3;}//actual_delay counts the number of seconds passed since the last//beep, while delay_s is time where the beep will sound, referenced//to the last beep alsouint16_t actual_delay = 0;uint16_t delay_s = 2;//playing is an indicator that the piezo is currently on//piezo cycles counts the number of cycles it has been playing,//referenced to the PWM frequencyuint8_t playing = 0;uint16_t piezo_cycles = 0;uint8_t randval = 0;//CCR0 timer interrupt, which toggles the LEDs//Theres more than one definition for this interrupt, depending on the model#ifdef TIMER0_A0_VECTORinterrupt(TIMER0_A0_VECTOR) TIMERA0_ISR() {#elseinterrupt(TIMERA0_VECTOR) TIMERA0_ISR() {#endif		//if we are playing and the time has not yet passed to stop	//playing, return. I prefer this over a while approach, as this saves battery	//To understand this value, read first the long comment just before	//setting TACCR0 and TACCR1 inside the 'if'. Ok, so we want to play for half a second,	//which in a crystal of 32768 Hz, is 16384. This interrupt will be called every 64 cycles,	//value calculated below. So, we will achieve 16384 cycles (half a second)	//after 16384/64 interrupt calls, which equals to 256.	//Remember, if you want a frequency of X, you need to set TACCR0 to 32768/X.	//Then if you want to play for T seconds, set this comparison to 32768*T/TACCR0		if (playing) {	    piezo_cycles++;	    if (piezo_cycles == 48 && (brandom_seed % 2)) {	        randval = brandom_uniform();	        TACCR0 = randval;//32768 >> 1;		    TACCR1 = randval/2;	    }	    if (piezo_cycles < 94) return;	} 		//after it has finished the playing time, stop playing and reset the cycles for the next	//beep	playing = 0;	piezo_cycles = 0;		//We turn the PIEZO off just in case	PIEZO_OUT &= ~PIEZO;		//This turns off the pwm in cc1	TACCTL1 &= ~OUTMOD_7; 		//We set the normal time on CCR0 so the interrupt	//interval is still 1 second	TACCR0 = 12000;		if (++actual_delay >= delay_s)	{		//The time has come to beep		//we calculate the new delay and reset actual_delay		actual_delay = 0;		delay_s = random_uniform();				//Having a crystal of 32768 Hz, and wanting to play at a frequency of		//500 hz, we set TACCR0 to 32768/500, rounded down to the nearest even		//which is 64. We then set the PWM duty cycle in TACCR1, in this case to		//50% -> 64*0.5 = 32. The duty cycle should control the volume of the piezo,		//but when tested on my headphones, it didn't make much difference, but		//with a higher value I think it sounds better. Keep in mind, if its higher 		//than TACCR0, nothing will sound		//TACCR0 = 64;//32768 >> 1;		//TACCR1 = 32;		//TACCR0 = 24;//32768 >> 1;		//TACCR1 = 6;		        randval = brandom_uniform();        TACCR0 = randval;//32768 >> 1;	    TACCR1 = randval/2;				//We set the PWM output mode to toggle set/reset mode		//See the MSP430x2xx User's Guide for more information		//in the TimerA module		TACCTL1 |= OUTMOD_7; 				//Finally, we tell the system that it is playing		playing = 1;			}	}