mirror of
https://github.com/oliverschmidt/contiki.git
synced 2024-12-22 10:30:13 +00:00
Added support for the RE-Mote on-board Real Time Clock Calendar (RTCC)
This commit is contained in:
parent
a2cae3359b
commit
834f965c95
12
examples/zolertia/zoul/rtcc/Makefile
Normal file
12
examples/zolertia/zoul/rtcc/Makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
|
||||||
|
CONTIKI_PROJECT = test-rtcc
|
||||||
|
|
||||||
|
TARGET = zoul
|
||||||
|
|
||||||
|
# Works in Linux and probably on OSX too (RTCC example)
|
||||||
|
CFLAGS = -DDATE="\"`date +"%02u %02d %02m %02y %02H %02M %02S"`\""
|
||||||
|
|
||||||
|
all: $(CONTIKI_PROJECT)
|
||||||
|
|
||||||
|
CONTIKI = ../../../..
|
||||||
|
include $(CONTIKI)/Makefile.include
|
45
examples/zolertia/zoul/rtcc/project-conf.h
Normal file
45
examples/zolertia/zoul/rtcc/project-conf.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* 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. Neither the name of the copyright holder nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \addtogroup remote-examples
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \file
|
||||||
|
* Project specific configuration defines for the basic RE-Mote examples
|
||||||
|
*/
|
||||||
|
#ifndef PROJECT_CONF_H_
|
||||||
|
#define PROJECT_CONF_H_
|
||||||
|
|
||||||
|
#define NETSTACK_CONF_RDC nullrdc_driver
|
||||||
|
|
||||||
|
#endif /* PROJECT_CONF_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
181
examples/zolertia/zoul/rtcc/test-rtcc.c
Normal file
181
examples/zolertia/zoul/rtcc/test-rtcc.c
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Zolertia - http://www.zolertia.com
|
||||||
|
*
|
||||||
|
* 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. Neither the name of the copyright holder nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \addtogroup remote-examples
|
||||||
|
* @{
|
||||||
|
|
||||||
|
* \defgroup remote-rtcc-test RE-Mote on-board RTCC test application
|
||||||
|
*
|
||||||
|
* Example project to show the on-board RTCC configuration and operation
|
||||||
|
* Retrieves the current time and date from the system, then sets an alarm to
|
||||||
|
* trigger every TEST_ALARM_SECOND match, generating an interrupt event and
|
||||||
|
* printing the current time/date, toggling also the LEDs
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \file
|
||||||
|
* RE-Mote on-board RTCC test application
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
*
|
||||||
|
* Antonio Lignan <alinan@zolertia.com>
|
||||||
|
* Aitor Mejias <amejias@zolertia.com>
|
||||||
|
* Toni Lozano <tlozano@zolertia.com>
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#include "contiki.h"
|
||||||
|
#include "rtcc.h"
|
||||||
|
#include "dev/i2c.h"
|
||||||
|
#include "dev/leds.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#ifndef DATE
|
||||||
|
#define DATE "Unknown"
|
||||||
|
#endif
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#define LOOP_PERIOD 60L
|
||||||
|
#define LOOP_INTERVAL (CLOCK_SECOND * LOOP_PERIOD)
|
||||||
|
#define TEST_ALARM_SECOND 30
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
PROCESS(test_remote_rtcc_process, "Test RTC driver process");
|
||||||
|
AUTOSTART_PROCESSES(&test_remote_rtcc_process);
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static uint8_t rtc_buffer[sizeof(simple_td_map)];
|
||||||
|
static simple_td_map *simple_td = (simple_td_map *)rtc_buffer;
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static struct etimer et;
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
rtcc_interrupt_callback(uint8_t value)
|
||||||
|
{
|
||||||
|
printf("A RTCC interrupt just happened! time/date: ");
|
||||||
|
rtcc_print(RTCC_PRINT_DATE_DEC);
|
||||||
|
leds_toggle(LEDS_PURPLE);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
PROCESS_THREAD(test_remote_rtcc_process, ev, data)
|
||||||
|
{
|
||||||
|
static char *next;
|
||||||
|
|
||||||
|
PROCESS_BEGIN();
|
||||||
|
|
||||||
|
/* Alternatively for test only, undefine DATE and define on your own as
|
||||||
|
* #define DATE "07 06 12 15 16 00 00"
|
||||||
|
* Also note that if you restart the node at a given time, it will use the
|
||||||
|
* already defined DATE, so if you want to update the device date/time you
|
||||||
|
* need to reflash the node
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Get the system date in the following format: wd dd mm yy hh mm ss */
|
||||||
|
printf("RE-Mote RTC test, system date: %s\n", DATE);
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
if(strcmp("Unknown", DATE) == 0) {
|
||||||
|
printf("Fail: could not retrieve date from system\n");
|
||||||
|
PROCESS_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure RTC and return structure with all parameters */
|
||||||
|
rtcc_init();
|
||||||
|
|
||||||
|
/* Map interrupt callback handler */
|
||||||
|
RTCC_REGISTER_INT1(rtcc_interrupt_callback);
|
||||||
|
|
||||||
|
/* Configure the RTC with the current values */
|
||||||
|
simple_td->weekdays = (uint8_t)strtol(DATE, &next, 10);
|
||||||
|
simple_td->day = (uint8_t)strtol(next, &next, 10);
|
||||||
|
simple_td->months = (uint8_t)strtol(next, &next, 10);
|
||||||
|
simple_td->years = (uint8_t)strtol(next, &next, 10);
|
||||||
|
simple_td->hours = (uint8_t)strtol(next, &next, 10);
|
||||||
|
simple_td->minutes = (uint8_t)strtol(next, &next, 10);
|
||||||
|
simple_td->seconds = (uint8_t)strtol(next, NULL, 10);
|
||||||
|
|
||||||
|
/* Don't care about the milliseconds... */
|
||||||
|
simple_td->miliseconds = 0;
|
||||||
|
|
||||||
|
/* This example relies on 24h mode */
|
||||||
|
simple_td->mode = RTCC_24H_MODE;
|
||||||
|
|
||||||
|
/* And to simplify the configuration, it relies it will be executed in the
|
||||||
|
* present century
|
||||||
|
*/
|
||||||
|
simple_td->century = RTCC_CENTURY_20XX;
|
||||||
|
|
||||||
|
/* Set the time and date */
|
||||||
|
if(rtcc_set_time_date(simple_td) == AB08_ERROR) {
|
||||||
|
printf("Fail: Time and date not configured\n");
|
||||||
|
PROCESS_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait a bit */
|
||||||
|
etimer_set(&et, (CLOCK_SECOND * 2));
|
||||||
|
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
|
||||||
|
|
||||||
|
/* Retrieve the configured time and date, this doesn't overwrites the
|
||||||
|
* mode and century values
|
||||||
|
*/
|
||||||
|
if(rtcc_get_time_date(simple_td) == AB08_ERROR) {
|
||||||
|
printf("Fail: Couldn't read time and date\n");
|
||||||
|
PROCESS_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ...or for visualization only, just print the date directly from the RTCC */
|
||||||
|
printf("Configured time: ");
|
||||||
|
rtcc_print(RTCC_PRINT_DATE_DEC);
|
||||||
|
|
||||||
|
/* Configure the RTCC to trigger an alarm every TEST_ALARM_SECOND tick */
|
||||||
|
printf("Setting an alarm to tick every minute matching %u seconds\n",
|
||||||
|
TEST_ALARM_SECOND);
|
||||||
|
simple_td->seconds = TEST_ALARM_SECOND;
|
||||||
|
|
||||||
|
/* Notice the arguments, we want to trigger the alarm every time the clock
|
||||||
|
* matches the seconds values, so the alarm would have to be repeated every
|
||||||
|
* minute. In case we would want to trigger the alarm on a specific time,
|
||||||
|
* then we would want to set a daily repeat interval
|
||||||
|
*/
|
||||||
|
if(rtcc_set_alarm_time_date(simple_td, RTCC_ALARM_ON,
|
||||||
|
RTCC_REPEAT_MINUTE) == AB08_ERROR) {
|
||||||
|
printf("Fail: couldn't set the alarm\n");
|
||||||
|
PROCESS_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Alarm set to match: ");
|
||||||
|
rtcc_print(RTCC_PRINT_ALARM_DEC);
|
||||||
|
|
||||||
|
PROCESS_END();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
@ -59,6 +59,7 @@ In terms of hardware support, the following drivers have been implemented for th
|
|||||||
* Buttons
|
* Buttons
|
||||||
* Built-in core temperature and battery sensor.
|
* Built-in core temperature and battery sensor.
|
||||||
* CC1200 sub-1GHz radio interface.
|
* CC1200 sub-1GHz radio interface.
|
||||||
|
* Real Time Clock Calendar (on the RE-Mote platform).
|
||||||
|
|
||||||
There is a Zoul powering the RE-Mote and Firefly platforms, check out its specific README files for more information about on-board features.
|
There is a Zoul powering the RE-Mote and Firefly platforms, check out its specific README files for more information about on-board features.
|
||||||
|
|
||||||
@ -218,7 +219,7 @@ LPM is highly related to the operations of the Radio Duty Cycling (RDC) driver o
|
|||||||
* When NullRDC is in use, the radio will be always on. As a result, the algorithm discussed above will always choose PM0 and will never attempt to drop to PM1/2.
|
* When NullRDC is in use, the radio will be always on. As a result, the algorithm discussed above will always choose PM0 and will never attempt to drop to PM1/2.
|
||||||
|
|
||||||
### Shutdown Mode
|
### Shutdown Mode
|
||||||
The RE-Mote has a built-in shutdown mode which effectively reduces the power consumption down to 300nA. Check its specific README file for more information.
|
The RE-Mote has a built-in shutdown mode which effectively reduces the power consumption down to 150nA. Check its specific README file for more information.
|
||||||
|
|
||||||
Build headless nodes
|
Build headless nodes
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
MOTELIST_ZOLERTIA = remote
|
MOTELIST_ZOLERTIA = remote
|
||||||
BOARD_SOURCEFILES += board.c antenna-sw.c
|
BOARD_SOURCEFILES += board.c antenna-sw.c rtcc.c
|
||||||
|
@ -23,13 +23,13 @@ The RE-Mote features a Zoul as its core module and it is bundled with the follow
|
|||||||
* Power input with wide range 3.7-26VDC.
|
* Power input with wide range 3.7-26VDC.
|
||||||
* On-board micro USB connector for USB 2.0 applications.
|
* On-board micro USB connector for USB 2.0 applications.
|
||||||
* RGB LED to allow more than 7 colour combinations.
|
* RGB LED to allow more than 7 colour combinations.
|
||||||
* On-board nano-watt RTC.
|
* On-board nano-watt Real Time Clock Calendar (RTCC).
|
||||||
* User and Reset buttons.
|
* User and Reset buttons.
|
||||||
* On-board Micro-SD for external storage.
|
* On-board Micro-SD for external storage.
|
||||||
* On-board external Watchdog Timer (WDT) for resilient operation.
|
* On-board external Watchdog Timer (WDT) for resilient operation.
|
||||||
* Small form-factor of 73x40 mm.
|
* Small form-factor of 73x40 mm.
|
||||||
|
|
||||||
The most prominent feature of the RE-Mote is its ultra low-power implementation, allowing a flexible and time/date-aware control of the platform operation modes by introducing a real-time clock (RTC), nanowatt external timer, ultra-low power PIC governing the battery manager, etc.
|
The most prominent feature of the RE-Mote is its ultra low-power implementation, allowing a flexible and time/date-aware control of the platform operation modes by introducing a real-time clock (RTCC), nanowatt external timer, ultra-low power PIC governing the battery manager, etc.
|
||||||
|
|
||||||
The RE-Mote features an optional custom-made enclosure to fit most scenarios, allowing to easily connect sensors, actuators and rechargeable LiPo batteries. Its on-board RP-SMA antenna eliminates the need to mechanize an external antenna, allowing to alternatively use either a sub-1GHz or 2.4GHz antenna, or a multiband one.
|
The RE-Mote features an optional custom-made enclosure to fit most scenarios, allowing to easily connect sensors, actuators and rechargeable LiPo batteries. Its on-board RP-SMA antenna eliminates the need to mechanize an external antenna, allowing to alternatively use either a sub-1GHz or 2.4GHz antenna, or a multiband one.
|
||||||
|
|
||||||
|
103
platform/zoul/remote/rtcc-config.h
Normal file
103
platform/zoul/remote/rtcc-config.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Zolertia <http://www.zolertia.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* 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. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS 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.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* \addtogroup remote-rtcc
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* Driver for the RE-Mote RTCC (Real Time Clock Calendar)
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \file
|
||||||
|
* RTCC configuration file
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
*
|
||||||
|
* Antonio Lignan <alinan@zolertia.com>
|
||||||
|
* Aitor Mejias <amejias@zolertia.com>
|
||||||
|
* Toni Lozano <tlozano@zolertia.com>
|
||||||
|
*/
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
#ifndef RTCC_CONFIG_H_
|
||||||
|
#define RTCC_CONFIG_H_
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
#include "rtcc.h"
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* \name RTCC configuration macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define RTCC_SET_DEFAULT_CONFIG 1
|
||||||
|
#define RTCC_CLEAR_INT_MANUALLY 1
|
||||||
|
#define RTCC_SET_AUTOCAL 1
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* \name RTCC default configuration (if enabled by RTCC_SET_DEFAULT_CONFIG)
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* Reset values from the Application Manual */
|
||||||
|
#define RTCC_DEFAULT_STATUS 0x00
|
||||||
|
#define RTCC_DEFAULT_CTRL1 0x11
|
||||||
|
#define RTCC_DEFAULT_CTRL2 0x00
|
||||||
|
#define RTCC_DEFAULT_INTMASK 0xE0
|
||||||
|
#define RTCC_DEFAULT_SQW 0x26
|
||||||
|
#define RTCC_DEFAULT_TIMER_CTRL 0x23
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* \name RTCC default configuration structure
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
typedef struct ab080x_register_config {
|
||||||
|
uint8_t reg;
|
||||||
|
uint8_t val;
|
||||||
|
} ab080x_register_config_t;
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
static const ab080x_register_config_t ab080x_default_setting[] =
|
||||||
|
{
|
||||||
|
{ (CONFIG_MAP_OFFSET + STATUS_ADDR), RTCC_DEFAULT_STATUS },
|
||||||
|
{ (CONFIG_MAP_OFFSET + CTRL_1_ADDR), RTCC_DEFAULT_CTRL1 },
|
||||||
|
{ (CONFIG_MAP_OFFSET + CTRL_2_ADDR), RTCC_DEFAULT_CTRL2 },
|
||||||
|
{ (CONFIG_MAP_OFFSET + INT_MASK_ADDR), RTCC_DEFAULT_INTMASK },
|
||||||
|
{ (CONFIG_MAP_OFFSET + SQW_ADDR), RTCC_DEFAULT_SQW },
|
||||||
|
{ (CONFIG_MAP_OFFSET + TIMER_CONTROL_ADDR), RTCC_DEFAULT_TIMER_CTRL },
|
||||||
|
};
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
#endif /* ifndef RTCC_CONFIG_H_ */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
868
platform/zoul/remote/rtcc.c
Normal file
868
platform/zoul/remote/rtcc.c
Normal file
@ -0,0 +1,868 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Zolertia <http://www.zolertia.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* 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. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS 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.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \addtogroup remote-rtcc
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* Driver for the RE-Mote RTCC (Real Time Clock Calendar)
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \file
|
||||||
|
* Driver for the RE-Mote RF Real Time Clock Calendar (RTCC)
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
*
|
||||||
|
* Antonio Lignan <alinan@zolertia.com>
|
||||||
|
* Aitor Mejias <amejias@zolertia.com>
|
||||||
|
* Toni Lozano <tlozano@zolertia.com>
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#include "contiki.h"
|
||||||
|
#include "dev/gpio.h"
|
||||||
|
#include "dev/i2c.h"
|
||||||
|
#include "rtcc.h"
|
||||||
|
#include "rtcc-config.h"
|
||||||
|
#include "dev/leds.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#define DEBUG 0
|
||||||
|
#if DEBUG
|
||||||
|
#define PRINTF(...) printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define PRINTF(...)
|
||||||
|
#endif
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#define RTC_INT1_PORT_BASE GPIO_PORT_TO_BASE(RTC_INT1_PORT)
|
||||||
|
#define RTC_INT1_PIN_MASK GPIO_PIN_MASK(RTC_INT1_PIN)
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Callback pointers when interrupt occurs */
|
||||||
|
void (*rtcc_int1_callback)(uint8_t value);
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
static const char *ab080x_td_register_name[] =
|
||||||
|
{
|
||||||
|
"Mseconds",
|
||||||
|
"Seconds",
|
||||||
|
"Minutes",
|
||||||
|
"Hours",
|
||||||
|
"Days",
|
||||||
|
"Months",
|
||||||
|
"Years",
|
||||||
|
"Weekdays",
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
static const char *ab080x_config_register_name[] =
|
||||||
|
{
|
||||||
|
"STATUS",
|
||||||
|
"CTRL1",
|
||||||
|
"CTRL2",
|
||||||
|
"INTMASK",
|
||||||
|
"SQW",
|
||||||
|
"CAL_XT",
|
||||||
|
"CAL_RCU",
|
||||||
|
"CAL_RCL",
|
||||||
|
"INTPOL",
|
||||||
|
"TIMER_CTRL",
|
||||||
|
"TIMER_CDOWN",
|
||||||
|
"TIMER_INIT",
|
||||||
|
"WDT",
|
||||||
|
"OSC_CTRL",
|
||||||
|
"OSC_STAT",
|
||||||
|
"CONF_KEY",
|
||||||
|
"TRICKLE",
|
||||||
|
"BREF",
|
||||||
|
};
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static uint8_t
|
||||||
|
bcd_to_dec(uint8_t val)
|
||||||
|
{
|
||||||
|
return (uint8_t)(((val >> 4) * 10) + (val % 16));
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static uint8_t
|
||||||
|
dec_to_bcd(uint8_t val)
|
||||||
|
{
|
||||||
|
return (uint8_t)(((val / 10) << 4) + (val % 10));
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static uint8_t
|
||||||
|
check_leap_year(uint8_t val)
|
||||||
|
{
|
||||||
|
return ((val % 4) && (val % 100)) || (val % 400);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static uint16_t
|
||||||
|
ab08_read_reg(uint8_t reg, uint8_t *buf, uint8_t regnum)
|
||||||
|
{
|
||||||
|
i2c_master_enable();
|
||||||
|
if(i2c_single_send(AB08XX_ADDR, reg) == I2C_MASTER_ERR_NONE) {
|
||||||
|
if(i2c_burst_receive(AB08XX_ADDR, buf, regnum) == I2C_MASTER_ERR_NONE) {
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int8_t
|
||||||
|
ab08_write_reg(uint8_t reg, uint8_t *buf, uint8_t regnum)
|
||||||
|
{
|
||||||
|
uint8_t i, buff[INT_BUFF_SIZE];
|
||||||
|
|
||||||
|
if(regnum > (INT_BUFF_SIZE - 1)) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Replace by single_send/burst_send */
|
||||||
|
|
||||||
|
buff[0] = reg;
|
||||||
|
for(i = 0; i < regnum; i++) {
|
||||||
|
buff[(i + 1)] = buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_master_enable();
|
||||||
|
if(i2c_burst_send(AB08XX_ADDR, buff, (regnum + 1)) == I2C_MASTER_ERR_NONE) {
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
write_default_config(void)
|
||||||
|
{
|
||||||
|
const ab080x_register_config_t *settings;
|
||||||
|
settings = ab080x_default_setting;
|
||||||
|
uint8_t i, len = (sizeof(ab080x_default_setting) / sizeof(ab080x_register_config_t));
|
||||||
|
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
ab08_write_reg(settings[i].reg, (uint8_t *)&settings[i].val, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int8_t
|
||||||
|
ab08_key_reg(uint8_t unlock)
|
||||||
|
{
|
||||||
|
if((unlock != RTCC_CONFKEY_OSCONTROL) && (unlock != RTCC_CONFKEY_SWRESET) &&
|
||||||
|
(unlock != RTCC_CONFKEY_DEFREGS)) {
|
||||||
|
PRINTF("RTC: invalid confkey values\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_write_reg((CONFIG_MAP_OFFSET + CONF_KEY_ADDR), &unlock, 1)) {
|
||||||
|
PRINTF("RTC: failed to write to confkey register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int8_t
|
||||||
|
ab08_read_status(uint8_t *buf)
|
||||||
|
{
|
||||||
|
return ab08_read_reg((STATUS_ADDR + CONFIG_MAP_OFFSET), buf, 1);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int8_t
|
||||||
|
ab08_ctrl1_config(uint8_t cmd)
|
||||||
|
{
|
||||||
|
uint8_t ctrl1 = 0;
|
||||||
|
|
||||||
|
if(cmd >= RTCC_CMD_MAX) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_read_reg((CONFIG_MAP_OFFSET + CTRL_1_ADDR), &ctrl1, 1)) {
|
||||||
|
PRINTF("RTC: failed to retrieve CTRL1 register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cmd) {
|
||||||
|
case RTCC_CMD_LOCK:
|
||||||
|
ctrl1 &= ~CTRL1_WRTC;
|
||||||
|
break;
|
||||||
|
case RTCC_CMD_UNLOCK:
|
||||||
|
ctrl1 |= CTRL1_WRTC;
|
||||||
|
break;
|
||||||
|
case RTCC_CMD_ENABLE:
|
||||||
|
ctrl1 &= ~CTRL1_STOP;
|
||||||
|
break;
|
||||||
|
case RTCC_CMD_STOP:
|
||||||
|
ctrl1 |= CTRL1_STOP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_write_reg((CONFIG_MAP_OFFSET + CTRL_1_ADDR),
|
||||||
|
&ctrl1, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to write to the CTRL1 register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int8_t
|
||||||
|
ab08_check_td_format(simple_td_map *data, uint8_t alarm_state)
|
||||||
|
{
|
||||||
|
/* Using fixed values as these are self-indicative of the variable */
|
||||||
|
if((data->seconds > 59) || (data->minutes > 59) || (data->hours > 23)) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((data->months > 12) || (data->weekdays > 7) || (data->day > 31)) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fixed condition for February (month 2) */
|
||||||
|
if(data->months == 2) {
|
||||||
|
if(check_leap_year(data->years)) {
|
||||||
|
if(data->day > 29) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(data->day > 28) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alarm doesn't care about year */
|
||||||
|
if(!alarm_state) {
|
||||||
|
/* AB08X5 Real-Time Clock Family, page 55 (year up to 2199) */
|
||||||
|
if(data->years > 199) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int8_t
|
||||||
|
rtcc_set_time_date(simple_td_map *data)
|
||||||
|
{
|
||||||
|
uint8_t aux = 0;
|
||||||
|
uint8_t rtc_buffer[RTCC_TD_MAP_SIZE];
|
||||||
|
|
||||||
|
if(ab08_check_td_format(data, 0) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: Invalid time/date values\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_read_reg((CTRL_1_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to retrieve CONTROL1 register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_buffer[WEEKDAYLS_ADDR] = dec_to_bcd(data->weekdays);
|
||||||
|
rtc_buffer[YEAR_ADDR] = dec_to_bcd(data->years);
|
||||||
|
rtc_buffer[MONTHS_ADDR] = dec_to_bcd(data->months);
|
||||||
|
rtc_buffer[DAY_ADDR] = dec_to_bcd(data->day);
|
||||||
|
rtc_buffer[HOUR_ADDR] = dec_to_bcd(data->hours);
|
||||||
|
rtc_buffer[MIN_ADDR] = dec_to_bcd(data->minutes);
|
||||||
|
rtc_buffer[SEC_ADDR] = dec_to_bcd(data->seconds);
|
||||||
|
rtc_buffer[CENTHS_ADDR] = dec_to_bcd(data->miliseconds);
|
||||||
|
|
||||||
|
/* Check if we are to set the time in 12h/24h format */
|
||||||
|
if(data->mode == RTCC_24H_MODE) {
|
||||||
|
aux &= ~CTRL1_1224;
|
||||||
|
} else {
|
||||||
|
if((data->hours == 0) || (data->hours > 12)) {
|
||||||
|
PRINTF("RTC: Invalid hour configuration (12h mode selected)\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
aux |= CTRL1_1224;
|
||||||
|
if(data->mode == RTCC_12H_MODE_PM) {
|
||||||
|
/* Toggle bit for PM */
|
||||||
|
rtc_buffer[HOUR_ADDR] |= RTCC_TOGGLE_PM_BIT;
|
||||||
|
} else {
|
||||||
|
PRINTF("RTC: Invalid time mode selected\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the 12h/24h config */
|
||||||
|
if(ab08_write_reg((CTRL_1_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to write 12h/24h configuration\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reading the STATUS register with the CONTROL1.ARST set will clear the
|
||||||
|
* interrupt flags, we write directly to the register without caring its
|
||||||
|
* actual status and let the interrupt handler take care of any pending flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(ab08_read_reg((STATUS_ADDR + CONFIG_MAP_OFFSET), &aux, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to retrieve STATUS register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->century == RTCC_CENTURY_20XX) {
|
||||||
|
aux |= STATUS_CB;
|
||||||
|
} else if(data->century == RTCC_CENTURY_19XX_21XX) {
|
||||||
|
aux |= ~STATUS_CB;
|
||||||
|
} else {
|
||||||
|
PRINTF("RTC: invalid century value\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINTF("RTC: current STATUS value 0x%02X\n", aux);
|
||||||
|
|
||||||
|
if(ab08_write_reg((STATUS_ADDR + CONFIG_MAP_OFFSET), &aux, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to write century to STATUS register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the WRTC bit to enable writting to the counters */
|
||||||
|
if(ab08_ctrl1_config(RTCC_CMD_UNLOCK) == AB08_ERROR) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the buffers but the mode and century fields (used only for config) */
|
||||||
|
if(ab08_write_reg(CENTHS_ADDR, rtc_buffer,
|
||||||
|
RTCC_TD_MAP_SIZE) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to write date configuration\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock the RTCC and return */
|
||||||
|
if(ab08_ctrl1_config(RTCC_CMD_LOCK) == AB08_ERROR) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int8_t
|
||||||
|
rtcc_get_time_date(simple_td_map *data)
|
||||||
|
{
|
||||||
|
uint8_t rtc_buffer[RTCC_TD_MAP_SIZE];
|
||||||
|
|
||||||
|
if(ab08_read_reg(CENTHS_ADDR, rtc_buffer,
|
||||||
|
RTCC_TD_MAP_SIZE) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to retrieve date and time values\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->weekdays = bcd_to_dec(rtc_buffer[WEEKDAYLS_ADDR]);
|
||||||
|
data->years = bcd_to_dec(rtc_buffer[YEAR_ADDR]);
|
||||||
|
data->months = bcd_to_dec(rtc_buffer[MONTHS_ADDR]);
|
||||||
|
data->day = bcd_to_dec(rtc_buffer[DAY_ADDR]);
|
||||||
|
data->hours = bcd_to_dec(rtc_buffer[HOUR_ADDR]);
|
||||||
|
data->minutes = bcd_to_dec(rtc_buffer[MIN_ADDR]);
|
||||||
|
data->seconds = bcd_to_dec(rtc_buffer[SEC_ADDR]);
|
||||||
|
data->miliseconds = bcd_to_dec(rtc_buffer[CENTHS_ADDR]);
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int8_t
|
||||||
|
rtcc_set_alarm_time_date(simple_td_map *data, uint8_t state, uint8_t repeat)
|
||||||
|
{
|
||||||
|
uint8_t aux[4], buf[RTCC_ALARM_MAP_SIZE];
|
||||||
|
|
||||||
|
if(state == RTCC_ALARM_OFF) {
|
||||||
|
if(ab08_read_reg((INT_MASK_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux[0], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to retrieve INTMASK register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
aux[0] &= ~INTMASK_AIE;
|
||||||
|
|
||||||
|
if(ab08_write_reg((INT_MASK_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux[0], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to clear the alarm config\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((data == NULL) || (ab08_check_td_format(data, 1) == AB08_ERROR)) {
|
||||||
|
PRINTF("RTC: invalid alarm values\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state >= RTCC_ALARM_MAX) || (repeat >= RTCC_REPEAT_100THS)) {
|
||||||
|
PRINTF("RTC: invalid alarm config type or state\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the RTCC */
|
||||||
|
ab08_ctrl1_config(RTCC_CMD_STOP);
|
||||||
|
|
||||||
|
buf[WEEKDAYS_ALARM_ADDR] = dec_to_bcd(data->weekdays);
|
||||||
|
buf[MONTHS_ALARM_ADDR] = dec_to_bcd(data->months);
|
||||||
|
buf[DAY_ALARMS_ADDR] = dec_to_bcd(data->day);
|
||||||
|
buf[HOURS_ALARM_ADDR] = dec_to_bcd(data->hours);
|
||||||
|
buf[MINUTES_ALARM_ADDR] = dec_to_bcd(data->minutes);
|
||||||
|
buf[SECONDS_ALARM_ADDR] = dec_to_bcd(data->seconds);
|
||||||
|
buf[HUNDREDTHS_ALARM_ADDR] = dec_to_bcd(data->miliseconds);
|
||||||
|
|
||||||
|
/* Check if the 12h/24h match the current configuration */
|
||||||
|
if(ab08_read_reg((CTRL_1_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux[0], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to retrieve CONTROL1 register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((aux[0] & CTRL1_1224) && (data->mode == RTCC_24H_MODE)) ||
|
||||||
|
(!(aux[0] & CTRL1_1224) && ((data->mode == RTCC_12H_MODE_AM) ||
|
||||||
|
(data->mode == RTCC_12H_MODE_PM)))) {
|
||||||
|
PRINTF("RTC: 12/24h mode and present date config mismatch\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->mode != RTCC_24H_MODE) {
|
||||||
|
if((data->hours == 0) || (data->hours > 12)) {
|
||||||
|
PRINTF("RTC: Invalid hour configuration (12h mode selected)\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toggle the PM bit */
|
||||||
|
if(data->mode == RTCC_12H_MODE_PM) {
|
||||||
|
buf[HOURS_ALARM_ADDR] |= RTCC_TOGGLE_PM_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the RPT field */
|
||||||
|
if(ab08_read_reg((TIMER_CONTROL_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux[0], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to retrieve TIMER CTRL register\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
aux[0] &= ~COUNTDOWN_TIMER_RPT_SECOND;
|
||||||
|
|
||||||
|
/* AB08XX application manual, table 76 */
|
||||||
|
if(repeat == RTCC_REPEAT_10THS) {
|
||||||
|
buf[HUNDREDTHS_ALARM_ADDR] |= RTCC_FIX_10THS_HUNDRETHS;
|
||||||
|
repeat = RTCC_REPEAT_SECOND;
|
||||||
|
} else if(repeat == RTCC_REPEAT_100THS) {
|
||||||
|
buf[HUNDREDTHS_ALARM_ADDR] |= RTCC_FIX_100THS_HUNDRETHS;
|
||||||
|
repeat = RTCC_REPEAT_SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(repeat != RTCC_REPEAT_NONE) {
|
||||||
|
aux[0] |= (repeat << COUNTDOWN_TIMER_RPT_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are using as default the level interrupt instead of pulses */
|
||||||
|
/* FIXME: make this selectable */
|
||||||
|
aux[0] |= COUNTDOWN_TIMER_TM;
|
||||||
|
aux[0] &= ~COUNTDOWN_TIMER_TRPT;
|
||||||
|
|
||||||
|
if(ab08_write_reg((TIMER_CONTROL_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux[0], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to clear the alarm config\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_read_reg((STATUS_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
aux, 4) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to read configuration registers\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear ALM field if any */
|
||||||
|
aux[STATUS_ADDR] &= ~STATUS_ALM;
|
||||||
|
|
||||||
|
#if RTCC_CLEAR_INT_MANUALLY
|
||||||
|
aux[CTRL_1_ADDR] &= ~CTRL1_ARST;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Clear the AIE alarm bit */
|
||||||
|
aux[INT_MASK_ADDR] &= ~INTMASK_AIE;
|
||||||
|
|
||||||
|
/* Configure Interrupt parameters for Alarm Interrupt Mode in nIRQ pin,
|
||||||
|
* and fixed level until interrupt flag is cleared
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Enable nIRQ if at least one interrupt is enabled */
|
||||||
|
aux[CTRL_2_ADDR] |= CTRL2_OUT1S_NIRQ_NAIRQ_OUT;
|
||||||
|
|
||||||
|
if(repeat != RTCC_REPEAT_NONE) {
|
||||||
|
aux[INT_MASK_ADDR] &= ~INTMASK_IM_LOW;
|
||||||
|
} else {
|
||||||
|
aux[INT_MASK_ADDR] |= INTMASK_IM_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_write_reg((STATUS_ADDR + CONFIG_MAP_OFFSET), aux, 4) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to clear alarm config\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable interrupts */
|
||||||
|
GPIO_ENABLE_INTERRUPT(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK);
|
||||||
|
ioc_set_over(RTC_INT1_PORT, RTC_INT1_PIN, IOC_OVERRIDE_PUE);
|
||||||
|
nvic_interrupt_enable(RTC_INT1_VECTOR);
|
||||||
|
|
||||||
|
/* Write to the alarm counters */
|
||||||
|
if(ab08_write_reg((HUNDREDTHS_ALARM_ADDR + ALARM_MAP_OFFSET), buf,
|
||||||
|
RTCC_ALARM_MAP_SIZE) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to set the alarm\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And finally enable the AIE bit */
|
||||||
|
aux[INT_MASK_ADDR] |= INTMASK_AIE;
|
||||||
|
if(ab08_write_reg((INT_MASK_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux[INT_MASK_ADDR], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to enable the alarm\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable back the RTCC */
|
||||||
|
ab08_ctrl1_config(RTCC_CMD_ENABLE);
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
PROCESS(rtcc_int_process, "RTCC interruption process handler");
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
PROCESS_THREAD(rtcc_int_process, ev, data)
|
||||||
|
{
|
||||||
|
static uint8_t buf;
|
||||||
|
PROCESS_EXITHANDLER();
|
||||||
|
PROCESS_BEGIN();
|
||||||
|
while(1) {
|
||||||
|
PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
|
||||||
|
|
||||||
|
if(ab08_read_status(&buf) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to retrieve ARST value\n");
|
||||||
|
PROCESS_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We only handle the AIE (alarm interrupt) only */
|
||||||
|
if((buf & STATUS_ALM) && (rtcc_int1_callback != NULL)) {
|
||||||
|
#if RTCC_CLEAR_INT_MANUALLY
|
||||||
|
buf &= ~STATUS_ALM;
|
||||||
|
if(ab08_write_reg((STATUS_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&buf, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to clear the alarm\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
rtcc_int1_callback(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PROCESS_END();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int8_t
|
||||||
|
rtcc_print(uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t i, len, reg;
|
||||||
|
char **name;
|
||||||
|
uint8_t rtc_buffer[RTCC_CONFIG_MAP_SIZE];
|
||||||
|
|
||||||
|
if(value >= RTCC_PRINT_MAX) {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(value) {
|
||||||
|
case RTCC_PRINT_CONFIG:
|
||||||
|
len = (RTCC_CONFIG_MAP_SIZE - 1);
|
||||||
|
reg = STATUS_ADDR + CONFIG_MAP_OFFSET;
|
||||||
|
name = (char **)ab080x_config_register_name;
|
||||||
|
break;
|
||||||
|
case RTCC_PRINT_ALARM:
|
||||||
|
case RTCC_PRINT_ALARM_DEC:
|
||||||
|
len = RTCC_ALARM_MAP_SIZE;
|
||||||
|
reg = HUNDREDTHS_ALARM_ADDR + ALARM_MAP_OFFSET;
|
||||||
|
name = (char **)ab080x_td_register_name;
|
||||||
|
break;
|
||||||
|
case RTCC_PRINT_DATE:
|
||||||
|
case RTCC_PRINT_DATE_DEC:
|
||||||
|
len = RTCC_TD_MAP_SIZE;
|
||||||
|
reg = CENTHS_ADDR;
|
||||||
|
name = (char **)ab080x_td_register_name;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_read_reg(reg, rtc_buffer, len) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to retrieve values to print\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(value == RTCC_PRINT_ALARM_DEC) {
|
||||||
|
printf("%02u/%02u (%02u) %02u:%02u:%02u/%02u\n",
|
||||||
|
bcd_to_dec(rtc_buffer[MONTHS_ALARM_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[DAY_ALARMS_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[WEEKDAYS_ALARM_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[HOURS_ALARM_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[MINUTES_ALARM_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[SECONDS_ALARM_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[HUNDREDTHS_ALARM_ADDR]));
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(value == RTCC_PRINT_DATE_DEC) {
|
||||||
|
printf("%02u/%02u/%02u (%02u) %02u:%02u:%02u/%02u\n",
|
||||||
|
bcd_to_dec(rtc_buffer[YEAR_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[MONTHS_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[DAY_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[WEEKDAYLS_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[HOUR_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[MIN_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[SEC_ADDR]),
|
||||||
|
bcd_to_dec(rtc_buffer[CENTHS_ADDR]));
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
printf("0x%02X <- %s\n", rtc_buffer[i], name[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
rtcc_interrupt_handler(uint8_t port, uint8_t pin)
|
||||||
|
{
|
||||||
|
process_poll(&rtcc_int_process);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int8_t
|
||||||
|
rtcc_set_autocalibration(uint8_t period)
|
||||||
|
{
|
||||||
|
uint8_t aux;
|
||||||
|
|
||||||
|
if(period > RTCC_AUTOCAL_9_MIN) {
|
||||||
|
PRINTF("RTC: invalid autocal value\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_read_reg((OSC_CONTROL_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to read oscillator registers\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear ACAL */
|
||||||
|
aux &= ~OSCONTROL_ACAL_9_MIN;
|
||||||
|
|
||||||
|
/* Unlock the key register */
|
||||||
|
ab08_key_reg(RTCC_CONFKEY_OSCONTROL);
|
||||||
|
|
||||||
|
switch(period) {
|
||||||
|
case RTCC_AUTOCAL_DISABLE:
|
||||||
|
break;
|
||||||
|
case RTCC_AUTOCAL_ONCE:
|
||||||
|
case RTCC_AUTOCAL_17_MIN:
|
||||||
|
aux |= OSCONTROL_ACAL_17_MIN;
|
||||||
|
break;
|
||||||
|
case RTCC_AUTOCAL_9_MIN:
|
||||||
|
aux |= OSCONTROL_ACAL_9_MIN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_write_reg((OSC_CONTROL_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to clear the autocalibration\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(period == RTCC_AUTOCAL_ONCE) {
|
||||||
|
clock_delay_usec(10000);
|
||||||
|
ab08_key_reg(RTCC_CONFKEY_OSCONTROL);
|
||||||
|
aux &= ~OSCONTROL_ACAL_9_MIN;
|
||||||
|
if(ab08_write_reg((OSC_CONTROL_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&aux, 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to clear the autocalibration\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int8_t
|
||||||
|
rtcc_set_calibration(uint8_t mode, int32_t adjust)
|
||||||
|
{
|
||||||
|
int32_t adjint;
|
||||||
|
uint8_t adjreg[2];
|
||||||
|
uint8_t xtcal;
|
||||||
|
|
||||||
|
if(mode > RTCC_CAL_RC_OSC) {
|
||||||
|
PRINTF("RTC: invalid calibration mode\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fixed values dependant on the oscillator source (Application Manual) */
|
||||||
|
if((mode == RTCC_CAL_XT_OSC) && ((adjust <= -610) || (adjust >= 242))) {
|
||||||
|
PRINTF("RTC: invalid adjust value for XT oscillator\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((mode == RTCC_CAL_RC_OSC) && ((adjust <= -65536) || (adjust >= 65520))) {
|
||||||
|
PRINTF("RTC: invalid adjust value for XT oscillator\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calibration routine taken from the Application manual */
|
||||||
|
if(adjust < 0) {
|
||||||
|
adjint = ((adjust) * 1000 - 953);
|
||||||
|
} else {
|
||||||
|
adjint = ((adjust) * 1000 + 953);
|
||||||
|
}
|
||||||
|
|
||||||
|
adjint = adjint / 1907;
|
||||||
|
|
||||||
|
if(mode == RTCC_CAL_XT_OSC) {
|
||||||
|
if(adjint > 63) {
|
||||||
|
xtcal = 0;
|
||||||
|
/* CMDX = 1 */
|
||||||
|
adjreg[0] = ((adjint >> 1) & 0x3F) | 0x80;
|
||||||
|
} else if(adjint > -65) {
|
||||||
|
xtcal = 0;
|
||||||
|
adjreg[0] = (adjint & 0x7F);
|
||||||
|
} else if(adjint > -129) {
|
||||||
|
xtcal = 1;
|
||||||
|
adjreg[0] = ((adjint + 64) & 0x7F);
|
||||||
|
} else if(adjint > -193) {
|
||||||
|
xtcal = 2;
|
||||||
|
adjreg[0] = ((adjint + 128) & 0x7F);
|
||||||
|
} else if(adjint > -257) {
|
||||||
|
xtcal = 3;
|
||||||
|
adjreg[0] = ((adjint + 192) & 0x7F);
|
||||||
|
} else {
|
||||||
|
xtcal = 3;
|
||||||
|
adjreg[0] = ((adjint + 192) >> 1) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_write_reg((CAL_XT_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&adjreg[0], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to clear the autocalibration\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_read_reg((OSC_STATUS_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&adjreg[0], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to read oscillator registers\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear XTCAL and write new value */
|
||||||
|
adjreg[0] &= 0x3F;
|
||||||
|
adjreg[0] |= (xtcal << 6);
|
||||||
|
|
||||||
|
if(ab08_write_reg((OSC_STATUS_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
&adjreg[0], 1) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to clear the autocalibration\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
} else if(mode == RTCC_CAL_RC_OSC) {
|
||||||
|
if(adjint > 32767) {
|
||||||
|
adjreg[1] = ((adjint >> 3) & 0xFF);
|
||||||
|
adjreg[0] = ((adjint >> 11) | 0xC0);
|
||||||
|
} else if(adjint > 16383) {
|
||||||
|
adjreg[1] = ((adjint >> 2) & 0xFF);
|
||||||
|
adjreg[0] = ((adjint >> 10) | 0x80);
|
||||||
|
} else if(adjint > 8191) {
|
||||||
|
adjreg[1] = ((adjint >> 1) & 0xFF);
|
||||||
|
adjreg[0] = ((adjint >> 9) | 0x40);
|
||||||
|
} else if(adjint >= 0) {
|
||||||
|
adjreg[1] = ((adjint) & 0xFF);
|
||||||
|
adjreg[0] = (adjint >> 8);
|
||||||
|
} else if(adjint > -8193) {
|
||||||
|
adjreg[1] = ((adjint) & 0xFF);
|
||||||
|
adjreg[0] = (adjint >> 8) & 0x3F;
|
||||||
|
} else if(adjint > -16385) {
|
||||||
|
adjreg[1] = ((adjint >> 1) & 0xFF);
|
||||||
|
adjreg[0] = (adjint >> 9) & 0x7F;
|
||||||
|
} else if(adjint > -32769) {
|
||||||
|
adjreg[1] = ((adjint >> 2) & 0xFF);
|
||||||
|
adjreg[0] = (adjint >> 10) & 0xBF;
|
||||||
|
} else {
|
||||||
|
adjreg[1] = ((adjint >> 3) & 0xFF);
|
||||||
|
adjreg[0] = (adjint >> 11) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ab08_write_reg((CAL_RC_HI_ADDR + CONFIG_MAP_OFFSET),
|
||||||
|
adjreg, 2) == AB08_ERROR) {
|
||||||
|
PRINTF("RTC: failed to set the RC calibration\n");
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This should not happen */
|
||||||
|
} else {
|
||||||
|
return AB08_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int8_t
|
||||||
|
rtcc_init(void)
|
||||||
|
{
|
||||||
|
i2c_init(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SCL_PORT, I2C_SCL_PIN,
|
||||||
|
I2C_SCL_NORMAL_BUS_SPEED);
|
||||||
|
|
||||||
|
#if RTCC_SET_DEFAULT_CONFIG
|
||||||
|
write_default_config();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if RTCC_SET_AUTOCAL
|
||||||
|
rtcc_set_autocalibration(RTCC_AUTOCAL_17_MIN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Initialize interrupts handlers */
|
||||||
|
rtcc_int1_callback = NULL;
|
||||||
|
|
||||||
|
/* Configure the interrupts pins */
|
||||||
|
GPIO_SOFTWARE_CONTROL(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK);
|
||||||
|
GPIO_SET_INPUT(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK);
|
||||||
|
|
||||||
|
/* Pull-up resistor, detect falling edge */
|
||||||
|
GPIO_DETECT_EDGE(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK);
|
||||||
|
GPIO_TRIGGER_SINGLE_EDGE(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK);
|
||||||
|
GPIO_DETECT_FALLING(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK);
|
||||||
|
gpio_register_callback(rtcc_interrupt_handler, RTC_INT1_PORT, RTC_INT1_PIN);
|
||||||
|
|
||||||
|
/* Spin process until an interrupt is received */
|
||||||
|
process_start(&rtcc_int_process, NULL);
|
||||||
|
|
||||||
|
return AB08_SUCCESS;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
380
platform/zoul/remote/rtcc.h
Normal file
380
platform/zoul/remote/rtcc.h
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Zolertia <http://www.zolertia.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* 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. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS 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.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* \addtogroup remote
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \defgroup remote-rtcc RE-Mote Real Time Clock Calendar
|
||||||
|
*
|
||||||
|
* Driver for the RE-Mote on-board ultra-low power RTCC (Real Time Clock
|
||||||
|
* Calendar)
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \file
|
||||||
|
* Header file for the RE-Mote RF antenna switch
|
||||||
|
*/
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
#ifndef RTCC_H_
|
||||||
|
#define RTCC_H_
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "i2c.h"
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* \name Callback function to handle the RTCC alarm interrupt and macro
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define RTCC_REGISTER_INT1(ptr) rtcc_int1_callback = ptr;
|
||||||
|
extern void (*rtcc_int1_callback)(uint8_t value);
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/** \name AB08XX Address registers
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Time/date registers (no offset) */
|
||||||
|
#define CENTHS_ADDR 0x00
|
||||||
|
#define SEC_ADDR 0x01
|
||||||
|
#define MIN_ADDR 0x02
|
||||||
|
#define HOUR_ADDR 0x03
|
||||||
|
#define DAY_ADDR 0x04
|
||||||
|
#define MONTHS_ADDR 0x05
|
||||||
|
#define YEAR_ADDR 0x06
|
||||||
|
#define WEEKDAYLS_ADDR 0x07
|
||||||
|
|
||||||
|
/* Alarm registers */
|
||||||
|
#define ALARM_MAP_OFFSET 0x08
|
||||||
|
#define HUNDREDTHS_ALARM_ADDR 0x00
|
||||||
|
#define SECONDS_ALARM_ADDR 0x01
|
||||||
|
#define MINUTES_ALARM_ADDR 0x02
|
||||||
|
#define HOURS_ALARM_ADDR 0x03
|
||||||
|
#define DAY_ALARMS_ADDR 0x04
|
||||||
|
#define MONTHS_ALARM_ADDR 0x05
|
||||||
|
#define WEEKDAYS_ALARM_ADDR 0x06
|
||||||
|
|
||||||
|
/* Configuration registers */
|
||||||
|
#define CONFIG_MAP_OFFSET 0x0F
|
||||||
|
#define STATUS_ADDR 0x00
|
||||||
|
#define CTRL_1_ADDR 0x01
|
||||||
|
#define CTRL_2_ADDR 0x02
|
||||||
|
#define INT_MASK_ADDR 0x03
|
||||||
|
#define SQW_ADDR 0x04
|
||||||
|
#define CAL_XT_ADDR 0x05
|
||||||
|
#define CAL_RC_HI_ADDR 0x06
|
||||||
|
#define CAL_RC_LO_ADDR 0x07
|
||||||
|
#define INT_POL_ADDR 0x08
|
||||||
|
#define TIMER_CONTROL_ADDR 0x09
|
||||||
|
#define TIMER_COUNTDOWN_ADDR 0x0A
|
||||||
|
#define TIMER_INITIAL_ADDR 0x0B
|
||||||
|
#define WDT_ADDR 0x0C
|
||||||
|
#define OSC_CONTROL_ADDR 0x0D
|
||||||
|
#define OSC_STATUS_ADDR 0x0E
|
||||||
|
#define CONF_KEY_ADDR 0x10
|
||||||
|
#define TRICKLE_ADDR 0x11
|
||||||
|
#define BREF_CTRL_ADDR 0x12
|
||||||
|
#define AF_CTRL_ADDR 0x17
|
||||||
|
#define BAT_MODE_IO_ADDR 0x18
|
||||||
|
#define ASTAT_ADDR 0x20
|
||||||
|
#define OCTRL_ADDR 0x21
|
||||||
|
#define EXT_ADDR 0x30
|
||||||
|
/* 256b. The upper 2 bits are taken from XADS field */
|
||||||
|
#define RAM_1_ADDR (CONFIG_MAP_OFFSET + 0x31)
|
||||||
|
/* 256b. The upper 2 bits are taken from XADA field */
|
||||||
|
#define RAM_2_ADDR (CONFIG_MAP_OFFSET + 0x71)
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/** \name RTCC Bitmasks and shifts
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define STATUS_CB 0x80
|
||||||
|
#define STATUS_BAT 0x40
|
||||||
|
#define STATUS_WDT 0x20
|
||||||
|
#define STATUS_BL 0x10
|
||||||
|
#define STATUS_TIM 0x08
|
||||||
|
#define STATUS_ALM 0x04
|
||||||
|
#define STATUS_EX2 0x02
|
||||||
|
#define STATUS_EX1 0x01
|
||||||
|
|
||||||
|
#define CTRL1_WRTC 0x01
|
||||||
|
#define CTRL1_ARST 0x04
|
||||||
|
#define CTRL1_OUT 0x10
|
||||||
|
#define CTRL1_OUTB 0x20
|
||||||
|
#define CTRL1_1224 0x40
|
||||||
|
#define CTRL1_STOP 0x80
|
||||||
|
|
||||||
|
/* Defines the nIRQ pin control */
|
||||||
|
#define CTRL2_OUT1S_NIRQ_OUT 0x00
|
||||||
|
#define CTRL2_OUT1S_NIRQ_SQW_OUT 0x01
|
||||||
|
#define CTRL2_OUT1S_NIRQ_SQW_NIRQ 0x02
|
||||||
|
#define CTRL2_OUT1S_NIRQ_NAIRQ_OUT 0x03
|
||||||
|
|
||||||
|
/* Defines the nIRQ2 pin control */
|
||||||
|
#define CTRL2_OUT2S_SQW_OUT 0x04
|
||||||
|
#define CTRL2_OUT2S_NAIRQ_OUTB 0x0C
|
||||||
|
#define CTRL2_OUT2S_TIRQ_OUTB 0x10
|
||||||
|
#define CTRL2_OUT2S_NTIRQ_OUTB 0x14
|
||||||
|
#define CTRL2_OUT2S_OUTB 0x1C
|
||||||
|
|
||||||
|
/* Interrupt Mask */
|
||||||
|
#define INTMASK_EX1E 0x01
|
||||||
|
#define INTMASK_EX2E 0x02
|
||||||
|
#define INTMASK_AIE 0x04
|
||||||
|
#define INTMASK_TIE 0x08
|
||||||
|
#define INTMASK_BLIE 0x10
|
||||||
|
#define INTMASK_IM_HIGH 0x20
|
||||||
|
#define INTMASK_IM_MED 0x40
|
||||||
|
#define INTMASK_IM_LOW 0x60
|
||||||
|
#define INTMASK_CEB 0x80
|
||||||
|
|
||||||
|
/* Timer countdown control */
|
||||||
|
#define COUNTDOWN_TIMER_TE 0x80
|
||||||
|
#define COUNTDOWN_TIMER_TM 0x40
|
||||||
|
#define COUNTDOWN_TIMER_TRPT 0x20
|
||||||
|
#define COUNTDOWN_TIMER_RPT_SECOND 0x1C
|
||||||
|
#define COUNTDOWN_TIMER_RPT_MINUTE 0x18
|
||||||
|
#define COUNTDOWN_TIMER_RPT_HOUR 0x24
|
||||||
|
#define COUNTDOWN_TIMER_RPT_DAY 0x10
|
||||||
|
#define COUNTDOWN_TIMER_RPT_WEEK 0x0C
|
||||||
|
#define COUNTDOWN_TIMER_RPT_MONTH 0x08
|
||||||
|
#define COUNTDOWN_TIMER_RPT_YEAR 0x04
|
||||||
|
#define COUNTDOWN_TIMER_RPT_SHIFT 0x02
|
||||||
|
#define COUNTDOWN_TIMER_TFS_ONE 0x01
|
||||||
|
#define COUNTDOWN_TIMER_TFS_TWO 0x02
|
||||||
|
#define COUNTDOWN_TIMER_TFS_THREE 0x03
|
||||||
|
|
||||||
|
/* Oscillator control */
|
||||||
|
#define OSCONTROL_ACIE 0x01
|
||||||
|
#define OSCONTROL_OFIE 0x02
|
||||||
|
#define OSCONTROL_FOS 0x08
|
||||||
|
#define OSCONTROL_AOS 0x10
|
||||||
|
#define OSCONTROL_ACAL_NO_CAL 0x00
|
||||||
|
#define OSCONTROL_ACAL_17_MIN 0x40
|
||||||
|
#define OSCONTROL_ACAL_9_MIN 0x60
|
||||||
|
#define OSCONTROL_OSEL 0x80
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/** \name RTCC operational values
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* I2C address (7-bits) */
|
||||||
|
#define AB08XX_ADDR 0x69
|
||||||
|
#define INT_BUFF_SIZE 20L
|
||||||
|
#define TCS_DIODE_3K (TCS_ENABLE + 0x05)
|
||||||
|
#define TCS_DIODE_6K (TCS_ENABLE + 0x06)
|
||||||
|
#define TCS_DIODE_11K (TCS_ENABLE + 0x07)
|
||||||
|
#define RTCC_TOGGLE_PM_BIT 0x20
|
||||||
|
#define RTCC_FIX_10THS_HUNDRETHS 0xF0
|
||||||
|
#define RTCC_FIX_100THS_HUNDRETHS 0xFF
|
||||||
|
#define RTCC_TD_MAP_SIZE (WEEKDAYLS_ADDR + 1)
|
||||||
|
#define RTCC_ALARM_MAP_SIZE (WEEKDAYS_ALARM_ADDR + 1)
|
||||||
|
#define RTCC_CONFIG_MAP_SIZE (BREF_CTRL_ADDR + 1)
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/** \name RTCC error values
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define AB08_ERROR (-1)
|
||||||
|
#define AB08_SUCCESS 0x00
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/** \name RTCC enumeration and options
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
RTCC_PRINT_DATE = 0,
|
||||||
|
RTCC_PRINT_CONFIG,
|
||||||
|
RTCC_PRINT_ALARM,
|
||||||
|
RTCC_PRINT_ALARM_DEC,
|
||||||
|
RTCC_PRINT_DATE_DEC,
|
||||||
|
RTCC_PRINT_MAX,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
enum {
|
||||||
|
RTCC_ALARM_OFF = 0,
|
||||||
|
RTCC_ALARM_ON,
|
||||||
|
RTCC_ALARM_MAX,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
enum {
|
||||||
|
RTCC_CMD_UNLOCK = 0,
|
||||||
|
RTCC_CMD_LOCK,
|
||||||
|
RTCC_CMD_ENABLE,
|
||||||
|
RTCC_CMD_STOP,
|
||||||
|
RTCC_CMD_MAX,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
enum {
|
||||||
|
RTCC_24H_MODE = 0,
|
||||||
|
RTCC_12H_MODE_AM,
|
||||||
|
RTCC_12H_MODE_PM,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
enum {
|
||||||
|
RTCC_CENTURY_19XX_21XX = 1,
|
||||||
|
RTCC_CENTURY_20XX,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
enum {
|
||||||
|
RTCC_REPEAT_NONE = 0,
|
||||||
|
RTCC_REPEAT_YEAR,
|
||||||
|
RTCC_REPEAT_MONTH,
|
||||||
|
RTCC_REPEAT_WEEK,
|
||||||
|
RTCC_REPEAT_DAY,
|
||||||
|
RTCC_REPEAT_HOUR,
|
||||||
|
RTCC_REPEAT_MINUTE,
|
||||||
|
RTCC_REPEAT_SECOND,
|
||||||
|
RTCC_REPEAT_10THS,
|
||||||
|
RTCC_REPEAT_100THS,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
enum {
|
||||||
|
RTCC_CONFKEY_OSCONTROL = 0xA1,
|
||||||
|
RTCC_CONFKEY_SWRESET = 0x3C,
|
||||||
|
RTCC_CONFKEY_DEFREGS = 0x9D,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
enum {
|
||||||
|
RTCC_CAL_XT_OSC = 0,
|
||||||
|
RTCC_CAL_RC_OSC,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
enum {
|
||||||
|
RTCC_AUTOCAL_DISABLE = 0,
|
||||||
|
RTCC_AUTOCAL_ONCE,
|
||||||
|
RTCC_AUTOCAL_17_MIN,
|
||||||
|
RTCC_AUTOCAL_9_MIN,
|
||||||
|
};
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/** \name Readable Date and time memory map implementation
|
||||||
|
*
|
||||||
|
* This simplified structure allows the user to set date/alarms with a
|
||||||
|
* reduced structure, without the bit-defined restrictions of the memory map,
|
||||||
|
* using decimal values
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
typedef struct ab0805_struct_simple_td_reg {
|
||||||
|
uint8_t miliseconds;
|
||||||
|
uint8_t seconds;
|
||||||
|
uint8_t minutes;
|
||||||
|
uint8_t hours;
|
||||||
|
uint8_t day;
|
||||||
|
uint8_t months;
|
||||||
|
uint8_t years;
|
||||||
|
uint8_t weekdays;
|
||||||
|
uint8_t mode;
|
||||||
|
uint8_t century;
|
||||||
|
} __attribute__ ((packed)) simple_td_map;
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* \name RTCC User functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set the time and date
|
||||||
|
* \param *data Time and date value (decimal format)
|
||||||
|
* \return
|
||||||
|
* \ AB08_SUCCESS date/time set
|
||||||
|
* \ AB08_ERROR failed to set time/date (enable DEBUG for more info)
|
||||||
|
*/
|
||||||
|
int8_t rtcc_set_time_date(simple_td_map *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the current time and date
|
||||||
|
* \param *data buffer to store the results
|
||||||
|
* \return
|
||||||
|
* \ AB08_SUCCESS date/time set
|
||||||
|
* \ AB08_ERROR failed to set time/date (enable DEBUG for more info)
|
||||||
|
*/
|
||||||
|
int8_t rtcc_get_time_date(simple_td_map *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Print data from the RTCC module, either from the memory
|
||||||
|
* map (values in BCD) or actual readable data (decimal).
|
||||||
|
* \param value value to print, see RTCC_PRINT_* options available
|
||||||
|
* \return
|
||||||
|
* \ AB08_SUCCESS date/time set
|
||||||
|
* \ AB08_ERROR failed to set time/date (enable DEBUG for more info)
|
||||||
|
*/
|
||||||
|
int8_t rtcc_print(uint8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Configure the RTCC to match an alarm counter
|
||||||
|
* \param data date and time values (in decimal) to match against
|
||||||
|
* \param state set on/off the alarm interruption
|
||||||
|
* \param repeat set the frequency of the alarm (minute, hourly, daily, etc.)
|
||||||
|
* \return
|
||||||
|
* \ AB08_SUCCESS date/time set
|
||||||
|
* \ AB08_ERROR failed to set time/date (enable DEBUG for more info)
|
||||||
|
*/
|
||||||
|
int8_t rtcc_set_alarm_time_date(simple_td_map *data, uint8_t state,
|
||||||
|
uint8_t repeat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Manually calibrate the RTCC
|
||||||
|
* \param mode oscillator to calibrate
|
||||||
|
* \param adjust value (in ppm) to adjust the oscillator
|
||||||
|
* \return
|
||||||
|
* \ AB08_SUCCESS date/time set
|
||||||
|
* \ AB08_ERROR failed to set time/date (enable DEBUG for more info)
|
||||||
|
*/
|
||||||
|
int8_t rtcc_set_calibration(uint8_t mode, int32_t adjust);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set the autocallibration period
|
||||||
|
* \param period autocalibration configuration
|
||||||
|
* \return
|
||||||
|
* \ AB08_SUCCESS date/time set
|
||||||
|
* \ AB08_ERROR failed to set time/date (enable DEBUG for more info)
|
||||||
|
*/
|
||||||
|
int8_t rtcc_set_autocalibration(uint8_t period);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize the RTCC, configures the I2C bus, interrupts and registers
|
||||||
|
* \return
|
||||||
|
* \ AB08_SUCCESS date/time set
|
||||||
|
* \ AB08_ERROR failed to set time/date (enable DEBUG for more info)
|
||||||
|
*/
|
||||||
|
int8_t rtcc_init(void);
|
||||||
|
/** @} */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
#endif /* ifndef RTCC_H_ */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user