# ASCII ovladač

Tento ovladač umožňuje přijímat a vysílat textové řetězce přes sériové rozhraní počítače. Řetězec je ukončen speciálním znakem nebo dvojicí znaků (terminator). Terminator není součástí řetězce. Při vysílání je k němu automaticky připojen. Při příjmu slouží jako detekce konce řetězce. Jako terminator můžete použít standardní znaky CR, LF nebo dvojici CRLF, popřípadě můžete zadat jiný libovolný znak nebo skupinu dvou znaků s kódy různými od NULL (0). Jméno souboru ovladače je 'ascdrv.dll'.

## Kanály ovladače

- kanál č.1 - stav čtení řetězce (input status)
- kanál č.2 - stav zápisu řetězce (output status)
- kanál č.3 - přijatý řetězec (input string)
- kanál č.4 - řetězec k vyslání (output string)
- kanál č.5 - zapnutí/vypnutí ovladače (driver on/off)
- kanál č.6 - podřetězec z přijatého řetězce (input string item)
- kanál č.7 - povolení příjmu řetězců (enable input)
- kanál č.8 - povolení vysílání řetězců (enable output)
- kanál č.9 - povolení kombinovaných řetězců (enable multistring)
- kanál č.10 - číselný kód znaku ze vstupní vyrovnávací paměti (character code from circle buffer)
- kanál č.11 - indikace naplnění vstupní vyrovnávací paměti (circle buffer full)
- kanál č.12 - vymazání vstupní vyrovnávací paměti (clear circle buffer)

Pro sledování stavu přijímače a vysílače jsou určeny 2 stavové kanály. Kanál č.1 udává stav přijímací linky, kanál číslo 2 udává stav vysílače. Další kanály slouží přímo pro předávání řetězců. Kanál č.3 obsahuje vstupní řetězec z linky, kanál č.4 je výstupní a slouží pro vyslání řetězce na linku, kanál č.6 je vstupní a vrací postupně podřetězce ze vstupního přijatého řetězce (sekvenční přístup). Při vysílání se na konec řetězce automaticky přidává ukončovací znak CR nebo LF nebo CRLF. Kanál č.5 umožňuje odpojit nebo zapnout komunikaci ovladače zápisem hodnoty false resp. true. To umožňuje např. spojení ovladače s ovladačem pro telefonní modem, kdy je třeba nejdříve navázat spojení a teprve potom předat řízení ovladači ASCDRV. Po inicializaci ovladače je komunikace zapnuta. Pracujeme-li s modemem, je třeba nejdříve komunikaci odpojit, např. v přístroji program se jménem startup zapíšeme na kanál č.5 hodnotu false. Přijme-li ovladač řetězec, nastaví kanál č.1 a zároveň generuje výjimku ovladače (driver exception). Oddělovací znaky pro separaci podřetězců (delimiter) a ukončovací znak (terminator) lze zvolit v souboru parametrů. Implicitní nastavení je CRLF. Pro individuální zablokování funkcí čtení a/nebo zápisu jsou určeny kanály č.7 (čtení) a č.8 (zápis). Hodnota true danou funkci povolí, hodnota false funkci zakáže. Implicitně jsou nastaveny hodnoty true, tzn. funkce čtení a zápis jsou povoleny.

Ovladač umožňuje pracovat s řetězci, které obsahují i netisknutelné znaky a hodnoty pro časové zpoždění mezi znaky (kombinované řetězce - multistring). Tato vlastnost se zapíná nebo vypíná zápisem logické hodnoty true nebo false do kanálu č.9. Netisknutelné znaky (kód 0 až 1FH) a hodnoty zpoždění jsou do řetězce vkládány jako dvouznakové konstanty v hexadecimální soustavě za patřičný prefix.

  # - prefix pro číselnou hodnotu znaku - 0 až FF
  ~ - prefix pro číselnou hodnotu zpoždění - 0 až FF odpovídá 0,01 až 2,55s

Číselná hodnota se musí zadávat v hexa tvaru a má délku 2 znaky. Má-li řetězec obsahovat znak # nebo ~, uvede se tento znak dvakrát.

Příklad řetězce, který začíná znakem 01H (SOH) a obsahuje text "DRIVER" a pak následuje zpoždění 0,5 sekundy:

      #01DRIVER~32

