; FILENAME      MTOOL7.ASM V1.2
; DESCRIPTION   MTOOL7 MICRO-TOOL SYSTEM
; HARDWARE      MTOOL7 BOARD
; ASSEMBLER     SXA51
; START-DATE    14/09/94 update 11/07/95
; SOFTWARE ENG. KRIANGSAK B.
; COMPANY       SILA RESEARCH CO.,LTD.
;               TEL 392-3886 392-6183 FAX 381-1447
; NOTE          DS5000 FIRST  16K (0000-3FFF) = MONITOR PROGRAM , PMEM
;                      SECOND 16K (4000-7FFF) = WORKING DATA    , DMEM

; ********** VARIABLE **********

P0DATA   EQU    P0           ;DATA FOR LCD,8255
LCDRS    EQU    P1.0         ;ON BOARD LCD (CONTROL BIT)
LCDRW    EQU    P1.1
LCDEN    EQU    P1.2
PRTSTB   EQU    P1.3         ;PRINTER PORT (CONTROL BIT)
PRTBSY   EQU    P1.4
LEDRED   EQU    P1.5         ;LED BIT
LEDGRN   EQU    P1.6
TOOLBT   EQU    P1.7         ;TOOL BIT

COMDRV   EQU    T0           ;SERIAL PORT DRIVE BIT
SOUNDB   EQU    T1           ;SOUND BIT
P8255A0  EQU    INT0         ;8255 A0,A1 BIT
P8255A1  EQU    INT1

BRAT12   EQU    0E8H         ;1200 BAUD RATE VAR.
BRAT24   EQU    0F4H         ;2400
BRAT48   EQU    0FAH         ;4800
BRAT96   EQU    0FDH         ;9600
SMOD     EQU    B.7          ;FOR BAUD FUNCTION
STX      EQU    02H
ETX      EQU    03H

MCON     EQU    0C6H         ;DS5000 SFR
TA       EQU    0C7H
TIMVAR   EQU    4100

; ********** INTERNAL RAM **********

         ORG    0000H
         DS     8            ;REGISTOR BANK-0
SYSSTK:  DS     24

SYSFAG:  DS     2            ;SYSTEM FLAG (BIT ADDRESS)
GKEYOK   EQU    00H          ;GKEY - OK FLAG
GKEYPF   EQU    01H          ;GKEY - PRESS FLAG
SHFFAG   EQU    02H          ;GKEY - SHIFT FLAG
FUNFAG   EQU    03H          ;GKEY - FUNCTION FLAG
INPBKF   EQU    04H          ;INPUT - BACK FIELD FLAG
INPEXF   EQU    05H          ;INPUT - EXIT FLAG
INPHXF   EQU    06H          ;INPUT - HEX ONLY FLAG
COMERR   EQU    07H          ;RECV - RECEIVE ERROR

TCNTUD   EQU    08H          ;TCNT - UP/DOWN
TCNTRA   EQU    09H          ;TCNT - RESET/AUTO
TCNTLF   EQU    0AH          ;TCNT - LOW FLAG
TCNTOK   EQU    0BH          ;TCNT - COUNT OK FLAG
DUMPBM   EQU    0CH          ;TLREC - DUMP FLAG
TERMFG   EQU    0DH          ;RXTERM - TERMINAL FLAG
TXOK     EQU    0EH          ;RXTERM - TX OK
SCANPF   EQU    0FH          ;SCAN - PRESS FLAG

MAINCT:  DS     1            ;MAIN PAGE COUNTER
TERMCT:  DS     1            ;TERMINAL CHAR. COUNTER
INPSTT:  DS     1            ;INPUT - START POSITION
INPEND:  DS     1            ;INPUT - END POSITION
BAUDMM:  DS     1            ;BAUD RATE MEMORY (12,24,48,96,19)
TIMDIV:  DS     1            ;15 Hz COUNTER
TIMBUF:  DS     3            ;HH:MM:SS
HEXBUF:  DS     2            ;DK-124 HEX BUFFER

DISBUF:                      ;DK-124 DISPLAY BUFFER (4 BYTE)
RTCBUF:                      ;REAL TIME CLOCK BUFFER (8 BYTE)
COMBUF:  DS     19           ;COMMUNICATION BUFFER (DATA=16MAX)
LCDBUF:  DS     64           ;LCD BUFFER
ENDINT:

; ********** POWER **********

         ORG    0000H
POWER:   LJMP   RES
         DB     0FFH,0FFH,0FFH,0FFH
         DB     0FFH,0FFH,0FFH,0FFH
         LJMP   TIMUP
         DB     0FFH,0FFH,0FFH,0FFH
         DB     0FFH,0FFH,0FFH,0FFH
         DB     0FFH,0FFH,0FFH,0FFH
         DB     0FFH,0FFH,0FFH,0FFH
         DB     0FFH,0FFH,0FFH,0FFH
         DB     0FFH
         JNB    TERMFG,POWER2
         LJMP   RXTERM
POWER2:  LJMP   RXINT

; ********** RES **********

RES:     MOV    R2,#40H           ;POWER UP DELAY
RES1:    MOV    R3,#0
         DJNZ   R3,$
         DJNZ   R2,RES1
         MOV    SP,#SYSSTK        ;SET SYSTEM STACK
         CLR    SOUNDB            ;SOUND BIT LOW FIRST

         MOV    TA,#0AAH          ;TIME ACCESS (PAGE 24 OF DS5000UG)
         MOV    TA,#055H
         MOV    MCON,#11111010B   ;PAA=1
         MOV    TA,#0AAH
         MOV    TA,#055H
         MOV    MCON,#10001000B   ;SET DATA-RAM AT 4000H

         MOV    R0,#8             ;CLEAR INT-RAM
         MOV    R2,#80H-8
RES4:    MOV    @R0,#0
         INC    R0
         DJNZ   R2,RES4

         MOV    A,#00111000B      ;FUNCTION SET (LCD)
         LCALL  LCDWI
         MOV    A,#00001100B      ;DISPLAY ON/OFF
         LCALL  LCDWI
         MOV    A,#01H            ;CLEAR
         LCALL  LCDWI

         MOV    TMOD,#21H         ;TIMER1 MODE2 / TIMER0 MODE1
         MOV    SCON,#52H         ;SERIAL 8 BIT UART MODE
         MOV    A,#96H
         MOV    BAUDMM,A
         LCALL  BAUDS
         SETB   TR1               ;TIMER1 ON

         MOV    TH0,#HIGH TIMVAR
         MOV    TL0,#LOW TIMVAR
         MOV    TIMDIV,#0
         SETB   ET0
         SETB   EA                ;ALL ENABLE INTERRUPT

         LCALL  HBEEP
         MOV    DPTR,#RESTAB
         LCALL  LCDLDP
         MOV    R2,#20
         LCALL  DTSEC
         MOV    MAINCT,#0
         LJMP   MAIN

RESTAB:  DB     '     MTOOL-7    '
         DB     'Super Micro Tool'
         DB     'V1.2 Re.16/09/95'
         DB     'BY SILA RESEARCH'

; ********** TIMUP SUB ********** (TIMER 0 INTERRUPT)
; TIMER COUNT-UP FOR TIMER & STOP WATCH

TIMUP:   PUSH   ACC
         PUSH   PSW

         MOV    TH0,#HIGH TIMVAR  ;RESET TIME VARIABLE
         MOV    TL0,#LOW TIMVAR
         INC    TIMDIV
         MOV    A,TIMDIV
         CJNE   A,#15,TIMUP9
         MOV    TIMDIV,#0

         JB     TCNTUD,TIMUP4
         LCALL  TIMUPS
         SJMP   TIMUP9
TIMUP4:  LCALL  TIMDNS

TIMUP9:  POP    PSW
         POP    ACC
         RETI

TIMUPS:  MOV    A,TIMBUF+2        ;SECOND (**** TIME UP ****)
         ADD    A,#1
         DA     A
         MOV    TIMBUF+2,A
         CJNE   A,#60H,TIMUPS9
         MOV    TIMBUF+2,#0

         MOV    A,TIMBUF+1        ;MINUTE
         ADD    A,#1
         DA     A
         MOV    TIMBUF+1,A
         CJNE   A,#60H,TIMUPS9
         MOV    TIMBUF+1,#0

         MOV    A,TIMBUF          ;HOUR
         ADD    A,#1
         DA     A
         MOV    TIMBUF,A
TIMUPS9: RET

TIMDNS:  MOV    A,TIMBUF+2        ;SECOND (**** TIME DOWN ****)
         CLR    C
         SUBB   A,#1
         LCALL  SUBDA
         MOV    TIMBUF+2,A
         CJNE   A,#99H,TIMDNS9
         MOV    TIMBUF+2,#59H

         MOV    A,TIMBUF+1        ;MINUTE
         CLR    C
         SUBB   A,#1
         LCALL  SUBDA
         MOV    TIMBUF+1,A
         CJNE   A,#99H,TIMUPS9
         MOV    TIMBUF+1,#59H

         MOV    A,TIMBUF          ;HOUR
         CLR    C
         SUBB   A,#1
         LCALL  SUBDA
         MOV    TIMBUF,A
TIMDNS9: RET

; ********** MAIN **********
; MAIN MENU

MAIN:    SETB   TOOLBT
         MOV    DPTR,#MAINTA
         MOV    A,#80H            ;LINE 1
         LCALL  LCDLDS
         LCALL  MAINX

MAIN2:   LCALL  GKEYX
         CJNE   A,#0DH,$+6
         LJMP   MAIND
         CJNE   A,#81H,$+6
         LJMP   MAIND
         CJNE   A,#08H,$+6
         LJMP   MAINU
         CJNE   A,#80H,$+6
         LJMP   MAINU

         LCALL  UPPER
         CJNE   A,#'1',$+6        ;FUNCTION
         LJMP   MBOARD
         CJNE   A,#'2',$+6
         LJMP   MLCD
         CJNE   A,#'3',$+6
         LJMP   MPRINT
         CJNE   A,#'4',$+6
         LJMP   MTERM
         CJNE   A,#'5',$+6
         LJMP   MSTDA
         CJNE   A,#'6',$+6
         LJMP   SHMON
         CJNE   A,#'7',$+6
         LJMP   TCNT
         CJNE   A,#'8',$+6
         LJMP   TMER
         CJNE   A,#'9',$+6
         LJMP   TSTW
         CJNE   A,#'A',$+6
         LJMP   TLGP
         CJNE   A,#'B',$+6
         LJMP   TLREC
         CJNE   A,#'C',$+6
         LJMP   TPGEN
         CJNE   A,#'D',$+6
         LJMP   M8255
         CJNE   A,#'E',$+6
         LJMP   SDATE
         CJNE   A,#'F',$+6
         LJMP   SBAUD
         SJMP   MAIN2

MAINTA:  DB     'MAIN MENU ...   '
MAINTB:  DB     '1.TEST BOARD    ' ;0
         DB     '2.TEST LCD      '
         DB     '3.TEST PRINTER  '
         DB     '4.RS232/422 TERM' ;1
         DB     '5.RS485 STD-COM '
         DB     '6.SERIAL HEX-MON'
         DB     '7.TOOL COUNTER  ' ;2
         DB     '8.TOOL TIMER    '
         DB     '9.TOOL STOPWATCH'
         DB     'A.TOOL LOGIC-PRB' ;3
         DB     'B.TOOL LOGIC-REC'
         DB     'C.TOOL PULSE GEN'
         DB     'D.8255 INPUT MAP' ;4
         DB     'E.SET DATE/TIME '
         DB     'F.SET BAUD RATE '

MAIND:   MOV    A,MAINCT          ;PAGE DOWN
         CJNE   A,#4,MAIND2
         LJMP   MAIN2
MAIND2:  INC    MAINCT
         LCALL  MAINX
         LJMP   MAIN2

MAINU:   MOV    A,MAINCT          ;PAGE UP
         CJNE   A,#0,MAINU2
         LJMP   MAIN2
MAINU2:  DEC    MAINCT
         LCALL  MAINX
         LJMP   MAIN2

MAINX:   MOV    DPTR,#MAINTB      ;**** LOAD DISPLAY SUB ****
         MOV    A,MAINCT
         MOV    B,#48
         MUL    AB
         MOV    R3,A
         MOV    R2,#0
         LCALL  DPADD

         MOV    A,#0C0H           ;LINE 2
         LCALL  LCDLDS
         MOV    A,#90H            ;LINE 3
         LCALL  LCDLDS
         MOV    A,#0D0H           ;LINE 4
         LCALL  LCDLDS
         RET

; ********** MBOARD **********
; TEST BOARD

MBOARD:  MOV    DPTR,#MBOARDT
         LCALL  LCDLDP
MBOARD1: LCALL  GKEYX
         CJNE   A,#1BH,$+6
         LJMP   MAIN
         CJNE   A,#'1',$+6
         LJMP   MEX
         CJNE   A,#'2',$+6
         LJMP   MDP
         SJMP   MBOARD1

MBOARDT: DB     'TEST SILA BOARD '
         DB     '1.EX-SERIES     '
         DB     '2.DP/DK-SERIES  '
         DB     '                '

; ********** MDP **********
; TEST DP/DK-SERIES

MDP:     MOV    DPTR,#MDPT
         LCALL  LCDLDP
MDP1:    LCALL  GKEYX
         CJNE   A,#1BH,$+6
         LJMP   MBOARD
         CJNE   A,#'1',$+6
         LJMP   EXDP
         CJNE   A,#'2',$+6
         LJMP   EXDP73
         CJNE   A,#'3',$+6
         LJMP   DK124
         SJMP   MDP1

MDPT:    DB     'TEST DP/DK ...  '
         DB     '1.DP75          '
         DB     '2.DP73D         '
         DB     '3.DK124         '

; ********** MEX **********
; TEST EX-SEIRES

MEX:     MOV    DPTR,#MEXT
         LCALL  LCDLDP
MEX1:    LCALL  GKEYX
         CJNE   A,#1BH,$+6
         LJMP   MBOARD
         CJNE   A,#'1',$+6
         LJMP   EXLED
         CJNE   A,#'2',$+6
         LJMP   EXREL
         CJNE   A,#'3',$+6
         LJMP   EXSTEP
         CJNE   A,#'4',$+6
         LJMP   EXINP
         CJNE   A,#'5',$+6
         LJMP   EXSSR
         SJMP   MEX1

MEXT:    DB     'TEST EX-SERIES  '
         DB     '1.LED   4.INPUT '
         DB     '2.RELAY 5.SSR   '
         DB     '3.STEPM         '

; ********** EXLED **********

EXLED:   LCALL  CLEAR
         MOV    DPTR,#EXLEDT
         LCALL  LOAD2
         LCALL  CONF
         JNB    INPEXF,EXLED1
         LJMP   MEX
EXLED1:  LCALL  WORKING

         MOV    A,#80H            ;CONTROL CODE
         LCALL  WPORTX
EXLED2:  MOV    R6,#25            ;TABLE
         MOV    DPTR,#EXLEDU
EXLED4:  CLR    A
         MOVC   A,@A+DPTR
         LCALL  WPORTA
         LCALL  WPORTB
         LCALL  WPORTC
         MOV    R2,#3
         LCALL  DTSEC
         INC    DPTR
         DJNZ   R6,EXLED4
         LCALL  HBEEP
         LJMP   MEX

EXLEDT:  DB     'EX-LED TEST     '
         DB     'SHIFT & FLASH   '

EXLEDU:  DB     01H,02H,04H,08H
         DB     10H,20H,40H,80H
         DB     01H,02H,04H,08H
         DB     10H,20H,40H,80H
         DB     00H,55H,00H,0AAH
         DB     00H,55H,00H,0AAH
         DB     00H

; ********** EXREL **********

EXREL:   MOV    DPTR,#EXRELT
         LCALL  LOAD3
         LCALL  CONF
         JNB    INPEXF,EXREL1
         LJMP   MEX
EXREL1:  MOV    A,#80H            ;CONTROL CODE
         LCALL  WPORTX

         MOV    A,#01H            ;PA0
         LCALL  WPORTA
         MOV    LCDBUF+45,#'0'
         LCALL  LCDLDI
EXREL2:  LCALL  GKEYX
         CJNE   A,#0DH,EXREL2

         MOV    A,#02H            ;PA1
         LCALL  WPORTA
         MOV    LCDBUF+45,#'1'
         LCALL  LCDLDI
EXREL3:  LCALL  GKEYX
         CJNE   A,#0DH,EXREL3

         MOV    A,#04H            ;PA2
         LCALL  WPORTA
         MOV    LCDBUF+45,#'2'
         LCALL  LCDLDI
