#include #include #include #include "rtc.h" #include "i2c.h" #define DEC_2_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10)) #define BCD_2_DEC(bcd) (((((bcd) >> 4) & 0x0F) * 10) + ((bcd) & 0x0F)) static volatile struct RTC_DATA clock; static void (*rtc_handler)(struct RTC_DATA* clock); void rtc_read_datetime(struct RTC_DATA* data); void rtc_int0_init(void) { MCUCR |= (1<second); clock.buffer[1] = DEC_2_BCD(time->minute); clock.buffer[2] = DEC_2_BCD(time->hour); i2c_writebuf(RTC_I2C_ADDR, 0x02, 3, &clock.buffer); } void rtc_set_date(struct DATE_YMD* date) { clock.buffer[3] = ((date->year & 0x03) << 6) | DEC_2_BCD(date->day); clock.buffer[4] = DEC_2_BCD(date->month); i2c_writebuf(RTC_I2C_ADDR, 0x05, 2, &clock.buffer[3]); i2c_writebuf(RTC_I2C_ADDR, 0x10, 2, (uint8_t*) &date->year); } void rtc_inc_time(uint8_t part) { switch(part) { case SECOND: clock.buffer[0] = clock.time.second + 1; if(clock.buffer[0] >= 60) clock.buffer[0] = 0; break; case MINUTE: clock.buffer[0] = clock.time.minute + 1; if(clock.buffer[0] >= 60) clock.buffer[0] = 0; break; case HOUR: clock.buffer[0] = clock.time.hour + 1; if(clock.buffer[0] >= 24) clock.buffer[0] = 0; break; } clock.buffer[0] = DEC_2_BCD(clock.buffer[0]); i2c_writebuf(RTC_I2C_ADDR, part, 1, &clock.buffer); rtc_invoke_handler(); } void rtc_invoke_handler(void) { if(rtc_handler) { rtc_read_datetime(&clock); rtc_handler(&clock); } } void rtc_handle_event(void) { if(GIFR & (1<buffer); i2c_readbuf(RTC_I2C_ADDR, 0x10, 2, (uint8_t*) &(data->date.year)); char* curr_char = data->time_str; for(uint8_t i=0; i<3; ++i) { // data->time_str *(curr_char++) = ((data->buffer[2-i] & (!i ? 0x3F : 0x7F)) >> 4) + '0'; // Tens *(curr_char++) = (data->buffer[2-i] & 0x0F) + '0'; // Ones *(curr_char++) = i==2 ? 0 : ':'; // Separator // data->time structure *((uint8_t*)(&data->time)+i) = BCD_2_DEC(data->buffer[2-i]); } // data->date structure data->date.day = BCD_2_DEC(data->buffer[3] & 0x3F); // data->date.year uint8_t year = data->buffer[3] >> 6; if((data->date.year & 0x03) != year) { while((data->date.year & 0x03) != year) ++(data->date.year); i2c_writebuf(RTC_I2C_ADDR, 0x10, 2, (uint8_t*) &(data->date.year)); } data->date.month = BCD_2_DEC(data->buffer[4] & 0x1F); data->date.weekday = data->buffer[4] >> 5; // data->date_str curr_char = data->date_str; *(curr_char++) = ((data->buffer[3] & 0x3F) >> 4) + '0'; *(curr_char++) = (data->buffer[3] & 0x0F) + '0'; *(curr_char++) = DATE_SEPARATOR; *(curr_char++) = ((data->buffer[4] & 0x1F) >> 4) + '0'; *(curr_char++) = (data->buffer[4] & 0x0F) + '0'; *(curr_char++) = DATE_SEPARATOR; itoa(data->date.year, curr_char, 10); *(curr_char+4) = 0; }