/** ***************************************(C) COPYRIGHT 2018 DJI*************************************** * @file bsp_uart.c * @brief this file contains rc data receive and processing function * @note * @Version V1.0.0 * @Date Jan-30-2018 ***************************************(C) COPYRIGHT 2018 DJI*************************************** */ #include "string.h" #include "stdlib.h" #include "bsp_uart.h" #include "usart.h" #include "main.h" #include "oled.h" uint8_t dbus_buf[DBUS_BUFLEN]; RC_ctrl_t rc_ctrl; /** * @brief enable global uart it and do not use DMA transfer done it * @param[in] huart: uart IRQHandler id * @param[in] pData: receive buff * @param[in] Size: buff size * @retval set success or fail */ static int uart_receive_dma_no_it(UART_HandleTypeDef* huart, uint8_t* pData, uint32_t Size) { uint32_t tmp1 = 0; tmp1 = huart->RxState; if (tmp1 == HAL_UART_STATE_READY) { if ((pData == NULL) || (Size == 0)) { return HAL_ERROR; } huart->pRxBuffPtr = pData; huart->RxXferSize = Size; huart->ErrorCode = HAL_UART_ERROR_NONE; /* Enable the DMA Stream */ HAL_DMA_Start(huart->hdmarx, (uint32_t)&huart->Instance->DR, (uint32_t)pData, Size); /* * Enable the DMA transfer for the receiver request by setting the DMAR bit * in the UART CR3 register */ SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); return HAL_OK; } else { return HAL_BUSY; } } /** * @brief returns the number of remaining data units in the current DMAy Streamx transfer. * @param[in] dma_stream: where y can be 1 or 2 to select the DMA and x can be 0 * to 7 to select the DMA Stream. * @retval The number of remaining data units in the current DMAy Streamx transfer. */ uint16_t dma_current_data_counter(DMA_Stream_TypeDef *dma_stream) { /* Return the number of remaining data units for DMAy Streamx */ return ((uint16_t)(dma_stream->NDTR)); } /** * @brief handle received rc data * @param[out] rc: structure to save handled rc data * @param[in] buff: the buff which saved raw rc data * @retval */ void rc_callback_handler(RC_ctrl_t *rc_ctrl, uint8_t *buff) { rc_ctrl->rc.ch[3] = (buff[0] | buff[1] << 8) & 0x07FF; //0x07FF met la commande sur 11 bits (donc 2048 max) rc_ctrl->rc.ch[3] -= 1024; //on centre sur 0 rc_ctrl->rc.ch[2] = (buff[1] >> 3 | buff[2] << 5) & 0x07FF; rc_ctrl->rc.ch[2] -= 1024; rc_ctrl->rc.ch[1] = (buff[2] >> 6 | buff[3] << 2 | buff[4] << 10) & 0x07FF; rc_ctrl->rc.ch[1] -= 1024; rc_ctrl->rc.ch[0] = (buff[4] >> 1 | buff[5] << 7) & 0x07FF; rc_ctrl->rc.ch[0] -= 1024; rc_ctrl->rc.sw[0] = ((buff[5] >> 4) & 0x000C) >> 2; //!< Switch right rc_ctrl->rc.sw[1] = (buff[5] >> 4) & 0x0003; //!< Switch left rc_ctrl->mouse.x = buff[6] | (buff[7] << 8); //!< Mouse X axis rc_ctrl->mouse.y = buff[8] | (buff[9] << 8); //!< Mouse Y axis rc_ctrl->mouse.z = buff[10] | (buff[11] << 8); //!< Mouse Z axis rc_ctrl->mouse.press_l = buff[12]; //!< Mouse Left Is Press ? rc_ctrl->mouse.press_r = buff[13]; //!< Mouse Right Is Press ? rc_ctrl->key.v = buff[14] | (buff[15] << 8); //!< KeyBoard value rc_ctrl->rc.ch[4] = buff[16] | (buff[17] << 8); //!< Left Dial rc_ctrl->rc.ch[4] -= 1024; if ((abs(rc_ctrl->rc.ch[0]) > 660) || \ (abs(rc_ctrl->rc.ch[1]) > 660) || \ (abs(rc_ctrl->rc.ch[2]) > 660) || \ (abs(rc_ctrl->rc.ch[3]) > 660)) { memset(&rc_ctrl->rc, 0, sizeof(rc_ctrl->rc)); } } /** * @brief clear idle it flag after uart receive a frame data * @param[in] huart: uart IRQHandler id * @retval */ static void uart_rx_idle_callback(UART_HandleTypeDef* huart) { /* clear idle it flag avoid idle interrupt all the time */ __HAL_UART_CLEAR_IDLEFLAG(huart); /* handle received data in idle interrupt */ if (huart == &DBUS_HUART) { /* clear DMA transfer complete flag */ __HAL_DMA_DISABLE(huart->hdmarx); /* handle dbus data dbus_buf from DMA */ if ((DBUS_MAX_LEN - dma_current_data_counter(huart->hdmarx->Instance)) == DBUS_BUFLEN) { rc_callback_handler(&rc_ctrl, dbus_buf); } /* restart dma transmission */ __HAL_DMA_SET_COUNTER(huart->hdmarx, DBUS_MAX_LEN); __HAL_DMA_ENABLE(huart->hdmarx); } } /** * @brief callback this function when uart interrupt * @param[in] huart: uart IRQHandler id * @retval */ void uart_receive_handler(UART_HandleTypeDef *huart) { if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE)) { uart_rx_idle_callback(huart); } } /** * @brief initialize dbus uart device * @param * @retval */ void dbus_uart_init(void) { /* open uart idle it */ __HAL_UART_CLEAR_IDLEFLAG(&DBUS_HUART); __HAL_UART_ENABLE_IT(&DBUS_HUART, UART_IT_IDLE); uart_receive_dma_no_it(&DBUS_HUART, dbus_buf, DBUS_MAX_LEN); }