;******************************************************************
;* *
;* Day_of_Week, 2000-2099 Mike McLaren, K8LH, Aug '07 *
;* *
;* preset: Month (1..12), Day (1..31), Year (0..99) vars' *
;* return: W = 0..6 (Sun..Sat) *
;* *
;* 39 words, 1 local variable (14 bit core) *
;******************************************************************
radix dec
;
; char Month; // 1..12
; char Day; // 1..31
; char Year; // 0..99 (2000-2099)
;
; char DayOfWeek() // Mike McLaren, K8LH, Aug '07
; { // returns 0..6 (Sun..Sat)
; char Leap;
; const rom char Base[] = { 5, 1, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3 };
; Leap = (Year & 3) || (Month > 2);
; return (Base[Month-1] + Day + Leap + Year + Year/4) % 7;
; }
;
DayOfWeek
clrf Leap ; Leap = 0 |B0
movf Month,W ; get 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 (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. the "in-
; line table" is 256-byte-boundary tolerant.
;
; WREG = Y2000[Month-1]
;
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 Leap (0 or 1), C=0 |B0
rlf Leap,F ; multiply by 2, C=0 |B0
rrf Year,W ; divide year by 2 |B0
addwf Leap,F ; add 'em together, C=0 |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 ; W = 0..6 (Sun..Sat) |B0
;