Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

48
Bölüm 3: Propeller rehberi Propeller “El Kitabı59 Bölüm 3: Propeller rehberi Nesne tabanlı diller de dahil, programlamanın temel kavramlarını bildiğinizi varsayıyoruz. Her ne kadar temel noktaları sunuyor olsak da, programlama deneyiminiz yoksa bu bölümde anlatılanlardan umduğunuz yararı sağlayamazsınız. Ayrıca Bölüm 1 ve 2'yi okumuş olmanız gerekir. Bölüm 1'e göz gezdirmiş olmayı yeterli görebilirsiniz ama bu bölüme başlamadan önce Bölüm 2'yi muhakkak bitirin. İlk iki bölüme değinmekle geçeceğimiz bu bölümde, tüm kavramların adım adım ortaya konulduğu bir kurgu içinde Propeller çipinin programlanmasını anlatacağız. Bölümü başından sonuna atlamadan okumanızı öneririz. Tabii okurken PC ve çiple çalışacağınızı unutmayın. Örnekler ve alıştırmalar önemlidir! İlk alıştırmalar temel, sonrakiler de ileri kavramlara yöneliktir. Kavram Kavram Kavram Kavram Donanım, sistem ve yazılımdan oluşan Propeller'ın tasarımı, hem bilinen sınanmış hem de yeni geliştirilmiş fikirlere dayanır. Donanım, sistem, yazılım ve kullanılan iki dilden (Spin ve Assembly) oluşan tüm bileşenlerinin ayrı ayrı sıfırdan tasarlanmasıyla ortaya çıkan Propeller, kullanıcıya en etkili kontrolü sağlamak amacıyla geliştirilmiştir. Bütün bu bileşenlere iyi hakim olmak için en doğru yolun kalıplara sıkışık kalmamaktan geçtiğini düşünüyoruz. Dolayısıyla programlamayla ilgili alışkanlıklarınızın hem çip hem de dilleriyle ilgili olanakları gölgelemesine izin vermemek konusunda dikkati elden bırakmayın. Çünkü bazı alışkanlıkların hakiki olay-zamanlı (real-time) süreçlerde işleri karıştırmaktan başka faydaları yoktur. Propeller dilleri Propeller dilleri Propeller dilleri Propeller dilleri (Spin ve Propeller Assembly) Propeller çipinde iki dil kullanılır. Biri, nesne tabanlı yüksek düzey dil olan Spin'dir. Diğeri de optimize edilmiş düşük düzeyli Propeller Assembly (asembli)'dir. Asemblideki donanıma yönelik çok sayıda komutun eşdeğer karşılıkları Spin'de de vardır. Bu da çip üzerindeki hakimiyeti artırır. Spin programlar Tool yazılımıyla,

Transcript of Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Page 1: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

59

Bölüm 3:

Propeller rehberi Nesne tabanlı diller de dahil, programlamanın temel kavramlarını bildiğinizi varsayıyoruz. Her ne kadar temel noktaları sunuyor olsak da, programlama deneyiminiz yoksa bu bölümde anlatılanlardan umduğunuz yararı sağlayamazsınız. Ayrıca Bölüm 1 ve 2'yi okumuş olmanız gerekir. Bölüm 1'e göz gezdirmiş olmayı yeterli görebilirsiniz ama bu bölüme başlamadan önce Bölüm 2'yi muhakkak bitirin. İlk iki bölüme değinmekle geçeceğimiz bu bölümde, tüm kavramların adım adım ortaya konulduğu bir kurgu içinde Propeller çipinin programlanmasını anlatacağız. Bölümü başından sonuna atlamadan okumanızı öneririz. Tabii okurken PC ve çiple çalışacağınızı unutmayın. Örnekler ve alıştırmalar önemlidir! İlk alıştırmalar temel, sonrakiler de ileri kavramlara yöneliktir.

KavramKavramKavramKavram

Donanım, sistem ve yazılımdan oluşan Propeller'ın tasarımı, hem bilinen sınanmış hem de yeni geliştirilmiş fikirlere dayanır. Donanım, sistem, yazılım ve kullanılan iki dilden (Spin ve Assembly) oluşan tüm bileşenlerinin ayrı ayrı sıfırdan tasarlanmasıyla ortaya çıkan Propeller, kullanıcıya en etkili kontrolü sağlamak amacıyla geliştirilmiştir. Bütün bu bileşenlere iyi hakim olmak için en doğru yolun kalıplara sıkışık kalmamaktan geçtiğini düşünüyoruz. Dolayısıyla programlamayla ilgili alışkanlıklarınızın hem çip hem de dilleriyle ilgili olanakları gölgelemesine izin vermemek konusunda dikkati elden bırakmayın. Çünkü bazı alışkanlıkların hakiki olay-zamanlı (real-time) süreçlerde işleri karıştırmaktan başka faydaları yoktur.

Propeller dilleri Propeller dilleri Propeller dilleri Propeller dilleri (Spin ve Propeller Assembly)

Propeller çipinde iki dil kullanılır. Biri, nesne tabanlı yüksek düzey dil olan Spin'dir. Diğeri de optimize edilmiş düşük düzeyli Propeller Assembly (asembli)'dir. Asemblideki donanıma yönelik çok sayıda komutun eşdeğer karşılıkları Spin'de de vardır. Bu da çip üzerindeki hakimiyeti artırır. Spin programlar Tool yazılımıyla,

Page 2: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

60

çipteki Spin Interpreter'in olay-anında yorumladığı paketler halinde derlenir. Programlama deneyimi olanlar, Spin'in kolay öğrenildiğini söylemektedir. Spin ile yükzek düzey dar-bant süreçler yanında, geniş-bant 19200 baud hızında asenkron seri haberleşme süreçleri için de kod geliştirebilirsiniz. Asemblinin makine koduna çevrimi Tool tarafından olay-anında halledilir. Asembliyle yazanlar Propeller Assembly'nin yapısından ve geniş-bant işlerde sağladığı kod tasarrufundan memnun kalacaklardır. Propeller nesnelerini sadece Spin ile veya Spin-asembli birleşimiyle ya da sırf asembli ile oluşturmak mümkün olmakla birlikte, uygulamayı son halinde çalıştırmak için en az iki Spin satırına ihtiyaç vardır.

Propeller nesneleriPropeller nesneleriPropeller nesneleriPropeller nesneleri

Nesne tabanlı bir dil olan Spin bütün Propeller uygulamalarının temelinde yer alır.

Nesne (obje) nedir?

Nesne, belli bir işi görmek ve çeşitli uygulamalarda kullanılmak üzere yazılmış, bağımsız ve ayrı bir programdır (modüldür). Örneğin Keyboard (klavye) ve Mouse (fare), Tool yazılımının nesneleridir. Çip ile PC klavyesi arasındaki bağı Keyboard nesnesi/programı kurar. Mouse da böyledir. Her ikisi de programcılarla nesneler arasında ilişki kuran yazılımsal arabirimlerdir. Hazır objeler karmaşık tasarımlarda işi kolaylaştırırlar. Meselâ Keyboard ve Mouse bir kaç ilâve satır ile standart bir kullanıcı arabirimi haline getirilebilir. Objeler bağımsız oldukları için, nasıl çalıştıklarının tasarımcı tarafından bilinmeleri gerekmez. Yani tasarımcı motorun nasıl çalıştığını bilmeyen bir şöför gibidir. Hakkı verilerek yazılmış nesneler çeşitli uygulamalarda çeşitli tasarımcılar tarafından sorunsuzca kullanılabilir.

Nesneler ve uygulamalarNesneler ve uygulamalarNesneler ve uygulamalarNesneler ve uygulamalar

Propeller'deki bir obje Spin -ve gerek görülmüş ise asembli- kodundan oluşur. (Bakınız Şekil 3.1).

Nesneler bilgisayarda .spin uzantılı dosyalar halindedir. (Şekil 3.2). Yani, her nesne bir dosyadır. Nesneleri uygulamaların yapı taşları olarak görmek mümkündür.

Bir uygulamada çeşitli objeler başka objelerin bir araya getirilmesiyle oluşturulabilir. Kullanılan objelere "referans" veya "içerilen" objeler de denilmektedir.

Başka nesneleri referans alan (içeren) bir nesne şef nesnedir, yani referans nesnelerin üstüdür (Şekil 3.3). Üst objenin dosyası "Top Object File" olarak anılır ve uygulamanın derlenmesine bu dosyadan başlanır.

Page 3: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

61

Şekil 3.1 : Bir Propeller objesi.

Şekil 3.2 : .spin uzantılı nesne dosyaları ayrıca asembli kod da içerebilir.

Page 4: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

62

Şekil 3.3 : Nesne hiyerarşisi. Derleme diğer nesneleri içeren Graphics Demo'dan başlar.

Şekildeki TV, Graphics ve Mouse adlı nesneler Graphics Demo adlı nesnenin referanslarıdır. Graphics Demo derlendiğinde üst (veya şef) dosya olarak görülür. Bu da, önceki üç nesnenin yüklenip derlendikten sonra sonuçta ortaya çıkacak olan Propeller uygulamasında yer alacakları anlamına gelir. Bir uygulamada bir ya da fazla sayıda obje olabilir. Bir uygulama çip tarafından çalıştırılacak şekilde derlenmiş icra görecek koddan ve verilerden oluşur. Çipe yüklendiğinde esas geçici bellekte durur, ayrıca istenirse harici bir EEPROM'a da yüklenebilir. Uygulamanın icrası çipteki işlemciler tarafından, kontrolü ise bizzat uygulamanın kendisi tarafından yürütülür. Çipteki işlemcilere "cog" diyoruz.

Çipe yüklemek için bağlantı

Bir uygulamayı PC'den yüklemek için önce çipin bağlantısı doğru yapılmalıdır:

� Elinizdeki C yahut D tipi bir Propeller Demo Board'u (PDBc/d) çiple birlikte elemanları da içerir. Fişi ve PC'nin USB kablosunu takıp PDB'yi açın. USB sürücüleri PDB'nin kılavuzundaki tarife göre kurulmuş olmalıdır.

Page 5: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

63

Şekil 3.4 : Çipe yükleme. Uygulamalar çipin RAM'ına veyahut istenirse bir EEPROM'a yüklenen çeşitli nesnelerden oluşur.

� Ancak elinizde PBD olmadan da Propeller ile çalışabilirsniz. Ama bunun için hem bir Propeller çipine hem de prototip imalatı konusunda yeterli deneyime sahip olmanız gerekir. Örnek devre için Kılıf tipleri ve Donanım bağlantıları altında anlatılanlara bakınız. Ayrıca elinizde bir Propeller Plug cihaz varsa, yine USB sürücülerini cihazın kılavuzuna göre kurmanız gerekir. Bundan sonra anlatılanlarda kural olarak PDB'deki devre bağlantıları esas

- VEYA -

Page 6: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

64

alınacaktır. Belirtilen güç ve sinyal bağlantılarına ek olarak elinizdeki prototipte Şekil 3.5'te verilen şemaya uygun devre elemanlarının ve bağlantıların tamamlanması gerekir. Ayrıca Parallax'ın vebsitesinden indirmek kaydıyla PDB şematiğinden de yararlanabilirsiniz.

Şekil 3.5 : Propeller Kılavuz Şematiği

Bağlantılarınız yukarıdakine uygun tamamlandıysa, sıradaki iş, Tool yazılımı yoluyla çipin doğrulanmasıdır: Propeller Tool (Version 1.0) çalıştırılır ve F7 tuşlanır (veya menüden Run → Identify Hardware… seçilir). Çip fişe takılı ve PC'ye de bağlıysa, aşağıdaki gibi bir "Information" kutusu görüntüye gelir.

Şekil 3.6 : Information kutusu. Sizin PC'nizdeki port (yukarıda COM5) farklı olabilir.

Hızlı bakış: Intro

� Propeller çipi ya Spin ya da Asembli ile programlanır: o Spin nesne tabanlı, yüksek düzey dildir. Olay-anında yorumlanır. o Asembli optimize, düşük düzey dildir. Olay anında icra edilir.

� Nesneler: o Bağımsız programlardır; o Belli bir işi görürler;

Page 7: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

65

o Farklı uygulamalarda çalışabilirler. � İyi hazırlanmış objeler farklı kullanıcılar ve uygulamalarca kolaylıkla

kullanılabilirler: o En az iki Spin kod satırından oluşmak zorundadırlar. Başka Spin

satırlar ve asembli kodun varlığı tasarımın gereklerine ve tasarımcının tercihlerine bağlıdır.

o Bilgisayarda ".spin" uzantılı olarak kaydedilirler; o Uygulamanın gereğine göre başka nesnelerle bir araya getirilebilirler.

� Propeller uygulamaları: o Bir veya daha fazla obje içerebilirler; o İcra edilecek kodu ve verileri içeren binary gövde olarak derlenirler; o Uygulamanın denetiminde en az bir cog (işlemci) tarafından

çalıştırılırlar. � Uygulamanın en tepesindeki nesneye şef dosya (Top Object File) denilir.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----1 :1 :1 :1 : İlk obje

İlk obje çok basittir. Spin ile yazılmıştır. Bir I/O pinini lojik-1 ve lojik-0 arasında çevirir. Tool'u açıp aşağıdaki satırları editöre yazarken PUB satırının edit panosunda en soldan, yani birinci sütundan başlamasına dikkat edin. Ayrıca her satırın sol hizasına özellikle dikkat edin: YOKSA program çalışmaz!

PUB Toggle dira[16]~~ repeat !outa[16] waitcnt(3_000_000 + cnt)

Her satırın sol hizasının nerede olduğu son derece kritiktir. Oysa harfler büyük veya küçük olabilir. Propeller kodunda büyük/küçük harf kullanılmasının sonuç üzerinde etkisi yoktur. Bununla birlikte "fotoğraf" olarak kitaba alınan kodlardaki rezerve terimler kalın yazılmış görünecektir. Yazımın doğruluğundan eminseniz F10 tuşlayın veya menüden Run → Compile Current → Load RAM + Run tıklayın. Editöre yazdığınız satırlarda sentaks hatası yoksa, güç ve sinyal bağlantıları da doğruysa karşınıza Şekil 3.7'deki "Propeller Communication" kutusu çıkar. Ayrıca çipin 16. I/O pinindeki LED de saniyede iki kere yanıp sönüyor olmalıdır. Burada başarmış oluğumuz şey, Şekil 3.4'ün üst kısmında görünmektedir.

Şekil 3.7 : Propeller iletişim kutusu

Page 8: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

66

Her şeyin o kadar hızlı olmasının sebebi, girdiğimiz programın küçüklüğüdür. F10'a basıldığında kaynak kodu Propeller Tool tarafından derlenir ve sonra uygulamaya geri dönülür. Ardından, çip takılıysa uygulama RAM'a yüklenir ve buradan çalıştırılır. Bu sırada 16. I/O pini yanıp sönmeye başlar.

Yükleme nereye yapılmalı: RAM'a mı, EEPROM'a mı? Yükleme nereye yapılmalı: RAM'a mı, EEPROM'a mı? Yükleme nereye yapılmalı: RAM'a mı, EEPROM'a mı? Yükleme nereye yapılmalı: RAM'a mı, EEPROM'a mı?

Kod konusuna girmeden yükleme sürecine daha yakından bakalım. Yükleme RAM'a yapıldığında, enerji kesilir veya reset yapılacak olursa, RAM silineceği için program akışı kesilir. Program akışının kesilmemesi için bu kez yüklemeyi F11 (veya menüden Run → Compile Current → Load EEPROM + Run) ile yapalım. Şekil 3.4'de de görüldüğü üzere yükleme önce RAM'a, hemen ardından da harici EEPROM'a yapılır. Program yine RAM'dan çalıştırılır ve pin-16 yanıp söner. Dikkat ettiyseniz, "Propeller Communication" kutusunun daha geç kapandığını fark etmişsinizdir. Çünkü EEPROM'a yükleme RAM'a göre daha uzun sürer. Şimdi reset butonuna basılıp bırakılırsa, LED'in 1.5 saniyelik bir gecikmeden yanıp sönmeye başladığı görülür. Yani program akışı kesilmemiştir!

