RX-8025NB Real Time Clock Module by EPSON

Dependents:   TYBLE16_simple_data_logger Check_external_RTC

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RX8025NB.cpp Source File

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 }