contikimac.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010, 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  * $Id: contikimac.c,v 1.48 2011/01/25 14:29:46 adamdunkels Exp $
00032  */
00033 
00034 /**
00035  * \file
00036  *         The Contiki power-saving MAC protocol (ContikiMAC)
00037  * \author
00038  *         Adam Dunkels <adam@sics.se>
00039  *         Niclas Finne <nfi@sics.se>
00040  *         Joakim Eriksson <joakime@sics.se>
00041  */
00042 
00043 #include "net/netstack.h"
00044 #include "dev/leds.h"
00045 #include "dev/radio.h"
00046 #include "dev/watchdog.h"
00047 #include "lib/random.h"
00048 #include "net/mac/contikimac.h"
00049 #include "net/rime.h"
00050 #include "sys/compower.h"
00051 #include "sys/pt.h"
00052 #include "sys/rtimer.h"
00053 
00054 /*#include "cooja-debug.h"*/
00055 #include "contiki-conf.h"
00056 
00057 #ifdef EXPERIMENT_SETUP
00058 #include "experiment-setup.h"
00059 #endif
00060 
00061 #include <string.h>
00062 
00063 #ifndef WITH_PHASE_OPTIMIZATION
00064 #define WITH_PHASE_OPTIMIZATION      1
00065 #endif
00066 #ifndef WITH_STREAMING
00067 #define WITH_STREAMING               0
00068 #endif
00069 #ifndef WITH_CONTIKIMAC_HEADER
00070 #define WITH_CONTIKIMAC_HEADER       1
00071 #endif
00072 #ifndef WITH_FAST_SLEEP
00073 #define WITH_FAST_SLEEP              1
00074 #endif
00075 
00076 #if NETSTACK_RDC_CHANNEL_CHECK_RATE >= 64
00077 #undef WITH_PHASE_OPTIMIZATION
00078 #define WITH_PHASE_OPTIMIZATION 0
00079 #endif
00080 
00081 struct announcement_data {
00082   uint16_t id;
00083   uint16_t value;
00084 };
00085 
00086 /* The maximum number of announcements in a single announcement
00087    message - may need to be increased in the future. */
00088 #define ANNOUNCEMENT_MAX 10
00089 
00090 #if WITH_CONTIKIMAC_HEADER
00091 #define CONTIKIMAC_ID 0x00
00092 
00093 struct hdr {
00094   uint8_t id;
00095   uint8_t len;
00096 };
00097 #endif /* WITH_CONTIKIMAC_HEADER */
00098 
00099 /* The structure of the announcement messages. */
00100 struct announcement_msg {
00101   uint8_t announcement_magic[2];
00102   uint16_t num;
00103   struct announcement_data data[ANNOUNCEMENT_MAX];
00104 };
00105 
00106 #define ANNOUNCEMENT_MAGIC1 0xAD
00107 #define ANNOUNCEMENT_MAGIC2 0xAD
00108 
00109 /* The length of the header of the announcement message, i.e., the
00110    "num" field in the struct. */
00111 #define ANNOUNCEMENT_MSG_HEADERLEN (sizeof(uint16_t) * 2)
00112 
00113 #ifdef CONTIKIMAC_CONF_CYCLE_TIME
00114 #define CYCLE_TIME (CONTIKIMAC_CONF_CYCLE_TIME)
00115 #else
00116 #define CYCLE_TIME (RTIMER_ARCH_SECOND / NETSTACK_RDC_CHANNEL_CHECK_RATE)
00117 #endif
00118 
00119 
00120 /* ContikiMAC performs periodic channel checks. Each channel check
00121    consists of two or more CCA checks. CCA_COUNT_MAX is the number of
00122    CCAs to be done for each periodic channel check. The default is
00123    two.*/
00124 #define CCA_COUNT_MAX                      2
00125 
00126 /* CCA_CHECK_TIME is the time it takes to perform a CCA check. */
00127 #define CCA_CHECK_TIME                     RTIMER_ARCH_SECOND / 8192
00128 
00129 /* CCA_SLEEP_TIME is the time between two successive CCA checks. */
00130 #define CCA_SLEEP_TIME                     RTIMER_ARCH_SECOND / 2000
00131 
00132 /* CHECK_TIME is the total time it takes to perform CCA_COUNT_MAX
00133    CCAs. */
00134 #define CHECK_TIME                         (CCA_COUNT_MAX * (CCA_CHECK_TIME + CCA_SLEEP_TIME))
00135 
00136 /* LISTEN_TIME_AFTER_PACKET_DETECTED is the time that we keep checking
00137    for activity after a potential packet has been detected by a CCA
00138    check. */
00139 #define LISTEN_TIME_AFTER_PACKET_DETECTED  RTIMER_ARCH_SECOND / 80
00140 
00141 /* MAX_SILENCE_PERIODS is the maximum amount of periods (a period is
00142    CCA_CHECK_TIME + CCA_SLEEP_TIME) that we allow to be silent before
00143    we turn of the radio. */
00144 #define MAX_SILENCE_PERIODS                5
00145 
00146 /* MAX_NONACTIVITY_PERIODS is the maximum number of periods we allow
00147    the radio to be turned on without any packet being received, when
00148    WITH_FAST_SLEEP is enabled. */
00149 #define MAX_NONACTIVITY_PERIODS            10
00150 
00151 
00152 
00153 /* STROBE_TIME is the maximum amount of time a transmitted packet
00154    should be repeatedly transmitted as part of a transmission. */
00155 #define STROBE_TIME                        (CYCLE_TIME + 2 * CHECK_TIME)
00156 
00157 /* GUARD_TIME is the time before the expected phase of a neighbor that
00158    a transmitted should begin transmitting packets. */
00159 #define GUARD_TIME                         11 * CHECK_TIME
00160 
00161 /* INTER_PACKET_INTERVAL is the interval between two successive packet transmissions */
00162 #define INTER_PACKET_INTERVAL              RTIMER_ARCH_SECOND / 5000
00163 
00164 /* AFTER_ACK_DETECTECT_WAIT_TIME is the time to wait after a potential
00165    ACK packet has been detected until we can read it out from the
00166    radio. */
00167 #define AFTER_ACK_DETECTECT_WAIT_TIME      RTIMER_ARCH_SECOND / 1500
00168 
00169 /* MAX_PHASE_STROBE_TIME is the time that we transmit repeated packets
00170    to a neighbor for which we have a phase lock. */
00171 #define MAX_PHASE_STROBE_TIME              RTIMER_ARCH_SECOND / 60
00172 
00173 
00174 /* SHORTEST_PACKET_SIZE is the shortest packet that ContikiMAC
00175    allows. Packets have to be a certain size to be able to be detected
00176    by two consecutive CCA checks, and here is where we define this
00177    shortest size. */
00178 #define SHORTEST_PACKET_SIZE               43
00179 
00180 
00181 
00182 /* The cycle time for announcements. */
00183 #ifdef ANNOUNCEMENT_CONF_PERIOD
00184 #define ANNOUNCEMENT_PERIOD ANNOUNCEMENT_CONF_PERIOD
00185 #else /* ANNOUNCEMENT_CONF_PERIOD */
00186 #define ANNOUNCEMENT_PERIOD 1 * CLOCK_SECOND
00187 #endif /* ANNOUNCEMENT_CONF_PERIOD */
00188 
00189 /* The time before sending an announcement within one announcement
00190    cycle. */
00191 #define ANNOUNCEMENT_TIME (random_rand() % (ANNOUNCEMENT_PERIOD))
00192 
00193 
00194 #define ACK_LEN 3
00195 
00196 #include <stdio.h>
00197 static struct rtimer rt;
00198 static struct pt pt;
00199 
00200 static volatile uint8_t contikimac_is_on = 0;
00201 static volatile uint8_t contikimac_keep_radio_on = 0;
00202 
00203 static volatile unsigned char we_are_sending = 0;
00204 static volatile unsigned char radio_is_on = 0;
00205 
00206 #define DEBUG 0
00207 #if DEBUG
00208 #include <stdio.h>
00209 #define PRINTF(...) printf(__VA_ARGS__)
00210 #define PRINTDEBUG(...) printf(__VA_ARGS__)
00211 #else
00212 #define PRINTF(...)
00213 #define PRINTDEBUG(...)
00214 #endif
00215 
00216 #if CONTIKIMAC_CONF_ANNOUNCEMENTS
00217 /* Timers for keeping track of when to send announcements. */
00218 static struct ctimer announcement_cycle_ctimer, announcement_ctimer;
00219 
00220 static int announcement_radio_txpower;
00221 #endif /* CONTIKIMAC_CONF_ANNOUNCEMENTS */
00222 
00223 /* Flag that is used to keep track of whether or not we are snooping
00224    for announcements from neighbors. */
00225 static volatile uint8_t is_snooping;
00226 
00227 #if CONTIKIMAC_CONF_COMPOWER
00228 static struct compower_activity current_packet;
00229 #endif /* CONTIKIMAC_CONF_COMPOWER */
00230 
00231 #if WITH_PHASE_OPTIMIZATION
00232 
00233 #include "net/mac/phase.h"
00234 
00235 #ifndef MAX_PHASE_NEIGHBORS
00236 #define MAX_PHASE_NEIGHBORS 30
00237 #endif
00238 
00239 PHASE_LIST(phase_list, MAX_PHASE_NEIGHBORS);
00240 
00241 #endif /* WITH_PHASE_OPTIMIZATION */
00242 
00243 static volatile uint8_t is_streaming;
00244 static rimeaddr_t is_streaming_to, is_streaming_to_too;
00245 static volatile rtimer_clock_t stream_until;
00246 
00247 #define DEFAULT_STREAM_TIME (4 * CYCLE_TIME)
00248 
00249 #ifndef MIN
00250 #define MIN(a, b) ((a) < (b)? (a) : (b))
00251 #endif /* MIN */
00252 
00253 struct seqno {
00254   rimeaddr_t sender;
00255   uint8_t seqno;
00256 };
00257 
00258 #ifdef NETSTACK_CONF_MAC_SEQNO_HISTORY
00259 #define MAX_SEQNOS NETSTACK_CONF_MAC_SEQNO_HISTORY
00260 #else /* NETSTACK_CONF_MAC_SEQNO_HISTORY */
00261 #define MAX_SEQNOS 16
00262 #endif /* NETSTACK_CONF_MAC_SEQNO_HISTORY */
00263 static struct seqno received_seqnos[MAX_SEQNOS];
00264 
00265 #if CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT
00266 static struct timer broadcast_rate_timer;
00267 static int broadcast_rate_counter;
00268 #endif /* CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT */
00269 
00270 /*---------------------------------------------------------------------------*/
00271 static void
00272 on(void)
00273 {
00274   if(contikimac_is_on && radio_is_on == 0) {
00275     radio_is_on = 1;
00276     NETSTACK_RADIO.on();
00277   }
00278 }
00279 /*---------------------------------------------------------------------------*/
00280 static void
00281 off(void)
00282 {
00283   if(contikimac_is_on && radio_is_on != 0 && /*is_streaming == 0 &&*/
00284      contikimac_keep_radio_on == 0
00285      /* && is_snooping == 0*/) {
00286     radio_is_on = 0;
00287     NETSTACK_RADIO.off();
00288   }
00289 }
00290 /*---------------------------------------------------------------------------*/
00291 static volatile rtimer_clock_t cycle_start;
00292 static char powercycle(struct rtimer *t, void *ptr);
00293 static void
00294 schedule_powercycle(struct rtimer *t, rtimer_clock_t time)
00295 {
00296   int r;
00297 
00298   if(contikimac_is_on) {
00299 
00300     if(RTIMER_CLOCK_LT(RTIMER_TIME(t) + time, RTIMER_NOW() + 2)) {
00301       time = RTIMER_NOW() - RTIMER_TIME(t) + 2;
00302     }
00303 
00304 #if NURTIMER
00305     r = rtimer_reschedule(t, time, 1);
00306 #else
00307     r = rtimer_set(t, RTIMER_TIME(t) + time, 1,
00308                    (void (*)(struct rtimer *, void *))powercycle, NULL);
00309 #endif
00310     if(r != RTIMER_OK) {
00311       printf("schedule_powercycle: could not set rtimer\n");
00312     }
00313   }
00314 }
00315 static void
00316 schedule_powercycle_fixed(struct rtimer *t, rtimer_clock_t fixed_time)
00317 {
00318   int r;
00319 
00320   if(contikimac_is_on) {
00321 
00322     if(RTIMER_CLOCK_LT(fixed_time, RTIMER_NOW() + 1)) {
00323       fixed_time = RTIMER_NOW() + 1;
00324     }
00325 
00326 #if NURTIMER
00327     r = rtimer_reschedule(t, RTIMER_TIME(t) - time, 1);
00328 #else
00329     r = rtimer_set(t, fixed_time, 1,
00330                    (void (*)(struct rtimer *, void *))powercycle, NULL);
00331 #endif
00332     if(r != RTIMER_OK) {
00333       printf("schedule_powercycle: could not set rtimer\n");
00334     }
00335   }
00336 }
00337 static void
00338 powercycle_turn_radio_off(void)
00339 {
00340   if(we_are_sending == 0) {
00341     off();
00342   }
00343 }
00344 static void
00345 powercycle_turn_radio_on(void)
00346 {
00347   if(we_are_sending == 0) {
00348     on();
00349   }
00350 }
00351 static char
00352 powercycle(struct rtimer *t, void *ptr)
00353 {
00354   PT_BEGIN(&pt);
00355 
00356   cycle_start = RTIMER_NOW();
00357   
00358   while(1) {
00359     static uint8_t packet_seen;
00360     static rtimer_clock_t t0;
00361     static uint8_t count;
00362 
00363     cycle_start += CYCLE_TIME;
00364 
00365     if(WITH_STREAMING && is_streaming) {
00366 #if NURTIMER
00367       if(!RTIMER_CLOCK_LT(cycle_start, RTIMER_NOW(), stream_until))
00368 #else
00369         if(!RTIMER_CLOCK_LT(RTIMER_NOW(), stream_until))
00370 #endif
00371           {
00372             is_streaming = 0;
00373             rimeaddr_copy(&is_streaming_to, &rimeaddr_null);
00374             rimeaddr_copy(&is_streaming_to_too, &rimeaddr_null);
00375           }
00376     }
00377 
00378     packet_seen = 0;
00379 
00380     do {
00381       for(count = 0; count < CCA_COUNT_MAX; ++count) {
00382         t0 = RTIMER_NOW();
00383         if(we_are_sending == 0) {
00384           powercycle_turn_radio_on();
00385           //          schedule_powercycle_fixed(t, t0 + CCA_CHECK_TIME);
00386 #if 0
00387 #if NURTIMER
00388           while(RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t0 + CCA_CHECK_TIME));
00389 #else
00390           while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME));
00391 #endif
00392 #endif /* 0 */
00393           /* Check if a packet is seen in the air. If so, we keep the
00394              radio on for a while (LISTEN_TIME_AFTER_PACKET_DETECTED) to
00395              be able to receive the packet. We also continuously check
00396              the radio medium to make sure that we wasn't woken up by a
00397              false positive: a spurious radio interference that was not
00398              caused by an incoming packet. */
00399           if(NETSTACK_RADIO.channel_clear() == 0) {
00400             packet_seen = 1;
00401             break;
00402           }
00403           powercycle_turn_radio_off();
00404 #if CONTIKIMAC_CONF_COMPOWER
00405           compower_accumulate(&compower_idle_activity);
00406 #endif /* CONTIKIMAC_CONF_COMPOWER */
00407 
00408         }
00409         //        schedule_powercycle_fixed(t, t0 + CCA_CHECK_TIME + CCA_SLEEP_TIME);
00410         schedule_powercycle_fixed(t, RTIMER_NOW() + CCA_SLEEP_TIME);
00411         /*        COOJA_DEBUG_STR("yield\n");*/
00412         PT_YIELD(&pt);
00413       }
00414       
00415       if(packet_seen) {
00416         static rtimer_clock_t start;
00417         static uint8_t silence_periods, periods;
00418         start = RTIMER_NOW();
00419         
00420         periods = silence_periods = 0;
00421         while(we_are_sending == 0 && radio_is_on &&
00422               RTIMER_CLOCK_LT(RTIMER_NOW(),
00423                               (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) {
00424           
00425           /* Check for a number of consecutive periods of
00426              non-activity. If we see two such periods, we turn the
00427              radio off. Also, if a packet has been successfully
00428              received (as indicated by the
00429              NETSTACK_RADIO.pending_packet() function), we stop
00430              snooping. */
00431           if(NETSTACK_RADIO.channel_clear()) {
00432             ++silence_periods;
00433           } else {
00434             silence_periods = 0;
00435           }
00436           
00437           ++periods;
00438         
00439           if(NETSTACK_RADIO.receiving_packet()) {
00440             silence_periods = 0;
00441           }
00442           if(silence_periods > MAX_SILENCE_PERIODS) {
00443             powercycle_turn_radio_off();
00444 #if CONTIKIMAC_CONF_COMPOWER
00445             compower_accumulate(&compower_idle_activity);
00446 #endif /* CONTIKIMAC_CONF_COMPOWER */
00447             break;
00448           }
00449           if(WITH_FAST_SLEEP &&
00450              periods > MAX_NONACTIVITY_PERIODS &&
00451              !(NETSTACK_RADIO.receiving_packet() ||
00452                NETSTACK_RADIO.pending_packet())) {
00453             powercycle_turn_radio_off();
00454 #if CONTIKIMAC_CONF_COMPOWER
00455             compower_accumulate(&compower_idle_activity);
00456 #endif /* CONTIKIMAC_CONF_COMPOWER */
00457             break;
00458           }
00459           if(NETSTACK_RADIO.pending_packet()) {
00460             break;
00461           }
00462           
00463           schedule_powercycle(t, CCA_CHECK_TIME + CCA_SLEEP_TIME);
00464           PT_YIELD(&pt);
00465         }
00466         if(radio_is_on) {
00467           if(!(NETSTACK_RADIO.receiving_packet() ||
00468                NETSTACK_RADIO.pending_packet()) ||
00469              !RTIMER_CLOCK_LT(RTIMER_NOW(),
00470                               (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) {
00471             powercycle_turn_radio_off();
00472 #if CONTIKIMAC_CONF_COMPOWER
00473             compower_accumulate(&compower_idle_activity);
00474 #endif /* CONTIKIMAC_CONF_COMPOWER */
00475           }
00476         }
00477       }
00478     } while((is_snooping || is_streaming) &&
00479             RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 8));
00480 
00481     if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) {
00482       /*      schedule_powercycle(t, CYCLE_TIME - (RTIMER_NOW() - cycle_start));*/
00483       schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
00484       /*      printf("cycle_start 0x%02x now 0x%02x wait 0x%02x\n",
00485               cycle_start, RTIMER_NOW(), CYCLE_TIME - (RTIMER_NOW() - cycle_start));*/
00486       PT_YIELD(&pt);
00487     }
00488   }
00489 
00490   PT_END(&pt);
00491 }
00492 /*---------------------------------------------------------------------------*/
00493 #if CONTIKIMAC_CONF_ANNOUNCEMENTS
00494 static int
00495 parse_announcements(void)
00496 {
00497   /* Parse incoming announcements */
00498   struct announcement_msg adata;
00499   const rimeaddr_t *from;
00500   int i;
00501 
00502   memcpy(&adata, packetbuf_dataptr(),
00503          MIN(packetbuf_datalen(), sizeof(adata)));
00504   from = packetbuf_addr(PACKETBUF_ADDR_SENDER);
00505 
00506   /*  printf("%d.%d: probe from %d.%d with %d announcements\n",
00507      rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00508      from->u8[0], from->u8[1], adata.num); */
00509   /*  for(i = 0; i < packetbuf_datalen(); ++i) {
00510      printf("%02x ", ((uint8_t *)packetbuf_dataptr())[i]);
00511      }
00512      printf("\n"); */
00513 
00514   if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) {
00515     /* Sanity check. The number of announcements is too large -
00516        corrupt packet has been received. */
00517     return 0;
00518   }
00519 
00520   for(i = 0; i < adata.num; ++i) {
00521     /*    printf("%d.%d: announcement %d: %d\n",
00522        rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00523        adata.data[i].id,
00524        adata.data[i].value); */
00525 
00526     announcement_heard(from, adata.data[i].id, adata.data[i].value);
00527   }
00528   return i;
00529 }
00530 /*---------------------------------------------------------------------------*/
00531 static int
00532 format_announcement(char *hdr)
00533 {
00534   struct announcement_msg adata;
00535   struct announcement *a;
00536 
00537   /* Construct the announcements */
00538   /*  adata = (struct announcement_msg *)hdr; */
00539 
00540   adata.announcement_magic[0] = ANNOUNCEMENT_MAGIC1;
00541   adata.announcement_magic[1] = ANNOUNCEMENT_MAGIC2;
00542   adata.num = 0;
00543   for(a = announcement_list();
00544       a != NULL && adata.num < ANNOUNCEMENT_MAX;
00545       a = a->next) {
00546     if(a->has_value) {
00547       adata.data[adata.num].id = a->id;
00548       adata.data[adata.num].value = a->value;
00549       adata.num++;
00550     }
00551   }
00552 
00553   memcpy(hdr, &adata, sizeof(struct announcement_msg));
00554 
00555   if(adata.num > 0) {
00556     return ANNOUNCEMENT_MSG_HEADERLEN +
00557       sizeof(struct announcement_data) * adata.num;
00558   } else {
00559     return 0;
00560   }
00561 }
00562 #endif /* CONTIKIMAC_CONF_ANNOUNCEMENTS */
00563 /*---------------------------------------------------------------------------*/
00564 static int
00565 broadcast_rate_drop(void)
00566 {
00567 #if CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT
00568   if(!timer_expired(&broadcast_rate_timer)) {
00569     broadcast_rate_counter++;
00570     if(broadcast_rate_counter < CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT) {
00571       return 0;
00572     } else {
00573       return 1;
00574     }
00575   } else {
00576     timer_set(&broadcast_rate_timer, CLOCK_SECOND);
00577     broadcast_rate_counter = 0;
00578     return 0;
00579   }
00580 #else /* CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT */
00581   return 0;
00582 #endif /* CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT */
00583 }
00584 /*---------------------------------------------------------------------------*/
00585 static int
00586 send_packet(mac_callback_t mac_callback, void *mac_callback_ptr)
00587 {
00588   rtimer_clock_t t0;
00589   rtimer_clock_t encounter_time = 0, previous_txtime = 0;
00590   int strobes;
00591   uint8_t got_strobe_ack = 0;
00592   int hdrlen, len;
00593   uint8_t is_broadcast = 0;
00594   uint8_t is_reliable = 0;
00595   uint8_t is_known_receiver = 0;
00596   uint8_t collisions;
00597   int transmit_len;
00598   int i;
00599   int ret;
00600   uint8_t contikimac_was_on;
00601 #if WITH_CONTIKIMAC_HEADER
00602   struct hdr *chdr;
00603 #endif /* WITH_CONTIKIMAC_HEADER */
00604 
00605   if(packetbuf_totlen() == 0) {
00606     PRINTF("contikimac: send_packet data len 0\n");
00607     return MAC_TX_ERR_FATAL;
00608   }
00609 
00610   
00611   packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
00612   if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
00613     is_broadcast = 1;
00614     PRINTDEBUG("contikimac: send broadcast\n");
00615 
00616     if(broadcast_rate_drop()) {
00617       return MAC_TX_COLLISION;
00618     }
00619   } else {
00620 #if UIP_CONF_IPV6
00621     PRINTDEBUG("contikimac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
00622                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
00623                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
00624                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
00625                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
00626                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
00627                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
00628                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
00629                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
00630 #else /* UIP_CONF_IPV6 */
00631     PRINTDEBUG("contikimac: send unicast to %u.%u\n",
00632                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
00633                packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
00634 #endif /* UIP_CONF_IPV6 */
00635   }
00636   is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
00637     packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);
00638 
00639   if(WITH_STREAMING) {
00640     if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00641        PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
00642       if(rimeaddr_cmp(&is_streaming_to, &rimeaddr_null)) {
00643         rimeaddr_copy(&is_streaming_to,
00644                       packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00645       } else if(!rimeaddr_cmp
00646                 (&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
00647         rimeaddr_copy(&is_streaming_to_too,
00648                       packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00649       }
00650       stream_until = RTIMER_NOW() + DEFAULT_STREAM_TIME;
00651       is_streaming = 1;
00652     }
00653   }
00654 
00655   if(is_streaming) {
00656     packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
00657   }
00658   packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
00659 
00660   if(WITH_CONTIKIMAC_HEADER) {
00661     hdrlen = packetbuf_totlen();
00662     if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) {
00663       /* Failed to allocate space for contikimac header */
00664       PRINTF("contikimac: send failed, too large header\n");
00665       return MAC_TX_ERR_FATAL;
00666     }
00667     chdr = packetbuf_hdrptr();
00668     chdr->id = CONTIKIMAC_ID;
00669     chdr->len = hdrlen;
00670     
00671     /* Create the MAC header for the data packet. */
00672     hdrlen = NETSTACK_FRAMER.create();
00673     if(hdrlen == 0) {
00674       /* Failed to send */
00675       PRINTF("contikimac: send failed, too large header\n");
00676       packetbuf_hdr_remove(sizeof(struct hdr));
00677       return MAC_TX_ERR_FATAL;
00678     }
00679     hdrlen += sizeof(struct hdr);
00680   } else {
00681     /* Create the MAC header for the data packet. */
00682     hdrlen = NETSTACK_FRAMER.create();
00683     if(hdrlen == 0) {
00684       /* Failed to send */
00685       PRINTF("contikimac: send failed, too large header\n");
00686       return MAC_TX_ERR_FATAL;
00687     }
00688   }
00689 
00690 
00691   /* Make sure that the packet is longer or equal to the shortest
00692      packet length. */
00693   transmit_len = packetbuf_totlen();
00694   if(transmit_len < SHORTEST_PACKET_SIZE) {
00695 #if 0
00696     /* Pad with zeroes */
00697     uint8_t *ptr;
00698     ptr = packetbuf_dataptr();
00699     memset(ptr + packetbuf_datalen(), 0, SHORTEST_PACKET_SIZE - packetbuf_totlen());
00700 #endif
00701 
00702     PRINTF("contikimac: shorter than shortest (%d)\n", packetbuf_totlen());
00703     transmit_len = SHORTEST_PACKET_SIZE;
00704   }
00705 
00706 
00707   packetbuf_compact();
00708 
00709   NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len);
00710 
00711   /* Remove the MAC-layer header since it will be recreated next time around. */
00712   packetbuf_hdr_remove(hdrlen);
00713 
00714   if(!is_broadcast && !is_streaming) {
00715 #if WITH_PHASE_OPTIMIZATION
00716     ret = phase_wait(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00717                      CYCLE_TIME, GUARD_TIME,
00718                      mac_callback, mac_callback_ptr);
00719     if(ret == PHASE_DEFERRED) {
00720       return MAC_TX_DEFERRED;
00721     }
00722     if(ret != PHASE_UNKNOWN) {
00723       is_known_receiver = 1;
00724     }
00725 #endif /* WITH_PHASE_OPTIMIZATION */ 
00726   }
00727   
00728 
00729 
00730   /* By setting we_are_sending to one, we ensure that the rtimer
00731      powercycle interrupt do not interfere with us sending the packet. */
00732   we_are_sending = 1;
00733 
00734   /* If we have a pending packet in the radio, we should not send now,
00735      because we will trash the received packet. Instead, we signal
00736      that we have a collision, which lets the packet be received. This
00737      packet will be retransmitted later by the MAC protocol
00738      instread. */
00739   if(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet()) {
00740     we_are_sending = 0;
00741     PRINTF("contikimac: collision receiving %d, pending %d\n",
00742            NETSTACK_RADIO.receiving_packet(), NETSTACK_RADIO.pending_packet());
00743     return MAC_TX_COLLISION;
00744   }
00745   
00746   /* Switch off the radio to ensure that we didn't start sending while
00747      the radio was doing a channel check. */
00748   off();
00749 
00750 
00751   strobes = 0;
00752 
00753   /* Send a train of strobes until the receiver answers with an ACK. */
00754   collisions = 0;
00755 
00756   got_strobe_ack = 0;
00757 
00758   /* Set contikimac_is_on to one to allow the on() and off() functions
00759      to control the radio. We restore the old value of
00760      contikimac_is_on when we are done. */
00761   contikimac_was_on = contikimac_is_on;
00762   contikimac_is_on = 1;
00763   
00764   if(is_streaming == 0) {
00765     /* Check if there are any transmissions by others. */
00766     for(i = 0; i < CCA_COUNT_MAX; ++i) {
00767       t0 = RTIMER_NOW();
00768       on();
00769 #if NURTIMER
00770       while(RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t0 + CCA_CHECK_TIME));
00771 #else
00772       while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { }
00773 #endif
00774       if(NETSTACK_RADIO.channel_clear() == 0) {
00775         collisions++;
00776         off();
00777         break;
00778       }
00779       off();
00780       t0 = RTIMER_NOW();
00781 #if NURTIMER
00782       while(RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t0 + CCA_SLEEP_TIME));
00783 #else
00784       while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_SLEEP_TIME)) { }
00785 #endif
00786     }
00787   }
00788 
00789   if(collisions > 0) {
00790     we_are_sending = 0;
00791     off();
00792     PRINTF("contikimac: collisions before sending\n");
00793     contikimac_is_on = contikimac_was_on;
00794     return MAC_TX_COLLISION;
00795   }
00796 
00797   if(!is_broadcast) {
00798     on();
00799   }
00800   
00801   watchdog_periodic();
00802   t0 = RTIMER_NOW();
00803 
00804 #if NURTIMER
00805   for(strobes = 0, collisions = 0;
00806       got_strobe_ack == 0 && collisions == 0 &&
00807       RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {
00808 #else
00809   for(strobes = 0, collisions = 0;
00810       got_strobe_ack == 0 && collisions == 0 &&
00811       RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {
00812 #endif
00813 
00814     watchdog_periodic();
00815     
00816     if(is_known_receiver && !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
00817       PRINTF("miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
00818       break;
00819     }
00820     
00821     len = 0;
00822 
00823     previous_txtime = RTIMER_NOW();
00824     {
00825       rtimer_clock_t wt;
00826       rtimer_clock_t txtime;
00827       int ret;
00828 
00829       txtime = RTIMER_NOW();
00830       ret = NETSTACK_RADIO.transmit(transmit_len);
00831 
00832       wt = RTIMER_NOW();
00833 #if NURTIMER
00834       while(RTIMER_CLOCK_LT(wt, RTIMER_NOW(), wt + INTER_PACKET_INTERVAL));
00835 #else
00836       while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
00837 #endif
00838       if(!is_broadcast && (NETSTACK_RADIO.receiving_packet() ||
00839                            NETSTACK_RADIO.pending_packet() ||
00840                            NETSTACK_RADIO.channel_clear() == 0)) {
00841         uint8_t ackbuf[ACK_LEN];
00842         wt = RTIMER_NOW();
00843 #if NURTIMER
00844         while(RTIMER_CLOCK_LT(wt, RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME));
00845 #else
00846         while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
00847 #endif
00848         len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
00849         if(len == ACK_LEN) {
00850           got_strobe_ack = 1;
00851           encounter_time = previous_txtime;
00852           break;
00853         } else {
00854           PRINTF("contikimac: collisions while sending\n");
00855           collisions++;
00856         }
00857       }
00858       previous_txtime = txtime;
00859     }
00860   }
00861 
00862   off();
00863 
00864   PRINTF("contikimac: send (strobes=%u, len=%u, %s, %s), done\n", strobes,
00865          packetbuf_totlen(),
00866          got_strobe_ack ? "ack" : "no ack",
00867          collisions ? "collision" : "no collision");
00868 
00869 #if CONTIKIMAC_CONF_COMPOWER
00870   /* Accumulate the power consumption for the packet transmission. */
00871   compower_accumulate(&current_packet);
00872 
00873   /* Convert the accumulated power consumption for the transmitted
00874      packet to packet attributes so that the higher levels can keep
00875      track of the amount of energy spent on transmitting the
00876      packet. */
00877   compower_attrconv(&current_packet);
00878 
00879   /* Clear the accumulated power consumption so that it is ready for
00880      the next packet. */
00881   compower_clear(&current_packet);
00882 #endif /* CONTIKIMAC_CONF_COMPOWER */
00883 
00884   contikimac_is_on = contikimac_was_on;
00885   we_are_sending = 0;
00886 
00887   /* Determine the return value that we will return from the
00888      function. We must pass this value to the phase module before we
00889      return from the function.  */
00890   if(collisions > 0) {
00891     ret = MAC_TX_COLLISION;
00892   } else if(!is_broadcast && !got_strobe_ack) {
00893     ret = MAC_TX_NOACK;
00894   } else {
00895     ret = MAC_TX_OK;
00896   }
00897 
00898 #if WITH_PHASE_OPTIMIZATION
00899 
00900   if(is_known_receiver && got_strobe_ack) {
00901     PRINTF("no miss %d wake-ups %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
00902            strobes);
00903   }
00904 
00905   if(!is_broadcast) {
00906     if(collisions == 0 && is_streaming == 0) {
00907       phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time,
00908                    ret);
00909     }
00910   }
00911 #endif /* WITH_PHASE_OPTIMIZATION */
00912 
00913   if(WITH_STREAMING) {
00914     if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00915        PACKETBUF_ATTR_PACKET_TYPE_STREAM_END) {
00916       is_streaming = 0;
00917     }
00918   }
00919 
00920   return ret;
00921 }
00922 /*---------------------------------------------------------------------------*/
00923 static void
00924 qsend_packet(mac_callback_t sent, void *ptr)
00925 {
00926   int ret = send_packet(sent, ptr);
00927   if(ret != MAC_TX_DEFERRED) {
00928     //    printf("contikimac qsend_packet %p\n", ptr);
00929     mac_call_sent_callback(sent, ptr, ret, 1);
00930   }
00931 }
00932 /*---------------------------------------------------------------------------*/
00933 static void
00934 input_packet(void)
00935 {
00936   /* We have received the packet, so we can go back to being
00937      asleep. */
00938   off();
00939 
00940   /*  printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/
00941   
00942   
00943   if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse()) {
00944 
00945 #if WITH_CONTIKIMAC_HEADER
00946     struct hdr *chdr;
00947     chdr = packetbuf_dataptr();
00948     if(chdr->id != CONTIKIMAC_ID) {
00949       PRINTF("contikimac: failed to parse hdr (%u)\n", packetbuf_totlen());
00950       return;
00951     }
00952     packetbuf_hdrreduce(sizeof(struct hdr));
00953     packetbuf_set_datalen(chdr->len);
00954 #endif /* WITH_CONTIKIMAC_HEADER */
00955 
00956     if(packetbuf_datalen() > 0 &&
00957        packetbuf_totlen() > 0 &&
00958        (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00959                      &rimeaddr_node_addr) ||
00960         rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00961                      &rimeaddr_null))) {
00962       /* This is a regular packet that is destined to us or to the
00963          broadcast address. */
00964 
00965 #if CONTIKIMAC_CONF_ANNOUNCEMENTS
00966       {
00967         struct announcement_msg *hdr = packetbuf_dataptr();
00968         uint8_t magic[2];
00969         memcpy(magic, hdr->announcement_magic, 2);
00970         if(magic[0] == ANNOUNCEMENT_MAGIC1 &&
00971            magic[1] == ANNOUNCEMENT_MAGIC2) {
00972           parse_announcements();
00973         }
00974       }
00975 #endif /* CONTIKIMAC_CONF_ANNOUNCEMENTS */
00976 
00977 #if WITH_PHASE_OPTIMIZATION
00978       /* If the sender has set its pending flag, it has its radio
00979          turned on and we should drop the phase estimation that we
00980          have from before. */
00981       if(packetbuf_attr(PACKETBUF_ATTR_PENDING)) {
00982         phase_remove(&phase_list, packetbuf_addr(PACKETBUF_ADDR_SENDER));
00983       }
00984 #endif /* WITH_PHASE_OPTIMIZATION */
00985 
00986       /* Check for duplicate packet by comparing the sequence number
00987          of the incoming packet with the last few ones we saw. */
00988       {
00989         int i;
00990         for(i = 0; i < MAX_SEQNOS; ++i) {
00991           if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno &&
00992              rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER),
00993                           &received_seqnos[i].sender)) {
00994             /* Drop the packet. */
00995             /*        printf("Drop duplicate ContikiMAC layer packet\n");*/
00996             return;
00997           }
00998         }
00999         for(i = MAX_SEQNOS - 1; i > 0; --i) {
01000           memcpy(&received_seqnos[i], &received_seqnos[i - 1],
01001                  sizeof(struct seqno));
01002         }
01003         received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
01004         rimeaddr_copy(&received_seqnos[0].sender,
01005                       packetbuf_addr(PACKETBUF_ADDR_SENDER));
01006       }
01007 
01008 #if CONTIKIMAC_CONF_COMPOWER
01009       /* Accumulate the power consumption for the packet reception. */
01010       compower_accumulate(&current_packet);
01011       /* Convert the accumulated power consumption for the received
01012          packet to packet attributes so that the higher levels can
01013          keep track of the amount of energy spent on receiving the
01014          packet. */
01015       compower_attrconv(&current_packet);
01016 
01017       /* Clear the accumulated power consumption so that it is ready
01018          for the next packet. */
01019       compower_clear(&current_packet);
01020 #endif /* CONTIKIMAC_CONF_COMPOWER */
01021 
01022       PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen());
01023       NETSTACK_MAC.input();
01024       return;
01025     } else {
01026       PRINTDEBUG("contikimac: data not for us\n");
01027     }
01028   } else {
01029     PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen());
01030   }
01031 }
01032 /*---------------------------------------------------------------------------*/
01033 #if CONTIKIMAC_CONF_ANNOUNCEMENTS
01034 static void
01035 send_announcement(void *ptr)
01036 {
01037   int announcement_len;
01038   int transmit_len;
01039 #if WITH_CONTIKIMAC_HEADER
01040   struct hdr *chdr;
01041 #endif /* WITH_CONTIKIMAC_HEADER */
01042   
01043   /* Set up the probe header. */
01044   packetbuf_clear();
01045   announcement_len = format_announcement(packetbuf_dataptr());
01046 
01047   if(announcement_len > 0) {
01048     packetbuf_set_datalen(announcement_len);
01049 
01050     packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
01051     packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null);
01052     packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER,
01053                        announcement_radio_txpower);
01054 #if WITH_CONTIKIMAC_HEADER
01055     transmit_len = packetbuf_totlen();
01056     if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) {
01057       /* Failed to allocate space for contikimac header */
01058       PRINTF("contikimac: send announcement failed, too large header\n");
01059       return;
01060     }
01061     chdr = packetbuf_hdrptr();
01062     chdr->id = CONTIKIMAC_ID;
01063     chdr->len = transmit_len;
01064 #endif /* WITH_CONTIKIMAC_HEADER */
01065 
01066     if(NETSTACK_FRAMER.create()) {
01067       rtimer_clock_t t;
01068       int i, collisions;
01069       we_are_sending = 1;
01070 
01071       /* Make sure that the packet is longer or equal to the shorest
01072          packet length. */
01073       transmit_len = packetbuf_totlen();
01074       if(transmit_len < SHORTEST_PACKET_SIZE) {
01075 #if 0
01076         /* Pad with zeroes */
01077         uint8_t *ptr;
01078         ptr = packetbuf_dataptr();
01079         memset(ptr + packetbuf_datalen(), 0, SHORTEST_PACKET_SIZE - transmit_len);
01080 #endif
01081 
01082         PRINTF("contikimac: shorter than shortest (%d)\n", packetbuf_totlen());
01083         transmit_len = SHORTEST_PACKET_SIZE;
01084       }
01085 
01086       collisions = 0;
01087       /* Check for collisions */
01088       for(i = 0; i < CCA_COUNT_MAX; ++i) {
01089         t = RTIMER_NOW();
01090         on();
01091 #if NURTIMER
01092         while(RTIMER_CLOCK_LT(t, RTIMER_NOW(), t + CCA_CHECK_TIME));
01093 #else
01094         while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + CCA_CHECK_TIME));
01095 #endif
01096         if(NETSTACK_RADIO.channel_clear() == 0) {
01097           collisions++;
01098           off();
01099           break;
01100         }
01101         off();
01102 #if NURTIMER
01103         while(RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t + CCA_SLEEP_TIME + CCA_CHECK_TIME));
01104 #else
01105         while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + CCA_SLEEP_TIME + CCA_CHECK_TIME)) { }
01106 #endif
01107       }
01108 
01109       if(collisions == 0) {
01110         
01111         NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len);
01112         
01113         NETSTACK_RADIO.transmit(transmit_len);
01114         t = RTIMER_NOW();
01115 #if NURTIMER
01116         while(RTIMER_CLOCK_LT(t, RTIMER_NOW(), t + INTER_PACKET_INTERVAL));
01117 #else
01118         while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + INTER_PACKET_INTERVAL)) { }
01119 #endif
01120         NETSTACK_RADIO.transmit(transmit_len);
01121       }
01122       we_are_sending = 0;
01123     }
01124   }
01125 }
01126 /*---------------------------------------------------------------------------*/
01127 static void
01128 cycle_announcement(void *ptr)
01129 {
01130   ctimer_set(&announcement_ctimer, ANNOUNCEMENT_TIME,
01131              send_announcement, NULL);
01132   ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_PERIOD,
01133              cycle_announcement, NULL);
01134   if(is_snooping > 0) {
01135     is_snooping--;
01136     /*    printf("is_snooping %d\n", is_snooping); */
01137   }
01138 }
01139 /*---------------------------------------------------------------------------*/
01140 static void
01141 listen_callback(int periods)
01142 {
01143   printf("Snoop\n");
01144   is_snooping = periods + 1;
01145 }
01146 #endif /* CONTIKIMAC_CONF_ANNOUNCEMENTS */
01147 /*---------------------------------------------------------------------------*/
01148 void
01149 contikimac_set_announcement_radio_txpower(int txpower)
01150 {
01151 #if CONTIKIMAC_CONF_ANNOUNCEMENTS
01152   announcement_radio_txpower = txpower;
01153 #endif /* CONTIKIMAC_CONF_ANNOUNCEMENTS */
01154 }
01155 /*---------------------------------------------------------------------------*/
01156 static void
01157 init(void)
01158 {
01159   radio_is_on = 0;
01160   PT_INIT(&pt);
01161 #if NURTIMER
01162   rtimer_setup(&rt, RTIMER_HARD,
01163                (void (*)(struct rtimer *, void *, int status))powercycle,
01164                NULL);
01165   rtimer_schedule(&rt, CYCLE_TIME, 1);
01166 #else
01167   rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1,
01168              (void (*)(struct rtimer *, void *))powercycle, NULL);
01169 #endif
01170 
01171   contikimac_is_on = 1;
01172 
01173 #if WITH_PHASE_OPTIMIZATION
01174   phase_init(&phase_list);
01175 #endif /* WITH_PHASE_OPTIMIZATION */
01176 
01177 #if CONTIKIMAC_CONF_ANNOUNCEMENTS
01178   announcement_register_listen_callback(listen_callback);
01179   ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_TIME,
01180              cycle_announcement, NULL);
01181 #endif /* CONTIKIMAC_CONF_ANNOUNCEMENTS */
01182 }
01183 /*---------------------------------------------------------------------------*/
01184 static int
01185 turn_on(void)
01186 {
01187   if(contikimac_is_on == 0) {
01188     contikimac_is_on = 1;
01189     contikimac_keep_radio_on = 0;
01190 #if NURTIMER
01191     rtimer_schedule(&rt, CYCLE_TIME, 1);
01192 #else
01193     rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1,
01194                (void (*)(struct rtimer *, void *))powercycle, NULL);
01195 #endif
01196   }
01197   return 1;
01198 }
01199 /*---------------------------------------------------------------------------*/
01200 static int
01201 turn_off(int keep_radio_on)
01202 {
01203   contikimac_is_on = 0;
01204   contikimac_keep_radio_on = keep_radio_on;
01205   if(keep_radio_on) {
01206     radio_is_on = 1;
01207     return NETSTACK_RADIO.on();
01208   } else {
01209     radio_is_on = 0;
01210     return NETSTACK_RADIO.off();
01211   }
01212 }
01213 /*---------------------------------------------------------------------------*/
01214 static unsigned short
01215 duty_cycle(void)
01216 {
01217   return (1ul * CLOCK_SECOND * CYCLE_TIME) / RTIMER_ARCH_SECOND;
01218 }
01219 /*---------------------------------------------------------------------------*/
01220 const struct rdc_driver contikimac_driver = {
01221   "ContikiMAC",
01222   init,
01223   qsend_packet,
01224   input_packet,
01225   turn_on,
01226   turn_off,
01227   duty_cycle,
01228 };
01229 /*---------------------------------------------------------------------------*/
01230 uint16_t
01231 contikimac_debug_print(void)
01232 {
01233   return 0;
01234 }
01235 /*---------------------------------------------------------------------------*/

Generated on Mon Apr 11 14:23:29 2011 for Contiki 2.5 by  doxygen 1.6.1