realtime 10.7 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
; 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

17 18
; *****************************************************************************
;
19
;       SWI OS_ResyncTime
20
;
21 22 23 24 25 26 27 28 29 30 31 32 33
; in:   r0  = 0 - Real time clock soft copy only
;       r0 <> 0   reserved for future expansion
; out:  registers preserved
;    or VS and R0 -> error
;
ResyncTimeSWI ROUT
        Push    "R1, R12, LR"
        BYTEWS  WsPtr
        BL      RTCToRealTime
        MOVVC   R1, #Service_RTCSynchronised
        BLVC    Issue_Service
        Pull    "R1, R12, LR"
        B       SLVK_TestV
34

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
; *****************************************************************************
;
;       SetTime - Write the CMOS clock time and update 5-byte RealTime
;
; in:   UTC time:
;       R0 = hours
;       R1 = minutes
;       R2 = day of month (1-based)
;       R3 = month (1-based)
;       R5 = year (lo)
;       R6 = year (hi)
;       R7 = seconds
;       R8 = centiseconds
; out:  registers preserved
;    or VS and R0 -> error
;
;       If R0,R2,R5 or R6 is -1 then the time,date,year,century (respectively) will not be written.
;       However if R2=-1, R5 & R6 will also be -1, so only R0 (for time) and R2 (for D/M/Y) need checking.
;

SetTime ROUT
        Push    "R4, R9, LR"

        ; Prepare BCD data on stack
        ASSERT  (RTCTimeStruct_Size :AND: 3)=0
        SUB     R13, R13, #RTCTimeStruct_Size
        MOV     R9, R13
        MOV     R4, R0

        ; Ensure struct matches our setting order
        ASSERT  RTCTimeStruct_Centiseconds = 0
        ASSERT  RTCTimeStruct_Seconds = 1
        ASSERT  RTCTimeStruct_Minutes = 2
        ASSERT  RTCTimeStruct_Hours = 3
        ASSERT  RTCTimeStruct_DayOfMonth = 4
        ASSERT  RTCTimeStruct_Month = 5
        ASSERT  RTCTimeStruct_YearLO = 6
        ASSERT  RTCTimeStruct_YearHI = 7

        ; Are we setting the time?
        CMP     R4, #-1
        STREQ   R4, [R9], #4 ; Conveniently, 4 bytes of time info
        BEQ     %FT11
        MOV     R0, R8
        BL      HTBS9
        MOV     R0, R7
        BL      HTBS9
        MOV     R0, R1
        BL      HTBS9
        MOV     R0, R4
        BL      HTBS9
11
        ; Are we setting the date?
        CMP     R2, #-1
        STREQ   R2, [R9], #4 ; Conveniently, 4 bytes of date info
        BEQ     %FT12
91
        MOV     R0, R2
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
        BL      HTBS9
        MOV     R0, R3
        BL      HTBS9
        MOV     R0, R5
        BL      HTBS9
        MOV     R0, R6
        BL      HTBS9
12
        MOV     R0, SP
        SWI     XRTC_Write              ; Try update hardware

        MOV     R0, R4
        BL      RegToRealTime           ; Update soft copy regardless

        CLRV
        ADD     SP, SP, #RTCTimeStruct_Size
        Pull    "R4, R9, PC"

; *****************************************************************************
;
;       ReadTime - Read the CMOS clock time
;
; in:   -
; out:  R0 = hours
;       R1 = minutes
;       R2 = day of month (1-based)
;       R3 = month (1-based)
;       R5 = year (lo)
;       R6 = year (hi)
;       R7 = seconds
;       R8 = centiseconds
;    or VS and R0 -> error

