; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; > $.Source.PMF.realtime ; ***************************************************************************** ; ; CheckYear - Check for year wrap (year in RTC <> year "YearCMOS") ; and for leap year fudging ; CheckYear ROUT Push "R0,R1,R2,R14" LDR R0, =ZeroPage LDR R0, [R0, #RTCFitted] [ HAL CMP R0, #2048 [ RTCSupport BLO %FT8 | BLO %FT15 ] ; Ask the RTC what it thinks the year is Push "R3,R10,R12" MOV R10, R0 SUB R13, R13, #RTCTimeStruct_BCD_Size MOV R1, R13 ADRL R2, HALRTC_IICOp MOV LR, PC LDR PC, [R0, #HALDevice_RTCReadTime] ; Did we succeed? CMP R0, #RTCRetCode_OK LDRB R0, [R13, #RTCTimeStruct_BCD_YearLO] LDRB R1, [R13, #RTCTimeStruct_BCD_YearHI] ADD R13, R13, #RTCTimeStruct_BCD_Size LDRB R2, [R10, #HALDevice_RTCFormatFlags] Pull "R3,R10,R12" BNE %FT15 ASSERT RTCFormatFlags_BCD_NeedsYearHelp = 1 :SHL: 2 ASSERT RTCFormatFlags_BCD_YearLOIsGood = 1 :SHL: 3 AND LR, R2, #RTCFormatFlags_BCD_NeedsYearHelp + RTCFormatFlags_BCD_YearLOIsGood MOVS LR, LR, ROR #3 ; CC = good, CS+EQ = 2 bit, CS+NE = BCD ADDCS R1, LR, #RTCAddressPHI+1 ; 2 bit=RTCAddressPHI+1, BCD!=RTCAddressPHI+1 BCS %FT9 ; Year is reliable; convert R0 & R1 to ints and update CMOS if necessary. BL BCDToHex MOV R2, R1 MOV R1, R0 ; YearLO MOV R0, #YearCMOS BL Read CMP R0, R1 MOVNE R0, #YearCMOS BLNE Write MOV R0, R2 BL BCDToHex MOV R1, R0 ; YearHI MOV R0, #YearCMOS+1 BL Read CMP R0, R1 MOVNE R0, #YearCMOS+1 BLNE Write B %FT15 8 ] ; HAL [ RTCSupport :LOR: :LNOT: HAL TEQ R0, #RTCAddressPHI MOVEQ R1, #5 MOVNE R1, #6 ; year address (dependant on RTC) STRB R1, [R13, #-4]! MOV R1, R13 ORR R0, R0, #1:SHL:29 MOV R2, #1 BL IIC_Op ORR R0, R0, #1 BL IIC_Op AND R1, R0, #&FF LDRB R0, [R13], #4 TEQ R1, #RTCAddressPHI+1 ] ; RTCSupport :LOR: :LNOT: HAL 9 MOVEQ R0, R0, LSR #6 ; R0= year MOD 4. BLNE BCDToHex MOV R2, R0 ; remember RTC value MOV R0, #YearCMOS BL Read TEQ R1, #RTCAddressPHI+1 ANDEQ R1, R0, #3 MOVNE R1, R0 MOVEQ R14,#4 MOVNE R14,#100 SUBS R2, R2, R1 ; same year ? Pull "R0,R1,R2,PC", EQ ; [yes, so no bother] ADDCC R2, R2, R14 ; if lower, then must be carry ADD R2, R0, R2 ; new year value CMP R2, #100 BCC %FT10 ; no carry thru to next century SUB R2, R2, #100 MOV R0, #YearCMOS +1 BL Read ADD R1, R0, #1 TEQ R1, #100 MOVEQ R1, #0 ; wrap century MOV R0, #YearCMOS +1 BL Write 10 MOV R1, R2 MOV R0, #YearCMOS BL Write 15 BL RTCToRealTime Pull "R0,R1,R2,PC" ; ***************************************************************************** ; ; RTCToRealTime - Set RealTime from actual RTC ; ; in: R12 -> BYTEWS ; out: all registers preserved ; [ {FALSE} Construct5Byte ROUT Push R14 B Construct5ByteEntry ] RTCToRealTime ROUT Push "R0-R9, R14" BL ReadTime ; R0 := hours, R1 := minutes ; R2 := days, R3 := months ; R5 := year(lo), R6 := year(hi) ; R7 := seconds, R8 := centiseconds ; R0 will be negative on error. Just skip the update. CMP R0,#0 Pull "R0-R9, PC",LT BL ConvertTo5Byte BL Store5ByteInRealTime Pull "R0-R9, PC" RegToRealTime ROUT Push "R0-R9, R14" BL ConvertTo5Byte BL Store5ByteInRealTime Pull "R0-R9, PC" ConvertTo5Byte ROUT Push R14 MOV R4, R5 ; R4 := year MOD 100 MOV R5, R6 ; R5 := year DIV 100 MOV R6, R7 ; R6 := seconds MOV R7, R8 ; R7 := centiseconds Construct5ByteEntry MOV R9, #24 SUB R2, R2, #1 ; decrement day (day=1 => nowt to add) MLA R0, R9, R2, R0 ; R0 = hours + day*24 MOV R9, #60 MLA R1, R0, R9, R1 ; R1 = mins + hours*60 MLA R6, R1, R9, R6 ; R6 = secs + mins*60 MOV R9, #100 MLA R7, R6, R9, R7 ; R7 = centisecs + secs*100 ADR R0, STMonths-4 ; Point to table (month = 1..12) LDR R1, [R0, R3, LSL #2] ; get word of offset ADD R7, R7, R1 ; add to total ; if not had leap day in this year yet, then exclude this year from the ; leap day calculations CMP R3, #3 ; if month >= 3 SBCS R0, R4, #0 ; then R0,R1 = R4,R5 MOVCC R0, #99 ; else R0,R1 = R4,R5 -1 SBC R1, R5, #0 ; want (yl+100*yh) DIV 4 - (yl+100*yh) DIV 100 + (yl+100*yh) DIV 400 ; = (yl DIV 4)+ (25*yh) - yh + (yh DIV 4) ; = (yl >> 2) + 24*yh + (yh >> 2) MOV R0, R0, LSR #2 ; yl >> 2 ADD R0, R0, R1, LSR #2 ; + yh >> 2 ADD R0, R0, R1, LSL #4 ; + yh * 16 ADD R0, R0, R1, LSL #3 ; + yh * 8 ; now subtract off the number of leap days in first 1900 years = 460 SUBS R0, R0, #460 BCC BadYear ; before 1900, so bad CMP R0, #86 ; if more than 86 days, then it's BCS BadYear ; after 2248, so bad LDR R9, =ticksperday ; multiply by ticksperday and add to MLA R7, R9, R0, R7 ; total (no overflow possible as this ; can never be more than 85+31 days) ; now add on (year-1900)*ticksperyear SUBS R5, R5, #19 ; subtract off 1900 BCC BadYear MOV R9, #100 MLA R4, R9, R5, R4 ; R4 = year-1900 LDR R0, =ticksperyear ; lo word of amount to add on MOV R1, #0 ; hi word of amount to add on MOV R8, #0 ; hi word of result 10 MOVS R4, R4, LSR #1 BCC %FT15 ADDS R7, R7, R0 ; if bit set then add on amount ADCS R8, R8, R1 BCS BadYear ; overflow => bad time value 15 ADDS R0, R0, R0 ; shift up amount ADCS R1, R1, R1 TEQ R4, #0 ; if still bits to add in BNE %BT10 ; then loop CMP R8, #&100 ; R8 must only be a byte Pull PC, CC BadYear MOV R7, #-1 MOV R8, #-1 Pull PC Store5ByteInRealTime Push R14 PHPSEI ; disable IRQs for this bit STR R7, RealTime +0 STRB R8, RealTime +4 [ :LNOT: AssemblingArthur :LAND: :LNOT: Module ; for now, also put into normal time LDRB R0, TimerState TEQ R0, #5 ADREQ R3, TimerAlpha +0 ADRNE R3, TimerBeta +0 STR R7, [R3] STRB R8, [R3, #4] ] PLP Pull PC ; ***************************************************************************** tickspersecond * 100 ticksperminute * tickspersecond * 60 ticksperhour * ticksperminute * 60 ticksperday * ticksperhour * 24 ticksperyear * ticksperday * 365 ; &BBF81E00 STMonths & &00000000 ; Jan & &0FF6EA00 ; Feb & &1E625200 ; Mar & &2E593C00 ; Apr & &3DCC5000 ; May & &4DC33A00 ; Jun & &5D364E00 ; Jul & &6D2D3800 ; Aug & &7D242200 ; Sep & &8C973600 ; Oct & &9C8E2000 ; Nov & &AC013400 ; Dec & &F0000000 ; terminator, must be less than this (+1) LTORG END