⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmac.c

📁 Contiki是一个开源
💻 C
📖 第 1 页 / 共 2 页
字号:
  rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr);  rimeaddr_copy(&hdr->receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));  if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {    is_broadcast = 1;  }  rimebuf_compact();  t0 = RTIMER_NOW();  strobes = 0;  BB_SET(XMAC_RECEIVER, hdr->receiver.u16[0]);    LEDS_ON(LEDS_BLUE);  /* Send a train of strobes until the receiver answers with an ACK. */  /* Turn on the radio to listen for the strobe ACK. */  if(!is_broadcast) {    on();  }  watchdog_stop();  got_ack = 0;  for(strobes = 0;      got_ack == 0 &&	RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time);      strobes++) {    t = RTIMER_NOW();    rimeaddr_copy(&msg.sender, &rimeaddr_node_addr);    rimeaddr_copy(&msg.receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));#if WITH_TIMETABLE    if(rimeaddr_cmp(&msg.receiver, &rimeaddr_null)) {      TIMETABLE_TIMESTAMP(xmac_timetable, "send broadcast strobe");    } else {      TIMETABLE_TIMESTAMP(xmac_timetable, "send strobe");    }#endif    if(is_broadcast) {      /* If we are sending a broadcast, we don't send strobes, we	 simply send the data packet repetedly */      radio->send(rimebuf_hdrptr(), rimebuf_totlen());    } else {      /* Send the strobe packet. */      radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr));    }    CPRINTF("+");    while(got_ack == 0 &&	  RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {      /* See if we got an ACK */      len = radio->read((uint8_t *)&msg, sizeof(struct xmac_hdr));      if(len > 0) {	CPRINTF("_");	if(rimeaddr_cmp(&msg.sender, &rimeaddr_node_addr) &&	   rimeaddr_cmp(&msg.receiver, &rimeaddr_node_addr)) {#if WITH_TIMETABLE	  TIMETABLE_TIMESTAMP(xmac_timetable, "send ack received");#endif	  CPRINTF("@");	  /* We got an ACK from the receiver, so we can immediately send	     the packet. */	  got_ack = 1;	}      }    }    /* XXX: turn off radio if we haven't heard an ACK within a       specified time interval. */    /*    if(got_ack == 0) {      off();      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time));      on();      }*/  }  if(got_ack /* XXX && needs_ack */) {#if WITH_TIMETABLE    TIMETABLE_TIMESTAMP(xmac_timetable, "send got ack");#endif    on(); /* Wait for possible ACK packet */  } else if(!is_broadcast) {#if WITH_TIMETABLE    TIMETABLE_TIMESTAMP(xmac_timetable, "send no ack received");#endif    on(); /* shell ping don't seem to work with off() here, so we'll	     keep it on() for a while. */  }  /* Send the data packet. */  if(is_broadcast || got_ack) {#if WITH_TIMETABLE    TIMETABLE_TIMESTAMP(xmac_timetable, "send packet");#endif    radio->send(rimebuf_hdrptr(), rimebuf_totlen());    CPRINTF("#");  }  watchdog_start();  PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes,	 rimebuf_totlen(), got_ack ? "ack" : "no ack");  BB_SET(XMAC_STROBES, strobes);  if(got_ack) {    BB_INC(XMAC_SEND_WITH_ACK, 1);  } else {    BB_INC(XMAC_SEND_WITH_NOACK, 1);  }  /*  printf("Strobe %d got_ack %d\n", strobes, got_ack);*/  we_are_sending = 0;#if WITH_TIMETABLE  TIMETABLE_TIMESTAMP(xmac_timetable, "send we_are_sending = 0");#endif  LEDS_OFF(LEDS_BLUE);  return 1;}/*---------------------------------------------------------------------------*/static struct queuebuf *queued_packet;static intqsend_packet(void){  if(someone_is_sending) {    PRINTF("xmac: should queue packet, now just dropping %d %d %d %d.\n",	   waiting_for_packet, someone_is_sending, we_are_sending, radio_is_on);    if(queued_packet != NULL) {      RIMESTATS_ADD(sendingdrop);      return 0;    } else {#if WITH_QUEUE      queued_packet = queuebuf_new_from_rimebuf();      return 1;#else      RIMESTATS_ADD(sendingdrop);      return 0;#endif    }  } else {    PRINTF("xmac: send immediately.\n");    return send_packet();  }}/*---------------------------------------------------------------------------*/static voidinput_packet(const struct radio_driver *d){  if(receiver_callback) {    receiver_callback(&xmac_driver);  }}/*---------------------------------------------------------------------------*/static intread_packet(void){  struct xmac_hdr *hdr;  uint8_t len;  rimebuf_clear();  len = radio->read(rimebuf_dataptr(), RIMEBUF_SIZE);  if(len > 0) {    rimebuf_set_datalen(len);    hdr = rimebuf_dataptr();    rimebuf_hdrreduce(sizeof(struct xmac_hdr));    if(rimebuf_totlen() == 0) {      CPRINTF(".");      /* There is no data in the packet so it has to be a strobe. */      someone_is_sending = 2;            if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) {	/* This is a strobe packet for us. */	if(rimeaddr_cmp(&hdr->sender, &rimeaddr_node_addr)) {	  /* If the sender address is our node address, the strobe is	     a stray strobe ACK to us, which we ignore unless we are	     currently sending a packet.  */	  CPRINTF("&");	  someone_is_sending = 0;	} else {	  struct xmac_hdr msg;	  /* If the sender address is someone else, we should	     acknowledge the strobe and wait for the packet. By using	     the same address as both sender and receiver, we flag the	     message is a strobe ack. */#if WITH_TIMETABLE	  TIMETABLE_TIMESTAMP(xmac_timetable, "read send ack");#endif	  rimeaddr_copy(&msg.receiver, &hdr->sender);	  rimeaddr_copy(&msg.sender, &hdr->sender);	  CPRINTF("!");	  /* We turn on the radio in anticipation of the incoming	     packet. */	  someone_is_sending = 1;	  waiting_for_packet = 1;	  on();	  radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr));	}      } else if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {	/* If the receiver address is null, the strobe is sent to	   prepare for an incoming broadcast packet. If this is the	   case, we turn on the radio and wait for the incoming	   broadcast packet. */	waiting_for_packet = 1;	on();      }      /* We are done processing the strobe and we therefore return	 to the caller. */      return RIME_OK;    } else {      CPRINTF("-");      someone_is_sending = 0;      if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr) ||	 rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {#if WITH_TIMETABLE	TIMETABLE_TIMESTAMP(xmac_timetable, "read got packet");#endif	/* This is a regular packet that is destined to us or to the	   broadcast address. */		/* We have received the final packet, so we can go back to being	   asleep. */	off();	waiting_for_packet = 0;		/* XXX should set timer to send queued packet later. */	if(queued_packet != NULL) {	  queuebuf_free(queued_packet);	  queued_packet = NULL;	}		return rimebuf_totlen();      }    }  }  return 0;}/*---------------------------------------------------------------------------*/const struct mac_driver *xmac_init(const struct radio_driver *d){#if WITH_TIMETABLE  timetable_clear(&xmac_timetable);#endif  radio_is_on = 0;  waiting_for_packet = 0;  PT_INIT(&pt);  rtimer_set(&rt, RTIMER_NOW() + xmac_config.off_time, 1,	     (void (*)(struct rtimer *, void *))powercycle, NULL);  xmac_is_on = 1;  radio = d;  radio->set_receive_function(input_packet);  BB_SET("xmac.state_addr", (int) &waiting_for_packet);  BB_SET(XMAC_RECEIVER, 0);  BB_SET(XMAC_STROBES, 0);  BB_SET(XMAC_SEND_WITH_ACK, 0);  BB_SET(XMAC_SEND_WITH_NOACK, 0);  return &xmac_driver;}/*---------------------------------------------------------------------------*/static intturn_on(void){  xmac_is_on = 1;  return 1;}/*---------------------------------------------------------------------------*/static intturn_off(int keep_radio_on){  xmac_is_on = 0;  if(keep_radio_on) {    return radio->on();  } else {    return radio->off();  }}/*---------------------------------------------------------------------------*/const struct mac_driver xmac_driver =  {    "X-MAC",    qsend_packet,    read_packet,    set_receive_function,    turn_on,    turn_off  };

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -