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.

387 lines
12 KiB

2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
2 years ago
1 year ago
1 year ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. #include "mainwindow.h"
  2. #include <QDateTime>
  3. #include <QMessageBox>
  4. #include <QtConcurrent>
  5. #include <QtSerialPort/QSerialPort>
  6. #include <QtSerialPort/QSerialPortInfo>
  7. #include "./ui_mainwindow.h"
  8. #include "logger.hpp"
  9. #include "qt_serial_datachannel.hpp"
  10. #include "version.h"
  11. using namespace iflytop;
  12. using namespace std;
  13. static MainWindow *m_mainWindow;
  14. QTimer *timer0;
  15. QTimer *timer1;
  16. QTimer *timer2;
  17. QTimer *timer3;
  18. QTimer *checkConnectTimer0;
  19. static bool m_connected = false;
  20. ZQThread *m_zqthread;
  21. #define TAG "MainWindow"
  22. static const char *fmt(const char *fmt, ...) {
  23. va_list args;
  24. va_start(args, fmt);
  25. static char buf[1024] = {0};
  26. vsnprintf(buf, sizeof(buf), fmt, args);
  27. va_end(args);
  28. return buf;
  29. }
  30. static const uint32_t str2int(QString str) {
  31. // 如果0x开头,??16进制转换
  32. // 如果0b开头,??2进制转换
  33. // 否则??10进制转换
  34. // 去除掉str中_
  35. str.remove("_");
  36. if (str.startsWith("0x")) {
  37. return str.toUInt(nullptr, 16);
  38. } else if (str.startsWith("0b")) {
  39. // remove 0b
  40. str.remove(0, 2);
  41. return str.toUInt(nullptr, 2);
  42. } else {
  43. return str.toUInt(nullptr, 10);
  44. }
  45. }
  46. // static QSerialPort G_SerialPort;
  47. // static QThread G_SerialPortThread;
  48. static QTDataChannel G_QTDataChannel;
  49. // static const QString zaferror_to_str(zaf_error_code_t value) {
  50. // if (value == kaf_ec_overtime) {
  51. // return "通信超时";
  52. // } else if (value == kaf_ec_device_notopen) {
  53. // return "设备未打开";
  54. // } else {
  55. // return "未知错误";
  56. // }
  57. // }
  58. void MainWindow::log_output(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
  59. // QString text;
  60. // text.append(msg);
  61. }
  62. // void MainWindow::append_log_slot(QString text) { ui->logbrowser->append(text); }
  63. void MainWindow::doinui_slot(QFunction func) {
  64. if (func.get()) func.get()();
  65. }
  66. void MainWindow::refreshReadonlyPage0() {}
  67. void MainWindow::refreshReadonlyPage1() {}
  68. void MainWindow::refreshReadonlyPage2() {}
  69. void MainWindow::refreshReadonlyPage3() {}
  70. bool MainWindow::checkConnected() { return true; }
  71. void MainWindow::constructUI() {
  72. /*******************************************************************************
  73. * serialPortCB *
  74. *******************************************************************************/
  75. const auto infos = QSerialPortInfo::availablePorts();
  76. for (const QSerialPortInfo &info : infos) {
  77. ui->serialPortCB->addItem(info.portName());
  78. }
  79. /*******************************************************************************
  80. * ?? *
  81. *******************************************************************************/
  82. ui->serialBaudrateCB->addItem("9600");
  83. ui->serialBaudrateCB->addItem("14400");
  84. ui->serialBaudrateCB->addItem("19200");
  85. ui->serialBaudrateCB->addItem("38400");
  86. ui->serialBaudrateCB->addItem("57600");
  87. ui->serialBaudrateCB->addItem("115200");
  88. ui->serialBaudrateCB->addItem("500000");
  89. ui->serialBaudrateCB->setCurrentIndex(0);
  90. /*******************************************************************************
  91. * *
  92. *******************************************************************************/
  93. connect(ui->serialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  94. ui->serialPortCB->clear();
  95. const auto infos = QSerialPortInfo::availablePorts();
  96. for (const QSerialPortInfo &info : infos) {
  97. ui->serialPortCB->addItem(info.portName());
  98. }
  99. });
  100. /*******************************************************************************
  101. * *
  102. *******************************************************************************/
  103. connect(ui->serialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  104. // 打开串口
  105. if (ui->serialOpenKey->text() == "打开") {
  106. G_QTDataChannel.setPortName(ui->serialPortCB->currentText().toStdString());
  107. G_QTDataChannel.setBaudRate(ui->serialBaudrateCB->currentText().toInt());
  108. G_QTDataChannel.setDataBits(QSerialPort::Data8);
  109. G_QTDataChannel.setParity(QSerialPort::NoParity);
  110. G_QTDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  111. G_QTDataChannel.setStopBits(QSerialPort::OneStop);
  112. if (!G_QTDataChannel.open()) {
  113. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  114. return;
  115. }
  116. ui->serialOpenKey->setText("关闭");
  117. // 下拉菜单控件使能
  118. ui->serialBaudrateCB->setEnabled(false);
  119. ui->serialPortCB->setEnabled(false);
  120. ui->serialPortRefreshKey->setEnabled(false);
  121. } else {
  122. G_QTDataChannel.close();
  123. ui->serialOpenKey->setText("打开");
  124. ui->serialBaudrateCB->setEnabled(true);
  125. ui->serialPortCB->setEnabled(true);
  126. ui->serialPortRefreshKey->setEnabled(true);
  127. }
  128. });
  129. }
  130. typedef enum {
  131. koutput_mode_continue_mode,
  132. koutput_mode_pluse_mode,
  133. } OutputMode_t;
  134. typedef enum {
  135. // 自定义
  136. koutput_pluse_type_custom,
  137. // 方波
  138. koutput_pluse_type_square_wave,
  139. } OutputPluseType_t;
  140. static QString outputMode2Str(OutputMode_t mode) {
  141. if (mode == koutput_mode_continue_mode) {
  142. return "连续模式";
  143. } else if (mode == koutput_mode_pluse_mode) {
  144. return "脉冲模式";
  145. } else {
  146. return "未知模式";
  147. }
  148. }
  149. static OutputMode_t outputModeStr2Enum(QString str) {
  150. if (str == "连续模式") {
  151. return koutput_mode_continue_mode;
  152. } else if (str == "脉冲模式") {
  153. return koutput_mode_pluse_mode;
  154. } else {
  155. return koutput_mode_continue_mode;
  156. }
  157. }
  158. static QString outputPluseType2Str(OutputPluseType_t type) {
  159. if (type == koutput_pluse_type_custom) {
  160. return "自定义";
  161. } else if (type == koutput_pluse_type_square_wave) {
  162. return "方波";
  163. } else {
  164. return "未知";
  165. }
  166. }
  167. static OutputPluseType_t outputPluseTypeStr2Enum(QString str) {
  168. if (str == "自定义") {
  169. return koutput_pluse_type_custom;
  170. } else if (str == "方波") {
  171. return koutput_pluse_type_square_wave;
  172. } else {
  173. return koutput_pluse_type_custom;
  174. }
  175. }
  176. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
  177. // G_SerialPort.moveToThread();
  178. // QObject::connect(&G_SerialPortThread, &QThread::started, &G_SerialPort, &QSerialPort::open);
  179. G_QTDataChannel.init();
  180. ui->setupUi(this);
  181. m_mainWindow = this;
  182. qRegisterMetaType<int32_t>("int32_t");
  183. qRegisterMetaType<uint32_t>("uint32_t");
  184. qRegisterMetaType<float>("float");
  185. qRegisterMetaType<function<void()>>("function<void()>");
  186. qRegisterMetaType<QFunction>("QFunction");
  187. // qInstallMessageHandler(log_output);
  188. connect(this, SIGNAL(doinui_signal(QFunction)), this, SLOT(doinui_slot(QFunction)));
  189. constructUI();
  190. this->setMinimumSize(QSize(width(), height()));
  191. this->setMaximumSize(QSize(width(), height()));
  192. ui->UpperVersion->setText(fmt("V%d", VERSION));
  193. {
  194. //
  195. ui->StateGB->hide();
  196. ui->OutputModeVal->addItem(outputMode2Str(koutput_mode_continue_mode));
  197. ui->OutputModeVal->addItem(outputMode2Str(koutput_mode_pluse_mode));
  198. ui->OutputPluseTypeVal->addItem(outputPluseType2Str(koutput_pluse_type_custom));
  199. ui->OutputPluseTypeVal->addItem(outputPluseType2Str(koutput_pluse_type_square_wave));
  200. ui->OutputPluseWidthVal->setText("1");
  201. ui->OutputPluseNumVal->setText("1");
  202. ui->OutputPluseFreqVal->setText("1000");
  203. }
  204. G_QTDataChannel.regRxListener([this](uint8_t *data, size_t len) {
  205. char m_rxbuf[1024] = {0};
  206. int m_rxlen = 0;
  207. memcpy(m_rxbuf + m_rxlen, data, len);
  208. m_rxlen += len;
  209. iPreviewAppend(string((char *)data, len));
  210. // dumpLog("RX:%s", rxbuf, len);
  211. });
  212. // 创建定时器
  213. timer0 = new QTimer(this);
  214. timer1 = new QTimer(this);
  215. timer2 = new QTimer(this);
  216. timer3 = new QTimer(this);
  217. checkConnectTimer0 = new QTimer(this);
  218. m_zqthread = new ZQThread("", [this]() {
  219. while (true) {
  220. static bool first = true;
  221. bool connect = checkConnected();
  222. if (m_connected != connect || first) {
  223. first = false;
  224. m_connected = connect;
  225. emit doinui_signal(QFunction([this, connect]() {
  226. if (connect) {
  227. ui->DeviceConnectStateTB->setText("已连接");
  228. ui->DeviceConnectStateTB->setStyleSheet("color: green");
  229. } else {
  230. ui->DeviceConnectStateTB->setText("未连接");
  231. ui->DeviceConnectStateTB->setStyleSheet("color: red");
  232. }
  233. if (m_connected) {
  234. // m_clstc->initDevice();
  235. // m_clstc->setAllShawdowRegDirty();
  236. // refreshPage();
  237. }
  238. }));
  239. }
  240. if (connect) {
  241. refreshReadonlyPage0();
  242. refreshReadonlyPage1();
  243. refreshReadonlyPage2();
  244. refreshReadonlyPage3();
  245. }
  246. std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  247. }
  248. });
  249. m_zqthread->start();
  250. }
  251. QString iPreviewContent;
  252. void MainWindow::iPreviewClean() {
  253. emit doinui_signal(QFunction([this]() {
  254. ui->instructionPreview->clear();
  255. iPreviewContent = "";
  256. }));
  257. }
  258. void MainWindow::iPreviewAppend(std::string info) {
  259. emit doinui_signal(QFunction([this, info]() { //
  260. iPreviewContent += QString(info.c_str());
  261. ui->instructionPreview->setText(iPreviewContent);
  262. }));
  263. }
  264. void MainWindow::iPreviewShow(const char *fmt, ...) {
  265. va_list args;
  266. va_start(args, fmt);
  267. static char buf[1024] = {0};
  268. vsnprintf(buf, sizeof(buf), fmt, args);
  269. va_end(args);
  270. iPreviewAppend(buf);
  271. }
  272. MainWindow::~MainWindow() { delete ui; }
  273. void MainWindow::on_OutputModeVal_currentIndexChanged(const QString &arg1) { onModeChange(); }
  274. void MainWindow::on_OutputPluseTypeVal_currentIndexChanged(const QString &arg1) { onModeChange(); }
  275. void MainWindow::onModeChange() {
  276. OutputMode_t outputMode = outputModeStr2Enum(ui->OutputModeVal->currentText());
  277. OutputPluseType_t outputPluseType = outputPluseTypeStr2Enum(ui->OutputPluseTypeVal->currentText());
  278. if (outputMode == koutput_mode_continue_mode) {
  279. ui->OutputPluseNumVal->hide();
  280. ui->OutputPluseNumTag->hide();
  281. } else if (outputMode == koutput_mode_pluse_mode) {
  282. ui->OutputPluseNumVal->show();
  283. ui->OutputPluseNumTag->show();
  284. }
  285. if (outputPluseType == koutput_pluse_type_custom) {
  286. ui->OutputPluseWidthVal->show();
  287. ui->OutputPluseWidthTag->show();
  288. } else if (outputPluseType == koutput_pluse_type_square_wave) {
  289. ui->OutputPluseWidthVal->hide();
  290. ui->OutputPluseWidthTag->hide();
  291. }
  292. }
  293. void MainWindow::on_SendButton_clicked() {
  294. OutputMode_t outputMode = outputModeStr2Enum(ui->OutputModeVal->currentText());
  295. OutputPluseType_t outputPluseType = outputPluseTypeStr2Enum(ui->OutputPluseTypeVal->currentText());
  296. uint32_t outputPluseWidthUs_01 = str2int(ui->OutputPluseWidthVal->text()) * 10;
  297. uint32_t outputPluseNum = str2int(ui->OutputPluseNumVal->text());
  298. int freq = str2int(ui->OutputPluseFreqVal->text());
  299. /**
  300. *
  301. * @brief
  302. *
  303. * S0000112345601234567
  304. * S 0 0 0 0 1 1 2 3 4 5 6 0 1 2 3 4 5 6 7
  305. * [S] [2][3][4][5][6] [7][8][9][10][11][12][13] [14][15][16][17][18][19][20]
  306. * HZ 0.1us
  307. *
  308. *
  309. */
  310. // S9900000000500000010 99khz,50%,10个脉冲
  311. // S9900000000500000011 99khz,50%,11个脉冲
  312. // S9900000000500000000 99khz,50%,连续脉冲
  313. // S0100000050000000010 1khz,%50 10个脉冲
  314. // S0100000050000000020 1khz,%50 20个脉冲
  315. // S 01000 0005000 0000000 1khz,%50连续脉冲
  316. if (outputPluseType == koutput_pluse_type_square_wave) {
  317. double periodus = 1.0 * 1000 * 1000 / freq;
  318. outputPluseWidthUs_01 = periodus * 10 / 2;
  319. }
  320. QString cmd = fmt("S%05d%07d%07d", freq, outputPluseWidthUs_01, outputPluseNum);
  321. QString txcmd = fmt("%s\r\n", cmd.toStdString().c_str());
  322. iPreviewClean();
  323. iPreviewShow(" %s\n", QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString().c_str());
  324. if (G_QTDataChannel.isOpen()) {
  325. G_QTDataChannel.send((const uint8_t *)txcmd.toStdString().c_str(), txcmd.length());
  326. iPreviewShow("-----------------TX----------------\n");
  327. iPreviewShow("%s\n", cmd.toStdString().c_str());
  328. iPreviewShow("\n");
  329. iPreviewShow("-----------------RX----------------\n");
  330. } else {
  331. iPreviewShow("串口未打开\n");
  332. }
  333. // dumpLog
  334. }