/** @file bkp.h
 * Module handling the Backup (BKP) domain functionalities.
 *
 * This module includes management of the Real Time Clock (RTC), Tamper
 * protection system and a limited space (20 bytes) for persistent data storage
 *
 * All features present in this module stay running in standby mode / when
 * no-longer powered, so long as VBAT is maintained
 */

#ifndef _BKP_H_
#define _BKP_H_

//--includes--------------------------------------------------------------------

#include "stdint.h"
#include "tim.h"


//--type definitions------------------------------------------------------------

/**
 * Available clock sources for the RTC. See bkp_configure_rtc() for more
 * information
 */
enum BkpRtcClockSrc {
	BKP_RTC_CLOCK_SRC_LSE  = 0x0,
	BKP_RTC_CLOCK_SRC_LSI  = 0x1,
	BKP_RTC_CLOCK_SRC_HSE  = 0x2,
};

/**
 * Available IRQ sources. This enum is passed to the RTC callback to allow
 * differentiating IRQ sources
 */
enum BkpRtcIrq {
	BKP_RTC_IRQ_NONE     = 0,
	BKP_RTC_IRQ_SECOND   = 0x1 << 0,
	BKP_RTC_IRQ_ALARM    = 0x1 << 1,
	BKP_RTC_IRQ_OVERFLOW = 0x1 << 2,
};

enum BkpData {
	BKP_DATA_LSI_CALIB,
	BKP_DATA_1,
	BKP_DATA_2,
	BKP_DATA_3,
	BKP_DATA_4,
	BKP_DATA_5,
	BKP_DATA_6,
	BKP_DATA_7,
	BKP_DATA_8,
	BKP_DATA_9,
};

/**
 * Prototype of the IRQ callbacks that the applicative code can provide
 */
typedef void (*BkpRtcCallback)(enum BkpRtcIrq src);


//--functions-------------------------------------------------------------------

/**
 * Configures the RTC, starting it immediately. Configuration is saved between
 * boots as long as VBAT is present
 *
 * The RTC can run on a period of up to 1s and using one of 3 clocks. Clock
 * choice is a question of compromise :
 * - LSE consumes the less energy and continues to run in standby mode, but
 * requires an extra oscillator circuit
 * - LSI consumes little but isn't very accurate and requires extra calibration
 * (see bkp_callibrate_lsi). The calibration value is automatically used if
 * present when calling this function.
 * - HSE consumes the most.
 * WARNING : once configured, the clock source can only changed by reseting the
 * whole backup domain via bkp_reset()
 * Clocks must be enabled prior to calling this function
 *
 * Mulitple IRQs can be enabled and redirected to single callback. The alarm
 * IRQ, triggered at the tick value specified by bkp_set_rtc_alam() can be
 * rerouted to an exti line for wakeup from stop and standby, in wich case it
 * doesn't need to be enabled here.
 *
 * Ensure backup domain writes are enabled (see pwr_configure_bkp_write()) while
 * calling this function
 */
void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
		enum BkpRtcIrq irq_mask, BkpRtcCallback callback);

/**
 * Configure the alarm to trigger after the specified time in ticks, which can
 * be viewed as an offset to the current time value. This offset is only precise
 * to the tick and thus if the tick changes right after this function is
 * called, the observed offset will be close to 1 tick short
 */
void bkp_set_rtc_alam(uint32_t offset);

/**
 * Returns the current counter value of the RTC
 */
uint32_t bkp_read_rtc(void);
uint32_t bkp_read_rtc_div(void);

/**
 * Resets the entire backup domain, composed of everything configured through
 * this module
 */
void bkp_reset(void);

/**
 * Writes data to the specified backup domain index. The data will persist as
 * long as VBAT is present
 */
void bkp_write_data(enum BkpData data_index, uint16_t data);

/**
 * Writes data from the specified backup domain data index. The data will
 * persist as long as VBAT is present
 */
uint16_t bkp_read_data(enum BkpData data_index);

/**
 * Calibrate the LSI oscillator using the specified timer for accurate RTC
 * timings and store the calibration value at backup domain index
 * BKP_DATA_LSI_CALIB. This function has no effect if a calibration value is
 * already present
 */
void bkp_calibrate_lsi(enum TimPeriph timer);

//unimplemented functions
void bkp_configure_tamper();
void bkp_configure_lse(bool enable);


#endif //_BKP_H_

