Апаратно–програмний комплекс GSM-МТМ

Обґрунтування побудови апаратно-програмного комплексу, вибір апаратних та програмних засобів та введення комплексу в дію. Опис основних сервісних функцій мобільних телефонів стандарту GSM. Створення програми для ведення статистики використання комплексу.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык украинский
Дата добавления 07.06.2010
Размер файла 830,9 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

N = 30*1*30(2,88-1,28) = 1440 (грн/міс)

Зрозуміло, що при підключенні до комплексу мобільного телефону з іншим стартовим пакетом, сума заощаджених коштів буде іншою.

5.2 Розрахунок собівартості програмного комплексу

Основним завданням техніко-економічного обгрунтування дипломного проекту є визначення величини економічного ефекту від використання основних та другорядних результатів, які одержані в даній дипломному проекті. Оцінка ефективності прийнятого рішення повинна бути комплексною і враховувати всі його аспекти.

Проведемо оцінку витрат праці на розробку програмного забезпечення для комплексу, при цьому виходимо з того, що розмір вихідного тексту запису алгоритму і даних в основному визначає затрати праці та час розробки програмного продукту:

де -- кількість вихідних команд в тисячах.

В якості вихідної команди приймаємо рядок програми. Загальний об'єм вихідного тексту програм складає приблизно 1800 рядків. Тоді:

Продуктивність праці розробників програмного забезпечення визначається наступним чином:

Тоді ми отримуємо, що продуктивність праці розробників:

277,8

Час необхідний для розробки програмного продукту, можна визначити за формулою:

де -- строк розробки програмного продукту;

-- коефіцієнт вірності постановки завдання;

-- час розробки алгоритму;

-- час настройки та тестування;

-- час на підготовку тексту;

-- час на розробку документації.

Останні величини обчислюються по наступним формулам:

де К -- залежить від ступеня підготовки програміста;

-- кількість рядків програми (в тис.).

Підставляємо значення в останні формули враховуючи, що К=0,8 (стаж роботи до 2-х років).

Тоді час, який необхідний для розробки програмного продукту дорівнює:

Визначимо собівартість години роботи ПК. Для цього розраховуються поточні витрати на експлуатацію комп'ютера. До їх складу включаються витрати на електроенергію і амортизаційні відрахування на реновацію від вартості комп'ютера та інше.

Витрати на електроенергію визначають множенням витрати електроенергії за одну годину на вартість 1 кВт/год електроенергії і на час роботи комп'ютера за рік. Час роботи комп'ютера за рік визначається множенням кількості робочих днів у рік на час роботи комп'ютера за день:

де -- середня кількість робочих днів у рік.

Середня кількість робочих днів у рік буде рівна:

Тоді, час роботи ПК за рік дорівнює:

Витрати енергії визначаються за формулою:

де -- витрати електроенергії за одну годину;

-- вартість 1 кВт/год електроенергії;

-- час роботи комп'ютера за рік.

Тоді витрати енергії складають:

Амортизаційні відрахування визначаються множенням вартості комплекса на норму амортизаційних відрахувань 10%:

Річна заробітна плата обслуговуючого персоналу (бугалтера, що буде обробляти інформацію про дзвінки 200 грн.) складає:

Відрахування на соціальне страхування, складають 3% від загальної заробітної плати за рік:

Вартість витрачених матеріалів складає 2% від вартості обчислювальної техніки:

Утримання на ремонт приміщень, в яких знаходяться засоби обчислювальної техніки, складає 3% від вартості обчислювальної техніки:

Кількість комплексів, що реалізовують зв'язок:

Собівартість години роботи на комп'ютері визначається наступним співвідношенням:

Підставляємо значення в останню формулу й отримаємо:

Рахуємо прямі витрати на виконання дипломної роботи, які визначаються наступним добутком:

де -- собівартість години роботи на комп'ютері;

-- час необхідний для розробки програмного продукту.

Підставляємо значення й одержуємо:

Накладні витрати, що включають витрати на освітлення, опалення і т. п. приймаються в розмірі 40-50% від суми прямих витрат:

Загальні витрати на виконання дипломної роботи:

Підставляємо дані й одержуємо:

Визначення ціни на програмний продукт визначається наступним співвідношенням:

де В -- витрати на виконання дипломного проекту;

P -- рівень рентабельності, в нашому випадку P = 30;

K -- коефіцієнт, що залежить від науково-технічного рівня, в нашому випадку К = 1,1.

Підставляємо ці значення й отримаємо ціну програмного продукту, яка дорівнює:

Річний економічний ефект від програми обробки дзвінків визначається за наступною формулою:

де: -- витрати на розв'язання задачі традиційними методами;

-- періодичність розв'язку задачі, для нашого випадку T = 12;

-- приведені витрати.

Для визначення параметру використовується наступна формула:

де: -- трудомісткість на обробки дзвінків з комплексу, вимірюється в годинах;

-- заробітна плата виконавця за одну годину.

Підставляємо значення в останню формулу й одержуємо:

Для визначення параметру використовується наступна формула:

де: -- загальний об'єм вихідного тексту програмного додатка;

-- собівартість години роботи на комп'ютері;

-- продуктивність праці розробників програмного забезпечення;

-- нормативно-галузевий коефіцієнт ().

-- ціна програмного продукту.

Отже приведені витрати дорівнюють:

Тоді річний економічний ефект дорівнює:

6. Охорона праці

6.1 Загальні положення

Охорона праці - система законодавчих актів, соціально-економічних, організаційно-технічних, гігієнічних і лікувально-профілактичних заходів та засобів, що забезпечують безпеку, збереження здоров'я та працездатність людини в процесі роботи.

Все різноманіття нормативних документів, що включають поняття охорони праці, за яких виключено або значно послаблено вплив на працюючих шкідливих та небезпечних факторів трудового середовища.

6.2 Експлуатація комплексу у автономному режимі

Вміст шкідливих речовин, не попвинен перевищувати концентрацій, вказаних у переліку “Предельно допустимых концентраций загрязняющих веществ в атмосферном воздухе населенных мест” №3086-84 від 27.08.84р. Для озону концентрація не повинна перевищувати 0.03 мг/м3. Температурні норми повинні бути від 100 до 250. Приміщення де експлуатується комплекс не повинно бути запилене, вологість повітря не більше 55%. Комплекс необхідно розміщувати щонайменьше за два метри від робочого місця оператора, або в окремій кімнаті.

6.3 Електромагнітне випромінювання та поля від ЕОМ

ЕОМ з моніторами на основі електронно-променевих трубок є джерелом кількох видів електромагнітного випромінювання, зокрема мікрохвиль нетеплової інтенсивності. Види випромінювання:

рентгенівське випромінювання;

оптично випромінювання;

високочастотні електромагнітні поля;

низькочастотні електромагнітні поля;

електростатичні поля (ГОСТ 12.1045-84);

іонізуюче випромінювання;

випромінювання та поля радіочастотного діапазону (регламентуються ГОСТ 12.1.006.-84).

6.4 Шум, пов'язаний з ВДТ

ЕОМ є потенційним джерелом цілого ряду звуків, що містять як коливання, які можна почути, так і коливання ультразвукового діапазону. Цей шум справляє негативний вплив на функціональний стан користувача.

Відомо, що шум несприятливо діє на людину, особливо, при довготривалому впливі. У користувача, діяльність якого пов'язана з переробкою інформації, що часто супроводжується елементами творчості, це виражається у зниженні розумової працездатності (наприклад, швидкість обробки тексту зменшується на 10-15%, зростає кількість помилок), у прискореному розвитку зорового стомлення, підвищенні витрати енергії (на 17%), появі головного болю, розвитку безсоння, послаблення уваги та ін.

Вимірювання шуму на робочих місцях здійснюється згідно ГОСТ 12.1.050-86 та ГОСТ 23941-79.

Згідно ГОСТ 12.1.003-83 шум у приміщенні, де виконують роботу, пов'язану з виробленням концепцій, створення нових програм, творчістю, не повинен перевищувати 40 дБА. Під час виконання операторської та близької до неї діяльності рівень шуму не повинен перевищувати 65 дБА.

