XIX.  

JEDNOTKA  CRT


Jednotka Crt implementuje převážně prostředky pro řízení vstupu z klávesnice a výstupu na obrazovku. Standardní podpora těchto zařízení je implementována jednotkou System, která je zpracovává jako textové soubory, spojené s proměnnými InputOutput. Jednotka Crt nepoužívá pro ovládání souborů InputOutput univerzální přístup k obecným textovým souborům, nýbrž instaluje vlastní ovladače konkrétních fyzických zařízení klávesnice a obrazovka. Tento přístup umožňuje implementaci řady specializovaných mechanismů, využívajících zvláštní vlastnosti těchto zařízení, které jiná textová zařízení obecně nemají (například výstup textu na obrazovku není orientovaný pouze sekvenčně, pozici prvního znaku vypisovaného textu lze volit).

XIX.1. 

Vstup textu z klávesnice

Vstup dat z klávesnice lze realizovat pomocí standardních podprogramů jednotky System (Read, Readln, EOF, atd.), proměnná Input je však spojena speciálně s klávesnicí, nikoliv obecně se standardním vstupním zařízením operačního systému (nezávisle na případném přesměrování vstupu). Pro editování textu uvnitř vstupní řádky lze použít těchto klávesových povelů:

  povel     účinek  
BACKSPACE vymaže naposled zadaný znak
ESC vymaže celý obsah vstupní řádky
CTRL+D obnoví jeden znak z poslední vstupní řádky
CTRL+F obnoví celý obsah poslední vstupní řádky
ENTER ukončí vstupní řádku dvojicí znaků CR, LF
CTRL+Z ukončí vstupní řádku znakem konce souboru

XIX.2. 

Proměnné CheckEof a CheckBreak

Přiřazení hodnoty proměnným CheckEofCheckBreak jednotky Crt umožňuje volbu mezi povolením a zákazem generování řídících znaků konec souboru a ukonči program.

const CheckEof   : Boolean = False;
      CheckBreak : Boolean = True;

Hodnota True resp. False proměnné CheckEof povoluje resp. zakazuje generování znaku konce souboru (CTRL+Z) a hodnota True resp. False proměnné CheckBreak povoluje resp. zakazuje generování požadavku na ukončení programu (CTRL+BREAK). Implicitní hodnoty proměnných jsou False resp. True. Při zákazu nemá stisk příslušné kombinace kláves žádný efekt.


POZNÁMKA: Ve vývojovém prostředí Turbo Pascalu je význam povelu CTRL+BREAK předefinován (používá se pro přerušení běhu programu při jeho ladění). Hodnota False proměnné CheckBreak se proto při spouštění programu z vývojového prostředí nemůže projevit.

XIX.3. 

Funkce KeyPressed a ReadKey

Při čtení znaku z klávesnice je identifikována aktivní klávesa či kombinace kláves a vypočten odpovídající znak. Jako „znakové“ (znaky generující) jsou akceptovány i funkční klávesy (F1 až F10, PGDN, INS, kurzorové šipky atd.), ne však samotné přeřazovače (ALT, SHIFT, CTRL) a další „neklávesy“ (F11, F12, CAPSLOCK...), jejichž samostatný stisk nemá žádný efekt. Stiskem kterékoliv z funkčních kláves nebo ALT-kombinací je generována namísto jediného znaku dvojice, přičemž první z generovaných znaků je vždy #0.

Pro testování aktuálního stavu klávesnice a čtení znaku poskytuje jednotka Crt funkce KeyPressedReadKey.

function KeyPressed: Boolean;

Vrací True, pokud se ve vyrovnávací paměti klávesnice nachází alespoň jeden generovaný znak, jinak False.


POZNÁMKA: Klávesnicí generovaný znak vyvolá přerušení, jehož obsluha jej uloží do vyrovnávací paměti. Zde setrvá, dokud není přečten funkcí ReadKey či procedurou Read nebo Readln. Funkce KeyPressed tedy netestuje, zda je v daném okamžiku stisknuta nějaká klávesa, nýbrž zda jsou „uskladněny“ nějaké dosud nezpracované znaky.

function ReadKey: Char;

