RX-8025NB Real Time Clock Module by EPSON
Dependents: TYBLE16_simple_data_logger Check_external_RTC
RX8025NB.cpp
00001 /* 00002 * mbed library program 00003 * Control RX-8025NB Real Time Clock Module 00004 * EPSON 00005 * 00006 * Copyright (c) 2015,'16,'17,'19,'20 Kenji Arai / JH1PJL 00007 * http://www7b.biglobe.ne.jp/~kenjia/ 00008 * https://os.mbed.com/users/kenjiArai/ 00009 * Created: June 3rd, 2015 00010 * Revised: August 7th, 2020 00011 */ 00012 00013 #include "mbed.h" 00014 #include "RX8025NB.h" 00015 00016 #define RTC_Wk_Sunday ((uint8_t)0x00) 00017 00018 RX8025::RX8025 (PinName p_sda, PinName p_scl) : 00019 _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) 00020 { 00021 RX8025_addr = RX8025ADDR; 00022 init(); 00023 } 00024 00025 RX8025::RX8025 (I2C& p_i2c) : _i2c(p_i2c) 00026 { 00027 RX8025_addr = RX8025ADDR; 00028 init(); 00029 } 00030 00031 /////////////// Initialize ///////////////////////////////////////////////////// 00032 void RX8025::init() 00033 { 00034 tm t; 00035 int8_t dt; 00036 00037 _i2c.frequency(400000); 00038 dt = read_reg_byte(RX8025_REG_CONTL2); 00039 if (dt & 0x10) { // Power on reset 00040 dt = write_reg_byte(RX8025_REG_CONTL2, 0); // all clear 00041 // Set 24H 00042 dt = read_reg_byte(RX8025_REG_CONTL1); 00043 dt |= 0x20; 00044 dt = write_reg_byte(RX8025_REG_CONTL1, dt); 00045 // set January 1st,2019 1am as a default 00046 t.tm_sec = 0; 00047 t.tm_min = 0; 00048 t.tm_hour = 1; 00049 t.tm_mday = 1; 00050 t.tm_wday = 0; 00051 t.tm_mon = 0; 00052 t.tm_year = 119; 00053 write_rtc_std(&t); 00054 } else { 00055 // Set 24H 00056 dt = read_reg_byte(RX8025_REG_CONTL1); 00057 if (dt & 0x20) { // set already 00058 ; 00059 } else { 00060 dt |= 0x20; 00061 dt = write_reg_byte(RX8025_REG_CONTL1, dt); 00062 } 00063 } 00064 } 00065 00066 /////////////// Read RTC data ////////////////////////////////////////////////// 00067 void RX8025::get_time_rtc (tm *t) 00068 { 00069 read_rtc_std(t); 00070 } 00071 00072 void RX8025::read_rtc_std (tm *t) 00073 { 00074 rtc_time time; 00075 00076 read_rtc_direct(&time); 00077 t->tm_sec = time.rtc_seconds; 00078 t->tm_min = time.rtc_minutes; 00079 t->tm_hour = time.rtc_hours; 00080 t->tm_mday = time.rtc_date; 00081 if (time.rtc_weekday == RTC_Wk_Sunday) { 00082 t->tm_wday = 0; // Sun is not 7 but 0 00083 } else { 00084 t->tm_wday = time.rtc_weekday; 00085 } 00086 t->tm_mon = time.rtc_month - 1; 00087 t->tm_year = time.rtc_year_raw + 100; 00088 t->tm_isdst= 0; 00089 } 00090 00091 /////////////// Write data to RTC ////////////////////////////////////////////// 00092 void RX8025::set_time_rtc (tm *t) 00093 { 00094 write_rtc_std(t); 00095 } 00096 00097 void RX8025::write_rtc_std (tm *t) 00098 { 00099 rtc_time time; 00100 00101 time.rtc_seconds = t->tm_sec; 00102 time.rtc_minutes = t->tm_min; 00103 time.rtc_hours = t->tm_hour; 00104 time.rtc_date = t->tm_mday; 00105 if ( t->tm_wday == 0) { 00106 time.rtc_weekday = RTC_Wk_Sunday; 00107 } else { 00108 time.rtc_weekday = t->tm_wday; 00109 } 00110 time.rtc_month = t->tm_mon + 1; 00111 time.rtc_year_raw = t->tm_year - 100; 00112 write_rtc_direct(&time); 00113 } 00114 00115 /////////////// Set Alarm-D / INTA ///////////////////////////////////////////// 00116 void RX8025::set_alarmD_reg (uint16_t time) 00117 { 00118 tm t; 00119 int8_t dt; 00120 uint8_t m, h; 00121 00122 dt = read_reg_byte(RX8025_REG_CONTL1); 00123 dt &= ~0x40; // DALE = 0 00124 dt = write_reg_byte(RX8025_REG_CONTL1, dt); 00125 read_rtc_std(&t); // read current time 00126 m = t.tm_min + (uint8_t)(time % 60); 00127 h = t.tm_hour; 00128 if (m >= 60) { 00129 m -= 60; 00130 h += 1; 00131 } 00132 h += (uint8_t)(time / 60); 00133 if (h >= 24) { 00134 h -= 24; 00135 } 00136 rtc_buf[2] = bin2bcd(h); 00137 rtc_buf[1] = bin2bcd(m); 00138 rtc_buf[0] = RX8025_REG_ALARMD_MIN << 4; 00139 _i2c.write((int)RX8025_addr, (char *)rtc_buf, 3, false); 00140 dt = read_reg_byte(RX8025_REG_CONTL1); 00141 dt |= 0x60; // DALE = 1 00142 dt = write_reg_byte(RX8025_REG_CONTL1, dt); 00143 } 00144 00145 void RX8025::set_next_IRQ (uint16_t time) 00146 { 00147 set_next_alarmD_INTA(time); 00148 } 00149 00150 void RX8025::set_next_alarmD_INTA (uint16_t time) 00151 { 00152 uint16_t t; 00153 00154 if (time < 2) { 00155 // Alarm does not check seconds digit. 00156 // If 59 to 0 is occured during setting here, 00157 // 1 minute will have a trouble. 00158 t = 2; 00159 } else if (time > 1440) { // set less than 24 hours 00160 t = 1440; 00161 } else { 00162 t = time; 00163 } 00164 set_alarmD_reg(t); 00165 } 00166 00167 /////////////// Clear Alarm-D / INTA interrupt ///////////////////////////////// 00168 void RX8025::clear_IRQ() 00169 { 00170 clear_alarmD_INTA(); 00171 } 00172 00173 void RX8025::clear_alarmD_INTA () 00174 { 00175 int8_t dt, reg; 00176 00177 for (uint32_t i = 0; i < 40; i++) { 00178 reg = read_reg_byte(RX8025_REG_CONTL2); 00179 if ((reg & 0x01) == 0) { 00180 break; 00181 } 00182 dt = reg & 0xfe; 00183 write_reg_byte(RX8025_REG_CONTL1, dt); 00184 } 00185 } 00186 00187 /////////////// Read/Write specific register /////////////////////////////////// 00188 uint8_t RX8025::read_reg_byte(uint8_t reg) 00189 { 00190 rtc_buf[0] = reg << 4; 00191 _i2c.write((int)RX8025_addr, (char *)rtc_buf, 1, true); 00192 _i2c.read((int)RX8025_addr, (char *)rtc_buf, 1, false); 00193 return rtc_buf[0]; 00194 } 00195 00196 uint8_t RX8025::write_reg_byte(uint8_t reg, uint8_t data) 00197 { 00198 rtc_buf[0] = reg << 4; 00199 rtc_buf[1] = data; 00200 _i2c.write((int)RX8025_addr, (char *)rtc_buf, 2, false); 00201 return read_reg_byte(reg); 00202 } 00203 00204 /////////////// I2C Freq. ////////////////////////////////////////////////////// 00205 void RX8025::frequency(int hz) 00206 { 00207 _i2c.frequency(hz); 00208 } 00209 00210 /////////////// Read/Write RTC another format ////////////////////////////////// 00211 void RX8025::read_rtc_direct (rtc_time *tm) 00212 { 00213 rtc_buf[0] = RX8025_REG_SEC << 4; 00214 _i2c.write((int)RX8025_addr, (char *)rtc_buf, 1, true); 00215 _i2c.read((int)RX8025_addr, (char *)rtc_buf, 10, false); 00216 tm->rtc_seconds = bcd2bin(rtc_buf[RX8025_REG_SEC] & 0x7f); 00217 tm->rtc_minutes = bcd2bin(rtc_buf[RX8025_REG_MIN] & 0x7f); 00218 tm->rtc_hours = bcd2bin(rtc_buf[RX8025_REG_HOUR] & 0x3f); 00219 tm->rtc_date = bcd2bin(rtc_buf[RX8025_REG_DAY] & 0x3f); 00220 tm->rtc_weekday = rtc_buf[RX8025_REG_WDAY] & 0x07; 00221 tm->rtc_month = bcd2bin(rtc_buf[RX8025_REG_MON] & 0x1f); 00222 tm->rtc_year_raw= bcd2bin(rtc_buf[RX8025_REG_YEAR]); 00223 tm->rtc_year = tm->rtc_year_raw + 100 + 1900; 00224 } 00225 00226 void RX8025::write_rtc_direct (rtc_time *tm) 00227 { 00228 rtc_buf[RX8025_REG_YEAR + 1] = bin2bcd(tm->rtc_year_raw); 00229 rtc_buf[RX8025_REG_MON + 1] = bin2bcd(tm->rtc_month); 00230 rtc_buf[RX8025_REG_WDAY + 1] = (tm->rtc_weekday & 0x07); 00231 rtc_buf[RX8025_REG_DAY + 1] = bin2bcd(tm->rtc_date); 00232 rtc_buf[RX8025_REG_HOUR + 1] = bin2bcd(tm->rtc_hours); 00233 rtc_buf[RX8025_REG_MIN + 1] = bin2bcd(tm->rtc_minutes); 00234 rtc_buf[RX8025_REG_SEC + 1] = bin2bcd(tm->rtc_seconds); 00235 rtc_buf[0] = RX8025_REG_SEC << 4; 00236 _i2c.write((int)RX8025_addr, (char *)rtc_buf, 8, false); 00237 } 00238 00239 /////////////// Square wave output ///////////////////////////////////////////// 00240 void RX8025::set_sq_wave (sq_wave_t sqw_dt) 00241 { 00242 rtc_buf[0] = RX8025_REG_CONTL1 << 4; 00243 _i2c.write((int)RX8025_addr, (char *)rtc_buf, 1, true); 00244 _i2c.read((int)RX8025_addr, (char *)rtc_buf, 2, false); 00245 if (sqw_dt == RTC_SQW_NONE) { // FOUT is disable 00246 rtc_buf[2] = rtc_buf[1] | 0x08; // CLEN1 = 1 00247 rtc_buf[1] = rtc_buf[0] | 0x10; // CLEN2 = 1 00248 rtc_buf[0] = RX8025_REG_CONTL1 << 4; 00249 _i2c.write((int)RX8025_addr, (char *)rtc_buf, 3, false); 00250 } else { // FOUT is enable 00251 rtc_buf[2] = rtc_buf[1] & 0xf7; // CLEN1 = 0 00252 rtc_buf[1] = rtc_buf[0] & 0xef; // CLEN2 = 0 00253 rtc_buf[0] = RX8025_REG_CONTL1 << 4; 00254 _i2c.write((int)RX8025_addr, (char *)rtc_buf, 3, false); 00255 } 00256 } 00257 00258 /////////////// conversion BCD & BIN /////////////////////////////////////////// 00259 uint8_t RX8025::bin2bcd (uint8_t dt) 00260 { 00261 uint8_t bcdhigh = 0; 00262 00263 while (dt >= 10) { 00264 bcdhigh++; 00265 dt -= 10; 00266 } 00267 return ((uint8_t)(bcdhigh << 4) | dt); 00268 } 00269 00270 uint8_t RX8025::bcd2bin (uint8_t dt) 00271 { 00272 uint8_t tmp = 0; 00273 00274 tmp = ((uint8_t)(dt & (uint8_t)0xf0) >> (uint8_t)0x4) * 10; 00275 return (tmp + (dt & (uint8_t)0x0f)); 00276 }
Generated on Fri Jul 15 2022 07:35:33 by 1.7.2