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.

890 lines
34 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
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year 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 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 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 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 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 "ads129x/ads129x_type.h"
  9. #include "electrocardiograph_tester.hpp"
  10. #include "filter_algo_mgr.hpp"
  11. #include "filter_group/algo/iflytop_simple_filter_ext.h"
  12. #include "logger.hpp"
  13. #include "qt_serial_datachannel.hpp"
  14. #include "widgetplot2d.h"
  15. #include "zexception.hpp"
  16. WidgetPlot2D *wp2d;
  17. using namespace std;
  18. using namespace iflytop;
  19. typedef enum {
  20. kone_lead_ecg,
  21. kthree_lead_ecg,
  22. kone_lead_ecg_v2,
  23. } device_type_t;
  24. static MainWindow *m_mainWindow;
  25. static QTDataChannel G_QTDataChannel;
  26. static device_type_t m_devicetype;
  27. static const uint32_t str2int(QString str) {
  28. // 如果0x开头,按16进制转换
  29. // 如果0b开头,按2进制转换
  30. // 否则按10进制转换
  31. // 去除掉str中_
  32. str.remove("_");
  33. if (str.startsWith("0x")) {
  34. return str.toUInt(nullptr, 16);
  35. } else if (str.startsWith("0b")) {
  36. // remove 0b
  37. str.remove(0, 2);
  38. return str.toUInt(nullptr, 2);
  39. } else {
  40. return str.toUInt(nullptr, 10);
  41. }
  42. }
  43. #define TAG "MainWindow"
  44. static const char *fmt(const char *fmt, ...) {
  45. va_list args;
  46. va_start(args, fmt);
  47. static char buf[1024] = {0};
  48. vsnprintf(buf, sizeof(buf), fmt, args);
  49. va_end(args);
  50. return buf;
  51. }
  52. void MainWindow::log_output(QtMsgType type, const QMessageLogContext &context, const QString &msg) {}
  53. void MainWindow::doinui_slot(QFunction func) {
  54. if (func.get()) func.get()();
  55. }
  56. void MainWindow::ishow(const char *fmt, ...) {
  57. va_list args;
  58. va_start(args, fmt);
  59. char buf[1024] = {0};
  60. vsnprintf(buf, sizeof(buf), fmt, args);
  61. va_end(args);
  62. QString text(buf);
  63. QString info;
  64. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  65. info.append(" |");
  66. info.append(text);
  67. emit doinui_signal(QFunction([this, info]() { ui->instructionPreview->append(info); }));
  68. }
  69. void MainWindow::instructionPreviewClear() { ui->instructionPreview->document()->clear(); }
  70. void MainWindow::reportPreviewShow(const char *fmt, ...) {
  71. va_list args;
  72. va_start(args, fmt);
  73. char buf[1024] = {0};
  74. vsnprintf(buf, sizeof(buf), fmt, args);
  75. va_end(args);
  76. QString text(buf);
  77. QString info;
  78. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  79. info.append(text);
  80. emit doinui_signal(QFunction([this, info]() {
  81. if (ui->reportPreview->document()->lineCount() > 1000) {
  82. ui->reportPreview->document()->clear();
  83. }
  84. ui->reportPreview->append(info);
  85. }));
  86. }
  87. void MainWindow::blockDataUploadPreviewShow(const char *fmt, ...) {
  88. va_list args;
  89. va_start(args, fmt);
  90. char buf[1024] = {0};
  91. vsnprintf(buf, sizeof(buf), fmt, args);
  92. va_end(args);
  93. QString text(buf);
  94. QString info;
  95. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  96. info.append(text);
  97. emit doinui_signal(QFunction([this, info]() {
  98. if (ui->uploadDataPreview->document()->lineCount() > 1000) {
  99. ui->uploadDataPreview->document()->clear();
  100. }
  101. ui->uploadDataPreview->append(info);
  102. }));
  103. }
  104. void MainWindow::rawDataPreviewShow(const char *fmt, ...) {
  105. va_list args;
  106. va_start(args, fmt);
  107. char buf[1024] = {0};
  108. vsnprintf(buf, sizeof(buf), fmt, args);
  109. va_end(args);
  110. QString text(buf);
  111. QString info;
  112. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz"));
  113. info.append(text);
  114. emit doinui_signal(QFunction([this, info]() {
  115. if (ui->rawDataPreview->document()->lineCount() > 1000) {
  116. ui->rawDataPreview->document()->clear();
  117. }
  118. ui->rawDataPreview->append(info);
  119. }));
  120. }
  121. // uploadDataPreview
  122. #pragma pack(push, 1)
  123. typedef struct {
  124. uint16_t header;
  125. int16_t wave1;
  126. int16_t wave2;
  127. int16_t wave3;
  128. int16_t wave4;
  129. int16_t wave5;
  130. uint8_t check;
  131. uint16_t tail;
  132. } Wave_t;
  133. #pragma pack(pop)
  134. void MainWindow::displayInfo(bool suc, QString info) {}
  135. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
  136. /*******************************************************************************
  137. * QT初始化 *
  138. *******************************************************************************/
  139. ui->setupUi(this);
  140. m_mainWindow = this;
  141. qRegisterMetaType<int32_t>("int32_t");
  142. qRegisterMetaType<uint32_t>("uint32_t");
  143. qRegisterMetaType<float>("float");
  144. qRegisterMetaType<function<void()>>("function<void()>");
  145. qRegisterMetaType<QFunction>("QFunction");
  146. connect(this, SIGNAL(doinui_signal(QFunction)), this, SLOT(doinui_slot(QFunction)));
  147. // qInstallMessageHandler(log_output);
  148. wp2d = new WidgetPlot2D();
  149. QStringList lines;
  150. lines.push_back("心电1");
  151. lines.push_back("心电2");
  152. lines.push_back("心电3");
  153. wp2d->initGraphName(lines);
  154. FilterAlgoMgr::ins()->addFilter("心电1");
  155. FilterAlgoMgr::ins()->addFilter("心电2");
  156. FilterAlgoMgr::ins()->addFilter("心电3");
  157. /*******************************************************************************
  158. * *
  159. *******************************************************************************/
  160. constructUI();
  161. ui->TestCmd_writeSubICRegMask_p0->setPlaceholderText("寄存器地址");
  162. ui->TestCmd_writeSubICRegMask_p1->setPlaceholderText("偏移");
  163. ui->TestCmd_writeSubICRegMask_p2->setPlaceholderText("位数");
  164. ui->TestCmd_writeSubICRegMask_p3->setPlaceholderText("");
  165. ui->TestCmd_writeSubICReg_p0->setPlaceholderText("寄存器地址");
  166. ui->TestCmd_writeSubICReg_p1->setPlaceholderText("");
  167. /*******************************************************************************
  168. * *
  169. *******************************************************************************/
  170. G_QTDataChannel.init();
  171. ElectrocardiographTester::ins()->initialize(&G_QTDataChannel);
  172. }
  173. MainWindow::~MainWindow() { delete ui; }
  174. /*******************************************************************************
  175. * UI相关构造 *
  176. *******************************************************************************/
  177. void MainWindow::constructUI() {
  178. /*******************************************************************************
  179. * UI *
  180. *******************************************************************************/
  181. {
  182. const auto infos = QSerialPortInfo::availablePorts();
  183. for (const QSerialPortInfo &info : infos) {
  184. ui->serialPortCB->addItem(info.portName());
  185. }
  186. }
  187. ui->serialBaudrateCB->addItem("9600");
  188. ui->serialBaudrateCB->addItem("14400");
  189. ui->serialBaudrateCB->addItem("19200");
  190. ui->serialBaudrateCB->addItem("38400");
  191. ui->serialBaudrateCB->addItem("57600");
  192. ui->serialBaudrateCB->addItem("115200");
  193. ui->serialBaudrateCB->addItem("460800");
  194. ui->serialBaudrateCB->addItem("500000");
  195. ui->serialBaudrateCB->setCurrentIndex(6);
  196. connect(ui->serialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  197. ui->serialPortCB->clear();
  198. const auto infos = QSerialPortInfo::availablePorts();
  199. for (const QSerialPortInfo &info : infos) {
  200. ui->serialPortCB->addItem(info.portName());
  201. }
  202. });
  203. connect(ui->serialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  204. // 打开串口
  205. if (ui->serialOpenKey->text() == "打开") {
  206. G_QTDataChannel.setPortName(ui->serialPortCB->currentText().toStdString());
  207. G_QTDataChannel.setBaudRate(ui->serialBaudrateCB->currentText().toInt());
  208. G_QTDataChannel.setDataBits(QSerialPort::Data8);
  209. G_QTDataChannel.setParity(QSerialPort::NoParity);
  210. G_QTDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  211. G_QTDataChannel.setStopBits(QSerialPort::OneStop);
  212. if (!G_QTDataChannel.open()) {
  213. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  214. return;
  215. }
  216. ui->serialOpenKey->setText("关闭");
  217. // 下拉菜单控件使能
  218. ui->serialBaudrateCB->setEnabled(false);
  219. ui->serialPortCB->setEnabled(false);
  220. ui->serialPortRefreshKey->setEnabled(false);
  221. ui->deviceType->setEnabled(false);
  222. } else {
  223. G_QTDataChannel.close();
  224. ui->serialOpenKey->setText("打开");
  225. ui->serialBaudrateCB->setEnabled(true);
  226. ui->serialPortCB->setEnabled(true);
  227. ui->serialPortRefreshKey->setEnabled(true);
  228. ui->deviceType->setEnabled(true);
  229. }
  230. });
  231. /*******************************************************************************
  232. * UI *
  233. *******************************************************************************/
  234. {
  235. ui->deviceType->addItem("单导联一代(M1001)");
  236. ui->deviceType->addItem("三导联一代(M1002)");
  237. ui->deviceType->addItem("单导联二代(M1003)");
  238. ui->deviceType->setCurrentIndex(0);
  239. connect(ui->deviceType, &QComboBox::currentTextChanged, this, [this](const QString &text) {
  240. if (text == "单导联一代(M1001)") {
  241. m_devicetype = kone_lead_ecg;
  242. } else if (text == "三导联一代(M1002)") {
  243. m_devicetype = kthree_lead_ecg;
  244. } else if (text == "单导联二代(M1003)") {
  245. m_devicetype = kone_lead_ecg_v2;
  246. }
  247. });
  248. }
  249. // 事件填充
  250. ElectrocardiographTester::ins()->regReportCB([this](bool checkok, ify_hrs_packet_t *report_packet, size_t len) {
  251. int reportType = report_packet->cmd;
  252. switch (reportType) {
  253. case ify_hrs_report_heartrate_data: {
  254. if (m_devicetype == kone_lead_ecg) {
  255. heartrate_report_packet_t *heartrate_report = (heartrate_report_packet_t *)report_packet;
  256. static uint32_t lastpacket_index = 0;
  257. static uint32_t lostpacket = 0;
  258. if ((lastpacket_index + 5) != (heartrate_report->sample_data_index)) {
  259. lostpacket++;
  260. }
  261. lastpacket_index = heartrate_report->sample_data_index;
  262. reportPreviewShow("[preview data ] lost:%d index %d", lostpacket, heartrate_report->sample_data_index);
  263. if (checkok) {
  264. uint16_t data0 = (uint16_t)(heartrate_report->data[0]) + ((uint16_t)heartrate_report->data[1] << 8);
  265. uint16_t data1 = (uint16_t)(heartrate_report->data[2]) + ((uint16_t)heartrate_report->data[3] << 8);
  266. uint16_t data2 = (uint16_t)(heartrate_report->data[4]) + ((uint16_t)heartrate_report->data[5] << 8);
  267. uint16_t data3 = (uint16_t)(heartrate_report->data[6]) + ((uint16_t)heartrate_report->data[7] << 8);
  268. uint16_t data4 = (uint16_t)(heartrate_report->data[8]) + ((uint16_t)heartrate_report->data[9] << 8);
  269. emit doinui_signal(QFunction([this, data0, data1, data2, data3, data4]() { //
  270. wp2d->addData("心电1", data0, 0);
  271. wp2d->addData("心电1", data1, 2);
  272. wp2d->addData("心电1", data2, 4);
  273. wp2d->addData("心电1", data3, 6);
  274. wp2d->addData("心电1", data4, 8);
  275. }));
  276. }
  277. } else if (m_devicetype == kthree_lead_ecg) {
  278. heartrate_report_packet_t *heartrate_report = (heartrate_report_packet_t *)report_packet;
  279. static uint32_t lastpacket_index = 0;
  280. static uint32_t lostpacket = 0;
  281. int packetFrameNum = (len - sizeof(heartrate_report_packet_t)) / 9;
  282. if ((lastpacket_index + packetFrameNum) != (heartrate_report->sample_data_index)) {
  283. lostpacket++;
  284. }
  285. lastpacket_index = heartrate_report->sample_data_index;
  286. reportPreviewShow("[preview data ] lost:%d index %d", lostpacket, heartrate_report->sample_data_index);
  287. {
  288. // 解析心电数据
  289. int32_t val[3];
  290. for (size_t i = 0; i < packetFrameNum; i++) {
  291. uint8_t *val0p = heartrate_report->data + i * 9;
  292. uint8_t *val1p = val0p + 3;
  293. uint8_t *val2p = val1p + 3;
  294. val[0] = (int32_t)(val0p[0]) + ((int32_t)val0p[1] << 8) + ((int32_t)val0p[2] << 16);
  295. val[1] = (int32_t)(val1p[0]) + ((int32_t)val1p[1] << 8) + ((int32_t)val1p[2] << 16);
  296. val[2] = (int32_t)(val2p[0]) + ((int32_t)val2p[1] << 8) + ((int32_t)val2p[2] << 16);
  297. emit doinui_signal(QFunction([this, val, i]() { //
  298. int32_t data0 = FilterAlgoMgr::ins()->processData("心电1", val[0]);
  299. int32_t data1 = FilterAlgoMgr::ins()->processData("心电2", val[1]);
  300. int32_t data2 = FilterAlgoMgr::ins()->processData("心电3", val[2]);
  301. wp2d->addData("心电1", data0, 0);
  302. wp2d->addData("心电2", data1, 0);
  303. wp2d->addData("心电3", data2, 0);
  304. }));
  305. }
  306. }
  307. } else if (m_devicetype == kone_lead_ecg_v2) {
  308. if (!checkok) return;
  309. m1003_heartrate_report_packet_t *heartrate_report = (m1003_heartrate_report_packet_t *)report_packet;
  310. static uint32_t lostpacket = 0;
  311. {
  312. static uint32_t lastpacket_index = 0;
  313. if ((lastpacket_index + heartrate_report->sample_data_num) != (heartrate_report->sample_data_index)) {
  314. lostpacket++;
  315. }
  316. lastpacket_index = heartrate_report->sample_data_index;
  317. }
  318. reportPreviewShow("[preview data ] lost:%d index %d leadoff 0x%x", //
  319. lostpacket, heartrate_report->sample_data_index, heartrate_report->leadoff_state);
  320. // static LPFilterExt_t lp;
  321. // static bool lpenable = false;
  322. // if (!lpenable) {
  323. // LPFilterExt_init(&lp, 40, 0.002, 14, true);
  324. // lpenable = true;
  325. // }
  326. for (int i = 0; i < heartrate_report->sample_data_num; i++) {
  327. // {
  328. // int32_t data = heartrate_report->frame[i] ;
  329. // data = LPFilterExt_update(&lp, data);
  330. // emit doinui_signal(QFunction([this, data, i]() { wp2d->addData("心电2", data, i * 2); }));
  331. // }
  332. {
  333. int32_t data = heartrate_report->frame[i];
  334. data = FilterAlgoMgr::ins()->processData("心电1", data);
  335. emit doinui_signal(QFunction([this, data, i]() { wp2d->addData("心电1", data, i * 2); }));
  336. }
  337. }
  338. }
  339. break;
  340. }
  341. case ify_hrs_report_battery_level: {
  342. reportPreviewShow("[battery_level ]");
  343. break;
  344. }
  345. case ify_hrs_report_low_battey_level: {
  346. reportPreviewShow("[low_battey ]");
  347. break;
  348. }
  349. case ify_hrs_report_sample_finish_end: {
  350. reportPreviewShow("[sample_finish ]");
  351. break;
  352. }
  353. case ify_hrs_report_sensor_drop_detect: {
  354. sensor_drop_event_report_packet_t *sensor_drop_report = (sensor_drop_event_report_packet_t *)report_packet->data;
  355. reportPreviewShow("[sensor_drop ] %s %s", zhex2binary(sensor_drop_report->drop_state0).c_str(), zhex2binary(sensor_drop_report->drop_state1).c_str());
  356. break;
  357. }
  358. case ify_hrs_report_record_upload_end: {
  359. uint32_t checksum = *(uint32_t *)report_packet->data;
  360. reportPreviewShow("[upload end ] checksum: 0x%08x", checksum);
  361. break;
  362. }
  363. default:
  364. break;
  365. }
  366. });
  367. ElectrocardiographTester::ins()->regCh4CheckSumPacketReport([this](uint32_t rxcnt, uint32_t report_packet_checksum) { //
  368. blockDataUploadPreviewShow("RXCNT %d CHECKSUM 0x%08x", rxcnt, report_packet_checksum);
  369. });
  370. ElectrocardiographTester::ins()->regRawDataCB([this](raw_data_type_t type, uint8_t *hex, uint32_t hexlen) {
  371. if (type == kcmd_cmd) {
  372. rawDataPreviewShow("[CMD ] %s", zhex2str(hex, hexlen).c_str());
  373. } else if (type == kcmd_receipt) {
  374. rawDataPreviewShow("[RECEIPT] %s", zhex2str(hex, hexlen).c_str());
  375. } else if (type == kcmd_report) {
  376. rawDataPreviewShow("[REPORT ] %s", zhex2str(hex, hexlen).c_str());
  377. } else if (type == kcmd_ch4_data) {
  378. // rawDataPreviewShow("[CH4 ] %s", zhex2str(hex, hexlen).c_str());
  379. }
  380. });
  381. // FilterCommon_WindowsType
  382. auto windowsTypes = FilterAlgoMgr::ins()->windowsTypes();
  383. for (auto &type : windowsTypes) {
  384. ui->FilterCommon_WindowsType->addItem(type.c_str());
  385. }
  386. }
  387. void MainWindow::processException(zexception &e) { ishow("%s:%s", e.what(), ify_hrs_error_code_to_string((ify_hrs_error_code_t)e.ecode())); }
  388. void MainWindow::on_readDeviceVersion_clicked() {
  389. instructionPreviewClear();
  390. try {
  391. device_version_info_receipt_t version;
  392. ElectrocardiographTester::ins()->readDeviceVersion(&version);
  393. ishow("-------------- version ----------------");
  394. ishow(" blestack_version: %d", version.blestack_version);
  395. ishow(" bootloader_version: %d", version.bootloader_version);
  396. ishow(" firmware_version: %d", version.firmware_version);
  397. ishow(" hardware_version: %d", version.hardware_version);
  398. } catch (zexception &exception) {
  399. processException(exception);
  400. }
  401. }
  402. void MainWindow::on_readDeviceState_clicked() {
  403. instructionPreviewClear();
  404. try {
  405. device_state_receipt_t state;
  406. ElectrocardiographTester::ins()->readDeviceState(&state);
  407. ishow("-------------- state ----------------");
  408. ishow(" drop_state0: %s", zhex2binary(state.drop_state0).c_str());
  409. ishow(" drop_state1: %s", zhex2binary(state.drop_state1).c_str());
  410. ishow(" sampling_state: %d", state.device_state0.sampling_state);
  411. ishow(" report_state: %d", state.device_state0.report_state);
  412. ishow(" low_battery: %d", state.device_state0.low_battery);
  413. ishow(" full_storge: %d", state.device_state0.full_storge);
  414. ishow(" holder: %d", state.device_state0.holder);
  415. ishow(" powerlevel: %d", state.powerlevel);
  416. ishow(" storage_item_num: %d", state.storage_item_num);
  417. } catch (zexception &exception) {
  418. processException(exception);
  419. }
  420. }
  421. void MainWindow::on_readTime_clicked() {
  422. instructionPreviewClear();
  423. try {
  424. read_time_receipt_t time;
  425. ElectrocardiographTester::ins()->readTime(&time);
  426. ishow("-------------- time ----------------");
  427. ishow(" %d/%d/%d %d:%d:%d", time.year + 2000, time.month, time.day, time.hour, time.minute, time.second);
  428. } catch (zexception &exception) {
  429. processException(exception);
  430. }
  431. }
  432. void MainWindow::on_syncTime_clicked() {
  433. instructionPreviewClear();
  434. try {
  435. // 获取系统时间
  436. QDateTime now = QDateTime::currentDateTime();
  437. ElectrocardiographTester::ins()->syncTime(now.date().year() - 2000, now.date().month(), now.date().day(), now.time().hour(), now.time().minute(), now.time().second());
  438. ishow("sync time success!");
  439. } catch (zexception &exception) {
  440. processException(exception);
  441. }
  442. }
  443. std::string zhex2time(const uint8_t *hex, size_t len) {
  444. std::string str;
  445. if (len < 6) return str;
  446. str.append(fmt("%d/%d/%d %2d:%2d:%2d", hex[0] + 2000, hex[1], hex[2], hex[3], hex[4], hex[5]));
  447. return str;
  448. }
  449. void MainWindow::on_readAllRecords_clicked() {
  450. // 读取当前有多少条记录
  451. instructionPreviewClear();
  452. try {
  453. device_state_receipt_t state;
  454. ElectrocardiographTester::ins()->readDeviceState(&state);
  455. ishow("index recordid frameNum dataSize sensorNum captRate captPrec compAlgo checksum");
  456. for (int32_t i = 0; i < state.storage_item_num; i++) {
  457. read_record_info_receipt_t record;
  458. ElectrocardiographTester::ins()->readRecordsInfo(i, &record);
  459. ishow("%d %s %8d %8d %8d %8d %8d %8d 0x%08x", i, zhex2time(record.record_id, 6).c_str(), record.frameNum, record.dataSize, record.sensorNum, record.captureRate, record.capturePrecision, record.compressAlgorithm, record.checksum);
  460. }
  461. } catch (zexception &exception) {
  462. processException(exception);
  463. }
  464. }
  465. void MainWindow::on_startUploadRecord_clicked() {
  466. instructionPreviewClear();
  467. int reportIndex = ui->startUploadRecord_p0->toPlainText().toInt();
  468. try {
  469. read_record_info_receipt_t record;
  470. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  471. ElectrocardiographTester::ins()->startUploadRecord(record.record_id);
  472. ishow("start upload record [%s] success", zhex2time(record.record_id, 6).c_str());
  473. } catch (zexception &exception) {
  474. processException(exception);
  475. }
  476. }
  477. void MainWindow::on_readSensorInfo_clicked() {
  478. instructionPreviewClear();
  479. try {
  480. sensor_info_receipt_t sensor;
  481. ElectrocardiographTester::ins()->readSensorInfo(&sensor);
  482. ishow("-------------- sensor ----------------");
  483. ishow(" sensor_num: %d", sensor.sensor_num);
  484. ishow(" sensor_precision: %d", sensor.sensor_precision);
  485. ishow(" sensor_sample_rate:%d", sensor.sensor_sample_rate);
  486. ishow(" sensor0_pos: %d", sensor.sensor0_pos);
  487. ishow(" sensor1_pos: %d", sensor.sensor1_pos);
  488. ishow(" sensor2_pos: %d", sensor.sensor2_pos);
  489. } catch (zexception &exception) {
  490. processException(exception);
  491. }
  492. }
  493. void MainWindow::on_readSN_clicked() {
  494. instructionPreviewClear();
  495. try {
  496. string sn;
  497. ElectrocardiographTester::ins()->readSn(sn);
  498. ishow("-------------- sn ----------------");
  499. ishow(" sn: %s", sn.c_str());
  500. } catch (zexception &exception) {
  501. processException(exception);
  502. }
  503. }
  504. void MainWindow::on_stopUploadRecord_clicked() {
  505. instructionPreviewClear();
  506. try {
  507. ElectrocardiographTester::ins()->stopUploadRecord();
  508. ishow("stop upload record success");
  509. } catch (zexception &exception) {
  510. processException(exception);
  511. }
  512. }
  513. void MainWindow::on_delRecord_clicked() {
  514. instructionPreviewClear();
  515. int reportIndex = ui->delRecord_p0->toPlainText().toInt();
  516. try {
  517. read_record_info_receipt_t record;
  518. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  519. ElectrocardiographTester::ins()->delRecord(record.record_id);
  520. ishow("delete record [%s] success", zhex2time(record.record_id, 6).c_str());
  521. } catch (zexception &exception) {
  522. processException(exception);
  523. }
  524. }
  525. #if 0
  526. void MainWindow::on_startCapture_clicked() {
  527. instructionPreviewClear();
  528. try {
  529. ElectrocardiographTester::ins()->startCapture();
  530. ishow("start capture success");
  531. } catch (zexception &exception) {
  532. processException(exception);
  533. }
  534. }
  535. void MainWindow::on_stopCapture_clicked() {
  536. instructionPreviewClear();
  537. try {
  538. ElectrocardiographTester::ins()->stopCapture();
  539. ishow("stop capture success");
  540. } catch (zexception &exception) {
  541. processException(exception);
  542. }
  543. }
  544. #endif
  545. void MainWindow::on_startRealtimeReport_clicked() {
  546. instructionPreviewClear();
  547. try {
  548. wp2d->show();
  549. ElectrocardiographTester::ins()->startRealtimeReport();
  550. ishow("start realtime report success");
  551. } catch (zexception &exception) {
  552. processException(exception);
  553. }
  554. }
  555. void MainWindow::on_stopRealtimeReport_clicked() {
  556. instructionPreviewClear();
  557. try {
  558. ElectrocardiographTester::ins()->stopRealtimeReport();
  559. ishow("stop realtime report success");
  560. // wp2d->hide();
  561. } catch (zexception &exception) {
  562. processException(exception);
  563. }
  564. }
  565. void MainWindow::on_clearPreview_clicked() {
  566. ui->reportPreview->document()->clear();
  567. ui->uploadDataPreview->document()->clear();
  568. ui->rawDataPreview->document()->clear();
  569. ui->instructionPreview->document()->clear();
  570. }
  571. void MainWindow::on_TestCmd_readSubIcRegs_clicked() {
  572. instructionPreviewClear();
  573. try {
  574. uint8_t data[12];
  575. data[ADS129X_REG_ID] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_ID);
  576. data[ADS129X_REG_CONFIG1] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG1);
  577. data[ADS129X_REG_CONFIG2] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG2);
  578. data[ADS129X_REG_LOFF] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFF);
  579. data[ADS129X_REG_CH1SET] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH1SET);
  580. data[ADS129X_REG_CH2SET] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH2SET);
  581. data[ADS129X_REG_RLDSENS] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RLDSENS);
  582. data[ADS129X_REG_LOFFSENS] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFFSENS);
  583. data[ADS129X_REG_LOFFSTAT] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFFSTAT);
  584. data[ADS129X_REG_RESP1] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RESP1);
  585. data[ADS129X_REG_RESP2] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RESP2);
  586. data[ADS129X_REG_GPIO] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_GPIO);
  587. ishow("reg %10s %02d: 0x%02x", "ID", ADS129X_REG_ID, data[ADS129X_REG_ID]);
  588. ishow("reg %10s %02d: 0x%02x", "CONFIG1", ADS129X_REG_CONFIG1, data[ADS129X_REG_CONFIG1]);
  589. ishow("reg %10s %02d: 0x%02x", "CONFIG2", ADS129X_REG_CONFIG2, data[ADS129X_REG_CONFIG2]);
  590. ishow("reg %10s %02d: 0x%02x", "LOFF", ADS129X_REG_LOFF, data[ADS129X_REG_LOFF]);
  591. ishow("reg %10s %02d: 0x%02x", "CH1SET", ADS129X_REG_CH1SET, data[ADS129X_REG_CH1SET]);
  592. ishow("reg %10s %02d: 0x%02x", "CH2SET", ADS129X_REG_CH2SET, data[ADS129X_REG_CH2SET]);
  593. ishow("reg %10s %02d: 0x%02x", "RLDSENS", ADS129X_REG_RLDSENS, data[ADS129X_REG_RLDSENS]);
  594. ishow("reg %10s %02d: 0x%02x", "LOFFSENS", ADS129X_REG_LOFFSENS, data[ADS129X_REG_LOFFSENS]);
  595. ishow("reg %10s %02d: 0x%02x %s", "LOFFSTAT", ADS129X_REG_LOFFSTAT, data[ADS129X_REG_LOFFSTAT], zhex2binary(data[ADS129X_REG_LOFFSTAT]).c_str());
  596. ishow("reg %10s %02d: 0x%02x", "RESP1", ADS129X_REG_RESP1, data[ADS129X_REG_RESP1]);
  597. ishow("reg %10s %02d: 0x%02x", "RESP2", ADS129X_REG_RESP2, data[ADS129X_REG_RESP2]);
  598. ishow("reg %10s %02d: 0x%02x", "GPIO", ADS129X_REG_GPIO, data[ADS129X_REG_GPIO]);
  599. ishow("regs: %s", zhex2str(data, 12).c_str());
  600. } catch (zexception &exception) {
  601. processException(exception);
  602. }
  603. }
  604. void MainWindow::on_TestCmd_writeSubICReg_clicked() {
  605. uint32_t add = str2int(ui->TestCmd_writeSubICReg_p0->toPlainText());
  606. uint32_t val = str2int(ui->TestCmd_writeSubICReg_p1->toPlainText());
  607. instructionPreviewClear();
  608. try {
  609. ElectrocardiographTester::ins()->ecg_subic_write_reg(add, val);
  610. ishow("write reg %d: 0x%02x success", add, val);
  611. } catch (zexception &exception) {
  612. processException(exception);
  613. }
  614. }
  615. void MainWindow::on_TestCmd_writeSubICRegMask_clicked() {
  616. uint8_t add = ui->TestCmd_writeSubICRegMask_p0->toPlainText().toInt();
  617. uint8_t off = ui->TestCmd_writeSubICRegMask_p1->toPlainText().toInt();
  618. uint8_t bitnum = ui->TestCmd_writeSubICRegMask_p2->toPlainText().toInt();
  619. uint8_t val = ui->TestCmd_writeSubICRegMask_p3->toPlainText().toInt();
  620. instructionPreviewClear();
  621. try {
  622. uint8_t regval = ElectrocardiographTester::ins()->ecg_subic_read_reg(add);
  623. uint8_t oldval = regval;
  624. uint8_t mask = (1 << bitnum) - 1;
  625. mask = mask << off;
  626. regval = regval & (~mask);
  627. regval = regval | (val << off);
  628. ElectrocardiographTester::ins()->ecg_subic_write_reg(add, regval);
  629. ishow("write reg %d: 0x%02x -> 0x%02x success", add, oldval, regval);
  630. } catch (const std::exception &e) {
  631. std::cerr << e.what() << '\n';
  632. }
  633. }
  634. void MainWindow::on_TestCmd_startCapture_clicked() {
  635. instructionPreviewClear();
  636. try {
  637. ElectrocardiographTester::ins()->testCmdStartCapture();
  638. ishow("call start capture success");
  639. wp2d->show();
  640. } catch (zexception &exception) {
  641. processException(exception);
  642. }
  643. }
  644. void MainWindow::on_TestCmd_stopCapture_clicked() {
  645. instructionPreviewClear();
  646. try {
  647. ElectrocardiographTester::ins()->testCmdStopCapture();
  648. ishow("call stop capture success");
  649. } catch (zexception &exception) {
  650. processException(exception);
  651. }
  652. }
  653. void MainWindow::on_TestCmd_changeECGSrcToSquareWave_clicked() {
  654. instructionPreviewClear();
  655. try {
  656. uint8_t cfg2 = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG2);
  657. uint8_t ch1set = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH1SET);
  658. cfg2 = ADS129X_SET_BITS(cfg2, ADS129X_INT_TEST, ADS129X_INT_TEST_ON);
  659. cfg2 = ADS129X_SET_BITS(cfg2, ADS129X_INT_FREQ, ADS129X_INT_FREQ_AC);
  660. ch1set = ADS129X_SET_BITS(ch1set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST);
  661. ElectrocardiographTester::ins()->ecg_subic_write_reg(ADS129X_REG_CONFIG2, cfg2);
  662. ElectrocardiographTester::ins()->ecg_subic_write_reg(ADS129X_REG_CH1SET, ch1set);
  663. ishow("call change ECG src to square wave success");
  664. } catch (zexception &exception) {
  665. processException(exception);
  666. }
  667. }
  668. void MainWindow::on_resetDevice_clicked() {
  669. instructionPreviewClear();
  670. try {
  671. ElectrocardiographTester::ins()->reset();
  672. } catch (zexception &exception) {
  673. // processException(exception);
  674. }
  675. ishow("call reset device success");
  676. }
  677. void MainWindow::on_FilterUpdateParameter_clicked() {
  678. instructionPreviewClear();
  679. FilterAlgoMgr::ins()->setSampleTimeMs(ui->FilterCommon_SampleTimeMs->text().toFloat());
  680. FilterAlgoMgr::ins()->LPFilter_setEnable(ui->LPFilter_Enable->isChecked());
  681. FilterAlgoMgr::ins()->LPFilter_setCutoffFreqHz(ui->LPFilter_CutoffFreqHz->text().toFloat());
  682. FilterAlgoMgr::ins()->LPFilter_setOrder(ui->LPFilter_Order->text().toInt());
  683. FilterAlgoMgr::ins()->HPFilter_setEnable(ui->HPFilter_Enable->isChecked());
  684. FilterAlgoMgr::ins()->HPFilter_setCutoffFreqHz(ui->HPFilter_CutoffFreqHz->text().toFloat());
  685. FilterAlgoMgr::ins()->HPFilter_setOrder(ui->HPFilter_Order->text().toInt());
  686. FilterAlgoMgr::ins()->NOTCHFilter_setEnable(ui->NOTCHFilter_Enable->isChecked());
  687. FilterAlgoMgr::ins()->NOTCHFilter_setCenterFreqHz(ui->NOTCHFilter_CenterFreqHz->text().toFloat());
  688. FilterAlgoMgr::ins()->NOTCHFilter_setNotchWidthHz(ui->NOTCHFilter_NotchWidthHz->text().toFloat());
  689. FilterAlgoMgr::ins()->NOTCHFilter_setOrder(ui->NOTCHFilter_Order->text().toInt());
  690. FilterAlgoMgr::ins()->setWindowsSize(ui->FilterCommon_windowsSize->text().toInt());
  691. FilterAlgoMgr::ins()->setWindowsType(ui->FilterCommon_WindowsType->currentText().toStdString());
  692. FilterAlgoMgr::ins()->SmoothingFilter_setEnable(ui->SmoothingFilter_Enable->isChecked());
  693. FilterAlgoMgr::ins()->SmoothingFilter_setWindowsSize(ui->SmoothingFilter_WindowsSize->text().toInt());
  694. FilterAlgoMgr::ins()->BaselineDriftRemoval_setEnable(ui->BaselineDriftRemoval_Enable->isChecked());
  695. FilterAlgoMgr::ins()->BaselineDriftRemoval_setWindowsSize(ui->BaselineDriftRemoval_WindowsSize->text().toInt());
  696. FilterAlgoMgr::ins()->MedianFilter_setEnable(ui->MedianFilter_Enable->isChecked());
  697. FilterAlgoMgr::ins()->MedianFilter_setWindowsSize(ui->MedianFilter_WindowsSize->text().toInt());
  698. FilterAlgoMgr::ins()->updateParameter();
  699. on_buttonTabWidget_currentChanged(0);
  700. ishow("Filter Update Parameter success");
  701. }
  702. void MainWindow::on_buttonTabWidget_currentChanged(int index) {
  703. ui->FilterCommon_SampleTimeMs->setText(QString::number(FilterAlgoMgr::ins()->getSampleTimeMs()));
  704. ui->LPFilter_Enable->setChecked(FilterAlgoMgr::ins()->LPFilter_getEnable());
  705. ui->LPFilter_CutoffFreqHz->setText(QString::number(FilterAlgoMgr::ins()->LPFilter_getCutoffFreqHz()));
  706. ui->LPFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->LPFilter_getOrder()));
  707. ui->HPFilter_Enable->setChecked(FilterAlgoMgr::ins()->HPFilter_getEnable());
  708. ui->HPFilter_CutoffFreqHz->setText(QString::number(FilterAlgoMgr::ins()->HPFilter_getCutoffFreqHz()));
  709. ui->HPFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->HPFilter_getOrder()));
  710. ui->NOTCHFilter_Enable->setChecked(FilterAlgoMgr::ins()->NOTCHFilter_getEnable());
  711. ui->NOTCHFilter_CenterFreqHz->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getCenterFreqHz()));
  712. ui->NOTCHFilter_NotchWidthHz->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getNotchWidthHz()));
  713. ui->NOTCHFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getOrder()));
  714. ui->FilterCommon_windowsSize->setText(QString::number(FilterAlgoMgr::ins()->getWindowsSize()));
  715. ui->FilterCommon_WindowsType->setCurrentText(QString::fromStdString(FilterAlgoMgr::ins()->getWindowType()));
  716. ui->SmoothingFilter_Enable->setChecked(FilterAlgoMgr::ins()->SmoothingFilter_getEnable());
  717. ui->SmoothingFilter_WindowsSize->setText(QString::number(FilterAlgoMgr::ins()->SmoothingFilter_getWindowsSize()));
  718. ui->BaselineDriftRemoval_Enable->setChecked(FilterAlgoMgr::ins()->BaselineDriftRemoval_getEnable());
  719. ui->BaselineDriftRemoval_WindowsSize->setText(QString::number(FilterAlgoMgr::ins()->BaselineDriftRemoval_getWindowsSize()));
  720. ui->MedianFilter_Enable->setChecked(FilterAlgoMgr::ins()->MedianFilter_getEnable());
  721. ui->MedianFilter_WindowsSize->setText(QString::number(FilterAlgoMgr::ins()->MedianFilter_getWindowsSize()));
  722. }
  723. void MainWindow::on_TestCmd_writeSubICAllReg_clicked() {
  724. // 0x52,0x02,0xe0,0xF1,0x00,0x80,0x00,0x03,0x12,0x02,0x07,0x0c
  725. instructionPreviewClear();
  726. QString regs = ui->TestCmd_writeSubICAllReg_p0->toPlainText();
  727. QStringList reglist = regs.split(",");
  728. if (reglist.size() != 12) {
  729. ishow("reg size error %d != 12", reglist.size());
  730. return;
  731. }
  732. try {
  733. uint8_t data[12];
  734. for (int i = 0; i < 12; i++) {
  735. data[i] = str2int(reglist[i]);
  736. }
  737. for (size_t i = 0; i < 12; i++) {
  738. ElectrocardiographTester::ins()->ecg_subic_write_reg(i, data[i]);
  739. ishow("write reg %d: 0x%02x success", i, data[i]);
  740. }
  741. ishow("write all reg success");
  742. } catch (zexception &exception) {
  743. processException(exception);
  744. }
  745. }
  746. void MainWindow::on_setEcgInTestMode_clicked() {
  747. instructionPreviewClear();
  748. try {
  749. ElectrocardiographTester::ins()->set_ecg_in_test_mode(1);
  750. ishow("set ECG in test mode success");
  751. } catch (zexception &exception) {
  752. processException(exception);
  753. }
  754. }
  755. void MainWindow::on_setEcgInNormalMode_clicked() {
  756. instructionPreviewClear();
  757. try {
  758. ElectrocardiographTester::ins()->set_ecg_in_test_mode(0);
  759. ishow("set ECG in test mode success");
  760. } catch (zexception &exception) {
  761. processException(exception);
  762. }
  763. }
  764. void MainWindow::on_setEcgReportDataInRawMode__1_clicked() {
  765. instructionPreviewClear();
  766. try {
  767. ElectrocardiographTester::ins()->set_ecg_report_data_in_raw_mode(1);
  768. ishow("set_ecg_report_data_in_raw_mode(1) success");
  769. } catch (zexception &exception) {
  770. processException(exception);
  771. }
  772. }
  773. void MainWindow::on_setEcgReportDataInRawMode__0_clicked() {
  774. instructionPreviewClear();
  775. try {
  776. ElectrocardiographTester::ins()->set_ecg_report_data_in_raw_mode(0);
  777. ishow("set_ecg_report_data_in_raw_mode(0) success");
  778. } catch (zexception &exception) {
  779. processException(exception);
  780. }
  781. }