07 марта 2021

Amateur Radio Software written and collected by G4PMK and G3SEK

Most of these files are ASCII GWBASIC programs with the filename extension .BAS. You can use them as they are (this requires GWBASIC, QuickBasic or a compatible interpreter), compile them to run faster, or edit them to meet your own requirements. If you edit these files, DO NOT re-distribute them using our program names - invent your own! A few programs are ready-compiled as .COM or .EXE files, either because they were not written in GWBASIC or in order to retain control over future changes in the source code. New in the RF section is the latest version 5.5 of G3SEK's TCALC.

If you are using Win95 or Win98, some of the special character such as degree signs and Omegas (which were fine under DOS), may be displayed incorrectly. To solve that problem, go into c:\autoexec.bat and "rem-out" the codepage statements that Windows put in there when it installed itself.

For example my autoexec.bat now reads:

REM mode con codepage prepare=((850) C:\WINDOWS\COMMAND\ega.cpi)

REM mode con codepage select=850

It solves the problem with older DOS programs, and as far as I can see, Windows never uses that codepage setup anyway!

10 '   TCALC5.5, a program for calculating cumulative noise figures,

20 '           noise temperatures, gains and intermodulation intercepts

30 '           of cascaded stages in receiver systems.

40 '

50 '   (c) 1984, 1989, 1996 by Ian White, G3SEK.

60 '

70 '    GWBASIC version for IBM PC and compatibles only.

80 '

90 '

100 DIM STAGE(20)

110 ' STAGE codes:  1=first stage

120 '               2=AMPlifier, 3=MIXer  (equivalent)

130 '               4=CABle, 5=ATTenuator (filter, etc - all equivalent)

140 '               6=ANTenna

150 '               7=SYStem

160 '

170 DIM NT(20)                          ' Stage noise temperature (K)

180 DIM GAIN(20)                        ' Stage gain (ratio)

190 '

200 DEF FNA (X) = EXP(X * .230259)      ' Reverse dB

210 DEF FNB (X) = 4.34294 * LOG(X)      ' dB from natural log

220 '

230 CLS : KEY OFF

240 LOCATE 3, 33: COLOR 0, 7: PRINT " TCALC ": COLOR 7, 0

250 LOCATE 5, 16: PRINT "Version 5.5 (c) 1984-1996 Ian White, G3SEK"

260 GOSUB 1650   ' Print stage info

270 GOSUB 1750   ' Redefine keys

280 LOCATE 14, 1

290 PRINT TAB(8); "Stages are numbered backwards towards antenna, starting from"

300 PRINT TAB(8); " Stage 1 = `rest of system'."

310 PRINT

320 PRINT TAB(8); "Gain is cumulative from Stage 1, working backwards towards input."

330 PRINT

340 PRINT TAB(8); "Level is cumulative gain, working forwards from input into system"

350 PRINT TAB(8); " (only available within IMD analysis)."

360 LOCATE 23, 25: COLOR 0, 7: PRINT " Press spacebar to start ": COLOR 7, 0

370 T$ = INKEY$: IF T$ = "" GOTO 370 ELSE CLS

380 '

390 FIRST = -1: IMD = 0: GOTO 540             ' First calculation only

400 '

410 ' Return point after calc completed

420 PRINT STRING$(78, "-")

430 PRINT "Noise analysis, Intermod analysis or Quit?   (Press N/I/Q)  > ";

440 GOSUB 2260

450 IF T$ = "Q" THEN CLS : KEY OFF: END

460 IF T$ = "I" THEN FIRST = 0: IMD = -1: GOTO 1170 ' Go calculate intermods

470 IF T$ <> "N" GOTO 440

480 '

490 ' Repeat noise calculations

500 FIRST = 0: CLS : KEY ON: PRINT

510 PRINT "Input new data, or press <Enter> to recall old data."

520 PRINT "(For a new 1st stage, input N)": PRINT

530 ' Heading and initialization - 1st time starts here

540 GOSUB 1880: M = 1: T = 0: G = 1: STAGE(1) = 1

550 PRINT "Stage 1 (rest of system)": IF FIRST GOTO 730

560 INPUT ; "", T$: IF T$ = "" GOTO 1010

570 GOTO 730

580 '

590 ' Return point for more/new data

600 M = M + 1

610 IF M > 20 THEN BEEP: PRINT "TOO MANY STAGES": GOTO 420

620 ' Read in data

630 PRINT "Stage "; M; " STAGE: ";

640 INPUT ; "", A$: GOSUB 2310

650 STAGE(M) = (INSTR("AMPMIXCABATTANTSYS", A$) + 5) / 3

660 IF STAGE(M) < 2 THEN GOTO 690

670 PRINT

680 ON (STAGE(M) - 1) GOTO 730, 730, 850, 850, 920, 920

690 PRINT "???": BEEP: GOTO 630

700 '

710 ' Input for first stage, AMP or MIX

720 ON ERROR GOTO 730

730 LOCATE , 1: INPUT ; "T(>=25K) or NF(<25dB): ", SENS

740 ON ERROR GOTO 0