EXREL4:  LCALL  GKEYX
         CJNE   A,#0DH,EXREL4

         MOV    A,#08H            ;PA3
         LCALL  WPORTA
         MOV    LCDBUF+45,#'3'
         LCALL  LCDLDI
EXREL5:  LCALL  GKEYX
         CJNE   A,#0DH,EXREL5

         CLR    A
         LCALL  WPORTA
         LCALL  HBEEP
         LJMP   MEX

EXRELT:  DB     'EX-RELAY TEST   '
         DB     '(SET PA0-PA3)   '
         DB     'RELAY ON = PAx  '

; ********** EXSTEP **********

EXSTEP:  MOV    DPTR,#EXSTEPT
         LCALL  LOAD4
         MOV    A,#81H
         LCALL  WPORTX

EXSTEP2: MOV    A,#00010001B      ;START BIT
         MOV    COMBUF,A
         LCALL  WPORTA

EXSTEP3: LCALL  EXSTIN            ;LOOP
         MOV    LCDBUF+47,#'S'
         LCALL  LCDLDI
         LCALL  GKEY
         JNB    GKEYOK,EXSTEP3
EXSTEP4: CJNE   A,#1BH,$+6
         LJMP   MEX
         CJNE   A,#80H,$+6
         LJMP   EXSTL
         CJNE   A,#81H,$+6
         LJMP   EXSTR
         SJMP   EXSTEP3

EXSTL:   MOV    LCDBUF+47,#'<'
         LCALL  EX4X
         LCALL  LCDLDI
EXSTL2:  MOV    A,COMBUF          ;L <-
         RL     A
         MOV    COMBUF,A
         LCALL  WPORTA
         LCALL  EXSTD
         LCALL  GKEY
         JNB    GKEYOK,EXSTL2
         SJMP   EXSTEP4

EXSTR:   MOV    LCDBUF+47,#'>'
         LCALL  EX4X
         LCALL  LCDLDI
EXSTR2:  MOV    A,COMBUF          ;R ->
         RR     A
         MOV    COMBUF,A
         LCALL  WPORTA
         LCALL  EXSTD
         LCALL  GKEY
         JNB    GKEYOK,EXSTR2
         SJMP   EXSTEP4

EXSTEPT: DB     'EX-STEPM TEST   '
         DB     '(SET PA0-PA3)   '
         DB     'USE KEY <->,SP:X'
         DB     'INP/PC3-0 <XXXX>'

EXSTIN:  MOV    A,#'0'            ;READ INPUT
         MOV    LCDBUF+59,A
         MOV    LCDBUF+60,A
         MOV    LCDBUF+61,A
         MOV    LCDBUF+62,A

         LCALL  RPORTC
         JNB    ACC.3,EXSTIN1
         MOV    LCDBUF+59,#'1'
EXSTIN1: JNB    ACC.2,EXSTIN2
         MOV    LCDBUF+60,#'1'
EXSTIN2: JNB    ACC.1,EXSTIN3
         MOV    LCDBUF+61,#'1'
EXSTIN3: JNB    ACC.0,EXSTIN4
         MOV    LCDBUF+62,#'1'
EXSTIN4: RET

EX4X:    MOV    A,#'X'            ;XXXX ON PC3-0
         MOV    LCDBUF+59,A
         MOV    LCDBUF+60,A
         MOV    LCDBUF+61,A
         MOV    LCDBUF+62,A
         RET

EXSTD:   MOV    R2,#40H           ;DELAY
EXSTD1:  MOV    R3,#00H
         DJNZ   R3,$
         DJNZ   R2,EXSTD1
         RET

; ********** EXINP **********

EXINP:   MOV    DPTR,#EXINPT
         LCALL  LOAD4
         MOV    A,#9BH            ;CONTROL CODE (ALL IN)
         LCALL  WPORTX

EXINP2:  MOV    A,#'0'            ;START 0
         MOV    LCDBUF+49,A
         MOV    LCDBUF+53,A
         MOV    LCDBUF+57,A
         MOV    LCDBUF+61,A

         LCALL  RPORTA            ;CHECK INPUT PA0-PA3
         MOV    R0,#'1'
         JNB    ACC.0,EXINP31
         MOV    LCDBUF+49,R0
EXINP31: JNB    ACC.1,EXINP32
         MOV    LCDBUF+53,R0
EXINP32: JNB    ACC.2,EXINP33
         MOV    LCDBUF+57,R0
EXINP33: JNB    ACC.3,EXINP4
         MOV    LCDBUF+61,R0

EXINP4:  LCALL  LCDLDI
         LCALL  GKEY
         JNB    GKEYOK,EXINP2
         CJNE   A,#1BH,EXINP2
         LCALL  HBEEP
         LJMP   MEX

EXINPT:  DB     'EX-INPUT TEST   '
         DB     '(SET PA0-PA3)   '
         DB     'PA0 PA1 PA2 PA3 '
         DB     '<x> <x> <x> <x> '

; ********** EXSSR **********

EXSSR:   MOV    DPTR,#EXSSRT
         LCALL  LOAD3
         LCALL  CONF
         JNB    INPEXF,EXSSR1
         LJMP   MEX
EXSSR1:  MOV    A,#80H            ;CONTROL CODE
         LCALL  WPORTX

         MOV    A,#01H            ;PA0
         LCALL  WPORTA
         MOV    LCDBUF+43,#'0'
         LCALL  LCDLDI
EXSSR2:  LCALL  GKEYX
         CJNE   A,#0DH,EXSSR2

         MOV    A,#02H            ;PA1
         LCALL  WPORTA
         MOV    LCDBUF+43,#'1'
         LCALL  LCDLDI
EXSSR3:  LCALL  GKEYX
         CJNE   A,#0DH,EXSSR3

         MOV    A,#04H            ;PA2
         LCALL  WPORTA
         MOV    LCDBUF+43,#'2'
         LCALL  LCDLDI
EXSSR4:  LCALL  GKEYX
         CJNE   A,#0DH,EXSSR4

         MOV    A,#08H            ;PA3
         LCALL  WPORTA
         MOV    LCDBUF+43,#'3'
         LCALL  LCDLDI
EXSSR5:  LCALL  GKEYX
         CJNE   A,#0DH,EXSSR5

         CLR    A
         LCALL  WPORTA
         LCALL  HBEEP
         LJMP   MEX

EXSSRT:  DB     'EX-SSR TEST     '
         DB     '(SET PA0-PA3)   '
         DB     'SSR ON = PAx    '

; ********** EXDP **********

EXDP:    LCALL  CLEAR
         MOV    DPTR,#EXDPT
         LCALL  LOAD3
         LCALL  CONF
         JNB    INPEXF,EXDP1
         LJMP   MDP
EXDP1:   LCALL  WORKING

         MOV    A,#80H            ;CONTROL CODE
         LCALL  WPORTX
EXDP2:   MOV    R6,#25            ;TABLE
         MOV    DPTR,#EXDPU
EXDP4:   CLR    A
         MOVC   A,@A+DPTR
         LCALL  OUTDP
         MOV    R2,#5
         LCALL  DTSEC
         INC    DPTR
         DJNZ   R6,EXDP4
         LCALL  HBEEP
         LJMP   MDP

EXDPT:   DB     'DP-75 TEST      '
         DB     'SEGMENT & ALL   '
         DB     '(SET JUMPER PC0)'

EXDPU:   DB     01H,02H,04H,08H
         DB     10H,20H,40H,80H
         DB     01H,02H,04H,08H
         DB     10H,20H,40H,80H
         DB     00H,0FFH,00H,0FFH
         DB     00H,0FFH,00H,0FFH
         DB     00H

OUTDP:   LCALL  WPORTB            ;**** OUT SUB **** (IN=A)
         LCALL  RPORTC
         CLR    ACC.0             ;CLOCK LOW
         LCALL  WPORTC
         SETB   ACC.0             ;CLOCK HIGH
         LCALL  WPORTC
         RET

; ********** EXDP73 **********

EXDP73:  LCALL  CLEAR
         MOV    DPTR,#EXDP73T
         LCALL  LOAD3
         LCALL  CONF
         JNB    INPEXF,EXDP731
         LJMP   MDP
EXDP731: LCALL  WORKING
         MOV    A,#80H            ;CONTROL CODE
         LCALL  WPORTX

         CLR    A                 ;LEFT
         LCALL  OUTDPY
EXDP732: MOV    R6,#16            ;TABLE
         MOV    DPTR,#EXDPU
EXDP734: CLR    A
         MOVC   A,@A+DPTR
         CPL    A
         LCALL  OUTDPX
         MOV    R2,#5
         LCALL  DTSEC
         INC    DPTR
         DJNZ   R6,EXDP734

         CLR    A                 ;RIGHT
         LCALL  OUTDPX
EXDP736: MOV    R6,#16            ;TABLE
         MOV    DPTR,#EXDPU
EXDP738: CLR    A
         MOVC   A,@A+DPTR
         CPL    A
         LCALL  OUTDPY
         MOV    R2,#5
         LCALL  DTSEC
         INC    DPTR
         DJNZ   R6,EXDP738

         MOV    A,#0FFH
         LCALL  OUTDPX
         MOV    A,#0FFH
         LCALL  OUTDPY
         LCALL  HBEEP
         LJMP   MDP

EXDP73T: DB     'DP-73D TEST     '
         DB     'SEGMENT & ALL   '
         DB     '(SET JP PC0,PC1)'

OUTDPX:  LCALL  WPORTB            ;**** OUT SUB **** (IN=A)
         LCALL  RPORTC
         CLR    ACC.0             ;CLOCK LOW
         LCALL  WPORTC
         SETB   ACC.0             ;CLOCK HIGH
         LCALL  WPORTC
         RET

OUTDPY:  LCALL  WPORTB            ;**** OUT SUB **** (IN=A)
         LCALL  RPORTC
         CLR    ACC.1             ;CLOCK LOW
         LCALL  WPORTC
         SETB   ACC.1             ;CLOCK HIGH
         LCALL  WPORTC
         RET

; ********** DK124 **********

DK124:   LCALL  CLEAR
         MOV    DPTR,#DK124T
         LCALL  LOAD3
         LCALL  CONF
         JNB    INPEXF,DK1241
         LJMP   MDP
DK1241:  LCALL  WORKING

         MOV    A,#88H
         LCALL  WPORTX
         CLR    A
         LCALL  DKLOAD

         MOV    B,#24             ;SEGMENT SHIFT
         MOV    A,#01H
DK1242:  LCALL  DKLOAD
         PUSH   ACC
         MOV    R2,#30H
         LCALL  SCAND
         POP    ACC
         RL     A
         DJNZ   B,DK1242

         MOV    A,#0FFH
         LCALL  DKLOAD
         MOV    R2,#0
         LCALL  SCAND
         CLR    A
         LCALL  DKLOAD
         MOV    R2,#20H
         LCALL  SCAND

         CLR    A
DK1244:  MOV    HEXBUF,A
         MOV    HEXBUF+1,A
         LCALL  HTOS
         LCALL  SCAN
         CJNE   A,#0BH,DK1244
         LCALL  HBEEP
         LJMP   MDP

DK124T:  DB     'DK-124 TEST     '
         DB     'SEGMENT & KEY   '
         DB     '(EXIT BY KEY #) '

DKLOAD:  MOV    DISBUF,A
         MOV    DISBUF+1,A
         MOV    DISBUF+2,A
         MOV    DISBUF+3,A
         RET

; ********** SCAN SUB **********
; SCAN DISPLAY AND WAIT FOR KEY
; IN  = DISBUF
;     = SCANPF                        (KEY PRESS)
; OUT = A
; REG = A,R0,R1,R2,R3,R4,R5,R6,R7,DPTR

SCAN:    MOV    R4,#4             ;LOOP
         MOV    R5,#4             ;RELEASE KEY COUNT
         MOV    R6,#0             ;KEY-TABLE COUNT
         MOV    R7,#DISBUF

SCAN1:   CALL   SCANS             ;OUT SEGMENT
         LCALL  RPORTC
         ANL    A,#11110000B
         CJNE   A,#11110000B,SCAN3
         DJNZ   R5,SCAN2
         CLR    SCANPF
SCAN2:   DJNZ   R4,SCAN1
         SJMP   SCAN              ;LOOP FOREVER

SCAN3:   ORL    A,R6              ;PRESS
         JNB    SCANPF,SCAN5      ;IS NEW PRESS
         SJMP   SCAN2

SCAN5:   SETB   SCANPF            ;*** NEW PRESS ***
         MOV    R2,A              ;LOOKUP TABLE
         MOV    R3,#11
         MOV    DPTR,#KEYTAB
SCAN51:  CLR    A
         MOVC   A,@A+DPTR
         CLR    C
         SUBB   A,R2
         JZ     SCAN7
         INC    DPTR
         DJNZ   R3,SCAN51

SCAN7:   MOV    A,R3
         PUSH   ACC               ;--\
         CJNE   A,#0AH,$+3
         JNC    SCAN72
         CALL   KBEEP
         SJMP   SCAN8
SCAN72:  CALL   YBEEP
SCAN8:   POP    ACC               ;--/
         RET                      ;EXIT NEW PRESS

KEYTAB:  DB     0E3H,0E1H,0D3H
         DB     0D2H,0D1H,0B3H
         DB     0B2H,0B1H,073H
         DB     072H,071H,0E2H

; ********** SCANS SUB **********
; OUT ONE DIGIT & DELAY
; IN  = R6 DIGIT
;     = R7 INDEX TO DISBUF
; OUT = UPDATE R6 R7 + 1
; REG = A,R0,R2,R3,R6,R7,DPTR

SCANS:   MOV    A,R6
         ORL    A,#11111000B
         LCALL  WPORTC            ;DIGIT

         MOV    A,R7
         MOV    R0,A
         MOV    A,@R0
         LCALL  WPORTA            ;SEGMENT

         MOV    R2,#5             ;DELAY
SCANS2:  MOV    R3,#0C0H
         DJNZ   R3,$
         DJNZ   R2,SCANS2

         MOV    A,#0              ;CLR SEGMENT
         LCALL  WPORTA
         INC    R6
         INC    R7
         RET

; ********** SCAND SUB **********
; SCAN DISPLAY & DELAY
; IN  = DISBUF
;     = R2 DELAY VAR.
; REG = A,R0,R1,R2,R3,R4,R6,R7,DPTR

SCAND:   MOV    A,R2              ;DELAY
         MOV    R1,A
SCAND1:  MOV    R4,#4             ;LOOP
         MOV    R6,#0             ;DIGIT
         MOV    R7,#DISBUF
SCAND2:  CALL   SCANS
         DJNZ   R4,SCAND2
         DJNZ   R1,SCAND1
         RET

; ********** HTOSX SUB **********
; ONE BYTE HEX TO SEGMENT
; IN  = R2 HEX 0-F
; OUT = A SEGMENT CODE
; REG = A,DPTR

HTOSX:   MOV    A,R2              ;MAKE SURE 0-F
         ANL    A,#0FH
         MOV    R2,A
         MOV    DPTR,#SEGTAB      ;TABLE
         MOV    A,DPL
         ADD    A,R2
         MOV    DPL,A
         MOV    A,DPH
         ADDC   A,#0
         MOV    DPH,A
         CLR    A
         MOVC   A,@A+DPTR
         RET

SEGTAB:  DB     3FH,06H,5BH,4FH        ;0123
         DB     66H,6DH,7DH,07H        ;4567
         DB     7FH,6FH,77H,7CH        ;89AB
         DB     39H,5EH,79H,71H        ;CDEF

; ********** HTOS SUB **********
; HEX TO SEGMENT CODE
; IN  = HEXBUF
; OUT = DISBUF
; REG = A,R0,R1,R2,DPTR

HTOS:    MOV    R0,#HEXBUF
         MOV    R1,#DISBUF
         CALL   HTOSS
         CALL   HTOSS
         RET

HTOSS:   MOV    A,@R0             ;DIGIT L
         PUSH   ACC
         SWAP   A
         ANL    A,#0FH
         MOV    R2,A
         CALL   HTOSX
         MOV    @R1,A
         INC    R1
         POP    ACC               ;DIGIT R
         ANL    A,#0FH
         MOV    R2,A
         CALL   HTOSX
         MOV    @R1,A
         INC    R1
         INC    R0
         RET

; ********** STOHX SUB **********
; ONE BYTE SEGMENT TO HEX
; IN  = A SEGMENT CODE
; OUT = A HEX
; REG = A,R2,R3,DPTR

STOHX:   MOV    DPTR,#SEGTAB      ;TABLE
         ANL    A,#7FH            ;AND BIT 7 (DOT)
         MOV    R3,A              ;MEMO TO R3
         MOV    R2,#0             ;COUNTER
