180718 HJM : 8 Count sensing data RF send, certTest, temp(cold)Test
Fork of EV-COG-AD3029LZ by
Diff: source/SimpleSpirit1.cpp
- Revision:
- 83:54b207156a91
- Parent:
- 82:a18c22d2b83a
- Child:
- 84:45b9ff78a066
diff -r a18c22d2b83a -r 54b207156a91 source/SimpleSpirit1.cpp --- a/source/SimpleSpirit1.cpp Fri Feb 02 14:13:24 2018 +0100 +++ b/source/SimpleSpirit1.cpp Wed Mar 21 05:06:08 2018 +0000 @@ -1,8 +1,10 @@ /*** Mbed Includes ***/ #include "SimpleSpirit1.h" #include "radio_spi.h" +//#include "main.h" -#define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_3) +//#define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_0) +#define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_2) static uint16_t last_state; #define SPIRIT1_STATUS() ((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS) @@ -46,52 +48,76 @@ /** Init Function **/ void SimpleSpirit1::init() { - /* reset irq disable counter and irq callback & disable irq */ - _nr_of_irq_disables = 0; + /*cubebite HJM, reset irq disable counter and irq callback & disable irq */ + _nr_of_irq_disables = 0; // @@ disable_spirit_irq(); - /* unselect chip */ + /*cubebite HJM, unselect chip */ chip_unselect(); - /* configure spi */ + /*cubebite HJM, configure spi */ _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */ - _spi.frequency(10000000); // 10MHz (i.e. max speed allowed for Spirit1) + - /* install irq handler */ +// _spi.frequency(13000000); // 13MHz (i.e. max speed allowed for Spirit1) +// _spi.frequency(6500000); // 6.5MHz (i.e. max speed allowed for Spirit1) +// _spi.frequency(4333333); // 4.3333...MHz (i.e. max speed allowed for Spirit1) +// _spi.frequency(2600000); // 4.3333...MHz (i.e. max speed allowed for Spirit1) +// _spi.frequency(1444444); // 4.3333...MHz (i.e. max speed allowed for Spirit1) +// _spi.frequency(764705); // 4.3333...MHz (i.e. max speed allowed for Spirit1) + _spi.frequency(393939); // 4.3333...MHz (i.e. max speed allowed for Spirit1) + + + + /*cubebite HJM, install irq handler */ _irq.mode(PullUp); _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler)); - /* init cube vars */ + printf("test 4 \n"); + /*cubebite HJM, init cube vars */ spirit_on = OFF; last_rssi = 0 ; //MGR last_sqi = 0 ; //MGR - /* set frequencies */ - radio_set_xtal_freq(XTAL_FREQUENCY); - mgmt_set_freq_base((uint32_t)BASE_FREQUENCY); + printf("test 5 \n"); + /*cubebite HJM, set frequencies */ + radio_set_xtal_freq(XTAL_FREQUENCY); //cubebite HJM, 50MHz + mgmt_set_freq_base((uint32_t)BASE_FREQUENCY); // @@ - /* restart board */ - enter_shutdown(); - exit_shutdown(); + printf("test 6 \n"); + /*cubebite HJM , restart board */ + enter_shutdown(); + exit_shutdown(); - /* soft core reset */ + printf("test 7 \n"); + /*cubebite HJM, soft core reset */ cmd_strobe(SPIRIT1_STROBE_SRES); - /* Configures the SPIRIT1 radio part */ - SRadioInit x_radio_init = { - XTAL_OFFSET_PPM, - (uint32_t)BASE_FREQUENCY, - (uint32_t)CHANNEL_SPACE, - CHANNEL_NUMBER, - MODULATION_SELECT, - DATARATE, - (uint32_t)FREQ_DEVIATION, - (uint32_t)BANDWIDTH - }; - radio_init(&x_radio_init); - radio_set_pa_level_dbm(0,POWER_DBM); + printf("test 8 \n"); + /*cubebite HJM, Configures the SPIRIT1 radio part */ + //180119 HJM : 433MHz 설정으로 변경 후 테스트. + SRadioInit x_radio_init = { + XTAL_OFFSET_PPM, // Xtal offset in ppm + (uint32_t)BASE_FREQUENCY, // HJM 수정 후 테스트 중 base frequency + (uint32_t)CHANNEL_SPACE, // channel space + CHANNEL_NUMBER, // channel number, HJM : 뭐지 0 인줄 알았더니 1로 셋팅되어있네/ + MODULATION_SELECT, // modulation select + DATARATE, // HJM 수정 후 테스트 중 + (uint32_t)FREQ_DEVIATION, // frequency deviation + (uint32_t)BANDWIDTH // channel filter bandwidth + }; + + printf("test 9 \n"); + uint8_t ui8Return; + ui8Return = radio_init(&x_radio_init); + printf("test 9, ui8Return : [%d]\n", ui8Return); + /*180117 HJM : 송신 신호 세기 */ + radio_set_pa_level_dbm(0,POWER_DBM); //hjm test +// radio_set_pa_level_dbm(0,10.0); +// radio_set_pa_level_dbm(0,CUBEBITE_OUTPUT_POWER_DBM_TEST); radio_set_pa_level_max_index(0); + printf("test 10 \n"); /* Configures the SPIRIT1 packet handler part*/ PktBasicInit x_basic_init = { PREAMBLE_LENGTH, @@ -107,6 +133,7 @@ }; pkt_basic_init(&x_basic_init); + printf("test 11 \n"); /* Enable the following interrupt sources, routed to GPIO */ irq_de_init(NULL); irq_clear_status(); @@ -121,21 +148,24 @@ irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE); #endif // !RX_FIFO_THR_WA + printf("test 12 \n"); /* Configure Spirit1 */ radio_persistent_rx(S_ENABLE); qi_set_sqi_threshold(SQI_TH_0); qi_sqi_check(S_ENABLE); - qi_set_rssi_threshold_dbm(CCA_THRESHOLD); + qi_set_rssi_threshold_dbm(CCA_THRESHOLD); //180205 HJM : RRSI 셋팅 값 수정 테스트 timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD); timer_set_infinite_rx_timeout(); radio_afc_freeze_on_sync(S_ENABLE); calibration_rco(S_ENABLE); + spirit_on = OFF; CLEAR_TXBUF(); CLEAR_RXBUF(); _spirit_tx_started = false; _is_receiving = false; + printf("test 13 \n"); /* Configure the radio to route the IRQ signal to its GPIO 3 */ SGpioInit x_gpio_init = { SPIRIT_GPIO_IRQ, @@ -144,6 +174,7 @@ }; spirit_gpio_init(&x_gpio_init); + printf("test 14 \n"); /* Setup CSMA/CA */ CsmaInit x_csma_init = { S_ENABLE, // enable persistent mode @@ -155,46 +186,69 @@ }; csma_ca_init(&x_csma_init); + printf("test 15 \n"); #ifdef USE_STANDBY_STATE /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */ cmd_strobe(SPIRIT1_STROBE_STANDBY); #endif // USE_STANDBY_STATE } + + + + static volatile int tx_fifo_remaining = 0; // to be used in irq handler static volatile int tx_buffer_pos = 0; // to be used in irq handler static const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler -int SimpleSpirit1::send(const void *payload, unsigned int payload_len, bool use_csma_ca) { +int SimpleSpirit1::send(const void *payload, unsigned int payload_len, bool use_csma_ca) +{ /* Checks if the payload length is supported */ - if(payload_len > MAX_PACKET_LEN) { + printf("\r\n[SEND] 1, MAX_PACKET_LEN : [%d]\n", MAX_PACKET_LEN); + printf("[SEND] 2, payload_len : [%d]\n", payload_len); + + if(payload_len > MAX_PACKET_LEN) + { +// printf("[SEND] \n"); return RADIO_TX_ERR; } - + disable_spirit_irq(); BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); #ifndef NDEBUG - if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { + if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) + { debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); } #endif + + + + /* Reset State to Ready */ + printf("[SEND] 3, set_ready_state() call, \n"); set_ready_state(); + - cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer + printf("[SEND] 4, cmd_strobe() call, SPIRIT1_STROBE_FTX \n"); + cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer #ifndef NDEBUG debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); #endif - pkt_basic_set_payload_length(payload_len); // set desired payload len + printf("[SEND] 5, pkt_basic_set_payload_length() call, \n"); + pkt_basic_set_payload_length(payload_len); // set desired payload len - if(use_csma_ca) { + if(use_csma_ca) + { + printf("[SEND] 6, csma_ca_state() call, \n"); csma_ca_state(S_ENABLE); // enable CSMA/CA } /* Init buffer & number of bytes to be send */ + printf("[SEND] 7, csma_ca_state() call, \n"); tx_fifo_remaining = payload_len; tx_fifo_buffer = (const uint8_t*)payload; @@ -203,18 +257,21 @@ tx_fifo_remaining -= to_send; - /* Fill FIFO Buffer */ - if(to_send > 0) { - spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]); + /* Fill FIFO Buffer */ + if(to_send > 0) + { + printf("[SEND] 8, if(to_send > 0), if(to_send > 0) \n"); + spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]); } tx_buffer_pos = to_send; _spirit_tx_started = true; enable_spirit_irq(); + printf(" 6"); /* Start transmitting */ - cmd_strobe(SPIRIT1_STROBE_TX); + cmd_strobe(SPIRIT1_STROBE_TX); while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler) @@ -223,25 +280,35 @@ debug("\r\n%s (%d): state=%x, _spirit_tx_started=%d\r\n", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started); #endif - if(use_csma_ca) { + if(use_csma_ca) + { csma_ca_state(S_DISABLE); // disable CSMA/CA } - cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state + cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state + - disable_spirit_irq(); - if(_spirit_tx_started) { // in case of state timeout + disable_spirit_irq(); + if(_spirit_tx_started) + { // in case of state timeout _spirit_tx_started = false; - enable_spirit_irq(); + enable_spirit_irq(); + printf("[SEND] 8, if(_spirit_tx_started), in case of state timeout, return RADIO_TX_ERR \n"); + return RADIO_TX_ERR; - } else { - enable_spirit_irq(); + } + else + { + enable_spirit_irq(); + printf("[SEND] 8, else, in case of state timeout, return RADIO_TX_OK \n"); + return RADIO_TX_OK; } } /** Set Ready State **/ -void SimpleSpirit1::set_ready_state(void) { +void SimpleSpirit1::set_ready_state(void) +{ uint16_t state; disable_spirit_irq(); @@ -255,18 +322,27 @@ CLEAR_TXBUF(); state = SPIRIT1_STATUS(); - if(state == SPIRIT1_STATE_STANDBY) { + if(state == SPIRIT1_STATE_STANDBY) + { + printf("[SEND] 3-1, set_ready_state() call, if(state == SPIRIT1_STATE_STANDBY) in \n"); cmd_strobe(SPIRIT1_STROBE_READY); - } else if(state == SPIRIT1_STATE_RX) { + } + else if(state == SPIRIT1_STATE_RX) + { + printf("[SEND] 3-2, set_ready_state() call, if(state == SPIRIT1_STATE_RX) in \n"); cmd_strobe(SPIRIT1_STROBE_SABORT); - } else if(state != SPIRIT1_STATE_READY) { + } + else if(state != SPIRIT1_STATE_READY) + { #ifndef NDEBUG debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, state>>1); #endif + printf("[SEND] 3-3, set_ready_state() call, else if(state != SPIRIT1_STATE_READY) in, something is wrong. \n"); } BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT); - if(last_state != (SPIRIT1_STATE_READY | XO_ON)) { + if(last_state != (SPIRIT1_STATE_READY | XO_ON)) + { error("\r\nSpirit1: failed to become ready (%x) => pls. reset!\r\n", last_state); enable_spirit_irq(); return; @@ -277,8 +353,10 @@ enable_spirit_irq(); } -int SimpleSpirit1::off(void) { - if(spirit_on == ON) { +int SimpleSpirit1::off(void) +{ + if(spirit_on == ON) + { /* Disables the mcu to get IRQ from the SPIRIT1 */ disable_spirit_irq(); @@ -301,8 +379,10 @@ return 0; } -int SimpleSpirit1::on(void) { - if(spirit_on == OFF) { +int SimpleSpirit1::on(void) +{ + if(spirit_on == OFF) + { set_ready_state(); /* now we go to Rx */ @@ -339,14 +419,16 @@ } int SimpleSpirit1::read(void *buf, unsigned int bufsize) -{ +{ disable_spirit_irq(); + printf("read() 1 "); /* Checks if the RX buffer is empty */ if(IS_RXBUF_EMPTY()) { #ifndef NDEBUG debug("\r\nBuffer is empty\r\n"); #endif + printf("[DEBUG] 2-1"); set_ready_state(); cmd_strobe(SPIRIT1_STROBE_RX); @@ -365,19 +447,22 @@ return 0; } else { /* Copies the packet received */ + memcpy(buf, spirit_rx_buf, spirit_rx_len); - - bufsize = spirit_rx_len; + bufsize = spirit_rx_len; + printf("recv 3-1"); + CLEAR_RXBUF(); - + printf(" 3-2"); + enable_spirit_irq(); + printf(" 3-3 read ok\n"); return bufsize; } } -/* betzw - TODO: CCA should be reviewed (completely)! */ int SimpleSpirit1::channel_clear(void) { float rssi_value; @@ -407,232 +492,228 @@ enable_spirit_irq(); /* Puts the SPIRIT1 in its previous state */ - if(spirit_state == OFF) { + if(spirit_state==OFF) { off(); - #ifndef NDEBUG #ifdef USE_STANDBY_STATE if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) { - debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); - } -#else // !USE_STANDBY_STATE - if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) { - debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); - } -#endif // !USE_STANDBY_STATE -#endif // NDEBUG - } else { // spirit_state != OFF - disable_spirit_irq(); +#else + if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) { +#endif + debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); + } +#endif + } else { + disable_spirit_irq(); + + set_ready_state(); - set_ready_state(); + cmd_strobe(SPIRIT1_STROBE_RX); + BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); + if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { + error("\r\nSpirit1: (#2) failed to enter rx (%x) => retry\r\n", last_state>>1); + } - cmd_strobe(SPIRIT1_STROBE_RX); - BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); - if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { - error("\r\nSpirit1: (#2) failed to enter rx (%x) => retry\r\n", last_state>>1); + enable_spirit_irq(); + +#ifndef NDEBUG + if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { + debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); + } +#endif } - enable_spirit_irq(); + /* Checks the RSSI value with the threshold */ + if(rssi_value<CCA_THRESHOLD) { + return 0; + } else { + return 1; + } + } -#ifndef NDEBUG - if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { - debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); - } -#endif + int SimpleSpirit1::get_pending_packet(void) + { + return !IS_RXBUF_EMPTY(); } - /* If the received signal strength is above a certain level the medium is considered busy! */ - /* Compare RSSI value with threshold */ - if(rssi_value < CCA_THRESHOLD) { - return 0; // idle - } else { - return 1; // busy - } -} + /** Spirit Irq Callback **/ + /* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */ + void SimpleSpirit1::IrqHandler() { + st_lib_spirit_irqs x_irq_status; -int SimpleSpirit1::get_pending_packet(void) -{ - return !IS_RXBUF_EMPTY(); -} + /* get interrupt source from radio */ + irq_get_status(&x_irq_status); -/** Spirit Irq Callback **/ -/* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */ -void SimpleSpirit1::IrqHandler() { - st_lib_spirit_irqs x_irq_status; - - /* get interrupt source from radio */ - irq_get_status(&x_irq_status); - - /* The IRQ_TX_DATA_SENT notifies the packet has been sent. Puts the SPIRIT1 in RX */ - if(x_irq_status.IRQ_TX_DATA_SENT) { /* betzw - NOTE: MUST be handled before `IRQ_RX_DATA_READY` for Nanostack integration! + /* The IRQ_TX_DATA_SENT notifies the packet has been sent. Puts the SPIRIT1 in RX */ + if(x_irq_status.IRQ_TX_DATA_SENT) { /* betzw - NOTE: MUST be handled before `IRQ_RX_DATA_READY` for Nanostack integration! Logically, Nanostack only expects the "DONE" after "SUCCESS" (if it gets DONE before SUCCESS, it assumes you're not going to bother to send SUCCESS). - */ + */ #ifdef DEBUG_IRQ - uint32_t *tmp = (uint32_t*)&x_irq_status; - debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); - debug_if(tx_fifo_remaining != 0, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + debug_if(tx_fifo_remaining != 0, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + + if(_spirit_tx_started) { + _spirit_tx_started = false; + + /* call user callback */ + if(_current_irq_callback) { + _current_irq_callback(TX_DONE); + } + } + + /* Disable handling of other TX flags */ + x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET; + tx_fifo_buffer = NULL; + } + +#ifndef RX_FIFO_THR_WA + /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */ + if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) { +#ifdef DEBUG_IRQ + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + debug_if(tx_fifo_buffer == NULL, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); #endif - if(_spirit_tx_started) { - _spirit_tx_started = false; + int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo + int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; + + tx_fifo_remaining -= to_send; + + /* Fill FIFO Buffer */ + if(to_send > 0) { + spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]); + } + tx_buffer_pos += to_send; + } +#endif // !RX_FIFO_THR_WA + + /* TX FIFO underflow/overflow error */ + if(x_irq_status.IRQ_TX_FIFO_ERROR) { +#ifdef DEBUG_IRQ + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); + debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + if(_spirit_tx_started) { + _spirit_tx_started = false; + /* call user callback */ + if(_current_irq_callback) { + _current_irq_callback(TX_ERR); + } + } + + /* reset data still to be sent */ + tx_fifo_remaining = 0; + } - /* call user callback */ - if(_current_irq_callback) { - _current_irq_callback(TX_DONE); + /* The IRQ_RX_DATA_READY notifies a new packet arrived */ + if(x_irq_status.IRQ_RX_DATA_READY) { +#ifdef DEBUG_IRQ + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + + if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!) +#ifdef HEAVY_DEBUG + debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); +#endif + } else { + _is_receiving = false; // Finished receiving + stop_rx_timeout(); + + spirit_rx_len = pkt_basic_get_received_pkt_length(); + +#ifdef DEBUG_IRQ + debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); +#endif + + if(spirit_rx_len <= MAX_PACKET_LEN) { + uint8_t to_receive = spirit_rx_len - _spirit_rx_pos; + if(to_receive > 0) { + spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]); + _spirit_rx_pos += to_receive; + } + } + + cmd_strobe(SPIRIT1_STROBE_FRX); + + last_rssi = qi_get_rssi(); //MGR + last_sqi = qi_get_sqi(); //MGR + + /* call user callback */ + if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) { + _current_irq_callback(RX_DONE); + } + + /* Disable handling of other RX flags */ + x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET; } } - /* Disable handling of other TX flags */ - x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET; - tx_fifo_buffer = NULL; - } - #ifndef RX_FIFO_THR_WA - /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */ - if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) { + /* RX FIFO almost full */ + if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) { +#ifdef DEBUG_IRQ + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + if(!_is_receiving) { // spurious irq?!? #ifdef DEBUG_IRQ - uint32_t *tmp = (uint32_t*)&x_irq_status; - debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); - debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); - debug_if(tx_fifo_buffer == NULL, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); #endif - - int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo - int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; - - tx_fifo_remaining -= to_send; - - /* Fill FIFO Buffer */ - if(to_send > 0) { - spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]); + } else { + uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo(); + if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) { + spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]); + _spirit_rx_pos += fifo_available; + } else { +#ifdef DEBUG_IRQ + debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); +#endif + } + } } - tx_buffer_pos += to_send; - } #endif // !RX_FIFO_THR_WA - /* TX FIFO underflow/overflow error */ - if(x_irq_status.IRQ_TX_FIFO_ERROR) { + /* Reception errors */ + if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) { #ifdef DEBUG_IRQ - uint32_t *tmp = (uint32_t*)&x_irq_status; - debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); - debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); + debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); #endif - if(_spirit_tx_started) { - _spirit_tx_started = false; - /* call user callback */ - if(_current_irq_callback) { - _current_irq_callback(TX_ERR); + rx_timeout_handler(); + if(_spirit_tx_started) { + _spirit_tx_started = false; + /* call user callback */ + if(_current_irq_callback) { + _current_irq_callback(TX_ERR); + } } } - /* reset data still to be sent */ - tx_fifo_remaining = 0; - } - - /* The IRQ_RX_DATA_READY notifies a new packet arrived */ - if(x_irq_status.IRQ_RX_DATA_READY) { + /* The IRQ_VALID_SYNC is used to notify a new packet is coming */ + if(x_irq_status.IRQ_VALID_SYNC) { #ifdef DEBUG_IRQ - uint32_t *tmp = (uint32_t*)&x_irq_status; - debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); -#endif - - if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!) -#ifdef HEAVY_DEBUG - debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); -#endif - } else { - _is_receiving = false; // Finished receiving - stop_rx_timeout(); - - spirit_rx_len = pkt_basic_get_received_pkt_length(); - -#ifdef DEBUG_IRQ - debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); #endif - - if(spirit_rx_len <= MAX_PACKET_LEN) { - uint8_t to_receive = spirit_rx_len - _spirit_rx_pos; - if(to_receive > 0) { - spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]); - _spirit_rx_pos += to_receive; - } - } - - cmd_strobe(SPIRIT1_STROBE_FRX); - - last_rssi = qi_get_rssi(); //MGR - last_sqi = qi_get_sqi(); //MGR - - /* call user callback */ - if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) { - _current_irq_callback(RX_DONE); - } - - /* Disable handling of other RX flags */ - x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET; - } - } - -#ifndef RX_FIFO_THR_WA - /* RX FIFO almost full */ - if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) { -#ifdef DEBUG_IRQ - uint32_t *tmp = (uint32_t*)&x_irq_status; - debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); -#endif - if(!_is_receiving) { // spurious irq?!? -#ifdef DEBUG_IRQ - debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); -#endif - } else { - uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo(); - if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) { - spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]); - _spirit_rx_pos += fifo_available; - } else { + /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and + * the MCU trying to send a packet, which gets resolved in favor of + * sending. + */ + if(_spirit_tx_started) { #ifdef DEBUG_IRQ debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); #endif - } - } - } -#endif // !RX_FIFO_THR_WA - - /* Reception errors */ - if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) { -#ifdef DEBUG_IRQ - uint32_t *tmp = (uint32_t*)&x_irq_status; - debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); - debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); -#endif - rx_timeout_handler(); - if(_spirit_tx_started) { - _spirit_tx_started = false; - /* call user callback */ - if(_current_irq_callback) { - _current_irq_callback(TX_ERR); + } else { + _is_receiving = true; + start_rx_timeout(); } } } - - /* The IRQ_VALID_SYNC is used to notify a new packet is coming */ - if(x_irq_status.IRQ_VALID_SYNC) { -#ifdef DEBUG_IRQ - uint32_t *tmp = (uint32_t*)&x_irq_status; - debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); -#endif - /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and - * the MCU trying to send a packet, which gets resolved in favor of - * sending. - */ - if(_spirit_tx_started) { -#ifdef DEBUG_IRQ - debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); -#endif - } else { - _is_receiving = true; - start_rx_timeout(); - } - } -}