Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Dani u nedelji (PIC16xxxx)

[es] :: Asembler :: Dani u nedelji (PIC16xxxx)

[ Pregleda: 7206 | Odgovora: 10 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

blaza
n/a

Član broj: 961
Poruke: 743
*.gf.su.ac.yu



+3 Profil

icon Dani u nedelji (PIC16xxxx)25.09.2001. u 17:40 - pre 274 meseci
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; /
O_o
 
Odgovor na temu

blaza
n/a

Član broj: 961
Poruke: 743
*.gf.su.ac.yu



+3 Profil

icon Re: Dani u nedelji (PIC16xxxx)01.10.2001. u 20:50 - pre 274 meseci
O.K. PIC programeri. Dosta ste bili lenji. Evo malo zanimacije.

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

Ko prvi u POTPUNOSTI objasni princip rada ovih procedura, dobija simboličan poklon: čokoladu sa lešnicima od 200g.
Cao :)

O_o
 
Odgovor na temu

blaza
n/a

Član broj: 961
Poruke: 743
*.eccf.su.ac.yu



+3 Profil

icon Re: Dani u nedelji (PIC16xxxx)27.10.2001. u 16:02 - pre 273 meseci
Citat:
blaza je napisao:
Ko prvi u POTPUNOSTI objasni princip rada ovih procedura, dobija simboličan poklon: čokoladu sa lešnicima od 200g.


Deal is off. Blizio se best before datum cokolade, a kako za mesec dana niko nije bio u stanju da protumaci 2-3 programska reda, istu sam morao da uništim.
O_o
 
Odgovor na temu

Gojko Vujovic
Amsterdam, NL

Administrator
Član broj: 1
Poruke: 13651



+165 Profil

icon Re: Dani u nedelji (PIC16xxxx)27.10.2001. u 16:29 - pre 273 meseci
Hmm stvarno, šta je sa ASM programerima, mrzi ih ili ne znaju ili...?
 
Odgovor na temu

Mikky

Član broj: 18
Poruke: 1563
*.177.EUnet.yu

ICQ: 44582291


+58 Profil

icon Re: Dani u nedelji (PIC16xxxx)27.10.2001. u 22:25 - pre 273 meseci
mislim da je ovo drugo...
ja sam tu za x86 asm stvari za ostalo sam prilican laik
-I know UNIX, PASCAL, C, FORTRAN,
COBOL, and nineteen other high-tech
words.
 
Odgovor na temu

Vojislav Milunovic

Član broj: 25
Poruke: 2117
165.139.17.*



+1 Profil

icon Re: Dani u nedelji (PIC16xxxx)29.10.2001. u 16:45 - pre 273 meseci
Citat:
blaza je napisao:
O.K. PIC programeri. Dosta ste bili lenji. Evo malo zanimacije.


Samo da kazem, ja licno mislim da ovde nema nikog koji se zanim sa tim PIC ili sta vec. Kod nas je jedno zlatno pravilo, koji CPU imas za njega rdis asm. Mislim da ja imam SPARC radio bi asm za SPARC a ne za x86. Da idem preko telnet-a na neki SPARC da vezbam je malo sporo, tako da mozda nadjes odgovor kod nekih bogatijih zemljica ali kod nas... tesko :(
 
Odgovor na temu

blaza
n/a

Član broj: 961
Poruke: 743
*.gf.su.ac.yu



+3 Profil

icon Re: Dani u nedelji (PIC16xxxx)29.10.2001. u 17:25 - pre 273 meseci
PIC je serija mikrokontrolera firme Microchip. Starting price je $1.5 za najjednostavnije modele. Razvojno okruženje je besplatno. Programator se može namestiti u samogradnji za $3. Pošto je mikrokontroler mali kompjuter u jednom chip-u, tj. procesorskom jezgru je pridodata periferija, programska memorija (ROM,EPROM,EEPROM,FLASH) i data memorija (RAM, EEPROM) , upotrebljivost je praktično neograničena.
Slabija serija PIC mikrokontrolera koristi svega 35 (trideset pet) instrukcija.

Zbog jednostavnosti upotrebe i niske cene kod nas ima mnogo ljudi koji se bave ovom serijom mikrokontrolera (Bar ih ja znam mnogo.) Doduše, možda ih na ES nema toliko...

Sad ćete reci.....ahh.mikrokontroleri...to su igračke....JOK...u svakom mobilnom telefonu, pejdžeru, mp3 plejeru, itd...naći ćete bar jedan

O_o
 
Odgovor na temu

Dyra

Član broj: 6967
Poruke: 3
*.beotel.net



Profil

icon Re: Dani u nedelji (PIC16xxxx)22.12.2002. u 18:58 - pre 259 meseci
Ova mala diskusija me podstakla da se prijavim na forum.

incf PIC
 
Odgovor na temu

Mozak

Član broj: 14690
Poruke: 12
77.46.204.*



Profil

icon Re: Dani u nedelji (PIC16xxxx)23.09.2007. u 02:44 - pre 201 meseci


GetDayOfWeek movf Day,w (W is accumulator_register of this microprocessor)
btfsc YearH,3 (BitTestFile_register_andSkip_next_instruction_ifClear)
addlw 0x0002
movwf DayOfWeek DayOfWeek=Day[+2 if year=%1000 00xxxxxx>=2048,+0 if year=%0111 11xxxxxx<2048] ********************* 1)