STOHX1:  CLR    A
         MOVC   A,@A+DPTR
         CLR    C
         SUBB   A,R3              ;COMPARE
         JZ     STOHX2
         INC    DPTR
         INC    R2
         CJNE   R2,#16,STOHX1
         MOV    R2,#0
STOHX2:  MOV    A,R2
         RET

; ********** STOH SUB **********
; SEGMENT CODE TO HEX
; IN  = DISBUF
; OUT = HEXBUF
; REG = A,R0,R1,R2,R3,DPTR

STOH:    MOV    R0,#DISBUF
         MOV    R1,#HEXBUF
         CALL   STOHS
         CALL   STOHS
         RET

STOHS:   MOV    A,@R0             ;DIGIT L
         CALL   STOHX
         ANL    A,#0FH
         SWAP   A
         MOV    @R1,A
         INC    R0
         MOV    A,@R0             ;DIGIT R
         CALL   STOHX
         ANL    A,#0FH
         ORL    A,@R1
         MOV    @R1,A
         INC    R0
         INC    R1
         RET

; ********** MLCD **********
; TEST DMC-xxx

MLCD:    MOV    DPTR,#MLCDT
         LCALL  LCDLDP

MLCD1:   LCALL  GKEYX
         CJNE   A,#1BH,$+6
         LJMP   MAIN
         CJNE   A,#'1',$+6
         LJMP   DMC161
         CJNE   A,#'2',$+6
         LJMP   DMC164
         CJNE   A,#'3',$+6
         LJMP   DMC202
         CJNE   A,#'4',$+6
         LJMP   DMC162
         SJMP   MLCD1

MLCDT:   DB     'TEST DMC-xxx    '
         DB     '1.16x1   4.16x2 '
         DB     '2.16x4          '
         DB     '3.20x2          '

; ********** DMC161 **********

DMC161:  LCALL  DMCSET
         LCALL  CLEARX
         MOV    R7,#10            ;0-9
         MOV    R6,#'0'
DMC1612: MOV    R5,#16
         LCALL  DMCSX
         LCALL  UL161
         MOV    R2,#4
         LCALL  DTSEC
         INC    R6
         DJNZ   R7,DMC1612
         LCALL  DMCSY
         LCALL  UL161
         MOV    R2,#15
         LCALL  DTSEC
         LCALL  DMCSZ
         LCALL  UL161
         LJMP   MLCD

DMCSX:   MOV    R0,#LCDBUF        ;LOAD
         MOV    A,R6
DMCSX1:  MOV    @R0,A
         INC    R0
         DJNZ   R5,DMCSX1
         RET

DMCSY:   MOV    R0,#LCDBUF        ;LOAD ABC...
         MOV    R5,#64
         MOV    A,#'A'
DMCSY1:  MOV    @R0,A
         INC    R0
         INC    A
         DJNZ   R5,DMCSY1
         RET

DMCSZ:   MOV    R0,#LCDBUF        ;LOAD ALL 0FFH
         MOV    R5,#64
         MOV    A,#0FFH
DMCSZ1:  MOV    @R0,A
         INC    R0
         DJNZ   R5,DMCSZ1
         RET

DMCSET:  MOV    A,#80H            ;SETUP USER LCD
         LCALL  WPORTX
         MOV    A,#00111000B      ;FUNCTION SET (LCD)
         LCALL  ULCDWI
         MOV    A,#00001100B      ;DISPLAY ON/OFF
         LCALL  ULCDWI
         MOV    A,#01H            ;CLEAR
         LCALL  ULCDWI
         RET

; ********** DMC164 **********

DMC164:  LCALL  DMCSET
         LCALL  CLEARX
         MOV    R7,#10            ;0-9
         MOV    R6,#'0'
DMC1642: MOV    R5,#64
         LCALL  DMCSX
         LCALL  UL164
         MOV    R2,#4
         LCALL  DTSEC
         INC    R6
         DJNZ   R7,DMC1642
         LCALL  DMCSY
         LCALL  UL164
         MOV    R2,#15
         LCALL  DTSEC
         LCALL  DMCSZ
         LCALL  UL164
         LJMP   MLCD

; ********** DMC202 **********

DMC202:  LCALL  DMCSET
         LCALL  CLEARX
         MOV    R7,#10            ;0-9
         MOV    R6,#'0'
DMC2022: MOV    R5,#40
         LCALL  DMCSX
         LCALL  UL202
         MOV    R2,#4
         LCALL  DTSEC
         INC    R6
         DJNZ   R7,DMC2022
         LCALL  DMCSY
         LCALL  UL202
         MOV    R2,#15
         LCALL  DTSEC
         LCALL  DMCSZ
         LCALL  UL202
         LJMP   MLCD

; ********** DMC162 **********

DMC162:  LCALL  DMCSET
         LCALL  CLEARX
         MOV    R7,#10            ;0-9
         MOV    R6,#'0'
DMC1622: MOV    R5,#32
         LCALL  DMCSX
         LCALL  UL162
         MOV    R2,#4
         LCALL  DTSEC
         INC    R6
         DJNZ   R7,DMC1622
         LCALL  DMCSY
         LCALL  UL162
         MOV    R2,#15
         LCALL  DTSEC
         LCALL  DMCSZ
         LCALL  UL162
         LJMP   MLCD

; ********** MPRINT **********
; TEST PRINTER

MPRINT:  MOV    DPTR,#MPRINTT
         LCALL  LCDLDP

MPRINT1: LCALL  GKEYX
         CJNE   A,#1BH,$+6
         LJMP   MAIN
         CJNE   A,#'1',$+6
         LJMP   MPRTX
         CJNE   A,#'2',$+6
         LJMP   MPRTY
         CJNE   A,#'3',$+6
         LJMP   MPRTZ
         SJMP   MPRINT1

MPRINTT: DB     'TEST PRINTER    '
         DB     '1.PRINT STD.TEXT'
         DB     '2.PRINT FROM KEY'
         DB     '3.PRINT F/SERIAL'

; ********** MPRTX **********

MPRTX:   MOV    A,#80H
         LCALL  WPORTX
         LCALL  CLEAR

         MOV    DPTR,#MPRTX1
         LCALL  PBLOCK
         MOV    DPTR,#MPRTX2
         LCALL  PBLOCK
         MOV    R2,#20H
         MOV    R3,#64
         LCALL  MPRTXS
         MOV    DPTR,#MPRTX3
         LCALL  PBLOCK
         MOV    R2,#60H
         MOV    R3,#64
         LCALL  MPRTXS
         MOV    DPTR,#MPRTX4
         LCALL  PBLOCK
         MOV    R2,#0A0H
         MOV    R3,#64
         LCALL  MPRTXS
         MOV    DPTR,#MPRTX5
         LCALL  PBLOCK
         MOV    R2,#0E0H
         MOV    R3,#32
         LCALL  MPRTXS

         MOV    R2,#8
MPRTXA:  LCALL  PLF
         DJNZ   R2,MPRTXA
         LCALL  HBEEP
         LJMP   MPRINT

MPRTX1:  DB     'MTOOL-7 TEST PRINTER (STANDARD TEXT) ...',0DH
MPRTX2:  DB     'CODE 20H-5FH ',0
MPRTX3:  DB     'CODE 60H-9FH ',0
MPRTX4:  DB     'CODE A0H-DFH ',0
MPRTX5:  DB     'CODE E0H-FFH ',0

MPRTXS:  MOV    A,R2              ;LINE SUB.
         LCALL  PBYTE
         INC    R2
         DJNZ   R3,MPRTXS
         LCALL  PLF
         RET

; ********** MPRTY **********

MPRTY:   MOV    A,#80H
         LCALL  WPORTX
         MOV    DPTR,#MPRTYT
         LCALL  LOAD4
         LCALL  LCDLDI

MPRTY2:  LCALL  GKEY              ;LOOP
         JNB    GKEYOK,MPRTY2
         CJNE   A,#1BH,$+6
         LJMP   MPRINT
         CJNE   A,#80H,$+3
         JNC    MPRTY2            ;=>80H

         MOV    B,A               ;PRINT
         CJNE   A,#0DH,MPRTY3
         LCALL  PLF
         SJMP   MPRTY4
MPRTY3:  LCALL  PBYTE

MPRTY4:  MOV    R3,#32            ;SHIFT LCD
         MOV    R0,#LCDBUF+63
MPRTY5:  MOV    A,@R0
         MOV    @R0,B
         MOV    B,A
         DEC    R0
         DJNZ   R3,MPRTY5
         LCALL  LCDLDI
         SJMP   MPRTY2

MPRTYT:  DB     'PRINT FROM KEY  '
         DB     '(INTERACTIVE)   '
         DB     '----------------'
         DB     '----------------'

; ********** MPRTZ **********

MPRTZ:   MOV    A,#80H
         LCALL  WPORTX
         MOV    DPTR,#MPRTZT
         LCALL  LCDLDP

MPRTZ4:  LCALL  RBYTE
         LCALL  PBYTE
         SJMP   MPRTZ4

MPRTZT:  DB     'PRINT F/SERIAL  '
         DB     '(RS232,422,485) '
         DB     'NOW ACTIVE ...  '
         DB     '(EXIT BY RESET) '

; ********** MTERM **********
; TERMINAL EMULATOR

MTERM:   LCALL  CLEAR             ;FIRST CLEAR
         MOV    DPTR,#MTERMT
         LCALL  LOAD3
         MOV    TERMCT,#LCDBUF+48
         LCALL  SON
         SETB   TERMFG
         SETB   ES

MTERM2:  LCALL  LCDLDI            ;**** LOOP ****
MTERM3:  LCALL  GKEY
         JB     GKEYOK,MTERM6     ;WAIT KEY
         SJMP   MTERM2

MTERM6:  CJNE   A,#1BH,MTERM61    ;**** KEY ****
         CLR    ES                ;EXIT
         CLR    TERMFG
         LJMP   MAIN

MTERM61: JNB    TXOK,$            ;TXD
         CLR    TXOK
         MOV    SBUF,A
         SJMP   MTERM3

MTERMT:  DB     'RS232/422       '
         DB     'Terminal Emulate'
         DB     'NOW ACTIVE ...  '

; ********** RXTERM SUB ********** (INTERRUPT)

RXTERM:  JB     RI,RXTERM0
         CLR    TI
         SETB   TXOK
         RETI

RXTERM0: CLR    RI
         PUSH   ACC
         PUSH   PSW
         PUSH   B
         MOV    A,R0
         PUSH   ACC
         MOV    A,R1
         PUSH   ACC
         MOV    A,R2
         PUSH   ACC

         MOV    A,SBUF
         MOV    B,A               ;CHECK END LINE
         MOV    R0,TERMCT
         CJNE   R0,#LCDBUF+64,RXTERM1
         LCALL  MTERMS
RXTERM1: MOV    A,B
         CJNE   A,#0DH,RXTERM2
         MOV    TERMCT,#LCDBUF+48
         SJMP   RXTERM7
RXTERM2: CJNE   A,#0AH,RXTERM5
         LCALL  MTERMS
         SJMP   RXTERM7
RXTERM5: MOV    A,B
         MOV    R0,TERMCT
         MOV    @R0,A             ;CHAR.
         INC    TERMCT

RXTERM7: POP    ACC
         MOV    R2,A
         POP    ACC
         MOV    R1,A
         POP    ACC
         MOV    R0,A
         POP    B
         POP    PSW
         POP    ACC
         RETI

MTERMS:  MOV    R0,#LCDBUF        ;LINE UP
         MOV    R1,#LCDBUF+16
         MOV    R2,#48
MTERMS1: MOV    A,@R1
         MOV    @R0,A
         INC    R0
         INC    R1
         DJNZ   R2,MTERMS1
         MOV    TERMCT,#LCDBUF+48
         MOV    R0,#LCDBUF+48
         MOV    R2,#16
MTERMS2: MOV    @R0,#' '
         INC    R0
         DJNZ   R2,MTERMS2
         RET

; ********** MSTD **********
; RS485 STD-COM

MSTDA:   LCALL  SOFF
         MOV    DPTR,#MSTDTA
         LCALL  LCDLDP

MSTDA1:  LCALL  GKEYX
         CJNE   A,#1BH,$+6
         LJMP   MAIN
         CJNE   A,#'1',$+6
         LJMP   MSTD
         CJNE   A,#'2',$+6
         LJMP   MSTDX
         CJNE   A,#'3',$+6
         LJMP   MSTDY
         SJMP   MSTDA1

MSTDTA:  DB     'SELECT MODE     '
         DB     '1.MASTER/REQUEST'
         DB     '2.SLAVE/ECHO    '
         DB     '3.SLAVE/ECHO ALL'

; ********** MSTDX **********
; SLAVE/ECHO

MSTDX:   MOV    DPTR,#MSTDT
         LCALL  LOAD4
         MOV    LCDBUF+28,#' '
         MOV    LCDBUF+29,#' '
         LCALL  LCDLDI

MSTDX2:  MOV    INPSTT,#LCDBUF+12
         MOV    INPEND,#LCDBUF+13
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,MSTDX9
         JB     INPBKF,MSTDX2

         MOV    R2,LCDBUF+12
         MOV    R3,LCDBUF+13
         LCALL  ATOH
         MOV    TERMCT,A          ;ADDRESS

MSTDX3:  LCALL  RECV              ;LOOP
         JB     COMERR,MSTDX8
         MOV    A,COMBUF          ;CHECK ADDRESS
         CJNE   A,TERMCT,MSTDX3

         MOV    DPTR,#MSTDT       ;ADDRESS OK
         LCALL  LOAD4
         LCALL  MSTDU
         LCALL  LCDLDI
         LCALL  SEND
         SJMP   MSTDX3

MSTDX8:  LCALL  LBEEP
         SJMP   MSTDX3
MSTDX9:  LJMP   MSTDA

; ********** MSTDY **********
; SLAVE/ECHO ALL

MSTDY:   MOV    DPTR,#MSTDT
         LCALL  LOAD4
         MOV    A,#' '
         MOV    LCDBUF+12,A
         MOV    LCDBUF+13,A
         MOV    LCDBUF+28,A
         MOV    LCDBUF+29,A
         LCALL  LCDLDI

MSTDY3:  LCALL  RECV              ;LOOP
         JB     COMERR,MSTDY8

         MOV    DPTR,#MSTDT       ;ADDRESS OK
         LCALL  LOAD4
         LCALL  MSTDU
         LCALL  LCDLDI
         LCALL  SEND
         SJMP   MSTDY3

MSTDY8:  LCALL  LBEEP
         SJMP   MSTDY3
MSTDY9:  LJMP   MSTDA

; ********** MSTD **********
; MASTER/REQUEST

MSTD:    MOV    DPTR,#MSTDT
         LCALL  LOAD4
         LCALL  LCDLDI

MSTD2:   MOV    INPSTT,#LCDBUF+12
         MOV    INPEND,#LCDBUF+13
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,MSTD9
         JB     INPBKF,MSTD2

MSTD22:  MOV    INPSTT,#LCDBUF+28
         MOV    INPEND,#LCDBUF+29
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,MSTD9
         JB     INPBKF,MSTD2

MSTD23:  MOV    INPSTT,#LCDBUF+48
         MOV    INPEND,#LCDBUF+63
         CLR    INPHXF
         LCALL  INPX
         JB     INPEXF,MSTD9
         JB     INPBKF,MSTD22

         LCALL  MSTDP
         LCALL  SEND
         LCALL  RECV
         JB     COMERR,MSTD8
         LCALL  HBEEP
         MOV    DPTR,#MSTDT
         LCALL  LOAD4
         LCALL  MSTDU
         LCALL  LCDLDI
         SJMP   MSTD2

MSTD8:   LCALL  LBEEP
         SJMP   MSTD
MSTD9:   LJMP   MSTDA

MSTDT:   DB     'ADDR (HEX) :00  '
         DB     'CODE (HEX) :00  '
         DB     'DATA (ASCII)    '
         DB     '                '

MSTDP:   MOV    R2,LCDBUF+12      ;**** PACK LCDBUF -> COMBUF ****
         MOV    R3,LCDBUF+13
         LCALL  ATOH
         MOV    COMBUF,A

         MOV    R2,LCDBUF+28
         MOV    R3,LCDBUF+29
         LCALL  ATOH
         MOV    COMBUF+1,A

         MOV    R2,#0
         MOV    R0,#LCDBUF+48
         MOV    R1,#COMBUF+3
MSTDP2:  MOV    A,@R0
         CJNE   A,#' ',$+6
         LJMP   MSTDP4
         MOV    @R1,A
         INC    R2
         INC    R0
         INC    R1
         SJMP   MSTDP2
MSTDP4:  MOV    COMBUF+2,R2
         RET

