ScriptablePlugin umožňuje provádět nad piny složitější operace a dá se rovněž použít pro generování různých funkcí na výstupech. Celý plugin dokáže emulovat funkčnost většiny ostatních pluginů s vyjímkou těch, které přímo komunikují s HW (ISESCardPlugin, ISESProCardPlugin, PCI1202CardPlugin). Interface dostupný přímo z MeasureServeru je minimální a většina operací se provádí pomocí scriptu uloženého v samostatném souboru.
Pomocí tohoto dialogu jdou měnit základní parametry. Jakákoliv změna parametru vyžaduje restart MeasureServeru.
V dialogu MeasureServeru (viz. hlavní dokumentace) je nejdůležitější řádek pro volbu souboru se scriptem, který popisuje chování pluginu, dostupné piny a ostatní použité pluginy.
V případě, že script používá i jiné pluginy, je možné pomocí dalšího prvku umístěného v dialogu, nastavovat jejich parametry.
Scripty jsou textové soubory s koncovkou psc. Tyto scripty jsou načteny při startu MeasureServeru. Případné změny v nich provedené se projeví až při dalším spuštění MeasureServeru. Syntaxe použítá ve scriptu nejvíce připomíná programovací jazyk C s některými prvky z jiných jazyků. Všechny proměnné jsou reálná čísla (typ double v C), jiný datový typ není přímo podporovaný. Rozlišují se velká a malá písmena! Všechny operace prováděnné scriptem jsou synchronní s celým během serveru (dokud běží script, tak server nemůže provádět nic jiného).
Struktura scriptu je částečně fixní s tím, že většina částí je nepovinná, ale pokud jsou uvedeny tak musí být ve správném pořadí.
Struktura scriptu je následující:
Na většině míst v textu je možno používat komentáře uvedené znakem '#'. Cokoliv od tohoto znaku do konce řádku je ignorováno.
Hlavička má následující povinný formát
version 1.0 name example_generatorKde:
Popisuje jaké piny a z kterých pluginů budou použity. Piny se ve zbytku scriptu chovají jako proměnné. Zápis do takovéto proměnné zapíše hodnotu do pinu druhého pluginu. Čtení z takovéto proměnné přečte hodnotu z pinu druhého pluginu. Tato sekce má dvě části, jejichž pořadí je pevně dáno. První část definuje další pluginy, které jsou použity, včetně jména jejich konfigurace. Formát této části je následující:
using plugin_id "path_to_plugin" config_idKde:
using hw_lib "Plugins\ISESProCardPlugin.ldp" config1
Druhá část pak identifikuje piny z pluginů definovaných v první části, které jsou scriptem používány. Formát této části je následující:
import pin_id plugin_id "pin_name" [filter]Kde:
import output_a hw_lib "Write D/A 1"
Popisuje globální proměnné dostupné v celém scriptu. Proměnné vzniknou při startu serveru a nastaví se na hodnotu uvedenou v jejich definici. Následně může script jejich hodnoty libovolně číst a měnit. Formát definice proměnné je následující:
variable variable_id = valueKde:
variable sfrequency = 1.345
Tato část obsahuje výkonnou činnost scriptu. Celá je tvořena z bloků které mají následující syntaxi:
block_type [block_id] { operations }
Kde:
Operace asociované s jedním z těchto handlerů se spustí, pokud nastane operace asociovaná s handlerem.
Operace asociované s on_each_second se spusti přibližně každou sekundu.
Operace asociované s on_user_change se spustí, když dojde ke změně uživatele nebo odpojení posledního uživatele.
V případě, že je v souboru scriptu definováno několik handlerů stejného typu, se všechny provedou v pořadí uvedeném ve scriptu.
Operace asociované s těmito piny se spustí pří přečtení nebo žápisu hodnoty pinu jménem block_id. Je možné mít v jednom scriptu pin_read i pin_write se stejným block_id, ale není možné mít ve scriptu několik pin_read/pin_write se stejným block_id.
Neexistuje žádné omezení z jakých pinů z ostatních pluginů je možné v rámci bloku číst nebo na které je možné zapisovat. Čtecí handler pro pin může klidně zapisovat na pin jiného pluginu. To umožňuje tvorbu generátorů signálu jak je uvedeno v kapitole Příklady
V případě, že běží handler pin_write, je dostupná speciální proměnna new_value s hodnotou, která se má zapsat do pinu.
V případě, že běží handler pin_read, je dostupná speciální proměnná time, která obsahuje čas v sekundách od posledního zápisu do tohoto pinu popřípadě od startu serveru pokud k žádnému zápisu dosud nedošlo. V případě, že odpovídající pin_write handler neexistuje, je zápis na tento pin ignorován, ale k restartu času dojde. Dále je zde dostupná speciální proměnná result, do níž by měl pin uložit hodnotu, která se vrátí jako hodnota přečtená z pinu. Defaultně je v této proměnné na začátku bloku uložena hodnota 0. Dále je dostupná proměnná reset_time, která (pokud je na konci nastavena na kladnou hodnotu), způsobi restart hodnoty time. V případě experimentů, jejichž server běží dlouhodoběji, je potřeba jednou za čas provést tento restart, jinak dojde ke ztrátě přesnosti času uloženého v proměnné time. V závislosti na HW počítače a velikosti hodnoty proměnné time může být čas vyjádřen až s přesností na desetinu milisekundy.
experiment foo {
init { operations }
on_sample plugin_id { operations }
finalize { operations }
}
Oproti běžným handlerům obsahují bloky experimentů speciální podporu pro předávání dat mezi bloky. Obsah dočasných proměnných (t0-t99) se přenáší mezi voláními bloků (například hodnota zapsaná do proměnné t50 v init bloku v ní bude dostupná i v průběhu on_sample bloku).
V blocích init a on_manual_sample je možné používat funkci write_output, která zapíše aktuální stav burst_out_* proměnných do seznamu dat posílaných na výstup v případě init bloku nebo do záznamu experimentu v případě on_manual_sample bloku. V případě init bloku je možné zapsat až 1000000 vzorků. V případě on_manual_sample je možné zapsat desetinásobek naměřeného množství HW vzorků (uložené v sample_count).
Blok on_sample/on_manual_sample na začátku dostane v proměnných sample_index, burst_in_time a burst_in_0-burst_in_7 parametry HW vzorku pro který je právě volán. Hodnota burst_out_time je nastavena na stejnou hodnotu jako burst_in_time. V rámci bloku je možné použít funkce sample a isample pro načtení parametrů i jiných naměřených vzorků. Volání jedné z těchto funkcí naplní hodnoty burst_in_time a burst_in_0-burst_in_7 hodnotami pro příslušný vzorek. Ostatní proměnné, hlavně burst_out_time a sample_index, zůstanou nezměněnné.
Operace asociované s blokem popisují, co se má stát, když se blok zpracovává. Jsou podporovány základní matematické operace jako je sčítání, odčítání, násobení, dělení, zbytek po dělení. Script také obsahuje několik goniometrických funkcí a nástroje pro tvorbu jednoduchých podmínek. V operacích je možné používat všechny proměnné uvedené v předchozích sekcích a dále je možno použít 100 dočasných proměnných, které platí pouze po dobu běhu bloku a na jeho začátku jsou nastavené na hodnotu 0.
Každý blok může mít libovolný počet operací.
Každá operace může být jedno z následujícího:
Přiřazení:
Y = expression ;
if ( if_expression ) {
operations
}
[ else { operations } ]
while ( if_expression ) {
operations
}
exit ;
| Zápis | Význam |
| exit | Funkce ukončí běh bloku. |
| stop | Funkce má význam pouze v on_sample/on_manual_sample bloku burst experimentu. Ukončí zpracování naměřených vzorků po dokončení zpracování aktualního vzorku. |
| write_output | Funkce má význam pouze v on_sample/on_manual_sample/init bloku burst experimentu. Vygeneruje nový výstupní vzorek na základě aktualního stavu výstupních proměnných. |
| sample( expression ) | Funkce má význam pouze v on_sample/on_manual_sample bloku burst experimentu. Načte do vstupních proměnných hodnotu vzorku s indexem ( sample_index + expression ). Hodnota se před přístupem zaokrouhlí na nejbližší celé číslo. Pokud je index mimo naměřený rozsah, použije se nejbližší naměřená hodnota. |
| isample( expression ) | Podobné funkci sample, ale desetinná část je použita pro lineární interpolaci mezi dvěma vzorky, mezi které ( sample_index + expression ) padne. |
| rotate( start, end, ammount ) | Orotuje dočasné proměnné (t0-t99) v rozsahu |
Expression je výraz, který může obsahovat libovolnou syntakticky platnou kombinaci proměnných, explicitních číselných konstant (např. 2.4), operací a funkcí uvedených níže. V příkladech uvedených níže jsou pismena A a B jména proměnných.
| Znaménko | Operace | Příklad |
| + | Sčítání | 5 + A |
| - | Odčítání | 5 - A |
| - | Změna znaménka | -A |
| * | Násobení | 5 * A |
| / | Dělení | A/3. V případě, že dojde k dělení nulou, vraci hodnotu 0 |
| % | Zbytek po dělení | A % 3. V případě, že dojde k dělení nulou, vraci hodnotu 0 |
| Funkce | Příklad | Popis |
| clamp( x, minum, maximum ) | clamp( A, -5, 10.0 ) | Zajistí, aby vrácená hodnota byla pouze v uvedeném rozsahu. Pokud je minimum > maximum, je vrácena hodnota minimum. |
| min( x, minum ) | min( A, 0.0 ) | Vrací minimum z obou hodnot. |
| max( x, maximum ) | max( A, 0.0 ) | Vrací maximum z obou hodnot. |
| pow( x, y ) | pow( A, 2.0 ) | Spočítá x^y |
| cmp( x, treshold, result_a, result_b ) | cmp( A, 0.0, 1.0, 0.0 ) | Vraci result_a pokud x > treshold a jinak vraci result_b |
| cmps( x, treshold, result_a, result_b ) | cmps( A, 0.0, 1.0, 0.0 ) | Vraci result_a pokud x >= treshold a jinak vraci result_b |
| cmp( x, treshold ) | cmp( A, 0.0 ) | Zkratka pro cmp( x, treshold, 1.0, 0.0 ) |
| cmps( x, treshold ) | cmps( A, 0.0 ) | Zkratka pro cmps( x, treshold, 1.0, 0.0 ) |
| atan2( x, y ) | atan2( A, B ) | Vrací arc tangent v radiánech z hodnoty X / Y v radiánech včetně správného určení kvadrantu. |
| asin( x ) | asin( A ) | Vrací arc sinus v radiánech z hodnoty oříznuté do rozsahu <-1,1>. |
| acos( x ) | acos( A ) | Vrací arc cosinus v radiánech z hodnoty oříznuté do rozsahu <-1,1>. |
| sin( x ) | sin( A ) | Vrací sinus hodnoty v radiánech |
| cos( x ) | cos( A ) | Vrací cosinus hodnoty v radiánech |
| remap( x, s0, s1, s2, d0, d1, d2 ) | remap( A, 100, 200, 300, 0, 0.5, 1.0 ) | Přemapuje hodnoty z rozsahu <s0,s1,s2> do rozsahu <d0,d1,d2> s tím že s1 se přemapuje na d1. Vstupní hodnoty mimo platný rozsah se oříznou do rozsahu <s0,s2> |
| fraction( x ) | fraction( 3.5 ) | Vrací desetinou část vstupní hodnoty. Použitelné například pro generování signálu typu pila. |
| floor( x ) | floor( 3.5 ) | Zaokrouhlí hodnotu na nejbližší nižší celé číslo |
| ceil( x ) | ceil( 3.5 ) | Zaokrouhlí hodnotu na nejbližší vyžší celé číslo |
| round( x ) | round( 3.5 ) | Zaokrouhlí hodnotu na nejbližší celé číslo |
| abs( x ) | abs( -3.5 ) | Vrací absolutní hodnotu parametru |
Tento typ výrazu může být použit pouze v podmínce typu if. Oproti normálnímu výrazu je ještě rozšířen o následující užitečné zkratky.
| Zkratka | Význam |
| expression_a>expression_b | cmp( expression_a, expression_b ) |
| expression_a>=expression_b | cmps( expression_a, expression_b ) |
| expression_a<expression_b | cmp( expression_b, expression_a ) |
| expression_a<=expression_b | cmps( expression_b, expression_a ) |
Plugin je možné použit pro generování signálu přes ISES následujícím postupem.
Ukázka jednoduchého scriptu generujícího sinusový přůběh s nastavitelnou frekvencí
version 1.0
name sin_signal
# Importovani pinu do kterého budeme zapisovat.
using card_lib "plugins\ISESProCardPlugin.ldp" card_config_1
import output card_lib "Write D/A 1"
# Frequence generované křivky v HZ.
variable set_frequency = 1.0
# Pin jehož čtení generuje výstup.
pin_read generator {
# Generovani hodnoty pro aktuální okamžik.
result = sin( time * set_frequency * 6.28 ) * 2048 + 2048 ;
}
# Pin sloužící pro nastavení generované frequence.
pin_read frequency {
result = set_frequency ;
}
pin_write frequency {
set_frequency = new_value ;
}
# Script generujici sinusovou krivku nebo pilu s uzivatelsky nastavitelnou
# frekvenci.
#
# Script ma nasledujici piny:
# frequency .. cteni vraci aktualne nastavenou frekvenci v Hz.
# frequency .. zapis nastavi novou frekvenci v Hz.
# measured_value .. cteni vraci hodnotu prectenou z prvniho analogoveho vstupu
# ISESu.
# generator .. precteni tohoto pinu vygeneruje na vystup jednu hodnotu. Pro
# spravnou funkci generatoru je potreba mit u tohoto pinu zapnuty
# fastlog s rozume vysokou vzorkovaci frekvenci.
# Verze scriptovaciho jazyka.
version 1.0
# Nazev scriptu. Tato polozka se pouzije jako nazev pluginu v MeasureServeru.
name example_generator
# Reference na HW plugin, ktery se bude pouzivat pro vystup a vystup.
using card_lib "plugins\ISESProCardPlugin.ldp" card_config_1
# Importovani pinu, do kterého budeme zapisovat vystup.
import output card_lib "Write D/A 1"
# Importovani pinu, ze ktereho budeme cist namerene hodnoty.
import vstup_1 card_lib "Read A/D 1"
# Typ generovane krivky.
#
# Hodnota >= 0.0 odpovida sinusove krivce.
# Hodnota < 0.0 odpovida pile.
variable output_type = 1.0
# Frequence generované křivky v Hz.
variable generated_frequency = 1.0
# Promenna pouzita pro zastaveni generovani, kdyz neni komunikace
# s klientem.
variable watchdog_counter = 0.0
# Pin, jehož čtení generuje výstup.
pin_read generator {
# Generovani hodnoty pro aktuální okamžik. Pokud je generovani
# zapnute, tak se spocita skutecna hodnota, jinak se pouzije
# hodnota odpovidajici nule.
if ( watchdog_counter > 0.0 ) {
# Vygenerovani zvoleneho typu krivky jako hodnoty
# v rozsahu <-1,1>
if ( output_type >= 0.0 ) {
t0 = sin( time * generated_frequency * 6.28 ) ;
}
else {
t0 = fraction( time * generated_frequency ) * 2 - 1 ;
}
# Prepocet na vystupni rozsah 0 az 4095 (odpovida 12bitovemu rozliseni
# ADDA karty a vystupnimu rozsahu <-5V,5V> tj. 0-4095 binarne)
t0 = t0 * 2048 + 2048 ;
# Vyslani spocitane hodnoty na vystup. Normalni experiment by mohl
# spocitanou hodnotu vyslat i kdyz se nic negeneruje. Protoze vsak
# ostatni ukazkove experimenty pouzivaji vystup, tak by takoveto
# chovani tohoto prikladu zpusobilo nefunkcnost jejich vystupu.
output = t0 ;
}
else {
t0 = 2048 ;
# Nasledujici radek vynuti restart promenne time. Vsechny vypocty v
# tomto scriptu se provadeji pomoci 64bitovych cisel s pohyblivou
# desetinou carkou. Dusledkem je, ze u prilis velkych hodnot dochází
# ke ztrátě přesnosti hodnoty. Pokud by se reset neprovedl, experiment
# by po delsi dobe zacal generovat cim dal "zubatejsi" krivku.
reset_time = 1 ;
}
# Jeji vraceni jako hodnoty tohoto pinu.
result = t0 ;
}
# Pin, jehoz precteni nacte hodnotu z prvniho HW vstupu.
pin_read measured_value {
result = vstup_1 ;
}
# Pin sloužící pro cteni a nastavovani generovane frekvence.
pin_read frequency {
result = generated_frequency ;
# V ukazkove strance je applet, ktery periodicky cte tento pin (a zaroven
# tento pin neni logovan), takze se tento pin cte prave kdyz je funkcni
# spojeni s klientem.
# Pri kazdem precteni se nastavi promena watchdog_counter na vhodne
# zvolenou hodnotu. Hodnota teto promenne je kazdou sekundu snizena
# o 1 (viz on_each_second nize) a generovani se zastavi pokud bude mensi
# nez nula nebo rovna nule (viz. generator nahore).
# Dusledkem je, ze generovani se zastavi pokud si tento pin nekdo neprecte
# po odpovidajici pocet sekund.
watchdog_counter = 5 ;
}
pin_write frequency {
generated_frequency = new_value ;
}
# Pin slouzici na nastavovani typu generovaneho vystupu.
pin_write type {
output_type = new_value ;
}
# Nasledujici funkce je volana kazdou sekundu.
on_each_second {
# Odpocet casu do zastaveni generovani pokud uz toto nebylo zastaveno.
if ( watchdog_counter > 0.0 ) {
watchdog_counter = watchdog_counter - 1 ;
}
}
# Kdyz se zmeni uzivatel, nastavime zpatky pocatecni frekvenci a
# typ krivky.
on_user_change {
generated_frequency = 1.0 ;
output_type = 1.0 ;
}