Files
2023-09-20 19:14:17 +02:00

90 lines
2.2 KiB
Go

// Package pcf8523 implements a driver for the PCF8523 CMOS Real-Time Clock (RTC)
//
// Datasheet: https://www.nxp.com/docs/en/data-sheet/PCF8523.pdf
package pcf8523
import (
"time"
"tinygo.org/x/drivers"
)
type Device struct {
bus drivers.I2C
Address uint8
}
func New(i2c drivers.I2C) Device {
return Device{
bus: i2c,
Address: DefaultAddress,
}
}
// Reset resets the device according to the datasheet section 8.3
// This does not wipe the time registers, but resets control registers.
func (d *Device) Reset() (err error) {
return d.bus.Tx(uint16(d.Address), []byte{rControl1, 0x58}, nil)
}
// SetPowerManagement configures how the device makes use of the backup battery, see
// datasheet section 8.5
func (d *Device) SetPowerManagement(b PowerManagement) error {
return d.setRegister(rControl3, byte(b)<<5, 0xE0)
}
func (d *Device) setRegister(reg uint8, value, mask uint8) error {
var buf [1]byte
err := d.bus.Tx(uint16(d.Address), []byte{reg}, buf[:])
if err != nil {
return err
}
buf[0] = (value & mask) | (buf[0] & (^mask))
return d.bus.Tx(uint16(d.Address), []byte{reg, buf[0]}, nil)
}
// SetTime sets the time and date
func (d *Device) SetTime(t time.Time) error {
buf := []byte{
rSeconds,
bin2bcd(t.Second()),
bin2bcd(t.Minute()),
bin2bcd(t.Hour()),
bin2bcd(t.Day()),
bin2bcd(int(t.Weekday())),
bin2bcd(int(t.Month())),
bin2bcd(t.Year() - 2000),
}
return d.bus.Tx(uint16(d.Address), buf, nil)
}
// ReadTime returns the date and time
func (d *Device) ReadTime() (time.Time, error) {
buf := make([]byte, 9)
err := d.bus.Tx(uint16(d.Address), []byte{rSeconds}, buf)
if err != nil {
return time.Time{}, err
}
seconds := bcd2bin(buf[0] & 0x7F)
minute := bcd2bin(buf[1] & 0x7F)
hour := bcd2bin(buf[2] & 0x3F)
day := bcd2bin(buf[3] & 0x3F)
//skipping weekday buf[4]
month := time.Month(bcd2bin(buf[5] & 0x1F))
year := int(bcd2bin(buf[6])) + 2000
t := time.Date(year, month, day, hour, minute, seconds, 0, time.UTC)
return t, nil
}
// bin2bcd converts binary to BCD
func bin2bcd(dec int) uint8 {
return uint8(dec + 6*(dec/10))
}
// bcd2bin converts BCD to binary
func bcd2bin(bcd uint8) int {
return int(bcd - 6*(bcd>>4))
}