MSTDU:   MOV    A,COMBUF          ;**** UNPACK LCDBUF <- COMBUF ****
         LCALL  HTOA
         MOV    LCDBUF+12,R2
         MOV    LCDBUF+13,R3

         MOV    A,COMBUF+1
         LCALL  HTOA
         MOV    LCDBUF+28,R2
         MOV    LCDBUF+29,R3

         MOV    R2,COMBUF+2
         CJNE   R2,#0,MSTDU1
         RET

MSTDU1:  MOV    R0,#LCDBUF+48
         MOV    R1,#COMBUF+3
MSTDU2:  MOV    A,@R1
         MOV    @R0,A
         INC    R0
         INC    R1
         DJNZ   R2,MSTDU2
         RET

; ********** SEND SUB **********
; SEND STD.COM   COMBUF -> RS485

SEND:    LCALL  SON
         MOV    R7,#0             ;START CHECKSUM
         MOV    A,#STX
         LCALL  SBYTEX
         MOV    A,COMBUF
         LCALL  SBYTEX
         MOV    A,COMBUF+1
         LCALL  SBYTEX
         MOV    A,COMBUF+2
         LCALL  SBYTEX

         MOV    R2,COMBUF+2
         MOV    R0,#COMBUF+3
SEND2:   CJNE   R2,#0,$+6
         LJMP   SEND4
SEND22:  MOV    A,@R0
         LCALL  SBYTEX
         INC    R0
         DJNZ   R2,SEND22

SEND4:   MOV    A,#ETX
         LCALL  SBYTEX
         MOV    A,R7
         LCALL  SBYTEX
         LCALL  SOFF
         RET

; ********** RECV SUB **********
; RECEIVE STD.COM  COMBUF <- RS485

RECV:    MOV    R7,#0             ;START CHECKSUM
         LCALL  RBYTEX
         CJNE   A,#STX,RECV8
         LCALL  RBYTEX
         MOV    COMBUF,A
         LCALL  RBYTEX
         MOV    COMBUF+1,A
         LCALL  RBYTEX
         MOV    COMBUF+2,A

         CJNE   A,#0,$+6
         LJMP   RECV4
         MOV    R2,A
         MOV    R0,#COMBUF+3
RECV2:   LCALL  RBYTEX
         MOV    @R0,A
         INC    R0
         DJNZ   R2,RECV2

RECV4:   LCALL  RBYTEX
         CJNE   A,#ETX,RECV8
         MOV    B,R7
         LCALL  RBYTEX
         CJNE   A,B,RECV8
         CLR    COMERR
         RET

RECV8:   SETB   COMERR            ;ERROR
         RET

; ********** SHMON **********
; SERIAL HEX-MONITOR

SHMON:   MOV    R0,#COMBUF        ;CLEAR BUFFER
         MOV    R1,#16
SHMON1:  MOV    @R0,#0
         INC    R0
         DJNZ   R1,SHMON1
         LCALL  CLEAR
         CLR    TI                ;DISABLE TX
         SETB   ES                ;RECEIVE RX BY INTERRUPT

SHMON2:  MOV    R0,#COMBUF
         MOV    R1,#LCDBUF
         LCALL  SHMONS
         MOV    R0,#COMBUF+4
         MOV    R1,#LCDBUF+16
         LCALL  SHMONS
         MOV    R0,#COMBUF+8
         MOV    R1,#LCDBUF+32
         LCALL  SHMONS
         MOV    R0,#COMBUF+12
         MOV    R1,#LCDBUF+48
         LCALL  SHMONS
         LCALL  LCDLDI

         LCALL  GKEY
         JNB    GKEYOK,SHMON2
         CJNE   A,#1BH,SHMON2
         CLR    ES
         SETB   TI
         LJMP   MAIN

SHMONS:  MOV    R7,#4             ;**** 1 LINE SUB ****
         MOV    B,R0
SHMONS1: MOV    A,@R0             ;HEX
         LCALL  HTOA
         INC    R0
         MOV    A,R2
         MOV    @R1,A
         INC    R1
         MOV    A,R3
         MOV    @R1,A
         INC    R1
         INC    R1
         DJNZ   R7,SHMONS1

         MOV    R7,#4             ;ASCII
         MOV    R0,B
SHMONS3: MOV    A,@R0
         CJNE   A,#80H,$+3
         JNC    SHMONS4           ;=>80H
         CJNE   A,#20H,$+3
         JC     SHMONS4           ;<20H
         SJMP   SHMONS5
SHMONS4: MOV    A,#'.'
SHMONS5: MOV    @R1,A
         INC    R0
         INC    R1
         DJNZ   R7,SHMONS3
         RET

; ********** RXINT SUB ********** (INTERRUPT)
; RECEIVE INTERRUPT (FOR SHMON)

RXINT:   PUSH   ACC
         PUSH   PSW

         MOV    A,COMBUF+1
         MOV    COMBUF+0,A
         MOV    A,COMBUF+2
         MOV    COMBUF+1,A
         MOV    A,COMBUF+3
         MOV    COMBUF+2,A
         MOV    A,COMBUF+4
         MOV    COMBUF+3,A
         MOV    A,COMBUF+5
         MOV    COMBUF+4,A
         MOV    A,COMBUF+6
         MOV    COMBUF+5,A
         MOV    A,COMBUF+7
         MOV    COMBUF+6,A
         MOV    A,COMBUF+8
         MOV    COMBUF+7,A
         MOV    A,COMBUF+9
         MOV    COMBUF+8,A
         MOV    A,COMBUF+10
         MOV    COMBUF+9,A
         MOV    A,COMBUF+11
         MOV    COMBUF+10,A
         MOV    A,COMBUF+12
         MOV    COMBUF+11,A
         MOV    A,COMBUF+13
         MOV    COMBUF+12,A
         MOV    A,COMBUF+14
         MOV    COMBUF+13,A
         MOV    A,COMBUF+15
         MOV    COMBUF+14,A
         CLR    RI
         MOV    A,SBUF
         MOV    COMBUF+15,A

         POP    PSW
         POP    ACC
         RETI

; ********** TCNT **********
; TOOL COUNTER
; COMBUF+0 = PRESET (3 BYTE)
; COMBUF+3 = DIVIDER (2 BYTE)
; COMBUF+5 = COUNTER (3 BYTE)
; COMBUF+8 = COUNTER/DIV (2 BYTE)

TCNT:    MOV    DPTR,#TCNTTX
         LCALL  LOAD4
         LCALL  LCDLDI

TCNT2:   MOV    INPSTT,#LCDBUF+15 ;UP/DOWN
         MOV    INPEND,#LCDBUF+15
         CLR    INPHXF
         LCALL  INPX
         JB     INPEXF,TCNT9
         JB     INPBKF,TCNT2
         MOV    A,LCDBUF+15
         LCALL  UPPER
         MOV    LCDBUF+15,A

         CJNE   A,#'U',TCNT22
         CLR    TCNTUD
         SJMP   TCNT3
TCNT22:  CJNE   A,#'D',TCNT24
         SETB   TCNTUD
         SJMP   TCNT3
TCNT24:  LCALL  LBEEP
         SJMP   TCNT2

TCNT3:   MOV    INPSTT,#LCDBUF+31 ;RESET/AUTO
         MOV    INPEND,#LCDBUF+31
         CLR    INPHXF
         LCALL  INPX
         JB     INPEXF,TCNT9
         JB     INPBKF,TCNT2
         MOV    A,LCDBUF+31
         LCALL  UPPER
         MOV    LCDBUF+31,A

         CJNE   A,#'R',TCNT32
         CLR    TCNTRA
         SJMP   TCNT5
TCNT32:  CJNE   A,#'A',TCNT34
         SETB   TCNTRA
         SJMP   TCNT5
TCNT34:  LCALL  LBEEP
         SJMP   TCNT3
TCNT9:   LJMP   MAIN

TCNT5:   MOV    INPSTT,#LCDBUF+37 ;PRESET
         MOV    INPEND,#LCDBUF+42
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TCNT9
         JB     INPBKF,TCNT3

TCNT6:   MOV    INPSTT,#LCDBUF+44 ;DIVIDER
         MOV    INPEND,#LCDBUF+47
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TCNT9
         JB     INPBKF,TCNT5
         SJMP   TCNTX

TCNTTX:  DB     'TOOL  TYPE(UD):U'
         DB     'COUNT LOOP(RA):R'
         DB     'PSET 000000.0001'
         DB     'CNTR 000000.0000'

TCNTX:   MOV    R2,LCDBUF+37      ;FIRST SET
         MOV    R3,LCDBUF+38
         LCALL  ATOH
         MOV    COMBUF+0,A
         MOV    R2,LCDBUF+39
         MOV    R3,LCDBUF+40
         LCALL  ATOH
         MOV    COMBUF+1,A
         MOV    R2,LCDBUF+41
         MOV    R3,LCDBUF+42
         LCALL  ATOH
         MOV    COMBUF+2,A

         MOV    R2,LCDBUF+44
         MOV    R3,LCDBUF+45
         LCALL  ATOH
         MOV    COMBUF+3,A
         MOV    R2,LCDBUF+46
         MOV    R3,LCDBUF+47
         LCALL  ATOH
         MOV    COMBUF+4,A
         LCALL  HBEEP             ;FIRST BEEP
         CLR    TCNTLF

TCNTY:   CLR    TCNTOK            ;**** RESET ****
         JB     TCNTUD,TCNTY2
         CLR    A                 ;UP RESET
         MOV    COMBUF+5,A
         MOV    COMBUF+6,A
         MOV    COMBUF+7,A
         MOV    COMBUF+8,A
         MOV    COMBUF+9,A
         SJMP   TCNTY4
TCNTY2:  MOV    COMBUF+5,COMBUF+0 ;DOWN RESET
         MOV    COMBUF+6,COMBUF+1
         MOV    COMBUF+7,COMBUF+2
         MOV    COMBUF+8,COMBUF+3
         MOV    COMBUF+9,COMBUF+4

TCNTY4:  MOV    A,COMBUF+5        ;**** DISPLAY (LOOP) ****
         LCALL  HTOA
         MOV    LCDBUF+53,R2
         MOV    LCDBUF+54,R3
         MOV    A,COMBUF+6
         LCALL  HTOA
         MOV    LCDBUF+55,R2
         MOV    LCDBUF+56,R3
         MOV    A,COMBUF+7
         LCALL  HTOA
         MOV    LCDBUF+57,R2
         MOV    LCDBUF+58,R3

         MOV    A,COMBUF+8
         LCALL  HTOA
         MOV    LCDBUF+60,R2
         MOV    LCDBUF+61,R3
         MOV    A,COMBUF+9
         LCALL  HTOA
         MOV    LCDBUF+62,R2
         MOV    LCDBUF+63,R3
         LCALL  LCDLDI
         JB     TCNTOK,TCNTY7

TCNTY5:  LCALL  GKEY              ;WAIT FOR LOW LOOP
         JNB    GKEYOK,TCNTY52
         CJNE   A,#1BH,TCNTY52
         LJMP   MAIN              ;EXIT
TCNTY52: JNB    TOOLBT,TCNTY6
         CLR    TCNTLF            ;CLEAR LOW FLAG
         SJMP   TCNTY5

TCNTY6:  JB     TCNTLF,TCNTY5     ;NOT HIGH CHECK
         SETB   TCNTLF            ;SET LOW FLAG
         JB     TCNTUD,TCNTY62
         LCALL  TCNTU
         SJMP   TCNTY4
TCNTY62: LCALL  TCNTD
         SJMP   TCNTY4

TCNTY7:  JB     TCNTRA,TCNTY78    ;COUNT OK
TCNTY72: LCALL  HBEEP             ;RESET
         MOV    R2,#5
         LCALL  DTSEC
         LCALL  GKEY
         JNB    GKEYOK,TCNTY72
         CJNE   A,#1BH,$+6
         LJMP   MAIN              ;EXIT
         LJMP   TCNTY

TCNTY78: LCALL  HBEEP             ;AUTO
         MOV    R2,#5
         LCALL  DTSEC
         LJMP   TCNTY

TCNTU:   MOV    A,COMBUF+9        ;**** COUNT UP SUB ****
         ADD    A,#1
         DA     A
         MOV    COMBUF+9,A
         MOV    A,COMBUF+8
         ADDC   A,#0
         DA     A
         MOV    COMBUF+8,A

         MOV    A,COMBUF+8
         CJNE   A,COMBUF+3,TCNTU9
         MOV    A,COMBUF+9
         CJNE   A,COMBUF+4,TCNTU9

         CLR    A                 ;COUNT
         MOV    COMBUF+8,A
         MOV    COMBUF+9,A

         MOV    A,COMBUF+7
         ADD    A,#1
         DA     A
         MOV    COMBUF+7,A
         MOV    A,COMBUF+6
         ADDC   A,#0
         DA     A
         MOV    COMBUF+6,A
         MOV    A,COMBUF+5
         ADDC   A,#0
         DA     A
         MOV    COMBUF+5,A

         MOV    A,COMBUF+5
         CJNE   A,COMBUF+0,TCNTU9
         MOV    A,COMBUF+6
         CJNE   A,COMBUF+1,TCNTU9
         MOV    A,COMBUF+7
         CJNE   A,COMBUF+2,TCNTU9
         SETB   TCNTOK
TCNTU9:  RET

TCNTD:   MOV    A,COMBUF+9        ;**** COUNT DOWN SUB ****
         CLR    C
         SUBB   A,#1
         LCALL  SUBDA
         MOV    COMBUF+9,A
         MOV    A,COMBUF+8
         SUBB   A,#0
         LCALL  SUBDA
         MOV    COMBUF+8,A

         MOV    A,COMBUF+8
         ORL    A,COMBUF+9
         JNZ    TCNTD9

         MOV    COMBUF+8,COMBUF+3 ;COUNT
         MOV    COMBUF+9,COMBUF+4

         MOV    A,COMBUF+7
         CLR    C
         SUBB   A,#1
         LCALL  SUBDA
         MOV    COMBUF+7,A
         MOV    A,COMBUF+6
         SUBB   A,#0
         LCALL  SUBDA
         MOV    COMBUF+6,A
         MOV    A,COMBUF+5
         SUBB   A,#0
         LCALL  SUBDA
         MOV    COMBUF+5,A

         MOV    A,COMBUF+5
         ORL    A,COMBUF+6
         ORL    A,COMBUF+7
         JNZ    TCNTD9
         SETB   TCNTOK
TCNTD9:  RET

; ********** TMER **********
; TOOL TIMER
; COMBUF+0 = SET TIME (3 BYTE)

TMER:    MOV    DPTR,#TMERT
         LCALL  LOAD4
         LCALL  LCDLDI
         SETB   TOOLBT

TMER2:   MOV    INPSTT,#LCDBUF+15 ;UP/DOWN
         MOV    INPEND,#LCDBUF+15
         CLR    INPHXF
         LCALL  INPX
         JB     INPEXF,TMER9
         JB     INPBKF,TMER2
         MOV    A,LCDBUF+15
         LCALL  UPPER
         MOV    LCDBUF+15,A

         CJNE   A,#'U',TMER22
         CLR    TCNTUD
         SJMP   TMER3
TMER22:  CJNE   A,#'D',TMER24
         SETB   TCNTUD
         SJMP   TMER3
TMER24:  LCALL  LBEEP
         SJMP   TMER2

TMER3:   MOV    INPSTT,#LCDBUF+31 ;RESET/AUTO
         MOV    INPEND,#LCDBUF+31
         CLR    INPHXF
         LCALL  INPX
         JB     INPEXF,TMER9
         JB     INPBKF,TMER2
         MOV    A,LCDBUF+31
         LCALL  UPPER
         MOV    LCDBUF+31,A

         CJNE   A,#'R',TMER32
         CLR    TCNTRA
         SJMP   TMER5
TMER32:  CJNE   A,#'A',TMER34
         SETB   TCNTRA
         SJMP   TMER5
TMER34:  LCALL  LBEEP
         SJMP   TMER3
TMER9:   LJMP   MAIN

TMER5:   MOV    INPSTT,#LCDBUF+40 ;HOUR
         MOV    INPEND,#LCDBUF+41
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TMER9
         JB     INPBKF,TMER3

TMER6:   MOV    INPSTT,#LCDBUF+43 ;MINUTE
         MOV    INPEND,#LCDBUF+44
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TMER9
         JB     INPBKF,TMER5

TMER7:   MOV    INPSTT,#LCDBUF+46 ;SECOND
         MOV    INPEND,#LCDBUF+47
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TMER9
         JB     INPBKF,TMER6
         SJMP   TMERX

TMERT:   DB     'TOOL  TYPE(UD):D'
         DB     'TIMER LOOP(RA):R'
         DB     'SET-TIM HH:MM:SS'
         DB     'CNT-TIM 00:00:00'

