You are on page 1of 94

stanbul niversitesi Mhendislik Fakltesi BLGSAYAR MHENDSL BLM

NI DAQ ARABRM TASARIMI

Yneten: Hazrlayan:

Yard. Do. Dr. Mustafa DATEKN Hseyin KOZAN (1306040082)

DPLOMA PROJES

Haziran 2009

NDEKLER
NDEKLER VE EKL LSTES ZET ABSTRACT 1. GR 2. KULLANILAN ARALAR 2.1. rnekleme Teorisi 2.2. DAQ Kart 2.3. Neden DAQ Kart ? 2.4. NIDAQmx Src Yazlm 2.5. DAQCard 6062E 2.6. NIDAQmx Src Yazlm Kullanm 2.7. Qt 2.8. Qwt 2.9. Gelitireme Ortam : IDE 2.10. Filtreler 2.10.1. FFT 2.10.2. Ortalama 3. YNTEM 3.1. Bilgi Toplama 3.2. Aralarn Kurulumu 3.3. rneklerin Derlenmesi 3.4. Programn Oluturulmas SONU KAYNAKLAR EKLER EK A KAYNAK KODLARI EK B QMAKE PROJE DOSYASI EK C LSANS 1 2 2 2 3 3 5 6 6 8 9 10 11 12 16 16 17 18 18 19 19 19 23 23 24 24 84 85

EKL LSTES
ekil 1 : Nron kayt cihaz ekil 2 : DAC Sinyal kts ekil 3 : MAX ile sanal src eklenmesi ilemi 3 5 7

2 ekil 4 : DAQCard 6062E emas ekil 5 : Ktphane dosyas dnm ilemi ekil 6 : Qwt rnekleri ekil 7 : Creator ekran grnts - Kod ekil 8 : Creator ekran grnts - Designer ekil 9 : rnek Proje Dosyas ekil 10 : Ortalama Filtresi ekil 11 : Yeni lm diyalog penceresi ekil 12 : Ayarlar Diyalog Penceresi ekil 13 : Medaq ana penceresi Veri alma ekil 14 : Medaq ana penceresi Filtreler 9 10 11,12 13 14 15 17 22 23 24 25

ZET
Proje ile National Instruments firmasnn rettii ve NIDAQmx srcs ile destekledii veri toplama kartlarndan analog sinyal kaydetme ve kaydedilmi veriyi ykleme, dijital klardan saat darbesi gnderme, analog ktan istenen gerilim deerini karma ilemlerini gerekleyecek C++ grafik arabirimi tasarlanacaktr. Ayrca kaydedilen analog sinyalin stnde ortalama alma ve FFT dnm gibi sinyal ilemleri de gerekletirilebilecektir.

ABSTRACT
With this project a C++ graphical user interface will designed for data acquisition cards which are produced by National Instruments and supported by their NIDAQmx software driver to collect, save and open saved analog waveforms, produce clock pulse from digital outputs, and produce desired output voltage from analog output. And also some signal processing businesses will take place on saved waveforms like averaging and FFT transform.

1. GR
Gnmzde retilen dijital veri alma kartlar reticilerin sunduu kullanm ve programlanmas kolay yazlm ortamlar ile desteklenmektedir. Bu yazlm ortamlar genellikle reticinin tm rnlerini desteklemekte ve bu rnler ile temel sinyal ileme fonksiyonlar ve kendi grsel program tasarm ortamlarnn yan sra .NET Framework ve ANSI C programlama ktphaneleri ile donanm srcsne programsal olarak erimeye

3 olanak salamaktadrlar. reticilerin programlama ortamlar her ne kadar avantajl gibi grnse de programlama ortamlarnn ve dier ticari paketlere verilen destein birer rn olarak sunulmas ve maliyetinin yksek olmas kullanclar baka araylar iine sokmaktadr. Artan maliyetten belki daha da nemlisi kullanlmak istenen i iin program arayznn o ie adanm olarak sunulamamas olabilir. Bu proje ile zellikle maliyet unsurundan etkilenmeden kullancya yapaca deneyde kullanm kolay bir arayz ile ilemlerini kolaylatrmak amacn gtmekteyiz. Projede programlama maliyetini arttran lisansl gelitirme ortamlar yerine ak kaynak kodlu olan Qt programlama ktphanesi ve veri alma kartnn (DAQCard Data Acquisition Card) reticisinin cretsiz sunduu ANSI C src ktphanesi kullanlmtr. Yaplacak olan proje ile desteklenecek olan proje, bir nron kayt cihazndan gelen verileri analiz ederek kuvvetlendirici tasarm gelitiren bir projedir. Bu projede canl nron hcrelerinden gelen verilerin minimum hata ile elde edilmesi iin tasarlanp retilen devre emas ekil 1'deki gibidir.

ekil 1 : Nron kayt cihaz

2. KULLANILAN ARALAR 2.1. rnekleme Teorisi


rnekleme, srekli bir sinyalin belirli aralklarla llerek ayrk bir sinyale

4 dntrlmesidir. Havada yaylan ses dalgas ya da gzlerimizle algladmz ve grmemizi salayan k huzmeleri birer srekli sinyallerdir. Sesin bir dijital kayt cihaznda analogdijital dntrc yardm ile dijitale evrilmesi, n fotoraf makinesi ile bir annn kayt edilmesi birer rneklemedir. lm yaplmak istenen frekansn doru bir ekilde elde edilebilmesi iin istenen frekansn en az iki kat hzda lm yaplmas gereklidir. Bu olgu Nyquist-Shannon lme Teoremi [Ny] olarak da bilinen u teorem ile aklanr; Eer bir x(t) fonksiyonu B'den daha fazla bir frekansa sahip deilse fonksiyonun deeri saniyede 1/(2B) aralklarla tam olarak elde edilebilir. Teoremden de anlalaca zere rnekleyici cihazn rnekleme frekans (ya da rnekleme oran) rneklenmek istenen sinyalin frekansnn iki kat frekansta olmak zorundadr. rnekleme frekansnn yars olan bu frekansa nyquist frekans (fN) denir. Nyquist frekansnn zerindeki sinyallerin rneklenmesi durumunda rneklenen frekans belirsizdir. Bu yzden bir f frekansndaki bileenler (N, sayma saylar olmak zere) N fN + f ve N fN f frekansndaki bileenler tarafndan alglanamazlar. Bu belirsizlie rtme (aliasing) denir. Bu problemi olabildiince azaltabilmek iin analog sinyale lm yapmadan nce rtme nleyici (anti-aliasing) filtre (ya da ounlukla alak geirgen filtre low-pas filter) uygulanr. rneklemenin bu temel teoremi dnda ideal olmayan bir analog-dijital evirici (ADC Analog Digital Converter) aygtnn da snrlamalar vardr. Bunlardan biri rneklemenin anlk bir zamanda deil de bir zaman aralnn ortalamas olmasdr. Bu fiziksel bir kstlamadr. Kapasitr tabanl rneklemede kapasitrn geriliminin anlk olarak deitirilememesinden kaynaklanr. Bir dier snrlama da sensrlerin ve analog devrelerin kendisinin rettii grltlerdir. Bir dieri de ADC ktsnn yeterli hzda donanm tamponundan alnamayarak ADC'nin belleini aan verilerin alnamamasdr. Bir dieri de lm sonrasnda retilen deerlerin snrl sayda bit ile ifadesinden kaynaklanan hassasiyet derecelendirmesinin yetersiz kalmasdr. Analog-dijital evrim ileminin tersi olan dijital-analog evrim ileminin de baz fiziksel snrlamalar mevcuttur. Bunlardan analog devre grlts, yeterli hzda dnm gerekletirilememesi gibi bazlar ADC'nin snrlamalarna benzerler. Bir baka snrlama ise k sinyalinin anlk deiimler yerine dikdrtgensel deiimler ile sinyalin oluturulmas

5 sonucunda kazancn debilmesidir. Bir DAC'nin rnek sinyal kts ekil 3'teki gibidir.

ekil 2 : DAC Sinyal kts

2.2. DAQ Kart


DAQ, Data Acquisition kelimelerinin ksaltlm halidir ve Trke'ye veri toplama olarak evrilebilir. Veri toplama kartlar doada bulunan verileri toplayp bilgisayarda ilenebilecek hale evirirler. Bu ilem aamada zetlenebilir. Birinci safhada fiziksel ortamdaki zelliklerin gerilim, akm gibi elektriksel halde ifade edilebilecek ekle getirmelidirler. Bu ilem sensrler aracl ile yaplr. Sensrlere rnek olarak; mikrofon, fotosel, gerilim ler, termistr gibi yaplar verilebilir. kinci safhada sensrlerden gelen ve analog olan sinyallerin ykseltilip veya alaltlp rneklenerek bilgisayara gnderilmesidir. Ykseltme ve alaltma ilemi sensrden sonra gelen bir elektronik devre ile gerekletirilebilecei gibi DAQ kart yardm ile de izin verilen lde gerekletirilebilir. rnekleme ilemini ise DAQ kartnn iindeki ADC (Analog Digital Converter Analog Dijital evirici) yardmyla gerekletirilir. nc safhada toplanan dijital verinin iinden istenen zelliklerinin karlmasdr. Bu ilem dijital veri stnde alan yazlmlarn yardm ile olabilecei gibi ikinci safhada olan DAQ kartnn programlanarak istenen zellikte (belirli zaman aralklaryla, belirli frekans altnda/stnde...gibi) verilerin elde edilmesi ile de gerekletirilebilir. DAQ kart ile ilgili buraya kadar bahsedilenler daha ok analog verinin alm ile ilgili olan ksmlardr. Bu tr kartlar sadece analog veri alm ile snrl kalmazlar. Dijital veri

6 alm/gnderimi ve analog veri gnderimi ilemlerini de yapabilirler. Ayrca barndrdklar zamanlayc (timer), sayc (counter) gibi yaplar da veri almada ve vermede kolaylklar salamaktadrlar. Bu tr kartlarda toplanan verinin aktarm iin gerekli sre bekletilmesi ve/veya kartn programlanmas iin yeterli miktarda bellek bulunur. Bilgisayar ilemcisi ya da veri yolu ile haberleirken kesme ynetimli (interrupt), programlanm giri/k (programmed I/O) veya dorudan bellek eriimi (DMA) yntemleri kullanlarak srekli gelen verinin srekli (realtime) alamayan bilgisayar mimarisi ile en verimli ekilde almas salanr. Kartlar zerindeki mikrokontrolrleri programlamada ve/veya bilgisayarda alan iletim sistemi ile cihazdan veri alm esnasnda yaplan programlamada, reticiler programlama arabirimleri (API) sunarlar. Salanan bu arabirimler sayesinde programlama ilemi kolaylatrlr.

2.3. Neden DAQ Kart ?


DAQ kartlar veri toplama iin tek yol deildirler. Daha ok otomasyonda kullanlan PLC (Programmable Logic Contoller Programlanabilir Lojik Kontrolc) ve mikrokontrolrler de (PIC, AVR ... vs) veri toplama ilemi iin kullanlabilir. Sanayide oka kullanlan PLC, manyetik alan, byk scaklk farklar ve tozlu ortamlar gibi zor koullara dayankl rnlerdir. erisinde ADC, a modlleri barndran PLC modlleri bilgisayara balanarak veri toplama ilemi yapabilmesine ramen DAQ kartlarndan dk olan rnekleme hzlar ve esnek olmayan programlama olanaklar sebebiyle tercih edilmemitir. Alt dzey programlama ve rnekleme iin zel olarak devre tasarm gerektiren mikrokontrolrlerin programlama ve zel devre gereksinimi sebebiyle tercih edilmemilerdir. Test ve lme ilemlerini kolaylatran DAQ kartlar veri toplama iin en uygun sistemlerdir.

2.4. NIDAQmx Src Yazlm


Bahsi geen deneyde kullanlmas planlanan DAQ kart olan NI DAQCard 6062E iin gerekli olan src yazlm NIDAQmx'tir [NIDAQmx]. Src ile birlikte .NET Framework destei, Labview destei, LabWindows destei, Microsoft Visual Studio C++ iin Measurement Studio destei ve ANSI C destei yannda Measurement & Automation Explorer (MAX) yazlm da gelmektedir.

7 MAX (Measurement & Automation Explorer) ile var olan National Instruments firmasna ait fiziksel veri alma donanmlarnn srclerini ynetmek dnda, lmde kullanlacak yaplandrmay ieren grevler oluturma, sanal srcler oluturup cihazlara ait testler ve kalibrasyonlar yaplabilmektedir. MAX yardm ile bir simle edilmi srcnn eklenmesi aadaki ekillerde gsterilmitir.

ekil 3 : MAX ile sanal src eklenmesi ilemi

Simle edilmi sanal srcler baz kstlamalar ve nceden belirlenmi ayarlar ile gelmektedir. Bunlardan bazlar u ekildedir: Simle edilmi aygt, fiziksel bir aygt ile ayn grevde (task) kullanlamaz. Analog giri sinyali %3 grlt oranna sahip bir sins sinyali ile simle edilmitir. Bir grevde (task) birden fazla analog giri kanal kullanlm ise her kanaldaki sins sinyali zaman dzleminde 5 kaydrlarak simle edilir. Dijital giri portuna birer sayc balanmtr. Sayc ilemi grevlerde simle edilmez. Sayc verisi her zaman 0 olarak okunur. Aygtn almas iin zamanlanm bir dng kullanlamaz. Donanma bal olay tetikleyicileri almaz (rnekleme saat olay sample clock event) Gzc saatinin (wachdog timer) sresi dolmaz.

Src yazlm ile birlikte gelen ANSI C desteini salayan ktphane ve balk dosyasnn yannda baz temel ilemlerin rnek kodlar ve NIDAQmx C referans Yardm dosyas da gelmektedir.

2.5. DAQCard 6062E


Bu projeni destek verdii deneyde kullanlmas planlanan DAQ kart National Instruments firmasnn DAQCard 6062E modelidir [6062E]. Kart, PCMCIA formda olup aadaki zellikleri barndrr: 1 adet 12 bit ADC. 2 adet 12 bit DAC. 8 hat Dijital I/O. 2 adet 24 bit Sayc / Zamanlayc.

Aygtn stnde analog giri bir oklayc (multiplexer) tarafndan oklanarak ADC'ye (Analog Digital Converter) verilmitir. oklanan bu analog girilere kanal ad verilmitir. ADC'nin evrim kapasitesi birden fazla kanala blnerek ayn anda birden fazla analog

9 evrim yaplmas salanmtr. Aygtn emas ekil 5'da verilmitir.

ekil 4 : DAQCard 6062E emas Kullanlabilen kanal says seilen referans modeline gre deiiklik gstermektedir. Eer btn kanallarda lm tek utan yaplacak ise yani referans olarak kartn topra kullanlacak ise bu durumda en fazla 16 kanal kullanlabilir. Eer btn lmlerde her kanaln referans dardan verilecek ise bu durumda her kanal ifti iin iki giri ucu ayrlr ve en fazla kullanlabilen kanal says 8 olur. Analog giri ularnn referanslar ayr ayr programlanabilmektedir. Bu ekilde her kanal iin referansl veya referanssz model tek tek seilerek 8 ila 16 arasnda kanal elde edilebilmektedir. DAQCard 6062E, analog giri iin saniyede en fazla 500.000 rnek alabilmektedir. Kartn zerindeki FIFO tampon bellei 8129 rnek saklayabilmektedir. Kart veri transferi yaparken kesme veya programlanm I/O yntemlerinden birini kullanabilmektedir. Kartn dier teknik zellikleri reticinin salad kullanc kitabnda bulunabilir.

2.6. NIDAQmx Src Yazlm Kullanm


NI kartlarna programlama yoluyla eriebilmek iin src ile birlikte gelen, ANSI C desteini salayan NIDAQmx.h balk dosyas kullanlarak NIDAQmx.lib ktphane dosyasndaki fonksiyonlara eriim salanabilir. Balk dosyasndaki fonksiyonlar aygta

10 erimede bir API (Applicaiton Programming Interface) olutururlar. Bu API'yi kullanabilmek iin balk dosyas kaynak koda eklenir ve ktphane dosyas da derleyiciye parametre olarak verilerek API fonksiyonlarnn altrlabilir koda eriimi salanr. Projede kullanlan GCC (GNU C Compiler) derleyicisini Microsoft Windows stnde altrabilmek iin MinGW (Minimalist GNU for Windows) ortam kullanlmtr. Donanm src ktphanesini GCC derleyicisine ktphane olarak verebilmek iin NIDAQmx.lib biiminden NIDAQmx.a biimine dntrmek gereklidir. MinGW ortam ve gerekli aralar kurulduktan sonra bu dnm aadaki kodlar bir betik dosyasna yazlarak veya tek tek uygulanarak gerekletirilebilir:

#!/bin/sh PATH="$PATH" dumpbin /exports "C:\NIDAQmx.lib" > nidaq.exports echo LIBRARY nicaiu.dll > nidaq.defs echo EXPORTS >> nidaq.defs sed "1,/ordinal *name/d;/^$/d;/Summary$/,+100d;s/^ \+\([^ ]\+\)\( .*\|\)$/\\1/;s/^_\(.*\) $/\1/" nidaq.exports |sort >> nidaq.defs dlltool -k -d nidaq.defs -l libnidaq.a c:/WINDOWS/system32/nicaiu.dll

ekil 5 : Ktphane dosyas dnm ilemi

