/** * @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; }