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
END
... та модернізації переліку послуг, в основу проекту були покладені принципи, аналогічні принципам конструювання послуг інтелектуальної мережі. 2. Системи комп'ютерної телефонії фірми «Беркут» Науково-виробнича фірма «Беркут» (Санкт-Петербург) є виробником широкого спектра систем телекомунікаційного обладнання, розроблюваних на базі власної платформи комп'ютерної телефонії та прикладного ПЗ. ...
0 комментариев