2.7. Qt
Projenin arayz tasarmnda ve programlanmasnda kullanlan Qt, Windwos, Linux ve Mac OS X gibi birden ok platformu destekleyen bir uygulama gelitirme ara takmdr [Qt]. En ok bilinen rnek programlardan KDE masast ortam, Opera a taraycs ve Skype haberleme yazlm da bu ara takm kullanlarak yazlmlardr. Qt'nin lisans srmleri hem ak kaynakl program gelitirmeyi ve datmay hem de retici firmadan gerekli lisans alnarak ticari uygulamalarda kullanmay mmkn klar. Qt'nin projede kullanlmasnn birka sebebi olarak unlar sayabiliriz; C++ programlama dili kullanlarak (ki Python, Ruby, PHP, Perl, Pascal, C# ve Java gibi dilleri de desteklemektedir) kolaylkla grafik arabirim (GUI Graphical User Interface) oluturmaya olanak salamas, grafik ara birim tasarmn hzlandran Designer arac,

11 yazlan programn deiik dillere evrimini kolaylatran Linguist arac, grafik arabirim programlamadaki olay ynetimini kolaylatran sinyal-slot yaps, eklenti (plugin) mimarisi sayesinde datlan programa sonradan eklenti yapabilme imkan tanmas, yazlan program kodunda ok az deiiklikler ile yaplarak Windows, Linux ve Mac OS X zerinde altrlabilir hale getirilmesi olarak sralanabilir. Projede Qt'nin ak kaynak lisansl srm kullanlmtr. Bu srm ayrca Microsoft Visual Studio entegrasyonu destei kurularak Visual Studio ile ve MinGW gelitirme ortam ile birlikte kullanlabilmektedir. MinGW gelitirme ortam Windows zerinde, bir Unix derleyicisi olan GCC'yi ve gelitirme iin gerekli dier aralar sunar [MinGW]. Proje gelitireme srecinde Windows iletim sistemi kullanlmtr. Gerek NIDAQmx srcsnn hem Windows hem de Linux iletim sistemlerini desteklemesi, gerekse Qt'nin bu iki iletim sistemine verdii destek sayesinde projenin kolaylkla Linux iletim sistemine geirilmesi mmkn olacaktr.

2.8. Qwt
Qwt, Qt kullanlarak gelitirilen, teknik uygulamalarn grafik ara birimdeki grsel ihtiyalarn karlamak iin gelitirilen bir ara setidir [Qwt]. ekil 7 de Qwt ile salanan baz grsel nesneler Qwt ile birlikte gelen rnek programlar kullanlarak resmedilmitir.

12

ekil 6 : Qwt rnekleri

2.9. Gelitireme Ortam : IDE


Gelitirme aamasnda Qt'nin gelitiricilerinin salad Creator program kullanlmtr. Creator yardmyla kod yazmak, yazlan kodu derlemek, hata ayklamak ve grafik arayz tasarm yapmak mmkndr. Creator, program kodlarn derlemek iin GCC'yi, hata ayklamak iin GDB'yi ve grafik arabirim tasarlamak iin Designer aracn kullanr.

13

ekil 7 : Creator ekran grnts - Kod

14

ekil 8 : Creator ekran grnts - Designer Qt ara setinde C++ ile desteklenmeyen baz zellikler vardr. Bunlardan bazlar; sinyal-slot mimarisi, ok kanall programlama, bellek ynetimi, foreach anahtar kelimesi, MetaObject desteidir.

Bu zellikleri destekleyebilmek iin derleyiciden nce altrlmas gereken MOC (Meta Object Compiler) derleyicisi kodlar C++ derleyicisinin derleyebilecei ekle getirir. Bu ilemi gerekletirmek iin proje dosyasnn bulunduu dizinde komut satrndan qmake komutu arlr. Qmake program, desteklenmeyen zellikerin C++ derleyicisi ile almas iin gerekli olan balk ve kaynak kod dosyalarn retecek olan dosyalar ve derleme iin gereken Makefile dosyasn retir. Makefile dosyas projeyi derleyecek olan make programnn kullanaca toplu derleme komut dosyasdr.

15 Proje dizininde make komutu verilerek GCC nin Makefile dosyasndaki derleme yordamlarn altrmas salanr. Derleyicinin kts olan altrlabilir dosya proje dosyasnn belirttii isim ile belirttii dizine oluturulur. Proje dosyasnn bir rnei ekil 10'da verilmitir.

TEMPLATE = app TARGET = Medaq HEADERS SOURCES FORMS = src/mainwindow.h src/mdichild.h src/data_plot.h = = src/main.cpp src/mainwindow.cpp src/mdichild.cpp src/data_plot.cpp src/main.ui src/info.ui src/devselect.ui

CONFIG -= build_all CONFIG -= debug_and_release CONFIG += qt thread release INCLUDEPATH += C:\Qwt-5.1.1\include LIBS += C:\Qwt-5.1.1\lib\qwt5.dll LIBS += -lnidaq DEFINES += QWT_DLL RESOURCES = rc/medaq.qrc TRANSLATIONS = rc/medaq.ts RC_FILE = rc/medaq.rc MOC_DIR = tmp OBJECTS_DIR = tmp/o UI_DIR = tmp UI_SOURCES_DIR = tmp UI_HEADERS_DIR = tmp RCC_DIR = tmp DESTDIR = ../MEDAQ ekil 9 : rnek Proje Dosyas. Dosyada verilen parametrelerin bazlarnn anlamlar u ekildedir. TEMPLATE = app : uygulama program olduunu belirtir. u deerleri alabilir; app, lib, subdirs. TARGET = Medaq : altrlabilir dosya ismi. HEADERS = ... : balk dosyalar.

16 SOURCES = ... : kaynak kodu dosyalar. FORMS = ... : Designer dosyalar. CONFIG -= build_all : debug ileminin uygulanmamas iin. CONFIG -= debug_and_release : debug ileminin uygulanmamas iin. CONFIG += qt thread release : Qt ktphanesinin kullanlacan, ok kanall programlamaya destek vereceini ve datm iin kt retmesi gerektiini belirtir. INCLUDEPATH = C:\Qwt-5.1.1\include : Qwt iin balk dosyalarnn yolunu belirtir. LIBS += C:\Qwt-5.1.1\lib\qwt5.dll : Qwt iin ktphane dosyalarnn yolunu belirtir. LIBS += -lnidaq : NIDAQmx statik ktphanesinin yklenmesi gerektiini belirtir. DEFINES += QWT_DLL : Qwt iin C n derleyicisine verilmek istenen QWT_DLL makrosunu belirtir. RESOURCES belirtir. = rc/medaq.qrc : resim dosyalarn yneten kaynak dosyasn

TRANSLATIONS = rc/medaq.ts : dil destei iin retilecek dosyay belirtir. RC_FILE = rc/medaq.rc : programn ikonunu yneten kaynak dosyasn belirtir. MOC_DIR = tmp : geici dosyalarn konaca dizini belirtir. OBJECTS_DIR = tmp/o : geici dosyalarn konaca dizini belirtir. UI_DIR = tmp : geici dosyalarn konaca dizini belirtir. UI_SOURCES_DIR = tmp : geici dosyalarn konaca dizini belirtir. UI_HEADERS_DIR = tmp : geici dosyalarn konaca dizini belirtir. RCC_DIR = tmp : geici dosyalarn konaca dizini belirtir. DESTDIR = ../MEDAQ : altrlabilir dosyann kaydedilecei dizini belirtir.

2.10. Filtreler
Toplanan sinyal stnde baz filtreler uygulayarak sinyal analizi iin grafik arabirimde kullancya sunulacaktr. Bu amala oluturulan filtreler u ekildedir:

2.10.1 FFT
Fast Fourier Transform, yani Hzl Fourier Dnm anlamna gelen ilem zaman domain'inden alnan sinyalin frekans domain'ine dntrlmesinde kullanlr. Hzl kelimesi dnmn zel bir algoritma kullanlmasndan gelir. Hzl olmayan ekli, DFT Discrete Fourier Transform, yani Ayrk Fourier Dnmdr. Ayrk denmesinin

17 sebebi, dnm ileminin ayrk deerler kmesi stnde almasndan gelir. Dnmn srekli olan orjinal hali ise u ekildedir:

F u= f x ei 2 u x dx

Dnm kompleks domain'de alr. Kompleks ksmn sanal ksm u ekilde yazlabilir: e i =cos i sin Dnmn yapt iin z, verilen bir sinyalin sinz ve kosins sinyallerinin toplam eklinde ifadesine dntmesidir. Dnmn ayrk deerler kmesindeki gsterimi, yani DFT ise, u ekilde gsterilir: F n= f k e
k=0 N 1 i 2 kn N

Buradaki fk giri fonksiyonu, Fn ise dnmn sonucudur. Bu ilem dorudan basit bir algoritma ile gerekletirilirse, yaplacak ilemlerin karmakl O(N2) olacaktr. Eer dnm iin FFT algoritmalar kullanlrsa karmaklk O(N Log N) mertebelerine indirgenebilmektedir. Bu indirgemeyi salayan temel etken, dnmn yinelenebilir (recursive) bir yapda yazlarak altrlabilmesidir. FFT dnm iin programda, gvenirlii kantlanm, byk veriler stnde hzl ilem yapabilen ve ayn zamanda ak kaynak olan FFTW ktphanesi kullanlmtr [FFTW]. FFTW, dnm hzn arttrabilmek iin ilemcinin ve bilgisayarn dier bileenlerinin mimari yapsn snayarak n bilgi toplar. Toplad bilgilere gre en uygun algoritmalar seer. Ktphanenin bu ilk aamada alan test sreci uzun zaman alabildiinden test sonucu oluan ayarlarn saklanabilmesi salanmtr. Bizim programmzda da bu zellikten faydalanarak yaplan ilk dnmde ayarlar saklanr ve program kapatlncaya kadar bu ayarlar ile ilem yaplr. Bylece tekrar edilen dnmlerde test sresi kartlarak ilem hzlandrlm olur.

2.10.2 Ortalama Filtresi


Bu filtre alak frekanslar geiren ve yksek frekanstaki sinyalleri temizleyen bir filtre eididir. Filtre u ekilde alr:

18

ekil 10 : Ortalama Filtresi ekilde grlen kaynak dizinin zerinde gezen bir pencere iindeki saylarn ortalamas alnarak hedef dizide pencerenin ortasna rastlayan hzreye yazlr. Hedefte kayt yerinin bulunabilmesi iin pencerenin tek sayl bir byklnn olmas gerektii aka grlmektedir. Hedef dizinin banda ve sonunda bulunan, pencerenin yars kadar saydaki hcre sfr ile doldurulur. lemin dorudan yaplan bir algoritma iin karmakl O(W N) olaca grlr. Buradaki W, pencerenin boyunu ve N de dizinin boyunu ifade eder. Bu ilemin daha verimli bir ekli u ekilde yaplabilir: Pencere bykl kadar hcre toplanr ve bir deikende saklanr. Ortalama ilgili hcreye yazlr. Kaynak dizinin boyutu kadar bir dng iinde Pencereyi kaydrabilmek iin pencereden bir sonraki hcreden, pencerenin imdiki ilk hcresi kartlarak deikende tutlan toplama eklenir ve ortalama alnr. Ortalama ilgili hcreye yazlr. Bu ekilde yaplan algoritmann karmakl O(N) olacaktr. Buradaki N, kaynak dizinin boyutudur.

3. YNTEM 3.1. Bilgi Toplama


Projenin ieriinin belirmesinden sonra ilk yaptm i projede kullanlacak olan ara, teknoloji ve yntemler hakknda bilgi toplamak oldu. Veri toplama kartnn kitapl, NIDAQmx src yazlm ile birlikte gelen NIDAQmx Yardm'n okudum ve API hakknda bilgi edindim. Grafik arabirim iin kullanacam programlama ortamn Qt olarak setikten sonra Qt ile ilgili Alan Ezust ve Paul Ezust'un yazm olduklar Introduction to Design Patterns in C++ with Qt4 kitabn okudum. Kendisi de ak bir kaynak olan kitabn ieriine [QtBook] internet adresinden eriilebilmektedir. Projeyi aldktan sonra bilgi toplama srecinde program kullanacak olan kullanc ile grerek programn arabirim ve ileyii konularnda isteklerini ve nerilerini aldm.

19

3.2. Aralarn Kurulumu


Uygulama gelitirme ara takm olan Qt'yi ve Creator' ykledim. Qt ile birlikte MinGW, Unix program gelitirme ortam ile birlikte gcc, make gibi derleme iin gereken aralar da kurulmu oldu. Teknik uygulamalar iin gelitirilmi olan Qwt nesne ktphanesini derledim. Derlemeden sonra dinamik ktphane ve balk dosyalar oluturuldu. NI DAQ kartlarnn srcsn, MAX', programlama rneklerini ve belgelendirmesini ieren NIDAQmx'in kurlumunu yaptm. Fiziksel aygtm olmadndan MAX yardm ile yapacam testlerde kullanmak zere simle edilmi sanal bir aygt tanttm. NIDAQmx API'sine program iinden erimek iin gerekli olan NIDAQmx.lib statik ktphane dosyasn gcc derleyicisinin destekledii format olan libnidaq.a ekline getirmek iin yukardaki ekil 6'da verilen betii kullandm. Verilen betiin alabilmesi iin gerekli olan Microsoft Visual Studio ve MinGW-SYSCORE yazlm paketlerini kurdum. Dnm yaptktan sonra elde ettiim libnidaq.a statik ktphanesini MinGW gelitirme ortamnn ktphane dizinine aktararak gcc ile eriilebilir hale getirdim. Program kodunun API'ye eriebilmesini salayacak olan NIDAQmx.h balk dosyasn MinGW balk dosyas dizinine aktardm.

3.3. rneklerin Derlenmesi


Buraya kadar yaptm hazrln alrln kontrol etmek iin NIDAQmx ile birlikte gelen ANSI C rneklerini derleyerek nceden eklediim sanal srcden veri almay baardm. Aygt srcsnn alrln doruladktan sonra Qt rneklerinden birkan derleyerek grafik arabirimin de alrln doruladm. Her iki ortamn birlikte kullanlarak sanal aygttan okuduum sonlu saydaki rnekleri bir QwtPlot nesnesi zerinde grafik halinde izdirdim.

3.4. Programn Oluturulmas


Ana pencereyi Designer aracn kullanarak tasarladm.Designer aracyla menleri, ara ubuklar ve kullancnn istedii zellikleri ieren nesneleri dzenledim. Programda kullandm ikonlar GNOME [GNM] masast ortamnn ikon setinden aldm. Ana pencerenin gui dosyasn proje dosyasna ekleyerek uic (user interface compiler)'nin grafik arabirim snfn oluturulmasn saladm. QMainWindow Snfndan ve ana pencerenin isminden oluturulan snftan MainWindow snfn trettim. MainWindow snfnn yaplandrcsnda menlerin olaylarn yneten QAction snfndan oluturulmu olan action'larn sinyallerini connect ile uygun fonksiyonlara baladm. File > New mensnde bulunan seenek ile kullancnn bilgisayarndaki DAQ aygtnn ve sinyal almak istedii kanal belirleyebilecei, ayn zamanda lm tipi ve gerilim araln belirleyebilecei bir diyalog penceresi tasarladm. Bu aygt seim diyalounun snfn yazarak aygttan aldm bilgilerle diyalog zerindeki nesneleri doldurdum. Bu diyalog pencresini ekil 11'de grebilirsiniz.

20

ekil 11 : Yeni lm diyalog penceresi. Aygt, kanal, lm tipi ve gerilim aral gibi bilgileri kullancdan aldktan sonra NIDAQmx API'si ile bu bilgilere uygun, srekli veri alan bir rnekleme grevi (task) oluturdum. Okuduum verileri QwtPlot nesnesi ile ekrana grafik olarak izdirdim. Kullancnn kullanmak istedii aygt, k kanal ve portlarn, ve programn dier ayarlarn seebilecei ayarlar diyalog penceresini tasarlayp seilenlerin ayar dosyasna kaydedilmesi iin program kodunu yazdm.

21

ekil 12 : Ayarlar Diyalog Penceresi Analog ve dijital klar iin ana pencerede oluturduum nesneler iin NIDAQmx ktphane fonksiyonlarnn yardmyla k ilemlerini gerekletirdim. Aygt ynetebilmek ve gelen veriyi uygun biimde izime aktarabilmek iin aygt yneticisi snfn tasarladm. Bu snf ile : Yeni lm balatma, Balatlan lmden verileri bir zamanlayc yardmyla alp iziciye aktarma, Kaydetme ilemini balatma, duraklatma, durdurma lm ilemini bitirip kaynaklar temizleme Analog ve dijital k ilemlerini gerekletirme, Ve hatalar gsterme ilemlerini gerekletirir.

Arayzdeki snrlamalar iin ve aygt yneticisinde kullanlmak zere aygt bilgisi toplayc snf tasarladm. Bu snf ile: Aygt adn, Sanallk bilgisini, lme hz araln, Analog ve dijital kanallar

22 Analog giri iin sonlandrma referans modlarn Ve giri/k gerilim araln src ktphanesinden almasn saladm.

Bellekte topladm veriyi diske kaydetmek ve sonradan ykleyebilmek iin gerekli dosya formatn ve fonksiyonlar gerekletirdim. En son olarak da filtreleri daha nce akladm ekilde gerekletirerek sonularn gsterecek izim nesnelerini programa ekledim. Bu aamaya kadar yaptm almalarn sonucu olan programn ekran grnts ekil 12'de grebilirsiniz.

ekil 13 : Medaq ana penceresi Veri alma

23

ekil 14 : Medaq ana penceresi Filtreler

SONU
Bu proje ile yksek bteli programlar ile gerekletirilebilen, uygulamaya zg veri toplama ve analiz programlarnn ak kaynak aralar ve ktphaneler kullanarak da gerekletirilebileceini kantlam oldum.

KAYNAKLAR
[Ny] : http://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem [NIDAQmx] : http://www.ni.com/dataacquisition/nidaqmx.htm [6062E] : http://sine.ni.com/nips/cds/view/p/lang/en/nid/14632 [Qt] : http://trolltech.com/products [MinGW] : http://www.mingw.org/ [Qwt] : http://qwt.sourceforge.net/ [NP] : http://notepad-plus.sourceforge.net/uk/site.htm [QtBook] : http://cartan.cas.suffolk.edu/oopdocbook/opensource/ [GNM] : http://www.gnome.org/ [FFTW] : http://fftw.org/

24

EKLER EK A - KAYNAK KODLARI


main.cpp
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #include #include #include #include <QApplication> <QTranslator> <QSharedMemory> <QDebug>

#include "mainwindow.h" int main(int argc, char *argv[]) { QSharedMemory sharedMemory("MEDAQSHAREDMEMORY"); //UniqueNameForApplication if (sharedMemory.create(1) && sharedMemory.error() != QSharedMemory::AlreadyExists) qDebug() << "This is the only instance"; else exit(0); QApplication app(argc, argv); // lupdate *.pro ile pro da tanimlanan // kod dosyalarindan tr ile verilen // string ler cekilir. // lrelease *.pro ile ts ler qm ye // cevrilir. // qm asagidaki kod ile ayni // dizinden yuklenir. QTranslator translator; translator.load("medaq_tr"); app.installTranslator(&translator); Q_INIT_RESOURCE(medaq); MainWindow mainWin; mainWin.show(); return app.exec();

25
}

MainWindow.h
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "ui_MainWindow.h" class DeviceController; class QwtPlotCurve; class QwtPlot; QT_BEGIN_NAMESPACE class QAction; class SettingsDialog; class QLabel; QT_END_NAMESPACE class MainWindow : public QMainWindow, private Ui::MainWindow { Q_OBJECT public: MainWindow(); protected: void closeEvent(QCloseEvent *event); private slots: void settingsDialog(); void infoDialog(); void aboutDialog(); void helpDialog(); void showStatusbar(bool); void handleStateChanges(int state); void handleLogMessages(QString messsage);

26
void toggleManualScale(); // out void toggleAnalogOutCheck(); void toggleDigitalOutCheck(); // filter void toggleFFTFilter(); void updateFFTFilter(); void toggleAverageFilter(); void updateAverageFilter(); void scrollAverageFilter(int step); void newSamplingDialog(); void saveRecord(); void openRecord(); void fftMinSpinChanged(int); void fftMaxSpinChanged(int); void recordTimeChanged(int); private: void connections(); void readSettings(); void writeSettings(); private: QAction * dockToggleViewAction; DeviceController * dc; QLabel * samplingRateLabel; QLabel * visibleDurationLabel; // plot QwtPlot * fftMagnitudePlot; QwtPlot * fftPhasePlot; QwtPlot * psdPlot; QwtPlot * averagePlot; QwtPlotCurve * fftMagnitudeCurve; QwtPlotCurve * fftPhaseCurve; QwtPlotCurve * psdCurve; QwtPlotCurve * averageCurve; // filter QString QVector<double> QVector<double> QVector<double> QVector<double> QVector<double> QVector<double> QVector<double> }; #endif fftWisdom; fftMagnitudeData; fftPhaseData; psdData; fftBottomData; averageData; averageRecordData; averageBottomData;

MainWindow.cpp
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr)

27
This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include <QtGui> <QStatusBar> "MainWindow.h" "InfoDialog.h" "SettingsDialog.h" "DeviceController.h" "DeviceSensor.h" "NewSamplingDialog.h" <qwt_plot.h> <qwt_plot_curve.h> "fftw3.h" <QVector> "math.h" "TimeScale.h" <qwt_scale_widget.h> <qwt_plot_picker.h>

MainWindow::MainWindow(){ setupUi(this); connections(); readSettings(); } void MainWindow::connections(){ menuView->insertAction(actionStatusBar, parametersDock>toggleViewAction()); menuHelp->addAction(QWhatsThis::createAction()); samplingRateLabel = new QLabel; samplingRateLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); statusBar()->insertPermanentWidget(0, samplingRateLabel); visibleDurationLabel = new QLabel; visibleDurationLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); statusBar()->insertPermanentWidget(0, visibleDurationLabel);

