The structure of the modem driver
for the program MMD 2.20
music by DNK
(C) MAS
_______________________________
To work terminalki "Macro Modem
v2.20 "requires a modem. This
driver performs all functions reception / transfer information
and handles the telephone line and system
hours.
Driver to be on the 6 th page
49,152 addresses (# C000). Under his needs allocated all 16Kb
given page. Log in driver is done through an entry point,
located in the very early drivers
ie from address 49152.
Attention!
DRAYVER_NE_DOLZHEN:
- Spoil registers content IX, IY,
SP;
- Change any of the memory cell core
program except for those specifically allocated buffer for the
exchange of information; - Change the mode interrupt (interrupt
status can be changed - all the same it will be prohibited).
Driver entry points:
INSTALLING DRIVERS
D_INSTAL EQU # C000
If you call in a couple regitrovoy
[HL] will be the address of the working buffer for the transmit
/ receive data. This buffer located in main memory, and
has a size of about 270 bytes up, and about 30 down from the
specified value. Exchange data between main program and the
driver made only through the clipboard.
With installations in the buffer driver
should be written in the form of ASCII value
existing rates. On each speed allocated 5 bytes, total
velocities - 8. Should describe each speed,
if the driver supports a smaller number, then the descriptors
are filled with non-existent velocity Code # 00. Example
descriptor velocities:
DEFB "600", 1 st speed 600 baud
DEFB "1800", 2 nd speeds of 1800 baud
DEFB "2400", the third at 2400 baud
DEFS 25; only 3 speed,
; Remaining 5 absent
The program takes into account the fact that the driver
modem can be packed. Therefore, the installation procedure is
called twice. Ie the first call to unpacking
driver, and the second of its installation.
The program uses the jars for transport
Facebook to inform driver what challenge
occurs:
- If carry flag is set - the first
call
- If carry flag is cleared - the second.
OBTAINING INFORMATION ABOUT THE DRIVERS
D_COPYREQU # C003
This feature puts in the work buffer driver information. This
information is the driver name and the name its author. Buffer
Size - 50 bytes line should end with a code # 00
Example of a function D_COPYR:
LD DE, (WORK_ADR); buffer address
LD HL, TEXT; address line
LD BC, ETEXT-TEXT; length of the string
LDIR; moved and
RET; returned
TEXTDEFB "Vicomm-driver v2.95"
DEFB "(C) 1997 * MAS *"
DEFB 0
ETEXT
READING THE STATUS LINE / DRIVER
D_RD_STAT EQU # C006
This function returns the
DRIVERS line and also produces Cor
Correction of data for the port # FE.
When invoked given function in [A] located current color curb.
On return from the function:
- √ In case [B] various bits is characterized by:
bit0 - the status line: "1" modem is connected
to the line, "0" is disabled
bit1
bit2
, Bit3 if "1" then driver may recruit
Room tone method.
bit4 if "1" - to disable TUR
BO-mode when you call the driver (for
all modems except XTR - required)
bit5 if "1", the driver allows you to pack
ravlyat line (to connect the modem to
line and disable)
- Bit6 if "1" then the driver has hours
- Bit7 if "1", then the driver has a tie
measures
√ In the case [A] will be located data
port # FE. If the driver for his
needs is not using port # FE, then the contents of the battery
should not be changed. For example: Vicomm with gadgets "v1.2
transmits data and controls the line via port # FE, and when
you call this function to install 3 rd and 5 th bits of the
battery in accordance with their needs.
INSTALLATION OF FRONT LINE POLLS
D_WAIT_INS EQU # C009
This function is called immediately before the loop function
calls the survey line. If the driver must set any variables,
this function and it does.
When you call this function, the battery will be a number from
0 to 15, characterizes the volume with which the functions of
the survey lines should sound output through the embedded
speaker. Vydor device for sound output is not
negotiated (you can use beeper,
AY, COVOX, etc.) When sound on AY
There is one restriction: if the sound output
not necessary, ie [A] = # 00, then change the contents of the
registers muzprotsessora not recommended.
SURVEY LINE
D_WAIT_LN EQU # C00C
This function produces a survey line
within a short period of time.
This function returns Output:
√ If the carry flag is set, then nothing happened, while the
register [B] indicates the number of produced
Polls line, and in case [C] - how much
vsogo be polls. The data in the registers [B] and [C] can more
or less rhythmically blinking cursor and query
keyboard.
For example, if the function performs
15 polls the line, and the presence of noise in
line in any of the cycles of the survey returns. In the case
[B] indicates as function of time to perform surveys.
If the function of the survey line runs
always strictly fixing the time, then
register [B] is entered # 01
Contents of the register [C] allows you to adjust chastoru
Mugan cursor keys and the survey. The higher the number, the
rarer and rhythmically blinks cursor.
√ If the function returns D_WAIT_LN
carry flag is cleared, then there was some event. In case [A]
is indicated by its code:
# 01: was adopted by the unit. Adopted by the unit is in the
buffer on the modem and its length in register pair [BC] The
Register [D] is the speed at which it was submitted this block.
If the speed does not determine succeeded then [D] recorded #
80
# 02: were discovered short hooters
# 03: it was discovered the call (call)
LONG WAITING
D_WAIT_BLC EQU # C00F
This function produces long poll line approximately 1 ... 4
seconds. When function return:
√ If carry flag installed then nothing was accepted
, √ If the carry flag is cleared, then took
block:
Adopted by the unit is in the buffer on the modem and its
length in the register pair [BC] B register [D] located speed
at which was handed given block. If the speed could not be
determined, then [D] entered # 80
DATA TRANSFER
D_TRANSMIT EQU # C012
This function sends the data block.
The data itself is in the buffer modem in
register pair [BC] is the length of the transmission unit, in
the [A] - speed.
Connect the modem to the line
D_ON_LINE EQU # C015
RETIRE FROM LINE MODEM
D_OFF_LINE EQU # C018
These functions are just "remove" or
"Lay" handset. The function did not spread and the functions do
not return.
SEND NUMBER
D_CALL EQU # C01B
This function performs a set of numbers. If you call the modem
is already connected to the line and register pair [HL] buffer
address is the phone number that you must dial. Number
represents the ASCII string that ends with code # 00. If a line
meets a symbol "-", then set it to skip. During the recruitment
is necessary to analyze pressing the keys , and when it
is pressed to produce vyod from the function.
Also, when entering a function:
√ in the register [A] a method set
Prefix: "0" - Pulse, "1" - tone.
, √ in the register [B] specified pulse period
in ms
- √ in case [C] mezhtsifrovaya pause ms/10
This function returns:
√ Carry Flag cleared - a set of numbers
performed successfully.
√ Carry Flag is set - bug
error code [A]:
# 00 ERROR SET
# 01 No long Toots
# 02 execution is terminated, pressed the spacebar>
This function is called
If you notice BELL.
Modem connects to the line and
Specifies the number.
D_AON EQU # C01E
When you call the function:
[A] number zaprovoe
[B] pause before requesting
[C] the number of digits
[D] sensitivity to the response PBX
[E] the sensitivity of the line
When leaving the functions in the modem buffer
be ASCII string with a message ending with Code # 00.
Pairing
ACTIVE
SET_CON_A EQU # C021
The passive
SET_CON_P EQU # C024
These functions try to choose nailudshuyu exchange rate.
Function active Setup passes at different speeds
data, and then check how they started. Function of the passive
installation first accepts data then informs their
admission. Konkternaya implementation of these
functions not specified.
Both functions return a text message about the speed required
one. Message located in the buffer ends with a modem and Code #
00. Also at return from functions accumulator written number
required one speed or # 80 if speed select failed.
In case of impossibility of performance
function returns with carry flag set.
SET TIME
D_SET_TIME EQU # C027
This feature allows you to set
current time. If you call the data
located in registers [A], [B], [C]: [A]
- Watch, [B] - minute, [C] - seconds. Data presented in BCD
form. In the case of error, the function returns
carry flag set.
COUNT TIME
D_RD_TIME EQU # C02A
This feature allows you to see the current time. On return from
the function data should be kept in registers [A], [B],
[C] in BCD form. In [A] -
hours, [B] - minute, [C] - seconds. In the case of error, the
function returns with carry flag set.
CORRECTION TIME
D_CALC_TIM EQU # C02D
This function is called multiple
times per minute. If the clock is not used
are completely independent (eg
Hours are femtosecond counter
pulses connected to parallel
port), and it takes time correction, then
it uses this function.
Attention! This function must preserves the value of all
registers!
Set the timer
D_SET_ALR EQU # C036
If the driver supports the timer mode, this function should set
timer indications in register pair
[BC] seconds.
In the case of error, the function returns
carry flag set.
ADD TO TIMER
D_ADD_ALR EQU # C039
This feature adds to the remaining time indication in the
register pair [BC] seconds.
In the case of error, the function returns
carry flag set.
Time has run out?
D_RD_ALR EQU # C03C
This function verifies approached-whether to
the end of the time set in timer. If
time out, then the function returns with
carry flag set.
Attention!
The program Macro Modem v2.20 features
works with clock / timer not used
they are reserved for buduyuschie version.
_____
We offer you an example
drivers under the most simple "modem"
common in Saint-Petersburg.
CALLING EQU 01
; FLAG PERMISSION DIALING
And if "1", then the drivers will gain
; NUMBER AND RESPOND TO CALLS
And if "0" - WILL NOT, BUT WILL NOT
; Hangs ABSENCE gadgets
ORG # C000
; KERNAL SUBPROGRAMME
JP D_INSTAL
JP D_NAME
JP D_RD_STAT
JP D_WAIT_INS
JP D_WAIT_LN
JP D_WAIT_BLC
JP D_TRANSMIT
JP D_ON_LINE
JP D_OFF_LINE
JP D_CALL
JP D_AON
JP SET_CON_A
JP SET_CON_P
JP D_SET_TIME
JP D_RD_TIME
JP D_CAL_TIM
JP D_SET_ALR
JP D_ADD_ALR
JP D_RD_ALR
; Working variables DRIVERS
LINE_STATUS DB 0
SPEED DB 0
LCOUNT_ADB 0
LCOUNT_BDB 0
LCOUNT_CDB 0
ZERO_BYTE DB 0; BYTES are before
; LENGTH IN BLOCK
SYNC_TABL DS 15
; INSTALLING DRIVERS
; In: [HL] Address of buffer MODEM
; Out: the buffer in ASCII form of values
, Speed.
; Every SPEED 4 bytes,
; Number of speeds, 8 ENDS # 00
D_INSTAL RET C
And if DRAVER Called SET
; FLAG CY - it's RUNNING FOR
, Unpacking, and ignore it
LD (MOD_BUFF1), HL; Write to
LD (MOD_BUFF2), HL; THE RIGHT PLACE
LD (MOD_BUFF3), HL; ADDRESS
LD (MOD_BUFF4), HL; BUFFER
; Throws in BUFFER SPEED DRIVER
EX DE, HL
LD HL, SPD_MODEM
LD BC, ESPD_MODEM-SPD_MODEM
LDIR
RET
SPD_MODEM
DB "600", "1800", "2400"
DS 5 * 5
ESPD_MODEM
: Reading driver information
; Out: ON [DE] RECORD TITLE
; Drivers (up to 80 characters)
; ENDS CODE # 00
D_NAME LD HL, NAME_MODEM
LD BC, ENAME_MODEM-NAME_MODEM
LD DE, (MOD_BUFF1)
LDIR
RET
NAME_MODEM
DB "Vicomm-modem driver v1.04"
DB "(C) 1997 * MAS *", 0
GENAME_MODEM
; Read the status of lines / DRIVER
; In: [A] Border color
; Out: [A] - DATA FOR PORT # FE
, TK Border color + control bits
; LINE AND EXIT LINES
; [B]: bit-:
, 0 STATUS LINES (free / busy)
3 availability of touchtone
, 4 TUBRO SWITCH OFF IN DRIVERS CHALLENGE
, 5 The line
, 6 AVAILABLE TIMER
, 7 HOURS OF AVAILABILITY
D_RD_STAT
AND 7: LD C, A
LD A, (LINE_STATUS)
LD B, A: OR C
OUT (# FE), A: LD (BORDER_0 +1), A
OR # 08: LD (BORDER_1 +1), A
PUSH AF
XOR A: INC B: DEC B
JR Z, $ +3: INC A
IF CALLING
; SWITCH OFF TURBO, IS MANAGEMENT LINE,
; NO HOURS TIMER
OR% 00110000
ELSE
; SWITCH OFF THE TURBO, NO CONTROL LINE,
; NO HOURS TIMER, HANDSET WITHDRAW
OR% 00010001
ENDIF
LD B, A
POP AF: RET
; WITHDRAW PIPE
D_ON_LINE LD A, # 20: JR ON_OFF_L
; Hang
D_OFF_LINE XOR A
ON_OFF_L
; CHANGE STATUS LINE, IF NO
; CONTROL LINE - RETURN IMMEDIATELY
IF CALLING
LD (LINE_STATUS), A
LD B, A: LD A, (BORDER_0 +1)
OR B: LD (BORDER_0 +1), A
OUT (# FE), A
OR # 08: LD (BORDER_1 +1), A
ENDIF
RET
; Dialed TUBE already removed
; In:
; [HL] - Address of buffer NUMBER
; [A] - 0 pulse, a tone
; [B] pulse period ms, typ. 100
; [C] mezhtsifrovaya pause ms/10
; CY = 1 Error, error code [A]:
; 0 error DIALING
; 1 NO slow beeps
2 INTERRUPT
; CY = 0 Connection established:
; Returns data from both SET_CON_P
D_CALL
IF CALLING
LD (ID_CALL +1), HL
PUSH BC
; SETS P / P SCAN LINES
XOR A: CALL D_WAIT_INS
POP BC
LD A, C: LD (CDEL_COD +1), A
; ASK pulse period, by the standards
, Gives 2 / 5 PERIOD LINE closed
And 3 / 5 PERIOD LINE OPEN
; DIVISIBLE PERIOD TO 5
LD A, B: LD B, 0
DIV5SUB 5: JR C, EDIV5
INC B: JR DIV5
-EDIV5 INC B: DEC B: JR NZ, $ +3: INC B
LD A, B: RLCA; 2 / 5 PERIOD
LD (CDEL_1 +1), A
ADD A, B; 3 / 5 PERIOD
LD (CDEL_0 +1), A
; Writes a value to be issued PORT
; # FE for closing / opening LINES
LD A, (BORDER_0 +1): AND # 0F
LD (DCAL_OFF +1), A
LD A, (BORDER_1 +1): OR # 20
LD (DCAL_ON +1), A
; MASENKAYA Pause before dialing
EI: LD B, 45: HALT: DJNZ $ -1
; CONTROL slow beeps:
; Making 200 SURVEY LINE IF
; CATCH 30 consecutive BUZZER - ALL OK
LD BC, 200 * 256 30
WAIT_DIA CALL WAIT_CALL
JR C, DWAIT_R; Toots NO
DEC C
JR Z, ID_CALL; CATCH 30 times
JR DWAIT_N
And if at least once LOST BUZZER - Charter; VIT COUNTER AGAIN
AT 30
DWAIT_R LD C, 30
And if pressing the space bar - EXIT
DWAIT_N LD A, # 7F: IN A, (# FE)
RRCA: JR NC, BRK_CALL
DJNZ WAIT_DIA
NO_DIAL LD A, 1: SCF: RET; NO SIGNAL
-BRK_CALL LD A, 2: SCF: RET; INTERRUPT
ERRD_CALL XOR A: SCF: RET; ERROR
ED_CALL XOR A: RET; number is entered
; Own set NUMBERS
/ ID_CALL LD HL, 0; HERE TO ADDRESS BUFFER
LD A, (HL): INC HL
LD (ID_CALL +1), HL
OR A; Find the code # 00
JR Z, ED_CALL; Ending SET
, The symbol "-", "(" ")", "" ignoring
CP "-": JR Z, ID_CALL
CP "(": JR Z, ID_CALL
CP ")": JR Z, ID_CALL
CP "": JR Z, ID_CALL
SUB "0": JR C, ERRD_CALL
; If it's not numbers - type error
, Figure "0" corresponds to 10 pulses
JR NZ, $ +4: LD A, 10
CP 11: JR NC, ERRD_CALL
LD B, A
; RECRUITED figures, in [B] NUMBER OF PULSES
CALL_C
; BREAK LINE 60ms (3 / 5)
DCAL_OFF LD A, 0
OUT (# FE), A
CDEL_0 LD A, 0
DDEL_0 LD C, 248
DEC C: JP NZ, $ -1
DEC A: JP NZ, DDEL_0
; SHORT LINE AND BREAK 40ms (2 / 5)
DCAL_ON LD A, 0
OUT (# FE), A
; DELAY IN [A] ms
CDEL_1 LD A, 0
DDEL_1 LD C, 248
DEC C: JP NZ, $ -1
DEC A: JP NZ, DDEL_1
DJNZ CALL_C
; MEZHTSIFROVAYA Pause 600ms
CDEL_COD LD B, 0
W_CDEL NOP: NOP: LD DE, 1457
DEC DE: LD A, D
OR E: JP NZ, $ -3
DJNZ W_CDEL
And if pressing the space bar - LEAVING, AKA RECRUITED
; NUMBER ON
LD A, # 7F: IN A, (# FE)
RRCA: JR NC, BRK_CALL
JR ID_CALL
; Examine LINE 32 times
WAIT_CALL DI: PUSH BC
LD B, 32
LD HL, 0
CALL_DIAL LD DE, # 0B59
CALL SCAN_IN
CALL DELAY_37
LD E, A: LD D, 0: ADD HL, DE
DJNZ CALL_DIAL
POP BC
; CONTROL Toots, average. Arithmetic.
; VALUE RATE FOR THE 1932 SURVEY
SRA H: RR L: SRA H: RR L
SRA H: RR L: SRA H: RR L
SRA H: RR L
LD A, L: SRA A
; In the range 150 ... 250 - FREQUENCY Toots
CP 150: RET C
CP 250: CCF
RET
XOR A: SCF: RET
ENDIF
; Called when DETECTED BELL.
, Picks up the receiver. + Caller ID
; (HERE MISSING!)
; Out: MOD_BUFF NUMBER IN ASCII, END 0
D_AON CALL D_ON_LINE
LD B, 75: EI: HALT: DJNZ $ -2: DI
, After removing the Handset Pause 1.5 sec.
, IF ANY AON, then he can determine
; NUMBER
; Throws MODEM MESSAGE IN BUFFER
; On Off-hook
MOD_BUFF3 EQU $ +1: LD DE, # 1111
LD HL, AON_TXT
LD BC, EAON_TXT-AON_TXT
LDIR
RET
AON_TXT
DB 13, "The modem is connected to the line, 13.0
EAON_TXT
; Two following the P / P USED
; AS "stub", as Auto Algorithm
; RATE IS NOT Ponders
; Establish a connection, transfer
, TE IN THE BEGINNING "Send", then "LISTEN"
SET_CON_A
; Establish a connection, the reception
, TE FIRST LISTEN, THEN "Send"
SET_CON_P
MOD_BUFF4 EQU $ +1: LD DE, 0
IF CALLING
PUSH HL
LD (HL), 13: LD BC, 1: XOR A
CALL D_TRANSMIT
POP HL
ENDIF
; Pairing
; In MOD_BUFF Returns a text Messaging.
; The connection at the end - RCD # 00
, V [A] set speed, OR # 80
And if it Undefined
LD HL, CARR_TXT
LD BC, ECARR_TXT-CARR_TXT
LDIR
LD A, # 80; SPEED Undefined
RET
CARR_TXT
DB 13, "set to bridge the" 13.0
ECARR_TXT
; INSTALLATION BEFORE SCAN LINES
; In [A] - VOLUME AUDIO OUTPUT LINE
; THROUGH AY
D_WAIT_INS
LD HL, # 4000: LD (LCOUNT_A), HL
AND # 0F: SET 6, A: LD (SOUND +1), A
JR Z, D_WAIT_INS1
LD BC, # FFFD: LD A, 7: OUT (C), A
LD B, # BF: LD A, # 3F: OUT (C), A
GD_WAIT_INS1
XOR A: LD (LAST_DT +1), A
LD (COUNT0 +1), A
LD (COUNT1 +1), A
LD (LAST0 +1), A
LD (OFFCOU +1), A
RET
; SCAN LINES
; Out
; CY = 1: NOTHING
; [B] NUMBER OF CYCLES SURVEY
; [C] How many SHOULD BE CYCLES
; CY = 0,; [A] - CODE:
, 1 - APPROVED UNIT, 2 - Activities 3 - A CHALLENGE
D_WAIT_LN
DI
LD HL, 0
LD DE, 16 * 256 12, 11
LD BC, # FFFD: LD A, 8: OUT (C), A
LD A, (SOUND +1)
AND # 0F: JR Z, $ +4: LD B, # BF
; POLL LINE UNIT AND CLOCK
; CONTROL KOTOTKIH Gudkov, BEGINNING
, Is considered average. Arithmetic. SIGNIFICANCE OF FREQUENCY
; For 16 POLLS
MDLOOP1
IN A, (# FE): AND # 20
; ANALYSIS / NO ALARM CALL
IF CALLING
JP Z, RING: ELSE: JP $ +3
ENDIF
CALL IN_LINE_F
CP 1911: JP C, MDLOOP2
CP 1989: JP NC, MDLOOP2
DEC E: JP Z, INPUT_BLOCK; BLOCK?
MDLOOP2 ADD A, L: LD L, A
JR NC, $ +3: INC H
DEC D: JP NZ, MDLOOP1
SRA H: RR L: SRA H: RR L
SRA H: RR L: SRA H: RR L
LD A, L: SRA A
; In the range 150 ... 250 - FREQUENCY Toots
And if a dial tone, then A = 1 OTHERWISE A = 0
CP 150: JR C, TST_OFFL
CP 250: JR C, TST_ONL
TST_OFFL XOR A: JR $ +4
TST_ONL LD A, 1
; IF Comp. Signal does not change,
; Simply increase COUNTER. IF
; Change, then SWITCH COUNTER
LAST_DT CP 0: LD (LAST_DT +1), A
JR NZ, NEW_DTL
ADR_IDL LD HL, 0: INC (HL): LD A, (HL)
CP 200: CALL NC, D_WAIT_INS1
JR E_WAIT_LN
; Frequency changing:
NEW_DTL DEC A: JR Z, NEW_DTL1
, Became "0": Switch COUNTER
LD HL, COUNT0 +1: LD (HL), 0
LD (ADR_IDL +1), HL
, IF> 4 One unit> 4 zeros in succession,
; MEAN CATCH Last post
COUNT1 LD A, 0: CP 4: JP C, RES_OFF
LAST0 LD A, 0: CP 4: JP C, RES_OFF
; CAUGHT 3 beeps RETIRE
OFFCOU LD A, 0: INC A: LD (OFFCOU +1), A
CP 3: JR Z, BUSY_FOUND
; SPEED STEEL "1": Switch COUNTER
NEW_DTL1 LD HL, COUNT1 +1: LD (HL), 0
LD (ADR_IDL +1), HL
COUNT0 LD A, 0
JPE_WAIT_LN LD (LAST0 +1), A
JR E_WAIT_LN
RES_OFF XOR A
LD (COUNT0 +1), A
LD (COUNT1 +1), A
JR JPE_WAIT_LN
BUSY_FOUND
OR A: LD A, 2; CY = 0, A = 2 "BUSY"
RET
; CATCH CALL FOR A REALITY CHECK
; IF SIGNAL CALL WILL KEEP
; Some time - THEN CALL IN NATURE
GRINGLD C, 2
RING1 LD B, 30: NOP: DJNZ $ -1
IN A, (# FE): AND # 20
JP NZ, D_WAIT_LN
DEC C: JR NZ, RING1
; CALL IS EXPECTED ITS END
RING2 IN A, (# FE): AND # 20: JR Z, RING2
LD A, 3; CY = 0, A = 3 "BELL"
RET
E_WAIT_LN LD BC, # 0101
SCF: RET; CY = 1 - nothing
; POLL hold: [A] TO FREQUENCY SIGNAL
IN_LINE_F PUSH HL: PUSH DE
LD DE, (LCOUNT_A)
SOUND LD L, 0
LP_TIN_F INC E: JP Z, END_TIN_F
INC E: JP Z, END_TIN_F
IN A, (# FE)
RLCA: RLCA: SBC A, A
AND L: NOP: OUT (C), A
AND # 40: XOR D: JP Z, LP_TIN_F
XOR D: LD (LCOUNT_B), A
RET_TIN_F LD A, E
LD HL, LCOUNT_A
SUB (HL): LD (HL), A
LD A, E
POP DE: POP HL
RET
END_TIN_F DEC E: JR RET_TIN_F
; CATCH CLOCK, TAKE THE BLOCK
INPUT_BLOCK
CALL IN_LINE
CALL CONTR_SPEED
CALL LOAD_DATA
RET C
E_LOAD_DT LD A, (SPEED): LD D, A
BLOCK_LEN EQU $ +1: LD BC, # 0101
; CY = 0 Successful TOOK THE BLOCK
OR A: LD A, 1
RET
; Long wait UNIT AND RECEIVING UNIT
; Out: CY NO BLOCK
; [BC] LENGTH
; [D] SPEED (# 80 unknown)
D_WAIT_BLC
CALL WAIT_LINE: RET C
CALL LOAD_DATA
CALL LINE_FREE
JR E_LOAD_DT
SCAN_IN CALL IN_LINE
CP D: RET C
CP E: CCF
RET
IN_LINE_D; DELAY AND SURVEY ENTRY
PUSH BC: POP BC
; SURVEY ENTRY
IN_LINE PUSH HL: PUSH BC
LD A, (LCOUNT_A): LD C, A
LD A, (LCOUNT_B): LD B, A
LOOP_TIN INC C: JP Z, END_TIN
IN A, (# FE): AND # 40
XOR B: JP Z, LOOP_TIN
XOR B: LD (LCOUNT_B), A
RET_TIN LD A, C
LD HL, LCOUNT_A
SUB (HL): LD (HL), A
LD A, C
POP BC: POP HL
RET
END_TIN DEC C: JR RET_TIN
; PENDING RELEASE OF LINE, VERT
; Here as long as the lines are not
; Disappear SUBSCRIBER SIGNAL
LINE_FREE
PUSH AF: PUSH DE: PUSH BC
XOR A: LD (LCOUNT_A), A
LD A, # 40: LD (LCOUNT_B), A
CALL IN_LINE
LD DE, # 0570, # 0180
NOP: NOP
LN_FREE1 NOP: NOP
LN_FREE2 LD B, 4
CALL DELAY_37
CALL SCAN_IN
NOP: JP NC, LN_FREE1
LN_FREE3 DEC B: JP Z, LINE_FREE4
CP # FF: JP NC, LINE_FREE4
CALL DELAY_37
CALL SCAN_IN
JP C, LN_FREE3
JP LN_FREE2
, The line is free
LINE_FREE4
POP BC: POP DE: POP AF
RET
; TIMING UNIT
SYNCD1_IN JP SYNC1_IN
SYNC1_IN NOP: NOP
CALL IN_LINE
CP D: JP C, ED_SYNCD
CP E: CCF: JP C, ED_SYNCD
LD B, A
LD A, (HL)
OR A: JP Z, SYNC1_I1
ADD A, B: LD (HL), A
SYNC1_I2 ADD A, 0
INC HL
RET
SYNC1_I1 JP SYNC1_I2
SYNCD2_IN JP SYNC2_IN
SYNC2_IN NOP: NOP
SYNC2_I6 CALL IN_LINE
CP D: JP C, ED_SYNCD
CP E: CCF: JP C, ED_SYNCD
LD B, A
LD A, (HL)
SUB B
JP P, SYNC2_I2
XOR A: ADD A, 0
SYNC2_I1 LD (HL), A
INC HL
RET
SYNC2_I2 JP SYNC2_I1
ED_SYNCD INC SP: INC SP
ERR_SYNC POP DE: POP HL
RET
; DELAY ON PASS. The number of cycles
DELAY_57 JP DELAY_47
DELAY_47 JP DELAY_37
DELAY_37 CALL DELAY_27
DELAY_27 RET
DELAY_68 CALL DELAY_27
CALL DELAY_27
NOP
RET
DELAY_C LD B, # FE
CALL DELAY_47
CALL DELAY_47
DJNZ DELAY_C +2
DEC C: JP NZ, DELAY_C
RET
, Waiting for a signal SUBSCRIBER
; During 2 ... 4 seconds
WAIT_LINE DI
LD HL, # 4000: LD (LCOUNT_A), HL
LD D, 3
WT_LINE1 LD E, 3
WT_LINE2 LD H, 1
WT_LINE3 LD B, 16
LD A, H: LD (LCOUNT_C), A
LP_WLINE CALL IN_LINE
CP MIN +1: JP C, WAIT_CONTR1
CP # 2D: JP C, WAIT_SPEED
WAIT_CONTR
ADD A, L: JP NC, $ +4: INC H
ADD A, 6: LD L, A
JP NC, $ +4: INC H
LD A, (LCOUNT_C)
CP H
JP C, WT_LINE3
JP Z, WAIT_CONTR2
DEC E: JP NZ, WT_LINE2
DEC D: JP NZ, WT_LINE1
SCF: RET
WAIT_CONTR1 CP 5
JP WAIT_CONTR
WAIT_CONTR2 LD B, 16
JP LP_WLINE
; SPEED CONTROL IN WAITING
WAIT_SPEED
CALL DELAY_47: NOP
DEC B: JP NZ, LP_WLINE
CALL IN_LINE
; Speed control. Counting the number of pulses, SOI => SPEED
CONTR_SPEED
LD BC, # 0006
CALL IN_LINE
CALL IN_LINE_D
CALL IN_LINE_D
PUSH BC: POP BC
C_SPEED CALL IN_LINE
ADD A, B: LD B, A
DEC C: JR NZ, C_SPEED
OR A
RET
; RECEPTION UNIT.
; In [B] The number of pulses (SPEED)
LOAD_DATA
MOD_BUFF1 EQU $ +1: LD HL, 0
LD A, 195: CP B
JP C, INP_600;?> 195 = 600
LD A, 130: CP B
JP C, INP_1800;?> 130 = 1800
LD A, 60: CP B
CCF: RET C;?> 060 = 2400
INP_FAST LD A, 2
LD (SPEED), A; 2400
CALL SYNC_FAST: RET C
CALL LOAD_BYTE_FAST: RET C
And the taking of block length: if 0-byte
; Equals # 08, then the length UNIT FOR MORE
; 256 bytes
LD (ZERO_BYTE), A
LD D, 0
CP 8: JR NZ, $ +3: INC D
And the taking of the MLS. Length Byte
CALL LOAD_BYTE_FAST: RET C
LD E, A: OR A: JR NZ, $ +3: INC D
LD (BLOCK_LEN), DE
And the taking of the block, LONG [DE]
GLD_BLOCK_FAST
CALL LOAD_BYTE_FAST: RET C
LD (HL), A
INC HL: DEC DE
LD A, D: OR E
JP NZ, LD_BLOCK_FAST
RET
; ACCEPT BYTES
LOAD_BYTE_FAST
LD B, 8; We catch 8-bit
CALL IN_LINE
; Determine the frequency, if it lies
; In the range from MIN to MAX, the bit
; ACCEPTED, AKA - ERROR
CP MIN: JP C, ERR_LDFAST
CP MAX: JP NC, ERR_LDFAST
; IF frequency is greater than ZERO - ADOPTED
; UNIT LESS - ZERO
CP ZERO
RL C; TOOK INVERTED BIT
CALL DELAY_47; 27
DEC B: JP Z, _LOAD_BYTE_FAST
CALL IN_LINE
JP LOAD_BYTE_FAST +2
_LOAD_BYTE_FAST
LD A, C: CPL; INVERTED BYTES
PUSH AF
CALL IN_LINE
POP AF
OR A: RET; BYTES ACCEPTED
ERR_LDFAST; receive error
POP BC
SCF: RET
; TIMING UNIT
SYNC_FAST PUSH HL
LD DE, MIN * 256 + ZERO-3
LD A, 1
LD (SYNC_TABL), A
LD (SYNC_TABL +1), A
CALL IN_LINE
CALL DELAY_68
CALL IN_LINE
S1_FAST CALL DELAY_57
CALL IN_LINE
CP D: JP C, ERR_SYNC
CP E: JP C, S1_FAST
LD E, MAX-1
LD HL, SYNC_TABL
CALL DELAY_47
CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
CALL IN_LINE
CALL DELAY_47
CALL DELAY_27
CALL SYNCD1_IN
CALL SYNCD1_IN
LD HL, SYNC_TABL
CALL SYNC2_IN
CALL SYNCD2_IN
LD HL, SYNC_TABL
CALL SYNC1_IN
CALL SYNCD1_IN
LD HL, SYNC_TABL
CALL SYNC2_IN
CALL SYNCD2_IN
LD HL, SYNC_TABL
CALL SYNC1_IN
LD C, A
CALL SYNCD1_IN
CP C: JP M, S2_FAST
CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
S2_FAST CALL IN_LINE
CALL DELAY_68
CALL IN_LINE
POP HL
OR A: RET
;! For the rate of 1800/600 are all very
, LIKE, SO NO COMMENT
INP_1800 LD A, 1: LD (SPEED), A
CALL IN_LINE
CALL DELAY_27
NOP
LD DE, # 0E19
LD DE, # 0E19
CALL SYNC_1800: RET C
LD D, 0
CALL LOAD_BYTE_1800: RET C
LD (ZERO_BYTE), A
CP 8: JR NZ, $ +3: INC D
; Receives long
CALL LOAD_BYTE_1800: RET C
LD E, A: OR A: JR NZ, $ +3: INC D
LD (BLOCK_LEN), DE
GLD_BLOCK_1800
CALL LOAD_BYTE_1800: RET C
LD (HL), A
INC HL: DEC DE
LD A, D: OR E
JP NZ, LD_BLOCK_1800
RET
LOAD_BYTE_1800
PUSH BC: LD B, 8
CALL IN_LINE
CP # 0F: JP C, ERR_LD1800
CP # 2D: JP NC, ERR_LD1800
CP # 1C: LD A, C: RLA: LD C, A
CALL DELAY_27
DEC B: JP NZ, NEXT_B1800
LD A, C: CPL
POP BC
PUSH AF
CALL IN_LINE
POP AF
OR A: RET
NEXT_B1800
CALL DELAY_27
NOP
CALL IN_LINE
CALL DELAY_57
CALL DELAY_27
NOP
JP LOAD_BYTE_1800 +3
ERR_LD1800
POP BC
SCF: RET
SYNC_1800 PUSH HL
PUSH DE
OR A: LD A, 1
LD (SYNC_TABL), A
LD (SYNC_TABL +1), A
CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
NOP
CALL IN_LINE
CALL DELAY_27
NOP
S1_1800 CALL DELAY_68
CALL IN_LINE
NOP
CP D: JP C, ERR_SYNC
CP E: JP C, S1_1800
LD DE, # 0E2E
LD HL, SYNC_TABL
CALL DELAY_47
CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
NOP
CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
NOP
CALL IN_LINE
CALL DELAY_47
CALL DELAY_27
ADD A, 0
CALL SYNCD1_IN
CALL SYNCD1_IN
LD HL, SYNC_TABL
CALL SYNC2_IN
CALL SYNCD2_IN
LD HL, SYNC_TABL
CALL SYNC1_IN
CALL SYNCD1_IN
LD HL, SYNC_TABL
CALL SYNC2_IN
CALL SYNCD2_IN
LD HL, SYNC_TABL
CALL SYNC1_IN
LD C, A
ADD A, 0
CALL SYNCD1_IN
CP C: JP M, S2_1800
CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
NOP
S2_1800 CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
NOP
CALL IN_LINE
POP DE
POP HL
OR A: RET
INP_600 XOR A: LD (SPEED), A
CALL IN_LINE
NOP
LD DE, # 1728
LD DE, # 1728
CALL SYNC_600: RET C
LD D, 0
CALL LOAD_BYTE_600: RET C
LD (ZERO_BYTE), A
CP 8: JR NZ, $ +3: INC D
; Receives long
CALL LOAD_BYTE_600: RET C
LD E, A: OR A: JR NZ, $ +3: INC D
LD (BLOCK_LEN), DE
LD_BLOCK_600
CALL LOAD_BYTE_600: RET C
LD (HL), A
INC HL: DEC DE
LD A, D: OR E
JP NZ, LD_BLOCK_600
RET
GLOAD_BYTE_600
PUSH DE: PUSH BC
LD B, 8
CALL IN_LINE
CALL IN_LINE
CALL IN_LINE
CP # 17: JP C, ERR_LD600
CP # 59: JP NC, ERR_LD600
CP # 2D: LD A, E: RLA: LD E, A
CALL IN_LINE
DEC B
JP NZ, LOAD_BYTE_600 +4
LD A, E: CPL: OR A
POP BC
POP DE
RET
ERR_LD600 POP BC: POP DE
SCF: RET
SYNC_600 PUSH HL: PUSH DE
OR A
LD A, 1
LD (SYNC_TABL), A
LD (SYNC_TABL +1), A
LD (SYNC_TABL +2), A
LD (SYNC_TABL +3), A
CALL IN_LINE
CALL DELAY_68
CALL DELAY_27
NOP
CALL IN_LINE
CALL DELAY_27
NOP
S1_600 CALL DELAY_68
CALL IN_LINE
NOP
CP D: JP C, ERR_SYNC
CP E: JP C, S1_600
LD A, (SYNC_TABL +4)
INC A
LD (SYNC_TABL +4), A
ADD A, 0
LD DE, # 0E59
LD HL, SYNC_TABL
CALL SYNCD1_IN
CALL SYNCD1_IN
CALL SYNCD1_IN
CALL SYNCD1_IN
LD HL, SYNC_TABL
CALL SYNC2_IN
CALL SYNCD2_IN
CALL SYNCD2_IN
CALL SYNCD2_IN
LD HL, SYNC_TABL
CALL SYNC1_IN
CALL SYNCD1_IN
CALL SYNCD1_IN
CALL SYNCD1_IN
LD HL, SYNC_TABL
CALL SYNC2_IN
CALL SYNCD2_IN
CALL SYNCD2_IN
CALL SYNCD2_IN
LD HL, SYNC_TABL
CALL SYNC1_IN
CALL SYNCD1_IN
CALL SYNCD1_IN
CALL SYNCD1_IN
LD HL, SYNC_TABL
CALL SYNC2_IN
CALL SYNCD2_IN
CALL SYNCD2_IN
CALL SYNCD2_IN
LD HL, SYNC_TABL
CALL SYNC1_IN
CALL SYNCD1_IN
CALL SYNCD1_IN
CALL SYNCD1_IN
LD HL, SYNC_TABL
CALL SYNC2_IN
LD C, A
ADD A, 0
CALL SYNC2_IN
CP C: JP M, EXT_SYNC
LD C, A
CALL SYNC2_I6
CP C: JP M, EXT_SYNC
LD C, A
CALL SYNC2_I6
CP C: JP M, EXT_SYNC
OR A: JP Z, ERR_SYNC
NOP
CALL IN_LINE
EXT_SYNC POP DE: POP HL
OR A: RET
; TRANSFER UNIT FROM MOD_BUFF,
; BC - LENGTH, A - SPEED
D_TRANSMIT DI
LD (SPEED), A
PUSH AF; keep your speed
MOD_BUFF2 EQU $ +1: LD HL, 0
DEC HL
PUSH HL
ADD HL, BC
EX (SP), HL; Ambassador. BYTE
LD (HL), C; MLS. Length Byte
DEC HL: LD (HL), 7
LD A, B: OR A
JR Z, $ +3: INC (HL); LENGTH> 256
DEC HL
LD (HL), # AA; SYNC BYTES
XOR A
DEC HL: LD (HL), A
DEC HL: LD (HL), A
DEC HL
POP DE; ADDRESS OF LAST BYTE
POP AF; RATE
OR A: JP Z, TRANSMIT_600
DEC A: JP Z, TRANSMIT_1800
GTRANSMIT_FAST
XOR A: LD (HL), A; SYNCHRO
DEC HL: LD (HL), A
DEC HL: LD (HL), A
DEC HL: LD (HL), A
DEC HL: LD (HL), A
CALL LINE_FREE
PUSH BC
LD C, 1: CALL DELAY_C
POP BC
CALL OUTPUT_FAST
PUSH HL
PUSH DE
LD BC, # 020C
LD A, 0
NOP: NOP: NOP: NOP
JP OUT_BIT2600
, Gives BLOCK
OUTPUT_FAST
LD A, (HL); Bytes sent
CALL OU_BYTE_FAST
NOP
CALL COMP_HL_DE
RET Z; block is transferred
INC HL: JP OUTPUT_FAST
; TRANSFER BYTE
OU_BYTE_FAST
PUSH HL: PUSH DE
LD BC, # 080C
OUT_BIT2600
PUSH AF
RLA: JP C, BIT1_FAST
LD HL, D0_FAST: JP OB_FAST; = 0
. BIT1_FAST LD HL, D1_FAST: JP OB_FAST; = 1
; When transferring 1-th bit MIC OFF FOR LESS
, 12 (168 cycle), because 168 CTTA NEEDED
; To obtain the next. BYTE, CONTROL, ...
GOB_FAST RRA
LD A, (HL)
SUB C: LD D, A: INC HL
LD E, (HL): INC HL
CALL OUT_DATA
POP AF
RLCA
DEC B
LD C, 0: LD C, 0: NOP
JP NZ, OUT_BIT2600
POP DE: POP HL
RET
; LIKE FOR 1800/600
GTRANSMIT_1800
XOR A: LD (HL), A
DEC HL: LD (HL), A
CALL LINE_FREE
PUSH BC
LD C, 1: CALL DELAY_C
POP BC
CALL OUTPUT_1800
PUSH HL: PUSH DE
LD BC, # 020C
LD A, 0
NOP: NOP: NOP: NOP
JP OUT_BIT1800
OUTPUT_1800
LD A, (HL)
CALL OU_BYTE_1800
NOP
CALL COMP_HL_DE
RET Z
INC HL: JP OUTPUT_1800
OU_BYTE_1800
PUSH HL: PUSH DE
LD BC, # 080C
OUT_BIT1800
PUSH AF
RLA: JP C, BIT1_1800
LD HL, D0_1800: JP OB_1800; = 0
-BIT1_1800 LD HL, D1_1800: JP OB_1800; = 1
GOB_1800 RRA
LD A, (HL)
SUB C: LD D, A: INC HL
LD E, (HL): INC HL
CALL OUT_DATA
POP AF
RLCA
DEC B
LD C, 0: LD C, 0: NOP
JP NZ, OUT_BIT1800
POP DE: POP HL
RET
TRANSMIT_600
CALL LINE_FREE
PUSH BC
LD C, 1: CALL DELAY_C
POP BC
CALL OUTPUT_600
PUSH HL: PUSH DE
LD BC, # 020D
LD A, 0
NOP: NOP: NOP: NOP
JP OUT_BIT600
OUTPUT_600
LD A, (HL)
CALL OU_BYTE_600
RLA: LD B, A
CALL COMP_HL_DE
LD A, B: RRA
RET Z
INC HL: JP OUTPUT_600
OU_BYTE_600
PUSH HL: PUSH DE
LD BC, # 080D
NOP
OUT_BIT600
PUSH AF
RLA: JP C, B71_600; B7 = 1
RRA: JP C, B70_B01; B7 = 0, B0 = 1
LD HL, D00_600; B7 = 0 B0 = 0
JP OB_600
B71_600 RRA: JP NC, B71_B01
LD HL, D10_600; B7 = 1 B0 = 0
JP OB_600
B71_B01 LD HL, D11_600; B7 = 1 B0 = 1
JP OB_600
B70_B01 LD HL, D01_600; B7 = 0 B0 = 1
JP OB_600
OB_600 NOP
LD A, (HL)
SUB C: LD D, A: INC HL
LD E, (HL): INC HL
CALL OUT_DATA
CALL OUT_DATA
POP AF
RLCA
DEC B
LD C, 0: NOP: NOP
JP NZ, OUT_BIT600
POP DE: POP HL
RET
To compare the HL AND DE
COMP_HL_DE
NOP
LD A, H: CP D
JP NZ, $ +6: LD A, L: CP E: RET
NOP: NOP: RET
; TRANSFER BIT
OUT_DATA
DEC D: JP NZ, $ -1; DELAY D
BORDER_0 LD A, # 00; MIC OFF
JP $ +3
OUT (# FE), A
DEC E: JP NZ, $ -1; DELAY E
BORDER_1 LD A, # 08; MIC ON
JP $ +3
OUT (# FE), A
LD D, (HL): INC HL
LD E, (HL): INC HL
NOP
RET
; TABLES FOR TRANSMITTER
, 1800
D0_1800 DB 36,36 +13; frequency for "0"
D1_1800 DB 67,67 +13; FREQUENCY FOR "1"
D00_600 DB # 36, # 44, # 40, # 44; B7 = 0 B0 = 0
-D01_600 DB # 57, # 58, # 49, # 44; B7 = 0 B0 = 1
-D10_600 DB # 57, # 65, # 61, # 65; B7 = 1 B0 = 0
-D11_600 DB # 36, # 4D, # 54, # 65; B7 = 1 B0 = 1
D0_FAST DB 28,28 +13; TRANSFER CODE "0"
D1_FAST DB 51,51 +13; SPEED FAST "1"
MIN EQU 11
MAX EQU 37
GZEROEQU 23
, The number of ticks in the TRANSFER BIT
; T = (2 * D +13) * 14 +56 D - NUMBER OF TABLES
; D0_?? FOR TRANSMISSION "0" and D1_?? FOR "1"
; AVERAGE SPEED:
; SPEED = (SPD0 + SPD1) / 2
; SPD0 = 3500000/T0 SPD1 = 3500000/T1
; RECEIVER:
And if the line relevant number <MIN-ERROR
And if> MAX: ERROR
, If MIN