dcf77.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #include "dcf77.h"
  2. #define DST_BIT 17
  3. #define MIN_BIT 21
  4. #define HOUR_BIT 29
  5. #define DAY_BIT 36
  6. #define WEEKDAY_BIT 42
  7. #define MONTH_BIT 45
  8. #define YEAR_BIT 50
  9. static uint8_t dcf77_bits[] = {
  10. 0, // 00: Start of minute
  11. 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 01: Weather broadcast / Civil warning bits
  12. 8, // 15: Call bit: abnormal transmitter operation
  13. 0, // 16: Summer time announcement. Set during hour before change
  14. 0, 1, // 17: 01=CET, 10=CEST
  15. 0, // 19: Leap second announcement. Set during hour before leap second
  16. 1, // 20: Start of encoded time
  17. 8, 0, 0, 0, 0, 0, 0, 0, // 21: Minutes (7bit + parity, 00-59)
  18. 8, 0, 0, 0, 0, 0, 0, // 29: Hours (6bit + parity, 0-23)
  19. 8, 0, 0, 0, 0, 0, // 36: Day of month (6bit, 1-31)
  20. 8, 0, 0, // 42: Day of week (3bit, 1-7, Monday=1)
  21. 8, 0, 0, 0, 0, // 45: Month number (5bit, 1-12)
  22. 8, 0, 0, 0, 0, 0, 0, 0, 0, // 50: Year within century (8bit + parity, 00-99)
  23. 0 // 59: Not used
  24. };
  25. void dcf77_encode(int start, int len, int val, int par) {
  26. uint8_t parity = (par != -1 ? par : dcf77_bits[start]) & 1;
  27. uint8_t byte = ((val / 10) << 4) + (val % 10);
  28. for(int bit = 0; bit < len; bit++) {
  29. uint8_t dcf77_bit = (byte >> bit) & 1;
  30. parity ^= dcf77_bit;
  31. dcf77_bits[start + bit] = (dcf77_bits[start + bit] & 0x0E) + dcf77_bit;
  32. }
  33. dcf77_bits[start + len] = (dcf77_bits[start + len] & 0xE) + (parity & 1);
  34. }
  35. void set_dcf77_time(DateTime* dt, bool is_dst) {
  36. dcf77_encode(DST_BIT, 2, is_dst > 0 ? 1 : 2, 1); // parity = leap second -> 0
  37. dcf77_encode(MIN_BIT, 7, dt->minute, 0);
  38. dcf77_encode(HOUR_BIT, 6, dt->hour, 0);
  39. dcf77_encode(DAY_BIT, 6, dt->day, 0);
  40. dcf77_encode(WEEKDAY_BIT, 3, dt->weekday, -1);
  41. dcf77_encode(MONTH_BIT, 5, dt->month, -1);
  42. dcf77_encode(YEAR_BIT, 8, dt->year % 100, -1);
  43. }
  44. bool get_dcf77_bit(int sec) {
  45. return dcf77_bits[sec % 60] & 1;
  46. }
  47. char* get_dcf77_data(int sec) {
  48. static char data[70];
  49. int idx = 0;
  50. int start = sec > 25 ? sec - 25 : 0;
  51. for(int bit = start; bit <= sec; bit++) {
  52. if(dcf77_bits[bit] & 8) data[idx++] = '-';
  53. data[idx++] = '0' + (dcf77_bits[bit] & 1);
  54. }
  55. data[idx] = 0;
  56. return data;
  57. }