Stránka 1 z 1
Jak dekódovat RTC?
Napsal: 21 říj 2014, 09:50
od Celeron
Zařízení s generátorem reálnýho času (RTC) má klasickej výstup času ve třech byte HH:MM:SS (hodina:minuta:sekunda).
Ale datum má naprosto nepochopitelnej formát, kdy je informace DD:MM:RRRR uložen ve dvou byte.

Formát uložení je následující: 00 01 = (SU 01-JAN-1978) a FF FF = (SU 05-JUN-2157). RTC umí přestupný roky, tedy únor 28/29. Takže 1978=365, 1979=365,1980=366, 1981=365 a dále dál po čtyřech letech.
Potřeboval bych datum rozklíčovat do klasický podoby DD:MM:RRRR. Jenže si lámu hlavu jak. Vychází mi z toho naprostý monstrum, kdy jen na získání roku se musí stále dokola odčítat cykly 365, 365, 366, 365 a po každým odečtení kontrolovat, zda výsledek není menší než 366. A až se dostanu sem, tak se musí ještě zkontrolovat jestli to náhodou není přestupnej rok a případně upravit. To bych ještě zvládl. Jenže pak rozebrání na počet měsíců je úplná hrůza, asi odčítat počty dnů za jednotlivý měsíce uložený v tabulce, zohlednit únor pokud bude náhodou přestupnej rok a zastavit odčítání až bude zbytek menší než počet dní v měsíci. No a zbytek budou dny. Nojo, ale tohle napsat v Z80-kovým asembleru je šílenost. Kvůli 16 bitový matematice to bude spousta výpočtových cyklů, co zabere hromadu času procesoru a taky na to není moc místa v paměti.
Nemáte prosím někdo nápad, jestli to nejde nějak jednodušeji? Neleze tenhle nesmysl taky z RTC na boardech v PC a v biosu se to neláme do klasický podoby?
Díky
Jirka
Napsal: 21 říj 2014, 10:12
od rnbw
Nie, v PC sa pouziva MC146818 a ten ma v samostatnych registroch den, mesiac a rok.
Ten tvoj "RTC" vlastne nema kalendar, ale len pocitadlo dni. A "neumi" prestupne roky, pretoze s nimi vobec nepracuje. Tie si musis implementovat sam v programe.
Napsal: 21 říj 2014, 10:17
od termit256
Jaky je tam pouzity obvod rtc? Nedavno jsem hledal jaky RTC zvolit pro sve zarizeni a vicemene vsude z toho lezl klasicky format.
Napsal: 21 říj 2014, 11:26
od Celeron
rnbw píše: Ten tvoj "RTC" vlastne nema kalendar, ale len pocitadlo dni. A "neumi" prestupne roky, pretoze s nimi vobec nepracuje. Tie si musis implementovat sam v programe.
Já vím, že to počítá dny od 1.1.1978. I když nevím, proč tam teda píšou, že to zohledňuje přestupný roky, zjevně nesmysl.
Problém, jak převést počet dní na DD:MM:RRRR (tedy počet dní přičíst k 1.1.1978) stále trvá.
Jirka
Napsal: 21 říj 2014, 11:34
od Celeron
termit256 píše:Jaky je tam pouzity obvod rtc? Nedavno jsem hledal jaky RTC zvolit pro sve zarizeni a vicemene vsude z toho lezl klasicky format.
Já nevím konkrétní typ, schéma není, šváby jsou vydrápany bez popisu a tak píšu, co je v manuálu toho zařízení. Dělal jsem dosud s dvěma RTC, třeba s Epsonem 72421 a tam bylo vše z data a času dokonce rozdělený na byte jednotek a desitek navíc i den v týdnu ale zase rok tam nebyly stovky a tisíce. Dost dobrej, sice starej šváb, ale suprová stabilita, vím o případu, kde se nenastavoval asi 10 let a uhnul jen o asi 45 sekund.
Jirka
Napsal: 21 říj 2014, 11:42
od termit256
Tak to je blbe. Mozna by dalo min prace resit to pomoci sproste konverzni tabulky, nez se morit se slozitym vypoctem.
Napsal: 21 říj 2014, 11:51
od rnbw
A ked tie udaje nepouziva nikto iny, mozes si ten rok posunut. Napr. tak, aby 0 znamenala 1.1.2000.
Napsal: 21 říj 2014, 14:06
od Celeron
To by šlo.