TMERX:   MOV    R2,LCDBUF+40      ;FIRST SET
         MOV    R3,LCDBUF+41
         LCALL  ATOH
         MOV    COMBUF+0,A
         MOV    R2,LCDBUF+43
         MOV    R3,LCDBUF+44
         LCALL  ATOH
         MOV    COMBUF+1,A
         MOV    R2,LCDBUF+46
         MOV    R3,LCDBUF+47
         LCALL  ATOH
         MOV    COMBUF+2,A
         LCALL  HBEEP

TMERY:   JB     TCNTUD,TMERY2     ;**** RESET ****
         CLR    A
         MOV    TIMBUF,A
         MOV    TIMBUF+1,A
         MOV    TIMBUF+2,A
         SJMP   TMERY4
TMERY2:  MOV    TIMBUF,COMBUF
         MOV    TIMBUF+1,COMBUF+1
         MOV    TIMBUF+2,COMBUF+2
TMERY4:  MOV    TIMDIV,#0
         SETB   TR0               ;START TIEMR-0
         CLR    TOOLBT

TMERY5:  LCALL  TMERD             ;DISPLAY
         LCALL  GKEY
         JNB    GKEYOK,TMERY7
         CJNE   A,#1BH,TMERY7
         LJMP   MAIN              ;EXIT

TMERY7:  JB     TCNTUD,TMERY8
         MOV    A,TIMBUF          ;UP-CHECK
         CJNE   A,COMBUF,TMERY5
         MOV    A,TIMBUF+1
         CJNE   A,COMBUF+1,TMERY5
         MOV    A,TIMBUF+2
         CJNE   A,COMBUF+2,TMERY5
         SJMP   TMERZ
TMERY8:  MOV    A,TIMBUF          ;DOWN-CHECK
         ORL    A,TIMBUF+1
         ORL    A,TIMBUF+2
         JZ     TMERZ
         SJMP   TMERY5

TMERZ:   CLR    TR0               ;STOP TIMER-0
         SETB   TOOLBT
         LCALL  TMERD
         JB     TCNTRA,TMERZ4     ;TIMER OK
TMERZ2:  LCALL  HBEEP             ;RESET
         MOV    R2,#5
         LCALL  DTSEC
         LCALL  GKEY
         JNB    GKEYOK,TMERZ2
         CJNE   A,#1BH,$+6
         LJMP   MAIN              ;EXIT
         LJMP   TMERY

TMERZ4:  LCALL  HBEEP             ;AUTO
         MOV    R2,#5
         LCALL  DTSEC
         LJMP   TMERY

TMERD:   MOV    A,TIMBUF          ;**** DISPLAY LOOP ****
         LCALL  HTOA
         MOV    LCDBUF+56,R2
         MOV    LCDBUF+57,R3
         MOV    A,TIMBUF+1
         LCALL  HTOA
         MOV    LCDBUF+59,R2
         MOV    LCDBUF+60,R3
         MOV    A,TIMBUF+2
         LCALL  HTOA
         MOV    LCDBUF+62,R2
         MOV    LCDBUF+63,R3
         LCALL  LCDLDI
         RET

; ********** TSTW **********
; TOOL STOP WATCH
; COMBUF+0 = TOTAL TIME (3 BYTE)

TSTW:    MOV    DPTR,#TSTWT
         LCALL  LOAD4
         LCALL  LCDLDI
         CLR    A
         MOV    COMBUF,A
         MOV    COMBUF+1,A
         MOV    COMBUF+2,A
         CLR    TCNTUD            ;SET DOWN FLAG

TSTW3:   LCALL  GKEY              ;**** WAIT FOR START ****
         JNB    TOOLBT,TSTW4      ;CHECK START
         JNB    GKEYOK,TSTW3
         CJNE   A,#1BH,TSTW3
         LJMP   MAIN              ;EXIT

TSTW4:   CLR    A
         MOV    TIMBUF,A
         MOV    TIMBUF+1,A
         MOV    TIMBUF+2,A
         MOV    TIMDIV,A
         SETB   TR0               ;START TIMER-0
         LCALL  HBEEP

TSTW5:   LCALL  TMERD             ;DISPLAY LOOP
         JB     TOOLBT,TSTW7
         LCALL  GKEY
         JNB    GKEYOK,TSTW5
         CJNE   A,#1BH,TSTW5
         LJMP   MAIN              ;EXIT

TSTW7:   CLR    TR0               ;STOP TIMER-0
         LCALL  HBEEP
         LCALL  TMERD
         MOV    LCDBUF+40,LCDBUF+56
         MOV    LCDBUF+41,LCDBUF+57
         MOV    LCDBUF+43,LCDBUF+59
         MOV    LCDBUF+44,LCDBUF+60
         MOV    LCDBUF+46,LCDBUF+62
         MOV    LCDBUF+47,LCDBUF+63
         LCALL  TSTWTL
         LCALL  TSTWTD
         LCALL  LCDLDI
         SJMP   TSTW3

TSTWT:   DB     'TOOL STOPWATCH  '
         DB     'TOTAL   00:00:00'
         DB     'LAST    00:00:00'
         DB     'TIME    00:00:00'

TSTWTL:  MOV    A,COMBUF+2        ;**** ADD TOTAL SUB ****
         ADD    A,TIMBUF+2
         DA     A
         CJNE   A,#60H,$+3        ;CHECK >60
         JBC    CY,TSTWTL2
         CLR    C
         SUBB   A,#60H
         CALL   SUBDA
         SETB   C
TSTWTL2: MOV    COMBUF+2,A

         MOV    A,COMBUF+1
         ADDC   A,TIMBUF+1
         DA     A
         CJNE   A,#60H,$+3        ;CHECK <60
         JBC    CY,TSTWTL4
         CLR    C
         SUBB   A,#60H
         CALL   SUBDA
         SETB   C
TSTWTL4: MOV    COMBUF+1,A

         MOV    A,COMBUF
         ADDC   A,TIMBUF
         DA     A
         MOV    COMBUF,A
         RET

TSTWTD:  MOV    A,COMBUF          ;**** DISPLAY TOTAL SUB ****
         LCALL  HTOA
         MOV    LCDBUF+24,R2
         MOV    LCDBUF+25,R3
         MOV    A,COMBUF+1
         LCALL  HTOA
         MOV    LCDBUF+27,R2
         MOV    LCDBUF+28,R3
         MOV    A,COMBUF+2
         LCALL  HTOA
         MOV    LCDBUF+30,R2
         MOV    LCDBUF+31,R3
         RET

; ********** TLGP **********
; TOOL LOGIC PROBE

TLGP:    LCALL  CLEAR
         MOV    DPTR,#TLGPT
         LCALL  LOAD3
         LCALL  LCDLDI

TLGP2:   MOV    INPSTT,#LCDBUF+29 ;SPEED
         MOV    INPEND,#LCDBUF+30
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TLGP9
         JB     INPBKF,TLGP2

         MOV    R2,LCDBUF+29
         MOV    R3,LCDBUF+30
         LCALL  ATOH
         CPL    A
         INC    A
         MOV    B,A
         MOV    LCDBUF+49,#'-'

TLGP4:   MOV    R7,#14            ;**** LOGIC PROBE LOOP ****
         MOV    R1,#LCDBUF+50

TLGP41:  MOV    R2,B              ;SPEED DELAY
TLGP42:  MOV    R3,B
         DJNZ   R3,$
         DJNZ   R2,TLGP42

         JNB    TOOLBT,TLGP5
         MOV    @R1,#'1'          ;HIGH
         MOV    LCDBUF+48,#'1'
         SJMP   TLGP6
TLGP5:   MOV    @R1,#'0'          ;LOW
         MOV    LCDBUF+48,#'0'
TLGP6:   LCALL  LCDLDI
         INC    R1                ;NEXT
         DJNZ   R7,TLGP41
         SJMP   TLGP4
TLGP9:   LJMP   MAIN

TLGPT:   DB     'TOOL LOGIC-PROBE'
         DB     'SPEED (HEX) :XX '
         DB     '(EXIT BY RESET) '

; ********** TLREC **********

TLREC:   MOV    DPTR,#TLRECT
         LCALL  LOAD4
         LCALL  LCDLDI
         SJMP   TLREC2

TLREC9:  LJMP   MAIN
TLREC2:  MOV    INPSTT,#LCDBUF+22
         MOV    INPEND,#LCDBUF+25
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TLREC9
         JB     INPBKF,TLREC2

         MOV    INPSTT,#LCDBUF+38
         MOV    INPEND,#LCDBUF+39
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TLREC9
         JB     INPBKF,TLREC2

         MOV    R2,LCDBUF+22      ;CHANGE TO HEX (DELAY)
         MOV    R3,LCDBUF+23
         LCALL  ATOH
         MOV    B,A
         MOV    R2,LCDBUF+24
         MOV    R3,LCDBUF+25
         LCALL  ATOH
         MOV    R3,A
         MOV    R2,B
         MOV    R1,#0
         LCALL  DTOH
         MOV    A,DPH             ;CHECK ZERO
         ORL    A,DPL
         JZ     TLREC2
         MOV    COMBUF,DPH
         MOV    COMBUF+1,DPL

         MOV    R2,LCDBUF+38      ;CHANGE TO HEX (SIZE)
         MOV    R3,LCDBUF+39
         LCALL  ATOH
         MOV    B,A
         MOV    R2,LCDBUF+40
         MOV    R3,LCDBUF+41
         LCALL  ATOH
         MOV    DPL,A
         MOV    DPH,B
         MOV    A,DPH             ;CHECK ZERO
         ORL    A,DPL
         JZ     TLREC2

         MOV    A,DPL             ;ADD 4000H (IS END ADDRESS)
         ADD    A,#00H
         MOV    DPL,A
         MOV    A,DPH
         ADDC   A,#40H
         MOV    DPH,A
         MOV    COMBUF+2,DPH
         MOV    COMBUF+3,DPL

TLREC4:  MOV    DPTR,#TLRECTX     ;**** SELECT MODE LOOP ****
         LCALL  LOADBM
         LCALL  LCDLDI

         MOV    INPSTT,#LCDBUF+62
         MOV    INPEND,#LCDBUF+62
         CLR    INPHXF
         LCALL  INPX
         JB     INPEXF,TLREC91
         MOV    A,LCDBUF+62
         LCALL  UPPER
         CJNE   A,#'R',$+6
         LJMP   TLR
         CJNE   A,#'S',$+6
         LJMP   TLS
         CJNE   A,#'D',$+6
         LJMP   TLD
         SJMP   TLREC4
TLREC91: LJMP   MAIN

TLRECT:  DB     'TOOL LOGIC-REC  '
         DB     'DELAY:0001 (mS) '
         DB     'SIZE :4000 (HEX)'
TLRECTX: DB     'Type (R,S,D) :X '

TLR:     LCALL  WORKING           ;**** RECORD ****
         MOV    DPTR,#4000H
         SETB   TOOLBT

TLR1:    MOV    R7,#0             ;8 BIT LOOP
         MOV    R6,#8
TLR2:    MOV    C,TOOLBT
         MOV    A,R7
         RRC    A
         MOV    R7,A
         MOV    R2,COMBUF         ;DELAY
         MOV    R3,COMBUF+1
         LCALL  DMSEC
         DJNZ   R6,TLR2

         MOV    A,R7              ;NEXT & CHECK END
         MOVX   @DPTR,A
         INC    DPTR
         MOV    A,DPH
         CJNE   A,COMBUF+2,TLR1
         MOV    A,DPL
         CJNE   A,COMBUF+3,TLR1
         LCALL  HBEEP
         LJMP   TLREC4

TLS:     LCALL  WORKING           ;**** SIMULATE ****
         MOV    DPTR,#4000H

TLS1:    MOVX   A,@DPTR
         MOV    R7,A              ;8 BIT LOOP
         MOV    R6,#8
TLS2:    MOV    A,R7
         RRC    A
         MOV    R7,A
         MOV    TOOLBT,C
         MOV    R2,COMBUF         ;DELAY
         MOV    R3,COMBUF+1
         LCALL  DMSEC
         DJNZ   R6,TLS2

         INC    DPTR              ;NEXT & CHECK END
         MOV    A,DPH
         CJNE   A,COMBUF+2,TLS1
         MOV    A,DPL
         CJNE   A,COMBUF+3,TLS1
         SETB   TOOLBT
         LCALL  HBEEP
         LJMP   TLREC4

TLD:     LCALL  CONF              ;**** DUMP ****
         JNB    INPEXF,TLD1
         LJMP   TLREC4

TLD1:    SETB   DUMPBM
         MOV    A,#80H
         LCALL  WPORTX
         LCALL  PLF
         MOV    DPTR,#4000H       ;START RAM

TLD2:    MOV    R7,#16            ;128 LOOP
         MOV    A,#1BH            ;IMAGE MODE CODE
         LCALL  PBYTE
         MOV    A,#'K'
         LCALL  PBYTE
         MOV    A,#80H            ;128 DOT LOOP
         LCALL  PBYTE
         MOV    A,#00H
         LCALL  PBYTE

TLD3:    MOV    R6,#8             ;8 BIT LOOP
         MOVX   A,@DPTR
TLD4:    RRC    A
         PUSH   ACC
         JC     TLD42
         LCALL  TLDL              ;LOW
         SJMP   TLD43
TLD42:   LCALL  TLDH              ;HIGH
TLD43:   POP    ACC
         DJNZ   R6,TLD4
         INC    DPTR
         DJNZ   R7,TLD3

         MOV    A,DPH
         CJNE   A,COMBUF+2,TLD2
         MOV    A,DPL
         CJNE   A,COMBUF+3,TLD2
         LCALL  HBEEP
         LJMP   TLREC4

TLDL:    JB     DUMPBM,TLDL1      ;PRINT LOW SUB.
         MOV    A,#01H
         LCALL  PBYTE
         RET
TLDL1:   MOV    A,#0FFH
         LCALL  PBYTE
         CLR    DUMPBM
         RET

TLDH:    JNB    DUMPBM,TLDH1      ;PRINT HIGH SUB.
         MOV    A,#80H
         LCALL  PBYTE
         RET
TLDH1:   MOV    A,#0FFH
         LCALL  PBYTE
         SETB   DUMPBM
         RET

; ********** TPGEN **********
; COMBUF+0 = HIGH TIME (2 BYTE)
; COMBUF+2 = LOW TIME (2 BYTE)

TPGEN:   LCALL  CLEAR
         MOV    DPTR,#TPGENT
         LCALL  LOAD3
         LCALL  LCDLDI
         SETB   TOOLBT

TPGEN2:  MOV    INPSTT,#LCDBUF+18
         MOV    INPEND,#LCDBUF+21
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TPGEN9
         JB     INPBKF,TPGEN2

TPGEN3:  MOV    INPSTT,#LCDBUF+25
         MOV    INPEND,#LCDBUF+28
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,TPGEN9
         JB     INPBKF,TPGEN2

TPGEN4:  MOV    INPSTT,#LCDBUF+46
         MOV    INPEND,#LCDBUF+46
         CLR    INPHXF
         LCALL  INPX
         JB     INPEXF,TPGEN9
         JB     INPBKF,TPGEN3

         MOV    A,LCDBUF+46
         LCALL  UPPER
         MOV    LCDBUF+46,A
         CJNE   A,#'C',$+6
         LJMP   TPGENC
         CJNE   A,#'K',$+6
         LJMP   TPGENK
         CJNE   A,#'S',$+6
         LJMP   TPGENS
         SJMP   TPGEN4
TPGEN9:  LJMP   MAIN

TPGENT:  DB     'TOOL PULSE GEN  '
         DB     'H:XXXX L:XXXX mS'
         DB     'Type (C,K,S) :X '
TPGENTX: DB     'Type Key 1-0    '
TPGENTY: DB     'SET PULSE :0000 '

TPGENK:  MOV    DPTR,#TPGENTX     ;**** PULSE BY KEY ****
         LCALL  LOADBM
         LCALL  LCDLDI
TPGENK2: LCALL  GKEY
         JNB    GKEYOK,TPGENK2
         CJNE   A,#1BH,$+6
         LJMP   MAIN
         CJNE   A,#'0',$+3
         JC     TPGENK2
         CJNE   A,#'9'+1,$+3
         JNC    TPGENK2

         ANL    A,#0FH            ;CHANGE TO HEX
         JNZ    TPGENK4
         MOV    A,#10
TPGENK4: PUSH   ACC
         LCALL  TPGENX
         POP    ACC
TPGENK5: PUSH   ACC
         LCALL  TPGENPL
         POP    ACC
         DEC    A
         JNZ    TPGENK5
         SJMP   TPGENK2

