1 | #define DEBUG 0
|
2 |
|
3 | #include <avr/io.h>
|
4 | #include <util/parity.h>
|
5 | #include "timer_10ms.h"
|
6 | #include "dcf77.h"
|
7 | #include "UART.h" // nur Debug
|
8 |
|
9 | static union
|
10 | {
|
11 | volatile uint64_t dcf_bits;
|
12 | struct
|
13 | {
|
14 | volatile uint8_t DUMMY:5; // Rest für long long
|
15 | volatile uint8_t START:1; // Start Minute (0)
|
16 | volatile uint16_t METEO:14; // Wetterdaten
|
17 | volatile uint8_t RUF:1; // Rufbit (ehem. Reserveantenne)
|
18 | volatile uint8_t MEST_F:1; // Zeitumstellung am Ende der Stunde
|
19 | volatile uint8_t MESZ:2; // MEZ (10), MESZ (01)
|
20 | volatile uint8_t SEK_S:1; // Schaltsekunde am Ende der Stunde
|
21 | volatile uint8_t BEGIN:1; // Start Zeit (1)
|
22 | volatile uint8_t MIN_E:4; // Minute BCD
|
23 | volatile uint8_t MIN_Z:3; // Minute BCD
|
24 | volatile uint8_t MIN_P:1; // Parität Minute
|
25 | volatile uint8_t STU_E:4; // Stunde BCD
|
26 | volatile uint8_t STU_Z:2; // Stunde BCD
|
27 | volatile uint8_t STU_P:1; // Parität Stunde
|
28 | volatile uint8_t TAG_E:4; // Tag BCD
|
29 | volatile uint8_t TAG_Z:2; // Tag BCD
|
30 | volatile uint8_t WTAG:3; // Wochentag BCD
|
31 | volatile uint8_t MON_E:4; // Monat BCD
|
32 | volatile uint8_t MON_Z:1; // Monat BCD
|
33 | volatile uint8_t JAHR_E:4; // Jahr BCD
|
34 | volatile uint8_t JAHR_Z:4; // Jahr BCD
|
35 | volatile uint8_t DATUM_P:1; // Parität Datum
|
36 | };
|
37 | } dcf77_daten;
|
38 |
|
39 | uint8_t dcf77_check(void);
|
40 | void dcf77_init(void);
|
41 |
|
42 | static uint8_t dcf77_time_cnt; // Anzahl 10ms IRQs
|
43 | static uint8_t dcf77_bit_cnt; // Anzahl Bits seit Minutenwechsel
|
44 | uint8_t dcf77_ok = 0, dcf77_err = 0, dcf77_min = 0;
|
45 |
|
46 | //-----------------------------------------------------------------------------------------
|
47 |
|
48 | uint8_t dcf77_10ms()
|
49 | {
|
50 | dcf77_ok = FALSE;
|
51 |
|
52 | if (DCF77_PIN & (1<<DCF77_DATA)) // low oder high?
|
53 | { // high
|
54 | dcf77_time_cnt++; // 10ms Time +1
|
55 | if (dcf77_time_cnt > 250) // 2,5s
|
56 | {
|
57 | dcf77_err = TRUE; // Fehler, kein Impuls
|
58 | }
|
59 | }
|
60 | else
|
61 | { // low
|
62 | if (dcf77_time_cnt) // bei 0 ist Auswertung fertig
|
63 | {
|
64 | if ((dcf77_time_cnt > 195) | (dcf77_time_cnt < 6))
|
65 | {
|
66 | dcf77_err = TRUE;
|
67 | }
|
68 | else
|
69 | {
|
70 | if (dcf77_time_cnt > 177) // Minute rum
|
71 | {
|
72 | dcf77_min = TRUE; // Flag setzen für Minute komplett
|
73 | dcf77_time_cnt -= 100; // 1s time abziehen für Auswertung
|
74 | }
|
75 | if ((dcf77_time_cnt > 95) | (dcf77_time_cnt < 78)) // zu lang oder zu kurz -> Fehler
|
76 | {
|
77 | dcf77_err = TRUE; // Fehler, kein gültiger Impuls
|
78 | }
|
79 | else
|
80 | {
|
81 | dcf77_bit_cnt++; // Bitcount erhöhen
|
82 | asm volatile // shift long long right und höchstwertiges Bit bleibt 0
|
83 | (
|
84 | "lds __tmp_reg__, %0 + 7" "\n\t"
|
85 | "lsr __tmp_reg__" "\n\t"
|
86 | "sts %0 + 7, __tmp_reg__" "\n\t"
|
87 | "lds __tmp_reg__, %0 + 6" "\n\t"
|
88 | "ror __tmp_reg__" "\n\t"
|
89 | "sts %0 + 6, __tmp_reg__" "\n\t"
|
90 | "lds __tmp_reg__, %0 + 5" "\n\t"
|
91 | "ror __tmp_reg__" "\n\t"
|
92 | "sts %0 + 5, __tmp_reg__" "\n\t"
|
93 | "lds __tmp_reg__, %0 + 4" "\n\t"
|
94 | "ror __tmp_reg__" "\n\t"
|
95 | "sts %0 + 4, __tmp_reg__" "\n\t"
|
96 | "lds __tmp_reg__, %0 + 3" "\n\t"
|
97 | "ror __tmp_reg__" "\n\t"
|
98 | "sts %0 + 3, __tmp_reg__" "\n\t"
|
99 | "lds __tmp_reg__, %0 + 2" "\n\t"
|
100 | "ror __tmp_reg__" "\n\t"
|
101 | "sts %0 + 2, __tmp_reg__" "\n\t"
|
102 | "lds __tmp_reg__, %0 + 1" "\n\t"
|
103 | "ror __tmp_reg__" "\n\t"
|
104 | "sts %0 + 1, __tmp_reg__" "\n\t"
|
105 | "lds __tmp_reg__, %0" "\n\t"
|
106 | "ror __tmp_reg__" "\n\t"
|
107 | "sts %0, __tmp_reg__"
|
108 | : "+m" (dcf77_daten)
|
109 | );
|
110 | if (dcf77_time_cnt < 87) // Bit war 1
|
111 | {
|
112 | asm volatile // höchstwertiges Bit des long long auf 1 setzen
|
113 | (
|
114 | "lds __tmp_reg__, %0 + 7" "\n\t"
|
115 | "set" "\n\t" // T setzen
|
116 | "bld __tmp_reg__, 7" "\n\t" // und in Bit 7 kopieren
|
117 | "sts %0 + 7, __tmp_reg__" "\n\t"
|
118 | : "+m" (dcf77_daten)
|
119 | );
|
120 | }
|
121 | }
|
122 |
|
123 | #if DEBUG
|
124 | uart_send_byte_hex(dcf77_bit_cnt);
|
125 | uart_send_byte(' ');
|
126 | uart_send_byte_hex(dcf77_time_cnt);
|
127 | uart_send_byte(' ');
|
128 | uart_send_byte_hex(dcf77_min);
|
129 | uart_send_text("\r\n");
|
130 | #endif
|
131 |
|
132 | dcf77_time_cnt = 0;
|
133 | if (dcf77_min)
|
134 | {
|
135 | if (dcf77_bit_cnt == 59) // alle Bits da?
|
136 | {
|
137 | dcf77_ok = dcf77_check();
|
138 | }
|
139 | dcf77_err = TRUE;
|
140 | }
|
141 | }
|
142 | }
|
143 | }
|
144 | if (dcf77_err) // Fehler?
|
145 | {
|
146 | dcf77_reset();
|
147 | }
|
148 | return dcf77_ok;
|
149 | }
|
150 |
|
151 | //-----------------------------------------------------------------------------------------
|
152 |
|
153 | void dcf77_reset()
|
154 | {
|
155 | dcf77_daten.dcf_bits = 0;
|
156 | dcf77_time_cnt = 0;
|
157 | dcf77_bit_cnt = 0;
|
158 | dcf77_err = FALSE;
|
159 | dcf77_min = FALSE;
|
160 | }
|
161 |
|
162 | //-----------------------------------------------------------------------------------------
|
163 |
|
164 | void dcf77_init()
|
165 | {
|
166 | DCF77_DDR &= ~(1<<DCF77_DATA); // Eingang
|
167 | DCF77_PORT |= (1<<DCF77_DATA); // PullUp ein
|
168 |
|
169 | dcf77_reset();
|
170 | }
|
171 |
|
172 | //-----------------------------------------------------------------------------------------
|
173 |
|
174 | unsigned char dcf77_check()
|
175 | {
|
176 | uint8_t parity;
|
177 |
|
178 | // wenn Parität gerade ist Ergebnis 0
|
179 | parity = parity_even_bit((dcf77_daten.MIN_Z << 5) | (dcf77_daten.MIN_E << 1) | dcf77_daten.MIN_P);
|
180 | if (parity)
|
181 | {
|
182 | return FALSE; // Fehler
|
183 | }
|
184 |
|
185 | // wenn Parität gerade ist Ergebnis 0, dazu das Ergebnis von oben
|
186 | if (parity_even_bit((dcf77_daten.STU_Z << 5) | (dcf77_daten.STU_E << 1) | dcf77_daten.STU_P))
|
187 | {
|
188 | return FALSE; // Fehler
|
189 | }
|
190 |
|
191 | // wenn Parität gerade ist Ergebnis 0
|
192 | parity = parity_even_bit((dcf77_daten.TAG_Z << 4) | dcf77_daten.TAG_E);
|
193 |
|
194 | // wenn Parität gerade ist Ergebnis 0, dazu das Ergebnis von oben
|
195 | parity = parity_even_bit((dcf77_daten.MON_Z << 5) | (dcf77_daten.MON_E << 1) | parity);
|
196 |
|
197 | // wenn Parität gerade ist Ergebnis 0, dazu die Ergebnisse von oben
|
198 | parity = parity_even_bit((dcf77_daten.JAHR_Z << 5) | (dcf77_daten.JAHR_E << 1) | parity);
|
199 |
|
200 | // wenn Parität gerade ist Ergebnis 0, dazu die Ergebnisse von oben
|
201 | parity = parity_even_bit((dcf77_daten.WTAG << 2) | (dcf77_daten.DATUM_P << 1) | parity);
|
202 |
|
203 | if (parity)
|
204 | {
|
205 | return FALSE; // Fehler
|
206 | }
|
207 | uhrzeit.SEK = 0; // und Zeit übernehmen
|
208 | uhrzeit.MIN = (dcf77_daten.MIN_Z << 4) | dcf77_daten.MIN_E;
|
209 | uhrzeit.STU = (dcf77_daten.STU_Z << 4) | dcf77_daten.STU_E;
|
210 | uhrzeit.WTAG = dcf77_daten.WTAG; //
|
211 | uhrzeit.TAG = (dcf77_daten.TAG_Z << 4) | dcf77_daten.TAG_E;
|
212 | uhrzeit.MON = (dcf77_daten.MON_Z << 4) | dcf77_daten.MON_E;
|
213 | uhrzeit.JAHR = (dcf77_daten.JAHR_Z << 4) | dcf77_daten.JAHR_E;
|
214 | FLAGS.FLAG_MINUTE = 1;
|
215 | FLAGS.FLAG_TAG = 0; // keine Datums-Berechnung in Software nötig
|
216 |
|
217 | return TRUE; // ok
|
218 | }
|
219 |
|
220 | //-----------------------------------------------------------------------------------------
|