161 lines
4.2 KiB
C++
161 lines
4.2 KiB
C++
/* Das Programm dekodiert die DCF77 Zeit,
|
|
macht die Paritätsprüfung und
|
|
schickt die vier benötigten Ziffern für die Zeitanzeige
|
|
als serielle Daten über den TX Pin 1 an den Anzeigecontroller.
|
|
Datengeschwindigkeit: 9600 Baud
|
|
Wenn ein gültiges Signal gesendet wurde, gibt es eine Pause von 30 Minuten,
|
|
in dieser Zeit wird der DCF Empfänger an Pin 6 abgeschaltet.
|
|
mit Hilfe von: https://wolles-elektronikkiste.de/dcf77-funkuhr
|
|
19.05.2025
|
|
www.buschke.net
|
|
info@buschke.net
|
|
*/
|
|
|
|
#include <util/parity.h> //comment out if you don't use an AVR MCU
|
|
|
|
#define dcfOnOff 6
|
|
int interruptPin = 2;
|
|
|
|
volatile unsigned long lastInt = 0;
|
|
volatile unsigned long long currentBuf = 0;
|
|
volatile byte bufCounter;
|
|
volatile byte parityStat = 0;
|
|
volatile byte dcf77MinuteEiner = 0;
|
|
volatile byte dcf77MinuteZehner = 0;
|
|
volatile byte dcf77HourEiner = 0;
|
|
volatile byte dcf77HourZehner = 0;
|
|
volatile int testVar = 0;
|
|
unsigned long startMillis = 0;
|
|
const long waitingTime = 1800000; // 30 Minuten
|
|
byte dcfState = 0;
|
|
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
pinMode(dcfOnOff, OUTPUT);
|
|
digitalWrite(dcfOnOff, HIGH);
|
|
pinMode(interruptPin, INPUT);
|
|
attachInterrupt(digitalPinToInterrupt(interruptPin), DCF77_ISR, CHANGE);
|
|
}
|
|
|
|
void loop() {
|
|
if (parityStat == 1) {
|
|
delay(100);
|
|
Serial.print(dcf77HourZehner);
|
|
Serial.print(",");
|
|
Serial.print(dcf77HourEiner);
|
|
Serial.print(",");
|
|
Serial.print(dcf77MinuteZehner);
|
|
Serial.print(",");
|
|
Serial.print(dcf77MinuteEiner);
|
|
delay(100);
|
|
|
|
dcfState = LOW;
|
|
digitalWrite(dcfOnOff, dcfState);
|
|
|
|
parityStat = 0;
|
|
|
|
}
|
|
|
|
unsigned long currentMillis = millis();
|
|
|
|
if (currentMillis - startMillis >= waitingTime) {
|
|
startMillis = currentMillis;
|
|
if (dcfState == HIGH) {
|
|
dcfState = LOW;
|
|
}
|
|
else {
|
|
dcfState = HIGH;
|
|
}
|
|
digitalWrite(dcfOnOff, dcfState);
|
|
}
|
|
|
|
}
|
|
|
|
/*************************************************************************
|
|
|
|
lesen des dcf Signals am Pin 2
|
|
|
|
**************************************************************************/
|
|
|
|
void DCF77_ISR() {
|
|
unsigned int dur = 0;
|
|
dur = millis() - lastInt;
|
|
|
|
if (digitalRead(interruptPin)) {
|
|
|
|
if (dur > 1500) {
|
|
|
|
unsigned long highBuf = (currentBuf >> 32) & 0x7FFFFFF;
|
|
unsigned long lowBuf = (currentBuf & 0xFFFFFFFF);
|
|
testVar = bufCounter;
|
|
bufCounter = 0;
|
|
|
|
evaluateSequence();
|
|
currentBuf = 0;
|
|
}
|
|
}
|
|
else {
|
|
if (dur > 150) {
|
|
currentBuf |= ((unsigned long long)1 << bufCounter);
|
|
}
|
|
bufCounter++;
|
|
|
|
}
|
|
lastInt = millis();
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Umwandlung Binärcode in Ziffern
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
void evaluateSequence() {
|
|
parityStat = 1;
|
|
byte dcf77Year = (currentBuf >> 50) & 0xFF; // year = bit 50-57
|
|
byte dcf77Month = (currentBuf >> 45) & 0x1F; // month = bit 45-49
|
|
byte dcf77DayOfWeek = (currentBuf >> 42) & 0x07; // day of the week = bit 42-44
|
|
byte dcf77DayOfMonth = (currentBuf >> 36) & 0x3F; // day of the month = bit 36-41
|
|
byte dcf77Hour = (currentBuf >> 29) & 0x3F;
|
|
dcf77HourEiner = (currentBuf >> 29) & 0xF; // hour = bit 29-34, 6 bit
|
|
dcf77HourZehner = (currentBuf >> 33) & 0x3; // hour = bit 29-34, 6 bit
|
|
byte dcf77Minute = (currentBuf >> 21) & 0x7F;
|
|
dcf77MinuteEiner = (currentBuf >> 21) & 0xF; // minute = 21-27, 7 bit
|
|
dcf77MinuteZehner = (currentBuf >> 25) & 0x7; // minute = 21-27, 7 bit
|
|
|
|
bool parityBitMinute = (currentBuf >> 28) & 1;
|
|
bool parityBitHour = (currentBuf >> 35) & 1;
|
|
bool parityBitDate = (currentBuf >> 58) & 1;
|
|
|
|
if ((parity_even_bit(dcf77Minute)) != parityBitMinute) {
|
|
parityStat = 0;
|
|
}
|
|
if ((parity_even_bit(dcf77Hour)) != parityBitHour) {
|
|
parityStat = 0;
|
|
}
|
|
if (((parity_even_bit(dcf77DayOfMonth) + parity_even_bit(dcf77DayOfWeek)
|
|
+ parity_even_bit(dcf77Month) + parity_even_bit(dcf77Year)) % 2) != parityBitDate)
|
|
{
|
|
parityStat = 0;
|
|
}
|
|
|
|
|
|
|
|
if (dcf77MinuteEiner > 9) {
|
|
parityStat = 0;
|
|
}
|
|
if (dcf77MinuteZehner > 5) {
|
|
parityStat = 0;
|
|
}
|
|
if (dcf77HourEiner > 9) {
|
|
parityStat = 0;
|
|
}
|
|
if (dcf77HourZehner > 2) {
|
|
parityStat = 0;
|
|
}
|
|
if (testVar != 59) {
|
|
parityStat = 0;
|
|
}
|
|
}
|