summaryrefslogtreecommitdiff
path: root/avr/pcf8583.c
diff options
context:
space:
mode:
Diffstat (limited to 'avr/pcf8583.c')
-rw-r--r--avr/pcf8583.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/avr/pcf8583.c b/avr/pcf8583.c
new file mode 100644
index 0000000..d33c9b0
--- /dev/null
+++ b/avr/pcf8583.c
@@ -0,0 +1,106 @@
+/*
+ * Date & Time support for Philips PCF8583 RTC
+ */
+
+/* #define DEBUG */
+
+#include "common.h"
+#include <stdlib.h>
+#include "debug.h"
+#include "command.h"
+#include "rtc.h"
+#include "i2c.h"
+
+#define REG_CS 0x00 /* control/status */
+#define REG_CSEC 0x01 /* hundredth of a second */
+#define REG_SEC 0x02 /* seconds */
+#define REG_MIN 0x03 /* minutes */
+#define REG_HOUR 0x04 /* hours */
+#define REG_YRDATE 0x05 /* year/date */
+#define REG_WDMON 0x06 /* weekdays/months */
+#define NR_OF_REGS 7
+
+
+/* ------------------------------------------------------------------------- */
+
+static uint_fast8_t bcd2bin(uint8_t val)
+{
+ return (val >> 4) * 10 + (val & 0x0f);
+}
+
+static uint8_t bin2bcd (uint_fast8_t val)
+{
+ div_t d = div(val, 10);
+
+ return (d.quot << 4) | d.rem;
+}
+
+
+int rtc_get (struct rtc_time *tmp)
+{
+ int rel = 0;
+ uint8_t rtcbuf[NR_OF_REGS];
+ uint16_t year;
+
+ i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, NR_OF_REGS);
+ i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0x10, 1, (uint8_t *) &year, 2);
+
+ debug("Get RTC year: %u, year/date: %02x, wdays/month: %02x, "
+ "hour: %02x, min: %02x, sec: %02x, (stat: %02x)\n", year,
+ rtcbuf[6], rtcbuf[5], rtcbuf[4], rtcbuf[3], rtcbuf[2], rtcbuf[0]);
+
+ tmp->tm_sec = bcd2bin (rtcbuf[REG_SEC] & 0x7F);
+ tmp->tm_min = bcd2bin (rtcbuf[REG_MIN] & 0x7F);
+ tmp->tm_hour = bcd2bin (rtcbuf[REG_HOUR] & 0x3F);
+ tmp->tm_mday = bcd2bin (rtcbuf[REG_YRDATE] & 0x3F);
+ tmp->tm_mon = bcd2bin (rtcbuf[REG_WDMON] & 0x1F);
+ while (year%4 < (rtcbuf[REG_YRDATE]>>6)) {
+ year++;
+ /* TODO: update RTC ram */
+ }
+ tmp->tm_year = year;
+ tmp->tm_wday = rtcbuf[REG_WDMON] >> 5;
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+
+
+ debug ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+ return rel;
+}
+
+int rtc_set (struct rtc_time *tmp)
+{
+ uint8_t rtcbuf[NR_OF_REGS];
+
+ debug ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+ rtcbuf[REG_CS] = 0x84;
+ rtcbuf[REG_CSEC] = 0x00;
+ rtcbuf[REG_WDMON ] = bin2bcd(tmp->tm_mon) | ((tmp->tm_wday) << 5);
+ rtcbuf[REG_YRDATE] = ((tmp->tm_year % 4) << 6) | bin2bcd(tmp->tm_mday);
+ rtcbuf[REG_HOUR ] = bin2bcd(tmp->tm_hour);
+ rtcbuf[REG_MIN ] = bin2bcd(tmp->tm_min);
+ rtcbuf[REG_SEC ] = bin2bcd(tmp->tm_sec);
+
+ i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, NR_OF_REGS);
+ i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0x10, 1, (uint8_t *) &tmp->tm_year, 2);
+ rtcbuf[REG_CS] = 0x04;
+ i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, 1);
+
+
+ return 0;
+}
+
+void rtc_reset (void)
+{
+ uint8_t c = 0;
+
+ i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, &c, 1);
+}
+
+