6.5 Параметри освітлення робочого місця та робочого приміщення

Невикористовуване рентгенівське випромінювання, а також випромінювання в ультрафіолетовому, інфрачервоному та радіочастотному діапазонах повинні відповідати гігієнічним нормам згідно з ГОСТ 12.2.003-74, ГОСТ 12.3.002-75, ГОСТ 12.1.006-84.

Згідно з тимчасовими санітарними нормами і правилами для працівників обчислювальних центрів № 4559-88 освітлення в приміщення з ЕОМ має бути змішаним (природним і штучним). Доцільно, щоб орієнтація світлових отворів для приміщень з ЕОМ була на північ. Природне освітлення повинно здійснюватись у вигляді бічного освітлення і відповідати нормальним рівням за санітарними нормами і правилами 11-4-79 “Природне і штучне освітлення. Норми проектування”.

6.6 Температура і вологість у приміщенні

Як оптимальні мікрокліматичні параметри прийнято вважати такі, що при тривалому та систематичному впливі на людину забезпечують збереження нормального функціонального та теплового стану організму без напруження реакцій терморегуляції, створюють відчуття теплового комфорту та є передумовою збереження високого рівня працездатності.

За даними ВООЗ, оптимальні значення температури повітря у приміщенні становлять 19-23% ?С. Рекомендується відносна вологість повітря 55%. Швидкість руху повітря не повинна перевищувати на рівні обличчя 0.1 м/с.

6.7 Організація робочого місця

Робоче місце (РМ) - це обладнаний технічними засобами (засобами відображення інформації, органами управління, допоміжним обладнанням) простір, де здійснюється діяльність виконавця (або групи виконавців).

Удосконалення організації РМ є однією з умов, що сприяють підвищенню продуктивності праці, тому питанню організації РМ необхідно приділити особливу увагу. За літературними даними, при правильній організації РМ продуктивність праці, операторів ЕОМ від 8 до 20%.

Основним обладнанням робочого місця користувача ЕОМ є монітор, клавіатура, робочий стіл, стілець (крісло); допоміжним - пюпітр, підставка для ніг, шафи, полиці та ін. Вимоги до них відображені у нормативних документах: ВСПиПРВЦ; ГОСТ 12.2.032-78; ГОСТ 22269-76.

Робочі місця з ЕОМ повинні розташовуватися на відстані не менше як 1.5 м від стіни з віконними прорізами, від інших стін - на відстані 1м, між собою на відстані не менше 1.5 м. При розміщенні робочих місць необхідно виключити можливість прямого засвічування екрана джерелом природного освітлення. Джерело природного освітлення (вікно) не повинно також потрапляти в зону прямого спостереження користувача.

При розміщенні ЕОМ на робочому місці потрібно забезпечити простір для користувача величиною не менше як 850 мм з урахуванням виступаючих частин обладнання та застосування (при необхідності) спецодягу. Для стіп має бути передбачено простір по глибині та висоті не менше 150 мм, по ширині - не менше як 530 мм.

При розміщенні робочих місць з відеотерміналами та персональними ЕОМ необхідно забезпечити виконання наступних вимог:

робочі місця з відеотерміналами та персональними ЕОМ розміщуються на відстані не менше 1 м від стін зі світловими прорізами;

відстань між бічними поверхнями відеотерміналів має бути не меншою за 1,2 м;

відстань між тильною поверхнею одного відеотермінала та екраном іншого не повинна бути меншою 2,5 м;

прохід між рядами робочих місць має бути не меншим 1 м.

Вимоги цього пункту щодо відстані між бічними поверхнями відеотерміналів та відстані між тильною поверхнею одного відеотерміналу та екраном іншого враховуються також при розміщенні робочих місць з відеотерміналами та персональними ЕОМ в суміжних приміщеннях, з урахуванням конструктивних особливостей стін та перегородок.

Конструкція робочого місця користувача відеотерміналу (при роботі сидячи) має забезпечувати підтримання оптимальної робочої пози з такими ергономічними характеристиками: ступні ніг -- на підлозі або на підставці для ніг; стегна - в горизонтальній площині; передпліччя - вертикально; лікті -- під кутом 70 -- 90 град. до вертикальної площини; зап'ястя зігнуті під кутом не більше 20 град. відносно горизонтальної площини, нахил голови -- 15 - 20 град. відносно вертикальної площини.

Якщо користування відеотерміналом та персональною ЕОМ є основним видом діяльності, то вказане обладнання розміщується на основному робочому столі, як правило, з лівого боку.

Якщо використання відеотерміналу та персональної ЕОМ є періодичним, то устаткування, як правило, розміщується на приставному столі, переважно з лівого боку від основного робочого столу. Кут між поздовжніми осями основного та приставного столів має бути 90--140 град.

Висота робочої поверхні столу для відеотерміналу має бути в межах 680--800 мм, а ширина -- забезпечувати можливість виконання операцій в зоні досяжності моторного поля.

Рекомендовані розміри столу: висота -- 725 мм, ширина -- 600--1400 мм, глибина -- 800 -- 1000 мм.

Робочий стіл для відеотерміналу повинен мати простір для ніг висотою не менше 600 мм, шириною не менше 500 мм, глибиною на рівні колін не менше 450 мм, на рівні витягнутої ноги - не менше 650 мм.

Робочий стіл для відеотерміналу, як правило, має бути обладнаним підставкою для ніг шириною не менше 300 мм та глибиною не менше 400 мм, з можливістю регулювання по висоті в межах 150 мм та кута нахилу опорної поверхні -- в межах 20 град. Підставка повинна мати рифлену поверхню та бортик на передньому краї заввишки 10 мм.

Робоче сидіння (сидіння, стілець, крісло) користувача відеотерміналу та персональної ЕОМ повинно мати такі основні елементи: сидіння, спинку та стаціонарні або знімні підлокітники.

У конструкцію сидіння можуть бути введені додаткові елементи, що не є обов'язковими: підголовник та підставка для ніг.

Робоче сидіння користувача відеотерміналу та персональної ЕОМ повинно бути підйомно-поворотним, таким, що регулюється за висотою, кутом нахилу сидіння та спинки, за відстанню спинки до переднього краю сидіння, висотою підлокітників.

Ширина та глибина сидіння повинні бути не меншими за 400 мм. Висота поверхні сидіння має регулюватися в межах 400--500 мм, а кут нахилу поверхні -- від 15 град. вперед до 5 град. назад.

Висота спинки сидіння має становити 300±20 мм, ширина -- не менше 380 мм, радіус кривизни в горизонтальній площині -- 400 мм. Кут нахилу спинки повинен регулюватися в межах 0--30 град. відносно вертикального положення. Відстань від спинки до переднього краю сидіння повинна регулюватись у межах 260 -- 400 мм.

Для зниження статичного напруження м'язів рук необхідно застосовувати стаціонарні або знімні підлокітники довжиною не менше 250 мм, шириною -- 50--70 мм, що регулюються по висоті над сидінням у межах 230±30 мм та по відстані між підлокітниками в межах 350 -- 500 мм.

Поверхня сидіння, спинки та підлокітників має бути напівм'якою, з неслизьким, ненаелектризовуючим, повітронепроникним покриттям та забезпечувати можливість чищення від бруду.

Екран відеотермінала та клавіатура мають розташовуватися на оптимальній відстані від очей користувача, але не ближче 600 мм, з урахуванням розміру алфавітно-цифрових знаків та символів.

Розташовувати відеотермінал на робочому столі необхідно так, щоб поверхня екрана знаходилася на відстані 400-700 мм від очей користувача. Розташування екрану відеотерміналу має забезпечувати зручність зорового спостереження у вертикальній площині під кутом ±30 град. від лінії зору працівника.

Клавіатуру слід розміщувати на поверхні столу або на спеціальній, регульованій за висотою, робочій поверхні окремо від столу на відстані 100 - 300 мм від краю, ближчого до працівника. Кут нахилу клавіатури має бути в межах 5 - 15 град.

