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
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;
|
|
}
|