Metropoli BBS
VIEWER: clock2.asm MODE: TEXT (CP437)
INCLUDE Clock2.Hd
;╒══════════════════════════════════════════════════════════════════════════╕
;│                              System Clock				    │
;│  This program shows the RTC.  It reads the RTC with a polling	    │ 
;│  approach.								    │
;╘══════════════════════════════════════════════════════════════════════════╛
COMSEG SEGMENT BYTE PUBLIC
	ASSUME	CS:COMSEG, DS:COMSEG, ES:COMSEG, SS:COMSEG
	ORG	100H
;────────────────────────────────────────────────────────────────────────────
ComStart:	jmp	RealStart	
;╒══════════════════════════════════════════════════════════════════════════╕
;│                                VARIABLES				    │
;╘══════════════════════════════════════════════════════════════════════════╛
CurrentSeconds	db	00		; Seconds in BCD
CurrentMinutes	db	00		; Minutes in BCD
CurrentHours	db	00		; Hours in BCD

PreviousSeconds	db	00

StatusA		db	00
UpdateScreen	db	FALSE
;╒══════════════════════════════════════════════════════════════════════════╕
;│                                  CODE				    │
;╘══════════════════════════════════════════════════════════════════════════╛
RealStart:	Call	BlastUserMessage	; Display user message
		Call	InstallRTCInterruptHandler ; Install our INT 70h
						; handler to catch clock
						; update interrupts
		Call	EnableRTCUpdateInts	; Allow RTC system interrupts
;--------------------------------------------------------------------------
DisplayTime:	Call	DisplayCurrentTime	; Blast the time onto the
						; template
		Call	CheckForTermination	; Check for ESC character
		jnc	DisplayTime		; If we didn't terminate, do
						; it again.
;--------------------------------------------------------------------------
Goodbye:	Call	DisableRTCUpdateInts	; Disable RTC system interrupts
		Call	RemoveRTCInterruptHandler ; Remove our INT 70h
						; handler
		Call	ClearScreen		; Clear off the clock
		mov	ah, EXE_TERMINATE	; Exit back to DOS
		int	DOS_FUNCTION


;╒══════════════════════════════════════════════════════════════════════════╕
;│                               SUBROUTINES				    │
;╘══════════════════════════════════════════════════════════════════════════╛
;┌──────────────────────────────────────────────────────────────────────────┐
;│                              Clear Screen				    │
;│  This routine will clear the screen by writing spaces to every	    │ 
;│  location.								    │
;│  Call With    :       Nothing					    │
;│  Alters       :       AX, BX, CX, DX					    │
;│  Returns      :       Nothing					    │
;│  Calls        :       SetCursorLoc					    │
;└──────────────────────────────────────────────────────────────────────────┘
ClearScreen:	xor	dx, dx				; Move cursor to the
		Call	SetCursorLoc			; top of the screen
;--------------------------------------------------------------------------
		mov	al, SPACE_CHARACTER		; Fill the screen
		xor	bh, bh				; with bright white
		mov	bl, BR_WHT_ON_BLK		; on black spaces
		mov	cx, ONE_SCREEN_OF_CHARS
		mov	ah, WRITE_CHAR_AND_ATTRIB
		int	VIDEO_IO		
		ret					
;┌──────────────────────────────────────────────────────────────────────────┐
;│                          Blast Clock Template			    │
;│  This routine will write the clock template to the screen.		    │
;│  Call With    :       Nothing					    │
;│  Alters       :       AX, DX						    │
;│  Returns      :       Nothing					    │
;│  Calls        :       ClearScreen					    │
;└──────────────────────────────────────────────────────────────────────────┘
BlastClockTemplate:
		Call	ClearScreen		; Clear screen and move
						; cursor to top of screen
;--------------------------------------------------------------------------
		mov	dx, OFFSET ClockTemplate ; Use DOS to write clock
		mov	ah, DOS_PRINTSTRING	; onto screen
		int	DOS_FUNCTION
		ret
;┌──────────────────────────────────────────────────────────────────────────┐
;│                          Blast User Message				    │
;│  This routine will write the user message onto the screen and wait	    │ 
;│  for a keystroke.							    │
;│  Call With    :       Nothing					    │
;│  Alters       :       AX, DX						    │
;│  Returns      :       Nothing					    │
;│  Calls        :       ClearScreen					    │
;└──────────────────────────────────────────────────────────────────────────┘
BlastUserMessage:
		Call	ClearScreen		; Clear screen and move
						; cursor to top of screen