TPGENS9: LJMP   MAIN
TPGENS:  MOV    DPTR,#TPGENTY     ;**** SET PULSE ****
         LCALL  LOADBM
         LCALL  LCDLDI
         MOV    INPSTT,#LCDBUF+59
         MOV    INPEND,#LCDBUF+62
         SETB   INPHXF
         LCALL  INPX
         JB     INPBKF,TPGENS9
         JB     INPEXF,TPGENS9

         MOV    R2,LCDBUF+59      ;CHANGE TO HEX
         MOV    R3,LCDBUF+60
         LCALL  ATOH
         MOV    B,A
         MOV    R2,LCDBUF+61
         MOV    R3,LCDBUF+62
         LCALL  ATOH
         MOV    R3,A
         MOV    R2,B
         MOV    R1,#0
         LCALL  DTOH

         MOV    A,DPH             ;CHECK ZERO
         ORL    A,DPL
         JZ     TPGENS
         MOV    COMBUF+4,DPH
         MOV    COMBUF+5,DPL
         LCALL  TPGENX
         MOV    DPTR,#0
TPGENS4: LCALL  TPGENPL
         INC    DPTR
         MOV    A,DPH
         CJNE   A,COMBUF+4,TPGENS4
         MOV    A,DPL
         CJNE   A,COMBUF+5,TPGENS4
         LCALL  HBEEP
         SJMP   TPGENS

TPGENC:  LCALL  TPGENX            ;**** CONTINUE PULSE ****
         LCALL  WORKING
TPGENC2: LCALL  TPGENPL
         SJMP   TPGENC2

TPGENPL: SETB   TOOLBT            ;1 PULSE SUB.
         MOV    R2,COMBUF
         MOV    R3,COMBUF+1
         LCALL  DMSEC
         CLR    TOOLBT
         MOV    R2,COMBUF+2
         MOV    R3,COMBUF+3
         LCALL  DMSEC
         SETB   TOOLBT            ;DEFAULT HIGH
         RET

TPGENX:  MOV    R2,LCDBUF+18      ;**** CHANGE HIGH/LOW TO COMBUF ****
         MOV    R3,LCDBUF+19
         LCALL  ATOH
         MOV    B,A
         MOV    R2,LCDBUF+20
         MOV    R3,LCDBUF+21
         LCALL  ATOH
         MOV    R3,A
         MOV    R2,B
         MOV    R1,#0
         LCALL  DTOH
         MOV    COMBUF+0,DPH
         MOV    COMBUF+1,DPL

         MOV    R2,LCDBUF+25
         MOV    R3,LCDBUF+26
         LCALL  ATOH
         MOV    B,A
         MOV    R2,LCDBUF+27
         MOV    R3,LCDBUF+28
         LCALL  ATOH
         MOV    R3,A
         MOV    R2,B
         MOV    R1,#0
         LCALL  DTOH
         MOV    COMBUF+2,DPH
         MOV    COMBUF+3,DPL
         RET

; ********** M8255 **********
; 8255 INPUT MAP

M8255:   MOV    DPTR,#M8255T
         LCALL  LOAD4
         MOV    A,#9BH            ;ALL BIT = IN
         LCALL  WPORTX

M82551:  MOV    R2,#2             ;DELAY
M82552:  MOV    R3,#0
         DJNZ   R3,$
         DJNZ   R2,M82552

         LCALL  RPORTA
         MOV    R0,#LCDBUF+23
         LCALL  TOBIT
         LCALL  RPORTB
         MOV    R0,#LCDBUF+39
         LCALL  TOBIT
         LCALL  RPORTC
         MOV    R0,#LCDBUF+55
         LCALL  TOBIT
         LCALL  LCDLDI

         LCALL  GKEY
         JNB    GKEYOK,M82551
         CJNE   A,#1BH,M82551
         LJMP   MAIN

M8255T:  DB     '8255 INPUT MAP  '
         DB     'PA7-0 <XXXXXXXX>'
         DB     'PB7-0 <XXXXXXXX>'
         DB     'PC7-0 <XXXXXXXX>'

TOBIT:   MOV    R2,#8             ;CHANGE A -> BIT ON LCDBUF
TOBIT2:  MOV    @R0,#'0'
         RLC    A
         JNC    TOBIT3
         MOV    @R0,#'1'
TOBIT3:  INC    R0
         DJNZ   R2,TOBIT2
         RET

; ********** SDATE **********
; SET DATE/TIME

SDATE:   MOV    DPTR,#SDATET
         LCALL  LOAD4

SDATE2:  LCALL  RTCRD             ;DISPLAY LOOP
         MOV    A,RTCBUF+5        ;DATE (CHANGE RTCBUF TO LCDBUF)
         LCALL  HTOA
         MOV    LCDBUF+21,R2
         MOV    LCDBUF+22,R3
         MOV    A,RTCBUF+6
         LCALL  HTOA
         MOV    LCDBUF+24,R2
         MOV    LCDBUF+25,R3
         MOV    A,RTCBUF+7
         LCALL  HTOA
         MOV    LCDBUF+27,R2
         MOV    LCDBUF+28,R3

         MOV    A,RTCBUF+3        ;TIME
         LCALL  HTOA
         MOV    LCDBUF+37,R2
         MOV    LCDBUF+38,R3
         MOV    A,RTCBUF+2
         LCALL  HTOA
         MOV    LCDBUF+40,R2
         MOV    LCDBUF+41,R3
         MOV    A,RTCBUF+1
         LCALL  HTOA
         MOV    LCDBUF+43,R2
         MOV    LCDBUF+44,R3

         LCALL  LCDLDI
         LCALL  GKEY
         JNB    GKEYOK,SDATE2
         CJNE   A,#1BH,$+6
         LJMP   MAIN              ;EXIT
         CJNE   A,#0DH,$+6
         LJMP   SDATE5
SDATEX:  SJMP   SDATE2
         
SDATE5:  MOV    INPSTT,#LCDBUF+21 ;**** SET DATE ****
         MOV    INPEND,#LCDBUF+22
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,SDATEX
         JB     INPBKF,SDATE5

SDATE52: MOV    INPSTT,#LCDBUF+24
         MOV    INPEND,#LCDBUF+25
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,SDATEX
         JB     INPBKF,SDATE5

SDATE53: MOV    INPSTT,#LCDBUF+27
         MOV    INPEND,#LCDBUF+28
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,SDATEX
         JB     INPBKF,SDATE52

SDATE54: MOV    INPSTT,#LCDBUF+37 ;SET TIME
         MOV    INPEND,#LCDBUF+38
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,SDATEX
         JB     INPBKF,SDATE53

SDATE55: MOV    INPSTT,#LCDBUF+40
         MOV    INPEND,#LCDBUF+41
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,SDATEX
         JB     INPBKF,SDATE54

SDATE56: MOV    INPSTT,#LCDBUF+43
         MOV    INPEND,#LCDBUF+44
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,SDATEX
         JB     INPBKF,SDATE55

         MOV    R2,LCDBUF+21      ;DATE (CHANGE LCDBUF TO RTCBUF)
         MOV    R3,LCDBUF+22
         LCALL  ATOH
         MOV    RTCBUF+5,A
         MOV    R2,LCDBUF+24
         MOV    R3,LCDBUF+25
         LCALL  ATOH
         MOV    RTCBUF+6,A
         MOV    R2,LCDBUF+27
         MOV    R3,LCDBUF+28
         LCALL  ATOH
         MOV    RTCBUF+7,A

         MOV    R2,LCDBUF+37      ;TIME
         MOV    R3,LCDBUF+38
         LCALL  ATOH
         MOV    RTCBUF+3,A
         MOV    R2,LCDBUF+40
         MOV    R3,LCDBUF+41
         LCALL  ATOH
         MOV    RTCBUF+2,A
         MOV    R2,LCDBUF+43
         MOV    R3,LCDBUF+44
         LCALL  ATOH
         MOV    RTCBUF+1,A

         MOV    RTCBUF+4,#01H     ;DAY=1,OSC=0
         MOV    RTCBUF,#00H       ;1/100SEC=0
         CLR    ET0
         MOV    R2,#0
         DJNZ   R2,$
         LCALL  RTCWR
         SETB   ET0
         LCALL  HBEEP
         MOV    R2,#2
         LCALL  DTSEC
         LCALL  RTCRD
         LJMP   SDATE2

SDATET:  DB     'SET DATE/TIME   '
         DB     'DATE DD/MM/YY   '
         DB     'TIME HH:MM:SS   '
         DB     'Type ENT to set '

; ********** SBAUD **********
; SET BAUD RATE

SBAUD:   MOV    DPTR,#SBAUDT
         LCALL  LOAD4

SBAUD2:  MOV    A,BAUDMM          ;DISPLAY CURRENT BUAD-RATE
         LCALL  HTOA
         MOV    LCDBUF+22,R2
         MOV    LCDBUF+23,R3
         LCALL  LCDLDI

SBAUD3:  MOV    INPSTT,#LCDBUF+22 ;INPUT
         MOV    INPEND,#LCDBUF+23
         SETB   INPHXF
         LCALL  INPX
         JB     INPEXF,SBAUD9
         JB     INPBKF,SBAUD2

         MOV    R2,LCDBUF+22      ;CHECK
         MOV    R3,LCDBUF+23
         LCALL  ATOH
         CJNE   A,#12H,$+6
         LJMP   SBAUD7
         CJNE   A,#24H,$+6
         LJMP   SBAUD7
         CJNE   A,#48H,$+6
         LJMP   SBAUD7
         CJNE   A,#96H,$+6
         LJMP   SBAUD7
         CJNE   A,#19H,$+6
         LJMP   SBAUD7
         LCALL  LBEEP
         SJMP   SBAUD3

SBAUD7:  MOV    BAUDMM,A          ;SET BAUD-RATE
         LCALL  BAUDS
         LCALL  HBEEP
         MOV    R2,#5
         LCALL  DTSEC
SBAUD9:  LJMP   MAIN

SBAUDT:  DB     'SET BAUD-RATE   '
         DB     'BAUD :XX        '
         DB     '(12,24,48,96,19)'
         DB     '                '

; ********** INPX SUB **********
; INPUT CHAR. ON LCD (HEX,ASCII)
; IN  = INPSTT   FIRST POSITION AT LCDBUF
;       INPEND   END POSITION AT LCDBUF
;       INPHXF   HEX ONLY FLAG (0-F INPUT)
; OUT = (LCDBUF) AT POSITION
;       INPBKF   BACK FIELD FLAG
;       INPEXF   EXIT FLAG
; REG = ALL

INPX:    CLR    INPBKF
         CLR    INPEXF
         MOV    R1,INPSTT

INPX2:   MOV    A,R1
         CLR    C
         SUBB   A,#LCDBUF
         LCALL  INPADD
         ORL    A,#10000000B      ;SET ADDRESS
         LCALL  LCDWI
         MOV    A,#00001110B      ;SET CURSOR
         LCALL  LCDWI

INPX3:   LCALL  GKEY
         JNB    GKEYOK,INPX3
         CJNE   A,#08H,$+6
         LJMP   INPXBF
         CJNE   A,#1BH,$+6
         LJMP   INPXEX
         CJNE   A,#80H,$+6
         LJMP   INPXL
         CJNE   A,#81H,$+6
         LJMP   INPXR
         CJNE   A,#0DH,$+6
         LJMP   INPXCR

         JNB    INPHXF,INPX5      ;CHECK HEX ONLY
         LCALL  UPPER
         CJNE   A,#'0',$+3
         JC     INPX45            ;<0
         CJNE   A,#'F'+1,$+3
         JNC    INPX45            ;>F
         CJNE   A,#'9'+1,$+3
         JC     INPX4             ;OK 0-9
         CJNE   A,#'A',$+3
         JC     INPX45            ;<A
INPX4:   SJMP   INPX6
INPX45:  SJMP   INPX3             ;NOT OK

INPX5:   CJNE   A,#20H,$+3        ;CHECK ASCII < SPACE
         JNC    INPX6
         SJMP   INPX2

INPX6:   MOV    @R1,A             ;CHAR.
         LCALL  LCDWD
         MOV    A,R1
         CJNE   A,INPEND,$+6
         LJMP   INPX2
         INC    R1
         SJMP   INPX3

INPXL:   MOV    A,R1              ;L
         CJNE   A,INPSTT,INPXL2
         LCALL  LBEEP
         SJMP   INPX3
INPXL2:  DEC    R1
         SJMP   INPX2

INPXR:   MOV    A,R1              ;R
         CJNE   A,INPEND,INPXR2
         LCALL  LBEEP
         SJMP   INPX3
INPXR2:  INC    R1
         SJMP   INPX2

INPXEX:  SETB   INPEXF            ;EXIT
         SJMP   INPXCR
INPXBF:  SETB   INPBKF            ;BACK FIELD
INPXCR:  MOV    A,#00001100B      ;CR (EXIT)
         LCALL  LCDWI
         RET

INPADD:  CJNE   A,#10H,$+3        ;**** FIND LCD ADDRESS **** (IN=A)
         JNC    INPADD1
         RET
INPADD1: CJNE   A,#20H,$+3
         JNC    INPADD2
         ANL    A,#11101111B
         ORL    A,#01000000B
         RET
INPADD2: CJNE   A,#30H,$+3
         JNC    INPADD3
         ANL    A,#11011111B
         ORL    A,#00010000B
         RET
INPADD3: ANL    A,#11001111B
         ORL    A,#01010000B
         RET

; ********** CONF SUB **********
; LOAD MESSAGE TO LINE4 & OUT TO LCD & WAIT KEY
; OUT = INPEXF
; REG = A,R0,R2,DPTR

CONF:    CLR    INPEXF
         MOV    DPTR,#CONFT
         LCALL  LOADBM
         LCALL  LCDLDI

CONF5:   LCALL  GKEYX
         CJNE   A,#1BH,CONF6
         SETB   INPEXF
         RET
CONF6:   CJNE   A,#0DH,CONF5
         RET
CONFT:   DB     'type ENT to work'

; ********** WORKING SUB **********
; LOAD MESSAGE TO LINE4 & OUT TO LCD
; IN  = DPTR
; REG = A,R0,R2,DPTR

WORKING: MOV    DPTR,#WORKT
         LCALL  LOADBM
         LCALL  LCDLDI
         RET
WORKT:   DB     'Working ...     '

; ********** LOADBM SUB **********
; LOAD FROM DPTR (PMEM) -> LCDBUF (BOTTOM LINE ONLY) (NOT OUT TO LCD)
; IN  = DPTR
; REG = A,R0,R2,DPTR

LOADBM:  MOV    R2,#16            ;LINE 4
         MOV    R0,#LCDBUF+48
LOADBM2: CLR    A
         MOVC   A,@A+DPTR
         MOV    @R0,A
         INC    DPTR
         INC    R0
         DJNZ   R2,LOADBM2
         RET

; ********** LOAD2,3,4 SUB **********
; LOAD FROM DPTR (PMEM) -> LCDBUF (NOT OUT TO LCD)
; 2,3,4 LINE
; IN  = DPTR
; REG = A,R0,R2,DPTR

LOAD4:   MOV    R2,#64            ;LINE 1,2,3,4
         SJMP   LOAD21
LOAD3:   MOV    R2,#48            ;LINE 1,2,3
         SJMP   LOAD21
LOAD2:   MOV    R2,#32            ;LINE 1,2

LOAD21:  MOV    R0,#LCDBUF
LOAD22:  CLR    A
         MOVC   A,@A+DPTR
         MOV    @R0,A
         INC    DPTR
         INC    R0
         DJNZ   R2,LOAD22
         RET

; ********** CLEAR SUB **********
; CLEAR LCDBUF

CLEAR:   MOV    A,#01H
         LCALL  LCDWI
CLEARX:  MOV    R2,#64            ;CLEAR RAM ONLY
         MOV    R0,#LCDBUF
CLEAR1:  MOV    @R0,#' '
         INC    R0
         DJNZ   R2,CLEAR1
         RET

; ********** SON,SOFF SUB **********

SON:     CLR    COMDRV            ;INVERSE
         RET

SOFF:    JNB    TI,$
         NOP
         NOP
         NOP
         NOP
         SETB   COMDRV
         RET

; ********** SBYTE SUB **********
; SEND BYTE
; IN  = A
; REG = NO

SBYTEX:  PUSH   ACC               ;WITH CHECKSUM
         XRL    A,R7
         MOV    R7,A
         POP    ACC

SBYTE:   JNB    TI,$              ;WAIT FOR SEND OK
         CLR    TI
         MOV    SBUF,A
         RET

; ********** SBYTEH SUB **********
; SEND 2 BYTE HEX FROM A
; IN  = A
; REG = A,R2,R3

