Skip to content

Commit

Permalink
[driver] MCP7941X RTC driver w/ EUI-48/64 & EEPROM
Browse files Browse the repository at this point in the history
Co-authored-by: odinthenerd <odinthenerd@gmail.com>
  • Loading branch information
rleh and odinthenerd committed Dec 19, 2021
1 parent d2ac8d2 commit 68cb1f9
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 5 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -642,37 +642,38 @@ you specific needs.
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max7219">MAX7219</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp23x17">MCP23X17</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp2515">MCP2515</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp7941x">MCP7941X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mmc5603">MMC5603</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nokia5110">NOKIA5110</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nokia5110">NOKIA5110</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nrf24">NRF24</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-parallel_tft_display">TFT-DISPLAY</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pat9125el">PAT9125EL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca8574">PCA8574</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9535">PCA9535</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9548a">PCA9548A</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9548a">PCA9548A</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9685">PCA9685</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sh1106">SH1106</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s65">SIEMENS-S65</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s75">SIEMENS-S75</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk6812">SK6812</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk9822">SK9822</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk9822">SK9822</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ssd1306">SSD1306</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-st7586s">ST7586S</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stts22h">STTS22H</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stusb4500">STUSB4500</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx1276">SX1276</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3414">TCS3414</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3414">TCS3414</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3472">TCS3472</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tlc594x">TLC594X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp102">TMP102</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp12x">TMP12X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-touch2046">TOUCH2046</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-touch2046">TOUCH2046</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl53l0">VL53L0</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ws2812">WS2812</a></td>
Expand Down
114 changes: 114 additions & 0 deletions src/modm/driver/rtc/mcp7941x.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2021, Odin Holmes
* Copyright (c) 2021, Raphael Lehmann
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* chip datasheet available at http://ww1.microchip.com/downloads/en/DeviceDoc/22266A.pdf
*/
// ----------------------------------------------------------------------------

#ifndef MODM_MCP7941X_HPP
#define MODM_MCP7941X_HPP

#include <array>
#include <optional>

#include <modm/architecture/interface/register.hpp>
#include <modm/architecture/interface/i2c_device.hpp>
#include <modm/processing/protothread.hpp>

namespace modm
{

struct mcp7941x
{
/// days, months, etc. are decoded (BCD) in this struct
struct modm_packed
DateTime
{
uint8_t days;
uint8_t months;
uint8_t years;
uint8_t seconds;
uint8_t minutes;
uint8_t hours;
};
};

/**
* @ingroup modm_driver_mcp7941x
* @author Odin Holmes
* @author Raphael Lehmann
*/
template < class I2cMaster >
class Mcp7941x : public modm::mcp7941x,
public modm::I2cDevice<I2cMaster, 2>
{
public:
Mcp7941x(uint8_t address = 0x6f);

modm::ResumableResult<std::optional<modm::mcp7941x::DateTime>>
getDateTime();

modm::ResumableResult<bool>
setDateTime(DateTime);

modm::ResumableResult<bool>
oscillatorRunning();

private:
constexpr uint8_t
decodeBcd(uint8_t bcd)
{
return (bcd / 16 * 10) + (bcd % 16);
}

constexpr uint8_t
encodeBcd(uint8_t decimal)
{
return (decimal / 10 * 16) + (decimal % 10);
}

private:
DateTime dateTime;

//address definition for registers of the MCP7941x
const uint8_t addr_seconds = 0x00;
const uint8_t addr_minutes = 0x01;
const uint8_t addr_hours = 0x02;
const uint8_t addr_weekday = 0x03; //not using day of the week
const uint8_t addr_days = 0x04;
const uint8_t addr_months = 0x05;
const uint8_t addr_years = 0x06;

uint8_t scratch[8];
};

/**
* @ingroup modm_driver_mcp7941x
* @author Raphael Lehmann
*/
template < class I2cMaster >
class Mcp7941xEeprom : public modm::I2cDevice<I2cMaster, 2>
{
public:
Mcp7941xEeprom(uint8_t address = 0x57);

modm::ResumableResult<std::optional<std::array<uint8_t, 8>>>
getUniqueId();

private:
const uint8_t addr_unique_id = 0xF0;

std::array<uint8_t, 8> data{};
};

} // namespace modm

#include "mcp7941x_impl.hpp"

