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