DCF77 fixes
This commit is contained in:
parent
82489524d3
commit
3c913095a2
@ -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
|
@ -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
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user