A8255 EQU 0640H

B8255 EQU 0642H

C8255 EQU 0644H

CON8255 EQU 0646H

C008254 EQU 0600H

C018254 EQU 0602H

C028254 EQU 0604H

CON8254 EQU 0606H

SSEG SEGMENT STACK

DW 20 DUP(?)

SSEG ENDS

DATA SEGMENT

TBL:

DB 3FH ;; 0

DB 06H ;; 1

DB 5BH ;; 2

DB 4FH ;; 3

DB 66H ;; 4

DB 6DH ;; 5

DB 7DH ;; 6

DB 07H ;; 7

DB 7FH ;; 8

DB 6FH ;; 9

DB 77H ;; A

DB 7CH ;; B

DB 39H ;; C

DB 5EH ;; D

DB 79H ;; E

DB 71H ;; F

DB 00H ;; CLR

SEQ:

DB 00011111B ;; POS 0

DB 00101111B ;; POS 1

DB 00110111B ;; POS 2

DB 00111011B ;; POS 3

DB 00111101B ;; POS 4

DB 00111110B ;; POS 5

CNT_STARTED DB 00H

CNT_PAUSED DB 00H

VAL_MIN:

DB 2 DUP(10H)

VAL_SEC:

DB 2 DUP(0)

MIR_COUNTER DB 00H

DATA ENDS

CODE SEGMENT

ASSUME CS:CODE, DS:DATA

START PROC

MOV AX, 0

MOV DS, AX

;; INIT 8255

MOV AL, 81H ;;10001001B ;; A B OUT, C IN

MOV DX, CON8255

OUT DX, AL

;; MIR6

MOV AX, OFFSET MIR6

MOV SI, 38H

MOV [SI], AX

MOV AX, CS

MOV SI, 3AH

MOV [SI], AX

;; --------------------------------------------------

;; INIT 8259

CLI

MOV AL, 11H

OUT 20H, AL

MOV AL, 08H

OUT 21H, AL

MOV AL, 04H

OUT 21H, AL

MOV AL, 07H

OUT 21H, AL

MOV AL, 2FH

OUT 21H, AL

STI

;; --------------------------------------------------

;; --------------------------------------------------

;; INIT 8254

MOV AL, 00110110B

MOV DX, CON8254

OUT DX, AL

MOV DX, C008254

MOV AL, 24H ;; LOWER 8 BYTES

OUT DX, AL

MOV AL, 0F4H ;; HIGHER 8 BYTES

OUT DX, AL

;; --------------------------------------------------

MOV AX, DATA

MOV DS, AX

LO:

CALL NUM_DISPLAY

CALL SCAN

CMP AX, 10H

JE LO

CMP AX, 0AH ;; PRESS A TO START/STOP

JNE LO_NB

;;;;;;

CMP CNT_STARTED, 00H

JE COUNTER_START

;; COUNTER_STOP

MOV CNT_STARTED, 0

CALL CLR_TIME

LEA BX, VAL_MIN

MOV [BX], 1010H

JMP WAIT_UP

COUNTER_START:

MOV CNT_STARTED, 1

MOV CNT_PAUSED, 0

JMP WAIT_UP

;;;;;;

LO_NB:

CMP AX, 0BH ;; PRESS B TO PAUSE/RESUME

JNE LO_NC

XOR CNT_PAUSED, 1

JMP WAIT_UP

LO_NC:

CMP AX, 0CH ;; PRESS C TO EXIT

JE MA_EXIT

CMP AX, 0AH

JGE WAIT_UP

CALL MIN_SET

WAIT_UP:

CALL NUM_DISPLAY

CALL KEY_PRESSED

CMP AX, 1

JE WAIT_UP

JMP LO

MA_EXIT:

MOV AX, 1000H

CALL PUT

MOV AX, 4C00H

INT 21H

START ENDP

MIN_SET PROC

CMP CNT_STARTED, 1

JE MS_EXIT

LEA BX, VAL_MIN

MOV AH, [BX]

CMP AH, 10H

JE MS_SW

MOV AH, [BX+1]

CMP AH, 10H

JE MS_GW

JMP MS_EXIT

MS_SW:

MOV [BX], AL

JMP MS_EXIT

MS_GW:

MOV [BX+1], AL

MS_EXIT:

RET

MIN_SET ENDP

TIMER_RESET PROC

MOV CNT_STARTED, 0

CALL CLR_TIME

MOV CX, 3

TR_LO:

PUSH CX

CALL ZERO_BLINK

CALL DELAY

CALL NUM_DISPLAY_CLS

CALL DELAY_LONG

POP CX

LOOP TR_LO

CALL CLR_TIME

RET

TIMER_RESET ENDP

CLR_TIME PROC

LEA BX, VAL_MIN

MOV AH, 10H

MOV [BX], AH

MOV [BX+1], AH

LEA BX, VAL_SEC

MOV AH, 00H

MOV [BX], AH

MOV [BX+1], AH

RET

CLR_TIME ENDP

ZERO_BLINK PROC

PUSH CX

MOV CX, 0FFH

ZB:

PUSH CX

MOV AX, 0005H

CALL PUT

CALL DELAY

MOV AX, 0004H

CALL PUT

CALL DELAY

MOV AX, 0003H

CALL PUT

CALL DELAY

MOV AX, 0002H

CALL PUT

CALL DELAY

POP CX

LOOP ZB

POP CX

RET

ZERO_BLINK ENDP

NUM_DISPLAY PROC

