s knihovnou inpout32.dll + .NET jsem taky začínal, brzo zjistíš, že v .NET se jenou za čas probudí garbage collector a tvé vlákno se nedostane ke slovu po dobu desítek stepů o které tak přijdeš. Mne se také motor točil. Ale dej si na rotor značku, spusť program, který hodně plynule zrychlí na maximum a zase hodně plynule zastaví v téže poloze. Pak se znovu podívej na značku.
proto jsem nejprve switchnul do C++ a nastavil proces na high-priority. Nic naplat, ve Windows nemá proces zaručeno, že se ke slovu dostane častěji než jednou za 15 ms (time slice). Proto jsem si napsal kernel mode driver, kterým jsem si na čtyřjádru přivlastnil jedno celé jádro pro sebe a čtením instrukce rdtsc v cyklu kontroloval že se s nikým nedělím o strojový čas (instrukce vrací hodnotu registru ve kterém si každé jádro zvlášť počítá počet taktů od okamžiku spuštění - mám základní takt 2,4 GHz a v biosu zakázané automatické úpravy frekvence - na rdtsc staví např. API funkce QueryPerformanceFrequency). Zjištění mne překvapilo, beztak jsem čas od času zaspal klidně 100 tis. taktů. Takto dlouho trvají některé obslužné rutiny interruptů, které jádro kromě mého procesu čas od času obsloužilo. Proto jsem ještě mému jádru disabloval interupty a pak už jsem preiodicky ztrácel "jen" stovky taktů, což šlo na úkor HW záležitostí jako je např. flush chache a pod. To už by bylo z hlediska potřeb mého časování naprosto dostačující, ale byl jsem tím dost otrávený (mám 64-bit Windows 7, které vyžadují podpis driveru a jiné překážky) že jsem hledal jiné řešení.
Zajímal jsem se o to, jak to dělají profesionální programy. Dočetl jsem se dva zajímavé principy:
využívají DMA přenost z paměti na LPT port, takže přenost není řízený procesorem, ale hardwarem, který ničím nerušen stále stejnou frekvencí bere místo ve fyzické paměti, přenese ho na jiné místo v paměti (kam je namapovaný LPT port) a zvětší zdrojovou adresu, zatímco cílová zůstává stejná. Toto se opakuje nezměněnou rychlostí, která je řádově vyšší než frekvence pulzů pro motor. V paměti to pak vypadá tak, že je za sebou třeba 100 bytů stejných, takže při jejich přehazování na LPT se výstupní signál nemění, dalších 100 bytů má hodnotu jinou. Pokud chci frekvenci o něco vyšší, zkracuji nebo prodlužuji počty stejných bytů. Pokud je žádaná frekvence mezi 100 a 101 byty, tak to střídám, motor to ani nepozná, odchylka od správného časování je pouze setina fáze jednoho kroku. Programu pak nevadí nepravidelnosti běhu, protože s velkým předstihem donaplňuje data do cyklického bufferu po kterém DMA s ničím nerušenou pravidelností roluje.
jiné programy používají mutilemdia timer, což je HW časovač, který umí vyvolat interupt s pravidelnou periodou a nebo po při dosažení nastaveného počtu. Programy druhou možnost nevyužívají, nechají timer tikat s pravidelnou periodou, která je řádově vyšší než maximální frekvence půlsů pro motor. V obslužné rutině navěšené na interupt z timeru program akorát zkontroluje za již nastal čas pro další puls pro motor, pokud ne, provede kontrolu znovu při dalším přerušení.
Já jsem šel úplně jinou třetí cestou, ale to si nechám na příště jsem už upsaný