Přijímaná data se dále ukládají do zvláštní vyrovnávací paměti (max. délka 512 znaků), kterou můžete sekvenčně číst přes kanál č.10. Tento kanál postupně vrací kódy znaků z paměti (0 až 255). Nejsou-li ve vyrovnávací paměti žádná data, vrátí hodnotu -1. Paměť můžete vynulovat zápisem hodnoty true do kanálu č.12. Kanál č.11 vrací hodnotu true, je-li vyrovnávací paměť plná. V tomto případě se další znaky ztrácejí.

Hodnoty stavových kanálů (kanál č.1 a č.2)

Čtení
  0 - Žádná data
  1 - Vstupní řetězec přítomen
  2 - Time-out
Zápis
  0 - Připraven vysílat
  1 - Data se právě vysílají
  2 - Time-out

## Čtení dat

Při čtení dat je nejdříve nutno číst stav přijímací linky. Jakmile je hodnota tohoto kanálu rovna 1, můžete z kanálu č.3 přečíst řetězec. Při dalším čtení je vrácen prázdný řetězec, dokud nepřijde další. Je-li hodnota kanálu rovna 2, znamená to, že do určité doby nepřišel žádný řetězec a nastal time-out.

Jiný způsob pro čtení řetězce je zaregistrování výjimky ovladače některému přístroji (např. string _display nebo program atd.). Tento přístroj je pak přímo aktivován příchodem textového řetězce do ovladače. Další výjimka ovladače může být vygenerována až po vyčtení celého řetězce (kanál č.3) nebo postupným vyčtením jeho podřetězců (kanál č.6). V případě, že se po příchodu výjimky řetězec nepřečte, budou další přijaté řetězce ukládány do fronty. Při zpracování výjimky ovladače procedurou nesmí dojít k jejímu přerušení například příkazy yield, pause, wait, if apod. Nejlepším způsobem, jak výjimku ošetřit, je použít příkaz send v této proceduře a čtení kanálů ovladače přesunout až do další procedury, která se takto zavolá.

Pro snadnější dekódování přijaté zprávy můžete využít kanálu č.6, který postupně vrací podřetězce z přijatého řetězce. Podřetězcem se rozumí skupina znaků oddělená mezerou popřípadě jinými znaky definovanými parametrem delimiter. Délka podřetězce není pevně stanovena a může být maximálně 255 znaků. Dosáhne-li se při čtení konce řetězce, ovladač vrátí definovaný podřetězec definovaný parametrem term_string (implicitně '$$$'). Další výjimka ovladače se povolí až při vyčtení řetězce nebo všech podřetězců jedné zprávy. To zabrání ztrátě dat v okamžiku, kdy systém nestačí zpracovat aktuální výjimku a přijde další řetězec. V případě, že připojené zařízení vysílá data nepřetržitě, může dojít k vygenerování výjimky ještě před spuštěním aplikace. Tato výjimka není zpracována, a proto je nutno při startu aplikace (např. program se jménem startup) vyčíst kanál č.3. Tím dojde k povolení další výjimky ovladače a aplikace bude korektně pracovat.

## Zápis dat

Při zápisu je třeba nejdřív otestovat stav vysílače. Je-li hodnota rovna 0, můžete zapsat řetězec do výstupního kanálu. Hodnota 1 signalizuje, že data se právě vysílají. Vrátí-li stavový kanál hodnotu 2, znamená to, že se do požadované doby nepodařilo odvysílat řetězec.

## Mapovací soubor ovladače

Standardní tvar mapovacího souboru 'ascdrv.dmf' je následující:

      begin
         1  real input
         2  real input
         3  string input
         4  string output
         5  boolean output
         6  string input
         7  boolean output
         8  boolean output
         9  boolean output
        10  real input
        11  boolean input
        12  boolean output
      end.

## Parametrický soubor ovladače

Soubor parametrů slouží ke konfiguraci ovladače a zadává se při definici ovladače. Jde o textový soubor, který můžete upravovat běžným textovým editorem. Standardně má jméno 'ascdrv.par', ale můžete si zvolit jakékoliv jiné jméno.

Syntax zápisu parametrů odpovídá INI standardu, a proto jsou jednotlivé parametry soustředěny podle významu do různých sekcí. Sekce [ascdrv] obsahuje konfigurační parametry ovladače, sekce [comm] obsahuje parametry pro nastavení sériového portu.

