Browse Source

支持单导联测试

master
zhaohe 1 year ago
parent
commit
5abefc93a7
  1. 3
      .gitmodules
  2. 6
      README.md
  3. 1
      ify_hrs_protocol
  4. 210
      mainwindow.cpp
  5. 21
      mainwindow.h
  6. 369
      mainwindow.ui
  7. BIN
      src/ads129x/ads1291.pdf
  8. 286
      src/ads129x/ads129x_type.h
  9. 46
      src/electrocardiograph_tester.cpp
  10. 29
      src/electrocardiograph_tester.hpp
  11. 236
      src/heart_rate_sensor_protocol.h

3
.gitmodules

@ -0,0 +1,3 @@
[submodule "ify_hrs_protocol"]
path = ify_hrs_protocol
url = zwsd@192.168.1.3:p_dynamic_electrocardiograph/ify_hrs_protocol.git

6
README.md

@ -37,4 +37,10 @@ V4:
4. 上报某条记录
5. 打印记录的checksum
regcache.cfg2 = ADS129X_SET_BITS(regcache.cfg2, ADS129X_INT_TEST, ADS129X_INT_TEST_ON);
regcache.cfg2 = ADS129X_SET_BITS(regcache.cfg2, ADS129X_INT_FREQ, ADS129X_INT_FREQ_AC);
regcache.ch1set = ADS129X_SET_BITS(regcache.ch1set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST);
regcache.ch2set = ADS129X_SET_BITS(regcache.ch2set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST);
```

1
ify_hrs_protocol

@ -0,0 +1 @@
Subproject commit 4ed480c0ba1b2326d4465f8139ee97673f35ffa8

210
mainwindow.cpp

@ -7,6 +7,7 @@
#include <QtSerialPort/QSerialPortInfo>
#include "./ui_mainwindow.h"
#include "ads129x/ads129x_type.h"
#include "electrocardiograph_tester.hpp"
#include "logger.hpp"
#include "qt_serial_datachannel.hpp"
@ -44,7 +45,7 @@ void MainWindow::doinui_slot(QFunction func) {
if (func.get()) func.get()();
}
void MainWindow::instructionPreviewShow(const char *fmt, ...) {
void MainWindow::ishow(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
char buf[1024] = {0};
@ -154,6 +155,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
*******************************************************************************/
constructUI();
ui->TestCmd_writeSubICRegMask_p0->setPlaceholderText("寄存器地址");
ui->TestCmd_writeSubICRegMask_p1->setPlaceholderText("偏移");
ui->TestCmd_writeSubICRegMask_p2->setPlaceholderText("位数");
ui->TestCmd_writeSubICRegMask_p3->setPlaceholderText("");
ui->TestCmd_writeSubICReg_p0->setPlaceholderText("寄存器地址");
ui->TestCmd_writeSubICReg_p1->setPlaceholderText("");
/*******************************************************************************
* *
*******************************************************************************/
@ -286,9 +295,9 @@ void MainWindow::constructUI() {
}
lastpacket_index = heartrate_report->sample_data_index;
uint32_t timestamp = *(uint32_t*)(&heartrate_report->data[50*4]);
uint32_t timestamp = *(uint32_t *)(&heartrate_report->data[50 * 4]);
reportPreviewShow("[preview data ] timestamp:%10d lost:%d index %d packetlen %d", timestamp,lostpacket, heartrate_report->sample_data_index, packetlen);
reportPreviewShow("[preview data ] timestamp:%10d lost:%d index %d packetlen %d", timestamp, lostpacket, heartrate_report->sample_data_index, packetlen);
int32_t *frame = (int32_t *)heartrate_report->data;
for (int i = 0; i < 50; i++) {
@ -343,18 +352,18 @@ void MainWindow::constructUI() {
});
}
void MainWindow::processException(zexception &e) { instructionPreviewShow("%s:%s", e.what(), hrs_ecode2str((ify_hrs_error_code_t)e.ecode())); }
void MainWindow::processException(zexception &e) { ishow("%s:%s", e.what(), ify_hrs_error_code_to_string((ify_hrs_error_code_t)e.ecode())); }
void MainWindow::on_readDeviceVersion_clicked() {
instructionPreviewClear();
try {
device_version_info_receipt_t version;
ElectrocardiographTester::ins()->readDeviceVersion(&version);
instructionPreviewShow("-------------- version ----------------");
instructionPreviewShow(" blestack_version: %d", version.blestack_version);
instructionPreviewShow(" bootloader_version: %d", version.bootloader_version);
instructionPreviewShow(" firmware_version: %d", version.firmware_version);
instructionPreviewShow(" hardware_version: %d", version.hardware_version);
ishow("-------------- version ----------------");
ishow(" blestack_version: %d", version.blestack_version);
ishow(" bootloader_version: %d", version.bootloader_version);
ishow(" firmware_version: %d", version.firmware_version);
ishow(" hardware_version: %d", version.hardware_version);
} catch (zexception &exception) {
processException(exception);
}
@ -365,17 +374,17 @@ void MainWindow::on_readDeviceState_clicked() {
try {
device_state_receipt_t state;
ElectrocardiographTester::ins()->readDeviceState(&state);
instructionPreviewShow("-------------- state ----------------");
instructionPreviewShow(" drop_state0: %s", zhex2binary(state.drop_state0).c_str());
instructionPreviewShow(" drop_state1: %s", zhex2binary(state.drop_state1).c_str());
instructionPreviewShow(" sampling_state: %d", state.device_state0.sampling_state);
instructionPreviewShow(" report_state: %d", state.device_state0.report_state);
instructionPreviewShow(" low_battery: %d", state.device_state0.low_battery);
instructionPreviewShow(" full_storge: %d", state.device_state0.full_storge);
instructionPreviewShow(" holder: %d", state.device_state0.holder);
instructionPreviewShow(" powerlevel: %d", state.powerlevel);
instructionPreviewShow(" storage_item_num: %d", state.storage_item_num);
ishow("-------------- state ----------------");
ishow(" drop_state0: %s", zhex2binary(state.drop_state0).c_str());
ishow(" drop_state1: %s", zhex2binary(state.drop_state1).c_str());
ishow(" sampling_state: %d", state.device_state0.sampling_state);
ishow(" report_state: %d", state.device_state0.report_state);
ishow(" low_battery: %d", state.device_state0.low_battery);
ishow(" full_storge: %d", state.device_state0.full_storge);
ishow(" holder: %d", state.device_state0.holder);
ishow(" powerlevel: %d", state.powerlevel);
ishow(" storage_item_num: %d", state.storage_item_num);
} catch (zexception &exception) {
processException(exception);
}
@ -386,8 +395,8 @@ void MainWindow::on_readTime_clicked() {
try {
read_time_receipt_t time;
ElectrocardiographTester::ins()->readTime(&time);
instructionPreviewShow("-------------- time ----------------");
instructionPreviewShow(" %d/%d/%d %d:%d:%d", time.year + 2000, time.month, time.day, time.hour, time.minute, time.second);
ishow("-------------- time ----------------");
ishow(" %d/%d/%d %d:%d:%d", time.year + 2000, time.month, time.day, time.hour, time.minute, time.second);
} catch (zexception &exception) {
processException(exception);
@ -400,7 +409,7 @@ void MainWindow::on_syncTime_clicked() {
// 获取系统时间
QDateTime now = QDateTime::currentDateTime();
ElectrocardiographTester::ins()->syncTime(now.date().year() - 2000, now.date().month(), now.date().day(), now.time().hour(), now.time().minute(), now.time().second());
instructionPreviewShow("sync time success!");
ishow("sync time success!");
} catch (zexception &exception) {
processException(exception);
}
@ -419,11 +428,11 @@ void MainWindow::on_readAllRecords_clicked() {
try {
device_state_receipt_t state;
ElectrocardiographTester::ins()->readDeviceState(&state);
instructionPreviewShow("index recordid frameNum dataSize sensorNum captRate captPrec compAlgo checksum");
ishow("index recordid frameNum dataSize sensorNum captRate captPrec compAlgo checksum");
for (int32_t i = 0; i < state.storage_item_num; i++) {
read_record_info_receipt_t record;
ElectrocardiographTester::ins()->readRecordsInfo(i, &record);
instructionPreviewShow("%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);
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);
}
} catch (zexception &exception) {
processException(exception);
@ -437,7 +446,7 @@ void MainWindow::on_startUploadRecord_clicked() {
read_record_info_receipt_t record;
ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
ElectrocardiographTester::ins()->startUploadRecord(record.record_id);
instructionPreviewShow("start upload record [%s] success", zhex2time(record.record_id, 6).c_str());
ishow("start upload record [%s] success", zhex2time(record.record_id, 6).c_str());
} catch (zexception &exception) {
processException(exception);
}
@ -448,13 +457,13 @@ void MainWindow::on_readSensorInfo_clicked() {
try {
sensor_info_receipt_t sensor;
ElectrocardiographTester::ins()->readSensorInfo(&sensor);
instructionPreviewShow("-------------- sensor ----------------");
instructionPreviewShow(" sensor_num: %d", sensor.sensor_num);
instructionPreviewShow(" sensor_precision: %d", sensor.sensor_precision);
instructionPreviewShow(" sensor_sample_rate:%d", sensor.sensor_sample_rate);
instructionPreviewShow(" sensor0_pos: %d", sensor.sensor0_pos);
instructionPreviewShow(" sensor1_pos: %d", sensor.sensor1_pos);
instructionPreviewShow(" sensor2_pos: %d", sensor.sensor2_pos);
ishow("-------------- sensor ----------------");
ishow(" sensor_num: %d", sensor.sensor_num);
ishow(" sensor_precision: %d", sensor.sensor_precision);
ishow(" sensor_sample_rate:%d", sensor.sensor_sample_rate);
ishow(" sensor0_pos: %d", sensor.sensor0_pos);
ishow(" sensor1_pos: %d", sensor.sensor1_pos);
ishow(" sensor2_pos: %d", sensor.sensor2_pos);
} catch (zexception &exception) {
processException(exception);
}
@ -465,8 +474,8 @@ void MainWindow::on_readSN_clicked() {
try {
string sn;
ElectrocardiographTester::ins()->readSn(sn);
instructionPreviewShow("-------------- sn ----------------");
instructionPreviewShow(" sn: %s", sn.c_str());
ishow("-------------- sn ----------------");
ishow(" sn: %s", sn.c_str());
} catch (zexception &exception) {
processException(exception);
}
@ -476,7 +485,7 @@ void MainWindow::on_stopUploadRecord_clicked() {
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->stopUploadRecord();
instructionPreviewShow("stop upload record success");
ishow("stop upload record success");
} catch (zexception &exception) {
processException(exception);
}
@ -489,17 +498,17 @@ void MainWindow::on_delRecord_clicked() {
read_record_info_receipt_t record;
ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
ElectrocardiographTester::ins()->delRecord(record.record_id);
instructionPreviewShow("delete record [%s] success", zhex2time(record.record_id, 6).c_str());
ishow("delete record [%s] success", zhex2time(record.record_id, 6).c_str());
} catch (zexception &exception) {
processException(exception);
}
}
#if 0
void MainWindow::on_startCapture_clicked() {
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->startCapture();
instructionPreviewShow("start capture success");
ishow("start capture success");
} catch (zexception &exception) {
processException(exception);
}
@ -509,17 +518,18 @@ void MainWindow::on_stopCapture_clicked() {
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->stopCapture();
instructionPreviewShow("stop capture success");
ishow("stop capture success");
} catch (zexception &exception) {
processException(exception);
}
}
#endif
void MainWindow::on_startRealtimeReport_clicked() {
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->startRealtimeReport();
instructionPreviewShow("start realtime report success");
ishow("start realtime report success");
wp2d->show();
} catch (zexception &exception) {
processException(exception);
@ -530,7 +540,7 @@ void MainWindow::on_stopRealtimeReport_clicked() {
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->stopRealtimeReport();
instructionPreviewShow("stop realtime report success");
ishow("stop realtime report success");
wp2d->hide();
} catch (zexception &exception) {
processException(exception);
@ -543,3 +553,119 @@ void MainWindow::on_clearPreview_clicked() {
ui->rawDataPreview->document()->clear();
ui->instructionPreview->document()->clear();
}
void MainWindow::on_TestCmd_readSubIcRegs_clicked() {
instructionPreviewClear();
try {
uint8_t data[12];
data[ADS129X_REG_ID] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_ID);
data[ADS129X_REG_CONFIG1] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_CONFIG1);
data[ADS129X_REG_CONFIG2] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_CONFIG2);
data[ADS129X_REG_LOFF] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_LOFF);
data[ADS129X_REG_CH1SET] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_CH1SET);
data[ADS129X_REG_CH2SET] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_CH2SET);
data[ADS129X_REG_RLDSENS] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_RLDSENS);
data[ADS129X_REG_LOFFSENS] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_LOFFSENS);
data[ADS129X_REG_LOFFSTAT] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_LOFFSTAT);
data[ADS129X_REG_RESP1] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_RESP1);
data[ADS129X_REG_RESP2] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_RESP2);
data[ADS129X_REG_GPIO] = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_GPIO);
ishow("reg %10s %02d: 0x%02x", "ID", ADS129X_REG_ID, data[ADS129X_REG_ID]);
ishow("reg %10s %02d: 0x%02x", "CONFIG1", ADS129X_REG_CONFIG1, data[ADS129X_REG_CONFIG1]);
ishow("reg %10s %02d: 0x%02x", "CONFIG2", ADS129X_REG_CONFIG2, data[ADS129X_REG_CONFIG2]);
ishow("reg %10s %02d: 0x%02x", "LOFF", ADS129X_REG_LOFF, data[ADS129X_REG_LOFF]);
ishow("reg %10s %02d: 0x%02x", "CH1SET", ADS129X_REG_CH1SET, data[ADS129X_REG_CH1SET]);
ishow("reg %10s %02d: 0x%02x", "CH2SET", ADS129X_REG_CH2SET, data[ADS129X_REG_CH2SET]);
ishow("reg %10s %02d: 0x%02x", "RLDSENS", ADS129X_REG_RLDSENS, data[ADS129X_REG_RLDSENS]);
ishow("reg %10s %02d: 0x%02x", "LOFFSENS", ADS129X_REG_LOFFSENS, data[ADS129X_REG_LOFFSENS]);
ishow("reg %10s %02d: 0x%02x %s", "LOFFSTAT", ADS129X_REG_LOFFSTAT, data[ADS129X_REG_LOFFSTAT], zhex2binary(data[ADS129X_REG_LOFFSTAT]).c_str());
ishow("reg %10s %02d: 0x%02x", "RESP1", ADS129X_REG_RESP1, data[ADS129X_REG_RESP1]);
ishow("reg %10s %02d: 0x%02x", "RESP2", ADS129X_REG_RESP2, data[ADS129X_REG_RESP2]);
ishow("reg %10s %02d: 0x%02x", "GPIO", ADS129X_REG_GPIO, data[ADS129X_REG_GPIO]);
} catch (zexception &exception) {
processException(exception);
}
}
void MainWindow::on_TestCmd_writeSubICReg_clicked() {
uint8_t add = ui->TestCmd_writeSubICReg_p0->toPlainText().toInt();
uint8_t val = ui->TestCmd_writeSubICReg_p1->toPlainText().toInt();
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->testCmdWriteReg(add, val);
ishow("write reg %d: 0x%02x success", add, val);
} catch (zexception &exception) {
processException(exception);
}
}
void MainWindow::on_TestCmd_writeSubICRegMask_clicked() {
uint8_t add = ui->TestCmd_writeSubICRegMask_p0->toPlainText().toInt();
uint8_t off = ui->TestCmd_writeSubICRegMask_p1->toPlainText().toInt();
uint8_t bitnum = ui->TestCmd_writeSubICRegMask_p2->toPlainText().toInt();
uint8_t val = ui->TestCmd_writeSubICRegMask_p3->toPlainText().toInt();
instructionPreviewClear();
try {
uint8_t regval = ElectrocardiographTester::ins()->testCmdReadReg(add);
uint8_t oldval = regval;
uint8_t mask = (1 << bitnum) - 1;
mask = mask << off;
regval = regval & (~mask);
regval = regval | (val << off);
ElectrocardiographTester::ins()->testCmdWriteReg(add, regval);
ishow("write reg %d: 0x%02x -> 0x%02x success", add, oldval, regval);
} catch (const std::exception &e) {
std::cerr << e.what() << '\n';
}
}
void MainWindow::on_TestCmd_startCapture_clicked() {
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->testCmdStartCapture();
ishow("call start capture success");
wp2d->show();
} catch (zexception &exception) {
processException(exception);
}
}
void MainWindow::on_TestCmd_stopCapture_clicked() {
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->testCmdStopCapture();
ishow("call stop capture success");
} catch (zexception &exception) {
processException(exception);
}
}
void MainWindow::on_TestCmd_changeECGSrcToSquareWave_clicked() {
instructionPreviewClear();
try {
uint8_t cfg2 = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_CONFIG2);
uint8_t ch1set = ElectrocardiographTester::ins()->testCmdReadReg(ADS129X_REG_CH1SET);
cfg2 = ADS129X_SET_BITS(cfg2, ADS129X_INT_TEST, ADS129X_INT_TEST_ON);
cfg2 = ADS129X_SET_BITS(cfg2, ADS129X_INT_FREQ, ADS129X_INT_FREQ_AC);
ch1set = ADS129X_SET_BITS(ch1set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST);
ElectrocardiographTester::ins()->testCmdWriteReg(ADS129X_REG_CONFIG2, cfg2);
ElectrocardiographTester::ins()->testCmdWriteReg(ADS129X_REG_CH1SET, ch1set);
ishow("call change ECG src to square wave success");
} catch (zexception &exception) {
processException(exception);
}
}
void MainWindow::on_resetDevice_clicked() {
instructionPreviewClear();
try {
ElectrocardiographTester::ins()->reset();
} catch (zexception &exception) {
// processException(exception);
}
ishow("call reset device success");
}

21
mainwindow.h

@ -96,10 +96,11 @@ class MainWindow : public QMainWindow {
void on_stopUploadRecord_clicked();
void on_delRecord_clicked();
#if 0
void on_startCapture_clicked();
void on_stopCapture_clicked();
#endif
void on_startRealtimeReport_clicked();
@ -107,12 +108,26 @@ class MainWindow : public QMainWindow {
void on_clearPreview_clicked();
signals:
void on_TestCmd_readSubIcRegs_clicked();
void on_TestCmd_writeSubICReg_clicked();
void on_TestCmd_startCapture_clicked();
void on_TestCmd_stopCapture_clicked();
void on_TestCmd_writeSubICRegMask_clicked();
void on_TestCmd_changeECGSrcToSquareWave_clicked();
void on_resetDevice_clicked();
signals:
void doinui_signal(QFunction);
private:
static void log_output(QtMsgType type, const QMessageLogContext &context, const QString &msg);
void instructionPreviewShow(const char *fmt, ...);
void ishow(const char *fmt, ...);
void instructionPreviewClear();
void reportPreviewShow(const char *fmt, ...);
void blockDataUploadPreviewShow(const char *fmt, ...);

369
mainwindow.ui

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1448</width>
<height>1040</height>
<width>1532</width>
<height>1044</height>
</rect>
</property>
<property name="sizePolicy">
@ -814,6 +814,19 @@ p, li { white-space: pre-wrap; }
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="title">
<string>GroupBox</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -959,19 +972,6 @@ p, li { white-space: pre-wrap; }
<string>设备信息</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="6" column="1">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="readDeviceState">
<property name="sizePolicy">
@ -991,21 +991,27 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
<item row="0" column="1">
<widget class="QPushButton" name="syncTime">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeHint" stdset="0">
<property name="minimumSize">
<size>
<width>20</width>
<height>40</height>
<width>0</width>
<height>30</height>
</size>
</property>
</spacer>
<property name="text">
<string>同步时间</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="readSN">
<item row="1" column="1">
<widget class="QPushButton" name="readTime">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
@ -1019,12 +1025,12 @@ p, li { white-space: pre-wrap; }
</size>
</property>
<property name="text">
<string>读取设备SN</string>
<string>读取设备时间</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="readDeviceVersion">
<item row="5" column="0">
<widget class="QPushButton" name="readSN">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
@ -1038,12 +1044,12 @@ p, li { white-space: pre-wrap; }
</size>
</property>
<property name="text">
<string>读取设备版本信息</string>
<string>读取设备SN</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="readSensorInfo">
<item row="0" column="0">
<widget class="QPushButton" name="readDeviceVersion">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
@ -1057,12 +1063,38 @@ p, li { white-space: pre-wrap; }
</size>
</property>
<property name="text">
<string>读取传感器信息</string>
<string>读取设备版本信息</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="syncTime">
<item row="7" column="1">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="readSensorInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
@ -1076,12 +1108,12 @@ p, li { white-space: pre-wrap; }
</size>
</property>
<property name="text">
<string>同步时间</string>
<string>读取传感器信息</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="readTime">
<item row="6" column="0">
<widget class="QPushButton" name="resetDevice">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
@ -1095,26 +1127,13 @@ p, li { white-space: pre-wrap; }
</size>
</property>
<property name="text">
<string>读取设备时间</string>
<string>复位设备</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
@ -1279,10 +1298,254 @@ p, li { white-space: pre-wrap; }
</size>
</property>
<property name="title">
<string>GroupBox</string>
<string>测试指令</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="3" column="1">
<widget class="QPushButton" name="TestCmd_stopCapture">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>停止采集</string>
</property>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="TestCmd_writeSubICReg">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>写ECG寄存器</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QTextEdit" name="TestCmd_writeSubICRegMask_p1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QTextEdit" name="TestCmd_writeSubICRegMask_p2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QTextEdit" name="TestCmd_writeSubICRegMask_p3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QTextEdit" name="TestCmd_writeSubICReg_p1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="TestCmd_startCapture">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>开始采集</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QTextEdit" name="TestCmd_writeSubICReg_p0">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="TestCmd_writeSubICRegMask">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>写ECG寄存器()</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="TestCmd_readSubIcRegs">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>读取ECG芯片寄存器</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QTextEdit" name="TestCmd_writeSubICRegMask_p0">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="TestCmd_changeECGSrcToSquareWave">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>修改信号源为方波</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
@ -1426,7 +1689,7 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
<width>1448</width>
<width>1532</width>
<height>20</height>
</rect>
</property>

BIN
src/ads129x/ads1291.pdf

286
src/ads129x/ads129x_type.h

@ -0,0 +1,286 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ADS129X_REG_ID = 0x00,
ADS129X_REG_CONFIG1 = 0x01,
ADS129X_REG_CONFIG2 = 0x02,
ADS129X_REG_LOFF = 0x03,
ADS129X_REG_CH1SET = 0x04,
ADS129X_REG_CH2SET = 0x05,
ADS129X_REG_RLDSENS = 0x06,
ADS129X_REG_LOFFSENS = 0x07,
ADS129X_REG_LOFFSTAT = 0x08,
ADS129X_REG_RESP1 = 0x09,
ADS129X_REG_RESP2 = 0x0A,
ADS129X_REG_GPIO = 0x0B
} ADS129X_REG_E;
typedef struct {
uint8_t id; /* id,ads1292r固定为0x73 */
uint8_t cfg1; /* 设置寄存器 */
uint8_t cfg2; /* 设置寄存器 */
uint8_t loff; /* 导联 */
uint8_t ch1set; /* 通道一设置 */
uint8_t ch2set; /* 通道二设置 */
uint8_t rld_sens; /* 右腿驱动 */
uint8_t loff_sens; /* 导联 */
uint8_t loff_stat; /* 导联 */
uint8_t resp1; /* 呼吸 */
uint8_t resp2; /* 呼吸 */
uint8_t gpio; /* gpio1,2的控制 */
} ads129x_regs_t;
#define ADS129X_REG_SIZE_MAX 12 /* ADS1291寄存器数量 */
#define ADS129X_ID 0x52
/* 属于ADS129X_REG_CONFIG1的寄存器设置 */
#define ADS129X_SINGLE_SHOT_OFF 0 /* 连续转换模式,默认 */
#define ADS129X_SINGLE_SHOT_ON 1 /* 单次转换模式 */
/* 采样率,该模块采用fclk为512k,0分频模式,其他配置下采样率会改变 */
#define ADS129X_OVERSAMPLING_125SPS 0
#define ADS129X_OVERSAMPLING_250SPS 1
#define ADS129X_OVERSAMPLING_500SPS 2 /* 默认 */
#define ADS129X_OVERSAMPLING_1000SPS 3
#define ADS129X_OVERSAMPLING_2000SPS 4
#define ADS129X_OVERSAMPLING_4000SPS 5
#define ADS129X_OVERSAMPLING_8000SPS 6
#define ADS129X_OVERSAMPLING_NONESPS 7
/* 属于ADS129X_REG_CONFIG2的寄存器设置 */
#define ADS129X_PDB_LOFF_COMP_OFF 0 /* 导联脱落比较器关,默认 */
#define ADS129X_PDB_LOFF_COMP_ON 1 /* 导联脱落比较器开 */
#define ADS129X_PDB_REFBUF_OFF 0 /* 内部参考电压关,默认 */
#define ADS129X_PDB_REFBUF_ON 1 /* 内部参考电压开 */
#define ADS129X_VREF_2420MV 0 /* 选择参考电压为2.42v,默认 */
#define ADS129X_VREF_4033MV 1 /* 选择参考电压为4.033v */
#define ADS129X_CLK_OUTPUT_OFF 0 /* 时钟输出关,默认 */
#define ADS129X_CLK_OUTPUT_ON 1 /* 时钟输出开 */
#define ADS129X_INT_TEST_OFF 0 /* 内部测试电压关,默认 */
#define ADS129X_INT_TEST_ON 1 /* 内部测试电压开 */
#define ADS129X_INT_FREQ_DC 0 /* 直流,默认 */
#define ADS129X_INT_FREQ_AC 1 /* 1HZ方波 */
/* 属于ADS129X_REG_LOFF的寄存器设置 */
/* 属于ADS129X_REG_CH1SET,与ADS129X_REG_CH2SET的寄存器设置 */
#define ADS129X_CHx_OFF 1 /* 禁止使用通道一 */
#define ADS129X_CHx_ON 0 /* 使用通道一,默认 */
#define ADS129X_GAIN_6 0 /* 使用通道一6倍增益,默认 */
#define ADS129X_GAIN_1 1 /* 使用通道一1倍增益 */
#define ADS129X_GAIN_2 2 /* 使用通道一2倍增益 */
#define ADS129X_GAIN_3 3 /* 使用通道一3倍增益 */
#define ADS129X_GAIN_4 4 /* 使用通道一4倍增益 */
#define ADS129X_GAIN_8 5 /* 使用通道一8倍增益 */
#define ADS129X_GAIN_12 6 /* 使用通道一12倍增益 */
/* 选择通道一的输入 */
#define ADS129X_CHx_INPUT_NORMAL 0 /* 正常电极输入,默认 */
#define ADS129X_CHx_INPUT_SHORTED 1 /* 短路,测偏执用 */
#define ADS129X_CHx_INPUT_RLD 2 /* 右腿驱动 */
/* For channel 1, (MVDDP – MVDDN) is [0.5(AVDD + AVSS)]; for channel 2, (MVDDP – MVDDN) is DVDD / 4. */
/* For channel 2,VDD / 2 for supply measurement */
#define ADS129X_CHx_INPUT_MVDD 3
#define ADS129X_CHx_INPUT_TEMP 4 /* 板载温度 */
#define ADS129X_CHx_INPUT_TEST 5 /* 内部测试信号 */
#define ADS129X_CHx_INPUT_RLDDRP 6
#define ADS129X_CHx_INPUT_RLDDRM 7
#define ADS129X_CHx_INPUT_RLDDRPM 8
#define ADS129X_CHx_INPUT_ROUTE 9 /* 连接到通道三 */
#define ADS129X_CHx_INPUT_RESERVED 10 /* 预留 */
/* 属于ADS129X_REG_RLDSENS的寄存器设置 */
#define ADS129X_CHOP_FREQ_DIV4 3 /* PGA斩波频率未fMOD/4 */
#define ADS129X_PDB_RLD_OFF 0 /* 右腿驱动电源关,默认 */
#define ADS129X_PDB_RLD_ON 1 /* 右腿驱动电源开 */
#define ADS129X_PDB_RLD_SENSE_OFF 0 /* 右腿驱动导联脱落检测关,默认 */
#define ADS129X_PDB_RLD_SENSE_ON 1 /* 右腿驱动导联脱落检测开 */
#define ADS129X_RLD2N_OFF 0 /* 通道二负极为右腿输入关,默认 */
#define ADS129X_RLD2N_ON 1 /* 通道二负极为右腿输入开 */
#define ADS129X_RLD2P_OFF 0 /* 通道二正极为右腿输入关,默认 */
#define ADS129X_RLD2P_ON 1 /* 通道二正极为右腿输入开 */
#define ADS129X_RLD1N_OFF 0 /* 通道一负极为右腿输入关,默认 */
#define ADS129X_RLD1N_ON 1 /* 通道一负极为右腿输入开 */
#define ADS129X_RLD1P_OFF 0 /* 通道一正极为右腿输入关,默认 */
#define ADS129X_RLD1P_ON 1 /* 通道一正极为右腿输入开 */
/* 属于ADS129X_REG_LOFFSENS的寄存器设置 */
#define ADS129X_FLIP2_OFF 0 /* 导联脱落检测通道二电流方向关,默认 */
#define ADS129X_FLIP2_ON 1 /* 导联脱落检测通道二电流方向开 */
#define ADS129X_FLIP1_OFF 0 /* 导联脱落检测通道一电流方向关,默认 */
#define ADS129X_FLIP1_ON 1 /* 导联脱落检测通道一电流方向开 */
#define ADS129X_LOFF2N_OFF 0 /* 通道二负极导联脱落检测关,默认 */
#define ADS129X_LOFF2N_ON 1 /* 通道二负极导联脱落检测开 */
#define ADS129X_LOFF2P_OFF 0 /* 通道二正极导联脱落检测关,默认 */
#define ADS129X_LOFF2P_ON 1 /* 通道二正极导联脱落检测开 */
#define ADS129X_LOFF1N_OFF 0 /* 通道一负极导联脱落检测关,默认 */
#define ADS129X_LOFF1N_ON 1 /* 通道一负极导联脱落检测开 */
#define ADS129X_LOFF1P_OFF 0 /* 通道一正极导联脱落检测关,默认 */
#define ADS129X_LOFF1P_ON 1 /* 通道一正极导联脱落检测开 */
/* 属于ADS129X_REG_LOFFSTAT的寄存器设置 */
#define ADS129X_CLK_DIV4 0 /* 0 = fMOD = fCLK / 4 (default, use when fCLK = 512 kHz) */
#define ADS129X_CLK_DIV16 1 /* 1 = fMOD = fCLK / 16 (use when fCLK = 2.048 MHz) */
/* 属于ADS129X_REG_RESP1的寄存器设置 */
#define ADS129X_DEMOD_EN1_OFF 0 /* 通道一上的呼吸解调电路关,默认 */
#define ADS129X_DEMOD_EN1_ON 1 /* 通道一上的呼吸解调电路开 */
#define ADS129X_DEMOD_EN_OFF 0 /* 通道一上的呼吸调制电路关,默认 */
#define ADS129X_DEMOD_EN_ON 1 /* 通道一上的呼吸调制电路开 */
#define ADS129X_RESPPH_0 0 /* 解调信号相位偏移0,默认 */
#define ADS129X_RESPPH_135 0x0c /* 解调信号相位偏移135度 */
#define ADS129X_RESP_CTRL_INT 0 /* 内部呼吸内部时钟,默认 */
#define ADS129X_RESP_CTRL_EXT 1 /* 内部呼吸外部时钟 */
/* 属于ADS129X_REG_RESP2的寄存器设置 */
#define ADS129X_CALIB_ON_OFF 0 /* 校准关,默认 */
#define ADS129X_CALIB_ON_ON 1 /* 校准开 */
#define ADS129X_RESP_FREQ_36 0 /* 通道一上的呼吸调制电路关,默认 */
#define ADS129X_RESP_FREQ_64 1 /* 通道一上的呼吸调制电路开 */
#define ADS129X_RLDREF_EXT 0 /* 右腿驱动参考电压选择外部反馈,默认 */
#define ADS129X_RLDREF_INT 1 /* 右腿驱动参考电压选择内部信号 */
/* 属于ADS129X_REG_GPIO的寄存器设置 */
/**
* @}
*/
/** @addtogroup ADS129X_TYP_REG_MASK ADS1291 TYP Reg Mask
* @brief ADS129X_GET_BITS与ADS129X_SET_BITS函数调用
* @{
*/
#define ADS129X_ID_POS 0
#define ADS129X_ID_MASK 0xFF
#define ADS129X_SINGLE_SHOT_POS 7
#define ADS129X_SINGLE_SHOT_MASK 0x80
#define ADS129X_DR_POS 0
#define ADS129X_DR_MASK 0x07
#define ADS129X_PDB_LOFF_COMP_POS 6
#define ADS129X_PDB_LOFF_COMP_MASK 0x40
#define ADS129X_PDB_REFBUF_POS 5
#define ADS129X_PDB_REFBUF_MASK 0x20
#define ADS129X_VREF_4V_POS 4
#define ADS129X_VREF_4V_MASK 0x10
#define ADS129X_CLK_EN_POS 3
#define ADS129X_CLK_EN_MASK 0x80
#define ADS129X_INT_TEST_POS 1
#define ADS129X_INT_TEST_MASK 0x02
#define ADS129X_INT_FREQ_POS 0
#define ADS129X_INT_FREQ_MASK 0x01
#define ADS129X_PDx_POS 7
#define ADS129X_PDx_MASK 0x80
#define ADS129X_GAINx_POS 4
#define ADS129X_GAINx_MASK 0x70
#define ADS129X_MUXx_POS 0
#define ADS129X_MUXx_MASK 0x0F
#define ADS129X_CHOP_POS 6
#define ADS129X_CHOP_MASK 0xC0
#define ADS129X_PDB_RLD_POS 5
#define ADS129X_PDB_RLD_MASK 0x20
#define ADS129X_RLD_LOFF_SENSE_POS 4
#define ADS129X_RLD_LOFF_SENSE_MASK 0x10
#define ADS129X_RLD2N_POS 3
#define ADS129X_RLD2N_MASK 0x08
#define ADS129X_RLD2P_POS 2
#define ADS129X_RLD2P_MASK 0x04
#define ADS129X_RLD1N_POS 1
#define ADS129X_RLD1N_MASK 0x02
#define ADS129X_RLD1P_POS 0
#define ADS129X_RLD1P_MASK 0x01
#define ADS129X_FLIP2_POS 5
#define ADS129X_FLIP2_MASK 0x20
#define ADS129X_FLIP1_POS 4
#define ADS129X_FLIP1_MASK 0x10
#define ADS129X_LOFF2N_POS 3
#define ADS129X_LOFF2N_MASK 0x08
#define ADS129X_LOFF2P_POS 2
#define ADS129X_LOFF2P_MASK 0x04
#define ADS129X_LOFFN_POS 1
#define ADS129X_LOFF1N_MASK 0x02
#define ADS129X_LOFF1P_POS 0
#define ADS129X_LOFF1P_MASK 0x01
#define ADS129X_CLK_DIV_POS 6
#define ADS129X_CLK_DIV_MASK 0x40
#define ADS129X_RESP_DEMOD_EN1_POS 7
#define ADS129X_RESP_DEMOD_EN1_MASK 0x80
#define ADS129X_RESP_MOD_EN_POS 6
#define ADS129X_RESP_MOD_EN_MASK 0x40
#define ADS129X_RESP_PH_POS 2
#define ADS129X_RESP_PH_MASK 0x3c
#define ADS129X_RESP_CTRL_POS 0
#define ADS129X_RESP_CTRL_MASK 0x01
#define ADS129X_CALIB_ON_POS 7
#define ADS129X_CALIB_ON_MASK 0x80
#define ADS129X_RESP_FREQ_POS 2
#define ADS129X_RESP_FREQ_MASK 0x04
#define ADS129X_RLDREF_INT_POS 1
#define ADS129X_RLDREF_INT_MASK 0x02
/**
* @}
*/
/** @addtogroup ADS129X_TYP_COMMAND ADS1291 TYP COMMAND
* @brief
* @{
*/
/* System Commands */
#define ADS129X_COMMAND_WAKEUP 0x02 // Wake-up from standby mode
#define ADS129X_COMMAND_STANDBY 0x04 // Enter standby mode
#define ADS129X_COMMAND_RESET 0x06 // Reset the device
#define ADS129X_COMMAND_START 0x08 // Start or restart (synchronize) conversion
#define ADS129X_COMMAND_STOP 0x0A // Stop conversion
#define ADS129X_COMMAND_OFFSETCAL 0x1A // Channel offset calibration
/* Data Read Commands */
#define ADS129X_COMMAND_RDATAC 0x10 // Enable Read Data Continuous mode. This mode is the default mode at power-up.(1)
#define ADS129X_COMMAND_SDATAC 0x11 // Stop Read Data Continuously mode
#define ADS129X_COMMAND_RDATA 0x12 // Read data by command; supports multiple read back
/* Register Read Commands,最后5位为读写的地址 */
#define ADS129X_COMMAND_RREG 0x20 // Read n nnnn registers starting at address r rrrr
#define ADS129X_COMMAND_WREG 0x40 // Write n nnnn registers starting at address r rrrr
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/** @brief 读取ADS1291的指定寄存器的指定位
* @details
* @param[in] bitname
* @param[in] reg
* @retval
*/
#define ADS129X_GET_BITS(bitname, reg) ((reg & bitname##_MASK) >> bitname##_POS)
/** @brief 设置ADS1291的指定寄存器的指定位
* @details
* @param[in] reg
* @param[in] bitname
* @param[in] val
* @retval NONE
*/
#define ADS129X_SET_BITS(reg, bitname, val) ((reg & ~bitname##_MASK) | ((val << bitname##_POS) & bitname##_MASK))
/* Exported functions --------------------------------------------------------*/
#ifdef __cplusplus
}
#endif

46
src/electrocardiograph_tester.cpp

@ -172,7 +172,7 @@ void ElectrocardiographTester::processRxReportPacket(ify_hrs_packet_t *rx, int32
void ElectrocardiographTester::sendCmd(ify_hrs_packet_t *tx, int32_t txlen, ify_hrs_packet_t *rx, int32_t *rxlen, int32_t overtime) {
if (m_channel == nullptr || m_channel->isOpen() == false) {
throw zexception(kifyhrs_ecode_channle_is_close, "channel is not open");
throw zexception(kifyhrs_ecode_channel_is_close, "channel is not open");
}
uint8_t txindex = m_txindex++;
@ -282,32 +282,33 @@ void ElectrocardiographTester::syncTime(uint8_t year, uint8_t month, uint8_t day
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(sync_time_cmd_t), m_rxcmd, &m_rxsize, 100);
return;
}
#if 0
void ElectrocardiographTester::startCapture() {
lock_guard<mutex> lock(m_tx_lock);
m_txcmd->cmd = ify_hrs_cmd_start_capture;
m_txcmd->cmd = ify_hrs_cmd_start_storage;
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
return;
}
void ElectrocardiographTester::stopCapture() {
lock_guard<mutex> lock(m_tx_lock);
m_txcmd->cmd = ify_hrs_cmd_stop_capture;
m_txcmd->cmd = ify_hrs_cmd_stop_storage;
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
return;
}
#endif
void ElectrocardiographTester::startRealtimeReport() {
lock_guard<mutex> lock(m_tx_lock);
m_txcmd->cmd = ify_hrs_cmd_start_realtime_report;
m_txcmd->cmd = ify_hrs_cmd_start_realtime_preview;
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
return;
}
void ElectrocardiographTester::stopRealtimeReport() {
lock_guard<mutex> lock(m_tx_lock);
m_txcmd->cmd = ify_hrs_cmd_stop_realtime_report;
m_txcmd->cmd = ify_hrs_cmd_stop_realtime_preview;
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
return;
}
@ -371,3 +372,36 @@ void ElectrocardiographTester::reset() {
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
return;
}
void ElectrocardiographTester::testCmdStartCapture() {
lock_guard<mutex> lock(m_tx_lock);
m_txcmd->cmd = ify_hrs_test_cmd_start_capture;
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
}
void ElectrocardiographTester::testCmdStopCapture() {
lock_guard<mutex> lock(m_tx_lock);
m_txcmd->cmd = ify_hrs_test_cmd_stop_capture;
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
}
uint8_t ElectrocardiographTester::testCmdReadReg(uint8_t addr) {
lock_guard<mutex> lock(m_tx_lock);
m_txcmd->cmd = ify_hrs_test_cmd_read_reg;
m_txcmd->data[0] = addr;
m_txcmd->cmd = ify_hrs_test_cmd_read_reg;
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + 1, m_rxcmd, &m_rxsize, 100);
return m_rxcmd->data[0];
}
void ElectrocardiographTester::testCmdWriteReg(uint8_t addr, uint8_t val) {
lock_guard<mutex> lock(m_tx_lock);
m_txcmd->cmd = ify_hrs_test_cmd_write_reg;
m_txcmd->data[0] = addr;
m_txcmd->data[1] = val;
m_txcmd->cmd = ify_hrs_test_cmd_write_reg;
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + 2, m_rxcmd, &m_rxsize, 100);
}

29
src/electrocardiograph_tester.hpp

@ -12,8 +12,8 @@
#include <thread>
#include <vector>
#include "../ify_hrs_protocol/heart_rate_sensor_protocol.h"
#include "electrocardiograph_tester.hpp"
#include "heart_rate_sensor_protocol.h"
#define SDK_VERSION 1
@ -27,9 +27,9 @@ typedef enum {
kcmd_ch4_data,
} raw_data_type_t;
typedef function<void(bool checkok,ify_hrs_packet_t *report_packet, size_t len)> on_report_t;
typedef function<void(uint32_t rxcnt, uint32_t report_packet_checksum)> on_ch4_check_sum_packet_report_t;
typedef function<void(raw_data_type_t type, uint8_t *hex, uint32_t hexlen)> on_raw_data_t;
typedef function<void(bool checkok, ify_hrs_packet_t *report_packet, size_t len)> on_report_t;
typedef function<void(uint32_t rxcnt, uint32_t report_packet_checksum)> on_ch4_check_sum_packet_report_t;
typedef function<void(raw_data_type_t type, uint8_t *hex, uint32_t hexlen)> on_raw_data_t;
class IDataChannel {
public:
@ -96,17 +96,22 @@ class ElectrocardiographTester {
void readDeviceState(device_state_receipt_t *state); // 读取设备状态信息
void readTime(read_time_receipt_t *time); // 读取设备时间
void syncTime(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); // 同步设备时间
void startCapture(); // 开始采集
void stopCapture(); // 停止采集
void startRealtimeReport(); // 开始实时数据上报
void stopRealtimeReport(); // 停止实时数据上报
void readRecordsInfo(int32_t recordoff, read_record_info_receipt_t *recordinfo); // 读取记录信息
void delRecord(uint8_t *recordId); // 删除记录
void startUploadRecord(uint8_t *recordId); // 开始上传记录
void stopUploadRecord(); // 停止上传记录
// void startCapture(); // 开始采集
// void stopCapture(); // 停止采集
void startRealtimeReport(); // 开始实时数据上报
void stopRealtimeReport(); // 停止实时数据上报
void readRecordsInfo(int32_t recordoff, read_record_info_receipt_t *recordinfo); // 读取记录信息
void delRecord(uint8_t *recordId); // 删除记录
void startUploadRecord(uint8_t *recordId); // 开始上传记录
void stopUploadRecord(); // 停止上传记录
void readSn(string &sn);
void reset(); // 重置设备
void testCmdStartCapture();
void testCmdStopCapture();
uint8_t testCmdReadReg(uint8_t addr);
void testCmdWriteReg(uint8_t addr, uint8_t val);
private:
void sendCmd(ify_hrs_packet_t *tx, int32_t txlen, ify_hrs_packet_t *rx, int32_t *rxlen, int32_t overtime);
void processCh3RxData(uint8_t *rx, int32_t rxlen); // 指令通道

236
src/heart_rate_sensor_protocol.h

@ -1,236 +0,0 @@
#include <stdint.h>
#ifndef HEART_RATE_SENSOR_PROTOCOL_H
#define HEART_RATE_SENSOR_PROTOCOL_H
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 1)
typedef struct {
uint8_t frame_type;
uint8_t frame_index;
uint8_t cmd;
uint8_t data[];
} ify_hrs_packet_t;
typedef enum {
kifyhrs_ecode_success = 0,
kifyhrs_ecode_unkown_error = 1,
kifyhrs_ecode_cmd_not_support = 2,
kifyhrs_ecode_illegal_parameter = 3,
kifyhrs_ecode_device_busy = 4,
kifyhrs_ecode_hardware_error = 5,
kifyhrs_ecode_sensor_drop = 6,
kifyhrs_ecode_no_record_find = 7,
kifyhrs_ecode_channle_is_close = 100,
kifyhrs_ecode_overtime = 101,
kifyhrs_ecode_logic_error = 102,
} ify_hrs_error_code_t;
static inline const char* hrs_ecode2str(ify_hrs_error_code_t ecode) {
switch (ecode) {
case kifyhrs_ecode_success:
return "success";
case kifyhrs_ecode_unkown_error:
return "unkown error";
case kifyhrs_ecode_cmd_not_support:
return "cmd not support";
case kifyhrs_ecode_illegal_parameter:
return "illegal parameter";
case kifyhrs_ecode_device_busy:
return "device busy";
case kifyhrs_ecode_hardware_error:
return "hardware error";
case kifyhrs_ecode_sensor_drop:
return "sensor drop";
case kifyhrs_ecode_no_record_find:
return "no record find";
case kifyhrs_ecode_channle_is_close:
return "channle is close";
case kifyhrs_ecode_overtime:
return "overtime";
case kifyhrs_ecode_logic_error:
return "logic error";
default:
return "unkown error";
}
}
typedef enum {
kifyhrs_pt_cmd = 1,
kifyhrs_pt_cmd_receipt = 2,
kifyhrs_pt_report = 3,
kifyhrs_pt_error_receipt = 4,
} ify_hrs_packet_type_t;
typedef enum {
kifyhrs_sensor_pos_none = 0, //
kifyhrs_sensor_pos_I = 1, // I
kifyhrs_sensor_pos_II = 2, // II
kifyhrs_sensor_pos_III = 3, // III
kifyhrs_sensor_pos_V1 = 4, // V1
kifyhrs_sensor_pos_V2 = 5, // V2
kifyhrs_sensor_pos_V3 = 6, // V3
kifyhrs_sensor_pos_V4 = 7, // V4
kifyhrs_sensor_pos_V5 = 8, // V5
kifyhrs_sensor_pos_V6 = 9, // V6
kifyhrs_sensor_pos_aVR = 10, //
kifyhrs_sensor_pos_aVL = 11, //
kifyhrs_sensor_pos_aVF = 12, //
} ify_hrs_sensor_pos_t;
typedef enum {
ify_hrs_cmd_read_device_version = 1,
ify_hrs_cmd_read_sensor_info = 2,
ify_hrs_cmd_read_device_state = 3,
ify_hrs_cmd_read_time = 4,
ify_hrs_cmd_sync_time = 5,
ify_hrs_cmd_start_capture = 6,
ify_hrs_cmd_stop_capture = 7,
ify_hrs_cmd_start_realtime_report = 8,
ify_hrs_cmd_stop_realtime_report = 9,
ify_hrs_cmd_read_records_info = 10,
ify_hrs_cmd_del_record = 11,
ify_hrs_cmd_start_upload_record = 12,
ify_hrs_cmd_enter_ota = 13,
ify_hrs_cmd_read_sn = 14,
ify_hrs_cmd_reset = 15,
ify_hrs_cmd_stop_upload_record = 16,
ify_hrs_cmd_start_capture_time_v2 = 17,
ify_hrs_cmd_start_upload_record_v2 = 18,
ify_hrs_report_heartrate_data = 101,
ify_hrs_report_battery_level = 102,
ify_hrs_report_low_battey_level = 103,
ify_hrs_report_sample_finish_end = 104,
ify_hrs_report_sensor_drop_detect = 105,
ify_hrs_report_record_upload_end = 106,
} ify_hrs_cmd_t;
/*******************************************************************************
* packet_struct *
*******************************************************************************/
typedef struct {
uint16_t placeholder;
uint16_t blestack_version;
uint16_t bootloader_version;
uint16_t firmware_version;
uint16_t hardware_version;
} device_version_info_receipt_t;
typedef struct {
uint8_t sensor_num; //
uint8_t sensor_precision; //
uint8_t sensor_sample_rate; //
uint8_t sensor0_pos; //
uint8_t sensor1_pos; //
uint8_t sensor2_pos; //
} sensor_info_receipt_t;
typedef struct {
uint8_t drop_state0;
uint8_t drop_state1;
struct {
uint8_t sampling_state : 1; //
uint8_t report_state : 1; //
uint8_t low_battery : 1; //
uint8_t full_storge : 1; //
uint8_t holder : 4; //
} device_state0;
uint8_t device_state1; //
uint8_t powerlevel; //
uint8_t storage_item_num; //
} device_state_receipt_t;
typedef struct {
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
} read_time_receipt_t;
typedef struct {
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
} sync_time_cmd_t;
typedef struct {
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
} start_capture_cmd_t;
typedef struct {
uint8_t record_index; //
} read_record_info_cmd_t;
typedef struct {
uint8_t record_id[6];
uint32_t frameNum;
uint32_t dataSize;
uint8_t sensorNum;
uint8_t captureRate; // N*10HZ
uint8_t capturePrecision;
uint8_t compressAlgorithm; //
uint32_t checksum;
} read_record_info_receipt_t;
#define A sizeof(read_record_info_receipt_t)
typedef struct {
uint8_t record_id[6];
} del_record_cmd_t;
typedef struct {
uint8_t record_id[6];
} start_upload_record_cmd_t;
typedef struct {
uint8_t sn[14];
} read_sn_receipt_t;
typedef struct {
uint8_t errorcode;
} error_receipt_t;
/*******************************************************************************
* *
*******************************************************************************/
typedef struct {
uint8_t frame_type;
uint8_t frame_index;
uint8_t cmd;
uint32_t sample_data_index;
uint8_t data[]; //
} heartrate_report_packet_t;
typedef struct {
uint8_t frame_type;
uint8_t frame_index;
uint8_t cmd;
uint8_t drop_state0;
uint8_t drop_state1;
} sensor_drop_event_report_packet_t;
#pragma pack(pop)
#ifdef __cplusplus
}
#endif
#endif
Loading…
Cancel
Save