; Author: Pawel Jablonski ; E-mail: pj@xirx.net ; WWW: xirx.net ; GIT: git.xirx.net ; ; License: You can use this code however you like ; but leave information about the original author. ; Code is free for non-commercial and commercial use. map ../../../bin/rom/rom.map ; Date change message const changedMessage "Date has been changed" ; Error messages const errorMessageLine0 "Date has wrong format" const errorMessageLine1 "Please use: YYMMDDhhmmss" ; Prefix for year const yearPrefix "20" ; First label is the entry point .entry: call .main ret ; Arguments ; X - Arguments address low ; Y - Arguments address high ; No return .main: push A push X push Y ; Check length of arguments call .xStringLength ; Print current date and time if argument list is empty cmp 0, A je .main_print ; Parse arguments call .parseDate ; Write new date nad time if arguments are correct cmp 0, A jne .main_write ; Load address to first line of error message mov low(*errorMessageLine0), X mov high(*errorMessageLine0), Y ; Print first line of error message call .xStringPrint call .xStringNewLine call .xStringNewLine ; Load address to second line of error message mov low(*errorMessageLine1), X mov high(*errorMessageLine1), Y ; Print second line of error message call .xStringPrint pop Y pop X pop A ret ; Write date and time to RTC .main_write: ; Write date and time to RTC buffers call .writeDate ; Write date and time from RTC buffers to RTC call .xRTCWrite ; Load address to message mov low(*changedMessage), X mov high(*changedMessage), Y ; Print message call .xStringPrint call .xStringNewLine call .xStringNewLine ; Print date and time from RTC .main_print: ; Read date and time from RTC to RTC buffers call .xRTCRead ; Print current date and time call .printDate pop Y pop X pop A ret ; Buffer for parse and write var year var month var day var hour var minute var second ; No arguments ; Return: ; A - success (0 - error, 1 - ok) .parseDate: push B push X push Y ; Check length of arguments call .xStringLength ; Good input should has 12 characters cmp 12, A jne .parseDate_error ; Good input should has only digits call .parseDigits cmp 0, A je .parseDate_error ; Converting two digits to year call .convertTwoDigits str A, *year ; Move to next field add 2, X incc Y ; Converting two digits to month call .convertTwoDigits ; Months are 1 to 12 cmp 1, A ; 1 > A jg .parseDate_error cmp 12, A ; 12 < A jl .parseDate_error str A, *month ; Move to next field add 2, X incc Y ; Converting two digits to day call .convertTwoDigits ; Days start from 1 cmp 1, A ; 1 > A jg .parseDate_error mov A, B push B ; Calculating quantity of days for selected year and month ldr *year, A ldr *month, B call .getDaysInMonth pop B xchg A, B ; Day number could not be higher than quantity of days in month cmp B, A ; B < A jl .parseDate_error str A, *day ; Move to next field add 2, X incc Y ; Hours are 0 to 23 call .convertTwoDigits cmp 23, A ; 23 < A jl .parseDate_error str A, *hour ; Move to next field add 2, X incc Y ; Minutes are 0 to 59 call .convertTwoDigits cmp 59, A ; 59 < A jl .parseDate_error str A, *minute ; Move to next field add 2, X incc Y ; Seconds are 0 to 59 call .convertTwoDigits cmp 59, A ; 59 < A jl .parseDate_error str A, *second mov 1, A pop Y pop X pop B ret ; Parse ends with error .parseDate_error: mov 0, A pop Y pop X pop B ret ; Days in month table const daysNumber 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ; Arguments: ; A - year ; B - month ; Return: ; A - days in month .getDaysInMonth: push B push X push Y ; Check an extra day for February cmp 2, B jne .getDaysInMonth_notLeapYear ; Years divisible by 4 are leap years and 0b11, A cmp 0, A jne .getDaysInMonth_notLeapYear ; Set 29 days if it is Februray in leap year mov 29, A jmp .getDaysInMonth_end ; Select days quanity of month .getDaysInMonth_notLeapYear: mov low(*daysNumber), X mov high(*daysNumber), Y dec B add B, X incc Y ldf A .getDaysInMonth_end: pop Y pop X pop B ret ; Arguments: ; X - low address ; Y - high address ; Return: ; A - success (0 - error, 1 - ok) .parseDigits: push B push X push Y ; Clear loop counter clr B ; Check every char .parseDigits_Loop: ; Load char from buffer ldr A ; It must be '0' or higher cmp '0', A ; '0' > A jg .parseDigits_Error ; It must be '9' or lower cmp '9', A ; '9' < A jl .parseDigits_Error ; Move to next char inc X incc Y ; Repeat 11+1 times loope 11, B, .parseDigits_Loop ; All chars are digits mov 1, A pop Y pop X pop B ret ; One or more chars are not digit .parseDigits_Error: mov 0, A pop Y pop X pop B ret ; Converting table number from string to hex const convertTable 00, 10, 20, 30, 40, 50, 60, 70, 80, 90 ; Arguments: ; X - low address ; Y - high address ; Return: ; A - number .convertTwoDigits: push B push X push Y ; Load first digit ldr B ; Convert from char to number sub '0', B ; Move to next digit inc X incc Y ; Load second digit ldr A ; Convert from char to number sub '0', A ; Set address to converting table mov low(*convertTable), X mov high(*convertTable), Y ; Calc number to take add B, X incc Y ; Load number from table ldf B ; Add number from table to the second digit add B, A pop Y pop X pop B ret ; No arguments ; No return .writeDate: push A ; Load year from buffer ldr *year, A ; Write year to RTC buffer call .xRTCSetYear ; Load month from buffer ldr *month, A ; Write month to RTC buffer call .xRTCSetMonth ; Load day from buffer ldr *day, A ; Write day to RTC buffer call .xRTCSetDay ; Load hour from buffer ldr *hour, A ; Write hour to RTC buffer call .xRTCSetHour ; Load minute from buffer ldr *minute, A ; Write minute to RTC buffer call .xRTCSetMinute ; Load second from buffer ldr *second, A ; Write second to RTC buffer call .xRTCSetSecond pop A ret ; No arguments ; No return .printDate: push A push X push Y ; Load address to prefix mov low(*yearPrefix), X mov high(*yearPrefix), Y ; Print prefix call .xStringPrint ; Read year call .xRTCGetYear ; Print year call .printTwoDigits mov '.', A call .xStringPrintChar ; Read month call .xRTCGetMonth ; Print month call .printTwoDigits mov '.', A call .xStringPrintChar ; Read day call .xRTCGetDay ; Print day call .printTwoDigits mov ' ', A call .xStringPrintChar ; Read hour call .xRTCGetHour ; Print hour call .printTwoDigits mov ':', A call .xStringPrintChar ; Read minute call .xRTCGetMinute ; Print minute call .printTwoDigits mov ':', A call .xStringPrintChar ; Read second call .xRTCGetSecond ; Print second call .printTwoDigits pop Y pop X pop A ret ; Arguments: ; A - number ; No return .printTwoDigits: ; 10 <= A cmp 10, A jle .printTwoDigits_noZero push A ; Print zero if lower than 10 mov '0', A call .xStringPrintChar pop A .printTwoDigits_noZero: ; Print number call .xStringPrintU8 ret