750 LOCATE , 1: PRINT STRING$(30, 32); : LOCATE , 1

760 IF SENS < 25 THEN NT(M) = 290 * (FNA(SENS) - 1): PRINT USING "NF =##.#dB"; SENS;

770 IF SENS >= 25 THEN NT(M) = SENS: PRINT USING "T = ####K"; SENS;

780 IF M = 1 THEN G2 = 1: GOTO 800

790 INPUT ; " Gain (dB): ", G2: G2 = FNA(G2)

800 GAIN(M) = G2

810 GOSUB 2100: GOTO 1100

820 '

830 ON ERROR GOTO 850

840 ' Input for CABle/ATTenuator

850 INPUT ; "Loss (dB) : ", L

860 ON ERROR GOTO 0

870 L = ABS(L): L = FNA(L)

880 NT(M) = 0: GAIN(M) = 1 / L

890 GOSUB 2150: GOTO 1100

900 '

910 ' Input for ANT; or SYStem

920 GAIN(M) = 1

930 IF STAGE(M) = 7 THEN NT(M) = 0: GOTO 420  ' SYS

940 ON ERROR GOTO 950

950 LOCATE , 1: INPUT ; "Ant. noise temp (K): ", NT(M)

960 ON ERROR GOTO 0

970 T = T + NT(M)

980 GOTO 1100

990 '

1000 ' Look for old data

1010 IF STAGE(M) = 0 THEN GOSUB 2200: GOTO 630

1020 IF STAGE(M) = 1 GOTO 810

1030 IF STAGE(M) = 2 THEN PRINT TAB(18); "Amp"; : GOSUB 2100: GOTO 1100

1040 IF STAGE(M) = 3 THEN PRINT TAB(18); "Mix"; : GOSUB 2100: GOTO 1100

1050 IF STAGE(M) = 4 THEN PRINT TAB(18); "Cab"; : GOSUB 2150: GOTO 1100

1060 IF STAGE(M) = 5 THEN PRINT TAB(18); "Att"; : GOSUB 2150: GOTO 1100

1070 IF STAGE(M) = 6 THEN PRINT TAB(18); "Ant"; : GOTO 970

1080 IF STAGE(M) = 7 THEN PRINT TAB(18); "System": GOTO 420

1090 '

1100 GOSUB 1970

1110 ' End of calculations

1120 IF STAGE(M) = 6 OR STAGE(M) = 7 GOTO 420' If ANT or SYS, finished

1130 GOTO 600                             ' Go back for more input

1140 '

1150 ' 3rd order intermod analysis

1160 '

1170 CLS : KEY OFF: LOCATE 2, 20: PRINT "THIRD ORDER INTERMODULATION ANALYSIS"

1180 PRINT : PRINT "Input IP3 values in dBm.  Coherent addition of intermod products is assumed."

1190 PRINT "For zero intermod, just press <Enter>   (This sets IP3 to +100dBm)"

1200 PRINT : PRINT

1210 '

1220 GT = G: T = 0: G = 1   ' Save old total gain; re-initialize

1230 IP = 1E+10  ' Initialize running-total system IP3 (mW) to a high value

1240 '

1250 COH = -1 ' Non-coherent option is seldom used, and is REM'd out below.

1260 REM PRINT "Press N for non-coherent addition of IPs, press <Enter> for coherent addition"

1270 REM PRINT "> "

1280 REM GOSUB 2140: IF T$="N" THEN COH = 0

1290 '

1300 GOSUB 1880   ' Print heading

1310 M = 1: GT1 = FNB(GT)

1320 IF STAGE(M) = 1 THEN GOSUB 2100: PRINT "Rest of system"; : GOTO 1380

1330 IF STAGE(M) = 2 THEN GOSUB 2100: PRINT "Stage"; M; "(Amp)"; : GOTO 1380

1340 IF STAGE(M) = 3 THEN GOSUB 2100: PRINT "Stage"; M; "(Mix)"; : GOTO 1380

1350 IF STAGE(M) = 4 THEN GOSUB 2150: PRINT "Stage"; M; "(Cab)"; : IM = 1E+10: GOTO 1490

1360 IF STAGE(M) = 5 THEN GOSUB 2150: PRINT "Stage"; M; "(Att)"; : IM = 1E+10: GOTO 1490

1370 IF STAGE(M) >= 6 THEN GOTO 1530

1380 INPUT ; " IP3(dBm): ", T$

1390 ' IM is stage input intercept.

1400 ' If high, leave IM alone; else refer IM to system input.

1410 IF T$ = "" THEN IM = 1E+10: GOTO 1450

1420 IM = FNA(VAL(T$)) * G / GT   ' Stage intercept, referred to system input

1430 '

1440 ' Update running-total system input intercept

1450 IF M = 1 THEN IP = IM: GOTO 1490

1460 IF COH THEN IP = 1 / (1 / IP + 1 / IM) ELSE IP = 1 / SQR(1 / (IP * IP) + 1 / (IM * IM))

1470 '

1480 ' Print output, loop back

1490 GOSUB 1970

