mirror of
https://github.com/mist-devel/mist-firmware.git
synced 2026-04-20 09:16:12 +00:00
102 lines
2.9 KiB
C
102 lines
2.9 KiB
C
//
|
|
// pcf85263.c
|
|
//
|
|
// Driver for NXP PCF85263/PCF85363 rtc
|
|
//
|
|
|
|
#include "usb.h"
|
|
#include "rtc/pcf85263.h"
|
|
|
|
#define PCF85263_ADDR 0x51
|
|
|
|
// date/time registers
|
|
#define REG_100THS 0x00
|
|
#define REG_SECS 0x01
|
|
#define SECS_BIT_OS 0x80
|
|
#define REG_MINUTES 0x02
|
|
#define MINUTES_BIT_EMON 0x80
|
|
#define REG_HOURS 0x03
|
|
#define REG_DAYS 0x04
|
|
#define REG_WEEKDAY 0x05
|
|
#define REG_MONTHS 0x06
|
|
#define REG_YEARS 0x07
|
|
|
|
// control registers
|
|
#define CTRL_OSCILLATOR 0x25
|
|
#define OSC_BIT_12HR 0x20
|
|
#define CTRL_BATTERY 0x26
|
|
#define BATT_BIT_BSM_VBAT 0x02
|
|
#define CTRL_PIN_IO 0x27
|
|
#define IO_BIT_CLKPM_OFF 0x80
|
|
#define IO_BIT_INTAPM_HIZ 0x03
|
|
#define CTRL_FUNCTION 0x28
|
|
#define FUNC_BIT_COF_OFF 0x07
|
|
#define CTRL_INTA_EN 0x29
|
|
#define CTRL_INTB_EN 0x2a
|
|
#define CTRL_FLAGS 0x2b
|
|
#define CTRL_STOP_EN 0x2e
|
|
#define STOP_BIT_EN_STOP 0x01
|
|
#define CTRL_RESET 0x2f
|
|
#define RESET_CPR 0xa4
|
|
|
|
static bool pcf85263_probe(
|
|
usb_device_t *dev, const i2c_bus_t *i2c)
|
|
{
|
|
uint8_t setup[] = {
|
|
(IO_BIT_CLKPM_OFF | IO_BIT_INTAPM_HIZ)
|
|
};
|
|
|
|
// disable CLK output pin for battery saving
|
|
return i2c->bulk_write(dev, PCF85263_ADDR, CTRL_PIN_IO, setup, sizeof(setup));
|
|
}
|
|
|
|
static bool pcf85263_get_time(
|
|
usb_device_t *dev, const i2c_bus_t *i2c, ctime_t date)
|
|
{
|
|
uint8_t regs[REG_YEARS + 1];
|
|
|
|
if (!i2c->bulk_read(dev, PCF85263_ADDR, REG_100THS, regs, sizeof(regs)))
|
|
return false;
|
|
|
|
date[T_YEAR] = bcd2bin(regs[REG_YEARS]) + 100;
|
|
date[T_MONTH] = bcd2bin(regs[REG_MONTHS]);
|
|
date[T_DAY] = bcd2bin(regs[REG_DAYS]);
|
|
date[T_HOUR] = bcd2bin(regs[REG_HOURS] & 0x3f);
|
|
date[T_MIN] = bcd2bin(regs[REG_MINUTES] & 0x7f);
|
|
date[T_SEC] = bcd2bin(regs[REG_SECS] & 0x7f);
|
|
date[T_WDAY] = (regs[REG_WEEKDAY] + 1) & 0x7;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool pcf85263_set_time(
|
|
usb_device_t *dev, const i2c_bus_t *i2c, const ctime_t date)
|
|
{
|
|
uint8_t regs[REG_YEARS + 1], zero = 0,
|
|
stop_reset[] = { STOP_BIT_EN_STOP, RESET_CPR };
|
|
|
|
regs[REG_100THS] = 0;
|
|
regs[REG_YEARS] = bin2bcd(date[T_YEAR] % 100);
|
|
regs[REG_MONTHS] = bin2bcd(date[T_MONTH]);
|
|
regs[REG_DAYS] = bin2bcd(date[T_DAY]);
|
|
regs[REG_HOURS] = bin2bcd(date[T_HOUR]) & 0x3f;
|
|
regs[REG_MINUTES] = bin2bcd(date[T_MIN]);
|
|
regs[REG_SECS] = bin2bcd(date[T_SEC]);
|
|
regs[REG_WEEKDAY] = (date[T_WDAY] - 1) & 0x7;
|
|
|
|
// stop and clear prescaler
|
|
// set new time
|
|
// start
|
|
return i2c->bulk_write(dev, PCF85263_ADDR, CTRL_STOP_EN, stop_reset, sizeof(stop_reset))
|
|
&& i2c->bulk_write(dev, PCF85263_ADDR, REG_100THS, regs, sizeof(regs))
|
|
&& i2c->bulk_write(dev, PCF85263_ADDR, CTRL_STOP_EN, &zero, 1);
|
|
}
|
|
|
|
const rtc_chip_t rtc_pcf85263_chip = {
|
|
.name = "PCF85263",
|
|
.clock_rate = 400,
|
|
.probe = pcf85263_probe,
|
|
.get_time = pcf85263_get_time,
|
|
.set_time = pcf85263_set_time,
|
|
};
|