Tilakoneet¶
Osaamistavoitteet: Opiskelija ymmärtää miten tilakoneita voidaan käyttää sulautetun ohjelman suunnittelussa ja toteutuksessa.
Tilakoneita (engl. finite-state machine, FSM) käytetään digitaalitekniikassa sekvenssilogiikan toteuttamiseen. Tämä lisäksi tilakoneita käytetään ohjelmistosuunnittelussa hyvin yleisesti ohjelman toiminnallisuuden tai käyttöliittymän mallintamiseksi. Sulautetuissa järjestelmissä tilakone on oiva keino mallintaa ohjelmiston toimintaa jo suunnitteluvaiheessa. Kuten rakenteellinen (modulaarinen) ohjelmointi, tilakoneiden käyttäminen nopeuttaa ja formalisoi ohjelmistosuunnittelun prosessia. Tilakone-mallinnuksen tuloksena on yksinkertaisesti parempi ymmärrys ohjelmaan toiminnallisuudesta ja sitä myötä laadukkaampi lopputulos.
Tässä materiaalissa emme mene tilakoneiden salaisuuksiin syvemmälle, vaan esitämme miten ne on helppo ottaa osaksi suunnitteluprosessia. Ohjelmoinnin ammattilaisilla on käytössä ohjelmointiympäristöjä ja työkaluja, joilla laatia tilakoneita osaksi ohjelmakoodia. Jotkut työkalut jopa automatisoivat itse ohjelmointia tuottamalla valmista koodia tilakonekuvauksesta!
Tilakone¶
Tilakone on järjestelmä, joka kuvataan tiloina ja niiden muutoksina. Esimerkiksi Mealy-tyyppinen tilakone muuttaa tilaansa seuraavasti: tilasiirtymä riippuu nykyisestä tilasta ja tuloista (ts. inputeista). Tilasiirtymien aikana voidaan myös suorittaa toimintoja, jotka tuottavat outputin. Tilakone on deterministinen, eli yhdestä tilasta yhdellä inputilla tuloksena voi olla vain yksi tilasiirtymä. Tilasiirtymäkaavio kuvaa järjestelmän mahdolliset tilat, siirtymät niiden välillä sekä tapahtumat, jotka aiheuttavat siirtymän tilasta toiseen.
Kuvassa alla tilakoneessa on kaksi tilaa
Tila a
ja Tila b
. Nuolilla kuvattuihin tilasiirtymiin on liitetty myös niiden inputit ja mahdolliset outputit. Digitaalitekniikassa ja ohjelmistosuunnittelussa esitellään monentyyppisiä erilaisia tilakoneita, mutta tämä yksinkertaistettu esitys riittää meille. Lisäksi tilakoneen formaaleja kuvaustapoja on erilaisia, mutta tyydymme kurssilla ylläolevaan kuvaukseen.
Esimerkki tilakoneesta¶
Alla sulautetun ohjelman toiminta kuvattuna tilakoneena. Tilakoneeseen on määritelty kolme tilaa
IDLE
, READ_SENSOR
ja MSG_WAITING
ja yksi tilamuuttuja. Tilamuuttujan tarkoitus on ylläpitää ohjelman tilaa, niin että sitä voidaan halutusti muuttaa. Tilassa IDLE vain odotetaan asioita tapahtuvaksi. Tapahtuma voi olla joko komento lukea sensoridataa (READ_SENSOR) tai käsitellä saapunut viesti (MSG_WAITING). Tässä tilasiirtymä tapahtuu kun tilamuuttujan arvoa muutetaan while-toistorakenteen ulkopuolella. Esimerkiksi ajastinkeskeytys voisi ohjata sensorin arvojen lukemista asettamalla tilan READ_SENSOR kerran sekunnissa.Toteutus C-kielellä¶
Ym. tilakoneen C-kielinen toteutus voisi olla seuraava.
enum
-muuttujatyyppi on kätevä tapa esitellä tarvittavat tilat. Tilamuuttujaksi esitellään globaali muuttuja myState
.// Määritellään mahdolliset tilat
enum state { IDLE=1, READ_SENSOR, MSG_WAITING };
// Esitellään ja alustetaan globaali tilamuuttuja
enum state myState = IDLE;
// Ajastinkeskeytys asettaa tilan (esim. kerran sekunnissa)
Void clkFxn(UArg arg0) {
// Muutetaan tilaa halutuksi
// Huom! If-lauseella asetetaan, että tilasiirto on mahdollinen
// vain jos nykyinen tila on IDLE!
if (myState == IDLE) {
myState = READ_SENSOR;
}
}
// Tiedonsiirron taski
Void commTask(UArg arg0, UArg arg1) {
while (1) {
// Onko viesti puskurissa odottamassa?
if (is_message_waiting() == TRUE && myState == IDLE) {
// Muutetaan tilaa
myState = MSG_WAITING;
}
}
}
// Ohjelman main-taski
Void myTask(UArg arg0, UArg arg1) {
while (1) {
// Tilakoneen toteutus
switch (myState) {
case READ_SENSOR:
// Suoritetaan tilan vaatima operaatio
read_sensor_values();
update_screen();
// Asetetaan tila takaisin IDLE
myState = IDLE;
break;
case MSG_WAITING:
// Suoritetaan tilan vaatima operaatio
handle_message();
send_reply();
// Asetetaan tila takaisin IDLE
myState = IDLE;
break;
}
}
}
Yllä koodissa siis määrittelimme
enum
:n avulla mahdolliset tilat ja esittelimme globaalin muuttujan myState
tilamuuttujaksi. Ohjelmassa on asetettu ajastinkeskeytys kerran sekunnissa, jonka käsittelijä on clkFxn
, joka muuttaa tilaa. Samoiten commTask
-tehtävässä muutamme tilaa, jos puskurissa on odottamassa viestejä. Seuraavan kerran kun mainTask
-tehtävässä tarkistamme tilan, näemme sen muuttuneen ja reagoimme muutokseen suorittamalla halutun toiminnon. if
-lauseella tarkistamme ennen tilamuutosta, että se on luvallinen. Ilman tarkastuksia saattaa koodissa tulla tilasiirtymiä, jotka eivät ole tarkoituksenmukaisia, tai jokin tila jäädä kokonaan suorittamatta. Yllä siis varmistetaan, että siirtymät ovat mahdollisia vain IDLE-tilasta. (Ym. esimerkissä tosin keskeytyksen korkeampi prioriteetti varmistaa, ettei toinen tila ohita sitä.) Yleisesti, tilasiirymän luvallisuuden tarkistus on varsin oleellinen juttu! Tilakonetta suunnitellessa tilat kannattaa järjestää esim. kasvavassa numerojärjestyksessä niin, että tarkistus voidaan tehdä vertailu-operaattorilla (pienempi kuin, suurempi kuin, ...) helposti. Tässäkin vältämme viimeiseen asti monimutkaisia
if-else
-rakenteita! Toinen oleellinen asia koodin rakenteen parantamiseksi on tilojen määrän minimointi.Tyypillinen toinen käyttötapaus tilakoneelle sulautetuissa ohjelmissa on käyttöliitttymän toteuttaminen. Tilakoneen avulla voimme määritellä rajatulle määrälle komponentteja, esimerkiksi kahdelle painonapille, ohjelman tilasta riippuvia toimintoja. Esimerkiksi MENU-tilassa yksi nappi on omistettu virtanapiksi, mutta PELI-tilassa sitä voidaan käyttää peliohjaukseen. Kätevää!
Lopuksi¶
Tulevilla kursseilla tilakoneet tulevat enemmän tutuksi. Niistä on valtavasti hyötyä kaikessa ohjelmoinnissa.
Yhtenä osana kurssin harjoitustyötä, tulee opiskelijoiden laatia ohjelmansa korkean tason tilakoneen kuvaus.
Anna palautetta
Kommentteja materiaalista?