Example #1
0
// Start a response, returns the partial CRC
void ICACHE_FLASH_ATTR
cmdResponseStart(uint16_t cmd, uint32_t value, uint16_t argc) {
  DBG("cmdResponse: cmd=%d val=%d argc=%d\n", cmd, value, argc);

  uart0_write_char(SLIP_END);
  cmdProtoWriteBuf((uint8_t*)&cmd, 2);
  resp_crc = crc16_data((uint8_t*)&cmd, 2, 0);
  cmdProtoWriteBuf((uint8_t*)&argc, 2);
  resp_crc = crc16_data((uint8_t*)&argc, 2, resp_crc);
  cmdProtoWriteBuf((uint8_t*)&value, 4);
  resp_crc = crc16_data((uint8_t*)&value, 4, resp_crc);
}
Example #2
0
// Start a response, returns the partial CRC
uint16_t ICACHE_FLASH_ATTR
CMD_ResponseStart(uint16_t cmd, uint32_t callback, uint32_t _return, uint16_t argc) {
  uint16_t crc = 0;

  uart0_write_char(SLIP_START);
  CMD_ProtoWriteBuf((uint8_t*)&cmd, 2);
  crc = crc16_data((uint8_t*)&cmd, 2, crc);
  CMD_ProtoWriteBuf((uint8_t*)&callback, 4);
  crc = crc16_data((uint8_t*)&callback, 4, crc);
  CMD_ProtoWriteBuf((uint8_t*)&_return, 4);
  crc = crc16_data((uint8_t*)&_return, 4, crc);
  CMD_ProtoWriteBuf((uint8_t*)&argc, 2);
  crc = crc16_data((uint8_t*)&argc, 2, crc);
  return crc;
}
Example #3
0
// Adds data to a response, returns the partial CRC
void ICACHE_FLASH_ATTR
cmdResponseBody(const void *data, uint16_t len) {
  cmdProtoWriteBuf((uint8_t*)&len, 2);
  resp_crc = crc16_data((uint8_t*)&len, 2, resp_crc);

  cmdProtoWriteBuf(data, len);
  resp_crc = crc16_data(data, len, resp_crc);

  uint16_t pad = (4-((len+2)&3))&3; // get to multiple of 4
  if (pad > 0) {
    uint32_t temp = 0;
    cmdProtoWriteBuf((uint8_t*)&temp, pad);
    resp_crc = crc16_data((uint8_t*)&temp, pad, resp_crc);
  }
}
Example #4
0
/*---------------------------------------------------------------------------*/
static void
recv_trickle(struct trickle_conn *c)
{
  struct trickle_msg *msg;
  uint16_t crc;
  int len;
  
  msg = packetbuf_dataptr();

  if(packetbuf_datalen() > 1 + TRICKLEMSG_HDR_SIZE) {
    
    /* First ensure that the old process is killed. */
    process_exit(&shell_netcmd_server_process);
    
    len = packetbuf_datalen() - 1 - TRICKLEMSG_HDR_SIZE;
    
    /* Make sure that the incoming command is null-terminated. */
    msg->netcmd[len] = 0;
    memcpy(&crc, &msg->crc, sizeof(crc));
    
    if(crc == crc16_data(msg->netcmd, len, 0)) {
      /* Start the server process with the incoming command. */
      process_start(&shell_netcmd_server_process, (void *)msg->netcmd);
    }
  }
}
Example #5
0
// SLIP process a packet or a bunch of debug console chars
static void ICACHE_FLASH_ATTR
slip_process() {
  if (slip_len < 1) return;

  if (!slip_inpkt) {
    // debug console stuff
    console_process(slip_buf, slip_len);
  } else {
    // proper SLIP packet, invoke command processor after checking CRC
    //os_printf("SLIP: rcv %d\n", slip_len);
    if (slip_len > 2) {
      uint16_t crc = crc16_data((uint8_t*)slip_buf, slip_len-2, 0);
      uint16_t rcv = ((uint16_t)slip_buf[slip_len-2]) | ((uint16_t)slip_buf[slip_len-1] << 8);
      if (crc == rcv) {
        CMD_parse_packet((uint8_t*)slip_buf, slip_len-2);
      } else {
        os_printf("SLIP: bad CRC, crc=%x rcv=%x\n", crc, rcv);

#ifdef SLIP_DBG
        for (short i=0; i<slip_len; i++) {
          if (slip_buf[i] >= ' ' && slip_buf[i] <= '~')
            os_printf("%c", slip_buf[i]);
          else
            os_printf("\\%02X", slip_buf[i]);
        }
        os_printf("\n");
#endif
      }
    }
  }
}
Example #6
0
/*---------------------------------------------------------------------------*/
static int
prepare(const void *payload, unsigned short payload_len)
{
  uint8_t i;
  uint16_t checksum;

  RIMESTATS_ADD(lltx);

  if(tx_in_progress) {
    return 1;
  }
  if(payload_len > 127 || payload == NULL) {
    return 1;
  }
  /* Copy payload to (soft) Ttx buffer */
  memcpy(tx_frame_buffer.uPayload.au8Byte, payload, payload_len);
  i = payload_len;
#if CRC_SW
  /* Compute CRC */
  checksum = crc16_data(payload, payload_len, 0);
  tx_frame_buffer.uPayload.au8Byte[i++] = checksum;
  tx_frame_buffer.uPayload.au8Byte[i++] = (checksum >> 8) & 0xff;
  tx_frame_buffer.u8PayloadLength = payload_len + CHECKSUM_LEN;
#else
  tx_frame_buffer.u8PayloadLength = payload_len;
#endif

  return 0;
}
Example #7
0
/*---------------------------------------------------------------------------*/
static int
cc2420_prepare(const void *payload, unsigned short payload_len)
{
  uint8_t total_len;
#if CC2420_CONF_CHECKSUM
  uint16_t checksum;
#endif /* CC2420_CONF_CHECKSUM */
  GET_LOCK();

  PRINTF("cc2420: sending %d bytes\n", payload_len);

  RIMESTATS_ADD(lltx);

  /* Wait for any previous transmission to finish. */
  /*  while(status() & BV(CC2420_TX_ACTIVE));*/

  /* Write packet to TX FIFO. */
  strobe(CC2420_SFLUSHTX);

#if CC2420_CONF_CHECKSUM
  checksum = crc16_data(payload, payload_len, 0);
#endif /* CC2420_CONF_CHECKSUM */
  total_len = payload_len + AUX_LEN;
  CC2420_WRITE_FIFO_BUF(&total_len, 1);
  CC2420_WRITE_FIFO_BUF(payload, payload_len);
#if CC2420_CONF_CHECKSUM
  CC2420_WRITE_FIFO_BUF(&checksum, CHECKSUM_LEN);
#endif /* CC2420_CONF_CHECKSUM */

  RELEASE_LOCK();
  return 0;
}
Example #8
0
/*---------------------------------------------------------------------------*/
static void
recv_uc(struct unicast_conn *c, const linkaddr_t *from)
{
  struct cmd_msg *msg;
  uint16_t crc;
  int len;

  msg = packetbuf_dataptr();

  if(packetbuf_datalen() > 1 + CMDMSG_HDR_SIZE) {

    /* First ensure that the old process is killed. */
    process_exit(&shell_sendcmd_server_process);

    len = packetbuf_datalen() - 1 - CMDMSG_HDR_SIZE;

    /* Make sure that the incoming command is null-terminated. */
    msg->sendcmd[len] = 0;
    memcpy(&crc, &msg->crc, sizeof(crc));

    if(crc == crc16_data((unsigned char *)msg->sendcmd, len, 0)) {
      /* Start the server process with the incoming command. */
      process_start(&shell_sendcmd_server_process, (void *)msg->sendcmd);
    }
  }
}
Example #9
0
static void
send_page(struct deluge_object *obj, unsigned pagenum)
{
  unsigned char buf[S_PAGE];
  struct deluge_msg_packet pkt;
  unsigned char *cp;

  pkt.cmd = DELUGE_CMD_PACKET;
  pkt.pagenum = pagenum;
  pkt.version = obj->pages[pagenum].version;
  pkt.packetnum = 0;
  pkt.object_id = obj->object_id;
  pkt.crc = 0;

  read_page(obj, pagenum, buf);

  /* Divide the page into packets and send them one at a time. */
  for(cp = buf; cp + S_PKT <= (unsigned char *)&buf[S_PAGE]; cp += S_PKT) {
    if(obj->tx_set & (1 << pkt.packetnum)) {
      pkt.crc = crc16_data(cp, S_PKT, 0);
      memcpy(pkt.payload, cp, S_PKT);
      packetbuf_copyfrom(&pkt, sizeof(pkt));
      broadcast_send(&deluge_broadcast);
    }
    pkt.packetnum++;
  }
  obj->tx_set = 0;
}
Example #10
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_netcmd_process, ev, data)
{
  struct trickle_msg *msg;
  int len;
  
  PROCESS_BEGIN();

  /* Get the length of the command line, excluding a terminating NUL character. */
  len = strlen((char *)data);

  /* Check the length of the command line to see that it is small
     enough to fit in a packet. We count with 32 bytes of header,
     which may be a little too much, but at least we are on the safe
     side. */
  if(len > PACKETBUF_SIZE - 32) {
    char buf[32];
    snprintf(buf, sizeof(buf), "%d", len);
    shell_output_str(&netcmd_command, "command line too large: ", buf);
  } else {
    
    packetbuf_clear();
    msg = packetbuf_dataptr();
    packetbuf_set_datalen(len + 1 + TRICKLEMSG_HDR_SIZE);
    strcpy(msg->netcmd, data);

    /* Terminate the string with a NUL character. */
    msg->netcmd[len] = 0;
    msg->crc = crc16_data(msg->netcmd, len, 0);
    printf("netcmd sending '%s'\n", msg->netcmd);
    trickle_send(&trickle);
  }
  
  PROCESS_END();
}
Example #11
0
// Adds data to a response, returns the partial CRC
uint16_t ICACHE_FLASH_ATTR
CMD_ResponseBody(uint16_t crc_in, uint8_t* data, short len) {
  short pad_len = len+3 - (len+3)%4; // round up to multiple of 4
  CMD_ProtoWriteBuf((uint8_t*)&pad_len, 2);
  crc_in = crc16_data((uint8_t*)&pad_len, 2, crc_in);

  CMD_ProtoWriteBuf(data, len);
  crc_in = crc16_data(data, len, crc_in);

  if (pad_len > len) {
    uint32_t temp = 0;
    CMD_ProtoWriteBuf((uint8_t*)&temp, pad_len-len);
    crc_in = crc16_data((uint8_t*)&temp, pad_len-len, crc_in);
  }

  return crc_in;
}
Example #12
0
uint16_t ESP::request(uint16_t cmd, uint32_t callback, uint32_t _return, uint16_t argc)
{
  uint16_t crc = 0;
  _serial->write(0x7E);
  write((uint8_t*)&cmd, 2);
  crc = crc16_data((uint8_t*)&cmd, 2, crc);

  write((uint8_t*)&callback, 4);
  crc = crc16_data((uint8_t*)&callback, 4, crc);

  write((uint8_t*)&_return, 4);
  crc = crc16_data((uint8_t*)&_return, 4, crc);

  write((uint8_t*)&argc, 2);
  crc = crc16_data((uint8_t*)&argc, 2, crc);
  return crc;
}
Example #13
0
/*---------------------------------------------------------------------------*/
static int
read(void *buf, unsigned short bufsize)
{
  int len = 0;
  uint16_t radio_last_rx_crc;
  uint8_t radio_last_rx_crc_ok = 1;

  len = input_frame_buffer->u8PayloadLength;

  if(len <= CHECKSUM_LEN) {
    input_frame_buffer->u8PayloadLength = 0;
    return 0;
  } else {
    len -= CHECKSUM_LEN;
    /* Check CRC */
#if CRC_SW
    uint16_t checksum = crc16_data(input_frame_buffer->uPayload.au8Byte, len, 0);
    radio_last_rx_crc =
      (uint16_t)(input_frame_buffer->uPayload.au8Byte[len + 1] << (uint16_t)8)
      | input_frame_buffer->uPayload.au8Byte[len];
    radio_last_rx_crc_ok = (checksum == radio_last_rx_crc);
    if(!radio_last_rx_crc_ok) {
      RIMESTATS_ADD(badcrc);
    }
#endif /* CRC_SW */
    if(radio_last_rx_crc_ok) {
      /* If we are in poll mode we need to check the frame here */
      if(poll_mode) {
        if(frame_filtering &&
           !is_packet_for_us(input_frame_buffer->uPayload.au8Byte, len, 0)) {
          len = 0;
        } else {
          read_last_rssi();
        }
      }
      if(len != 0) {
        bufsize = MIN(len, bufsize);
        memcpy(buf, input_frame_buffer->uPayload.au8Byte, bufsize);
        RIMESTATS_ADD(llrx);
        if(!poll_mode) {
          /* Not in poll mode: packetbuf should not be accessed in interrupt context */
          packetbuf_set_attr(PACKETBUF_ATTR_RSSI, radio_last_rssi);
          packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, radio_last_correlation);
        }
      }
    } else {
      len = 0;
    }
    /* Disable further read attempts */
    input_frame_buffer->u8PayloadLength = 0;
  }

  return len;
}
Example #14
0
void ESP::protoCompletedCb(void)
{
  PACKET_CMD *cmd = (PACKET_CMD*)_proto.buf;
  uint16_t crc = 0, argc, len, resp_crc;
  uint8_t *data_ptr;
  argc = cmd->argc;
  data_ptr = (uint8_t*)&cmd->args ;
  crc = crc16_data((uint8_t*)&cmd->cmd, 12, crc);
  while(argc--){
    len = *((uint16_t*)data_ptr);
    crc = crc16_data(data_ptr, 2, crc);
    data_ptr += 2;
    while(len --){
      crc = crc16_data(data_ptr, 1, crc);
      data_ptr ++;
    }
  }
  resp_crc =  *(uint16_t*)data_ptr;
  if(crc != resp_crc) {
      INFO("ARDUINO: Invalid CRC");
    return;
  }

  FP<void, void*> *fp;
  if(cmd->callback != 0){
    fp = (FP<void, void*>*)cmd->callback;

    return_cmd = cmd->cmd;
    return_value = cmd->_return;

    if(fp->attached())
      (*fp)((void*)cmd);
  } else {
    if(cmd->argc == 0) {
      is_return = true;
      return_cmd = cmd->cmd;
      return_value = cmd->_return;
    }
    
  }
}
Example #15
0
uint16_t ESP::request(uint16_t crc_in, uint8_t* data, uint16_t len)
{
  uint8_t temp = 0;
  uint16_t pad_len = len;
  while(pad_len % 4 != 0)
    pad_len++;
  write((uint8_t*)&pad_len, 2);
  crc_in = crc16_data((uint8_t*)&pad_len, 2, crc_in);
  while(len --){
    write(*data);
    crc_in = crc16_data((uint8_t*)data, 1, crc_in);
    data ++;
    if(pad_len > 0) pad_len --;
  }
  
  while(pad_len --){
    write(temp);
    crc_in = crc16_data((uint8_t*)&temp, 1, crc_in);
  }
  return crc_in;
}
Example #16
0
static void ICACHE_FLASH_ATTR
protoCompletedCb()
{
	uint16_t crc = 0, argc, len, resp_crc, argn = 0;
	uint8_t *data_ptr;
	PACKET_CMD *packet;
	packet = (PACKET_CMD*)protoRxBuf;

	data_ptr = (uint8_t*)&packet->args ;
	crc = crc16_data((uint8_t*)&packet->cmd, 12, crc);
	argc = packet->argc;

	INFO("CMD: %d, cb: %d, ret: %d, argc: %d\r\n", packet->cmd, packet->callback, packet->_return, packet->argc);

	while(argc--){
		len = *((uint16_t*)data_ptr);
		INFO("Arg[%d], len: %d:", argn++, len);
		crc = crc16_data(data_ptr, 2, crc);
		data_ptr += 2;
		crc = crc16_data(data_ptr, len, crc);
		while(len --){
		  INFO("%02X-", *data_ptr);
		  data_ptr ++;
		}
		INFO("\r\n\r\n");
	}
	resp_crc =  *(uint16_t*)data_ptr;
	INFO("Read CRC: %04X, calculated crc: %04X\r\n", resp_crc, crc);

	if(crc != resp_crc) {

		INFO("ESP: Invalid CRC\r\n");

		INFO("");
		return;
	}
	CMD_Exec(commands, packet);
}
Example #17
0
/*---------------------------------------------------------------------------*/
static void
recv_collect(const rimeaddr_t *originator, u8_t seqno, u8_t hops)
{
  struct collect_msg *collect_msg;
  rtimer_clock_t latency;
  int len;
  
  collect_msg = packetbuf_dataptr();
  
#if TIMESYNCH_CONF_ENABLED
  latency = timesynch_time() - collect_msg->timestamp;
#else
  latency = 0;
#endif
  
  if(waiting_for_collect) {
    struct {
      uint16_t len;
      uint16_t originator;
      uint16_t seqno;
      uint16_t hops;
      uint16_t latency;
    } msg;

    if(packetbuf_datalen() >= COLLECT_MSG_HDRSIZE) {
      len = packetbuf_datalen() - COLLECT_MSG_HDRSIZE;

      if(collect_msg->crc == crc16_data(collect_msg->data, len, 0)) {
	msg.len = 5 + (packetbuf_datalen() - COLLECT_MSG_HDRSIZE) / 2;
	rimeaddr_copy((rimeaddr_t *)&msg.originator, originator);
	msg.seqno = seqno;
	msg.hops = hops;
	msg.latency = latency;
	/*    printf("recv_collect datalen %d\n", packetbuf_datalen());*/
	
	shell_output(&collect_command,
		     &msg, sizeof(msg),
		     collect_msg->data, packetbuf_datalen() - COLLECT_MSG_HDRSIZE);
      }
    }
  } else if(waiting_for_nodes) {
    char buf[40];
    snprintf(buf, sizeof(buf), "%d.%d, %d hops, latency %lu ms",
	     originator->u8[0], originator->u8[1],
	     hops, (1000L * latency) / RTIMER_ARCH_SECOND);
    shell_output_str(&nodes_command, "Message from node ", buf);
    messages_received++;
  }

}
Example #18
0
ICACHE_FLASH_ATTR
uint16 CMD_ResponseBody(uint16_t crc_in, uint8_t* data, uint16_t len)
{
  uint8_t temp = 0;
  uint16_t pad_len = len;
  while(pad_len % 4 != 0)
    pad_len++;

  CMD_ProtoWriteBuf((uint8_t*)&pad_len, 2);
  crc_in = crc16_data((uint8_t*)&pad_len, 2, crc_in);
  while(len --){
	  CMD_ProtoWrite(*data);
    crc_in = crc16_data((uint8_t*)data, 1, crc_in);
    data ++;
    if(pad_len > 0) pad_len --;
  }

  while(pad_len --){
	  CMD_ProtoWrite(temp);
    crc_in = crc16_data((uint8_t*)&temp, 1, crc_in);
  }
  return crc_in;
}
Example #19
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_sendcmd_process, ev, data)
{
  struct cmd_msg  *msg;
  int len;
  linkaddr_t addr;
  const char *nextptr;
  char buf[32];

  PROCESS_BEGIN();

  addr.u8[0] = shell_strtolong(data, &nextptr);
  if(nextptr == data || *nextptr != '.') {
    shell_output_str(&sendcmd_command,
             "sendcmd <node addr>: receiver must be specified", "");
    PROCESS_EXIT();
  }
  ++nextptr;
  addr.u8[1] = shell_strtolong(nextptr, &nextptr);

  snprintf(buf, sizeof(buf), "%d.%d", addr.u8[0], addr.u8[1]);
  shell_output_str(&sendcmd_command, "Sending command to ", buf);

  /* Get the length of the command line, excluding a terminating NUL character. */
  len = strlen((char *)nextptr);

  /* Check the length of the command line to see that it is small
     enough to fit in a packet. We count with 32 bytes of header,
     which may be a little too much, but at least we are on the safe
     side. */
  if(len > PACKETBUF_SIZE - 32) {
    snprintf(buf, sizeof(buf), "%d", len);
    shell_output_str(&sendcmd_command, "command line too large: ", buf);
    PROCESS_EXIT();
  }

  packetbuf_clear();
  msg = packetbuf_dataptr();
  packetbuf_set_datalen(len + 1 + CMDMSG_HDR_SIZE);
  strcpy(msg->sendcmd, nextptr);

  /* Terminate the string with a NUL character. */
  msg->sendcmd[len] = 0;
  msg->crc = crc16_data((unsigned char *)msg->sendcmd, len, 0);
  /*    printf("sendcmd sending '%s'\n", msg->sendcmd);*/
  unicast_send(&uc, &addr);

  PROCESS_END();
}
Example #20
0
static void
init_page(struct deluge_object *obj, int pagenum, int have)
{
  struct deluge_page *page;
  unsigned char buf[S_PAGE];

  page = &obj->pages[pagenum];

  page->flags = 0;
  page->last_request = 0;
  page->last_data = 0;

  if(have) {
    page->version = obj->version;
    page->packet_set = ALL_PACKETS;
    page->flags |= PAGE_COMPLETE;
    read_page(obj, pagenum, buf);
    page->crc = crc16_data(buf, S_PAGE, 0);
  } else {
    page->version = 0;
    page->packet_set = 0;
  }
}
Example #21
0
// SLIP process a packet or a bunch of debug console chars
static void ICACHE_FLASH_ATTR
slip_process() {
  if (slip_len > 2) {
    // proper SLIP packet, invoke command processor after checking CRC
    //os_printf("SLIP: rcv %d\n", slip_len);
    uint16_t crc = crc16_data((uint8_t*)slip_buf, slip_len-2, 0);
    uint16_t rcv = ((uint16_t)slip_buf[slip_len-2]) | ((uint16_t)slip_buf[slip_len-1] << 8);
    if (crc == rcv) {
      cmdParsePacket((uint8_t*)slip_buf, slip_len-2);
    } else {
      os_printf("SLIP: bad CRC, crc=%04x rcv=%04x len=%d\n", crc, rcv, slip_len);

      for (short i=0; i<slip_len; i++) {
        if (slip_buf[i] >= ' ' && slip_buf[i] <= '~') {
          DBG("%c", slip_buf[i]);
        } else {
          DBG("\\%02X", slip_buf[i]);
        }
      }
      DBG("\n");
    }
  }
}
Example #22
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_send_process, ev, data)
{
  struct shell_input *input;
  int len;
  struct collect_msg *msg;
  
  PROCESS_BEGIN();

  while(1) {
    PROCESS_WAIT_EVENT_UNTIL(ev == shell_event_input);
    input = data;

    len = input->len1 + input->len2;

    if(len == 0) {
      PROCESS_EXIT();
    }

    if(len < PACKETBUF_SIZE) {
      packetbuf_clear();
      packetbuf_set_datalen(len + COLLECT_MSG_HDRSIZE);
      msg = packetbuf_dataptr();
      memcpy(msg->data, input->data1, input->len1);
      memcpy(msg->data + input->len1, input->data2, input->len2);
#if TIMESYNCH_CONF_ENABLED
      msg->timestamp = timesynch_time();
#else
      msg->timestamp = 0;
#endif
      msg->crc = crc16_data(msg->data, len, 0);
      /*      printf("Sending %d bytes\n", len);*/
      collect_send(&collect, COLLECT_REXMITS);
    }
  }
  PROCESS_END();
}
/*!
 *\brief This callback is called by the kernel when a packet is
 * received on the epoch-syncer broadcast channel. In here we compute
 * the time offsets that we use to control the epoch timing, e.g. by
 * delaying or anticipating the next epoch.
 */
