1 | /*
|
2 | * main.c
|
3 | *
|
4 | * Created: 01.10.2018 10:34:47
|
5 | * Author : Ingo
|
6 | */
|
7 |
|
8 | #include <avr/io.h>
|
9 | #include <stdint.h>
|
10 | #include <string.h>
|
11 | #include <avr/interrupt.h>
|
12 |
|
13 |
|
14 | #define DCF77_DDR DDRD
|
15 | #define DCF77_PORT PORTD
|
16 | #define DCF77_PIN PD0
|
17 | #define ONE_PULSE_TIME 200
|
18 | #define ZERO_PULSE_TIME 100
|
19 | #define PERIOD 1000
|
20 |
|
21 | #define BEGIN_ZEITINFO 20
|
22 | #define BEGIN_MINUTE 21
|
23 | #define ENDE_MINUTE 27
|
24 | #define PARI_MINUTE 28
|
25 | #define BEGIN_STUNDE 29
|
26 | #define ENDE_STUNDE 34
|
27 | #define PARI_STUNDE 35
|
28 |
|
29 | #define TIMEBASE_1MS TIMER1_COMPA_vect
|
30 |
|
31 | static void LogicalOne ( const int16_t *Millis );
|
32 | static void LogicalZero ( const int16_t *Millis );
|
33 |
|
34 | struct {
|
35 | struct {
|
36 | uint8_t ByteMinute, ByteHour;
|
37 | }bcd;
|
38 |
|
39 | uint8_t ParityCountMinute, ParityCountHour;
|
40 | uint8_t BitCounter;
|
41 | }DCF77;
|
42 |
|
43 | struct {
|
44 | uint8_t Sekunden, Minuten, Stunden;
|
45 | }Uhr;
|
46 |
|
47 | int main( void )
|
48 | {
|
49 | //////////////////////////////////////////////////////////////////////////
|
50 | // Oszillator Fine-Tune
|
51 | OSCCAL = 0x43;
|
52 |
|
53 | //////////////////////////////////////////////////////////////////////////
|
54 | // Variablen
|
55 | Uhr.Stunden = 12;
|
56 | Uhr.Minuten = 34;
|
57 | DCF77.BitCounter = 0;
|
58 | DCF77.bcd.ByteMinute = (Uhr.Minuten/10 << 4) | Uhr.Minuten % 10;
|
59 | DCF77.bcd.ByteHour = (Uhr.Stunden/10 << 4) | Uhr.Stunden % 10;
|
60 |
|
61 | //////////////////////////////////////////////////////////////////////////
|
62 | // IOs
|
63 | DCF77_DDR |= (1<<DCF77_PIN);
|
64 |
|
65 | //////////////////////////////////////////////////////////////////////////
|
66 | // Timer (Systick)
|
67 | OCR1A = 7999; // 8MHz/ 7999 = 1kHz
|
68 | TCCR1B |= (1<<CS10) | (1<<WGM12); // Prescaler = 1
|
69 | TIMSK1 |= (1<<OCIE1A);
|
70 |
|
71 | //////////////////////////////////////////////////////////////////////////
|
72 | // Global Interrupt enable
|
73 | sei();
|
74 |
|
75 | //////////////////////////////////////////////////////////////////////////
|
76 | while ( "DCF77 Sending" ){
|
77 | // Nothing to do ;)
|
78 | }
|
79 | }
|
80 |
|
81 | //////////////////////////////////////////////////////////////////////////
|
82 | // Uhr nachführen, DCF-77 Signal austakten
|
83 | //////////////////////////////////////////////////////////////////////////
|
84 | ISR ( TIMEBASE_1MS )
|
85 | {
|
86 | static int16_t Millis = -1;
|
87 | //////////////////////////////////////////////////////////////////////////
|
88 | // Uhr
|
89 | if ( ++Millis >= PERIOD ){
|
90 | if ( ++Uhr.Sekunden >= 60 ){
|
91 | Uhr.Sekunden = 0;
|
92 | if (++ Uhr.Minuten >= 60 ){
|
93 | Uhr.Minuten = 0;
|
94 | if ( ++Uhr.Stunden >= 24 ){
|
95 | Uhr.Stunden = 0;
|
96 | }
|
97 | }
|
98 | }
|
99 |
|
100 | DCF77.bcd.ByteMinute = (Uhr.Minuten/10 << 4) | Uhr.Minuten % 10;
|
101 | DCF77.bcd.ByteHour = (Uhr.Stunden/10 << 4) | Uhr.Stunden % 10;
|
102 |
|
103 | Millis = 0;
|
104 | DCF77.ParityCountMinute = 0;
|
105 | DCF77.ParityCountHour = 0;
|
106 | if ( ++DCF77.BitCounter >= 60 ) DCF77.BitCounter = 0;
|
107 | }
|
108 |
|
109 | //////////////////////////////////////////////////////////////////////////
|
110 | // Bit 0...19 => Null
|
111 | if ( DCF77.BitCounter < BEGIN_ZEITINFO ){
|
112 | LogicalZero( &Millis );
|
113 | }
|
114 |
|
115 | //////////////////////////////////////////////////////////////////////////
|
116 | // 1 gemäß "Beginn Zeitinformation"
|
117 | else if ( DCF77.BitCounter == BEGIN_ZEITINFO ){
|
118 | LogicalOne( &Millis );
|
119 | }
|
120 |
|
121 | //////////////////////////////////////////////////////////////////////////
|
122 | // Zeitinformation Minuten
|
123 | else if ( DCF77.BitCounter >= BEGIN_MINUTE && DCF77.BitCounter <= ENDE_MINUTE ){
|
124 | if ( DCF77.bcd.ByteMinute & (1<<(DCF77.BitCounter-BEGIN_MINUTE)) ){// 1
|
125 | if ( Millis == 0 ) DCF77.ParityCountMinute++;
|
126 | LogicalOne( &Millis );
|
127 | }
|
128 | else{//0
|
129 | LogicalZero( &Millis );
|
130 | }
|
131 | }
|
132 |
|
133 | // Parität Minute
|
134 | else if ( DCF77.BitCounter == PARI_MINUTE ){
|
135 | if ( DCF77.ParityCountMinute % 2 == 0 ){
|
136 | LogicalOne( &Millis );
|
137 | }else{
|
138 | LogicalZero( &Millis );
|
139 | }
|
140 | }
|
141 |
|
142 | //////////////////////////////////////////////////////////////////////////
|
143 | // Zeitinformation Stunden
|
144 | else if ( DCF77.BitCounter >= BEGIN_STUNDE && DCF77.BitCounter <= ENDE_STUNDE ){
|
145 | if ( DCF77.bcd.ByteHour & (1<<(DCF77.BitCounter-BEGIN_STUNDE)) ){// 1
|
146 | if ( Millis == 0 ) DCF77.ParityCountHour++;
|
147 | LogicalOne( &Millis );
|
148 | }
|
149 | else{//0
|
150 | LogicalZero( &Millis );
|
151 | }
|
152 | }
|
153 |
|
154 | // Parität Stunde
|
155 | else if ( DCF77.BitCounter == PARI_STUNDE ){
|
156 | if ( DCF77.ParityCountHour % 2 == 0 ){
|
157 | LogicalOne( &Millis );
|
158 | }else{
|
159 | LogicalZero( &Millis );
|
160 | }
|
161 | }
|
162 |
|
163 | //////////////////////////////////////////////////////////////////////////
|
164 | // Nullen bis zum Ende
|
165 | else if ( DCF77.BitCounter >= 36 && DCF77.BitCounter < 59 ){
|
166 | LogicalZero( &Millis );
|
167 | }
|
168 |
|
169 | //Ende
|
170 | }
|
171 |
|
172 | // DCF-Zeichen für logische 1
|
173 | static void LogicalOne ( const int16_t *Millis )
|
174 | {
|
175 | if ( *Millis < ONE_PULSE_TIME ){
|
176 | DCF77_PORT |= (1<<DCF77_PIN);
|
177 | }else{
|
178 | DCF77_PORT &= ~(1<<DCF77_PIN);
|
179 | }
|
180 | }
|
181 |
|
182 | // DCF-Zeichen für logische 0
|
183 | static void LogicalZero ( const int16_t *Millis )
|
184 | {
|
185 | if ( *Millis < ZERO_PULSE_TIME ){
|
186 | DCF77_PORT |= (1<<DCF77_PIN);
|
187 | }else{
|
188 | DCF77_PORT &= ~(1<<DCF77_PIN);
|
189 | }
|
190 | }
|