コード例 #1
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
/*---------------------------------------------------------------------------*/
static int
spirit_radio_off(void)
{  
  PRINTF("Spirit1: ->off\n");
  if(spirit_on == ON) {
    /* Disables the mcu to get IRQ from the SPIRIT1 */
    IRQ_DISABLE();

    /* first stop rx/tx */
    spirit1_strobe(SPIRIT1_STROBE_SABORT);

    /* Clear any pending irqs */
    SpiritIrqClearStatus();
    
    BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 5 * RTIMER_SECOND/1000);
    if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
      PRINTF("Spirit1: failed off->ready\n");
      return 1;
    }

    /* Puts the SPIRIT1 in STANDBY */
    spirit1_strobe(SPIRIT1_STROBE_STANDBY);
    BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, 5 * RTIMER_SECOND/1000);
    if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
      PRINTF("Spirit1: failed off->stdby\n");
      return 1;
    }

    spirit_on = OFF;
    CLEAR_TXBUF();
    CLEAR_RXBUF(); 
  }
  PRINTF("Spirit1: off.\n");
  return 0; 
}
コード例 #2
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
/*---------------------------------------------------------------------------*/
static int
spirit_radio_on(void)
{
  PRINTF("Spirit1: on\n");
  if(spirit_on == OFF) {
    IRQ_DISABLE();

    /* ensure we are in READY state as we go from there to Rx */
    spirit1_strobe(SPIRIT1_STROBE_READY);
    BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 5 * RTIMER_SECOND/1000);
    if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
      PRINTF("Spirit1: failed to turn on\n");
      panic_ra(4);
      return 1;
    }

    /* now we go to Rx */
    spirit1_strobe(SPIRIT1_STROBE_RX);
    BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 5 * RTIMER_SECOND/1000);
    if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
      PRINTF("Spirit1: failed to enter rx\n");
      panic_ra(5);
      return 1;
    }
    
    /* Enables the mcu to get IRQ from the SPIRIT1 */
    IRQ_ENABLE();
    spirit_on = ON;
  }

  return 0;
}
コード例 #3
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
/*---------------------------------------------------------------------------*/
static int
spirit_radio_transmit(unsigned short payload_len)
{ 
  /* This function blocks until the packet has been transmitted */
  rtimer_clock_t rtimer_txdone, rtimer_rxack;

  PRINTF("TRANSMIT IN\n");
  if(!packet_is_prepared) {
    return RADIO_TX_ERR;
  }

  /* Stores the length of the packet to send */
  /* Others spirit_radio_prepare will be in hold */
  spirit_txbuf[0] = payload_len;
  
  /* Puts the SPIRIT1 in TX state */
  receiving_packet = 0;
  SpiritSetReadyState(); 
  spirit1_strobe(SPIRIT1_STROBE_TX);
  just_got_an_ack = 0;
  BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_TX, 5 * RTIMER_SECOND/1000);
  BUSYWAIT_UNTIL(SPIRIT1_STATUS() != SPIRIT1_STATE_TX, 50 * RTIMER_SECOND/1000);

  /* Reset radio - needed for immediate RX of ack */
  CLEAR_TXBUF();
  CLEAR_RXBUF();
  SpiritIrqClearStatus();
  spirit1_strobe(SPIRIT1_STROBE_SABORT);
  BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 1 * RTIMER_SECOND/1000);
  spirit1_strobe(SPIRIT1_STROBE_READY);
  BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 1 * RTIMER_SECOND/1000);
  spirit1_strobe(SPIRIT1_STROBE_RX);
  BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 1 * RTIMER_SECOND/1000);

#if NULLRDC_CONF_802154_AUTOACK
  if (wants_an_ack) {
    rtimer_txdone = RTIMER_NOW();
    BUSYWAIT_UNTIL(just_got_an_ack, 15 * RTIMER_SECOND/1000);
    rtimer_rxack = RTIMER_NOW();

    if(just_got_an_ack) {
      ACKPRINTF("debug_ack: ack received after %u/%u ticks\n",
             (uint32_t)(rtimer_rxack - rtimer_txdone), 15 * RTIMER_SECOND/1000);
    } else {
      ACKPRINTF("debug_ack: no ack received\n");
    }
  }
