TMR1 ve tek pin, Timeslice ile melodi üreteci (her programa eklenebilir)

Başlatan eseneren, 20 Şubat 2011, 23:58:07

eseneren

Multitask deneme amaçlı yapmaya çalıştığım melodi üreteci sadece TMR1 kesmesi ve bir pin kullanarak 2 oktav kare dalga ses melodi üreteci.
melodi dizisine girilen rakamlar her biri char tipinde 8bitin ust 4 biti nota değeri alt 4 biti nota bilgisidir
bir iki örnek ile
0001/0001 1lik do notası
0010/0001 1/2 do notası
0100/0001 1/4 do notası 

0001/0010 1lik re notası
0010/0010 1/2 re notası
0100/0010 1/4 re notası

1000/0011 1/8 mi notası

0000/xxxx ust 4 bit sıfır ise melodi bitti manasındadır


Programınız çalışırken bir yandan da melodi çalışabilir
#include <htc.h>
#ifndef _XTAL_FREQ
	#define _XTAL_FREQ 20000000
#endif
#define out RC7 
#define out2 RC6 
__CONFIG(HS & UNPROTECT & WDTDIS & LVPDIS & PWRTDIS & BORDIS );

void mcu_initialize();
void play(const unsigned char *buffer);

// Bach Minuet
const char melodi[]={25,69,70,71,72,41,37,37,16,
						26,72,73,74,75,44,37,37,16,
							40,73,72,71,70,39,72,71,70,69,38,71,70,69,68,37,0};

const char ZT_TMR1H[]={0xB5,0xB5,0xBD,0xC4,0xC8,0xCE,0xD3,0xD8,0xDA,0xDE,0xE2,0xE4,0xE7,0xE9,0xEC,0xED,0x0};
const char ZT_TMR1L[]={0x56,0x56,0x7F,0xBE,0x11,0x2C,0x9C,0x74,0xAB,0xBF,0x5F,0x08,0x16,0xCE,0x3A,0x55,0x0};
//int nota_periyod[]={261,261,294,330,349,392,440,494,523,587,659,698,784,880,988,1046};
int nota_periyod[]={131,147,165,174,196,220,247,262,294,330,349,392,440,494,523};

unsigned char nota,nota_degeri;
unsigned char *notapointer;
int i,periyod;
// ***** tempo degerini gir *****/
double tempo=40;

void main(void) 									// Ana fonksiyon alanı
{
mcu_initialize();
tempo=tempo/60; 									//Tempo hesapla
for(i=0;i<16;i++)
	nota_periyod[i]=(int)(nota_periyod[i]*tempo);
while(1)
{
	play(melodi);									// Melodi cal
	for(i=0;i<100;i++)								// Sadece is olsun diye led yan son.
	{
		out2=!out2;					
		__delay_ms(250);
	}
}}//

void play(const unsigned char *buffer)
{
	if(!TMR1IE)										// Timer1 calıyorsa (melodi çalmıyorsa)
	{
		notapointer=buffer;							// Meledo başına konumlan
		periyod=0;									// degerleri sıfırla
		out=0;
		TMR1IF=1;
		TMR1IE=1;									// Interruptı başlat
	}
}//
	
static void interrupt 								// Kesme fonksiyonu
kesme(void) 				
{
	if(TMR1IF&&TMR1IE)								// TMR1 den kesme gelirse
	{
		TMR1IF=0;									// Flagı temizle
		if(!periyod)								// Nota Başında ise
		{
			nota_degeri=(*notapointer)>>4;			// Melodi dizisinden notadegerini hesapla
			nota=(*notapointer&0x0F);				// Melodi dizisinden notayı hesapla
			periyod++;								// Periyod sonraki kesme için artır
			TMR1H=10;								// TMR1e uyduruk deger melodi başlaması için
			TMR1L=100;
		}
		else										// Nota Başında değil ise ve
		{
			if(!nota_degeri)						// nota_degeri 0 ise(melodi sonu ise)
			{									
				periyod=0;							// Değerleri sıfırla 
				out=0;		
				TMR1IF=0;							// Interruptı iptal et
				TMR1IE=0;					
			}
			else									// Nota 0 değilse 
			{
				if(periyod<(nota_periyod[nota]/nota_degeri))// Periyod notaya ve degere baglı olarak 
				{											// tekrarlansın		
					if((out==0)&&(!(nota==0)))				// out 0 sa 1 yap lakin nota=0 sa (nota 0 ise es)
						out=1;								// 1 yapma 0 ları tekrar et
					else
					{
						out=0;
						periyod++;							// kare dalga periyod tamamlanınca periyod++
					}		
					TMR1H=ZT_TMR1H[nota];					// Timer1 icin gerekli değerler atanır
					TMR1L=ZT_TMR1L[nota];
				}
				else										// Nota sonu geldi ise
				{
					notapointer++;							// Dizide sonraki değere geç
					periyod=0;								// periyodu sıfırla
					TMR1H=10;								// TMR1e uyduruk deger melodi başlaması için
					TMR1L=100;
				}
			}
		}
	}
}//

void mcu_initialize()							// I/O portları ve PIC ayarlanır  
{
// I/O portları Belirlenir
TRISA=0x03; 									// Analog giris
PORTA=0x00;
TRISB=0x00;										
PORTB=0x00;
TRISC=0x00;
PORTC=0x00;
TRISD=0x00;
PORTD=0x00;
//TMR1 kurulur
TMR1CS=0;										// Dahili osilatör
T1CKPS1=0;										// Prescaler 1:4 oluyor
T1CKPS0=0;
T1SYNC=1;										// Senkronizasyon yok
TMR1IF=0;										// Timer1 flag temizle
TMR1IE=0;										// Timer1 kesmesine izin veriliyor
TMR1ON=1;										// Timer ON
PEIE=1; 										// Yardımcı kesme izni veriliyor
GIE=1; 											// Genel kesme izni veriliyor
}//


Eğitim amaçlı yazılmıştır hatalarını gördükçe düzeltiyorum derli toplu bir kutuphane oluşturup paylaşmayı düşünüyorum.
Nota girerek dizi oluşturması için excelde birşey hazırlayacağım..

Saygılar
Seçim yapmak için durum hakkında bilgi sahibi olmak zorunda değilsin, sonucuna hazır olmak için durum hakkında kaygılanırsın.  http://bit.ly/gixfTk

eseneren

Melodi oluşturmak için gerekli excel dosyası...
Sadece A ve B hucrelerini doldurarak dizi oluşturuyor,
hucreleri aşağı doğru uzatıp melodiyi istediğiniz kadar uzatabilirsiniz..
http://www.dosyaupload.net/4997697.html
Seçim yapmak için durum hakkında bilgi sahibi olmak zorunda değilsin, sonucuna hazır olmak için durum hakkında kaygılanırsın.  http://bit.ly/gixfTk

t2

Bach minuet tamam da  Toccata ve Füg nasıl olur?


eseneren

Notaları girdikden sonra komalıda olsa burhan çaçan vurun dalgaları bile çalar :)
Sagolun paylaşım için sevdigim bir parcayı paylaşmak isterim
Seçim yapmak için durum hakkında bilgi sahibi olmak zorunda değilsin, sonucuna hazır olmak için durum hakkında kaygılanırsın.  http://bit.ly/gixfTk