Seznam parametrů sekce [ascdrv]:

  com_driver
  terminator
  delimiters
  term_string
  readback
  disable_o_term
  ena_multi_str
  init_disable

Význam parametrů sekce [ascdrv]:

Parametr com_driver definuje jméno ovladače sériového rozhraní a jméno komunikačního portu. Pro standardní rozhraní počítače 'COM1' až 'COM4' je použit systémový ovladač 'cwcomm.dll' a 'COM1' až 'COM4'.

Příklad:

      com_driver = cwcomm.dll com2

Parametr terminator slouží k nastavení ukončovacího znaku (skupiny) řetězce. Povolená klíčová slova jsou:

      CR
      LF
      CRLF

nebo číselný kód ukončovacího znaku. Při zadávání v hexa tvaru se musí ukončit znakem "H". Je-li zadán kód větší než 255 (0FFH), bude oddělovač tvořen dvěma znaky v pořadí vyšší byte, nižší byte. V tomto případě je vhodné zadávat hodnotu oddělovače v hexa tvaru.

Příklad:

      terminator = 1003H

Oddělovač bude tvořen kombinací znaků DLE(10H) a ETX(03H) v pořadí: DLE, ETX.

Poznámka: Není dovoleno používat znak 0 ani jako oddělovač ani jako součást přenášeného řetězce.

Parametr delimiters slouží k definování množiny oddělovačů pro čtení podřetězců. Standardním oddělovačem je vždy znak mezera (kód 20H) a další znaky se mohou uvést za toto klíčové slovo (viz příklad souboru parametrů).

Parametr term_string slouží k definování řetězce, kterým ovladač signalizuje dosažení konce při postupném vyčítání kanálu č.6. Implicitní nastavení je '$$$'. Tento řetězec není součástí přijaté zprávy !

Parametr readback slouží k potlačení zpráv, které při vysílání přicházejí zpět do ovladače, je-li použita komunikace po RS-485 nebo proudové smyčce a daný převodník nemá možnost tuto vlastnost zablokovat.

Parametr disable_o_term potlačí přidání terminátoru k vysílanému řetězci

Parametr ena_multi_str zapíná vlastnost zpracování kombinovaných řetězců (podobně jako zápis do kanálu č.9).

Parametr init_disable uvede ovladač po spuštění aplikace do vypnutého stavu.

Nastavení parametrů komunikace

Nastavení parametrů komunikace je závislé na použitém ovladači linkové vrstvy. Samotný ovladač ASCDRV představuje protokolovou vrstvu, kterou je možné navázat na vrstvu linkovou, která realizuje skutečný transport dat. V systému Control Web lze provozovat několik ovladačů ASCDRV současně nad jednou linkovou vrstvou a tedy i jedním výstupním zařízením. Pokud ovladač ASCDRV používá standardní ovladač linkové vrstvy sériového rozhraní 'cwcomm.dll', je nutno do souboru parametrů uvést sekci [comm]. V ní můžete buď definovat přímo parametry sériové komunikace nebo uvést odkaz (přesměrovaní) na konfigurační soubor s parametry sériové komunikace.

V případě přesměrování obsahuje sekce [comm] pouze jediný parametr - file:

      [comm]
      file=c:\cw\par\comm.par

Struktura parametrů linkové vrstvy CWCOMM:

[comm] sekce:
  file* = <filename>
  device* = <device_name>
[<device_name>] sekce - pokud je definován parametr device a existuje sekce jména <device_name>, budou konfigurační parametry přednostně získány z této sekce, jinak budou použity parametry následující v této sekci [comm]
  priority* = idle | low | below_normal | normal** | above_normal | high | realtime
  mode* = fullduplex** | halfduplex
  pre_key* = <number>
  hold_key* = <number>
  rx_frame_buffer = <number>
  tx_frame_buffer = <number>
  rx_buffer* = <number> (4096**)
  tx_buffer* = <number> (4096**)
  baudrate = <number>
  databits = <number>
  stopbits = one | 1 | oneandhalf | 1.5 | two | 2
  parity = none | no | even | mark | odd | space
  cts_flow = true | false
  dsr_flow = true | false
  dtr_control = disable | low | enable | high | handshake | toggle | toggle_neg
  rts_control = disable | low | enable | high | handshake | toggle | toggle_neg
  dsr_sense = low | high
  tx_continue_xon_xoff* = true | false**
  tx_xon_xoff* = true | false**
  rx_xon_xoff* = true | false**
  xon_tresh* = <number> (50% of buffer capacity**)
  xoff_tresh* = <number> (80% of buffer capacity**)
  error_xlat* = true | false**
  discard_null* = true | false**
  xon_char* = <number>
  xoff_char* = <number>
  err_char* = <number>
  eof_char* = <number>
  evt_char* = <number>
  rx_interchar_timeout = <number>
  rx_char_timeout = <number> | 0
  rx_timeout = <number> | 0
  tx_char_timeout = <number> | 0
  tx_timeout = <number> | 0

