static void ds1216e_latch_regs(rtc_ds1216e_t *context) { time_t latch = (context->inactive) ? context->latch : rtc_get_latch(context->offset); context->clock_regs[DS1216E_REGISTER_CENTISECONDS] = rtc_get_centisecond(1); context->clock_regs[DS1216E_REGISTER_SECONDS] = rtc_get_second(latch, 1); context->clock_regs[DS1216E_REGISTER_MINUTES] = rtc_get_minute(latch, 1); context->clock_regs[DS1216E_REGISTER_HOURS] = (context->hours12) ? 0x80 : 0; if (context->hours12) { context->clock_regs[DS1216E_REGISTER_HOURS] |= rtc_get_hour_am_pm(latch, 1); } else { context->clock_regs[DS1216E_REGISTER_HOURS] |= rtc_get_hour(latch, 1); } context->clock_regs[DS1216E_REGISTER_WEEKDAYS] = (context->inactive) ? 0x20 : 0; context->clock_regs[DS1216E_REGISTER_WEEKDAYS] |= (context->reset) ? 0x10 : 0; context->clock_regs[DS1216E_REGISTER_WEEKDAYS] |= ((rtc_get_weekday(latch) - 1) % 7) + 1; context->clock_regs[DS1216E_REGISTER_MONTHDAYS] = rtc_get_day_of_month(latch, 1); context->clock_regs[DS1216E_REGISTER_MONTHS] = rtc_get_month(latch, 1); context->clock_regs[DS1216E_REGISTER_YEARS] = rtc_get_year(latch, 1); }
static void pcf8583_i2c_start(rtc_pcf8583_t *context) { BYTE tmp; time_t latch = (context->clock_halt) ? context->clock_halt_latch : rtc_get_latch(context->offset); int i; context->clock_regs_for_read[PCF8583_REG_CONTROL] = context->clock_regs[PCF8583_REG_CONTROL]; context->clock_regs_for_read[PCF8583_REG_100TH_SECONDS] = rtc_get_centisecond(1); context->clock_regs_for_read[PCF8583_REG_SECONDS] = rtc_get_second(latch, 1); context->clock_regs_for_read[PCF8583_REG_MINUTES] = rtc_get_minute(latch, 1); tmp = context->am_pm << 7; if (context->am_pm) { tmp |= rtc_get_hour_am_pm(latch, 1); if (tmp & 0x20) { tmp &= 0xdf; tmp |= 0x40; } } else { tmp |= rtc_get_hour(latch, 1); } context->clock_regs_for_read[PCF8583_REG_HOURS] = tmp; tmp = rtc_get_year(latch, 1); tmp &= 3; tmp <<= 6; tmp |= rtc_get_day_of_month(latch, 1); context->clock_regs_for_read[PCF8583_REG_YEARS_MONTH_DAYS] = tmp; tmp = rtc_get_weekday(latch) + 1; tmp &= 7; tmp <<= 5; tmp |= rtc_get_month(latch, 1); context->clock_regs_for_read[PCF8583_REG_WEEK_DAYS_MONTHS] = tmp; context->clock_regs_for_read[PCF8583_REG_TIMER_DAYS] = 0; for (i = PCF8583_REG_ALARM_CONTROL; i <= PCF8583_REG_TIMER_ALARM; ++i) { context->clock_regs_for_read[i] = context->clock_regs[i]; } if (context->read_bit_shift) { make_read_register_train(context); } }
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; } }
BYTE rtc72421_read(rtc_72421_t *context, BYTE address) { BYTE retval = 0; time_t latch = (context->stop) ? context->latch : rtc_get_latch(context->offset); switch (address & 0xf) { case RTC72421_REGISTER_SECONDS: retval = rtc_get_second(latch, 0); retval %= 10; break; case RTC72421_REGISTER_10SECONDS: retval = rtc_get_second(latch, 0); retval /= 10; break; case RTC72421_REGISTER_MINUTES: retval = rtc_get_minute(latch, 0); retval %= 10; break; case RTC72421_REGISTER_10MINUTES: retval = rtc_get_minute(latch, 0); retval /= 10; break; case RTC72421_REGISTER_HOURS: if (context->hour24) { retval = rtc_get_hour(latch, 0); } else { retval = rtc_get_hour_am_pm(latch, 0); retval &= 0x1f; } retval %= 10; break; case RTC72421_REGISTER_10HOURS: if (context->hour24) { retval = rtc_get_hour(latch, 0); retval /= 10; retval |= 8; } else { retval = rtc_get_hour_am_pm(latch, 0); if (retval > 23) { retval = (retval - 32) / 10; retval |= 4; } else { retval /= 10; } } break; case RTC72421_REGISTER_WEEKDAYS: retval = rtc_get_weekday(latch) - 1; if (retval > 6) { retval = 6; } break; case RTC72421_REGISTER_MONTHDAYS: retval = rtc_get_day_of_month(latch, 0); retval %= 10; break; case RTC72421_REGISTER_10MONTHDAYS: retval = rtc_get_day_of_month(latch, 0); retval /= 10; break; case RTC72421_REGISTER_MONTHS: retval = rtc_get_month(latch, 0); retval %= 10; break; case RTC72421_REGISTER_10MONTHS: retval = rtc_get_month(latch, 0); retval /= 10; break; case RTC72421_REGISTER_YEARS: retval = rtc_get_year(latch, 0); retval %= 10; break; case RTC72421_REGISTER_10YEARS: retval = rtc_get_year(latch, 0); retval /= 10; break; case RTC72421_REGISTER_CTRL2: retval = context->hour24 ? 2 : 0; retval |= context->stop ? 1 : 0; break; } return retval; }
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; } }
BYTE rtc58321a_read(rtc_58321a_t *context) { BYTE retval = 0; time_t latch = (context->stop) ? context->latch : rtc_get_latch(context->offset[0]); switch (context->address) { case RTC58321A_REGISTER_SECONDS: retval = rtc_get_second(latch, 0); retval %= 10; break; case RTC58321A_REGISTER_10SECONDS: retval = rtc_get_second(latch, 0); retval /= 10; break; case RTC58321A_REGISTER_MINUTES: retval = rtc_get_minute(latch, 0); retval %= 10; break; case RTC58321A_REGISTER_10MINUTES: retval = rtc_get_minute(latch, 0); retval /= 10; break; case RTC58321A_REGISTER_HOURS: if (context->hour24) { retval = rtc_get_hour(latch, 0); } else { retval = rtc_get_hour_am_pm(latch, 0); retval &= 0x1f; } retval %= 10; break; case RTC58321A_REGISTER_10HOURS: if (context->hour24) { retval = rtc_get_hour(latch, 0); retval /= 10; retval |= 0x80; } else { retval = rtc_get_hour_am_pm(latch, 0); if (retval > 23) { retval = (retval - 32) / 10; retval |= 4; } else { retval /= 10; } } break; case RTC58321A_REGISTER_WEEKDAYS: retval = rtc_get_weekday(latch); break; case RTC58321A_REGISTER_MONTHDAYS: retval = rtc_get_day_of_month(latch, 0); retval %= 10; break; case RTC58321A_REGISTER_10MONTHDAYS: retval = rtc_get_day_of_month(latch, 0); retval /= 10; /* TODO: leapyear calculation */ break; case RTC58321A_REGISTER_MONTHS: retval = rtc_get_month(latch, 0); retval %= 10; break; case RTC58321A_REGISTER_10MONTHS: retval = rtc_get_month(latch, 0); retval /= 10; break; case RTC58321A_REGISTER_YEARS: retval = rtc_get_year(latch, 0); retval %= 10; break; case RTC58321A_REGISTER_10YEARS: retval = rtc_get_year(latch, 0); retval /= 10; break; } return retval; }
void rtc_print_time() { kprintf("20%x, %x. %x. %x:%x:%x\n", rtc_get_year(), rtc_get_month(), rtc_get_day(), rtc_get_hour(), rtc_get_minute(), rtc_get_second()); }