Guest User

Untitled

a guest
Oct 23rd, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.37 KB | None | 0 0
  1. #include "dcf.h"
  2. #include <time.h>
  3. #include <inttypes.h>
  4.  
  5. // 8-bit BCD decoder
  6. static inline int dcf_decode_bcd( uint8_t bits )
  7. {
  8. return ( bits & 0x0f ) + 10 * ( ( bits >> 4 ) & 0x0f );
  9. }
  10.  
  11. // Checks parity of `n' bits starting at `start'
  12. static int dcf_parity( uint64_t frame, int start, int n )
  13. {
  14. int parity = 0;
  15. uint64_t b;
  16. for ( b = ( 1ul << start ); b != ( 1ul << ( start + n ) ); b <<= 1 )
  17. parity ^= !!( frame & b );
  18. return parity;
  19. }
  20.  
  21. // Convert DCF77 frame to `struct tm`
  22. static int dcf_parse( struct tm *t, uint64_t frame )
  23. {
  24. if ( t == NULL ) return 0;
  25.  
  26. // Validate frame
  27. if ( frame & ( 1 << 0 ) ) return 0; // Start of minute - 0
  28. if ( ~frame & ( 1ul << 20 ) ) return 0; // Start of time - 1
  29. if ( ~( frame ^ ( frame >> 1 ) ) & ( 1ul << 17 ) ) return 0; // Exclusive CET / CEST
  30. if ( dcf_parity( frame, 21, 8 ) ) return 0; // Minute parity
  31. if ( dcf_parity( frame, 29, 7 ) ) return 0; // Hour parity
  32. if ( dcf_parity( frame, 36, 23 ) ) return 0; // Date parity
  33.  
  34. // Construct time struct
  35. t->tm_sec = 0;
  36. t->tm_min = dcf_decode_bcd( ( frame >> 21 ) & 0x7f ); // 7 bits
  37. t->tm_hour = dcf_decode_bcd( ( frame >> 29 ) & 0x3f ); // 6 bits
  38. t->tm_mday = dcf_decode_bcd( ( frame >> 36 ) & 0x3f ); // 6 bits
  39. t->tm_mon = dcf_decode_bcd( ( frame >> 45 ) & 0x1f ) - 1; // 5 bits
  40. t->tm_year = dcf_decode_bcd( ( frame >> 50 ) & 0xff ) + 100; // 8 bits
  41. t->tm_wday = dcf_decode_bcd( ( frame >> 42 ) & 0x07 ) - 1; // 3 bits
  42. t->tm_yday = 0; // FIXME?
  43. t->tm_isdst = !!( frame & ( 1ul << 17 ) ); // CEST
  44.  
  45. return 1;
  46. }
  47.  
  48. // Enqueues an incoming data bit for parsing
  49. int dcf_pushbit( struct tm *t, int state, int duration )
  50. {
  51. static uint64_t buffer = 0; // Frame buffer
  52. static int length = 0; // Number of bits received so far
  53. int bit = 0; // Received bit value. Ignore if `err' is set
  54. int err = 0; // Set if impulse has invalid duration
  55.  
  56. // Determine bit value
  57. if ( state == 0 )
  58. {
  59. if ( duration < 600 || duration > 1400 ) err = 1;
  60. }
  61. else
  62. {
  63. if ( duration >= 40 && duration <= 130 ) bit = 0; // 0 - 100ms
  64. else if ( duration >= 140 && duration <= 250 ) bit = 1; // 1 - 200ms
  65. else err = 1;
  66. }
  67.  
  68. // Check bit error
  69. if ( err )
  70. {
  71. if ( length == 59 )
  72. {
  73. err = dcf_parse( t, buffer );
  74. buffer = 0;
  75. length = 0;
  76. return err;
  77. }
  78. else
  79. {
  80. buffer = 0;
  81. length = 0;
  82. return 0;
  83. }
  84. }
  85. else if ( state == 1 )
  86. {
  87. buffer >>= 1;
  88. buffer |= ( (uint64_t) bit << 58 );
  89. length++;
  90. }
  91.  
  92. return 0;
  93. }
Add Comment
Please, Sign In to add comment