Poznámka: * -- parametr je nepovinný; ** -- implicitní hodnota

Popis jednotlivých parametrů:
  file ... soubor parametrů. Tento parametr je výhodné použít v případech, kdy více ovladačů používá jedinou linkovou vrstvu. Parametry lze potom udržovat v jediném souboru.
  device ... jméno zařízení, například COM1. Pokud je tento parametr uveden, bude použito zařízení tohoto jména. Pokud zároveň existuje sekce stejného jména, budou následující parametry získány z této sekce. Pokud sekce tohoto jména neexistuje, parametry jsou načteny z aktuální sekce [comm].
  priority ... priorita komunikačního threadu
  mode ... režim činnosti (obousměrná/jednosměrná komunikace)
  pre_key ... určuje prodlevu před zahájením přenosu; stav signálů DTR/RTS, pokud pracují v toggle módu, je po dobu prodlevy již změněn na aktivní
  hold_key ... určuje prodlevu po ukončení přenosu; signály DTR/RTS, pokud pracují v toggle módu, zůstávají po tuto dobu prodlevy ještě aktivní
  rx_frame_buffer ... velikost sekundárního bufferu pro vstup; přípustný rozsah <96;65535>, parametr nemá implicitní hodnotu
  tx_frame_buffer ... velikost sekundárního bufferu pro výstup; přípustný rozsah <96;65535>, parametr nemá implicitní hodnotu
  rx_buffer ... velikost bufferu pro vstup; range <96;65535>, implicitně 4096
  tx_buffer ... velikost bufferu pro výstup; range <96;65535>, implicitně 4096
  baudrate ... komunikační rychlost
  databits ... počet data bitů
  stopbits ... počet stop bitů
  parity ... parita
  cts_flow ... povoluje CTS řízení (handshake)
  dsr_flow ... povoluje DSR řízení (handshake)
  dtr_control ... chování DTR
  rts_control ... chování RTS
  dtr_control & rts_control = význam hodnot:
    disable - řízení vypnuto, trvale v "low"
    low - stejně jako disable
    enable - řízení vypnuto, trvale v "high"
    high - stejně jako enable
    handshake - pozitivní handshake
    toggle - signál mění stav během přenosu dat na "high" (pozitivní klíč), jinak trvale v "low"
    toggle_neg - signál mění stav během přenosu dat na "low" (negativní klíč), jinak trvale v "high"
  Chování DTR/RTS v módech toggle/toggle_neg je znázorněno v následujícím schématu:
  dsr_sense ... určuje, je-li DSR aktivní v "high" nebo v "low" (high = pozitivní handshake, low = negativní handshake)
  tx_continue_xon_xoff ... povoluje zastavení vysílání pokud je vstupní buffer plný a byl vyslán znak XOFF (xoff_char). Pokud je nastaveno true, vysílání pokračuje od okamžiku, kdy je ve vstupním bufferu nejméně xoff_tresh znaků volných a ovladač vyslal XOFF znak (xoff_char) pro přibrždění příjmu. Pokud je nastaveno false, vysílání nepokračuje do okamžiku než je ve vstupním bufferu alespoň xon_tresh znaků volných a ovladač vyslal XON znak (xon_char) pro obnovení příjmu.
  tx_xon_xoff ... povoluje XON/XOFF (software) řízení pro výstup
  rx_xon_xoff ... povoluje XON/XOFF (software) řízení pro vstup
  xon_tresh ... minimální volná kapacita vstupního bufferu pro vyslání XON
  xoff_tresh ... ovlivňuje maximální počet znaků ve vstupním bufferu pro vyslání XOFF. Maximální počet přípustných znaků lze spočítat odečtením uvedené hodnoty od velikosti vstupního bufferu (rx_buffer)
  error_xlat ... povoluje nahrazení znaků přijatých s chybou parity znakem err_char. Pokud je nastaveno true a kontrola parity povolena, dochází k nahrazení.
  discard_null ... povoluje odstranění prázdných (NULL) znaků. Pokud je nastaveno true, každý NULL znak je ihned po přijetí odstraněn ze vstupního bufferu
  xon_char ... dekadický kód znaku XON
  xoff_char ... dekadický kód znaku XOFF
  err_char ... dekadický kód znaku, který je určen pro nahrazení znaků přijatých s chybou parity
  eof_char ... dekadický kód znaku EOF
  evt_char ... dekadický kód znaku EVT
  rx_interchar_timeout ... meziznaková prodleva pro příjem v milisekundách
  rx_char_timeout ... prodleva na jeden přijatý znak v milisekundách
  rx_timeout ... konstantní prodleva pro příjem v milisekundách
  Upozornění: Parametry rx_interchar_timeout, rx_char_timeout a rx_timeout ovlivňují propustnost na vstupu. Zvýšením hodnoty rx_timeout lze dosáhnout zvýšení efektivity pro rozsáhlé přenosy dat (pozor na kapacitu vstupního bufferu!), ale dojde také k prodloužení prodlev při příjmu separátních bloků dat. Nulové hodnoty parametrů způsobí nastavení optimálních hodnot podle parametrů komunikace.
  tx_char_timeout ... prodleva na vyslání jednoho znaku v milisekundách
  tx_timeout ... konstantní prodleva pro vysílání v milisekundách
  Upozornění: Parametry tx_char_timeout a tx_timeout ovlivňují propustnost na výstupu. Zvýšením hodnot lze docílit vyšší efektivity pro rozsáhlé přenosy dat, zvláště při povoleném handshake. Příliš malé hodnoty mohou způsobit problémy při vysílání, včetně potenciálně velkého počtu neúspěšných pokusů o vyslání. Nulové hodnoty parametrů způsobí nastavení optimálních hodnot podle parametrů komunikace.

