AVR- Buzzer ile Müzik



Sadece birkaç değişik "bip" sesi çıkartmak amacıyla başladığım iş biraz büyüdü. Bip sesi yerine farklı notaları farklı hızlarda çalsam derken bana göre güzel bir şey çıktı. Okuyan birçok kişi için basit gelebilir ama ben yine de paylaşmak istedim. Çünkü hem ilerde tekrar aynı şeyleri araştırmak zorunda kalmamak için yazmış olurum hem de ihtiyaç duyanlara bir kaynak olur. Bu arada gerçekten çocuk gibi eğlenerek yaptığım bir iş oldu. Arduino Tone() fonksiyonunu muhtemelen herkes kullanmıştır veya duymuştur. Onda bazı sorunlar var. Birden fazla kart ve timer ile çalışacak şekilde ayarlandığından oluşan bu sorunlar burada yok. Mesela Tone ile arada bekleme olmadan ses çıkartamazsınız benim paylaşımımda nota aralarına bekleme koymasanız da çalışır. Buna ek olarak aynı notayı farklı oktav değerlerinde çalmak isterseniz tüm notaları tekrar yazmanız gerekmez sadece parametre değiştirirsiniz. Tek tek anlatmak yerine konuya geçmek daha doğru olacak.

Notalar

Ses basit bir anlatımla bir yüzeyin belirli bir frekansla titreşimiyle oluşur. 20 ile 20000Hz arasındaki titreşimlerin çıkardığı sesi duyabiliyoruz. Yaşlandıkça bu üst sınır düşüyor. Çocuklarla test ettik, onların duyduğu sesi ne yazık ki ben duyamıyorum,  15000 Hz sonrası sessizlik. Bu geniş aralıkta duyulan ve müzik aletlerinin çıkardığı kulağa hoş gelen kısmını 0 dan başlayıp 8 e kadar oktav denilen bölümlere ayırmışlar. Tam ortada yer alan 4 oktav "LA" notasının frekansı 440 Hz kabul edilmiş ve her oktav 12 ye bölünmüş. La notasının frekansına göre bir sonraki notayı bulmak için 2^(1/12) ile çarpmak veya bölmek gerekiyor. Ayrıca La notasının bir alt veya üst oktav frekansı 2 katı veya yarısı şeklinde ilerliyor. Bunları öğrenince bir tablo ile tüm notaların frekanslarını hesapladım. Hazır olarak bulduğum değerlerde virgülden sonrası yeterli gelmedi.



La notası frekansı için 432Hz değerinin kullanıldığı enstrümanlar ve müzik türleri varmış ama ben o konulara girmedim, komplo teorilerine kadar gidiyor. Bu tabloda görülen Hz cinsinden frekansa göre benim çıkışı ayarlamam gerekecek.

Zamanlayıcı

Notalar için Timer1 birimini kullandım. Bunun nedeni timer1 in 16 bit olmasıdır. Bu sayede notaların gerçek frekansına yaklaşmış oldum. Başta PWM ile yaptım ama farklı pinleri seçme şansı vermek için CTC modu ve pin toggle yaparak çıkış vermek mantıklı geldi. Aksi halde iki pine mahkum olacaktım. MCU saat frekansı 16MHz ve prescaler kullanmazsam çok büyük rakamlara ulaşacak olan sayıcıda taşma oluşacaktır. Bunun ilave kodlarıyla uğraşmak istemedim. Seçtiğim prescaler çok büyük olursa yüksek frekanslarda çok küçük OCR1A değerleri çıkartacağından gerçek frekansa yaklaşma şansım azalacaktır. Tüm bunları düşünerek prescaler değerini "8" olarak seçtim. CTC modunda timer1 sayıcı (TCNT1) registeri OCR1A ile eşleştiğinde kesme oluşuyor ve TCNT1 sıfırlanıyordu. Bu konu hakkında daha önce paylaşımlarım oldu aynı konuyu tekrar etmeyeceğim. OCR1A değeri ile kesme oluşunca çıkışı pini "1" ve "0" olarak sürekli değişiyor. Bu değişimin aralığı (frekansı) değiştikçe çıkan ses de değişiyor. Aşağıda datasheetten alınma şemada bunu görebilirsiniz.

 

 

 



OC1A (OCna) frekansı için de yukarıdaki formülü kullanıyoruz. Bu formülde "N" prescaler değeri ve Fclk MCU çalışma frekansıdır. Frekans değerleri bir saniyedeki değişime göre belirleniyor, en düşük frekans "1" ve "0" zaman olarak arası en çok olandır. Notaların frekanslarına baktığımızda en düşük frekans bizim için en büyük OCR1A (OCRnA) değeri demektir. Bu nedenle "0" oktav da yer alan notaları baz alarak hesaplama yaptım. "0" dan "8" e kadar oktav değeri büyüdükçe frekans değeri de büyüyor ve OCR1A değeri de düşüyor. Bu değişim frekans olarak bir alt oktavın 2 katı artarken OCR1A değeri olarak aynı oranda azalacaktır. Büyük OCR1A değerini bölerek daha doğru değerler bulmuş oldum. "0" oktav tüm notalar için gerekli değerleri ön tanımlı olarak yüklemek ve diğer oktav değerlerini kod içinde hesaplatmak daha doğru geldi. Örnek olarak "0" oktav "DO" için OCR1A değerini bulalım.

