You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

269 lines
9.9 KiB

#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<RemoteControlerReportPacket_t> ackQueue;
static ZQueue<RemoteControlerReportPacket_t> 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;
}