28
dc = new DeviceController(plotter); // device controller connect(dc, SIGNAL(stateChanged(int)), this, SLOT(handleStateChanges(int))); connect(dc, SIGNAL(logMessage(QString)), this, SLOT(handleLogMessages(QString))); // button connect(recordButton, SIGNAL(clicked()), dc, SLOT(startRecording())); connect(pauseButton, SIGNAL(clicked()), dc, SLOT(pauseRecording())); connect(stopButton, SIGNAL(clicked()), dc, SLOT(stopRecording())); connect(clearButton, SIGNAL(clicked()), dc, SLOT(clearSampling())); connect(clearButton, SIGNAL(clicked()), samplingRateLabel, SLOT(clear())); connect(clearButton, SIGNAL(clicked()), visibleDurationLabel, SLOT(clear())); // action connect(actionExit, SIGNAL(triggered()), this, SLOT(close())); connect(actionStatusBar, SIGNAL(toggled(bool)), this, SLOT(showStatusbar(bool))); connect(actionInfo, SIGNAL(triggered()), this, SLOT(infoDialog())); connect(actionSettings, SIGNAL(triggered()), this, SLOT(settingsDialog())); connect(actionAbout, SIGNAL(triggered()), this, SLOT(aboutDialog())); connect(actionHelp, SIGNAL(triggered()), this, SLOT(helpDialog())); connect(actionStart_Record, SIGNAL(triggered()), dc, SLOT(startRecording())); connect(actionPause, SIGNAL(triggered()), dc, SLOT(pauseRecording())); connect(actionStop, SIGNAL(triggered()), dc, SLOT(stopRecording())); connect(actionClear, SIGNAL(triggered()), dc, SLOT(clearSampling())); connect(actionClear, SIGNAL(clicked()), samplingRateLabel, SLOT(clear())); connect(actionClear, SIGNAL(clicked()), visibleDurationLabel, SLOT(clear())); connect(actionNew, SIGNAL(triggered()), this, SLOT(newSamplingDialog())); connect(actionSave, SIGNAL(triggered()), this, SLOT(saveRecord())); connect(actionOpen, SIGNAL(triggered()), this, SLOT(openRecord())); // scroll connect(timeScroll, SIGNAL(valueChanged(int)), plotter, SLOT(scrollTime(int))); connect(timeScroll, SIGNAL(valueChanged(int)), this, SLOT(scrollAverageFilter(int))); // scale connect(manualScaleCheck, SIGNAL(stateChanged(int)), this, SLOT(toggleManualScale())); connect(minScaleSpin, SIGNAL(valueChanged(double)), this, SLOT(toggleManualScale())); connect(maxScaleSpin, SIGNAL(valueChanged(double)), this, SLOT(toggleManualScale())); // filter connect(fftCheck, SIGNAL(stateChanged(int)), this, SLOT(toggleFFTFilter())); connect(fftMinSpin, SIGNAL(valueChanged(int)), this,

29
SLOT(fftMinSpinChanged(int)) ); connect(fftMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(fftMaxSpinChanged(int)) ); connect(fftMinSpin, SIGNAL(valueChanged(int)), this, SLOT(updateFFTFilter()) ); connect(fftMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(updateFFTFilter()) ); connect(averageCheck, SIGNAL(stateChanged(int)), this, SLOT(toggleAverageFilter())); connect(averageSpin, SIGNAL(valueChanged(int)), this, SLOT(updateAverageFilter()) ); // out connect(analogOutCheck, SIGNAL(stateChanged(int)), this, SLOT(toggleAnalogOutCheck())); connect(analogOutSpin, SIGNAL(valueChanged(double)), dc, SLOT(updateAnalogOut(double))); connect(digitalOutCheck, SIGNAL(stateChanged(int)), this, SLOT(toggleDigitalOutCheck())); connect(digitalOutSpin, SIGNAL(valueChanged(int)), dc, SLOT(updateDigitalOut(int))); // plotter connect(plotter, SIGNAL(recordTimeChanged(int)), this, SLOT(recordTimeChanged(int)));

QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); QString currentDevice = settings.value("currentDevice", QString("")).toString(); double analogOutStep = settings.value("analogOutStep", 0.1).toDouble(); settings.endGroup(); analogOutSpin->setSingleStep(analogOutStep); if( ! currentDevice.isEmpty()) { analogOutSpin>setMinimum(DeviceSensor::getAOMinVoltage(currentDevice)); analogOutSpin>setMaximum(DeviceSensor::getAOMaxVoltage(currentDevice)); } else { QMessageBox::warning(this, tr("First Start"), tr("<p><strong>There is no active device !</strong></p>" "<p>It seems this is your first start or you did not select any device at settings." "If you do not select and save a device you cannot acquire data from your device !</p>" "<p>I will open settings, please select a device and " "<strong><font size=\"+1\">save the settings</font></strong>. " "<br>If you change other settings you may <strong><font size=\"+1\">restart</font></strong> the application.<br>" "<font size=\"-1\"><strong>Hint :</strong> Wait tooltip on controls or use \"what is this\" mode from title bar.</font></p>"),

30
QMessageBox::Ok,QMessageBox::Ok); QTimer::singleShot(500, actionSettings, SLOT(trigger()));

if(dc->getState() != DeviceController::NoDevice) handleStateChanges(DeviceController::Waiting); else handleStateChanges(DeviceController::NoDevice);

void MainWindow::closeEvent(QCloseEvent *event){ writeSettings(); event->accept(); } void MainWindow::settingsDialog(){ SettingsDialog * sd = new SettingsDialog(this); if (sd->exec() == QDialog::Accepted) { QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); double analogOutStep = settings.value("analogOutStep", 0.1).toDouble(); settings.endGroup(); } } void MainWindow::infoDialog(){ InfoDialog * id = new InfoDialog(this); id->show(); } void MainWindow::aboutDialog(){ QMessageBox::about(this, tr("About MEDAQ"), tr("<p>The <b>MEDAQ</b>, <b>M</b>edical <b>E</b>xperimentation <b>D</b>ata <b>A</b>c<b>Q</b>uisition was created " "by Huseyin Kozan for an experimentation which collects data from an Neural Recording Board with a " "National Instruments Data Acquisition Card at Istanbul University.</p>" "<p>Huseyin Kozan - <a href='http://huseyinkozan.com.tr'>http://huseyinkozan.com.tr</a></p>")); } void MainWindow::helpDialog(){ QMessageBox::warning(this, tr("Attention!"),tr("Not implemented, yet !")); } void MainWindow::readSettings(){ analogOutSpin->setSingleStep(analogOutStep);

31
QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("MainWindow"); QPoint pos = settings.value("pos", QPoint(0, 0)).toPoint(); QSize size = settings.value("size", QSize(640, 480)).toSize(); QByteArray mainWindowState = settings.value("State").toByteArray(); double minScale = settings.value("minScale", 0.0).toDouble(); double maxScale = settings.value("maxScale", 0.0).toDouble(); bool manualScale = settings.value("manualScale", false).toBool(); double analogOut = settings.value("analogOut", 0.0).toDouble(); int digitalOut = settings.value("digitalOut", 0.0).toInt(); settings.endGroup(); move(pos); resize(size); restoreState(mainWindowState); minScaleSpin->setValue(minScale); maxScaleSpin->setValue(maxScale); manualScaleCheck->setChecked(manualScale); analogOutSpin->setValue(analogOut); digitalOutSpin->setValue(digitalOut);

void MainWindow::writeSettings() { QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("MainWindow"); settings.setValue("pos", pos()); settings.setValue("size", size()); settings.setValue("State", saveState()); settings.setValue("minScale", minScaleSpin->value()); settings.setValue("maxScale", maxScaleSpin->value()); settings.setValue("manualScale", manualScaleCheck->isChecked()); settings.setValue("analogOut", analogOutSpin->value()); settings.setValue("digitalOut", digitalOutSpin->value()); settings.endGroup(); } void MainWindow::handleStateChanges(int state) { switch(state) { case DeviceController::NoDevice: actionNew->setEnabled(false); actionOpen->setEnabled(true); actionSave->setEnabled(false); actionStart_Record->setEnabled(false); actionPause->setEnabled(false); actionStop->setEnabled(false); actionClear->setEnabled(false); recordButton->setEnabled(false); pauseButton->setEnabled(false); stopButton->setEnabled(false); clearButton->setEnabled(false);

32
timeScroll->setEnabled(false); fftCheck->setEnabled(false); noiseCheck->setEnabled(false); averageCheck->setEnabled(false); averageSpin->setEnabled(false); fftMinSpin->setEnabled(false); fftMaxSpin->setEnabled(false); break; case DeviceController::Waiting: actionNew->setEnabled(true); actionOpen->setEnabled(true); actionSave->setEnabled(false); actionStart_Record->setEnabled(false); actionPause->setEnabled(false); actionStop->setEnabled(false); actionClear->setEnabled(false); recordButton->setEnabled(false); pauseButton->setEnabled(false); stopButton->setEnabled(false); clearButton->setEnabled(false); timeScroll->setEnabled(false); fftCheck->setEnabled(false); noiseCheck->setEnabled(false); averageCheck->setEnabled(false); averageSpin->setEnabled(false); fftMinSpin->setEnabled(false); fftMaxSpin->setEnabled(false); plotter->clearPlotter(); fftMagnitudeData.clear(); fftPhaseData.clear(); psdData.clear(); fftBottomData.clear(); averageData.clear(); averageRecordData.clear(); averageBottomData.clear(); break; case DeviceController::Plotting: actionNew->setEnabled(true); actionOpen->setEnabled(true); actionSave->setEnabled(false); actionStart_Record->setEnabled(true); actionPause->setEnabled(false); actionStop->setEnabled(false); actionClear->setEnabled(true); recordButton->setEnabled(true); pauseButton->setEnabled(false); stopButton->setEnabled(false); clearButton->setEnabled(true); timeScroll->setEnabled(false);

33
fftCheck->setEnabled(false); noiseCheck->setEnabled(false); averageCheck->setEnabled(false); averageSpin->setEnabled(false); fftMinSpin->setEnabled(false); fftMaxSpin->setEnabled(false); break; case DeviceController::Paused: actionNew->setEnabled(true); actionOpen->setEnabled(true); actionSave->setEnabled(false); actionStart_Record->setEnabled(true); actionPause->setEnabled(false); actionStop->setEnabled(true); actionClear->setEnabled(true); recordButton->setEnabled(true); pauseButton->setEnabled(false); stopButton->setEnabled(true); clearButton->setEnabled(true); timeScroll->setEnabled(false); fftCheck->setEnabled(false); noiseCheck->setEnabled(false); averageCheck->setEnabled(false); averageSpin->setEnabled(false); fftMinSpin->setEnabled(false); fftMaxSpin->setEnabled(false); break; case DeviceController::Recording: actionNew->setEnabled(true); actionOpen->setEnabled(true); actionSave->setEnabled(false); actionStart_Record->setEnabled(false); actionPause->setEnabled(true); actionStop->setEnabled(true); actionClear->setEnabled(true); recordButton->setEnabled(false); pauseButton->setEnabled(true); stopButton->setEnabled(true); clearButton->setEnabled(true); timeScroll->setEnabled(false); fftCheck->setChecked(false); noiseCheck->setChecked(false); averageCheck->setChecked(false); fftCheck->setEnabled(false); noiseCheck->setEnabled(false); averageCheck->setEnabled(false); averageSpin->setEnabled(false); fftMinSpin->setEnabled(false); fftMaxSpin->setEnabled(false);

34
break; case DeviceController::Scrolling: actionNew->setEnabled(true); actionOpen->setEnabled(true); actionSave->setEnabled(true); actionStart_Record->setEnabled(false); actionPause->setEnabled(false); actionStop->setEnabled(false); actionClear->setEnabled(true); recordButton->setEnabled(false); pauseButton->setEnabled(false); stopButton->setEnabled(false); clearButton->setEnabled(true); timeScroll->setEnabled(true); fftCheck->setEnabled(true); noiseCheck->setEnabled(true); averageCheck->setChecked(false); averageCheck->setEnabled(true); averageSpin->setEnabled(true); fftMinSpin->setEnabled(true); fftMaxSpin->setEnabled(true); dc->stopSampling(); plotter->prepareForScroll(); timeScroll->setMaximum(plotter->getMaxScrollStep()); plotter->scrollTime(0); fftMinSpin->setMinimum(0); fftMinSpin->setMaximum(0); fftMaxSpin->setMinimum(1); fftMaxSpin->setMaximum( qFloor( plotter>recordData.size() / plotter->getSamplingRate() ) ); break; } }

void MainWindow::handleLogMessages(QString message) { loggerEdit->append(message); } void MainWindow::newSamplingDialog() { NewSamplingDialog d(this); if( d.exec() == QDialog::Accepted ) { dc->clearSampling(); samplingRateLabel->clear(); visibleDurationLabel->clear(); QString channelName = d.channelName; int terminalConfiguration; if(d.terminalConfiguration == 0) terminalConfiguration = DeviceSensor::AIReferenced;

35
else if(d.terminalConfiguration == 1) terminalConfiguration = DeviceSensor::AINonReferenced; else if(d.terminalConfiguration == 2) terminalConfiguration = DeviceSensor::AIDifferential; else if(d.terminalConfiguration == 3) terminalConfiguration = DeviceSensor::AIPseudoDifferential; double minVoltage = d.minVoltage; double maxVoltage = d.maxVoltage; unsigned int visibleDuration = d.visibleDuration; unsigned int samplingRate = d.samplingRate; bool startRecordImmediately = d.startRecordImmediately; samplingRateLabel->setText(tr("Sampling Rate : %1 S/s").arg(samplingRate)); visibleDurationLabel->setText(tr("Visible Duration : %1 s").arg(visibleDuration)); dc->newSampling( channelName, terminalConfiguration, minVoltage, maxVoltage, visibleDuration, samplingRate, startRecordImmediately); } } void MainWindow::toggleManualScale() { if(manualScaleCheck->isChecked()) { plotter->setScale(minScaleSpin->value(), maxScaleSpin>value()); } else { plotter->setScale(0,0,true); } } void MainWindow::toggleAnalogOutCheck() { QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); QString currentAOChannel = settings.value("currentAOChannel", QString("")).toString(); settings.endGroup(); if( ! currentAOChannel.isEmpty()) { if(analogOutCheck->isChecked()) { dc->startAnalogOut(analogOutSpin->value()); } else { dc->stopAnalogOut(); } }

36
void MainWindow::toggleDigitalOutCheck() { QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); QString currentDOLine = settings.value("currentDOLine", QString("")).toString(); settings.endGroup(); if( ! currentDOLine.isEmpty()) { if(digitalOutCheck->isChecked()) { dc->startDigitalOut(digitalOutSpin->value()); } else { dc->stopDigitalOut(); } } } void MainWindow::saveRecord() { QString saveName = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("Medaq File (*.medaq)")); if( ! saveName.isNull()){ QFile file(saveName); file.open(QIODevice::WriteOnly); QDataStream out(&file); quint32 visibleDuration = plotter->getVisibleDuration(); quint32 samplingRate = plotter->getSamplingRate(); QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); QString currentDevice = settings.value("currentDevice", QString("")).toString(); settings.endGroup(); qreal minScale = DeviceSensor::getAIMinVoltage(currentDevice); qreal maxScale = DeviceSensor::getAIMaxVoltage(currentDevice); // Write a header with a "magic number" and a version out << (quint32) 0x11111111; // magic number, this file is out out out out out << << << << << (quint32) 100; //1.00, internal version visibleDuration; samplingRate; minScale; maxScale;

medaq file

// Write the data for(int i=0; i<plotter->recordData.size(); ++i){ out << plotter->recordData.at(i); } } }