;--------------------------------------------------------------------------
		mov	dx, OFFSET ClockMessage ; Use DOS to write clock
		mov	ah, DOS_PRINTSTRING	; message onto screen
		int	DOS_FUNCTION
		Call	WaitForKeystroke
		ret
;┌──────────────────────────────────────────────────────────────────────────┐
;│                          Check For Termination			    │
;│  This routine checks to see if the ESC key was hit.  If it wasn't, we    │ 
;│  leave.								    │
;│  Call With    :       Nothing					    │
;│  Alters       :       AX						    │
;│  Returns      :       CY set if termination set			    │
;│  Calls        :       CheckForKeystroke				    │
;│                       WaitForKeystroke				    │
;└──────────────────────────────────────────────────────────────────────────┘
CheckForTermination:
		Call	CheckForKeystroke
		clc
		jz	FinishedTerminationCheck
		Call	WaitForKeystroke
		cmp	ah, ESC_SCAN_CODE
		jne	CheckForTermination
		stc
FinishedTerminationCheck:
		ret

;┌──────────────────────────────────────────────────────────────────────────┐
;│                             Get RTC Reading				    │
;│  This routine is responsible for reading the seconds, minutes, and	    │ 
;│  hours from the RTC.							    │
;│  Call With    :       DS pointing to data				    │
;│  Alters       :       AX, DI						    │
;│  Returns      :       Hours:Minutes:Seconds in data region		    │
;│  Calls        :       ReadCMOSByte					    │
;└──────────────────────────────────────────────────────────────────────────┘
GetRTCReading:	push	ds			; Save current data seg
		push	cs			; Then make it point to
		pop	ds			; the current segment
		mov	di, OFFSET CurrentSeconds ; Point destination pointer
						; to data area
;──────────────────────────────────────────────────────────────────────────
		cli				; Turn off system interrupts
;--------------------------------------------------------------------------
		mov	al, RTC_SECONDS 	; Read in current RTC
		Call	ReadCMOSByte		; seconds and store it
		stosb				; to a local variable
;--------------------------------------------------------------------------
		mov	al, RTC_MINUTES 	; Read in current RTC
		Call	ReadCMOSByte		; minutes and store it to
		stosb				; a local variable
;--------------------------------------------------------------------------
		mov	al, RTC_HOURS 		; Read in current RTC
		Call	ReadCMOSByte		; hours and store it to
		stosb				; a local variable
;--------------------------------------------------------------------------
		sti				; Restore system interrupts
		pop	ds			; Restore data segment
		ret				; Return to caller

;┌──────────────────────────────────────────────────────────────────────────┐
;│                          Display Current Time			    │
;│  This routine will convert the BCD time to text and blast it onto the    │ 
;│  screen.								    │
;│  Call With    :       New Time in data region			    │
;│  Alters       :       AX, DI						    │
;│  Returns      :       Nothing					    │
;│  Calls        :       ConvertByteToText				    │
;└──────────────────────────────────────────────────────────────────────────┘
DisplayCurrentTime:
		cmp	UpdateScreen, TRUE
		jne	FinishedScreenUpdate	
		mov	UpdateScreen, FALSE
;--------------------------------------------------------------------------
		xor	ah, ah				; Convert the seconds
		mov	al, CurrentSeconds		; into text format
		mov	di, OFFSET SecondsText		; and place into the
		Call	ConvertByteToText		; clock template
;--------------------------------------------------------------------------
		xor	ah, ah				; Now convert the
		mov	al, CurrentMinutes		; minutes
		mov	di, OFFSET MinutesText
		Call	ConvertByteToText
;--------------------------------------------------------------------------
		xor	ah, ah				; Now convert the
		mov	al, CurrentHours		; hours
		mov	di, OFFSET HoursText
		Call	ConvertByteToText
;--------------------------------------------------------------------------
		mov	dx, OFFSET ClockTemplate	; Copy the entire
		mov	ah, DOS_PRINTSTRING		; clock onto the
		Call	BlastClockTemplate		; screen
FinishedScreenUpdate:
		ret