CMP CNT_STARTED, 1

JE ND_TIMER

;; INPUT MODE

LEA BX, VAL_MIN

MOV SI, 0

MOV AH, [BX+SI]

MOV AL, 03H

CALL PUT

CALL DELAY

LEA BX, VAL_MIN

MOV SI, 0

MOV AH, [BX+SI+1]

MOV AL, 02H

CALL PUT

CALL DELAY

RET

ND_TIMER:

;; TIMER MODE

LEA BX, VAL_MIN

MOV SI, 0

MOV AH, [BX+SI]

MOV AL, 05H

CALL PUT

CALL DELAY

LEA BX, VAL_MIN

MOV SI, 0

MOV AH, [BX+SI+1]

MOV AL, 04H

CALL PUT

CALL DELAY

LEA BX, VAL_SEC

MOV SI, 0

MOV AH, [BX+SI]

MOV AL, 03H

CALL PUT

CALL DELAY

LEA BX, VAL_SEC

MOV SI, 0

MOV AH, [BX+SI+1]

MOV AL, 02H

CALL PUT

CALL DELAY

RET

NUM_DISPLAY ENDP

NUM_DISPLAY_CLS PROC

MOV CX, 5

ND_CLS:

MOV AH, 10H

MOV AL, AL

CALL PUT

LOOP ND_CLS

RET

NUM_DISPLAY_CLS ENDP

;; DECREASE SECOND & MIN WHEN NECESSARY

DEC_SEC PROC

CMP CNT_STARTED, 0 ;; NOT STARTED

JE DEC_EXIT

CMP CNT_PAUSED, 1 ;; PAUSED

JE DEC_EXIT

LEA BX, VAL_SEC

MOV AH, [BX+1]

CMP AH, 0

JE DS_JW_S

DEC AH

MOV [BX+1], AH

JMP DEC_EXIT

DS_JW_S:

MOV AH, 9

MOV [BX+1], AH

MOV AH, [BX]

CMP AH, 0

JE DS_JW_MG

DEC AH

MOV [BX], AH

JMP DEC_EXIT

DS_JW_MG:

MOV AH, 5

MOV [BX], AH

LEA BX, VAL_MIN

MOV AH, [BX+1]

CMP AH, 0

JE DS_JW_MS

DEC AH

MOV [BX+1], AH

JMP DEC_EXIT

DS_JW_MS:

MOV AH, 9

MOV [BX+1], AH

MOV AH, [BX]

CMP AH, 0

JE DS_FIN

DEC AH

MOV [BX], AH

JMP DEC_EXIT

DS_FIN:

CALL TIMER_RESET

DEC_EXIT:

RET

DEC_SEC ENDP

MIR6 PROC

STI

INC MIR_COUNTER

CMP MIR_COUNTER, 10H

JNE MIR6_FIN

MOV MIR_COUNTER, 0

CALL DEC_SEC

MIR6_FIN:

IRET

MIR6 ENDP

SCAN PROC

BEGIN:

CALL KEY_PRESSED ;; EXIT IF NOT PRESSED

CMP AX, 0

JE SCAN_NO_KEY

CALL DELAY

CALL KEY_PRESSED

CMP AX, 0

JE SCAN_NO_KEY

MOV CH, 0FEH

MOV CL, 0

COLUMN:

MOV AL, CH

MOV DX, A8255

OUT DX, AL

MOV DX, C8255

IN AL, DX

L1:

TEST AL, 1

JNZ L2

MOV AL, 00H

JMP KCODE

L2:

TEST AL, 2

JNZ L3

MOV AL, 04H

JMP KCODE

L3:

TEST AL, 4

JNZ L4

MOV AL, 08H

JMP KCODE

L4:

TEST AL, 8

JNZ NEXT

MOV AL, 0CH

KCODE:

ADD AL, CL

JMP SCAN_FIN

NEXT:

INC CL

MOV AL, CH

TEST AL, 08H

JE SCAN_NO_KEY

ROL AL, 1

MOV CH, AL

JMP COLUMN

SCAN_NO_KEY:

MOV AX, 10H

SCAN_FIN:

RET

SCAN ENDP

;; RETURN WHETHER KEY PRESSED IN AX

KEY_PRESSED PROC

MOV DX, A8255

MOV AL, 00H

OUT DX, AL ;; LINE OUTPUT 0000

MOV DX, C8255

IN AL, DX ;; GET LINE STATUS

AND AL, 0FH

CMP AL, 0FH

JE KP_NONE

MOV AX, 1 ;; KEY PRESSED

RET

KP_NONE:

MOV AX, 0

RET

KEY_PRESSED ENDP

;; NUM: AH

;; POS: AL

PUT PROC

PUSH AX

;; SELECT POS

LEA BX, SEQ

PUSH AX

MOV AH, 0

MOV SI, AX

;; OUTPUT POS

MOV DX, A8255

MOV AL, [BX+SI]

OUT DX, AL

POP AX

;; SELECT NUM

LEA BX, TBL

MOV AL, AH

MOV AH, 0

MOV SI, AX

;; OUTPUT DATA

MOV DX, B8255

MOV AL, [BX+SI]

OUT DX, AL

POP AX

RET

PUT ENDP

DELAY PROC

MOV CX, 0FFH

LOOP $

RET

DELAY ENDP

DELAY_LONG PROC

MOV CX, 0FFFFH

LOOP $

RET

DELAY_LONG ENDP

CODE ENDS

END START