mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 02:28:41 +00:00
DS3231 Alarm features (#805)
* Added alarm features * more functions * chore: fix typo * feat(ds3231): add Alarm2Mode type and mode consts * docs(ds3231): add docstrings for SQW functions * feat(ds3231): add methods for Alarm2 * fix(ds3231): use Alarm2Mode for SetAlarm2 method * docs(ds3231): add example for alarms * docs(ds3231): refactor alarms example * make main function more concise to avoid llvm error for pico * ci(ds3231): split basic and alarm tests * style(ds3231): reorder private funcs to the bottom * docs(ds3231): add docstring for alarm modes * docs(ds3231): make alarm docstrings more descriptive * chore(ds3231): fix typo in docstring * style(ds3231): reorder public functions * style(ds3231): reorder private methods * chore(ds3231): add missing error handling * feat(ds3231): use setter funcs for en/disabling instead of separate funcs * fix(ds3231): correctly enable alarms in example * style(ds3231): rename SetEnable32K to SetEnabled32K for consistency * refactor(ds3231): replace legacy with regmap package * refactor(ds3231): use Write32 instead of Tx for SetAlarm1 * chore(ds3231): remove fmt deps and and use println in examples * refactor(ds3231): read temperature as uint16 --------- Co-authored-by: Matthias Fulz <mfulz@olznet.de>
This commit is contained in:
+288
-36
@@ -5,10 +5,12 @@
|
||||
package ds3231 // import "tinygo.org/x/drivers/ds3231"
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/internal/legacy"
|
||||
"tinygo.org/x/drivers/internal/regmap"
|
||||
)
|
||||
|
||||
type Mode uint8
|
||||
@@ -17,6 +19,7 @@ type Mode uint8
|
||||
type Device struct {
|
||||
bus drivers.I2C
|
||||
Address uint16
|
||||
d regmap.Device8I2C
|
||||
}
|
||||
|
||||
// New creates a new DS3231 connection. The I2C bus must already be
|
||||
@@ -24,54 +27,50 @@ type Device struct {
|
||||
//
|
||||
// This function only creates the Device object, it does not touch the device.
|
||||
func New(bus drivers.I2C) Device {
|
||||
return Device{
|
||||
d := Device{
|
||||
bus: bus,
|
||||
Address: Address,
|
||||
}
|
||||
d.Configure()
|
||||
return d
|
||||
}
|
||||
|
||||
// Configure sets up the device for communication
|
||||
func (d *Device) Configure() bool {
|
||||
d.d.SetBus(d.bus, d.Address, binary.BigEndian)
|
||||
return true
|
||||
}
|
||||
|
||||
// IsTimeValid return true/false is the time in the device is valid
|
||||
func (d *Device) IsTimeValid() bool {
|
||||
data := []byte{0}
|
||||
err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_STATUS, data)
|
||||
status, err := d.d.Read8(REG_STATUS)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return (data[0] & (1 << OSF)) == 0x00
|
||||
return (status & (1 << OSF)) == 0x00
|
||||
}
|
||||
|
||||
// IsRunning returns if the oscillator is running
|
||||
func (d *Device) IsRunning() bool {
|
||||
data := []uint8{0}
|
||||
err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_CONTROL, data)
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return (data[0] & (1 << EOSC)) == 0x00
|
||||
return (control & (1 << EOSC)) == 0x00
|
||||
}
|
||||
|
||||
// SetRunning starts the internal oscillator
|
||||
func (d *Device) SetRunning(isRunning bool) error {
|
||||
data := []uint8{0}
|
||||
err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_CONTROL, data)
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isRunning {
|
||||
data[0] &^= uint8(1 << EOSC)
|
||||
control &^= uint8(1 << EOSC)
|
||||
} else {
|
||||
data[0] |= 1 << EOSC
|
||||
control |= 1 << EOSC
|
||||
}
|
||||
err = legacy.WriteRegister(d.bus, uint8(d.Address), REG_CONTROL, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return d.d.Write8(REG_CONTROL, control)
|
||||
}
|
||||
|
||||
// SetTime sets the date and time in the DS3231. The DS3231 hardware supports
|
||||
@@ -86,18 +85,16 @@ func (d *Device) SetRunning(isRunning bool) error {
|
||||
// 2100 as a leap year, causing it to increment from 2100-02-28 to 2100-02-29
|
||||
// instead of 2100-03-01.
|
||||
func (d *Device) SetTime(dt time.Time) error {
|
||||
data := []byte{0}
|
||||
err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_STATUS, data)
|
||||
status, err := d.d.Read8(REG_STATUS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data[0] &^= 1 << OSF
|
||||
err = legacy.WriteRegister(d.bus, uint8(d.Address), REG_STATUS, data)
|
||||
if err != nil {
|
||||
status &^= 1 << OSF
|
||||
if err = d.d.Write8(REG_STATUS, status); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data = make([]uint8, 7)
|
||||
data := make([]uint8, 7)
|
||||
data[0] = uint8ToBCD(uint8(dt.Second()))
|
||||
data[1] = uint8ToBCD(uint8(dt.Minute()))
|
||||
data[2] = uint8ToBCD(uint8(dt.Hour()))
|
||||
@@ -118,21 +115,16 @@ func (d *Device) SetTime(dt time.Time) error {
|
||||
data[5] = uint8ToBCD(uint8(dt.Month()) | centuryFlag)
|
||||
data[6] = uint8ToBCD(year)
|
||||
|
||||
err = legacy.WriteRegister(d.bus, uint8(d.Address), REG_TIMEDATE, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return d.bus.Tx(d.Address, append([]byte{REG_TIMEDATE}, data...), nil)
|
||||
}
|
||||
|
||||
// ReadTime returns the date and time
|
||||
func (d *Device) ReadTime() (dt time.Time, err error) {
|
||||
data := make([]uint8, 7)
|
||||
err = legacy.ReadRegister(d.bus, uint8(d.Address), REG_TIMEDATE, data)
|
||||
if err != nil {
|
||||
if err = d.d.ReadData(REG_TIMEDATE, data); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
second := bcdToInt(data[0] & 0x7F)
|
||||
minute := bcdToInt(data[1])
|
||||
hour := hoursBCDToInt(data[2])
|
||||
@@ -150,12 +142,264 @@ func (d *Device) ReadTime() (dt time.Time, err error) {
|
||||
|
||||
// ReadTemperature returns the temperature in millicelsius (mC)
|
||||
func (d *Device) ReadTemperature() (int32, error) {
|
||||
data := make([]uint8, 2)
|
||||
err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_TEMP, data)
|
||||
temp, err := d.d.Read16(REG_TEMP)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return milliCelsius(data[0], data[1]), nil
|
||||
return milliCelsius(temp), nil
|
||||
}
|
||||
|
||||
// GetSqwPinMode returns the current square wave output frequency
|
||||
func (d *Device) GetSqwPinMode() SqwPinMode {
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return SQW_OFF
|
||||
}
|
||||
|
||||
control &= 0x1C // turn off INTCON
|
||||
if control&0x04 != 0 {
|
||||
return SQW_OFF
|
||||
}
|
||||
|
||||
return SqwPinMode(control)
|
||||
}
|
||||
|
||||
// SetSqwPinMode sets the square wave output mode to the given frequency
|
||||
func (d *Device) SetSqwPinMode(mode SqwPinMode) error {
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
control &^= 0x04 // turn off INTCON
|
||||
control &^= 0x18 // set freq bits to 0
|
||||
|
||||
control |= uint8(mode)
|
||||
|
||||
return d.d.Write8(REG_CONTROL, control)
|
||||
}
|
||||
|
||||
// SetAlarm1 sets alarm1 to the given time and mode
|
||||
func (d *Device) SetAlarm1(dt time.Time, mode Alarm1Mode) error {
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if control&(1<<INTCN) == 0x00 {
|
||||
return errors.New("INTCN has to be disabled")
|
||||
}
|
||||
|
||||
A1M1 := uint8((mode & 0x01) << 7)
|
||||
A1M2 := uint8((mode & 0x02) << 6)
|
||||
A1M3 := uint8((mode & 0x04) << 5)
|
||||
A1M4 := uint8((mode & 0x08) << 4)
|
||||
DY_DT := uint8((mode & 0x10) << 2)
|
||||
|
||||
day := dt.Day()
|
||||
if DY_DT > 0 {
|
||||
day = dowToDS3231(int(dt.Weekday()))
|
||||
}
|
||||
|
||||
alarm1 := uint32(uint8ToBCD(uint8(dt.Second()))|A1M1) << 24
|
||||
alarm1 |= uint32(uint8ToBCD(uint8(dt.Minute()))|A1M2) << 16
|
||||
alarm1 |= uint32(uint8ToBCD(uint8(dt.Hour()))|A1M3) << 8
|
||||
alarm1 |= uint32(uint8ToBCD(uint8(day)) | A1M4 | DY_DT)
|
||||
|
||||
if err := d.d.Write32(REG_ALARMONE, alarm1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
control |= AlarmFlag_Alarm1
|
||||
return d.d.Write8(REG_CONTROL, control)
|
||||
}
|
||||
|
||||
// ReadAlarm1 returns the alarm1 time
|
||||
func (d *Device) ReadAlarm1() (dt time.Time, err error) {
|
||||
data := make([]uint8, 4)
|
||||
if err = d.d.ReadData(REG_ALARMONE, data); err != nil {
|
||||
return
|
||||
}
|
||||
second := bcdToInt(data[0] & 0x7F)
|
||||
minute := bcdToInt(data[1] & 0x7F)
|
||||
hour := hoursBCDToInt(data[2] & 0x3F)
|
||||
|
||||
isDayOfWeek := (data[3] & 0x40) >> 6
|
||||
var day int
|
||||
if isDayOfWeek > 0 {
|
||||
day = bcdToInt(data[3] & 0x0F)
|
||||
} else {
|
||||
day = bcdToInt(data[3] & 0x3F)
|
||||
}
|
||||
|
||||
dt = time.Date(2000, 5, day, hour, minute, second, 0, time.UTC)
|
||||
return
|
||||
}
|
||||
|
||||
// SetAlarm2 sets alarm2 to the given time and mode
|
||||
func (d *Device) SetAlarm2(dt time.Time, mode Alarm2Mode) error {
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if control&(1<<INTCN) == 0x00 {
|
||||
return errors.New("INTCN has to be disabled")
|
||||
}
|
||||
|
||||
A2M2 := uint8((mode & 0x01) << 7)
|
||||
A2M3 := uint8((mode & 0x02) << 6)
|
||||
A2M4 := uint8((mode & 0x04) << 5)
|
||||
DY_DT := uint8((mode & 0x08) << 3)
|
||||
|
||||
day := dt.Day()
|
||||
if DY_DT > 0 {
|
||||
day = dowToDS3231(int(dt.Weekday()))
|
||||
}
|
||||
|
||||
data := make([]uint8, 4)
|
||||
data[0] = uint8ToBCD(uint8(dt.Minute())) | A2M2
|
||||
data[1] = uint8ToBCD(uint8(dt.Hour())) | A2M3
|
||||
data[2] = uint8ToBCD(uint8(day)) | A2M4 | DY_DT
|
||||
if err = d.bus.Tx(d.Address, append([]byte{REG_ALARMTWO}, data...), nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
control |= AlarmFlag_Alarm2
|
||||
return d.d.Write8(REG_CONTROL, control)
|
||||
}
|
||||
|
||||
// ReadAlarm2 returns the alarm2 time
|
||||
func (d *Device) ReadAlarm2() (dt time.Time, err error) {
|
||||
data := make([]uint8, 3)
|
||||
if err = d.d.ReadData(REG_ALARMTWO, data); err != nil {
|
||||
return
|
||||
}
|
||||
minute := bcdToInt(data[0] & 0x7F)
|
||||
hour := hoursBCDToInt(data[1] & 0x3F)
|
||||
|
||||
isDayOfWeek := (data[2] & 0x40) >> 6
|
||||
var day int
|
||||
if isDayOfWeek > 0 {
|
||||
day = bcdToInt(data[2] & 0x0F)
|
||||
} else {
|
||||
day = bcdToInt(data[2] & 0x3F)
|
||||
}
|
||||
|
||||
dt = time.Date(2000, 5, day, hour, minute, 0, 0, time.UTC)
|
||||
return
|
||||
}
|
||||
|
||||
// IsEnabledAlarm1 returns true when alarm1 is enabled
|
||||
func (d *Device) IsEnabledAlarm1() bool {
|
||||
return d.isEnabledAlarm(1)
|
||||
}
|
||||
|
||||
// SetEnabledAlarm1 sets the enabled status of alarm1
|
||||
func (d *Device) SetEnabledAlarm1(enable bool) error {
|
||||
if enable {
|
||||
return d.enableAlarm(1)
|
||||
}
|
||||
return d.disableAlarm(1)
|
||||
}
|
||||
|
||||
// IsEnabledAlarm2 returns true when alarm2 is enabled
|
||||
func (d *Device) IsEnabledAlarm2() bool {
|
||||
return d.isEnabledAlarm(2)
|
||||
}
|
||||
|
||||
// SetEnabledAlarm2 sets the enabled status of alarm2
|
||||
func (d *Device) SetEnabledAlarm2(enable bool) error {
|
||||
if enable {
|
||||
return d.enableAlarm(2)
|
||||
}
|
||||
return d.disableAlarm(2)
|
||||
}
|
||||
|
||||
// ClearAlarm1 clears status of alarm1
|
||||
func (d *Device) ClearAlarm1() error {
|
||||
return d.clearAlarm(1)
|
||||
}
|
||||
|
||||
// ClearAlarm2 clears status of alarm2
|
||||
func (d *Device) ClearAlarm2() error {
|
||||
return d.clearAlarm(2)
|
||||
}
|
||||
|
||||
// IsAlarm1Fired returns true when alarm1 is firing
|
||||
func (d *Device) IsAlarm1Fired() bool {
|
||||
return d.isAlarmFired(1)
|
||||
}
|
||||
|
||||
// IsAlarm2Fired returns true when alarm2 is firing
|
||||
func (d *Device) IsAlarm2Fired() bool {
|
||||
return d.isAlarmFired(2)
|
||||
}
|
||||
|
||||
// SetEnabled32K sets the enabled status of the 32KHz output
|
||||
func (d *Device) SetEnabled32K(enable bool) error {
|
||||
status, err := d.d.Read8(REG_STATUS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if enable {
|
||||
status |= 1 << EN32KHZ
|
||||
} else {
|
||||
status &^= 1 << EN32KHZ
|
||||
}
|
||||
|
||||
return d.d.Write8(REG_STATUS, status)
|
||||
}
|
||||
|
||||
// IsEnabled32K returns true when the 32KHz output is enabled
|
||||
func (d *Device) IsEnabled32K() bool {
|
||||
status, err := d.d.Read8(REG_STATUS)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return (status & (1 << EN32KHZ)) != 0x00
|
||||
}
|
||||
|
||||
func (d *Device) disableAlarm(alarm_num uint8) error {
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
control &^= (1 << (alarm_num - 1))
|
||||
return d.d.Write8(REG_CONTROL, control)
|
||||
}
|
||||
|
||||
func (d *Device) enableAlarm(alarm_num uint8) error {
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
control |= (1 << (alarm_num - 1))
|
||||
return d.d.Write8(REG_CONTROL, control)
|
||||
}
|
||||
|
||||
func (d *Device) isEnabledAlarm(alarm_num uint8) bool {
|
||||
control, err := d.d.Read8(REG_CONTROL)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return (control & (1 << (alarm_num - 1))) != 0x00
|
||||
}
|
||||
|
||||
func (d *Device) clearAlarm(alarm_num uint8) error {
|
||||
status, err := d.d.Read8(REG_STATUS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
status &^= (1 << (alarm_num - 1))
|
||||
return d.d.Write8(REG_STATUS, status)
|
||||
}
|
||||
|
||||
func (d *Device) isAlarmFired(alarm_num uint8) bool {
|
||||
status, err := d.d.Read8(REG_STATUS)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return (status & (1 << (alarm_num - 1))) != 0x00
|
||||
}
|
||||
|
||||
// milliCelsius converts the raw temperature bytes (msb and lsb) from the DS3231
|
||||
@@ -172,8 +416,8 @@ func (d *Device) ReadTemperature() (int32, error) {
|
||||
// 16-bit signed integer in units of centi Celsius (1/100 deg C) with no loss of
|
||||
// precision or dynamic range. But for backwards compatibility, let's instead
|
||||
// convert this into a 32-bit signed integer in units of milli Celsius.
|
||||
func milliCelsius(msb uint8, lsb uint8) int32 {
|
||||
t256 := int16(uint16(msb)<<8 | uint16(lsb))
|
||||
func milliCelsius(tempBytes uint16) int32 {
|
||||
t256 := int16(uint16(tempBytes>>8)<<8 | uint16(tempBytes&0xFF))
|
||||
t1000 := int32(t256) / 64 * 250
|
||||
return t1000
|
||||
}
|
||||
@@ -200,3 +444,11 @@ func hoursBCDToInt(value uint8) (hour int) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// dowToDS3231 converts the day of the week to internal DS3231 format
|
||||
func dowToDS3231(d int) int {
|
||||
if d == 0 {
|
||||
return 7
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
+13
-13
@@ -5,71 +5,71 @@ import (
|
||||
)
|
||||
|
||||
func TestPositiveMilliCelsius(t *testing.T) {
|
||||
t1000 := milliCelsius(0, 0)
|
||||
t1000 := milliCelsius(0)
|
||||
if t1000 != 0 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(0, 0b01000000)
|
||||
t1000 = milliCelsius(0b0000000001000000)
|
||||
if t1000 != 250 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(0, 0b10000000)
|
||||
t1000 = milliCelsius(0b0000000010000000)
|
||||
if t1000 != 500 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(0, 0b11000000)
|
||||
t1000 = milliCelsius(0b0000000011000000)
|
||||
if t1000 != 750 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(1, 0b00000000)
|
||||
t1000 = milliCelsius(0b0000000100000000)
|
||||
if t1000 != 1000 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(2, 0b00000000)
|
||||
t1000 = milliCelsius(0b0000001000000000)
|
||||
if t1000 != 2000 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
// highest temperature is 127.750C
|
||||
t1000 = milliCelsius(0x7f, 0b11000000)
|
||||
t1000 = milliCelsius(0b0111111111000000)
|
||||
if t1000 != 127750 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegativeMilliCelsius(t *testing.T) {
|
||||
t1000 := milliCelsius(0xff, 0b11000000)
|
||||
t1000 := milliCelsius(0b1111111111000000)
|
||||
if t1000 != -250 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(0xff, 0b10000000)
|
||||
t1000 = milliCelsius(0b1111111110000000)
|
||||
if t1000 != -500 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(0xff, 0b01000000)
|
||||
t1000 = milliCelsius(0b1111111101000000)
|
||||
if t1000 != -750 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(0xff, 0b00000000)
|
||||
t1000 = milliCelsius(0b1111111100000000)
|
||||
if t1000 != -1000 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
t1000 = milliCelsius(0xfe, 0b00000000)
|
||||
t1000 = milliCelsius(0b1111111000000000)
|
||||
if t1000 != -2000 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
// lowest temperature is -128.000C
|
||||
t1000 = milliCelsius(0x80, 0b00000000)
|
||||
t1000 = milliCelsius(0b1000000000000000)
|
||||
if t1000 != -128000 {
|
||||
t.Fatal(t1000)
|
||||
}
|
||||
|
||||
@@ -46,3 +46,52 @@ const (
|
||||
AlarmTwo Mode = 4
|
||||
ModeAlarmBoth Mode = 5
|
||||
)
|
||||
|
||||
// SQW Pin Modes
|
||||
type SqwPinMode uint8
|
||||
|
||||
const (
|
||||
SQW_OFF SqwPinMode = 0x1C
|
||||
SQW_1HZ SqwPinMode = 0x00
|
||||
SQW_1KHZ SqwPinMode = 0x08
|
||||
SQW_4KHZ SqwPinMode = 0x10
|
||||
SQW_8KHZ SqwPinMode = 0x18
|
||||
)
|
||||
|
||||
// Alarm1 Modes define which parts of the set alarm time has to match the current timestamp of the clock device for
|
||||
// alarm1 to fire
|
||||
type Alarm1Mode uint8
|
||||
|
||||
const (
|
||||
// Alarm1 fires every second
|
||||
A1_PER_SECOND Alarm1Mode = 0x0F
|
||||
// Alarm1 fires when the seconds match
|
||||
A1_SECOND Alarm1Mode = 0x0E
|
||||
// Alarm1 fires when both seconds and minutes match
|
||||
A1_MINUTE Alarm1Mode = 0x0C
|
||||
// Alarm1 fires when seconds, minutes and hours match
|
||||
A1_HOUR Alarm1Mode = 0x08
|
||||
// Alarm1 fires when seconds, minutes, hours and the day of the month match
|
||||
A1_DATE Alarm1Mode = 0x00
|
||||
// Alarm1 fires when seconds, minutes, hours and the day of the week match
|
||||
A1_DAY Alarm1Mode = 0x10
|
||||
)
|
||||
|
||||
// Alarm2 Modes define which parts of the set alarm time has to match the current timestamp of the clock device for
|
||||
// alarm2 to fire.
|
||||
//
|
||||
// Alarm2 only supports matching down to the minute unlike alarm1 which supports matching down to the second.
|
||||
type Alarm2Mode uint8
|
||||
|
||||
const (
|
||||
// Alarm2 fires every minute
|
||||
A2_PER_MINUTE Alarm2Mode = 0x07
|
||||
// Alarm2 fires when the minutes match
|
||||
A2_MINUTE Alarm2Mode = 0x06
|
||||
// Alarm2 fires when both minutes and hours match
|
||||
A2_HOUR Alarm2Mode = 0x04
|
||||
// Alarm2 fires when minutes, hours and the day of the month match
|
||||
A2_DATE Alarm2Mode = 0x00
|
||||
// Alarm2 fires when minutes, hours and the day of the week match
|
||||
A2_DAY Alarm2Mode = 0x08
|
||||
)
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Connects to an DS3231 I2C Real Time Clock (RTC) and sets both alarms. It then repeatedly checks
|
||||
// if the alarms are firing and prints out a message if that is the case.
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/ds3231"
|
||||
)
|
||||
|
||||
func main() {
|
||||
machine.I2C0.Configure(machine.I2CConfig{})
|
||||
|
||||
rtc := ds3231.New(machine.I2C0)
|
||||
rtc.Configure()
|
||||
|
||||
valid := rtc.IsTimeValid()
|
||||
if !valid {
|
||||
date := time.Date(2019, 12, 05, 20, 34, 12, 0, time.UTC)
|
||||
rtc.SetTime(date)
|
||||
}
|
||||
|
||||
// Set alarm1 so it triggers when the seconds match 59 => repeats every minute at dd:hh:mm:59
|
||||
if err := rtc.SetAlarm1(time.Date(0, 0, 0, 0, 0, 59, 0, time.UTC), ds3231.A1_SECOND); err != nil {
|
||||
println("Error while setting Alarm1")
|
||||
}
|
||||
if err := rtc.SetEnabledAlarm1(true); err != nil {
|
||||
println("Error while enabling Alarm1")
|
||||
}
|
||||
|
||||
// Set alarm2 so it triggers when the minutes match 35 => repeats every hour at dd:hh:35:ss
|
||||
if err := rtc.SetAlarm2(time.Date(0, 0, 0, 0, 35, 0, 0, time.UTC), ds3231.A2_MINUTE); err != nil {
|
||||
println("Error while setting Alarm2")
|
||||
}
|
||||
if err := rtc.SetEnabledAlarm2(true); err != nil {
|
||||
println("Error while enabling Alarm2")
|
||||
}
|
||||
|
||||
running := rtc.IsRunning()
|
||||
if !running {
|
||||
err := rtc.SetRunning(true)
|
||||
if err != nil {
|
||||
println("Error configuring RTC")
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
dt, err := rtc.ReadTime()
|
||||
if err != nil {
|
||||
println("Error reading date:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
a1 := rtc.IsAlarm1Fired()
|
||||
a2 := rtc.IsAlarm2Fired()
|
||||
|
||||
println(dt.Format(time.DateTime), "A1:", a1, "A2:", a2)
|
||||
|
||||
if a1 {
|
||||
if err := rtc.ClearAlarm1(); err != nil {
|
||||
println("Error while clearing alarm1")
|
||||
}
|
||||
}
|
||||
if a2 {
|
||||
if err := rtc.ClearAlarm2(); err != nil {
|
||||
println("Error while clearing alarm2")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,9 @@ package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"fmt"
|
||||
|
||||
"tinygo.org/x/drivers/ds3231"
|
||||
)
|
||||
|
||||
@@ -26,19 +25,19 @@ func main() {
|
||||
if !running {
|
||||
err := rtc.SetRunning(true)
|
||||
if err != nil {
|
||||
fmt.Println("Error configuring RTC")
|
||||
println("Error configuring RTC")
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
dt, err := rtc.ReadTime()
|
||||
if err != nil {
|
||||
fmt.Println("Error reading date:", err)
|
||||
println("Error reading date:", err)
|
||||
} else {
|
||||
fmt.Printf("Date: %d/%s/%02d %02d:%02d:%02d \r\n", dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute(), dt.Second())
|
||||
println(dt.Format(time.DateTime))
|
||||
}
|
||||
temp, _ := rtc.ReadTemperature()
|
||||
fmt.Printf("Temperature: %.2f °C \r\n", float32(temp)/1000)
|
||||
println("Temperature:", strconv.FormatFloat(float64(temp)/1000, 'f', -1, 32), "°C")
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
+2
-1
@@ -22,7 +22,8 @@ tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp
|
||||
tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bmp388/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/sram/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/time/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/alarms/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/basic/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/easystepper/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/flash/console/spi
|
||||
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/flash/console/qspi
|
||||
|
||||
Reference in New Issue
Block a user