You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

255 lines
8.4 KiB

#ifndef GUARD_DS3231_H
#define GUARD_DS3231_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#define DS3231_ADDRESS_READ 0b11010001
#define DS3231_ADDRESS_WRITE 0b11010000
#define DS3231_OPERATION_SUCCESS 0 // this is returned if a function ran without errors
// general time keeping registers
#define DS3231_REGISTER_SECONDS 0
#define DS3231_REGISTER_MINUTES 0x1
#define DS3231_REGISTER_HOURS 0x2
#define DS3231_REGISTER_DAY 0x3
#define DS3231_REGISTER_DATE 0x4
#define DS3231_REGISTER_MONTH_CENTURY 0x5
#define DS3231_REGISTER_YEAR 0x6
// alarm 1 registers
#define DS3231_REGISTER_ALARM1_SECONDS 0x7
#define DS3231_REGISTER_ALARM1_MINUTES 0x8
#define DS3231_REGISTER_ALARM1_HOURS 0x9
#define DS3231_REGISTER_ALARM1_DAY_DATE 0xa
// alarm 1 trigger interval bits
#define DS3231_ALARM1_A1M1_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.)
#define DS3231_ALARM1_A1M2_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.)
#define DS3231_ALARM1_A1M3_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.)
#define DS3231_ALARM1_A1M4_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.)
// alarm 2 registers
#define DS3231_REGISTER_ALARM2_MINUTES 0xb
#define DS3231_REGISTER_ALARM2_HOURS 0xc
#define DS3231_REGISTER_ALARM2_DAY_DATE 0xd
// alarm 2 trigger interval bits
#define DS3231_ALARM2_A2M2_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.)
#define DS3231_ALARM2_A2M3_BIT (1 << 7)
#define DS3231_ALARM2_A2M4_BIT (1 << 7)
// other alarm bits
#define DS3231_ALARM_DAY_BIT (1 << 6) // used to indicate if an alarm is set for a DAY or DATE
// control register
#define DS3231_REGISTER_CONTROL 0xe
// control register bits
#define DS3231_CONTROL_EOSC_BIT (1 << 7)
#define DS3231_CONTROL_BBQSW_BIT (1 << 6)
#define DS3231_CONTROL_CONV_BIT (1 << 5)
#define DS3231_CONTROL_RS2_BIT (1 << 4)
#define DS3231_CONTROL_RS1_BIT (1 << 3)
#define DS3231_CONTROL_INTCN_BIT (1 << 2) // enable interrupts
#define DS3231_CONTROL_A2IE_BIT (1 << 1) // enable alarm 2
#define DS3231_CONTROL_A1IE_BIT (1 << 0) // enable alarm 1
// status register
#define DS3231_REGISTER_STATUS 0xf
// status register bits
#define DS3231_STATUS_OSF_BIT (1 << 7) // oscillator stop
#define DS3231_STATUS_EN32KHZ_BIT (1 << 3) // enable 32KHz square wave output
#define DS3231_STATUS_BSY_BIT (1 << 2) // device busy bit
#define DS3231_STATUS_A2F_BIT (1 << 1) // alarm 2 triggered flag
#define DS3231_STATUS_A1F_BIT (1 << 0) // alarm 1 triggered flag
// aging register
#define DS3231_REGISTER_AGING_OFFSET 0x10
// temperature registers
#define DS3231_REGISTER_TEMPERATURE_MSB 0x11
#define DS3231_REGISTER_TEMPERATURE_LSB 0x12
// special toggle bits
#define DS3231_HOUR_MODE_12_BIT (1 << 6) // this will be 1 in the HOURS register if 12 hour mode is selected. 0 if 24 hour mode selected
#define DS3231_PM_BIT (1 << 5) // if using 12 hr mode, this bit is set in the HOURS register to indicate if the time is AM or PM with PM being indicated by a 1 and AM by a 0
#define DS3231_20_HOUR_BIT (1 << 5) // if using 24 hr mode, this bit is set in the HOURS register to indicate the hours between 20 and 23
#define DS3231_CENTURY_BIT (1 << 7) // in the month/century register bit 7 is set when a new century is entered
// possible days
typedef enum
{
DS_SUNDAY = 1, // must start from 1 according to datasheet
DS_MONDAY = 2,
DS_TUESDAY = 3,
DS_WEDNESDAY = 4,
DS_THURSDAY = 5,
DS_FRIDAY = 6,
DS_SATURDAY = 7,
DAY_T_MAX = 8
} day_t;
// possible months
typedef enum
{
DS_JANUARY = 1,
DS_FEBRUARY = 2,
DS_MARCH = 3,
DS_APRIL = 4,
DS_MAY = 5,
DS_JUNE = 6,
DS_JULY = 7,
DS_AUGUST = 8,
DS_SEPTEMBER = 9,
DS_OCTOBER = 10,
DS_NOVEMBER = 11,
DS_DECEMBER = 12,
MONTH_T_MAX = 13
} month_t;
// the available alarms of the ds3231
typedef enum
{
ALARM_1,
ALARM_2,
ALARM_NUMBER_T_MAX
} alarm_number_t;
// defines when alarms should be triggered, e.g. when seconds match
typedef enum
{
//////////////////////////
// ALARM1 (A1) triggers //
//////////////////////////
A1_EVERY_SEC, // triggers every second
A1_SEC_MATCH, // triggers when seconds value in ALARM1 seconds register match ds3231 seconds register
A1_MIN_SEC_MATCH, // triggers when seconds & min value the ALARM1 seconds & min registers match ds3231 seconds & min registers
A1_HOUR_MIN_SEC_MATCH, // triggers when hours, min & seconds value in ALARM1 respective registers match ds3231 hour, min & seconds registers
A1_DAY_DATE_HOUR_MIN_SEC_MATCH, // triggers when day/date, hours, min & seconds in ALARM1 register match the values in the ds3231 time & date registers
// depending on what is "useDay" is true in the alarm_t used selects whether the alarm triggers on a day or date
//////////////////////////
// ALARM2 (A2) triggers //
//////////////////////////
A2_EVERY_MIN, // triggers every minute (at 0 seconds of the new minute)
A2_MIN_MATCH, // triggers when ALARM2 minute register matches the ds3231 minute register
A2_HOUR_MIN_MATCH, // triggers when ALARM2 minute & hour register matches the ds3231 minute & hour registers
A2_DAY_DATE_HOUR_MIN_MATCH, // triggers when ALARM2 day/date, hour & min register match the ds3231 registers
// depending on what is "useDay" is true in the alarm_t used selects whether the alarm triggers on a day or date
ALARM_TRIGGER_T_MAX
} alarm_trigger_t;
// used to set alarms
typedef struct
{
alarm_number_t alarmNumber; // which alarm to set
uint8_t second; // the seconds value of the alarm, this is only valid for ALARM_1
uint8_t minute; // minutes value of alarm
uint8_t hour; // hour value of alarm
bool useDay; // if TRUE, then the value in the "dayDate" field is interpreted as the day_t to trigger the alarm
// e.g. THURSDAY.
// if FALSE, then the value in "dayDate" is interpreted as a numerical date value to trigger the alarm
// e.g. 12 (the 12th of the month)
uint8_t dayDate; // the day OR date of the alarm (depends on useDay);
alarm_trigger_t trigger; // when the alarm will trigger, e.g. on match on mins & seconds
} alarm_t;
// the frequencies the bbsqw can output
typedef enum
{
HZ_1, // 1 Hz
KHZ_1_024, // 1.024 KHz
KHZ_4_096, // 4.096 KHz
KHZ_8_192, // 8.192 KHz
BBSQW_FREQUENCY_MAX
} bbsqw_frequency_t;
////////////////////////////////////////////////////////////////
// Global variables //
////////////////////////////////////////////////////////////////
// used to track the century
static uint8_t century = 21; // year 20xx has a century of 21
// used to indicate the hour storing mode, either AM/PM (12 hour mode) or 24 hour mode
static bool is24HourMode = true;
////////////////////////////////////////////////////////////////
// Function prototypes //
////////////////////////////////////////////////////////////////
void initDS3231(void);
// time setting / getting functions
void ds3231Use12HourMode(bool);
uint8_t ds3231SetSecond(uint8_t);
uint8_t ds3231GetSecond(void);
uint8_t ds3231SetMinute(uint8_t);
uint8_t ds3231GetMinute(void);
uint8_t ds3231SetHour(uint8_t, bool);
uint8_t ds3231GetHour(void);
uint8_t ds3231SetDay(day_t);
day_t ds3231GetDay(void);
uint8_t ds3231SetDate(uint8_t);
uint8_t ds3231GetDate(void);
uint8_t ds3231SetMonth(month_t);
month_t ds3231GetMonth(void);
uint8_t ds3231SetYear(uint8_t);
uint8_t ds3231GetYear(void);
void ds3231SetCentury(uint8_t);
uint8_t ds3231GetCentury(void);
uint8_t ds3231SetFullDate(day_t, uint8_t, month_t, uint8_t, uint8_t);
uint8_t ds3231SetTime(uint8_t, uint8_t, uint8_t, bool);
// alarm functions
uint8_t ds3231SetAlarm(const alarm_t *);
uint8_t ds3231ClearAlarmFlag(alarm_number_t);
uint8_t ds3231RemoveAlarm(alarm_number_t);
// temperature functions
void ds3231ForceTemperatureUpdate(void);
int16_t ds3231GetTemperature(void);
// oscillator functions
uint8_t ds3231DisableOscillatorOnBattery(void);
uint8_t ds3231EnableOscillatorOnBattery(void);
bool ds3231HasOscillatorStopped(void);
// 32KHz output pin functions
uint8_t ds3231Enable32KHzOutput(void);
uint8_t ds3231Disable32KhzOutput(void);
// aging offset functions
uint8_t ds3231SetAgingOffset(int8_t);
int8_t ds3231GetAgingOffset(void);
// other functions
uint8_t ds3231EnableBBSQW(bbsqw_frequency_t);
// utility functions
uint8_t setRegisterPointer(uint8_t);
uint8_t getRegisterValue(uint8_t);
uint8_t writeValueThenStop(uint8_t, uint8_t);
#ifdef __cplusplus
}
#endif
#endif