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.

860 lines
33 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. #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. if ((lastpacket_index + 5) != (heartrate_report->sample_data_index)) {
  282. lostpacket++;
  283. }
  284. lastpacket_index = heartrate_report->sample_data_index;
  285. reportPreviewShow("[preview data ] lost:%d index %d", lostpacket, heartrate_report->sample_data_index);
  286. } else if (m_devicetype == kone_lead_ecg_v2) {
  287. if (!checkok) return;
  288. m1003_heartrate_report_packet_t *heartrate_report = (m1003_heartrate_report_packet_t *)report_packet;
  289. static uint32_t lostpacket = 0;
  290. {
  291. static uint32_t lastpacket_index = 0;
  292. if ((lastpacket_index + heartrate_report->sample_data_num) != (heartrate_report->sample_data_index)) {
  293. lostpacket++;
  294. }
  295. lastpacket_index = heartrate_report->sample_data_index;
  296. }
  297. reportPreviewShow("[preview data ] lost:%d index %d leadoff 0x%x", //
  298. lostpacket, heartrate_report->sample_data_index, heartrate_report->leadoff_state);
  299. // static LPFilterExt_t lp;
  300. // static bool lpenable = false;
  301. // if (!lpenable) {
  302. // LPFilterExt_init(&lp, 40, 0.002, 14, true);
  303. // lpenable = true;
  304. // }
  305. for (int i = 0; i < heartrate_report->sample_data_num; i++) {
  306. // {
  307. // int32_t data = heartrate_report->frame[i] ;
  308. // data = LPFilterExt_update(&lp, data);
  309. // emit doinui_signal(QFunction([this, data, i]() { wp2d->addData("心电2", data, i * 2); }));
  310. // }
  311. {
  312. int32_t data = heartrate_report->frame[i];
  313. data = FilterAlgoMgr::ins()->processData("心电1", data);
  314. emit doinui_signal(QFunction([this, data, i]() { wp2d->addData("心电1", data, i * 2); }));
  315. }
  316. }
  317. }
  318. break;
  319. }
  320. case ify_hrs_report_battery_level: {
  321. reportPreviewShow("[battery_level ]");
  322. break;
  323. }
  324. case ify_hrs_report_low_battey_level: {
  325. reportPreviewShow("[low_battey ]");
  326. break;
  327. }
  328. case ify_hrs_report_sample_finish_end: {
  329. reportPreviewShow("[sample_finish ]");
  330. break;
  331. }
  332. case ify_hrs_report_sensor_drop_detect: {
  333. sensor_drop_event_report_packet_t *sensor_drop_report = (sensor_drop_event_report_packet_t *)report_packet->data;
  334. reportPreviewShow("[sensor_drop ] %s %s", zhex2binary(sensor_drop_report->drop_state0).c_str(), zhex2binary(sensor_drop_report->drop_state1).c_str());
  335. break;
  336. }
  337. case ify_hrs_report_record_upload_end: {
  338. uint32_t checksum = *(uint32_t *)report_packet->data;
  339. reportPreviewShow("[upload end ] checksum: 0x%08x", checksum);
  340. break;
  341. }
  342. default:
  343. break;
  344. }
  345. });
  346. ElectrocardiographTester::ins()->regCh4CheckSumPacketReport([this](uint32_t rxcnt, uint32_t report_packet_checksum) { //
  347. blockDataUploadPreviewShow("RXCNT %d CHECKSUM 0x%08x", rxcnt, report_packet_checksum);
  348. });
  349. ElectrocardiographTester::ins()->regRawDataCB([this](raw_data_type_t type, uint8_t *hex, uint32_t hexlen) {
  350. if (type == kcmd_cmd) {
  351. rawDataPreviewShow("[CMD ] %s", zhex2str(hex, hexlen).c_str());
  352. } else if (type == kcmd_receipt) {
  353. rawDataPreviewShow("[RECEIPT] %s", zhex2str(hex, hexlen).c_str());
  354. } else if (type == kcmd_report) {
  355. rawDataPreviewShow("[REPORT ] %s", zhex2str(hex, hexlen).c_str());
  356. } else if (type == kcmd_ch4_data) {
  357. // rawDataPreviewShow("[CH4 ] %s", zhex2str(hex, hexlen).c_str());
  358. }
  359. });
  360. // FilterCommon_WindowsType
  361. auto windowsTypes = FilterAlgoMgr::ins()->windowsTypes();
  362. for (auto &type : windowsTypes) {
  363. ui->FilterCommon_WindowsType->addItem(type.c_str());
  364. }
  365. }
  366. void MainWindow::processException(zexception &e) { ishow("%s:%s", e.what(), ify_hrs_error_code_to_string((ify_hrs_error_code_t)e.ecode())); }
  367. void MainWindow::on_readDeviceVersion_clicked() {
  368. instructionPreviewClear();
  369. try {
  370. device_version_info_receipt_t version;
  371. ElectrocardiographTester::ins()->readDeviceVersion(&version);
  372. ishow("-------------- version ----------------");
  373. ishow(" blestack_version: %d", version.blestack_version);
  374. ishow(" bootloader_version: %d", version.bootloader_version);
  375. ishow(" firmware_version: %d", version.firmware_version);
  376. ishow(" hardware_version: %d", version.hardware_version);
  377. } catch (zexception &exception) {
  378. processException(exception);
  379. }
  380. }
  381. void MainWindow::on_readDeviceState_clicked() {
  382. instructionPreviewClear();
  383. try {
  384. device_state_receipt_t state;
  385. ElectrocardiographTester::ins()->readDeviceState(&state);
  386. ishow("-------------- state ----------------");
  387. ishow(" drop_state0: %s", zhex2binary(state.drop_state0).c_str());
  388. ishow(" drop_state1: %s", zhex2binary(state.drop_state1).c_str());
  389. ishow(" sampling_state: %d", state.device_state0.sampling_state);
  390. ishow(" report_state: %d", state.device_state0.report_state);
  391. ishow(" low_battery: %d", state.device_state0.low_battery);
  392. ishow(" full_storge: %d", state.device_state0.full_storge);
  393. ishow(" holder: %d", state.device_state0.holder);
  394. ishow(" powerlevel: %d", state.powerlevel);
  395. ishow(" storage_item_num: %d", state.storage_item_num);
  396. } catch (zexception &exception) {
  397. processException(exception);
  398. }
  399. }
  400. void MainWindow::on_readTime_clicked() {
  401. instructionPreviewClear();
  402. try {
  403. read_time_receipt_t time;
  404. ElectrocardiographTester::ins()->readTime(&time);
  405. ishow("-------------- time ----------------");
  406. ishow(" %d/%d/%d %d:%d:%d", time.year + 2000, time.month, time.day, time.hour, time.minute, time.second);
  407. } catch (zexception &exception) {
  408. processException(exception);
  409. }
  410. }
  411. void MainWindow::on_syncTime_clicked() {
  412. instructionPreviewClear();
  413. try {
  414. // 获取系统时间
  415. QDateTime now = QDateTime::currentDateTime();
  416. ElectrocardiographTester::ins()->syncTime(now.date().year() - 2000, now.date().month(), now.date().day(), now.time().hour(), now.time().minute(), now.time().second());
  417. ishow("sync time success!");
  418. } catch (zexception &exception) {
  419. processException(exception);
  420. }
  421. }
  422. std::string zhex2time(const uint8_t *hex, size_t len) {
  423. std::string str;
  424. if (len < 6) return str;
  425. str.append(fmt("%d/%d/%d %2d:%2d:%2d", hex[0] + 2000, hex[1], hex[2], hex[3], hex[4], hex[5]));
  426. return str;
  427. }
  428. void MainWindow::on_readAllRecords_clicked() {
  429. // 读取当前有多少条记录
  430. instructionPreviewClear();
  431. try {
  432. device_state_receipt_t state;
  433. ElectrocardiographTester::ins()->readDeviceState(&state);
  434. ishow("index recordid frameNum dataSize sensorNum captRate captPrec compAlgo checksum");
  435. for (int32_t i = 0; i < state.storage_item_num; i++) {
  436. read_record_info_receipt_t record;
  437. ElectrocardiographTester::ins()->readRecordsInfo(i, &record);
  438. 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);
  439. }
  440. } catch (zexception &exception) {
  441. processException(exception);
  442. }
  443. }
  444. void MainWindow::on_startUploadRecord_clicked() {
  445. instructionPreviewClear();
  446. int reportIndex = ui->startUploadRecord_p0->toPlainText().toInt();
  447. try {
  448. read_record_info_receipt_t record;
  449. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  450. ElectrocardiographTester::ins()->startUploadRecord(record.record_id);
  451. ishow("start upload record [%s] success", zhex2time(record.record_id, 6).c_str());
  452. } catch (zexception &exception) {
  453. processException(exception);
  454. }
  455. }
  456. void MainWindow::on_readSensorInfo_clicked() {
  457. instructionPreviewClear();
  458. try {
  459. sensor_info_receipt_t sensor;
  460. ElectrocardiographTester::ins()->readSensorInfo(&sensor);
  461. ishow("-------------- sensor ----------------");
  462. ishow(" sensor_num: %d", sensor.sensor_num);
  463. ishow(" sensor_precision: %d", sensor.sensor_precision);
  464. ishow(" sensor_sample_rate:%d", sensor.sensor_sample_rate);
  465. ishow(" sensor0_pos: %d", sensor.sensor0_pos);
  466. ishow(" sensor1_pos: %d", sensor.sensor1_pos);
  467. ishow(" sensor2_pos: %d", sensor.sensor2_pos);
  468. } catch (zexception &exception) {
  469. processException(exception);
  470. }
  471. }
  472. void MainWindow::on_readSN_clicked() {
  473. instructionPreviewClear();
  474. try {
  475. string sn;
  476. ElectrocardiographTester::ins()->readSn(sn);
  477. ishow("-------------- sn ----------------");
  478. ishow(" sn: %s", sn.c_str());
  479. } catch (zexception &exception) {
  480. processException(exception);
  481. }
  482. }
  483. void MainWindow::on_stopUploadRecord_clicked() {
  484. instructionPreviewClear();
  485. try {
  486. ElectrocardiographTester::ins()->stopUploadRecord();
  487. ishow("stop upload record success");
  488. } catch (zexception &exception) {
  489. processException(exception);
  490. }
  491. }
  492. void MainWindow::on_delRecord_clicked() {
  493. instructionPreviewClear();
  494. int reportIndex = ui->delRecord_p0->toPlainText().toInt();
  495. try {
  496. read_record_info_receipt_t record;
  497. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  498. ElectrocardiographTester::ins()->delRecord(record.record_id);
  499. ishow("delete record [%s] success", zhex2time(record.record_id, 6).c_str());
  500. } catch (zexception &exception) {
  501. processException(exception);
  502. }
  503. }
  504. #if 0
  505. void MainWindow::on_startCapture_clicked() {
  506. instructionPreviewClear();
  507. try {
  508. ElectrocardiographTester::ins()->startCapture();
  509. ishow("start capture success");
  510. } catch (zexception &exception) {
  511. processException(exception);
  512. }
  513. }
  514. void MainWindow::on_stopCapture_clicked() {
  515. instructionPreviewClear();
  516. try {
  517. ElectrocardiographTester::ins()->stopCapture();
  518. ishow("stop capture success");
  519. } catch (zexception &exception) {
  520. processException(exception);
  521. }
  522. }
  523. #endif
  524. void MainWindow::on_startRealtimeReport_clicked() {
  525. instructionPreviewClear();
  526. try {
  527. wp2d->show();
  528. ElectrocardiographTester::ins()->startRealtimeReport();
  529. ishow("start realtime report success");
  530. } catch (zexception &exception) {
  531. processException(exception);
  532. }
  533. }
  534. void MainWindow::on_stopRealtimeReport_clicked() {
  535. instructionPreviewClear();
  536. try {
  537. ElectrocardiographTester::ins()->stopRealtimeReport();
  538. ishow("stop realtime report success");
  539. // wp2d->hide();
  540. } catch (zexception &exception) {
  541. processException(exception);
  542. }
  543. }
  544. void MainWindow::on_clearPreview_clicked() {
  545. ui->reportPreview->document()->clear();
  546. ui->uploadDataPreview->document()->clear();
  547. ui->rawDataPreview->document()->clear();
  548. ui->instructionPreview->document()->clear();
  549. }
  550. void MainWindow::on_TestCmd_readSubIcRegs_clicked() {
  551. instructionPreviewClear();
  552. try {
  553. uint8_t data[12];
  554. data[ADS129X_REG_ID] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_ID);
  555. data[ADS129X_REG_CONFIG1] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG1);
  556. data[ADS129X_REG_CONFIG2] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG2);
  557. data[ADS129X_REG_LOFF] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFF);
  558. data[ADS129X_REG_CH1SET] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH1SET);
  559. data[ADS129X_REG_CH2SET] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH2SET);
  560. data[ADS129X_REG_RLDSENS] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RLDSENS);
  561. data[ADS129X_REG_LOFFSENS] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFFSENS);
  562. data[ADS129X_REG_LOFFSTAT] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFFSTAT);
  563. data[ADS129X_REG_RESP1] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RESP1);
  564. data[ADS129X_REG_RESP2] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RESP2);
  565. data[ADS129X_REG_GPIO] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_GPIO);
  566. ishow("reg %10s %02d: 0x%02x", "ID", ADS129X_REG_ID, data[ADS129X_REG_ID]);
  567. ishow("reg %10s %02d: 0x%02x", "CONFIG1", ADS129X_REG_CONFIG1, data[ADS129X_REG_CONFIG1]);
  568. ishow("reg %10s %02d: 0x%02x", "CONFIG2", ADS129X_REG_CONFIG2, data[ADS129X_REG_CONFIG2]);
  569. ishow("reg %10s %02d: 0x%02x", "LOFF", ADS129X_REG_LOFF, data[ADS129X_REG_LOFF]);
  570. ishow("reg %10s %02d: 0x%02x", "CH1SET", ADS129X_REG_CH1SET, data[ADS129X_REG_CH1SET]);
  571. ishow("reg %10s %02d: 0x%02x", "CH2SET", ADS129X_REG_CH2SET, data[ADS129X_REG_CH2SET]);
  572. ishow("reg %10s %02d: 0x%02x", "RLDSENS", ADS129X_REG_RLDSENS, data[ADS129X_REG_RLDSENS]);
  573. ishow("reg %10s %02d: 0x%02x", "LOFFSENS", ADS129X_REG_LOFFSENS, data[ADS129X_REG_LOFFSENS]);
  574. ishow("reg %10s %02d: 0x%02x %s", "LOFFSTAT", ADS129X_REG_LOFFSTAT, data[ADS129X_REG_LOFFSTAT], zhex2binary(data[ADS129X_REG_LOFFSTAT]).c_str());
  575. ishow("reg %10s %02d: 0x%02x", "RESP1", ADS129X_REG_RESP1, data[ADS129X_REG_RESP1]);
  576. ishow("reg %10s %02d: 0x%02x", "RESP2", ADS129X_REG_RESP2, data[ADS129X_REG_RESP2]);
  577. ishow("reg %10s %02d: 0x%02x", "GPIO", ADS129X_REG_GPIO, data[ADS129X_REG_GPIO]);
  578. ishow("regs: %s", zhex2str(data, 12).c_str());
  579. } catch (zexception &exception) {
  580. processException(exception);
  581. }
  582. }
  583. void MainWindow::on_TestCmd_writeSubICReg_clicked() {
  584. uint32_t add = str2int(ui->TestCmd_writeSubICReg_p0->toPlainText());
  585. uint32_t val = str2int(ui->TestCmd_writeSubICReg_p1->toPlainText());
  586. instructionPreviewClear();
  587. try {
  588. ElectrocardiographTester::ins()->ecg_subic_write_reg(add, val);
  589. ishow("write reg %d: 0x%02x success", add, val);
  590. } catch (zexception &exception) {
  591. processException(exception);
  592. }
  593. }
  594. void MainWindow::on_TestCmd_writeSubICRegMask_clicked() {
  595. uint8_t add = ui->TestCmd_writeSubICRegMask_p0->toPlainText().toInt();
  596. uint8_t off = ui->TestCmd_writeSubICRegMask_p1->toPlainText().toInt();
  597. uint8_t bitnum = ui->TestCmd_writeSubICRegMask_p2->toPlainText().toInt();
  598. uint8_t val = ui->TestCmd_writeSubICRegMask_p3->toPlainText().toInt();
  599. instructionPreviewClear();
  600. try {
  601. uint8_t regval = ElectrocardiographTester::ins()->ecg_subic_read_reg(add);
  602. uint8_t oldval = regval;
  603. uint8_t mask = (1 << bitnum) - 1;
  604. mask = mask << off;
  605. regval = regval & (~mask);
  606. regval = regval | (val << off);
  607. ElectrocardiographTester::ins()->ecg_subic_write_reg(add, regval);
  608. ishow("write reg %d: 0x%02x -> 0x%02x success", add, oldval, regval);
  609. } catch (const std::exception &e) {
  610. std::cerr << e.what() << '\n';
  611. }
  612. }
  613. void MainWindow::on_TestCmd_startCapture_clicked() {
  614. instructionPreviewClear();
  615. try {
  616. ElectrocardiographTester::ins()->testCmdStartCapture();
  617. ishow("call start capture success");
  618. wp2d->show();
  619. } catch (zexception &exception) {
  620. processException(exception);
  621. }
  622. }
  623. void MainWindow::on_TestCmd_stopCapture_clicked() {
  624. instructionPreviewClear();
  625. try {
  626. ElectrocardiographTester::ins()->testCmdStopCapture();
  627. ishow("call stop capture success");
  628. } catch (zexception &exception) {
  629. processException(exception);
  630. }
  631. }
  632. void MainWindow::on_TestCmd_changeECGSrcToSquareWave_clicked() {
  633. instructionPreviewClear();
  634. try {
  635. uint8_t cfg2 = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG2);
  636. uint8_t ch1set = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH1SET);
  637. cfg2 = ADS129X_SET_BITS(cfg2, ADS129X_INT_TEST, ADS129X_INT_TEST_ON);
  638. cfg2 = ADS129X_SET_BITS(cfg2, ADS129X_INT_FREQ, ADS129X_INT_FREQ_AC);
  639. ch1set = ADS129X_SET_BITS(ch1set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST);
  640. ElectrocardiographTester::ins()->ecg_subic_write_reg(ADS129X_REG_CONFIG2, cfg2);
  641. ElectrocardiographTester::ins()->ecg_subic_write_reg(ADS129X_REG_CH1SET, ch1set);
  642. ishow("call change ECG src to square wave success");
  643. } catch (zexception &exception) {
  644. processException(exception);
  645. }
  646. }
  647. void MainWindow::on_resetDevice_clicked() {
  648. instructionPreviewClear();
  649. try {
  650. ElectrocardiographTester::ins()->reset();
  651. } catch (zexception &exception) {
  652. // processException(exception);
  653. }
  654. ishow("call reset device success");
  655. }
  656. void MainWindow::on_FilterUpdateParameter_clicked() {
  657. instructionPreviewClear();
  658. FilterAlgoMgr::ins()->setSampleTimeMs(ui->FilterCommon_SampleTimeMs->text().toFloat());
  659. FilterAlgoMgr::ins()->LPFilter_setEnable(ui->LPFilter_Enable->isChecked());
  660. FilterAlgoMgr::ins()->LPFilter_setCutoffFreqHz(ui->LPFilter_CutoffFreqHz->text().toFloat());
  661. FilterAlgoMgr::ins()->LPFilter_setOrder(ui->LPFilter_Order->text().toInt());
  662. FilterAlgoMgr::ins()->HPFilter_setEnable(ui->HPFilter_Enable->isChecked());
  663. FilterAlgoMgr::ins()->HPFilter_setCutoffFreqHz(ui->HPFilter_CutoffFreqHz->text().toFloat());
  664. FilterAlgoMgr::ins()->HPFilter_setOrder(ui->HPFilter_Order->text().toInt());
  665. FilterAlgoMgr::ins()->NOTCHFilter_setEnable(ui->NOTCHFilter_Enable->isChecked());
  666. FilterAlgoMgr::ins()->NOTCHFilter_setCenterFreqHz(ui->NOTCHFilter_CenterFreqHz->text().toFloat());
  667. FilterAlgoMgr::ins()->NOTCHFilter_setNotchWidthHz(ui->NOTCHFilter_NotchWidthHz->text().toFloat());
  668. FilterAlgoMgr::ins()->NOTCHFilter_setOrder(ui->NOTCHFilter_Order->text().toInt());
  669. FilterAlgoMgr::ins()->setWindowsSize(ui->FilterCommon_windowsSize->text().toInt());
  670. FilterAlgoMgr::ins()->setWindowsType(ui->FilterCommon_WindowsType->currentText().toStdString());
  671. FilterAlgoMgr::ins()->SmoothingFilter_setEnable(ui->SmoothingFilter_Enable->isChecked());
  672. FilterAlgoMgr::ins()->SmoothingFilter_setWindowsSize(ui->SmoothingFilter_WindowsSize->text().toInt());
  673. FilterAlgoMgr::ins()->BaselineDriftRemoval_setEnable(ui->BaselineDriftRemoval_Enable->isChecked());
  674. FilterAlgoMgr::ins()->BaselineDriftRemoval_setWindowsSize(ui->BaselineDriftRemoval_WindowsSize->text().toInt());
  675. FilterAlgoMgr::ins()->updateParameter();
  676. on_buttonTabWidget_currentChanged(0);
  677. ishow("Filter Update Parameter success");
  678. }
  679. void MainWindow::on_buttonTabWidget_currentChanged(int index) {
  680. ui->FilterCommon_SampleTimeMs->setText(QString::number(FilterAlgoMgr::ins()->getSampleTimeMs()));
  681. ui->LPFilter_Enable->setChecked(FilterAlgoMgr::ins()->LPFilter_getEnable());
  682. ui->LPFilter_CutoffFreqHz->setText(QString::number(FilterAlgoMgr::ins()->LPFilter_getCutoffFreqHz()));
  683. ui->LPFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->LPFilter_getOrder()));
  684. ui->HPFilter_Enable->setChecked(FilterAlgoMgr::ins()->HPFilter_getEnable());
  685. ui->HPFilter_CutoffFreqHz->setText(QString::number(FilterAlgoMgr::ins()->HPFilter_getCutoffFreqHz()));
  686. ui->HPFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->HPFilter_getOrder()));
  687. ui->NOTCHFilter_Enable->setChecked(FilterAlgoMgr::ins()->NOTCHFilter_getEnable());
  688. ui->NOTCHFilter_CenterFreqHz->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getCenterFreqHz()));
  689. ui->NOTCHFilter_NotchWidthHz->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getNotchWidthHz()));
  690. ui->NOTCHFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getOrder()));
  691. ui->FilterCommon_windowsSize->setText(QString::number(FilterAlgoMgr::ins()->getWindowsSize()));
  692. ui->FilterCommon_WindowsType->setCurrentText(QString::fromStdString(FilterAlgoMgr::ins()->getWindowType()));
  693. ui->SmoothingFilter_Enable->setChecked(FilterAlgoMgr::ins()->SmoothingFilter_getEnable());
  694. ui->SmoothingFilter_WindowsSize->setText(QString::number(FilterAlgoMgr::ins()->SmoothingFilter_getWindowsSize()));
  695. ui->BaselineDriftRemoval_Enable->setChecked(FilterAlgoMgr::ins()->BaselineDriftRemoval_getEnable());
  696. ui->BaselineDriftRemoval_WindowsSize->setText(QString::number(FilterAlgoMgr::ins()->BaselineDriftRemoval_getWindowsSize()));
  697. }
  698. void MainWindow::on_TestCmd_writeSubICAllReg_clicked() {
  699. // 0x52,0x02,0xe0,0xF1,0x00,0x80,0x00,0x03,0x12,0x02,0x07,0x0c
  700. instructionPreviewClear();
  701. QString regs = ui->TestCmd_writeSubICAllReg_p0->toPlainText();
  702. QStringList reglist = regs.split(",");
  703. if (reglist.size() != 12) {
  704. ishow("reg size error %d != 12", reglist.size());
  705. return;
  706. }
  707. try {
  708. uint8_t data[12];
  709. for (int i = 0; i < 12; i++) {
  710. data[i] = str2int(reglist[i]);
  711. }
  712. for (size_t i = 0; i < 12; i++) {
  713. ElectrocardiographTester::ins()->ecg_subic_write_reg(i, data[i]);
  714. ishow("write reg %d: 0x%02x success", i, data[i]);
  715. }
  716. ishow("write all reg success");
  717. } catch (zexception &exception) {
  718. processException(exception);
  719. }
  720. }
  721. void MainWindow::on_setEcgInTestMode_clicked() {
  722. instructionPreviewClear();
  723. try {
  724. ElectrocardiographTester::ins()->set_ecg_in_test_mode(1);
  725. ishow("set ECG in test mode success");
  726. } catch (zexception &exception) {
  727. processException(exception);
  728. }
  729. }
  730. void MainWindow::on_setEcgInNormalMode_clicked() {
  731. instructionPreviewClear();
  732. try {
  733. ElectrocardiographTester::ins()->set_ecg_in_test_mode(0);
  734. ishow("set ECG in test mode success");
  735. } catch (zexception &exception) {
  736. processException(exception);
  737. }
  738. }
  739. void MainWindow::on_setEcgReportDataInRawMode__1_clicked() {
  740. instructionPreviewClear();
  741. try {
  742. ElectrocardiographTester::ins()->set_ecg_report_data_in_raw_mode(1);
  743. ishow("set_ecg_report_data_in_raw_mode(1) success");
  744. } catch (zexception &exception) {
  745. processException(exception);
  746. }
  747. }
  748. void MainWindow::on_setEcgReportDataInRawMode__0_clicked() {
  749. instructionPreviewClear();
  750. try {
  751. ElectrocardiographTester::ins()->set_ecg_report_data_in_raw_mode(0);
  752. ishow("set_ecg_report_data_in_raw_mode(0) success");
  753. } catch (zexception &exception) {
  754. processException(exception);
  755. }
  756. }