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

     1  // Package pcf8563 implements a driver for the PCF8563 CMOS Real-Time Clock (RTC)
     2  //
     3  // Datasheet: https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf
     4  //
     5  
     6  package pcf8563
     7  
     8  import (
     9  	"time"
    10  
    11  	"tinygo.org/x/drivers"
    12  )
    13  
    14  // Device wraps an I2C connection to a PCF8563 device.
    15  type Device struct {
    16  	bus     drivers.I2C
    17  	Address uint16
    18  }
    19  
    20  // New creates a new PCF8563 connection. I2C bus must be already configured.
    21  func New(i2c drivers.I2C) Device {
    22  	return Device{
    23  		bus:     i2c,
    24  		Address: PCF8563_ADDR,
    25  	}
    26  }
    27  
    28  // Reset resets the `control and status registers`. When this method is
    29  // called, it writes `0x00` to the `control and status registers`. This will
    30  // cause `Alarm` and `Timer` to become Inactive. Please refer to the datasheet
    31  // for details.
    32  func (d *Device) Reset() (err error) {
    33  	return d.bus.Tx(d.Address, []byte{0x00, 0x00, 0x00}, nil)
    34  }
    35  
    36  // SetTime sets the time and date
    37  func (d *Device) SetTime(t time.Time) error {
    38  	var buf [9]byte
    39  	buf[0] = 0x02
    40  	buf[1] = decToBcd(t.Second())
    41  	buf[2] = decToBcd(t.Minute())
    42  	buf[3] = decToBcd(t.Hour())
    43  	buf[4] = decToBcd(t.Day())
    44  	buf[5] = decToBcd(int(t.Weekday() + 1))
    45  	buf[6] = decToBcd(int(t.Month()))
    46  	buf[7] = decToBcd(t.Year() - 2000)
    47  	err := d.bus.Tx(d.Address, buf[:], nil)
    48  	return err
    49  }
    50  
    51  // ReadTime returns the date and time
    52  func (d *Device) ReadTime() (time.Time, error) {
    53  	var buf [9]byte
    54  	err := d.bus.Tx(d.Address, []byte{0x00}, buf[:])
    55  	if err != nil {
    56  		return time.Time{}, err
    57  	}
    58  
    59  	seconds := bcdToDec(buf[2] & 0x7F)
    60  	minute := bcdToDec(buf[3] % 0x7F)
    61  	hour := bcdToDec(buf[4] & 0x3F)
    62  	day := bcdToDec(buf[5] & 0x3F)
    63  	month := time.Month(bcdToDec(buf[7] & 0x0F))
    64  	year := int(bcdToDec(buf[8])) + 2000
    65  
    66  	t := time.Date(year, month, day, hour, minute, seconds, 0, time.UTC)
    67  	return t, nil
    68  }
    69  
    70  // SetAlarm sets the alarm
    71  func (d *Device) SetAlarm(t time.Time) error {
    72  	var buf [5]byte
    73  	buf[0] = 0x09
    74  	buf[1] = RTC_ALARM_ENABLE | decToBcd(t.Minute())
    75  	buf[2] = RTC_ALARM_ENABLE | decToBcd(t.Hour())
    76  	buf[3] = RTC_ALARM_ENABLE | decToBcd(t.Day())
    77  	buf[4] = RTC_ALARM_DISABLE
    78  	err := d.bus.Tx(d.Address, buf[:], nil)
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	// enable alarm
    84  	buf[0] = 0x01
    85  	err = d.bus.Tx(d.Address, buf[:1], buf[1:])
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	buf[1] |= RTC_CTRL_AF
    91  	err = d.bus.Tx(d.Address, buf[:2], nil)
    92  	return err
    93  }
    94  
    95  // ClearAlarm disables alarm.
    96  func (d *Device) ClearAlarm() error {
    97  	var buf [2]byte
    98  	buf[0] = 0x01
    99  	err := d.bus.Tx(d.Address, buf[:1], buf[1:])
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	buf[1] &= ^uint8(RTC_CTRL_AF)
   105  	err = d.bus.Tx(d.Address, buf[:], nil)
   106  	return err
   107  }
   108  
   109  // EnableAlarmInterrupt enables alarm interrupt. When triggered, INT pin (3)
   110  // goes low.
   111  func (d *Device) EnableAlarmInterrupt() error {
   112  	var buf [2]byte
   113  	buf[0] = 0x01
   114  	err := d.bus.Tx(d.Address, buf[:1], buf[1:])
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	buf[1] |= RTC_CTRL_AIE
   120  	err = d.bus.Tx(d.Address, buf[:], nil)
   121  	return err
   122  }
   123  
   124  // DisableAlarmInterrupt disable alarm interrupt.
   125  func (d *Device) DisableAlarmInterrupt() error {
   126  	var buf [2]byte
   127  	buf[0] = 0x01
   128  	err := d.bus.Tx(d.Address, buf[:1], buf[1:])
   129  	if err != nil {
   130  		return err
   131  	}
   132  
   133  	buf[1] &= ^uint8(RTC_CTRL_AIE)
   134  	err = d.bus.Tx(d.Address, buf[:], nil)
   135  	return err
   136  }
   137  
   138  // AlarmTriggered returns whether or not an Alarm has been triggered.
   139  func (d *Device) AlarmTriggered() bool {
   140  	var buf [1]byte
   141  	buf[0] = 0x01
   142  	err := d.bus.Tx(d.Address, buf[:], buf[:])
   143  	if err != nil {
   144  		return false
   145  	}
   146  	return (buf[0] & RTC_CTRL_AF) != 0
   147  }
   148  
   149  // SetTimer sets timer. The available durations are 1 to 127 seconds.  If any
   150  // other value is specified, it will be truncated.
   151  func (d *Device) SetTimer(dur time.Duration) error {
   152  	var buf [3]byte
   153  
   154  	sec := dur / time.Second
   155  	if sec > 127 {
   156  		sec = 127
   157  	}
   158  
   159  	// Treat as sec timer.
   160  	buf[0] = 0x0E
   161  	buf[1] = RTC_TIMER_1S
   162  	buf[2] = byte(sec)
   163  	err := d.bus.Tx(d.Address, buf[:], nil)
   164  	if err != nil {
   165  		return err
   166  	}
   167  
   168  	// enable alarm
   169  	buf[0] = 0x01
   170  	err = d.bus.Tx(d.Address, buf[:1], buf[1:])
   171  	if err != nil {
   172  		return err
   173  	}
   174  
   175  	buf[1] |= RTC_CTRL_TF
   176  	err = d.bus.Tx(d.Address, buf[:2], nil)
   177  	return err
   178  }
   179  
   180  // ClearTimer disables timer.
   181  func (d *Device) ClearTimer() error {
   182  	var buf [2]byte
   183  	buf[0] = 0x01
   184  	err := d.bus.Tx(d.Address, buf[:1], buf[1:])
   185  	if err != nil {
   186  		return err
   187  	}
   188  
   189  	buf[1] &= ^uint8(RTC_CTRL_TF)
   190  	err = d.bus.Tx(d.Address, buf[:], nil)
   191  	return err
   192  }
   193  
   194  // EnableTimerInterrupt enables timer interrupt. When triggered, INT pin (3)
   195  // goes low.
   196  func (d *Device) EnableTimerInterrupt() error {
   197  	var buf [2]byte
   198  	buf[0] = 0x01
   199  	err := d.bus.Tx(d.Address, buf[:1], buf[1:])
   200  	if err != nil {
   201  		return err
   202  	}
   203  
   204  	buf[1] |= RTC_CTRL_TIE
   205  	err = d.bus.Tx(d.Address, buf[:], nil)
   206  	return err
   207  }
   208  
   209  // DisableTimerInterrupt disable timer interrupt.
   210  func (d *Device) DisableTimerInterrupt() error {
   211  	var buf [2]byte
   212  	buf[0] = 0x01
   213  	err := d.bus.Tx(d.Address, buf[:1], buf[1:])
   214  	if err != nil {
   215  		return err
   216  	}
   217  
   218  	buf[1] &= ^uint8(RTC_CTRL_TIE)
   219  	err = d.bus.Tx(d.Address, buf[:], nil)
   220  	return err
   221  }
   222  
   223  // TimerTriggered returns whether or not an Alarm has been triggered.
   224  func (d *Device) TimerTriggered() bool {
   225  	var buf [1]byte
   226  	buf[0] = 0x01
   227  	err := d.bus.Tx(d.Address, buf[:], buf[:])
   228  	if err != nil {
   229  		return false
   230  	}
   231  	return (buf[0] & RTC_CTRL_TF) != 0
   232  }
   233  
   234  // SetOscillatorFrequency sets output oscillator frequency
   235  // Available modes: RTC_COT_DISABLE, RTC_COT_32KHZ, RTC_COT_1KHZ,
   236  // RTC_COT_32Hz, RTC_COT_1HZ.
   237  func (d *Device) SetOscillatorFrequency(sqw uint8) error {
   238  	var buf [2]byte
   239  	buf[0] = 0x0D
   240  	buf[1] = sqw
   241  	return d.bus.Tx(d.Address, buf[:], nil)
   242  }
   243  
   244  // decToBcd converts int to BCD
   245  func decToBcd(dec int) uint8 {
   246  	return uint8(dec + 6*(dec/10))
   247  }
   248  
   249  // bcdToDec converts BCD to int
   250  func bcdToDec(bcd uint8) int {
   251  	return int(bcd - 6*(bcd>>4))
   252  }