MCP794xx Real-Time Clock (RTC) / Calendar Driver in Rust

MCP7940N is similar to this DS1307 RTC module

   

Today I present you a platform-agnostic rust driver for the MCP794xx family of real-time clock / calendar devices compatible with MCP7940N, MCP7940M, MCP79400, MCP79401, MCP79402, MCP79410, MCP79411 and MCP79412.
If you are reading this you probably know about monotron, the 1980’s home computer style application written in Rust by Jonathan Pallant.
He has now designed a dedicated PCB for it including an MCP7940N RTC which did not have a Rust driver so here it is.

The devices

The Real-Time Clock/Calendar (RTCC) tracks time using internal counters for hours, minutes, seconds, days, months, years, and day of week. Alarms can be configured on all counters up to and including months. For usage and configuration, the devices support I2C communications up to 400 kHz.

The open-drain, multi-functional output can be configured to assert on an alarm match, to output a selectable frequency square wave, or as a general purpose output.

The devices are designed to operate using a 32.768 kHz tuning fork crystal with external crystal load capacitors. On-chip digital trimming can be used to adjust for frequency variance caused by crystal tolerance and temperature.

SRAM and timekeeping circuitry are powered from the back-up supply when main power is lost, allowing the device to maintain accurate time and the SRAM contents. The times when the device switches over to the back-up supply and when primary power returns are both logged by the power-fail time-stamp.

Some of the devices feature 1 Kbit of internal non-volatile EEPROM with software write-protectable regions. There is an additional 64 bits of protected non-volatile memory which is only writable after an unlock sequence, making it ideal for storing a unique ID or other critical information.

Some of the devices offer a pre-programmed with EUI-48 and EUI-64 addresses. Custom programming is also available.

Datasheets:

Using the driver

To use the device from Rust, you have to add the mcp794xx crate to your project as well as a concrete implementation of the embedded-hal traits. For example if you are using the Raspberry Pi running Linux (see driver-examples for bare-metal hardware):

1
2
3
4
5
# Cargo.toml
...
[dependencies]
mcp794xx = "0.1"
linux-embedded-hal = "0.3"

Here is an example program which will set a date and time and read back the seconds later on (source):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
extern crate embedded_hal;
extern crate linux_embedded_hal;
extern crate mcp794xx;

use linux_embedded_hal::I2cdev;
use mcp794xx::{DateTime, Hours, Mcp794xx, Rtcc};

fn main() {
let dev = I2cdev::new("/dev/i2c-1").unwrap();
let mut rtc = Mcp794xx::new_mcp7940n(dev);
rtc.enable().unwrap();
let datetime = DateTime {
year: 2019,
month: 9,
day: 15,
weekday: 7,
hour: Hours::H24(11),
minute: 59,
second: 58,
};
rtc.set_datetime(&datetime).unwrap();
rtc.enable().unwrap();
// do something else...
let seconds = rtc.get_seconds().unwrap();
println!("Seconds: {}", seconds);

let _dev = rtc.destroy();
}

I also created an example program that runs on the STM32F3Discovery board which continuously reads the date and time and prints it on an OLED display. You can find the application source code here.

In the driver-examples repository you can find further examples which you can adapt to do other things with this device.

Where to go from here?

There is much more information and example programs in the crate documentation.
Please give this driver a try and report any issues you may encounter in the issue tracker.
Feedback, suggestions and improvements are gladly welcome.

What’s next?

I have been writing many other platform-agnostic Rust drivers although I am slow to announce them here. If you want to know what I am currently working on you can follow me on github.

Thanks for reading and stay tuned!

Links: Source code - Crate - Documentation

Share