42 #include "contiki-conf.h"
45 #include "dev/watchdog.h"
46 #include "lib/random.h"
59 #ifdef CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION
60 #define WITH_PHASE_OPTIMIZATION CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION
62 #define WITH_PHASE_OPTIMIZATION 1
65 #ifndef WITH_FAST_SLEEP
66 #define WITH_FAST_SLEEP 1
69 #ifndef RDC_CONF_HARDWARE_CSMA
70 #define RDC_CONF_HARDWARE_CSMA 0
73 #ifndef RDC_CONF_HARDWARE_ACK
74 #define RDC_CONF_HARDWARE_ACK 0
77 #ifndef RDC_CONF_MCU_SLEEP
78 #define RDC_CONF_MCU_SLEEP 0
81 #if NETSTACK_RDC_CHANNEL_CHECK_RATE >= 64
82 #undef WITH_PHASE_OPTIMIZATION
83 #define WITH_PHASE_OPTIMIZATION 0
87 #ifdef CONTIKIMAC_CONF_CYCLE_TIME
88 #define CYCLE_TIME (CONTIKIMAC_CONF_CYCLE_TIME)
90 #define CYCLE_TIME (RTIMER_ARCH_SECOND / NETSTACK_RDC_CHANNEL_CHECK_RATE)
100 #if RTIMER_ARCH_SECOND & (RTIMER_ARCH_SECOND - 1)
101 #define SYNC_CYCLE_STARTS 1
105 static int we_are_receiving_burst = 0;
109 #define INTER_PACKET_DEADLINE CLOCK_SECOND / 32
115 #ifdef CONTIKIMAC_CONF_CCA_COUNT_MAX
116 #define CCA_COUNT_MAX (CONTIKIMAC_CONF_CCA_COUNT_MAX)
118 #define CCA_COUNT_MAX 2
123 #ifdef CONTIKIMAC_CONF_CCA_COUNT_MAX_TX
124 #define CCA_COUNT_MAX_TX (CONTIKIMAC_CONF_CCA_COUNT_MAX_TX)
126 #define CCA_COUNT_MAX_TX 6
131 #ifdef CONTIKIMAC_CONF_CCA_CHECK_TIME
132 #define CCA_CHECK_TIME (CONTIKIMAC_CONF_CCA_CHECK_TIME)
134 #define CCA_CHECK_TIME RTIMER_ARCH_SECOND / 8192
139 #if RTIMER_ARCH_SECOND > 8000
140 #define CCA_SLEEP_TIME RTIMER_ARCH_SECOND / 2000
142 #define CCA_SLEEP_TIME (RTIMER_ARCH_SECOND / 2000) + 1
147 #define CHECK_TIME (CCA_COUNT_MAX * (CCA_CHECK_TIME + CCA_SLEEP_TIME))
151 #define CHECK_TIME_TX (CCA_COUNT_MAX_TX * (CCA_CHECK_TIME + CCA_SLEEP_TIME))
156 #define LISTEN_TIME_AFTER_PACKET_DETECTED RTIMER_ARCH_SECOND / 80
161 #define MAX_SILENCE_PERIODS 5
166 #define MAX_NONACTIVITY_PERIODS 10
172 #define STROBE_TIME (CYCLE_TIME + 2 * CHECK_TIME)
176 #define GUARD_TIME 10 * CHECK_TIME + CHECK_TIME_TX
179 #ifdef CONTIKIMAC_CONF_INTER_PACKET_INTERVAL
180 #define INTER_PACKET_INTERVAL CONTIKIMAC_CONF_INTER_PACKET_INTERVAL
182 #define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 2500
188 #ifdef CONTIKIMAC_CONF_AFTER_ACK_DETECTECT_WAIT_TIME
189 #define AFTER_ACK_DETECTECT_WAIT_TIME CONTIKIMAC_CONF_AFTER_ACK_DETECTECT_WAIT_TIME
191 #define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1500
196 #define MAX_PHASE_STROBE_TIME RTIMER_ARCH_SECOND / 60
204 static volatile uint8_t contikimac_is_on = 0;
205 static volatile uint8_t contikimac_keep_radio_on = 0;
207 static volatile unsigned char we_are_sending = 0;
208 static volatile unsigned char radio_is_on = 0;
213 #define PRINTF(...) printf(__VA_ARGS__)
214 #define PRINTDEBUG(...) printf(__VA_ARGS__)
217 #define PRINTDEBUG(...)
220 #if CONTIKIMAC_CONF_COMPOWER
224 #if WITH_PHASE_OPTIMIZATION
230 #define DEFAULT_STREAM_TIME (4 * CYCLE_TIME)
233 #define MIN(a, b) ((a) < (b)? (a) : (b))
236 #if CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT
237 static struct timer broadcast_rate_timer;
238 static int broadcast_rate_counter;
245 if(contikimac_is_on && radio_is_on == 0) {
254 if(contikimac_is_on && radio_is_on != 0 &&
255 contikimac_keep_radio_on == 0) {
257 NETSTACK_RADIO.off();
261 static volatile rtimer_clock_t cycle_start;
262 static char powercycle(
struct rtimer *t,
void *ptr);
264 schedule_powercycle(
struct rtimer *t, rtimer_clock_t time)
268 if(contikimac_is_on) {
275 (
void (*)(
struct rtimer *,
void *))powercycle,
NULL);
277 PRINTF(
"schedule_powercycle: could not set rtimer\n");
283 schedule_powercycle_fixed(
struct rtimer *t, rtimer_clock_t fixed_time)
287 if(contikimac_is_on) {
289 if(RTIMER_CLOCK_LT(fixed_time,
RTIMER_NOW() + 1)) {
294 (
void (*)(
struct rtimer *,
void *))powercycle,
NULL);
296 PRINTF(
"schedule_powercycle: could not set rtimer\n");
302 powercycle_turn_radio_off(
void)
304 #if CONTIKIMAC_CONF_COMPOWER
305 uint8_t was_on = radio_is_on;
308 if(we_are_sending == 0 && we_are_receiving_burst == 0) {
310 #if CONTIKIMAC_CONF_COMPOWER
311 if(was_on && !radio_is_on) {
319 powercycle_turn_radio_on(
void)
321 if(we_are_sending == 0 && we_are_receiving_burst == 0) {
327 powercycle(
struct rtimer *t,
void *ptr)
329 #if SYNC_CYCLE_STARTS
330 static volatile rtimer_clock_t sync_cycle_start;
331 static volatile uint8_t sync_cycle_phase;
336 #if SYNC_CYCLE_STARTS
343 static uint8_t packet_seen;
344 static rtimer_clock_t t0;
345 static uint8_t count;
347 #if SYNC_CYCLE_STARTS
350 if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
351 sync_cycle_phase = 0;
352 sync_cycle_start += RTIMER_ARCH_SECOND;
353 cycle_start = sync_cycle_start;
355 #if (RTIMER_ARCH_SECOND * NETSTACK_RDC_CHANNEL_CHECK_RATE) > 65535
356 cycle_start = sync_cycle_start + ((
unsigned long)(sync_cycle_phase*RTIMER_ARCH_SECOND))/NETSTACK_RDC_CHANNEL_CHECK_RATE;
358 cycle_start = sync_cycle_start + (sync_cycle_phase*RTIMER_ARCH_SECOND)/NETSTACK_RDC_CHANNEL_CHECK_RATE;
362 cycle_start += CYCLE_TIME;
367 for(count = 0; count < CCA_COUNT_MAX; ++count) {
369 if(we_are_sending == 0 && we_are_receiving_burst == 0) {
370 powercycle_turn_radio_on();
377 if(NETSTACK_RADIO.channel_clear() == 0) {
381 powercycle_turn_radio_off();
383 schedule_powercycle_fixed(t,
RTIMER_NOW() + CCA_SLEEP_TIME);
388 static rtimer_clock_t start;
389 static uint8_t silence_periods, periods;
392 periods = silence_periods = 0;
393 while(we_are_sending == 0 && radio_is_on &&
395 (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) {
403 #if !RDC_CONF_HARDWARE_CSMA
406 if(NETSTACK_RADIO.channel_clear()) {
415 if(NETSTACK_RADIO.receiving_packet()) {
418 if(silence_periods > MAX_SILENCE_PERIODS) {
419 powercycle_turn_radio_off();
422 if(WITH_FAST_SLEEP &&
423 periods > MAX_NONACTIVITY_PERIODS &&
424 !(NETSTACK_RADIO.receiving_packet() ||
425 NETSTACK_RADIO.pending_packet())) {
426 powercycle_turn_radio_off();
429 if(NETSTACK_RADIO.pending_packet()) {
433 schedule_powercycle(t, CCA_CHECK_TIME + CCA_SLEEP_TIME);
437 if(!(NETSTACK_RADIO.receiving_packet() ||
438 NETSTACK_RADIO.pending_packet()) ||
440 (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) {
441 powercycle_turn_radio_off();
446 if(RTIMER_CLOCK_LT(
RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) {
451 #if RDC_CONF_MCU_SLEEP
452 static uint8_t sleepcycle;
453 if((sleepcycle++ < 16) && !we_are_sending && !radio_is_on) {
454 rtimer_arch_sleep(CYCLE_TIME - (
RTIMER_NOW() - cycle_start));
457 schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
461 schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
471 broadcast_rate_drop(
void)
473 #if CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT
475 broadcast_rate_counter++;
476 if(broadcast_rate_counter < CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT) {
483 broadcast_rate_counter = 0;
492 send_packet(mac_callback_t mac_callback,
void *mac_callback_ptr,
493 struct rdc_buf_list *buf_list,
494 int is_receiver_awake)
497 rtimer_clock_t encounter_time = 0;
499 uint8_t got_strobe_ack = 0;
501 uint8_t is_broadcast = 0;
502 uint8_t is_reliable = 0;
503 uint8_t is_known_receiver = 0;
507 uint8_t contikimac_was_on;
511 if(!contikimac_is_on && !contikimac_keep_radio_on) {
512 PRINTF(
"contikimac: radio is turned off\n");
513 return MAC_TX_ERR_FATAL;
517 PRINTF(
"contikimac: send_packet data len 0\n");
518 return MAC_TX_ERR_FATAL;
521 #if !NETSTACK_CONF_BRIDGE_MODE
527 PRINTDEBUG(
"contikimac: send broadcast\n");
529 if(broadcast_rate_drop()) {
534 PRINTDEBUG(
"contikimac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
535 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
536 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
537 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
538 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
539 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
540 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
541 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
542 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
544 PRINTDEBUG(
"contikimac: send unicast to %u.%u\n",
545 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
546 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
549 is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
550 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);
552 if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) {
553 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
554 if(NETSTACK_FRAMER.create_and_secure() < 0) {
555 PRINTF(
"contikimac: framer failed\n");
556 return MAC_TX_ERR_FATAL;
563 if(!is_broadcast && !is_receiver_awake) {
564 #if WITH_PHASE_OPTIMIZATION
565 ret = phase_wait(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
566 CYCLE_TIME, GUARD_TIME,
567 mac_callback, mac_callback_ptr, buf_list);
568 if(ret == PHASE_DEFERRED) {
571 if(ret != PHASE_UNKNOWN) {
572 is_known_receiver = 1;
588 if(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet()) {
590 PRINTF(
"contikimac: collision receiving %d, pending %d\n",
591 NETSTACK_RADIO.receiving_packet(), NETSTACK_RADIO.pending_packet());
610 contikimac_was_on = contikimac_is_on;
611 contikimac_is_on = 1;
613 #if !RDC_CONF_HARDWARE_CSMA
616 if(is_receiver_awake == 0) {
618 for(i = 0; i < CCA_COUNT_MAX_TX; ++i) {
621 #if CCA_CHECK_TIME > 0
622 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { }
624 if(NETSTACK_RADIO.channel_clear() == 0) {
631 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + CCA_SLEEP_TIME)) { }
638 PRINTF(
"contikimac: collisions before sending\n");
639 contikimac_is_on = contikimac_was_on;
644 #if !RDC_CONF_HARDWARE_ACK
655 seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
656 for(strobes = 0, collisions = 0;
657 got_strobe_ack == 0 && collisions == 0 &&
658 RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {
662 if(!is_broadcast && (is_receiver_awake || is_known_receiver) &&
663 !RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
664 PRINTF(
"miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
672 rtimer_clock_t txtime;
676 ret = NETSTACK_RADIO.transmit(transmit_len);
678 #if RDC_CONF_HARDWARE_ACK
681 if(ret == RADIO_TX_OK) {
684 encounter_time = txtime;
687 }
else if (ret == RADIO_TX_NOACK) {
688 }
else if (ret == RADIO_TX_COLLISION) {
689 PRINTF(
"contikimac: collisions while sending\n");
693 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
697 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
699 if(!is_broadcast && (NETSTACK_RADIO.receiving_packet() ||
700 NETSTACK_RADIO.pending_packet() ||
701 NETSTACK_RADIO.channel_clear() == 0)) {
702 uint8_t ackbuf[ACK_LEN];
704 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
706 len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
707 if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) {
709 encounter_time = txtime;
712 PRINTF(
"contikimac: collisions while sending\n");
722 PRINTF(
"contikimac: send (strobes=%u, len=%u, %s, %s), done\n", strobes,
724 got_strobe_ack ?
"ack" :
"no ack",
725 collisions ?
"collision" :
"no collision");
727 #if CONTIKIMAC_CONF_COMPOWER
742 contikimac_is_on = contikimac_was_on;
750 }
else if(!is_broadcast && !got_strobe_ack) {
756 #if WITH_PHASE_OPTIMIZATION
757 if(is_known_receiver && got_strobe_ack) {
758 PRINTF(
"no miss %d wake-ups %d\n",
759 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
764 if(collisions == 0 && is_receiver_awake == 0) {
765 phase_update(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
766 encounter_time, ret);
775 qsend_packet(mac_callback_t sent,
void *ptr)
777 int ret = send_packet(sent, ptr,
NULL, 0);
779 mac_call_sent_callback(sent, ptr, ret, 1);
784 qsend_list(mac_callback_t sent,
void *ptr,
struct rdc_buf_list *buf_list)
786 struct rdc_buf_list *curr;
787 struct rdc_buf_list *next;
789 int is_receiver_awake;
791 if(buf_list ==
NULL) {
795 if(we_are_receiving_burst) {
797 queuebuf_to_packetbuf(buf_list->buf);
807 queuebuf_to_packetbuf(curr->buf);
808 if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) {
811 packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
813 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
814 if(NETSTACK_FRAMER.create_and_secure() < 0) {
815 PRINTF(
"contikimac: framer failed\n");
816 mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1);
820 packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1);
821 queuebuf_update_from_packetbuf(curr->buf);
824 }
while(next !=
NULL);
827 is_receiver_awake = 0;
833 queuebuf_to_packetbuf(curr->buf);
836 ret = send_packet(sent, ptr, curr, is_receiver_awake);
838 mac_call_sent_callback(sent, ptr, ret, 1);
844 is_receiver_awake = 1;
851 }
while((next !=
NULL) && packetbuf_attr(PACKETBUF_ATTR_PENDING));
858 recv_burst_off(
void *ptr)
861 we_are_receiving_burst = 0;
867 static struct ctimer ct;
868 if(!we_are_receiving_burst) {
887 we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
888 if(we_are_receiving_burst) {
898 #if RDC_WITH_DUPLICATE_DETECTION
908 #if CONTIKIMAC_CONF_COMPOWER
923 NETSTACK_MAC.input();
926 PRINTDEBUG(
"contikimac: data not for us\n");
940 (
void (*)(
struct rtimer *,
void *))powercycle,
NULL);
942 contikimac_is_on = 1;
944 #if WITH_PHASE_OPTIMIZATION
953 if(contikimac_is_on == 0) {
954 contikimac_is_on = 1;
955 contikimac_keep_radio_on = 0;
957 (
void (*)(
struct rtimer *,
void *))powercycle,
NULL);
963 turn_off(
int keep_radio_on)
965 contikimac_is_on = 0;
966 contikimac_keep_radio_on = keep_radio_on;
969 return NETSTACK_RADIO.on();
972 return NETSTACK_RADIO.off();
976 static unsigned short
979 return (1ul *
CLOCK_SECOND * CYCLE_TIME) / RTIMER_ARCH_SECOND;
994 contikimac_debug_print(
void)
int mac_sequence_is_duplicate(void)
Tell whether the packetbuf is a duplicate packet.
Common functionality for phase optimization in duty cycling radio protocols
linkaddr_t linkaddr_node_addr
The Rime address of the node.
void compower_accumulate(struct compower_activity *e)
Accumulate power contumption for a communication activity.
#define PT_YIELD(pt)
Yield from the current protothread.
Header file for the radio API
const linkaddr_t linkaddr_null
The null Rime address.
int rtimer_set(struct rtimer *rtimer, rtimer_clock_t time, rtimer_clock_t duration, rtimer_callback_t func, void *ptr)
Post a real-time task.
The MAC layer deferred the transmission for a later time.
void * list_item_next(void *item)
Get the next item following this item.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
#define RTIMER_TIME(task)
Get the time that a task last was executed.
void compower_attrconv(struct compower_activity *e)
Convert power contumption information to packet attributes.
#define NULL
The null pointer.
#define PT_INIT(pt)
Initialize a protothread.
Header file for MAC sequence numbers management
struct compower_activity compower_idle_activity
The default idle communication activity.
uint16_t packetbuf_totlen(void)
Get the total length of the header and data in the packetbuf.
Header file for the Rime stack
void compower_clear(struct compower_activity *e)
Clear power consumption information for a communication activity.
Header file for the communication power accounting module
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
void watchdog_periodic(void)
Writes the WDT clear sequence.
Header file for the real-time timer module.
Protothreads implementation.
void mac_sequence_register_seqno(void)
Register the sequence number of the packetbuf.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
The structure of a RDC (radio duty cycling) driver in Contiki.
void(* init)(void)
Initialize the RDC driver.
#define PT_END(pt)
Declare the end of a protothread.
The MAC layer transmission was OK.
#define RTIMER_NOW()
Get the current clock time.
The MAC layer transmission could not be performed because of an error.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two Rime addresses.
The MAC layer did not get an acknowledgement for the packet.
Representation of a real-time task.
int timer_expired(struct timer *t)
Check if a timer has expired.
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
An activity record that contains power consumption information for a specific communication activity...
Header file for the ContikiMAC radio duty cycling protocol
Include file for the Contiki low-layer network stack (NETSTACK)
#define CLOCK_SECOND
A second, measured in system clock time.