;┌──────────────────────────────────────────────────────────────────────────┐
;│                          Convert Byte To Text			    │
;│  This routine will take a two digit BCD number and store it to the	    │ 
;│  location pointed to by DI.						    │
;│  Call With    :       AL = BCD number				    │
;│                       DI pointing to location to write text		    │
;│  Alters       :       AX, BX, DI					    │
;│  Returns      :       Nothing					    │
;│  Calls        :       Nothing					    │
;└──────────────────────────────────────────────────────────────────────────┘
ConvertByteToText:
		mov	bl, 16 			; Divide by 16 since it's
		div	bl			; BCD and not binary
		add	ah, NUMBER_ZERO		; AH will have lower digit
		mov	[di], ah		; Add Character 0 and store
		dec	di			; Point to next digit
		add	al, NUMBER_ZERO		; AL will have upper digit
		mov	[di], al		; Add character 0 and store
		ret

;┌──────────────────────────────────────────────────────────────────────────┐
;│                           Set Cursor Location			    │
;│  This routine will set the cursor position to the value in DX	    │
;│  Call With    :       DX = New Cursor Position			    │
;│  Returns      :       Nothing					    │
;│  Alters       :       AX, BX, DX					    │
;│  Calls        :       Nothing					    │
;└──────────────────────────────────────────────────────────────────────────┘
SetCursorLoc:	mov	ah, SET_CURSOR_POSITION
		xor	bh, bh
		int	VIDEO_IO
		ret
;┌──────────────────────────────────────────────────────────────────────────┐
;│                           Check For Keystroke			    │
;│  This routine will check to see if there are any keystrokes waiting	    │ 
;│  in the keyboard buffer.						    │
;│  Call With    :       Nothing					    │
;│  Alters       :       AX						    │
;│  Returns      :       NZ if key is waiting				    │
;│  Calls        :       Nothing					    │
;└──────────────────────────────────────────────────────────────────────────┘
CheckForKeystroke:
		mov	ah, NO_WAIT_FOR_KEY 
		int	KEYBOARD_IO
		ret
;┌──────────────────────────────────────────────────────────────────────────┐
;│                           Wait For Keystroke				    │
;│  This routine will wait until a key is in the buffer.		    │
;│  Call With    :       Nothing					    │
;│  Alters       :       AX						    │
;│  Returns      :       Nothing					    │
;│  Calls        :       Nothing					    │
;└──────────────────────────────────────────────────────────────────────────┘
WaitForKeystroke:
		mov	ah, WAIT_FOR_KEYSTROKE
		int	KEYBOARD_IO
		ret 
;╒══════════════════════════════════════════════════════════════════════════╕
;│                              INCLUDE FILES				    │
;╘══════════════════════════════════════════════════════════════════════════╛
INCLUDE PcMag2.Asm
;╒══════════════════════════════════════════════════════════════════════════╕
;│                         DATA, SCREENS, BUFFERS			    │
;╘══════════════════════════════════════════════════════════════════════════╛
CLOCK_WIDTH	equ	12
CLOCK_LENGTH	equ	03
ClockTemplate:
db"╔══ TIME ══╗",CR, LF
db"║ 0"
HoursText:
db"0:0"
MinutesText:
db"0:0"
SecondsText:
db"0 ║", CR, LF
db"╚══════════╝", "$"
;--------------------------------------------------------------------------
ClockMessage:
db"█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█"
db"█                                                                              █"
db"█                                   Clock 2                                    █"
db"█                                                                              █"
db"█                                                                              █"
db"█  This short program will display an Hour:Minute:Second clock in the upper    █"
db"█  left hand corner of the screen.  The current time is acquired from the      █"
db"█  CMOS Real Time Clock.  In this particular program, the time is checked      █"
db"█  after each RTC update interrupt.  This will result in the time being        █"
db"█  updated once a second.  After each interrupt, the program will read in      █"
db"█  the current time and set a flag indicating the time has changed.  The       █"
db"█  main loop simply waits for this flag to change.  As soon as the time has    █"
db"█  been altered, the main loop will drop into the routines to display the      █"
db"█  clock.  By writing faster code to display the clock and moving that code    █"
db"█  into the interrupt handler, a clock can be displayed while other code is    █"
db"█  running.  This example uses that extra processing power in a useless loop,  █"
db"█  but with a little thought, this time can be put to better use.              █"
db"█                                                                              █"
db"█                                                                              █"
db"█  In order to return to DOS, press the ESC key.                               █"
db"█                                                                              █"
db"█                                                                              █"
db"█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█"
db"                                                                                "
db"                             Press Any Key To Begin                            ","$"


;────────────────────────────────────────────────────────────────────────────
COMSEG	ENDS
	END	ComStart


[ RETURN TO DIRECTORY ]