Files
Funkuhr/Coprozessor_DCF77.ino

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;
}
}