movf YearL,w
movwf Temp1 Temp1=YearL (because we can't shift w register by self later where needed,so we must use local temp)
call AddMod7 DayOfWeek=(DayOfWeek+YearL)mod7 ********************* 2)
rrf Temp1
rrf Temp1,w
call AddMod7 DayOfWeek=(DayOfWeek+int(YearL/4))mod7 ********************* 3)


btfss YearL,0
btfsc YearL,1
goto Cont1
movlw 0x0002
subwf Month,w
btfss c
decf DayOfWeek if 1 extra day (29th feb.) of the 366day-year isn't passed yet,adjust by adding -1


Cont1 decf Month,w prepare W for (addwf PCL) instruction (1 instruction cycle wasted)


call GetMonthVal get ((which day of the 365days-year is the 1st day of this month) mod 7)


call AddMod7
call AddMod7 adjust to mod7 by calling adjust procedure not once,but 3 times(because of the trickiest summ 17octal->10octal->01octal)


(empty line,AKA goto AddMod7)
----------------------------
AddMod7 andlw 0x003f limiting input parameter by masking (affecting if year=%0111 11xxxxxx<2048 ) ********************* 2)

addwf DayOfWeek DayOfWeek=DayOfWeek+W=%0aaaabbb=8a+b=7a+a+b=7a+(a+b)

movlw 0x0007
andwf DayOfWeek,w W=%00000bbb
xorwf DayOfWeek DayOfWeek=[%0aaaabbb XOR %00000bbb]=%0aaaa000
rlf DayOfWeek DayOfWeek=%aaaa0000
swapf DayOfWeek DayOfWeek=%0000aaaa (swap nibbles)
addwf DayOfWeek DayOfWeek=%0000aaaa+W=aaaa+bbb <=> (DayOfWeek=DayOfWeek-7*INT(DayOfWeek/8 ))
retlw 0
----------------------------
GetMonthVal addwf PCL get ((which day of the 365days-year is the 1st day of this month) mod 7)
retlw 1
retlw 4
retlw 4
retlw 0
retlw 2
retlw 5
retlw 0
retlw 3
retlw 6
retlw 1
retlw 4
retlw 6

Najveca komplikacija je deo koda oznacen sa *********************.Da pojasnim:

----------------------------------------------------------------------------------------------------------------------------------
ukupna formula za racunanje dana u nedelji je