37
void MainWindow::openRecord() { QString openName = QFileDialog::getOpenFileName(this, tr("Save File"), "", tr("Medaq File (*.medaq)")); if( ! openName.isNull()) { dc->clearSampling(); samplingRateLabel->clear(); visibleDurationLabel->clear(); QFile file(openName); file.open(QIODevice::ReadOnly); QDataStream in(&file); quint32 visibleDuration; quint32 samplingRate; qreal minScale; qreal maxScale; // Read and check the header quint32 magic; in >> magic; if (magic != 0x11111111){ loggerEdit->append( tr("The file that you trying to open is not a Medaq file !") ); return; } // Read the version quint32 version; in >> version; if (version < 100){ loggerEdit->append( tr("The file that you trying to open is an old file format !") ); return; } if (version > 100){ loggerEdit->append( tr("The file that you trying to open is a newer file format !") ); return; } in in in in >> >> >> >> visibleDuration; samplingRate; minScale; maxScale;

samplingRateLabel->setText(tr("Sampling Rate : %1 S/s").arg(samplingRate)); visibleDurationLabel->setText(tr("Visible Duration : %1 s").arg(visibleDuration)); minScaleSpin->setMinimum(minScale); minScaleSpin->setMaximum(maxScale); maxScaleSpin->setMinimum(minScale); maxScaleSpin->setMaximum(maxScale); dc->clearSampling(); unsigned int dataSize = ( file.size() -

38
(4*sizeof(quint32)) - (2*sizeof(qreal)) ) / for(int i=0; i<dataSize; ++i) { double x = 0; in >> x; plotter->recordData.append(x); } file.close(); sizeof(double);

recordTimeChanged( dataSize / samplingRate ); plotter->prepareForPlot(visibleDuration, samplingRate); plotter->prepareForScroll(); timeScroll->setMaximum(plotter->getMaxScrollStep()); dc->stopRecording(); // state = Scrolling } }

void MainWindow::showStatusbar(bool value){ if(value) { statusBar()->show(); } else { statusBar()->hide(); } } void MainWindow::toggleFFTFilter() { if(fftCheck->isChecked()) { fftMagnitudePlot = new QwtPlot(tr("FFT Magnitude"), this); fftPhasePlot = new QwtPlot(tr("FFT Phase"), this); psdPlot = new QwtPlot(tr("PSD"), this); fftMagnitudePlot->setCanvasBackground(Qt::white); fftPhasePlot->setCanvasBackground(Qt::white); psdPlot->setCanvasBackground(Qt::white); gridLayout->addWidget(fftMagnitudePlot, 0, 1); gridLayout->addWidget(fftPhasePlot, 1, 1); gridLayout->addWidget(psdPlot, 1, 0); fftMagnitudeCurve = new QwtPlotCurve(tr("FFT Magnitude Curve")); fftPhaseCurve = new QwtPlotCurve(tr("FFT Phase Curve")); psdCurve = new QwtPlotCurve(tr("PSD Curve")); QwtPlotPicker * fftMagnitude_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::PointSelection | QwtPicker::DragSelection, QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, fftMagnitudePlot->canvas()); fftMagnitude_picker->setRubberBandPen(QColor(Qt::green)); fftMagnitude_picker->setRubberBand(QwtPicker::CrossRubberBand); fftMagnitude_picker->setTrackerPen(QColor(Qt::blue)); QwtPlotPicker * fftPhase_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::PointSelection | QwtPicker::DragSelection, QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, fftPhasePlot->canvas());

39
fftPhase_picker->setRubberBandPen(QColor(Qt::green)); fftPhase_picker->setRubberBand(QwtPicker::CrossRubberBand); fftPhase_picker->setTrackerPen(QColor(Qt::blue)); QwtPlotPicker * psd_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::PointSelection | QwtPicker::DragSelection, QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, psdPlot->canvas()); psd_picker->setRubberBandPen(QColor(Qt::green)); psd_picker->setRubberBand(QwtPicker::CrossRubberBand); psd_picker->setTrackerPen(QColor(Qt::blue)); // call the update function updateFFTFilter(); fftMagnitudeCurve->attach(fftMagnitudePlot); fftPhaseCurve->attach(fftPhasePlot); psdCurve->attach(psdPlot); fftMagnitudePlot->replot(); fftPhasePlot->replot(); psdPlot->replot(); plotter->setTitle(tr("Sampled Signal")); } else {

if(fftMagnitudePlot) { delete fftMagnitudeCurve; delete fftMagnitudePlot; fftMagnitudeCurve = NULL; fftMagnitudePlot = NULL; } if(fftPhasePlot) { delete fftPhaseCurve; delete fftPhasePlot; fftPhaseCurve = NULL; fftPhasePlot = NULL; } if(psdPlot) { delete psdCurve; delete psdPlot; psdCurve = NULL; psdPlot = NULL; } plotter->setTitle(tr(""));

void MainWindow::updateFFTFilter() { if(fftCheck->isChecked()) { // calculate fft // get data from plotter record about the duration int start = fftMinSpin->value() * plotter->getSamplingRate();

40
int end >getSamplingRate(); = fftMaxSpin->value() * plotter-

if( start >= plotter->recordData.size() ) return; if( end > plotter->recordData.size() ) return; // do fft int size = end - start; double *in = (double*) fftw_malloc( sizeof(double) * size ); fftw_complex *out = (fftw_complex*) fftw_malloc( sizeof(fftw_complex) * size ); fftw_plan p = fftw_plan_dft_r2c_1d( size, in, out, FFTW_ESTIMATE ); if(fftWisdom.isEmpty()) { char * s = fftw_export_wisdom_to_string(); fftWisdom = QString::fromLatin1(s); } else { fftw_import_wisdom_from_string(fftWisdom.toLatin1().data()); } if( p!=NULL && in!=NULL && out!=NULL ) { statusBar()->showMessage(tr("Deriving the FFT data ...")); memcpy(&(in[0]), &(plotter->recordData.data()[start]), size * sizeof(double)); // take data from plot screen fftw_execute(p); fftMagnitudeData.fill(0.0, size); fftPhaseData.fill(0.0, size); psdData.fill(0.0, size); fftBottomData.resize(size); for(int i=0; i<size; ++i) { register int xr = out[i][0]; register int xi = out[i][1]; fftMagnitudeData[i] = qSqrt( xr*xr + xi*xi ); fftPhaseData[i] = atan2( (double) xi,(double) xr ); psdData[i] = xr*xr + xi*xi ; fftBottomData[i] = i; } statusBar()->showMessage(tr("")); } else {

statusBar()->showMessage(tr("Could not derive fft")); qDebug() << "cannot create plan";

41
} fftw_destroy_plan(p); fftw_free(in); fftw_free(out); // set datas if(fftMagnitudeCurve) fftMagnitudeCurve->setRawData( fftBottomData.data(), fftMagnitudeData.data(), size ); if(fftPhaseCurve) fftPhaseCurve->setRawData( fftBottomData.data(), fftPhaseData.data(), size ); if(psdCurve) psdCurve->setRawData( fftBottomData.data(), psdData.data(), size ); fftMagnitudePlot->replot(); fftPhasePlot->replot(); psdPlot->replot(); } }

void MainWindow::fftMinSpinChanged(int val) { fftMaxSpin->setMinimum(val+1); } void MainWindow::fftMaxSpinChanged(int val) { fftMinSpin->setMaximum(val-1); } void MainWindow::recordTimeChanged(int sec) { int m = sec / 60; int s = sec % 60; QString s_m; QString s_s; QString z("0"); if(m<10) s_m = z + QString::number(m); else s_m = QString::number(m); if(s<10) s_s = z + QString::number(s); else s_s = QString::number(s); recordTimeLabel->setText(s_m + QString(":") + s_s); } void MainWindow::toggleAverageFilter() { if(averageCheck->isChecked()) { averagePlot = new QwtPlot(tr("Average"), this); averagePlot->setCanvasBackground(Qt::white); gridLayout->addWidget(averagePlot, 2, 0); averageCurve = new QwtPlotCurve(tr("Average Curve"));

42
QwtPlotPicker * average_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::PointSelection | QwtPicker::DragSelection, QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, averagePlot->canvas()); average_picker->setRubberBandPen(QColor(Qt::green)); average_picker->setRubberBand(QwtPicker::CrossRubberBand); average_picker->setTrackerPen(QColor(Qt::blue)); int size = plotter->getSamplingRate() * plotter>getVisibleDuration(); averageData.fill(0.0, size); averageBottomData.resize(size); for( int i = 0 ; i < size ; ++i ) { averageBottomData[i] = i; } // call the update function updateAverageFilter(); if(averageCurve) averageCurve->setRawData( averageBottomData.data(), averageData.data(), averageBottomData.size() ); averageCurve->attach(averagePlot); // time scale TimeScaleDraw * tsd = new TimeScaleDraw(QTime(0,0), plotter>getSamplingRate()); averagePlot->setAxisScaleDraw(QwtPlot::xBottom, tsd ); averagePlot->setAxisScale(QwtPlot::xBottom, 0, size); averagePlot->setAxisLabelRotation(QwtPlot::xBottom, -50.0); averagePlot->setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom); // To avoid this "jumping canvas" effect, we add a permanent margin. QwtScaleWidget *scaleWidget = averagePlot>axisWidget(QwtPlot::xBottom); const int fmh = QFontMetrics(scaleWidget->font()).height(); scaleWidget->setMinBorderDist(0, fmh / 2); averagePlot->replot(); } else { plotter->setTitle(tr("Sampled Signal"));

if(averagePlot) { delete averageCurve; delete averagePlot; averageCurve = NULL; averagePlot = NULL; } } } plotter->setTitle(tr(""));

43
void MainWindow::updateAverageFilter() { if(averageCheck->isChecked()) { int winSize = averageSpin->value(); if( winSize < 3 || winSize % 2 == 0 || winSize > plotter>recordData.size() ) return; int recordSize = plotter->recordData.size(); int half = (winSize - 1) / 2; averageRecordData.fill ( 0.0, recordSize ); double * r = plotter->recordData.data(); double * a = averageRecordData.data(); // data without boundary spaces for(int i = half; i < recordSize - half; ++i) { double total = 0; for(int j = -half; j <= half; ++j) { total += r[i+j]; } a[i] = total / winSize; } scrollAverageFilter(timeScroll->value()); } } void MainWindow::scrollAverageFilter(int step) { if( ! averageCheck->isChecked()) return; if ( step > plotter->getMaxScrollStep() ) return; int size = plotter->getSamplingRate() * plotter>getVisibleDuration(); if( size > plotter->recordData.size()) { // copy recorddata and return memcpy(&(averageData.data()[0]), &(averageRecordData.data() [0]), averageRecordData.size() * sizeof(double)); averagePlot->replot(); return; } QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); int plotSplitCount = settings.value("plotSplitCount", 50).toInt(); settings.endGroup(); averagePlot->replot();

44
int sourceIndex = step*(size/plotSplitCount); memcpy(&(averageData.data()[0]), &(averageRecordData.data() [sourceIndex]), averageData.size() * sizeof(double)); unsigned int plotSize = averageBottomData.size(); double * d = averageBottomData.data(); int samplingRate = plotter->getSamplingRate(); QwtValueList vlist_y[3]; for ( unsigned int i = 0 ; i < plotSize ; ++i ) { register int x = sourceIndex + i; d[i] = x; if( 0 == x % samplingRate ) vlist_y[0] << d[i]; } averagePlot->setAxisScale(QwtPlot::xBottom, averageBottomData[0], averageBottomData[plotSize - 1]); QwtScaleDiv scdiv_y(averageBottomData.at(0), averageBottomData.at(averageBottomData.size()-1), vlist_y); scdiv_y.setTicks(QwtScaleDiv::MajorTick, vlist_y[0]); averagePlot->setAxisScaleDiv(QwtPlot::xBottom, scdiv_y); averagePlot->replot(); }

NewSamplingDialog.h
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #ifndef DEVSELECT_H #define DEVSELECT_H #include <QDialog> #include <QString> #include "ui_NewSamplingDialog.h" class NewSamplingDialog : public QDialog, private Ui::NewSamplingDialog { Q_OBJECT

45
public: NewSamplingDialog(QWidget * parent = 0); ~NewSamplingDialog() { } QString channelName; int terminalConfiguration; double minVoltage; double maxVoltage; unsigned int visibleDuration; unsigned int samplingRate; bool startRecordImmediately; private slots: void saveValues(); private: QStringList channelList; QStringList terminalList; }; #endif

NewSamplingDialog.cpp
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #include #include #include #include <QtGui> <QSettings> "NewSamplingDialog.h" "DeviceSensor.h"

NewSamplingDialog::NewSamplingDialog(QWidget * parent) : QDialog(parent) //channelName(""), //terminalConfiguration(0), //minVoltage(0), //maxVoltage(0), //visibleDuration(0), //samplingRate(0), //startRecordImmediately(false)

46
{ /*setAttribute(Qt::WA_DeleteOnClose);*/ setupUi(this); QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("NewSamplingDialog"); channelName = settings.value("channelName", QString()).toString(); terminalConfiguration = settings.value("terminalConfiguration", 0).toInt(); minVoltage = settings.value("minVoltage", 0.0).toDouble(); maxVoltage = settings.value("maxVoltage", 0.0).toDouble(); visibleDuration = settings.value("visibleDuration", 0).toUInt(); samplingRate = settings.value("samplingRate", 0).toUInt(); startRecordImmediately = settings.value("startRecordImmediately", 0).toBool(); settings.endGroup(); settings.beginGroup("Settings"); QString currentDevice = settings.value("currentDevice", QString("")).toString(); settings.endGroup(); deviceEdit->setText(currentDevice + " : " + DeviceSensor::getLongDeviceName(currentDevice)); minSpin->setMinimum(DeviceSensor::getAIMinVoltage(currentDevice)); minSpin->setMaximum(DeviceSensor::getAIMaxVoltage(currentDevice)); maxSpin->setMinimum(DeviceSensor::getAIMinVoltage(currentDevice)); maxSpin->setMaximum(DeviceSensor::getAIMaxVoltage(currentDevice)); rateSpin>setMinimum(DeviceSensor::getAIMinSampleRate(currentDevice)); rateSpin>setMaximum(DeviceSensor::getAIMaxSampleRate(currentDevice)); // fill channel list and select saved channelList = DeviceSensor::getAIChannelNames(currentDevice); foreach(QString chan, channelList){ channelCombo->addItem(chan); int count = -1; int index = -1; foreach(QString chan, channelList){ count++; if(channelName == chan) index = count; } if(index != -1){ channelCombo->setCurrentIndex(index); }

// fill terminalconf list and select saved terminalList = DeviceSensor::getAITerminalConfigurations(currentDevice); foreach(QString term, terminalList){ terminalCombo->addItem(term); } terminalCombo->setCurrentIndex(terminalConfiguration);

47
minSpin->setValue(minVoltage); maxSpin->setValue(maxVoltage); rateSpin->setValue(samplingRate); visibleSpin->setValue(visibleDuration); startRecordCheck->setChecked(startRecordImmediately); connect(buttonBox, SIGNAL(accepted()), this, SLOT(saveValues())); } void NewSamplingDialog::saveValues() { channelName = channelList.at(channelCombo->currentIndex()); terminalConfiguration = terminalCombo->currentIndex(); minVoltage = minSpin->value(); maxVoltage = maxSpin->value(); visibleDuration = visibleSpin->value(); samplingRate = rateSpin->value(); startRecordImmediately = startRecordCheck->isChecked(); QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("NewSamplingDialog"); settings.setValue("channelName", channelName); settings.setValue("terminalConfiguration", terminalConfiguration); settings.setValue("minVoltage", minVoltage); settings.setValue("maxVoltage", maxVoltage); settings.setValue("visibleDuration", visibleDuration); settings.setValue("samplingRate", samplingRate); settings.setValue("startRecordImmediately", startRecordImmediately); settings.endGroup(); }

InfoDialog.h
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #ifndef INFODIALOG_H #define INFODIALOG_H #include <QDialog> #include <QWidget>

48
#include "ui_InfoDialog.h" class InfoDialog : public QDialog, private Ui::InfoDialog { Q_OBJECT public: InfoDialog(QWidget * parent = 0); private slots: void deviceComboChanged(int); private: QStringList deviceList; }; #endif

InfoDialog.cpp
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #include #include #include #include #include <QtGui> <QString> <QStringList> "InfoDialog.h" "DeviceSensor.h"

InfoDialog::InfoDialog(QWidget * parent) : QDialog(parent) { setAttribute(Qt::WA_DeleteOnClose); setupUi(this); deviceCombo->clear(); deviceList = DeviceSensor::getDeviceNames(); foreach(QString dev, deviceList){ deviceCombo->addItem(DeviceSensor::getLongDeviceName(dev) + " : " + dev); } connect(deviceCombo,SIGNAL(currentIndexChanged(int)), this, SLOT(deviceComboChanged(int)));

49
deviceComboChanged(0);

void InfoDialog::deviceComboChanged(int index){ QString text; QStringList strList; QString deviceName = DeviceSensor::getLongDeviceName(deviceList.at(index)); text += "<h2>" + deviceName + " : " + deviceList.at(index) + "</h2>"; if(DeviceSensor::isSimulated(deviceList.at(index))){ text += tr("<p><strong>Simulated Device</strong><br>Note that; some values may not consistent !</p>") + "<br>"; } text += tr("<strong>Sample Rates :</strong>") + "<br>"; text += tr("Analog Input Min : "); text += QString::number(DeviceSensor::getAIMinSampleRate(deviceList.at(index))) + "<br>"; text += tr("Analog Input Max : "); text += QString::number(DeviceSensor::getAIMaxSampleRate(deviceList.at(index))) + "<br>"; text += tr("Analog Output Min : "); text += QString::number(DeviceSensor::getAOMinSampleRate(deviceList.at(index))) + "<br>"; text += tr("Analog Output Max : "); text += QString::number(DeviceSensor::getAOMaxSampleRate(deviceList.at(index))) + "<br>"; text += tr("Digital Output Max : "); text += QString::number(DeviceSensor::getDOMaxRate(deviceList.at(index))) + "<br>"; text += tr("<strong>Voltage Ranges :</strong>") + "<br>"; text += tr("Analog Input Min : "); text += QString::number(DeviceSensor::getAIMinVoltage(deviceList.at(index))) "<br>"; text += tr("Analog Input Max : "); text += QString::number(DeviceSensor::getAIMaxVoltage(deviceList.at(index))) "<br>"; text += tr("Analog Output Min : "); text += QString::number(DeviceSensor::getAOMinVoltage(deviceList.at(index))) "<br>"; text += tr("Analog Output Max : "); text += QString::number(DeviceSensor::getAOMaxVoltage(deviceList.at(index))) "<br>";

//text += tr("<strong>Terminal Configurations :</strong>") + "<br>"; //strList = DeviceSensor::getAITerminalConfigurations(deviceList.at(index)); //foreach(QString str, strList){ // text += str + "<br>"; //}

50
strList.clear(); text += tr("<strong>Analog Input Channels :</strong>") + "<br>"; strList = DeviceSensor::getAIChannelNames(deviceList.at(index)); foreach(QString str, strList){ text += str + "<br>"; } strList.clear(); text += tr("<strong>Analog Output Channels :</strong>") + "<br>"; strList = DeviceSensor::getAOChannelNames(deviceList.at(index)); foreach(QString str, strList){ text += str + "<br>"; } strList.clear(); text += tr("<strong>Digital Output Lines :</strong>") + "<br>"; strList = DeviceSensor::getDOLines(deviceList.at(index)); foreach(QString str, strList){ text += str + "<br>"; } } infoEdit->setText(text);

SettingsDialog.h
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #ifndef SETTINGSDIALOG_H #define SETTINGSDIALOG_H #include <QDialog> #include <QWidget> #include "ui_SettingsDialog.h" class QString; class QStringList; class SettingsDialog : public QDialog, private Ui::SettingsDialog { Q_OBJECT public: SettingsDialog(QWidget * parent = 0);

51
public slots: void deviceComboChanged(int); void analogOutComboChanged(int); void digitalOutComboChanged(int); void saveButtonClicked(); void revertButtonClicked(); public: QString selectedDevice; QString selectedAOChannel; QString selectedDOLine; private: QStringList deviceList; QStringList channelList; QStringList lineList; }; #endif

SettingsDialog.cpp
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #include #include #include #include #include <QtGui> <QString> <QStringList> "SettingsDialog.h" "DeviceSensor.h"

SettingsDialog::SettingsDialog(QWidget * parent) : QDialog(parent) { setAttribute(Qt::WA_DeleteOnClose); setupUi(this); deviceCombo->clear(); deviceList = DeviceSensor::getDeviceNames(); foreach(QString dev, deviceList){ deviceCombo->addItem(dev + " : " + DeviceSensor::getLongDeviceName(dev));

52
} connect(deviceCombo,SIGNAL(currentIndexChanged(int)), this, SLOT(deviceComboChanged(int))); connect(analogOutCombo,SIGNAL(currentIndexChanged(int)), this, SLOT(analogOutComboChanged(int))); connect(digitalOutCombo,SIGNAL(currentIndexChanged(int)), this, SLOT(digitalOutComboChanged(int))); connect(saveButton,SIGNAL(clicked()), this, SLOT(saveButtonClicked())); connect(revertButton,SIGNAL(clicked()), this, SLOT(revertButtonClicked())); connect(closeButton,SIGNAL(clicked()), this, SLOT(close())); deviceComboChanged(0); revertButtonClicked(); } void SettingsDialog::deviceComboChanged(int index){ if(index < deviceList.size()) { selectedDevice = deviceList.at(index); if( ! selectedDevice.isEmpty()) { analogOutCombo->clear(); channelList = DeviceSensor::getAOChannelNames(selectedDevice); foreach(QString chan, channelList){ analogOutCombo->addItem(chan); } digitalOutCombo->clear(); lineList = DeviceSensor::getDOLines(selectedDevice); foreach(QString line, lineList){ digitalOutCombo->addItem(line); }

} } }

void SettingsDialog::analogOutComboChanged(int index){ if(index < channelList.size() && index >= 0 ) selectedAOChannel = channelList.at(index); } void SettingsDialog::digitalOutComboChanged(int index){ if(index < lineList.size() && index >= 0 ) selectedDOLine = lineList.at(index); } void SettingsDialog::saveButtonClicked(){ QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); settings.setValue("currentDevice", deviceList.at(deviceCombo-

53
>currentIndex())); settings.setValue("currentAOChannel", channelList.at(analogOutCombo>currentIndex())); settings.setValue("currentDOLine", lineList.at(digitalOutCombo>currentIndex())); settings.setValue("maxVisiblePoint", maxVisiblePointSpin->value()); settings.setValue("plotSplitCount", plotSplitCountSpin->value()); settings.setValue("fifoSize", fifoSizeSpin->value()); settings.setValue("refreshRate", refreshRateSpin->value()); settings.setValue("analogOutStep", analogOutStepSpin->value()); settings.endGroup(); } void SettingsDialog::revertButtonClicked(){ QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); QString currentDevice = settings.value("currentDevice", QString("")).toString(); QString currentAOChannel = settings.value("currentAOChannel", QString("")).toString(); QString currentDOLine = settings.value("currentDOLine", QString("")).toString(); unsigned int maxVisiblePoint = settings.value("maxVisiblePoint", 1000).toUInt(); unsigned int plotSplitCount = settings.value("plotSplitCount", 50).toUInt(); unsigned int fifoSize = settings.value("fifoSize", 1000000).toUInt(); unsigned int refreshRate = settings.value("refreshRate", 20).toUInt(); double analogOutStep = settings.value("analogOutStep", 0.1).toDouble(); settings.endGroup(); // for device combo int count = -1; int index = -1; foreach(QString dev, deviceList){ count++; if(currentDevice == dev) index = count; } if(index != -1){ deviceCombo->setCurrentIndex(index); } // for channel combo count = -1; index = -1; foreach(QString chan, channelList){ count++; if(currentAOChannel == chan) index = count; } if(index != -1){ analogOutCombo->setCurrentIndex(index); } // for line combo

54
count = -1; index = -1; foreach(QString line, lineList){ count++; if(currentDOLine == line) index = count; if(index != -1){ digitalOutCombo->setCurrentIndex(index); } maxVisiblePointSpin->setValue(maxVisiblePoint); plotSplitCountSpin->setValue(plotSplitCount); fifoSizeSpin->setValue(fifoSize); refreshRateSpin->setValue(refreshRate); analogOutStepSpin->setValue(analogOutStep); }

DeviceSensor.h
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #ifndef DEVICESENSOR_H #define DEVICESENSOR_H #include <QObject> #include <NIDAQmx.h> class QString; class QStringList; class DeviceSensor : public QObject { Q_OBJECT public: DeviceSensor(); virtual ~DeviceSensor(); static QStringList getDeviceNames(void);

55
static QString static QStringList static QStringList static QStringList static QStringList deviceName); static bool static static static static static static static static static enum double double double double double double double double double getLongDeviceName(QString deviceName); getAIChannelNames(QString deviceName); getAOChannelNames(QString deviceName); getDOLines(QString deviceName); getAITerminalConfigurations(QString isSimulated(QString deviceName); getAIMinSampleRate(QString deviceName); getAIMaxSampleRate(QString deviceName); getAOMinSampleRate(QString deviceName); getAOMaxSampleRate(QString deviceName); getDOMaxRate(QString deviceName); getAIMinVoltage(QString getAIMaxVoltage(QString getAOMinVoltage(QString getAOMaxVoltage(QString deviceName); deviceName); deviceName); deviceName);

DAQmx_Val_PseudoDiff,

TerminalConfigurations { AIDefault = DAQmx_Val_Cfg_Default, AIReferenced = DAQmx_Val_RSE, AINonReferenced = DAQmx_Val_NRSE, AIDifferential = DAQmx_Val_Diff, AIPseudoDifferential = AOReferenced = DAQmx_Val_RSE, AODifferential = DAQmx_Val_Diff, AOPseudoDifferential = };

DAQmx_Val_PseudoDiff }; #endif