static void __broadcast_recv_cb(struct broadcast_conn *ptr, const rimeaddr_t *sender) {
	int datalen;
	int distance_nr_epochs;
	long int now, offset;
	struct epoch_sync_packet packet;

	/*
	 * Get the current time first-thing; this will be used in the
	 * computation of the epoch offset
	 */
	now = clock_time();

	/*
	 * TODO: we could use the packet rssi to seed tha random number generator
	 *
	 * ! iff the radio operates on lower power modes: otherwise the rssi is the same
	 *   constant all the time
	 *
	 * if (0) {
	 *	uint16_t rssi;
         *
	 *	rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI);
	 *	printf("rssi=0x%.4x\n", rssi);
	 * }
	 */

	datalen = packetbuf_datalen();
	if (datalen != sizeof(struct epoch_sync_packet)) {
		/*
		 * xfer corruption; happens rarely.
		 */
		trace("@%d sync xfer corruption, datalen %d\n", __epoch_syncer.epoch, datalen);
		return;
	}

	/*
	 * Copy the received packet into local storage
	 *
	 * ! the pointer returned by packetbuf_dataptr() is not necesserely aligned
	 *   wrt the mcu platform requirements, thus we cannot simply dereference
	 *   it into a 'struct epoch_sync_packet'. The msp430, in particular, can
	 *    have undefined behaviour when loading from unaligned addresses.
	 */
	memcpy(&packet, packetbuf_dataptr(), datalen);

#ifdef XFER_CRC16
	{
		uint16_t recv_crc16, crc16;

		/*
		 * Compute the received packet crc with the .crc16 field zeroed
		 */
		recv_crc16 = packet.crc16;

		packet.crc16 = 0;
		crc16 = crc16_data((const unsigned char *)&packet, sizeof(struct epoch_sync_packet), 0);

		if (recv_crc16 != crc16) {
			/*
			 * xfer corruption; happens rarely.
			 */
			trace("@%d sync xfer crc mismatch\n", __epoch_syncer.epoch);
			return;
		}
	}
#endif

	/*
	 * The packet is valid: compute the offset between our and the
	 * other node's `time to end of epoch`.
	 *
	 * ! If we are sufficiently out-of-sync than this node and the
	 *   sender node are currently in different epochs and we need to
	 *   special case a bit.
	 */
	offset = 0;
	distance_nr_epochs = __epoch_syncer.epoch - packet.epoch;
	if (distance_nr_epochs > 0) {
		/*
		 * We are going too fast but we don't care, we simply let slower
		 * nodes adjust to us.
		 *
		 * ! don't trace the sender and return.
		 */
		printf("epoch-syncer: discarding packet from epoch %d at epoch %d\n", packet.epoch, __epoch_syncer.epoch);
		return;
	} else if (distance_nr_epochs < 0) {
		long int time_to_epoch_end;
		/*
		 * We are going too slow !
		 */
		if (distance_nr_epochs == -1) {
			assert(__epoch_syncer.epoch_end_time > now);
			time_to_epoch_end = (long int)__epoch_syncer.epoch_end_time - now;
			offset = time_to_epoch_end + packet.time_from_epoch_start;
		} else {
			offset = __epoch_syncer.epoch_interval*(packet.epoch - __epoch_syncer.epoch);
		}
	} else {
		long int time_from_epoch_start, time_to_epoch_end;

		/* 
		 * Both this node and the sender node are in the same epoch.
		 */
		if (now > __epoch_syncer.epoch_end_time) {
			/*
			 * The epoch is expired but the epoch counter has not been updated yet.
			 * If this happens there is a *bug*: something is delaying the epoch_timer `is-expired`
			 * check in the process main loop.
			 *
			 * ! we can't and don't want to recover from this situation: go fix your changes in the code :)
			 */
			printf("@%d BUG epoch-syncer: packet received after end-of-epoch %ld\n", __epoch_syncer.epoch, now - (long int)__epoch_syncer.epoch_end_time);
			return;
		}

		/*
		 * compute this node's `time from epoch start` and `time to epoch end`
		 */
		assert(now <= __epoch_syncer.epoch_end_time);
		assert(__epoch_syncer.epoch_start_time <= now);
		assert(__epoch_syncer.epoch_end_time >__epoch_syncer.epoch_start_time);
		time_from_epoch_start = now - __epoch_syncer.epoch_start_time;

		assert(time_from_epoch_start >= 0);
		assert(time_from_epoch_start < (__epoch_syncer.epoch_end_time -__epoch_syncer.epoch_start_time));
		time_to_epoch_end = __epoch_syncer.epoch_end_time - now;

		/*
		 * compute the `time to epoch end` offset between this node and the sender node
		 */
		offset = time_to_epoch_end - packet.time_to_epoch_end;

		/*
		 * linearly interpolate to guess the eventual offset at end of this node epoch
		 */
		offset = (offset*__epoch_syncer.epoch_interval)/time_from_epoch_start;
	}

	/* update offset statistics */
	__epoch_syncer.max_offset = max(offset, __epoch_syncer.max_offset);
	__epoch_syncer.min_offset = min(offset, __epoch_syncer.min_offset);

	/*
	 * Accumulate the offsets: from this sum the `offset-average` can be computed.
	 * This average is then used to adjust the timing of the next epoch.
	 */
	__epoch_syncer.sum_sync_offsets += offset;
	__epoch_syncer.nr_offsets++;

#ifdef TRACK_CONNECTIONS
	/* trace the xfer */
	connection_track(CONNECTION_TRACK_SYNC, packet.board_id16, __epoch_syncer.epoch);
#endif
}
Example #24
0
static void
handle_packet(struct deluge_msg_packet *msg)
{
  struct deluge_page *page;
  uint16_t crc;
  struct deluge_msg_packet packet;

  memcpy(&packet, msg, sizeof(packet));

  PRINTF("Incoming packet for object id %u, version %u, page %u, packet num %u!\n",
	(unsigned)packet.object_id, (unsigned)packet.version,
	(unsigned)packet.pagenum, (unsigned)packet.packetnum);

  if(packet.pagenum != current_object.current_rx_page) {
    return;
  }

  if(packet.version != current_object.version) {
    neighbor_inconsistency = 1;
  }

  page = &current_object.pages[packet.pagenum];
  if(packet.version == page->version && !(page->flags & PAGE_COMPLETE)) {
    memcpy(&current_object.current_page[S_PKT * packet.packetnum],
	packet.payload, S_PKT);

    crc = crc16_data(packet.payload, S_PKT, 0);
    if(packet.crc != crc) {
      PRINTF("packet crc: %hu, calculated crc: %hu\n", packet.crc, crc);
      return;
    }

    page->last_data = clock_time();
    page->packet_set |= (1 << packet.packetnum);

    if(page->packet_set == ALL_PACKETS) {
      /* This is the last packet of the requested page; stop streaming. */
      packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
			 PACKETBUF_ATTR_PACKET_TYPE_STREAM_END);

      write_page(&current_object, packet.pagenum, current_object.current_page);
      page->version = packet.version;
      page->flags = PAGE_COMPLETE;
      PRINTF("Page %u completed\n", packet.pagenum);

      current_object.current_rx_page++;

      if(packet.pagenum == OBJECT_PAGE_COUNT(current_object) - 1) {
	current_object.version = current_object.update_version;
	leds_on(LEDS_RED);
	PRINTF("Update completed for object %u, version %u\n", 
	       (unsigned)current_object.object_id, packet.version);
      } else if(current_object.current_rx_page < OBJECT_PAGE_COUNT(current_object)) {
        if(ctimer_expired(&rx_timer)) {
	  ctimer_set(&rx_timer,
		CONST_OMEGA * ESTIMATED_TX_TIME + (random_rand() % T_R),
		send_request, &current_object);
	}
      }
      /* Deluge R.3 */
      transition(DELUGE_STATE_MAINTAIN);
    } else {
      /* More packets to come. Put lower layers in streaming mode. */
      packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
			 PACKETBUF_ATTR_PACKET_TYPE_STREAM);
    }
  }
}
PROCESS_THREAD(proc_epoch_syncer, ev, data) {
	static struct etimer send_timer;
	static struct etimer epoch_timer;
	static const struct broadcast_callbacks broadcast_cbs = {__broadcast_recv_cb, __broadcast_sent_cb};
	static struct broadcast_conn conn;

	PROCESS_EXITHANDLER(broadcast_close(&conn));

	PROCESS_BEGIN();


#ifdef TRACK_CONNECTIONS
	/* Log the node id */
	printf("board-id64 0x%.16llx\n", board_get_id64());
#endif
#ifdef XFER_CRC16
	/* Log the node id */
	printf("xfer crc16\n");
#endif
	printf("epoch interval %ld ticks\n", EPOCH_INTERVAL);

	/*
	 * Alloc the two syncer events
	 */
	evt_epoch_synced = process_alloc_event();
	evt_end_of_epoch = process_alloc_event();

	/*
	 * Open a `connection` on the syncer broadcasting channel
	 */
	broadcast_open(&conn, BROADCAST_CHANNEL_TIMESYNC, &broadcast_cbs);

	/*
	 * init the epoch-syncer instance
	 */
	epoch_syncer_init(&__epoch_syncer);

	/*
	 * This is the main syncer loop. Initially we try to sync the
	 * epoch between nodes without concurrently running any other
	 * algo. After a period, at which time the network is synced,
	 * we start generating epoch events which can be
	 * consumed by, e.g., the estimator process.
	 */
	etimer_set(&epoch_timer, __epoch_syncer.epoch_interval);
	__epoch_syncer.epoch_start_time = clock_time();
	__epoch_syncer.epoch_end_time = etimer_expiration_time(&epoch_timer);
	while (1) {
		/*
		 * The start of a new epoch !
		 */
		epoch_syncer_at_epoch_start(&__epoch_syncer);


		clock_time_t now;
		clock_time_t time_to_epoch_end;
			
		now = clock_time();

		assert(__epoch_syncer.epoch_end_time == etimer_expiration_time(&epoch_timer));
		assert(__epoch_syncer.epoch_end_time > now);
		time_to_epoch_end = __epoch_syncer.epoch_end_time - now;

		/* 
		 * Setup a random wait time before sending the sync packet
		 *
		 * ! we cannot let send_timer delay the epoch_timer, especially
		 *   when the next `end-of-epoch-time` has been anticipated by a lot
		 *   (this can happen at startup)
		 */
		if (time_to_epoch_end > __epoch_syncer.epoch_sync_start) {
			long int send_wait;
			long int send_wait_rnd;
			long int rnd;

			rnd = rand();
			send_wait_rnd = (unsigned)rnd % (unsigned) __epoch_syncer.epoch_sync_xfer_interval;
			send_wait = __epoch_syncer.epoch_sync_start + send_wait_rnd;
			assert(send_wait >= __epoch_syncer.epoch_sync_start);
			assert(send_wait <= __epoch_syncer.epoch_sync_start + __epoch_syncer.epoch_sync_xfer_interval);

			if (send_wait > time_to_epoch_end)
				send_wait = __epoch_syncer.epoch_sync_start;

			assert(send_wait < time_to_epoch_end);
			etimer_set(&send_timer, send_wait);

			PROCESS_WAIT_UNTIL(etimer_expired(&send_timer));

			/*
			 * Acquire the radio lock
			 *
			 * ! we don't use WAIT/YIELD_UNTIL() because
			 *   1) we do not want to yield if we can acquire the lock on the first try
			 *   2) no kernel signal is generated when the lock is released (we would `deadlock')
			 */
			do {
				if (!radio_trylock())
					break;

				PROCESS_PAUSE();
			} while (1);


			{
				clock_time_t now;
				struct epoch_sync_packet packet;
					
				/*
				 * broadcast the sync packet
				 *
				 * ! We put this part into its own block since non static stack
				 * variables/allocations in the parent block wouldn't get preserved trough
				 * kernel calls (e.g. the PROCESS_PAUSE() a few lines above)
				 */
#ifdef TRACK_CONNECTIONS
				packet.board_id16 = board_get_id16();
#endif
				packet.epoch = __epoch_syncer.epoch;

				now = clock_time();
				assert(now > __epoch_syncer.epoch_start_time);
				assert(__epoch_syncer.epoch_end_time > now);
				packet.time_from_epoch_start = now - __epoch_syncer.epoch_start_time;
				packet.time_to_epoch_end = __epoch_syncer.epoch_end_time - now;

				
#ifdef XFER_CRC16
				/*
				 * Compute the packet crc with the .crc16 field zeroed
				 */
				{
					uint16_t crc16;

					packet.crc16 = 0;
					crc16 = crc16_data((const unsigned char *)&packet,  sizeof(struct epoch_sync_packet), 0);

					packet.crc16 = crc16;
				}
#endif
				packetbuf_copyfrom(&packet, sizeof(struct epoch_sync_packet));
				broadcast_send(&conn);
			}
		} else {
			printf("epoch-syncer: skipping sync send\n");
		}
			

		/*
		 * We cannot YIELD here: if epoch_timer has already expired there won't be
		 * any event to wake us up.
		 *
		 * FIXME: if we get here and the epoch timer has fired
		 * already print by how much we are late: this can be terribly useful
		 * to trace bugs in the epoch sync code or the kernel.
		 */
		if (etimer_expired(&epoch_timer)) {
			long int now;

			now = clock_time();
			assert(now > __epoch_syncer.epoch_end_time);
			
		} else {
			char do_wait;
			do_wait = 1;

			if (__epoch_syncer.sum_sync_offsets) {
				long int avg_offset = __epoch_syncer.sum_sync_offsets / __epoch_syncer.nr_offsets;
				const long int threshold = CLOCK_SECOND;

				if (avg_offset > threshold) {
					/*
					 * if we are late don't wait until the timer expires
					 * ! this migth give us the opportunity to re-enter the right sync_xfer_interval
					 */
					do_wait = 0;
				} else if (avg_offset < -threshold) {
					/*
					 * we are too fast, delay end of epoch
					 */
					clock_time_t now;
					clock_time_t time_to_epoch_end;
			
					now = clock_time();
					assert(__epoch_syncer.epoch_end_time == etimer_expiration_time(&epoch_timer));
					assert(__epoch_syncer.epoch_end_time > now);
					time_to_epoch_end = __epoch_syncer.epoch_end_time - now;

					long int delay = time_to_epoch_end + (-avg_offset/2);

					static struct etimer delay_timer;
					trace("epoch-syncer: delaying end-of-epoch by %ld ticks\n", (-avg_offset/2));
					etimer_set(&delay_timer, delay);
					__epoch_syncer.epoch_end_time += (-avg_offset/2);

					PROCESS_WAIT_UNTIL(etimer_expired(&delay_timer));
				}
			}

			if (do_wait) {
				PROCESS_WAIT_UNTIL(etimer_expired(&epoch_timer));
			} else {
				trace("epoch-syncer: not waiting for end-of-epoch\n");
			}
		}
		trace("epoch-syncer: epoch %d ended\n",  __epoch_syncer.epoch);

#ifdef TRACK_CONNECTIONS
		connection_print_and_zero(CONNECTION_TRACK_SYNC, __epoch_syncer.epoch);
#endif

		/*
		 * Re-Set the end-of-epoch timer
		 */
		if (__epoch_syncer.epoch == EPOCHS_UNTIL_SYNCED) {
			/*
			 * We have hopefully achieved sync at this point
			 *
			 * 1) update the epoch timings, and set the epoch timer
			 *
			 * 2) signal the size-estimator process that the epoch is now synced
			 */
			__epoch_syncer.epoch_interval = EPOCH_INTERVAL;
			__epoch_syncer.epoch_sync_start = EPOCH_SYNC_START;
			__epoch_syncer.epoch_sync_xfer_interval = EPOCH_SYNC_XFER_INTERVAL;

			etimer_stop(&epoch_timer);
			etimer_set(&epoch_timer, __epoch_syncer.epoch_interval);
			/*
			 * The epoch timer has been re-set: update the time until the next epoch end
			 * Increase the epoch count.
			 * ! these operations must happen in a block which cannot block in kernel calls
			 */
			__epoch_syncer.epoch_start_time = clock_time();
			__epoch_syncer.epoch_end_time = etimer_expiration_time(&epoch_timer);
			__epoch_syncer.epoch++;

			process_post(&proc_size_estimator, evt_epoch_synced, NULL);
		} else {
			/*
			 * Re-set and adjust the epoch timer using the data received trough sync packets
			 * (in this epoch)
			 *
			 * ! using re-set (instead of, e.g., restart) is important here in order to avoid
			 *   drifting
			 */ 
			etimer_reset(&epoch_timer);

			/*
			 * The epoch timer has been re-set: update the time until the next epoch end
			 * Increase the epoch count.
			 * ! these operations must happen in a block which cannot block in kernel calls
			 */
			//__epoch_syncer.epoch_start_time = epoch_timer.timer.start;
			__epoch_syncer.epoch_start_time = clock_time();
			__epoch_syncer.epoch_end_time = etimer_expiration_time(&epoch_timer);
			__epoch_syncer.epoch++;
			if (__epoch_syncer.sum_sync_offsets) {
				long int avg_offset = __epoch_syncer.sum_sync_offsets / __epoch_syncer.nr_offsets;
				const long int threshold = 1;//(CLOCK_SECOND/32);//*3;

#if __CONTIKI_NETSTACK_RDC==__CONTIKI_NETSTACK_RDC_NULL
				const int tx_delay = 0;
#elif __CONTIKI_NETSTACK_RDC==__CONTIKI_NETSTACK_RDC_CXMAC
				/*
				 * When the cxmac RDC is used we must consider an added delay due to the fact that when
				 * other nodes radios are turned off the sync packet must be re-sent.
				 */
				const int tx_delay = 8;
#endif

				/*
				 * estimate the avg tx delay
				 */
				avg_offset += tx_delay;

				trace("epoch-syncer: sync offsets %d ~ %ld < %ld < %ld\n", __epoch_syncer.nr_offsets,  __epoch_syncer.min_offset + tx_delay, avg_offset, __epoch_syncer.max_offset+tx_delay);
				
				if ((avg_offset < -threshold) || (avg_offset > threshold)) {
					clock_time_t new_expiration_time;

					const long int adjust_threshold = CLOCK_SECOND/2;
					long int adjust;
		
					/*
					 * feedback control the next expiration time
					 */
					adjust = -avg_offset/2;
					adjust = min(adjust, adjust_threshold);
					adjust = max(adjust, -adjust_threshold);

					if (adjust)
						etimer_adjust(&epoch_timer, adjust);
						
					new_expiration_time = etimer_expiration_time(&epoch_timer);
					__epoch_syncer.epoch_end_time = new_expiration_time;
				}
			}

			if (__epoch_syncer.epoch > EPOCHS_UNTIL_SYNCED) {
				/*
				 * Signal the estimator-process that this epoch has ended
				 */
				process_post(&proc_size_estimator, evt_end_of_epoch, NULL);
			}
		}
	}

	PROCESS_END();
}
Example #26
0
/*---------------------------------------------------------------------------*/
int
nrf24l01_read(void *buf, unsigned short bufsize)
{
  uint8_t *framep;
 // uint8_t footer[2];
  uint8_t len;
 
#if RF230_CONF_CHECKSUM
  uint16_t checksum;
#endif /* RF230_CONF_CHECKSUM */

#if RF230_CONF_TIMESTAMPS
  struct timestamp t;
#endif /* RF230_CONF_TIMESTAMPS */

  PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe.length,rxframe.lqi,rxframe.crc);

