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 }