Yukarıdaki formülde OC1A frekansını yerine yazıp OCR1A değerini formülden çekelim. OC1A frekansı bizim çıkış frekansımız yani notanın frekansıdır. Bu durumda formül OCR1A=(Fclk/fOC1A/(2*N))-1 şekline dönüşür. OCR1A=(16000000/nota Hz/(2*8))-1=(16000000/16,35160/16)-1=61155,103 olarak buluruz.

//0 oktav nota ocr değerleri prescaler 8
//datasheet CTC fOCR= f Clk/ (2*N*(1+OCR1A) N prescaler fOCR istenen frekans
// =((16000000/(Nota Hz)/2/8)-1) formülden OCRA değerini çekince bulunur.
#define DO    61155// 0 oktav DO 16,35159 Hz
#define DO_d  57723
#define RE_b  57723
#define RE    54483
#define RE_d  51425
#define MI_b  51425
#define MI    48539
#define FA    45814
#define FA_d  43243
#define SOL_b 43243
#define SOL   40816
#define SOL_d 38525
#define LA_b  38525//0 oktav 25,956 LA/2^(1/12)
#define LA    36363//0 oktav 27,50Hz ---tüm notalar 4 oktav 440Hz e göre hesaplandı 
#define LA_d  34322//0 oktav 29,135 LA*2^(1/12)
#define SI_b  34322
#define SI    32395
#define DO_I  30577

Timer Kesmesi

Bulduğumuz bu değere TCNT1 her ulaştığında yani OCR1A ile her eşleşmede kesme oluşur. Her kesme oluşumunda çıkış için ayarladığımız pin "1" veya "0" olur. Böylece istenen frekansa en yakın çıkışı sağlamış oluruz. Notaların frekansları kadar duyulma süresi yani vuruş zamanı da önemlidir. Aksi halde sadece gürültü olacaktır. Vuruş süresini delay veya benzeri bir şekilde ayarlamak yerine zaten kullanmakta olduğumuz timer ile bir sayaç kullanarak ayarlamak mantıklı olandır. Oktav değiştikçe değişen bir OCR1A değeriyle sabit bir sayaç kullanamayız. Bu nedenle her nota için istediğimiz vuruş süresini hesaplamak gerekir. Bu hesaba daha sonra değineceğim.

Kesme içinde bulduğumuz sayaç değerini kontrol edip sınıra gelince timer1 birimini durdurarak vuruş süresini de ayarlıyoruz. Toggle ile pin durumunu terslerken boşta ya da notalar arası beklemede çıkış vermemesi için her seferinde pin durumunu "1" yapıyorum.  OCR1A tek sayı olduğunda "1" ile başlayıp "1" ile bitirir ve sorun olmazken çift sayı olduğunda bir notadan diğerine geçerken pin durumu "0" olarak kalır ki bu durum çıkışı bozabilir. Pin "0" olduğunda  çıkış alacak şekilde ayarladım. Buzzer "+" ucu +5 volta bağlı, bu nedenle çıkış yokken pin "1" yapıldı. Anlamlı bir müzik için "sus" işaretleri de olmazsa olmazlardan. Sus için bir bayrak tanımlı ve "1" olduğunda toggle işlemi yapılmıyor.

ISR(TIMER1_COMPA_vect){	
	if (kesme_sayac<=nota_sayac){
		if (sus!=1){
			NOTA_PIN_T;//pin toggle
		}
		kesme_sayac++;
	}else{					
		nota_bitti=1;
		kesme_sayac=0;		
		TCCR1B&=~(1<<CS11);//timer1 durdu
		NOTA_PIN_H;//sonraki toggle işlemine high olarak başlar
		sus=0;		
	}	
}

Nota Fonksiyonu

Nota

Notaların güzel bir melodiye dönüşmesi için öncelikle doğru sesi çıkarması gerekir. Bunun için yukarıda gerekli işlemleri yaptım ve çok küçük farklar dışında en yakın frekansları elde ettim. İlk parametre olan notaya tekrar değinmeye gerek yok.

Oktav