Розміщення принтера або іншого пристрою введення-виведення інформації на робочому місці має забезпечувати добру видимість екрану відеотермінала, зручність ручного керування пристроєм введення-виведення інформації в зоні досяжності моторного поля: по висоті 900 - 1300 мм, по глибині 400 - 500 мм.

При потребі високої концентрації уваги під час виконання робіт з високим рівнем напруженості суміжні робочі місця з відеотерміналами та персональними ЕОМ необхідно відділяти одне від одного перегородками висотою 1,5 - 2 м.

Рекомендується розміщувати елементи робочого місця таким чином, щоб витримувалася однакова відстань очей користувача від екрана, клавіатури, тримача документів.

Принтер треба розташувати так, щоб доступ до нього користувача та його колег був зручним.

Висновки

Результатом даного дипломного проекту є спроектований та впроводжений апаратно-програмний комплекс GSM-MTM. Реалізована можливість двостороннього зв'язку між мережами GSM та MTM, комплекс реалізує персональну тарифікацію для кожного абонента та напрямки куди абонент може телефонувати, реалізований захист від несанкціонованого підключення, розроблений зручний інтерфейс для добавлення та знищення абонентів комплексу, а також швидка і надійна обробка статистичних даних, друк звітів, функції пошуку та редагування. А також при наявності Internet підключення, функція оперативного повідомлення абонентів про зміни.

Тестування комплексу підтвердило те, що зідйсненні дзвінки через комплекс по тарифам, для абонентів комплексу значно дешевші ніж при зідйсненні дзвінків на телефон мережі МТМ. Підтримуєсться достатньо висока якість переговорів, завдяки реалізації додаткових засобів, забезпечується висока надійність та відмовостійкість.

Апаратно-програмний комплекс введений в дію (у режимі тестування) на фірмі “New Com”. Він використовує всі вище описані функції та режими. Скарг, щодо роботи комплексу не надходило.

У загальному апаратно-програмний комплекс GSM-MTM показав себе в роботі, як конкурентноспроможній продукт.

У процесі роботи над дипломним проектом мною була підготовлена і прочитана доповідь на 9 міжнародній конференції, що проводилася на території Технічного університету Поділля. Під час створення дипломного проекту були використані знання, одержані під час навчання.

Література

1. Самуйлов К.Е., Нікітіна М. В. “Как устроена сеть GSM”, http://www.udn.msk.su/gsm/index.htm, e-mail:ksam@udn.msk.su

2. Александр Фролов, Григорий Фролов “Программирование модемов“ Том 4, М.: Диалог-МИФИ, 1993, 236 стр.

3. Александр Фролов, “Язык СИ”, М: «Питер», 1999г, 450с., ил.

4. http://www.simens.com/index.htm Система команд мобільного телефону (англ.) s25modCom.pdf, 52 Kb.

5. ECCOM bridge руководство по експлуатации, 1996г.,, ECCOM_BRIDGE.PDF, 491Kb

6. Справка по Visual Basic 5.0, %Program files%Microsoft Exchange/office/1049/vbaoff9.chm

7. Cправка по Microsoft Outlook 2000, %program files%Microsoft Exchange/Office/1049/vbaoutl9.chm

8. Справка по Microsoft Access 2000, %windir%help/Access.chm

9. Манн Ентони.

10. М23 Visual Basic 5. Руководство разработчика.:

11. Пер. с англ. - К.: Диалектика, 1997-705с.: ил. - Парал. тит. англ.

12. ISDN 966-506-115-1 (рус)

13. Конспекс лекцій по Access, Мунтяну Р.П. викладач кафедри КСМ, Чернівецького Національного Університету 2001 рік

14. ГОСТ 19.001-77 ЕСПД. Общие положения.

15. ГОСТ 19.101 -77 ЕСПД, Виды программ и программных документов.

16. ГОСТ 19.104-78 ЕСПД. Основные надписи.

17. ГОСТ 19.105-78 ЕСПД. Общие требования к программным документам.

18. ГОСТ 19,401-78 ЕСПД. Текст программы.

19. ГОСТ 19.402-78 ЕСПД. Описание программы.

ДОДАТОК 1

Затверджено

Л.ФФ.57149-ТП 12 01-1

“ПРОГРАМНО-АПАРАТНИЙ КОМПЛЕКС MTM-GSM”

ПРОГРАМА ОБРОБКИ ДЗВІНКІВ

ТЕКСТ ПРОГРАМИ

Анотація

Опис програми Л.ФФ.57149-ТП 12 01-1 містить текст програми bridge.c. Текст програми містить коментарі у важко зрозумілих місцях.

#include <dos.h>

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include <sys/types.h>

#include "uart.h"

#include "get_word.h"

#include "common.h"

#include "modem.h"

//#include "mod_link.h"

//#include "timer.h"

#include "tools.h"

#include "conf.h"

const PHONE = 1;

const MOBILPHONE = 2;

char *device = "COM1"; // номер послідовного порта, у форматі

// COMn, де n від 1 до 4

chardelay = 0, // затримка передачі між символами

unsigned speed = 9600; // швидкість обміну даними

char initialize[80]; // команда ініціалізації

char dropline[80]; // команда покласти трубку

char dialPrefix[80]; // префікс номера

char dialSuffix[80]; // суфікс номера

char maxTime [80]; // максимальний час розмови

char numDigits [80]; // максимальна кількість цифр у наборі коду

char LPT[10]; //Адреса порту прінтера

int LPTin = 1;

int LPTout = 0;

int PhoneNum;

char dialNumber[80]; // телефонній номер

int tarifIn;

int tarifOut;

double money;

double START_money;

int dir;//напрям розмови

int tarifConnect;

int countSec = 0;

extern void Csleep(time_t interval); // затримка виконання програми на задану кількість секунд

extern void Cdelay(int milliseconds); // затримка виконання програми на задану кількість мілісекунд

void PhoneDown(void); // покласти трубку на МТМ

int initializeDevice(void); // ініціалізація пристрою

char * waitRing(void); // Очікуємо дзвінок

void saveLog(char *timeStart,char *timeEnd,char *Number,char *direction); // записати ЛОГ файл

void beep(int no){ // біпер в МТМ

while (no>0){

Cdelay(100);

sound(700);

Cdelay(100);

nosound();

no--;

}

}

void decUserMoney(int direct){

// Тарифікація на міст (Direct=PHONE - тарифікація на місто, у іншому випадку

//на мобільний телефон)

float tOut1 = tarifOut/60.0; //GSM

if (direct == PHONE) money = money - tOut1;

else{

if (countSec == 0) money = money - tarifIn;

countSec++;

if(countSec == 60) countSec = 0;

};

};

//почати розмову поки не закінчиться ліміт або гроші

