Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "dcf.h"
- #include <time.h>
- #include <inttypes.h>
- // 8-bit BCD decoder
- static inline int dcf_decode_bcd( uint8_t bits )
- {
- return ( bits & 0x0f ) + 10 * ( ( bits >> 4 ) & 0x0f );
- }
- // Checks parity of `n' bits starting at `start'
- static int dcf_parity( uint64_t frame, int start, int n )
- {
- int parity = 0;
- uint64_t b;
- for ( b = ( 1ul << start ); b != ( 1ul << ( start + n ) ); b <<= 1 )
- parity ^= !!( frame & b );
- return parity;
- }
- // Convert DCF77 frame to `struct tm`
- static int dcf_parse( struct tm *t, uint64_t frame )
- {
- if ( t == NULL ) return 0;
- // Validate frame
- if ( frame & ( 1 << 0 ) ) return 0; // Start of minute - 0
- if ( ~frame & ( 1ul << 20 ) ) return 0; // Start of time - 1
- if ( ~( frame ^ ( frame >> 1 ) ) & ( 1ul << 17 ) ) return 0; // Exclusive CET / CEST
- if ( dcf_parity( frame, 21, 8 ) ) return 0; // Minute parity
- if ( dcf_parity( frame, 29, 7 ) ) return 0; // Hour parity
- if ( dcf_parity( frame, 36, 23 ) ) return 0; // Date parity
- // Construct time struct
- t->tm_sec = 0;
- t->tm_min = dcf_decode_bcd( ( frame >> 21 ) & 0x7f ); // 7 bits
- t->tm_hour = dcf_decode_bcd( ( frame >> 29 ) & 0x3f ); // 6 bits
- t->tm_mday = dcf_decode_bcd( ( frame >> 36 ) & 0x3f ); // 6 bits
- t->tm_mon = dcf_decode_bcd( ( frame >> 45 ) & 0x1f ) - 1; // 5 bits
- t->tm_year = dcf_decode_bcd( ( frame >> 50 ) & 0xff ) + 100; // 8 bits
- t->tm_wday = dcf_decode_bcd( ( frame >> 42 ) & 0x07 ) - 1; // 3 bits
- t->tm_yday = 0; // FIXME?
- t->tm_isdst = !!( frame & ( 1ul << 17 ) ); // CEST
- return 1;
- }
- // Enqueues an incoming data bit for parsing
- int dcf_pushbit( struct tm *t, int state, int duration )
- {
- static uint64_t buffer = 0; // Frame buffer
- static int length = 0; // Number of bits received so far
- int bit = 0; // Received bit value. Ignore if `err' is set
- int err = 0; // Set if impulse has invalid duration
- // Determine bit value
- if ( state == 0 )
- {
- if ( duration < 600 || duration > 1400 ) err = 1;
- }
- else
- {
- if ( duration >= 40 && duration <= 130 ) bit = 0; // 0 - 100ms
- else if ( duration >= 140 && duration <= 250 ) bit = 1; // 1 - 200ms
- else err = 1;
- }
- // Check bit error
- if ( err )
- {
- if ( length == 59 )
- {
- err = dcf_parse( t, buffer );
- buffer = 0;
- length = 0;
- return err;
- }
- else
- {
- buffer = 0;
- length = 0;
- return 0;
- }
- }
- else if ( state == 1 )
- {
- buffer >>= 1;
- buffer |= ( (uint64_t) bit << 58 );
- length++;
- }
- return 0;
- }
Add Comment
Please, Sign In to add comment