#include "remote_controler.hpp" #include "app_protocols/ble_through/ble_proto_utils.h" using namespace iflytop; #define TAG "RemoteControler" #define MODULE_DEBUG 0 #define UART_RX_OVERTIME 200 #define CMD_OVERTIME 500 static ZQueue ackQueue; static ZQueue eventQueue; static ZThread usartRxThread; static ZThread eventProcessThread; static bool m_isWaitingForAck; static UART_HandleTypeDef* m_uart; static const char* zhex2str(uint8_t* data, size_t len) { static char buf[256]; memset(buf, 0, sizeof(buf)); for (size_t i = 0; i < len; i++) { sprintf(buf + i * 2, "%02X", data[i]); } return buf; } void RemoteControlerUpper::initialize() { ackQueue.initialize(1, sizeof(RemoteControlerReportPacket_t)); eventQueue.initialize(3, sizeof(RemoteControlerReportPacket_t)); usartRxThread.init("usartRxThread", 1024); eventProcessThread.init("eventProcessThread", 1024); ZASSERT(AppHardware::ins()->remoteContolerUart); m_uart = AppHardware::ins()->remoteContolerUart; m_cmdlock.init(); zble_proto_utils_init(kzble_master); // m_cmdlock } void RemoteControlerUpper::regOnReport(on_report_cb_t on_report) { m_cb[m_ncb] = on_report; m_ncb++; } bool RemoteControlerUpper::isConnected() { return AppHardware::ins()->BLE_CONNECTED_STATE.getState(); } void RemoteControlerUpper::callOnReport(uint8_t* rx, int32_t len) { for (int32_t i = 0; i < m_ncb; i++) { m_cb[i](rx, len); } } void RemoteControlerUpper::startSchedule() { usartRxThread.start([this]() { static uint8_t rxbuf[128]; m_uart->USR_UartITRxing = 1; m_uart->USR_UartITRxBuf = rxbuf; m_uart->USR_UartITRxBufSize = 128; m_uart->USR_UartITRxOff = 0; HAL_UART_Receive_IT(m_uart, &m_uart->USR_UartITRxBufCache, 1); while (1) { // static uint8_t processbuf[128]; static RemoteControlerReportPacket_t rxpacket; rxpacket.datalen = 0; zble_proto_packet_t* rxblepacket = (zble_proto_packet_t*)m_uart->USR_UartITRxBuf; uint8_t* rxblepacketu8 = (uint8_t*)m_uart->USR_UartITRxBuf; int curPacketlen = rxblepacket->packetlen; if (m_uart->USR_UartITRxOff != 0) { if ((m_uart->USR_UartITRxOff >= curPacketlen) && // rxblepacket->h1 == 0xAA && // rxblepacket->h2 == 0xBB && // rxblepacketu8[curPacketlen - 1] == 0xCC) { //ZLOGI(TAG, "uuuuuuuuuuuuuuuuuuuuuuuuuu"); vPortEnterCritical(); // copy data memcpy(rxpacket.data, rxblepacketu8, curPacketlen); rxpacket.datalen = curPacketlen; // move data memmove(m_uart->USR_UartITRxBuf, m_uart->USR_UartITRxBuf + curPacketlen, curPacketlen); m_uart->USR_UartITRxOff = m_uart->USR_UartITRxOff - curPacketlen; vPortExitCritical(); } else { if (zos_haspassedms(m_uart->USR_UartITLastRxTicket) > UART_RX_OVERTIME) { // drop data ZLOGI(TAG, "drop data %d %s", m_uart->USR_UartITRxOff, zhex2str(m_uart->USR_UartITRxBuf, m_uart->USR_UartITRxOff)); vPortEnterCritical(); m_uart->USR_UartITRxOff = 0; memset(rxbuf, 0, 128); vPortExitCritical(); } } } if (rxpacket.datalen != 0) { preProcessrxpacket(&rxpacket); } // ZLOGI(TAG,"."); osDelay(2); } }); /** * @brief �����ϱ���Ϣ */ eventProcessThread.start([this]() { while (1) { static RemoteControlerReportPacket_t packet; bool suc = eventQueue.receive(&packet, 10); if (suc) { processRxEventPacket(&packet); } osDelay(1); } }); } void RemoteControlerUpper::preProcessrxpacket(RemoteControlerReportPacket_t* packet) { #if MODULE_DEBUG ZLOGI(TAG, "[rx-thread] : rx :%s(%d)", zhex2str(packet->data, packet->datalen), packet->datalen); #endif zble_proto_packet_t* p_packet = (zble_proto_packet_t*)packet->data; if (!ble_through_proto_check_packet(p_packet)) { ZLOGI(TAG, "rx invalid packet %s", zhex2str(packet->data, packet->datalen)); return; } bool suc = true; if (p_packet->frameType == kzble_proto_cmd) { // suc = ackQueue.send(packet, 10); } else if (p_packet->frameType == kzble_proto_report) { suc = eventQueue.send(packet, 10); } else if (p_packet->frameType == kzble_proto_error_receipt || p_packet->frameType == kzble_proto_cmd_receipt) { if (m_isWaitingForAck) { suc = ackQueue.send(packet, 10); m_isWaitingForAck = false; } } if (!suc) { ZLOGI(TAG, "eventQueue send failed"); } } void RemoteControlerUpper::processRxEventPacket(RemoteControlerReportPacket_t* packet) { #if MODULE_DEBUG ZLOGI(TAG, "[process-thread] rx event : %s", zhex2str(packet->data, packet->datalen)); #endif // if (m_on_report) { // m_on_report(packet->data, packet->datalen); // } callOnReport(packet->data, packet->datalen); } bool RemoteControlerUpper::txcmd(uint8_t* data, uint32_t len) { /** * @brief */ zlock_guard lg(m_cmdlock); ackQueue.clear(); m_isWaitingForAck = true; #if MODULE_DEBUG ZLOGI(TAG, "txcmd : %s(%d)", zhex2str(data, len), len); #endif // vPortEnterCritical(); HAL_UART_Transmit(m_uart, data, len, 100); // vPortExitCritical(); // HAL_UART_Transmit_DMA(m_uart, data, len); bool suc = ackQueue.receive(&ackcache, CMD_OVERTIME); if (!suc) { ZLOGI(TAG, "txcmd : %s(%d) fail", zhex2str(data, len), len); // HAL_UART_DMAStop(m_uart); return false; } #if MODULE_DEBUG ZLOGI(TAG, "ack : %s", zhex2str(ackcache.data, ackcache.datalen)); #endif // HAL_UART_DMAStop(m_uart); return true; } /*********************************************************************************************************************** * CMD * ***********************************************************************************************************************/ bool RemoteControlerUpper::resetMasterBoard() { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_reset, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_master); bool suc = txcmd(txbuf, txpacket->packetlen); return suc; } bool RemoteControlerUpper::resetClientBoard() { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_reset, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_slave); bool suc = txcmd(txbuf, txpacket->packetlen); return suc; } bool RemoteControlerUpper::readMasterBoardVersion(zble_read_version_t* version) { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_read_version, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_master); bool suc = txcmd(txbuf, txpacket->packetlen); if (suc) *version = *(zble_read_version_t*)(rxpacket->data); return suc; } bool RemoteControlerUpper::readClientBoardVersion(zble_read_version_t* version) { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_read_version, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_slave); bool suc = txcmd(txbuf, txpacket->packetlen); if (suc) *version = *(zble_read_version_t*)(rxpacket->data); return suc; } bool RemoteControlerUpper::clearMasterResetFlag() { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_clear_reset_flag, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_master); bool suc = txcmd(txbuf, txpacket->packetlen); return suc; } bool RemoteControlerUpper::clearSlaveResetFlag() { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_clear_reset_flag, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_slave); bool suc = txcmd(txbuf, txpacket->packetlen); return suc; } bool RemoteControlerUpper::setMasterInDfuMode() { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_set_in_dfu_mode, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_master); bool suc = txcmd(txbuf, txpacket->packetlen); return suc; } bool RemoteControlerUpper::setSlaveInDfuMode() { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_set_in_dfu_mode, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_slave); bool suc = txcmd(txbuf, txpacket->packetlen); return suc; } bool RemoteControlerUpper::startScan(const char* slaveName, bool autoConnect) { // typedef struct { // uint8_t slaveName[20]; // uint8_t autoConnect; // } zble_start_scan_t; zble_start_scan_t scanparam = {0}; if (slaveName) strncpy((char*)scanparam.slaveName, slaveName, 20); scanparam.autoConnect = autoConnect; zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_start_scan, m_index++, (uint8_t*)&scanparam, sizeof(scanparam)); zble_proto_utils_set_packet_to(txpacket, kzble_master); bool suc = txcmd(txbuf, txpacket->packetlen); return suc; } bool RemoteControlerUpper::stopScan() { zble_proto_utils_create_cmd_packet(txpacket, kzble_cmd_stop_scan, m_index++, NULL, 0); zble_proto_utils_set_packet_to(txpacket, kzble_master); bool suc = txcmd(txbuf, txpacket->packetlen); return suc; } /*********************************************************************************************************************** * APP * ***********************************************************************************************************************/ bool RemoteControlerUpper::setRemoterState(hand_acid_mode_t mode, bool state) { zble_proto_packet_t* packet = (zble_proto_packet_t*)txbuf; int32_t param[2] = {mode, state}; zble_proto_utils_create_cmd_packet_int32(packet, kzble_app_cmd_set_state, m_index++, param, 2); bool suc = txcmd(txbuf, packet->packetlen); return suc; }