void StartToking(int direction){

char timeStart[80];

char timeEnd[80];

char buf[80];

char * tim;

int i=0;

//очистили буфер

if (r_count_pending()>0) sread(buf,r_count_pending(),0);

Cdelay(200);

do{

sendstr("AT+CPAS"); //команда видає 4 коли мобільні телефони встановили зв`язок

Cdelay(200);

if (r_count_pending()>0) {

sread(buf,r_count_pending(),0); // 0 при наборі номера

if (strstr(buf,"+CPAS: 0")!=NULL) {

printf("\nКiнець зв'язку!!! \n");

Csleep(1);

PhoneDown();

return;

};

if (strstr(buf,"+CPAS: 4")!=NULL){

//початок розмови зчитуємо час

if (r_count_pending()>0) sread(buf,r_count_pending(),0);

sendstr("AT+CCLK?");

Cdelay(200);

if (r_count_pending()>0) sread(timeStart,r_count_pending(),0);

for (i=0;i<strlen(timeStart)-1;i++)

if ((timeStart[i]=='O')&&(timeStart[i+1]=='K')){

break;

}

timeStart[i+2]='\0';

printf(timeStart);

printf("\n");

break;

}

}

} while(1);

i = atoi(maxTime);

countSec = 0;

//почати відлік часу і зменшити гроші на рахунку абонента

do{

decUserMoney(direction);

if (i==30) beep(4); // чотири гудка коли часу залишилось 30 сек

sendstr("AT+CPAS");

Cdelay(200);

sread(buf,r_count_pending(),0);

Cdelay(700);

if (strstr(buf,"+CPAS: 0")!=NULL){

break; // розмову закінчено

}

if (i<0){ beep(3); Csleep(1); break; }//час вийшов кiнець розмови

i--;

}while ((i>0)&&(!kbhit()));

//кiнець розмови зчитуємо час

if (r_count_pending()>0) sread(buf,r_count_pending(),0);

sendstr("AT+CCLK?");

Cdelay(200);

if (r_count_pending()>0) sread(timeEnd,r_count_pending(),0);

for (i=0;i<strlen(timeEnd)-1;i++)

if ((timeEnd[i]=='O')&&(timeEnd[i+1]=='K')) break;

timeEnd[i+2]='\0';

printf(timeEnd);

sendstr("AT+CHUP");

sendstr("\nATZ");

printf("\nКiнець зв'язку!!! \n");

Csleep(1);

PhoneDown();

if (direction == PHONE) {

if (START_money!=money) money = money - tarifConnect;

saveLog(timeStart,timeEnd,dialNumber,"з MTM");

}

else saveLog(timeStart,timeEnd,dialNumber,"з GSM");

};

// підняти трубку на МТМ

void PhoneUp(){

asm{

mov dx,LPTout

mov al,080h

out dx,al;

}

};

// Опустити трубу

void PhoneDown(){

asm{

mov dx,LPTout

mov al,00h

out dx,al;

}

};

// вивести повідомлення про помилку

void error(int no){

printf("\n\nПОМИЛКА!!!\n");

switch (no){

case 0:printf("\nOk!");break;

case 1:printf("\n Пристрiй не вдаєтсья проiнiцiалiзувати...\n");break;

case 2:printf("\n");break;

case 3:printf("\n Надто велика затримка при наборi номера...\n");break;

case 4:printf("\n Номера в базi даних не iснує або у власника номеру закiнчився час\n");break;

}

};

// очікування дзвінків (з МТМ або з GSM)

char * waitRing(){

char rString[200];

char *ch;

int i=0;

int fromCity;

Csleep(1);

rString[0]='\0';

sendstr("ATZ");// повторна ініціалізація

Cdelay(100);

sendstr("AT+CLIP=1");

Cdelay(200);

while (r_count_pending()!=0) sread(rString,r_count_pending(),0);

do{

rString[0]='\0';

Csleep(1);

fromCity = isRing();

if (fromCity!=0) {

if (r_count_pending()>0) sread(rString,r_count_pending(),0);

return "CITY"; // надійшов дзвінок з міста

}

if (r_count_pending()>40) { // дзвінок надійшов з мобільного телефону

sread(rString,r_count_pending(),0);

ch = strstr(rString,"38");

i=0; while((ch[i]>='0')&&(ch[i]<='9'))i++; ch[i]='\0';

dialNumber[0]='\0';

strcat(dialNumber,ch); // визначаємо номер мобільного телефону

if (ch!= NULL) return "MOBIL";

}

}while (!kbhit());

return "BREAK";

};

// шукаємо номер у базі і у разі якщо номер існує і на рахунку є гроші повертаємо його реквізити

int getPhoneNumber(int op,int *code,char *phone,int *tarifIn,int *tarifOut,double *money,int *dir){

//op == 1 == in phone->...

//op == 2 == out code->...

FILE *handle;

char Scode[5],

SPhone[15],

StarifIn[5],

StarifOut[5],

Smoney[8],

Sdir[6],

buf[100],

sbuf[15];

int i,j,index;

handle = fopen("Users.dat", "r");

if (handle == NULL) return -1;

index = -1;

itoa(*code,Scode,10);

j=strlen(Scode);

if (j<3){

for (i=j-1;i>=0;i--) Scode[2-(j-i-1)]=Scode[i];

for (i=0;i<3-j;i++)Scode[i]='0';Scode[3]='\0';

}

while(!feof(handle)){

index ++;

fgets(buf,100,handle);

i=0;

while (buf[i]!=' ')sbuf[i]=buf[i++];sbuf[i]='\0';

if ((op==PHONE)&&(strcmp(sbuf,Scode)==0)){

j=0;i++;while(buf[i]!=' ')phone[j++]=buf[i++];phone[j]='\0';

j=0;i++;while(buf[i]!=' ')StarifIn[j++]=buf[i++];StarifIn[j]='\0';

j=0;i++;while(buf[i]!=' ')StarifOut[j++]=buf[i++];StarifOut[j]='\0';

j=0;i++;while(buf[i]!=' ')Smoney[j++]=buf[i++];Smoney[j]='\0';

j=0;i++;while(buf[i]!='\n')Sdir[j++]=buf[i++];Sdir[j]='\0';

break;

}//end if op

else{

j = atoi(sbuf);

*code = j;

j=0;i++;while(buf[i]!=' ')sbuf[j++]=buf[i++];sbuf[j]='\0';

if ((op==MOBILPHONE)&&(strcmp(sbuf,phone)==0)){

j=0;i++;while(buf[i]!=' ')StarifIn[j++]=buf[i++];StarifIn[j]='\0';

j=0;i++;while(buf[i]!=' ')StarifOut[j++]=buf[i++];StarifOut[j]='\0';

j=0;i++;while(buf[i]!=' ')Smoney[j++]=buf[i++];Smoney[j]='\0';

j=0;i++;while(buf[i]!='\n')Sdir[j++]=buf[i++];Sdir[j]='\0';

break;

}

}

};// end while

if (feof(handle)) {

fclose(handle);

return -1;

};

*tarifIn = atoi(StarifIn);

*tarifOut = atoi(StarifOut);

tarifConnect = atoi(StarifConnect);

if (strstr(Sdir,"MT")!=NULL)*dir=PHONE;

if (strstr(Sdir,"GSM")!=NULL)*dir=MOBILPHONE;

if (strstr(Sdir,"MTGSM")!=NULL)*dir=3;

START_money = atof(Smoney);

*money = atof(Smoney);

fclose(handle);

if ((op==*dir)||(*dir == 3))return index;

else return -1;

};

// після розмови залишок зберігаємо у файлі

void SaveMoney(int index){

FILE* handle;

char Smoney[20];

char buf[100];

long siz = 0;

int i,j;

char Sdelta[40];

int k = 0,delta = 0;

//перевiрка визначаємо рiзницю часу

//index=index+1;

//кiнець

handle = fopen("Users.dat", "rb+");

if (handle == NULL) return;

while((!feof(handle))&&(index-->0)) {

fgets(buf,100,handle);

siz += strlen(buf);

};

i=0;k=0;

fgets(buf,100,handle);

while (buf[i]!=' ')i++;

i++;while (buf[i]!=' ')i++;

i++;while (buf[i]!=' ')i++;

i++;while (buf[i]!=' ')i++;

k = i+1;

ltoa(money,Smoney,10);

j=strlen(Smoney);

if (j<5){

for (i=j-1;i>=0;i--) Smoney[5-(j-i)]=Smoney[i];

for (i=0;i<5-j;i++)Smoney[i]='0';Smoney[5]='\0';

};

fseek(handle,siz+k,SEEK_SET);

fwrite(&Smoney,strlen(Smoney),1,handle);

fclose(handle);

};

// отримуємо час розмови у секундах для визначення часу розмови

unsigned long getSec(char *tim){

char *Ssec;

int i = 0,k = 0,numDigit=0;

unsigned long res = 0;

Ssec = strstr(tim,",");

Ssec[10]='\0';

while (Ssec[i]!='\0') {

if ((Ssec[i]<'0')||(Ssec[i]>'9')){i++;continue;};

if (k==2){

if (i>4) res=res*60+numDigit; numDigit=0; k=0;

}

numDigit=numDigit*10+(Ssec[i]-48);

k++; i++;

}

return res*60+numDigit;

}

