Hi Guys,
Here’s my 500 year calendar that can be used with Darrel Taylor’s Elapsed Timer routines (when used as a clock).
There’s a video demonstration coming up shortly 
This can save you a RTC/Calendar Chip such as Maxim/Dallas 1307/1302 when you are already using the clock routine.
The DS1307 is only accurate to the year 2100, where I have checked accuracy against iOS in the range 1800-2300.
Usage:
Set your variables calday, calmonth, calyear with the input numbers and call setcal subroutine.
If the date made sense, and the year was within range 1800-2300 the flag calbadentry will be zero.
If the year was out of range or you used a number that was too high for day or months (i.e. entered 29th of Feb when it was not a leap year),
the number for day or month will be set to 1, and the value for calbadentry will be 1
for your program to throw an error.
If the year is out of range it gets adjusted back to the upper or lower limit.
The variable caldow will contain the day of the week where zero is Sunday through to 6 for Saturday.
From there you can just check the value of DayChanged with he provided code waiting for the day to change,
and the program routine will increment the date and weekday each day.
The lookup table epochyears contains 12 years that begin on a Monday to make the calendar faster.
The calendar routine only has to iterate from the closest year before the current year the user input.
During testing the weekday and leap year routines were tested against the stock iPhone calendar App.
Implementation:
In the Elasped.bas file, add the DayChanged bit like so:
Code:
TicksChanged var bit
SecondsChanged var bit
DayChanged var bit
You will also need to make a small change to the sequence that increments the time variables
to wrap around after 24 hours (if you haven’t done so for a clock already),
and set the DayChanged status every 24 hours.
Code:
Ticks = Ticks + 1
if Ticks = 100 then
Ticks = 0
Seconds = Seconds + 1
SecondsChanged = 1
if Seconds = 60 then
Seconds = 0
Minutes = Minutes + 1
endif
if Minutes = 60 then
Minutes = 0
Hours = Hours + 1
endif
if Hours = 24 then <————
Hours = 0
DayChanged = 1 ‘ <—————
endif
endif
In your own main program file, declare some calendar variables:
Code:
caldim var byte [12] ' calendar days in months
calday var word ' calendar day
calmonth var word ' calendar month
calyear var word ' calendar year
caldow var byte ' calendar day of the week
calleap var bit ' current year leap status bit
calbadentry var bit ' bad calendar input flag
cacnt var word ' counter for calendar
cwork var word ' work buffer for calendar
xwork var word ' work buffer for calendar
calleapx var bit ' leap year buffer for calendar
reset some variables in a place that is only run once at startup,
and set a default date (be sure the date is in range 1800-2300.
Code:
calyear = 2015 ' set default date to 01/01/2015
calday = 0 ' day is incremented to 1 at startup
DayChanged = 1 ' because this day changed flag is set
calmonth = 1 ' month defaults to January
Now somewhere in your main program that cycles, check this code regularly:
Code:
‘ program initialisation
‘ tris something = something
‘ some flag = 0
calyear = 2015 ' set default date to 01/01/2015
calday = 0 ' day is incremented to 1 at startup
DayChanged = 1 ' because this day changed flag is set
calmonth = 1 ' month defaults to January
main:
‘ your main program..
' increment date if day changed over
'
if DayChanged = 1 then
calday = calday + 1
if calday > caldim[calmonth-1] then
calday = 1
calmonth = calmonth + 1
endif
if calmonth > 12 then
calmonth = 1
calyear = calyear + 1
endif
'
DayChanged = 0
gosub setcal
endif ' DayChanged
'
‘
goto main
‘
This is the calendar that is called as a subroutine called “setcal”:
Code:
‘
‘
‘ 500 year calendar for pic (tested with 16F877A) by Brek Martin (Art) 2015.
‘
‘ This is free software. Please credit the author if it’s reused or distributed.
'
' ******************* set calendar date and find day of week *******************
'
setcal: ' find leap year status
caldim[0] = 31 ' set default days in month table
caldim[1] = 28 ' days in February is changed to 29 by the program
caldim[2] = 31 '
caldim[3] = 30 '
caldim[4] = 31 '
caldim[5] = 30 '
caldim[6] = 31 '
caldim[7] = 31 '
caldim[8] = 30 '
caldim[9] = 31 '
caldim[10] = 30 '
caldim[11] = 31 '
'
calleap = 0 ' clear leap year status
if calyear // 4 = 0 then '
calleap = 1 ' set leap year status
if calyear // 100 = 0 then '
calleap = 0 ' clear leap year status
if calyear // 400 = 0 then '
calleap = 1 ' set leap year status
endif '
endif '
endif '
'
if calleap = 1 then '
caldim[1] = 29 '
endif '
'
calbadentry = 0 ' reset calendar bad entry status
if calmonth = 0 then ' check for invalid date input
calbadentry = 1 '
calmonth = 1 '
endif '
if calmonth > 12 then '
calbadentry = 1 '
calmonth = 1 '
endif '
if calday = 0 then '
calbadentry = 1 '
calday = 1 '
endif '
if calday > caldim[calmonth-1] then
calbadentry = 1 '
calday = 1 '
endif '
if calyear < 1800 then ' implement lower year range restriction
calbadentry = 1 ' prevent far away dates slowing program down
calyear = 1800 '
endif '
if calyear > 2300 then ' implement higher year range restriction
calbadentry = 1 ' in case of errors far into the future
calyear = 2300 '
endif ' the hardware probably won't last that long
'
' day of week
'
xwork = 2310 ' find best epoch year to iterate from
cacnt = 12 '
while xwork >= calyear '
gosub epochyears '
cacnt = cacnt - 1 '
wend '
'
'
cwork = 0 ' working variable for days
'
for cacnt = xwork to calyear - 1' iterate years from epoch year
calleapx = 0 ' clear leap year status
if cacnt // 4 = 0 then '
calleapx = 1 ' set leap year status
if cacnt // 100 = 0 then '
calleapx = 0 ' clear leap year status
if cacnt // 400 = 0 then '
calleapx = 1 ' set leap year status
endif '
endif '
endif '
'
if calleapx = 0 then ' add days over the years from epoch
cwork = (cwork + 365)//7 '
else '
cwork = (cwork + 366)//7 '
endif '
'
next cacnt '
'
if calleap = 1 then ' fix day of month table for current year
caldim[1] = 29 '
else '
caldim[1] = 28 '
endif '
'
cacnt = calmonth-1 ' add days for elapsed months of current year
while cacnt > 0 '
xwork = caldim[cacnt-1] '
cwork = (cwork + xwork)//7 '
cacnt = cacnt - 1 '
wend '
'
cacnt = calday-1 ' add days elapsed of current month
xwork = 0 '
while cacnt > 0 '
xwork = xwork + 1 '
cacnt = cacnt - 1 '
wend '
cwork = (cwork + xwork)//7 '
'
'
caldow = cwork + 1 ' shift range for display so 0=Sunday, 6=Saturday.
if caldow = 7 then caldow = 0 '
return
'
'
epochyears:
lookup2 cacnt,[1798,1849,1900,1951,1990,2035,2052,2091,2125,2153,2198,2227,2244],xwork
return
'
Cheers, Art.
Bookmarks