Driver for MAX31331 and MAX31334 Real Time Clock ICs.
Revision 0:4a2754e462db, committed 2022-08-02
- Comitter:
- Sinan Divarci
- Date:
- Tue Aug 02 18:20:54 2022 +0300
- Commit message:
- Initial Commit
Changed in this revision
diff -r 000000000000 -r 4a2754e462db max3133x.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/max3133x.cpp Tue Aug 02 18:20:54 2022 +0300 @@ -0,0 +1,1406 @@ +/******************************************************************************* + * Copyright(C) Analog Devices 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 Analog Devices Inc. + * shall not be used except as stated in the Analog Devices 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. Analog Devices Inc.retains all ownership rights. + ******************************************************************************* + */ + +#include "max3133x.hpp" +#include <iostream> + +#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 SWAPBYTES(val) (((val & 0xFF) << 8) | ((val & 0xFF00) >> 8)) + +#define POST_INTR_WORK_SIGNAL_ID 0x1 + +MAX3133X::MAX3133X(const reg_addr_t *reg_addr, I2C *i2c, PinName inta_pin, PinName intb_pin) +{ + int ret; + if (i2c == NULL || reg_addr == NULL) { + pr_err("i2c object is invalid!"); + return; + } + + this->reg_addr = reg_addr; + i2c_handler = i2c; + + ret = interrupt_disable(INT_ALL); + if (ret != MAX3133X_NO_ERR) { + pr_err("interrupt_disable failed!"); + return; + } + + for (int i = 0; i < NUM_OF_INTR_ID; i++) { + interrupt_handler_list[i].func = NULL; + interrupt_handler_list[i].cb = NULL; + } + + if (inta_pin != NC) { + this->inta_pin = new InterruptIn(inta_pin); + this->inta_pin->fall(Callback<void()>(this, &MAX3133X::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, &MAX3133X::interrupt_handler)); + this->intb_pin->enable_irq(); + } else + this->intb_pin = NULL; + + if (inta_pin != NC || intb_pin != NC) + { + post_intr_work_thread = new Thread(); + post_intr_work_thread->start(Callback<void()>(this, &MAX3133X::post_interrupt_work)); + } +} + +int MAX3133X::read_register(uint8_t reg, uint8_t *value, uint8_t len) +{ + int rtn_val; + + if (value == NULL) + return MAX3133X_NULL_VALUE_ERR; + + rtn_val = i2c_handler->write(MAX3133X_I2C_W, (const char *)®, 1, true); + if (rtn_val != 0) + return MAX3133X_WRITE_REG_ERR; + + rtn_val = i2c_handler->read(MAX3133X_I2C_R, (char *) value, len, false); + if (rtn_val != 0) + return MAX3133X_READ_REG_ERR; + + return MAX3133X_NO_ERR; +} + +int MAX3133X::write_register(uint8_t reg, const uint8_t *value, uint8_t len) +{ + int rtn_val; + uint8_t *local_data; + + if (value == NULL) + return MAX3133X_NULL_VALUE_ERR; + + local_data = new uint8_t[1 + len]; + local_data[0] = reg; + + memcpy(&local_data[1], value, len); + + rtn_val = i2c_handler->write(MAX3133X_I2C_W, (const char *)local_data, 1 + len); + delete[] local_data; //delete local_data anymore not used + + if (rtn_val != 0) + return MAX3133X_WRITE_REG_ERR; + + return MAX3133X_NO_ERR; +} + +#define SET_BIT_FIELD(address, reg_name, bit_field_name, value) \ +{ int ret; \ + ret = read_register(address, (uint8_t *)&(reg_name), 1); \ + if (ret != MAX3133X_NO_ERR) { \ + return ret; \ + } \ + if (bit_field_name != value) { \ + bit_field_name = value; \ + ret = write_register(address, (uint8_t *)&(reg_name), 1); \ + if (ret != MAX3133X_NO_ERR) { \ + return ret; \ + } \ + } \ +} + +inline void MAX3133X::rtc_regs_to_time(struct tm *time, const max3133x_rtc_time_regs_t *regs, uint16_t *sub_sec) +{ + if (sub_sec != NULL) + *sub_sec = (1000 * regs->seconds_1_128_reg.raw) / 128.0; + + /* tm_sec seconds [0,61] */ + time->tm_sec = BCD2BIN(regs->seconds_reg.bcd.value); + + /* tm_min minutes [0,59] */ + time->tm_min = BCD2BIN(regs->minutes_reg.bcd.value); + + /* tm_hour hour [0,23] */ + hour_format_t format = regs->hours_reg.bits_24hr.f_24_12 == 1 ? HOUR12 : HOUR24; + if (format == HOUR24) + time->tm_hour = BCD2BIN(regs->hours_reg.bcd_24hr.value); + else if (format == HOUR12) { + uint8_t hr24 = to_24hr(BCD2BIN(regs->hours_reg.bcd_12hr.value), regs->hours_reg.bits_12hr.am_pm); + time->tm_hour = hr24; + } + + /* tm_wday day of week [0,6] (Sunday = 0) */ + time->tm_wday = BCD2BIN(regs->day_reg.bcd.value) - 1; + + /* tm_mday day of month [1,31] */ + time->tm_mday = BCD2BIN(regs->date_reg.bcd.value); + + /* tm_mon month of year [0,11] */ + time->tm_mon = BCD2BIN(regs->month_reg.bcd.value) - 1; + + /* tm_year years since 2000 */ + if (regs->month_reg.bits.century) + time->tm_year = BCD2BIN(regs->year_reg.bcd.value) + 200; + else + time->tm_year = BCD2BIN(regs->year_reg.bcd.value) + 100; + + /* tm_yday day of year [0,365] */ + time->tm_yday = 0; + + /* tm_isdst daylight savings flag */ + time->tm_isdst = 0; +} + +inline int MAX3133X::time_to_rtc_regs(max3133x_rtc_time_regs_t *regs, const struct tm *time, hour_format_t format) +{ + /********************************************************* + * +----------+------+---------------------------+-------+ + * | 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_reg.bcd.value = BIN2BCD(time->tm_sec); + + regs->minutes_reg.bcd.value = BIN2BCD(time->tm_min); + + if (format == HOUR24) { + regs->hours_reg.bcd_24hr.value = BIN2BCD(time->tm_hour); + regs->hours_reg.bits_24hr.f_24_12 = HOUR24; + } else if (format == HOUR12) { + uint8_t hr_12, pm; + to_12hr(time->tm_hour, &hr_12, &pm); + regs->hours_reg.bcd_12hr.value = BIN2BCD(hr_12); + regs->hours_reg.bits_12hr.f_24_12 = HOUR12; + regs->hours_reg.bits_12hr.am_pm = pm; + } else { + pr_err("Invalid Hour Format!"); + return MAX3133X_INVALID_TIME_ERR; + } + + regs->day_reg.bcd.value = BIN2BCD(time->tm_wday + 1); + regs->date_reg.bcd.value = BIN2BCD(time->tm_mday); + regs->month_reg.bcd.value = BIN2BCD(time->tm_mon + 1); + + if (time->tm_year >= 200) { + regs->month_reg.bits.century = 1; + regs->year_reg.bcd.value = BIN2BCD(time->tm_year - 200); + } else if (time->tm_year >= 100) { + regs->month_reg.bits.century = 0; + regs->year_reg.bcd.value = BIN2BCD(time->tm_year - 100); + } else { + pr_err("Invalid set date!"); + return MAX3133X_INVALID_DATE_ERR; + } + + return MAX3133X_NO_ERR; +} + +int MAX3133X::get_time(struct tm *time, uint16_t *sub_sec) +{ + int ret; + max3133x_rtc_time_regs_t max3133x_rtc_time_regs = {}; + if (time == NULL) { + pr_err("rtc_ctime is invalid!"); + return MAX3133X_NULL_VALUE_ERR; + } + + ret = read_register(reg_addr->seconds_1_128_reg_addr, (uint8_t *) &max3133x_rtc_time_regs.seconds_1_128_reg, sizeof(max3133x_rtc_time_regs)); + if (ret != MAX3133X_NO_ERR) { + pr_err("read time registers failed!"); + return ret; + } + + rtc_regs_to_time(time, &max3133x_rtc_time_regs, sub_sec); + return MAX3133X_NO_ERR; +} + +int MAX3133X::set_time(const struct tm *time, hour_format_t format) +{ + int ret; + max3133x_rtc_time_regs_t max3133x_rtc_time_regs = {}; + + if (time == NULL) { + pr_err("rtc_ctime is invalid!"); + return MAX3133X_NULL_VALUE_ERR; + } + + ret = time_to_rtc_regs(&max3133x_rtc_time_regs, time, format); + if (ret != MAX3133X_NO_ERR) + return ret; + + ret = write_register(reg_addr->seconds_reg_addr, (uint8_t *)&max3133x_rtc_time_regs.seconds_reg.raw, sizeof(max3133x_rtc_time_regs)-1); + if (ret != MAX3133X_NO_ERR) { + pr_err("write time registers failed!"); + return ret; + } + + return MAX3133X_NO_ERR; +} + +inline void MAX3133X::timestamp_regs_to_time(timestamp_t *timestamp, const max3133x_ts_regs_t *timestamp_reg) +{ + /* tm_sec seconds [0,61] */ + timestamp->ctime.tm_sec = BCD2BIN(timestamp_reg->ts_sec_reg.bcd.value); + + /* tm_min minutes [0,59] */ + timestamp->ctime.tm_min = BCD2BIN(timestamp_reg->ts_min_reg.bcd.value); + + /* tm_hour hour [0,23] */ + hour_format_t format = timestamp_reg->ts_hour_reg.bits_24hr.f_24_12 ? HOUR12 : HOUR24; + if (format == HOUR24) + timestamp->ctime.tm_hour = BCD2BIN(timestamp_reg->ts_hour_reg.bcd_24hr.value); + else if (format == HOUR12) { + uint8_t hr24 = to_24hr(BCD2BIN(timestamp_reg->ts_hour_reg.bcd_12hr.value), timestamp_reg->ts_hour_reg.bits_12hr.am_pm); + timestamp->ctime.tm_hour = hr24; + } + + /* tm_mday day of month [1,31] */ + timestamp->ctime.tm_mday = BCD2BIN(timestamp_reg->ts_date_reg.bcd.value); + + /* tm_mon month of year [0,11] */ + timestamp->ctime.tm_mon = BCD2BIN(timestamp_reg->ts_month_reg.bcd.value) - 1; + + /* tm_year years since 2000 */ + if (timestamp_reg->ts_month_reg.bits.century) + timestamp->ctime.tm_year = BCD2BIN(timestamp_reg->ts_year_reg.bcd.value) + 200; + else + timestamp->ctime.tm_year = BCD2BIN(timestamp_reg->ts_year_reg.bcd.value) + 100; + + /* tm_yday day of year [0,365] */ + timestamp->ctime.tm_yday = 0; /* TODO */ + + /* tm_isdst daylight savings flag */ + timestamp->ctime.tm_isdst = 0; /* TODO */ + + timestamp->sub_sec = (1000 * timestamp_reg->ts_sec_1_128_reg.raw) / 128.0; +} + +int MAX3133X::get_status_reg(max3133x_status_reg_t * status_reg) +{ + return read_register(reg_addr->status_reg_addr, &status_reg->raw, 1); +} + +int MAX3133X::get_interrupt_reg(max3133x_int_en_reg_t * int_en_reg) +{ + return read_register(reg_addr->int_en_reg_addr, &int_en_reg->raw, 1); +} + +int MAX3133X::interrupt_enable(uint8_t mask) +{ + int ret; + max3133x_int_en_reg_t int_en_reg = {}; + + ret = read_register(reg_addr->int_en_reg_addr, &int_en_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + int_en_reg.raw |= mask; + return write_register(reg_addr->int_en_reg_addr, &int_en_reg.raw, 1); +} + +int MAX3133X::interrupt_disable(uint8_t mask) +{ + int ret; + max3133x_int_en_reg_t int_en_reg = {}; + + ret = read_register(reg_addr->int_en_reg_addr, &int_en_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + int_en_reg.raw &= ~mask; + return write_register(reg_addr->int_en_reg_addr, &int_en_reg.raw, 1); +} + +int MAX3133X::sw_reset_assert() +{ + max3133x_rtc_reset_reg_t rtc_reset_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_reset_reg_addr, rtc_reset_reg, rtc_reset_reg.bits.swrst, 1); + return MAX3133X_NO_ERR; +} + +int MAX3133X::sw_reset_release() +{ + max3133x_rtc_reset_reg_t rtc_reset_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_reset_reg_addr, rtc_reset_reg, rtc_reset_reg.bits.swrst, 0); + return MAX3133X_NO_ERR; +} + +int MAX3133X::sw_reset() +{ + int ret; + ret = sw_reset_assert(); + if (ret != MAX3133X_NO_ERR) + return ret; + + ThisThread::sleep_for(5); + return sw_reset_release(); +} + +int MAX31331::rtc_config(rtc_config_t *max31331_config) +{ + int ret; + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + max31331_rtc_config2_reg_t rtc_config2_reg = {}; + + rtc_config1_reg.bits.a1ac = max31331_config->a1ac; + rtc_config1_reg.bits.dip = max31331_config->dip; + rtc_config1_reg.bits.data_ret = max31331_config->data_ret; + rtc_config1_reg.bits.i2c_timeout = max31331_config->i2c_timeout; + rtc_config1_reg.bits.en_osc = max31331_config->en_osc; + + ret = write_register(reg_addr.rtc_config1_reg_addr, &rtc_config1_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + rtc_config2_reg.bits.clko_hz = max31331_config->clko_hz; + rtc_config2_reg.bits.enclko = max31331_config->enclko; + + return write_register(reg_addr.rtc_config2_reg_addr, &rtc_config2_reg.raw, 1); +} + +int MAX31334::rtc_config(rtc_config_t *max31334_config) +{ + int ret; + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + max31334_rtc_config2_reg_t rtc_config2_reg = {}; + + rtc_config1_reg.bits.a1ac = max31334_config->a1ac; + rtc_config1_reg.bits.dip = max31334_config->dip; + rtc_config1_reg.bits.data_ret = max31334_config->data_ret; + rtc_config1_reg.bits.i2c_timeout = max31334_config->i2c_timeout; + rtc_config1_reg.bits.en_osc = max31334_config->en_osc; + + ret = write_register(reg_addr.rtc_config1_reg_addr, &rtc_config1_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + rtc_config2_reg.bits.clko_hz = max31334_config->clko_hz; + rtc_config2_reg.bits.enclko = max31334_config->enclko; + rtc_config2_reg.bits.ddb = max31334_config->ddb; + rtc_config2_reg.bits.dse = max31334_config->dse; + + return write_register(reg_addr.rtc_config2_reg_addr, &rtc_config2_reg.raw, 1); +} + +int MAX31331::get_rtc_config(rtc_config_t *max31331_config) +{ + int ret; + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + max31331_rtc_config2_reg_t rtc_config2_reg = {}; + + ret = read_register(reg_addr.rtc_config1_reg_addr, &rtc_config1_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + max31331_config->a1ac = (a1ac_t)rtc_config1_reg.bits.a1ac; + max31331_config->dip = (dip_t)rtc_config1_reg.bits.dip; + max31331_config->data_ret = (data_ret_t)rtc_config1_reg.bits.data_ret; + max31331_config->i2c_timeout = (i2c_timeout_t)rtc_config1_reg.bits.i2c_timeout; + max31331_config->en_osc = (en_osc_t)rtc_config1_reg.bits.en_osc; + + ret = read_register(reg_addr.rtc_config2_reg_addr, &rtc_config2_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + max31331_config->clko_hz = (clko_hz_t)rtc_config2_reg.bits.clko_hz; + max31331_config->enclko = (enclko_t)rtc_config2_reg.bits.enclko; + return MAX3133X_NO_ERR; +} + +int MAX31334::get_rtc_config(rtc_config_t *max31334_config) +{ + int ret; + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + max31334_rtc_config2_reg_t rtc_config2_reg = {}; + + ret = read_register(reg_addr.rtc_config1_reg_addr, &rtc_config1_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + max31334_config->a1ac = (a1ac_t)rtc_config1_reg.bits.a1ac; + max31334_config->dip = (dip_t)rtc_config1_reg.bits.dip; + max31334_config->data_ret = (data_ret_t)rtc_config1_reg.bits.data_ret; + max31334_config->i2c_timeout = (i2c_timeout_t)rtc_config1_reg.bits.i2c_timeout; + max31334_config->en_osc = (en_osc_t)rtc_config1_reg.bits.en_osc; + + ret = read_register(reg_addr.rtc_config2_reg_addr, &rtc_config2_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + max31334_config->clko_hz = (clko_hz_t)rtc_config2_reg.bits.clko_hz; + max31334_config->ddb = (ddb_t)rtc_config2_reg.bits.ddb; + max31334_config->dse = (dse_t)rtc_config2_reg.bits.dse; + max31334_config->enclko = (enclko_t)rtc_config2_reg.bits.enclko; + + return MAX3133X_NO_ERR; +} + +int MAX3133X::set_alarm1_auto_clear(a1ac_t a1ac) +{ + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_config1_reg_addr, rtc_config1_reg, rtc_config1_reg.bits.a1ac, a1ac); + return MAX3133X_NO_ERR; +} + +int MAX3133X::set_din_polarity(dip_t dip) +{ + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_config1_reg_addr, rtc_config1_reg, rtc_config1_reg.bits.dip, dip); + return MAX3133X_NO_ERR; +} + +int MAX3133X::data_retention_mode_config(bool enable) +{ + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_config1_reg_addr, rtc_config1_reg, rtc_config1_reg.bits.data_ret, enable); + return MAX3133X_NO_ERR; +} + +int MAX3133X::data_retention_mode_enter() +{ + return data_retention_mode_config(1); +} + +int MAX3133X::data_retention_mode_exit() +{ + return data_retention_mode_config(0); +} + +int MAX3133X::i2c_timeout_config(bool enable) +{ + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_config1_reg_addr, rtc_config1_reg, rtc_config1_reg.bits.i2c_timeout, enable); + return MAX3133X_NO_ERR; +} + +int MAX3133X::i2c_timeout_enable() +{ + return i2c_timeout_config(1); +} + +int MAX3133X::i2c_timeout_disable() +{ + return i2c_timeout_config(0); +} + +int MAX3133X::oscillator_config(bool enable) +{ + max3133x_rtc_config1_reg_t rtc_config1_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_config1_reg_addr, rtc_config1_reg, rtc_config1_reg.bits.en_osc, enable); + return MAX3133X_NO_ERR; +} + +int MAX3133X::oscillator_enable() +{ + return oscillator_config(1); +} + +int MAX3133X::oscillator_disable() +{ + return oscillator_config(0); +} + +int MAX31334::get_sleep_state() +{ + int ret; + max31334_rtc_config2_reg_t rtc_config2_reg = {}; + + ret = read_register(reg_addr.rtc_config2_reg_addr, &rtc_config2_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + return rtc_config2_reg.bits.slst; +} + +int MAX31334::din_sleep_entry_config(bool enable) +{ + max31334_rtc_config2_reg_t rtc_config2_reg = {}; + SET_BIT_FIELD(reg_addr.rtc_config2_reg_addr, rtc_config2_reg, rtc_config2_reg.bits.dse, enable); + return MAX3133X_NO_ERR; +} + +int MAX31334::din_sleep_entry_enable() +{ + return din_sleep_entry_config(1); +} + +int MAX31334::din_sleep_entry_disable() +{ + return din_sleep_entry_config(0); +} + +int MAX31334::din_pin_debounce_config(bool enable) +{ + max31334_rtc_config2_reg_t rtc_config2_reg = {}; + SET_BIT_FIELD(reg_addr.rtc_config2_reg_addr, rtc_config2_reg, rtc_config2_reg.bits.ddb, enable); + return MAX3133X_NO_ERR; +} + +int MAX31334::din_pin_debounce_enable() +{ + return din_pin_debounce_config(1); +} + +int MAX31334::din_pin_debounce_disable() +{ + return din_pin_debounce_config(0); +} + +int MAX3133X::clkout_config(bool enable) +{ + max31334_rtc_config2_reg_t rtc_config2_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_config2_reg_addr, rtc_config2_reg, rtc_config2_reg.bits.enclko, enable); + return MAX3133X_NO_ERR; +} + +int MAX3133X::clkout_enable() +{ + return clkout_config(1); +} + +int MAX3133X::clkout_disable() +{ + return clkout_config(0); +} + +int MAX3133X::set_clko_freq(clko_hz_t clko_hz) +{ + max31334_rtc_config2_reg_t rtc_config2_reg = {}; + SET_BIT_FIELD(reg_addr->rtc_config2_reg_addr, rtc_config2_reg, rtc_config2_reg.bits.clko_hz, clko_hz); + return MAX3133X_NO_ERR; +} + +int MAX3133X::get_clko_freq(clko_hz_t *clko_hz) +{ + int ret; + max31334_rtc_config2_reg_t rtc_config2_reg = {}; + + ret = read_register(reg_addr->rtc_config2_reg_addr, &rtc_config2_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + *clko_hz = (clko_hz_t)rtc_config2_reg.bits.clko_hz; + return MAX3133X_NO_ERR; +} + +int MAX3133X::timestamp_function_enable() +{ + max3133x_timestamp_config_reg_t timestamp_config_reg = {}; + SET_BIT_FIELD(reg_addr->timestamp_config_reg_addr, timestamp_config_reg, timestamp_config_reg.bits.tse, 1); + return MAX3133X_NO_ERR; +} + +int MAX3133X::timestamp_function_disable() +{ + max3133x_timestamp_config_reg_t timestamp_config_reg = {}; + SET_BIT_FIELD(reg_addr->timestamp_config_reg_addr, timestamp_config_reg, timestamp_config_reg.bits.tse, 0); + return MAX3133X_NO_ERR; +} + +int MAX3133X::timestamp_registers_reset() +{ + max3133x_timestamp_config_reg_t timestamp_config_reg = {}; + SET_BIT_FIELD(reg_addr->timestamp_config_reg_addr, timestamp_config_reg, timestamp_config_reg.bits.tsr, 1); + return MAX3133X_NO_ERR; +} + +int MAX3133X::timestamp_overwrite_config(bool enable) +{ + max3133x_timestamp_config_reg_t timestamp_config_reg = {}; + SET_BIT_FIELD(reg_addr->timestamp_config_reg_addr, timestamp_config_reg, timestamp_config_reg.bits.tsow, enable); + return MAX3133X_NO_ERR; +} + +int MAX3133X::timestamp_overwrite_enable() +{ + return timestamp_overwrite_config(1); +} + +int MAX3133X::timestamp_overwrite_disable() +{ + return timestamp_overwrite_config(0); +} + +int MAX3133X::timestamp_record_enable(uint8_t record_enable_mask) +{ + int ret; + max3133x_timestamp_config_reg_t timestamp_config_reg = {}; + + if (record_enable_mask > (TSVLOW | TSPWM | TSDIN)) + return MAX3133X_INVALID_MASK_ERR; + + ret = read_register(reg_addr->timestamp_config_reg_addr, ×tamp_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timestamp_config_reg.raw |= record_enable_mask; + return write_register(reg_addr->timestamp_config_reg_addr, ×tamp_config_reg.raw, 1); +} + +int MAX3133X::timestamp_record_disable(uint8_t record_disable_mask) +{ + int ret; + max3133x_timestamp_config_reg_t timestamp_config_reg = {}; + + if (record_disable_mask > (TSVLOW | TSPWM | TSDIN)) + return MAX3133X_INVALID_MASK_ERR; + + ret = read_register(reg_addr->timestamp_config_reg_addr, ×tamp_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timestamp_config_reg.raw &= ~record_disable_mask; + return write_register(reg_addr->timestamp_config_reg_addr, ×tamp_config_reg.raw, 1); +} + +int MAX31331::timer_init(uint8_t timer_init, bool repeat, timer_freq_t freq) +{ + int ret; + max3133x_timer_config_reg_t timer_config_reg = {}; + + ret = read_register(reg_addr.timer_config_reg_addr, &timer_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timer_config_reg.bits.te = 0; /* timer is reset */ + timer_config_reg.bits.tpause = 1; /* timer is paused */ + timer_config_reg.bits.trpt = repeat ? 1 : 0; /* Timer repeat mode */ + timer_config_reg.bits.tfs = freq; /* Timer frequency */ + + ret = write_register(reg_addr.timer_config_reg_addr, &timer_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + return write_register(reg_addr.timer_init_reg_addr, &timer_init, 1); +} + +int MAX31334::timer_init(uint16_t timer_init, bool repeat, timer_freq_t freq) +{ + int ret; + max3133x_timer_config_reg_t timer_config_reg = {}; + + ret = read_register(reg_addr.timer_config_reg_addr, &timer_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timer_config_reg.bits.te = 0; /* timer is reset */ + timer_config_reg.bits.tpause = 1; /* timer is paused */ + timer_config_reg.bits.trpt = repeat ? 1 : 0; /* Timer repeat mode */ + timer_config_reg.bits.tfs = freq; /* Timer frequency */ + + ret = write_register(reg_addr.timer_config_reg_addr, &timer_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timer_init = SWAPBYTES(timer_init); + + return write_register(reg_addr.timer_init2_reg_addr, (uint8_t *)&timer_init, 2); +} + +int MAX31331::timer_get() +{ + int ret; + uint8_t timer_count; + + ret = read_register(reg_addr.timer_count_reg_addr, &timer_count, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + return timer_count; +} + +int MAX31334::timer_get() +{ + int ret; + uint16_t timer_count; + + ret = read_register(reg_addr.timer_count2_reg_addr, (uint8_t *)&timer_count, 2); + if (ret != MAX3133X_NO_ERR) + return ret; + + return SWAPBYTES(timer_count); +} + +int MAX3133X::timer_start() +{ + int ret; + max3133x_timer_config_reg_t timer_config_reg = {}; + + ret = read_register(reg_addr->timer_config_reg_addr, &timer_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timer_config_reg.bits.te = 1; + timer_config_reg.bits.tpause = 0; + + return write_register(reg_addr->timer_config_reg_addr, &timer_config_reg.raw, 1); +} + +int MAX3133X::timer_pause() +{ + int ret; + max3133x_timer_config_reg_t timer_config_reg = {}; + + ret = read_register(reg_addr->timer_config_reg_addr, &timer_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timer_config_reg.bits.te = 1; + timer_config_reg.bits.tpause = 1; + + return write_register(reg_addr->timer_config_reg_addr, &timer_config_reg.raw, 1); +} + +int MAX3133X::timer_continue() +{ + int ret; + max3133x_timer_config_reg_t timer_config_reg = {}; + + ret = read_register(reg_addr->timer_config_reg_addr, &timer_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timer_config_reg.bits.te = 1; + timer_config_reg.bits.tpause = 0; + + return write_register(reg_addr->timer_config_reg_addr, &timer_config_reg.raw, 1); +} + +int MAX3133X::timer_stop() +{ + int ret; + max3133x_timer_config_reg_t timer_config_reg = {}; + + ret = read_register(reg_addr->timer_config_reg_addr, &timer_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timer_config_reg.bits.te = 0; + timer_config_reg.bits.tpause = 1; + + return write_register(reg_addr->timer_config_reg_addr, &timer_config_reg.raw, 1); +} + +int MAX31334::sleep_enter() +{ + max31334_sleep_config_reg_t sleep_config_reg = {}; + SET_BIT_FIELD(reg_addr.sleep_config_reg_addr, sleep_config_reg, sleep_config_reg.bits.slp, 1); + return MAX3133X_NO_ERR; +} + +int MAX31334::sleep_exit() +{ + max31334_sleep_config_reg_t sleep_config_reg = {}; + SET_BIT_FIELD(reg_addr.sleep_config_reg_addr, sleep_config_reg, sleep_config_reg.bits.slp, 0); + return MAX3133X_NO_ERR; +} + +int MAX31334::set_wait_state_timeout(wsto_t wsto) +{ + max31334_sleep_config_reg_t sleep_config_reg = {}; + SET_BIT_FIELD(reg_addr.sleep_config_reg_addr, sleep_config_reg, sleep_config_reg.bits.wsto, wsto); + return MAX3133X_NO_ERR; +} + +int MAX31334::get_wait_state_timeout(wsto_t* wsto) +{ + int ret; + max31334_sleep_config_reg_t sleep_config_reg = {}; + + ret = read_register(reg_addr.sleep_config_reg_addr, &sleep_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + *wsto = (wsto_t)sleep_config_reg.bits.wsto; + return MAX3133X_NO_ERR; +} + +int MAX31334::wakeup_enable(uint8_t wakeup_enable_mask) +{ + int ret; + max31334_sleep_config_reg_t sleep_config_reg = {}; + + ret = read_register(reg_addr.sleep_config_reg_addr, &sleep_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + sleep_config_reg.raw |= wakeup_enable_mask; + return write_register(reg_addr.sleep_config_reg_addr, &sleep_config_reg.raw, 1); +} + +int MAX31334::wakeup_disable(uint8_t wakeup_disable_mask) +{ + int ret; + max31334_sleep_config_reg_t sleep_config_reg = {}; + + ret = read_register(reg_addr.sleep_config_reg_addr, &sleep_config_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + sleep_config_reg.raw &= ~wakeup_disable_mask; + return write_register(reg_addr.sleep_config_reg_addr, &sleep_config_reg.raw, 1); +} + +int MAX3133X::battery_voltage_detector_config(bool enable) +{ + max3133x_pwr_mgmt_reg_t pwr_mgmt_reg = {}; + SET_BIT_FIELD(reg_addr->pwr_mgmt_reg_addr, pwr_mgmt_reg, pwr_mgmt_reg.bits.en_vbat_detect, enable); + return MAX3133X_NO_ERR; +} + +int MAX3133X::battery_voltage_detector_enable() +{ + return battery_voltage_detector_config(1); +} + +int MAX3133X::battery_voltage_detector_disable() +{ + return battery_voltage_detector_config(0); +} + +int MAX3133X::supply_select(power_mgmt_supply_t supply) +{ + int ret; + max3133x_pwr_mgmt_reg_t pwr_mgmt_reg = {}; + + ret = read_register(reg_addr->pwr_mgmt_reg_addr, &pwr_mgmt_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + switch (supply) { + case POW_MGMT_SUPPLY_SEL_VCC: + pwr_mgmt_reg.bits.manual_sel = 1; + pwr_mgmt_reg.bits.vback_sel = 0; + break; + case POW_MGMT_SUPPLY_SEL_VBAT: + pwr_mgmt_reg.bits.manual_sel = 1; + pwr_mgmt_reg.bits.vback_sel = 1; + break; + case POW_MGMT_SUPPLY_SEL_AUTO: + default: + pwr_mgmt_reg.bits.manual_sel = 0; + break; + } + + return write_register(reg_addr->pwr_mgmt_reg_addr, &pwr_mgmt_reg.raw, 1); +} + +int MAX3133X::trickle_charger_enable(trickle_charger_ohm_t res, bool diode) +{ + max3133x_trickle_reg_reg_t trickle_reg_reg = {}; + trickle_reg_reg.bits.trickle = res; + + if (diode) + trickle_reg_reg.bits.trickle |= 0x04; + + trickle_reg_reg.bits.en_trickle = true; + + return write_register(reg_addr->trickle_reg_addr, &trickle_reg_reg.raw, 1); +} + +int MAX3133X::trickle_charger_disable() +{ + max3133x_trickle_reg_reg_t trickle_reg_reg = {}; + SET_BIT_FIELD(reg_addr->trickle_reg_addr, trickle_reg_reg, trickle_reg_reg.bits.en_trickle, 0); + return MAX3133X_NO_ERR; +} + +int MAX3133X::get_timestamp(int ts_num, timestamp_t *timestamp) +{ + int ret; + max3133x_ts_regs_t timestamp_reg; + max3133x_ts_flags_reg_t ts_flags_reg; + uint8_t ts_reg_addr; + uint8_t ts_flag_reg_addr = reg_addr->ts0_flags_reg_addr + sizeof(max3133x_ts_regs_t)*ts_num; + + ret = read_register(ts_flag_reg_addr, (uint8_t *)&ts_flags_reg, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timestamp->ts_num = (ts_num_t)ts_num; + timestamp->ts_trigger = (ts_trigger_t)(ts_flags_reg.raw & 0xF); + + if (ts_flags_reg.raw == NOT_TRIGGERED) // no need to read timestamp register + return MAX3133X_NO_ERR; + + ts_reg_addr = reg_addr->ts0_sec_1_128_reg_addr + sizeof(max3133x_ts_regs_t)*ts_num; + ret = read_register(ts_reg_addr, (uint8_t *)×tamp_reg, sizeof(max3133x_ts_regs_t)-1); + if (ret != MAX3133X_NO_ERR) + return ret; + + timestamp_regs_to_time(timestamp, ×tamp_reg); + return MAX3133X_NO_ERR; +} + +int MAX3133X::offset_configuration(int meas) +{ + short int offset; + double acc = (meas - 32768)*30.5175; + + offset = (short int)(acc/0.477); + + return write_register(reg_addr->offset_high_reg_addr, (uint8_t *)&offset, 2); +} + +int MAX3133X::oscillator_flag_config(bool enable) +{ + max3133x_int_en_reg_t int_en_reg = {}; + SET_BIT_FIELD(reg_addr->int_en_reg_addr, int_en_reg, int_en_reg.bits.dosf, !enable); + return MAX3133X_NO_ERR; +} + +void MAX3133X::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 MAX3133X::post_interrupt_work() +{ + int ret; + uint8_t mask; + max3133x_int_en_reg_t int_en_reg = {}; + max3133x_status_reg_t status_reg = {}; + + while (true) { + ThisThread::flags_wait_any(POST_INTR_WORK_SIGNAL_ID); + + ret = read_register(reg_addr->status_reg_addr, &status_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) { + pr_err("Read status register failed!"); + continue; + } + + ret = read_register(reg_addr->int_en_reg_addr, &int_en_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) { + pr_err("Read interrupt enable register failed!"); + continue; + } + + for (int i = 0; i < NUM_OF_INTR_ID; i++) { + mask = (1 << i); + if ((status_reg.raw & mask) && (int_en_reg.raw & mask)) { + if (interrupt_handler_list[i].func != NULL) + interrupt_handler_list[i].func(interrupt_handler_list[i].cb); + } + } + } +} + +void MAX3133X::interrupt_handler() +{ + post_intr_work_thread->flags_set(POST_INTR_WORK_SIGNAL_ID); +} + +uint8_t MAX3133X::to_24hr(uint8_t hr, uint8_t pm) { + if (pm) { + if (hr < 12) + hr += 12; + } else { + if (hr == 12) + hr -= 12; + } + return hr; +} + +void MAX3133X::to_12hr(uint8_t hr, uint8_t *hr_12, uint8_t *pm) { + if (hr == 0) { + *hr_12 = 12; + *pm = 0; + } else if (hr < 12) { + *hr_12 = hr; + *pm = 0; + } else if (hr == 12) { + *hr_12 = 12; + *pm = 1; + } else { + *hr_12 = hr - 12; + *pm = 1; + } +} + +int MAX3133X::set_alarm_period(alarm_no_t alarm_no, max3133x_alarm_regs_t ®s, alarm_period_t period) +{ + regs.sec.bits.am1 = 1; + regs.min.bits.am2 = 1; + regs.hrs.bits_24hr.am3 = 1; + regs.day_date.bits.am4 = 1; + regs.mon.bits.am5 = 1; + regs.mon.bits.am6 = 1; + regs.day_date.bits.dy_dt_match = 1; + + switch (period) { + case ALARM_PERIOD_ONETIME: + if (alarm_no == ALARM2) /* not supported! */ + return MAX3133X_ALARM_ONETIME_NOT_SUPP_ERR; + regs.mon.bits.am6 = 0; + case ALARM_PERIOD_YEARLY: + if (alarm_no == ALARM2) /* not supported! */ + return MAX3133X_ALARM_YEARLY_NOT_SUPP_ERR; + regs.mon.bits.am5 = 0; + case ALARM_PERIOD_MONTHLY: + regs.day_date.bits.dy_dt_match = 0; + case ALARM_PERIOD_WEEKLY: + regs.day_date.bits.am4 = 0; + case ALARM_PERIOD_DAILY: + regs.hrs.bits_24hr.am3 = 0; + case ALARM_PERIOD_HOURLY: + regs.min.bits.am2 = 0; + case ALARM_PERIOD_EVERYMINUTE: + if ((alarm_no == ALARM2) && (period == ALARM_PERIOD_EVERYMINUTE)) + return MAX3133X_ALARM_EVERYMINUTE_NOT_SUPP_ERR; /* Alarm2 does not support "every minute" alarm*/ + regs.sec.bits.am1 = 0; + case ALARM_PERIOD_EVERYSECOND: + if ((alarm_no == ALARM2) && (period == ALARM_PERIOD_EVERYSECOND)) + return MAX3133X_ALARM_EVERYSECOND_NOT_SUPP_ERR; /* Alarm2 does not support "once per second" alarm*/ + break; + default: + return MAX3133X_INVALID_ALARM_PERIOD_ERR; + } + + return MAX3133X_NO_ERR; +} + +int MAX3133X::time_to_alarm_regs(max3133x_alarm_regs_t ®s, const struct tm *alarm_time, hour_format_t format) +{ + regs.sec.bcd.value = BIN2BCD(alarm_time->tm_sec); + regs.min.bcd.value = BIN2BCD(alarm_time->tm_min); + + if (format == HOUR24) + regs.hrs.bcd_24hr.value = BIN2BCD(alarm_time->tm_hour); + else if (format == HOUR12) { + uint8_t hr_12, pm; + to_12hr(alarm_time->tm_hour, &hr_12, &pm); + regs.hrs.bcd_12hr.value = BIN2BCD(hr_12); + regs.hrs.bits_12hr.am_pm = pm; + } else { + pr_err("Invalid Hour Format!"); + return MAX3133X_INVALID_TIME_ERR; + } + + if (regs.day_date.bits.dy_dt_match == 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 MAX3133X_INVALID_DATE_ERR; + } + + return MAX3133X_NO_ERR; +} + +int MAX3133X::set_alarm_regs(alarm_no_t alarm_no, const max3133x_alarm_regs_t *regs) +{ + uint8_t len = sizeof(max3133x_alarm_regs_t); + + if (alarm_no == ALARM1) + return write_register(reg_addr->alm1_sec_reg_addr, (uint8_t *)®s->sec.raw, len); + else + return write_register(reg_addr->alm2_min_reg_addr, (uint8_t *)®s->min.raw, len-3); +} + +int MAX3133X::get_rtc_time_format(hour_format_t *format) +{ + int ret; + max3133x_hours_reg_t hours_reg = {}; + ret = read_register(reg_addr->hours_reg_addr, (uint8_t *)&hours_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + *format = (hour_format_t)hours_reg.bits_24hr.f_24_12; + + return MAX3133X_NO_ERR; +} + +int MAX3133X::set_alarm(alarm_no_t alarm_no, const struct tm *alarm_time, alarm_period_t period) +{ + int ret; + max3133x_alarm_regs_t alarm_regs = {}; + hour_format_t format = {}; + + ret = set_alarm_period(alarm_no, alarm_regs, period); + if (ret != MAX3133X_NO_ERR) + return ret; + + ret = get_rtc_time_format(&format); + if (ret != MAX3133X_NO_ERR) + return ret; + + /* Convert time structure to alarm registers */ + ret = time_to_alarm_regs(alarm_regs, alarm_time, format); + if (ret != MAX3133X_NO_ERR) + return ret; + + return set_alarm_regs(alarm_no, &alarm_regs); +} + +inline void MAX3133X::alarm_regs_to_time(alarm_no_t alarm_no, struct tm *alarm_time, const max3133x_alarm_regs_t *regs, hour_format_t format) +{ + alarm_time->tm_min = BCD2BIN(regs->min.bcd.value); + + if (format == HOUR24) + alarm_time->tm_hour = BCD2BIN(regs->hrs.bcd_24hr.value); + else if (format == HOUR12) + alarm_time->tm_hour = to_24hr(BCD2BIN(regs->hrs.bcd_12hr.value), regs->hrs.bits_12hr.am_pm); + + if (regs->day_date.bits.dy_dt_match == 0) { /* date */ + alarm_time->tm_mday = BCD2BIN(regs->day_date.bcd_date.value); + alarm_time->tm_wday = 0; + } else { /* day */ + alarm_time->tm_wday = BCD2BIN(regs->day_date.bcd_day.value); + alarm_time->tm_mday = 0; + } + + if (alarm_no == ALARM1) { + alarm_time->tm_sec = BCD2BIN(regs->sec.bcd.value); + alarm_time->tm_mon = BCD2BIN(regs->mon.bcd.value) - 1; + alarm_time->tm_year = BCD2BIN(regs->year.bcd.value) + 100; /* XXX no century bit */ + } +} + +int MAX3133X::get_alarm(alarm_no_t alarm_no, struct tm *alarm_time, alarm_period_t *period, bool *is_enabled) +{ + int ret; + max3133x_alarm_regs_t alarm_regs = {}; + max3133x_int_en_reg_t int_en_reg = {}; + uint8_t len = sizeof(max3133x_alarm_regs_t); + hour_format_t format; + + ret = get_rtc_time_format(&format); + if (ret != MAX3133X_NO_ERR) + return ret; + + if (alarm_no == ALARM1) + ret = read_register(reg_addr->alm1_sec_reg_addr, &alarm_regs.sec.raw, len); + else + ret = read_register(reg_addr->alm2_min_reg_addr, &alarm_regs.min.raw, len-3); + + if (ret != MAX3133X_NO_ERR) + return ret; + + /* Convert alarm registers to time structure */ + alarm_regs_to_time(alarm_no, alarm_time, &alarm_regs, format); + + *period = ALARM_PERIOD_EVERYSECOND; + + if (alarm_no == ALARM1) { + if (alarm_regs.sec.bits.am1 == 0) + *period = ALARM_PERIOD_EVERYMINUTE; + } + + if (alarm_regs.min.bits.am2 == 0) + *period = ALARM_PERIOD_HOURLY; + if (alarm_regs.hrs.bits_24hr.am3 == 0) + *period = ALARM_PERIOD_DAILY; + if (alarm_regs.day_date.bits.am4 == 0) + *period = ALARM_PERIOD_WEEKLY; + if (alarm_regs.day_date.bits.dy_dt_match == 0) + *period = ALARM_PERIOD_MONTHLY; + if (alarm_no == ALARM1) { + if (alarm_regs.mon.bits.am5 == 0) + *period = ALARM_PERIOD_YEARLY; + if (alarm_regs.mon.bits.am6 == 0) + *period = ALARM_PERIOD_ONETIME; + } + + ret = read_register(reg_addr->int_en_reg_addr, (uint8_t *)&int_en_reg.raw, 1); + if (ret != MAX3133X_NO_ERR) + return ret; + + if (alarm_no == ALARM1) + *is_enabled = ((int_en_reg.raw & A1IE) == A1IE); + else + *is_enabled = ((int_en_reg.raw & A2IE) == A2IE); + + return MAX3133X_NO_ERR; +} + +const MAX3133X::reg_addr_t MAX31334::reg_addr = { + MAX31334_STATUS, + MAX31334_INT_EN, + MAX31334_RTC_RESET, + MAX31334_RTC_CONFIG1, + MAX31334_RTC_CONFIG2, + MAX31334_TIMESTAMP_CONFIG, + MAX31334_TIMER_CONFIG, + MAX31334_SLEEP_CONFIG, + MAX31334_SECONDS_1_128, + MAX31334_SECONDS, + MAX31334_MINUTES, + MAX31334_HOURS, + MAX31334_DAY, + MAX31334_DATE, + MAX31334_MONTH, + MAX31334_YEAR, + MAX31334_ALM1_SEC, + MAX31334_ALM1_MIN, + MAX31334_ALM1_HRS, + MAX31334_ALM1_DAY_DATE, + MAX31334_ALM1_MON, + MAX31334_ALM1_YEAR, + MAX31334_ALM2_MIN, + MAX31334_ALM2_HRS, + MAX31334_ALM2_DAY_DATE, + REG_NOT_AVAILABLE, + MAX31334_TIMER_COUNT2, + MAX31334_TIMER_COUNT1, + REG_NOT_AVAILABLE, + MAX31334_TIMER_INIT2, + MAX31334_TIMER_INIT1, + MAX31334_PWR_MGMT, + MAX31334_TRICKLE_REG, + MAX31334_OFFSET_HIGH, + MAX31334_OFFSET_LOW, + MAX31334_TS0_SEC_1_128, + MAX31334_TS0_SEC, + MAX31334_TS0_MIN, + MAX31334_TS0_HOUR, + MAX31334_TS0_DATE, + MAX31334_TS0_MONTH, + MAX31334_TS0_YEAR, + MAX31334_TS0_FLAGS, + MAX31334_TS1_SEC_1_128, + MAX31334_TS1_SEC, + MAX31334_TS1_MIN, + MAX31334_TS1_HOUR, + MAX31334_TS1_DATE, + MAX31334_TS1_MONTH, + MAX31334_TS1_YEAR, + MAX31334_TS1_FLAGS, + MAX31334_TS2_SEC_1_128, + MAX31334_TS2_SEC, + MAX31334_TS2_MIN, + MAX31334_TS2_HOUR, + MAX31334_TS2_DATE, + MAX31334_TS2_MONTH, + MAX31334_TS2_YEAR, + MAX31334_TS2_FLAGS, + MAX31334_TS3_SEC_1_128, + MAX31334_TS3_SEC, + MAX31334_TS3_MIN, + MAX31334_TS3_HOUR, + MAX31334_TS3_DATE, + MAX31334_TS3_MONTH, + MAX31334_TS3_YEAR, + MAX31334_TS3_FLAGS +}; + +const MAX3133X::reg_addr_t MAX31331::reg_addr = { + MAX31331_STATUS, + MAX31331_INT_EN, + MAX31331_RTC_RESET, + MAX31331_RTC_CONFIG1, + MAX31331_RTC_CONFIG2, + MAX31331_TIMESTAMP_CONFIG, + MAX31331_TIMER_CONFIG, + REG_NOT_AVAILABLE, + MAX31331_SECONDS_1_128, + MAX31331_SECONDS, + MAX31331_MINUTES, + MAX31331_HOURS, + MAX31331_DAY, + MAX31331_DATE, + MAX31331_MONTH, + MAX31331_YEAR, + MAX31331_ALM1_SEC, + MAX31331_ALM1_MIN, + MAX31331_ALM1_HRS, + MAX31331_ALM1_DAY_DATE, + MAX31331_ALM1_MON, + MAX31331_ALM1_YEAR, + MAX31331_ALM2_MIN, + MAX31331_ALM2_HRS, + MAX31331_ALM2_DAY_DATE, + MAX31331_TIMER_COUNT, + REG_NOT_AVAILABLE, + REG_NOT_AVAILABLE, + MAX31331_TIMER_INIT, + REG_NOT_AVAILABLE, + REG_NOT_AVAILABLE, + MAX31331_PWR_MGMT, + MAX31331_TRICKLE_REG, + MAX31331_OFFSET_HIGH, + MAX31331_OFFSET_LOW, + MAX31331_TS0_SEC_1_128, + MAX31331_TS0_SEC, + MAX31331_TS0_MIN, + MAX31331_TS0_HOUR, + MAX31331_TS0_DATE, + MAX31331_TS0_MONTH, + MAX31331_TS0_YEAR, + MAX31331_TS0_FLAGS, + MAX31331_TS1_SEC_1_128, + MAX31331_TS1_SEC, + MAX31331_TS1_MIN, + MAX31331_TS1_HOUR, + MAX31331_TS1_DATE, + MAX31331_TS1_MONTH, + MAX31331_TS1_YEAR, + MAX31331_TS1_FLAGS, + MAX31331_TS2_SEC_1_128, + MAX31331_TS2_SEC, + MAX31331_TS2_MIN, + MAX31331_TS2_HOUR, + MAX31331_TS2_DATE, + MAX31331_TS2_MONTH, + MAX31331_TS2_YEAR, + MAX31331_TS2_FLAGS, + MAX31331_TS3_SEC_1_128, + MAX31331_TS3_SEC, + MAX31331_TS3_MIN, + MAX31331_TS3_HOUR, + MAX31331_TS3_DATE, + MAX31331_TS3_MONTH, + MAX31331_TS3_YEAR, + MAX31331_TS3_FLAGS +};
diff -r 000000000000 -r 4a2754e462db max3133x.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/max3133x.hpp Tue Aug 02 18:20:54 2022 +0300 @@ -0,0 +1,1096 @@ +/******************************************************************************* + * Copyright(C) Analog Devices 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 Analog Devices Inc. + * shall not be used except as stated in the Analog Devices 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. Analog Devices Inc.retains all ownership rights. + ******************************************************************************* + */ + +#ifndef MAX3133X_HPP_ +#define MAX3133X_HPP_ + +#include "mbed.h" +#include "rtos.h" +#include "max3133x_regs.hpp" + +#define MAX3133X_I2C_ADDRESS 0x68 +#define MAX3133X_I2C_W (MAX3133X_I2C_ADDRESS << 1) +#define MAX3133X_I2C_R ((MAX3133X_I2C_ADDRESS << 1) | 1) + +enum max3133x_error_codes { + MAX3133X_NO_ERR, + MAX3133X_NULL_VALUE_ERR = -1, + MAX3133X_READ_REG_ERR = -2, + MAX3133X_WRITE_REG_ERR = -3, + MAX3133X_INVALID_TIME_ERR = -4, + MAX3133X_INVALID_DATE_ERR = -5, + MAX3133X_INVALID_MASK_ERR = -6, + MAX3133X_INVALID_ALARM_PERIOD_ERR = -7, + MAX3133X_ALARM_ONETIME_NOT_SUPP_ERR = -8, + MAX3133X_ALARM_YEARLY_NOT_SUPP_ERR = -9, + MAX3133X_ALARM_EVERYMINUTE_NOT_SUPP_ERR = -10, + MAX3133X_ALARM_EVERYSECOND_NOT_SUPP_ERR = -11 +}; + +class MAX3133X +{ +public: + /* PUBLIC FUNCTION DECLARATIONS */ + + /** + * @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 MAX3133X_NO_ERR on success, 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 MAX3133X_NO_ERR on success, 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_ctime Time info from RTC. + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int get_time(struct tm *rtc_ctime, uint16_t *sub_sec = NULL); + + /** + * @brief Selection of 24hr-12hr hour format + */ + typedef enum { + HOUR24 = 0, /**< 24-Hour format */ + HOUR12 = 1, /**< 12-Hour format */ + }hour_format_t; + + /** + * @brief Set time info to RTC. + * + * @param[in] rtc_ctime Time info to be written to RTC. + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int set_time(const struct tm *rtc_ctime, hour_format_t format = HOUR24); + + /** + * @brief Alarm periodicity selection + */ + typedef enum { + ALARM_PERIOD_EVERYSECOND, /**< Once a second */ + ALARM_PERIOD_EVERYMINUTE, /**< Seconds match */ + ALARM_PERIOD_HOURLY, /**< Seconds and Minutes match */ + ALARM_PERIOD_DAILY, /**< Hours, Minutes and Seconds match*/ + ALARM_PERIOD_WEEKLY, /**< Day and Time match */ + ALARM_PERIOD_MONTHLY, /**< Date and Time match */ + ALARM_PERIOD_YEARLY, /**< Month, Date and Time match */ + ALARM_PERIOD_ONETIME, /**< Year, Month, Date and Time match */ + }alarm_period_t; + + /** + * @brief Alarm number selection + */ + typedef enum { + ALARM1, /**< Alarm number 1 */ + ALARM2, /**< Alarm number 2 */ + }alarm_no_t; + + /** + * @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 MAX3133X_NO_ERR 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 MAX3133X_NO_ERR 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 Gets Status Register Value + * + * @param[in] status_reg + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int get_status_reg(max3133x_status_reg_t * status_reg); + + /** + * @brief Gets Interrupt Enable Register Value + * + * @param[in] int_en_reg + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int get_interrupt_reg(max3133x_int_en_reg_t * int_en_reg); + + /** + * @brief Selection of interrupt ids + */ + typedef enum { + INTR_ID_A1IE, /**< Alarm1 interrupt flag */ + INTR_ID_A2IE, /**< Alarm2 interrupt flag */ + INTR_ID_TIE, /**< Timer interrupt flag */ + INTR_ID_DIE, /**< Digital (DIN) interrupt flag */ + INTR_ID_VBATLOWIE, /**< VBAT Low Interrupt enable */ + INTR_ID_PFAILE /**< Power fail Interrupt flag */ + }intr_id_t; + + /*Interrupt Enable Register Masks*/ + #define A1IE 0b00000001 /*Alarm1 interrupt mask*/ + #define A2IE 0b00000010 /*Alarm2 interrupt mask*/ + #define TIE 0b00000100 /*Timer interrupt mask*/ + #define DIE 0b00001000 /*Digital (DIN) interrupt mask*/ + #define VBATLOWIE 0b00010000 /*VBAT Low Interrupt mask*/ + #define PFAILE 0b00100000 /*Power fail Interrupt mask*/ + #define DOSF 0b01000000 /*Disable oscillator flag*/ + #define INT_ALL 0b00111111 /*All Interrupts*/ + #define NUM_OF_INTR_ID 6 /*Number of Interrupt IDs*/ + + /** + * @brief Enables Interrupts + * + * @param[in] mask + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int interrupt_enable(uint8_t mask); + + /** + * @brief Disables Interrupts + * + * @param[in] mask + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int interrupt_disable(uint8_t mask); + + /** + * @brief Put device into reset state + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int sw_reset_assert(); + + /** + * @brief Release device from state state + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int sw_reset_release(); + + /** + * @brief Resets the digital block and the I2C programmable registers except for RAM registers and RTC_reset. + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int sw_reset(); + + /** + * @brief Data retention mode enable/disable Configuration + * + * @details + * - Register : RTC_CONFIG1 + * - Bit Fields : [2] + * - Default : 0x0 + * - Description : Data retention mode enable/disable. + */ + typedef enum { + NORMAL_OP_MODE, + DATA_RETENTION_MODE + }data_ret_t; + + /** + * @brief I2C timeout enable Configuration + * + * @details + * - Register : RTC_CONFIG1 + * - Bit Fields : [1] + * - Default : 0x1 + * - Description : I2C timeout enable + */ + typedef enum { + DISABLE_I2C_TIMEOUT, + ENABLE_I2C_TIMEOUT + }i2c_timeout_t; + + /** + * @brief Active-high enable for the crystal oscillator Configuration + * + * @details + * - Register : RTC_CONFIG1 + * - Bit Fields : [0] + * - Default : 0x1 + * - Description : Active-high enable for the crystal oscillator + */ + typedef enum { + DISABLE_OSCILLATOR, + ENABLE_OSCILLATOR + }en_osc_t; + + /** + * @brief Digital (DIN) pin Sleep Entry Enable Configuration + * + * @details + * - Register : RTC_CONFIG2 + * - Bit Fields : [4] + * - Default : 0x0 + * - Description : Digital (DIN) pin Sleep Entry Enable + */ + typedef enum { + DIN_SLEEP_ENTRY_DISABLE, + DIN_SLEEP_ENTRY_ENABLE + }dse_t; + + /** + * @brief Digital (DIN) pin Debounce Enable Configuration + * + * @details + * - Register : RTC_CONFIG2 + * - Bit Fields : [3] + * - Default : 0x0 + * - Description : Digital (DIN) pin Debounce Enable + */ + typedef enum { + DIN_DEBOUNCE_DISABLE, + DIN_DEBOUNCE_ENABLE + }ddb_t; + + /** + * @brief CLKOUT enable Configuration + * + * @details + * - Register : RTC_CONFIG2 + * - Bit Fields : [2] + * - Default : 0x0 + * - Description : CLKOUT enable + */ + typedef enum { + INTERRUPT, + CLOCK_OUTPUT + }enclko_t; + + /** + * @brief Register Configuration + * + * @details + * - Register : RTC_CONFIG1 + * - Bit Fields : [5:4] + * - Default : 0x0 + * - Description : Alarm1 Auto Clear + */ + typedef enum { + BY_READING, /**< 0x0: Alarm1 flag and interrupt can only be cleared by reading Status register via I2C */ + AFTER_10MS, /**< 0x1: Alarm1 flag and interrupt are cleared ~10ms after assertion */ + AFTER_500MS, /**< 0x2: Alarm1 flag and interrupt are cleared ~500ms after assertion */ + AFTER_5s /**< 0x3: Alarm1 flag and interrupt are cleared ~5s after assertion. This option should not be used when Alarm1 is set to OncePerSec. */ + }a1ac_t; + + /** + * @brief Sets Alarm1 Auto Clear Mode + * + * @param[in] a1ac A1AC bits. + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int set_alarm1_auto_clear(a1ac_t a1ac); + + /** + * @brief Digital (DIN) interrupt polarity configuration + * + * @details + * - Register : RTC_CONFIG1 + * - Bit Fields : [3] + * - Default : 0x0 + * - Description : Digital (DIN) interrupt polarity + */ + typedef enum { + FALLING_EDGE, /**< 0x0: Interrupt triggers on falling edge of DIN input. */ + RISING_EDGE /**< 0x1: Interrupt triggers on rising edge of DIN input. */ + }dip_t; + + /** + * @brief Digital (DIN) interrupt polarity + * + * @param[in] dip + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int set_din_polarity(dip_t dip); + + /** + * @brief Put device into data retention mode + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int data_retention_mode_enter(); + + /** + * @brief Remove device from data retention mode + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int data_retention_mode_exit(); + + /** + * @brief Enable I2C timeout + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int i2c_timeout_enable(); + + /** + * @brief Disable I2C timeout + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int i2c_timeout_disable(); + + /** + * @brief Enable the crystal oscillator. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int oscillator_enable(); + + /** + * @brief Disable the crystal oscillator. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int oscillator_disable(); + + /** + * @brief Enable the CLKOUT. Sets INTBb/CLKOUT pin as CLKO (clock output). + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int clkout_enable(); + + /** + * @brief Disable the CLKOUT. Sets INTBb/CLKOUT pin as INTBb (interrupt). + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int clkout_disable(); + + /** + * @brief Set output clock frequency on INTBb/CLKOUT pin Configuration + * + * @details + * - Register : RTC_CONFIG2 + * - Bit Fields : [1:0] + * - Default : 0x3 + * - Description : Output clock frequency on INTBb/CLKOUT pin + */ + typedef enum { + CLKOUT_1HZ, + CLKOUT_64HZ, + CLKOUT_1024KHZ, + CLKOUT_32KHZ_UNCOMP + }clko_hz_t; + + /** + * @brief Set output clock frequency on INTBb/CLKOUT pin + * + * @param[in] clko_hz + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int set_clko_freq(clko_hz_t clko_hz); + + /** + * @brief Get output clock frequency on INTBb/CLKOUT pin + * + * @param[out] clko_hz + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int get_clko_freq(clko_hz_t *clko_hz); + + /** + * @brief Enable the Timestamp Function + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int timestamp_function_enable(); + + /** + * @brief Disable the Timestamp Function + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int timestamp_function_disable(); + + /** + * @brief All Timestamp registers are reset to 0x00. If the Timestamp Function is Enabled, timestamp recording will start again. + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int timestamp_registers_reset(); + + /** + * @brief Enable Timestamp Overwrite mode + * + * @details More than 4 timestamps are recorded by overwriting oldest timestamp. Latest timestamp is always stored in the TS0 bank; earliest timestamp will be stored in the TS3 bank. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int timestamp_overwrite_enable(); + + /** + * @brief Disable Timestamp Overwrite mode + * + * @details Timestamps are recorded (TS0 -> .. -> TS3). Latest timestamp is always stored in the TS0 bank. Further TS trigger events do not record timestamps. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int timestamp_overwrite_disable(); + + /*Timestamp Config Register Masks*/ + #define TSVLOW 0b00100000 /*Record Timestamp on VBATLOW detection */ + #define TSPWM 0b00010000 /*Record Timestamp on power supply switch (VCC <-> VBAT)*/ + #define TSDIN 0b00001000 /*Record Timestamp on DIN transition. Polarity controlled by DIP bitfield in RTC_Config1 register.*/ + + /** + * @brief Enable Timestamp Records + * + * @param[in] record_enable_mask one or more of TS* + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int timestamp_record_enable(uint8_t record_enable_mask); + + /** + * @brief Disable Timestamp Records + * + * @param[in] record_disable_mask one or more of TS* + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int timestamp_record_disable(uint8_t record_disable_mask); + + /** + * @brief Timer frequency selection Configuration + * + * @details + * - Register : TIMER_CONFIG + * - Bit Fields : [1:0] + * - Default : 0x0 + * - Description : 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 Enable timer + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int timer_start(); + + /** + * @brief Pause timer, timer value is preserved + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int timer_pause(); + + /** + * @brief Start timer from the paused value + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int timer_continue(); + + /** + * @brief Disable timer + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int timer_stop(); + + /** + * @brief Turn-on the Battery Voltage Detector Function + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int battery_voltage_detector_enable(); + + /** + * @brief Turn-off the Battery Voltage Detector Function + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int battery_voltage_detector_disable(); + + /** + * @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_VBAT, /**< Use VBAT as supply */ + }power_mgmt_supply_t; + + /** + * @brief Select device power source + * + * @param[in] supply Supply selection, one of POW_MGMT_SUPPLY_SEL_* + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int supply_select(power_mgmt_supply_t supply); + + /** + * @brief Selection of charging path's resistor value + */ + typedef enum { + TRICKLE_CHARGER_3K, /**< 3000 Ohm */ + TRICKLE_CHARGER_3K_2, /**< 3000 Ohm */ + TRICKLE_CHARGER_6K, /**< 6000 Ohm */ + TRICKLE_CHARGER_11K, /**< 11000 Ohm */ + }trickle_charger_ohm_t; + + /** + * @brief Configure trickle charger charging path, also enable it + * + * @param[in] res Value of resistor + * @param[in] diode Enable diode + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int trickle_charger_enable(trickle_charger_ohm_t res, bool diode); + + /** + * @brief Disable Trickle Charger + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int trickle_charger_disable(); + + /** + * @brief Selection of Timestamp + */ + typedef enum { + TS0, /**< Timestamp 0 */ + TS1, /**< Timestamp 1 */ + TS2, /**< Timestamp 2 */ + TS3, /**< Timestamp 3 */ + NUM_OF_TS /**< Number of Timestamps */ + }ts_num_t; + + /** + * @brief Timestamp Triggers + */ + typedef enum { + NOT_TRIGGERED, /**< Not Triggered */ + DINF, /**< triggered by DIN transition */ + VCCF, /**< triggered by VBAT -> VCC switch */ + VBATF, /**< triggered by VCC -> VBAT switch */ + VLOWF, /**< triggered by VLOW detection */ + NUM_OF_TRIG /**< Number of Triggers */ + }ts_trigger_t; + + typedef struct { + ts_num_t ts_num; + ts_trigger_t ts_trigger; + uint16_t sub_sec; + struct tm ctime; + }timestamp_t; + + /** + * @brief Read Timestamp info. + * + * @param[in] ts_num Timestamp number. + * @param[out] timestamp Time info. + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int get_timestamp(int ts_num, timestamp_t *timestamp); + + /** + * @brief correct the clock accuracy on your board. refer the datasheet for additional informations + * + * @param[in] meas Timestamp number. + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int offset_configuration(int meas); + + /** + * @brief Allow the OSF to indicate the oscillator status. + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int oscillator_flag_enable(); + + /** + * @brief Disable the oscillator flag, irrespective of the oscillator status + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int oscillator_flag_disable(); + + /** + * @brief Function pointer type to interrupt handler function + */ + typedef void (*interrupt_handler_function)(void *); + + /** + * @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); + +protected: + + typedef struct { + uint8_t status_reg_addr; + uint8_t int_en_reg_addr; + uint8_t rtc_reset_reg_addr; + uint8_t rtc_config1_reg_addr; + uint8_t rtc_config2_reg_addr; + uint8_t timestamp_config_reg_addr; + uint8_t timer_config_reg_addr; + uint8_t sleep_config_reg_addr; + uint8_t seconds_1_128_reg_addr; + uint8_t seconds_reg_addr; + uint8_t minutes_reg_addr; + uint8_t hours_reg_addr; + uint8_t day_reg_addr; + uint8_t date_reg_addr; + uint8_t month_reg_addr; + uint8_t year_reg_addr; + uint8_t alm1_sec_reg_addr; + uint8_t alm1_min_reg_addr; + uint8_t alm1_hrs_reg_addr; + uint8_t alm1_day_date_reg_addr; + uint8_t alm1_mon_reg_addr; + uint8_t alm1_year_reg_addr; + uint8_t alm2_min_reg_addr; + uint8_t alm2_hrs_reg_addr; + uint8_t alm2_day_date_reg_addr; + uint8_t timer_count_reg_addr; + uint8_t timer_count2_reg_addr; + uint8_t timer_count1_reg_addr; + uint8_t timer_init_reg_addr; + uint8_t timer_init2_reg_addr; + uint8_t timer_init1_reg_addr; + uint8_t pwr_mgmt_reg_addr; + uint8_t trickle_reg_addr; + uint8_t offset_high_reg_addr; + uint8_t offset_low_reg_addr; + uint8_t ts0_sec_1_128_reg_addr; + uint8_t ts0_sec_reg_addr; + uint8_t ts0_min_reg_addr; + uint8_t ts0_hour_reg_addr; + uint8_t ts0_date_reg_addr; + uint8_t ts0_month_reg_addr; + uint8_t ts0_year_reg_addr; + uint8_t ts0_flags_reg_addr; + uint8_t ts1_sec_1_128_reg_addr; + uint8_t ts1_sec_reg_addr; + uint8_t ts1_min_reg_addr; + uint8_t ts1_hour_reg_addr; + uint8_t ts1_date_reg_addr; + uint8_t ts1_month_reg_addr; + uint8_t ts1_year_reg_addr; + uint8_t ts1_flags_reg_addr; + uint8_t ts2_sec_1_128_reg_addr; + uint8_t ts2_sec_reg_addr; + uint8_t ts2_min_reg_addr; + uint8_t ts2_hour_reg_addr; + uint8_t ts2_date_reg_addr; + uint8_t ts2_month_reg_addr; + uint8_t ts2_year_reg_addr; + uint8_t ts2_flags_reg_addr; + uint8_t ts3_sec_1_128_reg_addr; + uint8_t ts3_sec_reg_addr; + uint8_t ts3_min_reg_addr; + uint8_t ts3_hour_reg_addr; + uint8_t ts3_date_reg_addr; + uint8_t ts3_month_reg_addr; + uint8_t ts3_year_reg_addr; + uint8_t ts3_flags_reg_addr; + }reg_addr_t; + + /* Constructors */ + MAX3133X(const reg_addr_t *reg_addr, I2C *i2c, PinName inta_pin = NC, PinName intb_pin = NC); + +private: + /* PRIVATE TYPE DECLARATIONS */ + + /* PRIVATE VARIABLE DECLARATIONS */ + I2C *i2c_handler; + InterruptIn *inta_pin; + InterruptIn *intb_pin; + + /* PRIVATE CONSTANT VARIABLE DECLARATIONS */ + const reg_addr_t *reg_addr; + + /* PRIVATE FUNCTION DECLARATIONS */ + void rtc_regs_to_time(struct tm *time, const max3133x_rtc_time_regs_t *regs, uint16_t *sub_sec); + + int time_to_rtc_regs(max3133x_rtc_time_regs_t *regs, const struct tm *time, hour_format_t format); + + void timestamp_regs_to_time(timestamp_t *timestamp, const max3133x_ts_regs_t *timestamp_reg); + + int time_to_alarm_regs(max3133x_alarm_regs_t ®s, const struct tm *alarm_time, hour_format_t format); + + void alarm_regs_to_time(alarm_no_t alarm_no, struct tm *alarm_time, const max3133x_alarm_regs_t *regs, hour_format_t format); + + int set_alarm_period(alarm_no_t alarm_no, max3133x_alarm_regs_t ®s, alarm_period_t period); + + int set_alarm_regs(alarm_no_t alarm_no, const max3133x_alarm_regs_t *regs); + + uint8_t to_24hr(uint8_t hr, uint8_t pm); + + void to_12hr(uint8_t hr, uint8_t *hr_12, uint8_t *pm); + + int get_rtc_time_format(hour_format_t *format); + + int data_retention_mode_config(bool enable); + + int battery_voltage_detector_config(bool enable); + + int clkout_config(bool enable); + + int i2c_timeout_config(bool enable); + + int oscillator_config(bool enable); + + int timestamp_overwrite_config(bool enable); + + int oscillator_flag_config(bool enable); + + /** + * @brief Interrupt handler function + */ + void interrupt_handler(); + + /** + * @brief Post interrupt jobs after interrupt is detected. + */ + void post_interrupt_work(); + + Thread *post_intr_work_thread; + + struct handler { + void (*func)(void *); + void *cb; + }; + + handler interrupt_handler_list[NUM_OF_INTR_ID]; +}; + +/** MAX31334 Device Class +* +* Hold configurations for the MAX31334 +*/ +class MAX31334 : public MAX3133X +{ +private: + static const reg_addr_t reg_addr; + + int din_sleep_entry_config(bool enable); + + int din_pin_debounce_config(bool enable); + +public: + typedef struct { + a1ac_t a1ac; /*RTC_CONFIG1 - Alarm1 Auto Clear */ + dip_t dip; /*RTC_CONFIG1 - Digital (DIN) interrupt polarity */ + data_ret_t data_ret; /*RTC_CONFIG1 - Data retention mode enable/disable. */ + i2c_timeout_t i2c_timeout;/*RTC_CONFIG1 - I2C timeout enable */ + en_osc_t en_osc; /*RTC_CONFIG1 - Active-high enable for the crystal oscillator */ + dse_t dse; /*RTC_CONFIG2 - Digital (DIN) pin Sleep Entry Enable */ + ddb_t ddb; /*RTC_CONFIG2 - Digital (DIN) pin Debounce Enable */ + enclko_t enclko; /*RTC_CONFIG2 - CLKOUT enable */ + clko_hz_t clko_hz; /*RTC_CONFIG2 - Set output clock frequency on INTBb/CLKOUT pin */ + }rtc_config_t; + + /** + * @brief Configure the device + * + * @param[in] max31334_config Device configuration + * + * @return MAX3133X_NO_ERR on success, error code on failure + * + * @note RTC_CONFIG1 and RTC_CONFIG2 registers are set. + */ + int rtc_config(rtc_config_t *max31334_config); + + /** + * @brief Get device configuration + * + * @param[out] max31334_config Device configuration + * + * @return MAX3133X_NO_ERR on success, error code on failure + * + * @note RTC_CONFIG1 and RTC_CONFIG2 register values are read. + */ + int get_rtc_config(rtc_config_t *max31334_config); + + /** + * @brief Initialize timer + * + * @param[in] init_val Timer initial value + * @param[in] repeat Timer repeat mode enable/disable + * @param[in] freq Timer frequency, one of TIMER_FREQ_* + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int timer_init(uint16_t init_val, bool repeat, timer_freq_t freq); + + /** + * @brief Read timer value + * + * @return timer value on success, error code on failure + */ + int timer_get(); + + /** + * @brief Get Sleep State + * + * @return Sleep State. 0: SLST=0 indicates the PSW SM is not in Sleep state, + * 1: SLST=1 indicates the PSW SM is in Sleep state. + * negative: on failure + */ + int get_sleep_state(); + + /** + * @brief Enable the Digital (DIN) pin Sleep Entry + * + * @details DIN pin can be used to enter sleep state. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int din_sleep_entry_enable(); + + /** + * @brief Disable the Digital (DIN) pin Sleep Entry + * + * @details DIN pin cannot be used to enter sleep state (Sleep state entry is only possible by writing SLP=1 over I2C). + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int din_sleep_entry_disable(); + + /** + * @brief Enable the Digital (DIN) pin Debounce function + * + * @details 50ms debounce on DIN pin enabled. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int din_pin_debounce_enable(); + + /** + * @brief Disable the Digital (DIN) pin Debounce function + * + * @details No debounce on DIN pin. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int din_pin_debounce_disable(); + + /** + * @brief Put PSW SM into Active state. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int sleep_enter(); + + /** + * @brief Put PSW SM into Sleep state. + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int sleep_exit(); + + /** + * @brief Register Configuration + * + * @details + * - Register : SLEEP_CONFIG + * - Bit Fields : [6:4] + * - Default : 0x0 + * - Description : Wait State Timeout. This bitfield must be set before writing SLP=1 if a finite wait state duration is + * desired before entering the sleep state. + */ + typedef enum { + WSTO_0MS, /**< 0ms */ + WSTO_8MS, /**< 8ms */ + WSTO_16MS, /**< 16ms */ + WSTO_24MS, /**< 24ms */ + WSTO_32MS, /**< 32ms */ + WSTO_40MS, /**< 40ms */ + WSTO_48MS, /**< 48ms */ + WSTO_56MS /**< 56ms */ + }wsto_t; + + /** + * @brief Set Wait State Timeout + * + * @param[in] wsto Wait State Timeout + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int set_wait_state_timeout(wsto_t wsto); + + /** + * @brief Get Wait State Timeout + * + * @param[out] wsto Wait State Timeout + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int get_wait_state_timeout(wsto_t* wsto); + + /*Sleep Config Register Masks*/ + #define A1WE 0b00000001 /*Alarm1 Wakeup Enable */ + #define A2WE 0b00000010 /*Alarm2 Wakeup Enable */ + #define TWE 0b00000100 /*Timer Wakeup Enable */ + #define DWE 0b00001000 /*DIN Wakeup Enable */ + + /** + * @brief Enable Wakeup + * + * @param[in] wakeup_enable_mask one or more of Sleep Config Register Masks + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int wakeup_enable(uint8_t wakeup_enable_mask); + + /** + * @brief Disable Wakeup + * + * @param[in] wakeup_disable_mask one or more of Sleep Config Register Masks + * + * @returns MAX3133X_NO_ERR on success, error code on failure. + */ + int wakeup_disable(uint8_t wakeup_disable_mask); + + MAX31334(I2C *i2c, PinName inta_pin = NC, PinName intb_pin = NC) : MAX3133X(®_addr, i2c, inta_pin, intb_pin) {} +}; + +/** MAX31331 Device Class +* +* Hold configurations for the MAX31331 +*/ +class MAX31331 : public MAX3133X +{ +private: + static const reg_addr_t reg_addr; + +public: + typedef struct { + a1ac_t a1ac; /*RTC_CONFIG1 - Alarm1 Auto Clear */ + dip_t dip; /*RTC_CONFIG1 - Digital (DIN) interrupt polarity */ + data_ret_t data_ret; /*RTC_CONFIG1 - Data retention mode enable/disable. */ + i2c_timeout_t i2c_timeout;/*RTC_CONFIG1 - I2C timeout enable */ + en_osc_t en_osc; /*RTC_CONFIG1 - Active-high enable for the crystal oscillator */ + enclko_t enclko; /*RTC_CONFIG2 - CLKOUT enable */ + clko_hz_t clko_hz; /*RTC_CONFIG2 - Set output clock frequency on INTBb/CLKOUT pin */ + }rtc_config_t; + + /** + * @brief Configure the device + * + * @param[in] max31331_config Device configuration + * + * @return MAX3133X_NO_ERR on success, error code on failure + * + * @note RTC_CONFIG1 and RTC_CONFIG2 registers are set. + */ + int rtc_config(rtc_config_t *max31331_config); + + /** + * @brief Get device configuration + * + * @param[out] max31331_config Device configuration + * + * @return MAX3133X_NO_ERR on success, error code on failure + * + * @note RTC_CONFIG1 and RTC_CONFIG2 register values are read. + */ + int get_rtc_config(rtc_config_t *max31331_config); + + /** + * @brief Initialize timer + * + * @param[in] init_val Timer initial value + * @param[in] repeat Timer repeat mode enable/disable + * @param[in] freq Timer frequency, one of TIMER_FREQ_* + * + * @return MAX3133X_NO_ERR on success, error code on failure + */ + int timer_init(uint8_t init_val, bool repeat, timer_freq_t freq); + + /** + * @brief Read timer value + * + * @return timer value on success, error code on failure + */ + int timer_get(); + + MAX31331(I2C *i2c, PinName inta_pin = NC, PinName intb_pin = NC) : MAX3133X(®_addr, i2c, inta_pin, intb_pin) {} +}; + +#endif /* MAX3133X_HPP_ */
diff -r 000000000000 -r 4a2754e462db max3133x_regs.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/max3133x_regs.hpp Tue Aug 02 18:20:54 2022 +0300 @@ -0,0 +1,777 @@ +/******************************************************************************* + * Copyright(C) Analog Devices 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 Analog Devices Inc. + * shall not be used except as stated in the Analog Devices 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. Analog Devices Inc.retains all ownership rights. + ******************************************************************************* + */ + +#ifndef MAX3133X_REGS_HPP_ +#define MAX3133X_REGS_HPP_ + +#define REG_NOT_AVAILABLE 0xFF + +/** + * @brief STATUS Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char a1f : 1; + unsigned char a2f : 1; + unsigned char tif : 1; + unsigned char dif : 1; + unsigned char vbatlow : 1; + unsigned char pfail : 1; + unsigned char osf : 1; + unsigned char psdect : 1; + } bits; +} max3133x_status_reg_t; + +/** + * @brief ENT_EN Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char a1ie : 1; + unsigned char a2ie : 1; + unsigned char tie : 1; + unsigned char die : 1; + unsigned char vbatlowie : 1; + unsigned char pfaile : 1; + unsigned char dosf : 1; + unsigned char : 1; + } bits; +} max3133x_int_en_reg_t; + +/** + * @brief RTC_RESET Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char swrst : 1; + unsigned char : 7; + } bits; +} max3133x_rtc_reset_reg_t; + +/** + * @brief RTC_CONFIG1 Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char en_osc : 1; + unsigned char i2c_timeout : 1; + unsigned char data_ret : 1; + unsigned char dip : 1; + unsigned char a1ac : 2; + unsigned char : 2; + } bits; +} max3133x_rtc_config1_reg_t; + +/** + * @brief RTC_CONFIG2 Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char clko_hz : 2; + unsigned char enclko : 1; + unsigned char : 5; + } bits; +} max31331_rtc_config2_reg_t; + +/** + * @brief RTC_CONFIG2 Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char clko_hz : 2; + unsigned char enclko : 1; + unsigned char ddb : 1; + unsigned char dse : 1; + unsigned char : 2; + unsigned char slst : 1; + } bits; +} max31334_rtc_config2_reg_t; + +/** + * @brief TIMESTAMP_CONFIG Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char tse : 1; + unsigned char tsr : 1; + unsigned char tsow : 1; + unsigned char tsdin : 1; + unsigned char tspwm : 1; + unsigned char tsvlow : 1; + unsigned char : 2; + } bits; +} max3133x_timestamp_config_reg_t; + +/** + * @brief TIMER_CONFIG Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char tfs : 2; + unsigned char trpt : 1; + unsigned char tpause : 1; + unsigned char te : 1; + unsigned char : 3; + + } bits; +} max3133x_timer_config_reg_t; + +/** + * @brief SLEEP_CONFIG Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char a1we : 1; + unsigned char a2we : 1; + unsigned char twe : 1; + unsigned char dwe : 1; + unsigned char wsto : 3; + unsigned char slp : 1; + } bits; +} max31334_sleep_config_reg_t; + +/** + * @brief SECONDS_1_128 Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char _1_128s : 1; + unsigned char _1_64s : 1; + unsigned char _1_32s : 1; + unsigned char _1_16s : 1; + unsigned char _1_8s : 1; + unsigned char _1_4s : 1; + unsigned char _1_2s : 1; + unsigned char : 1; + } bits; +} max3133x_seconds_1_128_reg_t; + +/** + * @brief SECONDS Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char seconds : 4; + unsigned char sec_10 : 3; + unsigned char : 1; + } bits; + struct { + unsigned char value : 7; + unsigned char : 1; + } bcd; +} max3133x_seconds_reg_t; + +/** + * @brief MINUTES Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char minutes : 4; + unsigned char min_10 : 3; + unsigned char : 1; + } bits; + struct { + unsigned char value : 7; + unsigned char : 1; + } bcd; +} max3133x_minutes_reg_t; + +/** + * @brief HOURS Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char hour : 4; + unsigned char hr_10 : 1; + unsigned char am_pm : 1; + unsigned char f_24_12 : 1; + unsigned char : 1; + } bits_12hr; + struct { + unsigned char value : 5; + unsigned char : 3; + } bcd_12hr; + struct { + unsigned char hour : 4; + unsigned char hr_10 : 2; + unsigned char f_24_12 : 1; + unsigned char : 1; + } bits_24hr; + struct { + unsigned char value : 6; + unsigned char : 2; + } bcd_24hr; +} max3133x_hours_reg_t; + +/** + * @brief DAY Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char day : 3; + unsigned char : 5; + } bits; + struct { + unsigned char value : 3; + unsigned char : 5; + } bcd; +} max3133x_day_reg_t; + +/** + * @brief DATE Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char date : 4; + unsigned char date_10 : 2; + unsigned char : 2; + } bits; + struct { + unsigned char value : 6; + unsigned char : 2; + } bcd; +} max3133x_date_reg_t; + +/** + * @brief MONTH Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char month : 4; + unsigned char month_10 : 1; + unsigned char : 2; + unsigned char century : 1; + } bits; + struct { + unsigned char value : 5; + unsigned char : 3; + } bcd; +} max3133x_month_reg_t; + +/** + * @brief YEAR Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char year : 4; + unsigned char year_10 : 4; + } bits; + struct { + unsigned char value : 8; + } bcd; +} max3133x_year_reg_t; + +/** + * @brief ALM_SEC Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char seconds : 4; + unsigned char sec_10 : 3; + unsigned char am1 : 1; + } bits; + struct { + unsigned char value : 7; + unsigned char : 1; + } bcd; +} max3133x_alm_sec_reg_t; + +/** + * @brief ALM_MIN Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char minutes : 4; + unsigned char min_10 : 3; + unsigned char am2 : 1; + } bits; + struct { + unsigned char value : 7; + unsigned char : 1; + } bcd; +} max3133x_alm_min_reg_t; + +/** + * @brief ALM_HRS Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char hour : 4; + unsigned char hr_10 : 1; + unsigned char am_pm : 1; + unsigned char : 1; + unsigned char am3 : 1; + } bits_12hr; + struct { + unsigned char value : 5; + unsigned char : 3; + } bcd_12hr; + struct { + unsigned char hour : 4; + unsigned char hr_10 : 2; + unsigned char : 1; + unsigned char am3 : 1; + } bits_24hr; + struct { + unsigned char value : 6; + unsigned char : 2; + } bcd_24hr; +} max3133x_alm_hrs_reg_t; + +/** + * @brief ALM_DAY_DATE Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char day_date : 4; + unsigned char date_10 : 2; + unsigned char dy_dt_match : 1; + unsigned char am4 : 1; + } bits; + struct { + unsigned char value : 3; + unsigned char : 5; + } bcd_day; + struct { + unsigned char value : 6; + unsigned char : 2; + } bcd_date; +} max3133x_alm_day_date_reg_t; + +/** + * @brief ALM_MON Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char month : 4; + unsigned char month_10 : 1; + unsigned char : 1; + unsigned char am6 : 1; + unsigned char am5 : 1; + } bits; + struct { + unsigned char value : 5; + unsigned char : 3; + } bcd; +} max3133x_alm_mon_reg_t; + +/** + * @brief ALM_YEAR Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char year : 4; + unsigned char year_10 : 4; + } bits; + struct { + unsigned char value : 8; + } bcd; +} max3133x_alm_year_reg_t; + +/** + * @brief PWR_MGMT Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char manual_sel : 1; + unsigned char vback_sel : 1; + unsigned char : 1; + unsigned char en_vbat_detect : 1; + unsigned char : 4; + } bits; +} max3133x_pwr_mgmt_reg_t; + +/** + * @brief TRICKLE_REG Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char en_trickle : 1; + unsigned char trickle : 3; + unsigned char : 4; + } bits; +} max3133x_trickle_reg_reg_t; + +/** + * @brief OFFSET_HIGH Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char compword; + } bits; +} max3133x_offset_high_reg_t; + +/** + * @brief OFFSET_LOW Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char compword; + } bits; +} max3133x_offset_low_reg_t; + +/** + * @brief TS_SEC_1_128 Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char _1_128s : 1; + unsigned char _1_64s : 1; + unsigned char _1_32s : 1; + unsigned char _1_16s : 1; + unsigned char _1_8s : 1; + unsigned char _1_4s : 1; + unsigned char _1_2s : 1; + unsigned char : 1; + } bits; +} max3133x_ts_sec_1_128_reg_t; + +/** + * @brief TS_SEC Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char sec : 4; + unsigned char sec_10 : 3; + unsigned char : 1; + } bits; + struct { + unsigned char value : 7; + unsigned char : 1; + } bcd; +} max3133x_ts_sec_reg_t; + +/** + * @brief TS_MIN Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char min : 4; + unsigned char min_10 : 3; + unsigned char : 1; + } bits; + struct { + unsigned char value : 7; + unsigned char : 1; + } bcd; +} max3133x_ts_min_reg_t; + +/** + * @brief TS_HOUR Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char hour : 4; + unsigned char hr_10 : 1; + unsigned char am_pm : 1; + unsigned char f_24_12 : 1; + unsigned char : 1; + } bits_12hr; + struct { + unsigned char value : 5; + unsigned char : 3; + } bcd_12hr; + struct { + unsigned char hour : 4; + unsigned char hr_10 : 2; + unsigned char f_24_12 : 1; + unsigned char : 1; + } bits_24hr; + struct { + unsigned char value : 6; + unsigned char : 2; + } bcd_24hr; +} max3133x_ts_hour_reg_t; + +/** + * @brief TS_DATE Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char date : 4; + unsigned char date_10 : 2; + unsigned char : 2; + } bits; + struct { + unsigned char value : 6; + unsigned char : 2; + } bcd; +} max3133x_ts_date_reg_t; + +/** + * @brief TS_MONTH Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char month : 4; + unsigned char month_10 : 1; + unsigned char : 2; + unsigned char century : 1; + } bits; + struct { + unsigned char value : 5; + unsigned char : 3; + } bcd; +} max3133x_ts_month_reg_t; + +/** + * @brief TS_YEAR Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char year : 4; + unsigned char year_10 : 4; + } bits; + struct { + unsigned char value : 8; + } bcd; +} max3133x_ts_year_reg_t; + +/** + * @brief TS_FLAGS Register + */ +typedef union { + unsigned char raw; + struct { + unsigned char dinf : 1; + unsigned char vccf : 1; + unsigned char vbatf : 1; + unsigned char vlowf : 1; + unsigned char : 4; + } bits; +} max3133x_ts_flags_reg_t; + +typedef struct { + max3133x_seconds_1_128_reg_t seconds_1_128_reg; + max3133x_seconds_reg_t seconds_reg; + max3133x_minutes_reg_t minutes_reg; + max3133x_hours_reg_t hours_reg; + max3133x_day_reg_t day_reg; + max3133x_date_reg_t date_reg; + max3133x_month_reg_t month_reg; + max3133x_year_reg_t year_reg; +} max3133x_rtc_time_regs_t; + +typedef struct { + max3133x_alm_sec_reg_t sec; + max3133x_alm_min_reg_t min; + max3133x_alm_hrs_reg_t hrs; + max3133x_alm_day_date_reg_t day_date; + max3133x_alm_mon_reg_t mon; + max3133x_alm_year_reg_t year; +}max3133x_alarm_regs_t; + +typedef struct { + max3133x_ts_sec_1_128_reg_t ts_sec_1_128_reg; + max3133x_ts_sec_reg_t ts_sec_reg; + max3133x_ts_min_reg_t ts_min_reg; + max3133x_ts_hour_reg_t ts_hour_reg; + max3133x_ts_date_reg_t ts_date_reg; + max3133x_ts_month_reg_t ts_month_reg; + max3133x_ts_year_reg_t ts_year_reg; + max3133x_ts_flags_reg_t ts_flags_reg; +}max3133x_ts_regs_t; + +enum max31331_register_address { + /*RTC REG*/ + MAX31331_STATUS = 0x00, + MAX31331_INT_EN = 0x01, + MAX31331_RTC_RESET = 0x02, + MAX31331_RTC_CONFIG1 = 0x03, + MAX31331_RTC_CONFIG2 = 0x04, + MAX31331_TIMESTAMP_CONFIG = 0x05, + MAX31331_TIMER_CONFIG = 0x06, + MAX31331_SECONDS_1_128 = 0x07, + MAX31331_SECONDS = 0x08, + MAX31331_MINUTES = 0x09, + MAX31331_HOURS = 0x0A, + MAX31331_DAY = 0x0B, + MAX31331_DATE = 0x0C, + MAX31331_MONTH = 0x0D, + MAX31331_YEAR = 0x0E, + MAX31331_ALM1_SEC = 0x0F, + MAX31331_ALM1_MIN = 0x10, + MAX31331_ALM1_HRS = 0x11, + MAX31331_ALM1_DAY_DATE = 0x12, + MAX31331_ALM1_MON = 0x13, + MAX31331_ALM1_YEAR = 0x14, + MAX31331_ALM2_MIN = 0x15, + MAX31331_ALM2_HRS = 0x16, + MAX31331_ALM2_DAY_DATE = 0x17, + MAX31331_TIMER_COUNT = 0x18, + MAX31331_TIMER_INIT = 0x19, + MAX31331_PWR_MGMT = 0x1A, + MAX31331_TRICKLE_REG = 0x1B, + MAX31331_OFFSET_HIGH = 0x1D, + MAX31331_OFFSET_LOW = 0x1E, + /*TS_RAM_REG*/ + MAX31331_TS0_SEC_1_128 = 0x20, + MAX31331_TS0_SEC = 0x21, + MAX31331_TS0_MIN = 0x22, + MAX31331_TS0_HOUR = 0x23, + MAX31331_TS0_DATE = 0x24, + MAX31331_TS0_MONTH = 0x25, + MAX31331_TS0_YEAR = 0x26, + MAX31331_TS0_FLAGS = 0x27, + MAX31331_TS1_SEC_1_128 = 0x28, + MAX31331_TS1_SEC = 0x29, + MAX31331_TS1_MIN = 0x2A, + MAX31331_TS1_HOUR = 0x2B, + MAX31331_TS1_DATE = 0x2C, + MAX31331_TS1_MONTH = 0x2D, + MAX31331_TS1_YEAR = 0x2E, + MAX31331_TS1_FLAGS = 0x2F, + MAX31331_TS2_SEC_1_128 = 0x30, + MAX31331_TS2_SEC = 0x31, + MAX31331_TS2_MIN = 0x32, + MAX31331_TS2_HOUR = 0x33, + MAX31331_TS2_DATE = 0x34, + MAX31331_TS2_MONTH = 0x35, + MAX31331_TS2_YEAR = 0x36, + MAX31331_TS2_FLAGS = 0x37, + MAX31331_TS3_SEC_1_128 = 0x38, + MAX31331_TS3_SEC = 0x39, + MAX31331_TS3_MIN = 0x3A, + MAX31331_TS3_HOUR = 0x3B, + MAX31331_TS3_DATE = 0x3C, + MAX31331_TS3_MONTH = 0x3D, + MAX31331_TS3_YEAR = 0x3E, + MAX31331_TS3_FLAGS = 0x3F, + MAX31331_END, +}; + +enum max31334_register_address { + /*RTC REG*/ + MAX31334_STATUS = 0x00, + MAX31334_INT_EN = 0x01, + MAX31334_RTC_RESET = 0x02, + MAX31334_RTC_CONFIG1 = 0x03, + MAX31334_RTC_CONFIG2 = 0x04, + MAX31334_TIMESTAMP_CONFIG = 0x05, + MAX31334_TIMER_CONFIG = 0x06, + MAX31334_SLEEP_CONFIG = 0x07, + MAX31334_SECONDS_1_128 = 0x08, + MAX31334_SECONDS = 0x09, + MAX31334_MINUTES = 0x0A, + MAX31334_HOURS = 0x0B, + MAX31334_DAY = 0x0C, + MAX31334_DATE = 0x0D, + MAX31334_MONTH = 0x0E, + MAX31334_YEAR = 0x0F, + MAX31334_ALM1_SEC = 0x10, + MAX31334_ALM1_MIN = 0x11, + MAX31334_ALM1_HRS = 0x12, + MAX31334_ALM1_DAY_DATE = 0x13, + MAX31334_ALM1_MON = 0x14, + MAX31334_ALM1_YEAR = 0x15, + MAX31334_ALM2_MIN = 0x16, + MAX31334_ALM2_HRS = 0x17, + MAX31334_ALM2_DAY_DATE = 0x18, + MAX31334_TIMER_COUNT2 = 0x19, + MAX31334_TIMER_COUNT1 = 0x1A, + MAX31334_TIMER_INIT2 = 0x1B, + MAX31334_TIMER_INIT1 = 0x1C, + MAX31334_PWR_MGMT = 0x1D, + MAX31334_TRICKLE_REG = 0x1E, + MAX31334_OFFSET_HIGH = 0x20, + MAX31334_OFFSET_LOW = 0x21, + /*TS_RAM_REG*/ + MAX31334_TS0_SEC_1_128 = 0x30, + MAX31334_TS0_SEC = 0x31, + MAX31334_TS0_MIN = 0x32, + MAX31334_TS0_HOUR = 0x33, + MAX31334_TS0_DATE = 0x34, + MAX31334_TS0_MONTH = 0x35, + MAX31334_TS0_YEAR = 0x36, + MAX31334_TS0_FLAGS = 0x37, + MAX31334_TS1_SEC_1_128 = 0x38, + MAX31334_TS1_SEC = 0x39, + MAX31334_TS1_MIN = 0x3A, + MAX31334_TS1_HOUR = 0x3B, + MAX31334_TS1_DATE = 0x3C, + MAX31334_TS1_MONTH = 0x3D, + MAX31334_TS1_YEAR = 0x3E, + MAX31334_TS1_FLAGS = 0x3F, + MAX31334_TS2_SEC_1_128 = 0x40, + MAX31334_TS2_SEC = 0x41, + MAX31334_TS2_MIN = 0x42, + MAX31334_TS2_HOUR = 0x43, + MAX31334_TS2_DATE = 0x44, + MAX31334_TS2_MONTH = 0x45, + MAX31334_TS2_YEAR = 0x46, + MAX31334_TS2_FLAGS = 0x47, + MAX31334_TS3_SEC_1_128 = 0x48, + MAX31334_TS3_SEC = 0x49, + MAX31334_TS3_MIN = 0x4A, + MAX31334_TS3_HOUR = 0x4B, + MAX31334_TS3_DATE = 0x4C, + MAX31334_TS3_MONTH = 0x4D, + MAX31334_TS3_YEAR = 0x4E, + MAX31334_TS3_FLAGS = 0x4F, + MAX31334_END, +}; + +#endif /* MAX3133X_REGS_HPP_ */