text: /**
   * \file
   *
   * \brief SAM RTC Driver (Tamper)
   *
   * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
   *
   * \asf_license_start
   *
   * \page License
   *
   * Subject to your compliance with these terms, you may use Microchip
   * software and any derivatives exclusively with Microchip products.
   * It is your responsibility to comply with third party license terms applicable
   * to your use of third party software (including open source software) that
   * may accompany Microchip software.
   *
   * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
   * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
   * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
   * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
   * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
   * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
   * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
   * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
   * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
   * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
   * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
   *
   * \asf_license_stop
   *
   */
  /*
   * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
   */
  
  #ifndef RTC_TAMPER_H_INCLUDED
  #define RTC_TAMPER_H_INCLUDED
  
  /**
   *
   * \section asfdoc_sam0_rtc_tamper_detect RTC Tamper Detect
   * The RTC provides several selectable polarity external inputs (INn) that can be
   * used for tamper detection. When detect, tamper inputs support the four actions:
   *   - Off
   *   - Wake
   *   - Capture
   *   - Active layer protection
   *
   * \note The Active Layer Protection is a means of detecting broken traces on the
   * PCB provided by RTC. In this mode an RTC output signal is routed over critical
   * components on the board and fed back to one of the RTC inputs. The input and
   * output signals are compared and a tamper condition is detected when they do not match.
   *
   *
   * Separate debouncers are embedded for each external input. The detection time 
   * depends on whether the debouncer operates synchronously or asynchronously, 
   * and whether majority detection is enabled or not. For details, refer to the section
   * "Tamper Detection" of datasheet.
   * \if RTC_COUNT_CALLBACK_MODE
   *  \addtogroup asfdoc_sam0_rtc_count_group
   * \else
   * \if RTC_CALENDAR_CALLBACK_MODE
   *  \addtogroup asfdoc_sam0_rtc_calendar_group
   * \endif
   * \endif
   * @{
   */
  
  #if defined(FEATURE_RTC_TAMPER_DETECTION) || defined(__DOXYGEN__)
  
  /** RTC tamper ID0 detection bitmask. */
  #define RTC_TAMPER_DETECT_ID0    (1UL << 0)
  /** RTC tamper ID1 detection bitmask. */
  #define RTC_TAMPER_DETECT_ID1    (1UL << 1)
  /** RTC tamper ID2 detection bitmask. */
  #define RTC_TAMPER_DETECT_ID2    (1UL << 2)
  /** RTC tamper ID3 detection bitmask. */
  #define RTC_TAMPER_DETECT_ID3    (1UL << 3)
  /** RTC tamper ID4 detection bitmask. */
  #define RTC_TAMPER_DETECT_ID4    (1UL << 4)
  /** RTC tamper input event detection bitmask. */
  #define RTC_TAMPER_DETECT_EVT    (1UL << 5)
  
  
  
  /**
   * \brief RTC tamper active layer frequency divider.
   *
   * The available prescaler factor for the RTC clock output used during active
   * layer protection.
   */
  enum rtc_tamper_active_layer_freq_divider {
  	/** RTC active layer frequency is prescaled by a factor of 2 */
  	RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_2    = RTC_MODE0_CTRLB_ACTF_DIV2,
  	/** RTC active layer frequency is prescaled by a factor of 4 */
  	RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_4    = RTC_MODE0_CTRLB_ACTF_DIV4,
  	/** RTC active layer frequency is prescaled by a factor of 8 */
  	RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_8    = RTC_MODE0_CTRLB_ACTF_DIV8,
  	/** RTC active layer frequency is prescaled by a factor of 16 */
  	RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_16   = RTC_MODE0_CTRLB_ACTF_DIV16,
  	/** RTC active layer frequency is prescaled by a factor of 32 */
  	RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_32   = RTC_MODE0_CTRLB_ACTF_DIV32,
  	/** RTC active layer frequency is prescaled by a factor of 64 */
  	RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_64   = RTC_MODE0_CTRLB_ACTF_DIV64,
  	/** RTC active layer frequency is prescaled by a factor of 128 */
  	RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_128  = RTC_MODE0_CTRLB_ACTF_DIV128,
  	/** RTC active layer frequency is prescaled by a factor of 256 */
  	RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_256  = RTC_MODE0_CTRLB_ACTF_DIV256,
  };
  
  /**
   * \brief RTC tamper debounce frequency divider.
   *
   * The available prescaler factor for the input debouncers.
   */
  enum rtc_tamper_debounce_freq_divider {
  	/** RTC debounce frequency is prescaled by a factor of 2 */
  	RTC_TAMPER_DEBOUNCE_FREQ_DIV_2    = RTC_MODE0_CTRLB_DEBF_DIV2,
  	/** RTC debounce frequency is prescaled by a factor of 4 */
  	RTC_TAMPER_DEBOUNCE_FREQ_DIV_4    = RTC_MODE0_CTRLB_DEBF_DIV4,
  	/** RTC debounce frequency is prescaled by a factor of 8 */
  	RTC_TAMPER_DEBOUNCE_FREQ_DIV_8    = RTC_MODE0_CTRLB_DEBF_DIV8,
  	/** RTC debounce frequency is prescaled by a factor of 16 */
  	RTC_TAMPER_DEBOUNCE_FREQ_DIV_16   = RTC_MODE0_CTRLB_DEBF_DIV16,
  	/** RTC debounce frequency is prescaled by a factor of 32 */
  	RTC_TAMPER_DEBOUNCE_FREQ_DIV_32   = RTC_MODE0_CTRLB_DEBF_DIV32,
  	/** RTC debounce frequency is prescaled by a factor of 64 */
  	RTC_TAMPER_DEBOUNCE_FREQ_DIV_64   = RTC_MODE0_CTRLB_DEBF_DIV64,
  	/** RTC debounce frequency is prescaled by a factor of 128 */
  	RTC_TAMPER_DEBOUNCE_FREQ_DIV_128  = RTC_MODE0_CTRLB_DEBF_DIV128,
  	/** RTC debounce frequency is prescaled by a factor of 256 */
  	RTC_TAMPER_DEBOUNCE_FREQ_DIV_256  = RTC_MODE0_CTRLB_DEBF_DIV256,
  };
  
  /**
   * \brief RTC tamper input action.
   *
   * The available action taken by the tamper input.
   */
  enum rtc_tamper_input_action {
  	/** RTC tamper input action is disabled */
  	RTC_TAMPER_INPUT_ACTION_OFF     = RTC_TAMPCTRL_IN0ACT_OFF,
  	/** RTC tamper input action is wake and set tamper flag */
  	RTC_TAMPER_INPUT_ACTION_WAKE    = RTC_TAMPCTRL_IN0ACT_WAKE,
  	/** RTC tamper input action is capture timestamp and set tamper flag */
  	RTC_TAMPER_INPUT_ACTION_CAPTURE = RTC_TAMPCTRL_IN0ACT_CAPTURE,
  	/** RTC tamper input action is compare IN to OUT, when a mismatch occurs,
  	 *  capture timestamp and set tamper flag */
  	RTC_TAMPER_INPUT_ACTION_ACTL    = RTC_TAMPCTRL_IN0ACT_ACTL,
  };
  
  /**
   * \brief RTC tamper input level select.
   *
   * The available edge condition for tamper INn level select.
   */
  enum rtc_tamper_level_sel {
  	/** A falling edge condition will be detected on Tamper input */
  	RTC_TAMPER_LEVEL_FALLING = (0),
  	/** A rising edge condition will be detected on Tamper input */
  	RTC_TAMPER_LEVEL_RISING  = (1),
  };
  
  /**
   * \brief RTC tamper debounce sequential.
   *
   * The available sequential for tamper debounce.
   */
  enum rtc_tamper_debounce_seq {
  	/** Tamper input detect edge with synchronous stability debounce */
  	RTC_TAMPER_DEBOUNCE_SYNC,
  	/** Tamper input detect edge with asynchronous stability debounce */
  	RTC_TAMPER_DEBOUNCE_ASYNC,
  	/** Tamper input detect edge with majority debounce */
  	RTC_TAMPER_DEBOUNCE_MAJORITY,
  };
  
  /**
   * \brief RTC tamper input configuration structure.
   *
   * The configuration structure for tamper INn.
   */
  struct rtc_tamper_input_config {
  	/** Debounce enable */
  	bool debounce_enable;
  	/** Tamper level select */
  	enum rtc_tamper_level_sel level;
  	/** Tamper input action */
  	enum rtc_tamper_input_action action;
  };
  
  /**
   * \brief RTC Tamper configuration structure.
   *
   * The configuration structure for the RTC tamper. This structure should
   * be initialized using the \ref rtc_tamper_get_config_defaults() before any
   * user configurations are set.
   */
  struct rtc_tamper_config {
  	/** Backup register reset on tamper enable */
  	bool bkup_reset_on_tamper;
  	/** GP register reset on tamper enable */
  	bool gp_reset_on_tamper;
  	/** Active layer frequency */
  	enum rtc_tamper_active_layer_freq_divider actl_freq_div;
  	/** Debounce frequency */
  	enum rtc_tamper_debounce_freq_divider deb_freq_div;
  	/** Debounce sequential */
  	enum rtc_tamper_debounce_seq deb_seq;
  	/** DMA on tamper enable */
  	bool dma_tamper_enable;
  	/** General Purpose 0/1 Enable */
  	bool gp0_enable;
  	/** Tamper IN configuration */
  	struct rtc_tamper_input_config in_cfg[RTC_TAMPER_NUM];
  };
  
  /**
   * \name RTC Tamper Detection
   * @{
   */
  
  /**
   *  \brief Gets the RTC tamper default configurations.
   *
   *  Initializes the configuration structure to default values. 
   *
   *  The default configuration is as follows:
   *  - Disable backup register reset on tamper
   *  - Disable GP register reset on tamper
   *  - Active layer clock divided by a factor of 8
   *  - Debounce clock divided by a factor of 8
   *  - Detect edge on INn with synchronous stability debouncing
   *  - Disable DMA on  tamper
   *  - Enable GP register
   *  - Disable debouce, detect on falling edge and no action on INn
   *
   *  \param[out] config Configuration structure to be initialized to default values.
   */
  static inline void rtc_tamper_get_config_defaults(
  		struct rtc_tamper_config *const config)
  {
  	/* Sanity check argument */
  	Assert(config);
  
  	config->bkup_reset_on_tamper= false;
  	config->gp_reset_on_tamper  = false;
  	config->actl_freq_div       = RTC_TAMPER_ACTIVE_LAYER_FREQ_DIV_8;
  	config->deb_freq_div        = RTC_TAMPER_DEBOUNCE_FREQ_DIV_8;
  	config->deb_seq             = RTC_TAMPER_DEBOUNCE_SYNC;
  	config->dma_tamper_enable   = false;
  	config->gp0_enable          = true;
  
  	for (uint8_t id = 0; id < RTC_TAMPER_NUM; id++) {
  		config->in_cfg[id].debounce_enable = false;
  		config->in_cfg[id].level = RTC_TAMPER_LEVEL_FALLING;
  		config->in_cfg[id].action = RTC_TAMPER_INPUT_ACTION_OFF;
  	}
  }
  enum status_code rtc_tamper_set_config (struct rtc_module *const module,
  		struct rtc_tamper_config *const tamper_cfg);
  
  /**
   * \brief Retrieves the RTC tamper detection status.
   *
   * Retrieves the detection status of each input pin and the input event.
   *
   * \param[in] module  Pointer to the RTC software instance struct
   *
   * \return Bitmask of detection flags.
   *
   * \retval RTC_TAMPER_DETECT_ID0   Tamper condition on IN0 has been detected
   * \retval RTC_TAMPER_DETECT_ID1   Tamper condition on IN1 has been detected
   * \retval RTC_TAMPER_DETECT_ID2   Tamper condition on IN2 has been detected
   * \retval RTC_TAMPER_DETECT_ID3   Tamper condition on IN3 has been detected
   * \retval RTC_TAMPER_DETECT_ID4   Tamper condition on IN4 has been detected
   * \retval RTC_TAMPER_DETECT_EVT   Tamper input event has been detected
   */
  static inline uint32_t rtc_tamper_get_detect_flag (struct rtc_module *const module)
  {
  	/* Sanity check arguments */
  	Assert(module);
  	Assert(module->hw);
  
  	uint32_t tamper_id = module->hw->MODE0.TAMPID.reg;
  	uint32_t detect_flags = 0;
  
  	if (tamper_id & RTC_TAMPID_TAMPID0) {
  		detect_flags |= RTC_TAMPER_DETECT_ID0;
  	}
  
  	if (tamper_id & RTC_TAMPID_TAMPID1) {
  		detect_flags |= RTC_TAMPER_DETECT_ID1;
  	}
  
  	if (tamper_id & RTC_TAMPID_TAMPID2) {
  		detect_flags |= RTC_TAMPER_DETECT_ID2;
  	}
  
  	if (tamper_id & RTC_TAMPID_TAMPID3) {
  		detect_flags |= RTC_TAMPER_DETECT_ID3;
  	}
  
  	if (tamper_id & RTC_TAMPID_TAMPID4) {
  		detect_flags |= RTC_TAMPER_DETECT_ID4;
  	}
  
  	if (tamper_id & RTC_TAMPID_TAMPEVT) {
  		detect_flags |= RTC_TAMPER_DETECT_EVT;
  	}
  
  	return detect_flags;
  }
  
  /**
   * \brief Clears RTC tamper detection flag.
   *
   * Clears the given detection flag of the module.
   *
   * \param[in] module   Pointer to the TC software instance struct
   * \param[in] detect_flags  Bitmask of detection flags
   */
  static inline void rtc_tamper_clear_detect_flag(
  		struct rtc_module *const module,
  		const uint32_t detect_flags)
  {
  	/* Sanity check arguments */
  	Assert(module);
  	Assert(module->hw);
  
  	uint32_t tamper_id = 0;
  
  	if (detect_flags & RTC_TAMPER_DETECT_ID0) {
  		tamper_id |= RTC_TAMPID_TAMPID0;
  	}
  
  	if (detect_flags & RTC_TAMPER_DETECT_ID1) {
  		tamper_id |= RTC_TAMPID_TAMPID1;
  	}
  
  	if (detect_flags & RTC_TAMPER_DETECT_ID2) {
  		tamper_id |= RTC_TAMPID_TAMPID2;
  	}
  
  	if (detect_flags & RTC_TAMPER_DETECT_ID3) {
  		tamper_id |= RTC_TAMPID_TAMPID3;
  	}
  
  	if (detect_flags & RTC_TAMPER_DETECT_ID4) {
  		tamper_id |= RTC_TAMPID_TAMPID4;
  	}
  
  	if (detect_flags & RTC_TAMPER_DETECT_EVT) {
  		tamper_id |= RTC_TAMPID_TAMPEVT;
  	}
  
  	module->hw->MODE0.TAMPID.reg = tamper_id;
  
  }
  
  /** @} */
  
  #endif
  /** @} */
  
  
  #endif /* RTC_TAMPER_H_INCLUDED */