1 | /************************************************************************/
|
2 | /* */
|
3 | /* Decode DCF Time Information */
|
4 | /* */
|
5 | /* Author: Peter Dannegger */
|
6 | /* danni@specs.de */
|
7 | /* */
|
8 | /************************************************************************/
|
9 | #include <avr/pgmspace.h>
|
10 | #define LPM(i) (__LPM_classic__(i))
|
11 |
|
12 | #include <util/delay.h> // only while debugging gboek
|
13 | #include <stdio.h> // only while debugging gboek
|
14 | #include "clock.h"
|
15 | #include "dcf77.h"
|
16 |
|
17 | uint8_t PROGMEM BITNO[] = {
|
18 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // minute
|
19 | 0xFF, // parity
|
20 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, // hour
|
21 | 0xFF, // parity
|
22 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, // day
|
23 | 0x30, 0x31, 0x32, // weekday
|
24 | 0x40, 0x41, 0x42, 0x43, 0x44, // month
|
25 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, // year
|
26 | 0xFF // parity
|
27 | };
|
28 | uint8_t PROGMEM BMASK[] = { 1, 2, 4, 8, 10, 20, 40, 80 };
|
29 |
|
30 | struct time newtime;
|
31 |
|
32 | uint8_t dcf77error = 0;
|
33 | uint8_t synchronize = 0; // successful recieved
|
34 |
|
35 | uint8_t timeflags;
|
36 | uint8_t dcf77_period;
|
37 | uint8_t dcf77_pulse;
|
38 | uint8_t dcf_timer_tick_counter;
|
39 |
|
40 |
|
41 | void dcf77_init ( void ) {
|
42 | DCF_DDR &= ~(1<<DCF) ; // Port auf Input
|
43 | DCF_PORT |= (1<<DCF) ; // PullUp setzen
|
44 | #if ( DEBUG_DCF77 == TRUE )
|
45 | DCF_DEBUG_DDR |= (1<<DCF_DEBUG) ; // Port auf Output
|
46 | #endif
|
47 | }
|
48 | void dcf77_decode( uint8_t pulse ) {
|
49 | static uint8_t parity = 0;
|
50 | uint8_t i;
|
51 | uint8_t *d;
|
52 |
|
53 | i = newtime.second - 21;
|
54 | if( i >= sizeof( BITNO )) {
|
55 | return; // only bit 21 ... 58
|
56 | }
|
57 | parity ^= pulse; // calculate parity
|
58 | i = LPM(&BITNO[i]);
|
59 | if( i == 0xFF ) { // test parity
|
60 | if( parity ) {
|
61 | dcf77error = 1;
|
62 | debug_num2port(50); // Parityfehler, dcf77error=1
|
63 | }
|
64 | parity = 0;
|
65 | return;
|
66 | }
|
67 | d = (uint8_t *)&newtime.minute + (i >> 4); // byte address
|
68 | i &= 0x0F; // bit number
|
69 | if( i == 0 ) {
|
70 | *d = 0; // clear all, if lsb
|
71 | }
|
72 | if( pulse ) {
|
73 | *d += LPM(&BMASK[i]); // set bit
|
74 | }
|
75 | }
|
76 | void dcf77_signal_auswerten( void ) {
|
77 | if( dcf77_pulse ) {
|
78 | if( dcf77_pulse >= 7 && dcf77_pulse <= 15 ) { // eine logische null von 100-150ms
|
79 | dcf77_decode( 0 );
|
80 | uart_putc('0');
|
81 | debug_num2port(10); // eine logische 0 wurde erkannt
|
82 | }
|
83 | else {
|
84 | if( dcf77_pulse >= 18 && dcf77_pulse <= 25 ) { // eine logische eins von 200-250ms
|
85 | dcf77_decode( 1 );
|
86 | uart_putc('1');
|
87 | debug_num2port(11); // eine logische 1 wurde erkannt
|
88 | }
|
89 | else {
|
90 | dcf77error = 1;
|
91 | debug_num2port(12); // weder 0 noch 1 wurden erkannt, dcf77error=1
|
92 | debug_num2port(51); // weder 0 noch 1 wurden erkannt, dcf77error=1
|
93 | {
|
94 | char buffer[30];
|
95 | sprintf(buffer, "Error. PulseLenght: %d\n\r",dcf77_pulse);
|
96 | uart_puts(buffer);
|
97 | }
|
98 | }
|
99 | }
|
100 | dcf77_pulse = 0;
|
101 | }
|
102 | if( dcf77_period ) {
|
103 | if( newtime.second < 60 ) {
|
104 | newtime.second++;
|
105 | }
|
106 | if( dcf77_period > 180 && dcf77_period < 220 ) {
|
107 | uart_puts("newSek erkannt\n\r");
|
108 | debug_num2port(30); // Sekunde 59 erkannt, nächster Wert am LogicPort --> (newtime.second), danach (dcf77error + 128)
|
109 | debug_num2port(newtime.second); // = 3
|
110 | debug_num2port(dcf77error + 128); // = 129
|
111 | // {
|
112 | // char buffer[30];
|
113 | // sprintf(buffer, "vorher newtime.sec = %d ",newtime.second);
|
114 | // uart_puts(buffer);
|
115 | // sprintf(buffer, "dcf77error = %d\n\r", dcf77error);
|
116 | // uart_puts(buffer);
|
117 | // }
|
118 |
|
119 | if( dcf77error == 0 && newtime.second == 59) {
|
120 | debug_num2port(31); // bisher dcf77error == 0 und newtime.second == 59
|
121 | synchronize = 0xFF;
|
122 | time = newtime;
|
123 | time.second = 0;
|
124 | sync_sec();
|
125 | uart_puts("set time\n\r");
|
126 | // time.minute = newtime.minute;
|
127 | // time.hour = newtime.hour;
|
128 | // time.wday = newtime.wday;
|
129 | // time.day = newtime.day;
|
130 | // time.month = newtime.month;
|
131 | // time.year = newtime.year;
|
132 | }
|
133 | newtime.second = 0;
|
134 | dcf77error = 0;
|
135 | // {
|
136 | // char buffer[30];
|
137 | // sprintf(buffer, "nachher newtime.sec = %d ",newtime.second);
|
138 | // uart_puts(buffer);
|
139 | // sprintf(buffer, "dcf77error = %d\n\r", dcf77error);
|
140 | // uart_puts(buffer);
|
141 | // }
|
142 |
|
143 | }
|
144 | else {
|
145 | debug_num2port(33); // normale Sekunde, nicht die 59ste
|
146 | debug_num2port(newtime.second); // = 3
|
147 | if( dcf77_period < 90 || dcf77_period > 110) {
|
148 | dcf77error = 1;
|
149 | debug_num2port(34); // Sekunde war <900 oder >1100ms, dcf77error=1
|
150 | debug_num2port(52); // Sekunde war <900 oder >1100ms, dcf77error=1
|
151 | uart_puts("Err: Period <0.9 && >1.1sec\n\r");
|
152 | }
|
153 | }
|
154 | dcf77_period = 0;
|
155 | debug_num2port(35); //
|
156 | }
|
157 | }
|
158 |
|
159 | void dcf77_isr_modul_auslesen ( void ) {
|
160 | // diese Funktion wird von einem Timer Interrupt aufgerufen
|
161 | // hier jetzt alle 10ms
|
162 |
|
163 | #if ( DEBUG_DCF77 == TRUE )
|
164 | #if ( DCF_MODUL_MIT_ACTIVE_LOW == TRUE )
|
165 | if( ~DCF_PIN & (1<<DCF) )
|
166 | #else
|
167 | if( DCF_PIN & (1<<DCF) )
|
168 | #endif
|
169 | {
|
170 | DCF_DEBUG_PORT |= (1<< DCF_DEBUG);
|
171 | }
|
172 | else
|
173 | {
|
174 | DCF_DEBUG_PORT &= ~(1<<DCF_DEBUG);
|
175 | }
|
176 | // DCF_DEBUG_DDR |= (1<<DCF_DEBUG) ; // Port auf Output
|
177 | // DCF_DEBUG_PORT ^= (1<<DCF_DEBUG) ; // Ausgang togglen
|
178 | #endif
|
179 |
|
180 |
|
181 | static uint8_t dcf77_time, old_dcf77;
|
182 | // DCF77 receive
|
183 | if( dcf77_time != 0xFF ) { // stop on 0xFF
|
184 | dcf77_time++; // count ticks
|
185 | }
|
186 | #if ( DCF_MODUL_MIT_ACTIVE_LOW == TRUE )
|
187 | if( ( ~DCF_PIN ^ old_dcf77) & (1<<DCF) ) // pin changed ? (DCF input Port inverted)
|
188 | #else
|
189 | if( ( DCF_PIN ^ old_dcf77) & (1<<DCF) ) // pin changed ?
|
190 | #endif
|
191 | {
|
192 | old_dcf77 ^= 0xFF; // change old flag
|
193 | if( old_dcf77 & (1<<DCF) ) {
|
194 | dcf77_period = dcf77_time; // store ticks of period
|
195 | debug_num2port(40); // folgender Wert --> Periodenlänge der erkannten Sekunde
|
196 | debug_num2port(dcf77_period);
|
197 | dcf77_time = 0; // count next period
|
198 | } else {
|
199 | dcf77_pulse = dcf77_time; // store ticks of pulse
|
200 | debug_num2port(41); // folgender Wert --> Pulslänge der erkannten Sekundenbits
|
201 | debug_num2port(dcf77_pulse);
|
202 | }
|
203 | }
|
204 |
|
205 | /*
|
206 | if( ( DCF_PIN ^ old_dcf77) & (1<<DCF) ) { // pin changed ?
|
207 | old_dcf77 ^= 0xFF; // change old flag
|
208 | if( old_dcf77 & (1<<DCF) ) {
|
209 | dcf77_period = dcf77_time; // store ticks of period
|
210 | dcf77_time = 0; // count next period
|
211 | } else {
|
212 | dcf77_pulse = dcf77_time; // store ticks of pulse
|
213 | }
|
214 | }
|
215 | */ // time base 1 second
|
216 | // TCNT0 = (uint16_t)(256 - T0COUNT); // reload per tick: -183
|
217 | if( ++dcf_timer_tick_counter & 100 ){ // 100 ticks = one second
|
218 | timeflags = 1<<ONE_TICK; // one tick over
|
219 | return;
|
220 | }
|
221 | // TCNT0 = (uint16_t)(256 - T0COUNTSEC); // reload per second: -189
|
222 | // if( timeflags & (1<< ONE_MINUTE ))
|
223 | // TCNT0 = (uint16_t)(256 - T0COUNTMIN); // reload per minute: -234
|
224 | timeflags = 1<<ONE_SECOND^1<<ONE_TICK; // one tick, one second over
|
225 | }
|
226 |
|
227 | void sync_sec( void ) { // synchronize by DCF77
|
228 | // Register so einstellen, dass wieder bei 0 zu zählen begonnen wird
|
229 | // TCNT0 = (uint16_t)(256 - T0COUNTMIN);
|
230 | dcf_timer_tick_counter = 0;
|
231 | timeflags = 0;
|
232 | }
|