diff --git a/core/net/mac/contikimac.c b/core/net/mac/contikimac.c index 47dd8d07b..adfb3c795 100644 --- a/core/net/mac/contikimac.c +++ b/core/net/mac/contikimac.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: contikimac.c,v 1.23 2010/04/01 17:17:36 joxe Exp $ + * $Id: contikimac.c,v 1.24 2010/04/03 13:28:30 adamdunkels Exp $ */ /** @@ -102,24 +102,25 @@ struct announcement_msg { #define MAX_PHASE_STROBE_TIME RTIMER_ARCH_SECOND / 20 #define CCA_COUNT_MAX 2 -#define CCA_CHECK_TIME RTIMER_ARCH_SECOND / 8192 -#define CCA_SLEEP_TIME RTIMER_ARCH_SECOND / 2000 //+ CCA_CHECK_TIME +#define CCA_CHECK_TIME RTIMER_ARCH_SECOND / 8192 //- RTIMER_ARCH_SECOND / 5000 +#define CCA_SLEEP_TIME RTIMER_ARCH_SECOND / 2000 //- RTIMER_ARCH_SECOND / 5000 //+ CCA_CHECK_TIME #define CHECK_TIME (CCA_COUNT_MAX * (CCA_CHECK_TIME + CCA_SLEEP_TIME)) #define STROBE_TIME (CYCLE_TIME + 2 * CHECK_TIME) #define STREAM_CCA_COUNT (CYCLE_TIME / (CCA_SLEEP_TIME + CCA_CHECK_TIME) - CCA_COUNT_MAX) -#define GUARD_TIME 7 * CHECK_TIME +#define GUARD_TIME 9 * CHECK_TIME #define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 5000 #define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1500 #define LISTEN_TIME_AFTER_PACKET_DETECTED RTIMER_ARCH_SECOND / 100 -#define SHORTEST_PACKET_SIZE 23 +#define SHORTEST_PACKET_SIZE 43 #define MAX_SILENCE_PERIODS 5 +#define MAX_NONACTIVITY_PERIODIC 30 /* The cycle time for announcements. */ #ifdef ANNOUNCEMENT_CONF_PERIOD @@ -185,7 +186,7 @@ static volatile uint8_t is_streaming; static rimeaddr_t is_streaming_to, is_streaming_to_too; static volatile rtimer_clock_t stream_until; -#define DEFAULT_STREAM_TIME (4 * CYCLE_TIME) +#define DEFAULT_STREAM_TIME (1 * CYCLE_TIME) #ifndef MIN #define MIN(a, b) ((a) < (b)? (a) : (b)) @@ -205,7 +206,7 @@ on(void) static void off(void) { - if(contikimac_is_on && radio_is_on != 0 && is_streaming == 0) { + if(contikimac_is_on && radio_is_on != 0 && is_streaming == 0 && is_snooping == 0) { radio_is_on = 0; NETSTACK_RADIO.off(); } @@ -225,8 +226,11 @@ schedule_powercycle(struct rtimer *t, rtimer_clock_t time) } while(RTIMER_TIME(t) + time == RTIMER_NOW() || - RTIMER_TIME(t) + time == RTIMER_NOW() + 1) { - ++time; + RTIMER_TIME(t) + time == RTIMER_NOW() + 1 || + RTIMER_TIME(t) + time == RTIMER_NOW() + 2 || + RTIMER_TIME(t) + time == RTIMER_NOW() + 3 || + RTIMER_TIME(t) + time == RTIMER_NOW() + 4) { + time++; } #if NURTIMER @@ -347,8 +351,9 @@ powercycle(struct rtimer *t, void *ptr) leds_off(LEDS_RED); break; } - if(periods > 10 && !(NETSTACK_RADIO.receiving_packet() || - NETSTACK_RADIO.pending_packet())) { +#if 1 + if(periods > MAX_NONACTIVITY_PERIODIC && !(NETSTACK_RADIO.receiving_packet() || + NETSTACK_RADIO.pending_packet())) { leds_on(LEDS_GREEN); powercycle_turn_radio_off(); #if CONTIKIMAC_CONF_COMPOWER @@ -358,6 +363,7 @@ powercycle(struct rtimer *t, void *ptr) leds_off(LEDS_GREEN); break; } +#endif /* 0 */ if(NETSTACK_RADIO.pending_packet()) { break; } @@ -381,15 +387,19 @@ powercycle(struct rtimer *t, void *ptr) compower_accumulate(&compower_idle_activity); #endif /* CONTIKIMAC_CONF_COMPOWER */ } - } while((is_snooping) && - RTIMER_NOW() - cycle_start < CYCLE_TIME - CCA_CHECK_TIME * CCA_COUNT_MAX); - - if(RTIMER_NOW() - cycle_start < CYCLE_TIME) { + } while(0 && (is_snooping) && + RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - 8 * CHECK_TIME * CCA_COUNT_MAX)); + + if(is_snooping) { + leds_on(LEDS_RED); + } + if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - 4)) { schedule_powercycle(t, CYCLE_TIME - (RTIMER_NOW() - cycle_start) + 1); /* printf("cycle_start 0x%02x now 0x%02x wait 0x%02x\n", cycle_start, RTIMER_NOW(), CYCLE_TIME - (RTIMER_NOW() - cycle_start));*/ PT_YIELD(&pt); } + leds_off(LEDS_RED); } PT_END(&pt); @@ -446,11 +456,13 @@ format_announcement(char *hdr) adata.announcement_magic[1] = ANNOUNCEMENT_MAGIC2; adata.num = 0; for(a = announcement_list(); - a != NULL && a->has_value && adata.num < ANNOUNCEMENT_MAX; + a != NULL && adata.num < ANNOUNCEMENT_MAX; a = a->next) { - adata.data[adata.num].id = a->id; - adata.data[adata.num].value = a->value; - adata.num++; + if(a->has_value) { + adata.data[adata.num].id = a->id; + adata.data[adata.num].value = a->value; + adata.num++; + } } memcpy(hdr, &adata, sizeof(struct announcement_msg)); @@ -528,6 +540,9 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr) } } + if(is_streaming || !contikimac_is_on) { + packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1); + } /* Create the MAC header for the data packet. */ hdrlen = NETSTACK_FRAMER.create(); if(hdrlen == 0) { @@ -664,9 +679,9 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr) watchdog_periodic(); - if(is_known_receiver && !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) { + /* if(is_known_receiver && !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) { break; - } + }*/ len = 0; @@ -677,9 +692,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr) rtimer_clock_t wt; rtimer_clock_t now = RTIMER_NOW(); - leds_on(LEDS_RED); NETSTACK_RADIO.transmit(transmit_len); - leds_off(LEDS_RED); wt = RTIMER_NOW(); #if NURTIMER @@ -825,7 +838,15 @@ input_packet(void) } } #endif /* CONTIKIMAC_CONF_ANNOUNCEMENTS */ - + +#if WITH_PHASE_OPTIMIZATION + /* If the sender has set its pending flag, it has its radio + turned on and we should drop the phase estimation that we + have from before. */ + if(packetbuf_attr(PACKETBUF_ATTR_PENDING)) { + phase_remove(&phase_list, packetbuf_addr(PACKETBUF_ADDR_SENDER)); + } +#endif /* WITH_PHASE_OPTIMIZATION */ #if CONTIKIMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ @@ -903,6 +924,7 @@ send_announcement(void *ptr) while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + CCA_SLEEP_TIME + CCA_CHECK_TIME)) { } #endif } + if(collisions == 0) { NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen()); diff --git a/core/net/mac/framer-802154.c b/core/net/mac/framer-802154.c index be5b23a5f..099da18c0 100644 --- a/core/net/mac/framer-802154.c +++ b/core/net/mac/framer-802154.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: framer-802154.c,v 1.7 2010/03/16 18:11:58 adamdunkels Exp $ + * $Id: framer-802154.c,v 1.8 2010/04/03 13:28:30 adamdunkels Exp $ */ /** @@ -89,7 +89,7 @@ create(void) /* Build the FCF. */ params.fcf.frame_type = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; - params.fcf.frame_pending = 0; + params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { params.fcf.ack_required = 0; } else { @@ -184,8 +184,9 @@ parse(void) } } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *)&frame.src_addr); + packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ - packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); + /* packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq);*/ PRINTF("15.4-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); diff --git a/core/net/mac/phase.c b/core/net/mac/phase.c index ee355a3ab..02137c43b 100644 --- a/core/net/mac/phase.c +++ b/core/net/mac/phase.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: phase.c,v 1.7 2010/03/31 20:27:15 adamdunkels Exp $ + * $Id: phase.c,v 1.8 2010/04/03 13:28:30 adamdunkels Exp $ */ /** @@ -54,10 +54,10 @@ struct phase_queueitem { struct queuebuf *q; }; -#define PHASE_DEFER_THRESHOLD 2 +#define PHASE_DEFER_THRESHOLD 1 #define PHASE_QUEUESIZE 8 -#define MAX_NOACKS 3 +#define MAX_NOACKS 2 MEMB(phase_memb, struct phase_queueitem, PHASE_QUEUESIZE); @@ -71,6 +71,30 @@ MEMB(phase_memb, struct phase_queueitem, PHASE_QUEUESIZE); #define PRINTDEBUG(...) #endif /*---------------------------------------------------------------------------*/ +struct phase * +find_neighbor(const struct phase_list *list, const rimeaddr_t *addr) +{ + struct phase *e; + for(e = list_head(*list->list); e != NULL; e = e->next) { + if(rimeaddr_cmp(addr, &e->neighbor)) { + return e; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +void +phase_remove(const struct phase_list *list, const rimeaddr_t *neighbor) +{ + struct phase *e; + e = find_neighbor(list, neighbor); + if(e != NULL) { + list_remove(*list->list, e); + memb_free(&phase_memb, e); + } + +} +/*---------------------------------------------------------------------------*/ void phase_update(const struct phase_list *list, const rimeaddr_t *neighbor, rtimer_clock_t time, @@ -79,46 +103,45 @@ phase_update(const struct phase_list *list, struct phase *e; /* If we have an entry for this neighbor already, we renew it. */ - for(e = list_head(*list->list); e != NULL; e = e->next) { - if(rimeaddr_cmp(neighbor, &e->neighbor)) { - if(mac_status == MAC_TX_OK) { - e->time = time; + e = find_neighbor(list, neighbor); + if(e != NULL) { + if(mac_status == MAC_TX_OK) { + e->time = time; + } + + /* If the neighbor didn't reply to us, it may have switched + phase (rebooted). We try a number of transmissions to it + before we drop it from the phase list. */ + if(mac_status == MAC_TX_NOACK) { + PRINTF("phase noacks %d to %d.%d\n", e->noacks, neighbor->u8[0], neighbor->u8[1]); + e->noacks++; + if(e->noacks >= MAX_NOACKS) { + list_remove(*list->list, e); + memb_free(&phase_memb, e); + return; } - - /* If the neighbor didn't reply to us, it may have switched - phase (rebooted). We try a number of transmissions to it - before we drop it from the phase list. */ - if(mac_status == MAC_TX_NOACK) { - PRINTF("phase noacks %d to %d.%d\n", e->noacks, neighbor->u8[0], neighbor->u8[1]); - e->noacks++; - if(e->noacks >= MAX_NOACKS) { - list_remove(*list->list, e); - memb_free(&phase_memb, e); - return; - } - } else if(mac_status == MAC_TX_OK) { - e->noacks = 0; - } - - /* Make sure this entry is first on the list so subsequent + } else if(mac_status == MAC_TX_OK) { + e->noacks = 0; + } + + /* Make sure this entry is first on the list so subsequent searches are faster. */ - list_remove(*list->list, e); - list_push(*list->list, e); - break; - } - } - /* No matching phase was found, so we allocate a new one. */ - if(mac_status == MAC_TX_OK && e == NULL) { - e = memb_alloc(list->memb); - if(e == NULL) { - /* We could not allocate memory for this phase, so we drop - the last item on the list and reuse it for our phase. */ - e = list_chop(*list->list); - } - rimeaddr_copy(&e->neighbor, neighbor); - e->time = time; - e->noacks = 0; + list_remove(*list->list, e); list_push(*list->list, e); + } else { + /* No matching phase was found, so we allocate a new one. */ + if(mac_status == MAC_TX_OK && e == NULL) { + e = memb_alloc(list->memb); + if(e == NULL) { + /* We could not allocate memory for this phase, so we drop + the last item on the list and reuse it for our phase. */ + e = list_chop(*list->list); + } + rimeaddr_copy(&e->neighbor, neighbor); + e->time = time; + e->noacks = 0; + list_push(*list->list, e); + } } } /*---------------------------------------------------------------------------*/ @@ -140,68 +163,65 @@ phase_wait(struct phase_list *list, mac_callback_t mac_callback, void *mac_callback_ptr) { struct phase *e; - + // const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); /* We go through the list of phases to find if we have recorded a phase for this particular neighbor. If so, we can compute the time for the next expected phase and setup a ctimer to switch on the radio just before the phase. */ - for(e = list_head(*list->list); e != NULL; e = e->next) { - const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); - - if(rimeaddr_cmp(neighbor, &e->neighbor)) { - rtimer_clock_t wait, now, expected, additional_wait; - clock_time_t ctimewait; - - /* We expect phases to happen every CYCLE_TIME time - units. The next expected phase is at time e->time + - CYCLE_TIME. To compute a relative offset, we subtract - with clock_time(). Because we are only interested in turning - on the radio within the CYCLE_TIME period, we compute the - waiting time with modulo CYCLE_TIME. */ - - /* printf("neighbor phase 0x%02x (cycle 0x%02x)\n", e->time & (cycle_time - 1), - cycle_time);*/ - - additional_wait = 2 * e->noacks * wait_before; - - /* if(e->noacks > 0) { - printf("additional wait %d\n", additional_wait); - }*/ - - now = RTIMER_NOW(); - wait = (rtimer_clock_t)((e->time - now) & - (cycle_time - 1)); - if(wait < wait_before + additional_wait) { - wait += cycle_time; - } - - ctimewait = (CLOCK_SECOND * (wait - wait_before - additional_wait)) / RTIMER_ARCH_SECOND; - - if(ctimewait > PHASE_DEFER_THRESHOLD) { - struct phase_queueitem *p; - - p = memb_alloc(&phase_memb); - if(p != NULL) { - p->q = queuebuf_new_from_packetbuf(); - if(p->q != NULL) { - p->mac_callback = mac_callback; - p->mac_callback_ptr = mac_callback_ptr; - ctimer_set(&p->timer, ctimewait, send_packet, p); - return PHASE_DEFERRED; - } else { - memb_free(&phase_memb, p); - } - } - } - - expected = now + wait - wait_before - additional_wait; - if(!RTIMER_CLOCK_LT(expected, now)) { - /* Wait until the receiver is expected to be awake */ - while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected)) { - } - } - return PHASE_SEND_NOW; + e = find_neighbor(list, neighbor); + if(e != NULL) { + rtimer_clock_t wait, now, expected, additional_wait; + clock_time_t ctimewait; + + /* We expect phases to happen every CYCLE_TIME time + units. The next expected phase is at time e->time + + CYCLE_TIME. To compute a relative offset, we subtract + with clock_time(). Because we are only interested in turning + on the radio within the CYCLE_TIME period, we compute the + waiting time with modulo CYCLE_TIME. */ + + /* printf("neighbor phase 0x%02x (cycle 0x%02x)\n", e->time & (cycle_time - 1), + cycle_time);*/ + + additional_wait = 2 * e->noacks * wait_before; + + /* if(e->noacks > 0) { + printf("additional wait %d\n", additional_wait); + }*/ + + now = RTIMER_NOW(); + wait = (rtimer_clock_t)((e->time - now) & + (cycle_time - 1)); + if(wait < wait_before + additional_wait) { + wait += cycle_time; } + + ctimewait = (CLOCK_SECOND * (wait - wait_before - additional_wait)) / RTIMER_ARCH_SECOND; + + if(ctimewait > PHASE_DEFER_THRESHOLD) { + struct phase_queueitem *p; + + p = memb_alloc(&phase_memb); + if(p != NULL) { + p->q = queuebuf_new_from_packetbuf(); + if(p->q != NULL) { + p->mac_callback = mac_callback; + p->mac_callback_ptr = mac_callback_ptr; + ctimer_set(&p->timer, ctimewait, send_packet, p); + return PHASE_DEFERRED; + } else { + memb_free(&phase_memb, p); + } + } + } + + expected = now + wait - wait_before - additional_wait; + if(!RTIMER_CLOCK_LT(expected, now)) { + /* Wait until the receiver is expected to be awake */ + while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected)) { + } + } + return PHASE_SEND_NOW; } return PHASE_UNKNOWN; } diff --git a/core/net/mac/phase.h b/core/net/mac/phase.h index d1886098a..26591cc58 100644 --- a/core/net/mac/phase.h +++ b/core/net/mac/phase.h @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: phase.h,v 1.3 2010/03/14 22:59:23 adamdunkels Exp $ + * $Id: phase.h,v 1.4 2010/04/03 13:28:30 adamdunkels Exp $ */ /** @@ -74,8 +74,9 @@ void phase_init(struct phase_list *list); phase_status_t phase_wait(struct phase_list *list, const rimeaddr_t *neighbor, rtimer_clock_t cycle_time, rtimer_clock_t wait_before, mac_callback_t mac_callback, void *mac_callback_ptr); -void phase_update(const struct phase_list *list, const rimeaddr_t * neighbor, +void phase_update(const struct phase_list *list, const rimeaddr_t *neighbor, rtimer_clock_t time, int mac_status); +void phase_remove(const struct phase_list *list, const rimeaddr_t *neighbor); #endif /* PHASE_H */