Maxim Integrated / MAX31343

MAX31343 RTC Driver

Files at this revision

API Documentation at this revision

Comitter:
Erman Komurcu
Date:
Tue Dec 01 13:32:54 2020 +0300
Commit message:
initial commit

Changed in this revision

Max31343.cpp Show annotated file Show diff for this revision Revisions of this file
Max31343.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Max31343.cpp	Tue Dec 01 13:32:54 2020 +0300
@@ -0,0 +1,1148 @@
+/*******************************************************************************
+ * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "Max31343.h"
+
+#define pr_err(fmt, ...) if(1) printf(fmt " (%s:%d)\r\n", ## __VA_ARGS__, __func__, __LINE__)
+#define pr_debug(fmt, ...) if(0) printf(fmt " (%s:%d)\r\n", ## __VA_ARGS__, __func__, __LINE__)
+
+#define BCD2BIN(val) (((val) & 15) + ((val) >> 4) * 10)
+#define BIN2BCD(val) ((((val) / 10) << 4) + (val) % 10)
+
+#define POST_INTR_WORK_SIGNAL_ID			0x1
+
+#define TRICKLE_ENABLE_CODE					0x5
+
+Max31343::Max31343(I2C *i2c, PinName pin_int)
+{
+    if (i2c == NULL) {
+        pr_err("i2c object is invalid!");
+        while (1);
+    }
+    i2c_handler = i2c;
+
+    sw_reset_release();
+
+    rtc_start();
+
+    irq_disable_all();
+
+    post_intr_work_thread = new Thread();
+
+    post_intr_work_thread->start(Callback<void()>(this, &Max31343::post_interrupt_work));
+
+    if (pin_int != NC) {
+        this->pin_int = new InterruptIn(pin_int);
+
+        this->pin_int->fall(Callback<void()>(this, &Max31343::interrupt_handler));
+
+        this->pin_int->enable_irq();
+    } else {
+        this->pin_int = NULL;
+    }
+}
+
+Max31343::~Max31343()
+{
+    if (post_intr_work_thread) {
+        delete post_intr_work_thread;
+    }
+
+    if (pin_int) {
+        delete pin_int;
+    }
+}
+
+int Max31343::read_register(uint8_t reg, uint8_t *value, uint8_t len)
+{
+    int ret;
+
+    if (value == NULL) {
+        pr_err("value is invalid!");
+        return -1;
+    }
+
+    ret = i2c_handler->write(MAX3134X_I2C_W, (const char *) &reg, 1, true);
+    if (ret != 0) {
+        pr_err("i2c write failed with %d!", ret);
+        return -1;
+    }
+
+    ret = i2c_handler->read(MAX3134X_I2C_R, (char *) value, len, false);
+    if (ret < 0) {
+        pr_err("i2c read failed with %d!", ret);
+        return -1;
+    }
+
+    return 0;
+}
+
+int Max31343::write_register(uint8_t reg, const uint8_t *value, uint8_t len)
+{
+    int ret;
+    uint8_t *buffer;
+
+    if (value == NULL) {
+        pr_err("value is invalid!");
+        return -1;
+    }
+
+    buffer = new uint8_t[1 + len];
+    buffer[0] = reg;
+
+    memcpy(&buffer[1], value, len);
+
+    ret = i2c_handler->write(MAX3134X_I2C_W, (const char *)buffer, 1 + len);
+    if (ret != 0) {
+        pr_err("i2c write failed with %d!", ret);
+    }
+
+    delete[] buffer;
+
+    return ret;
+}
+
+int Max31343::rtc_regs_to_time(struct tm *time, const rtc_time_regs_t *regs)
+{
+    /* tm_sec seconds [0,61] */
+    time->tm_sec = BCD2BIN(regs->seconds.bcd.value);
+
+    /* tm_min minutes [0,59] */
+    time->tm_min = BCD2BIN(regs->minutes.bcd.value);
+
+    /* tm_hour hour [0,23] */
+    time->tm_hour = BCD2BIN(regs->hours.bcd.value);
+
+    /* tm_wday day of week [0,6] (Sunday = 0) */
+    time->tm_wday = BCD2BIN(regs->day.bcd.value) - 1;
+
+    /* tm_mday day of month [1,31] */
+    time->tm_mday = BCD2BIN(regs->date.bcd.value);
+
+    /* tm_mon month of year [0,11] */
+    time->tm_mon = BCD2BIN(regs->month.bcd.value) - 1;
+
+    /* tm_year years since 2000 */
+    if (regs->month.bits.century) {
+        time->tm_year = BCD2BIN(regs->year.bcd.value) + 200;
+    } else {
+        time->tm_year = BCD2BIN(regs->year.bcd.value) + 100;
+    }
+
+    /* tm_yday day of year [0,365] */
+    time->tm_yday = 0; /* TODO */
+
+    /* tm_isdst daylight savings flag */
+    time->tm_isdst = 0; /* TODO */
+
+    return 0;
+}
+
+int Max31343::time_to_rtc_regs(rtc_time_regs_t *regs, const struct tm *time)
+{
+    /*********************************************************
+     * +----------+------+---------------------------+-------+
+     * | Member   | Type | Meaning                   | Range |
+     * +----------+------+---------------------------+-------+
+     * | tm_sec   | int  | seconds after the minute  | 0-61* |
+     * | tm_min   | int  | minutes after the hour    | 0-59  |
+     * | tm_hour  | int  | hours since midnight      | 0-23  |
+     * | tm_mday  | int  | day of the month          | 1-31  |
+     * | tm_mon   | int  | months since January      | 0-11  |
+     * | tm_year  | int  | years since 1900          |       |
+     * | tm_wday  | int  | days since Sunday         | 0-6   |
+     * | tm_yday  | int  | days since January 1      | 0-365 |
+     * | tm_isdst | int  | Daylight Saving Time flag |       |
+     * +----------+------+---------------------------+-------+
+     * * tm_sec is generally 0-59. The extra range is to accommodate for leap
+     *   seconds in certain systems.
+     *********************************************************/
+    regs->seconds.bcd.value = BIN2BCD(time->tm_sec);
+
+    regs->minutes.bcd.value = BIN2BCD(time->tm_min);
+
+    regs->hours.bcd.value= BIN2BCD(time->tm_hour);
+
+    regs->day.bcd.value = BIN2BCD(time->tm_wday + 1);
+
+    regs->date.bcd.value = BIN2BCD(time->tm_mday);
+
+    regs->month.bcd.value = BIN2BCD(time->tm_mon + 1);
+
+    if (time->tm_year >= 200) {
+        regs->month.bits.century = 1;
+        regs->year.bcd.value = BIN2BCD(time->tm_year - 200);
+    } else if (time->tm_year >= 100) {
+        regs->month.bits.century = 0;
+        regs->year.bcd.value = BIN2BCD(time->tm_year - 100);
+    } else {
+        pr_err("Invalid set date!");
+        return -1;
+    }
+
+    return 0;
+}
+
+int Max31343::get_time(struct tm *time)
+{
+    rtc_time_regs_t time_regs;
+
+    if (time == NULL) {
+        pr_err("rtc_ctime is invalid!");
+        return -1;
+    }
+
+    if (read_register(MAX31343_REG_SECONDS_ADDR, (uint8_t *) &time_regs, sizeof(time_regs)) < 0) {
+        pr_err("read time registers failed!");
+        return -1;
+    }
+
+    return rtc_regs_to_time(time, &time_regs);
+}
+
+int Max31343::set_time(const struct tm *time)
+{
+    rtc_time_regs_t time_regs;
+
+    if (time == NULL) {
+        pr_err("rtc_ctime is invalid!");
+        return -1;
+    }
+
+    time_to_rtc_regs(&time_regs, time);
+
+    if (write_register(MAX31343_REG_SECONDS_ADDR, (const uint8_t *) &time_regs, sizeof(time_regs)) < 0) {
+        pr_err("read time registers failed!");
+        return -1;
+    }
+
+    return 0;
+}
+
+int Max31343::time_to_alarm_regs(alarm_regs_t &regs, const struct tm *alarm_time)
+{
+    regs.sec.bcd.value = BIN2BCD(alarm_time->tm_sec);
+    regs.min.bcd.value = BIN2BCD(alarm_time->tm_min);
+
+    regs.hrs.bcd.value = BIN2BCD(alarm_time->tm_hour);
+
+    if (regs.day_date.bits.dy_dt == 0) {
+        /* Date match */
+        regs.day_date.bcd_date.value = BIN2BCD(alarm_time->tm_mday);
+    } else {
+        /* Day match */
+        regs.day_date.bcd_day.value = BIN2BCD(alarm_time->tm_wday);
+    }
+    regs.mon.bcd.value = BIN2BCD(alarm_time->tm_mon+1);
+
+    if (alarm_time->tm_year >= 200) {
+        regs.year.bcd.value = BIN2BCD(alarm_time->tm_year - 200);
+    } else if (alarm_time->tm_year >= 100) {
+        regs.year.bcd.value = BIN2BCD(alarm_time->tm_year - 100);
+    } else {
+        pr_err("Invalid set year!");
+        return -1;
+    }
+
+    return 0;
+}
+
+int Max31343::alarm_regs_to_time(struct tm *alarm_time, const alarm_regs_t *regs)
+{
+    alarm_time->tm_sec = BCD2BIN(regs->sec.bcd.value);
+    alarm_time->tm_min = BCD2BIN(regs->min.bcd.value);
+    alarm_time->tm_hour = BCD2BIN(regs->hrs.bcd.value);
+
+    if (regs->day_date.bits.dy_dt == 0) { /* date */
+        alarm_time->tm_mday = BCD2BIN(regs->day_date.bcd_date.value);
+    } else { /* day */
+        alarm_time->tm_wday = BCD2BIN(regs->day_date.bcd_day.value);
+    }
+
+    alarm_time->tm_mon = BCD2BIN(regs->mon.bcd.value) - 1;
+
+    /* XXX no century bit */
+    alarm_time->tm_year = BCD2BIN(regs->year.bcd.value) + 100;
+
+
+    return 0;
+}
+
+int Max31343::set_alarm_period(alarm_no_t alarm_no, alarm_regs_t &regs, alarm_period_t period)
+{
+    switch (period) {
+        case ALARM_PERIOD_ONETIME:
+            if (alarm_no == ALARM2) { /* not supported! */
+                return -1;
+            }
+            regs.sec.bits.a1m1 = 0;
+            regs.min.bits.a1m2 = 0;
+            regs.hrs.bits.a1m3 = 0;
+            regs.day_date.bits.a1m4 = 0;
+            regs.mon.bits.a1m5 = 0;
+            regs.mon.bits.a1m6 = 0;
+            regs.day_date.bits.dy_dt = 0;
+            break;
+        case ALARM_PERIOD_YEARLY:
+            if (alarm_no == ALARM2) { /* not supported! */
+                return -1;
+            }
+            regs.sec.bits.a1m1 = 0;
+            regs.min.bits.a1m2 = 0;
+            regs.hrs.bits.a1m3 = 0;
+            regs.day_date.bits.a1m4 = 0;
+            regs.mon.bits.a1m5 = 0;
+            regs.mon.bits.a1m6 = 1;
+            regs.day_date.bits.dy_dt = 0;
+            break;
+        case ALARM_PERIOD_MONTHLY:
+            regs.sec.bits.a1m1 = 0;
+            regs.min.bits.a1m2 = 0;
+            regs.hrs.bits.a1m3 = 0;
+            regs.day_date.bits.a1m4 = 0;
+            regs.mon.bits.a1m5 = 1;
+            regs.mon.bits.a1m6 = 1;
+            regs.day_date.bits.dy_dt = 0;
+            break;
+        case ALARM_PERIOD_WEEKLY:
+            regs.sec.bits.a1m1 = 0;
+            regs.min.bits.a1m2 = 0;
+            regs.hrs.bits.a1m3 = 0;
+            regs.day_date.bits.a1m4 = 0;
+            regs.mon.bits.a1m5 = 1;
+            regs.mon.bits.a1m6 = 1;
+            regs.day_date.bits.dy_dt = 1;
+            break;
+        case ALARM_PERIOD_DAILY:
+            regs.sec.bits.a1m1 = 0;
+            regs.min.bits.a1m2 = 0;
+            regs.hrs.bits.a1m3 = 0;
+            regs.day_date.bits.a1m4 = 1;
+            regs.mon.bits.a1m5 = 1;
+            regs.mon.bits.a1m6 = 1;
+            regs.day_date.bits.dy_dt = 0;
+            break;
+        case ALARM_PERIOD_HOURLY:
+            regs.sec.bits.a1m1 = 0;
+            regs.min.bits.a1m2 = 0;
+            regs.hrs.bits.a1m3 = 1;
+            regs.day_date.bits.a1m4 = 1;
+            regs.mon.bits.a1m5 = 1;
+            regs.mon.bits.a1m6 = 1;
+            regs.day_date.bits.dy_dt = 0;
+            break;
+        case ALARM_PERIOD_EVERYMINUTE:
+            regs.sec.bits.a1m1 = 0;
+            regs.min.bits.a1m2 = 1;
+            regs.hrs.bits.a1m3 = 1;
+            regs.day_date.bits.a1m4 = 1;
+            regs.mon.bits.a1m5 = 1;
+            regs.mon.bits.a1m6 = 1;
+            regs.day_date.bits.dy_dt = 0;
+            break;
+        case ALARM_PERIOD_EVERYSECOND:
+            if ((alarm_no == ALARM2) && (period == ALARM_PERIOD_EVERYSECOND)) {
+                return -1; /* Alarm2 does not support "once per second" alarm*/
+            }
+            regs.sec.bits.a1m1 = 1;
+            regs.min.bits.a1m2 = 1;
+            regs.hrs.bits.a1m3 = 1;
+            regs.day_date.bits.a1m4 = 1;
+            regs.mon.bits.a1m5 = 1;
+            regs.mon.bits.a1m6 = 1;
+            regs.day_date.bits.dy_dt = 0;
+            break;
+        default:
+            return -1;
+    }
+
+    return 0;
+}
+
+int Max31343::set_alarm_regs(alarm_no_t alarm_no, const alarm_regs_t *regs)
+{
+    uint8_t *ptr_regs = (uint8_t *)regs;
+    uint8_t off = 0;
+    uint8_t dev_ba;
+    uint8_t len = sizeof(alarm_regs_t);
+
+    if (alarm_no == ALARM1) {
+        dev_ba = MAX31343_REG_ALM1_SEC_ADDR;
+    } else {
+        dev_ba = MAX31343_REG_ALM2_MIN_ADDR;
+        off = 1;	/* starts from min register */
+        len -= 3;	/* XXX discard min, mon & sec registers */
+    }
+
+    return write_register(dev_ba, &ptr_regs[off], len);
+}
+
+int Max31343::get_alarm_regs(alarm_no_t alarm_no, alarm_regs_t *regs)
+{
+    uint8_t *ptr_regs = (uint8_t *)regs;
+    uint8_t off = 0;
+    uint8_t dev_ba;
+    uint8_t len = sizeof(alarm_regs_t);
+
+    if (alarm_no == ALARM1) {
+        dev_ba = MAX31343_REG_ALM1_SEC_ADDR;
+    } else {
+        regs->sec.raw = 0;	/* zeroise second register for alarm2 */
+        dev_ba = MAX31343_REG_ALM2_MIN_ADDR;
+        off = 1;	/* starts from min register (no sec register) */
+        len -= 2;	/* XXX discard mon & sec registers */
+    }
+
+    return read_register(dev_ba, &ptr_regs[off], len);
+}
+
+int Max31343::set_alarm(alarm_no_t alarm_no, const struct tm *alarm_time, alarm_period_t period)
+{
+    int ret;
+    alarm_regs_t regs;
+
+    ret = set_alarm_period(alarm_no, regs, period);
+    if (ret) {
+        return ret;
+    }
+
+    /* Convert time structure to alarm registers */
+    ret = time_to_alarm_regs(regs, alarm_time);
+    if (ret) {
+        return ret;
+    }
+
+    ret = set_alarm_regs(alarm_no, &regs);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::get_alarm(alarm_no_t alarm_no, struct tm *alarm_time,
+                        alarm_period_t *period, bool *is_enabled)
+{
+    int ret;
+    alarm_regs_t regs;
+    uint8_t reg;
+
+    ret = get_alarm_regs(alarm_no, &regs);
+    if (ret) {
+        return ret;
+    }
+
+    /* Convert alarm registers to time structure */
+    ret = alarm_regs_to_time(alarm_time, &regs);
+    if (ret) {
+        return ret;
+    }
+
+    if(alarm_no == ALARM1) {
+        int alarm = regs.sec.bits.a1m1 | (regs.min.bits.a1m2<<1)
+                    | (regs.hrs.bits.a1m3<<2) | (regs.day_date.bits.a1m4<<3)
+                    | (regs.mon.bits.a1m5<<4) | (regs.mon.bits.a1m6<<5)
+                    | (regs.day_date.bits.dy_dt<<6);
+
+        switch(alarm) {
+            case 0b1111111:
+            case 0b0111111:
+                *period = ALARM_PERIOD_EVERYSECOND;
+                break;
+            case 0b1111110:
+            case 0b0111110:
+                *period = ALARM_PERIOD_EVERYMINUTE;
+                break;
+            case 0b1111100:
+            case 0b0111100:
+                *period = ALARM_PERIOD_HOURLY;
+                break;
+            case 0b0111000:
+            case 0b1111000:
+                *period = ALARM_PERIOD_DAILY;
+                break;
+            case 0b0110000:
+                *period = ALARM_PERIOD_MONTHLY;
+                break;
+            case 0b0100000:
+                *period = ALARM_PERIOD_YEARLY;
+                break;
+            case 0b0000000:
+                *period = ALARM_PERIOD_ONETIME;
+                break;
+            case 0b1110000:
+                *period = ALARM_PERIOD_WEEKLY;
+        }
+    } else {
+        int alarm = (regs.min.bits.a1m2) | (regs.hrs.bits.a1m3<<1)
+                    | (regs.day_date.bits.a1m4<<2)
+                    | (regs.day_date.bits.dy_dt<<3);
+
+        switch(alarm) {
+            case 0b1111:
+            case 0b0111:
+                *period = ALARM_PERIOD_EVERYMINUTE;
+                break;
+            case 0b1110:
+            case 0b0110:
+                *period = ALARM_PERIOD_HOURLY;
+                break;
+            case 0b1100:
+            case 0b0100:
+                *period = ALARM_PERIOD_DAILY;
+                break;
+            case 0b0000:
+                *period = ALARM_PERIOD_MONTHLY;
+                break;
+            case 0b1000:
+                *period = ALARM_PERIOD_WEEKLY;
+        }
+    }
+
+    ret = read_register(MAX31343_REG_INT_EN_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    if (alarm_no == ALARM1) {
+        *is_enabled = (reg & (1 << INTR_ID_ALARM1)) != 0;
+    } else {
+        *is_enabled = (reg & (1 << INTR_ID_ALARM2)) != 0;
+    }
+
+    return 0;
+}
+
+int Max31343::powerfail_threshold_level(comp_thresh_t th)
+{
+    int ret;
+    pwr_mgmt_reg_t reg;
+
+    ret = read_register(MAX31343_REG_PWR_MGMT_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg.bits.pfvt = th;
+
+    ret = write_register(MAX31343_REG_PWR_MGMT_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::supply_select(power_mgmt_supply_t supply)
+{
+    int ret;
+    pwr_mgmt_reg_t reg;
+
+    ret = read_register(MAX31343_REG_PWR_MGMT_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    switch (supply) {
+        case POW_MGMT_SUPPLY_SEL_VCC:
+            reg.bits.d_man_sel = 1;
+            reg.bits.d_vback_sel = 0;
+            break;
+        case POW_MGMT_SUPPLY_SEL_VBACK:
+            reg.bits.d_man_sel = 1;
+            reg.bits.d_vback_sel = 1;
+            break;
+        case POW_MGMT_SUPPLY_SEL_AUTO:
+        default:
+            reg.bits.d_man_sel = 0;
+            break;
+    }
+
+    ret = write_register(MAX31343_REG_PWR_MGMT_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::trickle_charger_enable(trickle_charger_path_t path)
+{
+    int ret;
+    struct {
+        unsigned char path     : 4;
+        unsigned char tche     : 4;
+    } reg;
+
+    ret = read_register(MAX31343_REG_TRICKLE_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg.tche = TRICKLE_ENABLE_CODE;
+    reg.path = path;
+
+    ret = write_register(MAX31343_REG_TRICKLE_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::trickle_charger_disable()
+{
+    int ret;
+    struct {
+        unsigned char path     : 4;
+        unsigned char tche     : 4;
+    } reg;
+
+
+    ret = read_register(MAX31343_REG_TRICKLE_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg.tche = 0;
+
+    ret = write_register(MAX31343_REG_TRICKLE_REG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::set_output_square_wave_frequency(square_wave_out_freq_t freq)
+{
+    int ret;
+    config_reg2_t reg;
+
+    ret = read_register(MAX31343_REG_CONFIG_REG2_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg.bits.sqw_hz = freq;
+
+    ret = write_register(MAX31343_REG_CONFIG_REG2_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::clko_enable(clko_freq_t freq)
+{
+    int ret;
+    config_reg2_t cfg2;
+
+    ret = read_register(MAX31343_REG_CONFIG_REG2_ADDR, (uint8_t *)&cfg2, 1);
+    if (ret) {
+        return ret;
+    }
+
+    cfg2.bits.enclko = 1;
+    cfg2.bits.clko_hz = freq;
+
+    ret = write_register(MAX31343_REG_CONFIG_REG2_ADDR, (uint8_t *)&cfg2, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::clko_disable()
+{
+    int ret;
+    config_reg2_t cfg2;
+
+    ret = read_register(MAX31343_REG_CONFIG_REG2_ADDR, (uint8_t *)&cfg2, 1);
+    if (ret) {
+        return ret;
+    }
+
+    cfg2.bits.enclko = 0;
+
+    ret = write_register(MAX31343_REG_CONFIG_REG2_ADDR, (uint8_t *)&cfg2, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::timer_init(uint8_t value, bool repeat, timer_freq_t freq)
+{
+    int ret;
+    timer_config_t reg_cfg;
+
+    ret = read_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg_cfg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg_cfg.bits.te = 0; /* timer is reset */
+    reg_cfg.bits.tpause = 1; /* timer is paused */
+    reg_cfg.bits.trpt = repeat ? 1 : 0;	/* Timer repeat mode */
+    reg_cfg.bits.tfs = freq;	/* Timer frequency */
+
+    ret = write_register(MAX31343_REG_TIMER_CONFIG_ADDR,
+                         (uint8_t *)&reg_cfg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    ret = write_register(MAX31343_REG_TIMER_INIT_ADDR, (uint8_t *)&value, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+uint8_t Max31343::timer_get()
+{
+    int ret;
+    uint8_t reg;
+
+    ret = read_register(MAX31343_REG_TIMER_COUNT_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return (uint8_t) - 1;
+    }
+
+    return reg;
+}
+
+int Max31343::timer_start()
+{
+    int ret;
+    timer_config_t reg;
+
+    ret = read_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg.bits.te = 1;
+    reg.bits.tpause = 0;
+
+    ret = write_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::timer_pause()
+{
+    int ret;
+    timer_config_t reg;
+
+    ret = read_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg.bits.te = 1;
+    reg.bits.tpause = 1;
+
+    ret = write_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::timer_continue()
+{
+    int ret;
+    timer_config_t reg;
+
+    ret = read_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg.bits.te = 1;
+    reg.bits.tpause = 0;
+
+    ret = write_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::timer_stop()
+{
+    int ret;
+    timer_config_t reg;
+
+    ret = read_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg.bits.te = 0;
+    reg.bits.tpause = 1;
+
+    ret = write_register(MAX31343_REG_TIMER_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::data_retention_mode_config(int state)
+{
+    int ret;
+    config_reg1_t cfg1;
+
+    ret = read_register(MAX31343_REG_CONFIG_REG1_ADDR, (uint8_t *)&cfg1, 1);
+    if (ret) {
+        return ret;
+    }
+
+    if (state) {
+        cfg1.bits.enosc = 0;
+        cfg1.bits.data_reten = 1;
+    } else {
+        cfg1.bits.enosc = 1;
+        cfg1.bits.data_reten = 0;
+    }
+
+    ret = write_register(MAX31343_REG_CONFIG_REG1_ADDR, (uint8_t *)&cfg1, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::data_retention_mode_enter()
+{
+    return data_retention_mode_config(1);
+}
+
+int Max31343::data_retention_mode_exit()
+{
+    return data_retention_mode_config(0);
+}
+
+int Max31343::i2c_timeout_config(int enable)
+{
+    int ret;
+    config_reg1_t cfg1;
+
+    ret = read_register(MAX31343_REG_CONFIG_REG1_ADDR, (uint8_t *)&cfg1, 1);
+    if (ret) {
+        return ret;
+    }
+
+    cfg1.bits.i2c_timeout = (enable) ? 1 : 0;
+
+    ret = write_register(MAX31343_REG_CONFIG_REG1_ADDR, (uint8_t *)&cfg1, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::i2c_timeout_enable()
+{
+    return i2c_timeout_config(1);
+}
+
+int Max31343::i2c_timeout_disable()
+{
+    return i2c_timeout_config(0);
+}
+
+int Max31343::read_temp(float *temp)
+{
+    int ret;
+    uint8_t regs[2];
+    ts_config_t cfg_reg;
+    int itemp;
+
+    ret = read_register(MAX31343_REG_TS_CONFIG_ADDR, (uint8_t *)&cfg_reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    if (cfg_reg.bits.automode) { /* manual mode */
+        /* trigger temperature reading */
+        cfg_reg.bits.oneshotmode = 1;
+
+        ret = write_register(MAX31343_REG_TS_CONFIG_ADDR, (uint8_t *)&cfg_reg, 1);
+        if (ret) {
+            return ret;
+        }
+
+        while (cfg_reg.bits.oneshotmode) {
+            ret = read_register(MAX31343_REG_TS_CONFIG_ADDR, (uint8_t *)&cfg_reg, 1);
+            if (ret) {
+                return ret;
+            }
+        }
+    }
+
+    ret = read_register(MAX31343_REG_TEMP_MSB_ADDR, regs, 2);
+    if (ret) {
+        return ret;
+    }
+
+    itemp = ((regs[0] << 2) | (regs[1] >> 6));
+    if (regs[0] & 0x80) { /* if negative */
+        itemp |= -(1 << 10); /* sign extend */
+    }
+
+    *temp = (float)itemp / 4; /* LSB resolution: 0.25 C */
+
+    return 0;
+}
+
+int Max31343::temp_sensor_config(bool automode, ttsint_t interval)
+{
+    int ret;
+    ts_config_t reg;
+
+    ret = read_register(MAX31343_REG_TS_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    if (automode) {
+        reg.bits.automode = 1;
+        reg.bits.ttint = interval;
+    } else {
+        reg.bits.automode = 0;
+    }
+
+    ret = write_register(MAX31343_REG_TS_CONFIG_ADDR, (uint8_t *)&reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::irq_enable(intr_id_t id)
+{
+    int ret;
+    uint8_t reg;
+
+    ret = read_register(MAX31343_REG_INT_EN_REG_ADDR, &reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg |= (1 << id);
+
+    ret = write_register(MAX31343_REG_INT_EN_REG_ADDR, &reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::irq_disable(intr_id_t id)
+{
+    int ret;
+    uint8_t reg;
+
+    ret = read_register(MAX31343_REG_INT_EN_REG_ADDR, &reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    reg &= ~(1 << id);
+
+    ret = write_register(MAX31343_REG_INT_EN_REG_ADDR, &reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::irq_disable_all()
+{
+    int ret;
+    uint8_t reg = 0;
+
+    ret = write_register(MAX31343_REG_INT_EN_REG_ADDR, &reg, 1);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+void Max31343::set_intr_handler(intr_id_t id, interrupt_handler_function func, void *cb)
+{
+    interrupt_handler_list[id].func = func;
+    interrupt_handler_list[id].cb = cb;
+}
+
+void Max31343::post_interrupt_work()
+{
+    int ret;
+    uint8_t reg, inten, mask;
+
+
+    while (true) {
+        Thread::signal_wait(POST_INTR_WORK_SIGNAL_ID);
+
+        ret = read_register(MAX31343_REG_INT_STATUS_REG_ADDR, &reg, 1);
+        if (ret) {
+            pr_err("Read interrupt status register failed!");
+        }
+
+        ret = read_register(MAX31343_REG_INT_EN_REG_ADDR, &inten, 1);
+        if (ret) {
+            pr_err("Read interrupt enable register failed!");
+        }
+
+        for (int i = 0; i < INTR_ID_END; i++) {
+            mask = (1 << i);
+            if ((reg & mask) && (inten & mask)) {
+                if (interrupt_handler_list[i].func != NULL) {
+                    interrupt_handler_list[i]
+                    .func(interrupt_handler_list[i].cb);
+                }
+            }
+        }
+    }
+}
+
+void Max31343::interrupt_handler()
+{
+    post_intr_work_thread->signal_set(POST_INTR_WORK_SIGNAL_ID);
+}
+
+int Max31343::sw_reset_assert()
+{
+    int ret;
+    rtc_reset_reg_t rst_reg;
+
+    ret = read_register(MAX31343_REG_RTC_RESET_ADDR, (uint8_t *) &rst_reg, 1);
+    if (ret < 0) {
+        pr_err("read_register failed!");
+        return ret;
+    }
+
+    rst_reg.bits.swrst = 1;	/* Put device in reset state */
+
+    ret = write_register(MAX31343_REG_RTC_RESET_ADDR, (const uint8_t *) &rst_reg, 1);
+    if (ret < 0) {
+        pr_err("read_register failed!");
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::sw_reset_release()
+{
+    int ret;
+    rtc_reset_reg_t rst_reg;
+
+    ret = read_register(MAX31343_REG_RTC_RESET_ADDR, (uint8_t *) &rst_reg, 1);
+    if (ret < 0) {
+        pr_err("read_register failed!");
+        return ret;
+    }
+
+    rst_reg.bits.swrst = 0;	/* Remove device from reset state */
+
+    ret = write_register(MAX31343_REG_RTC_RESET_ADDR,
+                         (const uint8_t *) &rst_reg, 1);
+    if (ret < 0) {
+        pr_err("read_register failed!");
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::rtc_start()
+{
+    int ret;
+    config_reg1_t cfg1;
+
+    ret = read_register(MAX31343_REG_CONFIG_REG1_ADDR, (uint8_t *) &cfg1, 1);
+    if (ret < 0) {
+        return ret;
+    }
+
+    cfg1.bits.enosc = 1;	/* Enable the oscillator */
+
+    ret = write_register(MAX31343_REG_CONFIG_REG1_ADDR, (const uint8_t *) &cfg1, 1);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int Max31343::rtc_stop()
+{
+    int ret;
+    config_reg1_t cfg1;
+
+    ret = read_register(MAX31343_REG_CONFIG_REG1_ADDR, (uint8_t *) &cfg1, 1);
+    if (ret < 0) {
+        return ret;
+    }
+
+    cfg1.bits.enosc = 0;	/* Disable the oscillator */
+
+    ret = write_register(MAX31343_REG_CONFIG_REG1_ADDR,
+                         (const uint8_t *) &cfg1, 1);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Max31343.h	Tue Dec 01 13:32:54 2020 +0300
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#ifndef Max31343_H_
+#define Max31343_H_
+
+#include "mbed.h"
+#include <ctime>
+
+
+/**
+ * @brief	RTC base driver class for Maxim Max3134x RTC series.
+ */
+class Max31343
+{
+public:
+
+    /**
+    * @brief	Device register addresses
+    */
+    enum max31343_register_address {
+        MAX31343_REG_INT_STATUS_REG_ADDR	= 0x00,
+        MAX31343_REG_INT_EN_REG_ADDR		= 0x01,
+        MAX31343_REG_RTC_RESET_ADDR			= 0x02,
+        MAX31343_REG_CONFIG_REG1_ADDR		= 0x03,
+        MAX31343_REG_CONFIG_REG2_ADDR		= 0x04,
+        MAX31343_REG_TIMER_CONFIG_ADDR		= 0x05,
+        MAX31343_REG_SECONDS_ADDR			= 0x06,
+        MAX31343_REG_MINUTES_ADDR			= 0x07,
+        MAX31343_REG_HOURS_ADDR				= 0x08,
+        MAX31343_REG_DAY_ADDR				= 0x09,
+        MAX31343_REG_DATE_ADDR				= 0x0A,
+        MAX31343_REG_MONTH_ADDR				= 0x0B,
+        MAX31343_REG_YEAR_ADDR				= 0x0C,
+        MAX31343_REG_ALM1_SEC_ADDR			= 0x0D,
+        MAX31343_REG_ALM1_MIN_ADDR			= 0x0E,
+        MAX31343_REG_ALM1_HRS_ADDR			= 0x0F,
+        MAX31343_REG_ALM1DAY_DATE_ADDR		= 0x10,
+        MAX31343_REG_ALM1_MON_ADDR			= 0x11,
+        MAX31343_REG_ALM1_YEAR_ADDR			= 0x12,
+        MAX31343_REG_ALM2_MIN_ADDR			= 0x13,
+        MAX31343_REG_ALM2_HRS_ADDR			= 0x14,
+        MAX31343_REG_ALM2DAY_DATE_ADDR		= 0x15,
+        MAX31343_REG_TIMER_COUNT_ADDR		= 0x16,
+        MAX31343_REG_TIMER_INIT_ADDR		= 0x17,
+        MAX31343_REG_PWR_MGMT_REG_ADDR		= 0x18,
+        MAX31343_REG_TRICKLE_REG_ADDR		= 0x19,
+        MAX31343_REG_TEMP_MSB_ADDR			= 0x1A,
+        MAX31343_REG_TEMP_LSB_ADDR			= 0x1B,
+        MAX31343_REG_TS_CONFIG_ADDR			= 0x1C,
+        MAX31343_REG_END,
+    };
+
+    /**
+    * @brief	Uncompensated clock output frequency selection
+    */
+    typedef enum {
+        CLKO_FREQ_1HZ,		/**< 1Hz */
+        CLKO_FREQ_2HZ,		/**< 2Hz */
+        CLKO_FREQ_4HZ,		/**< 4Hz */
+        CLKO_FREQ_8HZ,		/**< 8Hz */
+        CLKO_FREQ_16HZ,		/**< 16Hz */
+        CLKO_FREQ_32HZ,		/**< 32Hz */
+        CLKO_FREQ_64HZ,		/**< 64Hz */
+        CLKO_FREQ_128HZ,	/**< 128Hz */
+        CLKO_FREQ_32000HZ,	/**< 32KHz */
+    } clko_freq_t;
+
+    /**
+    * @brief	Square wave output frequency selection
+    */
+    typedef enum {
+        SQUARE_WAVE_OUT_FREQ_1HZ,	/**<  1Hz */
+        SQUARE_WAVE_OUT_FREQ_2HZ,	/**<  2Hz */
+        SQUARE_WAVE_OUT_FREQ_4HZ,	/**<  4Hz */
+        SQUARE_WAVE_OUT_FREQ_8HZ,	/**<  8Hz */
+        SQUARE_WAVE_OUT_FREQ_16HZ,	/**< 16Hz */
+        SQUARE_WAVE_OUT_FREQ_32HZ,	/**< 32Hz */
+    } square_wave_out_freq_t;
+
+    /**
+    * @brief	Power fail threshold voltage
+    */
+    typedef enum {
+        COMP_THRESH_1V85 = 1,	/**< 1.85V */
+        COMP_THRESH_2V15,		/**< 2.15V */
+        COMP_THRESH_2V40,		/**< 2.40V */
+    } comp_thresh_t;
+
+    /**
+    * @brief	Supply voltage select.
+    */
+    typedef enum {
+        POW_MGMT_SUPPLY_SEL_AUTO,	/**< Circuit decides whether to use VCC or VBACKUP */
+        POW_MGMT_SUPPLY_SEL_VCC,	/**< Use VCC as supply */
+        POW_MGMT_SUPPLY_SEL_VBACK,	/**< Use VBACKUP as supply */
+    } power_mgmt_supply_t;
+
+    /**
+    * @brief	Selection of charging path's resistor value
+    */
+    typedef enum {
+        TRICKLE_CHARGER_3K_S,   /**< 3Kohm in series with a Schottky diode  */
+        TRICKLE_CHARGER_3K_2_S, /**< 3Kohm in series with a Schottky diode  */
+        TRICKLE_CHARGER_6K_S,	/**< 6Kohm in series with a Schottky diode */
+        TRICKLE_CHARGER_11K_S,    /**<  11Kohm in series with a Schottky diode */
+        TRICKLE_CHARGER_3K_D_S,   /**< 3Kohm in series with a diode+Schottky diode  */
+        TRICKLE_CHARGER_3K_2_D_S,   /**< 3Kohm in series with a diode+Schottky diode */
+        TRICKLE_CHARGER_6K_D_S,   /**< 6Kohm in series with a diode+Schottky diode */
+        TRICKLE_CHARGER_11K_D_S,  /**< 11Kohm in series with a diode+Schottky diode */
+        TRICKLE_CHARGER_NO_CONNECTION,   /**< No Connection  */
+    } trickle_charger_path_t;
+
+    /**
+    * @brief	Timer frequency selection
+    */
+    typedef enum {
+        TIMER_FREQ_1024HZ,	/**< 1024Hz */
+        TIMER_FREQ_256HZ,	/**< 256Hz */
+        TIMER_FREQ_64HZ,	/**< 64Hz */
+        TIMER_FREQ_16HZ,	/**< 16Hz */
+    } timer_freq_t;
+
+    /**
+    * @brief	Selection of interrupt ids
+    */
+    typedef enum {
+        INTR_ID_ALARM1 = 0,		/**< Alarm1 flag */
+        INTR_ID_ALARM2 = 1,		/**< Alarm2 flag */
+        INTR_ID_TIMER  = 2,		/**< Timer interrupt flag */
+        INTR_ID_TEMP   = 3,		/**< Temp sense ready flag */
+        INTR_ID_PFAIL  = 5,		/**< Power fail interrupt enable */
+        INTR_ID_DOSF   = 6,		/**< Disable Oscillator flag */
+        INTR_ID_END,
+    } intr_id_t;
+
+    /**
+    * @brief	Alarm number selection
+    */
+    typedef enum {
+        ALARM1,	/**< Alarm number 1 */
+        ALARM2,	/**< Alarm number 2 */
+    } alarm_no_t;
+
+    /**
+    * @brief	Alarm periodicity selection
+    */
+    typedef enum {
+        ALARM_PERIOD_EVERYSECOND,	/**< Once per second */
+        ALARM_PERIOD_EVERYMINUTE,	/**< Second match / Once per minute */
+        ALARM_PERIOD_HOURLY,		/**< Second and Minute match */
+        ALARM_PERIOD_DAILY,			/**< Hour, Minute and Second match*/
+        ALARM_PERIOD_WEEKLY,		/**< Day and Time match */
+        ALARM_PERIOD_MONTHLY,		/**< Date and Time match */
+        ALARM_PERIOD_YEARLY,		/**< Month, Date and Time match (Max31342 only) */
+        ALARM_PERIOD_ONETIME,		/**< Year, Month, Date and Time match (Max31342 only) */
+    } alarm_period_t;
+
+    /**
+    * @brief	Selection of INTB/CLKOUT pin function
+    */
+    typedef enum {
+        CONFIGURE_PIN_AS_CLKOUT,	/**< Output is square wave */
+        CONFIGURE_PIN_AS_INTB,		/**< Output is interrupt */
+    } config_intb_clkout_pin_t;
+
+    /**
+     * @brief	Temperature measurement interval for automatic mode
+     */
+    typedef enum {
+        TTS_INTERNAL_1SEC = 0,
+        TTS_INTERNAL_2SEC,
+        TTS_INTERNAL_4SEC,
+        TTS_INTERNAL_8SEC,
+        TTS_INTERNAL_16SEC,
+        TTS_INTERNAL_32SEC,
+        TTS_INTERNAL_64SEC,
+        TTS_INTERNAL_128SEC,
+    } ttsint_t;
+
+    /**
+    * @brief	Base class constructor.
+    *
+    * @param[in]	i2c Pointer to I2C bus object for this device.
+    * @param[in]	pin_int MCU's pin number that device's INT pin connected
+    */
+    Max31343(I2C *i2c, PinName pin_int = NC);
+
+    /**
+    * @brief	Function pointer type to interrupt handler function
+    */
+    typedef void (*interrupt_handler_function)(void *);
+
+    /**
+    * @brief		Read from a register.
+    *
+    * @param[in]	reg Address of a register to be read.
+    * @param[out]	value Pointer to save result value.
+    * @param[in]	len Size of result to be read.
+    *
+    * @returns		0 on success, negative error code on failure.
+    */
+    int read_register(uint8_t reg, uint8_t *value, uint8_t len);
+
+    /**
+    * @brief		Write to a register.
+    *
+    * @param[in]	reg Address of a register to be written.
+    * @param[out]	value Pointer of value to be written to register.
+    * @param[in]	len Size of result to be written.
+    *
+    * @returns		0 on success, negative error code on failure.
+    */
+    int write_register(uint8_t reg, const uint8_t *value, uint8_t len);
+
+    /**
+    * @brief		Read time info from RTC.
+    *
+    * @param[out]	rtc_time Time info from RTC.
+    *
+    * @returns		0 on success, negative error code on failure.
+    */
+    int get_time(struct tm *rtc_ctime);
+
+    /**
+    * @brief		Set time info to RTC.
+    *
+    * @param[in]	rtc_time Time info to be written to RTC.
+    *
+    * @returns		0 on success, negative error code on failure.
+    */
+    int set_time(const struct tm *rtc_ctime);
+
+    /**
+    * @brief		Set an alarm condition
+    *
+    * @param[in]	alarm_no Alarm number, ALARM1 or ALARM2
+    * @param[in]	alarm_time Pointer to alarm time to be set
+    * @param[in]	period Alarm periodicity, one of ALARM_PERIOD_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int set_alarm(alarm_no_t alarm_no, const struct tm *alarm_time, alarm_period_t period);
+
+    /**
+    * @brief		Get alarm data & time
+    *
+    * @param[in]	alarm_no Alarm number, ALARM1 or ALARM2
+    * @param[out]	alarm_time Pointer to alarm time to be filled in
+    * @param[out]	period Pointer to the period of alarm, one of ALARM_PERIOD_*
+    * @param[out]	is_enabled Pointer to the state of alarm
+    *
+    * @return		0 on success, error code on failure
+    */
+    int get_alarm(alarm_no_t alarm_no, struct tm *alarm_time, alarm_period_t *period, bool *is_enabled);
+
+    /**
+    * @brief		Set power fail threshold voltage
+    *
+    * @param[in]	th Set Analog Comparator Threshold level, one of COMP_THRESH_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int powerfail_threshold_level(comp_thresh_t th);
+
+    /**
+    * @brief		Select device power source
+    *
+    * @param[in]	supply Supply selection, one of POW_MGMT_SUPPLY_SEL_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int supply_select(power_mgmt_supply_t supply);
+
+    /**
+    * @brief		Configure trickle charger charging path, also enable it
+    *
+    * @param[in]	path Value of resister + diodes
+    *
+    * @return		0 on success, error code on failure
+    */
+    int trickle_charger_enable(trickle_charger_path_t path);
+
+    /**
+    * @brief		Disable trickle charger
+    *
+    * @return		0 on success, error code on failure
+    */
+    int trickle_charger_disable();
+
+    /**
+    * @brief		Select square wave output frequency selection
+    *
+    * @param[in]	freq Clock frequency, one of SQUARE_WAVE_OUT_FREQ_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int set_output_square_wave_frequency(square_wave_out_freq_t freq);
+
+    /**
+    * @brief		Enable CLKO
+    *
+    * @param[in]	freq Clock frequency, one of CLKO_FREQ_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int clko_enable(clko_freq_t freq);
+
+    /**
+    * @brief		Disable CLKO
+    *
+    * @return		0 on success, error code on failure
+    */
+    int clko_disable();
+
+    /**
+    * @brief		Initialize timer
+    *
+    * @param[in]	value Timer initial value
+    * @param[in]	repeat Timer repeat mode enable/disable
+    * @param[in]	freq Timer frequency, one of TIMER_FREQ_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int timer_init(uint8_t value, bool repeat, timer_freq_t freq);
+
+    /**
+    * @brief	Read timer value
+    *
+    * @return	0 on success, error code on failure
+    */
+    uint8_t timer_get();
+
+    /**
+    * @brief	Enable timer
+    *
+    * @return	0 on success, error code on failure
+    */
+    int timer_start();
+
+    /**
+    * @brief	Pause timer, timer value is preserved
+    *
+    * @return	0 on success, error code on failure
+    */
+    int timer_pause();
+
+    /**
+    * @brief	Start timer from the paused value
+    *
+    * @return	0 on success, error code on failure
+    */
+    int timer_continue();
+
+    /**
+    * @brief	Disable timer
+    *
+    * @return	0 on success, error code on failure
+    */
+    int timer_stop();
+
+    /**
+    * @brief	Put device into data retention mode
+    *
+    * @return	0 on success, error code on failure
+    */
+    int data_retention_mode_enter();
+
+    /**
+    * @brief	Remove device from data retention mode
+    *
+    * @return	0 on success, error code on failure
+    */
+    int data_retention_mode_exit();
+
+    /**
+    * @brief	Enable I2C bus timeout mechanism
+    *
+    * @return	0 on success, error code on failure
+    */
+    int i2c_timeout_enable();
+
+    /**
+    * @brief	Disable I2C bus timeout mechanism
+    *
+    * @return	0 on success, error code on failure
+    */
+    int i2c_timeout_disable();
+
+    /**
+    * @brief		Read Temperature
+    *
+    * @param[out]	temp temperature value
+    *
+    * @return		0 on success, error code on failure
+    */
+    int read_temp(float *temp);
+
+    /**
+    * @brief		Configure temperature sensor
+    *
+    * @param[in]	automode temperature value
+    * @param[in]	interval temperature read interval for automode, one of
+    * 				TTS_INTERNAL_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int temp_sensor_config(bool automode, ttsint_t interval = TTS_INTERNAL_1SEC);
+
+    /**
+    * @brief		Enable interrupt
+    *
+    * @param[in]	id Interrupt id, one of INTR_ID_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int irq_enable(intr_id_t id);
+
+    /**
+    * @brief		Disable interrupt
+    *
+    * @param[in]	id Interrupt id, one of INTR_ID_*
+    *
+    * @return		0 on success, error code on failure
+    */
+    int irq_disable(intr_id_t id);
+
+    /**
+    * @brief	Disable all interrupts
+    *
+    * @return	0 on success, error code on failure
+    */
+    int irq_disable_all();
+
+    /**
+    * @brief		Set interrupt handler for a specific interrupt id
+    *
+    * @param[in]	id Interrupt id, one of INTR_ID_*
+    * @param[in]	func Interrupt handler function
+    * @param[in]	cb Interrupt handler data
+    */
+    void set_intr_handler(intr_id_t id, interrupt_handler_function func, void *cb);
+
+    /**
+    * @brief	Put device into reset state
+    *
+    * @return 	0 on success, error code on failure
+    */
+    int sw_reset_assert();
+
+    /**
+    * @brief	Release device from reset state
+    *
+    * @return	0 on success, error code on failure
+    */
+    int sw_reset_release();
+
+    /**
+    * @brief	Enable the RTC oscillator
+    *
+    * @return	0 on success, error code on failure
+    */
+    int rtc_start();
+
+    /**
+    * @brief	Disable the RTC oscillator
+    *
+    * @return	0 on success, error code on failure
+    */
+    int rtc_stop();
+
+    /**
+    * @brief	Base class destructor.
+    */
+    ~Max31343();
+
+protected:
+    typedef struct {
+        uint8_t config_reg1;
+        uint8_t config_reg2;
+        uint8_t int_ploarity_config;
+        uint8_t timer_config;
+        uint8_t int_en_reg;
+        uint8_t int_status_reg;
+        uint8_t seconds;
+        uint8_t minutes;
+        uint8_t hours;
+        uint8_t day;
+        uint8_t date;
+        uint8_t month;
+        uint8_t year;
+        uint8_t alm1_sec;
+        uint8_t alm1_min;
+        uint8_t alm1_hrs;
+        uint8_t alm1day_date;
+        uint8_t alm1_mon;
+        uint8_t alm1_year;
+        uint8_t alm2_min;
+        uint8_t alm2_hrs;
+        uint8_t alm2day_date;
+        uint8_t timer_count;
+        uint8_t timer_init;
+        uint8_t ram_start;
+        uint8_t ram_end;
+        uint8_t pwr_mgmt_reg;
+        uint8_t trickle_reg;
+        uint8_t clock_sync_delay;
+        uint8_t temp_msb;
+        uint8_t temp_lsb;
+        uint8_t ts_config;
+    } regmap_t;
+
+    typedef struct {
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char seconds : 4;	/**< RTC seconds value. */
+                unsigned char sec_10  : 3;	/**< RTC seconds in multiples of 10 */
+                unsigned char         : 1;
+            } bits;
+            struct {
+                unsigned char value   : 7;
+                unsigned char         : 1;
+            } bcd;
+        } seconds;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char minutes : 4;	/**< RTC minutes value */
+                unsigned char min_10  : 3;	/**< RTC minutes in multiples of 10 */
+                unsigned char         : 1;
+            } bits;
+            struct {
+                unsigned char value   : 7;
+                unsigned char         : 1;
+            } bcd;
+        } minutes;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char hour       : 4;	/**< RTC hours value */
+                unsigned char hr_10      : 2;	/**< RTC hours in multiples of 10 */
+                unsigned char            : 2;
+            } bits;
+            struct {
+                unsigned char value      : 6;
+                unsigned char            : 2;
+            } bcd;
+        } hours;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char day : 3;	/**< RTC days */
+                unsigned char     : 5;
+            } bits;
+            struct {
+                unsigned char value : 3;
+                unsigned char       : 5;
+            } bcd;
+        } day;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char date    : 4;	/**< RTC date */
+                unsigned char date_10 : 2;	/**< RTC date in multiples of 10 */
+                unsigned char         : 2;
+            } bits;
+            struct {
+                unsigned char value   : 6;
+                unsigned char         : 2;
+            } bcd;
+        } date;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char month    : 4;	/**< RTC months */
+                unsigned char month_10 : 1;	/**< RTC month in multiples of 10 */
+                unsigned char          : 2;
+                unsigned char century  : 1;	/**< Century bit */
+            } bits;
+            struct {
+                unsigned char value   : 5;
+                unsigned char         : 3;
+            } bcd;
+        } month;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char year    : 4;	/**< RTC years */
+                unsigned char year_10 : 4;	/**< RTC year multiples of 10 */
+            } bits;
+            struct {
+                unsigned char value   : 8;
+            } bcd;
+        } year;
+    } rtc_time_regs_t;
+
+    typedef struct {
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char seconds : 4;	/**< Alarm1 seconds */
+                unsigned char sec_10  : 3;	/**< Alarm1 seconds in multiples of 10 */
+                unsigned char a1m1    : 1;	/**< Alarm1 mask bit for minutes */
+            } bits;
+            struct {
+                unsigned char value   : 7;
+                unsigned char         : 1;
+            } bcd;
+        } sec;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char minutes : 4;	/**< Alarm1 minutes */
+                unsigned char min_10  : 3;	/**< Alarm1 minutes in multiples of 10 */
+                unsigned char a1m2    : 1;	/**< Alarm1 mask bit for minutes */
+            } bits;
+            struct {
+                unsigned char value   : 7;
+                unsigned char         : 1;
+            } bcd;
+        } min;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char hour       : 4;	/**< Alarm1 hours */
+                unsigned char hr_10      : 2;	/**< Alarm1 hours in multiples of 10 */
+                unsigned char            : 1;
+                unsigned char a1m3       : 1;	/**< Alarm1 mask bit for hours */
+            } bits;
+            struct {
+                unsigned char value      : 6;
+                unsigned char            : 2;
+            } bcd;
+        } hrs;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char day_date : 4;	/**< Alarm1 day/date */
+                unsigned char date_10  : 2;	/**< Alarm1 date in multiples of 10 */
+                unsigned char dy_dt    : 1;
+                unsigned char a1m4     : 1;	/**< Alarm1 mask bit for day/date */
+            } bits;
+            struct {
+                unsigned char value   : 3;
+                unsigned char         : 5;
+            } bcd_day;
+            struct {
+                unsigned char value   : 6;
+                unsigned char         : 2;
+            } bcd_date;
+        } day_date;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char month    : 4;	/**< Alarm1 months */
+                unsigned char month_10 : 1;	/**< Alarm1 months in multiples of 10 */
+                unsigned char          : 1;
+                unsigned char a1m6     : 1;	/**< Alarm1 mask bit for year */
+                unsigned char a1m5     : 1;	/**< Alarm1 mask bit for month */
+            } bits;
+            struct {
+                unsigned char value   : 5;
+                unsigned char         : 3;
+            } bcd;
+        } mon;
+
+        union {
+            unsigned char raw;
+            struct {
+                unsigned char year    : 4;	/* Alarm1 years */
+                unsigned char year_10 : 4;	/* Alarm1 multiples of 10 */
+            } bits;
+            struct {
+                unsigned char value   : 8;
+            } bcd;
+        } year;
+    } alarm_regs_t;
+
+    typedef union {
+        unsigned char raw;
+        struct {
+            unsigned char swrst       : 1;	/**< Active high software reset bit */
+            unsigned char             : 7;
+        } bits;
+    } rtc_reset_reg_t;
+
+    typedef union {
+        unsigned char raw;
+        struct {
+            unsigned char             : 1;	/**< Reserved has to be set to 0. */
+            unsigned char enosc       : 1;	/**< Oscillator is on when set to 0. Oscillator is off when set to 1. */
+            unsigned char             : 1;
+            unsigned char i2c_timeout : 1;	/**< I2C timeout Enable */
+            unsigned char data_reten  : 1;	/**< Sets the circuit into data retention mode. */
+            unsigned char             : 3;
+        } bits;
+    } config_reg1_t;
+
+    typedef union {
+        unsigned char raw;
+        struct {
+            unsigned char sqw_hz  : 3;	/**< When INTCN=0, set output clock on SQW to specified frequency */
+            unsigned char clko_hz : 4;	/**< Specify uncompensated clock frequency output on pin CLKO. */
+            unsigned char enclko  : 1;	/**< CLKO enable */
+        } bits;
+    } config_reg2_t;
+
+    typedef union {
+        unsigned char raw;
+        struct {
+            unsigned char tfs    : 2;	/**< Timer frequency selection */
+            unsigned char trpt   : 1;	/**< Timer repeat mode. Controls the timer interrupt function along with TM. */
+            unsigned char tpause : 1;	/**< Timer Pause.*/
+            unsigned char te     : 1;	/**< Timer enable */
+            unsigned char        : 3;
+        } bits;
+    } timer_config_t;
+
+    typedef union {
+        unsigned char raw;
+        struct {
+            unsigned char             : 2;
+            unsigned char d_man_sel   : 1;	/**< Default low. When this bit is low, input control block decides which
+            supply to use. When this bit is high, user can manually select
+            whether to use V<sub>CC</sub> or VBACKUP as supply. */
+            unsigned char d_vback_sel : 1;	/**< Default low. When this bit is low, and
+            D_MANUAL_SEL is high, V<sub>CC</sub> is switched to supply. When this bit is high, and
+            D_MANUAL_SEL is high, V<sub>BACKUP</sub> is switched to supply. */
+            unsigned char pfvt        : 2;	/**< Power fail threshold voltage. Sets analog comparator threshold voltage.
+            Require D_MAN_SEL='0' for this setting to have effect. */
+            unsigned char             : 2;
+        } bits;
+    } pwr_mgmt_reg_t;
+
+    typedef union {
+        unsigned char raw;
+        struct {
+            unsigned char sync_delay : 2; /* Sync delay to take for the internal countdown chain to reset
+            after the rising edge of Set_RTC */
+            unsigned char            : 6;
+        } bits;
+    } clock_sync_reg_t;
+
+    typedef union {
+        unsigned char raw;
+        struct {
+            unsigned char             : 3;
+            unsigned char ttint       : 3;	/**< Set temp measurement interval to specified time for auto mode */
+            unsigned char oneshotmode : 1;	/**< One-shot user requested temp measurement in real-time.
+            AUTOMODE must be 0 in one-shot measurement mode. */
+            unsigned char automode    : 1;	/**< Automatic mode of temperature measurement.
+            This mode is valid only when ONESHOTMODE=0. */
+        } bits;
+    } ts_config_t;
+
+private:
+    /* PRIVATE TYPE DECLARATIONS */
+
+    /* PRIVATE VARIABLE DECLARATIONS */
+    I2C *i2c_handler;
+    InterruptIn *pin_int;
+
+    /* PRIVATE CONSTANT VARIABLE DECLARATIONS */
+    static const uint8_t I2C_WRITE = 0;
+    static const uint8_t I2C_READ = 1;
+    static const uint8_t MAX3134X_I2C_ADDRESS = 0x68;
+    static const uint8_t MAX3134X_I2C_W = ((MAX3134X_I2C_ADDRESS << 1) | I2C_WRITE);
+    static const uint8_t MAX3134X_I2C_R = ((MAX3134X_I2C_ADDRESS << 1) | I2C_READ);
+
+    enum config_reg2_set_rtc {
+        CONFIG_REG2_SET_RTC_RTCRUN = 0,	/**< Setting this bit to zero doesn't allow to write into the RTC */
+        CONFIG_REG2_SET_RTC_RTCPRGM,	/**< This bit must be set to one, before writing into the RTC.
+        i.e to set the initial time for the RTC this bit must be high. */
+    };
+
+    /* PRIVATE FUNCTION DECLARATIONS */
+    void interrupt_handler();
+
+    void (Max31343::*funcptr)(void);
+
+    void post_interrupt_work();
+
+    Thread *post_intr_work_thread;
+
+    struct handler {
+        void (*func)(void *);
+        void *cb;
+    };
+
+    handler interrupt_handler_list[INTR_ID_END];
+
+    int rtc_regs_to_time(struct tm *time, const rtc_time_regs_t *regs);
+
+    int time_to_rtc_regs(rtc_time_regs_t *regs, const struct tm *time);
+
+    int set_alarm_regs(alarm_no_t alarm_no, const alarm_regs_t *regs);
+
+    int get_alarm_regs(alarm_no_t alarm_no, alarm_regs_t *regs);
+
+    int time_to_alarm_regs(alarm_regs_t &regs, const struct tm *alarm_time);
+
+    int alarm_regs_to_time(struct tm *alarm_time, const alarm_regs_t *regs);
+
+    int set_alarm_period(alarm_no_t alarm_no, alarm_regs_t &regs, alarm_period_t period);
+
+    int set_rtc_time();
+
+    int data_retention_mode_config(int state);
+
+    int i2c_timeout_config(int enable);
+};
+
+#endif /* Max31343_H_ */