home *** CD-ROM | disk | FTP | other *** search
- ***************************************************************************
- ;
- ; SetMClock v1.21 14-Sep-93 by Adriano De Minicis
- ;
- ;--------------------------------------------------------------------------
- ; Assembler used: Devpac3
- ; Link: Blink SetMClock.o lib amiga.lib sc sd nd
- ;--------------------------------------------------------------------------
- ; HISTORY:
- ;
- ; V1.0 22-Jul-93 First release: ok, but OS1.2 can't see bool tooltypes
- ; V1.1 29-Jul-93 Changed configuration file name from "clock.config" to
- ; "MClock.upd", changed tooltypes (MODE=load|save|zero)
- ; to maintain compatibility with OS1.2
- ; V1.2 07-Aug-93 Fixed bug in WBParse with OS1.2
- ; V1.21 14-Sep-93 Fixed bug in updating "MClock.upd".
- ; Now performs a complete check to the configuration file.
- ;--------------------------------------------------------------------------
- ;
- ; NOTE: I've used a compact notation to show the content of a register
- ; when it contains more than one variable:
- ;
- ; (x) means x is a byte, [y] means y is a word
- ;
- ; Example: d0 = (day)(month)[year] means:
- ; byte #3 (upper) is day, byte #2 is month,
- ; lower word is year
- ;
- ***************************************************************************
-
- opt l+ ; linkable
-
- include exec/exec_lib.i
- ; include dos/dos_lib.i
- ; include dos/dos.i
- include devices/timer.i
- include graphics/text.i
- include graphics/rastport.i
- include intuition/intuition.i
- include intuition/intuition_lib.i
- include workbench/workbench.i
- include workbench/icon_lib.i
- include workbench/startup.i
-
- ****** Startup code *****************************************************
-
- include smallstartup.i
-
- ****** Macro definitions ************************************************
-
- CALL MACRO
- jsr _LVO\1(a6)
- ENDM
-
- ****** Constants and variables ******************************************
-
- even
-
- LIBVERS equ 33 ; library version required (v1.2)
- ABSEXECBASE equ 4
-
- ARWIDTH equ 450 ; requester width
- ARHEIGHT equ 37 ; requester height
-
- LOAD equ 'LOAD' ; used as a long value (4 chars)
- SAVE equ 'SAVE' ; "
- ZERO equ 'ZERO' ; "
-
- SHORTTIME equ 100 ; delay in microseconds
- LONGTIME equ 1000 ; delay in microseconds
- STOPTIME equ 5000 ; delay (µs) after bus stop ; and 'load'
-
- CLK_ADDR_RD equ %11010011 ; I2C address of clock (read)
- CLK_ADDR_WR equ %11010010 ; I2C address of clock (write)
-
- MONTH_MASK equ %00011111 ; mask for month data (BCD)
- DAYHR_MASK equ %00111111 ; mask for day and hour
- MINSEC_MASK equ %01111111 ; mask for minutes and seconds
-
- TimerPort dc.l 0 ; TimerPort pointer
- TimeReq dc.l 0 ; TimeRequest pointer
- TimerDevOpen dc.w 0 ; true if timer device opened
-
- _IntuitionBase dc.l 0
- _IconBase dc.l 0
-
- *---- Days from the beginning of the year ----*
-
- DayMonth dc.w 0,31,59,90,120,151,181,212,243,273,304,334,365
- DayMonthLeap dc.w 0,31,60,91,121,152,182,213,244,274,305,335,366
-
- *---- Version string ----*
-
- VersionString dc.b '$VER: SetMClock 1.21 (14.9.93)',0
-
- *---- String definitions ----*
-
- intui_name INTNAME
- timer_name TIMERNAME
- icon_name ICONNAME
-
- AROkTxt dc.b 'OK',0 ; Negative text for req.
- ToolStr dc.b 'MODE',0
- LoadStr dc.b 'load',0
- SaveStr dc.b 'save',0
- ZeroStr dc.b 'zero',0
- HelpTxt dc.b 'CLI Usage: SetMClock load|save|zero',$0a
- dc.b 'WB Tooltypes: MODE=load|save|zero',0
- ErrNoTimer dc.b 'Can''t open timer.device',0
- ErrNoClock dc.b 'Can''t find battery backed up clock',0
- ErrBadData dc.b 'Bad data in S:MClock.upd',0
- ErrClkNotSet dc.b 'Battery backed up clock not set',0
- ErrNoConfig dc.b 'Can''t open S:MClock.upd',0
- ErrNoSave dc.b 'Can''t save '
- ConfigFile dc.b 'S:MClock.upd',0
-
- ConfigModified dc.b 0 ; true if config.file modified
-
- even
-
- *---- Configuration file buffer ----*
-
- ConfigBuffer dc.b 0 ; day (1..31)
- dc.b 0 ; month (1..12)
- dc.w 0 ; year (1978..2066) (from Amiga0 to Amiga1E6)
-
- even
-
- *---- Intuitexts for AutoRequest ----*
-
- ARBodyIT dc.b 0,1,RP_JAM2,0
- dc.w 10,8
- dc.l 0 ;default font
- ARBTxt dc.l 0,0
-
- ARNegIT dc.b 0,1,RP_JAM2,0
- dc.w 6,3
- dc.l 0 ;default font
- dc.l AROkTxt, 0
-
- ****** External references for linker ***********************************
-
- XREF _CreatePort ; amiga.lib
- XREF _DeletePort ; amiga.lib
- XREF _CreateExtIO ; amiga.lib
- XREF _DeleteExtIO ; amiga.lib
-
- XDEF _SysBase
- XDEF _DOSBase
-
- ****** Main *************************************************************
-
- even
-
- main lea intui_name(pc),a1
- moveq #LIBVERS,d0
- CALLEXEC OpenLibrary ; open intuition.library
- move.l d0,_IntuitionBase
- beq Exit ; exit immediately
-
- GetTimer moveq #0,d0
- move.l d0,-(sp)
- move.l d0,-(sp)
- jsr _CreatePort ; create Port for timer
- addq #8,sp
- move.l d0,TimerPort
- beq.s NoTimer
-
- moveq #IOTV_SIZE,d1
- move.l d1,-(sp)
- move.l d0,-(sp)
- jsr _CreateExtIO ; create ExtIO for timer
- addq #8,sp
- move.l d0,TimeReq
- beq.s NoTimer
-
- lea timer_name(pc),a0
- move.l d0,a1
- moveq #UNIT_MICROHZ,d0
- moveq #0,d1
- CALLEXEC OpenDevice ; open timer.device (microHz)
- tst.l d0
- beq.s TimerOk
-
- NoTimer lea ErrNoTimer(pc),a0
- moveq #RETURN_ERROR,d7
- bra ErrorExit
-
- TimerOk move #-1,TimerDevOpen
-
- ****** Parse arguments passed from CLI or WB ****************************
-
- move.l WBenchMsg(pc),d0
- bne WBParse
-
- *---- Called from CLI ----*
-
- CLIParse move.l CmdLinePtr(pc),a0 ; pointer to command line
- move.b (a0)+,d0 ; get first char
- asl.w #8,d0
- move.b (a0)+,d0 ; get second char
- swap d0
- move.b (a0)+,d0 ; get third char
- asl.w #8,d0
- move.b (a0)+,d0 ; get fourth char
- and.l #$DFDFDFDF,d0 ; uppercase the four chars
-
- select_choice cmp.l #LOAD,d0
- beq LoadClock
- cmp.l #SAVE,d0
- beq SaveClock
- cmp.l #ZERO,d0
- beq ZeroClock
-
- lea HelpTxt(pc),a0 ; no match, show help
- moveq #0,d7 ; no error code
- bra ErrorExit
-
- *---- Called from WB ----*
-
- WBParse move.l #LOAD,d5 ; d5 = choice (default)
-
- move.l d0,a0
- move.l sm_NumArgs(a0),d1 ; d1 = NumArgs
- move.l sm_ArgList(a0),a1 ; a1 = pointer to first WBArg
-
- cmp #1,d1 ; only one arg?
- bls.s 1$ ; yes, skip
- addq #wa_SIZEOF,a1 ; no, get the second
-
- 1$ move.l wa_Name(a1),d7 ; d7 = icon who called us
- beq 11$
- move.l wa_Lock(a1),d1 ; file lock
- beq 11$
- CALLDOS CurrentDir ; change to the proper dir.
- move.l d0,d6 ; d6 = old lock
-
- lea icon_name(pc),a1
- moveq #LIBVERS,d0
- CALLEXEC OpenLibrary ; open icon.library
- move.l d0,a6 ; save icon.lib pointer
- tst.l d0 ; check if open error
- beq.s 10$
-
- move.l d7,a0
- CALL GetDiskObject ; open icon who called us
- tst.l d0
- beq.s 9$
-
- move.l d0,a5 ; save pointer to diskobj
- move.l do_ToolTypes(a5),a0 ; a0 = tooltype pointer
-
- lea ToolStr(pc),a1
- CALL FindToolType ; search 'MODE' tooltype
- tst.l d0
- beq.s 5$ ; not found, use default
-
- move.l d0,a4 ; save toolstring pointer
- move.l a4,a0
- lea ZeroStr(pc),a1
- CALL MatchToolValue ; search 'zero' string
- tst.l d0
- beq.s 4$ ; not found
- move.l #ZERO,d5 ; found: choice = ZERO
-
- 4$ move.l a4,a0
- lea SaveStr(pc),a1
- CALL MatchToolValue ; search 'save' string
- tst.l d0
- beq.s 5$ ; not found
- move.l #SAVE,d5 ; found: choice = SAVE
-
- 5$ move.l a5,a0
- CALL FreeDiskObject ; free icon
-
- 9$ move.l a6,a1
- CALLEXEC CloseLibrary ; close icon.library
- 10$ move.l d6,d0
- beq.s 11$
- CALLDOS CurrentDir ; restore old directory
- 11$ move.l d5,d0
- bra select_choice
-
-
- ****** Close and exit ***************************************************
-
- *---- Exits with error code in D7 and error string in A0 ----*
-
- ErrorExit bsr puts
- bra.s close
-
- *---- Normal exit code ----*
-
- CloseExit moveq #0,d7 ; no error code
-
- close move TimerDevOpen(pc),d0
- beq.s 1$
- move.l TimeReq(pc),a1
- CALLEXEC CloseDevice ; close timer device
-
- 1$ move.l TimeReq(pc),d0
- beq.s 2$
- moveq #IOTV_SIZE,d1
- move.l d1,-(sp)
- move.l d0,-(sp)
- jsr _DeleteExtIO ; delete TimeReq
- addq #8,sp
-
- 2$ move.l TimerPort(pc),d0
- beq.s 3$
- move.l d0,-(sp)
- jsr _DeletePort ; delete TimerPort
- addq #4,sp
-
- 3$ move.l _IntuitionBase(pc),d0
- beq.s 4$
- move.l d0,a1
- CALLEXEC CloseLibrary ; close intuition library
-
- 4$ bra Exit
-
-
- ****** Print string *****************************************************
- ;
- ; Prints null terminated string to standard output adding a line feed,
- ; if called from CLI, or shows a requester if started from WB.
- ;
- ; Input: A0 pointer to null terminated string
- ; Registers used: A0..A3, D0..D3
-
- puts tst.l WBenchMsg ; from CLI?
- bne.s autoreq ; no
-
- move.l OutputFH(pc),d1 ; d1 = output filehandle
- beq.s 3$ ; handle=0 ?, skip
-
- moveq #1,d3 ; d3 = text lenght
- move.l a0,d2 ; d2 = text pointer
- 1$ move.b (a0)+,d0 ; current char = 0 ?
- beq.s 2$ ; yes, end of text
- addq #1,d3 ; no, inc lenght
- bra.s 1$ ;
- 2$ move.b #$0a,-(a0) ; add a line feed
- move.l a0,a3 ; save pointer to null char
- CALLDOS Write ; print text
- move.b #0,(a3) ; restore null terminator
-
- 3$ rts
-
- autoreq move.l a0,ARBTxt ; set pointer to my text
- moveq #0,d0 ; no positive IDCMP flags
- moveq #0,d1 ; no negative IDCMP flags
- move.l #ARWIDTH,d2 ; width of autorequester
- moveq #ARHEIGHT,d3 ; heght of autorequester
- move.l d0,a0 ; no window
- move.l d0,a2 ; no positive text
- lea ARBodyIT(pc),a1 ; positive text
- lea ARNegIT(pc),a3 ; negative text
- CALLINT AutoRequest
- rts
-
-
- ****** Read/Write configuration file ************************************
- ;
- ; Input: D4 = Mode: (0=Read, 1=Write)
- ; D5 = ErrorCode
- ; A5 = ErrorString
-
- OpenConfig lea ConfigFile(pc),a0
- move.l a0,d1
- move.l #MODE_OLDFILE,d2 ; read mode (file must exist)
- tst.l d4 ; read or write ?
- beq.s 1$ ; read, ok
- move.l #MODE_NEWFILE,d2 ; save mode (create new file)
- 1$ CALLDOS Open ; open config file
- move.l d0,d7 ; d7 = file handle
- bne.s OpenOk
-
- RWError move.l a5,a0 ; error string
- move.l d5,d7
- bra ErrorExit
-
- OpenOk move.l d0,d1
- lea ConfigBuffer(pc),a0
- move.l a0,d2
- moveq #4,d3
- tst.b d4 ; read or write ?
- bne.s 1$
- CALL Read
- bra.s 2$
- 1$ CALL Write
- 2$ move.l d0,d6
- move.l d7,d1
- CALL Close
- cmp #4,d6
- bne.s RWError
- rts
-
- ****** I2C ROUTINES *****************************************************
-
- *---- Hardware register for mouse port #2 ----*
-
- CiaA_PortA equ $bfe001 ; bit 7 = fire, used for
- ; SCL line (I2C serial clock)
- CiaA_DDRA equ $bfe201 ; data direction (0=in, 1=out)
- ; for CiaA_PortA
- PotGo equ $dff034 ; bit 14 = PotY, bit 15 = OE
- ; used for data output (SDA)
- Joy1Dat equ $dff00c ; bit 1 = /Right (SDA input)
- ; bit 9 = /Left (SCL input)
-
- *---- Definitions ----*
-
- I2CStatus dc.b 0 ; Status of I2C: 0=ok
- ; bit 0=timeout, bit 1=no ack
- even
-
- POT0 equ $8000 ; value of POTGO for SDA=0
- POT1 equ $C000 ; value of POTGO for SDA=1
-
- TIMEOUT equ 10000 ; max timeout loops
-
- FIRE equr a3
- POT equr a4
- JOY equr a5
-
- ;----- Start I2C communications -----------------------------------------
- ;
- ; Call this routine to initialize registers and the I2C bus
- ;
- ; IMPORTANT: registers A3,A4,A5 are used by I2C routines. Do NOT modify
- ; them until StopI2C
- ;
- ; Register modified: D0..D1, A0..A1, A3..A6
-
- StartI2C move.b #0,I2CStatus ; status ok
- lea CiaA_PortA,FIRE
- lea PotGo,POT
- lea Joy1Dat,JOY
- bset.b #7,(FIRE) ; set SCL=1
- bset.b #7,CiaA_DDRA ; set SCL as output
- bsr sda1
- bsr sda0
- bsr scl0
- bra shortdelay
-
- ;----- Stop I2C communication -------------------------------------------
-
- StopI2C bsr sda0
- bsr scl1
- bsr sda1
- bclr.b #7,CiaA_DDRA ; set SCL as input
- move #0,(POT) ; set SDA as input (superfluous ?)
- move.l #STOPTIME,d0 ; delay from stop condition
- bra delay
-
- ;----- Transmit byte in d2 converting to BCD ----------------------------
- ;
- ; Input: D2 byte to transmit (binary)
- ; Register modified: D0..D3, A0..A1, A6
-
- TXByteToBCD moveq #0,d0 ; clear result
- move.b d2,d0 ; d0 = b (byte binary)
- moveq #10,d1
- divu d1,d0 ; d0 = [b MOD 10][b DIV 10]
- move d0,d2 ; d2 = b DIV 10
- lsl #4,d2 ; d2 = (b DIV 10)*16
- swap d0
- add d0,d2 ; d2 = (b DIV 10)*16 + (b MOD 10)
- bra.s TXByte ; transmit
-
-
- ;----- Receive byte in d4, mask it, and convert from BCD -----------------
- ;
- ; Input: D5 byte mask
- ; Output: D4 byte received (long)
- ; Register modified: D0..D4, A0..A1, A6
-
- RXByteFromBCD bsr.s RXByte ; d2 = B, byte received (BCD)
- and.b d5,d4 ; mask byte
- move d4,d0
- and.b #$0F,d0 ; d0 = LSD
- lsr #4,d4 ; d4 = MSD
- moveq #10,d1
- mulu d1,d4 ; d4 = MSD*10
- add d0,d4 ; d4 = MSD*10+LSD
- rts
-
- ;----- Transmit byte in d2 -----------------------------------------------
- ;
- ; Input: D2 byte to transmit
- ; Register modified: D0..D3, A0..A1, A6
-
- TXByte moveq #7,d3 ; bit counter
- 1$ bsr.s txbit
- lsl.b #1,d2
- dbra d3,1$
- bsr.s rxbit ; read ack bit
- btst #0,d2 ; test ack bit
- beq.s 2$ ; ack=0, ok
- bset.b #1,I2CStatus ; ack error
- 2$ rts
-
- ;----- Receive byte in d4 -----------------------------------------------
- ;
- ; Output: D4 byte received (long)
- ; Register modified: D0..D4, A0..A1, A6
-
- RXByte moveq #7,d3 ; bit counter
- moveq #0,d4 ; byte to be read
- 1$ bsr.s rxbit
- lsl #1,d4
- or.b d2,d4
- dbra d3,1$
- moveq #0,d2 ; transmit ack=0
- bra.s txbit
-
- ****** I2C subroutines **************************************************
-
- ; Transmit bit 7 of register D2
-
- txbit btst #7,d2 ; Transmit bit 7 of d2
- bne.s 1$
- bsr.s sda0
- bra.s 2$
- 1$ bsr.s sda1
- 2$ bsr.s scl1
- bsr shortdelay
- bra.s scl0
-
- ; Returns bit received in bit 0 of D2
-
- rxbit move #POT1,(POT) ; set SDA=1 without feedback
- bsr longdelay ; wait until SDA=1 (can't check)
- bsr.s scl1
- bsr shortdelay
- move (JOY),d2 ; read SDA (bit 1 negated)
- lsr #1,d2
- not d2
- and #1,d2
- bra.s scl0
-
- sda0 move #POT0,(POT) ; set SDA=0
- move #TIMEOUT,d0
- 1$ move (JOY),d1
- btst #1,d1
- dbne d0,1$
- bra.s TimeTest
-
- sda1 move #POT1,(POT) ; set SDA=1
- move #TIMEOUT,d0
- 1$ move (JOY),d1
- btst #1,d1
- dbeq d0,1$
- TimeTest cmp #-1,d0 ; if d0=-1 there is a timeout
- bne.s TimeOk
- bset.b #0,I2CStatus ; timeout error
- TimeOk rts
-
- scl0 bclr.b #7,(FIRE) ; set SCL=0
- move #TIMEOUT,d0
- 1$ move (JOY),d1
- btst #9,d1
- dbne d0,1$
- bra.s TimeTest
-
- scl1 bset.b #7,(FIRE) ; set SCL=0
- move #TIMEOUT,d0
- 1$ move (JOY),d1
- btst #9,d1
- dbeq d0,1$
- bra.s TimeTest
-
- ****** Timer delays *****************************************************
- ;
- ; Register modified: d0,d1,a0,a1
-
- shortdelay move.l #SHORTTIME,d0 ; short delay entry point
- bra.s delay
- longdelay move.l #LONGTIME,d0 ; long delay entry point
- delay move.l TimeReq(pc),a1 ; delay in d0 (microsec)
- moveq #TR_ADDREQUEST,d1
- move.w d1,IO_COMMAND(a1)
- moveq #0,d1
- move.l d1,(IOTV_TIME+TV_SECS)(a1)
- move.l d0,(IOTV_TIME+TV_MICRO)(a1)
- CALLEXEC DoIO
- rts
-
- ****** Save Clock *******************************************************
- ;
-
- ;----- Get system time in d0 --------------------------------------------
-
- SaveClock move.l TimeReq(pc),a1
- moveq #TR_GETSYSTIME,d1
- move.w d1,IO_COMMAND(a1)
- CALLEXEC DoIO
- move.l TimeReq(pc),a1
- move.l (IOTV_TIME+TV_SECS)(a1),d0
-
- ;----- Convert system time to date --------------------------------------
- ;
- ; Input: d0 = system_time.seconds
- ; Output: d5 = [year][month]
- ; d6 = [ hr ][ day ]
- ; d7 = [ sec][ min ]
-
- ConvFromSysTime move.b d0,d7 ; d0 = seconds from Jan,1 78
- and #3,d7 ; d7 = secs mod 4
- lsr.l #2,d0 ; d0 = secs/4
- move #21600,d1
- divu d1,d0 ; d0 = [secs/4][days]
-
- move.l d0,d2
- clr d2
- swap d2 ; d2 = secs/4
- moveq #15,d1
- divu d1,d2
- swap d2 ; d2 = [mins][sec/4]
- lsl #2,d2 ; d2 = [mins][sec]
- or d2,d7 ; d7 = sec
- swap d7 ; d7 = [sec][0]
- clr d2
- swap d2 ; d2 = [0][mins]
- moveq #60,d1
- divu d1,d2 ; d2 = [min][hr]
- move d2,d6 ; d6 = hr
- swap d6 ; d6 = [hr][0]
- swap d2 ; d2 = [hr][min]
- move d2,d7 ; d7 = [sec][min] - OK
-
- move #1978,d1 ; d0 = days, d1=year
- yloop bsr LeapCheck ; d2 = # of days of d1
- cmp d2,d0 ; days < days year ?
- bmi.s yearfound
- sub d2,d0 ; no, subtract days of this year
- addq #1,d1 ; next year
- bra.s yloop
- yearfound move d1,d5
- swap d5 ; d5 = [year][?]
- lea (DayMonth+2)(pc),a0
- cmp #366,d2 ; leap year ?
- bne.s searchmonth
- lea (DayMonthLeap+2)(pc),a0
- searchmonth move.w #1,d5 ; d5 = [year][month]
- addq #1,d0 ; days starts from 1..
- mloop cmp (a0)+,d0 ; days <= DayMonth(month) ?
- bls.s monthfound
- addi.w #1,d5 ; inc month (warning: NO QUICK!)
- bra.s mloop
- monthfound subq #4,a0 ; a0 points to month-1
- sub (a0),d0 ; d0 = day
- move d0,d6 ; d6 = [hr][day]
-
- ;----- Set configuration date -------------------------------------------
-
- move.b d6,d0 ; d0 = (day)
- lsl #8,d0 ; d0 = (day)(0)
- or.b d5,d0 ; d0 = (day)(month)
- swap d0
- move.l d5,d1
- swap d1 ; d1 = [month][year]
- move d1,d0 ; d0 = (day)(month)[year]
- move.l d0,ConfigBuffer ; save to buffer
-
- ;----- Save date/time to battery clock ----------------------------------
-
- bsr StartI2C ; initialize I2C bus
- move.b #CLK_ADDR_WR,d2 ; write mode
- bsr TXByte ; transmit address
- move.b I2CStatus(pc),d0
- bne I2CErrorStop ; bus error - Stops
- move.b d5,d2
- bsr TXByteToBCD ; transmit month
- move.b d6,d2
- bsr TXByteToBCD ; transmit day
- swap d6
- move.b d6,d2
- bsr TXByteToBCD ; transmit hour
- move.b d7,d2
- bsr TXByteToBCD ; transmit min
- bsr StopI2C
-
- move.b I2CStatus(pc),d0
- bne I2CError ; error
-
- ;----- Save configuration date ------------------------------------------
-
- moveq #1,d4 ; save mode
- moveq #RETURN_FAIL,d5 ; error code
- lea ErrNoSave(pc),a5 ; error string
- bsr OpenConfig ; save
- bra CloseExit
-
-
- ****** Load Clock *******************************************************
- ;
- ;
- ;----- Load date/time from battery clock --------------------------------
-
- LoadClock bsr StartI2C ; initialize I2C bus
- move.b #CLK_ADDR_RD,d2 ; read mode
- bsr TXByte ; transmit address
- move.b I2CStatus(pc),d0
- bne.s I2CErrorStop ; bus error - Stops
- moveq #MONTH_MASK,d5 ; month mask
- bsr RXByteFromBCD ; receive month
- move d4,-(sp) ; save month
- moveq #DAYHR_MASK,d5 ; day & hour mask
- bsr RXByteFromBCD ; recieve day
- move d4,d6
- swap d6
- bsr RXByteFromBCD ; receive hour
- move d4,d6 ; d6 = [day][hr]
- tst.l d6
- bne.s ClockSet ; ok, clock is set
- ClockNotSet bsr StopI2C ; clock is not set (day=0 & hr=0)
- moveq #RETURN_FAIL,d7
- lea ErrClkNotSet(pc),a0
- bra ErrorExit
- ClockSet moveq #MINSEC_MASK,d5 ; min & sec mask
- bsr RXByteFromBCD ; receive min
- move d4,d7
- swap d7
- bsr RXByteFromBCD ; receive sec
- move d4,d7 ; d7 = [min][sec]
- move (sp)+,d5 ; d5 = [?][month]
- bsr StopI2C ; end of I2C communication
-
- move.b I2CStatus(pc),d0
- beq.s RConfig ; status ok
- bne.s I2CError
-
- ;----- I2C error condition ----------------------------------------------
-
- I2CErrorStop bsr StopI2C ; stop I2C and exit
- I2CError moveq #RETURN_ERROR,d7 ; error code
- lea ErrNoClock(pc),a0 ; error string
- bra ErrorExit
-
- ;----- Read configuration file ------------------------------------------
-
- RConfig movem.l d5-d7,-(sp) ; save clock data
- moveq #0,d4 ; read mode
- moveq #RETURN_FAIL,d5 ; error code
- lea ErrNoConfig(pc),a5 ; error string
- bsr OpenConfig ; read config
- movem.l (sp)+,d5-d7 ; restore registers
-
- move.l ConfigBuffer(pc),d4 ; d4 = config data (cxxx)
-
- ;----- Test configuration range -----------------------------------------
-
- move.l d4,d3 ; d3 = (cday)(cmonth)[cyear]
- cmp #1978,d3 ; cyear < 1978 ?
- bpl ChkUpYBound ; no
-
- ConfigError moveq #RETURN_FAIL,d7 ; error code
- lea ErrBadData(pc),a0 ; error string
- bra ErrorExit
-
- ChkUpYBound cmp #2067,d3 ; cyear >= 2067 ?
- bpl ConfigError ; yes, error
-
- swap d3 ; d3 = (cday)(cmonth)
- tst.b d3 ; cmonth = 0 ?
- beq.s ConfigError
- cmp.b #12,d3 ; cmonth > 12 ?
- bhi.s ConfigError
- lsr #8,d3 ; d3 = (cday)
- beq.s ConfigError ; cday = 0 ?
- cmp.b #31,d3 ; cday > 31 ?
- bhi.s ConfigError
-
-
- ;----- Check if configuration file must be updated ----------------------
-
- move d4,d3 ; d3 = cyear
- swap d4 ; d4 = (cday)(cmonth)
- cmp.b d4,d5 ; month > cmonth ?
- bhi.s CheckZero ; yes, ok
- bne.s UpdateYear ; month < cmonth, update year
- lsr #8,d4 ; d4 = cday
- move.l d6,d0
- swap d0 ; d0 = [hr][day]
- cmp.b d4,d0 ; day < cday ?
- bmi.s UpdateYear ; yes, update year
-
- CheckZero move.b ConfigModified(pc),d0 ; Forced update ? (ZeroClok)
- bne.s Update ; yes, update
- bra.s SetYear ; no, skip
-
- UpdateYear addq #1,d3 ; inc year
- Update move.l d6,d2
- swap d2 ; d2 = [hr][day]
- lsl #8,d2 ; d2 = (day)(0)
- move.b d5,d2 ; d2 = (day)(month)
- swap d2
- move d3,d2 ; d2 = current date (config)
- move.l d2,ConfigBuffer ; save into config buffer
- move.b #$FF,ConfigModified ; set modified flag
-
- SetYear swap d5
- move d3,d5
- swap d5 ; d5 = [year][month]
-
- ;----- Convert to system time format ------------------------------------
- ;
- ; Input: d5 = [year][month]
- ; d6 = [ day][ hr ]
- ; d7 = [ min][ sec ]
-
-
- ConvToSysTime moveq #0,d0 ; clear d0
- move d7,d0 ; d0 = [0,sec]
- swap d7 ; d7 = [sec,min]
- move d6,d2 ; d2 = hr
- moveq #60,d1
- mulu d1,d2 ; d2 = hr*60
- add d7,d2 ; d2 = hr*60+min
- mulu d1,d2 ; d2 = hr*3600+min*60
- add.l d2,d0 ; d0 = seconds from midnight
-
- clr d6 ; d6 = [day,0]
- swap d6 ; d6 = day (long)
- subq #1,d6 ; days start from 0..
- lea (DayMonth-2)(pc),a0 ; array base pointer
- move d5,d1 ; d1 = month
- lsl #1,d1
- add (a0,d1.w),d6 ; d6 = days from Jan,1 (long)
- move d5,d3 ; d3 = month
- swap d5 ; d5 = [month,year]
- move d5,d1 ; d1 = year
- sub #1978,d5 ; d5 = year-1978
- move #365,d2
- mulu d5,d2 ; d2 = (year-1978)*365
- add d2,d6 ; d6 = days from Jan,1 1978 (no leap)
- bsr LeapCheck ; d2 = # of days of current year
- cmp #365,d2
- beq.s 1$ ; normal year
- cmp #2,d3 ; leap year: is month > feb ?
- bls.s 1$
- addq #1,d6 ; yes, add one day for current year
- 1$ cmp #2000,d1 ; year > 2000 ?
- bls.s 2$ ; no
- subq #1,d6 ; yes, sub. one day (2000 isn't leap)
- 2$ sub #1977,d1 ; compute (year-1977)/4,
- lsr #2,d1 ; number of leap years from 1978
- add d1,d6 ; d6 = # of days from Jan,1 78 - OK
- move #21600,d2
- mulu d2,d6
- lsl.l #2,d6 ; d6 converted in secs (*86400)
- add.l d6,d0 ; d0 = # of secs from Jan,1 78 - OK
-
- ;----- Set system time --------------------------------------------------
-
- SetSystemTime move.l TimeReq(pc),a1
- moveq #TR_SETSYSTIME,d1
- move.w d1,IO_COMMAND(a1)
- move.l d0,(IOTV_TIME+TV_SECS)(a1)
- moveq #0,d1
- move.l d1,(IOTV_TIME+TV_MICRO)(a1)
- CALLEXEC DoIO
-
- ;----- Check if configuration file must be saved ------------------------
-
- move.b ConfigModified(pc),d0
- beq.s LBye ; not modified, exits
- moveq #1,d4 ; mode = save
- moveq #RETURN_WARN,d5 ; error code
- lea ErrNoSave(pc),a5 ; error string
- bsr OpenConfig ; save data
- LBye bra CloseExit ; exits
-
-
- ****** Zero clock *******************************************************
-
- ZeroClock bsr StartI2C ; initialize I2C bus
- move.b #CLK_ADDR_WR,d2 ; write mode
- bsr TXByte ; transmit address
- bsr StopI2C
-
- move.b I2CStatus(pc),d0
- bne I2CError ; error
-
- move.b #$FF,ConfigModified ; force update
- bra LoadClock
-
-
- ****** Leap check *******************************************************
- ;
- ; Input : D1 year
- ; Output: D2 number of days of year D1
- ; Registers modified: D2
-
- LeapCheck move.l d1,-(sp) ; save d1
- move #365,d2
- cmp #2000,d1
- beq.s 1$ ; year 2000 is not leap
- and #3,d1 ; check if year divisible by 4
- bne.s 1$
- addq #1,d2 ; yes, it's a leap year: 366 days
- 1$ move.l (sp)+,d1 ; restore d1
- rts
-
- end
-