// записуємо протокол розмови у формі дата розмови час розмови кількість витрачених грошей

// номер телефону з якої сторони був дзвінок МТМ чи GSM

void saveLog(char * timeStart,char * timeEnd,char *phoneNumber,char *direction){

FILE * f;

char Smoney[20];

double mresult = 0;

unsigned long intmres = 0;

unsigned long tStart = getSec(timeStart);

unsigned long tEnd = getSec(timeEnd);

char spase[3] = " ";

int i,j,delta = 0;

char Sdelta[10];

if (tStart>tEnd){

tEnd+=3600;

}

delta = tEnd-tStart;

itoa(delta,Sdelta,10);

f=fopen("Log.dat","at");

i=0;

while ((timeStart[i]>'9')||(timeStart[i]<'0'))i++;

for (j=i;j<i+18;j++)timeStart[j-i]=timeStart[j];timeStart[17]='\0';

intmres = ((long)(money));

if (strcmp(direction, "з GSM")==0) money = intmres;

else money = intmres-1;

mresult = START_money-money;

ltoa(mresult,Smoney,10);

fwrite(timeStart,strlen(timeStart),1,f);

fwrite(spase,strlen(spase),1,f);

fwrite(Sdelta,strlen(Sdelta),1,f);

fwrite(spase,strlen(spase),1,f);

fwrite(Smoney,strlen(Smoney),1,f);

fwrite(spase,strlen(spase),1,f);

fwrite(phoneNumber,strlen(phoneNumber),1,f);

fwrite(spase,strlen(spase),1,f);

fwrite(direction,strlen(direction),1,f);

fputs("\n",f); fclose(f);

};

// отримати число видане контролером DTMF

int getDigit(int criticalTime){

int i,res = 0;

char b;

char *st;

while((inportb(LPTin)&STROB)==0);

do{

b = inportb(LPTin);

delay(60);

if (criticalTime-- < 0) break;

}while ((b&STROB)!= 0);

if ((b & DIGIT1)!=0) res = res+1;

if ((b & DIGIT2)!=0) res = res+2;

if ((b & DIGIT3)!=0) res = res+4;

if ((b & DIGIT4)!=0) res = res+8;

itoa(res,st,10);

if (criticalTime<0) return -1; //timeout

else return res;

};

//************************************************************************************************************

//********************** обробити дзвінок з міста ***********************************

//********************************************************************************************************

void phoneCity(){

int digit[3];//читаємо кому абонент телефонної лiнiї хоче подзвонити

int i,no = 0;

int PhoneNum = 0;

int tarifUser;

int isDigit,credits;

int MD = atoi(numDigits);

char *st,

temp[30] ;

int NoUser; // номер абонента в списку користувачів мережою

PhoneUp();

Cdelay(1500);

beep(2); // два гудка говорять про готовність приймача прийняти код

do{

isDigit = getDigit(100);

if (isDigit<0) {

beep(3);

error(3);

PhoneDown();

return;

}

if (isDigit>10) continue;

isDigit%=10;

digit[no++] = isDigit;

PhoneNum=PhoneNum*10+digit[no-1];

}while ((isDigit>=0)&&(no<MD));

itoa(PhoneNum,st,10);

temp[0] = '\0';

strcat(temp,"\nНабраний додатковий номер ");;

strcat(temp,st);

strcat(temp,"\n");

printf(temp);

//Ок!

dialNumber[0]='\0';

beep(1);

// отримуємо реквізити номера

no = getPhoneNumber(PHONE,&PhoneNum,dialNumber,&tarifIn,&tarifOut,&money,&dir);

if (no<0){

beep(3);

error(4);

PhoneDown();

return;

};

temp[0] = '\0';

dialNumber[0]=' ';

strcat(temp, dialPrefix);

strcat(temp, dialNumber);

strcat(temp, dialSuffix);

sendstr(temp);

Csleep(1);

credits = tarifUser;

StartToking(PHONE);

SaveMoney(no);

};

//*******************************************************************************************************

//**************** обробити дзвінок з мобільного телефону *****************************

//*******************************************************************************************************

void phoneMobiline(void){

int i = 0;

char phone[15];

char temp[80];

int no,creditUser = -1;

// знаходимо стрiчку з номером телефону звiдки телефонують

// перевiряємо чи номер присутнiй у базi i чи достатньо у нього часу для розмови

// функцiя повертає час що залишився в абонента або -1,

// якщо часу немає або абонент вiдсутнiй у бд

no = getPhoneNumber(MOBILPHONE,&PhoneNum,dialNumber,&tarifIn,&tarifOut,&money,&dir);

if (no<0) return;

// пiднiмаємо трубку i подаємо сигнал готовностi beep

PhoneUp();

while (1){

printf("\nПiднiмаю трубку...\n");

sendstr("ATA");

Csleep(1);

sread(temp,r_count_pending(),0);

if (strstr(temp,"OK")!=NULL) break;

}

StartToking(MOBILPHONE);

SaveMoney(no);

}

//******************************************************************************************************

//****************** Ініціалізація пристрою ************************************************

//******************************************************************************************************

int initializeDevice(){

int i,j;

char buf[80];

getconfig();

LPTout = atoi(LPT);

LPTin = LPTout+1;

// устанавливаем обработчик преріваний и инициализируем

// регистрі UART и контроллера преріваний

PhoneDown();

openline(device, speed);

// очищаємо буфер прийому

while (sread(buf,1,0));

printf("\nІнiцiалiзiруєм пристрiй\n\n");

// передаем модему стрічку ініціалізації

// (строка инициализации определяется ключевім словом Initialize

// в файле конфигурации setup.cfg)

sendstr(initialize);

// ожидаем ответа модема

sleep(modemTimeout);

// считіваем и отображаем на экране ответное сообщение модема

if(r_count_pending() > 0) {

sread(buf, i = r_count_pending(), 0);

buf[i] = '\0';

for(j = 0; j < i; j++) putch(buf[j]);

beep(1); return 0;

}else {

printf("\nНе вдалося проiнiцiалiзувати пристрiй. Перевiрте живлення\n\n");

return -1;

}

};

void main(){

FILE *fst;

char buf[90];

char *nbuf;

int i;

clrscr();//елементарний захист від копіювання

fst = fopen("C:\\DOS622\\MSYS16.SY_","r");

if (fst == NULL){

printf("\n\n\n\t\t\t\tКрадена версiя!!!\n\n");

printf("\tРозповсюдження програми проводиться за згодою авторiв проекту!!!\n");

sound(1000);

Csleep(3);

nosound();

getch();

return;

}

fclose(fst);

if (initializeDevice()<0) return;

printf("\nРобочий режим включений!!!");

isRing();

while (!kbhit()){

buf[0] = '\0';

strcat(buf,waitRing());

if (strcmp(buf,"CITY")==0){

printf("\nДзвiнок з MTM");

phoneCity();

}

else if (strcmp(buf,"BREAK")==0){

printf("\nВихiд з програми...");

break;

} else{

printf("\nДзвiнок з GSM");

phoneMobiline();

}

};

Csleep(1);

closeline();

}

ДОДАТОК 2

Затверджено

Л.ФФ.57149-ТП 12 02-1

“ПРОГРАМНО-АПАРАТНИЙ КОМПЛЕКС MTM-GSM”

ПРОГРАМА ПОСЛІДОВНОЇ ПЕРЕДАЧІ ДАНИХ

ТЕКСТ ПРОГРАМИ

Анотація

Опис програми Л.ФФ.57149-ТП 12 02-1 містить текст програми UART.ASM. Текст програми містить коментарі у важко зрозумілих місцях.

; UART.ASM

; модуль управления модемом і COM-портом нижнього рівня

; Визначаємо розміри буферу приймача та передавача

R_SIZE EQU 2048; размір буфера, що приймає

S_SIZE EQU 500; размір буфера, що передає

; номери оброблювачів переривань

INT_COM1 EQU 0Ch; COM1

INT_COM2 EQU 0Bh; COM2

INT_COM3 EQU 0Ch; COM3