Pak začínáš 2000 = přestupným, dělení a násobení čtyřma - rotacema. Takže rok by šel celkem rozumě. Jenže pak je problém co dál s tím zbytkem do 365 (366). Napadá mě jen 12 byte tabulka s počty dní v měsíci, (s modifikací 28/29 u přestupnýho) a zase odčítat a testovat zbytek.
Díky
Jirka
Napsal: 21 říj 2014, 14:27
od rnbw
Na dni v mesiaci asi nic lepsie ako tabulku nevymyslis, kedze logika v tom nie je ziadna...
Napsal: 21 říj 2014, 16:32
od Celeron
Tak naprogramovaný to mám, teď to odladit na pár příkladech na simulátoru Z80 jestli jsem se někde nesekl v úvahách či v instrukcích. Ta tabulka je ideál řešení, jen se musí modifikovat únor podle roku. No snad to půjde.
Díky
Jirka
Napsal: 21 říj 2014, 19:46
od Bernard
To už bude snad 15 let, co jsem takový převod řešil. LIN_DAT byl počet dní od 31.12.1999. Sic to bylo v c-čku, ale třeba pro inspiraci uvedu tu funkci:
Kód: Vybrat vše
void
dat_lin_2bcd (void) {
unsigned int DEN;
unsigned char ROK, MESIAC, WEEK;
;
WEEK = (LIN_DAT + 5) % 7; // 1.1.2000 (den 1) bola sobota
if (WEEK == 0) WEEK = 7; // RTC ide Po - Ne ako 1 - 7
DEN = 1 + LIN_DAT / 1460; // pocet prestupnych dni v uplynulych rokoch
ROK = (LIN_DAT - DEN) / 365; //terajsi rok
DEN = LIN_DAT - DEN - 365* ROK; // pocet dni v tomto roku
if ((ROK%4)==0) {if (DEN>60) DEN--;}
if (DEN < 32) MESIAC = 1;
else if (DEN<60) {MESIAC=2; DEN -=31;}
else if (DEN==60) {
if ((ROK%4)==0) {MESIAC=2; DEN=29;}
else {MESIAC=3; DEN=1;}
}
else if (DEN<91) {MESIAC=3; DEN -=59;}
else if (DEN<121) {MESIAC=4; DEN -=90;}
else if (DEN<152) {MESIAC=5; DEN -=120;}
else if (DEN<182) {MESIAC=6; DEN -=151;}
else if (DEN<213) {MESIAC=7; DEN -=181;}
else if (DEN<244) {MESIAC=8; DEN -=212;}
else if (DEN<274) {MESIAC=9; DEN -=243;}
else if (DEN<305) {MESIAC=10; DEN -=273;}
else if (DEN<335) {MESIAC=11; DEN -=304;}
else if (DEN<366) {MESIAC=12; DEN -=334;}
else error_cnt (ERR_DATUM);
DATUM_CAS [3] = bin_2bcd (DEN & 0x00FF);
DATUM_CAS [4] = bin_2bcd (MESIAC);
DATUM_CAS [5] = bin_2bcd (WEEK);
DATUM_CAS [6] = bin_2bcd (ROK);
}
Napsal: 21 říj 2014, 20:33
od FHonza
Dá se použít např.
toto. Je to vlastně dekódování Unix datumu
Napsal: 22 říj 2014, 01:12
od Celeron
Díky pánové! Mám to hodně podobný Bernardovu řešení v C-čku. Večer jsem to odladil na pár příkladech a chodí. I s tabulkou délky měsíce necelých 70 řádků v asembleru Z80. Počátek 1.1.2000, konec někde kolem 2170, to mě rozhodně nebolí.
Jirka