; Filename: SETTOD.ASM ; Description: This utility sets CP/M-86's internal Date & Time ; of Day according to the SmartWatch you have installed ; in your XT. If you don't have a SmartWatch installed or ; if this isn't an XT, this utility isn't going to work! ; This utility was intended for use in IBM XT computers ; equiped with both CP/M-86 and MS-DOS (or some other ; operating system/program) which supports SETTING the ; SmartWatch Real Time Clock. While this utility will work ; fine on an XT running only CP/M-86, it should be understood ; that this utility does NOT support setting the RTC, only ; CP/M-86's time/date. An assembly language programmer should ; be able to modify this program to set the SmartWatch without ; to much difficulty. ; Notes: This program makes use of Undocumented CP/M-86 `sysdata' ; variables- or at least undocumented in my documentation! ; Use with great care- and at your own risk!- especially on ; other versions of CP/M for the IBM PC. ; ; For Additional information on SmartWatches, see the Dallas Semiconductor ; 1992-1993 databook (DS1216E- Pg. 5-22). ; ; Copyright (C) 1993 by Richard Kanarek - All Rights Reserved. ; This program is Freeware- it may be used & distributed without charge at ; the discretion of its author. ; ; This program was written for execution under CP/M-86. It may be assembled ; by the assembler included with CP/M-86 (ASM86) and converted into a .CMD ; file with the GENCMD utility also included with CP/M-86. Execute GENCMD ; with the command line: GENCMD SETTOD 8080. ; ; At the time of this writing (11/06/93) CP/M-86 is still available from: ; DISCUS Distribution Services, Inc. ; 17607 Vierra Canyon road ; Salinas, CA 93907-3312 ; (408) 663-6966 ; ; 8080 (Tiny) Memory model program for CP/M-86 Ver. 2.2. ; CP/M-86 (tm)(C) Digital Research Inc. ; Note: CP/M Version number NOT checked! ; ; I would be happy to learn of your opinion regarding this program, its ; structure, implimentation, bugs, or any other thoughts you might have ; about it. Please send your comments to Richard Kanarek, Compu$erve ID ; 72371,111. Enjoy! ; ; Notes on editing/printing this file: ; Tabs were originally set to equal FOUR (4) spaces but have since been ; converted to spaces for those with no-frills editors. Lines containing ; comments may well exceed 80 characters (though not by much). If you are ; printing this file, you may wish to set your 80 column printer to its ; condensed (>80 column) mode. ;------------------------------ ; Equates... ;------------------------------ ; General: ; -------- tab equ 9d ;Equate for Tab cr equ 13d ;Equate for Carriage Ret. lf equ 10d ;Equate for LineFeed bell equ 7d ;Equate for Bell. EXIT_FAILURE equ 1d ;Same as Turbo C. EXIT_SUCCESS equ 0d ;Same as Turbo C. ; Program Specific: ;------------------ SW_SEG EQU 0F000h ;Segment of SmartWatch. ;Used by `update_time' procedure... ;Unfortunately CP/M's ASM86 won't support these equates so they had to be ; eliminated. They have been left here for reference only. ;ten_month EQU [bx] + 32d ;one_month EQU [bx] + 33d ;ten_date EQU [bx] + 35d ;one_date EQU [bx] + 36d ;ten_yr EQU [bx] + 38d ;one_yr EQU [bx] + 39d ;------- ;ten_hr EQU [bx] + 41d ;one_hr EQU [bx] + 42d ;ten_min EQU [bx] + 44d ;one_min EQU [bx] + 45d ;ten_sec EQU [bx] + 47d ;one_sec EQU [bx] + 48d ;------- ;sw_reg0 EQU [si] + 0d ;sw_reg1 EQU [si] + 1d ;sw_reg2 EQU [si] + 2d ;sw_reg3 EQU [si] + 3d ;sw_reg4 EQU [si] + 4d ;sw_reg5 EQU [si] + 5d ;sw_reg6 EQU [si] + 6d ;sw_reg7 EQU [si] + 7d CSEG ;Top of Code Segment. ORG 100h start: mov ax, SW_SEG ;Make ES = mov es, ax ; SmartWatch Segment. main: mov dx, OFFSET intro_msg ;Prepare to display introduction message. call put_str ;Display message. call any_tail ;Check for a command line tail. cmp ax, EXIT_SUCCESS ;Was there a command line tail? jnz main_notail ;No, then jump. main_tailfnd: ;This point is reached if a command line tail was found. ;Since the only time there should be a command line tail is when the user ; requests a help display or when he makes a mistake, lets display the ; help message and terminate. mov dx, OFFSET tail_msg ;DS:DX -> Command line tail (help) message. call put_str ;Display message. jmp fin ;Prepare to terminate. main_notail: ;This point is reached if there is NO command line tail. call copy_time ;Copy the current CP/M time to sw_buf. mov dx, OFFSET beforetime_msg ;Prepare to display 'time before setting' msg. call put_str ;Display msg. mov si, OFFSET sw_buf ;DS:SI -> TOD. call disp_tod ;Display time. ;Check for RTC... mov dx, OFFSET rtc_msg ;Prepare to display looking for RTC msg. call put_str ;Display message. call reset_sw ;Reset the SmartWatch (probably not needed as ; a read to the SmartWatch will also reset its ; comparison pointer, but why not be sure). call read_sw ;Make sure SW the comparison pointer is reset. mov bx, OFFSET sw_buf ;DS:BX -> SW reg. buffer. cli ;Disable interrupts. This is done to prevent ; an interrupt from occuring which might ; access the same memory locations occupied ; by the SmartWatch. call readreg_sw ;Fill buffer with data from the SmartWatch ; memory area BEFORE we have awoken the SW. ; This data should differ from the data read ; after the SmartWatch is awake! mov bx, OFFSET sw_enable ;DS:BX -> SW wakeup code. call writereg_sw ;Awaken SmartWatch. mov bx, OFFSET sw_enable ;DS:BX -> SW reg. buffer. Now read the same ; memory area as before. With the SmartWatch ; awake, the results should be different. call readreg_sw ;Fill buffer. SmartWatch should have automatically ; disabled its self. sti ;Enable interrupts. call reset_sw ;Disable the SmartWatch (Again, probably not ; needed as the SmartWatch becomes disabled ; after a full 8 byte read/write & the reset ; option might not even be enabled, but since ; we have the function anyway, lets use it). mov si, OFFSET sw_enable ;Compare buffers. They should be different! mov di, OFFSET sw_buf ; call comp_buf ; cmp ax, EXIT_SUCCESS ;Are the buffers equal? jnz main_rtcfnd ;No, then jump. main_nortc: ;This point is reached if NO real time clock (SmartWatch) is found. mov dx, OFFSET nortc_msg ;Display no rtc msg. call put_str ;Display message. mov dx, OFFSET tail_msg ;Display help message. call put_str ;Display message. jmps fin ;Quit. main_rtcfnd: mov dx, OFFSET rtcfnd_msg ;Display rtc found message. call put_str ;Display message. ;This point is reached if a real time clock (SmartWatch) IS found. mov bx, OFFSET sw_enable ;DS:BX -> SmartWatch Register Read Buffer. call isoscon ;Check OSC bit. (Osc bit set = Clock Off) cmp ax, EXIT_SUCCESS ;Is the RTC running? jz main_oscon ;Yes, then jump. main_oscoff: ;This point is reached if the SmartWatch is off. mov dx, OFFSET swoff_msg ;DS:DX -> RTC off message. call put_str ;Display message. jmp fin ;Quit. main_oscon: ;Update the system (CP/M) clock. mov si, OFFSET sw_enable ;DS:SI -> SmartWatch read. call update_time ;Update CP/M time based on info read from RTC. mov dx, OFFSET aftertime_msg ;Prepare to display time updated message. call put_str ;Display message. call copy_time ;sw_buf == Current CP/M time. mov si, OFFSET sw_buf ;DS:SI -> TOD. call disp_tod ;Display new time. mov dx, OFFSET bye_msg ;Prepare to display normal term. good bye msg. call put_str ;Display message. ;Fall into... fin: xor dx, dx ;Prepare for CP/M Func. 0... mov cl, dl ; "System Reset" (i.e. Terminate Pgrm). int 0E0h ;Bye! ;------------------------------ ; Subroutines... ;------------------------------ any_tail: ;Description: Check for the presence of a command line tail. ;Calling Reg.: DS -> Base Page. ;Return Reg: AX = EXIT_SUCCESS if command tail is present. ;Preserved: All registers except Flags & AX. mov al, ' ' ;AL = ' ' (space). cmp BYTE PTR .5Dh, al ;Is fist char in default FCB #1 filename field ' '? jz any_tail_no ;Yes then jump. any_tail_yes: ;If this point is reached, there was a command tail. mov ax, EXIT_SUCCESS ;AX = Return Code. jmps any_tail_fin ;Prepare to return. any_tail_no: ;If this point is reached, there was NO command tail. mov ax, EXIT_FAILURE ;AX = Return Code. ;Fall into... any_tail_fin: ;AX assumed == Return Code. ret ;Return. put_str: ;Description: Write an ASCII$ string to the console. ;Calling Reg.: DS:DX -> ASCII$ string. ;Return Reg: None. ;Preserved: ES & DS. push es ;Save ES. mov cl, 9h ;Prepare for CP/M Func. 9h "Print String" int 0E0h ;Print string. pop es ;Restore ES. nop ;For debugging only. ret ;Return. isoscon: ;Description: Is the oscillator in the smart watch running? ; Lets check the `Osc' bit and see. ; ;Calling Reg.: DS:BX -> SmartWatch read. ;Return Reg: AX = EXIT_SUCCESS if SmartWatch is on, EXIT_FAILURE ; otherwise. ;Preserved: BX, CX, DX, DI, SI, DS, ES mov al, BYTE PTR [BX] + 4d ;AL = Data from reg. #4. test al, 00100000b ;Check osc running bit. jnz isoscon_no ;Not set, then jump! isoscon_yes: ;If this point is reached, the SmartWatches osc. is running... mov ax, EXIT_SUCCESS ;AX = Return code. jmps is_fin ; isoscon_no: mov ax, EXIT_FAILURE ;AX = Return code. ;Fall into... is_fin: ret ;Return. update_time: ;Description: Convert data from SmartWatch to CP/M TOD form, then ; Update CP/M TOD. ; ;Calling Reg.: DS:SI -> SmartWatch read. ;Return Reg: None. ; ;Preserved: ES, DS, FLAGS ; ;Hardware notes: ;SmartWatch Register Definitions: ;Reg. 7 6 5 4 3 2 1 0 Range: ; ------------+------------- ------ ; 0 0.1s 0.01s 00-99 ; 1 0 10s 1s 00-59 ; 2 0 10min 1min 00-59 __ _ ; 3 12 0 10 10hr 1hr 01-12, 00-23. 12/24, A/P ; -- -- ; 24 AP ; 4 0 0 OscRst 0 Day 01-07 00-23 (Osc: 1 = Off; Rst: 1 = Disabled.) ; 5 0 0 10Date 1Date 01-31 ; 6 0 0 0 10Mon Month 01-12 ; 7 10Year 1Year 00-99 ; push es ;Save ES. pushf ;Save Flags. mov cl, 31h ;Prepare to Get Sysdata addrs. int 0E0h ;ES:BX -> Sysdata addrs. cli ;Disable interrupts (attempt to stop ; CP/M clock while its being changed. ;Set Seconds... mov al, BYTE PTR [si] + 1d ;AL = Packed BCD seconds. call packed2asc ;AH = 10sec; AL = ASCII 1sec. mov es: BYTE PTR [bx] + 48d, al ;Set 1 sec's. mov es: BYTE PTR [bx] + 47d, ah ;Set 10 sec's ;Set Minutes... mov al, BYTE PTR [si] + 2d ;AL = Packed BCD minutes. call packed2asc ;AH = 10min's; AL = 1min's. mov es: BYTE PTR [bx] + 45d, al ;Set 1 minute. mov es: BYTE PTR [bx] + 44d, ah ;Set 10 minute. ;Set Hours... mov al, BYTE PTR [si] + 3d ;AL = SmartWatch Reg. #3. test al, 10000000b ;Is SW in 24 hr mode? jz up24 ;Yes, then jump. up12: and al, 00111111b ;AL = offset into `table_12hr'. push bx ;Save BX. mov bx, OFFSET table_12hr ;BL = `table_12hr' OFFSET. xlat bx ;AL = Hours in PACKED BCD format. pop bx ;Restore BX. ;Fall into... up24: ;When this point is reached, bits 5-0 of AL ; contain the time in packed BCD format. and al, 00111111b ;Make sure control bits aren't set! call packed2asc ;AH = 10hr's; AL = 1hr's. mov es: BYTE PTR [bx] + 42d, al ;Set 1 hr's. mov es: BYTE PTR [bx] + 41d, ah ;Set 10 hr's. ;Set Date... mov al, BYTE PTR [si] + 5d ;AL = Packed BCD date. call packed2asc ;AH = 10's date; AL = 1's date. mov es: BYTE PTR [bx] + 36d, al ;Set 1's date. mov es: BYTE PTR [bx] + 35d, ah ;Set 10's date. ;Set Month... mov al, BYTE PTR [si] + 6d ;AL = Packed BCD Month. call packed2asc ;AH = 10's month; AL = 1's month. mov es: BYTE PTR [bx] + 33d, al ;Set 1's month. mov es: BYTE PTR [bx] + 32d, ah ;Set 10's month. ;Set Year... mov al, BYTE PTR [si] + 7d ;AL = Packed BCD Year. call packed2asc ;AH = 10's year; AL = 1's year. mov es: BYTE PTR [bx] + 39d, al ;Set 1's year. mov es: BYTE PTR [bx] + 38d, ah ;Set 10's year. ;The CP/M system clock has been updated! ;Prepare to return... popf ;Restore Flags. (re-enable interrupts) pop es ;Restore ES. nop ;Used for debugging purposes only. ret ;Return. packed2asc: ;Description: Unpack a packed BCD in AL into two ASCII bytes. ; ; ;Calling Reg.: AL = Packed BCD ;Return Reg: AH = ASCII MSB, AL = ASCII LSB ; ;Preserved: BX, CH, DX, SI, DI, DS, ES. mov ah, al ;AH = AL = Packed BCD and ax, 0F00Fh ;AL = Unpacked BCD, mov cl, 4d rol ah, cl ;AX = Unpacked BCD or ax, 3030h ;AX = Unpacked ASCII BCD. ret ;Return mk_al_bin: ;Description: Convert an Packed BCD byte pointed to by DS:BX ; into a binary value. ;Calling Reg.: DS:BX -> Packed BCD BYTE. ;Return Reg: AX = Packed BCD WORD. ; ;Preserved: BX, DX, SI, DI, DS, ES mov al, BYTE PTR [BX] ;AL = Packed BCD value. mov ah, BYTE PTR [BX] ;AH = Packed BCD value. and ax, 0F00Fh ;Converting AX into... mov cl, 4d ; ... rol ah, cl ; Unpacked BCD value. aad ;AL/AX Now Equal the binary value of the ; Packed BCD's. ret ;Return. disp_tod: ;Description: Display Time (and date) of day. ; ;Calling Reg.: DS:SI -> 17d byte ASCII string to write. ;Return Reg: None. ; ;Preserved: DS & ES. push ES ;Save ES. mov di, 17d ;Number of characters to display. disp_looptop: mov dl, BYTE PTR [si] ;DL = Char. to display. mov cl, 2h ;Prepare for CP/M Fun. 2h Console Output. int 0E0h ;CP/M Interrupt. inc si ;Point BX at next char to output. dec di ;Adj. write count. jnz disp_looptop ;Loop as required. pop es ;Restore ES. nop ;For debugging only. ret ;Return. copy_time: ;Description: Copy the current time from the Sysdata data area to ; sw_buf. ;Calling Reg.: None. ;Return Reg: None. ; ;Preserved: DS, ES, & FLAGS. push ds ;Save DS. push es ;Save ES. pushf ;Save Flags. mov cl, 31h ;Call Get Sysdata Addrs interrupt. int 0E0h ;CP/M interrupt. ES:BX -> Sysdata. add bx, 20h ;ES:BX now -> 17 bytes of time/date data. mov di, OFFSET sw_buf ;DS:DI -> sw_buf mov si, bx ;ES:SI = Sysdata area. mov ax, es ;AX = ES. mov bx, ds ;BX = DS. mov ds, ax ;DS:SI -> Sysdata Offset. mov es, bx ;ES:DI -> sw_buf mov cx, 17d ;CX = Bytes to copy. cld ;Clear Direction flag, string instructions inc. cli ;Disable interrupts. rep movsb ;sw_buf now contains time data. popf ;Restore flags/re-enable interrupts. pop es ;Restore ES. pop ds ;Restore DS. nop ;For debugging only. ret ;Return comp_buf: ;Description: This procedure compares the 8 byte buffer DS:SI ; with the 8 byte buffer DS:DI. ;Calling Reg.: DS:SI & DS:DI ;Return Reg: AX = EXIT_SUCCESS if both buffers are equal. EXIT_FAILURE ; otherwise. ;Preserved: BX, CX, DX, DS, ES pushf ;Save flags. push cx ;Save CX. push ds ;Save DS. push es ;Save ES. mov cx, ds ;CX = DS. mov es, cx ;ES = DS. DS:SI & DS:DI now set. mov cx, 4d ;Number of words to check. cld ;Clear direction flag- string ins. inc. repe cmpsw ;Compare buffers. jne cmp_fail ;Not equal? Then jump. cmp_ok: mov ax, EXIT_SUCCESS ;AX = Return Code. jmps cmp_fin ;Return... cmp_fail: mov ax, EXIT_FAILURE ;AX = Return Code. Fall into... cmp_fin: pop es ;Restore ES. pop ds ;Restore DS. pop cx ;Restore CX. popf ;Restore flags. ret ;Return. ;-------------------------------------------------- ; Note: All subroutines below assume ES == SW_SEG! ;-------------------------------------------------- reset_sw: ;Description: Reset SmartWatch (if reset is enabled). ; ;Calling Reg.: None. ;Return Reg: None. ;Preserved: ALL Registers EXCEPT AH (including flags) preserved. ; ;Hardware Notes: ;Make A15/Pin 1 (reset) low. mov ah, es: BYTE PTR .0 ;Reset Smart Watch. ret read_sw: ;Description: Read a bit from the SmartWatch. ; ;Calling Reg.: ES reg assumed = SmartWatch Seg. Address. ;Return Reg: AL == 1 or 0; ZF Flag set if bit == 0. ;Preserved: All regs and flags EXCEPT AL & ZF ; ;Hardware Notes: ; _____ _____ ;Make A2 (read/write) hi, A15 (reset) hi, and Read data from O(0). mov al, es: BYTE PTR .32772d ;bit 0 of al = bit from SW and al, 1b ;Test bit 0 & clear all other bits. ret write1_sw: ;Description: Write a 1 bit to the SmartWatch. ;Calling Reg.: ES reg assumed = SmartWatch Seg. Address. ;Return Reg: None. ;Preserved: All registers except AH. AH undefined. ; ;Hardware Notes: ; _____ _____ ;Make A2 (read/write) low, A15 (reset) hi, and A0 (Data Input) hi mov ah, es: BYTE PTR .32769d ret write0_sw: ;Description: Write a 0 bit to the SmartWatch. ;Calling Reg.: ES reg assumed = SmartWatch Seg. Address. ;Return Reg: None. ;Preserved: All registers except AH. AH undefined. ; ;Hardware Notes: ; _____ _____ ;Make A2 (read/write) low, A15 (reset) hi, and A0 (Data Input) low. mov ah, es: BYTE PTR .32768d ret ;Return. writereg_sw: ;Description: Transmit a 8 byte string pointed to by [BX] to ; the SmartWatch. ;Calling Reg.: DS:BX -> 8 Byte string (8bits per byte). ;Return Reg: None. ;Preserved: DI, ES ; ;Hardware Notes: ;Before attempting to awaken the SmartWatch, execute a read_sw so ; that the comparison reg. pointer is reset. mov cx, 8d ;CX = Num. bytes to write. pushf ;Save Flags. wbyte_looptop: mov dx, cx ;Save CX in DX. mov cx, 8d ;CX = Number of bits to xmit. mov al, BYTE PTR [bx] ;AL = Byte to xmit. wbit_looptop: test al, 1b ;Are we xmiting a 1 or 0? jz wsend_0 ;If zero, jump. wsend_1: ;Guess we're sending a 1... call write1_sw ;Write 1. jmps wbit_loopbot ;Prepare to loop if needed. wsend_0: ;Guess we're sending a 0... call write0_sw ;Write 0. Then fall into... wbit_loopbot: shr al, 1d ;Position next bit for xmission (if ; there is one). loop wbit_looptop ;Loop as needed. wbyte_loopbot: ;Prepare to xmit next byte. inc bx ;Point BX to the next byte to send. mov cx, dx ;Restore CX from DX (CX = Num. bytes to send). loop wbyte_looptop ;Loop if there are any bytes to send. ;The SmartWatch should now be awake! popf ;Restore flags. ret ;Return. readreg_sw: ;Description: Read the SmartWatch Register. ;Calling Reg.: DS:BX -> 8byte buffer. ;Return Reg: None (just memory above) ;Preserved: DI. All other registers modified! ;Notes: Interrups are disabled while this procedure is running. pushf ;Save flags (esp. int flag). mov cx, 8d ;CX = Number of bytes to read. cld ;Clear interrupt flag- int's disabled. rdbyte_looptop: mov dx, cx ;Save CX in DX. mov cx, 8d ;CX = Number of bits to read. rdbit_looptop: mov si, cx ;Save CX in SI. mov cx, 8d ;CX = No. bits in byte. sub cx, si ;Number of shifts to perform latter ; (CH assumed clr). call read_sw ;AL = 1 or 0; ZF flag set or cleared. jz rdread_0 ;If zero, jump. rdread_1: ;Bit read was 1: shl al, cl ;Move al's bit to the right spot. or ah, al ;Set AH per read. jmps rdbit_loopbot ;Prepare to loop again if needed. rdread_0: ;Bit read was 0. mov al, 1b ;Set a bit in AL. shl al, cl ;Move it where we need it. not al ;Clear the set bit in al, set the clear bits. and ah, al ;Clear the proper bit in AH. rdbit_loopbot: mov cx, si ;Restore CX from SI. loop rdbit_looptop ;More bits to read in current byte? Then jump. rdbyte_loopbot: ;Prepare to read next byte if there is one. mov BYTE PTR [bx], ah ;First save byte that was just read. inc bx ;Point BX to the next byte buffer. mov cx, dx ;Restore CX from DX (CX = Num. bytes to read). loop rdbyte_looptop ;Loop if there are any bytes to send. ;When this point is reached, sw_enable contains the contents of the ; SmartWatch data registers. popf ;Restore flags. ret ;Return. endcs EQU $ DSEG ;Top of Data Segment. ORG OFFSET endcs ;Data Goes Here! ;Messages/Strings: ;----------------- intro_msg db cr, lf, 'SETTOD: Set CP/M Time of Day from installed XT SmartWatch (tm) Real Time Clock' db cr, lf, ' Utility Written/Copyrighted (C) 1993 by Richard Kanarek. All Rights' db cr, lf, ' Reserved. Ver. 0.9 - - - FREEWARE - - - Limited Distribution Permitted!' db cr, lf, ' Note: SmartWatch (tm) Dallas Semiconductor Inc.' db cr, lf, ' Enter SETTOD ? For Help$' tail_msg db cr, lf db cr, lf, 'To use this utility to update your system (not Real Time) clock/calender, ' db cr, lf, 'enter this utility''s name without any command line arguments. Once started, it' db cr, lf, 'will read your SmartWatch (directly- not using any BIOS calls!) and update' db cr, lf, 'your system (CP/M-86) clock.' db cr, lf, 'IMPORTANT: Since this utility attempts to communicate directly with your RTC,' db cr, lf, '---------- your RTC must be a genuine SmartWatch(tm) DS1216E compatible RTC.' db cr, lf, ' Further, it must be installed in an XT computer (which are the only' db cr, lf, ' ones that can use SmartWatches, & addressed in segment F000h.' db cr, lf, ' Running this utility on an uncompatible computer is not likely to' db cr, lf, ' cause harm but it will not produce the desired results either!$' beforetime_msg db cr, lf, cr, lf, 'CP/M Time before update: $' rtc_msg db cr, lf, cr, lf, 'Checking for SmartWatch(tm): $' nortc_msg db '* * *SmartWatch =NOT= found! * * *' db cr, lf, ' Please remember this program will ONLY work with a genuine Dallas' db cr, lf, ' Semiconductor SmartWatch. Have you installed one? It should' db cr, lf, ' be sitting between your XT''s BIOS ROM IC and its socket. See anything?$' rtcfnd_msg db 'SmartWatch FOUND', cr, lf, '$' swoff_msg db cr, lf, cr, lf, 'Error: SmartWatch turned off! (OSC bit in SmartWatch Reg. #4 is set!)' db cr, lf, ' There is no point is reading the RTC if it isn''t ticking! SETTOD aborting.$' aftertime_msg db cr, lf, cr, lf, 'CP/M Time updated from RTC. Current Time: $' bye_msg db cr, lf, cr, lf, 'SETTOD: Normal termination. Bye!$' ;Variables/Buffers: ;------------------ sw_enable db 0C5h, 3Ah, 0A3h, 5Ch db 0C5h, 3Ah, 0A3h, 5Ch ;This code enables the Smart Watch. Send it ; Least Sig. Bit/Byte first. ;7 6 5 4 3 2 1 0 sw_buf db 0, 0, 0, 0, 0, 0, 0, 0 ;Buffer for SmartWatch reads db 0, 0, 0, 0, 0, 0, 0, 0 ; & time display. db 0 table_12hr db 0FFh ;0 o'clock AM (invalid). 00 0000 db 1b ;1 o'clock AM. 00 0001 db 10b ;2 o'clock AM. 00 0010 db 11b ;3 o'clock AM. 00 0011 db 100b ;4 o'clock AM. 00 0100 db 101b ;5 o'clock AM. 00 0101 db 110b ;6 o'clock AM. 00 0110 db 111b ;7 o'clock AM. 00 0111 db 1000b ;8 o'clock AM. 00 1000 db 1001b ;9 o'clock AM. 00 1001 db 0FFh ;A o'clock AM (invalid). 00 1010 db 0FFh ;B o'clock AM (invalid). 00 1011 db 0FFh ;C o'clock AM (invalid). 00 1100 db 0FFh ;D o'clock AM (invalid). 00 1101 db 0FFh ;E o'clock AM (invalid). 00 1110 db 0FFh ;F o'clock AM (invalid). 00 1111 db 10000b ;10 o'clock AM. 01 0000 db 10001b ;11 o'clock AM. 01 0001 db 10010b ;12 o'clock AM. 01 0010 db 0FFh ;13 o'clock AM (invalid). 01 0011 db 0FFh ;14 o'clock AM (invalid). 01 0100 db 0FFh ;15 o'clock AM (invalid). 01 0101 db 0FFh ;16 o'clock AM (invalid). 01 0110 db 0FFh ;17 o'clock AM (invalid). 01 0111 db 0FFh ;18 o'clock AM (invalid). 01 1000 db 0FFh ;19 o'clock AM (invalid). 01 1001 db 0FFh ;1A o'clock AM (invalid). 01 1010 db 0FFh ;1B o'clock AM (invalid). 01 1011 db 0FFh ;1C o'clock AM (invalid). 01 1100 db 0FFh ;1D o'clock AM (invalid). 01 1101 db 0FFh ;1E o'clock AM (invalid). 01 1110 db 0FFh ;1F o'clock AM (invalid). 01 1111 db 0FFh ;0 o'clock PM (invalid). 10 0000 db 00010011b ;1 o'clock PM (13:00). 10 0001 db 00010100b ;2 o'clock PM (14:00). 10 0010 db 00010101b ;3 o'clock PM (15:00). 10 0011 db 00010110b ;4 o'clock PM (16:00). 10 0100 db 00010111b ;5 o'clock PM (17:00). 10 0101 db 00011000b ;6 o'clock PM (18:00). 10 0110 db 00011001b ;7 o'clock PM (19:00). 10 0111 db 00100000b ;8 o'clock PM (20:00). 10 1000 db 00100001b ;9 o'clock PM (21:00). 10 1001 db 0FFh ;A o'clock PM (invalid). 10 1010 db 0FFh ;B o'clock PM (invalid). 10 1011 db 0FFh ;C o'clock PM (invalid). 10 1100 db 0FFh ;D o'clock PM (invalid). 10 1101 db 0FFh ;E o'clock PM (invalid). 10 1110 db 0FFh ;F o'clock PM (invalid). 10 1111 db 00110001b ;10 o'clock PM (22:00). 11 0000 db 00110010b ;11 o'clock PM (23:00). 11 0001 db 00110011b ;12 o'clock PM (24:00). 11 0010 db 0FFh ;---Invalid Time--- 11 0011 db 0FFh ;---Invalid Time--- 11 0100 db 0FFh ;---Invalid Time--- 11 0101 db 0FFh ;---Invalid Time--- 11 0110 db 0FFh ;---Invalid Time--- 11 0111 db 0FFh ;---Invalid Time--- 11 1000 db 0FFh ;---Invalid Time--- 11 1001 db 0FFh ;---Invalid Time--- 11 1010 db 0FFh ;---Invalid Time--- 11 1011 db 0FFh ;---Invalid Time--- 11 1100 db 0FFh ;---Invalid Time--- 11 1101 db 0FFh ;---Invalid Time--- 11 1110 db 0FFh ;---Invalid Time--- 11 1111 endds EQU $ ;Terminate file... CSEG ORG OFFSET endds END