tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/pcf8523/pcf8523.go (about)

     1  // Package pcf8523 implements a driver for the PCF8523 CMOS Real-Time Clock (RTC)
     2  //
     3  // Datasheet: https://www.nxp.com/docs/en/data-sheet/PCF8523.pdf
     4  package pcf8523
     5  
     6  import (
     7  	"time"
     8  	"tinygo.org/x/drivers"
     9  )
    10  
    11  type Device struct {
    12  	bus     drivers.I2C
    13  	Address uint8
    14  }
    15  
    16  func New(i2c drivers.I2C) Device {
    17  	return Device{
    18  		bus:     i2c,
    19  		Address: DefaultAddress,
    20  	}
    21  }
    22  
    23  // Reset resets the device according to the datasheet section 8.3
    24  // This does not wipe the time registers, but resets control registers.
    25  func (d *Device) Reset() (err error) {
    26  	return d.bus.Tx(uint16(d.Address), []byte{rControl1, 0x58}, nil)
    27  }
    28  
    29  // SetPowerManagement configures how the device makes use of the backup battery, see
    30  // datasheet section 8.5
    31  func (d *Device) SetPowerManagement(b PowerManagement) error {
    32  	return d.setRegister(rControl3, byte(b)<<5, 0xE0)
    33  }
    34  
    35  func (d *Device) setRegister(reg uint8, value, mask uint8) error {
    36  	var buf [1]byte
    37  	err := d.bus.Tx(uint16(d.Address), []byte{reg}, buf[:])
    38  	if err != nil {
    39  		return err
    40  	}
    41  	buf[0] = (value & mask) | (buf[0] & (^mask))
    42  	return d.bus.Tx(uint16(d.Address), []byte{reg, buf[0]}, nil)
    43  }
    44  
    45  // SetTime sets the time and date
    46  func (d *Device) SetTime(t time.Time) error {
    47  	buf := []byte{
    48  		rSeconds,
    49  		bin2bcd(t.Second()),
    50  		bin2bcd(t.Minute()),
    51  		bin2bcd(t.Hour()),
    52  		bin2bcd(t.Day()),
    53  		bin2bcd(int(t.Weekday())),
    54  		bin2bcd(int(t.Month())),
    55  		bin2bcd(t.Year() - 2000),
    56  	}
    57  
    58  	return d.bus.Tx(uint16(d.Address), buf, nil)
    59  }
    60  
    61  // ReadTime returns the date and time
    62  func (d *Device) ReadTime() (time.Time, error) {
    63  	buf := make([]byte, 9)
    64  	err := d.bus.Tx(uint16(d.Address), []byte{rSeconds}, buf)
    65  	if err != nil {
    66  		return time.Time{}, err
    67  	}
    68  
    69  	seconds := bcd2bin(buf[0] & 0x7F)
    70  	minute := bcd2bin(buf[1] & 0x7F)
    71  	hour := bcd2bin(buf[2] & 0x3F)
    72  	day := bcd2bin(buf[3] & 0x3F)
    73  	//skipping weekday buf[4]
    74  	month := time.Month(bcd2bin(buf[5] & 0x1F))
    75  	year := int(bcd2bin(buf[6])) + 2000
    76  
    77  	t := time.Date(year, month, day, hour, minute, seconds, 0, time.UTC)
    78  	return t, nil
    79  }
    80  
    81  // bin2bcd converts binary to BCD
    82  func bin2bcd(dec int) uint8 {
    83  	return uint8(dec + 6*(dec/10))
    84  }
    85  
    86  // bcd2bin converts BCD to binary
    87  func bcd2bin(bcd uint8) int {
    88  	return int(bcd - 6*(bcd>>4))
    89  }