Г.Тяпичев
«Цифровая радиосвязь на любительской радиостанции». Глава 5.
Глава 5. Как сделать программу
Глава 5. Как сделать программу
Предисловие
Начиная примерно с 1994 года, в нашей стране начали становиться
доступными компьютеры IBM PC и появилась возможность приобретать по различным каналам
программы для любительской радиосвязи, разработанные иностранными
программистами.
В те годы я старался освоить все попадавшиеся мне в руки программы
по радиосвязи. Восхищался их красочностью, большим разнообразием команд и
функций. Переводил файлы документации многих программ на русский язык, делал к
этим программам свои вспомогательные файлы, проводил и другую работу, которую
можно назвать словом "русификация".
По мере того, как мною осваивались разные программы, я стал
замечать, что очень многие из них по качеству приема сигналов работают в
несколько раз хуже созданных мною ранее аналогичных программ для
"Радио-86РК", хотя по красочности были бесподобными. Потом стал
замечать другую особенность — многие из задействованных в программе команд
и функций оставались невостребованными. И еще. Программы, содержащие в своем
составе несколько видов цифровой связи,
как правило, имеют наиболее плохие параметры, содержат наиболее примитивные
подпрограммы приема и передачи.
Так постепенно я пришел к выводу о том, что нужно снова начать
создавать свои программы, которые должны по основным параметрам — приему и
передаче без ошибок нужной информации — превосходить многие зарубежные. В
то же время на красочное оформление заставок и рабочих экранов обычно не
обращаю большого внимания. Не считаю этот параметр главным в программе по
радиосвязи.
В этой главе книги я привожу исходные тексты некоторых своих
программ с описаниями их основных
особенностей. Это делается мною в надежде на то, что тексты исходных кодов
разработанных мною программ помогут начинающим программистам создавать свои
программы на эту же тему, по этому же виду радиосвязи. Пускай тексты моих
программ не всегда совершенны с точки
зрения профессиональных программистов, но все программы работоспособны и
опробованы работой в эфире.
Эта
глава и размещенные в ней файлы с исходными кодами программ ни в коем случае не
являются учебными пособиями по программированию. Эти файлы просто рассказывают
вам о том, как та или иная задача была мною решена в прошлые годы при создании
определенной программы.
Буду считать свои цели достигнутыми, если кому-то удастся на базе
разработанных мною исходных текстов создать новые превосходные программы,
гораздо лучшие по всем параметрам.
Программа ORBITA предназначена для
расчета различных параметров орбит ИСЗ. Создана в конце 90-х годов прошлого
столетия, несколько раз дорабатывалась. Разрабатывалась в среде программирования
QuickBasic, хорошо компилируется в Turbo Basic. Программа хорошо работает как под
управлением MS DOS, так и под управлением Windows 95/98/ME/2000/XP.
Определенную ценность представляют именно те функции программы, в
которых располагается весь математический аппарат, необходимый для проведения
расчетов и производится выполнение этих расчетов.
Любители программировать в Visual Basic могут с успехом использовать эти функции
при создании своих приложений для Windows. Но в таком
случае программа будет работать только под управлением Windows.
Ниже приводится листинг исходного файла orbit101.bas. Листинг прерывается для размещения различных пояснений.
Листинг 5.1. Файл orbit101.bas
'Программа для расчетов параметров орбит
спутников,
' находящихся
на круговых орбитах.
ON
ERROR GOTO 10020
OPEN "orbit101.cfg" FOR INPUT AS #1: CLOSE 'Проверка
OPEN "tle1.dat" FOR INPUT AS #1: CLOSE '
файлов
10 CLS
SCREEN 0, 1: WIDTH 80:
COLOR 14, 1, 0: CLS
ON ERROR GOTO 10000
GOTO 18
15 T$ =
"orbit101.cfg"
OPEN T$ FOR INPUT AS
#2
LINE INPUT #2, A$
Num = Num + 1
LINE INPUT #2, B$
LINE INPUT #2, C$
LINE INPUT #2, D$
PRINT A$: AA$ =
LEFT$(A$, 15)
PRINT B$: BB$ =
LEFT$(B$, 7)
PRINT C$: CC$ =
LEFT$(C$, 7)
PRINT D$: DD$ =
LEFT$(D$, 2)
CLOSE #2
STAN$ = AA$
'- название станции слежения
LAT# = VAL(BB$) '- cев. широта станции слежения
LON# = VAL(CC$) '- зап. долгота станции слежения
TZ% = VAL(DD$) '- разница между местн. временем и GMT
T1 =
LAT#
L1 = LON#
PRINT
PRINT STAN$, LAT#,
LON#, TZ%
PRINT : PRINT : PRINT
PRINT " Удостовертесь в правильности
данных в конфигурационном файле."
PRINT :
PRINT
INPUT " Нажмите <Enter>"; C
CLS
RETURN
В предыдущем листинге сначала проводится проверка присутствия в
каталоге нужных дополнительных файлов, затем, начиная с метки 15, проводится
чтение информации из конфигурационного файла. Чтение проводится построчно, из
каждой строки берется только определенное число символов, которые затем декодируются.
Листинг 5.2 представляет собой главную экранную заставку, на
которой размещено первое меню.
Листинг 5.2. Продолжение 1
18 DEFSNG A-Z
20 COLOR 10, 4
LOCATE 3, 20: PRINT "
П Р О Г Р А М М А ORBITA v.1.01 ";
LOCATE 4, 20: PRINT "
ДЛЯ РАСЧЕТА ДАННЫХ ПО ОРБИТАМ СПУТНИКОВ
";
LOCATE
5, 20: PRINT " на IBM PC. Автор RA3XB, апрель 1999г ";
COLOR 14, 1, 1: GOSUB 9400
LOCATE 9, 20: PRINT " <I> — информация о программе"
LOCATE 10, 20: PRINT " <N> — прочитать данные в режиме NASA "
LOCATE 11, 20: PRINT " <T> — расчет параметров орбит по ORBIT_RS"
COLOR
12, 1, 0: LOCATE 14, 20: PRINT " <Esc> — выход в DOS":
COLOR 14, 1, 1
100 GOSUB 9500
LOCATE 16, 20, 0, 0,
7: COLOR 10, 4: PRINT "
ВЫБИРИТЕ <I,N,T,Esc>-->
";
COLOR 30: PRINT
STRING$(2, 176): Z$ = "IiNnTt" + CHR$(27)
110 K$ = INKEY$: IF K$ = "" THEN 110
COLOR 14, 1, 1: LOCATE
16, 46: PRINT SPACE$(2): K = INSTR(Z$, K$)
ON K GOTO 700, 700,
200, 200, 10100, 10100, 120, 120
GOSUB 9510: COLOR 28,
1, 0: GOTO 100
120 CLOSE : CLS : END
200 GOSUB 300: GOTO 20
В листинге 5.3
приводится текст подпрограммы вывода на экран основных данных по
выбранному спутнику. Сначала программа запрашивает ввод названия файла,
содержащего кеплеровские данные, затем просит ввести название спутника. При
этом написание названия спутника должно в точности соответствовать написанию
его названия в файле с кеплеровскими данными. Не путать верхний и нижний
регистры при написании букв.
Листинг 5.3. Продолжение 2
300
'******** Прочитать данные в
режиме NASA
*******
CLS : COLOR 14, 1, 0: LOCATE 2, 10
INPUT "Введите имя файла с данными (по умолчанию — tle1.dat): "; F$
IF F$ =
"" THEN F$ = "TLE1.DAT"
LOCATE 3, 10: INPUT "Введите слово (название спутника) для
поиска: "; P$
SP$ =
P$ ' — название
спутника
OPEN F$ FOR INPUT AS
#1
350 LINE INPUT #1,
Test$
Num = Num + 1
IF EOF(1) THEN 360
IF INSTR(Test$, P$)
<= 0 THEN 350
LINE INPUT #1, A$
LINE INPUT #1, B$
PRINT "Line
#"; Num; ": "; Test$
PRINT A$
PRINT B$
CLOSE #1
GL$ = A$: GK$ = B$
NK$ = MID$(GL$, 3, 5):
YZ$ = MID$(GL$, 10, 2): YY$ = MID$(GL$, 19, 2): TE$ = MID$(GL$, 21, 12)
DD$ = MID$(GL$, 34,
10): VV$ = MID$(GL$, 46, 7): GG$ = MID$(GL$, 55, 7)
II$ = MID$(GK$, 10,
7): RA$ = MID$(GK$, 18, 8): EE$ = MID$(GK$, 27, 7)
PP$ = MID$(GK$, 35,
8): AA$ = MID$(GK$, 44, 8): MM$ = MID$(GK$, 53, 11)
OO$ = MID$(GK$, 64, 5)
M# = VAL(MM$) ' — число орбит в сутки
NR = VAL(OO$) ' — номер эпохальной орбиты
PD# = VAL(DD$) ' — коррекция на движение
PS# = 1 / VAL(MM$) ' — период обращения — орбит/сутки
L0 = VAL(RA$) ' — долгота восходящего узла
R0 = ((PS# * 1440 * 7.365 * 60 / 3.14) — 2 * 6371) / 2
'-высота
спутника над Землей
GS# = 360 / VAL(MM$) ' — количество градусов долготы на оборот
YR = VAL(YY$)
' — эпохальный год
IN = VAL(II$)
ET# = VAL(TE$) ' — эпохальное время по NASA
CLS
LOCATE 2, 10: PRINT " Данные по спутнику "; P$
LOCATE 5, 2: PRINT "Номер спутн. по каталогу NASA "; NK$;
LOCATE 6, 2: PRINT "Год запуска "; YZ$;
LOCATE 7, 2: PRINT "Время эпохальное "; ET#;
LOCATE 8, 2: PRINT "Коррекция на движение
"; PD#;
LOCATE 9, 2: PRINT "Коррекция перемещения
"; GG$;
LOCATE 10, 2: PRINT "Наклонение орбиты
"; II$;
LOCATE 11, 2: PRINT "Долгота восходящего узла (R.A.A.N) "; L0;
LOCATE 12, 2: PRINT "Эксцентриситет "; EE$;
LOCATE 13, 2: PRINT "Аргумент перигея "; PP$;
LOCATE 14, 2: PRINT "Средняя аномалия "; AA$;
LOCATE 15, 2: PRINT "Количество орбит за сутки
"; MM$;
LOCATE 16, 2: PRINT "Эпохальный номер орбиты
"; OO$;
LOCATE 17, 2: PRINT "Эпохальный год "; YR;
LOCATE 18, 2: PRINT "Период обращения (минут)
"; PS# * 1440;
LOCATE 19, 2: PRINT "Высота спутника
"; R0;
LOCATE 20, 2: PRINT "Количество градусов долготы на оборот "; GS#;
LOCATE 23, 10: INPUT "Для выхода нажать <Enter> "; C: CLS
CLOSE #1
RETURN
360 PRINT
PRINT " Проверьте, не перепутаны ли
в названии спутника”
PRINT " строчные и заглавные
буквы!"
PRINT
PLAY "L3 O2 G L5 A L4
GFED L2 C" 'FEHLERCONDITION WO
SIND...
INPUT " НЕТ такого спутника! "; C:
RETURN
В листинге 5.4 должна располагаться информация, которую вы
хотите выдать пользователю. Пока здесь ничего нет.
Начиная с метки 9400 продолжается оформление главной экранной
заставки.
Начиная с метки 1000 идут строки обработки ошибок. Задается текст
строк, которые будут выдаваться на экран в случае обнаружения ошибок.
Листинг 5.4. Продолжение 3
700 CLS : COLOR 14, 1, 1: PRINT "ЗДЕСЬ пока ничего нет!"
INPUT
"Нажмите <Enter> :"; C: GOTO 10
9400 COLOR 1, 2
LOCATE 24, 6: PRINT "
ТОЛЬКО ДЛЯ НЕКОММЕРЧЕСКОГО РАСПРОСТРАНЕНИЯ И ИСПОЛЬЗОВАНИЯ ";
LOCATE 25, 6: PRINT "
Разработана Тяпичевым Г.А. (c) — RA3XB — в апреле 1999 года ";
COLOR
14, 1, 1: RETURN
9500 SOUND 990, 3: SOUND 32000, 1: SOUND 990, 1: SOUND 32000, 1:
SOUND 990, 4
RETURN
9510 FOR ISI = 1 TO 8
SOUND 990, 1: SOUND
32000, 1
NEXT ISI: RETURN
10000 PRINT ERL, ERR
STOP
10020 IF ERR = 53 THEN CLS : GOTO 10030 ELSE GOTO 10000
10030 IF ERL = 80 THEN PRINT "orbit101.cfg не найден":
GOTO 10060
IF ERL = 90 THEN PRINT
"tle1.dat не найден"
10060 PRINT "Файлы orbit101.cfg, и tle1.dat должны быть в текущей директории!"
PLAY
"L3 O2 G L5 A L4 GFED L2 C"
'FEHLERCONDITION WO SIND...
STOP
В листинге 5.5 размещаются строки программы начала расчета
элементов орбит ИСЗ. В двух строках с операторами DATA
приведен массив цифр, соответствующих числу дней от начала года до начала
расчетного месяца. Одна строка служит для високосного года, другая — для
обычного.
Далее программа запрашивает ввод даты и времени, начиная с
которого должен выполняться расчет элементов орбит.
Листинг 5.5. Продолжение 4
10100 COLOR 14, 1, 0: CLS
CLEAR
COLOR 10, 4:
LOCATE 4, 20: PRINT
"
"
LOCATE 5, 20: PRINT
" Приближенный расчет "
LOCATE 6, 20: PRINT
"
"
LOCATE 7, 20: PRINT
" орбит
спутников RS. "
LOCATE 8, 20: PRINT
"
"
LOCATE 9, 20: PRINT
" Время — местное "
LOCATE 10, 20: PRINT
"
"
COLOR 14, 1, 0
RD = 57.295779#
RM = 6371.1
TC = .0000308
UD = 1.8E+07
DATA
0,31,60,91,121,152,182,213,244,274,305,335
DATA
0,31,59,90,120,151,181,212,243,273,304,334
DIM MD(2, 12), Z0(2),
ZB(2)
FOR I = 0 TO 1: FOR J =
1 TO 12
READ MD(I, J): NEXT J:
NEXT I
DEF FNYR (Y) = SGN(Y /
4 — INT(Y / 4))
DEF FNRL (L) = L —
360 * INT(L / 360)
LOCATE 15, 10
INPUT "Нажмите
клавишу <Enter>"; C
GOSUB 300
GOSUB 15
L1 = FNRL(L1)
' Перевести эпох. время ET# в календарное
Z(1) = YR: Z(2) = ET#
'корректировка
данных NASA — эп. времени и RAAN
GOSUB 11600
HR = HR +
TZ% ' приведение к местному времени
' MI = MI — 2 ' корректировка (уменьшение) эп. времени
на 2 минуты
GOSUB
11200: EP = YR: GOSUB 11400
ET# = Z(2)
' L0 =
L0 — 6 ' корректировка
(уменьшение) RAAN на 6 градусов
В двух из шести последних строк предыдущего листинга показана
возможность корректировки времени (минуты) и RAAN
(градусы). Это можно ввести в случае обнаружения постоянных больших
несовпадений расчетного времени появления спутника в зоне радиовидимости и
времени фактического.
Начиная с метки 10600 выводится второе меню, которое служит для
начала расчетов, выбора нового спутника
и выхода из программы.
Листинг 5.6. Продолжение 5
10110 CLS : PRINT : PRINT
PRINT " Введите текущее время
сеанса связи через спутник "; SP$
INPUT " Календарная дата — день,месяц,год..."; DY, MN, YR
INPUT " Время — час,мин,сек................."; HR, MI, SC
PRINT : PRINT
PRINT " Проверьте введенные
данные"
INPUT " 1 — повторный ввод "; C: ON C GOTO 10110
Z0(1) =
Z(1): PD = PD#: R0 = (R0 + RM) / RM
NF = 120: Z0(1) = YR:
Z0(2) = Z(2)
GOSUB 11200: EP = Z0(1):
GOSUB 11400: ZB(1) = Z(1): ZB(2) = Z(2)
ND = INT((ZB(2) —
ET#) / PS#)
DT = (PS# + PD# * ND) /
NF
UT = (DT — TC) *
UD
10600 CLS
PRINT
PRINT TAB(10);
" Спутник "; SP$; " орбита N"; NR + ND
PRINT TAB(10); " Наземная станция: "; STAN$
PRINT :
PRINT
PRINT TAB(15);
" Примите решение: "
PRINT TAB(15); " ====================="
PRINT " 1 = выбрать новый спутник"
PRINT " 11 = выдать расписание сеансов связи"
PRINT
" 21 = выход"
PRINT : PRINT : PRINT
INPUT CM: ON INT(CM /
10) + 1 GOSUB 15000, 16000, 19000
GOTO 10600
Начиная с метки 11200 начинаются строки программы с непосредственными
математическими расчетами элементов орбит.
Каждая из подпрограмм имеет свою метку и краткое название, в
котором фактически содержится все необходимое разъяснение.
Листинг 5.7. Продолжение 6
11200 REM*Перевод календ.
времени в эпохальное
Z(1) = YR
Z(2) = MD(FNYR(YR), MN) +
DY + ((SC / 60 + MI) / 60 + HR) / 24
RETURN
11400 REM*Перевод Z в EP
S = SGN(EP —
Z(1)): IF S = 0 THEN GOTO 11450
FOR YR = Z(1) +
(S — 1) / 2 TO EP — (S + 1) / 2 STEP S
Z(2) = Z(2) — S *
(366 — FNYR(YR))
NEXT YR: Z(1) = EP
11450 RETURN
11600 REM*Перевод Z в календарное время
11610 EP = Z(1) + INT((Z(2) — 1) / (366 — FNYR(Z(1))))
GOSUB 11400
IF Z(2) < 1 OR Z(2)
>= 367 — FNYR(Z(1)) THEN GOTO 11610
YR = Z(1)
FOR IM = 1 TO 12
IF Z(2) >=
(MD(FNYR(YR), IM) + 1) THEN MN = IM
NEXT IM
DY = INT(Z(2) —
MD(FNYR(YR), MN)): Z(2) = Z(2) — INT(Z(2))
HR = INT(Z(2) * 24):
Z(2) = Z(2) * 24 — HR
MI = INT(Z(2) * 60):
Z(2) = Z(2) * 60 — MI
SC = INT(Z(2) * 60):
RETURN
11800 REM*Вычисление ARCSIN(X)
IF X = 1 THEN Y = 90:
GOTO 11840
IF X = -1 THEN Y = -90:
GOTO 11840
Y = RD * ATN(X /
SQR(ABS(1 — X * X)))
11840 RETURN
11900 REM*Вычисление ARCCOS(X)
IF X = 0 THEN Y = 90:
GOTO 11940
Y = RD * ATN(SQR(ABS(1 —
X * X)) / X)
IF X < 0 THEN Y = Y
+ 180
11940 RETURN
12000 REM*Вычисление ARCCTG(X)
IF X = 0 THEN Y = 90:
GOTO 12040
Y = RD * ATN(1 / X)
IF X < 0 THEN Y = Y
+ 180
12040 RETURN
12200 REM*Вычисление T2,L2,GM
X = SIN(EA / RD) *
SIN(IN / RD): GOSUB 11800: T2 = Y
IF IN > 90 THEN S =
1: GOTO 12240
S = -1
12240 IF FNRL(EA) > 180 THEN S = -S
IF T2 = 90 OR T2 = -90
THEN L2 = 0: GOTO 12270
X = COS(EA / RD) /
COS(T2 / RD): GOSUB 11900
L2 = FNRL(LA + S * Y)
12270 X = COS(T1 / RD) * COS(T2 / RD) * COS((L1 — L2) / RD)
X = X + SIN(T1 / RD) *
SIN(T2 / RD): GOSUB 11900: GM = Y
RETURN
12400 REM*Вычисление AZ
L2 = LS
IF L2 < L1 / 2 THEN
T2 = L2 / 1.8
IF L2 > L1 / 2 AND L2
< L1 THEN T2 = 90 — (L2 — L1 / 2) / 2.1
IF L2 > L1 AND L2
< 360 THEN T2 = (L2 — L1) / 2
IF L1 <> L2 THEN
GOTO 12440
IF T2 < T1 THEN AZ =
180: GOTO 12520
AZ = 0: GOTO 12520
12440 IF FNRL(L1 — L2) <> 180 THEN 12470
IF T2 < -T1 THEN AZ
= 180: GOTO 12520
AZ = 0: GOTO 12520
12470 IF T2 = 90 THEN AZ = 0: GOTO 12520
IF T2 = -90 THEN AZ =
180: GOTO 12520
X = COS(T1 / RD) * TAN(T2 / RD) — SIN(T1 / RD) *
COS((L1 — L2) / RD)
X = X / SIN((L1 —
L2) / RD): GOSUB 12000: AZ = INT(Y)
IF L2 < L1 / 2 AND
AZ < 2 THEN AZ = AZ + 180
IF L2 < L1 / 2 THEN
AZ = AZ + 180
IF L2 > L1 THEN AZ =
AZ + 180
IF AZ > 360 THEN AZ
= AZ — 360
12520 RETURN
15000 REM*К новому спутнику
RETURN 10100
В листинге 5.8
находятся строки программы, которые служат для вычисления времен входа и
выхода спутников в зону и из зоны радиовидимости, а также для вывода всех
необходимых данных на экран.
Листинг 5.8. Продолжение 7
16000 REM*Вычисление
восходящих узлов орбит
' ON CM — 20 GOTO
16020
' GOTO 16360
16020 CLS
PRINT " Проход зоны видимости
станции "; STAN$;
PRINT " спутником "; SP$
PRINT " ОРБ."; TAB(9); "Время узла"; TAB(25);
"Узел";
PRINT
TAB(36); "Вход"; TAB(48); "Выход"; TAB(60);
"Азим.";
PRINT TAB(65);
"<Enter>=продолж."
PRINT " N"; TAB(10); "чч мм сс";
TAB(25); "град"; TAB(36);
PRINT "чч
мм"; TAB(48); "чч мм"; TAB(60); "град"; TAB(68);
PRINT "1 =
выход";
DD = 0
Z0(2) = ET#
'Ниже строка задействована без дополнительной корректировки
16040 TD# = PS# * ND + PD# * ND * PS#
Z(1) = Z0(1): Z(2) =
Z0(2) + TD#: GOSUB 11600
IF DD = DY THEN 16160
IF YR < 70 THEN YR2
= 2000 + YR
DD = DY
PRINT TAB(20);
"Дата: "; DY; "."; MN; "."; YR2; "г"
' Ниже строка задействована без дополнительной корректировки
16160 LS = FNRL(GS# * ND + L0 + GS# * ND * PD#)
PRINT NR + ND; TAB(8);
HR; TAB(12); MI; TAB(16); SC;
PRINT TAB(24); INT(LS +
.5);
ZI = -1: Z0 = NF —
1: CZ = 0: X = 1 / R0: GOSUB 11900: G0 = Y
GOSUB 12400
FOR I = 0 TO NF —
1
LA = LS + (GS# + GS# *
PD#) / NF * I: EA = 360 * I / NF: GOSUB 12200
IF GM > G0 THEN GOTO
16250
IF CZ = 0 THEN CZ = 1:
ZI = I
GOTO 16260
16250 IF CZ = 1 THEN CZ = 0: Z0 = I — 1
16260 NEXT I
IF ZI = -1 THEN GOTO
16319
Z(1) = Z0(1): Z(2) =
Z0(2) + TD# + DT * ZI: GOSUB 11600
PRINT TAB(34); HR;
TAB(39); MI;
Z(1) = Z0(1): Z(2) =
Z0(2) + TD# + DT * Z0: GOSUB 11600
PRINT TAB(48); HR;
TAB(53); MI;
PRINT TAB(60); AZ;
GOTO 16320
16319 PRINT TAB(35); "Орбита за горизонтом";
16320 PRINT TAB(73);
INPUT C: ON C GOTO
16360, 16350
16350 ND = ND + 1: GOTO 16040
16360 RETURN
GOTO 16320
REM* DY — день, MN — месяц, YR — год
REM* HR — часы, MI — минуты, SC — секунды
REM* L0 — долгота восх.узла, PN — коррекция
долготы
REM* PS — период, PD — коррекция, R0 — высота
19000 REM*Выход в DOS
END
Приведенный выше листинг 5.8 можно дополнить. Например, можно
очень просто сделать одновременный вывод информации и на экран и на принтер.
Для этого в последнем продолжении следует после каждой строки с оператором PRINT дописать точно
такую же строку с оператором LPRINT.
Советую вам посредством среды программирования Visual Basic и использования
вышеприведенного листинга написать свою программу типа ORBITA
для Windows.
Очень часто для выполнения какой-либо задачи требуется
разработать специальную программу. Исходные коды основного файла одной из таких
вспомогательных программ WSPOM_RS привожу в этом разделе книги. Дело в том, что
задействованный в этой программе математический аппарат полностью соответствует
математическому аппарату программы ORBITA. Программа
разработана в среде программирования Turbo C++ v.3.
Вполне возможно, что кому-то из читателей захочется
сделать свою программу для расчета элементов круговых орбит на языке C/C++, тогда он
сможет воспользоваться кодами моей вспомогательной программы. Функции
математического аппарата этой программы в своем наименовании содержат число,
которое соответствует числовой метке точно такой же математической подпрограммы
в ORBITA.
Например, фунуция mat1800() выполняет точно такие же действия, как и
подпрограмма, начинающаяся с цифровой метки 11800 в программе ORBITA.
Начало файла wspom_rs.cpp располагается
в листинге 5.9.
В начале листинга 5.9 проводится объявление
подключаемых файлов, массива переменных с количествами дней до начала
последующего месяца, объявление прочих переменных величин и задействованных в
программе функций.
Листинг 5.9. Файл wspom_rs.cpp
/* Файл "wspom_RS" для отработки команд на Turbo C++ v.3 */
#include <iostream.h>
#include <time.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <dos.h>
#define RD 57.295779
#define RM 6371.1
#define TC 0.0000308
#define UD 1.8E+07
int md[2][12] =
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334;
int *mas;
double z02,zb2;
char *name[]={"RS-10”};
char *cl_st[]={"Ludinovo”};
int
dy,mn,yr,ep;
double
hr,mi,sc;
int
z1,s,z01,zb1,nf,az;
long n0,nd;
double z2, ut, dt;
double in, l0, pn, ps, pd;
double r0, f1, td;
double t1, t2, l1, l2;
int fn_yr,zi;
double la,gm,ls,ea,dd,xx,yy,z0,g0,fn_rl;
void print(void);
void sp_dat(void);
void ep1200(void);
void ep1400(void);
void ep1600(void);
void mat1800(void);
void mat1900(void);
void mat2000(void);
void mat2200(void);
void mat2400(void);
void mat4180(void);
void mat6000(void);
void mat6040(void);
int fnyr(double);
double fnrl(double);
int c_break(void);
В листинге 5.10 описана главная функция main() и функция, организующая прекращения работы
программы после нажатия сочетания клавиш <Ctrl>+<Break>.
Листинг 5.10. Продолжение 1
void main(void)
{
int repeat;
textbackground(1);
textcolor(14);
clrscr();
ctrlbrk(c_break);
sp_dat(); // считываются в память данные
по спутнику
ep1200(); // перевод календарного времени в эпохальное
z01 = z1;
z02 = z2;
do
{
mat4180();
mat6000();
repeat =
getchar();
if(repeat
== '\x1b') break;
}
while (repeat == 'Y' || repeat == 'y');
return;
}
int c_break(void)
{
printf("\n Нажато Ctrl-Break. Программа завершается.");
return(0);
}
В листинге 5.11 описываются функции
математического аппарата и перевода реального времени в эпохальное и наоборот.
Листинг 5.11. Продолжение 2
// Перевод календарного времени в эпохальное
void ep1200(void)
{
z1 = yr;
fnyr(z1);
z2 = md[fn_yr][mn-1] + dy + ((sc/60 + mi)/60 + hr)/24;
return;
}
// перевод Z в ЕР
void ep1400(void)
{
int i,yy,yz;
if(ep >
z1) s = 1;
if(ep <
z1) s = -1;
if(ep ==
z1) s = 0;
if(s == 0)
return;
yz = (z1 +(s-1)/2);
yy = (ep — (s + 1)/2);
if(yz <
yy) goto wyh1;
for (i = yz; i >= yy; i-- )
{
fnyr(i);
z2
=z2 — (366 — fn_yr)*s;
}
z1 = ep;
return;
wyh1:
for(i = yz; i <= yy; i++)
{
fnyr(i);
z2 =
z2 — (366 — fn_yr)*s;
}
z1 = ep;
return;
}
// перевод Z в календарное
время
void ep1600(void)
{
int im;
double nn;
fnyr(z1);
nn = ((z2 — 1)/(366 — fn_yr));
ep = z1 + floor(nn);
ep1400();
yr = z1;
fnyr(yr);
for (im = 1; im <= 12; im++)
{
if(z2
>= md[fn_yr][im-1] + 1) mn = im;
}
dy = floor(z2 — md[fn_yr][mn-1]);
if(dy >
31 || dy < 0) dy = 31;
z2 = z2 — floor(z2);
hr = floor(z2 * 24);
z2 = z2 * 24 — hr;
mi = floor(z2 * 60);
z2 = z2 * 60 — mi;
sc = floor(z2 * 60);
return;
}
// вычисление ARCSIN(X)
void mat1800(void)
{
if(xx == 1)
yy = 90; return;;
if(xx == -1)
yy = — 90; return;;
yy = RD * atan(xx/sqrt(fabs(1-xx * xx)));
return;
}
// вычисление
ARCCOS(X)
void
mat1900(void)
{
if(xx == 0) yy = 90; return;;
yy = RD * atan(sqrt(fabs(1 — xx * xx))/xx);
if(xx < 0) yy = yy +180;
return;
}
// вычисление
ARCCTG(X)
void mat2000(void)
{
if(xx == 0) yy = 90; return;;
yy = RD * atan(1/xx);
if (xx < 0) yy = yy +180;
return;
}
// вычисление T2,
L2, GM
void
mat2200(void)
{
static int ss;
xx = sin(ea/RD) * sin(in/RD);
mat1800();
t2 = yy;
if(in >
90) ss =1; goto wyh4;;
ss = -1;
wyh4:
fnrl(ea);
if(fn_rl
> 180) ss = ss * (-1);
if(t2 == 90
|| t2 == -90) l2 = 0; goto wyh5;;
xx = cos(ea/RD)/cos(t2/RD);
mat1900();
l2 = fnrl(la + ss * yy);
l2 = fn_rl;
wyh5:
xx = cos(t1/RD) * cos(t2/RD) * cos((l1 — l2)/RD);
xx = xx + sin(t1/RD) * sin(t2/RD);
mat1900();
gm = yy;
return;
}
// вычисление AZ
void mat2400(void)
{
l2 = ls;
if(l2 < l1/2) t2 = l2/1.8;
if(l2 > l1/2 && l2
< l1) t2 = 90 — (l2 -l1/2)/2.1;
if(l2 > l1 && l2
< 360) t2 = (l2-l1)/2;
if(l1 != l2) goto wyh6;
if(t2 < t1) az =
180;return;;
az = 0; return;
wyh6:
if(fnrl(l1 — l2) != 180) goto wyh7;
if(t2
< -t1) az = 180; return;;
az = 0; return;
wyh7:
if(t2
== 90) az = 0; return;;
if(t2
== -90) az = 180;return;;
xx = cos(t1/RD) * tan(t2/RD) — sin(t1/RD) *
cos((l1 — l2)/RD);
xx = xx/sin((l1 — l2)/RD);
mat2000();
az = floor(yy);
if(l2
< l1/2 && az < 2) az = az + 180;
if(l2
< l1/2) az = az + 180;
if(l2
> l1) az = az + 180;
if(az
> 360) az = az — 360;
return;
}
// задаются определенные данные, необходимые для расчетов
void mat4180(void)
{
ep1200();
z01 = z1; z02 = z2;
ps = ps/1440;
pd = pd/1440;
r0 = (r0 + RM)/RM;
t1 = 53.85; l1 = 325.35;
l1 = fnrl(l1);
l1 = fn_rl;
dy = 1; mn = 10; yr = 95;
hr = 00; mi = 00; sc = 00;
ep1200();
ep = z01;
ep1400();
zb1 = z1; zb2 = z2;
/*
printf("Число zb1 = %d, число zb2 = %f,число z1 = %d, число z02 =
%f",zb1,zb2,z1,z02);
*/
nd = floor((zb2 — z02)/ps);
dt = (ps + pd * nd)/nf;
ut = (dt — TC) * UD;
// printf("Величина nd = %ld, Значение dt =
%3.6f, Величина ut = %3.6f",nd,dt,ut);
return;
}
В листинге 5.12 описана функция, выполняющая
вывод на экран всей необходимой информации. Сначала выводятся строки заголовка,
затем строки с информацией.
Листинг 5.12. Продолжение 3
//вычисление восходящих узлов орбит
void mat6000(void)
{
int i, letter;
static int cz;
printf("\nПроход спутником %s зоны
видимости станции %s",name[0], cl_st[0]);
printf("\nОрб. Время узла Узел
Вход Выход Азим ");
printf("\n No
чч мм сс град. чч мм чч мм
град.");
whod30: dd =
0;
whod40: td
=ps * nd + pd * nd * (nd -1)/2;
z1 = z01;
z2 = z02 + td;
ep1600();
if(dd ==
dy) goto whod160;
dd = dy;
cout <<"\n Дата: " << dy <<
" — " << mn << " — " << yr;
whod160: ls =
fnrl(pn * td +l0); ls = fn_rl;
if(ls <
0) ls = 360 + ls;
printf("\n%6ld%4.0f%3.0f%3.0f%7.0f",(n0 +
nd),hr,mi,sc,ls);
ls = fnrl(pn * td + l0); ls = fn_rl;
zi = -1; z0 = nf -1; cz = 0; xx = 1/r0;
mat1900();
g0 = yy;
mat2400();
for(i = 0; i <= (nf-1); i++)
{
la = ls +
pn * dt * i;
ea = 360 *
i/nf;
mat2200();
//cout<<"\n+++ cz = "<< cz;
if(gm >
g0) goto wyh250;
if(cz == 0)
{cz = 1; zi = i;};
goto
wyh260;
//cout<<"... zi = " <<zi <<" z0 = "<<z0 << " cz = " << cz;
wyh250: if(cz
== 1) cz = 0; z0 = i — 1;;
wyh260:
}
if(zi ==
-1) goto wyh319;
z1 = z01;
z2 = z02 + td + dt * zi;
// printf("\n,,,,, z2 = %f .... td = %f ... dt =
%f .... zi = %d..,,,.",z2,td,dt,zi);
ep1600();
printf("%6.0f %3.0f",hr,mi);
z1 = z01;
z2 = z02 + td +dt * z0;
// printf("\n**** z2 = %f *** td = %f *** dt = %f
*** z0 = %d **",z2,td,dt,z0);
ep1600();
printf("%6.0f %3.0f %6d ",hr,mi,az);
letter = getchar();
if(letter == 'x' || letter == 'X') return;
nd = nd + 1;
goto whod40;
wyh319:
printf(" Орбита за горизонтом
");
letter = getchar();
if(letter == 'x' || letter == 'X') return;
nd = nd + 1;
goto whod40;
wyh360:
return;
}
В листинге 5.13 описаны вспомогательные функции,
необходимые для выполнения расчетов.
Листинг 5.13. Продолжение 4
// вспомогательная функция для определения високосного
года
int fnyr(double x)
{
double y = 4.0;
double result;
result = fmod(x,y);
if(result == 0) goto wyh1;
fn_yr = 1;
return(fn_yr);
wyh1: fn_yr = 0; return(fn_yr);
}
// вспомогательная функция
double fnrl(double l)
{
double x;
// if(l >
360) x = l -360;
// x = l;
x = (l — 360 * floor(l/360));
/* printf("^^^^^
fn_rl = %d",x); */
fn_rl = x;
return(fn_rl);
}
// задает определенные кеплеровские данные
void sp_dat(void)
{
n0 = 38700;
dy = 27;
mn = 9;
yr = 95;
hr = 0; mi = 46; sc = 13;
in = 83.0; l0 = 330.0;
pn = 362.0498;
ps = 104.98413;
pd = -0.0000001;
r0 = 1008.4;
nf =
120;
return;
}
Ниже располагаются листинги файла cw_qso.cpp, созданного в среде
программирования Turbo C++ v.3. Этот файл с исходными кодами программы CW_QSO
предлагается вам для рассмотрения и создания, на базе разработанных мною
исходных кодов, своих собственных программ для радиосвязи телеграфом.
В начальной части листинга 5.14 проводится объявление
подключаемых файлов, задействованных в программе функций и переменных величин.
Кроме того, здесь же размещены и специальные таблицы, необходимые для
кодирования символов при передаче и декодирования символов при приеме, а также
некоторые из текстов, которые часто используются в программе.
Листинг 5.14. Файл cw_qso.cpp
/*****************************************************************/
/* PROGRAMM_NAME CW_QSO v.1.10 (c) RA3XB */
/*****************************************************************/
/* Программа
для проведения CW
(телеграфной) любительской */
/* радиосвязи посредством компьютера
IBM PC. */
/* Автор разработки — Тяпичев Геннадий
А. < RA3XB > */
/* Начало: май 1998г, продолжено в мае
2000 года */
/*****************************************************************/
/* Программа создавалась на Turbo C++ v.3 */
/*****************************************************************/
#include <iostream.h>
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <process.h>
#include <ctype.h>
#include <string.h>
#include <bios.h>
#include <conio.h>
#include <sys/timeb.h>
#include <time.h>
#include "cw_qso1.h"
#include <alloc.h>
#define BORDER 1
#define ESC 27
#define REV_VID 0x70
#define NORM_VID 0x4a
#define MAX 250
#define FILENAME "qso_log.dat"
#define FILESPEC "cw_qso.spc"
#define FILEHLP "cw_qso.doc"
FILE *fp;
FILE *log_file;
FILE *init_file;
FILE *send_file;
FILE *save_file;
FILE *printer;
void bord_col(int num);
void draw_border(int startx,
int starty,int endx,int endy);
void write_video(int x,int
y,char *p,int attrib);
void save_video(int startx,int
endx,int starty,int endy,unsigned int *buffer);
void restore_video(int
startx,int endx,int starty,int endy,unsigned int *buffer);
void goto_xy(int x,int y),
cls(int zwet), scren_col(int rez);
void wind_zw(int attr, int
starx,int starty, int x, int y);
void
zastawka(void),zastawka2(void);
void err_wind(char *txt,int
x,int y, int endx,int endy);
void write_string(int x,int
y,int attrib,char *p);
void write_char(int x,int
y,char ch, int attrib);
void display_help(int x,int
y,int count);
void zabitie(int x,int y,int
attrib,int len);
void pered_simw(int ch);
void pauza(int count);
void zwuk(int count);
void perek_zw(void);
void peredacha(void);
void getxy(void);
void get_time(void); //int
date_flag);
void read_string(int x,int
y,int len,char *p);
void read_word(int x, int y,int
len,char *p);
void scr_scrup(int attr,int
x,int y,int x1,int y1);
void init_sys(),send_str(char
*str);
void cls_rx(void),cls_tx();
void copy_buf(int count);
void promt(char *text,int x,int
y, int endx,int endy);
void send_buf0(int x,int y,int
len,int attrib);
void send_buf1(int x,int y,int
len,int attrib);
void co_buf(int x,int y,int
len,int count,int attrib);
void write_simw(int ch, int
attrib);
void
wyzow(void),wyzow1(void),wyzow2(void);
void
wyhod(void),wyhod2(void),wyhod3(void);
void alt_f2(), alt_f3(),
alt_f4(), alt_f5();
void
alt_f6(),alt_f7(),alt_f8(),alt_f9(),alt_f10();
void copy_buf_fl(int x);
void cls_buf1(int
len),cls_buf0(int len);
void mouse(void);
int init_str(char *str, int
len),exec_cmd(int ch);
void izm_skor_p(void),izm_ton(void),izm_ton1(void);
void uwel_skor(void),
umen_skor(void);
void
addqso(void),nomer_qso(void),getslots(void),wlist(void);
void ctrl_msg(void);
void
ct_f5(void),ct_f6(void),ct_f7(void),ct_f8(void),ct_f9(void);
void
ust_dtr(void),ust_rts(void),ust_dtr_rts(void),sbros_dtr_rts(void);
void ProwSBl(void);
void NullRegistr(void);
void SetKanal(void);
void SetRegistr(void);
void SBlRegSet(int,int);
int inport(void);
void priem(void);
void perekl(void);
void rx_read(void);
void izm_pr(void),izm_pr1(void),izm_skor_priema(void);
void rus_lat(void);
void djoist(void);
void dis_help(void);
void cursor_ubrat(void);
void t_wysok(void),
t_nizk(void);
locate();
struct {
char frequency[5];
char mode[6];
char tim[8];
char date[12];
char call_sign[9];
char rst_sent[5];
char rst_rcvd[5];
char name_k[10];
char qth[13];
char comments[65];
char contest[17];
int number;
} qso;
struct CD
{
char name[9];
char diap[5];
char date[12];
char tim[8];
char rs1[5];
char rs2[5];
char namkor[10];
char qth[13];
char mod[6];
char category[17];
char infor[65];
int number;
} disc;
unsigned char simwol;
short int skorost;
short int skorost2;
int znak;
int flag_zw = 1;
unsigned int xx1,yy1;
unsigned int xx0=3,yy0=0;
unsigned int ton = 1000;
unsigned char far *vid_mem;
int slots[MAX];
int prt,prt1,i;
int flag_rus = 0;
unsigned int simw_nom; // номер символа в таблице
char simwol2;
unsigned int sch_pomeh = 5; // данные счетчика помех
unsigned int sch_posylok = 8; // данные счетчика посылок
char port[7];
char my_call[15];
char my_name[20];
char my_qth[25];
char my_log[80];
char save_fn[80];
char buf1[400];
char buf2[4000];
char buf0[80];
char temper[10];
int tabl[] =
{0x55,0x31,0x40,0x32,0x3f,0x2f,0x27,0x23,0x21,0x20,0x30,0x38,0x3c,0x3e,
0x78,0x36,0x2a,0x45,0x28,0x4c,0xc5,0x05,0x18,0x1a,0x0c,0x02,0x12,0x0e,
0x10,0x04,0x17,0x0d,0x14,0x07,0x06,0x0f,0x16,0x1d,0x0a,0x08,0x03,0x09,
0x11,0x0b,0x19,0x1b,0x1c,0x6d,0x73,0x6d,0x7d,0x80,0x13,0x05,0x18,0x1a,
0x0c,0x02,0x12,0x0e,0x10,0x04,0x17,0x0d,0x14,0x07,0x06,0x0f,0x16,0x1d,
0x0a,0x08,0x03,0x09,0x11,0x0b,0x19,0x1b,0x1c,0x1f,0x24,0x15,0x1e,0x80};
int abc[] = {
238,160,161,230,164,165,228,163,229,168,169,170,171,172,173,174,
175,233,224,225,226,227,166,162,236,235,167,232,237,239,231,234,
158,128,129,150,132,133,148,131,149,136,137,138,139,140,141,142,
143,153,144,145,146,147,134,130,156,155,135,152,157,159,151,154,
96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
81,82,83,84,85,86,87,88,89,90,123,124,125,126,88,
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,88};
char tab1[] ={
00,'E','T','I','A','N','M','S','U','R','W','D','K','G','O','H', 'V','F','ю','L','я','P','J','B','X','C','Y','Z','Q','ч','ш','5',
'4', 00,'3', 00, 00, 00,'2',
00, 00, 00, 00, 00, 00, 00,'1','6',
00,'/', 00, 00, 00, 00, 00,'7',
00, 00, 00,'8', 00,'9','0','>',
00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00,'?', 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00,
'-'};
char tab2[] ={ 00,'е','т','и','а','н','м','с','у','р','в','д','к','г','о','х', 'ж','ф','ю','л','я','п','й','б','ь','ц','ы','з','щ','ч','ш','5',
'4', 00,'3', 00, 00, 00,'2',
00, 00, 00, 00, 00, 00, 00,'1','6',
00,'/', 00, 00, 00, 00, 00,'7',
00, 00, 00,'8', 00,'9','0','>',
00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00,'?', 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00,
'-'};
char *txt1[] = { "Нажмите <Enter> " };
char *txt2[] = { "CW" };
char *txt3[] = { "* * * ПЕРЕДАЧА * * * " };
char *txt4[] = { "* * * ПРИЕМ * * * "};
char *txt5[] = {
" <Alt-X>-выход; <Alt-Fn>-тексты; <Home>-передача; <End>-прием; <F1>-HELP"};
char *txt7[] = { "Выходим в DOS ? (Y/N)
"};
char *txt8[] = {"CALL: "};
char *txt9[] = {"NAME: "};
char *txt10[]= {"QTH: "};
char *txt11[]= {"RST: "};
char *txt12[]= {"темпер.: "};
char *txt20[]= {"Введите ПОЗЫВНОЙ
корреспондента"};
char *txt21[]= {"Введите ИМЯ
корреспондента и RST"};
char *txt22[]= {" Введите ИМЯ файла"};
char *txt23[]= {"НЕ ЗАБУДЬТЕ ввести
данные по QSO!!!"};
int ch_k;
int
ch_n;
int yy=0;
int xx=3;
int col;
int row;
int flag1 = 0;
int date_flag = 0;
int save = 0;
int print =0;
int border = 0;
int v_attribute;
int count,ch;
int old_x,old_y;
unsigned int nomer = 0;
char help,str;
unsigned int com_x;
int com_adr1 = 0x2fc;
int com_adr2 = 0x2fe;
int nn,pp;
int del1 = 2;
int del2 = 10;
В листинге 5.15 размещена основная функция
программы — main(). Начальная часть
функции main() содержит вызовы функций для
инициализации программы, вывод на экран рабочих заставок и задание определенных
значений некоторым из переменных.
Листинг
5.15. Продолжение 1
main() // Начало подпрограммы main()
{
init_sys(); // инициализация программы
zastawka(); // выдает на экран первую заставку
zastawka2(); // выдает на экран рабочую заставку
skorost = 24; // назначается начальная величина
скорости
skorost2 = skorost;
ton = 1000; // назначается начальный тон 1000 Гц
outportb(0x201,0x10); // открывает порт джойстика
izm_skor_p(); // устанавливает начальную скорость
izm_skor_priema();
zabitie(2,31,0x0,14);
write_string(2,31,0xf,*txt4);
if(xx1 < 3) xx1 = 4;
goto_xy(xx1-1,yy1);
cursor_ubrat();
whod1:
get_time(); // выдает на экран текущее
время
if(kbhit()) perekl(); // задействует функцию переключения
prt = inport(); // получить данные из порта для
// проверки
наличия сигнала
if(prt == 1) priem(); // если сигнал
есть, перейти на прием
prt1 = inportb(0x201); // проверяем
нажатие джойстика
if(prt1 == 239 || prt1 == 223)
djoist(); // работа джойстика
goto whod1;
}
// конец подпрограммы
main();
Описание функции main() окончилось. Далее идет описание всех остальных
функций, задействованных в программе. В листинге 5.16 описываются
следующие функции:
q
работа порта джойстика в
режиме полуавтоматического телеграфного ключа;
q
большая функция всех
переключений, задействованных в программе;
q
функция
инициализации программы, в которой проводится проверка наличия в каталоге всех
необходимых файлов, устанавливается режим работы COM-порта и звуковой карты
компьютера.
Листинг 5.2. Продолжение 2
// убрать курсор
(погасить)
void
cursor_ubrat(void)
{
union REGS r;
r.h.ah=1;
r.h.ch=0x20;
int86(0x10,&r,&r);
return;
}
// джойстик — полуавтоматический телеграфный ключ
void djoist(void)
{
whd1:
if(prt1 == 239) {zwuk(2); pauza(2); goto
wyh1;}
if(prt1 == 223) {zwuk(7); pauza(2);}
wyh1:
prt1 = inportb(0x201);
if(prt1 == 239 || prt1 == 223) goto whd1;
sbros_dtr_rts();
return;
}
// Переключения,
задействованные в программе
void
perekl()
{
ch_k = getch();
if(ch_k == 0) { ch_k = getch() + 128;}
if(ch_k == 27) {sbros_dtr_rts();exit(1);}
/* Esc — быстрый выход */
if(ch_k == 192) goto wyh1; /* F6
— ввод CALL
*/
if(ch_k == 193) goto wyh2; /* F7
— ввод NAME
*/
if(ch_k == 194) goto wyh3; /* F8
— ввод QTH
*/
if(ch_k == 195) goto wyh4; /* F9
— ввод RST
*/
if(ch_k == 196) goto wyh5; /* F10
— ввод температуры */
if(ch_k == 223) perek_zw(); /* Ctrl-F2 — переключение
звука */
if(ch_k == 223) cls_rx(); /* Ctrl-F3 — очистка окна приема*/
if(ch_k == 224) cls_tx(); /* Ctrl-F4 — очистка окна передачи*/
if(ch_k == 261) addqso(); /* F11 — ввести QSO в журнал */
if(ch_k == 262) zastawka2(); /*
F12 — обновление экрана */
if(ch_k == 215)
{wlist();zastawka2();}/* Shift-F4 — чит.журнал*/
goto whod2;
wyh1: write_string(0,3,0x07,txt8[0]);
zabitie(0,9,0x5b,16); goto whod2;
wyh2: write_string(1,3,0x07,txt9[0]);
zabitie(1,9,0x5b,16); goto whod2;
wyh3: write_string(2,4,0x07,txt10[0]);
zabitie(2,9,0x5b,16); goto whod2;
wyh4: write_string(0,60,0x07,txt11[0]);
zabitie(0,65,0x5b,14); goto whod2;
wyh5: write_string(1,56,0x07,txt12[0]);
zabitie(1,65,0x5b,8); goto whod2;
whod2:
if(ch_k == 192) goto wyh10;
//F6 — ввод CALL
if(ch_k == 193) goto wyh11;
//F7 — ввод NAME
if(ch_k == 194) goto wyh12;
//F8 — ввод QTH
if(ch_k == 195) goto wyh13;
//F9 — ввод RST
if(ch_k == 196) goto wyh14;
//F10 — ввод температуры
exec_cmd(ch_k);
return;
wyh10:
if(flag1 == 0) {xx = 0; yy =9; flag1
= 1;}
ch_n = getch();
write_char(xx,yy,ch_n,0x5b);
if(ch_n == 13 || ch_n == 3) {
write_string(0,3,0x4e,txt8[0]); flag1
= 0;
read_word(0,9,6,qso.call_sign);
locate();
return;}
yy++;
goto whod2;
wyh11:
if(flag1 == 0) {xx = 1; yy =9; flag1
= 1;}
ch_n = getch();
write_char(xx,yy,ch_n,0x5b);
if(ch_n == 13 || ch_n == 3) {
write_string(1,3,0x4e,txt9[0]); flag1 =
0;
read_word(1,9,8,qso.name_k); return;}
yy++; goto whod2;
wyh12:
if(flag1 == 0) {xx = 2; yy =9; flag1
= 1;}
ch_n = getch();
write_char(xx,yy,ch_n,0x5b);
if(ch_n == 13 || ch_n == 3) {
write_string(2,4,0x4e,txt10[0]);
flag1 = 0;
read_word(2,9,8,qso.qth); return;}
yy++; goto whod2;
wyh13:
if(flag1 == 0) {xx = 0; yy =65;
flag1 = 1;}
ch_n = getch();
write_char(xx,yy,ch_n,0x5b);
if(ch_n == 13 || ch_n == 3) {
write_string(0,60,0x4e,txt11[0]);
flag1 = 0;
read_word(0,65,5,qso.rst_sent);
return; }
yy++; goto whod2;
wyh14:
if(flag1 == 0) {xx = 1; yy =65;
flag1 = 1;}
ch_n = getch();
write_char(xx,yy,ch_n,0x5b);
if(ch_n == 13 || ch_n == 3) {
write_string(1,56,0x4e,txt12[0]);
flag1 = 0;
read_word(1,65,6,temper); return; }
yy++; goto whod2;
wyh6:
err_wind(txt7[0],19,10,23,69);
if(ch_k == 121 || ch_k == 89) {
sbros_dtr_rts(); exit(1); }
else
goto_xy(18,0); return;
wyh7:
return;
}
// Инициализация
программы
void init_sys()
{
char ch, *err;
init_file =
fopen("CW_QSO1.CFG", "r");
if (init_file == 0) {
printf("НЕ открывается
файл 'CW_QSO1.CFG'\n");
printf("\nСоздайте текстовым редактором
следующее:\n");
printf(" COM — порт\n");
printf(" позывной своей р/станции\n");
printf(" свое имя\n");
printf(" свой город (QTH)\n");
printf(" имя Log файла и путь к нему\n");
printf(" имя Save файла и путь к нему\n");
getchar();
exit(1);
}
else {
// чтение строк
конфигурационного файла
init_str(port, 7);
init_str(my_call, 15);
init_str(my_name, 20);
init_str(my_qth, 25);
init_str(my_log, 80);
init_str(save_fn, 80);
init_str(temper,10);
init_str(qso.call_sign,10);
init_str(qso.name_k,15);
init_str(qso.qth,20);
init_str(qso.rst_sent,6);
}
fclose(init_file);
if(strcmp(port,"COM1")==0) {com_x
= 0; com_adr1=0x3fc; com_adr2=0x3fe;}// goto wyh;}
if(strcmp(port,"COM2")==0) {com_x
= 1; com_adr1=0x2fc; com_adr2=0x2fe;}//goto wyh;}
if(strcmp(port,"COM3")==0) {com_x
= 2; com_adr1=0x3ec; com_adr2=0x3ee;}// goto wyh;}
if(strcmp(port,"COM4")==0) {com_x
= 3; com_adr1=0x2ec; com_adr2=0x2ee;}//goto wyh;}
_bios_serialcom(_COM_INIT,com_x,_COM_1200|_COM_CHR8|_COM_STOP1);
// Инициализация
компьютерной звуковой карты
ProwSBl();
NullRegistr();
SetKanal();
SetRegistr();
SBlRegSet(0xb0, 0x11);
nomer_qso();
}
// Проверка наличия
конфигурационного файла
int init_str(char *str, int
len)
{
char *err;
err = fgets(str, len, init_file);
if (err == NULL) {
printf("Ошибка чтения файла CW_QSO1.CFG\n");
exit(1);
}
str[strlen(str) — 1] = 0;
return(0);
}
В листинге 5.17 располагается функция приема символов. Эта
функция использует при декодировании принятых сигналов определенные константы,
которые оператор назначает сам при изменении скорости приема. Каждая такая
константа действует в некотором диапазоне частот, поэтому оператор должен сам
примерно определять, с какой скоростью поступают сигналы от корреспондента. В
программах зарубежных разработчиков используется другой метод — метод
автоматической настойки программы на скорость поступающих сигналов. Этот метод
мне не нравится тем, что программа,
работающая по методу автоматической настройки, при этой самой автоматической
перестройке теряет как минимум один символ. Поскольку такая перестройка
происходит после каждой паузы, то символов теряется очень много.
В используемом мною варианте никаких потерь при перестройке не
происходит, так как никакой перестройки не проводится. Программа сразу начинает
прием любого символа после любой паузы.
Листинг 5.17. Продолжение 3
// подпрограмма приема
символа
void priem(void)
{
unsigned int ee, hh;
unsigned int simw_nom;
n1:
simw_nom = 0;
ee=sch_pomeh;
s1: ee--;
if(ee == 0) goto v1; // сигнал прошел
проверку на имп. помеху
delay(del1);
prt = inport(); // получить данные из порта и
// проверить на
наличие сигнала
if(prt == 1) goto s1; // если сигнал
есть, продолжить проверку
// сигнала, не
является ли он помехой
goto wyh0; // на выход из подпрограммы, т. к.
сигнал был помехой
// если сигнал не помеха, он
проходит далее для анализа
v1:
hh = sch_posylok; // включить
счетчик для проверки сигнала
va1: hh--;
if(hh == 0 ) goto l1; // сигнал длительнее
точки, анализировать далее
delay(del2);
prt = inport(); // получить данные из порта
// проверить на
наличие сигнала
if(prt == 1) goto va1; //продолжить
проверку
simw_nom++; // сигнал кончился досрочно, это
точка
goto k1; // проверить длительность паузы
после точки
l1: hh = sch_posylok; // провести доп.анализ длительного сигнала
la1:
hh--;
if(hh == 0) goto z1; // сигнал длиннее
тире
delay(del2);
prt = inport();
if(prt == 1) goto la1; // сигнал присутствует
z1:
za1: prt = inport();
if(prt == 1) goto za1; // дождаться
окончания длинного сигнала
simw_nom= simw_nom+2; // сигнал кончился, похоже, что это
// тире
k1:
hh = sch_posylok; // начало
проверки паузы
ee = sch_pomeh;
q1:
ee--;
if(ee == 0) goto r1; //пауза прошла проверку на помеху
delay(del1);
prt = inport();
if(prt != 1) goto q1; //пауза продолжается
goto tt;
// пауза есть интервал между посылками
r1:
hh--;
if(hh == 0) goto pa1; // пауза пошла
на дальнейшую проверку
delay(del2);
prt = inport();
if(prt != 1) goto r1;
goto tt;
pa1: hh = sch_posylok; // проверка паузы, не является ли она
// интервалом между буквами
p1:
hh--;
if(hh == 0) goto m0; // пауза есть интервал между буквами,выход
delay(del2);
prt = inport();
if(prt != 1) goto p1; //пауза продолжается
goto m2;
//пауза кончилась, на выход
tt: simw_nom = simw_nom * 2; // продолжаем дальше исследовать символ,
goto v1;
m2:
if(flag_rus == 1) simwol2 = tab2[simw_nom];
else simwol2 = tab1[simw_nom];
rx_read();
hh = sch_posylok; // провести доп.анализ паузы
la8: hh--;
if(hh == 0) goto m7; // пауза
длинная — выдать пробел
delay(del2);
prt = inport();
if(prt != 1) goto la8; // сигнала нет
goto n1;
m0:
if(flag_rus == 1) simwol2 = tab2[simw_nom];
else simwol2 = tab1[simw_nom];
rx_read();
hh = sch_posylok; // провести доп.анализ паузы
la7: hh--;
if(hh == 0) goto m7; // пауза
длинная — выдать пробел
delay(del2);
prt = inport();
if(prt != 1) goto la7; // сигнала нет
goto n1;
// сигнал появился
t1: simwol2 = 0x2e;
rx_read();
goto n1;
m7:
simwol2 = 0x20;
rx_read();
wyh0: return;
}
// подпрограмма
проверки наличия сигнала от приемника
int
inport(void)
{
int ch;
asm{
mov dx, com_adr2
in al, dx
and al,00010000b
jz wyh1
jnz wyh2
}
wyh1: prt = 0; t_nizk(); return prt;
wyh2: prt = 1; t_wysok();
return prt;
}
// тон высокий
void t_wysok(void)
{
goto_xy(0,32); putchar('o');
goto_xy(0,49); putchar(' ');
return;
}
// тон низкий
void t_nizk(void)
{
goto_xy(0,32); putchar(' ');
goto_xy(0,49); putchar('o');
return;
}
В листинге 5.18 размещены функции заставок. Эти функции не
представляют интереса, но я не стал их убирать, чтобы дать один из возможных
вариантов оформления. На мой взгляд, не самый лучший. У вас должно получиться
лучше.
Листинг 5.18. Продолжение 4.
// заставка начальная
void zastawka(void)
{
int i;
scren_col(3);
cls(0x0e);
draw_border(0,1,23,78);
wind_zw(0x70,2,5,7,74);
wind_zw(0x1e,8,5,14,74);
wind_zw(0xc0,15,5,21,74);
wind_zw(0x5e,5,13,17,66);
draw_border(5,14,17,65);
goto_xy(7,30);
printf(" П Р О Г Р А М М А ");
goto_xy(9,32);
printf(" CW_QSO v.1.10 ");
goto_xy(11,20);
printf("для проведения любительской
радиосвязи");
goto_xy(12,25);
printf("посредством компьютера IBM
PC");
goto_xy(14,18);
printf("Разработана Тяпичевым
Геннадием А. (c) RA3XB");
goto_xy(16,32);
printf("ноябрь 2000 года");
goto_xy(24,32);
printf("Нажмите <Enter> ");
getch();
}
// заставка рабочая — рабочий экран
void zastawka2(void)
{
cls(0x07);
wind_zw(0x6e,0,0,2,7);
goto_xy(0,3); puts("CALL:");
goto_xy(1,3); puts("NAME:");
goto_xy(2,4); puts("QTH:");
wind_zw(0x6e,0,56,2,63);
goto_xy(0,60); puts("RST:");
goto_xy(1,56); puts("темпер.:");
goto_xy(2,56); puts("скорость");
wind_zw(0x5a,0,8,2,25);
wind_zw(0x5a,0,64,2,79);
wind_zw(0x5a,17,0,15,79);
goto_xy(17,2);
puts("Принтер: ОТКЛ
*** Автор — RA3XB, 2000г ***
Файл сохранения: ОТКЛ");
write_video(0,39,*txt2,0xc); /* надпись
CW */
write_video(2,31,*txt4,0xf); /* надпись ПРИЕМ */
wind_zw(0x5b,24,1,24,78);
goto_xy(24,1);
write_video(24,1,*txt5,0x5b);
wind_zw(0x1e,18,0,23,79);
wind_zw(0x1d,3,0,16,79); goto_xy(16,0);
goto_xy(1,74);
printf("%dГц",ton);
izm_skor_p();
izm_skor_priema();
goto_xy(0,9);
printf("%s",qso.call_sign);
goto_xy(1,9);
printf("%s",qso.name_k);
goto_xy(2,9);
printf("%s",qso.qth);
goto_xy(0,65);
printf("%s",qso.rst_sent);
goto_xy(1,65);
printf("%s",temper);
return;
}
В листинге 5.19 приведены различные вспомогательные функции
для работы с выводом текста на экран, для работы с цветом. Здесь также
размещены функции, организующие вывод на экран вспомогательных информационных
окон.
Листинг 5.19. Продолжение 5.
/* ввести цвет бордюра */
void
bord_col(int num)
{
union REGS r;
r.h.ah=0x0b;
r.h.bh=0;
r.h.bl=num;
int86(0x10,&r,&r);
return;
}
/* установка курсора */
void goto_xy(int x,int y)
{
union REGS r;
r.h.ah=2; /* функция установки курсора */
r.h.dl=y; /* координата колонки */
r.h.dh=x; /* координата строки */
r.h.bh=0; /* видеостраница */
int86(0x10,&r,&r);
return;
}
/* нарисовать обрамление окна — цветную
рамку */
void
draw_border(int startx,int starty,int endx,int endy)
{
register int i;
for(i=startx;i<endx;i++) {
goto_xy(i,starty);
putchar(186);
goto_xy(i,endy);
putchar(186);
}
for(i=starty;i<endy;i++) {
goto_xy(startx,i);
putchar(205);
goto_xy(endx,i);
putchar(205);
}
goto_xy(startx,starty); putchar(201);
goto_xy(startx,endy ); putchar(187);
goto_xy(endx ,starty); putchar(200);
goto_xy(endx ,endy
); putchar(188);
return;
}
/* вывод строки с определенным атрибутом */
void
write_video(int x,int y,char *p,int attrib)
{
union REGS r;
register int i,j;
for(i=y; *p; i++) {
goto_xy(x,i);
r.h.ah=9; /* функция записи символа */
r.h.bh=0; /* видео страница */
r.x.cx=1; /* число повторений символа */
r.h.al=*p++; /* символ */
r.h.bl=attrib; /* атрибут */
int86(0x10,&r,&r);
}
return;
}
/* вывод одного
символа на экран в цвете */
void
write_simw(int ch,int attrib)
{
union REGS r;
r.h.ah=9; /* функция вывода символа */
r.h.bh=0; /* видео страница */
r.x.cx=1; /* число повторений символа */
r.h.al=ch; /* символ */
r.h.bl=attrib; /* атрибут */
int86(0x10,&r,&r);
}
/* сохранение части экрана */
void
save_video(int startx,int endx,int starty,int endy,unsigned int *buffer)
{
union REGS r;
register int i,j;
for(i=starty;i<endy;i++)
for(j=startx;j<endx;j++) {
goto_xy(j,i);
r.h.ah=8; /* функция чтения символа */
r.h.bh=0; /* видео страница */
*buffer++ = int86(0x10,&r,&r);
putchar(' ');
/* очистка экрана */
}
return;
}
/* восстановление части экрана */
void restore_video(int startx,int endx,int
starty,int endy,unsigned int *buffer)
{
union REGS r;
register int i,j;
for(i=starty;i<endy;i++)
for(j=startx;j<endx;j++)
{
goto_xy(j,i);
r.h.ah=9; /* функция записи
символа */
r.h.bh=0; /* видео страница */
r.x.cx=1; /* число повторений
символа */
r.h.al=*buffer++;
/* символ
*/
r.h.bl=0x1d;
int86(0x10,&r,&r);
}
return;
}
/* очистка экрана */
void cls(int zwet)
{
union REGS r;
r.h.ah=6; /* код прокрутки
экрана */
r.h.al=0; /* код очистки экрана */
r.h.ch=0; /* начальная строка */
r.h.cl=0; /* начальная колонка */
r.h.dh=24; /* конечная строка */
r.h.dl=79; /* конечная колонка */
r.h.bh=zwet; /* фон и цвет букв */
int86(0x10,&r,&r);
return;
}
/*
Установка цветового режима экрана
*/
void scren_col(int rez)
{
union REGS r;
r.h.ah=0; /*функция установки режима*/
r.h.al=rez;/*1 или 3 или другой режим
экрана*/
int86(0x10,&r,&r);
return;
}
/*
Установка активной видеостраницы
*/
void stran(int num)
{
union REGS r;
r.h.ah=5; /*функция выбора страницы*/
r.h.al=num; /*номер выбираемой
страницы*/
int86(0x10,&r,&r);
return;
}
/*
Задать окно (цветное) */
void wind_zw(int attr,int startx,int
starty,int x,int y)
{
union REGS r;
r.h.ah=6;
r.h.al=0;
r.h.bh=attr;/*цвет фона и букв*/
r.h.ch=startx;
r.h.cl=starty;
r.h.dh=x;
r.h.dl=y;
int86(0x10,&r,&r);
return;
}
/* Вывести на экран строку с
дополнительными атрибутами */
void
write_string(int x, int y, int attrib,char *p)
{
register int i;
unsigned char far *v;
vid_mem =(unsigned char far
*)0xb8000000;
v = vid_mem;
v += (x*160) + y*2; /* вычислить
адрес */
for(i=y;i<=(y+strlen(p) + 2);i++) {
*v++ = *p++; /*
вывести символ */
*v++ = attrib;
}
return;
}
/* прочитать строку из видеопамяти в буфер */
void
read_string(int x,int y,int len, char *p)
{
register int i;
unsigned char far *v;
vid_mem =(unsigned char far
*)0xb8000000;
v = vid_mem;
v += (x*160) + y*2; /* вычислить
адрес */
for(i=y;i<=(y+strlen(p) + len);i++) {
*p++ = *v++; /*
вывести символ из памяти в строку*/
*v++;
}
return;
}
/* прочитать слово из видеопамяти в буфер */
void
read_word(int x,int y,int len,char *p)
{
register int i;
unsigned char far *v;
vid_mem =(unsigned char far
*)0xb8000000;
v = vid_mem;
v += (x*160) + y*2; /* вычислить
адрес */
for(i=y;i<=(y+strlen(p) + len);i++) {
*p++ = *v++; /*
вывести символ из памяти в строку*/
*v++;
}
return;
}
// Заполняет строку нулями
void zabitie(int x, int y, int attrib,int len)
{
register int i;
unsigned char far *v;
vid_mem =(unsigned char far
*)0xb8000000;
v = vid_mem;
v += (x*160) + y*2; /* вычислить
адрес */
for(i=y;i<=(y+len);i++) {
*v++ = 0; /*
вывести символ */
*v++ = attrib;
}
return;
}
/* Вывести символы с определенными атрибутами
*/
void
write_char(int xx, int yy, char ch, int attrib)
{
register int i;
unsigned char far *v;
vid_mem =(unsigned char far
*)0xb8000000;
ch = ch_n;
v =vid_mem;
v += (xx*160) + yy*2;
if(ch == 13 || ch == 3) return;
*v++ = ch; /*
вывести символ */
*v++ = attrib; /* вывести атрибуты
*/
yy++;
return;
}
// Создать окно для подтверждения выхода в DOS
void
err_wind(char *txt,int x,int y,int endx,int endy)
{
unsigned int *p;
/* размещение памяти для видео буфера */
p=(unsigned int*)malloc((endx-x+1)*(endy-y+1));
if(!p) exit(1); /* Вы можете здесь сами
обработать ошибку */
/* сохранение части экрана */
save_video(x-1,endx,y-1,endy+1,p);
wind_zw(0x4a,x-1,y-1,endx-1,endy);
draw_border(x-1,y-1,endx-1,endy);
/* высвечивание меню на своем месте */
goto_xy(x+1,y+20);
printf("%s",txt7[0]);
ch_k = getch();
/* восстановление части экрана */
restore_video(x-1,endx,y-1,endy+1,p);
free(p);
return;
}
В листинге 5.20 располагаются функции, организующие передачу
символа кодом Морзе.
Функция передачи берет очередной символ из ячейки simwol и дает ему название ch_i. Далее выполняется исследование символа ch_i. Если код символа меньше 127 и больше 44, то символ поступает для
последующей обработки на часть функции, начинающуюся с метки whod1, где выполняется передача символа с использованием таблиц для
кодирования.
Листинг 5.20. Продолжение 6.
// подпрограмма
передачи кода Морзе
void
pered_simw(int simwol)
{
int count;
register int dd,bb;
register int ch_z;
int i;
int j;
int ch_i = simwol;
const int AA = 44;
if(ch_i == 0x20) pauza(8);
if(ch_i < 44 ) return;
if(ch_i < 127 ) goto whod1;
for(j=0;j<=64;j++)
{ bb =
abc[0+j];
if(bb == ch_i) {
ch_i = abc[j+64]; break;}
}
whod1:
i = ch_i — AA;
ch_z = tabl[i];
dd = 8;
kt:
ch_z = ch_z<<1;
dd--;
bb = ch_z & 0x100;
if(dd == 0) goto wyh;
if(bb == 0) goto kt;
g:
ch_z = ch_z<<1;
bb = ch_z & 0x100;
if(bb == 0) {count = 2; zwuk(count);
goto k2;}
count = 7;
zwuk(count);
k2:
count = 2;
pauza(count);
dd--;
if(dd == 0) goto wyh1;
goto g;
wyh1: count = 4;
pauza(count);
wyh:
return;
}
// пауза между посылками
void pauza(int count)
{
int j;
for(j=0; j<=count;j++) {
delay(skorost);
};
return;
}
// звуковая посылка
void zwuk(int count)
{
int j;
if(flag_zw == 1) sound(ton);
else nosound();
SBlRegSet(0xb0, 0x39); // 1200 Гц
ust_dtr_rts();
for(j=0;j<=count;j++) {
delay(skorost);
};
nosound(); sbros_dtr_rts(); // ust_rts();
SBlRegSet(0xb0, 0x11);
return;
}
// переключ звука
void perek_zw(void)
{
if(flag_zw == 1) {
flag_zw = 0; return;
}
flag_zw = 1;
}
В листинге 5.21 располагаются описания различных
вспомогательных функций, которые используются при работе на передачу, при
выдаче на экран текущего времени и другие. Много разных функций, но все они
очень простые.
Листинг 5.21. Продолжение 7.
// п/программа передачи
void peredacha(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
goto_xy(18,1);
wyzow();
sbros_dtr_rts();
write_video(2,31,*txt4,0xf);
bord_col(0);
}
// подпрограмма выхода
из передачи (концовка)
void wyhod3(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
goto_xy(18,1);
wyhod();
sbros_dtr_rts();
write_video(2,31,*txt4,0xf);
bord_col(0);
}
// чтение позиции
курсора
void getxy()
{
int i;
union REGS regs;
regs.h.ah = 3; // читает поз курсора
regs.h.bh
= 0;
int86(0x10,®s,®s);
i = regs.x.dx;
yy1 = 1 + (i & 0xff);
xx1 = 1 + (i >> 8);
return;
}
// выводит текущее
время на экран в определеннон место
void get_time(void)
{
struct tm *time_now;
time_t secs_now;
char str[80];
tzset();
time(&secs_now);
time_now = localtime(&secs_now);
strftime(str,80, "%H:%M %d-%m-%Y",time_now);
goto_xy(1,27);
puts(str); goto_xy(3,0);
}
/* Скроллинг
в окне */
void scr_scrup(int attr, int
frow, int fcol, int trow, int tcol)
{
union REGS regs;
regs.h.ah = 6;
regs.h.al = 1;
regs.h.bh = attr; /* обычные видео аттрибуты */
regs.h.ch = frow;
regs.h.cl = fcol;
regs.h.dh = trow;
regs.h.dl = tcol;
int86(0x10, ®s, ®s);
}
// Очистить окно
приема
void
cls_rx()
{
wind_zw(0x1d,3,0,16,79);
goto_xy(16,0);
}
// Очистить окно
передачи
void cls_tx()
{
wind_zw(0x1e,18,0,23,79);
goto_xy(23,0);
}
/* Копирование данных
из файла в буфер buf1[] */
void
copy_buf(int count)
{
int i,letter;
if(count ==1) goto wyh1;
if(count ==2) goto wyh2;
if(count ==3) goto wyh3;
if(count ==4) goto wyh4;
if(count ==5) goto wyh5;
if(count ==6) goto wyh6;
if(count ==7) goto wyh7;
if(count ==8) goto wyh8;
if(count ==9) goto wyh9;
if(count ==10) goto wyh10;
if(count ==11) goto wyh11;
wyh1: if((fp =
fopen("eqp.msg","r")) == NULL)
{
printf("Невозможно открыть файл
eqp.msg");
getchar();
exit(0);
}
goto wyh20;
wyh2: if((fp =
fopen("rpt.msg","r")) == NULL)
{
printf("Невозможно
открыть файл rpt.msg");
getchar();
exit(0);
}
goto wyh20;
wyh3: if((fp =
fopen("my_name.msg","r")) == NULL)
{
printf("Невозможно открыть файл
my_name.msg");
getchar();
exit(0);
}
goto wyh20;
wyh4: if((fp =
fopen("konec.msg","r")) == NULL)
{
printf("Невозможно открыть файл
konec.msg");
getchar();
exit(0);
}
goto wyh20;
wyh5: if((fp =
fopen("qrz.msg","r")) == NULL)
{
printf("Невозможно открыть файл
qrz.msg");
getchar();
exit(0);
}
goto wyh20;
wyh6: if((fp = fopen("cq.msg","r"))
== NULL)
{
printf("Невозможно открыть файл
cq.msg");
getchar();
exit(0);
}
goto wyh20;
wyh7: if((fp =
fopen("f5.msg","r")) == NULL)
{
printf("Невозможно открыть файл
f5.msg");
getchar();
exit(0);
}
goto wyh20;
wyh8: if((fp =
fopen("f6.msg","r")) == NULL)
{
printf("Невозможно открыть файл
f6.msg");
getchar();
exit(0);
}
goto wyh20;
wyh9: if((fp =
fopen("f7.msg","r")) == NULL)
{
printf("Невозможно открыть файл
f7.msg");
getchar();
exit(0);
}
goto wyh20;
wyh10: if((fp =
fopen("f8.msg","r")) == NULL)
{
printf("Невозможно открыть файл
f8.msg");
getchar();
exit(0);
}
goto wyh20;
wyh11: if((fp =
fopen("f9.msg","r")) == NULL)
{
printf("Невозможно открыть файл
f9.msg");
getchar();
exit(0);
}
wyh20: for(i=0;i<400;i++)
{
if((letter = fgetc(fp)) !=
EOF)
{
buf1[i] = letter;
}
}
fclose(fp);
return;
}
// выдать текст из
буфера buf0 на передачу
void
send_buf0(int x,int y,int len,int attrib)
{
int i;
unsigned int ch;
xx = x;
yy = y;
for(i=0;i<len;i++)
{
ch = buf0[i];
if(ch == NULL) break;
if(ch < 32)
{
if(ch ==0x0A | ch == 0x0D) {xx++; yy =
0;
if(xx>=22)
scr_scrup(0x1e,18,0,23,79);
}
}
else
{
simwol = buf0[i];
goto_xy(xx,yy);
write_simw(ch,attrib);
if(kbhit()) {
if((ch_k = getch()) == 0x1b)
break;}
pered_simw(simwol);
yy++;
if(yy > 79)
{yy = 1; xx++;}
if(xx == 23 & yy>= 79)
{
scr_scrup(0x1e,18,0,23,79);
xx = 23; yy = 1;
}
}
}
cls_tx();
}
// выдать текст из
буфера buf2 на передачу
void
send_buf2(int x,int y,int len,int attrib)
{
int i;
unsigned int ch;
xx = x;
yy = y;
for(i=0;i<len;i++)
{
ch = buf2[i];
if(ch == NULL) break;
if(ch < 32)
{
if(ch ==0x0A | ch == 0x0D) {xx++; yy =
0;
if(xx>=23)
scr_scrup(0x1e,18,0,23,79);
xx=23; yy=1;
}
}
else
{
simwol = buf2[i];
goto_xy(xx,yy);
write_simw(ch,attrib);
if(kbhit()) {
if((ch_k = getch()) == 0x1b)
break;}
pered_simw(simwol);
yy++;
if(yy > 79)
{yy = 1; xx++;}
if(xx == 23 & yy >= 79)
{
scr_scrup(0x1e,18,0,23,79);
xx = 23; yy = 1;
}
}
}
cls_tx();
}
// выдать текст из
буфера buf0 на передачу
void
send_buf1(int x,int y,int len,int attrib)
{
int i;
unsigned int ch;
xx = x;
yy = y;
for(i=0;i<len;i++)
{
ch = buf1[i];
if(ch == NULL) break;
if(ch < 32)
{
if(ch ==0x0A | ch == 0x0D) {xx++; yy =
0;
if(xx>=22)
scr_scrup(0x1e,18,0,23,79);
}
}
else
{
simwol = buf1[i];
goto_xy(xx,yy);
write_simw(ch,attrib);
if(kbhit()) {
if((ch_k = getch()) == 0x1b)
break;}
pered_simw(simwol);
yy++;
if(yy > 79)
{yy = 1; xx++;}
if(xx == 23 & yy >= 79)
{
scr_scrup(0x1e,18,0,23,79);
xx = 23; yy = 1;
}
}
}
cls_tx();
}
// вывести текст из
буфера на экран
void
co_buf(int x,int y,int len,int count,int attrib)
{
int i;
unsigned int ch;
xx = x;
yy = y;
for(i=0;i<len;i++)
{
if(count == 1) ch = buf1[i];
if(count == 0) ch = buf0[i];
if(ch == NULL) break;
if(ch < 32)
{
if(ch ==0x0A | ch == 0x0D) {xx++; yy =
0;
if(xx>=23)
scr_scrup(0x1e,18,0,23,79);
}
}
else
{
simwol = buf1[i];
goto_xy(xx,yy);
write_simw(ch,attrib);
yy++;
if(yy > 79)
{yy = 1; xx++;}
if(xx == 24 & yy >= 79)
{
scr_scrup(0x1e,18,0,23,79);
xx = 23; yy = 1;
}
}
}
}
/* начальная
фраза QSO */
void wyzow(void)
{
goto_xy(18,1);
if(qso.call_sign[0] == NULL) {promt(txt20[0],19,10,23,69);
goto_xy(18,1); return;
}
else
printf("%s de
%s",qso.call_sign,my_call);
read_string(18,1,17,buf0);
goto_xy(18,1);
send_buf0(18,1,17,0x1d);
cls_buf0(80);
}
/* начальная фраза QSO
вариант для текста по Alt-F5 */
void
wyzow1(void)
{
goto_xy(18,1);
if(qso.call_sign[0] == NULL) {promt(txt20[0],19,10,23,69);
goto_xy(18,1); return;
}
else
printf("%s de %s — HELLO DR
OM — UR RST IS %s
%s",qso.call_sign,my_call,qso.rst_sent,qso.rst_sent);
read_string(18,1,52,buf0);
goto_xy(18,1);
send_buf0(18,1,52,0x1d);
cls_buf0(80);
}
/* начальная фраза
QSO второй вариант*/
void
wyzow2(void)
{
goto_xy(18,1);
if(qso.call_sign[0] == NULL) promt(txt20[0],19,10,23,69);
if(qso.name_k[0] == NULL) { promt(txt21[0],19,10,23,69);
goto_xy(18,1); return;
}
else
printf("%s de %s — R OK DR
%s",qso.call_sign,my_call,qso.name_k);
read_string(18,1,35,buf0);
goto_xy(18,1);
send_buf0(18,1,35,0x1d);
cls_buf0(80);
}
/* конечнвя фраза QSO */
void wyhod(void)
{
goto_xy(18,1);
if(qso.call_sign[0] == NULL) {promt(txt20[0],19,10,23,69);
goto_xy(18,1); return;}
else
printf("%s de %s pse
k",qso.call_sign,my_call);
read_string(18,1,25,buf0);
goto_xy(18,1);
send_buf0(18,1,25,0x1d);
cls_tx();
cls_buf0(80);
}
/* конечнвя фраза QSO
вариант 2*/
void
wyhod2(void)
{
goto_xy(18,1);
if(qso.call_sign[0] == NULL) {promt(txt20[0],19,10,23,69); goto_xy(18,1);}
else
printf("%s de %s
k",qso.call_sign,my_call);
read_string(18,1,20,buf0);
goto_xy(18,1);
send_buf0(18,1,20,0x1d);
cls_tx();
cls_buf0(80);
}
// Создать окно подсказки
void promt(char *text,int x,int y, int
endx,int endy)
{
unsigned int *p;
/* размещение памяти для видео буфера */
p=(unsigned
int*)malloc((endx-x+1)*(endy-y+1));
if(!p) exit(1); /* Вы можете здесь сами обработать ошибку
*/
/* сохранение части экрана */
save_video(x-1,endx,y-1,endy+1,p);
wind_zw(0x4a,x-1,y-1,endx-1,endy);
draw_border(x-1,y-1,endx-1,endy);
/* высвечивание меню на своем месте */
goto_xy(x+1,y+13);
printf("%s",text);
sleep(1);
/* восстановление части экрана */
restore_video(x-1,endx,y-1,endy+1,p);
free(p);
return;
}
// очистка буфера buf1
void cls_buf1(int len)
{
int i;
for(i=0;i<len;i++)
buf1[i]=0x0;
}
// очистка буфера buf0
void cls_buf0(int len)
{
int i;
for(i=0;i<len;i++)
buf0[i]=0x0;
}
// очистка буфера buf2
void cls_buf2(int len)
{
int i;
for(i=0;i<len;i++)
buf2[i]=0x0;
}
В листинге 5.22 находится функция переключений при работе на
передачу, а также различные функции, задействованные в этих переключениях.
Здесь также много функций передачи различных файлов, некоторые
функции по работе с буферами. Все описанные в этом листинге функции очень
простые и какого-либо пояснения не требуют.
Листинг 5.22. Продолжение 8.
/* переключения при передаче */
int
exec_cmd(int ch_k)
{
int i, j;
get_time();
switch (ch_k) {
case F4
: izm_pr1();
break;
case F5
: izm_pr();
break;
case ALT_F2 :
alt_f2();
break;
case ALT_F3 :
alt_f3();
break;
case ALT_F4 :
alt_f4();
break;
case ALT_F5 :
alt_f5();
break;
case ALT_F6 : alt_f6();
break;
case ALT_F7 :
alt_f7();
break;
case ALT_F8 :
alt_f8();
break;
case ALT_F9 :
alt_f9();
break;
case ALT_F10 :
alt_f10();
break;
case SHF_F2 :
izm_ton1();
break;
case SHF_F3 :
izm_ton();
break;
case CTL_F5 :
ct_f5();
break;
case CTL_F6 :
ct_f6();
break;
case CTL_F7 :
ct_f7();
break;
case CTL_F8 :
ct_f8();
break;
case CTL_F9 :
ct_f9();
break;
case F2 :
uwel_skor();
break;
case F3 :
umen_skor();
break;
case 199 :
peredacha(); //<Home>
break; //<End>
case 207 :
wyhod3();
break;
case PGUP :
rus_lat();
break;
default : break;
}
return(0);
}
// общий вызов
void alt_f2(void)
{
ust_rts();
write_video(2,31,*txt3,0xf);
bord_col(0x3);
goto_xy(18,1);
copy_buf(6);
co_buf(18,1,400,1,0x1e);
send_buf1(18,1,400,0x1d);
sbros_dtr_rts();
write_video(2,31,*txt4,0xf);
bord_col(0);
cls_buf1(400);
}
// выдать QRZ
void alt_f3(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
goto_xy(18,1);
ust_rts();
copy_buf(5);
co_buf(18,1,400,1,0x1e);
send_buf1(18,1,400,0x1d);
sbros_dtr_rts();
write_video(2,31,*txt4,0xf);
bord_col(0);
cls_buf1(400);
}
void copy_buf_fl(int count)
{
int i,letter;
for(i=0;i<count;i++)
{
if((letter = fgetc(fp)) !=
EOF)
{
buf2[i] = letter;
}
}
fclose(fp);
return;
}
// вызов определенного
корреспондента
void alt_f4(void)
{
goto_xy(18,1);
if(qso.call_sign[0] == NULL) {promt(txt20[0],19,10,23,69);
goto_xy(18,1); return;
}
else
bord_col(0x3);
write_video(2,31,*txt3,0xf); goto_xy(18,1);
printf("%s %s de %s %s %s PSE
K",qso.call_sign,qso.call_sign,
my_call,my_call,my_call);
read_string(18,1,45,buf0);
goto_xy(18,1);
ust_rts();
send_buf0(18,1,45,0x1d);
sbros_dtr_rts();
write_video(2,31,*txt4,0xf);
bord_col(0);
cls_tx();
cls_buf0(80);
}
// начало qso
void alt_f5(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
ust_rts();
goto_xy(18,1);
wyzow1();
if(qso.call_sign[0] == NULL) {
bord_col(0);
write_video(2,31,*txt4,0xf);
sbros_dtr_rts(); return;}
copy_buf(3);
co_buf(18,1,400,1,0x1e);
send_buf1(18,1,400,0x1d);
wyhod();
write_video(2,31,*txt4,0xf);
bord_col(0);
sbros_dtr_rts();
cls_buf1(400);
}
// об аппаратуре
void alt_f6(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
ust_rts();
goto_xy(18,1);
wyzow2();
if(qso.call_sign[0] == NULL) {
bord_col(0);
write_video(2,31,*txt4,0xf);
sbros_dtr_rts(); return;}
if(qso.name_k[0] == NULL) { bord_col(0);
write_video(2,32,*txt4,0xf);
sbros_dtr_rts(); return;}
copy_buf(1);
co_buf(18,1,400,1,0x1e);
send_buf1(18,1,400,0x1d);
wyhod();
sbros_dtr_rts();
write_video(2,31,*txt4,0xf);
bord_col(0);
cls_buf1(400);
}
// концовка qso
void alt_f7(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
ust_rts();
goto_xy(18,1);
wyzow2();
if(qso.call_sign[0] == NULL) {
bord_col(0);
write_video(2,31,*txt4,0xf);
sbros_dtr_rts(); return;}
copy_buf(4);
co_buf(18,1,400,1,0x1e);
send_buf1(18,1,400,0x1d);
wyhod2();
sbros_dtr_rts();
write_video(2,32,*txt4,0xf);
bord_col(0);
cls_buf1(400);
}
// работать с клавиатуры
void alt_f8(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
ust_rts();
goto_xy(18,1);
wyzow2();
goto_xy(18,1);
xx=18; yy=1;
do{
do{
ch_n = getch();
if(ch_n == 13) goto wyh1;
if(ch_n == 8) {goto_xy(xx,--yy);
putchar(0x0);goto wyh0;}
write_char(xx,yy,ch_n,0x1e);
yy++;
if(ch_n == 32)
{
read_word(18,1,20,buf0);
xx=18; yy=1;
}
wyh0:
if(ch_n == 27) exit(0);
}
while(ch_n != 32);
send_buf0(18,1,17,0x1d);
xx=18; yy=1; goto_xy(18,1);
}
while(ch_n != 13 || ch_n != 9);
wyh1:
wyhod2();
sbros_dtr_rts();
write_video(2,31,*txt4,0xf);
bord_col(0);
cls_buf1(400);
}
// просьба повторить
имя и qth
void alt_f9(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
ust_rts();
goto_xy(18,1);
wyzow();
if(qso.call_sign[0] == NULL) {
bord_col(0);
write_video(2,32,*txt4,0xf);
sbros_dtr_rts(); return;}
copy_buf(2);
co_buf(18,1,400,1,0x1e);
send_buf1(18,1,400,0x1d);
bord_col(0);
wyhod();
write_video(2,31,*txt4,0xf);
sbros_dtr_rts();
bord_col(0);
cls_buf1(400);
}
// передать ASCII файл
void alt_f10(void)
{
char filename[15];
promt(txt22[0],19,10,23,69);
goto_xy(18,1);
gets(filename);
if((fp = fopen(filename, "r")) ==
NULL)
{
printf("Невозможно открыть файл
%s\n",filename);
getchar();
exit(0);
}
write_video(2,31,*txt3,0xf);
bord_col(0x3);
ust_rts();
copy_buf_fl(4000);
send_buf2(23,1,4000,0x1e);
write_video(2,31,*txt4,0xf);
sbros_dtr_rts();
bord_col(0);
cls_buf2(4000);
}
// общая подпрограмма
для
Ctrl_Fn qso
void ctrl_msg(void)
{
write_video(2,31,*txt3,0xf);
bord_col(0x3);
ust_rts();
goto_xy(18,1);
wyzow();
if(qso.call_sign[0] == NULL) {
bord_col(0);
write_video(2,31,*txt4,0xf);
return;}
copy_buf(count);
co_buf(18,1,400,1,0x1e);
send_buf1(18,1,400,0x1d);
wyhod2();
write_video(2,31,*txt4,0xf);
sbros_dtr_rts();
bord_col(0);
cls_buf1(400);
}
// выдать на передачу
текст f5.msg
void
ct_f5(void)
{
count = 7;
ctrl_msg();
}
// выдать на передачу
текст f6.msg
void
ct_f6(void)
{
count = 8;
ctrl_msg();
}
// выдать на передачу
текст f7.msg
void
ct_f7(void)
{
count = 9;
ctrl_msg();
}
// выдать на передачу
текст f8.msg
void
ct_f8(void)
{
count = 10;
ctrl_msg();
}
// выдать на передачу
текст f9.msg
void
ct_f9(void)
{
count = 11;
ctrl_msg();
}
//увеличение скорости
передачи
void uwel_skor(void)
{
static int wsp;
getxy();
// запомнить кординаты курсоро в xx1 и yy1
wsp
= skorost -3;
skorost = wsp;
if(skorost < 8) skorost =48;
izm_skor_p();
skorost2 = skorost;
izm_skor_priema();
goto_xy(xx1-1,yy1);
return;
}
// уменьшение скорости
передачи
void umen_skor(void)
{
static int wsp;
getxy();
// запомнить кординаты курсоро в xx1 и yy1
wsp
= skorost +3;
skorost = wsp;
if(skorost > 48) skorost = 9;
izm_skor_p();
skorost2 = skorost;
izm_skor_priema();
goto_xy(xx1-1,yy1);
return ;
}
//изменение скорости
передачи
void izm_skor_p(void)
{
goto_xy(2,65);
printf(" ");
goto_xy(2,65);
if(skorost ==48) {puts("42");
del1=2; del2 = 10;sch_posylok=23;}
if(skorost ==45) {puts("45");
del1=2; del2 = 10;sch_posylok=22;}
if(skorost ==42) {puts("48");
del1=2; del2 = 10;sch_posylok=21;}
if(skorost ==39) {puts("50");
del1=2; del2 = 10;sch_posylok=20;}
if(skorost ==36) {puts("55");
del1=2; del2 = 10;sch_posylok=19;}
if(skorost ==33) {puts("60");
del1=2; del2 = 10;sch_posylok=18;}
if(skorost ==30) {puts("65");
del1=2; del2 = 10;sch_posylok=17;}
if(skorost ==27) {puts("70");
del1=2; del2 = 10;sch_posylok=16;}
if(skorost ==24) {puts("75");
del1=1; del2 = 10;sch_posylok=15;}
if(skorost ==21) {puts("85");
del1=1; del2 = 10;sch_posylok=14;}
if(skorost ==18) {puts("95");
del1=1; del2 = 10;sch_posylok=13;}
if(skorost ==15)
{puts("110");del1=1; del2 = 10;sch_posylok=12;}
if(skorost ==12) {puts("125");del1=1;
del2 = 10;sch_posylok=11;}
if(skorost == 9)
{puts("150");del1=1; del2 = 10;sch_posylok=10;}
return;
}
// изменение тона
сигнала в динамике — понижение
void
izm_ton(void)
{
static int wsp;
getxy(); //
запомнить кординаты курсоро в xx1 и yy1
wsp
= ton — 100;
ton = wsp;
if(ton < 400) ton =1600;
izm_skor_p();
goto_xy(xx1-1,yy1);
goto_xy(1,74);
puts(" ");
goto_xy(1,74);
printf("%dГц",ton);
return;
}
// изменение тона сигнала
в динамике — повышение
void
izm_ton1(void)
{
static int wsp;
getxy(); //
запомнить кординаты курсоро в xx1 и yy1
wsp
= ton + 100;
ton = wsp;
if(ton > 1600) ton =400;
izm_skor_p();
goto_xy(xx1-1,yy1);
goto_xy(1,74);
puts(" ");
goto_xy(1,74);
printf("%dГц",ton);
return;
}
// уменьшение скорости
приема
void
izm_pr(void)
{
skorost2 = skorost2+3;
if(skorost2 > 48) skorost2 = 9;
izm_skor_priema();
return ;
}
// уменьшение скорости
передачи
void izm_pr1(void)
{
skorost2 = skorost2 -3;
if(skorost2 < 9) skorost2 = 48;
izm_skor_priema();
return ;
}
//изменение скорости
приема
void
izm_skor_priema(void)
{
goto_xy(2,74);
printf(" ");
goto_xy(2,74);
if(skorost2 ==48) {puts("42");
del1=2; del2 = 10;sch_posylok=23;}
if(skorost2 ==45) {puts("45");
del1=2; del2 = 10;sch_posylok=22;}
if(skorost2 ==42) {puts("48");
del1=2; del2 = 10;sch_posylok=21;}
if(skorost2 ==39) {puts("50");
del1=2; del2 = 10;sch_posylok=20;}
if(skorost2 ==36) {puts("55");
del1=2; del2 = 10;sch_posylok=19;}
if(skorost2 ==33) {puts("60");
del1=2; del2 = 10;sch_posylok=18;}
if(skorost2 ==30) {puts("65"); del1=2;
del2 = 10;sch_posylok=17;}
if(skorost2 ==27) {puts("70");
del1=2; del2 = 10;sch_posylok=16;}
if(skorost2 ==24) {puts("75");
del1=1; del2 = 10;sch_posylok=15;}
if(skorost2 ==21) {puts("85");
del1=1; del2 = 10;sch_posylok=14;}
if(skorost2 ==18) {puts("95");
del1=1; del2 = 10;sch_posylok=13;}
if(skorost2 ==15)
{puts("110");del1=1; del2 = 10;sch_posylok=12;}
if(skorost2 ==12)
{puts("125");del1=1; del2 = 10;sch_posylok=11;}
if(skorost2 == 9)
{puts("150");del1=1; del2 = 10;sch_posylok=10;}
return;
}
В листинге 5.23 размещены функции программы, предназначенные
для работы с аппаратным журналом. Аппаратный журнал, по моему мнению, должен
быть в каждой программе, предназначенной для цифрового вида связи. Встроенный в
эту программу аппаратный журнал является простейшим представителем своего вида,
но обладает всеми необходимыми функциями для хранения и поиска записей о
проведенных радиосвязях.
Листинг 5.23. Продолжение 9.
// добавить запись о QSO в аппаратный журнал
void
addqso(void)
{
int i;
if(nomer == MAX)
{
puts("В этом файле журнала больше
места нет. Сделайте новый.\n");
getchar();
return;
}
if((fp = fopen( FILENAME,
"a")) == NULL)
{
printf("Невозмиожно
открыть файл %s\n",FILENAME);
exit(0);
}
for(i=0;i<20;i++)
{
disc.name[i] = qso.call_sign[i];
disc.namkor[i] = qso.name_k[i];
disc.qth[i] = qso.qth[i];
disc.rs1[i] = qso.rst_sent[i];
read_word(1,26,5,disc.tim);
read_word(1,44,10,disc.date);
read_word(0,38,2,disc.mod);
}
promt(txt23[0],19,10,23,69);
goto_xy(19,5);
puts(" Так Вы УВЕРЕНЫ, что все правильно в экранной
таблице?");
puts("\n Тогда нажимайте <Enter>, иначе
для выхода жмите <Esc>!!!");
i
= getch();
if(i == 27) {cls_tx(); return;}
else
cls_tx();
goto_xy(18,0);
printf("Введите диапазон (до 3 цифр): ");
gets(disc.diap);
printf("Введите RST к Вам (до 3
цифр): ");
gets(disc.rs2);
printf("Введите информацию по
диплому (до 13 букв): ");
gets(disc.category);
printf("Введите дополнительную
информацию (до 50 букв) : ");
gets(disc.infor);
disc.number = nomer;
if(nomer == 12 || nomer == 25) {nomer =
nomer+2; goto wyh;}
else
nomer = nomer + 1;
wyh:
fwrite(&disc, sizeof(disc), 1, fp);
fclose(fp);
cls_tx();
return;
}
/* вывести записи на экран */
void wlist(void)
{
int ch;
if((fp = fopen(FILENAME,"r"))
== NULL)
{
printf("Невозможно открыть
файл %s\n",FILENAME);
exit(0);
}
cls(0x1e);
goto_xy(0,0);
puts(
" N
Диап. Дата Время
Позывной Город Мод.
Диплом");
puts("
==========================================================================");
while(fread(&disc,sizeof(disc), 1,
fp)==1)
{
if(disc.number >= 24) {ch_k = getch();
if(ch_k == 27) break;
else
goto wyh;}
else
wyh:
printf(
"%4d |%4s|%12s|%6s|%9s
|%15s|%4s|%15s|\n",disc.number,disc.diap,
disc.date,disc.tim,disc.name,disc.qth,disc.mod,disc.category); }
printf("
Для продолжения нажмите Enter");
getch();
fclose(fp);
return;
}
//ввести номер последнего QSO из файла
void
nomer_qso(void)
{
if((fp = fopen(FILENAME, "r")) ==
NULL)
{
printf("Невозможно открыть файл %s\n",FILENAME);
exit(0);
}
while(fread(&disc,sizeof(disc),1,fp) !=
NULL)
{
nomer = disc.number; }
nomer = nomer + 1;
fclose(fp);
}
В листинге 5.24 располагаются функции, которые управляют
величинами электрических напряжений на различных выводах COM-порта, а также функции для работы со звуковой картой компьютера в
режиме передачи (генерация звука нужной частоты).
Листинг 5.2. Продолжение 10.
// установка сигнала DTR
void ust_dtr(void)
{
asm mov dx, com_adr1
asm mov al, 1
asm out dx,al
}
// установка сигнала RTS
void
ust_rts(void)
{
asm
mov dx, com_adr1
asm mov al, 2
asm out dx,al
}
// установка
сигнала DTR и RTS
void ust_dtr_rts(void)
{
asm mov dx, com_adr1
asm mov al,3
asm out dx,al
}
// сброс сигналов DTR и RTS
void sbros_dtr_rts(void)
{
asm mov dx,com_adr1
asm mov al,0
asm out dx,al
}
// далее расположены
несколько функций, работающих со звуком
void
SBlRegSet(int regis, int value)
{
outportb(0x220,regis);
delay(6);
outportb(0x221,value);
delay(24);
}
void NullRegistr(void)
{
SBlRegSet(0x01, 00);
SBlRegSet(0x08, 00);
SBlRegSet(0x20, 00);
SBlRegSet(0x40, 00);
SBlRegSet(0x60, 00);
SBlRegSet(0x80, 00);
SBlRegSet(0xa0, 00);
SBlRegSet(0xb0, 00);
SBlRegSet(0xbd, 00);
SBlRegSet(0xc0, 00);
SBlRegSet(0xe0, 00);
}
void SetKanal(void)
{
SBlRegSet(0x4, 0x21);
delay(90);
}
void SetRegistr(void)
{
SBlRegSet(0x20, 0x1);
SBlRegSet(0x40, 0x10);
SBlRegSet(0x60, 0xf0);
SBlRegSet(0x80, 0x77);
SBlRegSet(0xa0, 127);
SBlRegSet(0x23, 0x1);
SBlRegSet(0x43, 00);
SBlRegSet(0x63, 0xf0);
SBlRegSet(0x83, 0x77);
SBlRegSet(0xb0, 0x39);
SBlRegSet(0xc0, 0x7);
}
void ProwSBl(void)
{
SBlRegSet(0x04, 0x60);
SBlRegSet(0x04, 0x80);
nn=inportb(0x220);
SBlRegSet(0x02, 0xff);
SBlRegSet(0x04, 0x21);
delay(90);
pp=inportb(0x220);
SBlRegSet(0x04, 0x60);
SBlRegSet(0x04, 0x80);
if((pp — 0xc0) == 0) {goto_xy(18,1);
printf("Все ОК, карта SB установлена"); }
else
{goto_xy(4,5);printf(" Необходимая
звуковая карта не обнаружена!!!");
getch();}
}
В листинге 5.25 располагается одна из важных функций —
функция вывода принятого символа на экран. Также здесь находятся некоторые
вспомогательные функции, в том числе и функция поиска в файле аппаратного
журнала нужной информации и выдачи этой информации на экран в информационную
строку.
Листинг 5.25. Продолжение 11.
// вывести принимаемый
символ на экран
void
rx_read(void)
{
goto_xy(xx0,yy0);
putchar(simwol2);
yy0++;
if(yy0 > 78) {yy0 = 1; xx0++;}
if(xx0 == 16 & yy0 >= 78)
{
{scr_scrup(0x1d,3,0,16,79);
xx0 = 16; yy0 = 1; }
}
}
// переключение
рус/лат
void rus_lat(void)
{
if(flag_rus == 1) {flag_rus = 0; goto_xy
(0,77); puts("LAT");}
else
{flag_rus = 1;goto_xy(0,77); puts("РУС");}
}
/* вывести help на экран */
void dis_help(void)
{
char *string;
char msg[80];
int len,d1=1;
int ch;
if((fp = fopen(FILEHLP,"r"))
== NULL)
{
printf("Невозможно открыть
файл %s\n",FILEHLP);
exit(0);
}
cls(0x1e);
goto_xy(0,0);
while(fgets(msg,len,fp) != 0)
{
if(d1 >= 23) { d1 = 1; ch_k = getch();
if(ch_k == 27) break;
else
goto wyh;}
else
wyh:
printf(" %s",msg); d1++;}
printf("
Для продолжения нажмите <Enter>");
getch();
fclose(fp);
return;
}
/* Поиск определенной
записи и вывод данных на экран */
locate()
{
char name[20];
char fflag,pause;
int zif;
fflag='n';
if((fp= fopen(FILENAME,"r"))
== NULL)
{
printf("Невозможно открыть
файл %s\n", FILENAME);
exit(0);
}
stpcpy(name,qso.call_sign);
strlwr(name);
zif = strlen(name);
while(fread(&disc,sizeof(disc), 1, fp)==1)
{
if(strnicmp(disc.name,
name,zif)==0)
{
fflag='y';
getxy();
goto_xy(17,2);
printf(" Последняя связь:
N%d %s
%s %s %s
%s ",disc.number,disc.date,disc.tim,disc.name,disc.rs1,disc.rs2);
goto_xy(1,9); printf(" ");
goto_xy(1,9); printf(" ");
goto_xy(2,9);
printf("%s",disc.qth);
goto_xy(1,9);
printf("%s",disc.namkor);
goto_xy(xx1,yy1);
}
}
fclose(fp);
if(fflag=='n')
{ getxy(); goto_xy(17,2);
printf(" Записей о связи с этим позывным в
журнале нет. ");
goto_xy(1,9); printf(" ");
goto_xy(2,9); printf(" ");
goto_xy(xx1,yy1);
}
return 0;
}
На этом закончились листинги исходных кодов программы CW_QSO. Надеюсь, что этот материал поможет вам
сделать свои собственные программы для телеграфной радиосвязи. Пускай сначала
все будет не так уж и хорошо, но последующие варианты с каждым разом будут
становиться все лучше и лучше.