Příklad souboru parametrů ovladače ASCDRV:

      [comm]
      baudrate = 9600
      parity = no
      databits = 8
      stopbits = 1
      rx_buffer = 128
      tx_buffer = 128
      rx_frame_buffer = 128
      tx_frame_buffer = 128
      cts_flow = false
      dsr_flow = false
      dtr_control = enable
      rts_control = disable
      dsr_sense = high
      rx_interchar_timeout = 50
      rx_char_timeout = 20
      rx_timeout = 50
      tx_char_timeout = 20
      tx_timeout = 50

      [ascdrv]
      com_driver = cwcomm.dll, com2
      terminator = cr
      delimiters = ,.;:
      term_string = @@
      readback = true
      disable_o_term = true
      ena_multi_str = true

## Nativní procedury ovladače

Některé parametry ovladače můžete měnit pomocí nativní procedury

system.DriverQueryProc( DriverName : string; DrvParam1 : any; &DrvParam2 : any )

kde DriverName je symbolické jméno ovladače, definované v aplikaci, DrvParam1 a DrvParam2 jsou obecné parametry procedury. DrvParam1 slouží k zadání povelu a DrvParam2 může být použit jako doplňující parametr nebo návratová hodnota. Povely (parametr DrvParam1) se zadávají jako textové řetězce.

Jednotlivé hodnoty DrvParam1 jsou:

  get_version - DrvParam2 vrátí řetězec s označením verze ovladače
  driver_enable - povel uvede ovladač do aktivního stavu
  driver_disable - povel vypne ovladač
  input_enable - povel zapne možnost čtení dat ze sériového portu, v případě, že je ovladač aktivní
  input_disable - povel vypne možnost čtení dat ze sériového portu
  output_enable - povel zapne možnost zápisu dat na sériový port, v případě, že je ovladač aktivní
  output_disable - povel vypne možnost zápisu dat na sériový port

Příklad:

      system.DriverQueryProc( 'ASCIIDriver', 'driver_enable', 0 );

V okně ovladače můžete sledovat přijaté a odeslané řetězce.

Okno ovladače ASCDRV