diff --git a/README.md b/README.md index 36a49e9..40aecba 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -rtc +RTC =============== -AVR gcc RTC Library for DS1307 \ No newline at end of file +AVR gcc RTC Library for DS1307 diff --git a/rtc.c b/rtc.c new file mode 100644 index 0000000..7eeff85 --- /dev/null +++ b/rtc.c @@ -0,0 +1,391 @@ +/** + * @file rtc.c + * + * @date 05.07.2012 + * @author Pascal Gollor + * web http://www.pgollor.de + * + * @copyright Dieses Werk ist unter einer Creative Commons Lizenz vom Typ + * Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich. + * Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie + * http://creativecommons.org/licenses/by-nc-sa/3.0/de/ oder wenden Sie sich + * brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + * + * -- englisch version -- + * @n This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + * + */ + +#include "rtc.h" + +#include "i2cmaster.h" + + +/** + * @brief system time + */ +time rtc_time; + +/** + * @brief system date + */ +date rtc_date; + +/** + * @brief init flag + */ +uint8_t init_rtc = 0; + + +/** + * decimal to binary + * @param val : decimal + * @return binary + */ +uint8_t DecToBcd(uint8_t val) +{ + return (val/10*16) + (val%10); +} + +/** + * binary to decimal + * @param val : binary + * @return decimal + */ +uint8_t BcdToDec(uint8_t val) +{ + return (val/16*10) + (val%16); +} + +/** + * @brief enable RTC device + * @param e: enable + * + * e = 1: enable + * e = 0: disable + */ +void rtc_enable(uint8_t e) +{ + uint8_t second = rtc_read_ram(0x00) & 0b01111111; + second = BcdToDec(second); + if (e == 1) + { + second = DecToBcd(second) & 0b01111111; + rtc_write_ram(0x00, second); + } + else if (e == 0) + { + second = DecToBcd(second) | 0b10000000; + rtc_write_ram(0x00, second); + } +} + +/** + * @brief write to RTC RAM + * @param addr : address + * @param val : value to write + */ +void rtc_write_ram(uint8_t addr, uint8_t val) +{ + if (init_rtc == 0) + return; + + i2c_start_wait(I2C_RTC+I2C_WRITE); + i2c_write(addr); + i2c_write(val); + i2c_stop(); +} + +/** + * @brief read from RTC RAM + * @param addr : address + * @return value from address + */ +uint8_t rtc_read_ram(uint8_t addr) +{ + char val = 0x00; + + if (init_rtc == 0) + return 0; + + i2c_start_wait(I2C_RTC+I2C_WRITE); + i2c_write(addr); + i2c_rep_start(I2C_RTC+I2C_READ); + val = i2c_readNak(); + i2c_stop(); + + return val; +} + +/** + * @brief set time and date for RTC + * @param year + * @param month + * @param day + * @param hour + * @param minute + * @param second + */ +void rtc_setup(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) +{ + second = DecToBcd(second) | 0b10000000; + i2c_start_wait(I2C_RTC+I2C_WRITE); + i2c_write(0x00); + i2c_write(second); + i2c_write(DecToBcd(minute)); + i2c_write(DecToBcd(hour)); + i2c_write(DecToBcd(1)); + i2c_write(DecToBcd(day)); + i2c_write(DecToBcd(month)); + i2c_write(DecToBcd(year)); + i2c_write(0b00010000); // clock out = 1Hz + i2c_stop(); + + rtc_enable(1); + + rtc_read(); +} + +/** + * @brief set date to RTC + * @param datum: date + */ +void rtc_set_date(date* datum) +{ + // stop rtc + rtc_enable(0); + + i2c_start_wait(I2C_RTC+I2C_WRITE); + i2c_write(0x04); + i2c_write(DecToBcd(datum->day)); + i2c_write(DecToBcd(datum->month)); + i2c_write(DecToBcd(datum->year)); + i2c_write(0b00010000); + i2c_stop(); + + // start rtc + rtc_enable(1); + + rtc_read(); +} + +/** + * @brief set time to RTC + * @param zeit: time + */ +void rtc_set_time(time* zeit) +{ + uint8_t second = DecToBcd(zeit->second) | 0b10000000; + + i2c_start_wait(I2C_RTC+I2C_WRITE); + i2c_write(0x00); + i2c_write(second); + i2c_write(DecToBcd(zeit->minute)); + i2c_write(DecToBcd(zeit->hour)); + i2c_stop(); + + // start rtc + rtc_enable(1); + + rtc_read(); +} + +/** + * initialize the RTC device on startup + * @retval 0: accessible + * @retval 1: failed to access device + */ +uint8_t rtc_init(void) +{ + init_rtc = 0; + + rtc_time.hour = 0; + rtc_time.minute = 0; + rtc_time.second = 0; + rtc_date.day = 0; + rtc_date.month = 0; + rtc_date.weekday = 0; + rtc_date.year = 0; + +#ifdef DEBUG + uart_puts_P("init rtc.. "); +#endif + + for (int i = 0; i < 100; i++) + { + if (i2c_start(I2C_RTC+I2C_READ) != 0) + { + i2c_stop(); + } + else + { + init_rtc = 1; + break; + } + } + + if (init_rtc == 0) + { +#ifdef DEBUG + uart_puts_P("fail" CR); +#endif + return 0; + } + + i2c_stop(); + + rtc_write_ram(0x07, 0b00010000); + rtc_enable(1); + rtc_read(); + + init_rtc = 1; + +#ifdef DEBUG + uart_puts_P("okay" CR); +#endif + + return 1; +} + +/** + * @brief read date and time from RTC Device + * + * save date and time in global vars + */ +void rtc_read(void) +{ + if (init_rtc == 0) + return; + + i2c_start_wait(I2C_RTC+I2C_WRITE); + i2c_write(0x00); + i2c_rep_start(I2C_RTC+I2C_READ); + rtc_time.second = i2c_readAck() & 0b01111111; + rtc_time.second = BcdToDec(rtc_time.second); + rtc_time.minute = BcdToDec(i2c_readAck()); + rtc_time.hour = i2c_readAck() & 0b00111111; + rtc_time.hour = BcdToDec(rtc_time.hour); + rtc_date.weekday = BcdToDec(i2c_readAck()); + rtc_date.day = BcdToDec(i2c_readAck()); + rtc_date.month = BcdToDec(i2c_readAck()); + rtc_date.year = BcdToDec(i2c_readNak()); + i2c_stop(); +} + +/** + * @brief add one second + */ +void rtc_inc(void) +{ + rtc_time.second++; + if (rtc_time.second >= 60) + { + rtc_time.second = 0; + rtc_time.minute++; + + if (rtc_time.minute >= 60) + { + rtc_time.minute = 0; + rtc_time.hour++; + + if (rtc_time.hour >= 24) + { + rtc_time.hour = 0; + rtc_date.day++; + + // wenn keine rtc verfuegbar werden Monate und Jahre nicht hochgezaehlt + } + } + } +} + +/** + * @brief get second from global var + * @return second + */ +uint8_t rtc_getSecond(void) +{ + return rtc_time.second; +} + +/** + * @brief get minute from global var + * @return minute + */ +uint8_t rtc_getMinute(void) +{ + return rtc_time.minute; +} + +/** + * @brief get hour from global var + * @return hour + */ +uint8_t rtc_getHour(void) +{ + return rtc_time.hour; +} + +/** + * @brief get day from global var + * @return day + */ +uint8_t rtc_getDay(void) +{ + return rtc_date.day; +} + +/** + * @brief get month from global var + * @return month + */ +uint8_t rtc_getMonth(void) +{ + return rtc_date.month; +} + +/** + * @brief get year from global var + * @return year + */ +uint8_t rtc_getYear(void) +{ + return rtc_date.year; +} + +/** + * @brief get copy of global time struct + * @return time + */ +time rtc_getTime(void) +{ + return rtc_time; +} + +/** + * @brief get global time struct pointer + * @return time + */ +time* rtc_getTimeP(void) +{ + return &rtc_time; +} + +/** + * @brief get copy of global date struct + * @return date + */ +date rtc_getDate(void) +{ + return rtc_date; +} + +/** + * @brief get global date struct pointer + * @return date + */ +date* rtc_getDateP(void) +{ + return &rtc_date; +} + diff --git a/rtc.h b/rtc.h new file mode 100644 index 0000000..249084a --- /dev/null +++ b/rtc.h @@ -0,0 +1,75 @@ +/** + * @file rtc.h + * + * @date 05.07.2012 + * @author Pascal Gollor + * web http://www.pgollor.de + * + * @copyright Dieses Werk ist unter einer Creative Commons Lizenz vom Typ + * Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich. + * Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie + * http://creativecommons.org/licenses/by-nc-sa/3.0/de/ oder wenden Sie sich + * brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + * + * -- englisch version -- + * @n This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + * + */ + +#ifndef RTC_H_ +#define RTC_H_ + + +#include + + + +// I2C real time clock +#define I2C_RTC 0xD0 + + +struct str_time +{ + uint8_t second; + uint8_t minute; + uint8_t hour; +}; +typedef struct str_time time; + +struct str_date +{ + uint8_t day; + uint8_t month; + uint8_t year; + uint8_t weekday; +}; +typedef struct str_date date; + + +uint8_t DecToBcd(uint8_t val); +uint8_t BcdToDec(uint8_t val); + + +void rtc_setup(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); +void rtc_set_date(date* datum); +void rtc_set_time(time* zeit); +uint8_t rtc_init(void); +void rtc_read(void); +void rtc_enable(uint8_t e); +void rtc_write_ram(uint8_t, uint8_t); +uint8_t rtc_read_ram(uint8_t); +void rtc_inc(void); + +uint8_t rtc_getSecond(void); +uint8_t rtc_getMinute(void); +uint8_t rtc_getHour(void); +uint8_t rtc_getDay(void); +uint8_t rtc_getMonth(void); +uint8_t rtc_getYear(void); +time rtc_getTime(void); +time* rtc_getTimeP(void); +date rtc_getDate(void); +date* rtc_getDateP(void); + + +#endif /* RTC_H_ */