timers/mcp794xx: add option to digital trimming

MCP794XX supports digital trimming that periodically adds or subtracts
clock cycles, resulting in small adjustments in the internal timing.
This way inaccuracies of clock source can be compensated.

This commit adds option to set the trimming register for MCP794XX.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
Michal Lenc 2024-05-28 11:01:40 +02:00 committed by Alan Carvalho de Assis
parent c59b48355c
commit 3cc65d5d35
2 changed files with 128 additions and 3 deletions

View File

@ -77,6 +77,7 @@ struct mcp794xx_dev_s
{
FAR struct i2c_master_s *i2c; /* Contained reference to the I2C bus driver. */
uint8_t addr; /* The I2C device address. */
bool coarse_trim; /* Coarse trim mode */
};
/****************************************************************************
@ -182,6 +183,105 @@ static int rtc_bcd2bin(uint8_t value)
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mcp794xx_rtc_set_trim
*
* Description:
* Sets the digital trimming to correct for inaccuracies of clock source.
* Digital trimming consists of the MCP794XX periodically adding or
* subtracting clock cycles, resulting in small adjustments in the internal
* timing.
*
* Input Parameters:
* trim_val - Calculated trimming value, refer to MCP794XX reference
* manual.
* rtc_slow - True indicates RTC is behind real clock, false otherwise.
* This has to be set to ensure correct trimming direction.
* coarse_mode - MCP794XX allows coarse mode that trims every second
* instead of every minute.
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
int mcp794xx_rtc_set_trim(uint8_t trim_val, bool rtc_slow, bool coarse_mode)
{
struct i2c_msg_s msg[2];
uint8_t buffer[2];
uint8_t address;
uint8_t ctrl;
int ret;
if (g_mcp794xx.coarse_trim != coarse_mode)
{
address = MCP794XX_REG_CONTROL;
msg[0].frequency = CONFIG_MCP794XX_I2C_FREQUENCY;
msg[0].addr = g_mcp794xx.addr;
msg[0].flags = I2C_M_NOSTOP;
msg[0].buffer = &address;
msg[0].length = 1;
msg[1].frequency = CONFIG_MCP794XX_I2C_FREQUENCY;
msg[1].addr = g_mcp794xx.addr;
msg[1].flags = I2C_M_READ;
msg[1].buffer = &ctrl;
msg[1].length = 1;
ret = I2C_TRANSFER(g_mcp794xx.i2c, msg, 2);
if (ret < 0)
{
rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret);
return ret;
}
ctrl &= ~MCP794XX_CONTROL_CRSTRIM;
if (coarse_mode)
{
ctrl |= MCP794XX_CONTROL_CRSTRIM;
}
buffer[0] = MCP794XX_REG_CONTROL;
buffer[1] = ctrl;
msg[0].frequency = CONFIG_MCP794XX_I2C_FREQUENCY;
msg[0].addr = g_mcp794xx.addr;
msg[0].flags = 0;
msg[0].buffer = buffer;
msg[0].length = 2;
ret = I2C_TRANSFER(g_mcp794xx.i2c, msg, 1);
if (ret < 0)
{
rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret);
return ret;
}
g_mcp794xx.coarse_trim = coarse_mode;
}
buffer[0] = MCP794XX_REG_OSCTRIM;
buffer[1] = trim_val & 0x7;
if (rtc_slow)
{
buffer[1] |= MCP794XX_OSCTRIM_SIGN;
}
msg[0].frequency = CONFIG_MCP794XX_I2C_FREQUENCY;
msg[0].addr = g_mcp794xx.addr;
msg[0].flags = 0;
msg[0].buffer = buffer;
msg[0].length = 2;
ret = I2C_TRANSFER(g_mcp794xx.i2c, msg, 1);
if (ret < 0)
{
rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret);
return ret;
}
return OK;
}
/****************************************************************************
* Name: mcp794xx_rtc_initialize
*
@ -211,9 +311,10 @@ int mcp794xx_rtc_initialize(FAR struct i2c_master_s *i2c, uint8_t addr)
{
/* Remember the i2c device and claim that the RTC is enabled */
g_mcp794xx.i2c = i2c;
g_mcp794xx.addr = addr;
g_rtc_enabled = true;
g_mcp794xx.i2c = i2c;
g_mcp794xx.addr = addr;
g_mcp794xx.coarse_trim = false;
g_rtc_enabled = true;
return OK;
}

View File

@ -41,6 +41,30 @@ extern "C"
#define EXTERN extern
#endif
/****************************************************************************
* Name: mcp794xx_rtc_set_trim
*
* Description:
* Sets the digital trimming to correct for inaccuracies of clock source.
* Digital trimming consists of the MCP794XX periodically adding or
* subtracting clock cycles, resulting in small adjustments in the internal
* timing.
*
* Input Parameters:
* trim_val - Calculated trimming value, refer to MCP794XX reference
* manual.
* rtc_slow - True indicates RTC is behind real clock, false otherwise.
* This has to be set to ensure correct trimming direction.
* coarse_mode - MCP794XX allows coarse mode that trims every second
* instead of every minute.
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
int mcp794xx_rtc_set_trim(uint8_t trim_val, bool rtc_slow, bool coarse_mode);
/****************************************************************************
* Name: mcp794xx_rtc_initialize
*