Blame | Last modification | View Log | Download
/*--------------------------------------------------------------------------*//* 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 */staticvoid iic_delay (void){int n;BYTE d;for (n = 4; n; n--) d = PINE;}/* Generate start condition on the IIC bus */staticvoid 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 */staticvoid iic_stop (void){SDA_LOW();iic_delay();SCL_HIGH();iic_delay();SDA_HIGH();iic_delay();}/* Send a byte to the IIC bus */staticBOOL 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 */staticBYTE 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;}