/** ****************************************************************************** * @file spirit1.c * @author System LAB * @version V1.0.0 * @date 17-June-2015 * @brief Source file for SPIRIT1 ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2014 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "spirit1.h" #include "spirit1-arch.h" #include "stm32l1xx.h" #include "contiki.h" #include "net/mac/frame802154.h" #include "net/netstack.h" #include "net/packetbuf.h" #include "net/rime/rimestats.h" #include "spirit1-arch.h" #include extern SpiritIrqs xIrqStatus; extern volatile FlagStatus rx_timeout; #define XXX_ACK_WORKAROUND 1 /*---------------------------------------------------------------------------*/ #define DEBUG 0 #if DEBUG #include #define PRINTF(...) printf(__VA_ARGS__) #else #define PRINTF(...) #endif #define BUSYWAIT_UNTIL(cond, max_time) \ do { \ rtimer_clock_t t0; \ t0 = RTIMER_NOW(); \ while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \ } while(0) /*---------------------------------------------------------------------------*/ #define CLEAR_TXBUF() (spirit_txbuf[0] = 0) #define CLEAR_RXBUF() (spirit_rxbuf[0] = 0) #define IS_TXBUF_EMPTY() (spirit_txbuf[0] == 0) #define IS_RXBUF_EMPTY() (spirit_rxbuf[0] == 0) #define IS_RXBUF_FULL() (spirit_rxbuf[0] != 0) /* transceiver state. */ #define ON 0 #define OFF 1 /*---------------------------------------------------------------------------*/ static volatile unsigned int spirit_on = OFF; static volatile uint8_t receiving_packet = 0; /* * The buffers which hold incoming data. * The +1 because of the first byte, * which will contain the length of the packet. */ static uint8_t spirit_rxbuf[MAX_PACKET_LEN+1]; static uint8_t spirit_txbuf[MAX_PACKET_LEN+1-SPIRIT_MAX_FIFO_LEN]; void SpiritManagementSetFrequencyBase(uint32_t lFBase); static int just_got_an_ack = 0; /* Interrupt callback just detected an ack */ #if NULLRDC_CONF_802154_AUTOACK #define ACK_LEN 3 static int wants_an_ack = 0; /* The packet sent expects an ack */ //static int just_got_an_ack = 0; /* Interrupt callback just detected an ack */ //#define ACKPRINTF printf #define ACKPRINTF(...) #endif /* NULLRDC_CONF_802154_AUTOACK */ /*---------------------------------------------------------------------------*/ static int packet_is_prepared = 0; /*---------------------------------------------------------------------------*/ PROCESS(spirit_radio_process, "SPIRIT radio driver"); /*---------------------------------------------------------------------------*/ static int spirit_radio_init(void); static int spirit_radio_prepare(const void *payload, unsigned short payload_len); static int spirit_radio_transmit(unsigned short payload_len); static int spirit_radio_send(const void *data, unsigned short len); static int spirit_radio_read(void *buf, unsigned short bufsize); static int spirit_radio_channel_clear(void); static int spirit_radio_receiving_packet(void); static int spirit_radio_pending_packet(void); static int spirit_radio_on(void); static int spirit_radio_off(void); /*---------------------------------------------------------------------------*/ const struct radio_driver spirit_radio_driver = { spirit_radio_init, spirit_radio_prepare, spirit_radio_transmit, spirit_radio_send, spirit_radio_read, spirit_radio_channel_clear, spirit_radio_receiving_packet, spirit_radio_pending_packet, spirit_radio_on, spirit_radio_off, }; /*---------------------------------------------------------------------------*/ /* convienience macro for reading the MC_STATE[1] register from Spirit1, to be used like eg if(SPIRIT1_STATUS() == SPIRIT1_STATE_READY) { } or BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, RTIMER_SECOND/1000); */ /*---------------------------------------------------------------------------*/ void spirit1_printstatus(void) { int s = SPIRIT1_STATUS(); if(s == SPIRIT1_STATE_STANDBY) { printf("spirit1: SPIRIT1_STATE_STANDBY\n"); } else if(s == SPIRIT1_STATE_READY) { printf("spirit1: SPIRIT1_STATE_READY\n"); } else if(s == SPIRIT1_STATE_TX) { printf("spirit1: SPIRIT1_STATE_TX\n"); } else if(s == SPIRIT1_STATE_RX) { printf("spirit1: SPIRIT1_STATE_RX\n"); } else { printf("spirit1: status: %d\n", s); } } /*---------------------------------------------------------------------------*/ /* Strobe a command. The rationale for this is to clean up the messy legacy code. */ static void spirit1_strobe(uint8_t s) { SpiritCmdStrobeCommand(s); } /*---------------------------------------------------------------------------*/ /** * @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"); } /*---------------------------------------------------------------------------*/ static int spirit_radio_init(void) { PRINTF("RADIO INIT IN\n"); SpiritSpiInit(); /* Configure radio shut-down (SDN) pin and activate radio */ RadioGpioInit(RADIO_GPIO_SDN, RADIO_MODE_GPIO_OUT); /* Configures the SPIRIT1 library */ SpiritRadioSetXtalFrequency(XTAL_FREQUENCY); SpiritManagementSetFrequencyBase(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 */ RADIO_GPIO_SDN_PORT->BSRR = RADIO_GPIO_SDN_PIN; HAL_GPIO_WritePin(RADIO_GPIO_SDN_PORT, RADIO_GPIO_SDN_PIN,GPIO_PIN_RESET); /* 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); /* 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); SpiritRadioSetXtalFrequency(XTAL_FREQUENCY); 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); spirit_on = OFF; CLEAR_RXBUF(); CLEAR_TXBUF(); /* Initializes the mcu pin as input, used for IRQ */ RadioGpioInit(RADIO_GPIO_IRQ, RADIO_MODE_EXTI_IN); /* Configure the radio to route the IRQ signal to its GPIO 3 */ SpiritGpioInit(&(SGpioInit){SPIRIT_GPIO_IRQ, SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP, SPIRIT_GPIO_DIG_OUT_IRQ}); process_start(&spirit_radio_process, NULL); PRINTF("Spirit1 init done\n"); return 0; } /*---------------------------------------------------------------------------*/ 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; } /* 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 */ IRQ_DISABLE(); spirit1_strobe(SPIRIT1_STROBE_FTX); SpiritPktBasicSetPayloadLength(payload_len); SpiritSpiWriteLinearFifo(payload_len, (uint8_t *)payload); IRQ_ENABLE(); PRINTF("PREPARE OUT\n"); packet_is_prepared = 1; return RADIO_TX_OK; } /*---------------------------------------------------------------------------*/ 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, 1 * RTIMER_SECOND/1000); //BUSYWAIT_UNTIL(SPIRIT1_STATUS() != SPIRIT1_STATE_TX, 4 * RTIMER_SECOND/1000); //For GFSK with high data rate BUSYWAIT_UNTIL(SPIRIT1_STATUS() != SPIRIT1_STATE_TX, 50 * RTIMER_SECOND/1000); //For FSK with low data rate /* Reset radio - needed for immediate RX of ack */ CLEAR_TXBUF(); CLEAR_RXBUF(); IRQ_DISABLE(); SpiritIrqClearStatus(); spirit1_strobe(SPIRIT1_STROBE_SABORT); BUSYWAIT_UNTIL(0, RTIMER_SECOND/2500); 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); IRQ_ENABLE(); #if XXX_ACK_WORKAROUND just_got_an_ack = 1; #endif /* XXX_ACK_WORKAROUND */ #if NULLRDC_CONF_802154_AUTOACK if (wants_an_ack) { rtimer_txdone = RTIMER_NOW(); BUSYWAIT_UNTIL(just_got_an_ack, 2 * 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), 2 * 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; clock_wait(1); return RADIO_TX_OK; } /*---------------------------------------------------------------------------*/ static int spirit_radio_send(const void *payload, unsigned short payload_len) { if(spirit_radio_prepare(payload, payload_len) == RADIO_TX_ERR) { return RADIO_TX_ERR; } return spirit_radio_transmit(payload_len); } /*---------------------------------------------------------------------------*/ static int spirit_radio_read(void *buf, unsigned short bufsize) { PRINTF("READ IN\n"); /* Checks if the RX buffer is empty */ if(IS_RXBUF_EMPTY()) { IRQ_DISABLE(); CLEAR_RXBUF(); spirit1_strobe(SPIRIT1_STROBE_SABORT); BUSYWAIT_UNTIL(0, RTIMER_SECOND/2500); 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); PRINTF("READ OUT RX BUF EMPTY\n"); IRQ_ENABLE(); return 0; } if(bufsize < spirit_rxbuf[0]) { /* If buf has the correct size */ PRINTF("TOO SMALL BUF\n"); return 0; } else { /* Copies the packet received */ memcpy(buf, spirit_rxbuf + 1, spirit_rxbuf[0]); bufsize = spirit_rxbuf[0]; CLEAR_RXBUF(); PRINTF("READ OUT\n"); return bufsize; } } /*---------------------------------------------------------------------------*/ 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_valueoff\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; } /*---------------------------------------------------------------------------*/ static int spirit_radio_on(void) { PRINTF("Spirit1: on\n"); spirit1_strobe(SPIRIT1_STROBE_SABORT); BUSYWAIT_UNTIL(0, RTIMER_SECOND/2500); 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"); while(1); //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"); while(1); //return 1; } /* Enables the mcu to get IRQ from the SPIRIT1 */ IRQ_ENABLE(); spirit_on = ON; } return 0; } /*---------------------------------------------------------------------------*/ static int interrupt_callback_in_progress = 0; static int interrupt_callback_wants_poll = 0; 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 && linkaddr_cmp((linkaddr_t *)&info154.dest_addr, &linkaddr_node_addr)) { #if !XXX_ACK_WORKAROUND /* Send an ACK packet */ uint8_t ack_frame[ACK_LEN] = { FRAME802154_ACKFRAME, 0x00, info154.seq }; IRQ_DISABLE(); spirit1_strobe(SPIRIT1_STROBE_FTX); SpiritPktBasicSetPayloadLength((uint16_t) ACK_LEN); SpiritSpiWriteLinearFifo((uint16_t) ACK_LEN, (uint8_t *) ack_frame); SpiritSetReadyState(); IRQ_ENABLE(); 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 /* !XXX_ACK_WORKAROUND */ } } #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(); } /*---------------------------------------------------------------------------*/ 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) { /* RX command - to ensure the device will be ready for the next reception */ if(xIrqStatus.IRQ_RX_TIMEOUT) { SpiritCmdStrobeFlushRxFifo(); rx_timeout = SET; } } interrupt_callback_in_progress = 0; } /*---------------------------------------------------------------------------*/