Wednesday, October 2, 2019

DCF-77 decoder

Niekde som čítal, že dnes sa už asi nikto do projektov s 8048 nebude púšťať. Napísal som program pre 8048 na dekódovanie časového signálu DCF-77 z Mainflingenu. Vysiela sa od roku 1970 výkonom cca 50kW a ako jediný v Európe ešte nejakú dobu určite bude. Program je síce bohato okomentovaný, ale aj tak by som ho o pár rokov asi márne lúštil, tak tu je rámcový opis. Program je na Githube tu: https://github.com/ncb85/ncb48/tree/master/dcf77

Ako sa vysiela DCF-77 je krásne vidno tu: DCF-77 Live


Na obrázku je vyznačené, kde sa nachádzajú minúty a hodiny (formát je BCD+parita - dvojkové číslo sa číta zprava, nie zľava ako je zvykom)

Signál má sekundový takt. Logická 1 má na začiatku sekundy 200ms vysokú úroveň, po zvyšok je signál v nízkej úrovni. Logická 0 má na začiatku sekundy 100ms vysokú úroveň, zvyšok nízku. 8048 má hodiny 4.9152MHz, čo dáva takt timer prerušenia 40Hz. To znamená, že sekunda je vzorkovaná 40x. Pre logickú 1 musí byť prvých 8 vzoriek vo vysokej úrovni a pre 0 iba štyri vzorky. 8 a 4 sú celkom výhodné čísla. Jeden byte je 8 bitov.

Takto nejako:
jednotka         1111111100000000000000000000000000000000
nula                1111000000000000000000000000000000000000
60. sekunda    0000000000000000000000000000000000000000

Jeden byte RAM používam ako posuvný register. Pri každom prerušení nasuniem aktuálnu logickú úroveň do byte zprava. Bit naľavo vypadáva. Potom si rozdelím byte na dve polovice. A spočítam koľko jednotiek je v každej polovici. Ak nájdem jednu polovicu takú a druhú onakú, tak máme prechod z jedného stavu do druhého. Vtedy si nastavím ďalší pomocný byte ako counter a počítam čas od do. Vyhodnocujem dĺžku vysokej úrovne pulzu a kontrolujem min./max. šírku obidvoch častí pulzu. Výsledkom sú v sekundovom takte pulzy 1 alebo 0 (ako na obrázku hore), alebo chyba. Toto sa deje v prerušení od timer, preto aj názov - timer.asm   Z princípu funkcie vyplývajú dve veci: program (ale nie čas hodín) je 4 prerušenia (0.1s) oneskorený za vysielaním a prerušenie sa vykonáva 40x za sekundu ale výstup z neho (PULSE_VALID) je iba 1x za sekundu.

O úroveň vyššie je decoder.asm. Nepracuje už v prerušení, ale v hlavnej slučke. Tam z pulzov vychádzajúcich z timer.asm dekóduje čas. Čas je priamo v BCD. Výsledný čas okrem kontroly na paritu kontrolujem aj formálne, aby nebol napr. 28:62. Ako je známe maximum je 23:59 :-) Kontrolujú sa aj bity 1 a 20, ktoré majú vždy pevnú hodnotu 0 resp. 1. Okrem toho kontrolujem prítomnosť kompletnej sekvencie pulzov. Aj posledná sekunda (samé 0) sa musí objaviť len v dobe pre ňu určenej. Po uplynutí aktuálnej minúty sa nastavuje nový čas z vysielania, samozrejme ak prešiel všetkými kontrolami. Kontroly sú také poctivé, že zatiaľ som nikdy nevidel falošný čas.

Aktuálny čas 8048 sa posúva pri každom prerušení v clock.asm S výhodou sa využíva inštrukcia DA A na počítanie s BCD číslami. A nakoniec sa aktuálny čas zobrazuje. Dá sa aj staticky aj multiplexne. Pre rôzne moduly displayov sú rôzne asm file. dis2x595.asm je pre 8-miestny multiplexovaný modul z eBay (hľadaj 74HC595 LED display), disNx595.asm je pre statické 2,3,4 miestne zreťazené moduly z eBay (hľadaj 74HC595 static LED display)

Pridal som aj modul s čipom DS1302 zálohovaným batériou CR2032, aby sa mohli hodiny aj vypínať. DS1302 je obvod hodiniek s tepelne nekompenzovaným externým kryštálom 32.768kHz a za deň si v kľude ubehne aj pár sekúnd od presného času. Za mesiac to ide do minút. Po zapnutí sa preberie čas z DS1302 a po rozlúštení časového signálu, čo môže trvať aj dlhšiu dobu, sa čas upraví na presnú hodnotu.

Pripojenie prijímača DCF je do vstupu T0. Momentálne su pulzy invertované, lebo ich prevádzam na TTL úroveň jedným NPN tranzistorom - výstup je z kolektoru. Ak by boli pulzy neinvertované, je treba zmeniť inštrukciu JT0 na JNT0 (v timer.asm)
_TCIN2   CLR C
         JT0 _TCIN3
Výstup na riadenie display a komunikácie s DS1302 je na porte P1.
P1.0 data pin of display
P1.1 clock pin of display
P1.2 latch pin of display
P1.3 data pin of DS1302
P1.4 clock pin of DS1302
P1.5 CE pin of DS1302