#endif /* NULLRDC_CONF_802154_AUTOACK */

  PRINTF("TRANSMIT OUT\n");

  CLEAR_TXBUF();

  packet_is_prepared = 0;
  return RADIO_TX_OK;
}
コード例 #4
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
/*---------------------------------------------------------------------------*/
static int
spirit_radio_channel_clear(void)
{
  float rssi_value;
  /* Local variable used to memorize the SPIRIT1 state */
  uint8_t spirit_state = ON;
  
  PRINTF("CHANNEL CLEAR IN\n");
  
  if(spirit_on == OFF) {
    /* Wakes up the SPIRIT1 */
    spirit_radio_on();
    spirit_state = OFF;
  }
  
  /*  */
  IRQ_DISABLE();
  spirit1_strobe(SPIRIT1_STROBE_SABORT);
/*  SpiritCmdStrobeSabort();*/
  SpiritIrqClearStatus();
  IRQ_ENABLE();
  {
    rtimer_clock_t timeout = RTIMER_NOW() + 5 * RTIMER_SECOND/1000;
    do {
      SpiritRefreshStatus();
    } while((g_xStatus.MC_STATE != MC_STATE_READY) && (RTIMER_NOW() < timeout));
    if(RTIMER_NOW() < timeout) {
      return 1;
    }
  }

  /* Stores the RSSI value */
  rssi_value = SpiritQiGetRssidBm();
  
  /* Puts the SPIRIT1 in its previous state */
  if(spirit_state==OFF) {
    spirit_radio_off();
  } else {
    spirit1_strobe(SPIRIT1_STROBE_RX);
/*    SpiritCmdStrobeRx();*/
    BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 5 * RTIMER_SECOND/1000);
  }
  
  PRINTF("CHANNEL CLEAR OUT\n");
  
  /* Checks the RSSI value with the threshold */
  if(rssi_value<CCA_THRESHOLD) {
    return 0;
  } else {
    return 1;
  }
}
コード例 #5
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
/**
* @brief  Puts the SPIRIT1 in READY state.
* @param  None
* @retval None
*/
void SpiritSetReadyState(void)
{
  PRINTF("READY IN\n");

  SpiritIrqClearStatus();
  IRQ_DISABLE();

  if(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY) {
    spirit1_strobe(SPIRIT1_STROBE_READY);
/*    SpiritCmdStrobeReady();*/
  } else if(SPIRIT1_STATUS() == SPIRIT1_STATE_RX) {
    spirit1_strobe(SPIRIT1_STROBE_SABORT);
/*    SpiritCmdStrobeSabort();*/
    SpiritIrqClearStatus();
  }

  IRQ_ENABLE();

  PRINTF("READY OUT\n");
}
コード例 #6
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
/*---------------------------------------------------------------------------*/
static int
spirit_radio_prepare(const void *payload, unsigned short payload_len)
{
  PRINTF("Spirit1: prep %u\n", payload_len);
  packet_is_prepared = 0;

  /* Checks if the payload length is supported */
  if(payload_len > MAX_PACKET_LEN) {
    return RADIO_TX_ERR;
  }
  
  /* Waits the end of a still running spirit_radio_transmit */
  BUSYWAIT_UNTIL(IS_TXBUF_EMPTY(), TX_WAIT_PCKT_PERIOD * RTIMER_SECOND/1000);
  if(!IS_TXBUF_EMPTY()) {
    PRINTF("PREPARE OUT ERR\n");
    return RADIO_TX_ERR;
  }

  /* Should we delay for an ack? */
#if NULLRDC_CONF_802154_AUTOACK
  frame802154_t info154;
  wants_an_ack = 0;
  if(payload_len > ACK_LEN
      && frame802154_parse((char*)payload, payload_len, &info154) != 0) {
    if(info154.fcf.frame_type == FRAME802154_DATAFRAME
        && info154.fcf.ack_required != 0) {
      wants_an_ack = 1;
    }
  }
#endif /* NULLRDC_CONF_802154_AUTOACK */

  /* Sets the length of the packet to send */
  spirit1_strobe(SPIRIT1_STROBE_FTX);
  SpiritPktBasicSetPayloadLength(payload_len);
  SpiritSpiWriteLinearFifo(payload_len, (uint8_t *)payload);
  
  PRINTF("PREPARE OUT\n");

  packet_is_prepared = 1;
  return RADIO_TX_OK;
}
コード例 #7
0
ファイル: SPIRIT1_interface.c プロジェクト: jpnorair/OpenTag
void spirit1_reset() {
/// Turn-off interrupts, send Reset strobe, and wait for reset to finish.
    spirit1_int_turnoff(RFI_ALL);
    spirit1_strobe(STROBE(SRES));
    spirit1_waitforreset();
}
コード例 #8
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
/*---------------------------------------------------------------------------*/
void
spirit1_interrupt_callback(void)
{
#define INTPRINTF // PRINTF
  SpiritIrqs xIrqStatus;

  if (SpiritSPIBusy() || interrupt_callback_in_progress) {
    process_poll(&spirit_radio_process);
    interrupt_callback_wants_poll = 1;
    return;
  }
  interrupt_callback_wants_poll = 0;
  interrupt_callback_in_progress = 1;

  /* get interrupt source from radio */
  SpiritIrqGetStatus(&xIrqStatus);
  SpiritIrqClearStatus();

  if(xIrqStatus.IRQ_RX_FIFO_ERROR) {
    receiving_packet = 0;
    interrupt_callback_in_progress = 0;
    spirit1_strobe(SPIRIT1_STROBE_FRX);
    return;
  }
  if(xIrqStatus.IRQ_TX_FIFO_ERROR) {
    receiving_packet = 0;
    interrupt_callback_in_progress = 0;
    spirit1_strobe(SPIRIT1_STROBE_FTX);
    return;
  }

  /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
  if(xIrqStatus.IRQ_VALID_SYNC) {
    INTPRINTF("SYNC\n");
    receiving_packet = 1;
  }

  /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
  if(xIrqStatus.IRQ_TX_DATA_SENT) {
    spirit1_strobe(SPIRIT1_STROBE_RX);
/*    SpiritCmdStrobeRx();*/
    INTPRINTF("SENT\n");
    CLEAR_TXBUF();
    interrupt_callback_in_progress = 0;
    return;
  }

  /* The IRQ_RX_DATA_READY notifies a new packet arrived */
  if(xIrqStatus.IRQ_RX_DATA_READY) {
    SpiritSpiReadLinearFifo(SpiritLinearFifoReadNumElementsRxFifo(), &spirit_rxbuf[1]);
    spirit_rxbuf[0] = SpiritPktBasicGetReceivedPktLength();
    spirit1_strobe(SPIRIT1_STROBE_FRX);

    INTPRINTF("RECEIVED\n");

   	process_poll(&spirit_radio_process);

    receiving_packet = 0;
    
#if NULLRDC_CONF_802154_AUTOACK
    if (spirit_rxbuf[0] == ACK_LEN) {
      /* For debugging purposes we assume this is an ack for us */
      just_got_an_ack = 1;
    }
#endif /* NULLRDC_CONF_802154_AUTOACK */

    interrupt_callback_in_progress = 0;
    return;
  }
  
  if(xIrqStatus.IRQ_RX_DATA_DISC) {
    spirit1_strobe(SPIRIT1_STROBE_FRX);
    CLEAR_RXBUF();
    INTPRINTF("DISC\n");
    receiving_packet = 0;
  }

  interrupt_callback_in_progress = 0;
}
コード例 #9
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
PROCESS_THREAD(spirit_radio_process, ev, data)
{
  PROCESS_BEGIN();
  PRINTF("Spirit1: process started\n");
  
  while(1) {
    int len;

    PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);    
    PRINTF("Spirit1: polled\n");

    packetbuf_clear();
    len = spirit_radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);

    if(len > 0) {

#if NULLRDC_CONF_802154_AUTOACK
      /* Check if the packet has an ACK request */
      frame802154_t info154;
      if(len > ACK_LEN &&
          frame802154_parse((char*)packetbuf_dataptr(), len, &info154) != 0) {
        if(info154.fcf.frame_type == FRAME802154_DATAFRAME &&
            info154.fcf.ack_required != 0 &&
            rimeaddr_cmp((rimeaddr_t *)&info154.dest_addr,
                         &rimeaddr_node_addr)) {

          /* Send an ACK packet */
          uint8_t ack_frame[ACK_LEN] = {
              FRAME802154_ACKFRAME,
              0x00,
              info154.seq
          };

          spirit1_strobe(SPIRIT1_STROBE_FTX);
          SpiritPktBasicSetPayloadLength((uint16_t) ACK_LEN);
          SpiritSpiWriteLinearFifo((uint16_t) ACK_LEN, (uint8_t *) ack_frame);

          SpiritSetReadyState();
          spirit1_strobe(SPIRIT1_STROBE_TX);
          BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_TX, 1 * RTIMER_SECOND/1000);
          BUSYWAIT_UNTIL(SPIRIT1_STATUS() != SPIRIT1_STATE_TX, 1 * RTIMER_SECOND/1000);

          ACKPRINTF("debug_ack: sent ack %d\n", ack_frame[2]);
        }
      }
