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.

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