diff --git a/core/sys/timesynch.c b/core/sys/timesynch.c new file mode 100644 index 000000000..6f9d190ba --- /dev/null +++ b/core/sys/timesynch.c @@ -0,0 +1,176 @@ +/** + * \addtogroup timesynch + * @{ + */ + + +/* + * Copyright (c) 2007, Swedish Institute of Computer Science. + * 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. + * + * $Id: timesynch.c,v 1.1 2007/12/16 14:29:56 adamdunkels Exp $ + */ + +/** + * \file + * A simple time synchronization mechanism + * \author + * Adam Dunkels + */ + +#include "sys/timesynch.h" +#include "net/rime/rimebuf.h" +#include "net/rime.h" +#include "dev/simple-cc2420.h" + +static const struct mac_driver timesynch_driver; +static const struct mac_driver *mac; +static void (* receiver_callback)(const struct mac_driver *); + +#include + +static int authority_level; +static rtimer_clock_t offset; + +/*---------------------------------------------------------------------------*/ +int +timesynch_authority_level(void) +{ + return authority_level; +} +/*---------------------------------------------------------------------------*/ +void +timesynch_set_authority_level(int level) +{ + authority_level = level; +} +/*---------------------------------------------------------------------------*/ +rtimer_clock_t +timesynch_time(void) +{ + return rtimer_arch_now() + offset; +} +/*---------------------------------------------------------------------------*/ +rtimer_clock_t +timesynch_time_to_rtimer(rtimer_clock_t synched_time) +{ + return synched_time - offset; +} +/*---------------------------------------------------------------------------*/ +rtimer_clock_t +timesynch_offset(void) +{ + return offset; +} +/*---------------------------------------------------------------------------*/ +static int +send(void) +{ + return mac->send(); +} +/*---------------------------------------------------------------------------*/ +static void +input(const struct mac_driver *d) +{ + if(receiver_callback) { + receiver_callback(×ynch_driver); + } +} +/*---------------------------------------------------------------------------*/ +static void +adjust_offset(rtimer_clock_t authoritative_time, rtimer_clock_t local_time) +{ + offset = offset + authoritative_time - local_time; +} +/*---------------------------------------------------------------------------*/ +static int +read(void) +{ + int len; + + len = mac->read(); + + /* We check the authority level of the sender of the incoming + packet. If the sending node has a lower authority level than we + have, we synchronize to the time of the sending node and set our + own authority level to be one more than the sending node. */ + if(simple_cc2420_authority_level_of_sender < authority_level) { + adjust_offset(simple_cc2420_time_of_departure + + simple_cc2420_time_for_transmission, + simple_cc2420_time_of_arrival); + if(simple_cc2420_authority_level_of_sender + 1 != authority_level) { + printf("New authority %d, previous %d\n", + simple_cc2420_authority_level_of_sender + 1, + authority_level); + authority_level = simple_cc2420_authority_level_of_sender + 1; + } + + /* XXX the authority level should be increased over time except + for the sink node. */ + } + + return len; +} +/*---------------------------------------------------------------------------*/ +static void +set_receive_function(void (* recv)(const struct mac_driver *)) +{ + receiver_callback = recv; +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return mac->on(); +} +/*---------------------------------------------------------------------------*/ +static int +off(void) +{ + return mac->off(); +} +/*---------------------------------------------------------------------------*/ +static const struct mac_driver timesynch_driver = { + send, + read, + set_receive_function, + on, + off, +}; +/*---------------------------------------------------------------------------*/ +const struct mac_driver * +timesynch_init(const struct mac_driver *d) +{ + mac = d; + mac->set_receive_function(input); + mac->on(); + return ×ynch_driver; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/sys/timesynch.h b/core/sys/timesynch.h new file mode 100644 index 000000000..e975b8247 --- /dev/null +++ b/core/sys/timesynch.h @@ -0,0 +1,144 @@ +/** + * \addtogroup sys + * @{ + */ + +/** + * \defgroup timesynch Implicit network time synchronization + * @{ + * + * This crude and simple network time synchronization module + * synchronizes clocks of all nodes in a network. The time + * synchronization is implicit in that no explicit time + * synchronization messages are sent: the module relies on the + * underlying network device driver to timestamp all radio messages, + * both outgoing and incoming. The code currently only works on the + * Tmote Sky platform and the simple-cc2420 driver. + * + * Every node has an authority level, which is included in every + * outgoing packet. If a message is received from a node with higher + * authority (lower authority number), the node adjusts its clock + * towards the clock of the sending node. + * + * The timesynch module is implemented as a meta-MAC protocol, so that + * the module is invoked for every incoming packet. + * + */ + +/* + * Copyright (c) 2007, Swedish Institute of Computer Science. + * 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. + * + * $Id: timesynch.h,v 1.1 2007/12/16 14:29:56 adamdunkels Exp $ + */ + +/** + * \file + * Header file for a simple time synchronization mechanism + * \author + * Adam Dunkels + */ + +#ifndef __TIMESYNCH_H__ +#define __TIMESYNCH_H__ + +#include "net/mac/mac.h" +#include "sys/rtimer.h" + +/** + * \brief Initialize the timesynch module; should be called during the MAC initialization procedure + * \param r The underlying MAC driver + * \return A pointer to the timesynch module's meta MAC driver + * + * This function initializes the timesynch module. The + * function should be called as part of the MAC + * initialization procedure. + * + */ +const struct mac_driver *timesynch_init(const struct mac_driver *r); + +/** + * \brief Get the current time-synchronized time + * \return The current time-synchronized time + * + * This function returns the current time-synchronized + * time. + * + */ +rtimer_clock_t timesynch_time(void); + +/** + * \brief Get the current time-synchronized rtimer time, suitable for use with the rtimer module + * \return The current time-synchronized rtimer time + * + * This function returns the (local) rtimer-equivalent + * time corresponding to the current time-synchronized + * (global) time. The rtimer-equivalent time is used for + * setting rtimer timers that are synchronized to other + * nodes in the network. + * + */ +rtimer_clock_t timesynch_time_to_rtimer(rtimer_clock_t synched_time); + +/** + * \brief Get the current time-synchronized offset from the rtimer clock, which is used mainly for debugging + * \return The current time-synchronized offset from the rtimer clock + * + * This function returns the current time-synchronized + * offset from the rtimer arch clock. This is mainly + * useful for debugging the timesynch module. + * + */ +rtimer_clock_t timesynch_offset(void); + +/** + * \brief Get the current authority level of the time-synchronized time + * \return The current authority level of the time-synchronized time + * + * This function returns the current authority level of + * the time-synchronized time. A node with a lower + * authority level is defined to have a better notion of + * time than a node with a higher authority + * level. Authority level 0 is best and should be used by + * a sink node that has a connection to an outside, + * "true", clock source. + * + */ +int timesynch_authority_level(void); + +/** + * \brief Set the authority level of the current time + * \param level The authority level + */ +void timesynch_set_authority_level(int level); + +#endif /* __TIMESYNCH_H__ */ + +/** @} */ +/** @} */