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
graham-pt.h
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 /** @} */
Generated on Tue Jul 12 2022 21:04:14 by 1.7.2