#endif /* NULLRDC_CONF_802154_AUTOACK */

      packetbuf_set_datalen(len);   
      NETSTACK_RDC.input();
    }
    if(!IS_RXBUF_EMPTY()){
      process_poll(&spirit_radio_process);
    }

    if(interrupt_callback_wants_poll) {
      spirit1_interrupt_callback();

      if(SPIRIT1_STATUS() == SPIRIT1_STATE_READY) {
        spirit1_strobe(SPIRIT1_STROBE_RX);
        BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 1 * RTIMER_SECOND/1000);
      }

    }
  }

  PROCESS_END();
}
コード例 #10
0
ファイル: spirit1.c プロジェクト: Cancan79/mist
/*---------------------------------------------------------------------------*/
static int
spirit_radio_init(void)
{  
  PRINTF("RADIO INIT IN\n");

  SpiritSpiInit();
  
  /* Configure radio shut-down (SDN) pin and activate radio */
  SdkEvalM2SGpioInit(M2S_GPIO_SDN, M2S_MODE_GPIO_OUT);
  
  /* Configures the SPIRIT1 library */
  SpiritRadioSetXtalFrequency(XTAL_FREQUENCY);
  SpiritManagementSetVersion(SPIRIT1_VERSION);
  SpiritGeneralSetSpiritVersion(SPIRIT1_VERSION);
  SpiritManagementSetXtalFrequency(XTAL_FREQUENCY);
  
  /* wake up to READY state */
  /* weirdly enough, this *should* actually *set* the pin, not clear it! The pins is declared as GPIO_pin13 == 0x2000 */
  M2S_GPIO_SDN_PORT->BSRRL = M2S_GPIO_SDN_PIN;
/*  GPIOC->BSRRL = M2S_GPIO_SDN_PIN;*/
  GPIO_ResetBits(M2S_GPIO_SDN_PORT, M2S_GPIO_SDN_PIN);

  /* wait minimum 1.5 ms to allow SPIRIT1 a proper boot-up sequence */
  BUSYWAIT_UNTIL(0, 3 * RTIMER_SECOND/2000);
  
  /* Soft reset of core */
  spirit1_strobe(SPIRIT1_STROBE_SRES);
/*  SpiritCmdStrobeSres();*/
  
  /* Configures the SPIRIT1 radio part */
  SRadioInit xRadioInit = {
    XTAL_FREQUENCY,
    XTAL_OFFSET_PPM,
    BASE_FREQUENCY,
    CHANNEL_SPACE,
    CHANNEL_NUMBER,
    MODULATION_SELECT,
    DATARATE,
    FREQ_DEVIATION,
    BANDWIDTH
  };
  SpiritRadioInit(&xRadioInit);
  SpiritRadioSetPALeveldBm(0,POWER_DBM);
  SpiritRadioSetPALevelMaxIndex(0);
  
  /* Configures the SPIRIT1 packet handler part*/
  PktBasicInit xBasicInit = {
    PREAMBLE_LENGTH,
    SYNC_LENGTH,
    SYNC_WORD,
    LENGTH_TYPE,
    LENGTH_WIDTH,
    CRC_MODE,
    CONTROL_LENGTH,
    EN_ADDRESS,
    EN_FEC,
    EN_WHITENING
  };
  SpiritPktBasicInit(&xBasicInit);
  
  /* Enable the following interrupt sources, routed to GPIO */
  SpiritIrqDeInit(NULL);
  SpiritIrqClearStatus();
  SpiritIrq(TX_DATA_SENT, S_ENABLE);
  SpiritIrq(RX_DATA_READY,S_ENABLE);
  SpiritIrq(VALID_SYNC,S_ENABLE);
  SpiritIrq(RX_DATA_DISC, S_ENABLE);
  SpiritIrq(TX_FIFO_ERROR, S_ENABLE);
  SpiritIrq(RX_FIFO_ERROR, S_ENABLE);

  /* Configure Spirit1 */
  SpiritRadioPersistenRx(S_ENABLE);
  SpiritQiSetSqiThreshold(SQI_TH_0);
  SpiritQiSqiCheck(S_ENABLE);
  SpiritQiSetRssiThresholddBm(CCA_THRESHOLD);
  SpiritTimerSetRxTimeoutStopCondition(SQI_ABOVE_THRESHOLD);
  SET_INFINITE_RX_TIMEOUT();
  SpiritRadioAFCFreezeOnSync(S_ENABLE);
  
  /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
  spirit1_strobe(SPIRIT1_STROBE_STANDBY);
/*  SpiritCmdStrobeCommand(SPIRIT1_STROBE_STANDBY);*/
/*  SpiritCmdStrobeStandby();*/
  spirit_on = OFF;
  CLEAR_RXBUF();
  CLEAR_TXBUF();
  
  /* Initializes the mcu pin as input, used for IRQ */
  SdkEvalM2SGpioInit(M2S_GPIO_0, M2S_MODE_EXTI_IN);
  SdkEvalM2SGpioInit(M2S_GPIO_1, M2S_MODE_EXTI_IN);
  SdkEvalM2SGpioInit(M2S_GPIO_2, M2S_MODE_EXTI_IN);
  SdkEvalM2SGpioInit(M2S_GPIO_3, M2S_MODE_EXTI_IN);
  
  /* Configure the radio to route the IRQ signal to its GPIO 3 */
  SpiritGpioInit(&(SGpioInit){SPIRIT_GPIO_3, SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP, SPIRIT_GPIO_DIG_OUT_IRQ});

  process_start(&spirit_radio_process, NULL);

  PRINTF("Spirit1 init done\n");

  return 0;
}