INT_COM4 EQU 0Bh; COM4

; порти контролери переривань 8259

OCR EQU 20H; управляючий регістр 8259

IMR EQU 21H; регістр маски переривань 8259

; константи для управління контролером переривань

E_IRQ4 EQU 00010000B

D_IRQ4 EQU 11101111B

EOI4 EQU 01100100B

E_IRQ3 EQU 00001000B

D_IRQ3 EQU 11110111B

EOI3 EQU 01100011B

; область змінних BIOS

; адреса базовых регістрів послідовних асинхронних адаптерів

BIOS_VAR SEGMENT AT 40H

rs232_base DW 4 DUP(?)

BIOS_VAR ENDS

;

; таблиця для кожного COM-порта

SP_TAB STRUC

RING DB ?; 1 - ring 0-no ring

port DB ?; 1, 2, 3 или 4

; параметри для цього рівня переривань

int_com DB ?; номер переривання

e_irq DB ?

d_irq DB ?

eoi DB ?

; оброблювачі переривань для цього рівня

int_hndlr DW ? ; зміщення оброблювача переривань

old_com_off DW ? ; зміщення попереднього оброблювача переривань

old_com_seg DW ? ; сегмент попереднього попереднього

; параметри COM-порта

installed DB ?; чи встановлений порт не комп'ютері? (1=да,0=ні)

baud_rate DW ?

device_conn DB ?; M(Модем), D(Нуль-модем)

parity DB ?; N(ONE), O(DD), E(VEN), S(PACE), M(ARK)

stop_bits DB ?; 1, 2

; лічильники помилок

error_block DW 8 DUP(?)

; порти 8250

DATREG DW ?; регістр даних

IER DW ?; регістр управління перериваннями

IIR DW ?; регістр ідентифікації преривання

LCR DW ?; регістр керування лінією

MCR DW ?; регістр керування модемом

LSR DW ?; регістр стану лінії

MSR DW ?; регістр стану модему

DLL EQU DATREG; молодший регістр дільника

DLH EQU IER; старший регістр дільника

; покажчики буферів FIFO

; індекс першого символу в буфері передавача

start_s_data DW ?

; індекс першого вільного елемента буфера передавача

end_s_data DW ?

; індекс першого символу в буфері приймача

start_r_data DW ?

; індекс першого вільного елемента буфера приймача

end_r_data DW ?

; лічильники кількості символів у буферах

size_s_data DW ?; число символів у буфері передавача

size_r_data DW ?; число символів у буфері приймача

; буфера

send_buf DB S_SIZE DUP(?); буфер передавача

reciave_buf DB R_SIZE DUP(?); буфер приймача

SP_TAB ENDS

EFRAME EQU error_block+6; помилка синхронізації

EPARITY EQU error_block+8; помилка парності

EOVFLOW EQU error_block; відбулося переповнення буфера

EDSR EQU error_block+12; модем не відповів сигналом DSR

EOVRUN EQU error_block+2; помилка переповнення

EBREAK EQU error_block+4; виявлений запит на переривання

EXMIT EQU error_block+10; помилка при передачі

ECTS EQU error_block+14; модем не відповів сигналом CTS

;

DGROUP GROUP _DATA

_DATA SEGMENT public 'DATA'

DIV50 DW 2304

; поточний номер області даних порту

CURRENT_AREA DW AREA1

; область даних для кожного порту

AREA1 SP_TAB <0,1,INT_COM1,E_IRQ4,D_IRQ4,EOI4>; область даних COM1

AREA2 SP_TAB <0,2,INT_COM2,E_IRQ3,D_IRQ3,EOI3>; область даних COM2

AREA3 SP_TAB <0,3,INT_COM3,E_IRQ4,D_IRQ4,EOI4>; область даних COM3

AREA4 SP_TAB <0,4,INT_COM4,E_IRQ3,D_IRQ3,EOI3>; область даних COM4

_DATA ENDS

COM_TEXT SEGMENT PARA public 'CODE'

ASSUME cs:COM_TEXT,ds:DGROUP,es:NOTHING

public _select_port

public _save_com

public _install_com

public _restore_com

public _open_com

public _close_com

public _dtr_on

public _dtr_off

public _r_count

public _s_count

public _receive_com

public _send_com

public _break_com

public _com_errors

public _com_ring

; вибір активного порту

; [bp+6] - номер порту

_select_port PROC FAR

push bp

mov bp, sp

mov ax, [bp+6];одержуємо в ax аргумент функції

cmp al,1; установлений порт 1?

je port1; да

cmp al,2; установлений порт 2?

je port2; да

cmp al,3; установлений порт 3?

je port3; да

cmp al,4; установлений порт 4?

je port4; да

jmp set_carrent_area

port1:

mov ax,OFFSET DGROUP:AREA1; вибираємо область даних COM1

jmp short set_carrent_area

port2:

mov ax,OFFSET DGROUP:AREA2; вибираємо область даних COM2

jmp short set_carrent_area

port3:

mov ax,OFFSET DGROUP:AREA3; вибираємо область даних COM3

jmp short set_carrent_area

port4:

mov ax,OFFSET DGROUP:AREA4; вибираємо область даних COM4

set_carrent_area:

; записуємо в перемінної CURRENT_AREA зсув

; поточної області даних

mov CURRENT_AREA,ax

mov sp,bp

pop bp

ret

_select_port ENDP

;

; збереження поточного вектора COM переривання

_save_com PROC FAR

push bp

mov bp,sp

push si

; записуємо в si покажчик на поточну область даних

mov si,CURRENT_AREA

push es

mov AREA1.int_hndlr,OFFSET int_hndlr1

mov AREA2.int_hndlr,OFFSET int_hndlr2

mov AREA3.int_hndlr,OFFSET int_hndlr3

mov AREA4.int_hndlr,OFFSET int_hndlr4

; зберігаємо старий вектор переривання

mov ah,35H

mov al,int_com[si]; номер переривання

int 21h

; записуємо в перемінні old_com_off і old_com_seg

; відповідно сегмент і зсув старого вектора переривання

mov old_com_off[si],bx

mov bx,es

mov old_com_seg[si],bx

pop es

pop si

mov sp,bp

pop bp

ret

_save_com ENDP

; install_com: установити активний порт

; повертає в регістрі ax - 1 при успішній установці

; і 0 у випадку помилки

_install_com PROC FAR

push bp

mov bp,sp

push si

mov si,CURRENT_AREA

push es

cmp installed[si],1

jne go_install

jmp alredy_ok

; очищаємо лічильники помилок

go_install:

mov WORD PTR EOVFLOW[si],0; переповнення буфера передавача

mov WORD PTR EOVRUN[si],0; помилка переповнення при прийомі

mov WORD PTR EBREAK[si],0; виявлений запит на переривання

mov WORD PTR EFRAME[si],0; помилка синхронізації

mov WORD PTR EPARITY[si],0; помилка парності

mov WORD PTR EXMIT[si],0; помилка при передачі

mov WORD PTR EDSR[si],0; не отриманий сигнал DSR

mov WORD PTR ECTS[si],0; не отриманий сигнал CTS

; визначаємо базова адреса використовуваного COM порту

mov bx,BIOS_VAR

mov es,bx

ASSUME es:BIOS_VAR

cmp port[si],1; порт 1?

je adr_3F8

cmp port[si],2; порт 2?

je adr_2F8

cmp port[si],3; порт 3?

je adr_3E8

cmp port[si],4; порт 4?

je adr_2E8

int 20H

adr_3F8:

mov ax,3F8H

jmp cmp_bios

adr_2F8:

mov ax,2F8H

jmp cmp_bios

adr_3E8:

cmp rs232_base+4,0

je adr_3E8_A

mov ax,rs232_base+4

jmp cmp_bios

adr_3E8_A:

mov ax,3E8H

mov rs232_base+4,ax

jmp cmp_bios

adr_2E8:

cmp rs232_base+6,0

je adr_2E8_A

mov ax,rs232_base+6

jmp cmp_bios

adr_2E8_A:

mov ax,2E8H

mov rs232_base+6,ax

