0,0 → 1,252 |
/*--------------------------------------------------------------------------*/ |
/* RTC controls */ |
|
#include <avr/io.h> |
#include <string.h> |
#include "rtc.h" |
|
|
|
#define SCL_LOW() DDRE |= 0x04 /* SCL = LOW */ |
#define SCL_HIGH() DDRE &= 0xFB /* SCL = High-Z */ |
#define SCL_VAL ((PINE & 0x04) ? 1 : 0) /* SCL input level */ |
#define SDA_LOW() DDRE |= 0x08 /* SDA = LOW */ |
#define SDA_HIGH() DDRE &= 0xF7 /* SDA = High-Z */ |
#define SDA_VAL ((PINE & 0x08) ? 1 : 0) /* SDA input level */ |
|
|
|
static |
void iic_delay (void) |
{ |
int n; |
BYTE d; |
|
for (n = 4; n; n--) d = PINE; |
} |
|
|
/* Generate start condition on the IIC bus */ |
static |
void iic_start (void) |
{ |
SDA_HIGH(); |
iic_delay(); |
SCL_HIGH(); |
iic_delay(); |
SDA_LOW(); |
iic_delay(); |
SCL_LOW(); |
iic_delay(); |
} |
|
|
/* Generate stop condition on the IIC bus */ |
static |
void iic_stop (void) |
{ |
SDA_LOW(); |
iic_delay(); |
SCL_HIGH(); |
iic_delay(); |
SDA_HIGH(); |
iic_delay(); |
} |
|
|
/* Send a byte to the IIC bus */ |
static |
BOOL iic_send (BYTE dat) |
{ |
BYTE b = 0x80; |
BOOL ack; |
|
|
do { |
if (dat & b) { /* SDA = Z/L */ |
SDA_HIGH(); |
} else { |
SDA_LOW(); |
} |
iic_delay(); |
SCL_HIGH(); |
iic_delay(); |
SCL_LOW(); |
iic_delay(); |
} while (b >>= 1); |
SDA_HIGH(); |
iic_delay(); |
SCL_HIGH(); |
ack = SDA_VAL ? FALSE : TRUE; /* Sample ACK */ |
iic_delay(); |
SCL_LOW(); |
iic_delay(); |
return ack; |
} |
|
|
/* Receive a byte from the IIC bus */ |
static |
BYTE iic_rcvr (BOOL ack) |
{ |
UINT d = 1; |
|
|
do { |
d <<= 1; |
SCL_HIGH(); |
if (SDA_VAL) d++; |
iic_delay(); |
SCL_LOW(); |
iic_delay(); |
} while (d < 0x100); |
if (ack) { /* SDA = ACK */ |
SDA_LOW(); |
} else { |
SDA_HIGH(); |
} |
iic_delay(); |
SCL_HIGH(); |
iic_delay(); |
SCL_LOW(); |
SDA_HIGH(); |
iic_delay(); |
|
return (BYTE)d; |
} |
|
|
|
|
BOOL rtc_read ( |
UINT adr, /* Read start address */ |
UINT cnt, /* Read byte count */ |
void* buff /* Read data buffer */ |
) |
{ |
BYTE *rbuff = buff; |
int n; |
|
|
if (!cnt) return FALSE; |
|
n = 10; |
do { /* Select DS1338 (0xD0) */ |
iic_start(); |
} while (!iic_send(0xD0) && --n); |
if (!n) return FALSE; |
|
if (iic_send((BYTE)adr)) { /* Set start address */ |
iic_start(); /* Reselect DS1338 in read mode (0xD1) */ |
if (iic_send(0xD1)) { |
do { /* Receive data */ |
cnt--; |
*rbuff++ = iic_rcvr(cnt ? TRUE : FALSE); |
} while (cnt); |
} |
} |
|
iic_stop(); /* Deselect device */ |
|
return cnt ? FALSE : TRUE; |
} |
|
|
|
|
BOOL rtc_write ( |
UINT adr, /* Write start address */ |
UINT cnt, /* Write byte count */ |
const void* buff /* Data to be written */ |
) |
{ |
const BYTE *wbuff = buff; |
int n; |
|
|
if (!cnt) return FALSE; |
|
n = 10; |
do { /* Select DS1338 (0xD0) */ |
iic_start(); |
} while (!iic_send(0xD0) && --n); |
if (!n) return FALSE; |
|
if (iic_send((BYTE)adr)) { /* Set start address */ |
do { /* Send data */ |
if (!iic_send(*wbuff++)) break; |
} while (--cnt); |
} |
|
iic_stop(); /* Deselect device */ |
|
return cnt ? FALSE : TRUE; |
} |
|
|
|
|
BOOL rtc_gettime (RTC *rtc) |
{ |
BYTE buf[8]; |
|
|
if (!rtc_read(0, 7, buf)) return FALSE; |
|
rtc->sec = (buf[0] & 0x0F) + ((buf[0] >> 4) & 7) * 10; |
rtc->min = (buf[1] & 0x0F) + (buf[1] >> 4) * 10; |
rtc->hour = (buf[2] & 0x0F) + ((buf[2] >> 4) & 3) * 10; |
rtc->mday = (buf[4] & 0x0F) + ((buf[4] >> 4) & 3) * 10; |
rtc->month = (buf[5] & 0x0F) + ((buf[5] >> 4) & 1) * 10; |
rtc->year = 2000 + (buf[6] & 0x0F) + (buf[6] >> 4) * 10; |
|
return TRUE; |
} |
|
|
|
|
BOOL rtc_settime (const RTC *rtc) |
{ |
|
BYTE buf[8]; |
|
|
buf[0] = rtc->sec / 10 * 16 + rtc->sec % 10; |
buf[1] = rtc->min / 10 * 16 + rtc->min % 10; |
buf[2] = rtc->hour / 10 * 16 + rtc->hour % 10; |
buf[3] = 0; |
buf[4] = rtc->mday / 10 * 16 + rtc->mday % 10; |
buf[5] = rtc->month / 10 * 16 + rtc->month % 10; |
buf[6] = (rtc->year - 2000) / 10 * 16 + (rtc->year - 2000) % 10; |
rtc_write(0, 7, buf); |
|
return TRUE; |
} |
|
|
|
|
BOOL rtc_init (void) |
{ |
BYTE buf[8]; /* RTC R/W buffer */ |
UINT n; |
|
|
/* Read RTC registers */ |
if (!rtc_read(0, 8, buf)) return FALSE; /* IIC error */ |
|
if (buf[7] & 0x20) { /* When RTC data has been broken, set default time */ |
/* Reset time to Jan 1, '08 */ |
memset(buf, 0, 8); |
buf[4] = 1; buf[5] = 1; buf[6] = 8; |
rtc_write(0, 8, buf); |
/* Clear data memory */ |
memset(buf, 0, 8); |
for (n = 8; n < 64; n += 8) |
rtc_write(n, 8, buf); |
return FALSE; |
} |
return TRUE; |
} |
|