Çip resetten çıkarken ilk bölümde anlatılan baştan-başlatma prosedürünü yürütür. Bu süreç, harici EEPROM'dan alınan 32K bilginin 1.5 saniyede RAM'a aktarılıp çalıştırılması şeklindedir. Program geliştirilirken EEPROM'a başvurmazsanız bu gecikmeye maruz kalmazsınız. Programı EEPROM'a bir iki kere yükleyip göz geçirdikten sonra sadece RAM'a yükleyerek çalışın. İstediğiniz program EEPROM'da olduğu sürece Propeller çalıştırmayı eski programdan yapar. Ancak durumu aklınızdan çıkarmamanız gerekir, aksi takdirde kafa karıştırabilir. Eğer reset sonrasında istenilmeyen bir durum meydana geliyorsa, önce EEPROM'daki programı inceleyin.

Output.spin hakkında bilgi

PUB Toggle dira[16]~~ repeat !outa[16] waitcnt(3_000_000 + cnt)

İlk satır, "Toggle" (çevir) isimli bir "public" (açık) yöntem oluşturulduğu anlamına gelir. Yöntem, nesne-tabanlı "prosedür" veya "rutin" demektir. "Toggle" terimi yöntemle yapılan işi doğrudan anlattığı için seçilmiştir. PUB terimi daha sonra izah edilecektir. Ama önceden bilinmesi gereken nokta şudur: Her nesnede en az bir PUB yönteminin bulunması şarttır.

Kodun izleyen kısmı TOGGLE ile ilgilidir. İzleyen iki satırın içerde yazılması bu durumu işaret etmek içindir. İçerde yazmak şart değildir ancak anlaşılırlığı artırır.

Page 9: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

67

Programın ikinci satırının işi I/O pini 16'yı çıkış olarak tayin etmektir. DIRA sembolü 0-31 arası I/O pinleri için yön yazmacını ifade eder. [16] ise yazmacın 16. bitini işaret eder. Onu izleyen "~~" sembolü sonuna geldiği biti lojik-1 (yüksek) yapan bir operatördür. Aslında bu satır, aynı anlama gelmek üzere başka dillerdeki ifadeleri andıran bir şekilde de yazılabilirdi: dira[16] := 1. İzleyen repeat, altındaki iki satırdan oluşan sonsuz bir döngü kurar. Döngüdeki !outa[16] ifadesi 16.pini VDD (yüksek) ile VSS (düşük) arasında çevrilmesini sağlar. Terimin OUTA kısmı P0-P31 pinlerinden oluşan A adlı çıkış durumları yazmacını simgeler. [16] da yazmacın ilgili bitini gösterir. Bütün terimin en başındaki « ! » simgesi de bit bazında iş gören NOT operatörüdür. İkinci satırda yer alan waitcnt(3_000_000 + cnt) ifadesi ile 3 milyon saat çevrimine eşit bir bekleme süresi oluşturulur. İlk terim WAITCNT, sistem saatini (sayacını) bekle, anlamına gelir. Terimdeki CNT sistem saatine karşılık gelen yazmacın simgesidir, ki sayacın halihazır değerini çevirir. Dolayısıyla ifadeyi şöyle anlamak en doğrusudur: sistem saatine bak ve 3 milyon artana kadar bekle.

Bu program parçasında çip için her hangi bir saat ayarı yapmadık. Bu durumda çip çalışırken içsel ön-ayarı yaklaşık 12MHz olan bir hızda çalışacaktır. Dolayısıyla 3 milyonluk çevrim de yaklaşık olarak çeyrek saniye gecikme yaratır. Hatırlarsanız, sol kenar ayarı kritiktir, demiştik. İşte sol kenar hizasının önemli olduğu bir durum: Spin dilinde koşul ifadeleri ve diğer döngü komutları, yapıya dahil durumları sol hizalarına bakarak seçer. Döngü başlangıcına göre en az bir boşluk karakteri kadar daha sağda (içerde) kalan satırların döngü yapısına dahil olduğu farz edilir. Bu konuda sıkıntı duyarsanız Block-Group göstergeleri vasıtasıyla inceleyebilirsiniz. Bu göstergeleri açıp kapamak için Ctrl+I anahtarını kullanın (Şekil 3.8).

Şekil 3.8 : Blok-grup göstergeleri. Aç/kapa yapmak için Ctrl+I kullanılır.

Yazdığınız satırları kaydetmek için Ctrl+S tuşlamak (veya menüden File → Save tıklamak) yeterlidir. İzleyen alıştırmalarla uyumlu olması açısından dosyanın ismini output.spin koyun.

Özet: Alıştırma-1

� Uygulamalar ya RAM'a ya da hem RAM'a hem de EEPROM'a yüklenir. o Enerji kesilmesi veya reset yapılması halinde RAM silinir. o Yeniden çalıştırma EEPROM'un içeriğini 1.5 saniyede RAM yükler.

Page 10: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

68

o Nesneyi RAM'a yüklemek için F10 tuşlayın veya menüden Run → Compile Current → Load RAM + Run tıklayın.

o RAM ve EEPROM'a yüklemek için F11 tuşlayın veya menüden Run → Compile Current → Load EEPROM + Run tıklayın.

� Spin dili: o Metod (yöntem), prosedür veya rutin anlamına gelir. Örneğin PUB

Sembol ifadesi ile sembol adında bir metod deklare edilir. Her nesnede en az bir adet PUB yöntemi olması şarttır.

o DIRA terimi ile 0-31 aralığındaki I/O pinlerini içeren yön yazmacı belirtilir. Bitler giriş olacaksa 0, çıkış olacaksa 1 yapılır.

o Yazmaç bitlerine -[16] gibi- indisler vasıtasıyla erişilir. o Yazmacın/değişkenin peşinden gelen ~~ sembolü, tüm bitleri lojik-1

yapar. (Operatörler başlığına bakınız.) o Başına ! imgesi konulan bir terimin bitleri değillenir (NOT isimli bit

operatörüne bakın). o REPEAT ile döngü, WAITCNT ile gecikme oluşturulur. o Satırların sol kenar hizalarının önemi ait oldukları yapılara göre

değişir. Koşul ve diğer döngü yapılarında kritik olan bu hizalar blok göstergelerinde önem taşımaz. Blok grup yapılarına ait göstergeleri Ctl+I anahtarı ile açıp kapatmak mümkündür.

Coglar Coglar Coglar Coglar (işlemciler)

Propeller 8 tane işlemciye sahiptir. Bunlara COG diyoruz. Bir cogun çalışması diğerlerininkine bağlı değildir: diğerlerinden farklı işler görebileceği gibi belli bir işin yürütülmesine ortak edilmesi de mümkündür. Üstelik bu ortaklık, uygulamanın çalışmasının her hangi bir anında değiştirilebilir.

output.spin ismiyle kaydettiğimiz yukarıdaki kodla ilgili belirtmediğimiz bir husus vardır! İşi görecek olan cog hangisidir? Bunun için Boot-Up ve Run-Time prosedürüyle ilgili başlıklara bakabilirsiniz. Ne var ki burada biraz daha ayrıntıya gireceğiz. Enerji verildiğinde Propeller ilk prosesör olan Cog0'ı işe koşar ve Boot-Loader programını çipteki sabit bellekten (ROM'dan) cogun değişken belleğine (RAM'ına) kopyalar/yükler. Yüklenen program cog0'ın RAM'ından çalıştırılır ve derhal kullanıcı programının harici EEPROM'dan yüklenip yüklenmeyeceğine hükmeder. Hükmettiyse, EEPROM'un 32KB'lik içeriği, çipin 32KB'lik esas değişken belleğine (Main RAM'a -cogun RAM'ından farklıdır) kaydeder. Daha sonra, Boot Loader programı bu kez içinde kurulu Spin Interpreter ile birlikte coga (Cog0'a) yeniden yüklenir. Bu süreçte, yani Spin yorumlayıcısının yüklenmesi sırasında cogda daha önceden yüklenmiş durumda bulunan Boot Loader programının faaliyeti engellenmiş durumdadır.

Page 11: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

69

Şekil 3.9 : Output.spin çalıştırılıyor. Cogun RAM'ına Spin Application (uygulama) değil, Spin Interpreter (yorumlayıcı) yüklenir. Spin uygulaması çipin esas RAM'ındadır ve cogda çalıştırılan Spin Interpreter tarafından yorumlanır.

Cog0 tarafından çalıştırılan Spin Interpreter ana RAM'dan uygulama kodunu alır ve icra eder (Şekil 3.9). Bizim uygulamamız Spin koddan ibarettir. Bu yüzden, yorumlayıcı cog tarafından çalıştırılırken de uygulama ana RAM'da kalır. Uygulamamız ne çalıştırıldığında ne de icra edilirken başka bir cog devreye girer; bu sırada geri kalan bütün coglar akım çekmeden uyku haline devam ederler. Ancak bu şimdilik böyledir. İleride, diğer cogları da uygulamamızda devreye sokacağız.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----2 : 2 : 2 : 2 : Sabitler

Programı bir parça genişletmeyi deneyelim. Örneğin I/O pin numarasını ve gecikme değerini değiştirme işini nasıl kolaylaştıracağımıza bakalım. Mevcut durumda yapılması gereken şey, pin numarasının ve gecikme değerinin geçtikleri yerleri bulmak ve değiştirmektir. Oysa bu işin daha pratik bir yöntemi vardır

CON Pin = 16 Delay = 3_000_000 PUB Toggle dira[Pin]~~ repeat !outa[Pin] waitcnt(Delay + cnt)

Page 12: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

70

Kodun başındaki CON bloğu, nesne için global sabitler tanımlanmasına imkân verir. Örnekte iki sembol vardır. PIN ve DELAY. Bunların değerleri de 16 ve 3 milyon olarak belirlenmiştir. Bundan böyle PIN ve DELAY terimleri, kullanıldıkları her yerde bu değerleri temsil edeceklerdir. 3 milyon yazarken binlik grupları ayırmakta kullanılan işaret düşük tiredir. Okumayı rahatlatmak amacını güden bu işaret yerine virgül kullanılamaz! TOGGLE yönteminde daha önce 16'nın ve 3_000_000'un yazılı olduğu yerlere bu kez PIN ve DELAY yazılmıştır. Derleme sırasında bunlar kullanılan semboller olarak değil, fakat değerleri itibariyle dikkate alınırlar. Bu teknikle pin numarasında veyahut gecikme değerinde değişiklik yapmak çok daha kolaydır. Çünkü kodun en üstüne bakıp sabitlerin değerlerini değiştirmek yeterlidir. Yani kod içinde geçtikleri yerleri aramaya gerek kalmaz. Örneğin gecikme değerini değiştirip sabit sembolünün karşısındaki 3_000_000 yerine 500_000 yazdıktan sonra programı yükleyince LED saniyede 12 kere yanıp sönmeye (24 kez durum değiştirmeye) başlayacaktır. Benzer şekilde bacak değeri de 16 yerine 17 yapılabilir. Bunun sonucunda başka bir LED'in yandığı görülür. (DİKKAT: 18 ile 23 aralığındakileri de deneyebilirsiniz. Fakat bunlar VGA sürücü devresi yüzünden çiftler halinde bağlı oldukları için bir defada 2 LED yanıp sönebilir.)

Blok tanımlarıBlok tanımlarıBlok tanımlarıBlok tanımları

Koddaki CON ve PUB bloklarının editördeki zemin renkleri farklıdır. Bu farklılık işlevsel farklılıklarına işaret eder. Bloklar farklı işlere yöneliktir. Spin kodları bu temelde tasarlanır. CON ve PUB, sırasıyla, sabitler ve public yöntem bloklarının başlangıcında yer alırlar. Bir blok tanımlayıcısı (designator) daima birinci sütundan, yani edit panosunun en sol kenarından başlar. Bu tanımlayıcılar 6 tanedir: CON, VAR, OBJ, PUB, PRI ve DAT. Her birinin işlevi aşağıda kısaca açıklanmıştır.

CON: Global sabitleri içerir. Objenin her hangi bir yerinde (içinde ve bazen de dışında) kullanılacak tüm sabit semboller ve sayısal değerler burada tayin edilir.

VAR: Global değişkenleri kapsar. Burada belirlenen tüm değişkenler nesnenin değişkene izin verilen bütün bölümlerinde kullanılabilir.

OBJ: Referansları tarif eder. Başka nesnelere yönelik referans tanımları burada yapılır. Bu tanımlar başka nesnelere, yöntemlerine ve sabitlerine erişimde kullanılır.

PUB: Açık (genelgeçer) yöntemi kapsar. Açık yöntemler kod rutinleridir. Obje içinden veya dışından erişilebilirler. Nesnenin arayüzü olarak çalışırlar. Nesne dışındaki yöntemler nesneyle etkileşimli çalışırlar. Her nesnede en az bir adet açık (public) bildirim (deklarasyon, tanımlayıcı) yer alır.

PRI: Hususi yöntemi içerir. Bunlar da kod rutinleridir. Ancak sadece obje içinden

Page 13: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

71

erişilebilirler. Dışarıdan görülmezler. Bu sebeple nesneyle ilgili kritik elemanları içerirler. Böylece programın hedefine yönelik bütünlüğü korumaya hizmet ederler.

DAT: Veri deklarasyonu içindir. Veri tabloları, bellek tamponları ve Propeller Assembly kod bu kapsamdadır. Sembolik isimler verilebilen bu bloklara hem Spin hem de Assembly program kanalıyla erişmek mümkündür.

Her deklarasyona istenilen sayıda başvurulabilir. Tek istisna en az bir tane PUB bloğu olmasıdır. Blok sayıları yahut sıraları konusunda bir sınır olmamakla birlikte CON, VAR, OBJ ve DAT blokları birden çok kullanılmazlar ve bu sıraya uygun olarak dizilirler.

Bir Propeller uygulamasında başlangıç, ilk (Top Object File) objenin ilk PUB deklaresidir. Uygulama çalıştığında otomatik olarak önce buradan başlanır ve sadece bu yöntem otomatik olarak icra edilir. Geri kalan açık veya hususi tüm yöntemler vb işte bu ilk yöntem gereksindiği ölçüde icra görürler. Blokların her birinin zemin rengi başkadır. Bu, aynı türden ardışık iki blok için de geçerlidir. Her bloğun kolayca ayırt edilmesini ve böylece kaynak kodunun rahatlıkla izlenmesini sağlayan bu yaklaşım sadece ekran görünümüyle ilgilidir; kodun işleyişini etkilemez. Dolayısıyla, paragrafları ayırmakla uğraşmanıza gerek kalmaz!

AlıştırmaAlıştırmaAlıştırmaAlıştırma----3 : 3 : 3 : 3 : Açıklamalar

Output adlı nesnemiz şimdi biraz daha anlaşılır bir durumdadır. Yine de bazı ekler gerekmektedir. Örneğin kodun işleyişiyle ilgili açıklamalar bunlardandır. Açıklamalar (comments) kod içinde yer alan ancak derleme sırasında yok sayılan metinlerdir. Dört çeşidi vardır:

