Mike - K8LH
Well-Known Member
Thought I'd share a DayOfWeek() algorithm I put together after studying some examples on the Internet. I needed the routine to light up the day-of-week LEDs on my Techie' BCD Clock kit and thought it might be useful to some of the others building PIC clocks. It might also be handy for displaying Mon, Tue, Wed, etc., on someones dot-matrix or LCD Clock/Calendar project.
Have fun. Regards, Mike
Have fun. Regards, Mike
Code:
;******************************************************************
;* *
;* Day_of_Week, 2000-2099 Mike McLaren, K8LH, Aug '07 *
;* *
;* params: Month (1..12), Day (1..31), Year (0..99) *
;* output: W = 0..6 (Sun..Sat) *
;* *
;* 39 words (14 bit core) *
;******************************************************************
radix dec
;
; char Month; // 1..12
; char Day; // 1..31
; char Year; // 0..99 (2000-2099)
;
; char DayOfWeek()
; { // returns 0..6 (Sun..Sat)
; char Leap;
; char Y2000 [] = { 5, 1, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3 };
; Leap = (Year & 3) || (Month > 2);
; return (Y2000[Month-1] + Day + Leap + Year + Year/4) % 7;
; }
;
DayOfWeek
clrf Leap ; Leap = 0 |B0
movf Month,W ; W = Month (1..12) |B0
addlw -3 ; C = 0 if Jan or Feb |B0
movf Year,W ; W = Year (0..99) |B0
andlw b'00000011' ; is this a leap year? |B0
skpz ; yes, skip, else |B0
setc ; set C (will force Leap = 1) |B0
rlf Leap,F ; Leap = 0 or 1 |B0
;
; an "in-line" table of DOW values minus 1 for the 1st of each
; month in 2000, a leap year. 1st param is desired value, 2nd
; param cancels out WREG, and 3rd param cancels out next table
; entry. an "in-line" table saves me 1 word and 1 stack level
; but uses more cycles for lower table index values. table is
; 256-byte-boundary tolerant.
;
movlw high (Y2000) ; |B0
movwf PCLATH ; |B0
decf Month,W ; |B0
addlw low (Y2000) ; |B0
skpnc ; |B0
incf PCLATH,F ; |B0
movwf PCL ; |B0
Y2000 xorlw 5^$^(1^$+1) ; 6 (Jan 2000) |B0
xorlw 1^$^(1^$+1) ; 2 (Feb) |B0
xorlw 1^$^(4^$+1) ; 2 (Mar) |B0
xorlw 4^$^(6^$+1) ; 5 (Apr) |B0
xorlw 6^$^(2^$+1) ; 0 (May) |B0
xorlw 2^$^(4^$+1) ; 3 (Jun) |B0
xorlw 4^$^(0^$+1) ; 5 (Jul) |B0
xorlw 0^$^(3^$+1) ; 1 (Aug) |B0
xorlw 3^$^(5^$+1) ; 4 (Sep) |B0
xorlw 5^$^(1^$+1) ; 6 (Oct) |B0
xorlw 1^$^(3^$+1) ; 2 (Nov) |B0
xorlw 3^$ ; 4 (Dec) |B0
;
; WREG = (((Y2000[Month-1] + Day + Leap)*2 + Year/2)/2 + Year) % 7
;
addwf Day,W ; add Day (1..31) |B0
addwf Leap,F ; add Leapday (0 or 1) |B0
rlf Leap,F ; multiply by 2 |B0
rrf Year,W ; divide year by 2 |B0
addwf Leap,F ; add 'em together |B0
rrf Leap,W ; divide result by 2 |B0
addwf Year,W ; add Year (0..99) |B0
Mod7 addlw -7 ; result % 7 |B0
bc Mod7 ; |B0
addlw 7 ; |B0
return ; |B0
;******************************************************************
Last edited: