RX-8025NB Real Time Clock Module by EPSON

Dependents:   TYBLE16_simple_data_logger Check_external_RTC

Committer:
kenjiArai
Date:
Tue Aug 22 10:16:48 2017 +0000
Revision:
5:e8e8b1b6c103
Parent:
4:d8ce59684dfa
Child:
6:414dbeb77add
countermeasure for  NonCopyable

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:cdf2921959b4 1 /*
kenjiArai 0:cdf2921959b4 2 * mbed library program
kenjiArai 0:cdf2921959b4 3 * Control RX-8025NB Real Time Clock Module
kenjiArai 0:cdf2921959b4 4 * EPSON
kenjiArai 0:cdf2921959b4 5 *
kenjiArai 5:e8e8b1b6c103 6 * Copyright (c) 2015,'16,'17 Kenji Arai / JH1PJL
kenjiArai 0:cdf2921959b4 7 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 0:cdf2921959b4 8 * http://mbed.org/users/kenjiArai/
kenjiArai 0:cdf2921959b4 9 * Created: June 3rd, 2015
kenjiArai 5:e8e8b1b6c103 10 * Revised: August 21st, 2017
kenjiArai 0:cdf2921959b4 11 */
kenjiArai 0:cdf2921959b4 12
kenjiArai 0:cdf2921959b4 13 #include "mbed.h"
kenjiArai 0:cdf2921959b4 14 #include "RX8025NB.h"
kenjiArai 0:cdf2921959b4 15
kenjiArai 5:e8e8b1b6c103 16 RX8025::RX8025 (PinName p_sda, PinName p_scl) :
kenjiArai 5:e8e8b1b6c103 17 _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p)
kenjiArai 5:e8e8b1b6c103 18 {
kenjiArai 0:cdf2921959b4 19 RX8025_addr = RX8025ADDR;
kenjiArai 1:817e81048235 20 init();
kenjiArai 0:cdf2921959b4 21 }
kenjiArai 0:cdf2921959b4 22
kenjiArai 3:d59c12d14ca9 23 RX8025::RX8025 (I2C& p_i2c) : _i2c(p_i2c){
kenjiArai 0:cdf2921959b4 24 RX8025_addr = RX8025ADDR;
kenjiArai 1:817e81048235 25 init();
kenjiArai 1:817e81048235 26 }
kenjiArai 1:817e81048235 27
kenjiArai 1:817e81048235 28 /////////////// Initialize ////////////////////////////////
kenjiArai 3:d59c12d14ca9 29 void RX8025::init(){
kenjiArai 2:ce49c4ba4c02 30 tm t;
kenjiArai 2:ce49c4ba4c02 31 char dt;
kenjiArai 1:817e81048235 32
kenjiArai 1:817e81048235 33 _i2c.frequency(400000);
kenjiArai 2:ce49c4ba4c02 34 dt = read_reg_byte(RX8025_REG_CONTL2);
kenjiArai 2:ce49c4ba4c02 35 if (dt & 0x10){ // Power on reset
kenjiArai 2:ce49c4ba4c02 36 dt = write_reg_byte(RX8025_REG_CONTL2, 0); // all clear
kenjiArai 2:ce49c4ba4c02 37 // Set 24H
kenjiArai 2:ce49c4ba4c02 38 dt = read_reg_byte(RX8025_REG_CONTL1);
kenjiArai 2:ce49c4ba4c02 39 dt |= 0x20;
kenjiArai 2:ce49c4ba4c02 40 dt = write_reg_byte(RX8025_REG_CONTL1, dt);
kenjiArai 2:ce49c4ba4c02 41 // set January 1st,2016 1am as a default
kenjiArai 2:ce49c4ba4c02 42 t.tm_sec = 0;
kenjiArai 2:ce49c4ba4c02 43 t.tm_min = 0;
kenjiArai 2:ce49c4ba4c02 44 t.tm_hour = 1;
kenjiArai 2:ce49c4ba4c02 45 t.tm_mday = 1;
kenjiArai 2:ce49c4ba4c02 46 t.tm_wday = 0;
kenjiArai 2:ce49c4ba4c02 47 t.tm_mon = 0;
kenjiArai 2:ce49c4ba4c02 48 t.tm_year = 116;
kenjiArai 2:ce49c4ba4c02 49 write_rtc_std(&t);
kenjiArai 2:ce49c4ba4c02 50 } else {
kenjiArai 2:ce49c4ba4c02 51 // Set 24H
kenjiArai 2:ce49c4ba4c02 52 dt = read_reg_byte(RX8025_REG_CONTL1);
kenjiArai 2:ce49c4ba4c02 53 dt |= 0x20;
kenjiArai 2:ce49c4ba4c02 54 dt = write_reg_byte(RX8025_REG_CONTL1, dt);
kenjiArai 2:ce49c4ba4c02 55 }
kenjiArai 0:cdf2921959b4 56 }
kenjiArai 0:cdf2921959b4 57
kenjiArai 0:cdf2921959b4 58 /////////////// Read RTC data /////////////////////////////
kenjiArai 3:d59c12d14ca9 59 void RX8025::get_time_rtc (tm *t){
kenjiArai 0:cdf2921959b4 60 read_rtc_std(t);
kenjiArai 0:cdf2921959b4 61 }
kenjiArai 0:cdf2921959b4 62
kenjiArai 3:d59c12d14ca9 63 void RX8025::read_rtc_std (tm *t){
kenjiArai 0:cdf2921959b4 64 rtc_time time;
kenjiArai 0:cdf2921959b4 65
kenjiArai 0:cdf2921959b4 66 read_rtc_direct(&time);
kenjiArai 0:cdf2921959b4 67 t->tm_sec = time.rtc_seconds;
kenjiArai 0:cdf2921959b4 68 t->tm_min = time.rtc_minutes;
kenjiArai 0:cdf2921959b4 69 t->tm_hour = time.rtc_hours;
kenjiArai 0:cdf2921959b4 70 t->tm_mday = time.rtc_date;
kenjiArai 0:cdf2921959b4 71 if ( time.rtc_weekday == RTC_Wk_Sunday) {
kenjiArai 0:cdf2921959b4 72 t->tm_wday = 0; // Sun is not 7 but 0
kenjiArai 0:cdf2921959b4 73 } else {
kenjiArai 0:cdf2921959b4 74 t->tm_wday = time.rtc_weekday;
kenjiArai 0:cdf2921959b4 75 }
kenjiArai 0:cdf2921959b4 76 t->tm_mon = time.rtc_month - 1;
kenjiArai 0:cdf2921959b4 77 t->tm_year = time.rtc_year_raw + 100;
kenjiArai 0:cdf2921959b4 78 t->tm_isdst= 0;
kenjiArai 0:cdf2921959b4 79 }
kenjiArai 0:cdf2921959b4 80
kenjiArai 0:cdf2921959b4 81 /////////////// Write data to RTC /////////////////////////
kenjiArai 3:d59c12d14ca9 82 void RX8025::set_time_rtc (tm *t){
kenjiArai 0:cdf2921959b4 83 write_rtc_std(t);
kenjiArai 0:cdf2921959b4 84 }
kenjiArai 0:cdf2921959b4 85
kenjiArai 3:d59c12d14ca9 86 void RX8025::write_rtc_std (tm *t){
kenjiArai 0:cdf2921959b4 87 rtc_time time;
kenjiArai 0:cdf2921959b4 88
kenjiArai 0:cdf2921959b4 89 time.rtc_seconds = t->tm_sec;
kenjiArai 0:cdf2921959b4 90 time.rtc_minutes = t->tm_min;
kenjiArai 0:cdf2921959b4 91 time.rtc_hours = t->tm_hour;
kenjiArai 0:cdf2921959b4 92 time.rtc_date = t->tm_mday;
kenjiArai 0:cdf2921959b4 93 if ( t->tm_wday == 0) {
kenjiArai 0:cdf2921959b4 94 time.rtc_weekday = RTC_Wk_Sunday;
kenjiArai 0:cdf2921959b4 95 } else {
kenjiArai 0:cdf2921959b4 96 time.rtc_weekday = t->tm_wday;
kenjiArai 0:cdf2921959b4 97 }
kenjiArai 0:cdf2921959b4 98 time.rtc_month = t->tm_mon + 1;
kenjiArai 0:cdf2921959b4 99 time.rtc_year_raw = t->tm_year - 100;
kenjiArai 0:cdf2921959b4 100 write_rtc_direct(&time);
kenjiArai 0:cdf2921959b4 101 }
kenjiArai 0:cdf2921959b4 102
kenjiArai 2:ce49c4ba4c02 103 /////////////// Set Alarm-D / INTA ////////////////////////
kenjiArai 4:d8ce59684dfa 104 uint8_t RX8025::set_alarmD_reg (uint16_t time){
kenjiArai 2:ce49c4ba4c02 105 tm t;
kenjiArai 2:ce49c4ba4c02 106 char dt;
kenjiArai 3:d59c12d14ca9 107 uint8_t m, h;
kenjiArai 4:d8ce59684dfa 108 uint16_t set, real;
kenjiArai 2:ce49c4ba4c02 109
kenjiArai 2:ce49c4ba4c02 110 dt = read_reg_byte(RX8025_REG_CONTL1);
kenjiArai 3:d59c12d14ca9 111 dt &= ~0x40; // DALE = 0
kenjiArai 2:ce49c4ba4c02 112 dt = write_reg_byte(RX8025_REG_CONTL1, dt);
kenjiArai 2:ce49c4ba4c02 113 read_rtc_std(&t); // read current time
kenjiArai 4:d8ce59684dfa 114 real = t.tm_hour * 60 + t.tm_min;
kenjiArai 4:d8ce59684dfa 115 set = real + time;
kenjiArai 4:d8ce59684dfa 116 m = t.tm_min + (uint8_t)(time % 60);
kenjiArai 4:d8ce59684dfa 117 h = t.tm_hour;
kenjiArai 3:d59c12d14ca9 118 if (m >= 60){
kenjiArai 3:d59c12d14ca9 119 m -= 60;
kenjiArai 3:d59c12d14ca9 120 h += 1;
kenjiArai 3:d59c12d14ca9 121 }
kenjiArai 4:d8ce59684dfa 122 h += (uint8_t)(time / 60);
kenjiArai 3:d59c12d14ca9 123 if (h >= 24){
kenjiArai 3:d59c12d14ca9 124 h -= 24;
kenjiArai 3:d59c12d14ca9 125 }
kenjiArai 3:d59c12d14ca9 126 rtc_buf[2] = bin2bcd(h);
kenjiArai 3:d59c12d14ca9 127 rtc_buf[1] = bin2bcd(m);
kenjiArai 2:ce49c4ba4c02 128 rtc_buf[0] = RX8025_REG_ALARMD_MIN << 4;
kenjiArai 2:ce49c4ba4c02 129 _i2c.write(RX8025_addr, rtc_buf, 3, false);
kenjiArai 2:ce49c4ba4c02 130 dt = read_reg_byte(RX8025_REG_CONTL1);
kenjiArai 3:d59c12d14ca9 131 dt |= 0x40; // DALE = 1
kenjiArai 2:ce49c4ba4c02 132 dt = write_reg_byte(RX8025_REG_CONTL1, dt);
kenjiArai 4:d8ce59684dfa 133 real = bcd2bin(read_reg_byte(RX8025_REG_ALARMD_MIN));
kenjiArai 4:d8ce59684dfa 134 real += (bcd2bin(read_reg_byte(RX8025_REG_ALARMD_HOUR)) * 60);
kenjiArai 4:d8ce59684dfa 135 if (set == real) {
kenjiArai 4:d8ce59684dfa 136 read_rtc_std(&t); // read current time
kenjiArai 4:d8ce59684dfa 137 real = t.tm_hour * 60 + t.tm_min;
kenjiArai 4:d8ce59684dfa 138 if (set > real){
kenjiArai 4:d8ce59684dfa 139 return 1;
kenjiArai 4:d8ce59684dfa 140 } else {
kenjiArai 4:d8ce59684dfa 141 return 0;
kenjiArai 4:d8ce59684dfa 142 }
kenjiArai 4:d8ce59684dfa 143 } else {
kenjiArai 4:d8ce59684dfa 144 return 0;
kenjiArai 4:d8ce59684dfa 145 }
kenjiArai 4:d8ce59684dfa 146 }
kenjiArai 4:d8ce59684dfa 147
kenjiArai 4:d8ce59684dfa 148 void RX8025::set_next_alarmD_INTA (uint16_t time){
kenjiArai 4:d8ce59684dfa 149 uint8_t ret;
kenjiArai 4:d8ce59684dfa 150 uint16_t t;
kenjiArai 4:d8ce59684dfa 151
kenjiArai 4:d8ce59684dfa 152 if (time < 2){
kenjiArai 4:d8ce59684dfa 153 // Alarm does not check seconds digit.
kenjiArai 4:d8ce59684dfa 154 // If 59 to 0 is occured during setting here, 1 minute will have a trouble.
kenjiArai 4:d8ce59684dfa 155 t = 2;
kenjiArai 4:d8ce59684dfa 156 } else if (time > 1440){ // Less than 24 hours
kenjiArai 4:d8ce59684dfa 157 t = 1440;
kenjiArai 4:d8ce59684dfa 158 } else {
kenjiArai 4:d8ce59684dfa 159 t = time;
kenjiArai 4:d8ce59684dfa 160 }
kenjiArai 4:d8ce59684dfa 161 do{
kenjiArai 4:d8ce59684dfa 162 ret = set_alarmD_reg(t);
kenjiArai 4:d8ce59684dfa 163 } while(ret == 0);
kenjiArai 2:ce49c4ba4c02 164 }
kenjiArai 2:ce49c4ba4c02 165
kenjiArai 2:ce49c4ba4c02 166 /////////////// Clear Alarm-D / INTA interrupt ////////////
kenjiArai 3:d59c12d14ca9 167 void RX8025::clear_alarmD_INTA (){
kenjiArai 3:d59c12d14ca9 168 char dt, reg;
kenjiArai 3:d59c12d14ca9 169 reg = read_reg_byte(RX8025_REG_CONTL2);
kenjiArai 3:d59c12d14ca9 170 do { // make sure to set Hi-imp state
kenjiArai 3:d59c12d14ca9 171 dt = reg & 0xfe;
kenjiArai 3:d59c12d14ca9 172 write_reg_byte(RX8025_REG_CONTL1, dt);
kenjiArai 3:d59c12d14ca9 173 reg = read_reg_byte(RX8025_REG_CONTL2);
kenjiArai 4:d8ce59684dfa 174 } while (reg & 0x01);
kenjiArai 2:ce49c4ba4c02 175 }
kenjiArai 2:ce49c4ba4c02 176
kenjiArai 0:cdf2921959b4 177 /////////////// Read/Write specific register //////////////
kenjiArai 3:d59c12d14ca9 178 uint8_t RX8025::read_reg_byte(uint8_t reg){
kenjiArai 2:ce49c4ba4c02 179 rtc_buf[0] = reg << 4;
kenjiArai 2:ce49c4ba4c02 180 _i2c.write(RX8025_addr, rtc_buf, 1, true);
kenjiArai 2:ce49c4ba4c02 181 _i2c.read(RX8025_addr, rtc_buf, 1, false);
kenjiArai 2:ce49c4ba4c02 182 return rtc_buf[0];
kenjiArai 0:cdf2921959b4 183 }
kenjiArai 0:cdf2921959b4 184
kenjiArai 3:d59c12d14ca9 185 uint8_t RX8025::write_reg_byte(uint8_t reg, uint8_t data){
kenjiArai 2:ce49c4ba4c02 186 rtc_buf[0] = reg << 4;
kenjiArai 2:ce49c4ba4c02 187 rtc_buf[1] = data;
kenjiArai 2:ce49c4ba4c02 188 _i2c.write(RX8025_addr, rtc_buf, 2, false);
kenjiArai 2:ce49c4ba4c02 189 return read_reg_byte(reg);
kenjiArai 0:cdf2921959b4 190 }
kenjiArai 0:cdf2921959b4 191
kenjiArai 0:cdf2921959b4 192 /////////////// I2C Freq. /////////////////////////////////
kenjiArai 3:d59c12d14ca9 193 void RX8025::frequency(int hz){
kenjiArai 0:cdf2921959b4 194 _i2c.frequency(hz);
kenjiArai 0:cdf2921959b4 195 }
kenjiArai 0:cdf2921959b4 196
kenjiArai 0:cdf2921959b4 197 /////////////// Read/Write RTC another format /////////////
kenjiArai 3:d59c12d14ca9 198 void RX8025::read_rtc_direct (rtc_time *tm){
kenjiArai 2:ce49c4ba4c02 199 rtc_buf[0] = RX8025_REG_SEC << 4;
kenjiArai 2:ce49c4ba4c02 200 _i2c.write(RX8025_addr, rtc_buf, 1, true);
kenjiArai 2:ce49c4ba4c02 201 _i2c.read(RX8025_addr, rtc_buf, 10, false);
kenjiArai 0:cdf2921959b4 202 tm->rtc_seconds = bcd2bin(rtc_buf[RX8025_REG_SEC] & 0x7f);
kenjiArai 0:cdf2921959b4 203 tm->rtc_minutes = bcd2bin(rtc_buf[RX8025_REG_MIN] & 0x7f);
kenjiArai 0:cdf2921959b4 204 tm->rtc_hours = bcd2bin(rtc_buf[RX8025_REG_HOUR] & 0x3f);
kenjiArai 0:cdf2921959b4 205 tm->rtc_date = bcd2bin(rtc_buf[RX8025_REG_DAY] & 0x3f);
kenjiArai 0:cdf2921959b4 206 tm->rtc_weekday = rtc_buf[RX8025_REG_WDAY] & 0x07;
kenjiArai 0:cdf2921959b4 207 tm->rtc_month = bcd2bin(rtc_buf[RX8025_REG_MON] & 0x1f);
kenjiArai 0:cdf2921959b4 208 tm->rtc_year_raw= bcd2bin(rtc_buf[RX8025_REG_YEAR]);
kenjiArai 0:cdf2921959b4 209 tm->rtc_year = tm->rtc_year_raw + 100 + 1900;
kenjiArai 0:cdf2921959b4 210 }
kenjiArai 0:cdf2921959b4 211
kenjiArai 4:d8ce59684dfa 212 void RX8025::write_rtc_direct (rtc_time *tm){
kenjiArai 0:cdf2921959b4 213 rtc_buf[RX8025_REG_YEAR + 1] = bin2bcd(tm->rtc_year_raw);
kenjiArai 2:ce49c4ba4c02 214 rtc_buf[RX8025_REG_MON + 1] = bin2bcd(tm->rtc_month);
kenjiArai 0:cdf2921959b4 215 rtc_buf[RX8025_REG_WDAY + 1] = (tm->rtc_weekday & 0x07);
kenjiArai 2:ce49c4ba4c02 216 rtc_buf[RX8025_REG_DAY + 1] = bin2bcd(tm->rtc_date);
kenjiArai 0:cdf2921959b4 217 rtc_buf[RX8025_REG_HOUR + 1] = bin2bcd(tm->rtc_hours);
kenjiArai 2:ce49c4ba4c02 218 rtc_buf[RX8025_REG_MIN + 1] = bin2bcd(tm->rtc_minutes);
kenjiArai 2:ce49c4ba4c02 219 rtc_buf[RX8025_REG_SEC + 1] = bin2bcd(tm->rtc_seconds);
kenjiArai 2:ce49c4ba4c02 220 rtc_buf[0] = RX8025_REG_SEC << 4;
kenjiArai 2:ce49c4ba4c02 221 _i2c.write(RX8025_addr, rtc_buf, 8, false);
kenjiArai 0:cdf2921959b4 222 }
kenjiArai 0:cdf2921959b4 223
kenjiArai 3:d59c12d14ca9 224 uint8_t RX8025::bin2bcd (uint8_t dt){
kenjiArai 0:cdf2921959b4 225 uint8_t bcdhigh = 0;
kenjiArai 0:cdf2921959b4 226
kenjiArai 0:cdf2921959b4 227 while (dt >= 10) {
kenjiArai 0:cdf2921959b4 228 bcdhigh++;
kenjiArai 0:cdf2921959b4 229 dt -= 10;
kenjiArai 0:cdf2921959b4 230 }
kenjiArai 0:cdf2921959b4 231 return ((uint8_t)(bcdhigh << 4) | dt);
kenjiArai 0:cdf2921959b4 232 }
kenjiArai 0:cdf2921959b4 233
kenjiArai 3:d59c12d14ca9 234 uint8_t RX8025::bcd2bin (uint8_t dt){
kenjiArai 0:cdf2921959b4 235 uint8_t tmp = 0;
kenjiArai 0:cdf2921959b4 236
kenjiArai 0:cdf2921959b4 237 tmp = ((uint8_t)(dt & (uint8_t)0xf0) >> (uint8_t)0x4) * 10;
kenjiArai 0:cdf2921959b4 238 return (tmp + (dt & (uint8_t)0x0f));
kenjiArai 0:cdf2921959b4 239 }