SBYTEH:  LCALL  HTOA
         MOV    A,R2
         LCALL  SBYTE
         MOV    A,R3
         LCALL  SBYTE
         RET

SBYTEHC: XCH    A,R7              ;R7=CHECKSUM
         ADD    A,R7
         XCH    A,R7
         LCALL  SBYTEH
         RET

; ********** SBYTEW SUB **********
; SEND 4 BYTE FROM SPTR
; IN  = DPTR
; REG = A,R2,R3

SBYTEW:  MOV    A,DPH
         LCALL  SBYTEH
         MOV    A,DPL
         LCALL  SBYTEH
         RET

; ********** SBLOCK SUB **********
; SEND BLOCK
; IN  = DPTR ROM-ADDRESS (END BY 0 OR 0DH)
; OUT = DPTR (NEXT)
; REG = A,DPTR

SBLOCK:  CLR    A
         MOVC   A,@A+DPTR
         CJNE   A,#0,SBLOCK1
         INC    DPTR              ;NEXT ADDRESS
         RET                      ;EXIT BY 0
SBLOCK1: CJNE   A,#0DH,SBLOCK2
         LCALL  SLF               ;CR/LF
         INC    DPTR              ;NEXT ADDRESS
         RET                      ;EXIT BY ODH
SBLOCK2: LCALL  SBYTE
         INC    DPTR
         SJMP   SBLOCK

; ********** SBLANK SUB **********
; SEND BLANK
; IN  = R2 (NO OF BLANK)
; REG = A,R2

SBLANK:  MOV    A,#' '
         LCALL  SBYTE
         DJNZ   R2,SBLANK
         RET

; ********** SLF SUB **********
; PRINT CR/LF
; REG = A

SLF:     MOV    A,#0DH
         LCALL  SBYTE
         MOV    A,#0AH
         LCALL  SBYTE
         RET

; ********** Sxxx SUB **********

S1B:     MOV    A,#' '
         LCALL  SBYTE
         RET

; ********** RBYTE SUB **********
; OUT = A
; REG = A

RBYTE:   JNB    RI,$              ;WAIT FOR RECEIVE OK
         CLR    RI
         MOV    A,SBUF
         RET

RBYTEX:  LCALL  RBYTE             ;WITH CHECKSUM
         PUSH   ACC
         XRL    A,R7
         MOV    R7,A
         POP    ACC
         RET

; ********** RBYTEH SUB **********
; READ HEX-ASCII FROM SERIAL (2 BYTE)
; OUT = A
; REG = A,R2,R3

RBYTEH:  LCALL  RBYTE
         MOV    R2,A
         LCALL  RBYTE
         MOV    R3,A
         LCALL  ATOH
         RET

RBYTEHC: LCALL  RBYTEH            ;R7=CHECKSUM
         XCH    A,R7
         ADD    A,R7
         XCH    A,R7
         RET

; ********** RBYTEW SUB **********
; READ BYTE WORD FROM SERIAL (4 BYTE)
; OUT = DPTR
; REG = A,R2,R3,DPTR

RBYTEW:  LCALL  RBYTEH
         MOV    DPH,A
         LCALL  RBYTEH
         MOV    DPL,A
         RET

; ********** BAUDS SUB **********
; SET BAUD RATE (SERIAL)
; IN  = A (12H,24H,48H,96H,19H)
; REG = B

BAUDS:   MOV    B,PCON
         CJNE   A,#19H,BAUDS1
         MOV    TH1,#BRAT96       ;19200
         SETB   SMOD
         SJMP   BAUDS7
BAUDS1:  CJNE   A,#96H,BAUDS2
         MOV    TH1,#BRAT96       ;9600
         CLR    SMOD
         SJMP   BAUDS7
BAUDS2:  CJNE   A,#48H,BAUDS3
         MOV    TH1,#BRAT48       ;4800
         SJMP   BAUDS7
BAUDS3:  CJNE   A,#24H,BAUDS4
         MOV    TH1,#BRAT24       ;2400
         SJMP   BAUDS7
BAUDS4:  CJNE   A,#12H,BAUDS71
         MOV    TH1,#BRAT12       ;1200

BAUDS7:  MOV    PCON,B
BAUDS71: RET

; ********** HTOA SUB **********
; CONVERT HEX TO ASCII
; IN  = A
; OUT = R2,R3
; REG = A,R2,R3

HTOA:    PUSH   ACC
         SWAP   A
         LCALL  HTOAS
         MOV    R2,A
         POP    ACC
         LCALL  HTOAS
         MOV    R3,A
         RET

HTOAS:   ANL    A,#0FH
         CJNE   A,#0AH,$+3
         JNC    HTOAS1
         ORL    A,#30H
         RET
HTOAS1:  SUBB   A,#9
         ORL    A,#40H
         RET

; ********** ATOH SUB **********
; ASCII TO HEX CONVERT
; IN  = R2,R3   30H,41H
; OUT = A       0AH
; REG = A,R2

ATOH:    MOV    A,R2
         LCALL  ATOHS
         SWAP   A
         MOV    R2,A
         MOV    A,R3
         LCALL  ATOHS
         ORL    A,R2
         RET

ATOHS:   CJNE   A,#'A',$+3
         JC     ATOHS1
         ADD    A,#9
ATOHS1:  ANL    A,#0FH
         RET

; ********** DTSEC SUB **********
; DELAY 1/10 SECOND
; IN  = R2
; REG = R2,R3,R4

DTSEC:   MOV    R3,#179
DTSEC1:  MOV    R4,#0
         DJNZ   R4,$
         NOP
         NOP
         DJNZ   R3,DTSEC1
         DJNZ   R2,DTSEC
         RET

; ********** DPCOM SUB **********
; COMPARE WORD (16 BIT) DPTR <> R2,R3
; IN  = DPTR,R2,R3
; OUT = CY,A
; REG = A

DPCOM:   PUSH   DPL
         CLR    C
         MOV    A,DPL
         SUBB   A,R3
         MOV    DPL,A
         MOV    A,DPH
         SUBB   A,R2
         ORL    A,DPL
         POP    DPL
         RET

; ********** DPDEC SUB **********
; DPTR = DPTR - 1
; IN  = DPTR
; OUT = DPTR
;     = A (ZERO FLAG)
; REG = NO

DPDEC:   XCH    A,DPL
         JNZ    $+4
         DEC    DPH
         DEC    A
         XCH    A,DPL
         RET

; ********** DPADD SUB **********
; DPTR = DPTR + R2,R3
; IN  = DPTR,R2,R3
; OUT = DPTR
; REG = A,DPTR

DPADD:   MOV    A,DPL
         ADD    A,R3
         MOV    DPL,A
         MOV    A,DPH
         ADDC   A,R2
         MOV    DPH,A
         RET

; ********** DPSUB SUB **********
; DPTR = DPTR - R2,R3
; IN  = DPTR,R2,R3
; OUT = DPTR
; REG = A,DPTR

DPSUB:   CLR    C
         MOV    A,DPL
         SUBB   A,R3
         MOV    DPL,A
         MOV    A,DPH
         SUBB   A,R2
         MOV    DPH,A
         RET

; ********** nBEEP SUB **********

KBEEP:   MOV    R2,#50H           ;KEY BEEP
         MOV    R3,#08H
         LCALL  SOUND
         RET

YBEEP:   MOV    R2,#40H           ;YELLOW BEEP
         MOV    R3,#10H
         LCALL  SOUND
         RET

HBEEP:   MOV    R2,#30H           ;OK BEEP
         MOV    R3,#40H
         LCALL  SOUND
         RET

LBEEP:   MOV    R2,#60H           ;ERROR BEEP
         MOV    R3,#60H
         LCALL  SOUND
         RET