DeviceSensor.cpp
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #include "DeviceSensor.h"

56
#include #include #include #include #include <QString> <QStringList> <QByteArray> <QMap> <QMessageBox>

#include <NIDAQmx.h> DeviceSensor::DeviceSensor(){ } DeviceSensor::~DeviceSensor(){ } QStringList DeviceSensor::getDeviceNames(){ QByteArray ba(1024,0); DAQmxGetSysDevNames(ba.data(), 1024); QString devices(ba); QStringList deviceList = devices.split(","); for(int i=0; i<deviceList.size(); ++i){ deviceList[i] = deviceList[i].trimmed(); } return deviceList; } QStringList DeviceSensor::getAIChannelNames(QString deviceName){ QByteArray ba(1024,0); DAQmxGetDevAIPhysicalChans(deviceName.toAscii().constData(), ba.data(), 1024); QString channels(ba); QStringList channelList = channels.split(","); for(int i=0; i<channelList.size(); ++i){ channelList[i] = channelList[i].trimmed(); } return channelList; } QStringList DeviceSensor::getAOChannelNames(QString deviceName){ QByteArray ba(1024,0); DAQmxGetDevAOPhysicalChans(deviceName.toAscii().constData(), ba.data(), 1024); QString channels(ba); QStringList channelList = channels.split(","); for(int i=0; i<channelList.size(); ++i){ channelList[i] = channelList[i].trimmed(); } return channelList; } QStringList DeviceSensor::getDOLines(QString deviceName){ QByteArray ba(1024,0); DAQmxGetDevDOLines(deviceName.toAscii().constData(), ba.data(), 1024); QString lines(ba); QStringList lineList = lines.split(","); for(int i=0; i<lineList.size(); ++i){ lineList[i] = lineList[i].trimmed(); } return lineList;

57
} QStringList DeviceSensor::getAITerminalConfigurations(QString deviceName){ QStringList conf; conf << "Referenced Single-Ended." << "Non-Referenced Single-Ended." << "Differential." << "Pseudodifferential."; return conf; } bool DeviceSensor::isSimulated(QString deviceName){ bool32 b; DAQmxGetDevIsSimulated(deviceName.toAscii().constData(), &b); return b; } double DeviceSensor::getDOMaxRate(QString deviceName){ float64 rate = 0; DAQmxGetDevDOMaxRate(deviceName.toAscii().constData(), &rate); return rate; } double DeviceSensor::getAIMinSampleRate(QString deviceName){ float64 rate = 0; DAQmxGetDevAIMinRate(deviceName.toAscii().constData(), &rate); return rate; } double DeviceSensor::getAIMaxSampleRate(QString deviceName){ float64 rate = 0; DAQmxGetDevAIMaxSingleChanRate(deviceName.toAscii().constData(), &rate); return rate; } double DeviceSensor::getAOMinSampleRate(QString deviceName){ float64 rate = 0; DAQmxGetDevAOMinRate(deviceName.toAscii().constData(), &rate); return rate; } double DeviceSensor::getAOMaxSampleRate(QString deviceName){ float64 rate = 0; DAQmxGetDevAOMaxRate(deviceName.toAscii().constData(), &rate); return rate; } double DeviceSensor::getAIMinVoltage(QString deviceName){ float64 marray[100] = {0}; DAQmxGetDevAIVoltageRngs(deviceName.toAscii().constData(), marray, 100); float64 min = 0; for (int i=0; i<100; i++) { if (min > marray[i]) min = marray[i]; } return min; } double DeviceSensor::getAIMaxVoltage(QString deviceName){

58
float64 marray[100] = {0}; DAQmxGetDevAIVoltageRngs(deviceName.toAscii().constData(), marray, float64 max = 0; for (int i=0; i<100; i++) { if (max < marray[i]) max = marray[i]; } return max; } double DeviceSensor::getAOMinVoltage(QString deviceName){ float64 marray[100] = {0}; DAQmxGetDevAOVoltageRngs(deviceName.toAscii().constData(), marray, 100); float64 min = 0; for (int i=0; i<100; i++) { if (min > marray[i]) min = marray[i]; } return min; } double DeviceSensor::getAOMaxVoltage(QString deviceName){ float64 marray[100] = {0}; DAQmxGetDevAOVoltageRngs(deviceName.toAscii().constData(), marray, 100); float64 max = 0; for (int i=0; i<100; i++) { if (max < marray[i]) max = marray[i]; } return max; } QString DeviceSensor::getLongDeviceName(QString deviceName){ QMap<QString, int> names; names.insert("NI PCI-DIO-96", 0x0160 ); names.insert("NI PCI-MIO-16XE-50", 0x0162 names.insert("NI DAQCard-6036E", 0x0245 names.insert("NI DAQCard-6062E", 0x02C4 names.insert("NI SCXI-1126", 0x0301 ); names.insert("NI SCXI-1121", 0x0302 ); names.insert("NI SCXI-1129", 0x0303 ); names.insert("NI SCXI-1120", 0x0304 ); names.insert("NI SCXI-1100", 0x0306 ); names.insert("NI SCXI-1140", 0x0308 ); names.insert("NI SCXI-1122", 0x030A ); names.insert("NI SCXI-1160", 0x030C ); names.insert("NI SCXI-1125", 0x030D ); names.insert("NI SCXI-1161", 0x030E ); names.insert("NI SCXI-1162", 0x0310 ); names.insert("NI SCXI-1163", 0x0312 ); names.insert("NI SCXI-1124", 0x0314 ); names.insert("NI SCXI-1162HV", 0x0318 ); names.insert("NI SCXI-1163R", 0x031C ); names.insert("NI SCXI-1102", 0x031E ); names.insert("NI SCXI-1102B", 0x031F ); names.insert("NI SCXI-1141", 0x0320 ); names.insert("NI SCXI-1112", 0x0321 );

100);

); ); );

59
names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI SCXI-1191", 0x0322 ); SCXI-1190", 0x0323 ); SCXI-1192", 0x0324 ); SCXI-1600", 0x0329 ); SCXI-1104", 0x032D ); SCXI-1104C", 0x032F ); SCXI-1531", 0x0330 ); SCXI-1540", 0x0331 ); SCXI-1530", 0x0332 ); SCXI-1102C", 0x033E ); SCXI-1143", 0x0340 ); SCXI-1120D", 0x0344 ); SCXI-1127", 0x0345 ); SCXI-1128", 0x0346 ); SCXI-1142", 0x0360 ); SCXI-1500", 0x038F ); SCXI-1520", 0x0407 ); SCXI-1581", 0x048B ); SCC-A10", 0x04AC ); SCC-CI20", 0x04AD ); SCC-FT01", 0x04AE ); SCC-TC01", 0x04B2 ); SCC-TC02", 0x04B3 ); SCC-FV01", 0x04B4 ); SCC-DI01", 0x04B6 ); SCC-DO01", 0x04B7 ); SCC-LP01", 0x04B8 ); SCC-LP02", 0x04B9 ); SCC-LP03", 0x04BA ); SCC-LP04", 0x04BC ); SCC-RTD01", 0x04BD ); SCC-SG01", 0x04BE ); SCC-CO20", 0x04BF ); SCC-AI01", 0x04DA ); SCC-AI02", 0x04DB ); SCC-AI03", 0x04DC ); SCC-AI04", 0x04DD ); SCC-AI05", 0x04DE ); SCC-AI06", 0x04DF ); SCC-AI07", 0x04E0 ); SCC-AI13", 0x04E1 ); SCC-AI14", 0x04E2 ); SCC-SG02", 0x04E3 ); SCC-SG03", 0x04E4 ); SCC-SG04", 0x04E5 ); SCC-SG11", 0x04E6 ); SCC-ACC01", 0x04EA ); SCC-RLY01", 0x04F0 ); SCC-AO10", 0x04F6 ); DAQCard-DIO-24", 0x075C DAQCard-6024E", 0x075E DAQCard-6715", 0x075F ); PCI-DIO-32HS", 0x1150 ); PCI-MIO-16XE-10", 0x1170 PCI-MIO-16E-1", 0x1180 PCI-MIO-16E-4", 0x1190 PXI-6070E", 0x11B0 ); PXI-6040E", 0x11C0 ); PXI-6030E", 0x11D0 ); PCI-6032E", 0x1270 ); PCI-6704", 0x1290 );

); ); ); ); );

60
names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI PCI-6534", 0x12B0 PCI-6602", 0x1310 PXI-6533", 0x1320 PCI-6031E", 0x1330 PCI-6033E", 0x1340 PCI-6071E", 0x1350 PXI-6602", 0x1360 PXI-6508", 0x13C0 PXI-6534", 0x1490 PCI-6110", 0x14E0 PCI-6111", 0x14F0 PXI-6031E", 0x1580 PXI-6071E", 0x15B0 PXI-6509", 0x1710 PCI-6503", 0x17D0 PCI-6713", 0x1870 PCI-6711", 0x1880 PCI-6052E", 0x18B0 PXI-6052E", 0x18C0 PXI-6704", 0x1920 6040E", 0x1930 ); PCI-6133", 0x1AD0 PXI-6133", 0x1AE0 PCI-6624", 0x1E30 PXI-6624", 0x1E40 PCI-6733", 0x2410 PXI-6733", 0x2420 PCI-6731", 0x2430 PXI-4200", 0x24B0 PXI-4472", 0x24F0 PCI-4472", 0x2510 PCI-4474", 0x2520 PCI-6123", 0x27A0 PXI-6123", 0x27B0 PCI-6036E", 0x2890 PXI-4461", 0x28A0 PCI-6013", 0x28B0 PCI-6014", 0x28C0 PCI-6023E", 0x2A60 PCI-6024E", 0x2A70 PCI-6025E", 0x2A80 PXI-6025E", 0x2AB0 PXI-6527", 0x2B10 PCI-6527", 0x2B20 PXI-6713", 0x2B80 PXI-6711", 0x2B90 PCI-6601", 0x2C60 PCI-6035E", 0x2C80 PCI-6703", 0x2C90 PCI-6034E", 0x2CA0 PXI-6608", 0x2CC0 PXI-6115", 0x2EC0 PCI-6115", 0x2ED0 PXI-6120", 0x2EE0 PCI-6120", 0x2EF0 PXI-2593", 0x7023 SCXI-1193", 0x7024 SCXI-1166", 0x703D SCXI-1167", 0x703E PXI-2566", 0x703F PXI-2567", 0x7040 ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); );

61
names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI SCXI-1130", PXI-2530", PXI-4220", PXI-4204", PXI-2529", PCI-6723", PXI-4462", PCI-6509", PXI-6528", PCI-6515", PCI-6514", PXI-2568", PXI-2569", SCXI-1169", SCC-SG24", USB-9421", USB-9472", USB-9481", WLS-9211", ENET-9211", USB-9201", USB-9221", WLS-9215", ENET-9215", USB-9263", USB-9233", PCI-6528", PCI-6229", PCI-6259", PCI-6289", PXI-6251", PXI-6220", PCI-6221", PCI-6220", PXI-6229", PXI-6259", PXI-6289", PCI-6250", PXI-6221", PCI-6280", PCI-6254", PCI-6251", PXI-6250", PXI-6254", PXI-6280", PCI-6284", PCI-6281", PXI-6284", PXI-6281", PCI-6143", PCI-6511", PCI-6513", PXI-6515", PCI-6512", PXI-6514", PXI-2570", PXI-6513", PXI-6512", PXI-6511", PCI-6722", PXI-2532", 0x704B 0x704C 0x704F 0x7050 0x7067 0x7073 0x707E 0x7085 0x7086 0x7087 0x7088 0x708C 0x708D 0x7090 0x7099 0x709F 0x70A1 0x70A2 0x70A3738E 0x70A3738F 0x70A4 0x70A5 0x70A6738E 0x70A6738F 0x70A7 0x70A8 0x70A9 0x70AA 0x70AB 0x70AC 0x70AD 0x70AE 0x70AF 0x70B0 0x70B1 0x70B2 0x70B3 0x70B4 0x70B5 0x70B6 0x70B7 0x70B8 0x70B9 0x70BA 0x70BB 0x70BC 0x70BD 0x70BE 0x70BF 0x70C0 0x70C3 0x70C8 0x70C9 0x70CC 0x70CD 0x70D0 0x70D1 0x70D2 0x70D3 0x70D4 0x70E1 ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); );

62
names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI PCI-6224", 0x70F2 ); PXI-6224", 0x70F3 ); DAQPad-6015", 0x70FA ); DAQPad-6016", 0x70FB ); PXI-6723", 0x70FF ); PXI-6722", 0x7100 ); SCXI-1521", 0x7103 ); PXI-6143", 0x710D ); PCI-6510", 0x7124 ); PCI-6516", 0x7125 ); PCI-6517", 0x7126 ); PCI-6518", 0x7127 ); PCI-6519", 0x7128 ); USB-9421 (DSUB)", 0x712E ); USB-9472 (DSUB)", 0x7132 ); WLS-9215 (BNC)", 0x7135738E ); ENET-9215 (BNC)", 0x7135738F ); PXI-2575", 0x7137 ); PXI-2585", 0x713C ); PXI-2586", 0x713D ); SCXI-1175", 0x713F ); PXI-4224", 0x7142 ); SCXI-1521B", 0x7143 ); PCI-6132", 0x7146 ); PXI-6132", 0x7147 ); PCI-6122", 0x7148 ); PXI-6122", 0x7149 ); PXI-2564", 0x7150 ); 9221", 0x715F ); 9421", 0x7160 ); 9421 (DSUB)", 0x7161 ); 9472", 0x7162 ); 9472 (DSUB)", 0x7163 ); 9481", 0x7164 ); 9401", 0x7165 ); PCI-6230", 0x716B ); PCI-6225", 0x716C ); PXI-6225", 0x716D ); PCI-4461", 0x716F ); PCI-4462", 0x7170 ); PCI-6010", 0x7171 ); DAQPad-6015 (Mass Termination)", 0x7172 DAQPad-6015 (BNC)", 0x7173 ); PXI-6230", 0x7177 ); USB-6008", 0x717A ); USB-6009", 0x717B ); PCIe-6251", 0x717D ); PCIe-6259", 0x717F ); USB-6501", 0x718A ); PCI-6521", 0x718B ); PXI-6521", 0x718C ); PCI-6154", 0x7191 ); USB-9201 (DSUB)", 0x71A1 ); USB-9221 (DSUB)", 0x71A2 ); PXI-2594", 0x71A5 ); SCXI-1194", 0x71A6 ); PXI-2595", 0x71A7 ); SCXI-1195", 0x71A8 ); PXI-2596", 0x71A9 ); PXI-2597", 0x71AA ); PXI-2598", 0x71AB );

);

63
names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI PXI-2599", 0x71AC ); 9211", 0x71B0 ); 9215", 0x71B1 ); 9215 (BNC)", 0x71B2 ); 9205 (DSUB)", 0x71B3 ); 9263", 0x71B4 ); PXI-2584", 0x71BB ); PCI-6221 (37-pin)", 0x71BC USB-9239", 0x71C2 ); USB-9237", 0x71C3 ); WLS-9237", 0x71C3738E ); ENET-9237", 0x71C3738F ); PCI-6520", 0x71C5 ); PXI-2576", 0x71C6 ); USB-9211A", 0x71D9 ); USB-9215A", 0x71DA ); USB-9215A (BNC)", 0x71DB USB-6525", 0x71DF ); PCI-6255", 0x71E0 ); PXI-6255", 0x71E1 ); 9233", 0x71E7 ); SCXI-1502", 0x71E8 ); PCI-6233", 0x7209 ); PXI-6233", 0x720A ); PCI-6238", 0x720B ); PXI-6238", 0x720C ); USB-6251", 0x7252 ); USB-6259", 0x7253 ); 9234", 0x7263 ); 9206", 0x7264 ); 9205", 0x7265 ); SCXI-1503", 0x726A ); SCC-CTR01", 0x726E ); USB-6210", 0x726F ); USB-6211", 0x7270 ); USB-6215", 0x7271 ); USB-6218", 0x7272 ); PXI-4461", 0x7273 ); PXI-4462", 0x7274 ); PCI-6232", 0x7279 ); PXI-6232", 0x727A ); PCI-6239", 0x727B ); PXI-6239", 0x727C ); PCI-6236", 0x7281 ); PXI-6236", 0x7282 ); PXI-2554", 0x7283 ); 9237", 0x7285 ); USB-6251 (Mass Termination)", USB-6259 (Mass Termination)", USB-9234", 0x72B5 ); WLS-9234", 0x72B5738E ); ENET-9234", 0x72B5738F ); 9411", 0x72B9 ); 9422", 0x72BA ); 9423", 0x72BB ); 9435", 0x72BC ); 9474", 0x72BD ); 9485", 0x72BE ); 9403", 0x72BF ); 9425", 0x72C0 ); 9476", 0x72C1 );

);

);

0x72A0 0x72A1

); );

64
names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI 9477", 0x72C2 ); 9264", 0x72C3 ); 9265", 0x72C4 ); 9201", 0x72C5 ); 9201 (DSUB)", 0x72C6 ); 9221 (DSUB)", 0x72C7 ); 9203", 0x72C8 ); 9217", 0x72C9 ); 9219", 0x72CA ); 9239", 0x72CB ); SensorDAQ", 0x72CC ); PXI-2545", 0x72D0 ); PXI-2546", 0x72D1 ); PXI-2547", 0x72D2 ); PXI-2548", 0x72D3 ); PXI-2549", 0x72D4 ); PXI-2555", 0x72D5 ); PXI-2556", 0x72D6 ); PXI-2557", 0x72D7 ); PXI-2558", 0x72D8 ); PXI-2559", 0x72D9 ); USB-6221", 0x72DC ); USB-6229", 0x72DE ); PXI-4498", 0x72EF ); PXI-4496", 0x72F0 ); USB-6005 VSA", 0x72F3 ); 9229", 0x72FA ); USB-9229", 0x72FD ); USB-6509", 0x72FF ); USB-9219", 0x730C ); WLS-9219", 0x730C738E ); ENET-9219", 0x730C738F ); USB-4431", 0x7318 ); PXI-2535", 0x731C ); PXI-2536", 0x731D ); PXIe-6124", 0x7322 ); PXI-6529", 0x7327 ); USB-6255", 0x732D ); USB-6255 (Mass Termination)", USB-6225", 0x732F ); USB-6225 (Mass Termination)", PXI-2533", 0x7335 ); PXI-2534", 0x7336 ); 9402", 0x7337 ); USB-6212", 0x7339 ); USB-6216", 0x733B ); USB-6281", 0x733F ); USB-6281 (Mass Termination)", PXI-4461", 0x7342 ); USB-6289", 0x7343 ); USB-6289 (Mass Termination)", USB-6221 (BNC)", 0x7345 USB-6229 (BNC)", 0x7346 USB-6251 (BNC)", 0x7347 USB-6259 (BNC)", 0x7348 PXI-4495", 0x7359 ); USB-9239 (BNC)", 0x7367 USB-9229 (BNC)", 0x7368 USB-9263 (BNC)", 0x7369 PXI-4461", 0x7370 ); 9229 (BNC)", 0x737A );

0x732E 0x7330

); );

0x7340 0x7344 ); ); ); ); ); ); );

); );

