[ blaza @ 25.09.2001. 17:40 ] @
Pre par meseci sam poslao Microchip-u email na poboljšanom verzijom njihovog technical breef-a TB28, gde su dali rešenje par procedura koje se bave proračunavanjem dana u nedelji. Odgovorili su mi da su email prosledili dalje, i od tada.....ništa. Ako ubace ovo rešenje u njihov DataBook, ovo će biti svetska premijera. Ako ne, bar mi neće u potpunosti propasti dva popodneva koje sam utrošio da bi razvio ove 2-3 procedure. U međuvremenu sam imao još par ideja za dalju optimizaciju (da li Vam se desilo da u snu rešite neki problem?) , ali nisam imao volje da ih realizujem. NE pokušavajte da shvatite kako procedura GetDayOfWeek u potpunosti radi. Prilično je optimizovana. Važno je da radi. Mogla bi se napisati i kraća, ako bi vršili kalkulaciju samo za godine 2000-2099. Date su tri procedure na raspolaganju: GetDayOfWeek - nalazi dan u nedelji (ponedeljak..nedelja) za zadat datum (1.1.1984. ...31.12.2099.) : 43 reči CheckDate - proverava da li je datum validan ili ne (1.1.1984. ...31.12.2099) :50 reči GetNextDate - izračunava datum sutrašnjeg dana (1.1.1984. ...30.12.2099.) : 16 reči Pitate se: gde bi se mogle upotrebiti ove procedure? Ove procedure bi se mogle upotrebiti kod proizvoda zasnovanih na PIC mikrokontrolerima, npr. kod električnih časovnika, alarmnih uređaja, kod raznih vrsta data logger-a, kod uređaja za praćenje kvaliteta transporta itd..sl.. Naravno, postoje gotova integrisana kola koja objedinjuju sve, časovnik, datum, alarm. Međutim, ova kola (proizovdi ih Dallas Semiconductors i drugi) se na mikrokontroler priključuju serijskim portom, obično I2C ili SPI protokolom, te zahtevaju 2 ili 3 I/O linije za komunikaciju. Ako "procesorska moć" PIC-a omogućuje da se primene ove procedure, ušteda na specijalnom kolu i na 2 do 3 I/O porta nije zanemariva. ------------------------------------------- Dear Sirs, I decided to send you some program code that I was incited to write when I read Microchip`s TB28. Here is shorter, more compact, faster and in general better solution for date-related calculations. If you respond to me, I`ll be happy to send you more text about theory of calculation and explanations for applied code optimization. Regards CENSORED CENSORED PROGRAM CODE FOLLOWS: List P=16F84A ;******************************************************************************** ********************* ;* These routines are intended for calculating day of the week, for validation of particular date, ;* and for finding date of the next day. First two routines represent better solution than ones ;* that were published in Microchip`s TB28. Third routine is not published in TB28, but can be ;* very useful. ;* Routine GetDayOfWeek (together with AddMod7 i GetMonthVal) is 43 lines long compared to 72 lines ;* in TB28. This routine requires only 1 auxillary RAM location -> Temp1. ;* Routine CheckDate is 50 lines long compared to 22 lines in TB28, but solution in TB28 only ;* checks for valid year range (1990.-2099.), and does not check if date is valid or not; therefore ;* dates like Feb, 29th 1998. and Mar, 32nd 1999. are evaluated as valid dates in TB28, but not in this ;* solution. ;* Routine GetNextDate is useful when we want to find date of the next day. ;******************************************************************************** ********************* ;* Author: CENSORED, CENSORED, blaza@www.com ;******************************************************************************** ********************* PCL equ 02h STATUS equ 03h #define Z STATUS,2 #define C STATUS,0 Day equ 10h Month equ 11h YearH equ 12h YearL equ 13h DayOfWeek equ 14h Temp1 equ 15h org 0x00 main movlw 0x0005 movwf Day movlw 0x0005 movwf Month movlw 0x0007 movwf YearH movlw 0x00d1 movwf YearL ;May, 5th 2001. call CheckDate nop ; <- break point here call GetDayOfWeek nop ; <-break point here end_ call GetNextDate goto end_ ; <-break point here ;******************************************************************************** ******************** ;* This routine computes day of week for particular date ;* Input: Day, Month, YearH & YearL --> Date in range Jan, 1st 1984. - Dec, 31st 2099. ;* Output: DayOfWeek --> 1 Monday, 2 Tuesday, 3 Wensday, 4 Thursday, 5 Friday, 6 Saturday, 7 Sunday ;* This routine uses routines AddMod7 i GetMonthVal, and RAM loccation Temp1 ;* Total code length : 43 lines (together with routines AddMod7 and GetMonthVal) ;******************************************************************************** ******************** GetDayOfWeek movf Day,w btfsc YearH,3 addlw 0x0002 movwf DayOfWeek movf YearL,w movwf Temp1 call AddMod7 rrf Temp1 rrf Temp1,w call AddMod7 btfss YearL,0 btfsc YearL,1 goto Cont1 movlw 0x0002 subwf Month,w btfss c decf DayOfWeek Cont1 decf Month,w call GetMonthVal call AddMod7 call AddMod7 AddMod7 andlw 0x003f addwf DayOfWeek movlw 0x0007 andwf DayOfWeek,w xorwf DayOfWeek rlf DayOfWeek swapf DayOfWeek addwf DayOfWeek retlw 0 GetMonthVal addwf PCL retlw 1 retlw 4 retlw 4 retlw 0 retlw 2 retlw 5 retlw 0 retlw 3 retlw 6 retlw 1 retlw 4 retlw 6 ;******************************************************************************** ******************** ;* This routine determines if particular date is valid or not ;* Input: Day, Month, YearH & YearL --> Date in range Jan 1st 1984. - Dec 31st 2099. ;* Output: Z --> 0 - Date is not valid ; 1 - Date is valid ;* This routine uses RAM loccation Temp1 ;* Code length : 50 lines ;******************************************************************************** ******************** CheckDate movf Month,w btfsc z goto NotValid movwf Temp1 sublw 0x000c btfss c goto NotValid btfsc Temp1,3 incf Temp1 movf Day,w btfsc z goto NotValid andlw 0x00e0 btfss z goto NotValid btfsc temp1,0 goto Cont2 incf Day,w andlw 0x0020 btfss z goto NotValid movf Month,w xorlw 0x0002 btfss z goto Cont2 movlw 0x001d subwf Day,w btfss c goto Cont2 btfss z goto NotValid btfss YearL,0 btfsc YearL,1 goto NotValid Cont2 movf YearH,w sublw 0x0007 btfss z goto Cont3 movf Yearl,w sublw 0x00bf goto Cont4 Cont3 addlw 0x0001 btfss z goto NotValid movlw 0x0034 subwf YearH,w Cont4 btfsc c NotValid bcf z Valid bsf z retlw 0 ;******************************************************************************** ******************** ;* This routine computes date of the next day ;* Input: Day, Month, YearH & YearL --> Date in range Jan, 1st 1984. - Dec, 30th 2099. ;* Output: Day, Month, YearH & YearL --> Date of the next day ;* This routine uses routine CheckDate ;* Code length : 16 lines ;******************************************************************************** ******************** GetNextDate incf Day call CheckDate btfsc z retlw 0 movlw 0x0001 movwf Day incf Month call CheckDate btfsc z retlw 0 movlw 0x0001 movwf Month incf Yearl btfsc z incf YearH goto CheckDate end n int�H = rand() % 10000; / |