# HG changeset patch # User Tero Koskinen # Date 1461599537 -10800 # Mon Apr 25 18:52:17 2016 +0300 # Node ID c9ae47eca21dd30bcad214b908259a1e029b098f # Parent 16a1b4a9af387a7ed8619e0c44207212ba810e6d Add DS3231 driver. diff --git a/ds3231.c b/ds3231.c new file mode 100644 --- /dev/null +++ b/ds3231.c @@ -0,0 +1,83 @@ +// Code originally by JeeLabs http://news.jeelabs.org/code/ +// Released to the public domain! Enjoy! + +#include +#include + +#include "ds3231.h" + +static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); } +static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); } + +#define DS3231_ADDRESS (0x68 << 1) +#define DS3231_CONTROL 0x0E +#define DS3231_STATUSREG 0x0F + +static CTL_I2C_BUS_t *ds3231_i2c_bus = 0; + +int RTC_DS3231_init(CTL_I2C_BUS_t *i2c) +{ + ds3231_i2c_bus = i2c; + + return 0; +} + +int RTC_DS3231_now(struct DS3231_DateTime *dt) { + CTL_STATUS_t s; + uint8_t cmd[1] = { 0 }; + uint8_t reply[7] = { 0 }; + + if (dt == NULL) { + return -1; + } + + s = ctl_i2c_write_read(ds3231_i2c_bus, DS3231_ADDRESS, + cmd, sizeof(cmd), + reply, sizeof(reply)); + if (s != 7+1) + { + return -1; + } + + dt->seconds = bcd2bin(reply[0] & 0x7F); + dt->minutes = bcd2bin(reply[1]); + dt->hours = bcd2bin(reply[2]); + dt->day = bcd2bin(reply[4]); + dt->month = bcd2bin(reply[5]); + dt->year = bcd2bin(reply[6]) + 2000; + + return 0; +} + +int RTC_DS3231_adjust(const struct DS3231_DateTime *dt) { + uint8_t cmd[8]; + uint8_t reply[1]; + CTL_STATUS_t s; + + cmd[0] = 0; + cmd[1] = bin2bcd(dt->seconds); + cmd[2] = bin2bcd(dt->minutes); + cmd[3] = bin2bcd(dt->hours); + cmd[4] = bin2bcd(0); + cmd[5] = bin2bcd(dt->day); + cmd[6] = bin2bcd(dt->month); + cmd[7] = bin2bcd(dt->year - 2000); + + s = ctl_i2c_write(ds3231_i2c_bus, DS3231_ADDRESS, cmd, sizeof(cmd)); + if (s != sizeof(cmd)) { + return -1; + } + + cmd[0] = DS3231_STATUSREG; + s = ctl_i2c_write_read(ds3231_i2c_bus, DS3231_ADDRESS, cmd, 1, reply, 1); + if (s != 2) { + return -2; + } + cmd[1] = reply[0] & (~0x80); // flip OSF bit + s = ctl_i2c_write(ds3231_i2c_bus, DS3231_ADDRESS, cmd, 2); + if (s != 2) { + return -3; + } + + return 0; +} \ No newline at end of file diff --git a/ds3231.h b/ds3231.h new file mode 100644 --- /dev/null +++ b/ds3231.h @@ -0,0 +1,22 @@ +// Code originally by JeeLabs http://news.jeelabs.org/code/ +// Released to the public domain! Enjoy! + +#ifndef DS3231_H +#define DS3231_H + +#include "ctl_i2c.h" + +struct DS3231_DateTime { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; +}; + +int RTC_DS3231_init(CTL_I2C_BUS_t *i2c); +int RTC_DS3231_now(struct DS3231_DateTime *dt); +int RTC_DS3231_adjust(const struct DS3231_DateTime *dt); + +#endif /* DS3231_H */ \ No newline at end of file