static void ds1216e_update_clock(rtc_ds1216e_t *context) { int new_osc; int new_reset; int new_12; /* setting centiseconds has no effect on the offset used for the clock, as this is defined in seconds, so any changes to the centiseconds will just be ignored. */ /* prepare clock regs for updating, clear unused bits, fix value offsets */ context->clock_regs[DS1216E_REGISTER_SECONDS] &= 0x7f; context->clock_regs[DS1216E_REGISTER_MINUTES] &= 0x7f; new_12 = context->clock_regs[DS1216E_REGISTER_HOURS] >> 7; context->clock_regs[DS1216E_REGISTER_HOURS] &= 0x3f; new_osc = (context->clock_regs[DS1216E_REGISTER_WEEKDAYS] & 0x20) ? 1 : 0; new_reset = (context->clock_regs[DS1216E_REGISTER_WEEKDAYS] & 0x10) ? 1 : 0; context->clock_regs[DS1216E_REGISTER_WEEKDAYS] &= 7; context->clock_regs[DS1216E_REGISTER_MONTHDAYS] &= 0x3f; context->clock_regs[DS1216E_REGISTER_MONTHS] &= 0x1f; if (context->inactive) { if (context->clock_regs_changed[DS1216E_REGISTER_YEARS]) { context->latch = rtc_set_latched_year(context->clock_regs[DS1216E_REGISTER_YEARS], context->latch, 1); } if (context->clock_regs_changed[DS1216E_REGISTER_MONTHS]) { context->latch = rtc_set_latched_month(context->clock_regs[DS1216E_REGISTER_MONTHS], context->latch, 1); } if (context->clock_regs_changed[DS1216E_REGISTER_MONTHDAYS]) { context->latch = rtc_set_latched_day_of_month(context->clock_regs[DS1216E_REGISTER_MONTHDAYS], context->latch, 1); } if (context->clock_regs_changed[DS1216E_REGISTER_WEEKDAYS]) { context->latch = rtc_set_latched_weekday(context->clock_regs[DS1216E_REGISTER_WEEKDAYS] % 7, context->latch); } if (context->clock_regs_changed[DS1216E_REGISTER_HOURS]) { if (new_12) { context->latch = rtc_set_latched_hour_am_pm(context->clock_regs[DS1216E_REGISTER_HOURS], context->latch, 1); } else { context->latch = rtc_set_latched_hour(context->clock_regs[DS1216E_REGISTER_HOURS], context->latch, 1); } } if (context->clock_regs_changed[DS1216E_REGISTER_MINUTES]) { context->latch = rtc_set_latched_minute(context->clock_regs[DS1216E_REGISTER_MINUTES], context->latch, 1); } if (context->clock_regs_changed[DS1216E_REGISTER_SECONDS]) { context->latch = rtc_set_latched_second(context->clock_regs[DS1216E_REGISTER_SECONDS], context->latch, 1); } if (!new_osc) { context->offset = context->offset - (rtc_get_latch(0) - (context->latch - context->offset)); context->inactive = 0; } } else { if (context->clock_regs_changed[DS1216E_REGISTER_YEARS]) { context->offset = rtc_set_year(context->clock_regs[DS1216E_REGISTER_YEARS], context->offset, 1); } if (context->clock_regs_changed[DS1216E_REGISTER_MONTHS]) { context->offset = rtc_set_month(context->clock_regs[DS1216E_REGISTER_MONTHS], context->offset, 1); } if (context->clock_regs_changed[DS1216E_REGISTER_MONTHDAYS]) { context->offset = rtc_set_day_of_month(context->clock_regs[DS1216E_REGISTER_MONTHDAYS], context->offset, 1); } if (context->clock_regs_changed[DS1216E_REGISTER_WEEKDAYS]) { context->offset = rtc_set_weekday(context->clock_regs[DS1216E_REGISTER_WEEKDAYS] % 7, context->offset); } if (context->clock_regs_changed[DS1216E_REGISTER_HOURS]) { if (new_12) { context->offset = rtc_set_hour_am_pm(context->clock_regs[DS1216E_REGISTER_HOURS], context->offset, 1); } else { context->offset = rtc_set_hour(context->clock_regs[DS1216E_REGISTER_HOURS], context->offset, 1); } } if (context->clock_regs_changed[DS1216E_REGISTER_MINUTES]) { context->offset = rtc_set_minute(context->clock_regs[DS1216E_REGISTER_MINUTES], context->offset, 1); } if (context->clock_regs_changed[DS1216E_REGISTER_SECONDS]) { context->offset = rtc_set_second(context->clock_regs[DS1216E_REGISTER_SECONDS], context->offset, 1); } if (new_osc) { context->latch = rtc_get_latch(context->offset); context->inactive = new_osc; } } context->reset = new_reset; context->hours12 = new_12; }
void rtc72421_write(rtc_72421_t *context, BYTE address, BYTE data) { time_t latch = (context->stop) ? context->latch : rtc_get_latch(context->offset); BYTE real_data = data & 0xf; BYTE new_data; switch (address & 0xf) { case RTC72421_REGISTER_SECONDS: new_data = rtc_get_second(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_second(new_data, latch, 0); } else { context->offset = rtc_set_second(new_data, context->offset, 0); } break; case RTC72421_REGISTER_10SECONDS: new_data = rtc_get_second(latch, 0); new_data %= 10; new_data += ((real_data & 7) * 10); if (context->stop) { context->latch = rtc_set_latched_second(new_data, latch, 0); } else { context->offset = rtc_set_second(new_data, context->offset, 0); } break; case RTC72421_REGISTER_MINUTES: new_data = rtc_get_minute(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_minute(new_data, latch, 0); } else { context->offset = rtc_set_minute(new_data, context->offset, 0); } break; case RTC72421_REGISTER_10MINUTES: new_data = rtc_get_minute(latch, 0); new_data %= 10; new_data += ((real_data & 7) * 10); if (context->stop) { context->latch = rtc_set_latched_minute(new_data, latch, 0); } else { context->offset = rtc_set_minute(new_data, context->offset, 0); } break; case RTC72421_REGISTER_HOURS: if (context->hour24) { new_data = rtc_get_hour(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_hour(new_data, latch, 0); } else { context->offset = rtc_set_hour(new_data, context->offset, 0); } } else { new_data = rtc_get_hour_am_pm(latch, 0); if (new_data >= 32) { new_data -= 32; new_data /= 10; new_data *= 10; new_data += (LIMIT_9(real_data) + 32); } else { new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); } if (context->stop) { context->latch = rtc_set_latched_hour_am_pm(new_data, latch, 0); } else { context->offset = rtc_set_hour_am_pm(new_data, context->offset, 0); } } break; case RTC72421_REGISTER_10HOURS: if (real_data & 8) { new_data = rtc_get_hour(latch, 0); new_data %= 10; new_data += ((real_data & 3) * 10); context->hour24 = 1; if (context->stop) { context->latch = rtc_set_latched_hour(new_data, latch, 0); } else { context->offset = rtc_set_hour(new_data, context->offset, 0); } } else { real_data &= 7; new_data = rtc_get_hour_am_pm(latch, 0); if (new_data >= 32) { new_data -= 32; } new_data %= 10; new_data += ((real_data & 3) * 10); if (real_data & 4) { new_data += 32; } context->hour24 = 0; if (context->stop) { context->latch = rtc_set_latched_hour_am_pm(new_data, latch, 0); } else { context->offset = rtc_set_hour_am_pm(new_data, context->offset, 0); } } break; case RTC72421_REGISTER_WEEKDAYS: if (context->stop) { context->latch = rtc_set_latched_weekday(((real_data + 1) & 7), latch); } else { context->offset = rtc_set_weekday(((real_data + 1) & 7), context->offset); } break; case RTC72421_REGISTER_MONTHDAYS: new_data = rtc_get_day_of_month(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_day_of_month(new_data, latch, 0); } else { context->offset = rtc_set_day_of_month(new_data, context->offset, 0); } break; case RTC72421_REGISTER_10MONTHDAYS: new_data = rtc_get_day_of_month(latch, 0); new_data %= 10; new_data += ((real_data & 3) * 10); if (context->stop) { context->latch = rtc_set_latched_day_of_month(new_data, latch, 0); } else { context->offset = rtc_set_day_of_month(new_data, context->offset, 0); } break; case RTC72421_REGISTER_MONTHS: new_data = rtc_get_month(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_month(new_data, latch, 0); } else { context->offset = rtc_set_month(new_data, context->offset, 0); } break; case RTC72421_REGISTER_10MONTHS: new_data = rtc_get_month(latch, 0); new_data %= 10; new_data += ((real_data & 1) * 10); if (context->stop) { context->latch = rtc_set_latched_month(new_data, latch, 0); } else { context->offset = rtc_set_month(new_data, context->offset, 0); } break; case RTC72421_REGISTER_YEARS: new_data = rtc_get_year(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_year(new_data, latch, 0); } else { context->offset = rtc_set_year(new_data, context->offset, 0); } break; case RTC72421_REGISTER_10YEARS: new_data = rtc_get_year(latch, 0); new_data %= 10; new_data += (LIMIT_9(real_data) * 10); if (context->stop) { context->latch = rtc_set_latched_year(new_data, latch, 0); } else { context->offset = rtc_set_year(new_data, context->offset, 0); } break; case RTC72421_REGISTER_CTRL2: context->hour24 = (real_data & 4) ? 1: 0; if (real_data & 2) { context->stop = 1; context->latch = rtc_get_latch(context->offset); } else { context->stop = 0; context->offset = context->offset - (rtc_get_latch(0) - (context->latch - context->offset)); } break; } }
void rtc58321a_write_data(rtc_58321a_t *context, BYTE data) { time_t latch = (context->stop) ? context->latch : rtc_get_latch(context->offset[0]); BYTE real_data = data & 0xf; BYTE new_data; switch (context->address) { case RTC58321A_REGISTER_SECONDS: new_data = rtc_get_second(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_second(new_data, latch, 0); } else { context->offset[0] = rtc_set_second(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_10SECONDS: new_data = rtc_get_second(latch, 0); new_data %= 10; new_data += ((real_data & 7) * 10); if (context->stop) { context->latch = rtc_set_latched_second(new_data, latch, 0); } else { context->offset[0] = rtc_set_second(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_MINUTES: new_data = rtc_get_minute(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_minute(new_data, latch, 0); } else { context->offset[0] = rtc_set_minute(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_10MINUTES: new_data = rtc_get_minute(latch, 0); new_data %= 10; new_data += ((real_data & 7) * 10); if (context->stop) { context->latch = rtc_set_latched_minute(new_data, latch, 0); } else { context->offset[0] = rtc_set_minute(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_HOURS: if (context->hour24) { new_data = rtc_get_hour(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_hour(new_data, latch, 0); } else { context->offset[0] = rtc_set_hour(new_data, context->offset[0], 0); } } else { new_data = rtc_get_hour_am_pm(latch, 0); if (new_data >= 32) { new_data -= 32; new_data /= 10; new_data *= 10; new_data += (LIMIT_9(real_data) + 32); } else { new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); } if (context->stop) { context->latch = rtc_set_latched_hour_am_pm(new_data, latch, 0); } else { context->offset[0] = rtc_set_hour_am_pm(new_data, context->offset[0], 0); } } break; case RTC58321A_REGISTER_10HOURS: if (real_data & 8) { new_data = rtc_get_hour(latch, 0); new_data %= 10; new_data += ((real_data & 3) * 10); context->hour24 = 1; if (context->stop) { context->latch = rtc_set_latched_hour(new_data, latch, 0); } else { context->offset[0] = rtc_set_hour(new_data, context->offset[0], 0); } } else { real_data &= 7; new_data = rtc_get_hour_am_pm(latch, 0); if (new_data >= 32) { new_data -= 32; } new_data %= 10; new_data += ((real_data & 3) * 10); if (real_data & 4) { new_data += 32; } context->hour24 = 0; if (context->stop) { context->latch = rtc_set_latched_hour_am_pm(new_data, latch, 0); } else { context->offset[0] = rtc_set_hour_am_pm(new_data, context->offset[0], 0); } } break; case RTC58321A_REGISTER_WEEKDAYS: if (context->stop) { context->latch = rtc_set_latched_weekday((real_data & 7), latch); } else { context->offset[0] = rtc_set_weekday((real_data & 7), context->offset[0]); } break; case RTC58321A_REGISTER_MONTHDAYS: new_data = rtc_get_day_of_month(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_day_of_month(new_data, latch, 0); } else { context->offset[0] = rtc_set_day_of_month(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_10MONTHDAYS: new_data = rtc_get_day_of_month(latch, 0); new_data %= 10; new_data += ((real_data & 3) * 10); if (context->stop) { context->latch = rtc_set_latched_day_of_month(new_data, latch, 0); } else { context->offset[0] = rtc_set_day_of_month(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_MONTHS: new_data = rtc_get_month(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_month(new_data, latch, 0); } else { context->offset[0] = rtc_set_month(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_10MONTHS: new_data = rtc_get_month(latch, 0); new_data %= 10; new_data += ((real_data & 1) * 10); if (context->stop) { context->latch = rtc_set_latched_month(new_data, latch, 0); } else { context->offset[0] = rtc_set_month(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_YEARS: new_data = rtc_get_year(latch, 0); new_data /= 10; new_data *= 10; new_data += LIMIT_9(real_data); if (context->stop) { context->latch = rtc_set_latched_year(new_data, latch, 0); } else { context->offset[0] = rtc_set_year(new_data, context->offset[0], 0); } break; case RTC58321A_REGISTER_10YEARS: new_data = rtc_get_year(latch, 0); new_data %= 10; new_data += (LIMIT_9(real_data) * 10); if (context->stop) { context->latch = rtc_set_latched_year(new_data, latch, 0); } else { context->offset[0] = rtc_set_year(new_data, context->offset[0], 0); } break; } }