; ********** SOUND SUB **********
; SOUND GENERATOR
; IN  = R2 FREQUENCY
;     = R3 LENGTH (DON'T = 0)
; REG = A,R2,R3,R4,R5

SOUND:   MOV    R5,#0             ;END FLAG
         MOV    R4,#0             ;DELAY CONSTANT
SOUND1:  LCALL  SOUNDS
         CJNE   R5,#1,SOUND1
         RET

SOUNDS:  SETB   SOUNDB            ;OUT 1
         LCALL  SOUNDX
         CLR    SOUNDB            ;OUT 0
         LCALL  SOUNDX
         RET

SOUNDX:  MOV    A,R2              ;FREQUENCY DELAY
SOUNDX1: LCALL  SOUNDY
         DEC    A
         JNZ    SOUNDX1
         RET

SOUNDY:  DJNZ   R4,SOUNDY1        ;LENGTH COUNT DOWN
         MOV    R4,#0
         DJNZ   R3,SOUNDY1
         MOV    R5,#1
SOUNDY1: RET

; ********** HTOD SUB **********
; HEX TO DECIMAL
; IN  = DPTR
; OUT = R1,R2,R3
; REG = A,R0,R1,R2,R3,R4,R5,DPTR

HTOD:    CLR    A                 ;CLEAR OUTPUT
         MOV    R1,A
         MOV    R2,A
         MOV    R3,A

         MOV    R4,#16            ;SHIFT 16 BIT
HTOD1:   MOV    A,DPL
         RLC    A
         MOV    DPL,A
         MOV    A,DPH
         RLC    A
         MOV    DPH,A

         MOV    R5,#3             ;ADD DECIMAL
         MOV    R0,#3             ;INDEX TO R3
HTOD2:   MOV    A,@R0
         ADDC   A,ACC
         DA     A
         MOV    @R0,A
         DEC    R0
         DJNZ   R5,HTOD2
         DJNZ   R4,HTOD1
         RET

; ********** DTOH SUB **********
; DECIMAL TO HEX
; IN  = R1,R2,R3
; OUT = DPTR
; REG = A,R0,R1,R2,R3,R4,R5,DPTR

DTOH:    MOV    R4,#16
DTOH1:   MOV    R5,#3             ;SHIFT & SUB
         MOV    R0,#1             ;INDEX TO R1
         CLR    C
DTOH2:   MOV    A,@R0
         RRC    A
         PUSH   PSW               ;-[
         JNB    ACC.7,DTOH3
         CLR    C
         SUBB   A,#30H
DTOH3:   JNB    ACC.3,DTOH4
         CLR    C
         SUBB   A,#03H
DTOH4:   MOV    @R0,A
         INC    R0
         POP    PSW               ;-]
         DJNZ   R5,DTOH2

         MOV    A,DPH
         RRC    A
         MOV    DPH,A
         MOV    A,DPL
         RRC    A
         MOV    DPL,A
         DJNZ   R4,DTOH1
         RET

; ********** DPMUL SUB **********
; IN  = DPTR   MULTIPLER
;     = R2,R3  MULTIPLICAND
; OUT = DPTR   RESULT
;     = CARRY FLAG SET WHEN RESULT OVERFLOW
; REG = A,R1,R2,R3,R4,R5,R6,DPTR

DPMUL:   MOV    R4,#0             ;CLEAR RESULT
         MOV    R5,#0
         MOV    R6,#0             ;CLEAR MUL FLAG

         MOV    R1,#16
DPMUL1:  MOV    A,R5              ;*2
         ADD    A,R5
         MOV    R5,A
         MOV    A,R4
         ADDC   A,R4
         MOV    R4,A
         JNC    DPMUL2            ;NO CARRY
         MOV    R6,#1             ;OVERFLOW (SET FLAG)

DPMUL2:  MOV    A,R3
         RLC    A
         MOV    R3,A
         MOV    A,R2
         RLC    A
         MOV    R2,A
         JNC    DPMUL3
         MOV    A,R5              ;R4R5=R4R5+DPTR
         ADD    A,DPL
         MOV    R5,A
         MOV    A,R4
         ADDC   A,DPH
         MOV    R4,A
         JNC    DPMUL3            ;NO CARRY
         MOV    R6,#1             ;OVERFLOW (SET FLAG)
DPMUL3:  DJNZ   R1,DPMUL1
         MOV    DPH,R4
         MOV    DPL,R5
         MOV    A,R6
         MOV    C,ACC.0           ;LOAD MUL FLAG TO CARRY
         RET

; ********** SUBDA SUB **********
; BCD ADJUST AFTER SUBB
; IN  = A,CARRY,AUX-CARRY
; OUT = A,CARRY
; REG = A

SUBDA:   JC     SUBDA2                 ;SUBB BCD ADJUST
         JB     AC,SUBDA1
         RET                           ;C=0,AC=0
SUBDA1:  ADD    A,#0FAH                ;C=0,AC=1
         CLR    C
         RET
SUBDA2:  JB     AC,SUBDA3
         ADD    A,#0A0H                ;C=1,AC=0
         SETB   C
         RET
SUBDA3:  ADD    A,#09AH                ;C=1,AC=1
         SETB   C
         RET

; ********** LCDLDP **********
; LOAD TABLE (PMEM) TO LCD-MODULE (DMC164)
; IN  = DPTR  START BLOCK (64 BYTE)
; REG = A,R2,DPTR

LCDLDP:  MOV    A,#80H            ;LINE 1
         LCALL  LCDLDS
         MOV    A,#0C0H           ;LINE 2
         LCALL  LCDLDS
         MOV    A,#90H            ;LINE 3
         LCALL  LCDLDS
         MOV    A,#0D0H           ;LINE 4
         LCALL  LCDLDS
         RET

LCDLDS:  PUSH   DPH               ;LOAD SUB.
         PUSH   DPL
         LCALL  LCDWI             ;WRITE ADDRESS
         POP    DPL
         POP    DPH
         MOV    R2,#16            ;16 CHAR.
LCDLDS1: CLR    A
         MOVC   A,@A+DPTR         ;MOVC FOR CODE
         PUSH   DPH
         PUSH   DPL
         LCALL  LCDWD             ;WRITE DATA
         POP    DPL
         POP    DPH
         INC    DPTR
         DJNZ   R2,LCDLDS1
         RET

; ********** LCDLDI SUB **********
; LOAD INTERNAL-RAM TO LCD-MODULE (DMC164)
; IN  = LCDBUF
; REG = A,R0,R2

LCDLDI:  MOV    R0,#LCDBUF
         MOV    A,#80H            ;LINE 1
         LCALL  LCDLDX
         MOV    A,#0C0H           ;LINE 2
         LCALL  LCDLDX
         MOV    A,#90H            ;LINE 3
         LCALL  LCDLDX
         MOV    A,#0D0H           ;LINE 4
         LCALL  LCDLDX
         RET

LCDLDX:  LCALL  LCDWI             ;LOAD ONE LINE
         MOV    R2,#16            ;16 CHAR.
LCDLDX1: MOV    A,@R0
         LCALL  LCDWD             ;WRITE DATA
         INC    R0
         DJNZ   R2,LCDLDX1
         RET

; ********** LCDWI **********
; LCD WRITE INSTRUCTION (RS=0)
; IN  = A
; REG = A,DPTR

LCDWI:   MOV    P0DATA,A          ;DATA
         CLR    LCDRS             ;RS=0
         CLR    LCDRW             ;R/W=0
         SETB   LCDEN             ;ENABLE=0 (INVERT)
         NOP
         CLR    LCDEN             ;ENABLE=1
         NOP
         SETB   LCDEN             ;ENABLE=0
         NOP
         MOV    A,#0              ;DELAY
LCDWI1:  DEC    A
         JNZ    LCDWI1
         RET

; ********** LCDWD **********
; LCD WRITE DATA (RS=1)
; IN  = A
; REG = A,DPTR

LCDWD:   MOV    P0DATA,A          ;DATA
         SETB   LCDRS             ;RS=1
         CLR    LCDRW             ;R/W=0
         SETB   LCDEN             ;ENABLE=0 (INVERT)
         NOP
         CLR    LCDEN             ;ENABLE=1
         NOP
         SETB   LCDEN             ;ENABLE=0
         NOP
         MOV    A,#0              ;DELAY
LCDWD1:  DEC    A
         JNZ    LCDWD1
         RET

; ********** UL161 SUB **********
; LOAD INTERNAL-RAM TO USER-LCD-MODULE (161)
; IN  = LCDBUF
; REG = A,R0,R2

UL161:   MOV    R0,#LCDBUF
         MOV    A,#80H            ;FIRST OF LINE
         MOV    R2,#8
         LCALL  ULLDX
         MOV    A,#0C0H           ;SECOND OF LINE
         MOV    R2,#8
         LCALL  ULLDX
         RET

ULLDX:   LCALL  ULCDWI            ;LOAD ONE LINE
ULLDX1:  MOV    A,@R0
         LCALL  ULCDWD            ;WRITE DATA
         INC    R0
         DJNZ   R2,ULLDX1
         RET

; ********** UL164 SUB **********
; LOAD INTERNAL-RAM TO USER-LCD-MODULE (164)
; IN  = LCDBUF
; REG = A,R0,R2

UL164:   MOV    R0,#LCDBUF
         MOV    A,#80H            ;LINE 1
         MOV    R2,#16
         LCALL  ULLDX
         MOV    A,#0C0H           ;LINE 2
         MOV    R2,#16
         LCALL  ULLDX
         MOV    A,#90H            ;LINE 3
         MOV    R2,#16
         LCALL  ULLDX
         MOV    A,#0D0H           ;LINE 4
         MOV    R2,#16
         LCALL  ULLDX
         RET

; ********** UL162 SUB **********
; LOAD INTERNAL-RAM TO USER-LCD-MODULE (162)
; IN  = LCDBUF
; REG = A,R0,R2

UL162:   MOV    R0,#LCDBUF
         MOV    A,#80H            ;LINE 1
         MOV    R2,#16
         LCALL  ULLDX
         MOV    A,#0C0H           ;LINE 2
         MOV    R2,#16
         LCALL  ULLDX
         RET

; ********** UL202 SUB **********
; LOAD INTERNAL-RAM TO USER-LCD-MODULE (202)
; IN  = LCDBUF
; REG = A,R0,R2

UL202:   MOV    R0,#LCDBUF
         MOV    A,#80H            ;LINE 1
         MOV    R2,#20
         LCALL  ULLDX
         MOV    A,#0C0H           ;LINE 2
         MOV    R2,#20
         LCALL  ULLDX
         RET

; ********** ULCDWI **********
; USER LCD WRITE INSTRUCTION (RS=0)
; IN  = A
; REG = A,DPTR

ULCDWI:  LCALL  WPORTA            ;DATA
         LCALL  RPORTB
         CLR    ACC.0             ;RS=0
         CLR    ACC.1             ;R/W=0
         CLR    ACC.2             ;ENABLE=0
         LCALL  WPORTB
         SETB   ACC.2             ;ENABLE=1
         LCALL  WPORTB
         CLR    ACC.2             ;ENABLE=0
         LCALL  WPORTB
         MOV    A,#0              ;DELAY
ULCDWI1: DEC    A
         JNZ    ULCDWI1
         RET

; ********** LCDWD **********
; LCD WRITE DATA (RS=1)
; IN  = A
; REG = A,DPTR

ULCDWD:  LCALL  WPORTA            ;DATA
         LCALL  RPORTB
         SETB   ACC.0             ;RS=1
         CLR    ACC.1             ;R/W=0
         CLR    ACC.2             ;ENABLE=0
         LCALL  WPORTB
         SETB   ACC.2             ;ENABLE=1
         LCALL  WPORTB
         CLR    ACC.2             ;ENABLE=0
         LCALL  WPORTB
         MOV    A,#0              ;DELAY
ULCDWD1: DEC    A
         JNZ    ULCDWD1
         RET

; ********** WPORTx SUB **********
; IN  = A
; REG = NO

WPORTA:  MOV    P0DATA,A
         CLR    P8255A0
         CLR    P8255A1
         SJMP   WPORTX2

WPORTB:  MOV    P0DATA,A
         SETB   P8255A0
         CLR    P8255A1
         SJMP   WPORTX2

WPORTC:  MOV    P0DATA,A
         CLR    P8255A0
         SETB   P8255A1
         SJMP   WPORTX2

WPORTX:  MOV    P0DATA,A
         SETB   P8255A0
         SETB   P8255A1
WPORTX2: CLR    WR
         SETB   WR
         RET

; ********** RPORTx SUB **********
; OUT = A
; REG = A

RPORTA:  CLR    P8255A0
         CLR    P8255A1
         SJMP   RPORTX2

RPORTB:  SETB   P8255A0
         CLR    P8255A1
         SJMP   RPORTX2

RPORTC:  CLR    P8255A0
         SETB   P8255A1
         SJMP   RPORTX2

RPORTX:  SETB   P8255A0
         SETB   P8255A1
         NOP
         NOP
RPORTX2: MOV    P0DATA,#0FFH
         NOP
         CLR    RD
         NOP
         MOV    A,P0DATA
         NOP
         SETB   RD
         RET

; ********** GKEY SUB **********
; SCAN & GET KEYBOARD
; IN  = GKEYPF (KEY PRESS FLAG)
; OUT = GKEYOK
;       A ASCII KEY CODE
; REG = A,B,R2,R3,R4,R5,R6,DPTR

GKEY:    MOV    R4,#14            ;LOOP
         MOV    R5,#14            ;RELEASE KEY COUNT
         MOV    R6,#0             ;KEY COUNT
         CLR    GKEYOK

GKEY1:   ANL    P2,#0F0H          ;OUT COLUMN
         MOV    A,R6
         ORL    P2,A
         MOV    R2,#10H           ;DELAY
         DJNZ   R2,$
         ORL    P2,#0F0H          ;IN ROW
         MOV    A,P2
         ANL    A,#0F0H
         CJNE   A,#0F0H,GKEY3
GKEY11:  DJNZ   R5,GKEY2          ;CHECK KEY RELEASE
         CLR    GKEYPF
GKEY2:   INC    R6
         DJNZ   R4,GKEY1
         RET                      ;1 LOOP EXIT

GKEY3:   JB     GKEYPF,GKEY2      ;KEY NOT RELEASE
         SETB   GKEYPF
         ORL    A,R6
         MOV    B,A

         MOV    R2,#52            ;FIND TABLE
         MOV    DPTR,#GKEYX1
GKEY4:   CLR    A
         MOVC   A,@A+DPTR
         CJNE   A,B,GKEY42
         SJMP   GKEY5
GKEY42:  INC    DPTR              ;NEXT
         INC    DPTR
         DJNZ   R2,GKEY4
         MOV    A,#0FFH
         RET                      ;EXIT ERROR

GKEY5:   INC    DPTR              ;FIND OK
         CLR    A
         MOVC   A,@A+DPTR
         CJNE   A,#83H,$+6        ;CHECK SHIFT KEY
         LJMP   GKEY7
         JNB    SHFFAG,GKEY55
         LCALL  GKEYSH            ;SHIFT ON
GKEY55:  JNB    FUNFAG,GKEY56
         LCALL  GKEYFN            ;FUNCTION ON

GKEY56:  CJNE   A,#84H,$+6        ;CHECK FUNCTION KEY
         LJMP   GKEY8
         LCALL  GKEYBP
         SETB   GKEYOK
         RET                      ;EXIT NEW PRESS

GKEY7:   CPL    SHFFAG            ;IS SHIFT KEY
         MOV    C,SHFFAG
         CPL    C
         MOV    LEDGRN,C
         LCALL  YBEEP
         RET                      ;EXIT NOTHING

GKEY8:   CPL    FUNFAG            ;IS FUNCTION KEY
         MOV    C,FUNFAG
         CPL    C
         MOV    LEDRED,C
         LCALL  YBEEP
         RET
            
GKEYX1:  DB     0E1H,1BH,0E2H,'1',0E3H,'2',0E4H,'3'
         DB     0E5H,'4',0E6H,'5',0E7H,'6',0E8H,'7'
         DB     0E9H,'8',0EAH,'9',0EBH,'0',0ECH,'-'
         DB     0EDH,08H
         DB     0D0H,82H,0D1H,'q',0D2H,'w',0D3H,'e'
         DB     0D4H,'r',0D5H,'t',0D6H,'y',0D7H,'u'
         DB     0D8H,'i',0D9H,'o',0DAH,'p',0DBH,'='
         DB     0DCH,80H,0DDH,81H
         DB     0B1H,83H,0B2H,'a',0B3H,'s',0B4H,'d'
         DB     0B5H,'f',0B6H,'g',0B7H,'h',0B8H,'j'
         DB     0B9H,'k',0BAH,'l',0BBH,';',0BCH,"'"
         DB     0BDH,0DH
         DB     071H,84H,072H,'z',073H,'x',074H,'c'
         DB     075H,'v',076H,'b',077H,'n',078H,'m'
         DB     079H,',',07AH,'.',07BH,'/',07DH,' '

GKEYX2:  DB     '1','!','2','@','3','#','4','$'
         DB     '5','%','6','^','7','&','8','*'
         DB     '9','(','0',')','-','+','=','`'
         DB     ';',':',"'",'"',',','<','.','>'
         DB     '/','?'

GKEYX3:  DB     1BH,82H,83H,84H
         DB     08H,80H,81H,0DH
         DB     20H

GKEYSH:  CJNE   A,#'a',$+3        ;**** SHIFT TABLE CONVERT ****
         JC     GKEYSH5
         CJNE   A,#'z'+1,$+3
         JNC    GKEYSH5
         LCALL  UPPER             ;A-Z
         RET

GKEYSH5: MOV    R2,#17            ;SPECIAL 17 KEYS
         MOV    DPTR,#GKEYX2
         MOV    B,A
GKEYSH6: CLR    A
         MOVC   A,@A+DPTR
         CJNE   A,B,GKEYSH7
         INC    DPTR              ;IS 17 KEYS
         CLR    A
         MOVC   A,@A+DPTR
         RET
GKEYSH7: INC    DPTR              ;NEXT
         INC    DPTR
         DJNZ   R2,GKEYSH6
         MOV    A,B
         RET                      ;NOT 17 KEYS

GKEYFN:  CJNE   A,#'a',$+3        ;**** FUNCTION KEY CONVERT ****
         JC     GKEYFN2
         CJNE   A,#'z'+1,$+3
         JNC    GKEYFN2
         LCALL  UPPER             ;CHANGE a-z TO A-Z

GKEYFN2: CJNE   A,#'A',$+3
         JC     GKEYFN8
         CJNE   A,#'Z'+1,$+3
         JNC    GKEYFN8
         CLR    C                 ;IS FUNCTION KEY (CTRL-CODE)
         SUBB   A,#64
         CLR    FUNFAG            ;AUTO CLEAR FUNCTION MODE
         SETB   LEDRED
         RET

GKEYFN8: MOV    A,#84H            ;NOT A-Z
         RET

GKEYBP:  MOV    B,A               ;**** CHECK BEEP ****
         MOV    R2,#9
         MOV    DPTR,#GKEYX3
GKEYBP2: CLR    A
         MOVC   A,@A+DPTR
         CJNE   A,B,GKEYBP4
         LCALL  YBEEP             ;YELLOW KEYS BEEP
         MOV    A,B
         RET
GKEYBP4: INC    DPTR
         DJNZ   R2,GKEYBP2
         LCALL  KBEEP             ;ANY KEYS BEEP
         MOV    A,B
         RET

; ********** GKEYX SUB **********
; GET KEY & WAIT
; OUT = A ASCII KEY CODE
; REG = A,B,R2,R3,R4,R5,R6,DPTR

GKEYX:   LCALL  GKEY
         JNB    GKEYOK,GKEYX
         RET

; ********** UPPER SUB **********
; CHANGE LOWER CHAR. TO UPPER CHAR.
; IN  = A
; OUT = A
; REG = A

UPPER:   CJNE   A,#61H,$+3
         JNC    UPPER1
         RET                      ;UNDER
UPPER1:  CJNE   A,#7BH,$+3
         JC     UPPER2
         RET                      ;OVER
UPPER2:  SUBB   A,#31
         RET                      ;IS LOWER

; ********** PBYTE SUB **********
; PRINT ONE BYTE
; IN  = A (ASCII)
; REG = A

PBYTE:   JB     PRTBSY,$          ;BUSY WAIT
         LCALL  WPORTA
         LCALL  PBYTED            ;DELAY
         CLR    PRTSTB            ;STB LOW
         LCALL  PBYTED
         SETB   PRTSTB            ;STB HIGH
         RET

PBYTED:  MOV    A,#80H            ;DELAY SUB
PBYTED1: DEC    A
         JNZ    PBYTED1
         RET

; ********** PBYTEH SUB **********
; PRINT 2 BYTE HEX FROM A
; IN  = A
; REG = A,R2,R3

PBYTEH:  LCALL  HTOA
         MOV    A,R2
         LCALL  PBYTE
         MOV    A,R3
         LCALL  PBYTE
         RET

; ********** PBYTEW SUB **********
; PRINT 4 BYTE FROM DPTR
; IN  = DPTR
; REG = A,R2,R3

PBYTEW:  MOV    A,DPH
         LCALL  PBYTEH
         MOV    A,DPL
         LCALL  PBYTEH
         RET

; ********** PBLOCK SUB **********
; PRINT BLOCK
; IN  = DPTR ROM-ADDRESS (END BY 0 OR 0DH)
; OUT = DPTR (NEXT)
; REG = A,DPTR

PBLOCK:  CLR    A
         MOVC   A,@A+DPTR
         CJNE   A,#0,PBLOCK1
         INC    DPTR              ;NEXT ADDRESS
         RET                      ;EXIT BY 0
PBLOCK1: CJNE   A,#0DH,PBLOCK2
         LCALL  PLF               ;CR/LF
         INC    DPTR              ;NEXT ADDRESS
         RET                      ;EXIT BY ODH
PBLOCK2: LCALL  PBYTE
         INC    DPTR
         SJMP   PBLOCK

; ********** PBLANK SUB **********
; PRINT BLANK
; IN  = R2 (NO OF BLANK)
; REG = A,R2

PBLANK:  MOV    A,#' '
         LCALL  PBYTE
         DJNZ   R2,PBLANK
         RET

; ********** PLF SUB **********
; PRINT CR/LF
; REG = A

PLF:     MOV    A,#0DH
         LCALL  PBYTE
         MOV    A,#0AH
         LCALL  PBYTE
         RET

; ********** Pxxx SUB **********

P1B:     MOV    A,#' '
         LCALL  PBYTE
         RET

; ********** RTCRD SUB **********
; OUT = RTCBUF
; REG = A,R0,R1,R2,DPTR

RTCRD:   MOV    A,MCON
         SETB   ACC.2
         MOV    MCON,A
         MOVX   A,@DPTR           ;RESET POINTER

         LCALL  RTCPAT
         MOV    DPH,#00000000B
         MOV    DPL,#00000100B
         MOV    R0,#RTCBUF
         MOV    R1,#8
RTCRD2:  LCALL  RTCG
         MOV    @R0,A
         INC    R0
         DJNZ   R1,RTCRD2

         MOV    A,MCON
         CLR    ACC.2
         MOV    MCON,A
         RET

RTCPAT:  MOV    DPH,#00000000B    ;**** WRITE PATTERN ****
         MOV    DPL,#00000000B
         MOV    A,#0C5H
         LCALL  RTCP
         MOV    A,#03AH
         LCALL  RTCP
         MOV    A,#0A3H
         LCALL  RTCP
         MOV    A,#05CH
         LCALL  RTCP
         MOV    A,#0C5H
         LCALL  RTCP
         MOV    A,#03AH
         LCALL  RTCP
         MOV    A,#0A3H
         LCALL  RTCP
         MOV    A,#05CH
         LCALL  RTCP
         RET

RTCP:    MOV    R2,#8             ;**** WRITE BYTE (IN=A,DPTR) ****
RTCP2:   RRC    A
         PUSH   ACC               ;--\
         MOV    A,DPL
         MOV    ACC.0,C
         MOV    DPL,A
         CLR    A
         MOVX   @DPTR,A
         POP    ACC               ;--/
         DJNZ   R2,RTCP2
         RET

RTCG:    MOV    R2,#8             ;**** READ BYTE (OUT=A) ****
RTCG2:   PUSH   ACC
         MOVX   A,@DPTR
         MOV    C,ACC.7
         POP    ACC
         RRC    A
         DJNZ   R2,RTCG2
         RET

; ********** RTCWR SUB **********
; IN  = RTCBUF
; REG = A,R0,R1,R2,DPTR

RTCWR:   MOV    A,MCON
         SETB   ACC.2
         MOV    MCON,A
         MOVX   A,@DPTR           ;RESET POINTER

         LCALL  RTCPAT
         MOV    DPH,#00000000B
         MOV    DPL,#00000000B
         MOV    R0,#RTCBUF
         MOV    R1,#8
RTCWR2:  MOV    A,@R0
         LCALL  RTCP
         INC    R0
         DJNZ   R1,RTCWR2

         MOV    A,MCON
         CLR    ACC.2
         MOV    MCON,A
         RET

; ********** DMSEC SUB **********
; DELAY 1/1000 SECOND
; IN  = R2,R3
; REG = A,R2,R3,R4

DMSEC:   MOV    R4,#230         ;1 MSEC LOOP
DMSEC1:  NOP
         NOP
         DJNZ   R4,DMSEC1
         DJNZ   R3,DMSEC
         MOV    A,R2
         CJNE   A,#0,DMSEC2
         RET
DMSEC2:  DEC    R2
         SJMP   DMSEC

         END