#if DEBUG>1
  for (len=0;len<rxframe.length;len++) PRINTF(" %x",rxframe.data[len]);PRINTF("\n");
#endif
  if (rxframe.length==0) {
    return 0;
  }

#if RF230_CONF_TIMESTAMPS
bomb
  if(interrupt_time_set) {
    rf230_time_of_arrival = interrupt_time;
    interrupt_time_set = 0;
  } else {
    rf230_time_of_arrival = 0;
  }
  rf230_time_of_departure = 0;
#endif /* RF230_CONF_TIMESTAMPS */
  GET_LOCK();
//  if(rxframe.length > RF230_MAX_PACKET_LEN) {
//    // Oops, we must be out of sync.
//  flushrx();
//    RIMESTATS_ADD(badsynch);
//    RELEASE_LOCK();
//    return 0;
//  }

//hal returns two extra bytes containing the checksum
//below works because auxlen is 2
  len = rxframe.length;
  if(len <= AUX_LEN) {
 // flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }
  
  if(len - AUX_LEN > bufsize) {
//  flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }
  /* Transfer the frame, stripping the checksum */
  framep=&(rxframe.data[0]);
  memcpy(buf,framep,len-2);
  /* Clear the length field to allow buffering of the next packet */
  rxframe.length=0;
 // framep+=len-AUX_LEN+2;

#if RADIOSTATS
  RF230_receivepackets++;
#endif

#if RF230_CONF_CHECKSUM
bomb
  memcpy(&checksum,framep,CHECKSUM_LEN);
  framep+=CHECKSUM_LEN;
#endif /* RF230_CONF_CHECKSUM */
#if RF230_CONF_TIMESTAMPS
bomb
  memcpy(&t,framep,TIMESTAMP_LEN);
  framep+=TIMESTAMP_LEN;
#endif /* RF230_CONF_TIMESTAMPS */
//  memcpy(&footer,framep,FOOTER_LEN);
 
#if RF230_CONF_CHECKSUM
bomb
  if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
    PRINTF("rf230: checksum failed 0x%04x != 0x%04x\n",
	   checksum, crc16_data(buf, len - AUX_LEN, 0));
  }
  
  if(footer[1] & FOOTER1_CRC_OK &&
     checksum == crc16_data(buf, len - AUX_LEN, 0)) {
#else
  if (rxframe.crc) {
#endif /* RF230_CONF_CHECKSUM */

 #if RADIOSTATS
    RF230_rsigsi=hal_subregister_read( SR_RSSI );
#endif      
    //nick packetbuf_set_attr(PACKETBUF_ATTR_RSSI, hal_subregister_read( SR_RSSI ));
    //nick packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rxframe.lqi);
    
    RIMESTATS_ADD(llrx);
    
#if RF230_CONF_TIMESTAMPS
bomb
    rf230_time_of_departure =
      t.time +
      setup_time_for_transmission +
      (total_time_for_transmission * (len - 2)) / total_transmission_len;
  
    rf230_authority_level_of_sender = t.authority_level;

    packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
#endif /* RF230_CONF_TIMESTAMPS */
  
  } else {
    PRINTF("rf230: Bad CRC\n");

#if RADIOSTATS
    RF230_receivefail++;
#endif

    RIMESTATS_ADD(badcrc);
    len = AUX_LEN;
  }
// if (?)
     /* Another packet has been received and needs attention. */
//    process_poll(&nrf24l01_process);
//  }
  
  RELEASE_LOCK();
  
  if(len < AUX_LEN) {
    return 0;
  }

  return len - AUX_LEN;
  }

/*---------------------------------------------------------------------------*/
void
nrf24l01_init(uint8_t mode)
{
  rf_mode = mode;

  /* Initialize Hardware Abstraction Layer. */
  //hal_init();
  
  //init the spi functions
  spi_init();

  SPI_CHIP_ENABLE();
  
  if(RF_TX_MODE == mode)  //tx mode
        {              
            SPI_WRITE_REG(WRITE_REG, 0x0C); //RX_DR, TX_DS, MAX_RT interrupts enabled, CRC enabled, CRC encoding with 2bytes and as PTX
	    //SPI_WRITE_REG(WRITE_REG+EN_AA, 0x3F); //Enable auto-acknowledge for all data pipe
	    //SPI_WRITE_REG(WRITE_REG+EN_RXADDR, 0x01); //Enable RX address data pipe 0, reset value is 0x03 (data pipe 0 and 1)
	    //SPI_WRITE_REG(WRITE_REG+SETUP_AW, 0x03); //Setup of address width, reset value is 0x33--5 bytes
	    SPI_WRITE_REG(WRITE_REG+SETUP_RETR, 0xFF); //Set auto-retransmision, ARD(auto retransmit delay): 1111, ARC(auto retransmit count): 1111
	    //SPI_WRITE_REG(WRITE_REG+RF_CH, 0x02); //RF Channel 2 (default, not really needed)
	    //SPI_WRITE_REG(WRITE_REG+RF_SETUP, 0x03); //Air data rate 1Mbit, -12dBm, Setup LNA

	    //SPI_WRITE_BUF(WRITE_REG+RX_ADDR_P0, (uint8_t*)&TX_ADDRESS, ADDR_WIDTH); //Set receive address to receive aut-ACK, it is equal to TX_ADDR if enbel enhanced shock burst
	    //SPI_WRITE_BUF(WRITE_REG+TX_ADDR, (uint8_t*)&TX_ADDRESS, ADDR_WIDTH); //Set transmit address: 0xE7E7E7E7E7
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P0, 0x04); // 4 byte receive payload
	
	    //the next 2 commands are relative with dynamic payload lenght, you need disable them if use static payload length
	    //enable dynamic payload length, enable dynamic ACK in specific package(then you can 
	    //use command W_TX_PAYLOAD_NOACK to set a specfic package that needn't wait for ACK)
	    SPI_WRITE_REG(WRITE_REG+DYNPD, 0x01);  //as PTX, at least enable pipe 0	
	    SPI_WRITE_REG(WRITE_REG+FEATURE, 0x05);  			
	    //SPI_WRITE_REG(WRITE_REG, 0x0E); //power upr	            
        }
	else   //rx mode
	{	    
            SPI_WRITE_REG(WRITE_REG, 0x0D); //RX_DR, TX_DS, MAX_RT interrupts enabled, CRC enabled, CRC encoding with 2bytes and as PRX
	    //SPI_WRITE_REG(WRITE_REG+EN_AA, 0x3F); //Enable auto-acknowledge for all data pipes(0-5)
	    SPI_WRITE_REG(WRITE_REG+EN_RXADDR, 0x3F); //Enable RX address for all data pipes(0-5)     
	    //SPI_WRITE_REG(WRITE_REG+SETUP_AW, 0x03); //Setup of address width, reset value is 0x33--5 bytes
	    SPI_WRITE_REG(WRITE_REG+SETUP_RETR, 0xFF); //Set auto-retransmision, ARD(auto retransmit delay): 1111, ARC(auto retransmit count): 1111
	    //SPI_WRITE_REG(WRITE_REG+RF_CH, 0x02); //RF Channel 2 (default, not really needed)
	    //SPI_WRITE_REG(WRITE_REG+RF_SETUP, 0x03); //Air data rate 1Mbit, -12dBm, Setup LNA

	    //SPI_WRITE_BUF(WRITE_REG+RX_ADDR_P0, (uint8_t*)&TX_ADDRESS, ADDR_WIDTH); //Set receive address for pipe0
	    //SPI_WRITE_BUF(WRITE_REG+RX_ADDR_P1, (uint8_t*)&RX_ADDRESS, ADDR_WIDTH); //Set receive address for pipe1
	    //SPI_WRITE_REG(WRITE_REG+RX_ADDR_P2, 0XC3); //Set receive address for pipe2
	    //SPI_WRITE_REG(WRITE_REG+RX_ADDR_P3, 0XC4); //Set receive address for pipe3
	    //SPI_WRITE_REG(WRITE_REG+RX_ADDR_P4, 0XC5); //Set receive address for pipe4
	    //SPI_WRITE_REG(WRITE_REG+RX_ADDR_P5, 0XC6); //Set receive address for pipe5

	    SPI_WRITE_REG(WRITE_REG+RX_PW_P0, 0x04); // 4 byte receive payload for pipe 0
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P1, 0x04); // 4 byte receive payload
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P2, 0x04); // 4 byte receive payload
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P3, 0x04); // 4 byte receive payload
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P4, 0x04); // 4 byte receive payload
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P5, 0x04); // 4 byte receive payload for pipe 5	
	
	    //don't use static payload length
	    /*SPI_WRITE_REG(WRITE_REG+RX_PW_P0, 0xFF);  //data pipe 0, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P1, 0xFF);  //data pipe 1, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P2, 0xFF);  //data pipe 2, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P3, 0xFF);  //data pipe 3, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P4, 0xFF);  //data pipe 4, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P5, 0xFF);  //data pipe 5, number of bytes: 32
	    */
	    SPI_WRITE_REG(WRITE_REG+DYNPD, 0x3F);  //as PRX, enable all pipes
	    SPI_WRITE_REG(WRITE_REG+FEATURE, 0x05);  //enable dynamic payload length			

	    //SPI_WRITE_REG(WRITE_REG, 0x0F); //power upr
	}	
	SPI_CHIP_DISABLE();
	
  /* Start the packet receive process */
  process_start(&nrf24l01_process, NULL);
}
Example #27
0
/*---------------------------------------------------------------------------*/
static int
cc2420_read(void *buf, unsigned short bufsize)
{
  uint8_t footer[2];
  uint8_t len;
#if CC2420_CONF_CHECKSUM
  uint16_t checksum;
#endif /* CC2420_CONF_CHECKSUM */

  if(!CC2420_FIFOP_IS_1) {
    return 0;
  }
  /*  if(!pending) {
    return 0;
    }*/
  
  pending = 0;
  
  GET_LOCK();

  cc2420_packets_read++;

  getrxbyte(&len);

  if(len > CC2420_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    flushrx();
    RIMESTATS_ADD(badsynch);
    RELEASE_LOCK();
    return 0;
  }

  if(len <= AUX_LEN) {
    flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }

  if(len - AUX_LEN > bufsize) {
    flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }

  getrxdata(buf, len - AUX_LEN);
#if CC2420_CONF_CHECKSUM
  getrxdata(&checksum, CHECKSUM_LEN);
#endif /* CC2420_CONF_CHECKSUM */
  getrxdata(footer, FOOTER_LEN);

#if CC2420_CONF_CHECKSUM
  if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
    PRINTF("checksum failed 0x%04x != 0x%04x\n",
	   checksum, crc16_data(buf, len - AUX_LEN, 0));
  }

  if(footer[1] & FOOTER1_CRC_OK &&
     checksum == crc16_data(buf, len - AUX_LEN, 0)) {
#else
  if(footer[1] & FOOTER1_CRC_OK) {
#endif /* CC2420_CONF_CHECKSUM */
    cc2420_last_rssi = footer[0];
    cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;


    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);

    RIMESTATS_ADD(llrx);

  } else {
    RIMESTATS_ADD(badcrc);
    len = AUX_LEN;
  }

  if(CC2420_FIFOP_IS_1) {
    if(!CC2420_FIFO_IS_1) {
      /* Clean up in case of FIFO overflow!  This happens for every
       * full length frame and is signaled by FIFOP = 1 and FIFO =
       * 0. */
      flushrx();
    } else {
      /* Another packet has been received and needs attention. */
      process_poll(&cc2420_process);
    }
  }

  RELEASE_LOCK();

  if(len < AUX_LEN) {
    return 0;
  }

  return len - AUX_LEN;
}
/*---------------------------------------------------------------------------*/
void
cc2420_set_txpower(uint8_t power)
{
  GET_LOCK();
  set_txpower(power);
  RELEASE_LOCK();
}
Example #28
0
/*---------------------------------------------------------------------------*/
int
cc2420_send(const void *payload, unsigned short payload_len)
{
  int i;
  uint8_t total_len;
  struct timestamp timestamp;
  uint16_t checksum;

  GET_LOCK();

  PRINTF("cc2420: sending %d bytes\n", payload_len);
  
  RIMESTATS_ADD(lltx);

  /* Wait for any previous transmission to finish. */
  while(status() & BV(CC2420_TX_ACTIVE));

  /* Write packet to TX FIFO. */
  strobe(CC2420_SFLUSHTX);

  checksum = crc16_data(payload, payload_len, 0);
  total_len = payload_len + AUX_LEN;
  FASTSPI_WRITE_FIFO(&total_len, 1);
  FASTSPI_WRITE_FIFO(payload, payload_len);
  FASTSPI_WRITE_FIFO(&checksum, CHECKSUM_LEN);

#if CC2420_CONF_TIMESTAMPS
  timestamp.authority_level = timesynch_authority_level();
  timestamp.time = timesynch_time();
  FASTSPI_WRITE_FIFO(&timestamp, TIMESTAMP_LEN);
#endif /* CC2420_CONF_TIMESTAMPS */

  /* The TX FIFO can only hold one packet. Make sure to not overrun
   * FIFO by waiting for transmission to start here and synchronizing
   * with the CC2420_TX_ACTIVE check in cc2420_send.
   *
   * Note that we may have to wait up to 320 us (20 symbols) before
   * transmission starts.
   */
#ifdef TMOTE_SKY
#define LOOP_20_SYMBOLS 100	/* 326us (msp430 @ 2.4576MHz) */
#elif __AVR__
#define LOOP_20_SYMBOLS 500	/* XXX */
#endif

#if WITH_SEND_CCA
  strobe(CC2420_SRXON);
  while(!(status() & BV(CC2420_RSSI_VALID)));
  strobe(CC2420_STXONCCA);
#else /* WITH_SEND_CCA */
  strobe(CC2420_STXON);
#endif /* WITH_SEND_CCA */
  
  for(i = LOOP_20_SYMBOLS; i > 0; i--) {
    if(SFD_IS_1) {
#if CC2420_CONF_TIMESTAMPS
      rtimer_clock_t txtime = timesynch_time();
#endif /* CC2420_CONF_TIMESTAMPS */

      if(receive_on) {
	ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
      }
      ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

      /* We wait until transmission has ended so that we get an
	 accurate measurement of the transmission time.*/
      while(status() & BV(CC2420_TX_ACTIVE));

#if CC2420_CONF_TIMESTAMPS
      setup_time_for_transmission = txtime - timestamp.time;

      if(num_transmissions < 10000) {
	total_time_for_transmission += timesynch_time() - txtime;
	total_transmission_len += total_len;
	num_transmissions++;
      }

#endif /* CC2420_CONF_TIMESTAMPS */

#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
      ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
#endif
      ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
      if(receive_on) {
	ENERGEST_ON(ENERGEST_TYPE_LISTEN);
      }

      RELEASE_LOCK();
      return 0;
    }
  }
  
  /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
     transmitted because of other channel activity. */
  RIMESTATS_ADD(contentiondrop);
  PRINTF("cc2420: do_send() transmission never started\n");
  RELEASE_LOCK();
  return -3;			/* Transmission never started! */
}
Example #29
0
/*---------------------------------------------------------------------------*/
int
cc2420_read(void *buf, unsigned short bufsize)
{
  uint8_t footer[2];
  uint8_t len;
  uint16_t checksum;
  struct timestamp t;
  
  if(!FIFOP_IS_1) {
    /* If FIFOP is 0, there is no packet in the RXFIFO. */
    return 0;
  }
  
  if(interrupt_time_set) {
#if CC2420_CONF_TIMESTAMPS
    cc2420_time_of_arrival = interrupt_time;
#endif /* CC2420_CONF_TIMESTAMPS */
    interrupt_time_set = 0;
  } else {
    cc2420_time_of_arrival = 0;
  }
  cc2420_time_of_departure = 0;
  GET_LOCK();

  getrxbyte(&len);

  if(len > CC2420_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    flushrx();
    RIMESTATS_ADD(badsynch);
    RELEASE_LOCK();
    return 0;
  }

  if(len <= AUX_LEN) {
    flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }
  
  if(len - AUX_LEN > bufsize) {
    flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }

  getrxdata(buf, len - AUX_LEN);
  getrxdata(&checksum, CHECKSUM_LEN);
  getrxdata(&t, TIMESTAMP_LEN);
  getrxdata(footer, FOOTER_LEN);
  
  if(footer[1] & FOOTER1_CRC_OK &&
     checksum == crc16_data(buf, len - AUX_LEN, 0)) {
    cc2420_last_rssi = footer[0];
    cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
    RIMESTATS_ADD(llrx);
    
#if CC2420_CONF_TIMESTAMPS
    cc2420_time_of_departure =
      t.time +
      setup_time_for_transmission +
      (total_time_for_transmission * (len - 2)) / total_transmission_len;
  
    cc2420_authority_level_of_sender = t.authority_level;
  
#endif /* CC2420_CONF_TIMESTAMPS */
  
  } else {
    RIMESTATS_ADD(badcrc);
    len = AUX_LEN;
  }
  
  /* Clean up in case of FIFO overflow!  This happens for every full
   * length frame and is signaled by FIFOP = 1 and FIFO = 0.
   */
  if(FIFOP_IS_1 && !FIFO_IS_1) {
    /*    printf("cc2420_read: FIFOP_IS_1 1\n");*/
    flushrx();
  } else if(FIFOP_IS_1) {
    /* Another packet has been received and needs attention. */
    process_poll(&cc2420_process);
  }
  
  RELEASE_LOCK();
  
  if(len < AUX_LEN) {
    return 0;
  }

  return len - AUX_LEN;
}
Example #30
0
/*---------------------------------------------------------------------------*/
static uint16_t packet_hash(const void *data, size_t length)
{
	return crc16_data(data, length, 0) & 0xFFFF;
}