示例#1
0
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;
}
示例#2
0
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;
    }
}
示例#3
0
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;
    }
}