/************************************************************************************************** * @fn MRFI_WakeUp * * @brief Wake up radio from sleep state. * * @param none * * @return none ************************************************************************************************** */ void MRFI_WakeUp(void) { /* if radio is already awake, just ignore wakeup request */ if (!mrfiRadioIsSleeping) { return; } /* drive CSn low to initiate wakeup */ MRFI_SPI_DRIVE_CSN_LOW(); /* wait for MISO to go high indicating the oscillator is stable */ while (MRFI_SPI_SO_IS_HIGH()); /* wakeup is complete, drive CSn high and continue */ MRFI_SPI_DRIVE_CSN_HIGH(); /* * The test registers must be restored after sleep for the CC1100 and CC2500 radios. * This is not required for the CC1101 radio. */ #ifndef MRFI_CC1101 mrfiSpiWriteReg( MRFI_CC2500_SPI_REG_TEST2, SMARTRF_SETTING_TEST2 ); mrfiSpiWriteReg( MRFI_CC2500_SPI_REG_TEST1, SMARTRF_SETTING_TEST1 ); mrfiSpiWriteReg( MRFI_CC2500_SPI_REG_TEST0, SMARTRF_SETTING_TEST0 ); #endif /* clear any residual SYNC pin interrupt and then re-enable SYNC pin interrupts */ MRFI_CLEAR_SYNC_PIN_INT_FLAG(); MRFI_ENABLE_SYNC_PIN_INT(); /* clear sleep flag and enter receive mode */ mrfiRadioIsSleeping = 0; mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SRX); }
void radioISR(void) { unsigned int coreIntSource = RF1AIV; // Radio Core interrupt register // Radio Core interrupt if(coreIntSource) { // Check for SYNC interrupt if(coreIntSource == RF1AIV_RFIFG9) { if(MRFI_SYNC_PIN_INT_IS_ENABLED()) { static CCPACKET ccPacket; /* clear the sync pin interrupt, run sync pin ISR */ /* * NOTE! The following macro clears the interrupt flag but it also *must* * reset the interrupt capture. In other words, if a second interrupt * occurs after the flag is cleared it must be processed, i.e. this interrupt * exits then immediately starts again. Most microcontrollers handle this * naturally but it must be verified for every target. */ MRFI_CLEAR_SYNC_PIN_INT_FLAG(); MRFI_DISABLE_SYNC_PIN_INT(); // Any packet waiting to be read? if (panstamp.radio.receiveData(&ccPacket) > 0) { // Is CRC OK? if (ccPacket.crc_ok) { if (panstamp.ccPacketReceived != NULL) panstamp.ccPacketReceived(&ccPacket); } MRFI_ENABLE_SYNC_PIN_INT(); } } } // Check for RF_RDY (Event1 WOR) interrupt else if(coreIntSource == RF1AIV_RFIFG14) { RF1AIE |= BIT9 + BIT1; RF1AIFG &= ~(BIT9 + BIT1); RF1AIES |= BIT9; // Falling edge of RFIFG9 panstamp.radio.setRxState(); __bic_SR_register_on_exit(LPM3_bits); } } }
/** * rxOn * * Enable RF reception */ void PANSTAMP::rxOn(void) { MRFI_ENABLE_SYNC_PIN_INT(); }
/************************************************************************************************** * @fn MRFI_Transmit * * @brief Transmit a packet using CCA algorithm. * * @param pPacket - pointer to packet to transmit * * @return Return code indicates success or failure of transmit: * MRFI_TRANSMIT_SUCCESS - transmit succeeded * MRFI_TRANSMIT_CCA_FAILED - transmit failed because of CCA check(s) * MRFI_TRANSMIT_RADIO_ASLEEP - transmit failed because radio was asleep ************************************************************************************************** */ uint8_t MRFI_Transmit(mrfiPacket_t * pPacket) { uint8_t ccaRetries; uint8_t txBufLen; uint8_t savedSyncIntState; uint8_t returnValue; /* abort transmit if radio is asleep */ { bspIState_t s; /* critical section necessary for watertight testing and setting of state variables */ BSP_ENTER_CRITICAL_SECTION(s); /* if radio is asleep, abort transmit and return reason for failure */ if (mrfiRadioIsSleeping) { BSP_EXIT_CRITICAL_SECTION(s); return( MRFI_TRANSMIT_RADIO_ASLEEP ); } /* radio is not asleep, set flag that indicates transmit is active */ mrfiTxActive = 1; BSP_EXIT_CRITICAL_SECTION(s); } /* set number of CCA retries */ ccaRetries = MRFI_CCA_RETRIES; /* compute number of bytes to write to transmit FIFO */ txBufLen = pPacket->frame[MRFI_LENGTH_FIELD_OFS] + MRFI_LENGTH_FIELD_SIZE; /* write packet to transmit FIFO */ mrfiSpiWriteTxFifo(&(pPacket->frame[0]), txBufLen); /* =============================================================================== * Main Loop * ============= */ for (;;) { /* CCA delay */ MRFI_DELAY(2000); /* disable sync pin interrupts, necessary because both transmit and receive affect sync signal */ MRFI_DISABLE_SYNC_PIN_INT(); /* store the sync pin interrupt flag, important so original state can be restored */ savedSyncIntState = MRFI_SYNC_PIN_INT_FLAG_IS_SET(); /* * Clear the PA_PD pin interrupt flag. This flag, not the interrupt itself, * is used to capture the transition that indicates a transmit was started. * The pin level cannot be used to indicate transmit success as timing may * prevent the transition from being detected. The interrupt latch captures * the event regardless of timing. */ MRFI_CLEAR_PAPD_PIN_INT_FLAG(); /* send strobe to initiate transmit */ mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_STX); /* delay long enough for the PA_PD signal to indicate a successful transmit */ MRFI_DELAY(250); /* if the interrupt flag of the PA_PD pin is set, CCA passed and the transmit has started */ if (MRFI_PAPD_INT_FLAG_IS_SET()) { /* ------------------------------------------------------------------ * Clear Channel Assessment passed. * ---------------------------------- */ /* wait for transmit to complete */ while (!MRFI_PAPD_PIN_IS_HIGH()); /* * Restore the original sync interrupt state. The successful transmit just * caused a transition on the sync signal that set the flag (if not already * set). To restore the original state, the flag is simply cleared if it * was clear earlier. */ if (!savedSyncIntState) { MRFI_CLEAR_SYNC_PIN_INT_FLAG(); } /* transmit complete, enable sync pin interrupts */ MRFI_ENABLE_SYNC_PIN_INT(); /* set return value for successful transmit and break */ returnValue = MRFI_TRANSMIT_SUCCESS; break; } /* ------------------------------------------------------------------ * Clear Channel Assessment failed. * ---------------------------------- */ /* CCA failed, safe to enable sync pin interrupts */ MRFI_ENABLE_SYNC_PIN_INT(); /* if no CCA retries are left, transmit failed so abort */ if (ccaRetries == 0) { bspIState_t s; /* * Flush the transmit FIFO. It must be flushed so that * the next transmit can start with a clean slate. * Critical section prevents receive interrupt from * occurring in the middle of clean-up. */ BSP_ENTER_CRITICAL_SECTION(s); mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SIDLE); mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SFTX); mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SRX); BSP_EXIT_CRITICAL_SECTION(s); /* set return value for failed transmit and break */ returnValue = MRFI_TRANSMIT_CCA_FAILED; break; } /* decrement CCA retries before loop continues */ ccaRetries--; } /* * =============================================================================== */ mrfiTxActive = 0; return( returnValue ); }
/************************************************************************************************** * @fn MRFI_Init * * @brief Initialize MRFI. * * @param none * * @return none ************************************************************************************************** */ void MRFI_Init(void) { /* ------------------------------------------------------------------ * Initialization * ----------------- */ /* initialize radio state variables */ mrfiRxFilterEnabled = 0; mrfiRadioIsSleeping = 0; mrfiTxActive = 0; mrfiRxActive = 0; /* initialize GPIO pins */ MRFI_CONFIG_GDO0_PIN_AS_INPUT(); MRFI_CONFIG_GDO2_PIN_AS_INPUT(); /* initialize SPI */ mrfiSpiInit(); /* ------------------------------------------------------------------ * Radio power-up reset * ---------------------- */ MRFI_ASSERT(MRFI_SPI_CSN_IS_HIGH()); /* pulse CSn low then high */ MRFI_SPI_DRIVE_CSN_LOW(); MRFI_DELAY(10); MRFI_SPI_DRIVE_CSN_HIGH(); /* hold CSn high for at least 40 microseconds */ MRFI_DELAY(100); /* pull CSn low and wait for SO to go low */ MRFI_SPI_DRIVE_CSN_LOW(); while (MRFI_SPI_SO_IS_HIGH()); /* directly send strobe command - cannot use function as it affects CSn pin */ MRFI_SPI_WRITE_BYTE(MRFI_CC2500_SPI_STROBE_SRES); MRFI_SPI_WAIT_DONE(); /* wait for SO to go low again, reset is complete at that point */ while (MRFI_SPI_SO_IS_HIGH()); /* return CSn pin to its default high level */ MRFI_SPI_DRIVE_CSN_HIGH(); /* ------------------------------------------------------------------ * Run-time integrity checks * --------------------------- */ /* verify that SPI is working */ #ifdef MRFI_ASSERTS_ARE_ON #define TEST_VALUE 0xA5 mrfiSpiWriteReg( MRFI_CC2500_SPI_REG_PKTLEN, TEST_VALUE ); MRFI_ASSERT( mrfiSpiReadReg( MRFI_CC2500_SPI_REG_PKTLEN ) == TEST_VALUE ); /* SPI is not responding */ #endif /* verify the correct radio is installed */ MRFI_ASSERT( mrfiSpiReadReg( MRFI_CC2500_SPI_REG_PARTNUM ) == MRFI_RADIO_PARTNUM); /* incorrect radio specified */ MRFI_ASSERT( mrfiSpiReadReg( MRFI_CC2500_SPI_REG_VERSION ) >= MRFI_RADIO_MIN_VERSION); /* obsolete radio specified */ /* ------------------------------------------------------------------ * Configure radio * ----------------- */ /* initialize radio registers */ { uint8_t i; for (i=0; i<(sizeof(mrfiRadioCfg)/sizeof(mrfiRadioCfg[0])); i++) { mrfiSpiWriteReg(mrfiRadioCfg[i][0], mrfiRadioCfg[i][1]); } } /* send strobe to turn on receiver */ mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SRX); /* ------------------------------------------------------------------ * Configure interrupts * ---------------------- */ /* * Configure and enable the SYNC signal interrupt. * * This interrupt is used to indicate receive. The SYNC signal goes * high when a receive OR a transmit begins. It goes high once the * sync word is received or transmitted and then goes low again once * the packet completes. */ MRFI_CONFIG_SYNC_PIN_FALLING_EDGE_INT(); MRFI_CLEAR_SYNC_PIN_INT_FLAG(); MRFI_ENABLE_SYNC_PIN_INT(); /* configure PA_PD signal interrupt */ MRFI_CONFIG_PAPD_FALLING_EDGE_INT(); /* enable global interrupts */ BSP_ENABLE_INTERRUPTS(); }