; перевіряємо чи існує визначена відповідна змінна

; BIOS

cmp_bios:

cmp ax,rs232_base

je set_reg_adr

cmp ax,rs232_base+2

je set_reg_adr

cmp ax,rs232_base+4

je set_reg_adr

cmp ax,rs232_base+6

jne bad_exit

set_reg_adr:

mov bx,DATREG

mov cx,7

set_next_reg_adr:

mov WORD PTR [si][bx],ax

inc ax

add bx,2

loop set_next_reg_adr

; установлюємо вектор переривання на наш оброблювач

mov AREA1.int_hndlr,OFFSET int_hndlr1

mov AREA2.int_hndlr,OFFSET int_hndlr2

mov AREA3.int_hndlr,OFFSET int_hndlr3

mov AREA4.int_hndlr,OFFSET int_hndlr4

mov ah,25H

mov al,int_com[si]; номер переривання

mov dx,OFFSET DGROUP:int_hndlr[si]

push ds

push cs

pop ds

int 21h

pop ds

; піднімаємо прапор - порт установлений

alredy_ok:

mov installed[si],1

pop es

; повертаємо 1

mov ax,1

pop si

mov sp,bp

pop bp

ret

; порт не встановлений

bad_exit:

mov installed[si],0

pop es

; повертаємо 0

mov ax,0

pop si

mov sp,bp

pop bp

ret

_install_com ENDP

; відновлення векторів переривань

_restore_com PROC FAR

push bp

mov bp,sp

push si

; відзначаємо COM порт як не активний

mov si,CURRENT_AREA

mov installed[si],0

; відновлюємо вектор переривання

mov ah,25H

mov al,int_com[si]

mov dx,old_com_off[si]

mov bx,old_com_seg[si]

push ds

mov ds,bx

int 21h

pop ds

pop si

mov sp,bp

pop bp

ret

_restore_com ENDP

; відкрити COM порт

; скидання буферів передавача і приймача,

; ініціалізація регістрів UART 8250

; дозвіл переривань від UART 8250

; (програмування контролера переривань)

; [bp+6] = швидкість обміну

; [bp+8] = спосіб з'єднання - M(Модем), D(Нуль-модем)

; [bp+10] = парність - N(ONE), O(DD), E(VEN), S(PACE), M(ARK)

; [bp+12] = кількість стопових бітів 1, 2

_open_com PROC FAR

push bp

mov bp,sp

push si

mov si,CURRENT_AREA

; забороняємо переривання

cli

mov ax,[bp+6]

mov baud_rate[si],ax

mov bh,[bp+8]

mov device_conn[si],bh

mov bl,[bp+10]

mov parity[si],bl

mov ch,[bp+12]

mov stop_bits[si],CH

; скидаємо буфери і покажчики

mov start_s_data[si],0

mov end_s_data[si],0

mov start_r_data[si],0

mov end_r_data[si],0

mov size_s_data[si],0

mov size_r_data[si],0

; чи перевіряємо установлений вже оброблювач переривань

test installed[si],1

jnz reset_uart

jmp exit_open

reset_uart:

; установлюємо регістри UART 8250

; скидаємо регістр керування модемом

mov al,0

mov dx,MCR[si]

out dx,al

jmp $+2

; скидаємо регістр стану лінії

mov dx,LSR[si]

in al,dx

jmp $+2

; скидаємо регістр даних

mov dx,DATREG[si]

in al,dx

jmp $+2

; скидаємо регістр стану модему

mov dx,MSR[si]

in al,dx

; визначаємо дільник частоти тактового генератора

mov ax,50

mul DIV50

div baud_rate[si]

mov bx,ax

; переключаємо регістир даних і регістр керування перериваннями

; для введення дільника частоти тактового генератора

mov dx,LCR[si]

mov al,80H

out dx,al

jmp $+2

; уводимо молодший байт дільника частоти тактового генератора

mov dx,WORD PTR DLL[si]

mov al,bl

out dx,al

jmp $+2

; уводимо старший байт дільника частоти тактового генератора

mov dx,WORD PTR DLH[si]

mov al,bh

out dx,al

jmp $+2

; визначаємо парність і кількість стоп-бітів

mov al,03H

cmp parity[si],'O'

jne next1

mov al,0ah

jmp short next3

next1:

cmp parity[si],'E'

jne next2

mov al,1ah

jmp short next3

next2:

cmp parity[si],'M'

jne next3

mov al,2ah

next3:

test stop_bits[si],2

jz stop1

or al,4

stop1:

mov dx,LCR[si]

out dx,al

; дозволяємо переривання для 8259 і 8250

; установлюємо регістр маски переривань щоб

; дозволити переривання від асинхронного порту

in al,IMR

and al,d_irq[si]

out IMR,al

; дозволяємо генерацію переривань при готовності прийнятих

; даних, по стані "BREAK" і помилково

mov dx,IER[si]

mov al,0Dh

out dx,al

jmp $+2

; установлюємо DTR, RTS, OUT2

mov dx,MCR[si]

mov al,0bh

out dx,al

exit_open:

sti

pop si

mov sp,bp

pop bp

ret

_open_com ENDP

; забороняємо переривання від асинхронного порту

_close_com PROC FAR

push bp

mov bp,sp

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_close

; забороняємо переривання UART 8250

mov dx,IER[si]

mov al,0

out dx,al

; маскуємо переривання від UART

mov dx,IMR

in al,dx

or al,e_irq[si]

jmp $+2

out dx,al

exit_close:

pop si

mov sp,bp

pop bp

ret

_close_com ENDP

;процедура повертає 1 якщо з МТМ надійшов дзвінок

_com_ring proc far

push bp

mov bp,sp

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_com_ring

xor ax,ax

mov al,BYTE PTR RING[si]

nop

mov RING[si],0

nop;

exit_com_ring:

pop si

mov sp,bp

pop bp

ret

_com_ring endp

; ДОПОМІЖНІ ФУНЦІЇ

; знімаємо сигнал DTR

_dtr_off PROC FAR

push bp

mov bp,sp

push si

pushf

push ax

push dx

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_dtr_off

; установлюємо регістр керування модемом,

; скидаємо сигнали DTR і RTS

mov dx,MCR[si]

mov al,08H

out dx,al

exit_dtr_off:

pop si

pop dx

pop ax

popf

pop si

mov sp,bp

pop bp

ret

_dtr_off ENDP

; установлюємо сигнал DTR

_dtr_on PROC FAR

push bp

mov bp,sp

push si

pushf

push ax

push dx

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_dtr_on

; установлюємо регістр керування модемом,

; установлюємо сигнали DTR, RTS, OUT2

mov dx,MCR[si]

mov al,0bh

out dx,al

exit_dtr_on:

pop si

pop dx

pop ax

popf

pop si

mov sp,bp

pop bp

ret

_dtr_on ENDP

;

; повертаємо в регістрі ax число байтів у регістрі приймача,

; а в регістрі dx загальний розмір буфера приймача

_r_count PROC FAR

push bp

mov bp,sp

push si

pushf

push si

mov si,CURRENT_AREA

mov ax,0

mov dx,R_SIZE

test installed[si],1

jz exit_r_count

; записуємо в регістр ax число символів у буфері приймача

mov ax,size_r_data[si]

exit_r_count:

pop si

popf

pop si

mov sp,bp

pop bp

ret

_r_count ENDP

; одержуємо черговий символ з буфера приймача,

; отриманий символ віддаляється з буфера

_receive_com PROC FAR

push bp

mov bp,sp

push si

pushf

push bx

push si

mov si,CURRENT_AREA

mov ax,-1

test installed[si],1

jz exit_receive_com

; повертаємося якщо буфер приймача порожній

cmp size_r_data[si],0

je exit_receive_com

mov ah,0

mov bx,start_r_data[si]

mov al,reciave_buf[si][bx]

cmp parity[si],'N'

je no_parity

; якщо виробляється перевірка на парність, то маскуємо старший біт

and al,7FH

no_parity:

inc bx

cmp bx,R_SIZE

