/** **************************************************************************************** * @brief Check if tx is ongoing * @return uart tx/rx status * @param[in] UART QN_UART0 or QN_UART1 * @description * This function is used to check UART TX status ***************************************************************************************** */ int uart_check_tx_free(QN_UART_TypeDef *UART) { #if UART_TX_DMA_EN==TRUE // check DMA status if (dma_dma_GetIntStatus(QN_DMA) & DMA_MASK_BUSY) return UART_TX_BUF_BUSY; #else #if CONFIG_ENABLE_DRIVER_UART0==TRUE if(UART == QN_UART0) { // check tx buffer if (uart0_env.tx.size > 0) return UART_TX_BUF_BUSY; } #endif #if CONFIG_ENABLE_DRIVER_UART1==TRUE if(UART == QN_UART1) { // check tx buffer if(uart1_env.tx.size > 0) return UART_TX_BUF_BUSY; } #endif #endif // check tx busy if(uart_uart_GetIntFlag(UART) & UART_MASK_TX_BUSY) return UART_LAST_BYTE_ONGOING; return UART_TX_FREE; }
/** **************************************************************************************** * @brief Proprietary mode receive * @param[in] ble_ch_idx Channel frequency index * Get this parameter from rf_freq_tab[](in file qnrf.c) accroding to the frequency * chosen * @param[in] aa_buf Access address buffer, own device address * @param[in] aa_num Access address length * @param[in] data_buf Receive data buffer * @param[in] data_len Receive data length * @param[in] tx_callback Called after receive complete ***************************************************************************************** */ void prop_mode_rx(uint32_t ble_ch_idx, uint8_t *aa_buf, enum PROP_AA_NUM aa_num, uint8_t *data_buf, uint16_t data_len) { /* Wait for last transfer complete */ while(dp_dp_GetReg(0x38)& DP_MASK_TX_BUSY); /* Channel configure */ rf_set_freq(RF_RX_IMR0, ble_ch_idx); /* Access Address and Payload length, Note: Payload length in bit */ dp_dp_SetRegWithMask(0x00, DP_MASK_RX_PDU_LEN_IN, data_len << 3); dp_dp_SetRegWithMask(0x04, (DP_MASK_PROP_AA_NUM | DP_MASK_PROP_AA_ADDR_IN), (aa_num << DP_POS_PROP_AA_NUM) | (aa_buf[4])); dp_dp_SetReg(0x08, *(uint32_t *)aa_buf); /* Enable transmit request */ dp_dp_SetRegWithMask(0x00, DP_MASK_RX_REQ, 0); dp_dp_SetRegWithMask(0x00, DP_MASK_RX_REQ, DP_MASK_RX_REQ); //Wait for ready(40us) delay(70); /* Receive pack by DMA */ prop_ctrl_reset(); dma_rx(DMA_TRANS_BYTE, DMA_PROP_RX, (uint32_t)data_buf, data_len, NULL); /* Wait for transfer complete */ while(!(dma_dma_GetIntStatus(QN_DMA) & DMA_MASK_DONE)); dma_dma_ClrIntStatus(QN_DMA, DMA_MASK_DONE); }
/** **************************************************************************************** * @brief Check if tx is ongoing * @return spi tx/rx status * @param[in] SPI QN_SPI0 or QN_SPI1 * @description * This function is used to check SPI TX status ***************************************************************************************** */ int spi_check_tx_free(QN_SPI_TypeDef *SPI) { #if SPI_TX_DMA_EN==TRUE // check DMA status if (dma_dma_GetIntStatus(QN_DMA) & DMA_MASK_BUSY) return SPI_TX_BUF_BUSY; #else #if CONFIG_ENABLE_DRIVER_SPI0==TRUE if(SPI == QN_SPI0) { // check tx buffer if (spi0_env.tx.size > 0) return SPI_TX_BUF_BUSY; } #endif #if CONFIG_ENABLE_DRIVER_SPI1==TRUE if(SPI == QN_SPI1) { // check tx buffer if(spi1_env.tx.size > 0) return SPI_TX_BUF_BUSY; } #endif #endif // check tx busy if ((spi_spi_GetSR(SPI) & (SPI_MASK_BUSY|SPI_MASK_TX_FIFO_EMPT)) == SPI_MASK_TX_FIFO_EMPT) { return SPI_TX_FREE; } else { return SPI_LAST_BYTE_ONGOING; } }
/** **************************************************************************************** * @brief Check DMA status * @return DMA status * @description * This function is used to check DMA status. ***************************************************************************************** */ int dma_check_status(void) { if (dma_dma_GetIntStatus(QN_DMA) & DMA_MASK_BUSY) { return DMA_BUSY; } else { return DMA_FREE; } }
/** **************************************************************************************** * @brief Proprietary mode transmit * @param[in] ble_ch_idx Channel frequency index * Get this parameter from rf_freq_tab[](in file qnrf.c) accroding to the frequency * chosen * @param[in] aa_buf Access address buffer, destination device address * @param[in] aa_num Access address length * @param[in] data_buf Transmit data buffer * @param[in] data_len Transmit data length * @param[in] tx_callback Called after transmission complete ***************************************************************************************** */ void prop_mode_tx(uint32_t ble_ch_idx, uint8_t *aa_buf, enum PROP_AA_NUM aa_num, uint8_t *data_buf, uint16_t data_len) { uint8_t preamble_byte; uint8_t preamble_num; uint16_t i; /* Wait for last transfer complete */ while(dp_dp_GetReg(0x38) & DP_MASK_TX_BUSY); /* Channel configure */ rf_set_freq(RF_TX, ble_ch_idx); /* Access Address and Payload length, Note: Payload length in bit */ dp_dp_SetRegWithMask(0x00, DP_MASK_RX_PDU_LEN_IN, data_len << 3); dp_dp_SetRegWithMask(0x04, DP_MASK_PROP_AA_NUM, aa_num << DP_POS_PROP_AA_NUM); /* Preamble pack */ preamble_num = PROP_PREAMBLE_NUM; preamble_byte = (prop_tx_buf[0] & 0x80) ? 0xAA : 0x55; for(i = 0; i < preamble_num; i++) { prop_tx_buf[i] = preamble_byte; } /* Access Address pack */ aa_num += 2; preamble_num = PROP_PREAMBLE_NUM; for(i = 0; i < aa_num; i++) { prop_tx_buf[preamble_num+i] = aa_buf[aa_num-1-i]; } /* Payload pack */ for(i = 0; i < data_len; i++) { prop_tx_buf[preamble_num + aa_num + i] = data_buf[i]; } /* Enable transmit request */ dp_dp_SetRegWithMask(0x00, DP_MASK_TX_REQ, 0); dp_dp_SetRegWithMask(0x00, DP_MASK_TX_REQ, DP_MASK_TX_REQ); //Wait for ready(40us) delay(70); /* Transmit pack by DMA */ prop_ctrl_reset(); dma_tx(DMA_TRANS_BYTE, (uint32_t)prop_tx_buf, DMA_PROP_TX, (preamble_num + aa_num + data_len), NULL); /* Wait for transfer complete */ while(!(dma_dma_GetIntStatus(QN_DMA) & DMA_MASK_DONE)); dma_dma_ClrIntStatus(QN_DMA, DMA_MASK_DONE); /* Wait for complete */ while(dp_dp_GetReg(0x38) & DP_MASK_TX_BUSY); }
/** **************************************************************************************** * @brief DMA interrupt handler **************************************************************************************** */ void DMA_IRQHandler(void) { uint32_t reg; dev_allow_sleep(PM_MASK_DMA_ACTIVE_BIT); reg = dma_dma_GetIntStatus(QN_DMA); if (reg & DMA_MASK_DONE) { /* clear interrupt flag */ dma_dma_ClrIntStatus(QN_DMA, DMA_MASK_DONE); #if DMA_CALLBACK_EN==TRUE // Call end of Transfer callback if (dma_env.callback != NULL) { dma_env.callback(); } #endif } else if (reg & DMA_MASK_ERRO) { /* clear interrupt flag */ dma_dma_ClrIntStatus(QN_DMA, DMA_MASK_ERRO); } }
/** **************************************************************************************** * @brief Initialize DMA controller * @description * This function is used to clear callback pointer and enable DMA NVIC IRQ. **************************************************************************************** */ void dma_init(void) { uint32_t reg; #if DMA_CALLBACK_EN==TRUE dma_env.callback = NULL; #endif dma_clock_on(); dma_reset(); /* Wait until current DMA complete */ while (dma_dma_GetIntStatus(QN_DMA) & DMA_MASK_BUSY); #if CONFIG_DMA_ENABLE_INTERRUPT==TRUE reg = DMA_MASK_DONE_IE /* dma done interrupt enable */ | DMA_MASK_ERROR_IE /* dma error interrupt enable */ | DMA_MASK_INT_EN /* enable dma int */ ; dma_dma_SetCR(QN_DMA, reg); /* Enable the DMA Interrupt */ NVIC_EnableIRQ(DMA_IRQn); #endif }