TITLE DS1616E MS-DOS INTERFACE PROGRAM PAGE 44,132 ;************************************************************ ; DSCLOCK.ASM 09/05/86 ;************************************************************ ;** Copyright (c) 1986 FBE Research Company, Incorporated ** ;** P.O. Box 68234, Seattle, WA 98168 ** ;************************************************************ ;** This program is yours. There is no license agreement. ** ;** However, the program is copyrighted and you may not ** ;** sell exact copies of it for profit. You may modify ** ;** the program and sell the result as long as you include ** ;** our copyright notice (above). ** ;************************************************************ ; DSCLOCK for MS-DOS ; ; This program is "generic" MS-DOS so that it will run on as ; many machines as possible. It assumes that a Dallas Semi- ; conductor DS1216E SmartWatch is installed in an EPROM/ROM ; socket addressible at FFFF:0000. This address is in the ; monitor program of most computers. ; ; INVOCATION: ACTION: ; ---------------------------------------------------------- ; DSCLOCK Read the SmartWatch and set ; the MS-DOS time and date. ; ; DSCLOCK MM DD YY hh mm ss Set the SmartWatch to the ; date and time given on the ; command line. ; ; DSCLOCK DST Make a Daylight Savings Time ; adjustment. ; ; For detailed operating instructions, list the DSCLOCK.HLP ; file. If this file is on the same disk and in the same ; directory as the program, it will be read and displayed ; if too few digits are supplied when setting the SmartWatch. ; The file is not necessary for the operation of the program ; and may be deleted to save space. ; ;************************************************************ ; ASSEMBLY INSTRUCTIONS ;************************************************************ ; ; MASM DSCLOCK; ; LINK DSCLOCK; ; EXE2BIN DSCLOCK.EXE DSCLOCK.COM ; ERASE DSCLOCK.EXE ; ERASE DSCLOCK.OBJ ; ;************************************************************ ; DEFINITIONS ;************************************************************ ; BEL EQU 7 ;ASCII CHARACTERS LF EQU 10 CR EQU 13 ; BASE EQU 0FFFFH ;EPROM Base Paragraph ; READ EQU 4 ;Magic Offsets WR0 EQU 0 WR1 EQU 1 ; ;************************************************************ ; MAIN LINE ;************************************************************ ; SSEG SEGMENT STACK SSEG ENDS ; CSEG SEGMENT ASSUME CS:CSEG, SS:CSEG, DS:CSEG, ES:NOTHING ; ORG 100H DSCLOCK: CALL SETTIM ;If Command, Set SmartWatch ; CALL RDCLK ;Read SmartWatch Registers ; CALL SMDTIM ;Set MSDOS Time ; CMP AL,255 ;Error? JZ ERRXIT ;Branch If Not ; CALL SMDDAT ;Set MSDOS Date ; CMP AL,255 ;Error? JNZ DATOK ;Branch If Not ; ERRXIT: MOV DX,OFFSET TDEMSG ;Issue Error Message CALL TYPTX ; DATOK: CALL SHOTIM ;Show Date and Time ; MOV AH,0 ;Exit to MSDOS INT 21H ; ; TDEMSG: DB BEL,CR,LF DB 'Could not set MS-DOS DATE and/or TIME.' DB ' Reset the SmartWatch Date and Time.' DB CR,LF DB '$' ; ;************************************************************ ; SET TIME SUBROUTINE ;************************************************************ ; SETTIM - ; If command line not there, exit. Else, process the line. ; If too few digits, show error message and exit to system. ; SETTIM: MOV SI,OFFSET 80H ;Point at Command Line Count MOV BL,[SI] ;Get Count Byte OR BL,BL ;Set Flags JNZ STNEXT ;Skip If Line Present ; RET ;Else, Exit ; STNEXT: INC SI ;Bump Pointer SKSPLP: MOV AL,[SI] ;Skip Leading Spaces CMP AL,' ' JNZ NOTSPC ;Exit If Not a Space ; INC SI ;Bump Pointer DEC BL ;Done All Of Line? JNZ SKSPLP ;Loop If Not ; JMP STMERR ;Else, Is Error ; NOTSPC: CMP AL,'D' ;Daylight Savings Time Command? JZ DODSTX ;Branch If So ; CMP AL,'d' ;Lower Case? JNZ DOLINE ;Branch If Not ; DODSTX: JMP DODST ;Else, Process Command ; ;************************************************************ ; DOLINE - ; Process command line by transferring only digits to digit ; buffer. Less than 12 digits is an error. ; DOLINE: MOV DI,OFFSET DGTBUF ;Setup Output Pointer MOV CL,12 ;Digit Count SCLOOP: LODSB ;Get Character CMP AL,'0' ;Less Than Zero? JL NEXT ;TRY NEXT IF SO ; CMP AL,'9' ;Greater Then Nine? JG NEXT ;Try Next If So ; STOSB ;Else, Buffer the Digit DEC CL ;Done Twelve Digits? JZ DODGTS ;Exit If So ; NEXT: DEC BL ;Done All of Command Line? JNZ SCLOOP ;Loop If Not ; JMP STMERR ;Entry Error If Get Here ; ;************************************************************ ; DODGTS - ; Process contents of digit buffer and set the SmartWatch. ; DODGTS: MOV SI,OFFSET DGTBUF ;Point at Digit Buffer ; MOV DI,OFFSET MONTH CALL PUTDG ;Month ; CALL PUTDG ;Date ; MOV DI,OFFSET YEAR CALL PUTDG ;Year ; MOV DI,OFFSET HOURS CALL PUTDG ;Hours ; CALL PUTDG ;Minutes ; CALL PUTDG ;Seconds ; CALL SETDOW ;Compute Day-Of-Week ; MOV DX,OFFSET STMSG ;Prompt Operator CALL TYPTX ; MOV AH,1 ;Wait for Response INT 21H ; MOV DL,LF ;Clean Up Screen CALL TYPEC ; MOV BYTE PTR HS,0 ;Zero Tenths/Hundredths ; JMP WRCLK ;Set the SmartWatch ; STMSG: DB CR,LF DB 'Type [RETURN] to set the SmartWatch:' DB '$' ; ;************************************************************ ; DODST - ; Process daylight saving time command. Does not check for ; roll over or roll under conditions. ; DODST: CALL RDCLK ;Get the SmartWatch Data ; MOV SI,OFFSET MONTH ;Get Month CALL FIX ;Make Binary ; MOV SI,OFFSET HOURS ;Point at Hours CMP AL,7 ;July or Later? JGE FALL ;Branch if So ; SPRING: MOV AL,[SI] ;Get Hours ADD AL,1 ;Add One DAA ;Correct JMP WRHRS ;Set Hours Register ; FALL: MOV AL,[SI] ;Get Hours SUB AL,1 ;Subtract One DAS ;Correct ; WRHRS: MOV [SI],AL ;Restore Hours JMP WRCLK ;Set the SmartWatch ; ;************************************************************ ; STMERR - ; Error in command line. Read and display help file. ; STMERR: MOV DX,OFFSET STMMSG ;Show Error Message CALL TYPTX ; MOV DX,OFFSET HLPFCB ;Open Help File MOV AH,15 INT 21H ; CMP AL,255 ;Open Successful? JZ OPEXIT ;Branch If Not ; STE1: MOV DX,OFFSET HLPFCB ;Read File Record MOV AH,20 INT 21H ; CMP AL,1 ;End Of File? JZ STEXIT ;Branch If So ; MOV SI,80H ;Point at Default Buffer MOV CX,128 ;Byte Count STE2: LODSB ;Fetch Character MOV DL,AL CALL TYPEC ;Display the Character LOOP STE2 ;Loop If Not End Of Buffer ; JMP STE1 ;Do Next Record ; STEXIT: MOV DX,OFFSET HLPFCB ;Close the File MOV AH,16 INT 21H ; OPEXIT: MOV AH,0 ;Exit to System INT 21H ; STMMSG: DB BEL DB 'ENTRY ERROR' DB '$' ; HLPFCB DB 0,'DSCLOCK HLP' DB 0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0 ; ;************************************************************ ; SHOW TIME SUBROUTINE ;************************************************************ ; SHOTIM - ; Output date and time from buffer to console. ; SHOTIM: MOV DX,OFFSET MSG1 ;Preamble CALL TYPTX ; MOV SI,OFFSET MONTH CALL TYDGT ;Month ; MOV DL,'/' CALL TYPEC ; CALL TYDGT ;Date ; MOV DL,'/' CALL TYPEC ; MOV SI,OFFSET YEAR CALL TYDGT ;Year ; MOV AL,BYTE PTR DOW ;Day of Week CALL SHODOW ; MOV DX,OFFSET MSG2 ;Postamble CALL TYPTX ; MOV SI,OFFSET HOURS CALL TYDGT ;Hours ; MOV DL,':' CALL TYPEC ; CALL TYDGT ;Minutes ; MOV DL,':' CALL TYPEC ; CALL TYDGT ;Seconds ; MOV DL,'.' CALL TYPEC ; JMP TYDGT ;Tenths and Hundredths ; MSG1: DB CR,LF DB 'FBE SmartWatch Date ' DB '$' ; MSG2: DB ' Time ' DB '$' ; ;************************************************************ ; MINOR SUBROUTINES ;************************************************************ ; TYPTX - ; Output a string at DX to console. ; TYPTX: MOV AH,9 ;Activate System Call INT 21H RET ; ;************************************************************ ; TYPEC - ; Output the character in DL to console. ; TYPEC: MOV AH,2 ;Activate System Call INT 21H RET ; ;************************************************************ ; TYDGT - ; Output two digits pointed at by SI. ; TYDGT: PUSH SI MOV DL,[SI] ;Get Digits SHR DL,1 ;Do High Nibble SHR DL,1 SHR DL,1 SHR DL,1 ADD DL,'0' ;Make ASCII CALL TYPEC ;Output Character MOV DL,[SI] ;Get Digits AND DL,00001111B ;Do Low Nibble ADD DL,'0' ;Make ASCII CALL TYPEC ;Output Character POP SI DEC SI ;Move Pointer RET ; ;************************************************************ ; PUTDG - ; Store two digits from [SI] as packed BCD at [DI]. Return ; packed BCD in AL. ; PUTDG: MOV AH,[SI] ;Get High Order Digit SHL AH,1 SHL AH,1 SHL AH,1 SHL AH,1 INC SI MOV AL,[SI] ;Get Low Order Digit AND AL,00001111B OR AL,AH ;Pack MOV [DI],AL ;Put the Digits DEC DI ;Decrement Destination INC SI ;Increment Source RET ; ;************************************************************ ; SETDOW - ; Compute Day-Of-Week from Date, Month, and Year. This ; algorithm was supplied by Rich Mueller (PhD). ; SETDOW: MOV SI,OFFSET DATE ;Start With Date CALL FIXXL ;Convert to Binary ; CMP AL,80 ;Next Century? JGE NOCENT ;Branch If Not ; ADD AL,100 ;Else, Add to Year NOCENT: MOV AH,AL ;Year to AH MOV CH,AL ;And CH SUB AH,80 ;Years Since 1980 MOV CL,AH ;To CL SHR AH,1 ;Divide by 2 SHR AH,1 ;Divide by 4 AND AH,3FH ;Make Leap Year Count MOV BX,OFFSET LYTABL-1 ;Assume is Leap Year TEST CH,3 ;Test for Leap Year JZ ISLYR ;Branch If So ; INC AH ;Else, Adjust Year MOV BX,OFFSET NYTABL-1 ;And Use Normal Table ISLYR: MOV AL,DH ;Month to AL XLAT ;Access Table ADD AL,DL ;Add Day ADD AL,AH ;Add Leap Year Count ADD AL,CL ;Add Years Since 1980 ; RM7: SUB AL,7 ;Reduce Modulo 7 JNC RM7 ; ADD AL,7 JNZ NOTSAT ;Branch If Not Saturday ; MOV AL,7 ;Else, Is Saturday NOTSAT: ; DEC AL ;Correct the Value OR AL,00010000B ;Set Bit to Disable Reset MOV BYTE PTR DOW,AL ;Write to Buffer RET ; ; NYTABL DB 2,5,5,8,3,6 ;For Normal Year DB 8,4,7,2,5,7 ; LYTABL DB 2,5,6,2,4,7 ;For Leap Year DB 2,5,8,3,6,8 ; ;************************************************************ ; SHODOW - ; Display day of week. On entry, AL contains day number. ; SHODOW: MOV BX,OFFSET DOWNDX ;Point to Address Table AND AL,00000111B ;Mask off for Safety ADD AL,AL ;Double the Index MOV AH,0 MOV SI,AX ;Index to Pointer Register MOV DX,[BX][SI] ;Fetch String Address JMP TYPTX ;Display String ; DOWNDX: DW OFFSET ERROR ;String Address Table DW OFFSET D1MSG DW OFFSET D2MSG DW OFFSET D3MSG DW OFFSET D4MSG DW OFFSET D5MSG DW OFFSET D6MSG DW OFFSET D7MSG ; ERROR DB ' >> No SmartWatch <<$' D1MSG: DB ' Sunday$' D2MSG: DB ' Monday$' D3MSG: DB ' Tuesday$' D4MSG: DB ' Wednesday$' D5MSG: DB ' Thursday$' D6MSG: DB ' Friday$' D7MSG: DB ' Saturday$' ; ;************************************************************ ; WRCLK - ; Write contents of Register Buffer to SmartWatch. ; WRCLK: CALL ACCESS ;Activate the SmartWatch ; PUSH ES MOV AX,BASE ;EPROM Segment MOV ES,AX MOV SI,OFFSET HS ;Point to Buffer CALL WR64 ;Write Bits STI ;Interrupts OK Now POP ES RET ; ;************************************************************ ; RDCLK - ; Read time and date from SmartWatch. ; RDCLK: CALL ACCESS ;Activate the SmartWatch ; PUSH DS MOV AX,BASE ;EPROM Segment MOV DS,AX MOV CX,64 ;Bit Counter MOV DI,OFFSET HS ;Point To Register Buffer RD1: JCXZ RD2 ; MOV AH,DS:READ ;Read Data Bit SHR AX,1 ;Prepare for Next Bit DEC CX TEST CX,7 ;Save Next Byte? JNZ RD1 ;Loop If Not ; STOSB ;Save Data Byte JMP RD1 ; RD2: POP DS STI ;Interrupts OK Now RET ; ;************************************************************ ; ACCESS - ; Access the SmartWatch. ; ACCESS: CLI ;Interrupts Off PUSH ES MOV AX,BASE ;EPROM Segment MOV ES,AX MOV AH,ES:READ ;Do A Read MOV SI,OFFSET PATERN ;Point to Pattern CALL WR64 ;Write Pattern POP ES RET ; PATERN: DB 0C5H,03AH,0A3H,05CH,0C5H,03AH,0A3H,05CH ; ;************************************************************ ; WR64 - ; Write 64 bits to SmartWatch. DS:SI points to bytes. ; WR64: MOV CX,64 ;Bit Counter WRX1: TEST CX,7 ;Next Pattern Byte? JNZ WRX2 ;Branch If Not ; LODSB ;Get Pattern Byte WRX2: TEST AL,1 ;Do the Write JNZ WRX3 ; MOV AH,ES:WR0 ;Write a Zero JMP WRX4 ; WRX3: MOV AH,ES:WR1 ;Write a One ; WRX4: SHR AL,1 ;Setup Next Pattern Bit LOOP WRX1 ; RET ; ;************************************************************ ; SMDTIM - ; Transform SmartWatch time and set MSDOS time. ; SMDTIM: MOV SI,OFFSET HS ;Start With Hundredths CALL FIXXL ;Convert to Binary MOV CL,AL ; CALL FIX ;Do Hours MOV CH,AL ; MOV AH,2DH ;Set MSDOS Time INT 21H RET ; ;************************************************************ ; SMDDAT - ; Transform SmartWatch date and set MSDOS date. ; SMDDAT: MOV SI,OFFSET DATE ;Start With Date CALL FIXXL ;Convert to Binary ; MOV CL,AL MOV CH,0 ADD CX,1900 CMP AL,80 ;Check for Century Rollover JGE NOROLL ; ADD CX,100 ;Make Year 2000+ NOROLL: MOV AH,2BH ;Set MSDOS Date INT 21H RET ; ;************************************************************ ; FIXXL - ; Convert three packed BCD bytes from SI to binary. Return ; first in DL, second in DH, and third in AL. ; FIXXL: CALL FIX ;Convert to Binary MOV DL,AL ;Then to DL ; CALL FIX ;Convert to Binary MOV DH,AL ;Then to DH ; FIX: MOV AL,[SI] ;Get Packed BCD MOV AH,AL SHR AH,1 ;Position the High Nibble SHR AH,1 SHR AH,1 SHR AH,1 AND AL,00001111B ;Mask Low Nibble AAD ;Make Binary INC SI ;Increment Pointer RET ; ;************************************************************ ; STORAGE ; DGTBUF DB 10 DUP(?) ;Digit Buffer for Setting ; ; SmartWatch Register Buffer ; HS DB 0 ; Hundredths & Tenths SECS DB 0 ; Seconds MINS DB 0 ; Minutes HOURS DB 0 ; Hours DOW DB 0 ; Day of Week DATE DB 0 ; Date MONTH DB 0 ; Month YEAR DB 0 ; Year ; CSEG ENDS ; END DSCLOCK