1500 M = M + 1: GOTO 1320

1510 '

1520 ' Finished stage calcs; print RX performance

1530 PRINT : PRINT "Whole receiver:"; :

1540 IP = FNB(IP)

1550 PRINT TAB(70); : PRINT USING "+##.#"; IP

1560 MDS = T * 1.38E-23 * 2500: MDS = FNB(MDS) + 30 ' dBm

1570 SFDR = 2 * (IP - MDS) / 3

1580 PRINT USING "Noise floor (2.5kHz) = +###.# dBm"; MDS

1590 PRINT USING "Dynamic range = ###.# dB"; SFDR

1600 IMD = 0             ' Clear IP flag

1610 '

1620 GOTO 420           ' What's next?

1630 '

1640 ' Info subroutine

1650 LOCATE 7, 8

1660 PRINT "Use function keys to enter the following types of stages,"

1665 PRINT TAB(8); "or type the first three letters and press <Enter>."

1670 PRINT TAB(15); "F1 = AMPlifier  F2 = MIXer      (both equivalent - has IMD)"

1680 PRINT TAB(15); "F5 = CABle      F6 = ATTenuator (both equivalent - no IMD)"

1690 PRINT TAB(15); "F8 = ANTenna  (contribution to system noise temperature)"

1700 PRINT TAB(15); "F9 = SYStem   (end of input, if no antenna)"

1710 PRINT

1720 RETURN

1730 '

1740 ' Key definitions

1750 KEY 1, "Amp.  " + CHR$(13)

1760 KEY 2, "Mixer " + CHR$(13)

1770 KEY 3, ""

1780 KEY 4, ""

1790 KEY 5, "Cable " + CHR$(13)

1800 KEY 6, "Atten." + CHR$(13)

1810 KEY 7, ""

1820 KEY 8, "Ant.  " + CHR$(13)

1830 KEY 9, "System" + CHR$(13)

1840 KEY 10, ""

1850 KEY ON: RETURN

1860 '

1870 ' Heading subroutine

1880 COLOR 15, 0: PRINT : PRINT TAB(5); "STAGE PARAMETERS"; TAB(47); "SYSTEM RESULTS"

1890 PRINT STRING$(27, "-"); TAB(31); STRING$(48, "-")

1900 PRINT TAB(33); "T"; TAB(44); "NF"; TAB(52); "Gain";

1910 IF IMD THEN PRINT TAB(61); "Level"; TAB(71); "IPi3" ELSE PRINT

1920 PRINT TAB(32); "(K)"; TAB(43); "(dB)"; TAB(52); "(dB)";

1930 IF IMD THEN PRINT TAB(61); "(dB)"; TAB(71); "(dB)" ELSE PRINT

1940 COLOR 7, 0: RETURN

1950 '

1960 ' Output subroutine

1970 F1 = FNB(T / 290 + 1)

1980 G1 = FNB(G)

1990 PRINT TAB(28); : PRINT USING "#######.#"; T; : PRINT TAB(41);

2000 IF STAGE(M) = 6 THEN PRINT : RETURN

2010 PRINT USING "###.##"; F1; : PRINT TAB(51);

2020 PRINT USING "+##.#"; G1;

2030 IF IMD THEN PRINT TAB(60); : PRINT USING "+##.#"; (GT1 - G1);

2040 IF NOT IMD OR STAGE(M) > 6 THEN PRINT : RETURN

2050 IF IM > 9.000001E+09 THEN PRINT : RETURN

2060 IM = FNB(IM): PRINT TAB(70); : PRINT USING "+##.#"; IM

2070 RETURN

2080 '

2090 '  AMP/MIX calc

2100 T = NT(M) + T / GAIN(M)

2110 G = G * GAIN(M)

2120 RETURN

2130 '

2140 ' CABle/ATTen calc

2150 T = 290 * (1 / GAIN(M) - 1) + T / GAIN(M)

2160 G = G * GAIN(M)

2170 RETURN

2180 '

2190 '  Error handling

2200 COLOR 0, 7: PRINT " Input please! "; : COLOR 7, 0: BEEP

2210 INPUT ; " Press <Enter>", T$

2220 LOCATE , 1: PRINT STRING$(60, 32); : LOCATE , 1

2230 RETURN

2240 '

2250 '  Keypress handling

2260 T$ = INKEY$: IF T$ = "" GOTO 2260

2270 IF T$ > "@" THEN T$ = CHR$(ASC(T$) AND &H5F)

2280 RETURN

2290 '

2300 ' Process keyword

2310 IF A$ = "" THEN RETURN 1010

2320 IF LEN(A$) < 3 THEN RETURN 690

2330 A$ = LEFT$(A$, 3)

2340 T$ = ""

2350 FOR LTR = 1 TO LEN(A$)

2360     TT$ = CHR$(ASC(MID$(A$, LTR)) AND &H5F)

2370     IF ASC(TT$) < 65 OR ASC(TT$) > 90 THEN GOTO 2420

2380     T$ = T$ + TT$

2390 NEXT

2400 A$ = T$

2410 RETURN

2420 RETURN 690