Vrací znak, přečtený z vyrovnávací paměti klávesnice. Pokud je vyrovnávací paměť v okamžiku volání prázdná, funkce vyčká na vstup znaku z klávesnice, který okamžitě převezme (bez odezvy na obrazovce a bez možnosti editace).


PŘÍKLAD: Následující program reaguje na stisk klávesy výpisem generovaného znaku a jeho kódu.

{======================================================================}
program Kody;
{======================================================================}

 uses Crt;
 var  Key: Char;                                    { generovaný znak  }

begin { program }
 Writeln;
 repeat                                             { opakuj           }
  Write('klávesa (ESC = konec): ');                 { výzva            }
  Key := ReadKey;                                   { načtení znaku    }
  if Key = #0 then                                  { funkční klávesa  }
   Writeln('#0, #', Ord(ReadKey))
  else                                              { obyčejná klávesa }
   Writeln('#', Ord(Key), ' (''', Key, ''')')
 until Key = #27;                                   { do stisku ESC    }
 Writeln
end. { program }

XIX.4. 

Výstup textu na obrazovku

Zobrazení informace na obrazovce zajišťuje tzv. videoadaptér (grafická karta). Plní funkci rozhraní mezi počítačem a monitorem po stránce technické i programové. Procesor počítače průběžně zapisuje data do videopaměti adaptéru, který je v pravidelných intervalech čte a generuje signály jejich zobrazení pro monitor. Frekvence obnovy zobrazení závisí na kvalitě adaptéru a monitoru a na nastaveném módu zobrazení (rozsahu zobrazovacích dat). Běžné hodnoty se pohybují v rozmezí 50 až 100 Hz.

V zásadě mohou videoadaptér a procesor spolupracovat ve dvou kvalitativně odlišných třídách módů — textovýchgrafických. Jednotka Crt implementuje podporu textových módů, ve kterých mohou být na obrazovce monitoru zobrazovány pouze znaky. Do videopaměti adaptéru zapisuje procesor na příslušnou pozici (definovanou pozicí kurzoru na obrazovce) hodnoty znaku a jeho atributu (barvy), převod do rastru elementárních zobrazovacích bodů realizuje adaptér podle definiční tabulky znakové sady.

Při zápisu znaku na obrazovku procedurou Write nebo Writeln mají následující znaky řídící význam. Ostatní znaky jsou zapsány normálně (objeví se na obrazovce).

  znak     řídící funkce  
BELL (#7) akustický signál (pípnutí)
BACKSPACE (#8) posun kurzoru o pozici vlevo (není-li na začátku řádky)
LF (#10) posun kurzoru o pozici dolů
CR (#13) posun kurzoru na začátek řádky

XIX.5. 

Textové módy

Pro práci v textovém režimu je možné volit z textových módů, které jsou aktuálním typem adaptéru podporovány. Z vizuálního hlediska se textové módy liší počtem řádek na obrazovce, počtem znaků v každé řádce (sloupců) a černobílým (resp. monochromatickým) nebo barevným zobrazením.

const BW40    =   0; { 25 řádek × 40 sloupců, černobíle }
      CO40    =   1; { 25 řádek × 40 sloupců, barevně   }
      BW80    =   2; { 25 řádek × 80 sloupců, černobíle }
      CO80    =   3; { 25 řádek × 80 sloupců, barevně   }
      Mono    =   7; { 25 řádek × 80 sloupců, černobíle }
      Font8x8 = 256; { 43/50 řádek × 40 sloupců         }

Hodnotami uvedených konstant jsou čísla jednotlivých textových módů, používaná jako parametry procedury TextMode (níže). Hodnoty 0 až 3 odpovídají čtyřem textovým módům adaptéru CGA, hodnota 7 jedinému módu adaptéru MDA. Adaptér VGA podporuje všechny uvedené módy, barevná složka videosignálu však není v módech 0 a 2 potlačena (módy 0 a 1 resp. 2 a 3 jsou tedy na VGA stejné). Na VGA/EGA je mód obecně reprezentován dvoubytovým číslem, jehož vyšší byte definuje počet řádek — 25 resp. 50 (na EGA pouze 43) pokud je nulový resp. nenulový — a nižší byte by měl obsahovat některou z povolených hodnot 0, 1, 2, 3 nebo 7. Například číslo 259 (Font8x8 + CO80) definuje textový mód o rozlišení 50/43 řádek krát 80 sloupců.

procedure TextMode (Mode: Word);

Nastaví požadovaný textový mód, specifikovaný parametrem Mode, a jeho číslo uschová do proměnné LastMode. Vedlejším efektem změny módu je reinicializace parametrů zobrazení (vesměs jsou popsány dále v této kapitole) — výmaz obrazovky, vložení počáteční hodnoty do proměnné TextAttr, nastavení implicitního výstupního okna a přesun kurzoru do jeho levého horního rohu.

var LastMode: Word;

Obsahuje automaticky udržované číslo aktuálního textového módu. Počáteční hodnota proměnné je inicializována na začátku běhu programu (je vhodné ji uschovat a původní mód před ukončením běhu programu obnovit), k automatické aktualizaci dochází při změně módu procedurou TextMode.

XIX.6. 

Výstupní okna

Výstupní okno je pravoúhelníkový výřez zobrazovací plochy, do nějž je směrován obrazovkový výstup textu. Pozice a velikost okna jsou definovány souřadnicemi jeho levého horního a pravého dolního rohu (strany okna jsou rovnoběžné s okraji zobrazovací plochy).

Jednotka Crt implementuje zobrazovací souřadnice tak, že řádky jsou číslovány od 1 shora (souřadnice y) a sloupce od 1 zleva (souřadnice x). Pouze při definici nového okna se používají absolutní souřadnice, vztažené k počátku (levému hornímu rohu) celé zobrazovací plochy. Ve všech ostatních případech jsou veškeré uváděné souřadnice vztaženy relativně k počátku aktuálního okna.

Mimo aktuální okno je obrazovka nepřístupná, uvnitř mají všechna okna stejné vlastnosti (až na rozměry) jako celá zobrazovací plocha (přechod kurzoru na novou řádku při dosažení pravého okraje, rolování při dosažení spodního okraje). Implicitním oknem (automaticky nastaveným při startu programu a při každé změně textového módu) je celá zobrazovací plocha.

var WindMin, WindMax: Word;

Proměnná WindMin resp. WindMax obsahuje absolutní obrazovkové souřadnice levého horního resp. pravého dolního rohu aktuálního výstupního okna. V nižších bytech proměnných jsou uloženy souřadnice horizontální (sloupce), ve vyšších souřadnice vertikální (řádky). Řádky i sloupce jsou však v těchto proměnných číslovány od 0!

procedure Window (XL, YH, XP, YD: Byte);

Vytvoří nové výstupní okno, definované absolutními souřadnicemi XLYH (levý horní roh) a XPYD (pravý dolní roh). Rozměry vytvořeného okna jsou tedy hodnotami výrazů XP – XL + 1 (šířka) a YD – YH + 1 (výška). Pokud jsou však zadané souřadnice neplatné (některá ze souřadnic je mimo zobrazovací plochu nebo je XL > XP či YH > YD), nemá volání procedury žádný efekt (původní výstupní okno zůstane zachováno).

Po vytvoření okna je kurzor umístěn do jeho levého horního rohu (souřadnice 1, 1) a absolutní souřadnice levého horního a pravého dolního rohu okna jsou uloženy (zmenšené o jedničku) do proměnných WindMinWindMax. Již zobrazený text není vytvořením nového okna ovlivněn (výmaz obsahu okna se neprovádí).

XIX.7. 

Barvy

Ve videopaměti odpovídá každé pozici na obrazovce dvoubytové slovo. V jeho nižším bytu je uložen znak, který je na příslušné pozici zobrazen, ve vyšším pak barevný atribut znaku. Barevné vlastnosti znaku jsou v osmi bitech atributu zakódovány takto:

pořadí bitu
76543210
hodnota bitu
b p p p z z z z

Nejnižší čtveřice bitů atributu obsahuje číslo zzzz barvy popředí, použité pro zobrazení tahů znaku. Jeho rozsah je 0000 až 1111 binárně, čili 0 až 15 decimálně.

Další trojice bitů atributu obsahuje číslo ppp barvy pozadí, použité pro zobrazení podkladu znaku. Jeho rozsah je 000 až 111 binárně, čili 0 až 7 decimálně.

Hodnota b nejvyššího bitu atributu je tzv. příznak blikání. Hodnota 0 resp. 1 příznaku zakazuje resp. povoluje blikání znaku. Při povoleném blikání je barva popředí znaku nahrazována v pravidelných intervalech barvou pozadí znaku a opět obnovována.


POZNÁMKA: Programováním grafického adaptéru lze způsob interpretace nejvyšších bitů barevných atributů změnit. Nejvyšší bit atributu je pak chápán jako součást čtyřbitové hodnoty barvy pozadí znaku, který pak ovšem nemůže blikat. Na některých adaptérech je tento stav dokonce implicitní.

Zobrazitelných barev je tedy celkem šestnáct a jsou reprezentovány čísly 0 až15. Všechny jsou použitelné pro definici barvy popředí znaku, ale jen prvých osm (s čísly 0 až 7) může být použito pro definici barvy pozadí znaku. Číselným hodnotám implicitně odpovídají následující vizuální barvy:

const Black        =   0;             { černá           }
      Blue         =   1;             { modrá           }
      Green        =   2;             { zelená          }
      Cyan         =   3;             { azurová         }
      Red          =   4;             { červená         }
      Magenta      =   5;             { fialová         }
      Brown        =   6;             { hnědá           }
      LightGray    =   7;             { světle šedá     }

      DarkGray     =   8;             { tmavošedá       }
      LightBlue    =   9;             { jasně modrá     }
      LightGreen   =  10;             { jasně zelená    }
      LightCyan    =  11;             { jasně azurová   }
      LightRed     =  12;             { jasně červená   }
      LightMagenta =  13;             { jasně fialová   }
      Yellow       =  14;             { žlutá           }
      White        =  15;             { bílá            }

      Blink        = 128;             { příznak blikání }

Uvedené konstanty jsou veřejnými konstantami jednotky Crt. Jejich identifikátory tedy mohou být ve zdrojových textech používány místo příslušných číselných literálů.

var TextAttr: Byte;

Aktuální atribut, používaný procedurami WriteWriteln. Na pozici atributu každého vypisovaného znaku ve videopaměti je procedurou Write resp. Writeln zapsána aktuální hodnota proměnné TextAttr. Počáteční hodnota proměnné je při startu programu inicializována hodnotou atributu znaku na aktuální pozici kurzoru. Protože se jedná o veřejnou proměnnou jednotky Crt, může být její hodnota změněna přímo, přiřazovacím příkazem. Například:

TextAttr := 226 { = 1 110 0100 binárně }
Od okamžiku provedení tohoto příkazu až do další změny hodnoty proměnné TextAttr budou všechny vypisované znaky barveny atributem 226, takže budou červené (0100b = 4), na hnědém pozadí (110b = 6) a blikající. Stejný přiřazovací příkaz lze zapsat i názorněji:
TextAttr := Red + Brown shl 4 + Blink
Barvu pozadí je nutno v hodnotě atributu posunout o čtyři bity výše (vlevo), což zajistí operátor shl (nebo vynásobení barvy pozadí šestnácti): 4 + 96 + 128 = 226.

Kromě přímé definice hodnoty proměnné TextAttr přiřazovacím příkazem lze aktuální barevný atribut měnit i pomocí veřejných procedur TextColor, TextBackGround, LowVideo, HighVideoNormVideo jednotky Crt.

procedure TextColor (Popredi: Byte);

Přepíše nejnižší čtyři bity proměnné TextAttr (aktuální barvu popředí) nejnižšími čtyřmi bity parametru Popredi a do nejvyššího bitu proměnné TextAttr (příznak blikání) vloží hodnotu 0 resp. 1, pokud parametr Popredi není resp. je větší než 15 (tedy pokud je každý ze čtyř vyšších bitů parametru roven nule resp. některý z nich není). Hodnoty ostatních bitů proměnné TextAttr (aktuální barva pozadí) zůstanou zachovány.

Příkaz TextColor (Red + Blink) například nastaví barvu popředí v proměnné TextAttr na hodnotu Red (červená) a příznak blikání na hodnotu 1 (blikání povoleno).

procedure TextBackGround (Pozadi: Byte);

Přepíše bity 4 až 6 proměnné TextAttr (aktuální barvu pozadí) nejnižšími třemi bity parametru Pozadi. Hodnoty ostatních bitů proměnné TextAttr (aktuální barva popředí a příznak blikání) zůstanou zachovány.

Příkaz TextBackGround (Brown) například nastaví barvu pozadí v proměnné TextAttr na hodnotu Brown (hnědá).

procedure LowVideo;

Nastaví nižší intenzitu barvy popředí nulováním bitu 3 proměnné TextAttr. Ostatní bity ponechá beze změny. Pokud má například aktuální barva popředí hodnotu LightRed (= 12 = 1100b), bude mít po volání procedury LowVideo hodnotu Red (= 4 = 0100b).

procedure HighVideo;

Nastaví vyšší intenzitu barvy popředí vložením hodnoty 1 do bitu 3 proměnné TextAttr. Ostatní bity ponechá beze změny. Pokud má například aktuální barva popředí hodnotu Red (= 4 = 0100b), bude mít po volání procedury HighVideo hodnotu LightRed (= 12 = 1100b).

procedure NormVideo;

Reinicializuje hodnotu proměnné TextAttr její hodnotou počáteční, tedy atributem znaku na aktuální pozici kurzoru při startu programu.

XIX.8. 

Ovládání pozice kurzoru

Výstup textu na obrazovku je směrován do aktuálního výstupního okna, na aktuální pozici kurzoru. Pomocí podprogramů jednotky Crt lze souřadnice aktuální pozice kurzoru v okně zjišťovat i měnit.

function WhereX: Byte;
function WhereY: Byte;

Hodnotou funkce WhereX resp. WhereY je horizontální resp. vertikální souřadnice aktuální pozice kurzoru v okně (pořadí sloupce od levého okraje okna resp. pořadí řádky od horního okraje okna).

Absolutní souřadnice pozice kurzoru na obrazovce lze získat jako součty relativní souřadnice a příslušného bytu proměnné WindMin. Vertikální absolutní souřadnice kurzoru je tedy hodnotou výrazu WhereY + Hi (WindMin) a horizontální absolutní souřadnice kurzoru hodnotou výrazu WhereX + Lo (WindMin).

procedure GotoXY (X, Y: Byte);

Přesune kurzor na pozici o relativních souřadnicích XY (sloupec, řádka). Pokud jsou zadané souřadnice neplatné (definují pozici mimo výstupní okno), nemá volání procedury GotoXY žádný efekt (původní pozice kurzoru zůstane zachována).

XIX.9. 

Editování textu v okně

Na rozdíl od standardního výstupu textu na obrazovku (chápanou jako obecný textový soubor) lze za použití jednotky Crt již vypsaný text v rámci výstupního okna editovat.

procedure ClrScr;

Smaže obsah aktuálního okna. Všechny pozice v okně jsou vyplněny znakem mezera a aktuálním atributem. Kurzor je přesunut do levého horního rohu okna.

procedure ClrEOL;

Smaže obsah aktuální řádky od pozice kurzoru včetně až po pravý okraj okna. Všechny uvedené pozice jsou vyplněny znakem mezera a aktuálním atributem. Pozice kurzoru je zachována.

procedure DelLine;

Smaže v okně řádku na pozici kurzoru. Obsah všech níže položených řádek roluje v okně o jednu pozici nahoru (původní obsah kurzorem označené řádky tedy zanikne) a všechny pozice poslední řádky okna jsou vyplněny znakem mezera a aktuálním atributem. Pozice kurzoru zůstane zachována.

procedure InsLine;

Vloží do okna prázdnou řádku na pozici kurzoru. Obsah kurzorem označené řádky a všech řádek níže položených (vyjma poslední) roluje v okně o jednu pozici dolů (původní obsah poslední řádky okna zanikne) a všechny pozice kurzorem označené řádky jsou vyplněny znakem mezera a aktuálním atributem. Pozice kurzoru zůstane zachována.


PŘÍKLAD: Následující program demonstruje některé prostředky jednotky Crt pro ovládání výstupu textu na obrazovku. Jeho základem je cyklus, v jehož těle se převezme znak z klávesnice a provede příslušná akce — kurzorovými šipkami a klávesou ENTER je řízen pohyb kurzoru uvnitř okna, ALT-kombinacemi kláves jsou voleny položky menu na poslední řádce obrazovky a ostatní generované znaky jsou vypisovány na aktuální pozici kurzoru (stisk neplatné funkční klávesy či ALT-kombinace je ignorován).

{======================================================================}
program CrtDemo;
{======================================================================}

 uses Crt;

 const AltC = #46;       AltW   = #17;        { použité Alt-kombinace  }
       AltD = #32;       Vlevo  = #75;        { a funkční klávesy      }
       AltE = #18;       Vpravo = #77;
       AltI = #23;       Nahoru = #72;
       AltQ = #16;       Dolu   = #80;
       AltR = #19;

 var   Key   : Char;                          { čtený znak             }
       Konec : Boolean;                       { indikace požadavku na  }
                                              { ukončení programu      }

 procedure Init;                              { počáteční inicializace }
 {-------------}

  const Normal = 6; Jas = 4; Podklad = 7;     { barvy menu             }

 begin { Init }
  TextMode(CO80);                             { 25 řádek x 80 sloupců  }
  Window(1, 25, 80, 25);                      { nastavení okna menu    }
  TextBackGround(Podklad);                    { výpis menu             }
  ClrScr;
  GotoXY(3, 1);
  TextColor(Jas);    Write('W');
  TextColor(Normal); Write('indow');
  TextColor(Jas);    Write('     R');
  TextColor(Normal); Write('andomText');
  TextColor(Jas);    Write('     C');
  TextColor(Normal); Write('lrScr     Clr');
  TextColor(Jas);    Write('E');
  TextColor(Normal); Write('OL');
  TextColor(Jas);    Write('     D');
  TextColor(Normal); Write('elLine');
  TextColor(Jas);    Write('     I');
  TextColor(Normal); Write('nsLine');
  TextColor(Jas); Write('     Q');
  TextColor(Normal); Write('uit');
  Window(1, 1, 80, 24);                       { počáteční nastavení    }
  NormVideo;                                  { demonstračního okna    }
  ClrScr                                      { a atributu             }
 end; { Init }

 procedure Okno;                              { nové demonstrační okno }
 {-------------}

  var Xl, Yh, Xp, Yd           : Byte;        { souřadnice okna        }
      Pozadi, Popredi, Blikani : Byte;        { aktuální barvy         }

 begin { Okno }
  Xl := Random(80) + 1;                       { náhodné souřadnice     }
  Xp := Random(81 - Xl) + Xl;
  Yh := Random(24) + 1;
  Yd := Random(25 - Yh) + Yh;
  Pozadi := Random(8);                        { náhodná barva pozadí   }
  repeat                                      { náhodná barva popředí  }
   Popredi := Random(16)
  until Pozadi <> Popredi;
  Blikani := Random(2);                       { náhodný příznak blikání}
  TextAttr := Popredi + Pozadi shl 4 + Blink; { definice atributu      }
  Window(Xl, Yh, Xp, Yd);                     { založení okna a výmaz  }
  ClrScr                                      { jeho obsahu            }
 end; { Okno }

 procedure RandomText;                        { výpis náhodných znaků  }
 {-------------------}                        { do stisku lib. klávesy }
 begin { RandomText }
  repeat
   Write(Chr(Random(256)))
  until KeyPressed
  { stiskem klávesy vygenerovaný znak zůstává nezpracován - bude po    }
  { návratu do příkazové části programu vyzvednut do Key a použit      }
 end; { RandomText }

begin { program }
 Init;                                        { inicializace           }
 Konec := False;
 repeat                                       { hlavní cyklus          }
  Key := ReadKey;                             { (čekání na) vstup znaku}
                                              { z klávesnice           }
  if Key = #0 then                            { funkční klávesa nebo   }
   begin                                      { ALT-kombinace          }
    Key := ReadKey;                           { rozlišovací znak       }
    case Key of                               { volba akce:            }
     Vlevo  : GotoXY(WhereX - 1, WhereY);     { - kurzor vlevo         }
     Vpravo : GotoXY(WhereX + 1, WhereY);     { - kurzor vpravo        }
     Nahoru : GotoXY(WhereX, WhereY - 1);     { - kurzor nahoru        }
     Dolu   : GotoXY(WhereX, WhereY + 1);     { - kurzor dolů          }
     AltW   : Okno;                           { - nové okno            }
     AltR   : RandomText;                     { - náhodný text         }
     AltC   : ClrScr;                         { - výmaz okna           }
     AltE   : ClrEOL;                         { - výmaz zbytku řádky   }
     AltD   : DelLine;                        { - zrušení řádky        }
     AltI   : InsLine;                        { - vložení řádky        }
     AltQ   : Konec := True                   { - požadavek ukončení   }
    end                                       {   programu             }
   end
  else                                        { obyčejná klávesa       }
   begin                                      { výstup generovaného    }
    Write(Key);                               { znaku do demonst. okna }
    if Key = #13 then Write(#10)              { když CR tak i LF       }
   end
 until Konec                                  { konec po stisku ALT+Q  }
end. { program }

XIX.10. 

Tónový generátor

Počítače třídy PC mají vestavěn jednoduchý tónový generátor. Pro jeho ovládání implementuje jednotka Crt procedury Sound (zapnutí, začátek tónu), Delay (čekání, trvání tónu) a NoSound (vypnutí, konec tónu). Tón je generován po celou dobu, po kterou je generátor zapnut, nezávisle na činnosti procesoru.

procedure Sound (Hz: Word);

Zahájí generování tónu. Hodnotou parametru Hz je požadovaná frekvence (výška) tónu v hertzích. Zadaný tón je trvale generován až do dalšího volání Sound (nový tón) nebo NoSound (konec tónu).

procedure NoSound;

Ukončí generování tónu — vypne generátor (pokud je již vypnut, nemá volání NoSound žádný efekt).

Každý program, který používá tónový generátor, by měl příkaz NoSound obsahovat ve své úklidové proceduře. Pokud by program skončil se zapnutým generátorem, bude zvuk generován dále (až do vypnutí počítače, restartu systému nebo spuštění programu, který generátor vypne).

Pro řízení délky tónu (doby mezi zapnutím a vypnutím generátoru) lze použít různých typů čekacích smyček — například čekání na stisk klávesy nebo cyklus s pevně zvoleným počtem průchodů. Zvláště vhodným prostředkem je procedura Delay, která umožňuje přesné nastavení délky tónu.

procedure Delay (MS: Word);

Zastaví výpočet programu na dobu, specifikovanou parametrem MS v milisekundách.


PŘÍKLAD: Program Sirena demonstruje použití tónového generátoru. Instalovaná úklidová procedura zajistí vypnutí generátoru při jakémkoliv ukončení běhu programu (mimo vývojové prostředí).

{======================================================================}
program Sirena;
{======================================================================}

 uses  Crt;

 const Min        = 600;        { parametry frekvenčního rozsahu       }
       Max        = 900;
       Rozsah     = Max - Min;

 var   Y          : Word;       { aktuální frekvenční přírustek        }
       DalsiKonec : Pointer;    { původní hodnota ExitProc             }

 procedure Konec; far;          { úklidová procedura programu          }
 {-------------------}
 begin { Konec }
  ExitProc := DalsiKonec;
  NoSound                       { vypnutí tónového generátoru          }
 end; { Konec }

begin { program }
 DalsiKonec := ExitProc;        { instalace úklidové procedury         }
 ExitProc := @Konec;
 Y := 0;                        { inicializace frekvenčního přírustku  }
 repeat                         { frekvenční cyklus                    }
  if Y <= Rozsah then           { lineární růst frekv. od Min do Max   }
   Sound(Min+Y)
  else                          { lineární pokles frekv. od Max do Min }
   Sound(Max + Rozsah - Y);
  Delay(50);                    { délka tónu                           }
  Y := (Y + 10) mod (2 * Rozsah){ aktualizace frekvenčního přírustku   }
 until KeyPressed               { do stisku klávesy                    }
end. { program }