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.

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