Oktav değeri yükseldikçe notanın frekansı artarken OCR1A değeri azalır. Bunun için "0" oktav değeri neyse istenen oktav değeri kadar sağa kaydırarak notanın OCR1A değerini buluyoruz. Örnek olarak 1 oktav değeri bulmak için 0 oktav değerini 2 ye bölmek gerekir. Oktav 1 Nota(OCR1A)=Oktav 0 Nota(OCR1A)/2=Oktav 0 Nota(OCR1A)>>1 olur. Bu şekilde parametre alıp ayarlamanın daha doğru olduğunu düşünüyorum. Diğer türlü bir parçayı farklı değerde çalmak için nota listenizi yenilemeniz gerekir. Bu şekilde sadece nota listenizi girmeniz yeterli olur, tek yapmanız gereken parametreyi değiştirmektir. Bir parça içinde birden fazla oktavda çalınması gereken nota olması durumu için ince hali yani bir üst oktav bilgisini de kod içinde tanımladım. İki ya da daha fazla olması durumunda oktav için bir dizi tanımlanması daha doğru olur. Ben İstiklal marşı için bu şekilde yaptım.

Sonraki adım notaların bir araya gelerek vuruş süresi ve gereken yerlerde de sus ile bir ahenk yakalanmasıdır.

Vuruş Süresi

Notaların vuruş süresini frekans için kullandığımız timer1 ile belirleyeceğim. Bunun için bir sayaç tanımlıyorum ama dediğim gibi sabit bir değer veremiyorum. Bunun nedeni TCNT1 değerinin benim hangi oktav da olduğuma bakmaksızın bir mikro saniyede 2 kere artmasıdır. 4 Oktav LA için OCR1A değeri 2273, 5 Oktav LA için 1136 olur. Biz 4 oktav da kullandığımız sayaç değerinin iki katını 5 oktav da kullanırsak ancak aynı vuruş süresini buluruz. Bir saniye olarak baz aldığım ikilik bir LA için hesap yapalım. 4 Oktav La notasını elde etmek için TCNT1 2273 olmalı, OCR1A ile eşleşmeli ve kesme oluşmalıdır. Bunun için gereken 2273 saat darbesi 2273/2=1136,33 µs dir. (Prescaler 8 ve 16000000/8=2000000 saniye=2 µs) Bu hesaba göre OCR1A değerinin yarısı bize geçen zamanı verir. Her 1136µs bir kesme oluşur ve sayaç değeri bir artar. Bunu ms cinsine çevirelim 1136,33/1000=1,13633ms buluruz.

Kesme için gereken süreyi yani sayaç değerinin 1 artışındaki süreyi ms cinsinden bulduk. Bir milisaniye için sayaç değerini bulmamız gerekiyor. Bunun için de 1/1,13633=0,880 olur. Bu değer 4 oktav la için oluşan kesmelerle artan sayacın 1ms içindeki değeridir. Artık bir saniye=1000ms için sayaç değerini bulmak kolay 1000*0,880=880dir. Sayaç eğer 880 olursa 1 saniye geçmiş demektir. Aynı hesabı 5 oktav için yaparsak sayaç için: 1136/2=568µs=568/1000=0,568 ms sayacın bir artması için geçen süre, 1/0,568=1,760 bir ms deki sayaç değeridir. Bir saniye için sayaç=1,760*1000= 1760 buluruz.

Karışık olarak yaptığımız bu işlemleri bir formül haline getirelim. Sayaç= istenen süre(vuruş)*((2*1000)/OCR1A)=vuruş*2000/OCR1A olur. Bu üç parametre sonrası notanın sonuna kadar çalınabilmesi için zoraki bir döngü kullanmak gerekiyor. Bunun için de bir bayrak tanımladım.

Aşağıda kod içinde yeterli açıklamanın mevcut olduğunu düşünüyorum.

Not: Pasif buzzer kullanılması gerekiyor.


/*
* nota_timer_1.c
*
* Created: 17.02.2022 14:32:47
* Author : haluk
*/


#define F_CPU 16000000ul
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>



#define NOTA_PORT	PORTD
#define NOTA_DIR	DDRD
#define NOTA_PIN	PORTD5

#define NOTA_OUT	NOTA_DIR|=(1<<NOTA_PIN);
#define NOTA_PIN_H	NOTA_PORT|=(1<<NOTA_PIN);
#define NOTA_PIN_L	NOTA_PORT&=~(1<<NOTA_PIN);
#define NOTA_PIN_T	NOTA_PORT^=(1<<NOTA_PIN);

//0 oktav nota ocr değerleri prescaler 8
//datasheet CTC fOCR= f Clk/ (2*N*(1+OCR1A) N prescaler fOCR istenen frekans
#define DO    61155// =((16000000/(Nota Hz)/2/8)-1) formülden OCRA değerini çekince bulunur. 
#define DO_d  57723
#define RE_b  57723
#define RE	  54483
#define RE_d  51425
#define MI_b  51425
#define MI    48539
#define FA    45814
#define FA_d  43243
#define SOL_b 43243
#define SOL   40816
#define SOL_d 38525
#define LA_b  38525//0 oktav 25,956 LA/2^(1/12)
#define LA    36363//0 oktav 27,50Hz ---tüm notalar 4 oktav 440Hz e göre hesaplandı
#define LA_d  34322//0 oktav 29,135 LA*2^(1/12)
#define SI_b  34322
#define SI    32395
#define DO_I  30577

