Lancaster University's (short term!) clone of mbed-src for micro:bit. This is a copy of the github branch https://github.com/lancaster-university/mbed-classic

Fork of mbed-src by mbed official

Revision:
592:a274ee790e56
Parent:
591:474d026f7d79
Child:
593:78ee8643776a
--- a/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_sam_d_r/rtc_calendar.c	Wed Jul 15 08:15:08 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,653 +0,0 @@
-/**
- * \file
- *
- * \brief SAM RTC Driver (Calendar Mode)
- *
- * Copyright (C) 2012-2014 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- *    Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-/**
-* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
-*/
-#include "rtc_calendar.h"
-#include <gclk.h>
-
-#if !defined(__DOXYGEN__)
-struct rtc_module *_rtc_instance[RTC_INST_NUM];
-#endif
-
-/**
- * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
- *
- * Checks to see if the underlying hardware peripheral module(s) are currently
- * synchronizing across multiple clock domains to the hardware bus, This
- * function can be used to delay further operations on a module until such time
- * that it is ready, to prevent blocking delays for synchronization in the
- * user application.
- *
- * \param[in]  module  RTC hardware module
- *
- * \return Synchronization status of the underlying hardware module(s).
- *
- * \retval true  if the module has completed synchronization
- * \retval false if the module synchronization is ongoing
- */
-static inline bool rtc_calendar_is_syncing(struct rtc_module *const module)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    if (rtc_module->MODE2.STATUS.reg & RTC_STATUS_SYNCBUSY) {
-        return true;
-    }
-
-    return false;
-}
-
-/**
- * \brief Enables the RTC module.
- *
- * Enables the RTC module once it has been configured, ready for use. Most
- * module configuration parameters cannot be altered while the module is enabled.
- *
- * \param[in,out] module  Pointer to the software instance struct
- */
-void rtc_calendar_enable(struct rtc_module *const module)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-#if RTC_CALENDAR_ASYNC == true
-    system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_RTC);
-#endif
-
-    while (rtc_calendar_is_syncing(module)) {
-        /* Wait for synchronization */
-    }
-
-    /* Enable RTC module. */
-    rtc_module->MODE2.CTRL.reg |= RTC_MODE2_CTRL_ENABLE;
-}
-
-/**
- * \brief Disables the RTC module.
- *
- * Disables the RTC module.
- *
- * \param[in,out] module  Pointer to the software instance struct
- */
-void rtc_calendar_disable(struct rtc_module *const module)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-#if RTC_CALENDAR_ASYNC == true
-    system_interrupt_disable(SYSTEM_INTERRUPT_MODULE_RTC);
-#endif
-
-    while (rtc_calendar_is_syncing(module)) {
-        /* Wait for synchronization */
-    }
-
-    /* Disable RTC module. */
-    rtc_module->MODE2.CTRL.reg &= ~RTC_MODE2_CTRL_ENABLE;
-}
-
-/**
- * \brief Resets the RTC module
- * Resets the RTC module to hardware defaults.
- *
- * \param[in,out] module  Pointer to the software instance struct
- */
-void rtc_calendar_reset(struct rtc_module *const module)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    /* Disable module before reset. */
-    rtc_calendar_disable(module);
-
-#if RTC_CALENDAR_ASYNC == true
-    module->registered_callback = 0;
-    module->enabled_callback    = 0;
-#endif
-
-    while (rtc_calendar_is_syncing(module)) {
-        /* Wait for synchronization */
-    }
-
-    /* Initiate software reset. */
-    rtc_module->MODE2.CTRL.reg |= RTC_MODE2_CTRL_SWRST;
-}
-
-/**
- * \internal Convert time structure to register_value.
- */
-static uint32_t _rtc_calendar_time_to_register_value(
-    struct rtc_module *const module,
-    const struct rtc_calendar_time *const time)
-{
-    /* Initialize return value. */
-    uint32_t register_value;
-
-    /* Set year value into register_value minus initial year. */
-    register_value = (time->year - module->year_init_value) <<
-                     RTC_MODE2_CLOCK_YEAR_Pos;
-
-    /* Set month value into register_value. */
-    register_value |= (time->month << RTC_MODE2_CLOCK_MONTH_Pos);
-
-    /* Set day value into register_value. */
-    register_value |= (time->day << RTC_MODE2_CLOCK_DAY_Pos);
-
-    /* Set 24 hour value into register_value. */
-    register_value |= (time->hour << RTC_MODE2_CLOCK_HOUR_Pos);
-
-    /* Check if 24 h clock and set pm flag. */
-    if (!(module->clock_24h) && (time->pm)) {
-        /* Set pm flag. */
-        register_value |= RTC_MODE2_CLOCK_HOUR_PM;
-    }
-
-    /* Set minute value into register_value. */
-    register_value |= (time->minute << RTC_MODE2_CLOCK_MINUTE_Pos);
-
-    /* Set second value into register_value. */
-    register_value |= (time->second << RTC_MODE2_CLOCK_SECOND_Pos);
-
-    return register_value;
-}
-
-/**
- * \internal Convert register_value to time structure.
- */
-static void _rtc_calendar_register_value_to_time(
-    struct rtc_module *const module,
-    const uint32_t register_value,
-    struct rtc_calendar_time *const time)
-{
-    /* Set year plus value of initial year. */
-    time->year = ((register_value & RTC_MODE2_CLOCK_YEAR_Msk) >>
-                  RTC_MODE2_CLOCK_YEAR_Pos) + module->year_init_value;
-
-    /* Set month value into time struct. */
-    time->month = ((register_value & RTC_MODE2_CLOCK_MONTH_Msk) >>
-                   RTC_MODE2_CLOCK_MONTH_Pos);
-
-    /* Set day value into time struct. */
-    time->day = ((register_value & RTC_MODE2_CLOCK_DAY_Msk) >>
-                 RTC_MODE2_CLOCK_DAY_Pos);
-
-    if (module->clock_24h) {
-        /* Set hour in 24h mode. */
-        time->hour = ((register_value & RTC_MODE2_CLOCK_HOUR_Msk) >>
-                      RTC_MODE2_CLOCK_HOUR_Pos);
-    } else {
-        /* Set hour in 12h mode. */
-        time->hour = ((register_value &
-                       (RTC_MODE2_CLOCK_HOUR_Msk & ~RTC_MODE2_CLOCK_HOUR_PM)) >>
-                      RTC_MODE2_CLOCK_HOUR_Pos);
-
-        /* Set pm flag */
-        time->pm = ((register_value & RTC_MODE2_CLOCK_HOUR_PM) != 0);
-    }
-
-    /* Set minute value into time struct. */
-    time->minute = ((register_value & RTC_MODE2_CLOCK_MINUTE_Msk) >>
-                    RTC_MODE2_CLOCK_MINUTE_Pos);
-
-    /* Set second value into time struct. */
-    time->second = ((register_value & RTC_MODE2_CLOCK_SECOND_Msk) >>
-                    RTC_MODE2_CLOCK_SECOND_Pos);
-}
-
-/**
- * \internal Applies the given configuration.
- *
- * Set the configurations given from the configuration structure to the
- * hardware module.
- *
- * \param[in,out] module  Pointer to the software instance struct
- * \param[in] config  Pointer to the configuration structure.
- */
-static void _rtc_calendar_set_config(
-    struct rtc_module *const module,
-    const struct rtc_calendar_config *const config)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    /* Set up temporary register value. */
-    uint16_t tmp_reg;
-
-    /* Set to calendar mode and set the prescaler. */
-    tmp_reg = RTC_MODE2_CTRL_MODE(2) | config->prescaler;
-
-    /* Check clock mode. */
-    if (!(config->clock_24h)) {
-        /* Set clock mode 12h. */
-        tmp_reg |= RTC_MODE2_CTRL_CLKREP;
-    }
-
-    /* Check for clear on compare match. */
-    if (config->clear_on_match) {
-        /* Set clear on compare match. */
-        tmp_reg |= RTC_MODE2_CTRL_MATCHCLR;
-    }
-
-    /* Set temporary value to register. */
-    rtc_module->MODE2.CTRL.reg = tmp_reg;
-
-    /* Check to set continuously clock read update mode. */
-    if (config->continuously_update) {
-        /* Set continuously mode. */
-        rtc_module->MODE2.READREQ.reg |= RTC_READREQ_RCONT;
-    }
-
-    /* Set alarm time registers. */
-    for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) {
-        rtc_calendar_set_alarm(module, &(config->alarm[i]), (enum rtc_calendar_alarm)i);
-    }
-}
-
-/**
- * \brief Initializes the RTC module with given configurations.
- *
- * Initializes the module, setting up all given configurations to provide
- * the desired functionality of the RTC.
- *
- * \param[out] module  Pointer to the software instance struct
- * \param[in]   hw      Pointer to hardware instance
- * \param[in] config  Pointer to the configuration structure.
- */
-void rtc_calendar_init(
-    struct rtc_module *const module,
-    Rtc *const hw,
-    const struct rtc_calendar_config *const config)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(hw);
-    Assert(config);
-
-    /* Initialize device instance */
-    module->hw = hw;
-
-    /* Turn on the digital interface clock */
-    system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, PM_APBAMASK_RTC);
-
-    /* Set up GCLK */
-    struct system_gclk_chan_config gclk_chan_conf;
-    system_gclk_chan_get_config_defaults(&gclk_chan_conf);
-    gclk_chan_conf.source_generator = GCLK_GENERATOR_2;
-    system_gclk_chan_set_config(RTC_GCLK_ID, &gclk_chan_conf);
-    system_gclk_chan_enable(RTC_GCLK_ID);
-
-    /* Reset module to hardware defaults. */
-    rtc_calendar_reset(module);
-
-    /* Save conf_struct internally for continued use. */
-    module->clock_24h           = config->clock_24h;
-    module->continuously_update = config->continuously_update;
-    module->year_init_value     = config->year_init_value;
-
-#if (RTC_INST_NUM == 1)
-    _rtc_instance[0] = module;
-#else
-    /* Register this instance for callbacks*/
-    _rtc_instance[_rtc_get_inst_index(hw)] = module;
-#endif
-
-    /* Set config. */
-    _rtc_calendar_set_config(module, config);
-}
-
-/**
- * \brief Swaps between 12h and 24h clock mode.
- *
- * Swaps the current RTC time mode:
- * - If currently in 12h mode, it will swap to 24h
- * - If currently in 24h mode, it will swap to 12h
- *
- * \note This will not change setting in user's configuration structure.
- *
- * \param[in, out] module  Pointer to the software instance struct
- */
-void rtc_calendar_swap_time_mode(struct rtc_module *const module)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    /* Initialize time structure. */
-    struct rtc_calendar_time time;
-    struct rtc_calendar_alarm_time alarm;
-
-    /* Get current time. */
-    rtc_calendar_get_time(module, &time);
-
-    /* Check current mode. */
-    if (module->clock_24h) {
-        /* Set pm flag. */
-        time.pm = (uint8_t)(time.hour / 12);
-
-        /* Set 12h clock hour value. */
-        time.hour = time.hour % 12;
-        if (time.hour == 0) {
-            time.hour = 12;
-        }
-
-        /* Update alarms */
-        for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) {
-            rtc_calendar_get_alarm(module, &alarm, (enum rtc_calendar_alarm)i);
-            alarm.time.pm = (uint8_t)(alarm.time.hour / 12);
-            alarm.time.hour = alarm.time.hour % 12;
-            if (alarm.time.hour == 0) {
-                alarm.time.hour = 12;
-            }
-            module->clock_24h = false;
-            rtc_calendar_set_alarm(module, &alarm, (enum rtc_calendar_alarm)i);
-            module->clock_24h = true;
-        }
-
-        /* Change value in configuration structure. */
-        module->clock_24h = false;
-    } else {
-        /* Set hour value based on pm flag. */
-        if (time.pm == 1) {
-            time.hour = time.hour + 12;
-
-            time.pm = 0;
-        } else if (time.hour == 12) {
-            time.hour = 0;
-        }
-
-        /* Update alarms */
-        for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) {
-            rtc_calendar_get_alarm(module, &alarm, (enum rtc_calendar_alarm)i);
-            if (alarm.time.pm == 1) {
-                alarm.time.hour = alarm.time.hour + 12;
-                alarm.time.pm = 0;
-                module->clock_24h = true;
-                rtc_calendar_set_alarm(module, &alarm, (enum rtc_calendar_alarm)i);
-                module->clock_24h = false;
-            } else if (alarm.time.hour == 12) {
-                alarm.time.hour = 0;
-            }
-        }
-
-        /* Change value in configuration structure. */
-        module->clock_24h = true;
-    }
-
-    /* Disable RTC so new configuration can be set. */
-    rtc_calendar_disable(module);
-
-    /* Toggle mode. */
-    rtc_module->MODE2.CTRL.reg ^= RTC_MODE2_CTRL_CLKREP;
-
-    /* Enable RTC. */
-    rtc_calendar_enable(module);
-
-    /* Set new time format in CLOCK register. */
-    rtc_calendar_set_time(module, &time);
-}
-
-/**
- * \brief Set the current calendar time to desired time.
- *
- * Sets the time provided to the calendar.
- *
- * \param[in, out] module  Pointer to the software instance struct
- * \param[in] time  The time to set in the calendar.
- */
-void rtc_calendar_set_time(
-    struct rtc_module *const module,
-    const struct rtc_calendar_time *const time)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    uint32_t register_value = _rtc_calendar_time_to_register_value(module, time);
-
-    while (rtc_calendar_is_syncing(module)) {
-        /* Wait for synchronization */
-    }
-
-    /* Write value to register. */
-    rtc_module->MODE2.CLOCK.reg = register_value;
-}
-
-/**
- * \brief Get the current calendar value.
- *
- * Retrieves the current time of the calendar.
- *
- * \param[in, out] module  Pointer to the software instance struct
- * \param[out] time  Pointer to value that will be filled with current time.
- */
-void rtc_calendar_get_time(
-    struct rtc_module *const module,
-    struct rtc_calendar_time *const time)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    /* Change of read method based on value of continuously_update value in
-     * the configuration structure. */
-    if (!(module->continuously_update)) {
-        /* Request read on CLOCK register. */
-        rtc_module->MODE2.READREQ.reg = RTC_READREQ_RREQ;
-
-        while (rtc_calendar_is_syncing(module)) {
-            /* Wait for synchronization */
-        }
-    }
-
-    /* Read value. */
-    uint32_t register_value = rtc_module->MODE2.CLOCK.reg;
-
-    /* Convert value to time structure. */
-    _rtc_calendar_register_value_to_time(module, register_value, time);
-}
-
-/**
- * \brief Set the alarm time for the specified alarm.
- *
- * Sets the time and mask specified to the requested alarm.
- *
- * \param[in, out] module  Pointer to the software instance struct
- * \param[in] alarm        The alarm struct to set the alarm with.
- * \param[in] alarm_index  The index of the alarm to set.
- *
- * \return Status of setting alarm.
- * \retval STATUS_OK               If alarm was set correctly.
- * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided.
- */
-enum status_code rtc_calendar_set_alarm(
-    struct rtc_module *const module,
-    const struct rtc_calendar_alarm_time *const alarm,
-    const enum rtc_calendar_alarm alarm_index)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    /* Sanity check. */
-    if ((uint32_t)alarm_index > RTC_NUM_OF_ALARMS) {
-        return STATUS_ERR_INVALID_ARG;
-    }
-
-    /* Get register_value from time. */
-    uint32_t register_value = _rtc_calendar_time_to_register_value(module, &(alarm->time));
-
-    while (rtc_calendar_is_syncing(module)) {
-        /* Wait for synchronization */
-    }
-
-    /* Set alarm value. */
-    rtc_module->MODE2.Mode2Alarm[alarm_index].ALARM.reg = register_value;
-
-    /* Set alarm mask */
-    rtc_module->MODE2.Mode2Alarm[alarm_index].MASK.reg = alarm->mask;
-
-    return STATUS_OK;
-}
-
-/**
- * \brief Get the current alarm time of specified alarm.
- *
- * Retrieves the current alarm time for the alarm specified.
- *
- * \param[in, out] module  Pointer to the software instance struct
- * \param[out] alarm  Pointer to the struct that will be filled with alarm
- *                    time and mask of the specified alarm.
- * \param[in] alarm_index  Index of alarm to get alarm time from.
- *
- * \return Status of getting alarm.
- * \retval STATUS_OK               If alarm was read correctly.
- * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided.
- */
-enum status_code rtc_calendar_get_alarm(
-    struct rtc_module *const module,
-    struct rtc_calendar_alarm_time *const alarm,
-    const enum rtc_calendar_alarm alarm_index)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    /* Sanity check. */
-    if ((uint32_t)alarm_index > RTC_NUM_OF_ALARMS) {
-        return STATUS_ERR_INVALID_ARG;
-    }
-
-    /* Read alarm value. */
-    uint32_t register_value =
-        rtc_module->MODE2.Mode2Alarm[alarm_index].ALARM.reg;
-
-    /* Convert to time structure. */
-    _rtc_calendar_register_value_to_time(module, register_value, &(alarm->time));
-
-    /* Read alarm mask */
-    alarm->mask = (enum rtc_calendar_alarm_mask)rtc_module->MODE2.Mode2Alarm[alarm_index].MASK.reg;
-
-    return STATUS_OK;
-}
-
-/**
- * \brief Calibrate for too-slow or too-fast oscillator.
- *
- * When used, the RTC will compensate for an inaccurate oscillator. The
- * RTC module will add or subtract cycles from the RTC prescaler to adjust the
- * frequency in approximately 1 PPM steps. The provided correction value should
- * be between -127 and 127, allowing for a maximum 127 PPM correction in either
- * direction.
- *
- * If no correction is needed, set value to zero.
- *
- * \note Can only be used when the RTC is operated at 1Hz.
- *
- * \param[in, out] module  Pointer to the software instance struct
- * \param[in] value Between -127 and 127 used for the correction.
- *
- * \return Status of the calibration procedure.
- * \retval STATUS_OK               If calibration was done correctly.
- * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided.
- */
-enum status_code rtc_calendar_frequency_correction(
-    struct rtc_module *const module,
-    const int8_t value)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    Rtc *const rtc_module = module->hw;
-
-    /* Check if valid argument. */
-    if (abs(value) > 0x7F) {
-        /* Value bigger than allowed, return invalid argument. */
-        return STATUS_ERR_INVALID_ARG;
-    }
-
-    uint32_t new_correction_value;
-
-    /* Load the new correction value as a positive value, sign added later */
-    new_correction_value = abs(value);
-
-    /* Convert to positive value and adjust register sign bit. */
-    if (value < 0) {
-        new_correction_value |= RTC_FREQCORR_SIGN;
-    }
-
-    while (rtc_calendar_is_syncing(module)) {
-        /* Wait for synchronization */
-    }
-
-    /* Set value. */
-    rtc_module->MODE2.FREQCORR.reg = new_correction_value;
-
-    return STATUS_OK;
-}