25 return (b >> 4) * 10 + (b & 0x0F);
29 return (uint8_t)(((v / 10) << 4) | (v % 10));
33long days_from_civil(
int y,
int m,
int d)
36 long era = (y >= 0 ? y : y - 399) / 400;
39 unsigned yoe = (unsigned)(y - era * 400);
40 unsigned doy = (153u * (unsigned)(m + (m > 2 ? -3 : 9)) + 2u) / 5u + (unsigned)d - 1u;
41 unsigned doe = yoe * 365u + yoe / 4u - yoe / 100u + doy;
42 return era * 146097L + (long)doe - 719468L;
44void civil_from_days(
long z,
int *y,
int *m,
int *d)
47 long era = (z >= 0 ? z : z - 146096) / 146097;
50 unsigned doe = (unsigned)(z - era * 146097);
51 unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
52 long yy = (long)yoe + era * 400;
53 unsigned doy = doe - (365u * yoe + yoe / 4u - yoe / 100u);
54 unsigned mp = (5u * doy + 2u) / 153u;
55 *d = (int)(doy - (153u * mp + 2u) / 5u + 1u);
56 *m = (int)(mp < 10 ? mp + 3 : mp - 9);
57 *y = (int)(yy + (*m <= 2));
67 int sec = bcd2int(r[0] & 0x7F);
68 int min = bcd2int(r[1] & 0x7F);
72 int h12 = bcd2int(r[2] & 0x1F);
73 if (h12 < 1 || h12 > 12)
77 bool pm = (r[2] & 0x20) != 0;
78 hour = (h12 % 12) + (pm ? 12 : 0);
82 hour = bcd2int(r[2] & 0x3F);
84 int date = bcd2int(r[4] & 0x3F);
85 int month = bcd2int(r[5] & 0x1F);
86 int year = 2000 + bcd2int(r[6]);
87 if (sec > 59 || min > 59 || hour > 23 || date < 1 || date > 31 || month < 1 || month > 12)
92 int64_t t = (int64_t)days_from_civil(year, month, date) * 86400 + hour * 3600 + min * 60 + sec;
93 if (t < 0 || t > 0xFFFFFFFFLL)
105 long days = (long)(epoch / 86400u);
106 int rem = (int)(epoch % 86400u);
110 civil_from_days(days, &y, &m, &d);
111 r[0] = int2bcd(rem % 60);
112 r[1] = int2bcd((rem % 3600) / 60);
113 r[2] = int2bcd(rem / 3600);
114 r[3] = (uint8_t)((((days % 7) + 3) % 7) + 1);
117 r[6] = int2bcd(y - 2000);
135 Wire.write((uint8_t)0x00);
136 if (Wire.endTransmission() != 0)
147 r[i] = (uint8_t)Wire.read();
158 Wire.write((uint8_t)0x00);
163 return Wire.endTransmission() == 0;
The one owner of the shared I2C bus bring-up for the peripheral drivers.
void pc_i2c_begin()
Bring up the shared I2C bus on PC_I2C_SDA_PIN / PC_I2C_SCL_PIN (-1 = default).
User-facing configuration for ProtoCore.
#define PC_RTC_I2C_ADDR
I2C address of the RTC (DS1307/DS3231 are fixed at 0x68).
I2C real-time-clock driver (DS1307 / DS3231) - a battery-backed time source.
#define RTC_REG_COUNT
Number of time registers read from the RTC (seconds..year).
void pc_rtc_epoch_to_regs(uint32_t epoch, uint8_t regs[RTC_REG_COUNT])
Convert a Unix timestamp to the 7 RTC time registers (BCD, 24-hour). Pure - no I2C....
bool pc_rtc_begin()
Initialize the I2C bus for the RTC.
bool pc_rtc_regs_to_epoch(const uint8_t regs[RTC_REG_COUNT], uint32_t *epoch)
Convert the 7 raw RTC time registers (BCD: sec, min, hour, dow, date, month, year) to a Unix timestam...
uint32_t pc_rtc_read_epoch()
Read the current time from the RTC over I2C.
uint32_t pc_rtc_time_source()
A TimeSourceFn wrapper (returns pc_rtc_read_epoch()) to register with pc_time_source_add().
bool pc_rtc_set_epoch(uint32_t epoch)
Set the RTC to epoch over I2C.