65
names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI names.insert("NI 9239 (BNC)", 0x737B ); 9263 (BNC)", 0x737C ); 9235", 0x7381 ); 9236", 0x7382 ); 9225", 0x7388 ); USB-6212 (Mass Termination)", USB-6216 (Mass Termination)", PXIe-4498", 0x73A1 ); PXIe-4496", 0x73A2 ); USB-9213", 0x73A3 ); ELVIS II", 0x73A6 ); PXIe-2527", 0x73C5 ); PXIe-2529", 0x73C6 ); PXIe-2530", 0x73C8 ); PXIe-2532", 0x73C9 ); PXIe-2569", 0x73CA ); PXIe-2575", 0x73CB ); PXIe-2593", 0x73CC ); USB-4432", 0x73D1 ); 9213", 0x73E2 ); 9426", 0x73E3 ); 9475", 0x73E4 ); 9478", 0x73E5 ); 9237 (DSUB)", 0x73E6 ); PXI-2501", 0x9020 ); PXI-2503", 0x9030 ); PXI-2527", 0x9040 ); PXI-2565", 0x9050 ); PXI-2590", 0x9060 ); PXI-2591", 0x9070 );

0x7389 0x738A

); );

uInt32 productNumber; DAQmxGetDevProductNum(deviceName.toAscii().constData(), &productNumber); return names.key(productNumber); }

DeviceController.h
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #ifndef DEVICECONTROLLER_H

66
#define DEVICECONTROLLER_H #include <QObject> #include <NIDAQmx.h> #include <QVector> QT_BEGIN_NAMESPACE class QTimer; QT_END_NAMESPACE class Plotter; class DeviceController : public QObject { Q_OBJECT public: DeviceController(Plotter * plotter); virtual ~DeviceController(); QString getLastError(){ return lastError; } int getState(){ return state; } bool newSampling( QString channelName, int terminalConfiguration, double minVoltage, double maxVoltage, unsigned int visibleDuration, unsigned int samplingRate, bool startRecordImmediately = false ); static int32 CVICALLBACK callback_Wrapper( TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData); int32 CVICALLBACK callback( TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData); bool startAnalogOut(double value); bool stopAnalogOut(); bool updateAnalogOut(double value); bool startDigitalOut(int frequency); bool stopDigitalOut(); bool updateDigitalOut(int frequency); signals: void stateChanged(int state); void logMessage(QString message); public slots: void timerFunction(); void startRecording(); // to recording void pauseRecording(); // to plotting void stopRecording(); // to scrolling void clearSampling(); // to waiting void stopSampling(); public: enum State {NoDevice, Waiting, Plotting, Recording, Scrolling, Paused} state;

67
private: void saveLastError(QString errorPrefix); private: QVector<double> unsigned int unsigned int unsigned int volatile bool QAtomicInt QString TaskHandle TaskHandle TaskHandle unsigned int QTimer Plotter }; #endif fifo; fifo_r; fifo_w; fifo_size; overflow; fifo_count; lastError; taskHandle; taskHandleAnalogOut; taskHandleDigitalOut; refreshRate; * timer; * plotter;

DeviceController.cpp
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #include "DeviceController.h" #include <NIDAQmx.h> #include #include #include #include #include #include #include <QVector> <QSettings> <QDir> <QDebug> "Plotter.h" <QTimer> "DeviceSensor.h"

DeviceController::DeviceController(Plotter * plotter) : taskHandle( NULL ),

68
taskHandleAnalogOut( NULL ), taskHandleDigitalOut( NULL ), fifo_r(0), fifo_w(0), overflow(false), fifo_count(0), plotter(plotter), state(Waiting)

QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); QString currentDevice = settings.value("currentDevice", QString("")).toString(); fifo_size = settings.value("fifoSize", 1000000).toUInt(); refreshRate = settings.value("refreshRate", 20).toUInt(); settings.endGroup(); fifo.resize(fifo_size); if(currentDevice.isEmpty()) state = NoDevice; emit stateChanged(state); timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(timerFunction())); }

DeviceController::~DeviceController() { clearSampling(); stopAnalogOut(); stopDigitalOut(); }

bool DeviceController::newSampling( QString channelName, int terminalConfiguration, double minVoltage, double maxVoltage, unsigned int visibleDuration, unsigned int samplingRate, bool startRecordImmediately ) { if( state == NoDevice ) { lastError = tr("No device"); emit logMessage(lastError); return false; } if( state == Plotting || state == Recording ) { lastError = tr("A sampling is already running. First stop sampling than retry again."); emit logMessage(lastError); return false; }

69
if( 0 != DAQmxCreateTask( "", &taskHandle) ) { saveLastError(tr("While creating the analog in task:\n")); return false; } if( 0 != DAQmxCreateAIVoltageChan( taskHandle, channelName.toAscii().constData(), "", ) ) terminalConfiguration, minVoltage, maxVoltage, DAQmx_Val_Volts, NULL

{ saveLastError(tr("While creating the analog in voltage channel:\n")); return false; } if( 0 != DAQmxCfgSampClkTiming( taskHandle, NULL /* OnboardClock */, samplingRate /* per second per channel */, DAQmx_Val_Rising, DAQmx_Val_ContSamps, fifo_size /* buffer size */ ) ) { saveLastError(tr("While configuring the clock timing:\n")); return false; } if( 0 != DAQmxRegisterEveryNSamplesEvent( taskHandle, DAQmx_Val_Acquired_Into_Buffer /* for input */, samplingRate/refreshRate /* nSamples */, 0, &callback_Wrapper, reinterpret_cast<void*>(this) ) ) { saveLastError(tr("While registering the callback function:\n")); return false; } if( 0 != DAQmxStartTask( taskHandle ) ) { saveLastError(tr("While starting the analog in task:\n")); return false; } plotter->prepareForPlot(visibleDuration, samplingRate); if( startRecordImmediately ) { startRecording(); } else { state = Plotting; emit stateChanged(state); } timer->start(1000/refreshRate); } return true;

/* static wrapper function be able to reach to the class members */ int32 CVICALLBACK DeviceController::callback_Wrapper( TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)

70
{ DeviceController * dc = reinterpret_cast<DeviceController * >(callbackData); dc->callback( taskHandle, everyNsamplesEventType, nSamples, NULL); return 0; } int32 CVICALLBACK DeviceController::callback( TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData) { Q_UNUSED(callbackData) Q_UNUSED(everyNsamplesEventType) /* The array to read samples into, organized according to fillMode. DAQmx_Val_GroupByChannel = Group by channel (non-interleaved) nSamples from channel 1, than nSamples from channel 2, ... DAQmx_Val_GroupByScanNumber Group by scan number (interleaved) 1 sample from channel 1, than 1 sample from channel 2, ... ! nSamples for each channel => channel count x nSamples = buffer size got only one channel */ int32 read = 0; double * buff = new double[nSamples]; if( 0 != DAQmxReadAnalogF64( taskHandle, DAQmx_Val_Auto /* read all available sample */, DAQmx_Val_WaitInfinitely, DAQmx_Val_GroupByScanNumber, buff /* read array */, nSamples /* arraySizeInSamps */, &read, NULL ) ) { saveLastError(tr("While reading the sampling values:\n")); return false; } if( ( fifo_count + nSamples ) > fifo_size ) { overflow = true; qDebug() << "overflow in callback"; } else { if( fifo_w + nSamples < fifo_size ) { memcpy(&(fifo.data()[fifo_w]), buff, nSamples*sizeof(double)); fifo_w += nSamples; } else { unsigned int first = fifo_size - fifo_w; unsigned int second = nSamples - first;

71
memcpy(&(fifo.data()[fifo_w]), &(buff[0]), first*sizeof(double)); memcpy(&(fifo.data()[0]), &(buff[first]), second*sizeof(double)); fifo_w = second; } fifo_count.fetchAndAddOrdered(nSamples); } delete [] buff; } return 0;

void DeviceController::saveLastError(QString errorPrefix) { char errBuff[2048]={'\0'}; lastError.clear(); DAQmxGetExtendedErrorInfo(errBuff,2048); lastError = QString("<p><font color='#FF0000'>") + errorPrefix + QString("</p></font>") + QString::fromAscii(errBuff); emit logMessage(lastError); } void DeviceController::timerFunction() { if( overflow ) { fifo_r = fifo_w; overflow = false; fifo_count.fetchAndStoreOrdered(0); qDebug() << "overflow occured"; return; } if( state == Waiting || state == Scrolling ) { qDebug() << "Entered timer fnc while state is waiting or scrolling."; if(fifo_count > 0) { fifo_r = fifo_w; fifo_count.fetchAndStoreOrdered(0); } return; } // get data from fifo unsigned int count = fifo_count; if(count == 0) return; double * buff = new double[count]; if( fifo_r + count < fifo_size ) { memcpy(&(buff[0]), &(fifo.data()[fifo_r]), count*sizeof(double));

72
fifo_r += count; } else {

unsigned int first = fifo_size - fifo_r; unsigned int second = count - first; memcpy(&(buff[0]), &(fifo.data()[fifo_r]), first*sizeof(double)); memcpy(&(buff[first]), &(fifo.data()[0]), second*sizeof(double)); fifo_r = second; } fifo_count.fetchAndAddOrdered(-count); // pump data to either plot or record if( state == Plotting ) { plotter->plot(buff, count); plotter->replot(); } else if( state == Recording ) { plotter->recordAndPlot(buff, count); plotter->replot(); } } delete [] buff;