[
Day
+(which day of the 365days-year is the 1st day of this Month) //(ovde uradjeno pomocu tablice)
+(Year*365.25-3) //(Year+INT(Year/4) otprilike sa shacovanjem)
-(1 extra day (29th feb.) of the 366day-year IF it isn't passed yet) //(popravak za prestupan dan prestupne godine)
]
MOD 7 //(svedeno na ostatak pri deljenju sa 7)
----------------------------------------------------------------------------------------------------------------------------------
Clan (Year*365.25-3) je problematican zbog parcijalnog racunanja,stedilo se...

1984<=Year<=2099<=2111 (godine 2100-2111 su izbegnute jer bi trebao popravak -1 zbog datuma posle 28.feb.2100)
---------------- ==>
Year=binarno=%0111 11xxxxxx ili %1000 00xxxxxx

U slucaju %0111 11000000=Year=1984 treba da dobijemo (Year*365.25-3)mod7=6

da vidimo delove koda sa *********************:
*********************1) nemamo +2,znaci ovde imamo +0=n1
*********************2) zbog maskiranja gornja 2 bita od YearL imamo +0=n2
*********************3) ovde imamo INT(YearL/4)=%00110000=48dec=n3 =>n1+n2+n3=0+0+48=48 a 48mod7=48-7*6=48-42=6=(1984*365.25-3)mod7=>OK

A u slucaju %1000 00000000=Year=2048 treba da dobijemo (Year*365.25-3)mod7=2
da vidimo:
*********************1) imamo +2=n1
*********************2) +0=n2
*********************3) +0=n3 => n1+n2+n3=2=(2048*365.25-3)mod7 OK

slazze se,znaci kod - izgleda shashavo,ali mene vishe kalendar ne bole (znam ga napamet)







 
Odgovor na temu

Mozak

Član broj: 14690
Poruke: 12
77.46.204.*



Profil

icon Re: Dani u nedelji (PIC16xxxx)23.09.2007. u 12:26 - pre 201 meseci
A inace time sam se bavio davno pa mi je ostala u glavi formula za racunanje koju ponekad koristim (napamet )
naprimer datum 23.sep.2007 (danas,i to ce biti nedelja;)
1) 23->mod7 (radis tako sto oduzmes najveci broj deljiv sa 7)
znaci 23-21=2(pamtis)
2)sep->iz tablice,samo ja koristim broj manji za 1=>sep->5
saberes sa prethodnim brojem i uradis mod7,tj. -7 ako predje>=7
u ovom slucaju 2+5=7-7=0(pamtis kumulativnu sumu mod7)
3)2007 rastavis na 20|07
4)za 20|xx tj. stotine godina ima "tablica" 16xx->6 17xx->4 18xx->2 19xx->0
20xx->6 21xx->4 22xx->2 23xx->0 itd.
u ovom slucaju 20xx->6 sto je isto sto i -1 po mod7 (ja koristim 0 za 19xx i -1 za 20xx)
pa je kumulativna suma 0-1=-1+7=6 (pamtis) (da se vrati u opseg 0-6)
5)za jedinice i desetice godina,u ovom slucaju 07,radi se ovako:
dopises 0 sa desne strane i delis 3 puta sa 2 bez ostatka;
sto znaci da neparan broj pre deljenja mozes smanjiti za 1 radi lakseg deljenja
u ovom slucaju 07|0->070 /2
=035-1=034 /2
=017-1=016 /2
=008
sada mod7,a ovaj broj moze biti povelik,pa se koristi napr.
ako je >=100 -> -100 +2 (<=>-98=7*14)
ako je >=70 -> -70
ako je >=50 -> -50 +1 (<=>-49)
u ovom slucaju 008-7=1+kumulativna suma dosad=1+6=7-7=0(pamtis)
6)i jos samo popravak rezultata zbog prestupnog dana:
ako je mesec januar ili februar (verovatnoca 1:6) i
ako je godina prestupna (otprilike 1:4) onda -> -1.
u ovom slucaju ni jedno nije tacno,znaci dobili smo 0=7=nedelja.

evo brzi primer2: 6.april.1941 (bombardovanje Beograda)
6+6+0+
(410/2=204/2=102/2=51-49=)2=14,popravak nema.
14mod7=14-14=0->nedelja

Imao sam i drugi algoritam za desetice i jedinice,ali ovaj sam trenutno koristim za racunanje napamet
evo asocijacije za pamcenje "moje" tablice za mesece:
jan - prvi mesec - od 1.januara do 1.januara=0 dana=>0
feb,mar,nov- 3 meseca imaju broj 3
april-6 (bombardovanje Beograda),juli-6
maj-1 (praznik rada)
juni-4
avgust-2
sep,dec-5
oktobar-0 kao 0ktobar
(vremenom/vezbom mozes zapamtiti tu tablicu)