#endif // MODM_MCP7941X_HPP
34 changes: 34 additions & 0 deletions src/modm/driver/rtc/mcp7941x.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021, Odin Holmes
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------


def init(module):
module.name = ":driver:mcp7941x"
module.description = """\
# MCP79410/MCP79411/MCP79412
Battery-Backed I2C Real-Time Clock/Calendar with SRAM, EEPROM and Protected EEPROM
"""


def prepare(module, options):
module.depends(
":architecture:i2c.device",
":architecture:register",
":processing:resumable")
return True


def build(env):
env.outbasepath = "modm/src/modm/driver/rtc"
env.copy("mcp7941x.hpp")
env.copy("mcp7941x_impl.hpp")
95 changes: 95 additions & 0 deletions src/modm/driver/rtc/mcp7941x_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2021, Odin Holmes
* Copyright (c) 2021, Raphael Lehmann
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_MCP7941X_HPP
# error "Don't include this file directly, use 'mcp7941x.hpp' instead!"
#endif

// ----------------------------------------------------------------------------
template < typename I2cMaster >
modm::Mcp7941x<I2cMaster>::Mcp7941x(uint8_t address)
: I2cDevice<I2cMaster, 2>(address), dateTime{}
{
}

template < typename I2cMaster >
modm::ResumableResult<std::optional<modm::mcp7941x::DateTime>>
modm::Mcp7941x<I2cMaster>::getDateTime()
{
RF_BEGIN();
this->transaction.configureWriteRead(&addr_seconds, 1, scratch, 7);
if (RF_CALL(this->runTransaction())) {
dateTime.seconds = decodeBcd(scratch[0] & 0b0111'1111);
dateTime.minutes = decodeBcd(scratch[1]);
dateTime.hours = decodeBcd(scratch[2] & 0b0011'1111);
//no need for day of the week
dateTime.days = decodeBcd(scratch[4]);
dateTime.months = decodeBcd(scratch[5] & 0b0001'1111);
dateTime.years = decodeBcd(scratch[6]);
RF_RETURN(dateTime);
}
RF_END_RETURN(std::nullopt);
}

template < typename I2cMaster >
modm::ResumableResult<bool>
modm::Mcp7941x<I2cMaster>::setDateTime(DateTime dt)
{
RF_BEGIN();
scratch[0] = addr_seconds;
scratch[1] = 0x00; // stop oscillator
scratch[2] = encodeBcd(dt.minutes);
scratch[3] = encodeBcd(dt.hours);
scratch[4] = 0b0000'1000 /* Set VBATEN bit */;
scratch[5] = encodeBcd(dt.days);
scratch[6] = encodeBcd(dt.months);
scratch[7] = encodeBcd(dt.years);
this->transaction.configureWrite(scratch, 8);
if (not RF_CALL(this->runTransaction())) {
RF_RETURN(false);
}
scratch[0] = addr_seconds;
scratch[1] = encodeBcd(dt.seconds) | 0b1000'0000 /* Start oscillator bit */;
this->transaction.configureWrite(scratch, 2);
RF_END_RETURN_CALL(this->runTransaction());
}

template < typename I2cMaster >
modm::ResumableResult<bool>
modm::Mcp7941x<I2cMaster>::oscillatorRunning()
{
RF_BEGIN();
this->transaction.configureWriteRead(&addr_weekday, 1, scratch, 1);
if (RF_CALL(this->runTransaction())) {
RF_RETURN((scratch[0] | 0b0010'0000 /* OSCRUN bit */) > 0);
}
RF_END_RETURN(false);
}


template < typename I2cMaster >
modm::Mcp7941xEeprom<I2cMaster>::Mcp7941xEeprom(uint8_t address)
: I2cDevice<I2cMaster, 2>(address)
{
}

template < typename I2cMaster >
modm::ResumableResult<std::optional<std::array<uint8_t, 8>>>
modm::Mcp7941xEeprom<I2cMaster>::getUniqueId()
{
RF_BEGIN();
this->transaction.configureWriteRead(&addr_unique_id, 1, data.data(), 8);
if (not RF_CALL(this->runTransaction())) {
RF_RETURN(std::nullopt);
}
RF_END_RETURN(data);
}

0 comments on commit 68cb1f9

Please sign in to comment.