@ -35,44 +35,81 @@
// Timer Abstractions
// -----------------------------------------------------------------------------
// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
// Turn on/off 3A interputs, stopping/enabling the ISR calls
# ifdef C6_AUDIO
//Currently we support timers 1 and 3 used at the sime time, channels A-C,
//pins PB5, PB6, PB7, PC4, PC5, and PC6
# if defined(C6_AUDIO)
# define CPIN_AUDIO
# define CPIN_SET_DIRECTION DDRC |= _BV(PORTC6);
# define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
# define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
# define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
# endif
# ifdef B5_AUDIO
# define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
# define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
# endif
// TCCR3A: Timer/Counter #3 Control Register
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
# ifdef C6_AUDIO
# define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
# define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
# endif
# ifdef B5_AUDIO
# define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
# define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
# endif
// Fast PWM Mode Controls
# ifdef C6_AUDIO
# define TIMER_3_PERIOD ICR3
# define TIMER_3_DUTY_CYCLE OCR3A
# define TIMER3_AUDIO_vect TIMER3_COMPA_vect
# endif
# if defined(C5_AUDIO)
# define CPIN_AUDIO
# define CPIN_SET_DIRECTION DDRC |= _BV(PORTC5);
# define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3B1) | (0 << COM3B0) | (1 << WGM31) | (0 << WGM30);
# define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3B)
# define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3B)
# define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3B1);
# define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3B1) | _BV(COM3B0));
# define TIMER_3_PERIOD ICR3
# define TIMER_3_DUTY_CYCLE OCR3B
# define TIMER3_AUDIO_vect TIMER3_COMPB_vect
# endif
# if defined(C4_AUDIO)
# define CPIN_AUDIO
# define CPIN_SET_DIRECTION DDRC |= _BV(PORTC4);
# define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3C1) | (0 << COM3C0) | (1 << WGM31) | (0 << WGM30);
# define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3C)
# define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3C)
# define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3C1);
# define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3C1) | _BV(COM3C0));
# define TIMER_3_PERIOD ICR3
# define TIMER_3_DUTY_CYCLE OCR3C
# define TIMER3_AUDIO_vect TIMER3_COMPC_vect
# endif
# ifdef B5_AUDIO
# if defined(B5_AUDIO)
# define BPIN_AUDIO
# define BPIN_SET_DIRECTION DDRC |= _BV(PORTB5);
# define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
# define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
# define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
# define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
# define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
# define TIMER_1_PERIOD ICR1
# define TIMER_1_DUTY_CYCLE OCR1A
# define TIMER1_AUDIO_vect TIMER1_COMPA_vect
# endif
# if defined(B6_AUDIO)
# define BPIN_AUDIO
# define BPIN_SET_DIRECTION DDRC |= _BV(PORTB6);
# define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1B1) | (0 << COM1B0) | (1 << WGM11) | (0 << WGM10);
# define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1B)
# define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1B)
# define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1B1);
# define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1B1) | _BV(COM1B0));
# define TIMER_1_PERIOD ICR1
# define TIMER_1_DUTY_CYCLE OCR1B
# define TIMER1_AUDIO_vect TIMER1_COMPB_vect
# endif
# if defined(B7_AUDIO)
# define BPIN_AUDIO
# define BPIN_SET_DIRECTION DDRC |= _BV(PORTB7);
# define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1C1) | (0 << COM1C0) | (1 << WGM11) | (0 << WGM10);
# define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1C)
# define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1C)
# define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1C1);
# define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1C1) | _BV(COM1C0));
# define TIMER_1_PERIOD ICR1
# define TIMER_1_DUTY_CYCLE OCR1C
# define TIMER1_AUDIO_vect TIMER1_COMPC_vect
# endif
// -----------------------------------------------------------------------------
@ -147,44 +184,48 @@ void audio_init()
if ( ! audio_initialized ) {
// Set port PC6 (OC3A and /OC4A) as output
# ifdef C6_AUDIO
DDRC | = _BV ( PORTC6 ) ;
//#else
// DDRC |= _BV(PORTC6); // Why is PC6 being set as output low, if C6_audio isn't defined?
// PORTC &= ~_BV(PORTC6);
// Set audio ports as output
# ifdef CPIN_AUDIO
CPIN_SET_DIRECTION
# endif
# ifdef B5_AUDIO
DDRB | = _BV ( PORTB5 ) ;
//#else
// DDRB |= _BV(PORTB5); // Same as with PC6
// PORTB &= ~_BV(PORTB5);
# ifdef BPIN_AUDIO
BPIN_SET_DIRECTION
# endif
# ifdef C 6 _AUDIO
# ifdef CPIN_AUDIO
DISABLE_AUDIO_COUNTER_3_ISR ;
# endif
# ifdef B5_AUDIO
# ifdef BPIN_AUDIO
DISABLE_AUDIO_COUNTER_1_ISR ;
# endif
// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
// Clock Select (CS3n) = 0b010 = Clock / 8
// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers TCCR3A/TCCR3B, TCCR1A/TCCR1B
// Compare Output Mode (COM3An and COM1An) = 0b00 = Normal port operation
// OC3A -- PC6
// OC3B -- PC5
// OC3C -- PC4
// OC1A -- PB5
// OC1B -- PB6
// OC1C -- PB7
// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14. Period = ICR3, Duty Cycle OCR3A)
// OCR3A - PC6
// OCR3B - PC5
// OCR3C - PC4
// OCR1A - PB5
// OCR1B - PB6
// OCR1C - PB7
# ifdef C6_AUDIO
TCCR3A = ( 0 < < COM3A1 ) | ( 0 < < COM3A0 ) | ( 1 < < WGM31 ) | ( 0 < < WGM30 ) ;
// Clock Select (CS3n) = 0b010 = Clock / 8
# ifdef CPIN_AUDIO
INIT_AUDIO_COUNTER_3
TCCR3B = ( 1 < < WGM33 ) | ( 1 < < WGM32 ) | ( 0 < < CS32 ) | ( 1 < < CS31 ) | ( 0 < < CS30 ) ;
TIMER_3_PERIOD = ( uint16_t ) ( ( ( float ) F_CPU ) / ( 440 * CPU_PRESCALER ) ) ;
TIMER_3_DUTY_CYCLE = ( uint16_t ) ( ( ( ( float ) F_CPU ) / ( 440 * CPU_PRESCALER ) ) * note_timbre ) ;
# endif
# ifdef B5_AUDIO
TCCR1A = ( 0 < < COM1A1 ) | ( 0 < < COM1A0 ) | ( 1 < < WGM11 ) | ( 0 < < WGM10 ) ;
# ifdef BPIN_AUDIO
INIT_AUDIO_COUNTER_1
TCCR1B = ( 1 < < WGM13 ) | ( 1 < < WGM12 ) | ( 0 < < CS12 ) | ( 1 < < CS11 ) | ( 0 < < CS10 ) ;
TIMER_1_PERIOD = ( uint16_t ) ( ( ( float ) F_CPU ) / ( 440 * CPU_PRESCALER ) ) ;
TIMER_1_DUTY_CYCLE = ( uint16_t ) ( ( ( ( float ) F_CPU ) / ( 440 * CPU_PRESCALER ) ) * note_timbre ) ;
# endif
@ -207,13 +248,12 @@ void stop_all_notes()
}
voices = 0 ;
# ifdef C6_AUDIO
# ifdef CPIN_AUDIO
DISABLE_AUDIO_COUNTER_3_ISR ;
DISABLE_AUDIO_COUNTER_3_OUTPUT ;
# endif
# ifdef B 5 _AUDIO
# ifdef B PIN _AUDIO
DISABLE_AUDIO_COUNTER_1_ISR ;
DISABLE_AUDIO_COUNTER_1_OUTPUT ;
# endif
@ -259,11 +299,11 @@ void stop_note(float freq)
voice_place = 0 ;
}
if ( voices = = 0 ) {
# ifdef C 6 _AUDIO
# ifdef C PIN _AUDIO
DISABLE_AUDIO_COUNTER_3_ISR ;
DISABLE_AUDIO_COUNTER_3_OUTPUT ;
# endif
# ifdef B 5 _AUDIO
# ifdef B PIN _AUDIO
DISABLE_AUDIO_COUNTER_1_ISR ;
DISABLE_AUDIO_COUNTER_1_OUTPUT ;
# endif
@ -295,15 +335,15 @@ float vibrato(float average_freq) {
# endif
# ifdef C 6 _AUDIO
ISR ( TIMER3_ COMP A_vect)
# ifdef C PIN _AUDIO
ISR ( TIMER3_ AUDIO _vect)
{
float freq ;
if ( playing_note ) {
if ( voices > 0 ) {
# ifdef B 5 _AUDIO
# ifdef B PIN _AUDIO
float freq_alt = 0 ;
if ( voices > 1 ) {
if ( polyphony_rate = = 0 ) {
@ -477,10 +517,10 @@ ISR(TIMER3_COMPA_vect)
}
# endif
# ifdef B 5 _AUDIO
ISR ( TIMER1_ COMP A_vect)
# ifdef B PIN _AUDIO
ISR ( TIMER1_ AUDIO _vect)
{
# if defined(B 5_AUDIO) && !defined(C6 _AUDIO)
# if defined(B PIN_AUDIO) && !defined(CPIN _AUDIO)
float freq = 0 ;
if ( playing_note ) {
@ -627,10 +667,10 @@ void play_note(float freq, int vol) {
}
if ( audio_config . enable & & voices < 8 ) {
# ifdef C 6 _AUDIO
# ifdef C PIN _AUDIO
DISABLE_AUDIO_COUNTER_3_ISR ;
# endif
# ifdef B 5 _AUDIO
# ifdef B PIN _AUDIO
DISABLE_AUDIO_COUNTER_1_ISR ;
# endif
@ -648,12 +688,12 @@ void play_note(float freq, int vol) {
voices + + ;
}
# ifdef C 6 _AUDIO
# ifdef C PIN _AUDIO
ENABLE_AUDIO_COUNTER_3_ISR ;
ENABLE_AUDIO_COUNTER_3_OUTPUT ;
# endif
# ifdef B 5 _AUDIO
# ifdef C 6 _AUDIO
# ifdef B PIN _AUDIO
# ifdef C PIN _AUDIO
if ( voices > 1 ) {
ENABLE_AUDIO_COUNTER_1_ISR ;
ENABLE_AUDIO_COUNTER_1_OUTPUT ;
@ -676,10 +716,10 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
if ( audio_config . enable ) {
# ifdef C 6 _AUDIO
# ifdef C PIN _AUDIO
DISABLE_AUDIO_COUNTER_3_ISR ;
# endif
# ifdef B 5 _AUDIO
# ifdef B PIN _AUDIO
DISABLE_AUDIO_COUNTER_1_ISR ;
# endif
@ -701,12 +741,12 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
note_position = 0 ;
# ifdef C 6 _AUDIO
# ifdef C PIN _AUDIO
ENABLE_AUDIO_COUNTER_3_ISR ;
ENABLE_AUDIO_COUNTER_3_OUTPUT ;
# endif
# ifdef B 5 _AUDIO
# ifndef C 6 _AUDIO
# ifdef B PIN _AUDIO
# ifndef C PIN _AUDIO
ENABLE_AUDIO_COUNTER_1_ISR ;
ENABLE_AUDIO_COUNTER_1_OUTPUT ;
# endif