Generic communication interface between the wireless board (mote) and the sensor board. Any kind of sensor board can be connected to the mote using this specification given it provides a SPI peripheral, one input pin with interrupt capability and one digital output. The sensor board must implement a special register set from which all required information can be retrieved. Protocol: http://is.gd/wuQorh Github: http://is.gd/ySj1L9

Dependencies:   mbed-src

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers graham-pt.h Source File

graham-pt.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
00003  * All rights reserved. 
00004  *
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions 
00007  * are met: 
00008  * 1. Redistributions of source code must retain the above copyright 
00009  *    notice, this list of conditions and the following disclaimer. 
00010  * 2. Redistributions in binary form must reproduce the above copyright 
00011  *    notice, this list of conditions and the following disclaimer in the 
00012  *    documentation and/or other materials provided with the distribution. 
00013  * 3. Neither the name of the Institute nor the names of its contributors 
00014  *    may be used to endorse or promote products derived from this software 
00015  *    without specific prior written permission. 
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
00027  * SUCH DAMAGE. 
00028  *
00029  * This file is part of the Contiki operating system.
00030  * 
00031  * Author: Adam Dunkels <adam@sics.se>
00032  *
00033  * $Id: graham-pt.h,v 1.1 2005/10/04 08:30:05 adam Exp $
00034  */
00035 
00036 /**
00037  * \addtogroup pt
00038  * @{
00039  */
00040 
00041 /**
00042  * \file
00043  * Protothreads implementation.
00044  * \author
00045  * Adam Dunkels <adam@sics.se>
00046  *
00047  */
00048 
00049 #ifndef __PT_H__
00050 #define __PT_H__
00051 
00052 #include "lc.h"
00053 
00054 struct pt {
00055   lc_t lc;
00056 };
00057 
00058 /**
00059  * Extended PT.
00060  * This add's a flags field to the basic pt structure.
00061  */
00062 struct ptx {
00063   lc_t lc;
00064   unsigned short flags;
00065 };
00066 
00067 #define PT_THREAD_WAITING 0
00068 #define PT_THREAD_EXITED  1
00069 
00070 /** Extended PT flag : thread is sleeping */
00071 #define PT_F_SLEEPING 1
00072 /** Extended PT flag : thread has been flagged to be killed (will exit on next block/wait/yield) */
00073 #define PT_F_KILL     2
00074 /** Extended PT flag : thread is waiting */
00075 #define PT_F_WAITING  4
00076 
00077 /**
00078  * Declaration of a protothread.
00079  *
00080  * This macro is used to declare a protothread. All protothreads must
00081  * be declared with this macro.
00082  *
00083  * Example:
00084  \code
00085  PT_THREAD(consumer(struct pt *p, int event)) {
00086    PT_BEGIN(p);
00087    while(1) {
00088      PT_WAIT_UNTIL(p, event == AVAILABLE);
00089      consume();
00090      PT_WAIT_UNTIL(p, event == CONSUMED);
00091      acknowledge_consumed();
00092    }
00093    PT_END(p);
00094  }
00095  \endcode
00096  *
00097  * \param name_args The name and arguments of the C function
00098  * implementing the protothread.
00099  *
00100  * \hideinitializer
00101  */
00102 #define PT_THREAD(name_args) char name_args
00103 
00104 /**
00105  * Initialize a protothread.
00106  *
00107  * Initializes a protothread. Initialization must be done prior to
00108  * starting to execute the protothread.
00109  *
00110  * \param pt A pointer to the protothread control structure.
00111  *
00112  * Example:
00113  *
00114  \code
00115  void main(void) {
00116    struct pt p;
00117    int event;
00118    
00119    PT_INIT(&p);
00120    while(PT_SCHEDULE(consumer(&p, event))) {
00121      event = get_event();
00122    }
00123  }
00124  \endcode
00125  *
00126  * \sa PT_SPAWN()
00127  *
00128  * \hideinitializer
00129  */
00130 #define PT_INIT(pt)   LC_INIT((pt)->lc)
00131 
00132 /**
00133  * Declare the start of a protothread inside the C function
00134  * implementing the protothread.
00135  *
00136  * This macro is used to declare the starting point of a
00137  * protothread. It should be placed at the start of the function in
00138  * which the protothread runs. All C statements above the PT_BEGIN()
00139  * invokation will be executed each time the protothread is scheduled.
00140  *
00141  * \param pt A pointer to the protothread control structure.
00142  *
00143  * Example:
00144  *
00145  \code
00146  PT_THREAD(producer(struct pt *p, int event)) {
00147    PT_BEGIN(p);
00148    while(1) {
00149      PT_WAIT_UNTIL(p, event == CONSUMED || event == DROPPED);
00150      produce();
00151      PT_WAIT_UNTIL(p, event == PRODUCED);
00152    }
00153    
00154    PT_END(p);
00155  }
00156  \endcode
00157  *
00158  * \hideinitializer
00159  */
00160 #define PT_BEGIN(pt) LC_RESUME((pt)->lc)
00161 
00162 /**
00163  * Block and wait until condition is true.
00164  *
00165  * This macro blocks the protothread until the specified condition is
00166  * true.
00167  *
00168  * \param pt A pointer to the protothread control structure.
00169  * \param condition The condition.
00170  *
00171  * Example:
00172  \code
00173  PT_THREAD(seconds(struct pt *p)) {
00174    PT_BEGIN(p);
00175 
00176    PT_WAIT_UNTIL(p, time >= 2 * SECOND);
00177    printf("Two seconds have passed\n");
00178    
00179    PT_END(p);
00180  }
00181  \endcode
00182  *
00183  * \hideinitializer
00184  */
00185 #define PT_WAIT_UNTIL(pt, condition)            \
00186   do {                      \
00187     LC_SET((pt)->lc);               \
00188     if(sizeof(*(pt))==sizeof(struct ptx)) \
00189     { \
00190       if(((struct ptx*)(pt))->flags&PT_F_KILL) \
00191       { \
00192         PT_INIT(pt);                \
00193         return PT_THREAD_EXITED; \
00194       } \
00195       if(condition) \
00196         ((struct ptx*)(pt))->flags&=PT_F_WAITING; \
00197       else \
00198         ((struct ptx*)(pt))->flags|=PT_F_WAITING; \
00199       if(((struct ptx*)(pt))->flags&PT_F_WAITING) {             \
00200         return PT_THREAD_WAITING;           \
00201       }                     \
00202     }else{ \
00203       if(!(condition)) {                \
00204         return PT_THREAD_WAITING;           \
00205       }                     \
00206     } \
00207   } while(0)
00208 
00209 /**
00210  * Block and wait while condition is true.
00211  *
00212  * This function blocks and waits while condition is true. See
00213  * PT_WAIT_UNTIL().
00214  *
00215  * \param pt A pointer to the protothread control structure.
00216  * \param cond The condition.
00217  *
00218  * \hideinitializer
00219  */
00220 #define PT_WAIT_WHILE(pt, cond)  PT_WAIT_UNTIL((pt), !(cond))
00221 
00222 
00223 /**
00224  * Block and wait until a child protothread completes.
00225  *
00226  * This macro schedules a child protothread. The current protothread
00227  * will block until the child protothread completes.
00228  *
00229  * \note The child protothread must be manually initialized with the
00230  * PT_INIT() function before this function is used.
00231  *
00232  * \param pt A pointer to the protothread control structure.
00233  * \param thread The child protothread with arguments
00234  *
00235  * Example:
00236  \code
00237  PT_THREAD(child(struct pt *p, int event)) {
00238    PT_BEGIN(p);
00239 
00240    PT_WAIT_UNTIL(p, event == EVENT1);   
00241    
00242    PT_END(p);
00243  }
00244 
00245  PT_THREAD(parent(struct pt *p, struct pt *child_pt, int event)) {
00246    PT_BEGIN(p);
00247 
00248    PT_INIT(child_pt);
00249    
00250    PT_WAIT_THREAD(p, child(child_pt, event));
00251    
00252    PT_END(p);
00253  }
00254  \endcode
00255  *
00256  * \sa PT_SPAWN()
00257  *
00258  * \hideinitializer 
00259  */
00260 #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
00261 
00262 /**
00263  * Spawn a child protothread and wait until it exits.
00264  *
00265  * This macro spawns a child protothread and waits until it exits. The
00266  * macro can only be used within a protothread.
00267  *
00268  * Example:
00269  \code
00270  static struct pt parent_pt, child_pt;
00271  int should_spawn_flag;
00272 
00273  PT_THREAD(child(struct pt *pt)) {
00274    PT_BEGIN(pt);
00275 
00276    while(all_items_processed()) {
00277      process_item();
00278      PT_WAIT_UNTIL(pt, item_processed());
00279    }
00280    
00281    PT_END(pt);
00282  }
00283  
00284  PT_THREAD(parent(void)) {
00285    PT_BEGIN(&parent_pt);
00286 
00287    if(should_spawn_flag) {
00288      PT_SPAWN(&parent_pt, &child_pt, child(&child_pt));
00289    }
00290    
00291    PT_END(&parent_pt);
00292  }
00293  \endcode
00294  *
00295  *
00296  * \param pt A pointer to the protothread control structure.
00297  * \param child A pointer to the child protothread's control structure.
00298  * \param thread The child protothread with arguments
00299  *
00300  * \hideinitializer
00301  */
00302 #define PT_SPAWN(pt, child, thread)     \
00303   do {                      \
00304     PT_INIT((child));               \
00305     PT_WAIT_THREAD((pt), (thread));     \
00306   } while(0)
00307 
00308 /**
00309  * Restart the protothread.
00310  *
00311  * This macro will block and cause the running protothread to restart
00312  * its execution at the place of the PT_BEGIN() call.
00313  *
00314  * \param pt A pointer to the protothread control structure.
00315  *
00316  * \hideinitializer
00317  */
00318 #define PT_RESTART(pt)              \
00319   do {                      \
00320     PT_INIT(pt);                \
00321     return PT_THREAD_WAITING;           \
00322   } while(0)
00323 
00324 /**
00325  * Exit the protothread.
00326  *
00327  * This macro causes the protothread to exit. If the protothread was
00328  * spawned by another protothread, the parent protothread will become
00329  * unblocked and can continue to run.
00330  *
00331  * \param pt A pointer to the protothread control structure.
00332  *
00333  * \hideinitializer
00334  */
00335 #define PT_EXIT(pt)             \
00336   do {                      \
00337     PT_INIT(pt);                \
00338     return PT_THREAD_EXITED;            \
00339   } while(0)
00340 
00341 /**
00342  * Declare the end of a protothread.
00343  *
00344  * This macro is used for declaring that a protothread ends. It should
00345  * always be used together with a matching PT_BEGIN() macro.
00346  *
00347  * \param pt A pointer to the protothread control structure.
00348  *
00349  * \hideinitializer
00350  */
00351 #define PT_END(pt) LC_END((pt)->lc); PT_EXIT(pt)
00352 
00353 
00354 /**
00355  * Schedule a protothread.
00356  *
00357  * This function shedules a protothread. The return value of the
00358  * function is non-zero if the protothread is running or zero if the
00359  * protothread has exited.
00360  *
00361  * Example
00362  \code
00363  void main(void) {
00364    struct pt p;
00365    int event;
00366    
00367    PT_INIT(&p);
00368    while(PT_SCHEDULE(consumer(&p, event))) {
00369      event = get_event();
00370    }   
00371  }
00372  \endcode
00373  *
00374  * \param f The call to the C function implementing the protothread to
00375  * be scheduled
00376  *
00377  * \hideinitializer
00378  */
00379 #define PT_SCHEDULE(f) (f == PT_THREAD_WAITING)
00380 
00381 /**
00382  * Declarare that a protothread can yield.
00383  *
00384  * If a protothread should be able to yield with the PT_YIELD()
00385  * statement, this flag must be placed first in the protothread's
00386  * function body.
00387  *
00388  * Example:
00389  \code
00390  static
00391  PT_THREAD(loop_thread(struct pt *pt))
00392  {
00393    PT_YIELDING();
00394    static int i;
00395 
00396    PT_BEGIN(pt);
00397    
00398    for(i = 0; i < 200; ++i) {
00399      handle_item(i);
00400      PT_YIELD(pt);
00401    }
00402    
00403    PT_END(pt);
00404  }
00405  \endcode
00406  *
00407  * \hideinitializer
00408  */
00409 #define PT_YIELDING() char pt_yielded = 1
00410 
00411 /**
00412  * Yield from the current protothread.
00413  *
00414  * This function will yield the protothread, thereby allowing other
00415  * processing to take place in the system.
00416  *
00417  * \note The PT_YIELDING() flag must be placed first in the
00418  * protothread's body if the PT_YIELD() function should be used.
00419  *
00420  * Example
00421  \code
00422 static
00423 PT_THREAD(fade(struct pt *pt))
00424 {
00425   PT_YIELDING();
00426   static int delay;
00427   
00428   PT_BEGIN(pt);
00429   
00430   for(delay = 3980; delay > 20; delay -= 20) {
00431     leds_red(LEDS_ON);
00432     clock_delay(4000 - delay);
00433     leds_red(LEDS_OFF);
00434     clock_delay(delay);
00435     PT_YIELD(pt);
00436   }
00437   
00438   PT_END(pt);
00439 }
00440  \endcode
00441  * \param pt A pointer to the protothread control structure.
00442  *
00443  * \hideinitializer
00444  */
00445 #define PT_YIELD(pt)                \
00446   do {                      \
00447     pt_yielded = 0;             \
00448     PT_WAIT_UNTIL(pt, pt_yielded);      \
00449   } while(0)
00450 
00451 /*
00452  * Extended Protothread API.
00453  * The following functions require a struct ptx, rather than a plan struct pt.
00454  */  
00455   
00456 /**
00457  * Put a protothread to sleep.
00458  * Execution of the thread won't continue until another thread explicitly wakes the thread
00459  * with PT_WAKE().
00460  * Requires a ptx.
00461  */
00462 #define PT_SLEEP(ptx)   \
00463   do {                      \
00464     ptx->flags|=PT_F_SLEEPING; \
00465     PT_WAIT_UNTIL(ptx, (((ptx)->flags&PT_F_SLEEPING)==0));      \
00466   } while(0)
00467 
00468 /**
00469  * Wake a protothread.
00470  * Wake up a protothread if it is sleeping (ie. has called PT_SLEEP()) - if the thread isn't sleeping,
00471  * then it has no effect.
00472  * NOTE: Requires a ptx.
00473  */
00474 #define PT_WAKE(ptx) (ptx)->flags&=~PT_F_SLEEPING
00475 
00476 /**
00477  * Kill a protothread.
00478  * The thread is marked with the kill flag and will exit next time the thread sleeps/waits/yields.
00479  * NOTE: Requires a ptx.
00480  */
00481 #define PT_KILL(ptx) (ptx)->flags&=~PT_F_KILL
00482 
00483 /**
00484  * Is a protothread blocked?
00485  * Returns non-zero is the thread is waiting.
00486  * NOTE: Requires a ptx.
00487  */
00488 #define PT_ISBLOCKED(ptx) ((ptx)->flags&PT_F_WAITING)
00489   
00490 #endif /* __PT_H__ */
00491 
00492 
00493 /** @} */