You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
zavlaha-kzk/src/ds_rtc.c

67 lines
1.8 KiB

/**
* Functions to access the RTC (DS3231)
*/
#include <pico/stdlib.h>
#include <stdint.h>
#include <hardware/i2c.h>
#include <string.h>
#include "ds_rtc.h"
#include "pinout.h"
#include "rv_try.h"
#define I2C_ADDR_RTC 0b1101000
#define TIMEOUT_US 10000
static int rtc_read(uint8_t start, uint8_t *dest, size_t len) {
int rv;
TRY(i2c_write_timeout_us(i2c0, I2C_ADDR_RTC, &start, 1, true, TIMEOUT_US));
TRY(i2c_read_timeout_us(i2c0, I2C_ADDR_RTC, dest, len, false, TIMEOUT_US));
return 0;
}
static uint8_t scratch[20];
static int rtc_write(uint8_t start, const uint8_t *data, size_t len) {
int rv;
if (len > 19) return -1;
scratch[0] = start;
memcpy(&scratch[1], data, len);
TRY(i2c_write_timeout_us(i2c0, I2C_ADDR_RTC, scratch, len + 1, true, TIMEOUT_US));
return 0;
}
int rtc_get_time(struct rtc_time *dest) {
int rv;
uint8_t buf[4];
TRY(rtc_read(0x00, buf, 4));
dest->second = (buf[0] & 15) + (buf[0] >> 4) * 10;
dest->minute = (buf[1] & 15) + (buf[1] >> 4) * 10;
dest->weekday = buf[3] & 7;
if (dest->weekday > 0) dest->weekday -= 1; // Normalize to 0-6, with failsafe in case we got zero, should not happen.
if (buf[2] & 0x40) {
// 12h time?
dest->hour = (buf[2] & 15) + ((buf[2] & 0x20) != 0) * 12 + ((buf[2] & 0x10) != 0) * 10;
} else {
dest->hour = (buf[2] & 15) + ((buf[2] >> 4) & 3) * 10;
}
return 0;
}
int rtc_set_time(const struct rtc_time *time) {
int rv;
uint8_t buf[3];
buf[0] = (time->second % 10) + ((time->second / 10) << 4);
buf[1] = (time->minute % 10) + ((time->minute / 10) << 4);
buf[2] = (time->hour % 10) + ((time->hour / 10) << 4);
TRY(rtc_write(0x00, buf, 3));
// just let the week counter go on its own - we only care about it incrementing
return 0;
}