Skip to main content

Musikausgabe mittels Timer

/*
 * Liederausgabe aufbauend auf dem 
 * Democode "Tonausgabe mittels Timer"
 * 
 * Code, um eine Tonfolge mit definierter Laenge auszugeben
 * https://www.eHaJo.de
 * (C) Hannes Jochriem, 2013
 */
 
#define F_CPU 8000000UL     /* 8MHz */
 
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
// Prototypen
void long_delay(uint16_t);
 
// Defines:
#define SUMMER		(1<<PD7)
 
// Diese Werte berechnen sich aus "8MHz / Frequenz des Tones / 2"
// Sollte ein anderer CPU-Takt verwendet werden muessen
// die Werte neu berechnet werden.
#define TON_C		15152l
#define TON_CIS		14545l
#define TON_D		13468l
#define TON_ES		12618l
#define TON_E		12121l
#define TON_F		11364l
#define TON_FIS		10899l
#define TON_G		10101l
#define TON_GIS		9479l
#define TON_A		9091l
#define TON_B		8421l
#define TON_H		8081l
#define TON_CC		7576l
#define TON_CCIS	7273l
#define TON_DD		6734l
#define TON_EES		6309l
#define TON_EE		6061l
#define TON_FF		5682l
#define TON_FFIS	5450l
#define TON_GG		5051l
#define TON_GGIS	4740l
#define TON_AA		4546l
#define TON_BB		4211l
#define TON_HH		4041l
 
// globale Variablen
 
// In diesem Array stehen die Werte fuer den CTC-Counter
uint16_t tonleiter[24] = {
	TON_C,		//  0
	TON_CIS,	//  1
	TON_D,		//  2
	TON_ES,		//  3
	TON_E,		//  4
	TON_F,		//  5
	TON_FIS,	//  6
	TON_G,		//  7
	TON_GIS,	//  8
	TON_A,		//  9
	TON_B,		// 10
	TON_H,		// 11
	TON_CC,		// 12
	TON_CCIS,	// 13
	TON_DD,		// 14
	TON_EES,	// 15
	TON_EE,		// 16
	TON_FF,		// 17
	TON_FFIS,	// 18
	TON_GG,		// 19
	TON_GGIS,	// 20
	TON_AA,		// 21
	TON_BB,		// 22
	TON_HH		// 23
};
 
// Melodie definieren, in diesem Fall 
uint8_t melodie[38] = {
	14,	// Sand-
	14,	// mann
	11,	// lie-
	12,	// ber
	14,	// Sand-
	14,	// mann
	11,	// es
	11,	// ist
	12,	// noch
	9,	// nicht
	11,	// so
	7,	// weit!
	7,	// Wir
	9,	// sen-
	11,	// den
	9,	// erst
	11,	// den
	7,	// A-
	4,	// bend-
	6,	// ...
	7,	// gruß,
	9,	// eh
	7,	// ...
	6,	// je-
	9,	// des
	7,	// Kind
	9,	// ins
	11,	// Bett-
	12,	// chen
	14,	// muss.
	11,	// Du
	12,	// ...
	9,	// hast
	7,	// ge-
	9,	// wiss
	4,	// noch
	6,	// ...
	7	// Zeit.
};
 
// Die Dauer der Noten definieren, 1 = 1/8-Note, 2 = 1/4 usw.
uint8_t dauer[38] = {2,2,1,1,2,2,2,3,1,1,1,4,2,3,1,1,1,2,1,1,4,1,1,1,1,1,1,1,1,4,1,1,1,1,2,1,1,6};
 
ISR(TIMER1_COMPA_vect)
{
	// Summer-Pin toggeln
	PORTD ^= SUMMER;
}
 
int main()
{
	// Laufvariable
	uint8_t i;
 
	// Summer als Ausgang definieren
	DDRD |= SUMMER;
 
	// Timer1 ohne Vorteiler starten, CTC-Mode
	TCCR1B |= (1<<CS10) | (1<<WGM12);
 
	// Outputcompare-Register setzen, hier fuer ~440Hz
	OCR1A = TON_C;
 
	// Interrupt einschalten
	TIMSK |= (1<<OCIE1A);
 
	// Globales Interruptflag einschalten:
	sei();
 
	for(i = 0; i<38; i++)
	{	// Fuer alle Noten im Array
 
		// Compare-Wert entsprechend Array setzen
		OCR1A = tonleiter[melodie[i]];
 
		// Warten damit die Note klingen kann...
		long_delay(dauer[i]*300); // *300 klingt ganz gut bei dem Lied
 
		// Timer kurz aus- und wieder einschalten damit gleiche Noten
		// hintereinander unterschieden werden koennen
		TCCR1B = 0;
		long_delay(2); 
		TCCR1B |= (1<<CS10) | (1<<WGM12);
	}
 
	// Lied Ende, Timer ausschalten:
	TCCR1B = 0;
 
	while(1)
	{
		// nix...
	}
 
	return 0;
}
 
 
void long_delay(uint16_t ms) 
{
	for(; ms>0; ms--) 
		_delay_ms(1);
}