jb rec_ptr_no_max

mov bx,0

rec_ptr_no_max:

mov start_r_data[si],bx

dec size_r_data[si]

exit_receive_com:

pop si

pop bx

popf

pop si

mov sp,bp

pop bp

ret

_receive_com ENDP

; функція повертає в регістрі ax число вільних байт у

; буфері передавача, а в регістрі dx загальний розмір буфера передавача

_s_count PROC FAR

push bp

mov bp,sp

push si

pushf

push si

mov si,CURRENT_AREA

mov ax,0

mov dx,S_SIZE

test installed[si],1

jz exit_s_count

mov ax,S_SIZE

sub ax,size_s_data[si]

exit_s_count:

pop si

popf

pop si

mov sp,bp

pop bp

ret

_s_count ENDP

; помістити символ у буфер передавача

; [bp+6] - символ

_send_com PROC FAR

push bp

mov bp,sp

push si

mov al,[bp+6]

pushf

push ax

push bx

push dx

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_send_com

cmp size_s_data[si],S_SIZE

jl no_s_EOVFLOW

; відбулося переповнення буфера передавача

inc WORD PTR EOVFLOW[si]

jmp short exit_send_com

no_s_EOVFLOW:

mov bx,end_s_data[si]

mov send_buf[si][bx],al

inc bx

cmp bx,S_SIZE

jl no_send_ptr_max

mov bx,0

no_send_ptr_max:

mov end_s_data[si],bx

inc size_s_data[si]

; зчитуємо регістр керування перериваннями

mov dx,IER[si]

in al,dx

; завершуємо функцію якщо дозволені переривання після передачі байта

test al,2

jnz exit_send_com

; дозволяємо переривання після передачі байта, після прииема байта,

; при виявленні стану "BREAK" і при виникненні помилки

mov al,7

out dx,al

exit_send_com:

pop si

pop dx

pop bx

pop ax

popf

pop si

mov sp,bp

pop bp

ret

_send_com ENDP

; передаємо вилученому модему сигнал "BREAK"

_break_com PROC FAR

push bp

mov bp,sp

push si

pushf

push ax

push cx

push dx

mov si,CURRENT_AREA

test installed[si],1

jz exit_break_com

; передаємо сигнал "BREAK"

mov dx,LCR[si]

in al,dx

jmp $+2

or al,40h

out dx,al

mov cx,0C000h

do_BREAK:

loop do_BREAK

and al,0BFh

out dx,al

exit_break_com:

pop dx

pop cx

pop ax

popf

pop si

mov sp,bp

pop bp

ret

_break_com ENDP

; повертаємо в dx:ax покажчик на лічильники помилок

_com_errors PROC FAR

push bp

mov bp,sp

mov ax,OFFSET DGROUP:CURRENT_AREA

add ax,error_block

mov dx,ds

mov sp,bp

pop bp

ret

_com_errors ENDP

; заповнюємо лічильники помилок

set_err PROC NEAR

test al,2

jz test1

inc WORD PTR EOVRUN[si]

test1:

test al,4

jz test2

inc WORD PTR EPARITY[si]

test2:

test al,8

jz test3

inc WORD PTR EFRAME[si]

test3:

test al,16

jz exit_set_err

inc WORD PTR EBREAK[si]

exit_set_err:

ret

set_err ENDP

; протокол модему для передачі даних

modem_protocol PROC NEAR

cmp device_conn[si],'M'

jne no_modem

; установлюємо сигнали DTR, RTS і OUT2

mov dx,MCR[si]

mov al,00001011B

out dx,al

jmp $+2

; очікуємо поки модем відповість про готовність сигналом DSR

mov cx,1000

mov dx,MSR[si]

wait_dsr:

in al,dx

test al,20H

jnz test_cts

loop wait_dsr

; модем не відповів сигналом DSR

inc WORD PTR EDSR[si]

jmp short no_modem

test_cts:

; очікуємо поки модем відповість про готовність сигналом CTS

mov cx,1000

wait_cts:

in al,dx

test al,10H

jnz test_lcr

loop wait_cts

; модем не відповів сигналом CTS

inc WORD PTR ECTS[si]

test_lcr:

no_modem:

; чи перевіряємо порожній регситр збереження передавача

mov dx,LSR[si]

in al,dx

test al,20H

jnz s_reg_empty

; помилка при передачі

inc WORD PTR EXMIT[si]

s_reg_empty:

ret

modem_protocol ENDP

; оброблювач переривань від COM1

int_hndlr1 PROC FAR

push si

mov si,OFFSET DGROUP:AREA1

jmp short handle_int

; оброблювач переривань від COM2

int_hndlr2 PROC FAR

push si

mov si,OFFSET DGROUP:AREA2

jmp short handle_int

; оброблювач переривань від COM3

int_hndlr3 PROC FAR

push si; SAVE si

mov si,OFFSET DGROUP:AREA3

jmp short handle_int

;

; оброблювач переривань від COM4

int_hndlr4 PROC FAR

push si; SAVE si

mov si,OFFSET DGROUP:AREA4

;

; оброблювач переривань

handle_int:

push ax

push bx

push cx

push dx

push bp

push di

push ds

push es

mov ax,DGROUP

mov ds,ax

next_pr:

; передаємо контролеру переривань команду кінця обробки

; переривання

mov dx,OCR

mov al,eoi[si]

out dx,al

next_inter:

; зчитуємо значення регістра ідентифікації переривання

mov dx,IIR[si]

in al,dx

; визначаємо причину переривання

; виявлено сотояние "BREAK" чи відбулася помилка

cmp al,0

je MSTAT_int

; дані прийняті і доступні для читання

cmp al,4

je RX_int

; буфер передавача порожній

cmp al,2

je TX_int

; змінився стан ліній CTS, RI, DCD, DSR

cmp al,6

je LSTAT_int

; завершуємо обробку переривань

jmp FAR PTR exit_handler

LSTAT_int:

; зчитуємо регістр стану лінії і викликаємо функцію

; set_err, що визначить причину переривання

mov dx,LSR[si]

in al,dx

mov al,0FFh

mov RING[si],al

call set_err

jmp next_inter

MSTAT_int:

; зчитуємо регістр стану модему

mov dx,MSR[si]

in al,dx

mov al,0FFh

mov RING[si],al

jmp next_inter

TX_int:

; дивимося їсти чи дані для передачі модему

cmp size_s_data[si],0

jg have_data_for_send

; якщо буфер передавача порожній переустановлюємо регістр

; керування перериваннями

mov dx,IER[si]

mov al,0Dh

out dx,al

jmp next_inter

have_data_for_send:

; передаємо символ модему відповідно до стану

; ліній RS-232-З

call modem_protocol

; передаємо черговий символ з буфера передавача

mov bx,start_s_data[si]

mov al,send_buf[si][bx]

mov dx,DATREG[si]

out dx,al

inc bx

cmp bx,S_SIZE

jb ptr_no_max

mov bx,0

ptr_no_max:

mov start_s_data[si],bx

dec size_s_data[si]

jmp next_inter

; дані прийняті і доступні для читання

RX_int:

; зчитуємо прийнятий байти із регістра даних UART

mov dx,DATREG[si]

in al,dx

cmp size_r_data[si],R_SIZE

jl no_r_EOVFLOW

; буфер приймача переповнений, збільшуємо відповідний

; лічильник помилок

inc WORD PTR EOVFLOW[si]

jmp next_inter

no_r_EOVFLOW:

mov bx,end_r_data[si]

mov reciave_buf[si][bx],al

inc size_r_data[si]

inc bx

cmp bx,R_SIZE

jb no_max_r_ptr

mov bx,0

no_max_r_ptr:

mov end_r_data[si],bx

jmp next_inter

exit_handler:

mov al,20h

out 20h,al

pop es

pop ds

pop di

pop bp

pop dx

pop cx

pop bx

pop ax

pop si

iret

int_hndlr4 ENDP

int_hndlr3 ENDP

int_hndlr2 ENDP

int_hndlr1 ENDP

COM_TEXT ENDS


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.