?? dcf77.c
字號(hào):
/* $Id: dcf77.c,v 1.10 2005/11/01 15:47:10 simimeie Exp $ * Functions for communicating with the DCF module and calculating time */ #define BV _BV#include <avr/io.h>#include <avr/signal.h>#include "dcf77.h"#include "timers.h"#include "ledmodule.h"#include "timeformat.h"#ifdef DCFDEBUG#include "debugconsole.h"#endif/* These two defines allow us to easily switch between inverted and * not-inverted output. */#define DCFHI BV(PIND2)#define DCFLO 0/* if the last bit was received more than 1.5 seconds ago, then this * signals the start of a minute. */#define BORDER_MINSTART ((3 * TICKSPERSECOND) / 2)#define BORDERU_1BIT ((24 * TICKSPERSECOND) / 100)#define BORDERL_1BIT ((16 * TICKSPERSECOND) / 100)#define BORDERU_0BIT ((14 * TICKSPERSECOND) / 100)#define BORDERL_0BIT (( 6 * TICKSPERSECOND) / 100)#define BITDINDEX(x) ((x & 0xF8) >> 3)#define getbit(x) (bitdata[BITDINDEX(x)] & BV(x & 0x07))#define getbitval(x) ((getbit(x) == 0) ? 0 : 1)static uint8_t bitdata[8];static uint8_t bitsrecvd;static uint8_t lastval;struct tickdata lastchange; /* "Timestamp" of last change */struct dcftime dcftime[2];uint8_t dcfvalid;uint8_t sumbits(uint8_t start, uint8_t end) { uint8_t mult = 1; uint8_t res = 0; while (start <= end) { res += getbitval(start) * mult; if (mult == 8) { mult = 10; } else { mult <<= 1; /* * 2 */ } start++; } return res;}uint8_t paritybits(uint8_t start, uint8_t end) { uint8_t res = 0; while (start <= end) { if (getbit(start)) { res = !res; } start++; } return res;}SIGNAL(SIG_INTERRUPT0) { uint8_t val = PIND; struct tickdata curticks; uint16_t tickdiff; gettickdata(&curticks); val &= BV(PIND2); if (val == lastval) { /* No change at all? why the IRQ then? */ return; } lastval = val; tickdiff = (curticks.seconds - lastchange.seconds) * TICKSPERSECOND + (curticks.ticks - lastchange.ticks); lastchange = curticks; if (val == DCFHI) { /* Signal changed to high */ if (tickdiff > BORDER_MINSTART) { /* Start of a new minute */ led_statusleds &= (uint8_t)~led_status_dcfgood; if (bitsrecvd == 59) { /* Sanity checks */ if (getbit(0)) { /* Bit 0 always has to be 0 */ bitsrecvd++; } if (!getbit(20)) { /* Bit 20 always has to be 1 */ bitsrecvd++; } if (paritybits(21, 28) != 0) { bitsrecvd++; } if (paritybits(29, 35) != 0) { bitsrecvd++; } if (paritybits(36, 58) != 0) { bitsrecvd++; } if (getbit(17) == getbit(18)) { bitsrecvd++; } if (bitsrecvd == 59) { struct brokentime bt; /* None of the sanity checks failed * - time should be valid. */ led_statusleds |= led_status_dcfgood; /* Decode data now */ dcfvalid = !dcfvalid; bt.year = sumbits(50, 57); bt.month = sumbits(45, 49); bt.day = sumbits(36, 41); bt.hour = sumbits(29, 34); bt.min = sumbits(21, 27); bt.sec = 0; dcftime[dcfvalid].timestamp = bttots(&bt); dcftime[dcfvalid].ticksecs = curticks.seconds; dcftime[dcfvalid].issummertime = getbit(17); timers_zero(); gettickdata(&lastchange); } }#ifdef DCFDEBUG debugconsole_printtext("\r\n");#endif bitsrecvd = 0; } } else { /* Signal changed to low */#ifdef LEDMODULE led_statusleds |= led_status_dcfbit;#endif if (bitsrecvd > 60) { return; } if ((tickdiff > BORDERL_1BIT) && (tickdiff < BORDERU_1BIT)) { /* valid '1' bit */ bitdata[BITDINDEX(bitsrecvd)] |= BV(bitsrecvd & 0x07); bitsrecvd++;#ifdef DCFDEBUG debugconsole_printtext("1");#endif } else if ((tickdiff > BORDERL_0BIT) && (tickdiff < BORDERU_0BIT)) { /* valid '0' bit */ bitdata[BITDINDEX(bitsrecvd)] &= (uint8_t)~BV(bitsrecvd & 0x07); bitsrecvd++;#ifdef DCFDEBUG debugconsole_printtext("0"); } else { debugconsole_printtext("X");#endif } }}void dcf77_init(void) { /* Set the IRQ line so that we get an IRQ whenever it changes * its logical level (0 -> 1 or 1 -> 0) */ MCUCR |= BV(ISC00); /* And allow IRQs from that port */ GICR |= BV(INTF0); /* Enable PullUp on Port D pin 2. The Port is already a input on * startup. */ PORTD |= BV(PD2);}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -