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.

778 lines
30 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. #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 "algo/iflytop_simple_filter.h"
  10. #include "electrocardiograph_tester.hpp"
  11. #include "filter_algo_mgr.hpp"
  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. wp2d->initGraphName(QStringList() << "心电");
  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. }
  334. void MainWindow::processException(zexception &e) { ishow("%s:%s", e.what(), ify_hrs_error_code_to_string((ify_hrs_error_code_t)e.ecode())); }
  335. void MainWindow::on_readDeviceVersion_clicked() {
  336. instructionPreviewClear();
  337. try {
  338. device_version_info_receipt_t version;
  339. ElectrocardiographTester::ins()->readDeviceVersion(&version);
  340. ishow("-------------- version ----------------");
  341. ishow(" blestack_version: %d", version.blestack_version);
  342. ishow(" bootloader_version: %d", version.bootloader_version);
  343. ishow(" firmware_version: %d", version.firmware_version);
  344. ishow(" hardware_version: %d", version.hardware_version);
  345. } catch (zexception &exception) {
  346. processException(exception);
  347. }
  348. }
  349. void MainWindow::on_readDeviceState_clicked() {
  350. instructionPreviewClear();
  351. try {
  352. device_state_receipt_t state;
  353. ElectrocardiographTester::ins()->readDeviceState(&state);
  354. ishow("-------------- state ----------------");
  355. ishow(" drop_state0: %s", zhex2binary(state.drop_state0).c_str());
  356. ishow(" drop_state1: %s", zhex2binary(state.drop_state1).c_str());
  357. ishow(" sampling_state: %d", state.device_state0.sampling_state);
  358. ishow(" report_state: %d", state.device_state0.report_state);
  359. ishow(" low_battery: %d", state.device_state0.low_battery);
  360. ishow(" full_storge: %d", state.device_state0.full_storge);
  361. ishow(" holder: %d", state.device_state0.holder);
  362. ishow(" powerlevel: %d", state.powerlevel);
  363. ishow(" storage_item_num: %d", state.storage_item_num);
  364. } catch (zexception &exception) {
  365. processException(exception);
  366. }
  367. }
  368. void MainWindow::on_readTime_clicked() {
  369. instructionPreviewClear();
  370. try {
  371. read_time_receipt_t time;
  372. ElectrocardiographTester::ins()->readTime(&time);
  373. ishow("-------------- time ----------------");
  374. ishow(" %d/%d/%d %d:%d:%d", time.year + 2000, time.month, time.day, time.hour, time.minute, time.second);
  375. } catch (zexception &exception) {
  376. processException(exception);
  377. }
  378. }
  379. void MainWindow::on_syncTime_clicked() {
  380. instructionPreviewClear();
  381. try {
  382. // 获取系统时间
  383. QDateTime now = QDateTime::currentDateTime();
  384. ElectrocardiographTester::ins()->syncTime(now.date().year() - 2000, now.date().month(), now.date().day(), now.time().hour(), now.time().minute(), now.time().second());
  385. ishow("sync time success!");
  386. } catch (zexception &exception) {
  387. processException(exception);
  388. }
  389. }
  390. std::string zhex2time(const uint8_t *hex, size_t len) {
  391. std::string str;
  392. if (len < 6) return str;
  393. str.append(fmt("%d/%d/%d %2d:%2d:%2d", hex[0] + 2000, hex[1], hex[2], hex[3], hex[4], hex[5]));
  394. return str;
  395. }
  396. void MainWindow::on_readAllRecords_clicked() {
  397. // 读取当前有多少条记录
  398. instructionPreviewClear();
  399. try {
  400. device_state_receipt_t state;
  401. ElectrocardiographTester::ins()->readDeviceState(&state);
  402. ishow("index recordid frameNum dataSize sensorNum captRate captPrec compAlgo checksum");
  403. for (int32_t i = 0; i < state.storage_item_num; i++) {
  404. read_record_info_receipt_t record;
  405. ElectrocardiographTester::ins()->readRecordsInfo(i, &record);
  406. 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);
  407. }
  408. } catch (zexception &exception) {
  409. processException(exception);
  410. }
  411. }
  412. void MainWindow::on_startUploadRecord_clicked() {
  413. instructionPreviewClear();
  414. int reportIndex = ui->startUploadRecord_p0->toPlainText().toInt();
  415. try {
  416. read_record_info_receipt_t record;
  417. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  418. ElectrocardiographTester::ins()->startUploadRecord(record.record_id);
  419. ishow("start upload record [%s] success", zhex2time(record.record_id, 6).c_str());
  420. } catch (zexception &exception) {
  421. processException(exception);
  422. }
  423. }
  424. void MainWindow::on_readSensorInfo_clicked() {
  425. instructionPreviewClear();
  426. try {
  427. sensor_info_receipt_t sensor;
  428. ElectrocardiographTester::ins()->readSensorInfo(&sensor);
  429. ishow("-------------- sensor ----------------");
  430. ishow(" sensor_num: %d", sensor.sensor_num);
  431. ishow(" sensor_precision: %d", sensor.sensor_precision);
  432. ishow(" sensor_sample_rate:%d", sensor.sensor_sample_rate);
  433. ishow(" sensor0_pos: %d", sensor.sensor0_pos);
  434. ishow(" sensor1_pos: %d", sensor.sensor1_pos);
  435. ishow(" sensor2_pos: %d", sensor.sensor2_pos);
  436. } catch (zexception &exception) {
  437. processException(exception);
  438. }
  439. }
  440. void MainWindow::on_readSN_clicked() {
  441. instructionPreviewClear();
  442. try {
  443. string sn;
  444. ElectrocardiographTester::ins()->readSn(sn);
  445. ishow("-------------- sn ----------------");
  446. ishow(" sn: %s", sn.c_str());
  447. } catch (zexception &exception) {
  448. processException(exception);
  449. }
  450. }
  451. void MainWindow::on_stopUploadRecord_clicked() {
  452. instructionPreviewClear();
  453. try {
  454. ElectrocardiographTester::ins()->stopUploadRecord();
  455. ishow("stop upload record success");
  456. } catch (zexception &exception) {
  457. processException(exception);
  458. }
  459. }
  460. void MainWindow::on_delRecord_clicked() {
  461. instructionPreviewClear();
  462. int reportIndex = ui->delRecord_p0->toPlainText().toInt();
  463. try {
  464. read_record_info_receipt_t record;
  465. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  466. ElectrocardiographTester::ins()->delRecord(record.record_id);
  467. ishow("delete record [%s] success", zhex2time(record.record_id, 6).c_str());
  468. } catch (zexception &exception) {
  469. processException(exception);
  470. }
  471. }
  472. #if 0
  473. void MainWindow::on_startCapture_clicked() {
  474. instructionPreviewClear();
  475. try {
  476. ElectrocardiographTester::ins()->startCapture();
  477. ishow("start capture success");
  478. } catch (zexception &exception) {
  479. processException(exception);
  480. }
  481. }
  482. void MainWindow::on_stopCapture_clicked() {
  483. instructionPreviewClear();
  484. try {
  485. ElectrocardiographTester::ins()->stopCapture();
  486. ishow("stop capture success");
  487. } catch (zexception &exception) {
  488. processException(exception);
  489. }
  490. }
  491. #endif
  492. void MainWindow::on_startRealtimeReport_clicked() {
  493. instructionPreviewClear();
  494. try {
  495. ElectrocardiographTester::ins()->startRealtimeReport();
  496. ishow("start realtime report success");
  497. wp2d->show();
  498. } catch (zexception &exception) {
  499. processException(exception);
  500. }
  501. }
  502. void MainWindow::on_stopRealtimeReport_clicked() {
  503. instructionPreviewClear();
  504. try {
  505. ElectrocardiographTester::ins()->stopRealtimeReport();
  506. ishow("stop realtime report success");
  507. wp2d->hide();
  508. } catch (zexception &exception) {
  509. processException(exception);
  510. }
  511. }
  512. void MainWindow::on_clearPreview_clicked() {
  513. ui->reportPreview->document()->clear();
  514. ui->uploadDataPreview->document()->clear();
  515. ui->rawDataPreview->document()->clear();
  516. ui->instructionPreview->document()->clear();
  517. }
  518. void MainWindow::on_TestCmd_readSubIcRegs_clicked() {
  519. instructionPreviewClear();
  520. try {
  521. uint8_t data[12];
  522. data[ADS129X_REG_ID] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_ID);
  523. data[ADS129X_REG_CONFIG1] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG1);
  524. data[ADS129X_REG_CONFIG2] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG2);
  525. data[ADS129X_REG_LOFF] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFF);
  526. data[ADS129X_REG_CH1SET] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH1SET);
  527. data[ADS129X_REG_CH2SET] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH2SET);
  528. data[ADS129X_REG_RLDSENS] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RLDSENS);
  529. data[ADS129X_REG_LOFFSENS] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFFSENS);
  530. data[ADS129X_REG_LOFFSTAT] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_LOFFSTAT);
  531. data[ADS129X_REG_RESP1] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RESP1);
  532. data[ADS129X_REG_RESP2] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_RESP2);
  533. data[ADS129X_REG_GPIO] = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_GPIO);
  534. ishow("reg %10s %02d: 0x%02x", "ID", ADS129X_REG_ID, data[ADS129X_REG_ID]);
  535. ishow("reg %10s %02d: 0x%02x", "CONFIG1", ADS129X_REG_CONFIG1, data[ADS129X_REG_CONFIG1]);
  536. ishow("reg %10s %02d: 0x%02x", "CONFIG2", ADS129X_REG_CONFIG2, data[ADS129X_REG_CONFIG2]);
  537. ishow("reg %10s %02d: 0x%02x", "LOFF", ADS129X_REG_LOFF, data[ADS129X_REG_LOFF]);
  538. ishow("reg %10s %02d: 0x%02x", "CH1SET", ADS129X_REG_CH1SET, data[ADS129X_REG_CH1SET]);
  539. ishow("reg %10s %02d: 0x%02x", "CH2SET", ADS129X_REG_CH2SET, data[ADS129X_REG_CH2SET]);
  540. ishow("reg %10s %02d: 0x%02x", "RLDSENS", ADS129X_REG_RLDSENS, data[ADS129X_REG_RLDSENS]);
  541. ishow("reg %10s %02d: 0x%02x", "LOFFSENS", ADS129X_REG_LOFFSENS, data[ADS129X_REG_LOFFSENS]);
  542. ishow("reg %10s %02d: 0x%02x %s", "LOFFSTAT", ADS129X_REG_LOFFSTAT, data[ADS129X_REG_LOFFSTAT], zhex2binary(data[ADS129X_REG_LOFFSTAT]).c_str());
  543. ishow("reg %10s %02d: 0x%02x", "RESP1", ADS129X_REG_RESP1, data[ADS129X_REG_RESP1]);
  544. ishow("reg %10s %02d: 0x%02x", "RESP2", ADS129X_REG_RESP2, data[ADS129X_REG_RESP2]);
  545. ishow("reg %10s %02d: 0x%02x", "GPIO", ADS129X_REG_GPIO, data[ADS129X_REG_GPIO]);
  546. ishow("regs: %s", zhex2str(data, 12).c_str());
  547. } catch (zexception &exception) {
  548. processException(exception);
  549. }
  550. }
  551. void MainWindow::on_TestCmd_writeSubICReg_clicked() {
  552. uint32_t add = str2int(ui->TestCmd_writeSubICReg_p0->toPlainText());
  553. uint32_t val = str2int(ui->TestCmd_writeSubICReg_p1->toPlainText());
  554. instructionPreviewClear();
  555. try {
  556. ElectrocardiographTester::ins()->ecg_subic_write_reg(add, val);
  557. ishow("write reg %d: 0x%02x success", add, val);
  558. } catch (zexception &exception) {
  559. processException(exception);
  560. }
  561. }
  562. void MainWindow::on_TestCmd_writeSubICRegMask_clicked() {
  563. uint8_t add = ui->TestCmd_writeSubICRegMask_p0->toPlainText().toInt();
  564. uint8_t off = ui->TestCmd_writeSubICRegMask_p1->toPlainText().toInt();
  565. uint8_t bitnum = ui->TestCmd_writeSubICRegMask_p2->toPlainText().toInt();
  566. uint8_t val = ui->TestCmd_writeSubICRegMask_p3->toPlainText().toInt();
  567. instructionPreviewClear();
  568. try {
  569. uint8_t regval = ElectrocardiographTester::ins()->ecg_subic_read_reg(add);
  570. uint8_t oldval = regval;
  571. uint8_t mask = (1 << bitnum) - 1;
  572. mask = mask << off;
  573. regval = regval & (~mask);
  574. regval = regval | (val << off);
  575. ElectrocardiographTester::ins()->ecg_subic_write_reg(add, regval);
  576. ishow("write reg %d: 0x%02x -> 0x%02x success", add, oldval, regval);
  577. } catch (const std::exception &e) {
  578. std::cerr << e.what() << '\n';
  579. }
  580. }
  581. void MainWindow::on_TestCmd_startCapture_clicked() {
  582. instructionPreviewClear();
  583. try {
  584. ElectrocardiographTester::ins()->testCmdStartCapture();
  585. ishow("call start capture success");
  586. wp2d->show();
  587. } catch (zexception &exception) {
  588. processException(exception);
  589. }
  590. }
  591. void MainWindow::on_TestCmd_stopCapture_clicked() {
  592. instructionPreviewClear();
  593. try {
  594. ElectrocardiographTester::ins()->testCmdStopCapture();
  595. ishow("call stop capture success");
  596. } catch (zexception &exception) {
  597. processException(exception);
  598. }
  599. }
  600. void MainWindow::on_TestCmd_changeECGSrcToSquareWave_clicked() {
  601. instructionPreviewClear();
  602. try {
  603. uint8_t cfg2 = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CONFIG2);
  604. uint8_t ch1set = ElectrocardiographTester::ins()->ecg_subic_read_reg(ADS129X_REG_CH1SET);
  605. cfg2 = ADS129X_SET_BITS(cfg2, ADS129X_INT_TEST, ADS129X_INT_TEST_ON);
  606. cfg2 = ADS129X_SET_BITS(cfg2, ADS129X_INT_FREQ, ADS129X_INT_FREQ_AC);
  607. ch1set = ADS129X_SET_BITS(ch1set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST);
  608. ElectrocardiographTester::ins()->ecg_subic_write_reg(ADS129X_REG_CONFIG2, cfg2);
  609. ElectrocardiographTester::ins()->ecg_subic_write_reg(ADS129X_REG_CH1SET, ch1set);
  610. ishow("call change ECG src to square wave success");
  611. } catch (zexception &exception) {
  612. processException(exception);
  613. }
  614. }
  615. void MainWindow::on_resetDevice_clicked() {
  616. instructionPreviewClear();
  617. try {
  618. ElectrocardiographTester::ins()->reset();
  619. } catch (zexception &exception) {
  620. // processException(exception);
  621. }
  622. ishow("call reset device success");
  623. }
  624. void MainWindow::on_FilterUpdateParameter_clicked() {
  625. instructionPreviewClear();
  626. FilterAlgoMgr::ins()->FilterCommon_setSampleTimeMs(ui->FilterCommon_SampleTimeMs->text().toFloat());
  627. FilterAlgoMgr::ins()->LPFilter_setEnable(ui->LPFilter_Enable->isChecked());
  628. FilterAlgoMgr::ins()->LPFilter_setCutoffFreqHz(ui->LPFilter_CutoffFreqHz->text().toFloat());
  629. FilterAlgoMgr::ins()->LPFilter_setOrder(ui->LPFilter_Order->text().toInt());
  630. FilterAlgoMgr::ins()->HPFilter_setEnable(ui->HPFilter_Enable->isChecked());
  631. FilterAlgoMgr::ins()->HPFilter_setCutoffFreqHz(ui->HPFilter_CutoffFreqHz->text().toFloat());
  632. FilterAlgoMgr::ins()->HPFilter_setOrder(ui->HPFilter_Order->text().toInt());
  633. FilterAlgoMgr::ins()->NOTCHFilter_setEnable(ui->NOTCHFilter_Enable->isChecked());
  634. FilterAlgoMgr::ins()->NOTCHFilter_setCenterFreqHz(ui->NOTCHFilter_CenterFreqHz->text().toFloat());
  635. FilterAlgoMgr::ins()->NOTCHFilter_setNotchWidthHz(ui->NOTCHFilter_NotchWidthHz->text().toFloat());
  636. FilterAlgoMgr::ins()->NOTCHFilter_setOrder(ui->NOTCHFilter_Order->text().toInt());
  637. FilterAlgoMgr::ins()->updateParameter();
  638. on_buttonTabWidget_currentChanged(0);
  639. ishow("Filter Update Parameter success");
  640. }
  641. void MainWindow::on_buttonTabWidget_currentChanged(int index) {
  642. ui->FilterCommon_SampleTimeMs->setText(QString::number(FilterAlgoMgr::ins()->FilterCommon_getSampleTimeMs()));
  643. ui->LPFilter_Enable->setChecked(FilterAlgoMgr::ins()->LPFilter_getEnable());
  644. ui->LPFilter_CutoffFreqHz->setText(QString::number(FilterAlgoMgr::ins()->LPFilter_getCutoffFreqHz()));
  645. ui->LPFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->LPFilter_getOrder()));
  646. ui->HPFilter_Enable->setChecked(FilterAlgoMgr::ins()->HPFilter_getEnable());
  647. ui->HPFilter_CutoffFreqHz->setText(QString::number(FilterAlgoMgr::ins()->HPFilter_getCutoffFreqHz()));
  648. ui->HPFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->HPFilter_getOrder()));
  649. ui->NOTCHFilter_Enable->setChecked(FilterAlgoMgr::ins()->NOTCHFilter_getEnable());
  650. ui->NOTCHFilter_CenterFreqHz->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getCenterFreqHz()));
  651. ui->NOTCHFilter_NotchWidthHz->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getNotchWidthHz()));
  652. ui->NOTCHFilter_Order->setText(QString::number(FilterAlgoMgr::ins()->NOTCHFilter_getOrder()));
  653. }
  654. void MainWindow::on_TestCmd_writeSubICAllReg_clicked() {
  655. // 0x52,0x02,0xe0,0xF1,0x00,0x80,0x00,0x03,0x12,0x02,0x07,0x0c
  656. instructionPreviewClear();
  657. QString regs = ui->TestCmd_writeSubICAllReg_p0->toPlainText();
  658. QStringList reglist = regs.split(",");
  659. if (reglist.size() != 12) {
  660. ishow("reg size error %d != 12", reglist.size());
  661. return;
  662. }
  663. try {
  664. uint8_t data[12];
  665. for (int i = 0; i < 12; i++) {
  666. data[i] = str2int(reglist[i]);
  667. }
  668. for (size_t i = 0; i < 12; i++) {
  669. ElectrocardiographTester::ins()->ecg_subic_write_reg(i, data[i]);
  670. ishow("write reg %d: 0x%02x success", i, data[i]);
  671. }
  672. ishow("write all reg success");
  673. } catch (zexception &exception) {
  674. processException(exception);
  675. }
  676. }
  677. void MainWindow::on_setEcgInTestMode_clicked() {
  678. instructionPreviewClear();
  679. try {
  680. ElectrocardiographTester::ins()->set_ecg_in_test_mode(1);
  681. ishow("set ECG in test mode success");
  682. } catch (zexception &exception) {
  683. processException(exception);
  684. }
  685. }
  686. void MainWindow::on_setEcgInNormalMode_clicked() {
  687. instructionPreviewClear();
  688. try {
  689. ElectrocardiographTester::ins()->set_ecg_in_test_mode(0);
  690. ishow("set ECG in test mode success");
  691. } catch (zexception &exception) {
  692. processException(exception);
  693. }
  694. }