ReadTime ROUT
        Push    "LR"

        ; Receive BCD data on stack
        ASSERT  (RTCTimeStruct_Size :AND: 3)=0
        SUB     R13, R13, #RTCTimeStruct_Size
        MOV     R0, R13
        SWI     XRTC_Read
        ADDVS   R13, R13, #RTCTimeStruct_Size
        Pull    "PC",VS

        ; Now convert the BCD ordinals
        LDRB    R0, [R13, #RTCTimeStruct_Centiseconds]
138
        BL      BCDToHex
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
        MOV     R8, R0                  ; centiseconds
        LDRB    R0, [R13, #RTCTimeStruct_Seconds]
        BL      BCDToHex
        MOV     R7, R0                  ; seconds
        LDRB    R0, [R13, #RTCTimeStruct_Minutes]
        BL      BCDToHex
        MOV     R1, R0                  ; minutes
        LDRB    R0, [R13, #RTCTimeStruct_DayOfMonth]
        BL      BCDToHex
        MOV     R2, R0                  ; days
        LDRB    R0, [R13, #RTCTimeStruct_Month]
        BL      BCDToHex
        MOV     R3, R0                  ; months
        LDRB    R0, [R13, #RTCTimeStruct_YearLO]
        BL      BCDToHex
        MOV     R5, R0                  ; year lo
        LDRB    R0, [R13, #RTCTimeStruct_YearHI]
        BL      BCDToHex
        MOV     R6, R0                  ; year hi
        LDRB    R0, [R13, #RTCTimeStruct_Hours]
        BL      BCDToHex
                                        ; hours
        CLRV

        ; We're done with our stack data, remove it
        ADD     R13, R13, #RTCTimeStruct_Size
        Pull    "PC"
166

Neil Turton's avatar
Neil Turton committed
167 168 169 170 171 172
; *****************************************************************************
;
;       RTCToRealTime - Set RealTime from actual RTC
;
; in:   R12 -> BYTEWS
; out:  all registers preserved
173
;    or VS and R0 -> error
Neil Turton's avatar
Neil Turton committed
174 175 176
;

RTCToRealTime ROUT
177
        Push    "R0-R9, LR"
Neil Turton's avatar
Neil Turton committed
178 179 180 181
        BL      ReadTime                ; R0 := hours, R1 := minutes
                                        ; R2 := days, R3 := months
                                        ; R5 := year(lo), R6 := year(hi)
                                        ; R7 := seconds, R8 := centiseconds
182
        BVS     %FT10
Neil Turton's avatar
Neil Turton committed
183 184
        BL      ConvertTo5Byte
        BL      Store5ByteInRealTime
185 186 187
        CLRV
10
        STRVS   R0, [SP, #0]
Neil Turton's avatar
Neil Turton committed
188 189
        Pull    "R0-R9, PC"

190 191 192 193 194 195 196 197 198
; *****************************************************************************
;
;       RegToRealTime - Set RealTime from a bunch of registers
;
; in:   R12 -> BYTEWS
;       R0-R3, R5-R8 = validated time and date
; out:  all registers preserved
;

Neil Turton's avatar
Neil Turton committed
199
RegToRealTime ROUT
200
        Push    "R0-R9, LR"
Neil Turton's avatar
Neil Turton committed
201 202 203 204
        BL      ConvertTo5Byte
        BL      Store5ByteInRealTime
        Pull    "R0-R9, PC"

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
; *****************************************************************************
;
;       Store5ByteInRealTime - put 5 byte centisecond UTC time into soft copy
;
; in:   R7 = low word of time
;       R8 = high byte of time
;       R12 -> BYTEWS
; out:  all registers preserved
;

Store5ByteInRealTime
        Push    "LR"
        PHPSEI                          ; disable IRQs for this bit
        STR     R7, RealTime +0
        STRB    R8, RealTime +4
        PLP
        Pull    "PC"

; *****************************************************************************
;
;       ConvertTo5Byte - Convert ordinals to 5 byte time
;
; in:   R12 -> BYTEWS
;       R0-R3, R5-R8 = time and date
; out:  R7 = low word
;       R8 = high byte
;    or R7 = R8 = -1 if conversion failed
;

Neil Turton's avatar
Neil Turton committed
234
ConvertTo5Byte ROUT
235
        Push    "LR"
Neil Turton's avatar
Neil Turton committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306

        MOV     R4, R5                  ; R4 := year MOD 100
        MOV     R5, R6                  ; R5 := year DIV 100
        MOV     R6, R7                  ; R6 := seconds
        MOV     R7, R8                  ; R7 := centiseconds

        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
307
        Pull    "PC",CC
Neil Turton's avatar
Neil Turton committed
308 309 310 311

BadYear
        MOV     R7, #-1
        MOV     R8, #-1
312
        Pull    "PC"
Neil Turton's avatar
Neil Turton committed
313 314 315 316 317 318 319 320 321 322

; *****************************************************************************

tickspersecond  * 100
ticksperminute  * tickspersecond * 60
ticksperhour    * ticksperminute * 60
ticksperday     * ticksperhour   * 24
ticksperyear    * ticksperday    * 365  ; &BBF81E00

STMonths
323 324 325 326 327 328 329 330 331 332 333 334 335
        DCD     &00000000       ; Jan
        DCD     &0FF6EA00       ; Feb
        DCD     &1E625200       ; Mar
        DCD     &2E593C00       ; Apr
        DCD     &3DCC5000       ; May
        DCD     &4DC33A00       ; Jun
        DCD     &5D364E00       ; Jul
        DCD     &6D2D3800       ; Aug
        DCD     &7D242200       ; Sep
        DCD     &8C973600       ; Oct
        DCD     &9C8E2000       ; Nov
        DCD     &AC013400       ; Dec
        DCD     &F0000000       ; terminator, must be less than this (+1)
Neil Turton's avatar
Neil Turton committed
336 337 338 339

        LTORG

        END