#pragma once
#ifndef DS3231_H
#define DS3231_H

/* i2c slave address of the DS3231 chip */
#define DS3231_I2C_ADDR             0xD0

/* timekeeping registers */
#define DS3231_ADDR_TIME            0x00
#define DS3231_ADDR_CALENDAR        0x03
#define DS3231_ADDR_ALARM1          0x07
#define DS3231_ADDR_ALARM2          0x0B
#define DS3231_ADDR_CONTROL         0x0E
#define DS3231_ADDR_STATUS          0x0F
#define DS3231_ADDR_AGING_OFFSET    0x10
#define DS3231_ADDR_TEMPERATURE     0x11

/* control register bits */
#define DS3231_A1IE                 0x01
#define DS3231_A2IE                 0x02
#define DS3231_INTCN                0x04
#define DS3231_RS1	                0x08
#define DS3231_RS2	                0x10
#define DS3231_CONV	                0x20
#define DS3231_BBSQW	              0x40
#define DS3231_OSC_OSC	            0x80

/* control/status register bits */
#define DS3231_A1F                  0x01
#define DS3231_A2F                  0x02
#define DS3231_BSY                  0x04
#define DS3231_EN32kHz              0x08
#define DS3231_OSF                  0x80

/* square-wave output frequency */
#define DS3231_1HZ	                0x00
#define DS3231_1024HZ	              DS3231_RS1
#define DS3231_4096HZ	              DS3231_RS2
#define DS3231_8192HZ	              (DS3231_RS1 | DS3231_RS2)

/* number of bytes */
#define DS3231_SIZE_TIME            3
#define DS3231_SIZE_CALENDAR        4
#define DS3231_SIZE_ALARM1          4
#define DS3231_SIZE_ALARM2          3
#define DS3231_SIZE_CONTROL         1
#define DS3231_SIZE_STATUS          1
#define DS3231_SIZE_AGOFFS          1
#define DS3231_SIZE_TEMPERATURE     2
#define DS3231_SIZE_ALL             19

/* RTC Status */
typedef enum {
  RTC_OK  = 0x00,
  RTC_TWI_TimeOut,
  RTC_TWI_Error
} rtc_status_t;

/**
 * @brief   Clock sructure.
 * @note    structure of ds3231 data.
 */
typedef struct {
  /**
   * @brief  00h: Seconds
   */
  uint8_t Sec;
  /**
   * @brief  01h: Minutes
   */
  uint8_t Min;
  /**
   * @brief  02h: Hours
   */
  uint8_t Hr;
  /**
   * @brief  03h: Week Day
   */
  uint8_t WD;
  /**
   * @brief  04h: Day of Month
   */
  uint8_t Day;
  /**
   * @brief  05h: Month
   */
  uint8_t Mon;
  /**
   * @brief  06h: Year
   */
  uint8_t Year;
  /**
   * @brief  07h: Alarm 1 Seconds
   */
  uint8_t A1SS;
  /**
   * @brief  08h: Alarm 1 Minutes
   */
  uint8_t A1MM;
  /**
   * @brief  09h: Alarm 1 Hours
   */
  uint8_t A1HH;
  /**
   * @brief  0Ah: Alarm 1 Day / Date
   */
  uint8_t A1DD;
  /**
   * @brief  0Bh: Alarm 2 Minutes
   */
  uint8_t A2MM;
  /**
   * @brief  0Ch: Alarm 2 Hours
   */
  uint8_t A2HH;
  /**
   * @brief  0Dh: Alarm 2 Day  / Date
   */
  uint8_t A2DD;
  /**
   * @brief  0Eh: Control
   */
  uint8_t Ctrl;
  /**
   * @brief  0Fh: Control/Status
   */
  uint8_t CtSt;
  /**
   * @brief  10h: Aging Offset
   */
  uint8_t AgOffset;
  /**
   * @brief  11h: MSB of Temp
   */
  uint8_t TempH;
  /**
   * @brief  12h: LSB of Temp
   */
  uint8_t TempL;
} rtc_t;

void RTC_Init(void);
void RTC_ReadAll(rtc_t * data);
void RTC_WriteTimeCalendar(rtc_t * data);
void RTC_WriteTime(rtc_t * data);
void RTC_WriteHHMM(rtc_t * data);
void RTC_WriteCalendar(rtc_t * data);

uint8_t bcd2bin(uint8_t bcd);
uint8_t bin2bcd(uint8_t bin);

#endif // DS3231_H
