/* Birdie.c */ #include #include #include #include enum { UP, DOWN }; volatile uint16_t ampl, upper, lower; volatile uint8_t direction, count, scount, max; SIGNAL (SIG_OVERFLOW1) { /* OCR1 gets the two values required to produce a pulse wave;the two values are upper and lower * OCR1 should be set to upper or lower based upon the MSB of your phase accumulator, which should * be enough bits to allow for pitch accuracy to reproduce the appropriate pitches */ if(++scount==max) { scount = 0; switch (direction) { case UP: OCR1A = upper; direction = DOWN; break; case DOWN: OCR1A = lower; direction = UP; break; } } /* This stuff should be in a counter/timer 2 routine. upper and lower should be set to: * upper = ampl + 127; * lower = 127 - ampl; * ampl controls loudness from 0 (off) to 127 (loudest). These values should come from a table with * ADSR (Attack, Decay, Sustain, Release) segments. The whole table should time scale to the * length of the note in your score */ if(++count == 50) /* duration */ { count = 0; if (--ampl == 0) { ampl = 127; if(--max ==1) max = 20; } upper = ampl + 127; lower = 127 - ampl; } } void ioinit (void) { ampl = 127; max = 20; /* tmr1 running on full MCU clock */ TCCR1B = _BV (WGM12) | _BV (CS10); /* tmr1 is 8-bit fast PWM, mode 5 , 28.8KHz sample rate*/ TCCR1A = _BV (WGM10) | _BV (COM1A1); /* set PWM value to 0 */ OCR1A = 0; /* enable PD5 as output */ DDRD = _BV (PD5); timer_enable_int (_BV (TOIE1)); /* enable interrupts */ sei (); } int main (void) { ioinit (); /* loop forever, the interrupts are doing the rest */ for (;;) ; return (0); }