RTC library for Max31341/2 devices
Fork of max3134x by
Revision 0:1efa49a69ff8, committed 2019-04-10
- Comitter:
- Mahir Ozturk
- Date:
- Wed Apr 10 17:28:15 2019 +0300
- Commit message:
- Initial commit
Changed in this revision
diff -r 000000000000 -r 1efa49a69ff8 Max31341.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Max31341.cpp Wed Apr 10 17:28:15 2019 +0300 @@ -0,0 +1,68 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All rights Reserved. +* +* This software is protected by copyright laws of the United States and +* of foreign countries. This material may also be protected by patent laws +* and technology transfer regulations of the United States and of foreign +* countries. This software is furnished under a license agreement and/or a +* nondisclosure agreement and may only be used or reproduced in accordance +* with the terms of those agreements. Dissemination of this information to +* any party or parties not specified in the license agreement and/or +* nondisclosure agreement is expressly prohibited. +* +* 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 "Max31341.h" + +const RtcBase::regmap_t Max31341::regmap = { + /*.config_reg1 = */MAX31341_REG_CONFIG_REG1_ADDR, + /*.config_reg2 = */MAX31341_REG_CONFIG_REG2_ADDR, + /*.int_ploarity_config = */MAX31341_REG_INT_POLARITY_CONFIG_ADDR, + /*.timer_config = */MAX31341_REG_TIMER_CONFIG_ADDR, + /*.int_en_reg = */MAX31341_REG_INT_EN_REG_ADDR, + /*.int_status_reg = */MAX31341_REG_INT_STATUS_REG_ADDR, + /*.seconds = */MAX31341_REG_SECONDS_ADDR, + /*.minutes = */MAX31341_REG_MINUTES_ADDR, + /*.hours = */MAX31341_REG_HOURS_ADDR, + /*.day = */MAX31341_REG_DAY_ADDR, + /*.date = */MAX31341_REG_DATE_ADDR, + /*.month = */MAX31341_REG_MONTH_ADDR, + /*.year = */MAX31341_REG_YEAR_ADDR, + /*.alm1_sec = */MAX31341_REG_ALM1_SEC_ADDR, + /*.alm1_min = */MAX31341_REG_ALM1_MIN_ADDR, + /*.alm1_hrs = */MAX31341_REG_ALM1_HRS_ADDR, + /*.alm1day_date = */MAX31341_REG_ALM1DAY_DATE_ADDR, + /*.alm1_mon = */RtcBase::REG_NOT_AVAILABLE, + /*.alm1_year = */RtcBase::REG_NOT_AVAILABLE, + /*.alm2_min = */MAX31341_REG_ALM2_MIN_ADDR, + /*.alm2_hrs = */MAX31341_REG_ALM2_HRS_ADDR, + /*.alm2day_date = */MAX31341_REG_ALM2DAY_DATE_ADDR, + /*.timer_count = */MAX31341_REG_TIMER_COUNT_ADDR, + /*.timer_init = */MAX31341_REG_TIMER_INIT_ADDR, + /*.ram_start = */MAX31341_REG_RAM_START_ADDR, + /*.ram_end = */MAX31341_REG_RAM_END_ADDR, + /*.pwr_mgmt_reg = */MAX31341_REG_PWR_MGMT_REG_ADDR, + /*.trickle_reg = */MAX31341_REG_TRICKLE_REG_ADDR, + /*.clock_sync_delay = */MAX31341_REG_CLOCK_SYNC_REG, +}; +
diff -r 000000000000 -r 1efa49a69ff8 Max31341.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Max31341.h Wed Apr 10 17:28:15 2019 +0300 @@ -0,0 +1,48 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All rights Reserved. +* +* This software is protected by copyright laws of the United States and +* of foreign countries. This material may also be protected by patent laws +* and technology transfer regulations of the United States and of foreign +* countries. This software is furnished under a license agreement and/or a +* nondisclosure agreement and may only be used or reproduced in accordance +* with the terms of those agreements. Dissemination of this information to +* any party or parties not specified in the license agreement and/or +* nondisclosure agreement is expressly prohibited. +* +* 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 "RtcBase.h" +#include "Max31341_regs.h" + +#ifndef MAX31341_H_ +#define MAX31341_H_ + +class Max31341 : public RtcBase { +public: + Max31341(I2C *i2c, PinName inta_pin = NC, PinName intb_pin = NC) : RtcBase(®map, i2c, inta_pin, intb_pin) {} +private: + static const regmap_t regmap; +}; + +#endif /* MAX31341_H_ */
diff -r 000000000000 -r 1efa49a69ff8 Max31341_regs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Max31341_regs.h Wed Apr 10 17:28:15 2019 +0300 @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (C) 2018 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 MAX31341_REGS_H_ +#define MAX31341_REGS_H_ + +enum max31341_register_address { + MAX31341_REG_CONFIG_REG1_ADDR = 0x00, + MAX31341_REG_CONFIG_REG2_ADDR = 0x01, + MAX31341_REG_INT_POLARITY_CONFIG_ADDR = 0x02, + MAX31341_REG_TIMER_CONFIG_ADDR = 0x03, + MAX31341_REG_INT_EN_REG_ADDR = 0x04, + MAX31341_REG_INT_STATUS_REG_ADDR = 0x05, + MAX31341_REG_SECONDS_ADDR = 0x06, + MAX31341_REG_MINUTES_ADDR = 0x07, + MAX31341_REG_HOURS_ADDR = 0x08, + MAX31341_REG_DAY_ADDR = 0x09, + MAX31341_REG_DATE_ADDR = 0x0A, + MAX31341_REG_MONTH_ADDR = 0x0B, + MAX31341_REG_YEAR_ADDR = 0x0C, + MAX31341_REG_ALM1_SEC_ADDR = 0x0D, + MAX31341_REG_ALM1_MIN_ADDR = 0x0E, + MAX31341_REG_ALM1_HRS_ADDR = 0x0F, + MAX31341_REG_ALM1DAY_DATE_ADDR = 0x10, + MAX31341_REG_ALM2_MIN_ADDR = 0x11, + MAX31341_REG_ALM2_HRS_ADDR = 0x12, + MAX31341_REG_ALM2DAY_DATE_ADDR = 0x13, + MAX31341_REG_TIMER_COUNT_ADDR = 0x14, + MAX31341_REG_TIMER_INIT_ADDR = 0x15, + MAX31341_REG_RAM_START_ADDR = 0x16, + MAX31341_REG_RAM_END_ADDR = 0x55, + MAX31341_REG_PWR_MGMT_REG_ADDR = 0x56, + MAX31341_REG_TRICKLE_REG_ADDR = 0x57, + MAX31341_REG_CLOCK_SYNC_REG = 0x58, + MAX31341_REG_END, +}; + +#endif /* MAX31341_REGS_H_ */
diff -r 000000000000 -r 1efa49a69ff8 Max31342.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Max31342.cpp Wed Apr 10 17:28:15 2019 +0300 @@ -0,0 +1,68 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All rights Reserved. +* +* This software is protected by copyright laws of the United States and +* of foreign countries. This material may also be protected by patent laws +* and technology transfer regulations of the United States and of foreign +* countries. This software is furnished under a license agreement and/or a +* nondisclosure agreement and may only be used or reproduced in accordance +* with the terms of those agreements. Dissemination of this information to +* any party or parties not specified in the license agreement and/or +* nondisclosure agreement is expressly prohibited. +* +* 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 "Max31342.h" + +const RtcBase::regmap_t Max31342::regmap = { + /*.config_reg1 = */MAX31342_REG_CONFIG_REG1_ADDR, + /*.config_reg2 = */MAX31342_REG_CONFIG_REG2_ADDR, + /*.int_ploarity_config = */RtcBase::REG_NOT_AVAILABLE, + /*.timer_config = */MAX31342_REG_TIMER_CONFIG_ADDR, + /*.int_en_reg = */MAX31342_REG_INT_EN_REG_ADDR, + /*.int_status_reg = */MAX31342_REG_INT_STATUS_REG_ADDR, + /*.seconds = */MAX31342_REG_SECONDS_ADDR, + /*.minutes = */MAX31342_REG_MINUTES_ADDR, + /*.hours = */MAX31342_REG_HOURS_ADDR, + /*.day = */MAX31342_REG_DAY_ADDR, + /*.date = */MAX31342_REG_DATE_ADDR, + /*.month = */MAX31342_REG_MONTH_ADDR, + /*.year = */MAX31342_REG_YEAR_ADDR, + /*.alm1_sec = */MAX31342_REG_ALM1_SEC_ADDR, + /*.alm1_min = */MAX31342_REG_ALM1_MIN_ADDR, + /*.alm1_hrs = */MAX31342_REG_ALM1_HRS_ADDR, + /*.alm1day_date = */MAX31342_REG_ALM1DAY_DATE_ADDR, + /*.alm1_mon = */MAX31342_REG_ALM1_MON_ADDR, + /*.alm1_year = */MAX31342_REG_ALM1_YEAR_ADDR, + /*.alm2_min = */MAX31342_REG_ALM2_MIN_ADDR, + /*.alm2_hrs = */MAX31342_REG_ALM2_HRS_ADDR, + /*.alm2day_date = */MAX31342_REG_ALM2DAY_DATE_ADDR, + /*.timer_count = */MAX31342_REG_TIMER_COUNT_ADDR, + /*.timer_init = */MAX31342_REG_TIMER_INIT_ADDR, + /*.ram_start = */RtcBase::REG_NOT_AVAILABLE, + /*.ram_end = */RtcBase::REG_NOT_AVAILABLE, + /*.pwr_mgmt_reg = */RtcBase::REG_NOT_AVAILABLE, + /*.trickle_reg = */RtcBase::REG_NOT_AVAILABLE, + /*.clock_sync_delay = */MAX31342_REG_CLOCK_SYNC_REG, +}; +
diff -r 000000000000 -r 1efa49a69ff8 Max31342.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Max31342.h Wed Apr 10 17:28:15 2019 +0300 @@ -0,0 +1,48 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All rights Reserved. +* +* This software is protected by copyright laws of the United States and +* of foreign countries. This material may also be protected by patent laws +* and technology transfer regulations of the United States and of foreign +* countries. This software is furnished under a license agreement and/or a +* nondisclosure agreement and may only be used or reproduced in accordance +* with the terms of those agreements. Dissemination of this information to +* any party or parties not specified in the license agreement and/or +* nondisclosure agreement is expressly prohibited. +* +* 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 "RtcBase.h" +#include "Max31342_regs.h" + +#ifndef MAX31342_H_ +#define MAX31342_H_ + +class Max31342 : public RtcBase { +public: + Max31342(I2C *i2c, PinName inta_pin = NC, PinName intb_pin = NC) : RtcBase(®map, i2c, inta_pin, intb_pin) {} +private: + static const regmap_t regmap; +}; + +#endif /* MAX31342_H_ */
diff -r 000000000000 -r 1efa49a69ff8 Max31342_regs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Max31342_regs.h Wed Apr 10 17:28:15 2019 +0300 @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (C) 2018 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 MAX31342_REGS_H_ +#define MAX31342_REGS_H_ + +enum max31342_register_address { + MAX31342_REG_CONFIG_REG1_ADDR = 0x00, + MAX31342_REG_CONFIG_REG2_ADDR = 0x01, + MAX31342_REG_SLEEP_CONFIG_ADDR = 0x02, + MAX31342_REG_TIMER_CONFIG_ADDR = 0x03, + MAX31342_REG_INT_EN_REG_ADDR = 0x04, + MAX31342_REG_INT_STATUS_REG_ADDR = 0x05, + MAX31342_REG_SECONDS_ADDR = 0x06, + MAX31342_REG_MINUTES_ADDR = 0x07, + MAX31342_REG_HOURS_ADDR = 0x08, + MAX31342_REG_DAY_ADDR = 0x09, + MAX31342_REG_DATE_ADDR = 0x0A, + MAX31342_REG_MONTH_ADDR = 0x0B, + MAX31342_REG_YEAR_ADDR = 0x0C, + MAX31342_REG_ALM1_SEC_ADDR = 0x0D, + MAX31342_REG_ALM1_MIN_ADDR = 0x0E, + MAX31342_REG_ALM1_HRS_ADDR = 0x0F, + MAX31342_REG_ALM1DAY_DATE_ADDR = 0x10, + MAX31342_REG_ALM1_MON_ADDR = 0x11, + MAX31342_REG_ALM1_YEAR_ADDR = 0x12, + MAX31342_REG_ALM2_MIN_ADDR = 0x13, + MAX31342_REG_ALM2_HRS_ADDR = 0x14, + MAX31342_REG_ALM2DAY_DATE_ADDR = 0x15, + MAX31342_REG_TIMER_COUNT_ADDR = 0x16, + MAX31342_REG_TIMER_INIT_ADDR = 0x17, + MAX31342_REG_CLOCK_SYNC_REG = 0x58, + MAX31342_REG_END, + }; + +#endif /* MAX31342_REGS_H_ */
diff -r 000000000000 -r 1efa49a69ff8 RtcBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RtcBase.cpp Wed Apr 10 17:28:15 2019 +0300 @@ -0,0 +1,1181 @@ +/******************************************************************************* + * Copyright (C) 2018 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 "RtcBase.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 + +RtcBase::RtcBase(const regmap_t *regmap, I2C *i2c, PinName inta_pin = NC, PinName intb_pin = NC) +{ + if (i2c == NULL) { + pr_err("i2c object is invalid!"); + while (1); + } + i2c_handler = i2c; + + this->regmap = regmap; + + sw_reset_release(); + + rtc_start(); + + irq_disable_all(); + + post_intr_work_thread = new Thread(); + + post_intr_work_thread->start(Callback<void()>(this, &RtcBase::post_interrupt_work)); + + if (inta_pin != NC) { + this->inta_pin = new InterruptIn(inta_pin); + + this->inta_pin->fall(Callback<void()>(this, &RtcBase::interrupt_handler)); + + this->inta_pin->enable_irq(); + } else { + this->inta_pin = NULL; + } + + if (intb_pin != NC) { + this->intb_pin = new InterruptIn(intb_pin); + + this->intb_pin->fall(Callback<void()>(this, &RtcBase::interrupt_handler)); + + this->intb_pin->enable_irq(); + } else { + this->intb_pin = NULL; + } +} + +RtcBase::~RtcBase() +{ + if (post_intr_work_thread) { + delete post_intr_work_thread; + } + + if (inta_pin) { + delete inta_pin; + } + + if (intb_pin) { + delete intb_pin; + } +} + +int RtcBase::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 *) ®, 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 RtcBase::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 RtcBase::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 RtcBase::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 RtcBase::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(regmap->seconds, (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 RtcBase::set_rtc_time() +{ + config_reg2_t reg; + + /* Toggle Set_RTC bit to set RTC date */ + + if (read_register(regmap->config_reg2, (uint8_t *)®, 1) < 0) { + pr_err("read time registers failed!"); + return -1; + } + + reg.bits.set_rtc = CONFIG_REG2_SET_RTC_RTCPRGM; + if (write_register(regmap->config_reg2, (uint8_t *)®, 1) < 0) { + pr_err("write config2 register failed!"); + return -1; + } + + /* SET_RTC bit should be kept high at least 10ms */ + ThisThread::sleep_for(10); + + reg.bits.set_rtc = CONFIG_REG2_SET_RTC_RTCRUN; + if (write_register(regmap->config_reg2, (uint8_t *)®, 1) < 0) { + pr_err("write config2 register failed!"); + return -1; + } + + return 0; +} + +int RtcBase::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(regmap->seconds, (const uint8_t *) &time_regs, + sizeof(time_regs)) < 0) { + pr_err("read time registers failed!"); + return -1; + } + + return set_rtc_time(); +} + +int RtcBase::nvram_write(const uint8_t *buffer, int offset, int length) +{ + int totlen; + + if (regmap->ram_start == REG_NOT_AVAILABLE) { + pr_err("Device does not have NVRAM!"); + return -1; + } + + totlen = regmap->ram_end - regmap->ram_start + 1; + + if ((offset + length) > totlen) { + return -1; + } + + if (length == 0) { + return 0; + } + + if (write_register(regmap->ram_start + offset, buffer, length) < 0) { + return -1; + } + + return 0; +} + +int RtcBase::nvram_read(uint8_t *buffer, int offset, int length) +{ + int totlen; + + if (regmap->ram_start == REG_NOT_AVAILABLE) { + pr_err("Device does not have NVRAM!"); + return -1; + } + + totlen = regmap->ram_end - regmap->ram_start + 1; + + if ((offset + length) > totlen) { + return -1; + } + + if (length == 0) { + return -1; + } + + if (read_register(regmap->ram_start + offset, buffer, length) < 0) { + return -1; + } + + return 0; +} + +int RtcBase::nvram_size() +{ + if ((regmap->ram_start == REG_NOT_AVAILABLE) || + (regmap->ram_end == REG_NOT_AVAILABLE)) { + return 0; + } + + return regmap->ram_end - regmap->ram_start + 1; +} + +int RtcBase::time_to_alarm_regs(alarm_regs_t ®s, 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); + + return 0; +} + +int RtcBase::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); + } + + if (regmap->alm1_mon != REG_NOT_AVAILABLE) { + alarm_time->tm_mon = BCD2BIN(regs->mon.bcd.value) - 1; + } + + if (regmap->alm1_year != REG_NOT_AVAILABLE) { + alarm_time->tm_year = BCD2BIN(regs->year.bcd.value) + 100; /* XXX no century bit */ + } + + return 0; +} + +int RtcBase::set_alarm_period(alarm_no_t alarm_no, alarm_regs_t ®s, alarm_period_t period) +{ + 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 = 1; + + switch (period) { + case ALARM_PERIOD_ONETIME: + if ((alarm_no == ALARM2) || (regmap->alm1_year == REG_NOT_AVAILABLE)) { /* not supported! */ + return -1; + } + regs.mon.bits.a1m6 = 0; + case ALARM_PERIOD_YEARLY: + if ((alarm_no == ALARM2) || (regmap->alm1_mon == REG_NOT_AVAILABLE)) { /* not supported! */ + return -1; + } + regs.mon.bits.a1m5 = 0; + case ALARM_PERIOD_MONTHLY: + regs.day_date.bits.dy_dt = 0; + case ALARM_PERIOD_WEEKLY: + regs.day_date.bits.a1m4 = 0; + case ALARM_PERIOD_DAILY: + regs.hrs.bits.a1m3 = 0; + case ALARM_PERIOD_HOURLY: + regs.min.bits.a1m2 = 0; + case ALARM_PERIOD_EVERYMINUTE: + regs.sec.bits.a1m1 = 0; + case ALARM_PERIOD_EVERYSECOND: + if ((alarm_no == ALARM2) && (period == ALARM_PERIOD_EVERYSECOND)) { + return -1; /* Alarm2 does not support "once per second" alarm*/ + } + break; + default: + return -1; + } + + return 0; +} + +int RtcBase::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 = regmap->alm1_sec; + if (regmap->alm1_mon == REG_NOT_AVAILABLE) len -= 2; /* discard mon & year registers */ + } else { + dev_ba = regmap->alm2_min; + off = 1; /* starts from min register */ + len -= 3; /* discard min, mon & sec registers */ + } + + return write_register(dev_ba, &ptr_regs[off], len); +} + +int RtcBase::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 = regmap->alm1_sec; + if (regmap->alm1_mon == REG_NOT_AVAILABLE) len -= 2; /* discard mon & year registers */ + } else { + regs->sec.raw = 0; /* zeroise second register for alarm2 */ + dev_ba = regmap->alm2_min; + off = 1; /* starts from min register (no sec register) */ + len -= 2; /* discard mon & sec registers */ + } + + return read_register(dev_ba, &ptr_regs[off], len); +} + +int RtcBase::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, ®s); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::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, ®s); + if (ret) { + return ret; + } + + /* Convert alarm registers to time structure */ + ret = alarm_regs_to_time(alarm_time, ®s); + if (ret) { + return ret; + } + + *period = (alarm_no == ALARM1) ? ALARM_PERIOD_EVERYSECOND : ALARM_PERIOD_EVERYMINUTE; + + if ((alarm_no == ALARM1) && (regs.sec.bits.a1m1 == 0)) *period = ALARM_PERIOD_EVERYMINUTE; + if (regs.min.bits.a1m2 == 0) *period = ALARM_PERIOD_HOURLY; + if (regs.hrs.bits.a1m3 == 0) *period = ALARM_PERIOD_DAILY; + if (regs.day_date.bits.a1m4 == 0) *period = ALARM_PERIOD_WEEKLY; + if (regs.day_date.bits.dy_dt == 0) *period = ALARM_PERIOD_MONTHLY; + if ((alarm_no == ALARM1) && (regmap->alm1_mon != REG_NOT_AVAILABLE) && (regs.mon.bits.a1m5 == 0)) *period = ALARM_PERIOD_YEARLY; + if ((alarm_no == ALARM1) && (regmap->alm1_mon != REG_NOT_AVAILABLE) && (regs.mon.bits.a1m6 == 0)) *period = ALARM_PERIOD_ONETIME; + + ret = read_register(regmap->int_en_reg, (uint8_t *)®, 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 RtcBase::set_power_mgmt_mode(power_mgmt_mode_t mode) +{ + int ret; + pwr_mgmt_reg_t reg; + + if (regmap->pwr_mgmt_reg == REG_NOT_AVAILABLE) { + pr_err("Device does not support power mgmt!"); + return -1; + } + + ret = read_register(regmap->pwr_mgmt_reg, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.d_mode = mode; + + ret = write_register(regmap->pwr_mgmt_reg, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::comparator_threshold_level(comp_thresh_t th) +{ + int ret; + config_reg2_t reg; + + if (regmap->pwr_mgmt_reg == REG_NOT_AVAILABLE) { + pr_err("Device does not support analog comparator!"); + return -1; + } + + ret = read_register(regmap->config_reg2, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.bref = th; + + ret = write_register(regmap->config_reg2, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::supply_select(power_mgmt_supply_t supply) +{ + int ret; + pwr_mgmt_reg_t reg; + + if (regmap->pwr_mgmt_reg == REG_NOT_AVAILABLE) { + pr_err("Device does not support power mgmt!"); + return -1; + } + + ret = read_register(regmap->pwr_mgmt_reg, (uint8_t *)®, 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_AIN: + 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(regmap->pwr_mgmt_reg, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::trickle_charger_enable(trickle_charger_ohm_t res, bool diode) +{ + int ret; + struct { + unsigned char ohm : 2; + unsigned char diode : 1; + unsigned char schottky : 1; + unsigned char : 4; + } reg; + + if (regmap->trickle_reg == REG_NOT_AVAILABLE) { /* trickle charger not supported! */ + pr_err("Device does not support trickle charger!"); + return -1; + } + + reg.ohm = res; + + reg.diode = (diode) ? 1 : 0; + + reg.schottky = 1; /* always enabled */ + + ret = write_register(regmap->trickle_reg, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::trickle_charger_disable() +{ + int ret; + uint8_t reg; + + if (regmap->trickle_reg == REG_NOT_AVAILABLE) { /* trickle charger not supported! */ + pr_err("Device does not support trickle charger!"); + return -1; + } + + reg = 0; + + ret = write_register(regmap->trickle_reg, ®, 1); + if (ret) { + return ret; + } + + return 0; +} + + +int RtcBase::set_output_square_wave_frequency(square_wave_out_freq_t freq) +{ + int ret; + config_reg1_t reg; + + ret = read_register(regmap->config_reg1, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.rs = freq; + + ret = write_register(regmap->config_reg1, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::set_clock_sync_delay(sync_delay_t delay) +{ + int ret; + clock_sync_reg_t reg; + + ret = read_register(regmap->clock_sync_delay, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.sync_delay = delay; + + ret = write_register(regmap->clock_sync_delay, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::set_clkin_frequency(clkin_freq_t freq) +{ + int ret; + config_reg1_t reg; + + ret = read_register(regmap->config_reg1, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.clksel = freq; + + ret = write_register(regmap->config_reg1, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + if (freq == CLKIN_FREQ_1HZ) { + ret = set_clock_sync_delay(SYNC_DLY_LESS_THAN_1SEC); + } else { + ret = set_clock_sync_delay(SYNC_DLY_LESS_THAN_100MS); + } + + return ret; +} + +int RtcBase::configure_intb_clkout_pin(config_intb_clkout_pin_t sel) +{ + int ret; + config_reg1_t reg; + + ret = read_register(regmap->config_reg1, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.intcn = (sel == CONFIGURE_PIN_AS_INTB) ? 1 : 0; + + ret = write_register(regmap->config_reg1, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::configure_inta_clkin_pin(config_inta_clkin_pin_t sel) +{ + int ret; + config_reg1_t reg; + + ret = read_register(regmap->config_reg1, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.eclk = (sel == CONFIGURE_PIN_AS_CLKIN) ? 1 : 0; + + ret = write_register(regmap->config_reg1, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + if (sel == CONFIGURE_PIN_AS_CLKIN) { + /* Default synchronization delay for external clock mode */ + ret = set_clock_sync_delay(SYNC_DLY_LESS_THAN_1SEC); + } else { + /* Synchronization delay for internal oscillator mode */ + ret = set_clock_sync_delay(SYNC_DLY_LESS_THAN_20MS); + } + + return ret; +} + +int RtcBase::timer_init(uint8_t value, bool repeat, timer_freq_t freq) +{ + int ret; + timer_config_t reg_cfg; + + ret = read_register(regmap->timer_config, (uint8_t *)®_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(regmap->timer_config, (uint8_t *)®_cfg, 1); + if (ret) { + return ret; + } + + ret = write_register(regmap->timer_init, (uint8_t *)&value, 1); + if (ret) { + return ret; + } + + return 0; +} + +uint8_t RtcBase::timer_get() +{ + int ret; + uint8_t reg; + + ret = read_register(regmap->timer_count, (uint8_t *)®, 1); + if (ret) { + return (uint8_t) - 1; + } + + return reg; +} + +int RtcBase::timer_start() +{ + int ret; + timer_config_t reg; + + ret = read_register(regmap->timer_config, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.te = 1; + reg.bits.tpause = 0; + + ret = write_register(regmap->timer_config, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::timer_pause() +{ + int ret; + timer_config_t reg; + + ret = read_register(regmap->timer_config, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.te = 1; + reg.bits.tpause = 1; + + ret = write_register(regmap->timer_config, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::timer_continue() +{ + int ret; + timer_config_t reg; + + ret = read_register(regmap->timer_config, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.te = 1; + reg.bits.tpause = 0; + + ret = write_register(regmap->timer_config, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::timer_stop() +{ + int ret; + timer_config_t reg; + + ret = read_register(regmap->timer_config, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.te = 0; + reg.bits.tpause = 1; + + ret = write_register(regmap->timer_config, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::data_retention_mode_config(int state) +{ + int ret; + config_reg1_t cfg1; + config_reg2_t cfg2; + + ret = read_register(regmap->config_reg1, (uint8_t *)&cfg1, 1); + if (ret) { + return ret; + } + + ret = read_register(regmap->config_reg2, (uint8_t *)&cfg2, 1); + if (ret) { + return ret; + } + + if (state) { + cfg1.bits.osconz = 1; + cfg2.bits.data_reten = 1; + } else { + cfg1.bits.osconz = 0; + cfg2.bits.data_reten = 0; + } + + ret = write_register(regmap->config_reg1, (uint8_t *)&cfg1, 1); + if (ret) { + return ret; + } + + ret = write_register(regmap->config_reg2, (uint8_t *)&cfg2, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::data_retention_mode_enter() +{ + return data_retention_mode_config(1); +} + +int RtcBase::data_retention_mode_exit() +{ + return data_retention_mode_config(0); +} + +int RtcBase::i2c_timeout_config(int enable) +{ + int ret; + config_reg2_t reg; + + ret = read_register(regmap->config_reg2, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + reg.bits.i2c_timeout = (enable) ? 1 : 0; + + ret = write_register(regmap->config_reg2, (uint8_t *)®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::i2c_timeout_enable() +{ + return i2c_timeout_config(1); +} + +int RtcBase::i2c_timeout_disable() +{ + return i2c_timeout_config(0); +} + +int RtcBase::irq_enable(intr_id_t id) +{ + int ret; + uint8_t reg; + + ret = read_register(regmap->int_en_reg, ®, 1); + if (ret) { + return ret; + } + + reg |= (1 << id); + + ret = write_register(regmap->int_en_reg, ®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::irq_disable(intr_id_t id) +{ + int ret; + uint8_t reg; + + ret = read_register(regmap->int_en_reg, ®, 1); + if (ret) { + return ret; + } + + reg &= ~(1 << id); + + ret = write_register(regmap->int_en_reg, ®, 1); + if (ret) { + return ret; + } + + return 0; +} + +int RtcBase::irq_disable_all() +{ + int ret; + uint8_t reg = 0; + + ret = write_register(regmap->int_en_reg, ®, 1); + if (ret) { + return ret; + } + + return 0; +} + +void RtcBase::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 RtcBase::post_interrupt_work() +{ + int ret; + uint8_t reg, inten, mask; + + + while (true) { + Thread::signal_wait(POST_INTR_WORK_SIGNAL_ID); + + ret = read_register(regmap->int_status_reg, ®, 1); + if (ret) { + pr_err("Read interrupt status register failed!"); + } + + ret = read_register(regmap->int_en_reg, &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 RtcBase::interrupt_handler() +{ + post_intr_work_thread->signal_set(POST_INTR_WORK_SIGNAL_ID); +} + +int RtcBase::sw_reset_assert() +{ + int ret; + config_reg1_t config_reg1; + + ret = read_register(regmap->config_reg1, (uint8_t *) &config_reg1, 1); + if (ret < 0) { + pr_err("read_register failed!"); + return ret; + } + + config_reg1.bits.swrstn = 0; /* Put device in reset state */ + + ret = write_register(regmap->config_reg1, (const uint8_t *) &config_reg1, 1); + if (ret < 0) { + pr_err("read_register failed!"); + return ret; + } + + return 0; +} + +int RtcBase::sw_reset_release() +{ + int ret; + config_reg1_t config_reg1; + + ret = read_register(regmap->config_reg1, (uint8_t *) &config_reg1, 1); + if (ret < 0) { + pr_err("read_register failed!"); + return ret; + } + + config_reg1.bits.swrstn = 1; /* Remove device from reset state */ + + ret = write_register(regmap->config_reg1, (const uint8_t *) &config_reg1, 1); + if (ret < 0) { + pr_err("read_register failed!"); + return ret; + } + + return 0; +} + +int RtcBase::rtc_start() +{ + int ret; + config_reg1_t config_reg1; + + ret = read_register(regmap->config_reg1, (uint8_t *) &config_reg1, 1); + if (ret < 0) { + pr_err("read_register failed!"); + return ret; + } + + config_reg1.bits.osconz = 0; /* Enable the oscillator */ + + ret = write_register(regmap->config_reg1, (const uint8_t *) &config_reg1, 1); + if (ret < 0) { + pr_err("read_register failed!"); + return ret; + } + + return 0; +} + +int RtcBase::rtc_stop() +{ + int ret; + config_reg1_t config_reg1; + + ret = read_register(regmap->config_reg1, (uint8_t *) &config_reg1, 1); + if (ret < 0) { + pr_err("read_register failed!"); + return ret; + } + + config_reg1.bits.osconz = 1; /* Disable the oscillator */ + + ret = write_register(regmap->config_reg1, (const uint8_t *) &config_reg1, 1); + if (ret < 0) { + pr_err("read_register failed!"); + return ret; + } + + return 0; +}
diff -r 000000000000 -r 1efa49a69ff8 RtcBase.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RtcBase.h Wed Apr 10 17:28:15 2019 +0300 @@ -0,0 +1,866 @@ +/******************************************************************************* + * Copyright (C) 2018 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 RTCBASE_H_ +#define RTCBASE_H_ + +#include "mbed.h" +#include <ctime> + + +/** + * @brief RTC base driver class for Maxim Max3134x RTC series. + */ +class RtcBase +{ +public: + /** + * @brief Mode of the comparator + */ + typedef enum { + POW_MGMT_MODE_COMPARATOR, /**< Comparator */ + POW_MGMT_MODE_POWER_MANAGEMENT, /**< Power Management / Trickle Charger Mode */ + } power_mgmt_mode_t; + + /** + * @brief Analog comparator threshold voltage + */ + typedef enum { + COMP_THRESH_1V4, /**< 1.4V */ + COMP_THRESH_1V6, /**< 1.6V */ + COMP_THRESH_1V8, /**< 1.8V */ + COMP_THRESH_2V0, /**< 2.0V */ + } 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_AIN, /**< Use AIN as supply */ + } power_mgmt_supply_t; + + /** + * @brief Selection of charging path's resistor value + */ + typedef enum { + TRICKLE_CHARGER_3K5, /**< 3500 Ohm */ + TRICKLE_CHARGER_3K5_2, /**< 3500 Ohm */ + TRICKLE_CHARGER_7K, /**< 7000 Ohm */ + TRICKLE_CHARGER_13K, /**< 13000 Ohm */ + } trickle_charger_ohm_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 CLKIN frequency selection + */ + typedef enum { + CLKIN_FREQ_1HZ, /**< 1Hz*/ + CLKIN_FREQ_50HZ, /**< 50Hz */ + CLKIN_FREQ_60HZ, /**< 60Hz */ + CLKIN_FREQ_32HZ768, /**< 32.768Hz */ + } clkin_freq_t; + + /** + * @brief Square wave output frequency selection on CLKOUT pin + */ + typedef enum { + SQUARE_WAVE_OUT_FREQ_1HZ, /**< 1Hz */ + SQUARE_WAVE_OUT_FREQ_4096HZ, /**< 4.098kHz */ + SQUARE_WAVE_OUT_FREQ_8192HZ, /**< 8.192kHz */ + SQUARE_WAVE_OUT_FREQ_32768HZ, /**< 32.768kHz */ + } square_wave_out_freq_t; + + /** + * @brief Selection of interrupt ids + */ + typedef enum { + INTR_ID_ALARM1, /**< Alarm1 flag */ + INTR_ID_ALARM2, /**< Alarm2 flag */ + INTR_ID_TIMER, /**< Timer interrupt flag */ + INTR_ID_RESERVED, + INTR_ID_EXTERNAL, /**< External interrupt flag for DIN1 */ + INTR_ID_ANALOG, /**< Analog Interrupt flag / Power fail flag */ + INTR_ID_OSF, /**< Oscillator stop flag */ + INTR_ID_LOS, /**< Loss of signal */ + 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 INTA/CLKIN pin function + */ + typedef enum { + CONFIGURE_PIN_AS_INTA, /**< Configure pin as interrupt out */ + CONFIGURE_PIN_AS_CLKIN, /**< Configure pin as external clock in */ + } config_inta_clkin_pin_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 Selection of sync delay + */ + typedef enum { + SYNC_DLY_LESS_THAN_1SEC = 0, /**< Sync delay less than 1 second, recommended for external 1Hz clock */ + SYNC_DLY_LESS_THAN_100MS, /**< Sync delay less than 100 msec, recommended for external 50Hz/60Hz/32KHz clock */ + SYNC_DLY_LESS_THAN_20MS, /**< Sync delay less than 20 msec, recommended for internal clock */ + } sync_delay_t; + + typedef enum { + TTS_INTERNAL_1SEC = 0, + TTS_INTERNAL_2SEC, + TTS_INTERNAL_4SEC, + TTS_INTERNAL_16SEC, + TTS_INTERNAL_32SEC, + TTS_INTERNAL_64SEC, + TTS_INTERNAL_128SEC, + } ttsint_t; + + /** + * @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 Non-volatile memory write + * + * @param[out] buffer Pointer to the data to be written + * @param[in] offset Offset of location in NVRAM + * @param[in] length Number of bytes to write + * + * @return 0 on success, error code on failure + */ + int nvram_write(const uint8_t *buffer, int offset, int length); + + /** + * @brief Non-volatile memory read + * + * @param[in] buffer Buffer to read in to + * @param[in] offset Offset of location in NVRAM + * @param[in] length Number of bytes to read + * + * @return 0 on success, error code on failure + */ + int nvram_read(uint8_t *buffer, int offset, int length); + + /** + * @brief NVRAM size of the part + * + * @return 0 if part does not have a NVRAM, otherwise returns size + */ + int nvram_size(); + + /** + * @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 Select power management mode of operation + * + * @param[in] mode Mode selection, one of COMP_MODE_* + * + * @return 0 on success, error code on failure + */ + int set_power_mgmt_mode(power_mgmt_mode_t mode); + + /** + * @brief Set comparator threshold + * + * @param[in] th Set Analog Comparator Threshold level, one of COMP_THRESH_* + * + * @return 0 on success, error code on failure + */ + int comparator_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] res Value of resister + * @param[in] diode Enable diode + * + * @return 0 on success, error code on failure + */ + int trickle_charger_enable(trickle_charger_ohm_t res, bool diode); + + /** + * @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 CLKOUT_FREQ_* + * + * @return 0 on success, error code on failure + */ + int set_output_square_wave_frequency(square_wave_out_freq_t freq); + + /** + * @brief Select external clock input frequency + * + * @param[in] freq Clock frequency, one of CLKIN_FREQ_* + * + * @return 0 on success, error code on failure + */ + int set_clkin_frequency(clkin_freq_t freq); + + /** + * @brief Select direction of INTB/CLKOUT pin + * + * @param[in] sel Pin function, one of CONFIGURE_PIN_B3_AS_INTB or CONFIGURE_PIN_B3_AS_CLKOUT + * + * @return 0 on success, error code on failure + */ + int configure_intb_clkout_pin(config_intb_clkout_pin_t sel); + + /** + * @brief Select direction of INTA/CLKIN pin + * + * @param[in] sel Pin function, one of CONFIGURE_PIN_B3_AS_INTA or CONFIGURE_PIN_B3_AS_CLKIN + * + * @return 0 on success, error code on failure + */ + int configure_inta_clkin_pin(config_inta_clkin_pin_t sel); + + /** + * @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_* + * @param[in] mode Timer mode, 0 or 1 + * + * @return 0 on success, error code on failure + * + * @note \p mode controls the countdown timer interrupt function + * along with \p repeat. + * Pulse interrupt when \p mode = 0, irrespective of \p repeat (true or false) + * Pulse interrupt when \p mode = 1 and \p repeat = true + * Level interrupt when \p mode = 1 and \p repeat = false + */ + 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 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 state 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. + */ + ~RtcBase(); + +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 swrstn : 1; /**< Software reset */ + unsigned char rs : 2; /**< Square wave output frequency selection on CLKOUT pin */ + unsigned char osconz : 1; /**< Oscillator is on when set to 0. Oscillator is off when set to 1. */ + unsigned char clksel : 2; /**< Selects the CLKIN frequency */ + unsigned char intcn : 1; /**< Interrupt control bit. Selects the direction of INTB/CLKOUT */ + unsigned char eclk : 1; /**< Enable external clock input */ + } bits; + } config_reg1_t; + + typedef union { + unsigned char raw; + struct { + unsigned char : 1; + unsigned char set_rtc : 1; /**< Set RTC */ + unsigned char rd_rtc : 1; /**< Read RTC. */ + unsigned char i2c_timeout : 1; /**< I2C timeout Enable */ + unsigned char bref : 2; /**< BREF sets the analog comparator threshold voltage. */ + unsigned char data_reten : 1; /**< Sets the circuit into data retention mode. */ + unsigned char : 1; + } bits; + } config_reg2_t; + + typedef union { + unsigned char raw; + struct { + unsigned char tfs : 2; /**< Timer frequency selection */ + unsigned char trpt : 1; /**< Timer repeat mode. It controls the timer interrupt function along with TM. */ + unsigned char : 1; + unsigned char te : 1; /**< Timer enable */ + unsigned char tpause : 1; /**< Timer Pause.*/ + unsigned char : 2; + } bits; + } timer_config_t; + + typedef union { + unsigned char raw; + struct { + unsigned char d_mode : 2; /**< Sets the mode of the comparator to one of the two following: comparator mode, and power management mode/trickle charger mode. */ + 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 : 4; + } 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 automode : 1; /**< Automatic mode of temperature measurement. This mode is valid only when ONESHOTMODE=0. */ + unsigned char oneshotmode : 1; /**< One-shot user requested temp measurement in real-time. AUTOMODE must be 0 in one-shot measurement mode. */ + unsigned char ttint : 3; /**< Set temp measurement interval to specified time for auto mode */ + unsigned char : 3; + } bits; + } ts_config_t; + + static const uint8_t REG_NOT_AVAILABLE = 0xFF; + + /** + * @brief Base class constructor. + * + * @param[in] regmap Pointer to device register mappings. + * @param[in] i2c Pointer to I2C bus object for this device. + * @param[in] inta_pin MCU's pin number that device's INTA pin connected + * @param[in] intb_pin MCU's pin number that device's INTB pin connected + */ + RtcBase(const regmap_t *regmap, I2C *i2c, PinName inta_pin, PinName intb_pin); + +private: + /* PRIVATE TYPE DECLARATIONS */ + + /* PRIVATE VARIABLE DECLARATIONS */ + I2C *i2c_handler; + InterruptIn *inta_pin; + InterruptIn *intb_pin; + const regmap_t *regmap; + + /* 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 = 0x69; + 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 (RtcBase::*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 tm_hour_to_rtc_hr12(int hours, bool *is_am); + + int rtc_hr12_to_tm_hour(int hours, bool is_am); + + 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 ®s, 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 ®s, alarm_period_t period); + + int set_rtc_time(); + + int data_retention_mode_config(int state); + + int i2c_timeout_config(int enable); + + int set_clock_sync_delay(sync_delay_t delay); +}; + +#endif /* RTCBASE_H_ */