ima neko prostiji/drukciji algoritam (za napamet ) ?
 
Odgovor na temu

Stojan Trifunovic

Član broj: 15156
Poruke: 366
212.200.223.*



+8 Profil

icon Re: Dani u nedelji (PIC16xxxx)28.02.2008. u 14:12 - pre 196 meseci
Citat:
Gojko Vujovic: šta je sa ASM programerima, mrzi ih ili ne znaju ili...? :)

Ništa drugo do pogrešog dela foruma (Više nas ima na Elektronika - mikrokontroleri). A taman bi mi trebalo par čokoladica za osmi mart! Makar i sa lešnikom.

Moje iskustvo!
Trebala mi je svojevremeno upravo takva rutina ali za sat, pa sam za osnovu koristio neke projekte sa neta i TB28. Razvio sam program koji za razliku od vašeg nije optimizovan za mali kod, već za veliku brzinu, tako da poređenje ne bi imalo mnogo smisla. Nije mi trenutno dostupan da bih mu mogao proveriti veličinu. Mislim da je oko 200 bajtova, ali sa satom, korekcijom prestupne godine i prelaska letnjeg/zimskog računanja vremena (daylight savings).

Par primedbi!
1) Zbog čega od 1990? Sumnjam da će iko želeti da realizuje mikrokontrolerski program sa datumima manjim od tekuće godine. U redu je za produženje licence programa na PC, ali nije i za mikrokontrolere. Sasvim je dovoljno od 2000.

2) Zbog čega samo do 2099? Setite se kakvu je pometnju izazvao New Year Bug. Koliko se sećam svojevremeno je prodavan HARDVER u obliku PCI kartice koji omogućuje loše napisanom softveru da radi i nakon 2000-te. Moj program na primer radi do 2299 To sam realizovao korekcijom vrednosti za vekove. Ukoliko iko bude koristio moj mikrokontrolerski sat i nakon toga, verovatno zaslužuje da se nađe u Ginisovoj knjizi rekorda.

Vaš program nije lako prepraviti za više godina upravo zbog načina čuvanja vrednosti godine. Da bi se ono moglo lakše implementirati predlažem Vam da umesto heksadecimalnog oblika čuvanja broja godina
Code:

     movlw 0x0007
     movwf YearH
     movlw 0x00d1
     movwf YearL

koristite običan decimalni oblik u kome se u YearH čuvaju vekovi, a u YearL godine ovako (za 2001 god.):
Code:

     movlw .20
     movwf YearH
     movlw .01 
     movwf YearL


Naravno, ovo zahteva odgovarajuću korekciju algoritma.

3) U zavisnosti od primene koda provera validnosti datuma bi mogla biti bolje postavljena. Naime logičnije je ograničiti korisniku mogućnost unosa pogrešne pojedinačne vrednosti nego dozvoliti mu da je unese i da se nakon toga od njega zatraži da ponovi kompletan unos. To spada u user friendly design. Kako bi se to moglo implementirati? Na primer zatražiti od korisnika unos godine (za Vaš slučaj 1984-2099), pri čemu je korisnik u startu ograničen na ovu vrednost. Nakon unosa godine unos meseca (1-12), pa unos dana (1-31 sa ograničenjem i korekcijom 29 februara za slučaj prestupne godine). Dalje bi se kroz glavni program samo povećavale vrednosti dana sa odgovarajućim prekoračenjima. Kod mog programa korisnik u nastavku unosi sate (0-23), minute (0-59), a eventualno i sekunde (ili jos bolje reset sekundi na 0).

4) Offtopic koristite code /code tagove prilikom navođenja koda. Ovako se labele ne razlikuju od instrukcija. I praktičnije je i razumljivije korišćenje skraćenog oblika zapisa heksadecimalnih brojeva 0x07 umesto 0x0007.
 
Odgovor na temu

[es] :: Asembler :: Dani u nedelji (PIC16xxxx)

[ Pregleda: 7206 | Odgovora: 10 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.