''''… Tek satır kod-açıklaması. Apostrof ile başlar

''''''''… Tek satır belge-açıklaması. Çift apostrofla başlar (Tırnak « " " " " » kullanmayın).

{{{{…}}}} Çok satırlı kod açıklaması. Küme parantezi içindedir.

{{{{{{{{…}}}}}}}} Çok satırlı belge-açıklaması. Çift küme-parantezi içindedir.

{{Output.spin Toggles Pin with Delay clock cycles of high/low time.}} CON Pin = 16 { I/O pin to toggle on/off } Delay = 3_000_000 { On/Off Delay, in clock cycles} PUB Toggle ''Toggle Pin forever

Page 14: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

72

{Toggles I/O pin given by Pin and waits Delay system clock cycles in between each toggle.} dira[Pin]~~ ' Set I/O pin to output direction repeat ' Repeat following endlessly !outa[Pin] ' Toggle I/O Pin waitcnt(Delay + cnt) ' Wait for Delay cycles

Tek satır açıklamalar en az bir apostrofla başlayarak satırın sonuna kadar yazılabilir. Açıklamanın sağ tarafında kalan kod dikkate alınmaz (derlenmez).

Çok satırlık açıklamalar en az bir küme paranteziyle başlar ve biter. Bu açıklama tekniğinde, açıklamanın sağında kod bulunabilir (derlenir).

Apostrof veya küme parantezi bir «'...'...'...'... ; {...}{...}{...}{...}» adet olduğunda kod-açıklamasından; iki «''...''...''...''... ; {{...}}{{...}}{{...}}{{...}}» adet olduğunda belge açıklamasından söz ediyoruz demektir. Belge açıklamaları, okuma kolaylığı açısından kodu içermeksizin Propeller Tool dışındaki ortamlara da kolayca aktarılabilir. Daha önce belirttiğimiz gibi Propeller Tool'da belge görünümü şeklinde bir olanak vardır. Yukarıdaki program belge ekranında kod satırları yerine kod satırlarının mahiyeti ve belge açıklamalarından ibaret olarak görünür.

Output.spin Toggles Pin with Delay clock cycles of high/low time. Object "Output" Interface: PUB Toggle Program: 8 Longs Variable: 0 Longs ___________ PUB Toggle Toggle Pin forever

Bu satırlar programdaki belge açıklamalarından kaynaklanır. Tool'un otomatik olarak ürettiği «Object "Output" Interface:» bölümünde PUB rutinleri ("Toggle" dışında yok) listelenir. Ayrıca programın büyüklüğü (8 long = 32 bayt) ile kullanılan değişkenler de gösterilir -ki bu programda değişken yoktur. Ardından kullanılan bütün PUB metodlar her seferinde üstüne bir yatay ayırma çizgisi atılmış olarak sırayla listelenir. Bu bölmede Toggle adlı PUB yöntemi ve yöntemin işini ifade eden Toggle Pin Forever şeklindeki son belge açıklaması gösterilmektedir. Belge açıklamalarının koda eklenebilmesi işin tek dosyada halledilmesi sayesinde programcıya büyük kolaylık sağlar. Bu kolaylıklara bir de Parallax'ın şematikler, zamanlama diyagramları, matematik semboller vs karakterler sağlayan fontunu da eklemek gerekir (Şekil 2.1'e bakınız).

Page 15: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

73

Özet: Alıştırma-2 ve -3

� Propeller içinde cog isimli birbiriyle aynı sekiz işlemci yer alır o Uygulamada bunlardan istenilen adedi çalıştırılıp durdurulabilir. o Her cog münferit veya müşterek işlerle görevlendirilebilir. o Baştan çalıştırmada Cog0 Spin yorumlayıcıyı işleterek bellek tabanlı

Spin uygulamasının çalışmasını sağlar. � Spin dili blok yapılıdır:

o CON ile global sabitler; o VAR ile global değişkenler; o OBJ ile nesne referansları; o PUB ile açık rutinler (metodlar); o PRI ile hususi rutinler (metodlar); o DAT ile veriler, tamponlar ve asembli kod tayin edilir. o Blok tanıtıcıları en sol kenardan, 1.kolondan başlarlar. o Her hangi bir blok her hangi bir sayıda ve sırada kullanılabilir. o İlk nesnedeki ilk PUB rutini Propeller uygulamasının başlangıcıdır. o Sabitlerde kullanılan «_ » [düşük tire] sayılardaki binlik gruplarını

belirtmeye yarar. o Açıklama çeşitleri:

� Kod açıklamaları sadece kaynak kodunda yer alır. Tek ya da çok satırlı olabilirler. Tek satırlık açıklamalar « ' » (apostrof) ile başlar ve satır içinde kalırlar. Çok satıra yayılan açıklamalar {…}(küme parantezi) içinde oluşturulurlar.

� Belge açıklamaları hem kaynak kodunda hem de belge görünümünde izlenebilirler. Şematikler, zamanlama diyagramları ve başka özel özel sembollere de açıktırlar. Tek satırlık açıklamalar « ' ' » (çift apostrof ) ile başlar ve satır içindedirler. Çok satıra yayılan açıklamalar {{…}}(çift küme parantezi) içinde oluşturulurlar.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----4 : 4 : 4 : 4 : Parametreler, çağrılar, döngüler

Alıştırma-3'teki obje istenilen özelliklere uygun değildir. Oradaki Toggle metodu başka bir pin ve gecikme söz konusu olduğunda elverişsizdir ve yeterince esnek değildir. Bu durumdan kurtulmak için önce döngüyü sonsuz olmaktan çıkaracağız. Yazdığınız programı aşağıdaki örneğe bakarak yenileyin. Her hangi bir karışıklığı önlemek amacıyla kaldırılması gereken kısımların üstü çizilmiştir.

{{Output.spin Toggles Pin with Delay clock cycles of high/low time.}} Toggles two pins, one after another.}} CON

Page 16: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

74

Pin = 16 { I/O pin to toggle on/off } Delay = 3_000_000 { On/Off Delay, in clock cycles}

PUB Main Toggle(16, 3_000_000, 10) 'Toggle P16 ten times, 1/4 s each Toggle(17, 2_000_000, 20) 'Toggle P17 twenty times, 1/6 s each

PUB Toggle(Pin, Delay, Count) ''Toggle Pin forever {Toggles I/O pin given by Pin and waits Delay system clock cycles in between each toggle.} {{Toggle Pin, Count times with Delay clock cycles in between.}}

dira[Pin]~~ 'Set I/O pin to output direction repeat Count 'Repeat for Count iterations !outa[Pin] 'Toggle I/O Pin waitcnt(Delay + cnt) 'Wait for Delay cycles

Sonuçları görmek üzere uygulamayı derleyin ve yükleyin. P16'daki LED'in 0.25 saniye fasılayla 5 kez yanıp söndükten (10 kere diğer duruma geçtikten) sonra durması ve ardından P17 LED'inin 0.167 saniyelik fasılalarla 10 kere yanıp sönmesi gerekir. Örnekte sabitler bloğu atılmış; Main adlı yeni bir metod eklenirken Toggle metodunda ufak değişikliklere gidilmiştir: Bu rutinde pinde durum-değişim yürütülmekle birlikte, işlemin ne zaman yapılacağı Main metodunda belirlenir.

Toggle metodu (rutini)

Önce Toggle rutinini ele alacağız. Deklare sırasında rutinin adının (Toggle) hemen yanında parantez içinde Pin, Delay ve Count kelimeleri yer almaktadır. Bu terimler Toggle rutininin parametre listesini oluşturur. Bir rutin işe koşulacağı zaman listesindeki sembollere değer atanması gerekir. Bir parametre sembolü, 4 bayt boyunda ve sadece o rutinde geçerli (local, global-olmayan, yerel) -yani metodun dışından erişilme imkânı olmayan- bir değişkeni anlatır. Parametrelerde yapılacak değer değişiklikleri metod dışına yansımaz. Bir metod başka metodlara alet olabilir. Parametrelerinin değeri her seferinde değişebilir. Toggle metodundaki tek değişiklik REPEAT sürecindedir. Burada döngünün tur sayısı bellidir. Oysa bundan önceki alıştırmada aynı döngünün sonu yoktu. Aradaki fark, REPEAT komutunun argümanından, yani COUNT teriminin varlığından kaynaklanır. Döngünün tur sayısı COUNT değeriyle verilir. Dolayısıyla COUNT kaç ise döngü o kadar tur atacak ve duracak; döngü içindeki komutlar da o kadar icra görecektir.

Main metodu

Rutinin ilk satırındaki Toggle(16, 3_000_000, 10) ifadesi metod çağrısıdır. Çağrıyla, Toggle metodunun Pin, Delay ve Count argümanlarına sırayla parantez içindeki değerler aktarılır. Bir sonraki satır da aynı işi yapar. Ama bu kez Pin değeri 17, Delay değeri 2 milyon ve Count değeri de 20 olacaktır.

Page 17: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

75

Main metodu Toggle metodundan önce yer almıştır. Uygulama çalıştırıldığında ilk icra edilecek metod, ilk nesnenin ilk açık metodudur. Dolayısıyla, bu örneğe göre, ilk icra edilecek metod Main metodu olacaktır. Bu örnekte bir obje kullandığımız için, uygulamanın çalışmasının ardından otomatik olarak Main icra edilir. Metodun ilk satırı işlem gördüğünde Toggle metodu çağrılır ve yürütülür. 16'daki LED çeyrek saniyelik fasılalarla 5 kere yanıp söner. Sonra program akışı yine Main metodunun ikinci satırına gelir ve Toggle metodu bu kez farklı değerlerle çalıştırılmak üzere yeniden çağrılır: 17'deki LED saniyenin 1/6'sı aralıklarla 10 kere yanıp söner. Sonra akış yine Main metoduna döner. Fakat başka işlenecek satır kalmadığı için Main'den çıkılır: Uygulama sona erer, cog işlem yapmayı keser, Propeller düşük güç sarfına geçer. Yeniden çalıştırmak için ya reset etmek ya da enerji vermek gerekir.

Propeller, Main ve Toggle metodlarını PUB ile başlayıp bir sonraki blok deklarasyonunun başlamasıyla sona eren farklı rutinler olarak algılar. Yani daha sonraki Toggle rutininin Main rutinine ait olmadığını bilir. Burada bir diğer önemli nokta, sadece bir adet cog kullanılması ve kodun ardışık (seri) olarak -önce P16'nın, sonra P17'nin çalışmasını sağlayacak şekilde- icra edilmesidir. Sonraki alıştırmada cog sayısı birden fazla olacaktır.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----5 : 5 : 5 : 5 : Paralel (koşut) düzenek

İlk dört alıştırmada sadece bir cog kullanılırken işler arka arkaya görülür: Önce P16 çalışır ve durur; sonra da P17. Buna seri düzenek (serial processing) denir. Oysa P16 ve P17'nin arka arkaya çalışmak zorunda kalmaksızın, hatta gerekirse eş-zamanlı ve üstelik farklı fasılalarla ve sürelerle çalışmalarını sağlayacak bir düzenek de kurulabilir. Örneğin P16 ve P17 eş anlı yanıp sönsünler fakat fasılaları ve süreleri farklı olsun diyebiliriz. İşte, seri düzenek üzerinde iyi bir programlamayla ustaca halledilmeyi gerektiren böyle işler, Propeller'in iki coguyla oluşturulacak koşut bir düzenek (parallel processing) sayesinde çok kolay ve esnek bir şekilde çözüme kavuşturulabilir. Bu amaçla kod, bir VAR bloğu eklendikten sonra Main metodunda bazı değişikliklere gidilerek aşağıdaki hale gelmiştir:

{{Output.spin Toggle two pins, one after another simultaneously.}} VAR long Stack[9] 'Stack space for new cog PUB Main cognew(Toggle(16, 3_000_000, 10), @Stack) 'Toggle P16 ten…

Toggle(17, 2_000_000, 20) 'Toggle P17 twenty…

Page 18: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

76

PUB Toggle(Pin, Delay, Count) {{Toggle Pin, Count times with Delay clock cycles in between.}} dira[Pin]~~ ' Set I/O pin to output direction repeat Count ' Repeat for Count iterations !outa[Pin] ' Toggle I/O Pin waitcnt(Delay + cnt) ' Wait for Delay cycles

VAR bloğu

Burada Stack isminde bir long-dizi tanımlanmıştır. 9 eleman uzunluğundadır. Main metodunda kullanılacaktır.

Main metodu

Metodun deklarasyondan sonraki ilk satırında yeni bir komut vardır: COGNEW ("yeni cog" anlamına gelir). Bu komut Toggle metodunu çağırmak üzere yeni bir cogu çalıştırır. Komutun iki parametresi vardır. İlki Toggle çağrısı, ikincisi de yeni cogun çalışma esnasında kullanacağı istif alanının başlangıç adresidir. Buradaki @ sembol adresi operatörüdür. Peşinden gelen değişkenin fiili adresini okur. Yeni cog Spin kodunu çalıştırmak için bir miktar belleğe ihtiyaç duyar. İstif alanı denilen bu bellekte dönüş adresleri, değerleri vb diğer içerikler geçici olarak tutulur. Programda bu alan için 9 long (36 bayt) uygun görülmüştür. Tahsis edilen bu alanın adresi de komutun ikinci parametresi @Stack ile belirtilmiştir. Peki, bir istif alanı ne kadar olmalıdır? Cevap tamamen Spin koda bağlıdır. Ancak ilgili ayrıntıları ileride tartışacağız. Bu aşamada 9 longun Toggle metodu için ihtiyacı karşılayacağını bilmek yeterlidir. Programı derleyip indirince şunlar olur: P16 ve P17 aynı anda fakat farklı fasılalarla yanıp sönmeye başlarlar. Bu durum iki cogun aynı anda çalışmasından kaynaklanır: bir cog P16'yi diğeri de P17'yi sürmektedir.

İşleyiş şu şekildedir: Main metodu Cog0 tarafından çalıştırılır. Metodun ilk satırındaki COGNEW komutu Cog1'i faaliyete alarak Toggle metoduna (16, 3_000_000, 10) değerlerini geçirir. Cog1 çalışmaya başlamak üzereyken, Cog0, Main metodunun ikinci satırını icra ederek Toggle metoduna (17, 2_000_000, 20) değerlerini geçirir. Nihayetinde, Cog0 ile P17 ve Cog1 ile P16 eşanlı bir şekilde Toggle metodunu farklı parametrelerle işe koşarlar. Başka bir iş tanımlanmadığı için Toggle metodunun icrasını bitirince ikisi de dururlar. Ancak, Cog1, Toggle metodunu bitirir bitirmez durur; Cog0 da Toggle metodunu bitirip Main metoduna döndükten sonra durur. Yani Cog1 daha önce durur. Süreç Şekil 3.10'da tasvir ediliyor. Spin Interpreter uygulamayı çalıştırması için Cog0'a yükleniyor (en soldaki iki ok). Ardından uygulama, COGNEW komutuyla yeni cogu devreye aldırarak Spin Interpreter'in sıradaki coga yüklenmesini ve böylece Spin koddaki Toggle yöntemini çalıştırmasını sağlıyor. Bu süreçte cogların birbiriyle hiç bir ilişkisi yoktur. Yani süreç gerçek anlamda paraleldir. Burada önemli olan her iki cogun aynı kodu farklı parametre içerikleriyle kendi çalışma ortamlarında yürütmelerdir.

Page 19: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

77

Şekil 3.10 : Output uygulamasının ve Toggle metodunun iki cog ile çalıştırılması.

Özet: Alıştırma-4 ve -5

� Spin dilinde metodlar: o Bir objedeki metodları işe koşarken metodun adı kullanılır; o Metoddan çıkış otomatiktir; kod bittiği zaman çağrıya dönülür; o Uygulamanın ilk metodundan çıkıldığında hem uygulamanın hem de

metodu çalıştıran cogun işi biter. � Parametre (argüman) listesi:

o Parametreler metod(prmtr1,prmtr2...) şeklinde deklare edilirler; o Parametre değişkendir; metod dışından erişilemez, long boyutludur.

� Metod içinde parametrelerde yapılan değişiklikler çağrılarında kullanılan değişkenleri etkilemez.

� REPEAT komutu: o Sonsuz formu: repeatrepeatrepeatrepeat o Sonlu formu: repeat repeat repeat repeat ifade. Bu formdaki ifade döngünün tur

sayısını anlatır. � Diziler:

o sembol[sayı] biçiminde tanımlanırlar. Buradaki sembol terimi dizinin adını sayı da dizinin eleman sayısını temsil eder.

� COGNEW komutu: o Spin veya Assembly kodu çalıştıracak bir diğer cogu devreye sokar; o Paralel süreci mümkün kılar; o Spin kodun çalışma anı için gereken istif alanının adresini gerektirir; o Sembol adresi @, peşinden gelen değişkenin adresini okur.

Spin Interpreter her iki coga da yüklüdür.

Spin uygulaması,(örnekte output.spin'dir) ana RAM'dadır fakat Cog0 tarafından yorumlanır ve Cog1'i sadece Toggle yöntemini çalıştırması için aktive eder

Page 20: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

78

AlıştırmaAlıştırmaAlıştırmaAlıştırma----6 : 6 : 6 : 6 : Nesnelerin alet olarak kullanımı

Önceki alıştırmalarda uygulama yalnızca bir objeden oluşuyordu: output.spin. Bunun altında yatan motif de başkalarına kendi tasarımlarında kullanacakları bir alet sunmaktı. Aslında bir takım I/O pinlerini çeviren bir nesne yapmak çok anlamlı bir iş olarak görülmeyebilir. Ama böyle bir nesneyi başka nesneler için arabirim olacak şekilde düzenleyince durum değişir. Son kodu aşağıdaki şekle getirmekle başlayalım:

Örnek obje: output.spin

{{ Output.spin }} Toggle two pins, one after another.}} VAR long Stack[9] 'Stack space for new cog PUB Main cognew(Toggle(16, 3_000_000, 10), @Stack) 'Toggle P16 ten…

Toggle(17, 2_000_000, 20) 'Toggle P17 twenty… PUB Start(Pin, Delay, Count) {{Start new toggling process in a new cog.}} cognew(Toggle(Pin, Delay, Count), @Stack) PUB Toggle(Pin, Delay, Count) {{Toggle Pin, Count times with Delay clock cycles in between.}} dira[Pin]~~ ' Set I/O pin to output direction repeat Count ' Repeat for Count iterations !outa[Pin] ' Toggle I/O Pin waitcnt(Delay + cnt) ' Wait for Delay cycles

Sonraki nesneyle birlikte kulanırken sorun çıkmaması için bu programı "output.spin" adıyla kaydedin.

Start metodu

Bu kez Main metodu çıkartılmış, yerine Start metodu konulmuştur. Start metodunda yapılan, Toggle rutinini bağımsızca çalıştıracak başka bir cogu devreye sokmaktan ibarettir. Yine COGNEW komutu kullanılır.

Bir objeye arabirim, o objenin PUB metodlarıyla oluşturulur. Buna göre, output adlı objenin bu amaca uygun iki elemanı var demektir: Start ve Toggle metodları!

Artık output objesi başka nesnelerin her hangi bir pini her hangi bir hızda ve sayıda çevirmesinde arabirim olarak kullanılabilir durumdadır. Aslında bu işlemin seri düzenekle yapılması için Toggle yönteminin kullanılması yeterldir. Ama paralel olarak yapılması istenildiğinde, o zaman Start metoduna başvurmak gerekir.

Page 21: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

79

Şimdi de output objesini kullanan başka bir nesne yapalım. Bunun için menüden File → New yolu izlenir. Böylece yeni bir edit sekmesi görünür. Bu yeni edit sayfasında aşağıdaki kod girilecektir. Kalın yazılmış kısımları tek tek ele alacağız.

Örnek obje: blinker.spin

{{ Blinker1.spin }} OBJ LED : "Output" PUB Main {Toggle pins at different rates, simultaneously} LED.Start(16, 3_000_000, 10) LED.Toggle(17, 2_000_000, 20)

Bu nesneyi blinker1.spin ismiyle output.spin'in durduğu yere koyun. Blinker'in edit sekmesi aktif durumdayken F10'a basarak derlemeyi ve yüklemeyi tamamlayın. LED'ler tıpkı Alıştırma-5'teki gibi çalışacaksa da burada fark yordamdadır; blinker1, output nesnesinin Start ve Toggle yöntemlerini çağırır. İşleyiş şöyledir: blinker1'de OBJ ve PUB olmak üzere iki metod vardır. OBJ metodundaki LED: "Output" satırı, output adında başka bir nesnenin çağrıldığını ve blinker 1 içinde kendisinden LED olarak bahsedileceğini belirtir.

Obje-metod

Blinker1.spin'deki Main metodunda iki çağrı vardır. Alıştırma-4'te de anlatıldığı gibi, bir metodu diğer bir metodun içinden çağırırken, çağrılan metodun adını ve parametrelerini yazmak yeterlidir. Ancak bu özellik bütün metodların aynı objeye ait olması halinde geçerlidir. Oysa biz burada başka bir objenin içindeki metodu çağırmaya çalışıyoruz.

Şekil 3.11 : Blinker1 hiyerarşisi ve Blinker1 uygulaması (application)

Page 22: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

80

Bu amaçla obje.metod(prmtr1, prmtr2, ...) formundan yararlanırız. Yani önce çağrılacak metodun ait olduğu objenin (OBJ bloğunda belirtilen) etiketi, ardından bir nokta ve sonra da çağrılacak metod ve varsa parametreleri yazılır. Buna obje-metod referansı diyoruz. Blinker1'de LED adıyla referans verilen obje Output dosyasıdır. LED.Start ile Output'un Start rutini, LED.Toggle ile yine aynı nesnedeki Toggle metodu çağrılır. Blinker1 derlenmek istenildiğinde, Output'a referans vermesi nedeniyle ikisi birlikte derlenirler. Şekil 3.11 bunu betimlemektedir. Şekildeki yapı ayrıca sonraki başlıkta da ele alınacaktır.

Obje GörünümüObje GörünümüObje GörünümüObje Görünümü

Blinker1 derlenince Object View panosu uygulamanın strüktürünü gösterecek şekilde değişir. Bu pano Integrated Explorer açık olduğu zaman Tool'un sol üst köşesindedir.

Şekil 3.12 : Blinker1 obje görünümü

Bir uygulama gereğince derlendiği zaman Object View uygun şekilde değişir. Blinker1 uygulamasının yapısı Şekil 3.12'de görülmektedir. Bu yüzden obje görünümü, derlemede sorun olup olmadığını görmek için iyi bir yöntem sunar. Uygulamanın tamamı Object View içinde görünür; daha doğrusu, gereğince derlenmiş son uygulama bu görünümde hemen belli olur. Dolayısıyla bu görünümü uygulamanın özelliklerini keşfetmek için çok uygundur. Örneğin bir obje hakkında temel bilgileri fareyle üstüne giderek almak mümkündür. Sol-tık yapılan bir nesne ya açılır ya da edit sekmesi aktif hale gelir. Sağ-tık da aynı şeyleri yapmakla birlikte objenin tüm kaynak görünümü yerine belge görünümüne geçmesine yol açar

Top Object File Top Object File Top Object File Top Object File ----şeşeşeşef dosyaf dosyaf dosyaf dosya

Obje görünümünün tepesindeki nesne, o derleme için Top Object File, yani şef dosyadır. Bu da derlemenin blinker1 dosyasından başladığını anlatır. Propeller Tool derlemeyi o sırada aktif (seçili, aydınlatılmış) olan edit sekmesini kullanarak başlatır.

Eğer istemeksizin önce output üzerine tıklanır ve ardından derleme F10 veya F11 ile çalıştırılırsa, bu durumda output dosyası derlenir. Sonuç arzu edilen şekilde olmaz ve obje görünümünde sadece bir dosya -yani output - ve yapısı görünür. Bunun sebebi de "Compile Current" (yürürlükte olanı, yani aktif objeyi -edit sekmesini- derle) seçeneklerini kullanıyor olmamızdır. Oysa başka seçenekler de vardır (Şekil 3.13).

Page 23: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

81

Şekil 3.13 : "Compile Current" menüsü (yukarıda) ve " Compile Top" menüsü (aşağıda)

Run menüsünün her iki kalemi de aynı alt seçeneklere sahiptir. Fark, derlemenin başladığı yerdedir: Compile Current ile derleme aktif edit sekmesinden, Compile Top ile şef olarak belirlenen dosyadan başlar. Hangi dosyanın şef olduğunu Propeller Tool'a bildirmek için aşağıdaki yollardan biri kullanılabilir:

1) İstenilen objenin edit sekmesine sağ-tık yapılıp Top Opject File seçilir;

2) Integrated Explorer içinde dosya listesinde dosyaya sağ-tık yapılır ve Top Object File seçilir;

3) Choose the File → Select Top Object File ile açılan pencereden seçilir;

4) Ctrl+T ile açılan pencereden seçilir.

Aşağıdaki şekilde blinker1'i belirlemek için ilk seçenek uygulanmıştır. Dikkat edilirse blinker1'in metni kalındır. Propeller Tool tarafından Top Object File olarak bilinen bir dosya daima kalın harflerle görünür.

Eğer Compile Top opsiyonlarından biri kullanılıyorsa, edit sekmesi ne olursa olsun derlemeye daima Top Object File ile başlanır. Örneğin Şekil 3.14b'de aktif edit sekmesi output dosyasını işaret eder. Ancak Ctrl+F10 tuşlanması halinde derleme blinker1 ile başlayacaktır. Öte yandan sadece F10 tuşlanırsa bu kez derlemeye output'dan başlanır. Kısayollar her iki seçenekte de aynı tarz derlemeye işaret ederler.

Page 24: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

82

Şekil 3.14 : Blinker1'in şef dosya olarak seçilmesi: (a) İlgili edit sekmesine sağ-tık yapıp Top Object File ile yapılır; (b) Bir şef dosya edit sekmesinde kalın harflerle görünür.

Hangi dosyalar (nesneler) derlenmiş durumdadır?

Eğer böyle bir kaygınız varsa, cevabını almak için derhal fareyi kullanarak nesne görünümünde uygulamanın yapısına bakınız. Çünkü hangi nesnenin şef dosya olarak tayin edildiğini ve derleme önceliğini, yani Current şıkkının mı yoksa Top şıkkının mı kullanılacağını bilmek önemlidir. Belli bir anda sadece bir dosya şef olabilir. Bir diğer nokta da şudur: derlenecek dosyanın açık olması şart değildir. Derlenen bir dosyanın referans verdiği bir nesne varsa, o nesne muhakkak derlenir; yani açık yahut kapalı olması durumu değiştirmez. Bu durum şef dosya için de aynen geçerlidir. Örneğin Ctrl+F10 tuşlanacak olursa şef dosya derlenir. O sırada çalışmakta olduğunuz uygulamaya ilgisi olmaması bunu etkilemez.

Özet: Alıştırma-6

� Spin dilinde başka bir objedeki metodlar, obje.metod şeklinde çağrılırlar. Burada obje ile OBJ bloğunda tanımlanan etiket; metod ile o objeye ait çağrılacak rutin belirtilir. Açık metodlar (PUB'lar) bir objenin arabirimidir. Diğer nesneler bu arabirimlerle çağrılır.

� Obje görünümü ile: o Gereğince derlenen son uygulamanın yapısı tasvir edilir. o Fareyi görünen nesnenin üzerine getirmek ipuçlarını görüntüler. o Sol-tık yapılan nesne ya kendi açılır ya da edit sekmesi aktive olur. o Sağ-tık yapılan nesne açılır veya belge görünümüne geçer.

� Compile Current (F8 ... F11) ile derlemeye yürürlükteki objeden başlanır. � Compile top (Ctrl+F8 ... F11) ile derlemeye şef dosyadan başlanır. � Şef dosya:

o Edit sekmesinde ve dosya listesinde kalın görünür o Dört şekilde tayin edilir:

� Edit sekmesinde sağ-tıktan sonra Top Object File seçilerek; � Dosya listesinde sağ-tıktan sonra Top Object File seçilerek; � Choose File → Select Top Object File ve pencereden seçilerek; � Ctrl+T ile açılan pencereden seçilerek.

Page 25: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

83

� Derlenecek nesnelerin açık olmaları şart değildir. Başka bir objenin derlenmesine bağlı olarak veya Compile Top sürecinin gereğince derlenebilirler.

Objeler ve coglar

Coglarla objeler arasında doğrudan bir ilişki söz konusu değildir. Örneğin Alıştırma-5'te bir obje fakat iki cog kullanılıyordu. Alıştırma-6'da ise her ikisi de ikişer taneydi. Kaldı ki her iki uygulamada da seri süreç kurgulayarak sadece bir cog kullanmak da pekala mümkündü. Cogların ne zaman ne şekilde kullanılacağı tamamıyla uygulamaya ve tasarımcıya bağlıdır.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----7 : 7 : 7 : 7 : Projeyi genişletiyoruz

Output'a bazı ilâvelerde bulunacağız. Toggle rutinini bir pini seri olarak çevirmek üzere kullanmak veya ayrı bir paralel süreç olarak çalıştırmak için Start rutinini çağırmak da mümkündür. Ancak devam eden bir süreci durduracak ya da çalışıp çalışmadığını sınayacak bir tekniğe henüz sahip değiliz. Yine, bir pini sonsuza kadar çevirmekle belli bir sayıda durmasını sağlamaya yönelik bir seçeneğimiz de yoktur.

Aktif gidişi durdurmak üzere bir Stop metodu tanımladıktan sonra işlemekte olan bir paralel süreci sınayacak bir Active metod tanımlayacak ve Toggle metoduna bazı ekler yapacağız.

Böylesi nesnelerle çalışırken yeni bir cogu işe koşmak üzere bir Start metodu ve çalışmakta olan bir cogu durdurmak üzere Stop metoduna başvurmak yaygın kullanılan ve tavsiye edeceğimiz bir uygulama geleneğidir. Bu yaklaşım, programı izleyen başka tasarımcıların ne yapıldığını anlamalarını kolaylaştırır. Start ve Stop, cogu işe koşmak ve durdurmak için gayet anlaşılır metod isimleridir. Başka bir cogu işe koşmayan fakat bir şekilde açan veya başlatan bir metod için Init adı daha uygun gibidir. Böyle bir kod çeşitli incelikler taşır. Açıklanması gereken pek çok nokta içermekle birlikte, hepsi bilinmeye değer şeylerdir. Yazmış olduğunuz kodu aşağıdaki hale getirin:

{{ Output.spin }} VAR long Stack[9] 'Stack space for new cog byte Cog 'Hold ID of cog in use, if any PUB Start(Pin, Delay, Count): Success {{Start new blinking process in new cog; return TRUE if successful}} Stop Success := (Cog := cognew(Toggle(Pin, Delay, Count), @Stack) + 1)

Page 26: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

84

PUB Stop {{Stop toggling process, if any.}} if Cog cogstop(Cog~ - 1) PUB Active: YesNo {{Return TRUE if process is active, FALSE otherwise.}} YesNo := Cog > 0 PUB Toggle(Pin, Delay, Count) {{Toggle Pin, Count times with Delay clock cycles in between. If Count = 0, toggle Pin forever.}} dira[Pin]~~ 'Set I/O pin to output… repeat 'Repeat the following !outa[Pin] ' Toggle I/O Pin waitcnt(Delay + cnt) ' Wait for Delay cycles while Count := --Count #> -1 'While not 0 (make min -1) Cog~ 'Clear Cog ID variable

VAR bloğu

Değişken tanım bloğunda yeni bir değişken eklendiği görülür: cog. Bu değişken bayt boyundadır. Start ile başlatılan cogun künyesini tutar. Hem stack hem de cog genel (global) değişkenlerdir. Yani mevcut değerleri özel olarak değiştirilmedikçe her PUB yahut PRI bloğunda, programın her bölmesinde geçerlidir. Dolayısıyla global bir değişkenin değeri her hangi bir yerde değişecek olursa, o andan itibaren yeni değer geçerli olur. Programın tüm diğer bölmeleri değişkeni bu yeni değeriyle tanırlar.

Start metodu

Sayıları sınırlı olduğu için çağrılan her cog işe koşulabilir durumda olmayabilir. Dolayısıyla cogun durumunu bilmek önemlidir. Bu amaçla, çıkışı cogun çalışma durumunu gösteren bir Boolean değerden yararlanıyoruz ve bunu metodun deklarasyon satırında belirtiyoruz: «: Success: Success: Success: Success». Metod, yeni bir cogda yeni bir yan-sön süreci başlatmaya girişecek ve eğer başlattıysa bunu TRUE (doğru) değeriyle Success içinde döndürecektir. Her açık yahut hususi (PUB veya PRI) yöntem, özellikle belirtilsin veya belirtilmesin, daima 1-long (4-bayt, 32-bit) değer döndürür. Bir yöntem anlamlı bir değerle sonuçlanmak üzere oluşturulduysa, söz konusu dönüş değerini -burada yaptığımız gibi- deklare etmek yararlı bir iştir. Programa eklediğimiz Success terimi, aslında, hazır RESULT değişkeninin lâkabı olarak iş görür. Yani Success ya da RESULT terimine metodun çıkışında döndüreceği bir değeri atamak mümkündür. Böyle bir kurgu varsa Start metodu şu iki işi yapar: O sırada başka her işi bırakır ve yeni bir işe başlar ve önce hemen Stop metodunu çağırır. Çünkü Start metoduna çok sayıda çağrı gelir. Bu da Stop metodunun obje dışından çağrılma ihtimali demektir. İşte, Stop'un hemen çağrılmasının sebebi bu

Page 27: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

85

ihtimali bertaraf etmektir. Bu önlem alınmazsa yeni çalışan bir cog, başka bir cogun Stack vb gibi çalışma yeri değişkenlerinin üstüne yazabilir.

Sonraki satır, Success := (Cog := cognew(Toggle(Pin, Delay, Count), Success := (Cog := cognew(Toggle(Pin, Delay, Count), Success := (Cog := cognew(Toggle(Pin, Delay, Count), Success := (Cog := cognew(Toggle(Pin, Delay, Count),

@Stack) + 1)@Stack) + 1)@Stack) + 1)@Stack) + 1), eski haline benzemekle birlikte daha karmaşıktır. Bu satırı anlamak için içerden dışarı doğru ele alacağız. COGNEW kısmı eskisiyle aynıdır. Burada yapılan, Toggle metodunu çalıştırmak üzere yeni bir cogun işe koşulmasıdır. Bilmediğiniz yanı, COGNEW komutunun işe koştuğu cogun künyesini almasıdır. İşe koştuğu cog için 0-7 aralığında bir değer alır. Eğer işe koşulabilen bir cog yoksa, bu durumda değeri -1 olur, ki Output'un önceki durumlarında sözünü etmediğimiz bir özelliktir. İşte COGNEW komutunun bu dönüş değeri 1 eklendikten sonra COG değişkenine konulur. ":=:=:=:=" işareti değer atamaya yarar ve diğer dillerdeki eşit gibidir. COG değişkeni çalıştırılan cogun numarasını tutar ve gerektiğinde o cogu durdurmakta kullanılır. Buna 1 eklememizin sebebi, sonucun en soldaki SuccessSuccessSuccessSuccess değişkenine aktarıldığı zaman 0 veya 1 değerini almasını sağlamaktır. Sağdaki terim -1 ile 7 arasındaki değerleri alır. Buna 1 eklendiğinde bu aralık 0-8 sınırlarında kalır. Soldaki, yani sonucun aktarılacağı terim BOOLEAN olduğu için, 0 değerini FALSE (yanlış) ve 0 dışındaki bütün değerleri de TRUE (doğru) olarak görür. Yani 0 olmayan her değer bir cogun işe koşulduğunu; 0 ise hiç bir cogun çalıştırılamadığını gösterir.

Böylece tek satırlık kodla o sırada meşgul olmayan bir cogu çalıştırmış, Toggle rutinine referans vermiş, kullanılacak istif alanını belirlemiş, aktive olan cogun numarasını (1 fazlasını) ve buradan türeyen doğru/yanlış değerini de işlemin başarısını göstermek üzere kaydetmiş oluyoruz. Bu satır, Spin dilinin en güçlü yönlerinden birini sergiler: Karmaşık ifadeler iç içe atanabilir terimler olarak düzenlenebilir. En dıştaki parantezler gereksiz ise de değer atama sırasını göstermek üzere kullandık. Buna göre, önce COG'un daha sonra SUCCESS'in değeri aktarılır. Karmaşık aritmetik ifadelerde işaretçinin (cursor) o anki yerini içeren parantezler kalın görünür. Şekildeki yıldızlar işaretçinin yerini; oklar ise o konumu kapsayan en iç parantezi gösterir. Parantezin içi zemin rengiyle ayırt edilmiştir.

Şekil 3.15 : İşaretçinin içinde bulunduğu yeri içeren parantezler kalın görünür. Uzun ve karmaşık ifadeleri takip ederken bu özellikten yararlanabilirsiniz.

Page 28: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

86

Stop metodu

Stop metodu, Start ile çalıştırılan cogu durdurur. Programdaki "if Cog" şu anlama gelir: "eğer cog değişkeni doğru ise izleyen kod bloğunu icra et". COG'un çalışacak cog olmaması halinde 0; aksi takdirde 1-8 arasında bir değer alacağını unutmayın. 0 değeri yanlış ve 0'dan büyük değerler doğru olduğu için izleyen kod bloğu sadece bir cog çalıştıysa icra edilecektir. Bu durumda COGSTOP komutu COG değişkeninin değerinin ima ettiği cogu durdurur. Durdurulacak işlemci, COG değerinin 1 eksiğiyle numaralanmış cogdur. Bu noktada Spin'in bir diğer gücüne tanık oluruz. "~~~~~~~~" operatörü, önceki alıştırmalardan biliyoruz, solundaki değişkeni set eder (1 yapar, doldurur). "~~~~" ise solundaki değişkeni temizler (0 yapar, boşaltır). Değişkenin orijinal değerinin işlenmesinden sonra görevlerini yerine getirmeleri nedeniyle bunlara ardıl (post) operatörler diyoruz. Yani Cog~ Cog~ Cog~ Cog~ ---- 1 1 1 1 ifadesi COG'un değerinden 1 çıkartır, sonucu COGSTOP komutuna verir ve COG'u sıfırlar. Neticede cogstop(Cog~ cogstop(Cog~ cogstop(Cog~ cogstop(Cog~ ---- 1) 1) 1) 1)'in yaptığı iş, numarası COG-1'e eşit olan cogu durdurduktan sonra COG değişkenini sıfırlayarak yine aynı işi yapmaya hazır hale getirmektir.

Active metodu

Rutin basittir. YesNo değişkeninin dönüş değeri 0 ise yanlış, sıfırdan büyükse doğrudur. ">>>>" işareti büyüktür anlamındaki mukayese operatörüdür. Bu yanlış/doğru değerlendirmesinin YESNO'yu COG değişkenine eşitlediğine dikkat ediniz.

Toggle metodu

Metodda yükte hafif pahada ağır değişiklikler yaptık. Son satırından başlayalım: Cog~. Hatırlanırsa, Start çalıştığında başka bir cogun Toggle metodunu işletip cogun künyesini COG değişkenine yazmasına yol açıyordu. Toggle sona erdiğinde cog da durur ancak numarası COG değişkeninde kalmaya devam eder. Bu da Active ve Start metodlarının cogun çalıştığını sanmalarına yol açar. Kodun gereğince işlemesi için aktif cog numarasını tutan değişkeni sıfırlama işini Toggle metodunun sonunda yapıyoruz. Daha önce de söylediğimiz gibi Toggle metodunu sonlu döngü gibi bir sonsuz döngüye çevirebiliriz. Metoddaki Count terimi pinin değer dönüşüm sayacıdır. Böyle bir terimi 0'a eşitlemenin anlamsız olacağı açıktır. Bu durumda terimin boşa çıkan 0 değerini "pini sonsuz sayıda çevir" sonucunu verecek şekilde kullanabiliriz. Bu amaçla döngü repeat Countrepeat Countrepeat Countrepeat Count şeklinden repeat...whilerepeat...whilerepeat...whilerepeat...while şekline çevrilmiştir. Yapının whilewhilewhilewhile terimi repeat teriminden üç satır aşağıda, döngünün sonundadır. Koşullu döngüler sınıfındaki bu yapıda döngü en az bir tur çalışır. Başka tur olup olmayacağı koşulun karşılanmasına bağlıdır. Koşul karşılandığı sürece döngüde kalınır. Döngüden çıkmak için koşulun karşılanmaması, yani sonucun YANLIŞ olması gerekir. Dolayısıyla while Count := while Count := while Count := while Count := --------Count #> Count #> Count #> Count #> ----1111 satırı icra edildiğinde sayaç sıfır değilse döngüde kalınır; tersi durumda, yani sayaç sıfır ise döngüden çıkılır.

Page 29: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

87

Döngünün koşul satırı bileşik ifadedir. Öncül (pre) operatörlerden olan "--" (çift-eksi), sağındaki değişkeni işleme girmeden önce 1 eksiltir. "#>" de minimum limit operatörünün simgesidir. Bu operatör soldaki terimin sağdaki terimden büyük olup olmadığına bakar. Koşula göre, döngünün her tekrarında count terimi bir eksiltildikten sonra operatörün (#>) sağındaki -1 ile kıyaslanır. Büyükse, eksiltmenin sonucu count değişkeninin yeni değeri olur ve döngü tekrarlanır. Meselâ Toggle metodu sayacın (Count) 2 değeriyle başlamış olsun. Buna göre döngü iki turdan sonra bitecektir. İlk iterasyonun ardından döngü sonuna gelindiğinde sayaç 1 eksiltilir ve 1'e düşer. 1 değeri -1'den büyük olduğu için sayacın yeni değeri 1 olur ve döngü baştan alınır. İkinci turda aynı satıra gelindiğinde Count yine 1 eksiltilerek 0 yapılır. 0>-1 olduğu için değer sayacın yeni değeri olur. Ancak 0 değeri YANLIŞ demek olduğu için WHILE koşulu döngüyü sona erdirir. Toggle sayacın sıfırdan büyük tüm değerleriyle işletildiğinde bu döngü normal çalışır. Ancak döngüye 0 ile girilirse durum değişir. Sayaç 1 eksilirek -1 olur. -1 limite eşit ve sıfırdan farklı olduğu için sayacın yeni değeri yapılır ve döngü baştan alınır. İşlemler yapılınca sayaç yine 1 eksilir ve -2 olur. Bu da limitten küçük olduğu için sayaç -1'e eşitlenir ve döngü yine baştan alınır. Böylece döngüyü sonsuz kılmak mümkündür. Bundan kurtulmanın tek yolu sayacın eksilmeden önceki değerinin pozitif olmasıdır.

Özet: Alıştırma-7

� Nesneler: o Coglarla aralarında doğrudan ilişki yoktur. o Başka coglar işe koşulacağı zaman "Start" ve "Stop" metodlarının

kullanılmasını gerektirirler. o Başlatma gerektirdiğinde "Init" metoduna ihtiyaçları vardır.

� Spin dili: o Değişken (VAR) bloğundaki tanımlar geneldir. Bir metodda genel

değişkenlerde yapılacak bir değişiklik diğer tüm metodları etkiler. � Boolean terimler: FALSE (yanlış) = 0; TRUE (doğru) = -1. Boolean

mukayesede sıfır olmayan her değer DOĞRU olarak görülür. � Operatörler: Öncül (pre)/ardıl (post) operatörler, değişken üzerindeki

görevlerini ifadenin işleme girmesinden önce/sonra yerine getirirler. o ":=" simgesi diğer dillerdeki "=" eşit simgesi ile aynı işi görür. o Sonra temizle (post-clear) simgesi (~) solundaki değişkeni sıfırlar. o Önce eksilt (--) simgesi sağındaki değişkenin değerinden 1 çıkartır. o Büyüktür (>) işareti, solundaki değeri sağındaki değerden büyük

olması halinde DOĞRU üretir. o Minimum limit (#>) operatörü, solunda ya da sağında olsun büyük

olan değeri seçer. � Metodlar:

o Belirtilsin ya da belirtilmesin daima long değer döndürürler.

Page 30: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

88

o Kendi çıkışını üreten RESULT hazır değişkenini içerirler. Çıkışlar metodun adını izleyen ":" simgesinden sonra yazılan terimde tutulur.

o COGNEW komutu çalıştırılan cogun 0-7 aralığındaki künyesini döndürür. İş için cog çalıştırılamadıysa sonuç -1 olur.

o COGSTOP ise künyesi verilen cogu durdurur. o IF döngüsü koşulun doğru olması halinde içindeki komutların icra

edildiği yapıdır. o REPEAT WHILE yapısı REPEAT döngüsünün koşullu formudur.

Döngü en az bir kez gerçekleşir. Devamı, sonuna konulan koşulun karşılanmasına (doğru olmasına) bağlıdır.

� İşaretçinin bulunduğu yeri kapsayan en iç parantez çifti kalın görünür.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----8 : 8 : 8 : 8 : Çok sayıda obje ve çok sayıda cog

Burada, Output'taki yeniliklerden yararlanan yeni bir obje geliştireceğiz.

Örnek obje: blinker2.spin {{ Blinker2.spin }} CON MAXLEDS = 6 'Number of LED objects to use OBJ LED[6] : "(Ch3-Ex07)-Output" PUB Main {Toggle pins at different rates, simultaneously} dira[16..23]~~ 'Set pins to outputs LED[NextObject].Start(16, 3_000_000, 0) 'Blink LEDs LED[NextObject].Start(17, 2_000_000, 0) LED[NextObject].Start(18, 600_000, 300) LED[NextObject].Start(19, 6_000_000, 40) LED[NextObject].Start(20, 350_000, 300) LED[NextObject].Start(21, 1_250_000, 250) LED[NextObject].Start(22, 750_000, 200) '<-Postponed LED[NextObject].Start(23, 400_000, 160) '<-Postponed LED[0].Start(20, 12_000_000, 0) 'Restart object 0 repeat 'Loop endlessly PUB NextObject : Index {Scan LED objects and return index of next available LED object. Scanning continues until one is available.} repeat repeat Index from 0 to MAXLEDS-1 if not LED[Index].Active quit while Index == MAXLEDS

Page 31: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

89

Blinker2'yi derleyip yükleyince altı LED'in bağımsız olarak yanıp sönmeye başladıklarını göreceksiniz. Dikkatli izlerseniz yaklaşık 8 saniye sonra P20 duracak, P22 çalışmaya başlayacaktır. Bir kaç saniye sonra P18 duracak, P23 çalışacaktır. Ardından P16 duracak ve P20 yeniden, fakat farklı sıklıkta yanıp sönecektir. Nihayetinde P17 ve P20 hariç hepsi duracaktır. Peki ama neden? Sebebi aşağıda!

OBJ bloğu

Burada LED isminde 6 elemanlı bir Output dizisi tanımlanmıştır. Birbirinden bağımsız çalışan altı adet eş zamanlı süreci bunlarla yürüteceğiz.

Main metodu

Bu metodun ilk satırı, dira[16..23]~~, 16-23 aralığındaki I/O pinlerini çıkış yapar. I/O yazmaçları, DIRA, OUTA ve INA'da, çok sayıda pini sürmek için bu yapı kullanılır. Bu pin grubunun çıkış yapılmasının sebebi, Propeller Demo Board'daki 18-23 numaralı I/O pin çiftleri arasındaki dirençlerden kaynaklanabilecek kafa karıştıracak sonuçlardan kaçınmaktır. Bir pin sadece bir cog tarafından çıkış yapılırsa, o pin, kapanışın ardından yeniden giriş olur. Bu da pinle komşusu arasındaki direncin komşunun LED'ini etkilemesine yol açar. Bu uygulamanın cogunu aktif bırakarak sonuçlarını açık edeceğiz. Metodun sonraki 9 satırı farklı değerler için aynı komutu içerir. Bunların her biri Output'un Start metodunu çağırarak yeni bir cogu çalıştırır ve her biriyle bir I/O pinini diğerlerinden farklı hızda sürer. İçinde NextObject terimi olan satırlar bu isimli metodu çağırırlar. Metodu az sonra açıklayacağız. Şimdilik şu kadarını söyleyelim: LED dizisinde müsait durumdaki Output objesinin indeks değerini alır; bunun için birinin müsait olmasını bekler. LED dizisi itibariyle sadece 6 Output nesnemiz vardır. Dolayısıyla Start'a yapılan ilk 6 çağrı hızla icra görecek, 0-5 aralığındaki indeksler üzerinden cogları aktive edecektir. İlk ikisinin sayaç değeri 0'dır. Yani bunlar sürekli yanıp söneceklerdir. Son dördü ise verilen sayaç değeri kadar döneceklerdir. LED'le başlayan satırların yedincisi de sıradaki obje için indeks değeri alacaksa da, o sırada tüm nesneler meşgul olduğu için NextObject beklemede kalacak, müsait bir nesne bulmadan Main metoduna dönmeyecektir. Görevini ilk bitiren nesne indeksi 4 olan ve P20'ye karşılık gelen nesnedir. Dolayısıyla NextObject'in alacağı numara 4'tür. Dolayısıyla Start metodu tekrar icra edilebilecek ve P22'yi işletmek için başka bir cog yeniden çalıştırılacaktır. Bir sonraki satırda da işleyiş bundan farklı değildir. Yine tüm nesneler meşgul olacağından, bir cogun müsait olması için işlem ertelenir. Bu kez elde edilecek indeks değeri 2'dir. Sonraki satır biraz farklıdır. Burada NextObject çağrılmaz. İndeksin 0 değeri kullanılır, ki 0 olarak indeksenmiş LED'i temsil eder. Ancak bu pin, P16, sürekli meşguldür. Bu noktada Start işletildiğinde P16'yı çalıştıran cog durur ve P20'yi sürmek üzere yeniden çalışmaya başlar. Son satırdaki repeat komutu uygulama cogunu canlı tutar. Sonsuz bir döngü yaratır. Çünkü uygulama cogunun durması, çıkış yaptığı I/O pinlerinin yine giriş olmasına

Page 32: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

90

yol açar. Bu da, söz edilen dirençlere bağlı olarak acaip sonuçlar yaratır. Ancak bu durum Propeller Demo Board (PDB) için böyledir. Yani eğer PDB kullanmıyorsanız Main metodunda ilk ve son satırlara gerek yoktur.

NextObject metodu

Programda altı adet LED nesnesi vardır. Bunların her hangi bir kombinasyonunu paralel işletmek mümkündür. Metodun varlık sebebi, bir cog müsait olana kadar operasyonun ertelenmesi, müsait olduğunda hangisi olduğunun belirtilmesidir. Bu amaçla, boşa çıkan bir tane bulana kadar bütün LED nesneleri yoklamak üzere, NextObject, Ouput'un Acive metodundan yardım alır. Programda iç içe iki REPEAT döngüsü vardır. repeat..while Index == MAXLEDS şeklindeki dış döngünün devamı, indeksin cog sayısına (örneğimizde 8'ya) eşit olmasına bağlıdır. Bu döngünün nasıl işlediğini daha önceden biliyoruz. İçteki döngü, repeat Index from 0 to MAXLEDS-1, yeni bir formdur. Tur sayısı bellidir. Her turda sayacı n değerini değiştirir. Başlangıçta 0 değerlidir. Sonra her turda 5 olana kadar 1 artar. Bu, döngü içindeki operasyonu döngünün işlem görme sayısıyla düzenlemek açısından çok etkili bir tekniktir. Takip eden satır, if not LED[Index].Active,bir koşul ifadesidir. İlgili kod, sayacın gösterdiği LED'in aktif olmaması durumunda icra edilir. Sayaç iç döngü tarafından 0-5 aralığında değiştirildiği için, bu koşul gereğince Active metodu her LED objelerinin her biri için sırayla cağrılır. Koşul karşılanıyorsa (doğruysa, TRUE ise) izleyen satırdaki quit komutu icra görür. Bu komut sırf REPEAT komutuna özgüdür ve döngüden bir anda çıkılmasını sağlar. Bu durumda iç döngüden çıkılır ve dış döngünün sonundaki while ifadesine varılır. Bütün LED nesneleri aktif ise, bunlar iç döngüde 0-5 arasında Index teriminde (sayaç) vasıtasıyla sayılacak, değer maksimuma (6, MAXLEDS) ulaşınca döngüden çıkılacak ve iş yeniden dış döngüye kalacaktır. Bununla birlikte, eğer aktif olmayan bir LED nesnesi varsa, sayaç değeri maksimumdan (Index değişkeninin değeri MAXLEDS değişkeninin değerinden) küçük olacağı için dış döngü de sona erecek ve NextObject metodunun müsait objenin sayaç değerini döndürmesine yola açacaktır. Bu değer ise Main metodu tarafından doğru LED'in çalıştırılması için kullanılır.

Perde arkası

Obje bloğunda 6 elemanlı bir Output objesi tanımladık. Bir uygulamadaki her obje kendi has kritik verileriyle özel olarak işlenmesi gereken bir büyüklüktür. Bizim ihtiyacımız altı elemanlı olduğu için OBJ içindeki tanımı da buna uygun yaptık. Bilnker2'nin derlenmesinden sonra Output objesi Object View içinde altı defa yer alır; Output obje imgesinin sağında "[6]" ifadesi yer alır. Uygulamanın 6 elemanlı yapısı Object View ile bu şekilde ekrana getirilir. (Şekil 3.16.)

Page 33: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

91

Şekil 3.16 : Blinker2 uygulaması. Ouput nesnesinin altı elemanı vardır. Uygulama, ilgili icra kodu için 1; genel değişken alanı için 6 altı kopya çıkartır

Bu durumda uygulama 6 tane Output objesi kadar şişer mi? Neyse ki yanıt hayırdır! Uygulama kodu Propeller Tool tarafından o şekilde optimize edilir ki, objenin her tekrarında obje kodunun sadece bir kopyası alınır. Ancak, objenin genel değişkenleri için bir kaç kopya oluşturulur. Sebebi şudur: Kodun durağan olduğu, her obje için aynı olduğu düşünülür. Fakat objenin genel değişkenleri (yani VAR ile tanımlanan değişkenler) böyle statik değildir. Her objenin kendi değişken alanının olması gerekir. Aksi takdirde başka nesnelerin müdahelesine maruz kalır.

Object Info penceresi

Page 34: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

92

Şekil 3.17 : Blinker2 uygulaması için “object info” penceresi

Bu durumu Tool'un Object Info'sunu kullanarak görebiliriz. Önce, Blinker2'deki obje bloğunu Output objesinin bir örneğine çevireceğiz: LED[1] : "Output". Ancak kod bu haliyle çalışmaz. Sonra, F8 tuşlayıp (Run → Compile Current → View Info…) uygulamayı derleyeceğiz ve Object Info penceresini açacağız. Sonucun nasıl olması gerektiği Şekil 3.17'de gösterilmektedir. Pencerenin en üstünde Info Object View görünür. Pencerenin ortasında uygulamanın RAM tahsisi yer alır. Program, yani derlenmiş kaynak kodu için 68 long RAM gitmiştir. Global değişkenler (Variable) için de 10 long harcanmıştır. Pencereyi kapatıp obje bloğunu Output'un 6 elemanlı haline çevirelim: LED[6] : "Output". Derlemeden sonra yine bilgi ekranına geçebiliriz (F8 or Run → Compile Current → View Info…).

Değişiklik, programın 73, değişkenlerin de 60 long RAM işgal etmesiyle sonuçlanmıştır. Yani fazladan, program için 5 long fakat değişkenler için 50 long RAM gerekmiştir. Ek program alanı ilâve 5 değişkenle uğraşma gereğinden doğar. Ancak değişken alanı öncekinin 6 katıdır. Çünkü her nesnenin ayrı bir statik genel değişken alanı bulunur. Blinker2'de genel değişken alanı yoktur. Output'da 9'u STACK ve 1'i de COG'dan gelen toplam 10 long değişken alanı vardır. COG 1 bayt olmasına rağmen değişken alanı 1 longdan az tahsis edilmez. Object Info

Page 35: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

93

penceresinde Output üzerine tıklanırsa nesnenin her unsuruna ne kadar yer ayrıldığı görülebilir: 21 long programa; 10 long da değişkenlere ayrılmıştır. Obje ömrü

Uygulama derlenince icra edilecek kodun binary (bin) sureti üretilir. Bu suret çipe yüklenen ve "uygulama/ Propeller uygulaması" dediğimiz dosyadır. Uygulama derlenirken başvurulan tüm objeler ve bunlara ait tüm unsurlar bin dosyada yer alır. Çalışma sürecinde her hangi bir nesne her hangi bir süre tutabilir. Bazı nesneler her aşamada, bazıları da sadece bazı anlarda işleyebilir. Ama her birinde program ve değişkenler için tahsis edilen alan ayrı ve sabittir.

Objelerle program yazmaya alışkın olanlar açısından bu nokta önemlidir. Propeller'de bir objenin ömrü bellidir; belli bir anda aktif olarak kullanımda olsun veya olmasın, uygulamanın bin suretinde belli bir bellek işgal eder. Masaüstü veya dizüstü bilgisayarlarda objeler için dinamik bellek gerekir. Bunun sebebi objelerin çalışma esnasında "yaratılmaları" ve "yok edilmeleri" olgusudur. Oysa Propeller'de objeler sadece bir kez, o da derleme anında "yaratılırlar"; çalışma esnasında yaratma veya yok etme gibi işler tanımsızdır. Çünkü bu işler belleğin bölümlendirilmesini, o da embedded sistemlerde belirsiz, kontrol edilemeyen sonuçların doğmasına yol açar. Yani gereken her nesnenin derlemede hazır olması için OBJ bloğunda deklare edilmesi şarttır. Nitekim Alıştırma-8'de deklare edilen Output objeleri böyledir

Özet: Alıştırma-8

� Uygulamalar: o Her obje için ayrı dizi elemanları ve semboller kullanılır. o Nesne kodunun bir, genel değişkenlerin en az bir kopyası kullanılır.

� Objeler: o Obje dizileri OBJ bloğu içinde, değişken dizilerinin VAR bloğunda

yaratıldıkları gibi tanımlanırlar. o Objelerin işgal ettiği bellek daima -aktif olmasalar da- sabittir. Yani

normal çalışma anında bellek fragmantasyonu oluşmaz. Böylece olay-zamanlı sistemlerde davranış sorunları ortaya çıkmaz.

� Spin dili: o REPEAT komutu:

� Sonlu, sayılı döngü: REPEAT değişken FROM ilk TO son şeklindedir. Buradaki değişken sayaçtır. Başlangıç değeri ilk terimiyle, bitiş değeri de son ile verilir.

� QUIT komutu sadece REPEAT döngülerine hastır ve bir anda döngüden çıkılmasını sağlar.

o I/O yazmaçları (DIRx, OUTx, INx) bağlantılı pinler için reg[a...b] formunda yazılırlar. Buradaki reg terimi yazmacı, a ve b terimleri de

Page 36: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

94

I/O pinlerinin numaralarını temsil eder. (Bkz: DIRA, DIRB; OUTA, OUTB; INA, INB.)

� Cog başka belirlemediyse I/O pinleri daima çıkış olarak set edilirler. � Compile ve View Info: F8 veya Run → Compile Current → View Info…

ile çalıştırılır.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----9 : 9 : 9 : 9 : Saat ayarları

Propeller çipinin iç saati iki hızda çalışır: 20 KHz (yavaş) ve 12MHz (hızlı). Uygulamamızda geçerli olan ise, özel bir saat ayarı yapmadığımız için, 12 MHz (hızlı) olacaktır. Çünkü bu hız içsel RC'nin ön-ayarının gereğidir. Saati uygulamaya göre ayarlarken şef dosyanın CON bloğunda _CLKMODE, _CLKFREQ ve _XINFREQ sabitlerini tanımlamak gerekir. (Saat modu ayarları için Tablo 4-3'e bakınız.) Blinker2 ile çalışırken CON bloğunu aşağıdaki gibi değiştirmek, iç yavaş saatin kullanımı için saat modunun set edilmesi gerekir.

{{ Blinker2.spin }} CON _CLKMODE = RCSLOW 'Set to internal slow clock MAXLEDS = 6 'Number of LED objects to use

Derleyip yüklendikten sonra baştan başlatma da bitince Propeller RCSLOW (yavaş) saat moduna geçerek uygulamayı yürütmeye başlar. Öncekinden yüzlerce kat yavaş çalışan saat, uygulamayı da yavaşlatır ve (yanıp sönme nedeniyle) en hızlı dönen pinin 20 saniyede çalışmasına yol açar. Bunu gidermek için _CLKMODE=RCSLOW atamasını _CLKMODE=RCFAST -yavaş saati hızlısı- ile değiştirebilirsiniz. Eğer dış saat kullanırsanız _CLKMODE için daha çok seçeneğiniz var demektir. PDB ile gelen gibi 5Mhz'lik bir dış saatle çalışacağınızı varsayıyoruz.

{{ Blinker2.spin }} CON _CLKMODE = RCSLOW 'Set to internal slow clock _CLKMODE = XTAL1 'Set to ext. low-speed crystal XINFREQ = 5_000_000 'Frequency on XIN pin is 5 MHz MAXLEDS = 6 'Number of LED objects to use

Yukarıdaki satırlara göre saat modu dışsal düşük hızlı kristale (XTAL1) ayarlamış ve Propeller'in iç osilatör kazanç devresi de 4 ile 16 MHz kristali sürecek şekilde belirlenmiştir. Bu saat konfigürasyonu için XI ve XO pinlerine takılması gereken- kristalden başka bir devreye ihtiyaç yoktur. Harici kristal/saat kullanılırsa _CLKMODE yanında _XINFREQ veya _CLKFREQ'en biri gerekir. _XINFREQ ile XI (cristal giriş) bacağına gelen frekans; _CLKFREQ ile sistem saatinin frekansı verilir. Bunlar PLL ayarları üzerienden ilişkilidir, ki daha sonra ele alınacaktır.

Page 37: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

95

Koddaki 5 milyon değeri XI pinine uygulanan frekansı (5 MHz) gösterir. Çünkü XI ve XO pinlerine bu hızda bir kristal takılıdır. Bu tanım, _CLKFREQ değerinin otomatik olarak hesaplanıp Propeller tarafından tatbik edilmesini sağlar. Bunun yerine 5MHz'lik bir _CLKFREQ değerinin belirlenip _XINFREQ değerinin Propeller tarafından atanmasını beklemek de mümkündü. Ne var ki _XINFREQ değerini belirlemek daha yaygındır. Çünkü PLL ayarları _CLKFREQ değerini doğrudan etkiler. Yukarıdaki örnek de her ikisi de aynı kapıya çıkar. Ancak daha sonra farklı olabileceklerini de göreceğiz. Blinker2'yi bu haliyle derleyip yüklersek, LEDlerin Alıştırma-8'deki hızın yarısından biraz yavaş çalıştıklarını görürüz. Ayarlarımıza göre 12 değil 5 MHz kristal söz konusudur. Peki harici bir kristalin daha yavaş olması hangi mantıkla açıklanabilir? İki sebebi olabilir: 1) Doğruluk -çipe yahut voltaj değişimlerine bağlı olarak içsel saatin doğruluğu dışsal osilatörlere göre daha düşüktür; 2) Faz kilitli döngüler (PLL) sadece dışsal saatlerle kullanılır. Örnek:

{{ Blinker2.spin }} CON _CLKMODE = XTAL1 + PLL4X 'Set to ext low-speed crystal, 4x PLL _XINFREQ = 5_000_000 'Frequency on XIN pin is 5 MHz MAXLEDS = 6 'Number of LED objects to use

Burada _CLKMODE değeri PLL4X değerinin eklenmesiyle değiştirilmiştir. Böylece saat modunda PLL kullanarak XIN frekansının 4 katına çıkması sağlanmıştır (Sistem saat frekansı 20 MHz'e çıkar). Blinker2'yi bu halde derleyip yükleyin. LEDlerin daha hızlı yanıp söndüğü görülecektir. NOT: _XINFREQ belirlendiği için _CLKFREQ otomatik olarak 20 MHz hesaplanır. Bunun yerine _CLKFREQ için 5 MHz verip PLL4X ilâve etseydik, sonuç 1.35 MHz'lik _XINFREQ olurdu, ki bu da harici kristalin frekansına uymazdı. İşte bu nedenle saat (CLK) frekansı yerine XIN frekansı belirlemek daha yaygındır.

Saat PLL devresi, aktive olduğunda frekansı 16 katına çıkarır. Ancak, nihai sistem saati frekansı için PLL1X, PLL2X ayarlarıyla 1x, 2x, ... 16x değerinde vanalar seçebilirsiniz.

_CLKMODE değerini XTAL1+PLL4X'ten XTAL1+PLL16X'e çevirip programı yeniden derleyin. Bunun sonucunda sistem saati 5*16=80 MHz olacaktır. LEDlerin hepsi öyle bir süratle yanıp söneceklerdir ki, söndükleri fark edilmeyecektir.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----10 :10 :10 :10 : Saate-bağlı zamanlama

Son alıştırmada Ouput objemizin saat frekansından ne kadar kolay etkilendiğini fark etmişsinizdir. Bunun temelinde özgül, donanım kodlu zaman-bazı yatar. Ancak bağlı -şef olmayan- nesneler, kullanılacakları pek çok uygulamada saat frekansının ne olacağını kestiremeyecekleri için, saat frekansından etkilenmezler. Kaldı ki,

Page 38: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

96

sistem saati de uygulama tarafından çalışma sırasında pek çok kez değiştirilebilir.

Diyelim pinlerin saatten bağımsız dönmesini mümkün kılan bir Output yazmak niyetindeyiz. Bu durum objenin sistem saatinin frekansına dinamik olarak tepki vermesini gerektirir. Kodu aşağıdaki hale getirin.

Örnek obje: Output.spin

{{ Output.spin }} VAR long Stack[9] 'Stack space for new cog byte Cog 'Hold ID of cog in use, if any PUB Start(Pin, DelayMS, Count): Success {{Start new blinking process in new cog; return True if successful.}} Stop Success := (Cog := cognew(Toggle(Pin, DelayMS, Count), @Stack) + 1) PUB Stop {{Stop toggling process, if any.}} if Cog cogstop(Cog~ - 1) PUB Active: YesNo {{Return TRUE if process is active, FALSE otherwise.}} YesNo := Cog > 0 PUB Toggle(Pin, DelayMS, Count) {{Toggle Pin, Count times with DelayMS milliseconds clock cycles in between. If Count = 0, toggle Pin forever.}} dira[Pin]~~ 'Set I/O pin to output… repeat 'Repeat the following !outa[Pin] ' Toggle I/O Pin waitcnt(clkfreq / 1000 * DelayMS + cnt)' Wait for DelayMS…

while Count := --Count #> -1 'While not 0 (make min… Cog~ 'Clear Cog ID variable

Start ve Toggle metodlarındaki DelayDelayDelayDelay parametresini DelayMSDelayMSDelayMSDelayMS ile değiştirdik. Yani gecikme değerini mili-saniye (ms) cinsinden sayacağız. Ayrıca waitcnt...waitcnt...waitcnt...waitcnt... ifadesi artık sabit sayıdaki saat çevrimlerini beklemiyor fakat onun yerine (DelayMS parametresindeki ms cinsinden)saat çevrimlerinin sayısını hesap ediyor. CLKFREQ ise Hz (saniyedeki çevrim) cinsinden cari sistem saat frekansını döndüren bir komut. Değeri derleme sırasında Propeller Tool, çalışırken de CLKSET komutu tarafından set ediliyor (CLKSET komutuna bakınız). CLKFREQ saniyedeki saat çevrimlerinin sayısıdır. Bir saniye de 1'000 ms olduğuna göre, clkfreq/1000 * DelayMsclkfreq/1000 * DelayMsclkfreq/1000 * DelayMsclkfreq/1000 * DelayMs ifadesinin sonucu DelayMSDelayMSDelayMSDelayMS milisaniyedeki saat çevrim sayısıdır.

Page 39: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

97

Bu değişikliklerle uygulamanın başlangıç frekansından ya da uygulamanın çalışma sırasında frekansı kaç kere değiştirdiğinden bağımsız olarak, Output nesnesi döngüden her geçişte gerçek gecikmeyi yeniden hesaplayacaktır. Bu değişiklik Blinker2'deki gecikmede de uygun değişikliğin yapılmasını gerektirir. İzleyen satırlara uygun değişiklikleri yapın. Ayrıca _CLKMODE ve XINFREQ ayarları bir önceki alıştırmadakiyle aynı olduğunu hatırlatalım.

Örnek obje: Blinker2.spin

{{ Blinker2.spin }} CON _CLKMODE = XTAL1 + PLL4X 'Set to ext low-speed crystal, 4x PLL _XINFREQ = 5_000_000 'Frequency on XIN pin is 5 MHz MAXLEDS = 6 'Number of LED objects to use OBJ LED[6] : "Output" PUB Main {Toggle pins at different rates, simultaneously} dira[16..23]~~ 'Set pins to outputs LED[NextObject].Start(16, 250, 0) 'Blink LEDs LED[NextObject].Start(17, 500, 0) LED[NextObject].Start(18, 50, 300) LED[NextObject].Start(19, 500, 40) LED[NextObject].Start(20, 29, 300) LED[NextObject].Start(21, 104, 250) LED[NextObject].Start(22, 63, 200) '<-Postponed LED[NextObject].Start(23, 33, 160) '<-Postponed LED[0].Start(20, 1000, 0) 'Restart object 0 repeat 'Loop endlessly PUB NextObject : Index {Scan LED objects and return index of next available LED object. Scanning continues until one is available.} repeat repeat Index from 0 to MAXLEDS-1 if not LED[Index].Active quit while Index == MAXLEDS

Main metodundaki tüm Start çağrılarının ikinci parametresi "saat çevrimi cinsinden" gecikmeden "milisaniye cinsinden" gecikmeye çevrildi. Bu haliyle Blinker2'yi derleyin ve yükleyin. LEDlerin yanıp sönme süreleri içsel hızlı saat değerine uyar. _CLKMODE değerini 4x'den 16x'e (XTAL1+PLL16X'e) çevirin. Saat frekansını 4 katına çıkarmış olmamıza rağmen hiç bir fark görmemeniz gerekir. Ancak şunu

Page 40: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

98

aklınızdan çıkarmayın: Elinizdeki çipin içsel saatinin doğruluğu bu durumlarda önemli rol oynar. Bu en çok RCSLOW modda böyledir. WAITCNT komutu iki ayrı teknikle uygulanabilirse de biz burada birini gösterdik. (Bkz WAITCNT)

Özet : Alıştırma-9 ve -10

� Saat: o İç saat iki hızda çalışır: 20 KHz (yavaş) ve 12 MHz (hızlı). o Uygulamanın saat ayarları şef dosyada belli sabitlere (_CLKMODE,

_CLKFREQ ve XINFREQ) değer atayarak yapılır. o Harici kristal veya saat kullanılacaksa _CLKMODE'dan başka

_XINFREQ veya _CLKFREQ'den birinin belirlemesi şarttır. o _CLKMODE ile saat modu belirlenir (içsel/dışsal, osilatör kazancı,

PLL ayarları vb) o _XINFREQ kristal giriş bacağına (XI) gelen frekansı tayin eder. o _CLKFREQ sistem saati frekansını tayin eden sabittir. o Hassasiyet (accuracy) sorun değilse iç saat daha uygundur.

Hassasiyet önemliyse veya faz-kilidi döngüsü gerektiğinde harici saat uygundur.

� Zamanlama: o Uygulamanın saat frekansını değiştirebilmesi nedeniyle ast (bağlı,

memur) objeler belli, donanım kodlu zaman bazına uyamazlar. o Zamanlama ayarı yaparken yürürlükteki sistem saati frekansını

Hertz cinsinden almak için CLKFREQ komutu kullanılır.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----11:11:11:11: Kitaplık nesneleri

Propeller Tool'da Parallax tasarımcılarının hazırladığı yararlı pek çok kitaplık nesnesi yer alır. Bunlar seri komünikasyon, oynak-nokta işlemleri, sayıdan karaktere çevrim, karakterden sayıya çevrim, TV’de görüntüleme , PC tarzı klavye-fare-ekran kullanımı vb başka nesnelerdir. Propeller Object Library bir klasördür. Tool'un kurulumu sırasında oluşturulur. Nesne dosyalarını içerir. Erişmek için Recent Folders listesinden "Propeller Library" seçilir. (Şekil 3.18.) Seçim yapılınca açılan dosya listesi tüm nesneleri içerir.

Şekil 3.18 : Propeller Library bakışı. Integrated Explorer'ın Recent Folders listesinden Propeller Library maddesini seçin.

Yeni bir dosya yapın ve aşağıdaki kodu girin. Seçili kısımlar kodla ilgili değerlendirmede ele alınacaktır.

Page 41: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

99

Örnek obje: display.spin {{ Display.spin }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 OBJ Num : "Numbers" TV : "TV_Terminal" PUB Main | Temp| Temp| Temp| Temp Num.InitNum.InitNum.InitNum.Init 'Initialize Numbers TV.Start(12)TV.Start(12)TV.Start(12)TV.Start(12) 'Start TV Terminal Temp := 900 * 45 + 401 'Evaluate expression TV.StrTV.StrTV.StrTV.Str((((stringstringstringstring("900 * 45 + 401 = ")) 'then display it and TV.Str(Num.ToStrNum.ToStrNum.ToStrNum.ToStr(Temp, Num#DDECNum#DDECNum#DDECNum#DDEC)) 'its result in decimal TV.Out(13)TV.Out(13)TV.Out(13)TV.Out(13) TV.Str(string("In hexadecimal it's = ")) 'and in hexadecimal TV.Str(Num.ToStr(Temp, Num#IHEX)) TV.Out(13) TV.Out(13) TV.Str(string("Counting by fives:")) 'Now count by fives TV.Out(13) repeat Temp from 5 to 30 step 5 TV.Str(Num.ToStr(Temp, Num#DEC)) if Temp < 30 TV.Out(",")

Bu satırları girin ve display.spin adıyla bir kaydedin. Biz bu projede "C:\Source" klasörünü kullandık. Örnekte iki Propeller objesinden yararlanıyoruz: Numbers ve TV_Terminal. Bunlarla sayıları karaktere çevirip TV'de görüntülüyoruz. Derleme ve yüklemeden sonra bir TV (NTSC) monitörünü PDB'nin kompozit çıkışına (RCA jakına) takın. Ekranda, aşağıdaki metnin görünmesi gerekir:

900 * 45 + 401 = 40,901

In hexadecimal it's = $9FC5

Counting by fives:

5, 10, 15, 20, 25, 30

Bakın ne yapmış olduk! Bir kaç satır kod yazdık. İki kitaplık nesnesi ve PDB'deki üç direnç ile sayıları metne çevirdikten sonra, metni standart TVde görüntülemek üzere bir TV-uyumlu sinyal ürettik. Nitekim şu anda coglardan biri saniyede 60 karelik bir NTSC sinyali üretmeye devam ediyor.

TV_Terminal objesi hataları ayıklama açısından müthiş bir olanak sağlar. Propeller çok sayıda işlemcisiyle çok hızlı çalışabileceği için, hata ayıklamada kullanılacak TV (CRT veya LCD) monitörü gibi gerçek zamanlı bir gösterici, en elverişli kaynak kodunu geliştirmek açısından bir hayli yararlıdır.

Page 42: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

100

Şimdi yukarıda resim olarak sunulan kodun önemli kısımlarına göz atalım. Bunların ilki Main metodunun deklarasyon satırındaki | Temp| Temp| Temp| Temp ifadesidir. Bu ifade dönüş değişkeni bildirimi gibi görünse de, öyle değildir. İfadenin solundaki dik çubuk sembolü takip eden değişkenlerin lokal olduğunu anlatır. Dolayısıyla TEMP terimi lokal bir değişkendir. Long boyutludur. Main metodu dışında tanımsızdır.

Diğer önemli kısımlardan ikisi Num.InitNum.InitNum.InitNum.Init ile TV.Start(12)TV.Start(12)TV.Start(12)TV.Start(12)'dir. Bu terimler sırasıyla Numbers nesnesini başlatır ve TV_Terminal objelerini çalıştırırlar (Pin 12, 13 ve 14 üzerinde). Bu objelerin kullanılabilmeleri için önce başlatılmaları (initialize) gerekir. Numbers objesi için Init metodu çağrılarak bazı iç yazmaçlar çalıştırılır. TV_Terminal için de Start metodu çağrılarak doğru çıkış bacakları konfigüre edilir ve görüntü sinyallerini üretecek iki cog işe koşulur. Böyle gerekler varsa, nesnelerin dokümanlarında gösterilir. Ancak, kullanılmadan önce başlatılması gereken objeler için hazır bir INIT veya START metodunun olması çok yaygındır.

Bir sonraki satırda, söz konusu lokal değişkene bir aritmetik işlemin sonucu aktarılır. Bu sonuç az ileride ele alınacaktır.

Bunu izleyen üç satır TVdeki görüntünün ilk satırını üretir: 900 * 45 + 401 = 40,901. TV.Str metodunun çıkışı ise görüntülenecek sıfır-sonlu stringdir. Bunun parametresi olan string("900 + 45 + 401 = ")string("900 + 45 + 401 = ")string("900 + 45 + 401 = ")string("900 + 45 + 401 = ") yeni bir durumdur. STRING yönergesi sıfır-sonlu karakter katarları (z-stringler) oluşturmaya yarar. Bunlar sonunda sıfır olan muhtelif baytlardan oluşur ve o stringin adresini döndürürler.

Stringlerle ilgili metodlar için stringin ilk karakterinin adresi gerekir. Ayrıca stringin son terimi de sıfırı işaret eden bayt olmalıdır. Nitekim TV.Str metodunun parametresi de tam böyledir. Dolayısıyla TV.Str(string("900 * 45 + 401 = "))TV.Str(string("900 * 45 + 401 = "))TV.Str(string("900 * 45 + 401 = "))TV.Str(string("900 * 45 + 401 = ")) satırı, tırnak içindeki kısmın TV ekranında görünmesini sağlar. Sonraki cümle, yani TV.Str(Num.ToStr(Temp, Num#DDEC))TV.Str(Num.ToStr(Temp, Num#DDEC))TV.Str(Num.ToStr(Temp, Num#DDEC))TV.Str(Num.ToStr(Temp, Num#DDEC)) ile işlemin sonucuna karşılık gelen 40,901 kısmı görüntülenir. İzleyen Num.ToStr metodu ise, sınırlanmış desimal format yardımıyla Temp değişkeninin değerini stringe çevirir ve bu stringin adresini döndürür. Temp'in değeri önceki ifadenin long boyutlu sonucu olan 40901'dir. Satırın sonundaki Num#DDECNum#DDECNum#DDECNum#DDEC de yeni bir terimdir. Buradaki # işareti bu şekilde kullanıldığında obje-sabitinin referansıdır. Başka bir objede tanımlanmış bir sabite referans vermek için kullanılır. Bu örnekte Num#DDECNum#DDECNum#DDECNum#DDEC "format" sabiti olan DDEC'e atıfta bulunur. DDEC ise Numbers objesinde deklare edilmiştir. Numbers içinde tanımlı şekliyle DDEC sınırlı desimal (Delimited Decimal) anlamına gelir ve ToStr metoduna şunu söyler: Gönderilen sayıyı bin haneler şeklinde (virgül ile) düzenle! Böylece ToStr "40,901" şeklinde görünen bir z-string oluşturur ve adresini döndürür. Bundan sonra TV.Str ile bu string TVye yollanır. (Format sabitleri konusunda daha fazla bilgi için Numbers objesinin dokümanlarına başvurunuz.) TV.Out(13)TV.Out(13)TV.Out(13)TV.Out(13) ile tek bayt, 13, yani enter tuşuna karşılık gelen görünmez "carriage

Page 43: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

101

return" karakterinin ASCII değeri gönderilir. Böylece TV_Terminal nesnesinin bir sonraki metin için izleyen satır konumlanması sağlanır.

Çalışma ve Kitaplık klasörleri

Display nesnesi derlendiğinde yapısı Object View içinde görünür. Görünüm şekildeki gibi olmalıdır.

Şekil 3.19 : Display uygulamasının nesne görünümü. Tepedeki klasör sarı renklidir ve work (çalışma) klasöründeki objeleri anlatır. Alttaki klasörler mavidir ve library (kitaplık) klasöründeki nesneleri gösterir.

Nesne görünümünde her nesnenin solundaki ikonların renkleri, nesnelerin ait oldukları klasörleri anlatır. Sarı ikon, yanındaki nesnenin çalışma klasöründe olduğunu; mavi de kitaplık klasöründe olduğunu gösterir. Şekle göre Numbers, TV_Terminal , TV ve Graphics objeleri kitaplık klasöründedir. Display ise çalışma klasöründe yer alır. Display objesini C:\Source klasörüne kaydettiğimizi söylemiştik. Bir uygulama derlendiğinde, şef dosyanın kayıtlı olduğu klasör çalışma klasörü olur. Bu dosyanın referans verdiği dosyalar için Propeller Tool önce çalışma klasörüne bakar. Eğer nesneler burada yoksa Tool bu kez bu kez kitaplık klasörünü arar. Eğer kitaplık klasöründeki bir nesne başka bir dosyaya atıfta bulunuyorsa, bu dosya da kitaplık klasöründe aranır. Gerek kitaplık gerekse çalışma klasöründe olsun, bakılan nesne bulunamadığında hata meydana gelir.

Özetle, bir uygulama için çalışma ve kitaplık şeklinde daima iki klasör söz konusudur. Uygulama geliştirirken bunu asla akıldan çıkarmayın. Fareyi bu nesnelerin üzerinde tutarsanız, her birinin fiziksel konumunu öğrenebilirsiniz. Aşağıdaki Şekil 3.20 bu durumu tasvir etmektedir: Fareyi Display (yani çalışma klasörü) üzerinde tutarsanız C:\Source\Display.spin; Numbers (yani kitaplık klasörü) üzerine getirirseniz C:\Program Files\Parallaz Inc\Propeller Tool\Numbers.spin görünecektir.

Page 44: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

102

Şekil 3.20 : Obje görünümünde Display uygulamasının fiziki yerleşimi. Çalışma ve kitaplık klasörlerinin yerlerini böyle öğreneblirsiniz.

AlıştırmaAlıştırmaAlıştırmaAlıştırma----12: 12: 12: 12: Tam ve gerçek sayılar

Propeller 32 bitlik bir cihazdır. -2,147,483,648 ile 2,147,483,647 aralığındaki eksi ve artı işaretli tamsayıları hem sabitler hem de çalışma sırasındaki matematik ifadeler olarak işleyebilir. Ancak, tam ve kesirli bölümlerden oluşan gerçek sayılar söz konusu olduğunda, sabitler için IEEE754 uyumlu tek duyarlıklı oynak-nokta (floating-point) formatı geçerliyken, çalışma anındaki matematiksel ifadeler için oynak nokta işlemlerine yönelik kitaplık objelerinden yararlanılır.

Sahte-gerçek (pseudo-real) sayılar

Gerçek sayılarla uğraşmanın çeşitli teknikleri vardır. Bir tanesi şudur: Çalışma anındaki ifadelerde oluşan gerçek sayıları temsil eden tamsayı matematiğine baş vurmaktır. Böyle temsili gerçek sayılara burada sahte-gerçek sayılar diyeceğiz.

Propeller'in 32 bit kapasitesi hesaplamalarda büyük kolaylık sağlar. Örneğin şöyle bir denklemle çalışıyor olalım:

A = B * C / D

Örneğe uygunluğu açısından A = 7.6 * 38.75 / 12.5 = 23.56 olduğunu kabul edebiliriz. Çalışma anında sonuç elde etmek üzere tüm değerleri iki hane saha kaydırmak için 100 ile çarpacağız. Böylece her değeri tamsayı değere çevireceğiz:

A = (B* 100) * (C * 100) / (D * 100)

A = (7.6 * 100) * (38.75 * 100) / (12.5 * 100)

Page 45: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

103

A = 760 * 3875 / 1250

A = 2356

Her değeri 100 ile çarptığımızı bildiğimiz için sonucun 23.56 olduğunu biliriz. Buna rağmen sonucu tamsayı olarak tutmaya devam ederiz. Bu tekniğin işlemesi için elde edilecek sonucun [-2,147,483,648 - 2,147,483,647] aralığında kalması şarttır. Örnekte hem sahte gerçek-sayılar hem de oynak noktalı sayılar tekniği yer alır.

Oynak nokta (floating-point) aritmetiği

Pek çok durumda gerçek sayılarla ilgili çözümlerde oynak nokta matematiğine gerek kalmaz. Yani örneğin sahte gerçek-sayılar tekniği yeterli olabilir. Üstelik böylece işlem hızı ve bellek tasarrufu en yüksek düzeyde gerçekleşir. Bu yüzden oynak noktaya gerek olup olmadığına karar vermek büyük dikkat gerektirir. Oynak nokta tekniğinin iyi bir çözüm olması için kodun icra süresi ve bellek kullanımı makul ölçüler içinde kalmalıdır.

Propeller Tool oynak noktalı sabitlere dolaysız destek sağlar. Çalışma sırasındaki eşitliklerle baş etmek için de çeşitli objelerden yararlanılır. Örneğin program çalışırken Spin Interpreter sadece tamsayı eşitlikleri doğrudan işleme koyabilir. Son objemiz olan RealNumbers.spin, önceden sahte gerçek-sayılar mahiyetindeki tamsayı sabitleri ile oynak noktalı sabitleri sergiler. Burada oynak nokta işlemleri için kitaplık nesnelerinin kullanılması yanında, oynak noktalı sabitlerin sahte gerçek-sayılara çevrilişi de yer alır. (iB, iC ve iD tamsayı sabitler; B, C ve D oynak-noktalı sabitlerdir. K gerçek-sayıdan sahte gerçek-sayıya çevrim çarpanıdır.)

Örnek obje: RealNumbers.spin

{{ RealNumbers.spin}} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 iB = 760 'Integer constants iC = 3875 iD = 1250 B = 7.6 'Floating-point constants C = 38.75 D = 12.5 K = 100.0 'Real-to-Pseudo-Real multiplier OBJ Term : "TV_Terminal" F : "FloatMath"

Page 46: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

104

FS : "FloatString" PUB Math Term.Start(12) {Integer constants (real numbers * 100) to do fast integer math} Term.Str(string("Pseudo-Real Number Result: ")) Term.Dec(iB*iC/iD) {Floating-point constants using FloatMath and FloatString objects} Term.Out(13) Term.Str(string("Floating-Point Number Result: ")) Term.Str(FS.FloatToString(F.FDiv(F.FMul(B, C), D))) {Floating-point constants translated to pseudo-real for fast math} Term.Out(13) Term.Str(string("Another Pseudo-Real Number Result: ")) Term.Dec(trunc(B*K)*trunc(C*K)/trunc(D*K))

Programı çalıştırınca TVdeki görüntü şu olmalıdır:

Pseudo-Real Number Result: 2356

Floating-Point Number Result: 23.56

Another Pseudo-Real Number Result: 2356

Sahte gerçek-sayılarda değer iki hane kaymış olarak temsil edilmektedir. Aslında noktalı görünümü elde etmek için ek olarak bir kaç satır yazmak yeter. iB, iC ve iD daha önceden bilinen tamsayı sabitlerdir. Ancak program gereğince noktalı sayıları temsil ederler. B, C, D ve K gerçek sayılar olup oynak noktalı sabitlerdir. Tanımlanışları gereğince derleyici tarafından 32 bit tek duyarlıklı oynak nokta formatında algılanırlar. Çalışma anında oynak-nokta metodları olarak kullanılmaları gerekir. Term.Dec(iB*iC/iD) ifadesi önceden tanımlanmış sahte gerçek-sayı sabitlerini içerir. Buradaki işlem süresi oynak nokta işleme sürecinden 1.6 kere daha hzılıdır ve çok daha az bellek işgal eder.

Öte yandan Term.Str(FS.FloatToString(F.FDiv(F.FMul(B, C), D))) ifadesinin işi (iç parantezden dışa doğru) sırayla oynak nokta metodlarını çağırmaktır: Önce FMul ile B*C'yi yapar; sonra FDiv ile çarpımın sonucunu D'ye böler; ardından sonucu FloatString metodu ile sonucu stringe çevirir; son olarak da sonucu TVde gösterir.

Term.Dec(trunc(B*K)*trunc(C*K)/trunc(D*K)) ifadesi ile yapılan da şudur: TRUNC yönergelerinin içindeki sabitleri noktalarını iki hane sağa kaydırarak tamsayılara çevirir. Sürecin çıkışı Term.Dec(iB*iC/iD) ifadesinin sonucuyla aynıdır. Ancak bir avantajı vardır: İç terimlerin değerlerinin oynak noktalı tanımlanmasına izin verir. TRUNC yönergesi ile tam olarak çözülmüş oynak noktalı ifadelerin

Page 47: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi

Propeller “El Kitabı„

105

derleme anında tamsayı formlara yuvarlanması sağlanır. Burada kullanılması şarttır. Çünkü, oynak noktalı değerler çalışma anındaki ifadeler tarafından doğrudan kullanılamazlar.

Bir nesne derlenince, işaretçinin civarında olduğu cismin derlemeyle ilgili içerik bilgileri durum çubuğunda (panel 5'te) gösterilir. Bu sayede objede deklare edilen sabitlerin değerlerini izlemek ve kontrol etmek mümkündür. Örneğin bu kodu F9 (veya menüden Run → Compile Current → Update Status) ile derleyin ve işaretçiyi CON bloğundaki iB sabitinin üstüne götürün. Durum çubuğunda aydınlatılmış kısım (CON iB = ...) aşağıdaki gibi olmalıdır:

Şekil 3.21 : Derleme bilgisinin göründüğü durum çubuğu. Derlemeden sonra çubuğun beşinci panelinde, işaretçiye en yakın unsur hakkındaki bilgi görünür.

Buna göre iB, CON bloğuna ait ve 760 DEC (veya $2F8 HEX) değerli bir sabittir. Şimdi işaretçiyi B'nin üstüne götürün. Bu kez yer alacak bilgi şöyledir: CON B = 7.6 ($40F3_3333) Floating Point. Yani, B, CON bloğunda 7.6 DEC değeriyle tanımlanmış bir oynak noktalı sabittir.

Oynak noktalı değerler 32 bitlik olup tamsayı değerlerle bağdaşıklık göstermezler. Çubuktaki derleme bilgilerinde ayrıca blokların bayt cinsinden boyutları da gösterilir. Örneğin işaretçi Math metodu kapsamında bir noktaya gittiğinde, çubuk 196 bayt gösterir. Bu sayede kod üzerinde değişiklik yaparak yerden tasarruf edebilirsiniz.

Özet: Alıştırma-11 ve -12

� Propeller kitaplığı: o Propeller Tool'un kurulumu sırasında otomatik olarak yaratılan bir

klasördür. o Çeşitli işleri gören Parallax tasarımı Propeller objelerini içerir. o Recent Folder listesindeki Propeller Library ile hızla erişilir.

� Spin dili: o Metod deklaresindeki dik çubuk sembolü, metod içinde tanımlı

(lokal, yerel) değişkenlerin deklaresinde kullanılır. o STRING yönergesi ile sıfır-sonlu stringler yaratılır ve adresleri alınır. o # (obje-sabiti) sembolü, başka objelerdeki sabitlere referans

verilirken kullanılır. o TRUNC yönergesi oynak noktalı sabitleri tamsayıya yuvarlamada

kullanılır. � Çalışma ve kitaplık klasörleri:

Page 48: Propeller El Kitabı - 3.Bölüm - Propeller Rehberi

Bölüm 3: Propeller rehberi Propeller “El Kitabı„

106

o Obje görünümündeki ikonlar nesnenin yerini belirtir. Sarı klasörler çalışma; maviler ise kitaplık klasörleridir.

o Her uygulamanın bütün dosyaları iki klasörden birinde, ya çalışma ya da kitaplık klasöründe yer alırlar.

� Tamsayılar ve gerçek-sayılar: o Tamsayılar hem sabitler hem de eşitlikler için geçerlidir. o Oynak noktalı gerçek-sayılar sabitlerde yer alabilirlerse de, çalışma

anında eşitliklerde kullanılmaları kitaplık objelerinin yardımıyla mümkündür.

o Gerçek-sayılar içeren çoğu eşitliğin (veya ifadenin) çözümünde oynak nokta teknikleri dışında teknikler de kullanılabilir.

o İşaretçinin civarında durduğu terimle ilgili derleme bilgisi durum çubuğunda gösterilir. CON/DAT blok sembollerinin boyut ve adresleri ile diğer PUB/PRI/DAT bloklarının boyutları bu bilgiler arasındadır.

Bir sonraki basamak... Bir sonraki basamak... Bir sonraki basamak... Bir sonraki basamak...

Şu an bulunduğunuz nokta itibariyle Propeller çipini kavramak ve uygulama geliştirmek için gereken bilgiye sahipsiniz! El Kitabı'nın sonraki bölümleri Spin ve Assembly dilleriyle ilgili formel bilgileri içermektedir. Propeller'i en etkili şekilde kullanabilmek için mevcut bütün kitaplık objelerini iyice öğrenin. Bunlar ve başka konularla ilgili güncel bilgilere ulaşmak, kendi sahip olduklarınızı diğer Propeller kullanıcılarıyla paylaşmak için Propeller Forum'a katılın.