DCF77 fixes

This commit is contained in:
Klaus K Wilting 2019-02-05 23:50:05 +01:00
parent 82489524d3
commit 3c913095a2
3 changed files with 67 additions and 40 deletions

View File

@ -7,10 +7,15 @@ extern TaskHandle_t DCF77Task;
extern hw_timer_t *dcfCycle; extern hw_timer_t *dcfCycle;
enum dcf_pulses { dcf_off, dcf_zero, dcf_one }; enum dcf_pulses { dcf_off, dcf_zero, dcf_one };
enum dcf_pinstate { dcf_low, dcf_high };
void IRAM_ATTR DCF77IRQ(void);
int dcf77_init(void); int dcf77_init(void);
void dcf77_loop(void *pvParameters); void dcf77_loop(void *pvParameters);
void IRAM_ATTR DCF77IRQ(void);
void sendDCF77(void); void sendDCF77(void);
void DCF_Out(uint8_t startsec);
void generateTimeframe(time_t t);
void set_DCF77_pin(dcf_pinstate state);
uint8_t dec2bcd(uint8_t dec, uint8_t startpos, uint8_t endpos, uint8_t pArray[]);
#endif #endif

View File

@ -2,9 +2,11 @@
// Emulate a DCF77 radio receiver // Emulate a DCF77 radio receiver
// //
// parts of this code werde adapted from source: // parts of this code werde adapted from source:
//
https://www.elektormagazine.com/labs/dcf77-emulator-with-esp8266-elektor-labs-version-150713 https://www.elektormagazine.com/labs/dcf77-emulator-with-esp8266-elektor-labs-version-150713
// //
// a nice & free logic test program for DCF77 can be found here:
https://www-user.tu-chemnitz.de/~heha/viewzip.cgi/hs/Funkuhr.zip/
//
*/ */
#if defined HAS_DCF77 #if defined HAS_DCF77
@ -25,10 +27,11 @@ uint8_t DCFtimeframe[DCF77_FRAME_SIZE];
// initialize and configure DCF77 output // initialize and configure DCF77 output
int dcf77_init(void) { int dcf77_init(void) {
time_t t, tt;
BitsPending = false; BitsPending = false;
pinMode(HAS_DCF77, OUTPUT); pinMode(HAS_DCF77, OUTPUT);
digitalWrite(HAS_DCF77, HIGH); set_DCF77_pin(dcf_low);
xTaskCreatePinnedToCore(dcf77_loop, // task function xTaskCreatePinnedToCore(dcf77_loop, // task function
"dcf77loop", // name of task "dcf77loop", // name of task
@ -46,34 +49,25 @@ int dcf77_init(void) {
timerAttachInterrupt(dcfCycle, &DCF77IRQ, true); timerAttachInterrupt(dcfCycle, &DCF77IRQ, true);
timerAlarmWrite(dcfCycle, 1000, true); // 100ms cycle timerAlarmWrite(dcfCycle, 1000, true); // 100ms cycle
// wait until beginning of next minute, then start DCF pulse // wait until beginning of next second, then kick off first DCF pulse and
// start timer interrupt
t = tt = now();
do { do {
delay(2); tt = now();
} while (second()); } while (t == tt);
DCF_Out(second(tt));
timerAlarmEnable(dcfCycle); timerAlarmEnable(dcfCycle);
return 1; // success return 1; // success
} // ifdcf77_init } // ifdcf77_init
uint8_t dec2bcd(uint8_t dec, uint8_t startpos, uint8_t endpos, void generateTimeframe(time_t tt) {
uint8_t pArray[]) {
uint8_t data = (dec < 10) ? dec : ((dec / 10) << 4) + (dec % 10);
uint8_t parity = 0;
for (uint8_t n = startpos; n <= endpos; n++) {
pArray[n] = (data & 1) ? dcf_one : dcf_zero;
parity += (data & 1);
data >>= 1;
}
return parity;
}
void generateTimeframe(time_t t) {
uint8_t ParityCount; uint8_t ParityCount;
time_t t = myTZ.toLocal(tt); // convert to local time
// ENCODE HEAD // ENCODE HEAD
// bits 0..19 initialized with zeros // bits 0..19 initialized with zeros
@ -118,24 +112,15 @@ void generateTimeframe(time_t t) {
*/ */
} }
// helper function to convert gps date/time into time_t
time_t nextMinute(time_t t) {
tmElements_t tm;
breakTime(t, tm);
tm.Minute++;
tm.Second = 0;
return makeTime(tm);
}
// called every 100msec by hardware timer to pulse out DCF signal // called every 100msec by hardware timer to pulse out DCF signal
void DCF_Out() { void DCF_Out(uint8_t startsec) {
static uint8_t bit = 0; static uint8_t bit = startsec;
static uint8_t pulse = 0; static uint8_t pulse = 0;
if (!BitsPending) { if (!BitsPending) {
// prepare frame for next minute to send // prepare frame to send for next minute
generateTimeframe(nextMinute(now())); generateTimeframe(now() + 61);
// start blinking symbol on display and kick off timer // start blinking symbol on display and kick off timer
BitsPending = true; BitsPending = true;
} }
@ -146,16 +131,16 @@ void DCF_Out() {
case 0: // start of second -> start of timeframe for logic signal case 0: // start of second -> start of timeframe for logic signal
if (DCFtimeframe[bit] != dcf_off) if (DCFtimeframe[bit] != dcf_off)
digitalWrite(HAS_DCF77, LOW); set_DCF77_pin(dcf_low);
break; break;
case 1: // 100ms after start of second -> end of timeframe for logic 0 case 1: // 100ms after start of second -> end of timeframe for logic 0
if (DCFtimeframe[bit] == dcf_zero) if (DCFtimeframe[bit] == dcf_zero)
digitalWrite(HAS_DCF77, HIGH); set_DCF77_pin(dcf_high);
break; break;
case 2: // 200ms after start of second -> end of timeframe for logic 1 case 2: // 200ms after start of second -> end of timeframe for logic 1
digitalWrite(HAS_DCF77, HIGH); set_DCF77_pin(dcf_high);
break; break;
case 9: // last pulse before next second starts case 9: // last pulse before next second starts
@ -190,10 +175,46 @@ void dcf77_loop(void *pvParameters) {
NULL, NULL,
portMAX_DELAY); // wait forever (missing error handling here...) portMAX_DELAY); // wait forever (missing error handling here...)
DCF_Out(); DCF_Out(0);
} }
BitsPending = false; // stop blink in display, should never be reached BitsPending = false; // stop blink in display, should never be reached
vTaskDelete(DCF77Task); vTaskDelete(DCF77Task);
} // dcf77_loop() } // dcf77_loop()
// helper function to convert decimal to bcd digit
uint8_t dec2bcd(uint8_t dec, uint8_t startpos, uint8_t endpos,
uint8_t pArray[]) {
uint8_t data = (dec < 10) ? dec : ((dec / 10) << 4) + (dec % 10);
uint8_t parity = 0;
for (uint8_t n = startpos; n <= endpos; n++) {
pArray[n] = (data & 1) ? dcf_one : dcf_zero;
parity += (data & 1);
data >>= 1;
}
return parity;
}
// helper function to switch GPIO line with DCF77 signal
void set_DCF77_pin(dcf_pinstate state) {
switch (state) {
case dcf_low:
#ifdef DCF77_ACTIVE_LOW
digitalWrite(HAS_DCF77, HIGH);
#else
digitalWrite(HAS_DCF77, LOW);
#endif
break;
case dcf_high:
#ifdef DCF77_ACTIVE_LOW
digitalWrite(HAS_DCF77, LOW);
#else
digitalWrite(HAS_DCF77, HIGH);
#endif
break;
} // switch
} // DCF77_pulse
#endif // HAS_DCF77 #endif // HAS_DCF77

View File

@ -56,7 +56,8 @@
#define HAS_IF482 9600, SERIAL_7E1, GPIO_NUM_12, GPIO_NUM_14 // IF482 serial port parameters #define HAS_IF482 9600, SERIAL_7E1, GPIO_NUM_12, GPIO_NUM_14 // IF482 serial port parameters
// Settings for DCF77 interface // Settings for DCF77 interface
#define HAS_DCF77 GPIO_NUM_13 #define HAS_DCF77 GPIO_NUM_1
//#define DCF77_ACTIVE_LOW 1
// Pins for LORA chip SPI interface, reset line and interrupt lines // Pins for LORA chip SPI interface, reset line and interrupt lines
#define LORA_SCK (5) #define LORA_SCK (5)