6 changed files with 387 additions and 1 deletions
-
0src/app/syncbox16ch/sdk/syncbox16ch_reg.hpp
-
0src/app/syncbox16ch/sdk/syncbox16ch_sdk.cpp
-
0src/app/syncbox16ch/sdk/syncbox16ch_sdk.hpp
-
276src/app/zfpga_commander/zfpga_commander.cpp
-
110src/app/zfpga_commander/zfpga_commander.hpp
-
2zfpga_basic_protocol
@ -0,0 +1,276 @@ |
|||
#include "zfpga_commander.hpp"
|
|||
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
|
|||
//
|
|||
#include "zqui/base/logger.hpp"
|
|||
#include "zqui/base/zexception.hpp"
|
|||
#include "zqui/channelmgr/channelmgr.hpp"
|
|||
|
|||
using namespace iflytop; |
|||
|
|||
#define TAG "Syncbox16ch"
|
|||
|
|||
QTSerialChannel *serial_ch; |
|||
|
|||
#define PACKET_LEN(__packet) (sizeof(zaf_packet_header_t) + (__packet->ndata) * sizeof(uint32_t) + 1 /*checksum*/ + 2 /*tail*/)
|
|||
#define DO_CMD(exptr) \
|
|||
{ \ |
|||
zaf_error_code_t ecode = exptr; \ |
|||
if (ecode != kaf_ec_success) return ecode; \ |
|||
} |
|||
|
|||
void ZFPGACommander::initialize() { |
|||
//
|
|||
serial_ch = &ChannelMgr::ins()->serialCh; |
|||
serial_ch->regRxListener([this](uint8_t *data, size_t len) { |
|||
{ |
|||
lock_guard<mutex> lock(lock_); |
|||
if (len + m_rxlen > sizeof(m_rxcache)) { |
|||
m_rxlen = 0; |
|||
} |
|||
memcpy(m_rxcache + m_rxlen, data, len); |
|||
m_rxlen += len; |
|||
} |
|||
}); |
|||
|
|||
m_thread.reset(new thread([this]() { |
|||
uint32_t last_rx_cnt = 0; |
|||
uint8_t rx_process_cache[1024]; |
|||
uint32_t rx_process_cache_len; |
|||
while (true) { |
|||
this_thread::sleep_for(chrono::milliseconds(4)); |
|||
|
|||
{ |
|||
lock_guard<mutex> lock(lock_); |
|||
if (last_rx_cnt == m_rxlen && m_rxlen != 0) { |
|||
memcpy(rx_process_cache, m_rxcache, m_rxlen); |
|||
rx_process_cache_len = m_rxlen; |
|||
|
|||
m_rxlen = 0; |
|||
last_rx_cnt = 0; |
|||
} |
|||
} |
|||
|
|||
if (rx_process_cache_len != 0) { |
|||
processRxData(rx_process_cache, rx_process_cache_len); |
|||
memset(rx_process_cache, 0, sizeof(rx_process_cache)); |
|||
rx_process_cache_len = 0; |
|||
} |
|||
|
|||
last_rx_cnt = m_rxlen; |
|||
} |
|||
})); |
|||
} |
|||
void ZFPGACommander::regRawDataListener(binary_cb_t cb) {} |
|||
|
|||
void ZFPGACommander::processRxData(uint8_t *rx, uint32_t rxlen) { |
|||
for (uint32_t i = 0; i < rxlen; i++) { |
|||
zaf_packet_header_t *header = (zaf_packet_header_t *)(&rx[i]); |
|||
uint8_t *packetu8 = &rx[i]; |
|||
|
|||
if (header->packet_header == PACKET_HEADER) { |
|||
uint8_t check = packetu8[header->ndata * 4 + sizeof(zaf_packet_header_t) + 0]; |
|||
uint8_t tail0 = packetu8[header->ndata * 4 + sizeof(zaf_packet_header_t) + 1]; |
|||
uint8_t tail1 = packetu8[header->ndata * 4 + sizeof(zaf_packet_header_t) + 2]; |
|||
|
|||
uint16_t tail = (tail1 << 8) | tail0; |
|||
|
|||
uint8_t expectcheck = 0; |
|||
for (uint32_t j = 2; j < header->ndata * 4 + sizeof(zaf_packet_header_t); j++) { |
|||
expectcheck += packetu8[j]; |
|||
} |
|||
|
|||
if (tail == PACKET_TAIL) { |
|||
if (expectcheck == check) { |
|||
processRxPacket(header); |
|||
} else { |
|||
ZLOGE(TAG, "Rx packet check error %d != %d", expectcheck, check); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
void ZFPGACommander::processRxPacket(zaf_packet_header_t *packet) { |
|||
//
|
|||
// ZLOGI(TAG, "RX packet");
|
|||
// ZLOGI(TAG, " type :%d", packet->packet_type);
|
|||
// ZLOGI(TAG, " index :%d", packet->index);
|
|||
// ZLOGI(TAG, " cmd :%d", packet->cmd);
|
|||
// ZLOGI(TAG, " ndata :%d", packet->ndata);
|
|||
// for (uint32_t i = 0; i < packet->ndata; i++) {
|
|||
// ZLOGI(TAG, " data[%d]:%d", i, packet->data[i]);
|
|||
// }
|
|||
// ZLOGI(TAG, "Rx.....");
|
|||
uint32_t packetlen = sizeof(zaf_packet_header_t) + packet->ndata * 4 + 3; |
|||
|
|||
if (m_raw_data_cb) { |
|||
m_raw_data_cb(kuart_raw_rx, (uint8_t *)packet, packetlen); |
|||
} |
|||
if (packet->packet_type == kzaf_packet_type_receipt) { |
|||
lock_guard<mutex> lock(m_rxReceiptContext_lock); |
|||
if (m_rxReceiptContext.waittingForReceipt) { |
|||
if (m_rxReceiptContext.waittingIndex == packet->index) { |
|||
m_rxReceiptContext.receiptIsReady = true; |
|||
m_rxReceiptContext.receiptLen = PACKET_LEN(packet); |
|||
memcpy(m_rxReceiptContext.receipt, packet, PACKET_LEN(packet)); |
|||
} |
|||
m_rxReceiptContext.waittingForReceipt = false; |
|||
} |
|||
} else if (packet->packet_type == kzaf_packet_type_heart) { |
|||
} |
|||
} |
|||
|
|||
void ZFPGACommander::resetRxContext(int32_t cmdIndex) { |
|||
lock_guard<mutex> lock(m_rxReceiptContext_lock); |
|||
m_rxReceiptContext.waittingIndex = cmdIndex; |
|||
m_rxReceiptContext.waittingForReceipt = true; |
|||
m_rxReceiptContext.receiptIsReady = false; |
|||
m_rxReceiptContext.receiptLen = 0; |
|||
} |
|||
|
|||
void ZFPGACommander::sendPacket(zaf_packet_header_t *packet, uint32_t len, uint32_t overtime) { |
|||
zaf_packet_header_t *rxpacket = (zaf_packet_header_t *)&m_rxReceiptContext.receipt[0]; |
|||
|
|||
resetRxContext(packet->index); |
|||
|
|||
if (serial_ch->isOpen() == false) { |
|||
throw zexception(ke_invalid_packet_format, "channel is not open"); |
|||
} |
|||
if (m_raw_data_cb) { |
|||
m_raw_data_cb(kuart_raw_tx, (uint8_t *)packet, PACKET_LEN(packet)); |
|||
} |
|||
serial_ch->send((uint8_t *)packet, len); |
|||
for (size_t i = 0; i < overtime; i++) { |
|||
{ |
|||
lock_guard<mutex> lock(m_rxReceiptContext_lock); |
|||
if (m_rxReceiptContext.receiptIsReady) { |
|||
break; |
|||
} |
|||
} |
|||
this_thread::sleep_for(chrono::milliseconds(1)); |
|||
} |
|||
|
|||
if (m_rxReceiptContext.receiptIsReady) { |
|||
if (rxpacket->data[0] != 0) { |
|||
throw zexception(rxpacket->data[0], zaf_ecode_to_string((zaf_error_code_t)rxpacket->data[0])); |
|||
} else { |
|||
return; |
|||
} |
|||
} else { |
|||
} |
|||
|
|||
throw zexception(ke_overtime, "overtime"); |
|||
} |
|||
|
|||
zaf_packet_header_t *ZFPGACommander::getReceipt() { return (zaf_packet_header_t *)&(m_rxReceiptContext.receipt[0]); } |
|||
|
|||
void ZFPGACommander::writeReg(uint32_t regadd, uint32_t regvalue, uint32_t ®backvalue, int32_t overtime_ms) { |
|||
Reginfo *reg = GetRegInfo(regadd); |
|||
|
|||
if (reg->flag & kreg_flag_force_write) { |
|||
_writeReg(regadd, regvalue, regbackvalue, overtime_ms); |
|||
} else if (reg->dirty) { |
|||
_writeReg(regadd, regvalue, regbackvalue, overtime_ms); |
|||
} else { |
|||
regbackvalue = reg->regshadow; |
|||
} |
|||
reg->dirty = false; |
|||
reg->regshadow = regvalue; |
|||
return; |
|||
} |
|||
void ZFPGACommander::readReg(uint32_t regadd, uint32_t ®value, int32_t overtime_ms) { |
|||
Reginfo *reg = GetRegInfo(regadd); |
|||
|
|||
if ((reg->flag & kreg_flag_force_read)) { |
|||
_readReg(regadd, regvalue, overtime_ms); |
|||
} else if (reg->dirty) { |
|||
_readReg(regadd, regvalue, overtime_ms); |
|||
} else { |
|||
regvalue = reg->regshadow; |
|||
} |
|||
reg->dirty = false; |
|||
reg->regshadow = regvalue; |
|||
} |
|||
|
|||
void ZFPGACommander::_writeReg(uint32_t regadd, uint32_t regvalue, uint32_t ®backvalue, int32_t overtime_ms) { |
|||
//
|
|||
lock_guard<mutex> lock(m_tx_lock); |
|||
|
|||
uint8_t txdata[128] = {0}; |
|||
|
|||
zaf_packet_header_t *txpacket = (zaf_packet_header_t *)txdata; |
|||
zaf_packet_header_t *rxpacket = (zaf_packet_header_t *)&m_rxReceiptContext.receipt[0]; |
|||
|
|||
txpacket->packet_header = PACKET_HEADER; |
|||
txpacket->packet_type = kzaf_packet_type_cmd; |
|||
txpacket->index = ++txindex; |
|||
txpacket->cmd = kzaf_cmd_reg_write; |
|||
txpacket->ndata = 2; |
|||
txpacket->data[0] = regadd; |
|||
txpacket->data[1] = regvalue; |
|||
|
|||
uint32_t txpacklen = PACKET_LEN(txpacket); |
|||
uint8_t checksum = 0; |
|||
for (uint32_t i = 2; i < txpacklen - 3; i++) { |
|||
checksum += txdata[i]; |
|||
} |
|||
txdata[txpacklen - 3] = checksum; |
|||
txdata[txpacklen - 2] = PACKET_TAIL & 0xFF; |
|||
txdata[txpacklen - 1] = (PACKET_TAIL >> 8) & 0xFF; |
|||
|
|||
sendPacket(txpacket, txpacklen, overtime_ms); |
|||
regbackvalue = rxpacket->data[1]; |
|||
} |
|||
void ZFPGACommander::_readReg(uint32_t regadd, uint32_t ®value, int32_t overtime_ms) { |
|||
lock_guard<mutex> lock(m_tx_lock); |
|||
|
|||
uint8_t txdata[128] = {0}; |
|||
|
|||
zaf_packet_header_t *txpacket = (zaf_packet_header_t *)txdata; |
|||
zaf_packet_header_t *rxpacket = (zaf_packet_header_t *)&m_rxReceiptContext.receipt[0]; |
|||
|
|||
txpacket->packet_header = PACKET_HEADER; |
|||
txpacket->packet_type = kzaf_packet_type_cmd; |
|||
txpacket->index = ++txindex; |
|||
txpacket->cmd = kzaf_cmd_reg_read; |
|||
txpacket->ndata = 1; |
|||
txpacket->data[0] = regadd; |
|||
|
|||
uint32_t txpacklen = PACKET_LEN(txpacket); |
|||
uint8_t checksum = 0; |
|||
for (uint32_t i = 2; i < txpacklen - 3; i++) { |
|||
checksum += txdata[i]; |
|||
} |
|||
txdata[txpacklen - 3] = checksum; |
|||
txdata[txpacklen - 2] = PACKET_TAIL & 0xFF; |
|||
txdata[txpacklen - 1] = (PACKET_TAIL >> 8) & 0xFF; |
|||
|
|||
sendPacket(txpacket, txpacklen, overtime_ms); |
|||
regvalue = rxpacket->data[1]; |
|||
|
|||
// ZLOGI(TAG, "RX packet");
|
|||
// ZLOGI(TAG, " type :%d", rxpacket->packet_type);
|
|||
// ZLOGI(TAG, " index :%d", rxpacket->index);
|
|||
// ZLOGI(TAG, " cmd :%d", rxpacket->cmd);
|
|||
// ZLOGI(TAG, " ndata :%d", rxpacket->ndata);
|
|||
// for (uint32_t i = 0; i < rxpacket->ndata; i++) {
|
|||
// ZLOGI(TAG, " data[%d]:%d", i, rxpacket->data[i]);
|
|||
// }
|
|||
// ZLOGI(TAG, "RX:%d", regvalue);
|
|||
} |
|||
|
|||
Reginfo *ZFPGACommander::GetRegInfo(uint32_t add) { |
|||
auto it = m_reginfoMap.find(add); |
|||
if (it != m_reginfoMap.end()) { |
|||
return &it->second; |
|||
} |
|||
m_reginfoMap.insert(make_pair(add, Reginfo())); |
|||
return &m_reginfoMap[add]; |
|||
} |
|||
void ZFPGACommander::RegInfo_Reset() { |
|||
for (auto &it : m_reginfoMap) { |
|||
it.second.dirty = true; |
|||
} |
|||
} |
@ -0,0 +1,110 @@ |
|||
#pragma once
|
|||
#include <fstream>
|
|||
#include <functional>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <mutex>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <thread>
|
|||
#include <vector>
|
|||
|
|||
#include "zfpga_basic_protocol\zaf_protocol.h"
|
|||
#include "zfpga_basic_protocol\zaf_regs.hpp"
|
|||
|
|||
namespace iflytop { |
|||
|
|||
using namespace std; |
|||
|
|||
typedef enum { |
|||
kuart_raw_tx, |
|||
kuart_raw_rx, |
|||
} uart_message_type_t; |
|||
|
|||
typedef function<void(bool connect)> device_state_cb_t; |
|||
|
|||
typedef function<void(uart_message_type_t type, uint8_t *data, size_t len)> binary_cb_t; |
|||
|
|||
class ZFPGARxReceiptContext { |
|||
public: |
|||
bool waittingForReceipt; |
|||
bool receiptIsReady; |
|||
uint16_t waittingIndex; |
|||
uint8_t receipt[1024]; |
|||
size_t receiptLen; |
|||
}; |
|||
|
|||
typedef enum { |
|||
|
|||
kreg_flag_r = 0x01, // 可读
|
|||
kreg_flag_w = 0x01 << 1, // 可写
|
|||
kreg_flag_force_read = 0x01 << 2, // 易变寄存器
|
|||
kreg_flag_force_write = 0x01 << 3, // 易变寄存器
|
|||
|
|||
kreg_flag_rw = kreg_flag_r | kreg_flag_w, |
|||
} reg_flag_t; |
|||
|
|||
class Reginfo { |
|||
public: |
|||
uint32_t regadd = 0; |
|||
uint32_t flag = kreg_flag_rw; |
|||
uint32_t regshadow = 0; |
|||
bool dirty = true; |
|||
|
|||
public: |
|||
}; |
|||
|
|||
class ZFPGACommander { |
|||
ZFPGACommander() {} |
|||
|
|||
uint8_t m_rxcache[1024]; |
|||
size_t m_rxlen = 0; |
|||
|
|||
mutex lock_; |
|||
|
|||
unique_ptr<thread> m_thread; |
|||
|
|||
ZFPGARxReceiptContext m_rxReceiptContext; |
|||
mutex m_rxReceiptContext_lock; |
|||
mutex m_tx_lock; |
|||
|
|||
binary_cb_t m_raw_data_cb; |
|||
uint16_t txindex = 0; |
|||
|
|||
map<uint32_t, Reginfo> m_reginfoMap; |
|||
|
|||
public: |
|||
static ZFPGACommander *ins() { |
|||
static ZFPGACommander cmder; |
|||
return &cmder; |
|||
} |
|||
|
|||
void initialize(); |
|||
void regRawDataListener(binary_cb_t cb); |
|||
|
|||
public: |
|||
void writeReg(uint32_t regadd, uint32_t regvalue, uint32_t ®backvalue, int32_t overtime_ms); |
|||
void readReg(uint32_t regadd, uint32_t ®value, int32_t overtime_ms); |
|||
void sendPacket(zaf_packet_header_t *packet, uint32_t len, uint32_t overtime); |
|||
|
|||
zaf_packet_header_t *getReceipt(); |
|||
|
|||
private: |
|||
void _writeReg(uint32_t regadd, uint32_t regvalue, uint32_t ®backvalue, int32_t overtime_ms); |
|||
void _readReg(uint32_t regadd, uint32_t ®value, int32_t overtime_ms); |
|||
|
|||
private: |
|||
void resetRxContext(int32_t cmdIndex); |
|||
void processRxData(uint8_t *rx, uint32_t rxlen); |
|||
void processRxPacket(zaf_packet_header_t *packet); |
|||
void setRxContext(int32_t cmdIndex); |
|||
|
|||
private: |
|||
Reginfo *GetRegInfo(uint32_t add); |
|||
void RegInfo_Reset(); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -1 +1 @@ |
|||
Subproject commit 3c83221293a425eb1b5e8fee3c1f108156465cc3 |
|||
Subproject commit 94290950d567241d8b82ba8b8ae5ea5a55cc9634 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue