Генерування звукових сигналів різної частоти за допомогою клавіатури
Для обробки і видачі звуків через динамік буде використовуватися програмування мікросхеми таймера. Всі ІBM PC використовують мікросхему таймера 8253 (чи 8254) для узгодження імпульсів від мікросхеми системного годинника. Число циклів системного годинника перетвориться в один імпульс, а послідовність цих імпульсів підраховується для визначення часу, чи вони можуть бути послані на гучномовець… Читати ще >
Генерування звукових сигналів різної частоти за допомогою клавіатури (реферат, курсова, диплом, контрольна)
Курсова робота
з дисципліни «Системне програмування»
на тему:
«Генерування звукових сигналів різної частоти за допомогою клавіатури «
ЗМІСТ Вступ
Розділ 1. Аналіз технічного завдання та методів його вирішення Розділ 2. Опис методики та алгоритму вирішення задачі
Розділ 3. Опис програми та аналіз отриманих результатів
Висновок
Список використаних джерел Додаток А
Додаток Б
ВСТУП Сучасне комп’ютерне програмне забезпечення перетворило персональні ПК у потужні обчислювальні машини, які здатні виконувати найрізноманітніші завдання. На даний момент існує безліч програм, які здатні задовольнити потреби користувачів у різних галузях науки та повсякденному житті: фізика, математика, графіка, економіка, бізнес тощо. Також у свою чергу розвивається програмне забезпечення, призначене для створення та написання музики.
На даний момент музичні програми здатні замінити навіть живі інструменти.
Завдання курсової роботи полягає в тому, щоб скласти програму яка здатна відтворювати системним динаміком звуки різної частоти. Основою цього програмування є програмування мікросхеми таймера 8253 або 8255.
Для розв’язання поставленої задачі вибрана мова програмування Асемблер, оскільки вона має досить потужний набір інструментів для того, щоб створювати не тільки звук, але й змінювати його надаючи йому певних відтінків і тонів.
Асемблерні програми можуть бути дуже ефективними. На Асемблері можна написати програму більш компактну і швидкодіючу ніж написану на мові високого рівня. Це дійсно так для невеликих або середніх програм. По мірі зростання розмірів, програми втрачають частину своїх переваг. Це відбувається через необхідність в Асемблерній програмі уваги до дрібниць. Мова Асемблер потребує від програміста планування кожної дії. В невеликих програмах це дозволяє оптимізувати роботу програми з апаратними засобами. У великих програмах величезна кількість деталей може перешкодити эффективно працювати над самою програмою, навіть якщо окремі компоненти програми виявляться дуже непоганими. Безумовно, програмування на мові Асемблера відповідає потребам не кожної програми. Програми на Асемблер дуже точні. Оскільки ця мова дозволяє програмісту безпосередньо працювати з всім апаратним забезпеченням. Поза сумнівом, що при програмуванні пристроїв вводу-виводу, де потрібен контроль над окремими розрядами регістрів пристрою, програмування на мові Асемблер — єдиний правильний вибір. Також програми написані на Асемблері можуть з'єднуватись із програмами, написаними на мовах високого рівня, що дозволяє оптимізувати останні.
РОЗДІЛ 1. АНАЛІЗ ТЕХНІЧНОГО ЗАВДАННЯ ТА МЕТОДІВ ЙОГО ВИРІШЕННЯ Завдання курсової роботи полягає в тому щоб відтворювати звуки заданої частоти. Розглядаючи вхідні дані ми можемо скласти такий їхній перелік: частота звуку, тривалість звуку. Частоту звуку можна в свою чергу розбити ще на приналежність його до певної музичної октави: мала, перша, друга, третя, та ін. Також окремим видом звуку можу бути і шум. Продумуючи програму був обраний шлях який полягає в тому що при натисканні певної клавіші на клавіатурі буде отриманий звук певної частоти, який буде відповідати частоті певної ноти (до, ре, мі, та ін.). Отже основним вихідним результатом має стати програний звук (нота) через системний динамік.
Для обробки і видачі звуків через динамік буде використовуватися програмування мікросхеми таймера. Всі ІBM PC використовують мікросхему таймера 8253 (чи 8254) для узгодження імпульсів від мікросхеми системного годинника. Число циклів системного годинника перетвориться в один імпульс, а послідовність цих імпульсів підраховується для визначення часу, чи вони можуть бути послані на гучномовець комп’ютера для генерації звуку визначеної частоти. Мікросхема 8253 має три ідентичних незалежних канали, кожний з який може програмуватися.
Мікросхема 8253 працює незалежно від процесора. Процесор програмує мікросхему і потім звертається до інших справ. У такий спосіб 8253 діє як годинник реального часу — вона рахує свої імпульси незалежно від того, що відбувається в комп’ютері. Однак, максимальний програмувальний інтервал складає приблизно1/12 секунди. Для підрахунку інтервалів часу в годин та хвилин потрібні якісь інші засоби. Саме з цієї причини імпульси від нульового каналу мікросхеми таймера накопичуються в перемінній, що знаходиться в області даних BІOS.
РОЗДІЛ 2. ОПИС МЕТОДИКИ ТА АЛГОРИТМУ ВИРІШЕННЯ ЗАДАЧІ
Генерація звуку за допомогою адаптера інтерфейсу з периферією 8255 складається у включенні і вимиканні з бажаною частотою біта порту B, що зв’язаний з динаміком (біт 1). Порт B має адреса 61H. Якщо програма переключає значення біта з максимально можливою частотою, то частота занадто висока, щоб бути потрібною. Тому між двома переключеннями треба вставляти порожній цикл. Пам’ятайте, що біт 0 порту B керує воротами каналу 2 мікросхеми таймера, що у свою чергу зв’язаний з динаміком. Тому цей біт повинний бути скинутий, від'єднуючись від каналу таймера.
Ми будемо використовувати той метод, який забезпечує відтворення звуку з іншими діями які відбуваються на РС. Ми використовуємо адрес порту мікросхеми 8255 який знаходиться по адресу 61Н, а для того щоб отримати звук нам потрібно послати число з потрібною частотою в канал 2 який знаходиться по адресу 42Н, а також після цього вимкнути динамік.
В ініціалізаційні частині - області програми, де описані змінні та константи містяться стрічки повідомлень:
slovo1 db 'Space-RESTART', 13,10,'$'
slovo2 db 'Enter-HELP', 13,10,'$'
slovo3 db 'Esc-EXIT', 13,10,'$'
mes db 'Matiyshun Yura$'
string db 'Vuberity trivalisty zvuchannya$'
string1 db 'Zvyk notu :$',
стрічки назв нот (n1 — n15).
not1 db 'DO$'
not2 db 'RE$'
not3 db 'MI$'
not4 db 'FA$'
not5 db 'SOL$'
not6 db 'LA$'
not7 db 'SI$'
not8 db 'DO1 $'
not9 db 'RE1 $'
not10 db 'MI1 $'
not11 db 'FA1 $'
not12 db 'SOL1 $'
not13 db 'LA1 $'
not14 db 'SI1 $'
not15 db 'DO2 $',
тривалості звучання нот:
t1 db '1 $'
t2 db '2 $'
t3 db '3 $'
t4 db '4 $'
t5 db '5 $'
t6 db '6 $',
та текст меню допомоги
help db ' Klavisha — Nota Klavisha — Nota', 13,10
db ' z — Do s — Do (verhnye)', 13,10
db ' x — Re d — Re (verhnye)', 13,10
db ' c — Mi f — Mi (verhnye)', 13,10
db ' v — Fa g — Fa (verhnye)', 13,10
db ' b — Sol h — Sol (verhnye)', 13,10
db ' n — La j — La (verhnye)', 13,10
db ' m — Si k — Si (verhnye)', 13,10,'$'
Також сюди входять змінні NOTE та DELAY.
NOTE dw ('?')
DELAY db ('?')
Ці змінні мають розмір відповідно два та один байт. У змінну NOTE під час виконання програми заноситься частота ноти, яка має програватись, а змінна DELAY призначена для зберігання часу тривалості звучання ноти. Після опису цих даних йде ініціалізація стеку розміром 128 байт:
.stack 128
Нижче розглянемо приклад отримання звуку певної частоти і певної тривалості:
IN AL, 61h — получаємо поточну адресу порту В
OR AL, 11B — дозволяємо таймер і динамік
OUT 61h, AL
Після цього встановлюємо режим для 2-го каналу. Керуюче слово пересилаємо у порт 43Н, який є командним регістром.
MOV AL, 0B6H
OUT 43h, AL
Після цього пересилаємо частоту ноти, яка знаходиться у змінній NOTE, у порт 42Н побайтово, використовуючи регістр AL.
MOV DX, NOTE
MOV AL, DL
OUT 42H, AL
MOV AL, DH
OUT 42H, AL
За допомогою функції 0Н переривання 1АН одержуємо значення лічильника, яке буде використовуватись для затримки звучання ноти. Далі змінну DELAY, у якій міститься час затримки звучання ноти, пересилаємо у регістр CL. Після цього заносимо молодший байт лічильника у регістр ВХ. Сумуємо його із даним часом затримки. Далі виконується переривання INT 1AH і у регістрі DX буде міститися текуче значення лічильника, яке перевіряється із вмістимим регістру BX.
MOV AH, 0
INT 1AH
MOV CL, DELAY
MOV CH, 0
MOV BX, DX
ADD BX, CX
PLAY:
INT 1AH
CMP DX, BX
Якщо вмістиме обох регістрів однакове, то відбувається вимкнення системного динаміка за допомогою команди AND AL, 0FCH і OUT 61H, AL, які пересилають керуюче слово у порт 61Н, чим у свою чергу вимикають системний динамік. Після цього завершується підпрограма міткою endp.
JNE PLAY
IN AL, 61H
AND AL, 0FCH
OUT 61H, AL
Алгоритм роботи програми можна описати такими пунктами:
1. Відображення на екрані текстового інтерфейсу
2. Вивід на екран повідомлення про можливість введення тривалості ноти
3. Читання коду клавіші яка натиснута
4. Перевірка на натиснення клавіш 1−6 (задання тривалості звучання ноти)
5. Якщо клавіша ESC з програми то до пункту 15
6. Якщо клавіша Enter то до пункту 14
7. Якщо клавіша Space 1
8. Читання коду клавіші яка натиснута
9. Перевірка на натиснення клавіш
10. Якщо клавіша ESC з програми то до пункту 15
11. Якщо клавіша Enter то до пункту 14
12. Якщо клавіша Space 1
13. Відтворення звуку після цього до пункту 2
14. Відображення на екрані інтерфейсу довідки, після натиску потрібної клавіші (ESC)переходимо на пункт 1
15. Вихід із програми Графічне відображення алгоритму роботи міститься в Додатку, А РОЗДІЛ 3. ОПИС ПРОГРАМИ ТА АНАЛІЗ ОТРИМАНИХ РЕЗУЛЬТАТІВ звук генерація інтерфейс клавіатура Дана програма призначена для роботи в текстовому режимі в операційній системі MS-DOS. Вона забезпечує програвання нот двох октав, використовуючи клавіатуру в якості емулятора клавіатури музичного інструмента. Також користувач за допомогою цифрових клавіш може керувати тривалістю звучання нот. Програма не вимоглива до апаратного забезпечення та ресурсів комп’ютера, містить надпростий зручний текстовий інтерфейс. Для завершення програми досить натиснути клавішу Esc.
Оскільки ми розробляємо програму яка програє звуки після того як буде нажата потрібна клавіша то ми вносимо потрібні функції які дають змогу зчитувати код натиснутої клавіші, була використана функція 7Н переривання 21Н.
mov ah, 7
int 21h
Очистка екрану від посторонніх символів здійснюється за допомогою переривання int 10h функції 6Н.
MOV AH, 6
MOV AL, 24
MOV CH, 0
MOV CL, 0
MOV DH, 24
MOV DL, 79
MOV BH, 9
INT 10H
Далі на екран виводяться повідомлення за допомогою переривання int 21h функції 9Н
mov dx, OFFSET string
mov ah, 9
int 21h
Для задання тривалості звучання ноти йде цілий блок порівняння вмістимого регістру із клавішами '1'…'6'. За допомогою команди cmp al, 49 порівнюється вмітиме регістра al із значенням 49. Якщо вони нерівні, то відбувається перехід на мітку наступного порівняння, якщо рівні - у змінну DELAY заноситься число, яке відповідає за тривалість звучання ноти.
cmp al, 49
jnz NEXT
mov DELAY, 1
NEXT:
Якщо код відповідає одній із натиснених клавіш, то у змінну DELAY відповідно заноситься певне значення тривалості звучання ноти. Якщо ж код не відповідає даним клавішам, то у змінну DELAY заноситься значення «6» .
Таким самим шляхом, ми зчитуємо наступну натиснуту клавішу, яка повинна відповідати певній ноті.
Таблиця 2.1 відповідності клавіш та нот
Клавіша | Нота звучання | Частота | |
z | DO | ||
x | RE | ||
c | MI | ||
v | FA | ||
b | SOL | ||
n | LA | ||
m | SI | ||
DO1 | |||
s | DO1 | ||
d | RE1 | ||
f | MI1 | ||
g | FA1 | ||
h | SOL1 | ||
j | LA1 | ||
k | SI2 | ||
l | DO2 | ||
cmp al, 'x'
JNZ GO_
mov dx, OFFSET n1
mov NOTE, 2300
jmp bym
GO_:
Якщо код клавіші співпав із кодом ноти, то при цьому у змінну NOTE заноситься частота звучання відповідної ноти mov NOTE, 2300, у регістр DX заноситься зміщення стрічки, яка є назвою ноти і буде відображатися на екрані і відбувається перехід на підпрограму опрацювання змінних NOTE та DELAY, тобто відбувається перехід на мітку BYM програвання даної ноти із даною затримкою звучання.
Якщо ж код клавіші не співпав із кодами нот та цифрами, то він перевіряється із кодом клавіші Esc.
cmp al, 27
jz EXIT
jmp CONTINUE
Якщо він співпав, то відбувається перехід на мітку завершення програми EXIT. Під час завершення відбувається очищення екрану та вивід повідомлення EXIT_MESSAGE і програма завершується. Якщо код клавіші не співпав із клавішею Esc, то відбувається перехід на мітку CONTINUE і все повторюється спочатку.
При натисненні додаткових клавіш програма виконує додаткові дії.
Так при натисненні клавіші «enter» викликається інформація меню HELP, в якому описано відповідність нажатої клавіші клавіатури та ноти яка повинна прозвучати. Порівняння і відображення довідки відбувається за допомогою
cmp al, 0dh
je help1
help1:
pov:
mov ah, 0
mov al, 2
int 10h
mov ah, 9h
mov dx, offset help
int 21h
poz 23,69
mov ah, 9
mov dx, offset slovo3
int 21h
mov ah, 7
int 21h
cmp al, 1bh
je znov
jmp pov
Повернутися в програму можна нажавши клавішу «esc», при натисненні будь-якої іншої клавіші довідка відображається знову.
Також при натисненні клавіші «space» основна програма запускається ще раз, тобто за допомогою мітки переходить на початок програми.
cmp al, 20h
je znov
Після вдалого запуску програми ви будете бачити вікно програми яке буде мати вигляд який представлений на рис. 3.1
Рис. 3.1
Користувач сам може задати тривалість звучання нот. На екран виводиться позначення ноти, яку натиснув користувач. У будь-який момент програми можна визвати інформаційну допомогу (Рис. 3.2) за допомогою клавіші Enter, ознайомившись з довідкою можна повернутися в попереднє меню натиснувши Esc; розпочати виконання програми заново, натиснувши клавішу Space; та вийти з програми натиснувши Esc.
Рис. 3.2
ВИСНОВКИ Результатом даної курсової роботи є створений програмний продукт на мові Асемблер який забезпечує можливість програвання звуків (нот) різної частоти. Вона містить зручний інтерфейс, використовує клавіатуру для програвання нот та системний динамік для їх озвучення. Забезпечує програвання двох октав з можливістю регулювання тривалості звучання ноти. Дана програма працює тільки під середовищем MS-DOS.
Якщо продовжувати модернізацію даної програми можна добитися різних результатів, наприклад можна запропонувати користувачеві вести порядок програвання звуків певної мелодії, яка запишеться в пам’ять і потім може бути програна, можна також вести звуки півтонів що теж дасть хороший результат. Впродовж всього програмування ми використовували безпосереднє програмування мікросхем 8253 та 8255.
Отже бачимо що мова Асемблер має потужний набір функцій для осягнення такої області культури як музика.
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ
1. Роберт Журден Справочник программиста персональных компьютеров типа IBM, 1992. — 541c.
2. К. Г. Финогенов. Самоучитель по системным функциям MS-DOS. — М.: «Малип», 1993. — 262с.
3. Зубков С. В. Assembler для DOS, Windows и UNIX. — М.:ДМК Пресс, 2000. — 608 с.
4.Орловский Г. В.
Введение
в архітектуру микропроцесора 80 386. Санкт-Петербург: ИНФОКОМ, 1992.-240с.
5.Юров В. Assembler. -СПб.:Питер, 2001.-624с
6. Юров В. Assembler. Практикум. Питер, 2006 г.- 400
7.Владислав Пирогов. Ассемблер для Windows — СПб.: БХВ-Петербург, 2002. — 896 с
8.Калашников О. А. Ассемблер? Это просто! Учимся программировать — БХВ-Петербург, 2005. — С. 374
9.Галисеев Геннадий Владимирович Ассемблер для Win 32. Самоучитель. — М.: «Діалектика», 2007. — С. 368.
10. http://www.codenet.ru/progr/dos/
ДОДАТОК, А БЛОК СХЕМА АЛГОРИТМУ ВИКОНАННЯ ПРОГРАМИ ДОДАТОК Б КОД ПРОГРАМИ
model small
.data
mes db 'PROHRAM$'
string db 'Vuberity trivalisty zvuchannya$'
string1 db 'Zvyk notu :$'
not1 db 'DO$'
not2 db 'RE$'
not3 db 'MI$'
not4 db 'FA$'
not5 db 'SOL$'
not6 db 'LA$'
not7 db 'SI$'
not8 db 'DO1 $'
not9 db 'RE1 $'
not10 db 'MI1 $'
not11 db 'FA1 $'
not12 db 'SOL1 $'
not13 db 'LA1 $'
not14 db 'SI1 $'
not15 db 'DO2 $'
t1 db '1 $'
t2 db '2 $'
t3 db '3 $'
t4 db '4 $'
t5 db '5 $'
t6 db '6 $'
SPACE db ' $'
slovo1 db 'Space-RESTART', 13,10,'$'
slovo2 db 'Enter-HELP', 13,10,'$'
slovo3 db 'Esc-EXIT', 13,10,'$'
help db ' Klavisha — Nota Klavisha — Nota', 13,10
db ' z — Do s — Do (verhnye)', 13,10
db ' x — Re d — Re (verhnye)', 13,10
db ' c — Mi f — Mi (verhnye)', 13,10
db ' v — Fa g — Fa (verhnye)', 13,10
db ' b — Sol h — Sol (verhnye)', 13,10
db ' n — La j — La (verhnye)', 13,10
db ' m — Si k — Si (verhnye)', 13,10,'$'
NOTE dw ('?')
DELAY db ('?')
.stack 128
.386
.code
mov ax,@data
mov ds, ax
poz macro x, y
mov ah, 2
mov bh, 0
mov dh, x
mov dl, y
int 10h
endm
znov:
MOV AH, 6
MOV AL, 24
MOV CH, 0
MOV CL, 0
MOV DH, 24
MOV DL, 79
MOV BH, 1
INT 10H
MOV AH, 2
MOV DH, 1
MOV DL, 22
MOV BH, 0
INT 10H
mov dx, OFFSET mes
mov ah, 9
int 21h
poz 23,69
mov ah, 9h
mov dx, offset slovo2
int 21h
poz 23,34
mov ah, 9h
mov dx, offset slovo1
int 21h
poz 23,1
mov ah, 9h
mov dx, offset slovo3
int 21h
MOV AH, 2
MOV DH, 3
MOV DL, 1
MOV BH, 0
INT 10H
mov dx, OFFSET string
mov ah, 9
int 21h
xor ax, ax
MOV AH, 2
MOV DH, 3
MOV DL, 40
MOV BH, 0
INT 10H
mov ah, 7
int 21h
push ax
cmp al, 0dh
je help1
cmp al, 1dh
je exit
cmp al, 49
jnz NEXT
mov DELAY, 1
mov dx, OFFSET t1
jmp print_t
NEXT:
cmp al, 50
jnz NEXT1
mov DELAY, 2
mov dx, OFFSET t2
jmp print_t
NEXT1:
cmp al, 51
jnz NEXT2
mov DELAY, 3
mov dx, OFFSET t3
jmp print_t
NEXT2:
cmp al, 52
jnz NEXT3
mov DELAY, 4
mov dx, OFFSET t4
jmp print_t
NEXT3:
cmp al, 53
jnz NEXT4
mov DELAY, 5
mov dx, OFFSET t5
jmp print_t
NEXT4:
cmp al, 54
mov DELAY, 6
mov dx, OFFSET t6
jmp print_t
print_t:
mov ah, 9
int 21h
MOV AH, 2
MOV DH, 5
MOV DL, 1
MOV BH, 0
INT 10H
mov dx, OFFSET string1
mov ah, 9
int 21h
CONTINUE:
xor ax, ax
MOV AH, 2
MOV DH, 5
MOV DL, 40
MOV BH, 0
INT 10H
mov ah, 7
int 21h
push ax
mov dx, offset SPACE
mov ah, 9
int 21h
MOV AH, 2
MOV DH, 5
MOV DL, 40
MOV BH, 0
INT 10H
pop ax
cmp al, 0dh
je help1
cmp al, 20h
je znov
cmp al, 'x'
JNZ GO_
mov dx, OFFSET not1
mov NOTE, 2300
jmp bym
GO_:
cmp al, 'c'
JNZ GO1_
mov dx, OFFSET not2
mov NOTE, 2031
jmp bym
GO1_:
cmp al, 'v'
JNZ GO2_
mov dx, OFFSET not3
mov NOTE, 1809
jmp bym
GO2_:
cmp al, 'b'
JNZ GO3_
mov dx, OFFSET not4
mov NOTE, 1709
jmp bym
GO3_:
cmp al, 'n'
JNZ GO4_
mov dx, OFFSET not5
mov NOTE, 1521
jmp bym
GO4_:
cmp al, 'm'
JNZ GO5_
mov dx, OFFSET not6
mov NOTE, 1353
jmp bym
GO5_:
cmp al, ','
JNZ GO6_
mov dx, OFFSET not7
mov NOTE, 1207
jmp bym
GO6_:
cmp al, '.'
JNZ GO7_
mov dx, OFFSET not8
mov NOTE, 1139
jmp bym
GO7_:
cmp al, 'd'
JNZ GO8_
mov dx, OFFSET not9
mov NOTE, 1015
jmp bym
GO8_:
cmp al, 'f'
JNZ GO9_
mov dx, OFFSET not10
mov NOTE, 905
jmp bym
GO9_:
cmp al, 'g'
JNZ GO10_
mov dx, OFFSET not11
mov NOTE, 854
jmp bym
GO10_:
cmp al, 'h'
JNZ GO11_
mov dx, OFFSET not12
mov NOTE, 760
jmp bym
GO11_:
cmp al, 'j'
JNZ GO12_
mov dx, OFFSET not13
mov NOTE, 676
jmp bym
GO12_:
cmp al, 'k'
JNZ GO13_
mov dx, OFFSET not14
mov NOTE, 603
jmp bym
GO13_:
cmp al, 'l'
JNZ GO14_
mov dx, OFFSET not15
mov NOTE, 569
jmp bym
GO14_:
cmp al, 's'
JNZ GO15_
mov dx, OFFSET not8
mov NOTE, 1139
jmp bym
GO15_:
cmp al, 27
jz EXIT
jmp CONTINUE
bym:
mov ah, 9
int 21h
call zvyk
jmp CONTINUE
help1:
pov:
mov ah, 0
mov al, 2
int 10h
mov ah, 9h
mov dx, offset help
int 21h
poz 23,69
mov ah, 9
mov dx, offset slovo3
int 21h
mov ah, 7
int 21h
cmp al, 1bh
je znov
jmp pov
EXIT:
mov ax, 4c00h
int 21h
zvyk proc
IN AL, 61h
OR AL, 11B
OUT 61h, AL
MOV AL, 0B6H
OUT 43h, AL
MOV DX, NOTE
MOV AL, DL
OUT 42H, AL
MOV AL, DH
OUT 42H, AL
MOV AH, 0
INT 1AH
MOV CL, DELAY
MOV CH, 0
MOV BX, DX
ADD BX, CX
PLAY:
INT 1AH
CMP DX, BX
JNE PLAY
IN AL, 61H
AND AL, 0FCH
OUT 61H, AL
ret
zvyk endp
end