void DeviceController::startRecording() { if( state == NoDevice ) { lastError = tr("No device"); emit logMessage(lastError); return; } state = Recording; emit stateChanged(state);

void DeviceController::pauseRecording() { state = Paused; emit stateChanged(state); } void DeviceController::stopRecording() { if(timer->isActive()) timer->stop(); state = Scrolling; emit stateChanged(state); }

73
void DeviceController::stopSampling() { if(timer->isActive()) timer->stop(); if( 0 != DAQmxClearTask(taskHandle)) { saveLastError(tr("While clearing the analog out task:\n")); } } void DeviceController::clearSampling() { if(timer->isActive()) timer->stop(); if( 0 != DAQmxClearTask(taskHandle)) { saveLastError(tr("While clearing the analog out task:\n")); } // clear buffer fifo_w = fifo_r = 0; fifo_count = 0; overflow = false; state = Waiting; emit stateChanged(state);

bool DeviceController::startAnalogOut(double value){ QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); QString currentDevice = settings.value("currentDevice", QString("")).toString(); QString currentAOChannel = settings.value("currentAOChannel", QString("")).toString(); settings.endGroup(); if( 0 != DAQmxCreateTask( "", &taskHandleAnalogOut) ) { saveLastError(tr("While creating the analog out task:\n")); return false; } if( 0 != DAQmxCreateAOVoltageChan( taskHandleAnalogOut, currentAOChannel.toAscii().constData(), DeviceSensor::getAOMinVoltage(currentDevice), DeviceSensor::getAOMaxVoltage(currentDevice), DAQmx_Val_Volts, NULL ) ) { saveLastError(tr("While creating the analog out voltage channel:\n")); return false; } if( 0 != DAQmxStartTask( taskHandleAnalogOut ) ) { saveLastError(tr("While starting the analog out task:\n")); return false; } updateAnalogOut(value); "",

74
return true;

bool DeviceController::stopAnalogOut(){ if(taskHandleAnalogOut) { if( 0 != DAQmxClearTask(taskHandleAnalogOut)) { saveLastError(tr("While clearing the analog out task:\n")); return false; } return true; } return false; } bool DeviceController::updateAnalogOut(double value){ if(taskHandleAnalogOut) { float64 data[1] = {0.0}; data[0] = value; if( 0 != DAQmxWriteAnalogF64(taskHandleAnalogOut,1,1,2.0,DAQmx_Val_GroupByChannel,da ta,NULL,NULL)) { saveLastError(tr("While writing the analog out value:\n")); return false; } return true; } return false; } bool DeviceController::startDigitalOut(int frequency){ QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); QString currentDevice = settings.value("currentDevice", QString("")).toString(); QString currentDigitalLine = settings.value("currentDigitalLine", QString("")).toString(); settings.endGroup(); if( 0 != DAQmxCreateTask( "", &taskHandleDigitalOut) ) { saveLastError(tr("While creating the digital out task:\n")); return false; } if( 0 != DAQmxCreateDOChan( taskHandleDigitalOut, currentDigitalLine.toAscii().constData(), "", DAQmx_Val_ChanForAllLines ) ) { saveLastError(tr("While creating the digital out line:\n")); return false; } if( 0 != DAQmxCfgSampClkTiming( taskHandleDigitalOut, NULL, frequency, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 2 ) ) { saveLastError(tr("While configuring the digital out clock timing:\n")); return false; } if( 0 != DAQmxStartTask( taskHandleDigitalOut ) ) { saveLastError(tr("While starting the digital out task:\n")); return false; } updateDigitalOut(frequency);

75
return true; } bool DeviceController::stopDigitalOut(){ if(taskHandleDigitalOut) { if( 0 != DAQmxClearTask(taskHandleDigitalOut)) { saveLastError(tr("While clearing the digital out task:\n")); return false; } return true; } return false; } bool DeviceController::updateDigitalOut(int frequency){ if(taskHandleDigitalOut) { uInt8 data[2] = {0x00, 0x01}; if( 0 != DAQmxCfgSampClkTiming( taskHandleDigitalOut, NULL, frequency, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 2 ) ) { saveLastError(tr("While updating the configuration of digital out clock timing:\n")); return false; } if( 0 != DAQmxWriteDigitalLines(taskHandleDigitalOut,2,1,2.0,DAQmx_Val_GroupByChanne l,data,NULL,NULL)) { saveLastError(tr("While writing the digital out value:\n")); return false; } return true; } return false; }

Plotter.h
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #ifndef PLOTTER_H #define PLOTTER_H #include <qwt_plot.h>

76
class QwtPlotCurve; class QwtPlotItem; class Plotter : public QwtPlot { Q_OBJECT public: Plotter(QWidget * parent = 0); ~Plotter() { } void prepareForPlot(unsigned int visibleDuration, unsigned int sampingRate); void prepareForScroll(); void plot(double * buff, unsigned int size); void recordAndPlot(double * buff, unsigned int size); int getMaxScrollStep(); void setScale(double min, double max, bool autoScale = false); unsigned int getVisibleDuration() { return visibleDuration; } unsigned int getSamplingRate() {return samplingRate; } signals: void recordTimeChanged(int); public slots: void scrollTime(int step); void clearPlotter(); public: QVector<double> recordData; private: QVector<double> plotData, plotBottomData; QwtPlotCurve * samplingCurve; unsigned int visibleDuration; unsigned int samplingRate; unsigned int plotSplitCount; bool ready; int recordTime; }; #endif

Plotter.cpp
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is it under published by the Free (at your free software: you can redistribute it and/or modify the terms of the GNU Lesser General Public License as Software Foundation, either version 3 of the License, or option) any later version.

Medaq is distributed in the hope that it will be useful,

77
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #include #include #include #include #include #include #include #include #include #include #include <qwt_plot.h> <qwt_plot_curve.h> <qwt_scale_widget.h> <qwt_plot_picker.h> "Plotter.h" "TimeScale.h" <qmath.h> <QSettings> <QDir> <QDebug> <QTime>

Plotter::Plotter(QWidget * parent) : QwtPlot(parent), ready(false), recordTime(0) { setCanvasBackground(Qt::white); } void Plotter::prepareForPlot(unsigned int visibleDuration, unsigned int samplingRate) { this->visibleDuration = visibleDuration; this->samplingRate = samplingRate; QSettings settings(QDir::currentPath() + "/medaq.ini", QSettings::IniFormat); settings.beginGroup("Settings"); unsigned int maxVisiblePoint = settings.value("maxVisiblePoint", 1000).toInt(); plotSplitCount = settings.value("plotSplitCount", 50).toInt(); settings.endGroup(); unsigned int size; if ( visibleDuration * samplingRate > maxVisiblePoint ) { size = maxVisiblePoint; } else { size = visibleDuration * samplingRate; } plotData.fill(0.0, size); plotBottomData.resize(size); for(int i=0; i<plotBottomData.size(); ++i){

78
plotBottomData[i] = i; } samplingCurve = new QwtPlotCurve(tr("Sampling")); samplingCurve->setPen(QPen(Qt::black)); samplingCurve->attach(this); samplingCurve->setRawData(plotBottomData.data(), plotData.data(), size); // time scale TimeScaleDraw * tsd = new TimeScaleDraw(QTime(0,0), samplingRate); setAxisScaleDraw(QwtPlot::xBottom, tsd ); setAxisScale(QwtPlot::xBottom, 0, size); setAxisLabelRotation(QwtPlot::xBottom, -50.0); setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom); // To avoid this "jumping canvas" effect, we add a permanent margin. QwtScaleWidget *scaleWidget = axisWidget(QwtPlot::xBottom); const int fmh = QFontMetrics(scaleWidget->font()).height(); scaleWidget->setMinBorderDist(0, fmh / 2); } ready = true;

void Plotter::prepareForScroll() { if(!ready) return; unsigned int size = visibleDuration * samplingRate; plotData.fill(0.0, size); plotBottomData.resize(size); for(int i=0; i<plotBottomData.size(); ++i){ plotBottomData[i] = i; } samplingCurve->setRawData(plotBottomData.data(), plotData.data(), size); setAxisScale(QwtPlot::xBottom, 0, size); QwtPlotPicker * d_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::PointSelection | QwtPicker::DragSelection, QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, canvas()); d_picker->setRubberBandPen(QColor(Qt::green)); d_picker->setRubberBand(QwtPicker::CrossRubberBand); d_picker->setTrackerPen(QColor(Qt::blue));

} void Plotter::plot(double * buff, unsigned int size) { if(!ready) return; unsigned int plotSize = plotData.size();

79
if( size < plotSize ) // size is smaller than plot size { if((visibleDuration*samplingRate) > plotSize) {

jump

// take by

unsigned int stepLength = qFloor((visibleDuration*samplingRate) / plotSize); unsigned int newSize = qFloor(size / stepLength); memmove(&(plotData.data()[0]), &(plotData.data() [newSize]), (plotSize-newSize) * sizeof(double)); // shift memset(&(plotData.data()[(plotSize-newSize)]),0, newSize * sizeof(double)); // clear shifted place unsigned int plotIndex = plotSize-1; for(int j=size-1; j>=0 && plotIndex >= (plotSizenewSize); j-=stepLength) { plotData[plotIndex] = buff[j]; plotIndex--; } } else // take original { memmove(&(plotData.data()[0]), &(plotData.data()[size]), (plotSize-size) * sizeof(double)); // shift memcpy(&(plotData.data()[(plotSize-size)]), &(buff[0]), size * sizeof(double)); } } else // size is bigger than plot size or equal { if((visibleDuration*samplingRate) > plotSize) // take by jump { unsigned int stepLength = qFloor((visibleDuration*samplingRate) / plotSize); unsigned int newSize = qFloor(size / stepLength); if(newSize < plotSize) { memmove(&(plotData.data()[0]), &(plotData.data() [newSize]), (plotSize-newSize) * sizeof(double)); // shift memset(&(plotData.data()[(plotSize-newSize)]),0, newSize * sizeof(double)); // clear shifted place } else { memset(&(plotData.data()[0]),0, plotSize * sizeof(double)); // clear all } int plotIndex = plotSize-1; for(int j=size-1; j>=0 && plotIndex >= 0; j-=stepLength) { plotData[plotIndex] = buff[j]; plotIndex--; } } else // take original

80
{ memcpy(&(plotData.data()[0]), &(buff[size-plotSize]), plotSize * sizeof(double)); } } } void Plotter::recordAndPlot(double * buff, unsigned int size){ if(!ready) return; int last = recordData.size(); recordData.resize(recordData.size()+size); // initialize new emelents 0 by qt memcpy(&(recordData.data()[last]), &(buff[0]), size * sizeof(double)); int sec = qFloor( recordData.size() / samplingRate ); if( sec >= recordTime ) { recordTime = sec; emit recordTimeChanged(recordTime); } } plot(buff, size);

void Plotter::scrollTime(int step){ if( ! ready ) return; int sourceIndex = 0; if( recordData.size() <= plotData.size() ) // stopped before signel filled the plot screen { plotData.fill(0.0, plotData.size()); memcpy(&(plotData.data()[0]), &(recordData.data()[0]), recordData.size() * sizeof(double)); } else { if( step > getMaxScrollStep() ) // if step is out of scope return return; sourceIndex = step*(plotData.size()/plotSplitCount); memcpy(&(plotData.data()[0]), &(recordData.data() [sourceIndex]), plotData.size() * sizeof(double)); } unsigned int plotSize = plotBottomData.size(); double * d = plotBottomData.data(); QwtValueList vlist_y[3]; for ( unsigned int i = 0 ; i < plotSize ; ++i ) { register int x = sourceIndex + i; d[i] = x; if( 0 == x % samplingRate ) vlist_y[0] << d[i]; }

81
setAxisScale(QwtPlot::xBottom, plotBottomData[0], plotBottomData[plotSize - 1]); QwtScaleDiv scdiv_y(plotBottomData.at(0), plotBottomData.at(plotBottomData.size()-1), vlist_y); scdiv_y.setTicks(QwtScaleDiv::MajorTick, vlist_y[0]); setAxisScaleDiv(QwtPlot::xBottom, scdiv_y); } replot();

int Plotter::getMaxScrollStep(){ if(!ready) return 0; if(recordData.size()<=plotData.size()) return 0; int piece = qFloor(plotData.size()/plotSplitCount); if(piece<1) piece = 1; return qFloor( (recordData.size()-plotData.size()) / piece);

void Plotter::clearPlotter(){ ready = false; plotData.fill(0.0, plotData.size()); plotData.clear(); recordData.clear(); clear(); } replot();

void Plotter::setScale(double min, double max, bool autoScale) { if(autoScale) { setAxisAutoScale(QwtPlot::yLeft); } else { setAxisScale(QwtPlot::yLeft, min, max); } replot(); }

TimeScale.h
/* Copyright 2008 Huseyin Kozan (posta@huseyinkozan.com.tr) This file is part of Medaq. Medaq is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by

82
the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Medaq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Medaq. If not, see <http://www.gnu.org/licenses/>. */ #ifndef TIMESCALE_H #define TIMESCALE_H #include <qwt_scale_draw.h> #include <QTime> class TimeScaleDraw: public QwtScaleDraw { public: TimeScaleDraw(const QTime &base, int samplingRate): baseTime(base), rate(samplingRate) { } virtual QwtText label(double v) const { QTime upTime = baseTime.addSecs((int)v/rate); return upTime.toString("mm:ss"); } private: QTime baseTime; int rate; }; #endif

EK B QMAKE PROJE DOSYASI TEMPLATE = app TARGET = Medaq HEADERS = src/MainWindow.h \ src/InfoDialog.h \ src/SettingsDialog.h \ src/NewSamplingDialog.h \ src/DeviceSensor.h \ src/Plotter.h \ src/TimeScale.h \ src/DeviceController.h SOURCES = src/main.cpp \ src/MainWindow.cpp \ src/InfoDialog.cpp \ src/SettingsDialog.cpp \ src/NewSamplingDialog.cpp \

83 src/DeviceSensor.cpp \ src/Plotter.cpp \ src/DeviceController.cpp FORMS = src/MainWindow.ui \ src/InfoDialog.ui \ src/NewSamplingDialog.ui \ src/SettingsDialog.ui CONFIG += build_all debug_and_release qt thread CONFIG(debug, debug|release) { LIBS += qwtd5.lib } else { LIBS += qwt5.lib } LIBS += NIDAQmx.lib LIBS += libfftw.lib DEFINES += QWT_DLL RESOURCES = resource/medaq.qrc TRANSLATIONS = resource/medaq.ts RC_FILE = resource/medaq.rc MOC_DIR = tmp OBJECTS_DIR = tmp/o UI_DIR = tmp UI_SOURCES_DIR = tmp UI_HEADERS_DIR = tmp RCC_DIR = tmp EK C LSANS GNU GPL (Genel Kamu Lisans) Srm 3 29 Haziran 2007 Haklar - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Herkes bu lisans belgesini deitirmeden kopyalama ve datma hakkna sahiptir, ancak deitirilmesine izin verilmemektedir. nsz GNU GPL yazlm ve dier tr iler iin copyleft (zgr) bir lisanstr. Pek ok yazlmn ve dier kullanl eyin lisans onu paylama ve deitirme zgrlnz elinizden almak iin hazrlanmtr. Buna karlk, GNU GPL (Genel Kamu Lisans), bir program deitirme ve paylama hakknzn mahfuz tutulmasn ve tm kullanclar iin

84 zgr yazlm olarak kalmasn gvence altna almay amalar. Free Software Foundation pek ok yazlm iin GNU GPL kullanmaktadr; ve GPL bu lisans tayan dier ilere de uygulanr. Siz de kendi programlarnza bu lisans uygulayabilirsiniz. zgr yazlm dediimizde bahsettiimiz cret deil zgrlktr. Bizim Genel Kamu Lisanslarmz, sizin zgr yazlmlarn kopyalarn datma (ve isterseniz onlar cretlendirme) zgrlnz, yazlm kaynak kodlarnn size datm esnasnda veya isterseniz verilmesini, yazlm deitirme ya da istediiniz blmlerini yeni programlarnzda kullanabilmenizi ve bunlar yapabileceinizi bilmeniz iin tasarlanmtr. Haklarnz korumak iin, bakalarnn bu haklarnz inkr etmesini veya sizden bu haklardan vazgemenizi istemesini engellememiz gerekir. Bu nedenle, yazlmn kopyalarn dattnz veya deitirdiiniz taktirde baz sorumluluklarnz vardr: dierlerinin zgrlklerine kar olan sorumluluklar. rnein, yle bir programn kopyalarn ister cretsiz ister cretli dattnz taktirde, sizden o program alanlara da program alrken elde ettiiniz zgrlkleri geirmeniz gerekir. Onlarn da kaynak kodu aldn veya isterlerse alabileceklerini garantilemeniz gerekir. Ve onlarn haklarndan haberdar olmalar iin onlara bu mukaveleyi gstermelisiniz. GNU GPL kullanan gelitiriciler haklarnz iki aamal olarak korur: (1) yazlm zerindeki haklar beyan etmek, ve (2) size yasal olarak kopyalama, datma ve/veya deitirme hakk veren bu Lisans' salamak. Gelitiricilerin ve yaymclarn korunmas iin, GPL bu zgr yazlm iin herhangi bir garanti bulunmadn net bir ekilde aklar. Hem kullanclarn ve hem de yaymclarn iyilii iin, GPL deitirilen srmlerde bulunan problemlerin yanl bir ekilde nceki srmlerin yaymclarna atfedilmemesi iin deitirilen srmlerin deitirildiklerine dair iaretlenmelerini gerektirir. Baz aygtlar, aygt reticilerinin aygt iindeki yazlmn deitirilmi hallerini aygta yklemesi veya altrmas mmkn olduu halde, kullanclarn bunu yapmasna izin vermeyecek ekilde tasarlanmtr. Bu temelde kullanclarn yazlm deitirme zgrlklerini koruma amacyla rtmemektedir. Bu suistimal bireylerin kullanm iin olan rnlerde sistematik olarak uygulanmakta ve grlmektedir, ki en kabul edilemez olduu yer de budur. Bu nedenle, bu rnlerin bu uygulamasna mani olmak iin GPL'nin bu srmn hazrladk. Benzeri problemler baka alanlarda da kendini gsterdii taktirde, buradaki tedariimizi GPL'nin gelecekteki srmlerinde, kullanclarn zgrlklerini koruma ihtiyacna binaen, o alanlara da geniletmeye hazrz. Son olarak, her program yazlm patentlerinin tehdidi altndadr. Devletler patentlerin genel amal bilgisayarlarda yazlm kullanmn ve gelitirilmesini kstlayan patentlere izin vermemelidir, ama izin verenlerde zgr bir yazlma uygulanan patentlerin onu uygulamada sahipli hale getirmesi tehlikesinden kanmak istiyoruz. GPL, bunu engellemek iin, programn zgrln kstlayan patentlerin kullanlamamasn kesinletirmektedir. Kopyalama, datma ve deitirmeyle ilgili detayl art ve koullar aadadr. ART ve KOULLAR Tanmlar.

85 Bu Lisans GNU GPL'nin nc srmn ifade eder. "Telif Haklar" (Copyright) ayn zamanda dier tr i ve rnler iin geerli olan telif hakk benzeri kanunlar kapsar. Program bu Lisans ile lisanslanabilen ve telif haklar kapsamna alnabilen her trl ii ifade eder. "Siz", "Lisans Sahibi" veya "alc" olarak ifade edilebilen lisans sahibi, gerek bir kii veya kurum olabilir. Bir ii "deitirmek" bir iin bir ksmn veya tamamn telif hakk izni gerektiren bir biimde tam bir kopyasn oluturma haricinde uyarlamak veya kopyalamak anlamna gelir. Sonuta ortaya kan ie nceki iin "deitirilmi srm" veya "deitirilmi hali" ya da nceki ii "temel alan" i denir. "kapsanan i" deitirilmemi Program veya Program temel alan bir ii anlatr. Bir ii "yaymak" (propagate), onu altrma veya yerel kopyasn deitirme dnda izinsiz yapldnda ilgili telif hakk kanunu ya da kanunlar kapsamnda sizi dolayl veya dolaysz olarak telif haklar ihllinden mesl tutacak ekilde o ile birey yapmak anlamna gelir. Yayma, kopyalamay, deitirerek veya deitirmeden datmay, halka amay ve baz lkelerde dier eylemleri ierir. Bir ii "tamak" (convey) bakalarnn kopya elde etmesini ya da yapmasn mmkn klan her trl yayma ilemidir. Bir kopya transfer edilmeden bir bilgisayar a yoluyla bir kullancyla etkileim tama deildir. Etkileimli bir kullanc arayz (1) uygun bir telif haklar bildirimi gsteren ve (2) kullancya ile ilgili (sunulan garantiler dnda) herhangi bir garanti olmadn, lisans sahiplerinin bu Lisans kapsamnda ii devredebileceklerini, ve bu Lisansn bir kopyasna nasl bakabileceklerini bildiren uygun ve grnr "lgili Yasal Bildirimler" gsterir. Eer arayz kullancya bir men gibi bir dizi komut veya seenek sunuyorsa, listede grnr bir e bu kriteri yerine getirir. Kaynak Kod. Bir iin "kaynak kod"u o ite deiiklik yapmak iin tercih edilen biimini anlatr. "Nesne kod"u bir iin kaynak kod halinde olmayan tm biimlerini anlatr. Bir "Standart Arayz" bilinen bir standart oluturma kurumu tarafndan tanmlanm resm bir arayz veya belirli bir programlama lisan iin oluturulan arayzlerde o dilde alan gelitiriciler arasnda yaygn olan arayz tanmlar. Bir altrlabilirin "Sistem Ktphaneleri" iin tamam hari olmak zere (a) bir Ana Bileen paketlenirken dhil edilen ama o Ana Bileenin bir paras olmayan, ve (b) iin o Ana Bileenle kullanlabilmesini mmkn klan veya halka kaynak kod biiminde bir uyarlamann ak olduu durumda bir Standart Arayz uyarlamak iin kullanlan her eyi kapsar. Bu balamda bir "Ana Bileen", altrlabilir iin kotuu -eer varsa- belirli bir iletim sisteminin elzem bir bileenini (ekirdek, pencere sistemi vd.), ii retmek iin kullanlan ekirdei, veya onu komak iin kullanlan nesne kodu yorumlaycsn anlatr. Bir ie nesne kodu biiminde "Karlk Gelen Kaynak" nesne kodunu oluturmak, yklemek, (altrlabilir bir i iin) koturmak ve (bu ilemleri kontrol etmek iin gereken betikler dahil) ii deitirmek iin gereken tm kaynak kodlar ifade eder. Ancak, in Sistem

86 Ktphanelerini ve iin paras olmayan ama bahsedilen ilemleri gerekletirmek iin kullanlan ve kolay eriilebilir olan genel amal aralar kapsamaz. Karlk Gelen Kaynak rnein iin kaynak dosyalaryla ilintili arayz tanmlama dosyalarn ve iin altprogramlar ve dier paralar arasnda veri iletiimi veya kontrol ak gibi iin zellikle gerektirmesi tasarlanm olan altprogramlarn (paylalan ktphanelerin ve dinamik balanan altprogramlarn) kaynak kodlarn ierir. Karlk Gelen Kaynan, Karlk Gelen Kaynan dier paralarndan kullanclarn otomatik olarak oluturabildii hibir eyi iermesi gerekmez. Bir iin kaynak kod halindeki Karlk Gelen Kayna iin kendisidir. Temel zinler. Bu Lisans kapsamnda verilen tm haklar Programn telif hakk art iin verilmitir ve belirtilen koullar karland taktirde geri evrilemez ve geri alnamaz. Bu Lisans deitirilmemi Program koma konusunda size salanan snrsz izni aikr bir ekilde snrsz tasdik eder. Kapsanan bir iin koulmas sonucunda oluan kt sadece ktnn ierii kapsanan bir ile rtt taktirde bu Lisans tarafndan kapsanr. Bu Lisans sizin adil kullanm veya edeer dier uygulamalarnz telif hakk kanunlar tarafndan saland ekliyle teslim ve tasdik eder. Kapsanan ilerden tamadklarnz lisansnzn uygun kld ekilde koulsuz olarak yapabilir, koabilir veya yayabilirsiniz. Kapsanan ileri sadece size zel deiiklikler yapmalar iin veya size zel deiiklikler yaptklar o ileri komak iin size imkn salamalar amacyla telif haklarn kontrol etmediiniz tm malzemenin yaylmas konusunda bu Lisansn artlarna uyduunuz srece bakalarna yayabilirsiniz. Kapsanan ileri yapan veya koanlar sadece size zel olarak, sizin adnza, sizin ynlendirmeniz ve kontrolnz dahilinde, telif haklar size ait malzemenin sizinle olan ilikilerinin dnda baka bir kopyasn yapmalarna izin vermeyen artlara uygun olarak bunu yapmaldr. Baka herhangi bir durumda yaymaya sadece aada saylan durumlarda izin verilir. Altlisanslamaya izin yoktur; blm 10 bunu gereksiz klar. Kullanclarn nlemlerin Etkisiz Klnmasna Kar Hukuka Dayal Yasal Haklarnn Korunmas. Kapsanan hibir i 20 Aralk 1996 tarihinde kabul edilmi olan WIPO telif haklar akdinin 11'inci maddesindeki ykmllkleri yerine getiren tatbiki hibir kanun veya benzer nlemlerin boluklardan yararlanlarak atlatlmasn yasaklayan veya snrlayan benzeri hibir kanun kapsamnda etkili bir teknolojik tedbirin bir paras olarak kabul edilmemelidir. Kapsanan bir ii tadnzda, atlatmann bu Lisansn kapsad haklarn icras yoluyla etkilenmesi kapsam dahilinde teknolojik nlemlerin alnmasn menetme yasal hakknzdan feragat etmi ve iin kullanclarnn, sizin veya nc kiilerin teknolojik nlemlerin atlatlmasn menetme yasal haklarnn uygulanmasnda iin altrlmasn veya deitirilmesini snrlama niyetinizi reddetmi olursunuz. Ayn Kopyalar Yaymak. Programn kaynak kodunun ayn kopyalarn aldnz ekliyle bariz ve uygun ekilde her kopyada uygun bir telif hakk bilgisi yaynlamak artyla herhangi bir biimde yayabilirsiniz; bu Lisans ve ksm 7'ye uymak kouluyla eklediiniz artlar beyan eden bildirilerin tamamn ve herhangi bir garanti bulunmadna dair olan bildirilerin tamamn eksiksiz olarak bulundurun; ve tm alclara Programla birlikte bu Lisansn bir kopyasn verin.

87 Yaydnz kopyalar iin bir cret talep edebilirsiniz ve/veya bir cret karlnda destek veya garanti teklif edebilirsiniz. Deitirilmi Kaynak Srmlerini Yaymak. Ksm 4 kapsamnda Program temel alan bir ii veya Programdan ii retecek deiiklikleri kaynak kod biiminde u koullar da karlamak artyla yayabilirsiniz: 1. onda deiiklik yaptnza dair gzle grlr bildiriler iermeli ve ilgili bir tarih vermelidir. 2. bu Lisans ve ksm 7 altna eklenen artlar gereince yaynlandna dair gzle grlr bildiriler iermelidir. Bu gereklilik ksm 4'teki "tm bildirileri deitirmeden tutma" gerekliliinde deiiklik yapar. 3. in bir kopyasn elde eden herkese tm ii bu Lisans kapsamnda bir btn olarak lisanslamalsnz.Bu Lisans bu sayede ksm 7'de verilecek tm ek koullar ile birlikte iin tamamn ve nasl paketlenmi olurlarsa olsunlar tm paralarn kapsayacaktr. Bu Lisans iin baka herhangi bir ekilde lisanslanmasna izin vermez, ama ayrca bunun iin bir izin aldysanz onu geersiz klmaz. 4. Eer iin etkileimli kullanc arayzleri varsa, her biri Uygun Yasal Bildirileri iermelidir; ancak eer Programda etkileimli arayzlerden Uygun Yasal Bildiriler gstermeyen varsa, sizin iinizin bunlar gsterecek ekilde deitirmesi gerekmez. Kapsanan bir iin doalar gerei kapsanan iin uzants olmayan ve daha byk bir i oluturmak iin o ile birletirilmeyen baka ayr ve bamsz ilerle bir depolama veya datm ortamnda derlenmi hali, derlenmi hl ve sonuta ortaya kan telif haklar ilerin her birinin izin verdiinin tesinde derlenmi halin kullancnn eriim veya yasal haklarn snrlamak iin kullanlmad taktirde, "yekn" olarak anlr. Kapsanan bir iin bir yekne dahil olmas bu Lisansn yeknn dier ksmlarn kapsamasna neden olmaz. Kaynak Hlde Olmayan Biimleri Yaymak. Makine tarafndan okunabilir Karlk Gelen Kayna da yaymak artyla ksm 4 ve 5'te verilen artlar dahilinde kapsanan bir ii nesne kodu biiminde bu Lisansn artlar kapsamnda u yollardan biriyle yayabilirsiniz. 1. Nesne kodunu, zellikle yazlm dei-tokuu iin kullanlan dayankl bir fiziksel ortama maktu Karlk Gelen Kaynakla birlikte olmak artyla, (fiziksel bir datm ortam dahil) fiziksel bir rnde yayabilirsiniz. 2. Nesne kodunu, en az yl ve sizin o rn modeli iin yedek para veya mteri destei salamay teklif ettiiniz sre boyunca geerli yazl bir teklifle birlikte, nesne koduna sahip olan herhangi kiilere (1) bu Lisans tarafndan kapsanan rndeki tm yazlma Karlk Gelen Kaynan bir kopyasn zellikle yazlm dei-tokuu iin kullanlan dayankl bir fiziksel ortamda bu kaynan yaymanza karlk makul bir tutar amayan bir cret karlnda veya (2) Karlk Gelen Kaynaa bir a sunucusu zerinden cretsiz olarak eriim imknyla, (fiziksel bir datm ortam dahil) fiziksel bir rnde yayabilirsiniz. 3. Karlk Gelen Kayna salamaya ynelik yazl bir teklifin bir kopyasyla birlikte nesne kodunun mstakil kopyalarn yayabilirsiniz. Bu alternatife sadece bazen ve ticari olmayacak ekilde, ve sadece eer siz nesne kodunu byle bir teklifle elde ettiyseniz, ksm 6 madde (b)'ye uygun olarak izin verilir. 4. Tasrih edilmi bir yerden cretli veya cretsiz eriim sunma yoluyla nesne kodunu yayabilirsiniz, ve ek bir cret talebinde bulunmadan Karlk Gelen Kaynaa ayn yer yoluyla ayn ekilde edeer eriim sunabilirsiniz. Alclarn nesne koduyla birlikte Karlk Gelen

88 Kaynan bir kopyasn almalarn art komanz gerekmez. Eer nesne kodunun kopyalanaca yer bir a sunucusu ise, nesne kodunun yannda Karlk Gelen Kaynan nereden edinilebileceini belirten ak talimatlar bulundurmak kouluyla Karlk Gelen Kaynak edeer kopyalama kolaylklarn sunan ve sizin tarafnzdan veya bir nc kii tarafndan iletilen farkl bir sunucu olabilir. Karlk Gelen Kaynan hangi sunucularda barndrldndan bamsz olarak, bu gereklilikleri karlamak gerektii srece mevcut ve eriilebilir olduundan emin olmakla zorunlu olursunuz. 5. Dier edzey kullanclar' (peer) iin nesne kodunun ve Karlk Gelen Kaynann ksm 6(b) kapsamnda cret talebi olmakszn umuma ak olarak nerede bulunduu konusunda bilgilendirmek artyla, nesne kodunu edzeyler / kullanclar aras (peer-to-peer) aktarm yoluyla yayabilirsiniz. Nesne kodunun ayrlabilir bir paras Nesne kodunun, kaynak kodu bir Sistem Ktphanesi olarak Karlk Gelen Kaynaa dahil edilmeyen ayrlabilir bir parasnn, nesne kodu iini yayarken dahil edilmesi gerekmez. Bir "Kullanc rn" ya (1) normalde, kiisel ve/veya ailevi amala ve/veya evin idamesi amacyla kullanlan gerek herhangi bir mlk anlamnda bir "tketici rn"dr veya (2) ikametghta kullanlmak zere tasarlanan veya satlan herhangi bir eydir. Bir rnn tketici rn olup olmadn belirlemede tereddt yaanan durumlar kapsam dikkate alnarak zmlenmelidir. Belirli bir kullanc tarafndan alnan belirli bir rn iin, "normal kullanm" o belirli kullancnn durumu ve o belirli kullancnn o rn kullanp kullanmadna, kullanmas beklenip beklenmediine, veya ne ekilde kullanmas beklendiine baklmakszn o snftaki bir rnn tipik ve yaygn kullanmna iaret eder. Bir rn rnn ticari, endstriyel veya tketici-d kullanmlar -bu kullanmlar rnn tek bariz kullanm ekli olmadklar srce- dikkate alnmakszn bir tketici rndr. Bir Kullanc rn iin "Kurulum Bilgisi" Kullanc rnnn Karlk Gelen Kaynann deitirilmi bir hlinden elde edilen Kullanc rnnde kapsanan bir iin kurulumu ve altrlmas iin gereken yntemler, prosedrler, yetkilendirme anahtarlar veya dier bilgilerdir. Bilginin deitirilmi nesne kodunun alabilir kalmasnn hibir durumunda srf deiiklik yapld diye engellenmediini ve mdahaleye maruz kalmadn garantilemesi yeterli olmaldr. Bu ksmdaki bir nesne kodu iini bir Kullanc rn ile, rnn iinde veya zellikle o rnde kullanlmak zere yayarsanz ve eer yayma sahip olma ve Kullanc rnn kullanma haklar belirli bir sre iin veya sresiz olacak ekilde alcya nakledilerek bir aktarmn (aktarmn tavsifi nasl olursa olsun) paras olursa, bu ksmdaki Karlk Gelen Kaynak Kurulum Bilgisine elik etmelidir. Ama bu gereklilik ne siz ne de herhangi bir nc kii deitirilmi nesne kodunu Kullanc rnne kurma veya ykleme kudretini elinde bulundurduu taktirde (rnein i ROM'a yklendiinde veya kurulduunda) geerli deildir. Kurulum Bilgisi sunma gereklilii alc tarafndan deitirilmi veya kurulumu bir i ve iin iinde deitirildii veya iin kurulduu ya da yklendii Kullanc rn iin destek servisi, garanti veya gncelleme gereklilii getirmez. Deitirme ileminin kendisi maddeten ve olumsuz ekilde an ileyiini etkilerse veya a ierisinde iletiim iin var olan kural veya protokolleri ihlal ederse bir aa eriim reddedilebilir. Bu ksma uygun olarak Karlk Gelen Kaynak yayldnda ve Kurulum Bilgisi sunulduunda, alenen belgelendirilmi ve umuma kaynak kod biiminde ak olarak uyarlanm bir biemde olmaldr, ve amak, okumak veya kopyalamak iin herhangi bir

89 parola veya anahtar gerektirmemelidir. Ek Koullar. "Ek koullar" bu Lisansn artlarna bir veya daha fazla koulun istisnasn oluturarak ilve edilen artlardr. Programn tamamna tatbik edilen ek koullar ilgili kanun kapsamnda geerli olmak kouluyla bu Lisansa dahil edilmi kabul edilmelidir. Eer ek koullar Programn sadece bir ksmna atfedilmise, o ksm o koullar kapsamnda ayrca kullanlabilir, ama Programn tamam, ek koullar dikkate alnmakszn, bu Lisans kapsamndadr. Kapsanan bir iinin bir kopyasn yaydnzda, kendi tercihinize bal olarak o kopyadan ve istediiniz herhangi bir ksmndan ek koullar kaldrabilirsiniz. (Belirli durumlarda ii deitirdiinizde kaldrlmalarn gerektirecek ekilde ek koullar yazlm olabilir.) Kapsanan bir ie sizin tarafnzdan eklenmi bir malzemeye uygun telif haklar koullarna sahip olmak veya verebilmek artyla ek koullar koyabilirsiniz. Bu Lisansn dier koullaryla uyumsuz olmayacak ekilde Kapsanan bir ie eklediiniz bir malzeme iin o malzemenin telif haklarn elinde bulunduranlar tarafndan yetkili klnrsanz bu Lisansn artlarna u koullar kapsamnda eklemelerde bulunabilirsiniz: 1. Bu Lisansn 15 ve 16'nc ksmlarndaki artlardan farkl olarak taahhdnz snrlandrabilir veya garanti vermeyebilirsiniz; veya 2. Belirteceiniz mahsus yasal bildirilerin veya o malzemeye yazarlarn yapt katklarn malzemede veya onu ieren iler tarafndan gsterilen Mahsus Yasal Bildirilerde korunmasn art koabilirsiniz; veya 3. O malzemenin kkeni hakknda yanl veya yalan bilgi verilmesini yasaklayabilir veya o malzemenin deitirilmi hallerinin ve srmlerinin asl hal ve srmlerinden farkl olduklarn makul ekillerde gstermelerini art koabilirsiniz; veya 4. Malzemenin yazarlarnn veya lisans sahiplerinin isimlerinin ilan edilme amacyla kullanlmasn snrlandrabilirsiniz; veya 5. Malzemeyi yayanlardan o malzemenin (veya deitirilmi hal ya da srmlerinin) lisans sahiplerinin ve yazarlarnn mukaveleden doan ve mukaveleyle alcya yklenen mesuliyet varsaym erevesinde lisanslayanlara ve yazarlarna kar her trl zararn denmesini ve karlanmasn talep edebilirsiniz. Kstlayc tm dier ek koullar ksm 10 kast dahilinde "ilave kstlama" olarak kabul edilir. Eer aldnz Program veya herhangi bir paras bu Lisansn hkmlerine tabi olduunu ve ilave kstlamalar bulunduunu belirten bir bildirim tayorsa, o koulu kaldrabilirsiniz. Eer bir lisans belgesi ilave kstlama tayor ama bu Lisans kapsamnda yeniden lisanslamaya veya yaymaya ruhsat veriyorsa, ilave kstlamann o tr bir yeniden lisanslama veya yayma durumunda devam etmemesi kouluyla kapsanan bir ie o lisans belgesi hkmlerince malzeme ekleyebilirsiniz. Kapsanan bir ie bu ksma zt dmemek artyla koul eklerseniz, ilgili kaynak dosyalarda o dosyalara hasreden ek koullarla ilgili bir beyanat veya tatbik edilmesi gereken koullarn nerede bulunabileceini belirten bir ibare yerletirmelisiniz. Kstlayc veya deil, ek koullar ayr yazlan bir lisans biiminde veya istisnalar olarak belirtilebilir; her iki durumda da yukardaki gereklilikler geerlidir. Sonlandrma. Bu Lisansla salanan yollar dnda kapsanan bir ii kesinlikle yayamaz ve deitiremezsiniz.

90 Yaymak veya deitirmek iin aksi her trl teebbs geersizdir ve bu Lisans kapsamndaki tm haklarnz (11'inci ksm 3'nc paragrafta salanan patent lisanslar dhil) sonlandrr. Ancak, bu Lisans ihlal davranlarnz keserseniz, belirli telif haklar sahibinden olan lisansnz (a) telif haklar sahibi sarih ve niha olarak sonlandrana kadar geici olarak ve (b) eer telif haklar sahibinin ihlali takiben 60 gn iinde sizi makl bir yolla ihllinizinden haberdar etmemesi halinde daimi olarak iade edilir. Ayrca, belirli telif haklar sahibinden olan lisansnz, telif haklar sahibi sizi makl bir yolla ihlalinizden haberdar ederse, bu sizin bu Lisans ihlalinize dair aldnz ilk ihbarname ise ve ihbarnameyi aldktan sonra 30 gn iinde ihlali durdurursanz, daimi olarak iade edilir. Bu ksm kapsamnda haklarnzn sonlandrlmas bu Lisans kapsamnda sizden kopyalar veya haklar alan nc kiilerin lisanslarn sonlandrmaz. Eer haklarnz sonlandrldysa ve daim olarak iade edilmediyse, ksm 10 kapsamnda ayn malzeme iin yeni lisans almaya ehliyetsiz olursunuz. Kopya Sahibi Olmak in Kabul Gerekmez. Programn bir kopyasn almak veya altrmak iin bu Lisans kabul etmeniz gerekmez. Kaynaktan kaynaa aktarm yntemleri sonucu kapsanan bir iin bir kopyasnn edinilmesi iin aktarlmasna yardmc olmak da benzer ekilde kabul etmeyi gerektirmez. Ancak, bu Lisans dnda hibir ey size kapsanan herhangi bir iin yaylmas veya deitirilmesi izni vermez. Bu Lisans kabul etmediiniz taktirde bu eylemler telif haklar ihlaline girer. Bundan dolay, kapsanan bir ii yayarak veya deitirerek, yle yapabilmek iin bu Lisans kabul ettiinizi dolayl olarak belirtmi olursunuz. Alcdan Alanlarn Downstream Recipients Otomatik Lisanslanmas. Kapsanan bir ii her aktarmanzda, alc bu Lisans kapsamnda otomatik olarak lisansn ilk sahibinden o ii komak, deitirmek ve yaymak iin bir lisans alr. nc kiileri bu Lisansa uymaya zorlama sorumluunuz yoktur. Bir "varlk aktarm ilemi" bir organizasyonun veya kurumun kendisinin veya tm mallarnn kontrolnn bakasna verilmesi, organizasyon veya kurumun alt blmlere ayrlmas, veya organizasyonlarn birlemesi ilemidir. Kapsanan bir iin yaylmas bir varlk aktarm ilemi sonucunda gereklemise, ilemin iin bir kopyasn alan tm halefler nceki paragraf kapsamnda ilgili selefin ile ilgili sahip olduu veya verebildii tm lisanslar ve ilgili seleften iin Karlk Gelen Kaynana (eer sahipse veya makl ekilde alabilecekse) sahip olma hakkn da elde eder. Bu Lisans kapsamnda temin ve tasdik edilen haklarn kullanm zerine baka herhangi bir kstlama getiremezsiniz. rnein, bir lisans creti, iletme pay, veya bu Lisans kapsamnda temin edilen haklarn kullanm iin baka herhangi bir cret ykleyemezsiniz ve Program veya herhangi bir parasn yaparak, kullanarak, sata kararak veya ithal ederek import patent haklarnn ihll edildiini iddia eden apraz cross-claim ya da kar dava counterclaim dahil dava aamazsnz. Patentler. Bir "itiraki" Programn veya Program temel alan bir iin bu Lisans kapsamnda kullanmna ruhsat veren telif haklar sahibidir. Bu vehile lisanslanan ie itirakinin "itiraki srm" denir. Bir itirakinin "asli patent mlkiyeti" itirakinin sahip olduu ya da itiraki tarafndan u

91 anda kontrol edilen veya ileride kontrol edilecek olan ve bu Lisans tarafndan izin verilen itiraki srmnn yaplmas, kullanlmas veya satlmas yoluyla bir anlamda ihll edilecek olan ama itiraki srmnn sadece deitirilmesi sonucu ihlal edilmesini tm patent mlkiyetidir. Bu tanmn amac gerei, "kontrol" bu Lisansn gerekleri ile uyumlu bir biimde patent alt lisanslar verme hakkn ierir. Her itiraki size itirakinin asli patent mlkiyeti dahilinde itiraki srmn yapmak, kullanmak, satmak, satla karmak, ithal etmek, komak, ieriini deitirmek ve yaymak iin size has olmayan, cihanmul ve iletme pay iermeyen patent lisans salar. Takip eden paragrafta, bir "patent lisans" bir patenti mecburi olarak tatbik ettirmemek iin ismi konmam her trl hususi mukavele ve taahhd (bir patenti tatbik etmek iin hususi izni veya patent ihlalinden dolay dava etmeme akdini) ifade eder. Bir nc kiiye byle bir patent lisansn vermek o nc kiiye kar patentin tatbiki zorunluluunu kaldracak bir mukavele yapma veya taahhtte bulunma anlamna gelir. Bilinli olarak bir patent lisansna dayanarak kapsanan bir ii tarsanz ve iin Karlk Gelen Kayna umuma ak bir a sunucusu veya dier kolayca eriilebilir yollardan cretsiz ve bu Lisansn artlar kapsamnda umuma ak olmazsa, ya (1) Karlk Gelen Kodu bahsi geen ekilde ak olmasn salamalsnz, ya (2) kendinizi o i iin patent lisansnn salad yarardan mahrum klmay ayarlamanz, ya da (3) bu Lisansn gerektirdikleriyle uyumlu bir biimde patent lisansn alcdan alanlar iin geniletmeniz gerekir. "Bilinli olarak dayanmak" patent lisansna ramen kapsanan ii bir lkede yaymanzn veya alcnzn kapsanan ii bir lkede kullanmasnn o lkede varolan ve geerli olduuna inandnz bir veya daha fazla patenti ihlal edecei fiili bilgisine sahip olmanz demektir. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. Bir patent lisans, kapsamnda bu Lisansla salanan haklarn bir veya daha fazlasn tamyorsa, kullanlmasn yasaklyorsa veya kullanlmamasn art kouyorsa "ayrmcdr". Eer yazlm datma iinde olan nc bir kiiyle ii tama eyleminizin kapsam dahilinde nc kiiye deme yaptnz ve kapsanan ii sizden alacak kiilere (a) tarafnzdan tanm kapsanan i kopyalaryla (veya onlardan yaplan kopyalarla) ilgili veya (b) kapsanan ii ieren belirli rn veya derlemeler iin ve onlarla ilgili ayrmc bir patent lisans veren bir mukavele yapmsanz, siz o anlamaya girmemiseniz veya o patent lisans 28 Mart 2007'den nce verilmemise, kapsanan bir ii tayamazsnz. Bu Lisanstaki hibir ey ima edilen herhangi bir lisans veya ihlal savunmasn uygulanabilir patent kanunlar kapsam dnda hari tutuyor veya snrlyormu gibi alglanmamaldr. Bakalarnn zgrln Teslim Etmeme. Eer size bu Lisansn artlaryla uyumayan baz zorunluluklar yklenirse (bir mahkeme karar, mukavele veya baka suretle), bu zorunluluklar sizi bu Lisansn artlarndan muaf klmaz. Eer kapsanan bir ii bu Lisans kapsamnda ve sresince srekli olarak karlayabilecek ekilde tayamyorsanz, bunun sonucu olarak, onu tayamazsnz. rnein, Program tadklarnzdan telif hakk creti almanz zorunlu klan artlar kabul ettiyseniz, hem o artlar hem de bu Lisans yerine getirmenin tek yolu Program tamaktan tamamen

92 ekilmektir. GNU Affero GPL (Genel Kamu Lisans) ile Kullanm. Bu Lisansn koullaryla ilintili olarak, kapsanan herhangi bir ii GNU Affero GPL'nin (Genel Kamu Lisans) 3'nc srmyle lisanslanm bir ile birletirip veya balayp tek bir birletirilmi i ortaya karabilir ve sonuta ortaya kan ii tayabilir veya devredebilirsiniz. Bu Lisansn koullar kapsanan i olan ksma tatbik edilmeye devam edecektir, ama GNU Affero GPL'nin (Genel Kamu Lisans) bir a zerinden etkileimle ilgili olan 13'nc ksm birleime tatbik edilecektir. Bu Lisansn Gzden Geirilmi Srmleri. Free Software Foundation zaman zaman GNU GPL'nin (Genel Kamu Lisans) gzden geirilmi veya yeni srmlerini yaymlayabilir. Bu yeni srmler temel dnce olarak u andaki srme benzer olacaktr, ancak detaylar yeni problemleri veya kayglar gidermek amacyla farkl olabilir. Her srme onu dierlerinden ayran bir srm numaras verilir. Eer Program GNU GPL'nin (Genel Kamu Lisans) belirli bir srm "veya daha sonraki srmlerinden biri" kapsamnda olduunu belirtiyorsa, o belirli srmn veya Free Software Foundation tarafndan daha sonra yaymlanan herhangi bir srmn art ve koullar kapsamnda hareket edebilirsiniz. Eer Program GNU GPL (Genel Kamu Lisans) iin herhangi bir srm numaras belirtmezse, Free Software Foundation tarafndan yaymlanan herhangi bir srm seebilirsiniz. Eer program bir vekilin GNU GPL'nin (Genel Kamu Lisans) hangi ilerki srmlerinin kullanlabileceine bir vekilin karar verebileceini belirtiyorsa, o vekilin bir srmn kabulne dair umum beyanat sizi Program iin o srm semeye kalc olarak yetkili klar. Daha sonraki lisans srmleri size ek veya farkl izinler verebilir. Ancak, daha sonraki bir srme gre hareket etme kararnz sonucunda hi bir mellif veya telif haklar sahibi zerine ek mecburiyetler yklenmez. Garanti Feragatnamesi. PROGRAM N, LGL KANUNLARIN ZN VERD LDE, HERHANG BR GARANT YOKTUR. AKS YAZILI OLARAK BELRTLMED MDDETE TELF HAKKI SAHPLER VE/VEYA BAKA AHISLAR YAZILIMI "OLDUU GB", SATILABLRL VEYA HERHANG BR AMACA UYGUNLUU DA DAHL OLMAK ZERE AKAR VEYA ZIMNEN HBR GARANT VERMEKSZN DAITMAKTADIRLAR. YAZILIMIN KALTES VEYA PERFORMANSI LE LGL TM RSKLER SZE ATTR. YAZILIMIN KUSURLU OLDUU ORTAYA IKTIINDA DAH, HERHANG BR KUSURDAN DOABLECEK OLAN GEREKL BTN SERVS, TAMR VEYA DZELTME MASRAFLARI SZE ATTR. Mesuliyetin Snrlanmas. LGL KANUNUN CBAR ETT VEYA YAZILI ANLAMA DAHLNDEK DURUMLAR HARCNDE HERHANG BR EKLDE TELF HAKKI SAHB VEYA YUKARIDA ZN VERLD EKLDE YAZILIMI DETREN VEYA AKTARAN HERHANG BR K, YAZILIMIN KULLANIMI VEYA KULLANILAMAMASI (VEYA VER KAYBI OLUMASI, VERNN YANLI, KULLANISIZ, KULLANILAMAZ VEYA BOZUK HALE GELMES, SZN VEYA NC AHISLARIN ZARARA URAMASI VEYA YAZILIMIN BAKA YAZILIMLARLA BERABER ALIMAYI BAARAMAMASI) YZNDEN OLUAN GENEL, ZEL, DORUDAN YA DA

93 DOLAYLI HERHANG BR ZARARDAN, BYLE BR TAZMNAT TALEB TELF HAKKI SAHB VEYA LGL KYE BLDRLM OLSA DAH, SORUMLU DELDR. Ksm 15 ve 16'nn Yorumlanmas. Eer yukarda belirtilen garanti feragatnamesi ve taahht snrlar artlar dikkate alnarak yerel ortamda yasal etki dahilinde uygulanamyorsa, konuyu ele alan mahkemeler, Programn bir kopyas ile birlikte bir cret karl olarak bir garanti veya mesuliyet kabul gelmedii taktirde, Programla ilintili tm bireysel mesuliyetlerden tam bir feragata en yakn yerel kanunlar uygulamaldr.

You might also like