//1 oktav nota ocr değerleri prescaler 8
//her oktav değeri bir öncekinin yarısı
//her parçada oktav dizisi oluşturmamak için yazıldı çok gerekli değil.
// bkz. İstiklal marşı
#define I_DO_d  (DO_d>>1)
#define I_RE_b  (RE_b>>1)
#define I_RE	(RE>>1)
#define I_RE_d  (RE_d>>1)
#define I_MI_b  (MI_b>>1)
#define I_MI    (MI>>1)
#define I_FA    (FA>>1)
#define I_FA_d  (FA_d>>1)
#define I_SOL_b (SOL_b>>1)
#define I_SOL   (SOL>>1)
#define I_SOL_d (SOL_d>>1)
#define I_LA_b  (LA_b>>1)
#define I_LA    (LA>>1)
#define I_LA_d  (LA_d>>1)
#define I_SI_b  (SI_b>>1)
#define I_SI    (SI>>1)
#define I_DO_I  (DO_I>>1)

volatile uint8_t sus=0,nota_bitti=0;
volatile uint16_t onceki_nota=0;
volatile uint32_t nota_sayac=0, kesme_sayac=0;

void timer1_init();
void nota_cal(uint16_t nota,uint8_t oktav, uint32_t vurus);

const uint16_t YASASIN[]={//yaşasın okulumz
	DO,DO,SOL,SOL,LA,LA,SOL,0,
	FA,FA,MI,MI,RE,RE,DO,0,
	SOL,SOL,FA,FA,MI,MI,RE,0,
SOL,SOL,FA,FA,MI,MI,RE,0};
const PROGMEM uint16_t  GEZSEN[115] ={//gezsen anadoluyu
	DO,FA,MI,FA,MI,FA,SOL,RE,0,
	DO,FA,MI,FA,MI,DO,RE,0,
	DO,DO,FA,FA,MI,FA,SOL,RE,0,
	DO,FA,MI,FA,MI,DO,RE,0,
	SOL,LA,FA,SOL,LA,SOL,LA,FA,SOL,0,
	FA,SOL,MI,FA,SOL,FA,SOL,MI,FA,0,
	FA,MI,RE,DO,MI,FA,SOL,RE,0,
	DO,FA,MI,FA,MI,DO,RE,0,
	DO_I,DO_I,SI,DO_I,SI,DO_I,LA,0,
	SOL,LA,SOL,DO_I,LA,SI_b,SOL,0,
	SOL,FA,SOL,LA,0,
	FA,SOL,MI,MI,FA,RE,0,
	DO,FA,MI,FA,MI,DO,RE,0,
	DO,FA,MI,FA,MI,DO,RE,0
};
const PROGMEM uint16_t GEZSEN_vur[115] ={
	500,125,125,250,125,125,250,500,125,
	250,250,125,125,125,125,1000,125,
	250,250,250,250,125,125,250,500,125,
	250,250,125,125,125,125,1000,125,
	250,250,250,250,125,125,125,125,500,125,
	250,250,250,250,125,125,125,125,500,125,
	125,375,250,250,125,125,250,500,125,
	250,250,125,125,125,125,1000,125,
	250,250,125,375,375,125,500,125,
	250,250,250,250,375,125,500,125,
	1500,125,125,250,125,
	375,125,500,375,125,500,125,
	250,250,125,125,125,125,1000,125,
	500,500,250,250,250,250,1500,750
};
const PROGMEM uint16_t IZMIR[124]={//izmir marşı
	RE,LA,LA,LA,LA,LA,LA,SI_b,LA,SOL,SI_b,LA,0,
	RE,LA,LA,LA,LA,LA,LA,SI_b,LA,SOL,SI_b,LA,0,
	LA,I_RE,DO_I,SI_b,LA,SOL,LA,SOL,FA,MI,FA,0,
	FA,LA,SOL,FA,MI,RE,FA,MI,RE,DO_d,RE,0,
	RE,LA,LA,LA,LA,LA,LA,SI_b,LA,SOL,SI_b,LA,0,
	RE,LA,LA,LA,LA,LA,LA,SI_b,LA,SOL,SI_b,LA,0,
	LA,I_RE,DO_I,SI_b,LA,SOL,LA,SOL,FA,MI,FA,0,
	FA,LA,SOL,FA,MI,RE,FA,MI,RE,DO_d,RE,0,
	LA,I_RE,DO_I,SI_b,LA,SOL,LA,SOL,FA,MI,FA,0,
	FA,LA,SOL,FA,MI,RE,FA,MI,RE,DO_d,RE,0,
	
	
};
const PROGMEM uint16_t IZMIR_vur[124]={
	500,250,250,250,250,250,250,250,250,250,250,750,250,
	500,250,250,250,250,250,250,250,250,250,250,750,250,
	500,500,250,250,250,250,250,250,250,250,750,250,
	500,500,250,250,250,250,250,250,250,250,750,250,
	500,250,250,250,250,250,250,250,250,250,250,750,250,
	500,250,250,250,250,250,250,250,250,250,250,750,250,
	500,500,250,250,250,250,250,250,250,250,750,250,
	500,500,250,250,250,250,250,250,250,250,750,250,
	500,500,250,250,250,250,250,250,250,250,750,250,
	500,500,250,250,250,250,250,250,250,250,750,250,
};
const PROGMEM uint16_t CAVBELLA[67]={
	MI,LA,SI,DO_I,LA,0,
	MI,LA,SI,DO_I,LA,0,
	MI,LA,SI,DO_I,SI,LA,DO_I,//doI
	SI,LA,I_MI,I_MI,I_MI,0,
	I_MI,I_RE,I_MI,I_FA,I_FA,0,
	I_FA,I_MI,I_RE,I_FA,I_MI,0,
	I_MI,I_RE,DO_I,SI,I_MI,DO_I,//do
	I_RE,I_MI,0,
	LA,
	I_RE,I_MI,I_FA,I_FA,0,
	I_FA,I_MI,I_RE,I_FA,I_MI,0,
	I_MI,I_RE,DO_I,SI,I_MI,DO_I,//do
	SI,LA,0,
};
const PROGMEM uint16_t CAVBELLA_vur[67]={
	250,250,250,250,1000,125,
	250,250,250,250,1000,125,
	250,250,250,500,250,250,500,//doI
	250,250,500,500,250,125,
	250,250,250,250,1000,125,
	250,250,250,250,1000,125,
	250,250,250,500,500,500,//do
	500,1000,250,
	250,
	250,250,250,1000,125,
	250,250,250,250,1000,125,
	250,250,250,500,500,500,//do
	500,1000,750,
};
const PROGMEM uint16_t babyshark_nota[170]={
	RE,MI_b,0,
	RE,MI_b,0,
	RE,MI_b,0,
	RE,MI_b,0,
	RE,MI_b,0,
	RE,MI_b,0,
	RE,MI_b,0,
	RE,MI_b,0,
	SOL,FA,SOL,LA_b,SOL,FA,RE,FA,
	SOL,FA,SOL,LA_b,SOL,FA,RE,FA,
	SOL,FA,SOL,LA_b,SOL,FA,MI,SOL,
	RE,0,
	I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_FA_d,0,
	I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_FA_d,0,
	I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_FA_d,0,
	I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_RE,I_MI,
	I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_SOL,I_FA_d,0,
};
const PROGMEM uint16_t babyshark_vur[170]={
	1000,125,875,
	1000,125,875,
	500,125,375,
	500,125,375,
	250,125,125,
	250,125,125,
	250,125,125,
	250,125,125,
	250,250,250,250,250,250,250,250,
	250,250,250,250,250,250,250,250,
	250,250,250,250,250,250,250,250,
	250,750,
	500,500,
	250,250,250,125,250,125,250,250,
	250,250,250,125,250,125,250,250,250,
	250,250,250,125,250,125,250,250,250,250,750,
	500,500,
	250,250,250,125,250,125,250,250,
	250,250,250,125,250,125,250,250,250,
	250,250,250,125,250,125,250,250,250,250,750,
	500,500,
	250,250,250,125,250,125,250,250,
	250,250,250,125,250,125,250,250,250,
	250,250,250,125,250,125,250,250,250,250,750,
	500,500,
	250,250,250,125,250,125,250,250,
	250,250,250,125,250,125,250,250,250,
	250,250,250,125,250,125,250,250,250,250,1750,
};
const PROGMEM uint16_t starwars[73]={
	SOL,SOL,SOL,MI_b,SI_b,
	SOL,MI_b,SI_b,SOL,0,
	I_RE,I_RE,I_RE,I_MI_b,SI_b,
	SOL_b,MI_b,SI_b,SOL,
	I_SOL,SOL,SOL,I_SOL,I_SOL_b,I_FA,
	I_MI,I_RE_d,I_MI,0,SOL_d,I_DO_d,DO_I,SI,
	SI_b,LA,SI_b,0,MI_b,SOL_b,MI_b,SOL_b,
	SI_b,SOL,SI_b,RE,0,
	I_SOL,SOL,SOL,I_SOL,I_SOL_b,I_FA,
	I_MI,I_RE_d,I_MI,0,SOL_d,I_DO_d,DO_I,SI,
	SI_b,LA,SI_b,0,MI_b,SOL,MI_b,SI_b,
	SOL,MI_b,SI_b,SOL,0,
	
};
const PROGMEM uint16_t starwars_vur[73]={
	500,500,500,375,125,
	500,375,125,1000,125,
	500,500,500,250,125,
	500,375,125,1000,
	500,375,125,500,375,125,
	125,125,250,250,250,500,375,125,
	125,125,250,250,250,500,375,125,
	500,375,125,1000,125,
	500,375,125,500,375,125,
	125,125,250,250,250,500,375,125,
	125,125,500,250,250,500,375,125,
	500,375,125,1000,750,
	
};
const PROGMEM uint16_t  cember[43]={//çemberimde gül oya
	MI,MI,MI,SOL,SOL,FA,MI,
	DO_I,DO_I,DO_I,DO_I,SI,LA,SI,LA,
	SOL,0,
	SOL,SOL,DO_I,DO_I,SI,LA,DO_I,DO_I,
	SI,SI,LA,SOL,SI,SI,SI,LA,SOL,
	LA,LA,DO_I,SI,LA,SOL,FA,
	MI,0,
};
const PROGMEM uint16_t  cember_vur[43]={
	250,250,250,250,250,250,750,
	375,125,250,250,250,250,500,250,
	1000,125,
	250,250,250,250,250,250,250,500,
	250,250,250,250,250,250,250,250,250,
	500,250,250,250,250,500,250,
	1000,750,
};
const PROGMEM uint16_t  panther[93]={
	RE_d,
	MI,0,FA_d,SOL,0,RE_d,
	MI,FA_d,SOL,DO_I,SI,MI,SOL,SI,
	SI_b,/*SI_b*/LA,SOL,MI,RE,MI,
	/*MI*/0,0,RE_d,
	MI,0,FA_d,SOL,0,RE_d,
	MI,FA_d,SOL,DO_I,SI,SOL,SI,I_MI,
	I_MI_b,/*I_MI_b*/0,RE_d,
	MI,0,FA_d,SOL,0,RE_d,
	MI,FA_d,SOL,DO_I,SI,MI,SOL,SI,
	SI_b,/*SI_b*/LA,SOL,MI,RE,MI
	/*MI*/,0,
	0,I_MI,I_RE,SI,LA,SOL,MI,
	SI_b,LA,SI_b,LA,SI_b,LA,SI_b,LA,
	SOL,MI,RE,MI,MI,/*MI*/
	SOL,MI,RE,MI,MI,/*MI*/
	SOL,MI,RE,MI,MI,/*MI*//*MI*/0,
	
};
const PROGMEM uint16_t  panther_vur[93]={
	125,
	500,375,125,500,375,125,
	375,125,375,125,375,125,375,125,
	1250,/*SI_b*/250,250,250,250,1250,
	/*MI*/500,375,125,
	500,375,125,500,375,125,
	375,125,375,125,375,125,375,125,
	3500,/*I_MI_b*/375,125,
	500,375,125,500,375,125,
	375,125,375,125,375,125,375,125,
	1250,/*SI_b*/250,250,250,250,1750
	/*MI*/,500,
	500,375,125,375,125,375,125,
	125,375,125,375,125,375,125,375,
	250,250,250,250,1250,/*MI*/
	250,250,250,250,1250,/*MI*/
	250,250,250,250,3250,/*MI*//*MI*/750,
	
};
const PROGMEM uint16_t  alibaba[38]={
	DO,
	FA,FA,FA,LA,
	SOL,FA,MI,FA,SOL,
	SOL,SOL,SOL,SI_b,
	LA,SOL,FA,SOL,LA,
	DO_I,0,DO_I,0,
	I_RE,DO_I,SI_b,LA,SI_b,
	SI_b,LA,SOL,FA,SOL,DO_I,
	LA,SOL,FA,0,
};
const PROGMEM uint16_t  alibaba_vur[38]={
	250,
	500,500,500,500,
	250,250,250,250,1000,
	500,500,500,500,
	250,250,250,250,1000,
	500,500,500,500,
	250,250,250,250,1000,
	250,250,250,250,500,500,
	500,500,750,750,
};
const PROGMEM uint16_t  benim[31]={//benim annem
	DO,RE,
	MI,MI,MI,FA,
	MI,RE,RE,MI,
	FA,LA,SOL,FA,
	MI,SOL,FA,
	RE,RE,MI,FA,
	LA,SOL,DO_I,LA,
	SOL,MI,SOL,FA,
	MI,0
};
const PROGMEM uint16_t  benim_vur[31]={//benim annem
	250,250,
	500,500,250,250,
	500,500,250,250,
	750,250,250,250,
	1000,250,250,
	500,500,250,250,
	500,500,250,250,
	500,500,250,250,
	1000,750
};
const PROGMEM uint16_t  istiklal[62]={//İstiklal marşı
	SI,
	MI,FA_d,SOL,RE_d,FA_d,
	MI,MI,
	LA,SI,DO,SI,SOL_d,SI,
	LA,SI,LA_d,SI,
	FA_d,FA_d/*FA_d*/,LA,SOL,RE_d,
	MI,FA_d,SOL,LA,SI,DO,RE,MI,
	RE,0,RE,DO_d,RE,SI,LA,
	SOL,SI,LA_d,SI,
	FA_d,SI,SI,LA,SOL,FA_d,SOL,
	MI,MI/*MI*/,RE,DO,SI,
	LA,SOL,FA_d,MI,SI,SI,
	MI,0,
};
const PROGMEM uint16_t  istiklal_oktav[62]={//İstiklal marşı
	-1,
	0,0,0,0,0,
	0,0,
	0,0,1,0,0,0,
	0,0,0,0,
	0,0/*FA_d*/,0,0,0,
	0,0,0,0,0,1,1,1,
	1,0,0,0,0,0,0,
	0,-1,-1,-1,
	0,-1,0,0,0,0,0,
	0,1/*MI*/,1,1,0,
	0,0,0,0,0,-1,
	0,0,
};
const PROGMEM uint16_t  istiklal_vur[62]={//İstiklal marşı
	500,
	500,500,500,375,125,
	1500,500,
	500,500,375,125,375,125,
	1500,250,250,250,
	500,875/*FA_d*/,125,375,125,
	375,125,375,125,375,125,375,125,
	500,125,250,250,250,500,500,
	1500,250,250,250,
	500,500,375,125,250,250,250,
	500,875/*MI*/,125,375,125,
	375,125,375,125,500,500,
	1500,1000,
};
const PROGMEM uint16_t  erikdali[89]={
	0,SI,SI,SI,SI,SI,DO_I,SI,LA,SI,LA,
	0,SI,SI,SI,SI,SI,DO_I,SI,LA,SI,LA,
	LA,LA,0,LA,SI,SOL,FA,MI,SOL,
	LA,LA,0,LA,SI,SOL,FA,MI,
	MI,SOL,LA,SOL,LA,SOL,LA,SI,SOL,FA,MI,SOL,
	LA,SOL,LA,SOL,LA,SOL,LA,SI,SOL,SOL,FA,MI,0,
	MI,SOL,LA,SOL,LA,SOL,LA,SI,SOL,FA,MI,SOL,
	LA,SOL,LA,SOL,LA,SOL,LA,SI,SOL,SOL,FA,MI,0
};
const PROGMEM uint16_t  erikdali_vur[89]={
	250,125,125,250,250,125,125,125,125,250,250,
	250,125,125,250,250,125,125,125,125,250,250,
	250,250,250,125,125,375,125,250,250,
	250,250,250,125,125,375,125,500,
	125,125,125,125,125,125,125,125,375,125,250,250,
	125,125,125,125,125,125,125,125,125,375,125,500,125,
	125,125,125,125,125,125,125,125,375,125,250,250,
	125,125,125,125,125,125,125,125,125,375,125,500,750
};
const PROGMEM uint16_t  dugme[54]={//kol düğmeleri
	MI,FA_d,SOL,
	SI,
	0,I_RE,DO_I,
	SI,DO_I,SI,LA,SI/*SI*/,
	0,MI,FA_d,SOL,
	SI,
	0,I_MI,I_RE,DO_I,
	SI,DO_I,SI,LA,SI/*SI*/,
	0,SOL,LA,SI,
	DO_I,SI,
	LA,DO_I,SI,LA,
	SI/*SI*/,LA,
	SOL,SOL,DO_I,SI,
	LA/*LA*/,SOL,
	LA,LA,I_RE,DO_I,
	SI,DO_I,SI,LA,SI/*SI*/,0
	
};
const PROGMEM uint16_t  dugme_vur[54]={//kol düğmeleri
	250,250,250,
	1500,
	750,500,250,
	62,62,62,62,1250/*SI*/,
	750,250,250,250,
	1500,
	750,250,250,250,
	62,62,62,62,1250/*SI*/,
	750,250,250,250,
	1250,250,
	750,250,250,250,
	1250/*SI*/,250,
	750,250,250,250,
	1250/*LA*/,250,
	750,250,250,250,
	62,62,62,62,1250/*SI*/,125
	
};
const PROGMEM uint16_t  bluey[88]={
	LA,SOL,FA,MI,0,DO,RE/*RE*/,
	FA,0,DO,RE,DO,0,
	LA,SOL,FA,MI,0,DO,RE/*RE*/,
	FA,0,
	LA,SOL,FA,MI,0,DO,RE/*RE*/,
	FA,0,DO,RE,DO,0,
	LA,SOL,FA,MI,0,DO,RE/*RE*/,
	FA,0,
	I_LA,I_SOL,I_FA,I_MI,0,DO_I,I_RE/*I_RE*/,
	I_FA,0,DO_I,I_RE,DO_I,0,
	I_LA,I_SOL,I_FA,I_MI,0,DO_I,I_RE/*I_RE*/,
	I_FA,0,
	I_LA,I_SOL,I_FA,I_MI,0,DO_I,I_RE/*I_RE*/,
	I_FA,0,DO_I,I_RE,DO_I,0,
	I_LA,I_SOL,I_FA,I_MI,0,DO_I,I_RE/*I_RE*/,
	I_FA,0,
	
};
const PROGMEM uint16_t  bluey_vur[88]={
	250,250,250,250,250,500,750/*RE*/,
	250,250,250,250,250,250,
	250,250,250,250,250,500,750/*RE*/,
	250,1250,
	250,250,250,250,250,500,750/*RE*/,
	250,250,250,250,250,250,
	250,250,250,250,250,500,750/*RE*/,
	250,1250,
	250,250,250,250,250,500,750/*I_RE*/,
	250,250,250,250,250,250,
	250,250,250,250,250,500,750/*I_RE*/,
	250,1250,
	250,250,250,250,250,500,750/*I_RE*/,
	250,250,250,250,250,250,
	250,250,250,250,250,500,750/*I_RE*/,
	250,1250,
	
};

ISR(TIMER1_COMPA_vect){
	if (kesme_sayac<=nota_sayac){
			if (sus!=1){
				NOTA_PIN_T;//pin toggle
			}
			kesme_sayac++;
		}else{
			nota_bitti=1;
			kesme_sayac=0;
			TCCR1B&=~(1<<CS11);//timer1 durdu
			NOTA_PIN_H;//sonraki toggle işlemine high olarak başlar
			sus=0;
	}
}
int main(void){
	NOTA_OUT;
	NOTA_PIN_H;
	timer1_init();
	nota_cal(DO,8,1);
	_delay_ms(500);
	while (1){
		for (uint8_t i=0;i<62;i++){
		nota_cal(pgm_read_word_near(istiklal+i),pgm_read_word_near(istiklal_oktav+i)+4,pgm_read_word_near(istiklal_vur+i));
		_delay_ms(10);
		}
		for (uint8_t i=0;i<124;i++){
		nota_cal(pgm_read_word_near(IZMIR+i),4,pgm_read_word_near(IZMIR_vur+i));
		_delay_ms(10);
		}
		for (uint8_t i=0;i<54;i++){
		nota_cal(pgm_read_word_near(dugme+i),3,pgm_read_word_near(dugme_vur+i));
		_delay_ms(10);
		}
		for (uint8_t i=0;i<43;i++){
		nota_cal(pgm_read_word_near(cember+i),4,pgm_read_word_near(cember_vur+i));
		_delay_ms(10);
		}		
		for (uint8_t i=0;i<115;i++){
		nota_cal(pgm_read_word_near(GEZSEN+i),4,pgm_read_word_near(GEZSEN_vur+i));
		_delay_ms(30);
		}
		for (uint8_t i=0;i<67;i++){
		nota_cal(pgm_read_word_near(CAVBELLA+i),4,pgm_read_word_near(CAVBELLA_vur+i));
		_delay_ms(30);
		}
		for (uint8_t i=0;i<89;i++){
		nota_cal(pgm_read_word_near(erikdali+i),4,pgm_read_word_near(erikdali_vur+i));
		_delay_ms(10);
		}
		for (uint8_t i=0;i<73;i++){
		nota_cal(pgm_read_word_near(starwars+i),3,pgm_read_word_near(starwars_vur+i));
		_delay_ms(10);
		}
		for (uint8_t i=0;i<93;i++){
		nota_cal(pgm_read_word_near(panther+i),4,pgm_read_word_near(panther_vur+i));
		_delay_ms(10);
		}
		for (uint8_t i=0;i<31;i++){
		nota_cal(pgm_read_word_near(benim+i),4,pgm_read_word_near(benim_vur+i));
		_delay_ms(10);
		}
		for (uint8_t i=0;i<32;i++){
		nota_cal(YASASIN[i],5,500);
		_delay_ms(10);
		}
		for (uint8_t i=0;i<38;i++){
		nota_cal(pgm_read_word_near(alibaba+i),4,pgm_read_word_near(alibaba_vur+i));
		_delay_ms(10);
		}
		for (uint8_t i=0;i<170;i++){
			nota_cal(pgm_read_word_near(babyshark_nota+i),4,pgm_read_word_near(babyshark_vur+i));
			_delay_ms(10);
		}
		for (uint8_t i=0;i<88;i++){
			nota_cal(pgm_read_word_near(bluey+i),4,pgm_read_word_near(bluey_vur+i));
			_delay_ms(10);
		}		
	}
}
void timer1_init(){
	cli();
	TCCR1B|=(1<<WGM12)|(1<<CS11);//ctc, pre 8
	TIMSK1|=(1<<OCIE1A);
	sei();
}
void nota_cal(uint16_t nota,uint8_t oktav, uint32_t vurus){	
	nota>>=oktav;//oktava göre ocr belirleniyor	
	if (nota!=0){
//Sayaç= istenen süre(vuruş)*((2*1000)/OCR1A) ms olarak istenen sürede oluşması gereken kesme sayısını verir
		nota_sayac=(vurus*2000)/nota;
		onceki_nota=nota;// önceki notanın değeri
		OCR1A=nota;//kesme aralığı
	}else{
		sus=1;
		nota_sayac=(vurus*2000)/onceki_nota;// es süresi
		OCR1A=onceki_nota;	//kesme aralığı önceki notaya göre aldım
	}
	TCCR1B|=(1<<CS11);//timer açıldı	
	while (nota_bitti==0);//nota bitene kadar bekler
	nota_bitti=0;	
}

 

 

 

 

 

Hiç yorum yok:

Yorum Gönder