#include "OneOsc.h" #include #include #include #include #include #include "ThreadPool/ThreadPool.h" #include "OscDataInfo.h" OneOscilloscope::OneOscilloscope() { /* 复位线程运行状态位 */ m_mapThreadState.clear(); /* 连接信号和槽 */ connect(&m_timerConnect, &QTimer::timeout, this, &OneOscilloscope::do_reconnectOsc); connect(this, &OneOscilloscope::signal_reconnectOsc, this, &OneOscilloscope::do_reconnectOsc); } OneOscilloscope::~OneOscilloscope() { if(m_isOpen) { closeOSC(); } if(m_buffer != nullptr) { delete[] m_buffer; m_buffer = nullptr; } if(m_bufferChnA != nullptr) { delete[] m_bufferChnA; m_bufferChnA = nullptr; } if(m_bufferChnB != nullptr) { delete[] m_bufferChnB; m_bufferChnB = nullptr; } } /** * @brief 初始化示波器,传入通道A和B的通道号,1和2是主设备,其他都是从设备 * * @param oscNum * */ void OneOscilloscope::initOSC(int oscNum) { m_logger = spdlog::get("OscData"); if(m_logger == nullptr) { SPDLOG_ERROR("获取 OscData logger 失败"); return; } m_oscNum = oscNum; QString libName = QApplication::applicationDirPath(); if(oscNum == 1) { libName = libName + QString("/USBInterFace.dll"); } else if(oscNum == 2) { libName = libName + QString("/USBInterFace2.dll"); } else if (oscNum == 3) { libName = libName + QString("/USBInterFace3.dll"); } else if (oscNum == 4) { libName = libName + QString("/USBInterFace4.dll"); } else { SPDLOG_LOGGER_ERROR(m_logger, "示波器编号错误!"); return; } m_usbInterface = std::make_shared(); if(!m_usbInterface->loadLib(libName)) { SPDLOG_LOGGER_ERROR(m_logger, "加载USBInterFace库失败! 路径:{}", libName.toStdString()); return; } /* 分配缓冲区内存 */ m_buffer = new unsigned char[BUFFER_SIZE]; m_bufferChnA = new unsigned char[BUFFER_SIZE / 2]; m_bufferChnB = new unsigned char[BUFFER_SIZE / 2]; /* 初始化数据、颜色矩阵,包括示波器自身编号 */ initMatrixPtr(); /* 设置默认的初始化参数 */ m_oneTimeGrid = 200; } /* 打开示波器 */ bool OneOscilloscope::openOSC() { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return false; } if(m_isOpen) { SPDLOG_LOGGER_ERROR(m_logger, "示波器已经打开!"); return false; } /* 指定示波器设备型号,OSCA02是6 */ m_usbInterface->specifyDevId(6); // auto ret = m_usbInterface->devOpen(); auto ret = m_usbInterface->devOpenWithID(m_oscNum); if(ret != 0) { SPDLOG_LOGGER_ERROR(m_logger, "打开示波器失败! 编号:{}", m_oscNum); /* 打开定时器 */ if(!m_timerConnect.isActive()) { m_timerConnect.setTimerType(Qt::PreciseTimer); m_timerConnect.setSingleShot(false); m_timerConnect.start(1000); m_isOpen = false; sendOscState(false); } return false; }else { if(m_timerConnect.isActive()) { m_timerConnect.stop(); } } /* 获取缓冲区首指针 */ m_devBuffer = m_usbInterface->bufferWR(-1); if(m_devBuffer == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "获取缓冲区指针失败!"); return false; } /* 关闭AB通道合并 */ m_ctrlByte1 &= 0x7f; m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); /* 开启B通道 */ m_ctrlByte1 &= 0xfe; m_ctrlByte1 |= 0x01; m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); /* 设置硬件触发命令,关闭外部触发,好像是有的设备需要,有的不需要 */ m_ctrlByte1 &= 0xdf; m_ctrlByte1 |= 0x00; m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); /* 设置触发位置在缓冲区中间 */ m_usbInterface->usbCtrlTrans(0x18, 0xff); m_usbInterface->usbCtrlTrans(0x17, 0x7f); /* 设置缓冲区大小 */ m_usbInterface->setInfo(BUFFER_SIZE); /* 获取零电压值 */ getZeroVoltage(); /* 获取电压校准系数 */ getVoltageCalibration(); /* 设置采样率 */ setSampleRate(OscSampleRate::SR_100MHZ); /* 设置电压等级 */ setChannelARange(m_rangeA); setChannelBRange(m_rangeB); m_isOpen = true; return true; } /* 关闭示波器 */ void OneOscilloscope::closeOSC() { if(m_runCapture) { stopCapture(); } if(m_usbInterface != nullptr) { m_usbInterface->devClose(); } m_isOpen = false; SPDLOG_INFO("示波器已关闭"); } /* 开始采集数据 */ bool OneOscilloscope::startCapture() { if(m_buffer == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "缓冲区指针为空!"); return false; } /* 判断示波器是否已经打开成功 */ if(!m_isOpen) { SPDLOG_LOGGER_ERROR(m_logger, "示波器{}未打开!", m_oscNum); return false; } /* 判断是否已经正在采集中 */ if(m_runCapture) { return false; } /* 清空数据矩阵 */ memset(m_buffer, 0, BUFFER_SIZE); memset(m_bufferChnA, 0, BUFFER_SIZE / 2); memset(m_bufferChnB, 0, BUFFER_SIZE / 2); resetData(); /* 启动子线程 */ m_runCapture = true; CPPTP.add_task(&OneOscilloscope::threadCaptureData, this); CPPTP.add_task(&OneOscilloscope::threadSeparateData, this); CPPTP.add_task(&OneOscilloscope::threadProcessData_A, this); CPPTP.add_task(&OneOscilloscope::threadProcessData_B, this); CPPTP.add_task(&OneOscilloscope::threadCopyData, this, OscChannel::CH_A); CPPTP.add_task(&OneOscilloscope::threadCopyData, this, OscChannel::CH_B); return true; } /** * @brief 开启采集数据,带有条件判断,如果两个通道都没有被使用,则不开启 * * @return true * @return false */ bool OneOscilloscope::startCaptureWithCondition() { if(m_chnUsedA || m_chnUsedB) { return startCapture(); } return false; } /* 停止采集数据 */ void OneOscilloscope::stopCapture() { if(!m_runCapture) { return; } // for(const auto& it : m_mapThreadState) // { // /* 打印线程ID */ // std::hash hasher; // size_t id = hasher(it.first); // SPDLOG_ERROR("线程ID:{}, 线程状态: {}", id, it.second.load()); // } /* 停止重连定时器 */ if(m_timerConnect.isActive()) { m_timerConnect.stop(); } /* 退出所有线程 */ m_runCapture = false; m_condCapture.notify_all(); m_condBuffer_A.notify_all(); m_condBuffer_B.notify_all(); m_condCopyData_A.notify_all(); m_condCopyData_B.notify_all(); waitAllThreadExit(); // qDebug() << "Osc:" << m_oscNum << ",thread exit all"; // SPDLOG_WARN("示波器 {} 线程已全部退出", m_oscNum); // for(const auto& it : m_mapThreadState) // { // /* 打印线程ID */ // std::hash hasher; // size_t id = hasher(it.first); // SPDLOG_ERROR("线程ID:{}, 线程状态: {}", id, it.second.load()); // } /* 清空采集的数据 */ resetData(); SPDLOG_LOGGER_INFO(m_logger, "示波器{}已停止采集数据", m_oscNum); } /* 获取颜色矩阵内存指针 */ EyeColorMatrix* OneOscilloscope::getColorMatrixPtr(OscChannel chn) { if(chn == OscChannel::CH_A) { return m_colorMatrix_A; } else if(chn == OscChannel::CH_B) { return m_colorMatrix_B; } return nullptr; } /* 设置颜色矩阵,把外部的颜色矩阵设置过来,通过这里的子线程拷贝进去 */ void OneOscilloscope::setColorMatrixPtr(OscChnNum num, EyeColorMatrix* colorMatrix) { OscChannel chn = (static_cast(num) % 2 == 1) ? OscChannel::CH_A : OscChannel::CH_B; if(chn == OscChannel::CH_A) { m_gColorMatrix_A = colorMatrix; } else if(chn == OscChannel::CH_B) { m_gColorMatrix_B = colorMatrix; } } /* 设置示波器的采样率 */ void OneOscilloscope::setSampleRate(OscSampleRate rate) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } m_ctrlByte0 &= 0xf0; if(rate == OscSampleRate::SR_49KHZ) { m_ctrlByte0 |= 0x0e; m_SampleIntervalTime.store(20408.16); } else if(rate == OscSampleRate::SR_96KHZ) { m_ctrlByte0 |= 0x04; m_SampleIntervalTime.store(10416.67); } else if(rate == OscSampleRate::SR_781KHZ) { m_ctrlByte0 |= 0x0c; m_SampleIntervalTime.store(1280.0); } else if(rate == OscSampleRate::SR_12_5MHZ) { m_ctrlByte0 |= 0x08; m_SampleIntervalTime.store(80.0); } else if(rate == OscSampleRate::SR_100MHZ) { m_ctrlByte0 |= 0x00; m_SampleIntervalTime.store(10); } else { SPDLOG_LOGGER_ERROR(m_logger, "采样率设置错误!"); return; } m_usbInterface->usbCtrlTrans(0x94, m_ctrlByte0); } /** * @brief 将示波器两个通道合并为一个通道 * 将AB两个通道的资源全部给A,B通道失效,A通道的采样率和带宽翻倍 * @param merge 是否合并 */ void OneOscilloscope::setChannelMerge(bool merge) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } if(merge) { m_ctrlByte1 |= 0x80; }else { m_ctrlByte1 &= 0x7f; } m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); } /** * @brief 设置通道A输入量程,这个函数需要在打开示波器之后调用 * * @param range */ void OneOscilloscope::setChannelARange(OscVoltageRange range) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } m_ctrlByte1 &= 0xf7; if(range == OscVoltageRange::CR_100MV) { m_usbInterface->usbCtrlTrans(0x22, 0x06); } else if(range == OscVoltageRange::CR_250MV) { m_usbInterface->usbCtrlTrans(0x22, 0x04); } else if(range == OscVoltageRange::CR_500MV) { m_usbInterface->usbCtrlTrans(0x22, 0x02); } else if(range == OscVoltageRange::CR_1V) { m_ctrlByte1 |= 0x08; m_usbInterface->usbCtrlTrans(0x22, 0x06); } else if(range == OscVoltageRange::CR_2V5) { m_ctrlByte1 |= 0x08; m_usbInterface->usbCtrlTrans(0x22, 0x04); } else if(range == OscVoltageRange::CR_5V) { m_ctrlByte1 |= 0x08; m_usbInterface->usbCtrlTrans(0x22, 0x02); } else if(range == OscVoltageRange::CR_8V) { m_ctrlByte1 |= 0x08; m_usbInterface->usbCtrlTrans(0x22, 0x00); } m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); setZeroVoltageAndCalibration(OscChannel::CH_A, range); m_rangeA = range; } /** * @brief 设置通道B输入量程 * * @param range */ void OneOscilloscope::setChannelBRange(OscVoltageRange range) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } m_ctrlByte1 &= 0xf9; if(range == OscVoltageRange::CR_100MV) { m_ctrlByte1 |= 0x06; m_usbInterface->usbCtrlTrans(0x23, 0x40); } else if(range == OscVoltageRange::CR_250MV) { m_ctrlByte1 |= 0x04; m_usbInterface->usbCtrlTrans(0x23, 0x40); } else if(range == OscVoltageRange::CR_500MV) { m_ctrlByte1 |= 0x02; m_usbInterface->usbCtrlTrans(0x23, 0x40); } else if(range == OscVoltageRange::CR_1V) { m_ctrlByte1 |= 0x06; m_usbInterface->usbCtrlTrans(0x23, 0x00); } else if(range == OscVoltageRange::CR_2V5) { m_ctrlByte1 |= 0x04; m_usbInterface->usbCtrlTrans(0x23, 0x00); } else if(range == OscVoltageRange::CR_5V) { m_ctrlByte1 |= 0x02; m_usbInterface->usbCtrlTrans(0x23, 0x00); } else if(range == OscVoltageRange::CR_8V) { m_usbInterface->usbCtrlTrans(0x23, 0x00); } else { SPDLOG_LOGGER_ERROR(m_logger, "输入量程设置错误!"); return; } m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); setZeroVoltageAndCalibration(OscChannel::CH_B, range); m_rangeB = range; } /** * @brief 设置通道耦合方式 * * @param channel 通道 * @param coupling 耦合方式,DC或者AC */ void OneOscilloscope::setChannelCoupling(OscChannel channel, OscChannelCoupling coupling) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } if(channel == OscChannel::CH_A) { m_ctrlByte0 &= 0xef; if(coupling == OscChannelCoupling::DC) { m_ctrlByte0 |= 0x10; } else if(coupling == OscChannelCoupling::AC) {} else { SPDLOG_LOGGER_ERROR(m_logger, "耦合方式设置错误!"); return; } m_usbInterface->usbCtrlTrans(0x94, m_ctrlByte0); } else if(channel == OscChannel::CH_B) { m_ctrlByte1 &= 0xef; if(coupling == OscChannelCoupling::AC) { m_ctrlByte1 |= 0x10; } else if(coupling == OscChannelCoupling::DC) {} else { SPDLOG_LOGGER_ERROR(m_logger, "耦合方式设置错误!"); return; } m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); } else { SPDLOG_LOGGER_ERROR(m_logger, "通道设置错误!"); return; } } /* 开启或关闭通道A触发 */ void OneOscilloscope::setChannelATrigger(bool enable) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } if(enable) { m_usbInterface->usbCtrlTrans(0xE7, 0x01); } else { m_usbInterface->usbCtrlTrans(0xE7, 0x00); } } /* 开启外触发 */ void OneOscilloscope::setExternalTrigger(bool enable) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } if(enable) { m_usbInterface->usbCtrlTrans(0xE7, 0x01); m_ctrlByte1 &= 0xdf; m_ctrlByte1 |= 0x20; m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); } else { m_usbInterface->usbCtrlTrans(0xE7, 0x00); m_ctrlByte1 &= 0xdf; m_ctrlByte1 |= 0x00; m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); } } /* 设置触发方式 */ void OneOscilloscope::setTriggerMode(OscTriggerMode mode) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } if(mode == OscTriggerMode::TM_RISE) { m_usbInterface->usbCtrlTrans(0xC5, 0x00); } else if (mode == OscTriggerMode::TM_DOWN) { m_usbInterface->usbCtrlTrans(0xC5, 0x01); } else if (mode == OscTriggerMode::TM_DOUBLE) { m_usbInterface->usbCtrlTrans(0xC5, 0x03); } } /** * @brief 设置触发电平 * * @param level 0~255的值 */ void OneOscilloscope::setTriggerLevel(unsigned char level) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } m_usbInterface->usbCtrlTrans(0x16, level); } /* 设置触发灵敏度 */ void OneOscilloscope::setTriggerSensitivity(OscTriggerSensitivity sensitivity) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } if(sensitivity == OscTriggerSensitivity::TS_LOW) { m_usbInterface->usbCtrlTrans(0x2b, 0); } else if(sensitivity == OscTriggerSensitivity::TS_HIGH) { m_usbInterface->usbCtrlTrans(0x2b, 1); } else { SPDLOG_LOGGER_ERROR(m_logger, "触发灵敏度设置错误!"); return; } } /* 设置触发在缓冲区的哪个位置 */ void OneOscilloscope::setTriggerPosition(unsigned char lowByte, unsigned char highByte) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } m_usbInterface->usbCtrlTrans(0x18, lowByte); m_usbInterface->usbCtrlTrans(0x17, highByte); } /* 设置时间刻度 */ void OneOscilloscope::setTimeGridValue(OscTimeGridValue value) { m_oneTimeGrid = static_cast(value); // SPDLOG_LOGGER_DEBUG(m_logger, "时间刻度设置为: {}", m_oneTimeGrid.load()); /* 修改时间刻度理论上需要清空已有的缓存 */ } /* 获取示波器不同档位下的零电压值 */ void OneOscilloscope::getZeroVoltage() { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } /* 获取通道A零电压值 */ unsigned char zeroVoltage = 0; /* 2V档位,正负8V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x82); m_mapChAZeroVoltage.insert(OscVoltageRange::CR_8V, zeroVoltage); /* 1V档位,正负5V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x01); m_mapChAZeroVoltage.insert(OscVoltageRange::CR_5V, zeroVoltage); /* 500mV档位,正负2.5V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x0e); m_mapChAZeroVoltage.insert(OscVoltageRange::CR_2V5, zeroVoltage); /* 200mV档位,正负1V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x14); m_mapChAZeroVoltage.insert(OscVoltageRange::CR_1V, zeroVoltage); /* 100mV档位,正负500mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x12); m_mapChAZeroVoltage.insert(OscVoltageRange::CR_500MV, zeroVoltage); /* 50mV档位,正负250mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x10); m_mapChAZeroVoltage.insert(OscVoltageRange::CR_250MV, zeroVoltage); /* 20mV档位,正负100mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0xa0); m_mapChAZeroVoltage.insert(OscVoltageRange::CR_100MV, zeroVoltage); /* 获取通道B零电压值 */ /* 2V档位,正负8V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x72); m_mapChBZeroVoltage.insert(OscVoltageRange::CR_8V, zeroVoltage); /* 1V档位,正负5V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x02); m_mapChBZeroVoltage.insert(OscVoltageRange::CR_5V, zeroVoltage); /* 500mV档位,正负2.5V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x0f); m_mapChBZeroVoltage.insert(OscVoltageRange::CR_2V5, zeroVoltage); /* 200mV档位,正负1V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x15); m_mapChBZeroVoltage.insert(OscVoltageRange::CR_1V, zeroVoltage); /* 100mV档位,正负500mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x13); m_mapChBZeroVoltage.insert(OscVoltageRange::CR_500MV, zeroVoltage); /* 50mV档位,正负250mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x11); m_mapChBZeroVoltage.insert(OscVoltageRange::CR_250MV, zeroVoltage); /* 20mV档位,正负100mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0xa1); m_mapChBZeroVoltage.insert(OscVoltageRange::CR_100MV, zeroVoltage); } /* 打印出零电压值 */ void OneOscilloscope::printZeroVoltage(OscChannel channel) { if(channel == OscChannel::CH_A) { for(auto it = m_mapChAZeroVoltage.begin(); it != m_mapChAZeroVoltage.end(); ++it) { SPDLOG_LOGGER_INFO(m_logger, "通道A {} 量程下的零电压值为: {}", static_cast(it.key()), it.value()); } } else if(channel == OscChannel::CH_B) { for(auto it = m_mapChBZeroVoltage.begin(); it != m_mapChBZeroVoltage.end(); ++it) { SPDLOG_LOGGER_INFO(m_logger, "通道B {} 量程下的零电压值为: {}", static_cast(it.key()), it.value()); } } else { SPDLOG_LOGGER_ERROR(m_logger, "通道设置错误!"); return; } } /* 获取不同档位下电压校准系数 */ void OneOscilloscope::getVoltageCalibration() { if (m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } /* 获取通道A电压校准系数 */ unsigned char voltageCalibration = 0; /* 2V档位,正负8V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0xc2); m_mapChAVoltageAmplitudeRatio.insert(OscVoltageRange::CR_8V, voltageCalibration); /* 1V档位,正负5V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x03); m_mapChAVoltageAmplitudeRatio.insert(OscVoltageRange::CR_5V, voltageCalibration); /* 500mV档位,正负2.5V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x08); m_mapChAVoltageAmplitudeRatio.insert(OscVoltageRange::CR_2V5, voltageCalibration); /* 200mV档位,正负1V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x06); m_mapChAVoltageAmplitudeRatio.insert(OscVoltageRange::CR_1V, voltageCalibration); /* 100mV档位,正负500mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x09); m_mapChAVoltageAmplitudeRatio.insert(OscVoltageRange::CR_500MV, voltageCalibration); /* 50mV档位,正负250mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x0a); m_mapChAVoltageAmplitudeRatio.insert(OscVoltageRange::CR_250MV, voltageCalibration); /* 20mV档位,正负100mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x2a); m_mapChAVoltageAmplitudeRatio.insert(OscVoltageRange::CR_100MV, voltageCalibration); /* 获取通道B电压校准系数 */ /* 2V档位,正负8V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0xd2); m_mapChBVoltageAmplitudeRatio.insert(OscVoltageRange::CR_8V, voltageCalibration); /* 1V档位,正负5V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x04); m_mapChBVoltageAmplitudeRatio.insert(OscVoltageRange::CR_5V, voltageCalibration); /* 500mV档位,正负2.5V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x0b); m_mapChBVoltageAmplitudeRatio.insert(OscVoltageRange::CR_2V5, voltageCalibration); /* 200mV档位,正负1V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x07); m_mapChBVoltageAmplitudeRatio.insert(OscVoltageRange::CR_1V, voltageCalibration); /* 100mV档位,正负500mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x0c); m_mapChBVoltageAmplitudeRatio.insert(OscVoltageRange::CR_500MV, voltageCalibration); /* 50mV档位,正负250mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x0d); m_mapChBVoltageAmplitudeRatio.insert(OscVoltageRange::CR_250MV, voltageCalibration); /* 20mV档位,正负100mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x2d); m_mapChBVoltageAmplitudeRatio.insert(OscVoltageRange::CR_100MV, voltageCalibration); } /* 打印出电压校准系数 */ void OneOscilloscope::printVoltageCalibration(OscChannel channel) { if(channel == OscChannel::CH_A) { for(auto it = m_mapChAVoltageAmplitudeRatio.begin(); it != m_mapChAVoltageAmplitudeRatio.end(); ++it) { SPDLOG_LOGGER_INFO(m_logger, "通道A {} 量程下的电压校准系数为: {}", static_cast(it.key()), it.value()); } } else if(channel == OscChannel::CH_B) { for(auto it = m_mapChBVoltageAmplitudeRatio.begin(); it != m_mapChBVoltageAmplitudeRatio.end(); ++it) { SPDLOG_LOGGER_INFO(m_logger, "通道B {} 量程下的电压校准系数为: {}", static_cast(it.key()), it.value()); } } else { SPDLOG_LOGGER_ERROR(m_logger, "通道设置错误!"); return; } } /* 清空数据 */ void OneOscilloscope::resetData() { m_dataMatrix_A->initEyeData(); m_dataMatrix_B->initEyeData(); m_colorMatrix_A->initEyeMapData(); m_colorMatrix_B->initEyeMapData(); } /* 设置示波器的两个通道是否在使用,都不使用则停止采集 */ void OneOscilloscope::setChannelUsed(OscChnNum chn, bool used) { if(chn == m_chnNumA) { m_chnUsedA = used; } else if(chn == m_chnNumB) { m_chnUsedB = used; } /* 判断是开启还是停止采集数据 */ if(m_chnUsedA || m_chnUsedB) { startCapture(); } else { stopCapture(); } } /** * @brief 采集数据,这个是子线程 * */ void OneOscilloscope::threadCaptureData() { SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 开启采集数据线程", m_oscNum); { std::lock_guard lock(m_mutexThreadState); m_mapThreadState.insert(std::make_pair(std::this_thread::get_id(), true)); } /* 这个记录等待数据的时间间隔,超过一定时间就认为设备离线了 */ std::chrono::steady_clock::time_point timePoint = std::chrono::steady_clock::now(); // unsigned char* buffer = nullptr; while(m_runCapture) { // SPDLOG_LOGGER_DEBUG(m_logger, "开始采集数据"); /* 开始采集数据 */ m_usbInterface->usbCtrlTransSimple(0x33); /* 查询数据是否采集完成(应该是填充满128KB的SRAM) * 注意,这里是十进制33,不是0x33 */ timePoint = std::chrono::steady_clock::now(); while(m_usbInterface->usbCtrlTransSimple(0x50) != 33) { std::this_thread::sleep_for(std::chrono::microseconds(100)); /* 如果超过1s还没有数据,就认为设备离线了 */ if(std::chrono::duration_cast(std::chrono::steady_clock::now() - timePoint).count() > 1) { SPDLOG_LOGGER_ERROR(m_logger, "示波器{}离线!", m_oscNum); m_isConnected.store(false); emit signal_reconnectOsc(); sendOscState(false); break; } } // SPDLOG_LOGGER_DEBUG(m_logger, "硬件缓冲区已满"); /* 将数据从示波器的SRAM中拷贝到电脑内存中,1次传输完成,设置超时时间100ms */ m_usbInterface->readBulkData(BUFFER_SIZE, 1, 100, m_devBuffer); /* 等待传输完成 */ auto ret = m_usbInterface->eventCheck(100); if(ret == 0x555) { SPDLOG_LOGGER_ERROR(m_logger, "数据传输超时!"); continue; } // SPDLOG_LOGGER_DEBUG(m_logger, "数据通过USB传输完成"); /* 取出数据 */ m_mutexBuffer.lock(); /* 清空数据缓冲区 */ std::memset(m_buffer, 0, BUFFER_SIZE); /* 从设备动态库拷贝数据 */ std::memcpy(m_buffer, m_devBuffer, BUFFER_SIZE); m_mutexBuffer.unlock(); // SPDLOG_LOGGER_DEBUG(m_logger, "count: {}", count++); m_isCapturedData = true; m_condCapture.notify_one(); /* 清空缓冲区 */ m_usbInterface->resetPipe(); // for(uint32_t i = 0; i < BUFFER_SIZE; i++) // { // SPDLOG_LOGGER_DEBUG(m_logger, "i:{}, {}", i, m_buffer[i]); // } /* 唤醒分离线程 */ m_condCapture.notify_one(); // SPDLOG_LOGGER_DEBUG(m_logger, "示波器编号:{}, 采集数据完成", m_oscNum); } /* 设置退出标志位 */ { std::lock_guard lock(m_mutexThreadState); m_mapThreadState.find(std::this_thread::get_id())->second = false; } SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 采集数据线程结束", m_oscNum); } /* 处理数据线程 */ void OneOscilloscope::threadSeparateData() { SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 开启处理数据线程", m_oscNum); { std::lock_guard lock(m_mutexThreadState); m_mapThreadState.insert(std::make_pair(std::this_thread::get_id(), true)); } while(m_runCapture) { { std::unique_lock lock(m_mutexBuffer); m_condCapture.wait(lock, [this](){ /* 检查线程是否需要退出 */ return (m_isCapturedData.load() || !m_runCapture.load()); }); /* 检查是否是退出线程而被唤醒的 */ if(!m_runCapture) { break; } /* 分离通道AB的数据 */ m_mutexBuffer_A.lock(); m_mutexBuffer_B.lock(); for(uint32_t i = 0; i < BUFFER_SIZE / 2; i++) { m_bufferChnA[i] = m_buffer[i * 2]; m_bufferChnB[i] = m_buffer[i * 2 + 1]; // SPDLOG_LOGGER_DEBUG(m_logger, "i:{}, m_buffer:{}, A:{}, B: {}", i, m_buffer[i], m_bufferChnA[i], m_bufferChnB[i]); } /* 处理数据 */ // SPDLOG_LOGGER_DEBUG(m_logger, "分离数据完成,通道A数据: {}, 通道B数据: {}", m_bufferChnA[3200], m_bufferChnB[3200]); m_mutexBuffer_A.unlock(); m_mutexBuffer_B.unlock(); m_condBuffer_A.notify_one(); m_condBuffer_B.notify_one(); } // SPDLOG_LOGGER_DEBUG(m_logger, "示波器编号:{}, 分离数据完成", m_oscNum); } /* 设置退出标志位 */ { std::lock_guard lock(m_mutexThreadState); m_mapThreadState.find(std::this_thread::get_id())->second = false; } SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 处理数据线程结束", m_oscNum); } /* 处理A通道数据 */ void OneOscilloscope::threadProcessData_A() { { std::lock_guard lock(m_mutexThreadState); m_mapThreadState.insert(std::make_pair(std::this_thread::get_id(), true)); } while (m_runCapture) { std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); std::unique_lock lock(m_mutexBuffer_A); m_condBuffer_A.wait(lock); /* 检查是否是退出线程而被唤醒的 */ if(!m_runCapture) { break; } /* 矫正零电压值 */ for(uint32_t i = 0; i < BUFFER_SIZE / 2; i++) { m_bufferChnA[i] = m_bufferChnA[i] + m_diffVoltageA; // SPDLOG_INFO("{}: {}", i, m_bufferChnA[i]); // m_bufferChnA[i] = calibrationVoltageA(m_bufferChnA[i]); } /* 对零电平进行矫正 */ /* 处理眼图数据 */ if(!parseEyeMapData(OscChannel::CH_A, m_bufferChnA, BUFFER_SIZE / 2)) { continue; } /* 发送条件变量 */ m_condCopyData_A.notify_one(); /* 计算需要的时间 */ // std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); // auto time = std::chrono::duration_cast(end - start); // SPDLOG_LOGGER_DEBUG(m_logger, "示波器编号:{}, 通道A处理数据时间: {}", m_oscNum, time.count()); } /* 设置退出标志位 */ { std::lock_guard lock(m_mutexThreadState); m_mapThreadState.find(std::this_thread::get_id())->second = false; } SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 处理A通道数据线程退出", m_oscNum); } /* 处理B通道数据 */ void OneOscilloscope::threadProcessData_B() { { std::lock_guard lock(m_mutexThreadState); m_mapThreadState.insert(std::make_pair(std::this_thread::get_id(), true)); } while (m_runCapture) { std::unique_lock lock(m_mutexBuffer_B); m_condBuffer_B.wait(lock); /* 检查是否是退出线程而被唤醒的 */ if(!m_runCapture) { break; } /* 矫正零电压值 */ for(uint32_t i = 0; i < BUFFER_SIZE / 2; i++) { m_bufferChnB[i] = m_bufferChnB[i] + m_diffVoltageB; } /* 对零电平进行矫正 */ /* 处理眼图数据 */ if(!parseEyeMapData(OscChannel::CH_B, m_bufferChnB, BUFFER_SIZE / 2)) { // SPDLOG_LOGGER_ERROR(m_logger, "解析B通道数据失败!"); continue; } /* 发送条件变量 */ m_condCopyData_B.notify_one(); } /* 设置退出标志位 */ { // qDebug() << "Osc" << m_oscNum << "Process B data thread exit"; std::lock_guard lock(m_mutexThreadState); m_mapThreadState.find(std::this_thread::get_id())->second = false; } SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 处理B通道数据线程退出", m_oscNum); } /** * @brief 拷贝数据线程,在这个线程中将数据拷贝到OneEyeMap实例中 * 1、拷贝数据的时候是非阻塞的,拿不到锁就进入下一个循环 * 2、在5次都没有拿到锁,就阻塞等待解锁,及时更新数据 * * @param chn */ void OneOscilloscope::threadCopyData(OscChannel chn) { /* 获取数据指针 */ EyeColorMatrix* colorMatrix = nullptr; EyeColorMatrix* gColorMatrix = nullptr; std::condition_variable* condCopyData = nullptr; std::mutex* mutex = nullptr; uint32_t copyCount = 0; if(chn == OscChannel::CH_A) { condCopyData = &m_condCopyData_A; mutex = &m_colorMatrix_A->mutexEyeData; colorMatrix = m_colorMatrix_A; gColorMatrix = m_gColorMatrix_A; } else if(chn == OscChannel::CH_B) { condCopyData = &m_condCopyData_B; mutex = &m_colorMatrix_B->mutexEyeData; colorMatrix = m_colorMatrix_B; gColorMatrix = m_gColorMatrix_B; } else { SPDLOG_LOGGER_ERROR(m_logger, "通道设置错误!"); return; } /* 将线程状态添加到数组中 */ { std::lock_guard lock(m_mutexThreadState); m_mapThreadState.insert(std::make_pair(std::this_thread::get_id(), true)); /* 打印线程ID */ // auto threadID = std::this_thread::get_id(); // std::hash hasher; // size_t id = hasher(threadID); // SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 拷贝数据线程ID: {}", m_oscNum, id); } while(m_runCapture) { std::unique_lock lock(*mutex); /* 这里只要被唤醒,就可以进行下一步,不需要再进行多余的判断 */ condCopyData->wait(lock); /* 检查是否是退出线程而被唤醒的 */ if(!m_runCapture) { break; } /* 将数据拷贝给全局的颜色矩阵数据 */ if(gColorMatrix->mutexEyeData.try_lock()) { /* 非阻塞等待解锁 */ gColorMatrix->copyColorMatrix(colorMatrix->dataMatrix); gColorMatrix->mutexEyeData.unlock(); copyCount = 0; }else { /* 超过5次都没有将数据拷贝过去,就等待拷贝 */ if(copyCount >= 5) { /* 阻塞等待解锁 */ gColorMatrix->mutexEyeData.lock(); gColorMatrix->copyColorMatrix(colorMatrix->dataMatrix); gColorMatrix->mutexEyeData.unlock(); copyCount = 0; }else { copyCount++; } } /* 发送信号,刷新一帧 */ // emit GOscDataInfo.signal_updateOneEyeMap(static_cast(m_chnNumB)); } /* 设置退出标志位 */ { // qDebug() << "Osc" << m_oscNum << "Copy thread exit"; std::lock_guard lock(m_mutexThreadState); m_mapThreadState.find(std::this_thread::get_id())->second = false; } SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 拷贝数据线程退出", m_oscNum); } /** * @brief 解析数据,眼图需要的数据,从C#代码中移植过来 * 1、采样率为100MHz的时候,采样点间隔时间是10ns * x轴时间是1000分度,当x轴整体时间是10us的时候,采样点和分辨率一一对应 * x轴时间大于10us,采样点比分辨率高,无需做什么操作 * x轴时间小于10us,采样点数量会小于1000,那么绘制的矩形小点间隔会比较长,这时候就需要进行插帧 * 2、屏幕中显示多少波形和波形的频率及时间屏幕可以显示的时间长度有关,波形的频率未知,所以这里只能通过调整时间长度来调整波形 * 在屏幕中显示的数目 * 3、当时间长度变小,小到整个屏幕的采样点数目不足1000的时候,就需要进行插值,插值到1000附近 * * @param buffer 数据缓冲区 * @param size 缓冲区大小,单位字节 */ bool OneOscilloscope::parseEyeMapData(OscChannel chn, unsigned char* buffer, unsigned int size) { EyeDataMatrix* eyeDataMatrix = nullptr; EyeColorMatrix* eyeMapMatrix = nullptr; if(chn == OscChannel::CH_A) { // SPDLOG_LOGGER_DEBUG(m_logger, "通道A, 开始解析数据"); /* 获取颜色矩阵 */ eyeDataMatrix = m_dataMatrix_A; eyeMapMatrix = m_colorMatrix_A; } else if (chn == OscChannel::CH_B) { // SPDLOG_LOGGER_DEBUG(m_logger, "通道B, 开始解析数据"); eyeDataMatrix = m_dataMatrix_B; eyeMapMatrix = m_colorMatrix_B; } else { SPDLOG_LOGGER_ERROR(m_logger, "通道设置错误!"); return false; } int bufferSize = size; uint8_t* array = buffer; uint8_t vaMax = 128; uint8_t vaMin = 128; uint8_t tmp = 128; /* 数据预处理,找出最大值和最小值 */ for (int i = 0; i < bufferSize; i++) { /* 取出这组数据的最大值和最小值 */ tmp = array[i]; if (tmp < vaMin) { vaMin = tmp; } if (tmp > vaMax) { vaMax = tmp; } } /* 取绝对值,小于15丢弃,丢弃幅度小于15的数据,这部分可能不是触发的数据 */ int numAmp = std::abs(vaMax - vaMin); if (numAmp <= 15) { // SPDLOG_LOGGER_DEBUG(m_logger, "数据幅度小于15,丢弃"); return false; } /* 计算最大值和最小值的中间数 */ uint8_t vaMid = (vaMax + vaMin) / 2; /* ======================================================================== * * 取出波形 * ======================================================================== */ /* 将采样点添加bool值,如果时间很短,就进行插值,每个采样点之间插入30个值 */ /* 采样率为100MHz的时候,采样点间隔时间是10ns * x轴时间是1000分度,当x轴整体时间是10us的时候,采样点和分辨率一一对应 * x轴时间大于10us,采样点比分辨率高,无需做什么操作 * x轴时间小于10us,采样点数量会小于1000,那么绘制的矩形小点间隔会比较长,这时候就需要进行插帧 */ /* 一个时间格子的采样率个数 */ int oneGridSa = m_oneTimeGrid / m_SampleIntervalTime; /* 当前一个格子中采样点的数目 */ int saTotal = oneGridSa * 10; /* 一个时间格子中采样点的总数 */ /* 采样点个数小于颜色矩阵x方向的个数,就进行插帧 */ bool isNeedFrameInsertion = ( saTotal < g_HorPixel ) ? true : false; int num9 = (int)((double)oneGridSa * 0.25); /* 1/4个时间格子长度 */ /* 记录buffer的值,并添加bool */ std::vector vecData; int numMulti = 0; /* 倍率,可能是1可能是30 */ if (isNeedFrameInsertion == false) { /* 将数据放入到list中,带有bool标志位,全部启用 */ for (int i = 0; i < bufferSize; i++) { vecData.push_back(EyeDataT(true, array[i])); } numMulti = 1; } else { /* 缩放系数小于1.0,下面会进行插值 */ int numTmp = bufferSize - 1; float num11 = 0.0; uint8_t b2 = 0; uint8_t b3 = 0; uint8_t b = 0; /* 进行插值,每个采样点之间插值根据实际的采样点来计算,插值后的采样点个数比1000略大 */ int numMulti2 = 0; double numMulti1 = g_HorPixel * 1.0 / saTotal; if(numMulti1 > 1.0 && numMulti1 < 2.0) { numMulti2 = 1; } else if(numMulti1 >= 2.0 && numMulti1 < 3.0) { numMulti2 = 2; } else if(numMulti1 >= 3.0) { numMulti2 = std::round(numMulti1); } for(int i = 0; i < numTmp; i++) { b2 = array[i]; b3 = array[i + 1]; num11 = (float)(b3 - b2) / numMulti2; vecData.push_back(EyeDataT(true, b2)); for(int j = 0; j < numMulti2; j++) { b = std::round((num11 * (float)j) + (int)b2); vecData.push_back(EyeDataT(true, b)); } vecData.push_back(EyeDataT(true, b3)); } numMulti = numMulti2; } if (vecData.size() <= 0) { SPDLOG_LOGGER_DEBUG(m_logger, "vecData.size() <= 0"); return false; } num9 *= numMulti; /* 1/4个时间格子长度,乘以倍数 */ /* 这里决定着时间的缩放关系,saTotal是整个显示区域的采样点个数 */ long oneJumpSa = saTotal * numMulti; // long oneJumpSa = 1000; /* ======================================================================== * * 寻找波形,找到上升沿和下降沿 * ======================================================================== */ /* 存储下标 */ std::vector listSub; size_t numDataSize = vecData.size() - num9; bool flag3 = true; /* 找到数组中的上升沿和下降沿,并记录其坐标 * 这里寻找上升沿和下降沿是检测的中间值,是每个跳变沿的中部 * 中间值理论上是零值 */ uint8_t vaPre = 0; // uint8_t va = 0; uint8_t vaNext = 0; // SPDLOG_LOGGER_DEBUG(m_logger, "numDataSize: {}", numDataSize); for (size_t i = 10; i < numDataSize; i++) { /* 取出相邻的三个值 */ vaPre = vecData[i - 1].value; // va = vecData[i].value; vaNext = vecData[i + 1].value; if (flag3) { /* 上升沿,就是中间值 */ if (vaPre <= vaMid && vaNext > vaMid) { listSub.push_back((int)i); /* 记录下标 */ flag3 = !flag3; /* 下一个监测下降沿 */ } } else { /* 下降沿 */ if (vaPre >= vaMid && vaNext < vaMid) { listSub.push_back((int)i); flag3 = !flag3; } } // SPDLOG_LOGGER_DEBUG(m_logger, "i: {}, vaPre: {}, vaMid: {}, vaNext: {}", i, vaPre, vaMid, vaNext); /* 采集到600个上升沿和下降沿 */ if (listSub.size() >= 600) { break; } } if (listSub.size() <= 0) { // SPDLOG_LOGGER_DEBUG(m_logger, "上升沿下降沿数目 = 0"); return false; } /* ======================================================================== * * 这里应该是根据跳变沿的中间值,取出完整的跳变沿 * ======================================================================== */ /* 创建一个二维数组,每一行就是一个跳变沿 */ Vec2Data vec2DEyeData; int jumpStart = 0; /* 跳变沿起点 */ size_t jumpEnd = 0; /* 跳变沿终点 */ int num17 = 0; size_t numSubSize = listSub.size(); /* 跳变沿下标的个数 */ int oneThirdSa = (int)(oneJumpSa / 3); /* 一个时间格子中三分之一的采样点个数 */ int numSub1 = 0; int numSub2 = 0; for (size_t i = 0; i < numSubSize; i++) { size_t j = 0; /* 这一个数组就是一个跳变沿,num12是一个跳变沿所有的采样点的个数 */ std::vector vecDataTmp(oneJumpSa, EyeDataT(false, 0)); numSub1 = listSub[i]; /* 取出下标值 */ numSub2 = numSub1 - oneThirdSa; /* 下标往后倒退1/3个时间格子的采样点数,当作起点 */ /* 判断是否小于0,这里是起点 */ jumpStart = numSub2; if (jumpStart <= 0) { jumpStart = 0; } /* 终点往后2/3个时间格子的采样点数,当作终点 */ jumpEnd = numSub1 + oneThirdSa * 2; if (jumpEnd >= vecData.size()) { jumpEnd = vecData.size() - 1; } /* 这里为了去掉jumpStart前面的值,让vecDataTmp从0开始计数 */ num17 = 0; if (numSub2 < 0) { num17 = std::abs(numSub2); } if (numSub2 > 0) { num17 = -numSub2; } /* num14是起点,num15是终点,num17应该是个负值,num17+j从0开始计数 */ for (j = jumpStart; j < jumpEnd; j++) { vecDataTmp[num17 + j].isEyeData = vecData[j].isEyeData; vecDataTmp[num17 + j].value = vecData[j].value; } // for(j = 0; j < oneGridTime2; j++) // { // vecDataTmp[j].isEyeData = vecData[jumpStart + j].isEyeData; // vecDataTmp[j].value = vecData[jumpStart + j].value; // } vec2DEyeData.push_back(std::move(vecDataTmp)); } // listSub.clear(); // vecData.clear(); if (vec2DEyeData.size() <= 0) { // SPDLOG_LOGGER_DEBUG(m_logger, "vec2DEyeData.size() <= 0"); return false; } /* ======================================================================== */ int xPos = 0; int yPos = 0; float dx = 0.0; /* 将数据拷贝到OscData的Matrix中 */ size_t numTmp = 0; /* 将跳变沿数据放入到全局变量中,并根据坐标进行排列 * x轴是这个跳变沿根据时间平分1000份 * y轴是这个值 */ // eyeDataMatrix->mutexEyeData.lock(); for (size_t i = 0; i < vec2DEyeData.size(); i++) { /* 取出一个跳变沿,将其分布在整个 1000 * 256像素的矩阵中 */ std::vector& vecTmp = vec2DEyeData[i]; numTmp = vecTmp.size(); dx = numTmp * 1.0 / g_HorPixel; /* x轴方向1000分 */ for (size_t i = 0; i < numTmp; i++) { if (vecTmp[i].isEyeData) { yPos = vecTmp[i].value; xPos = (int)((float)i / dx); /* 将数据添加到眼图矩阵中 */ eyeDataMatrix->addData(xPos, yPos); } } } // SPDLOG_LOGGER_DEBUG(m_logger, "跳变沿所占的内存大小:{}", vec2DEyeData.size() * oneJumpSa * sizeof(EyeDataT)); vec2DEyeData.clear(); eyeDataMatrix->eyeStatisticalWeight(); eyeDataMatrix->eyeLessenTheBurden(); auto eyeData = eyeDataMatrix->eyeZoomOut(); // eyeDataMatrix->mutexEyeData.unlock(); eyeMapMatrix->mutexEyeData.lock(); /* 拷贝数据 */ eyeMapMatrix->copyDataMatrix(*eyeData); /* 添加颜色 */ eyeMapMatrix->addColorBySample(); eyeMapMatrix->mutexEyeData.unlock(); // SPDLOG_LOGGER_INFO(m_logger, "示波器编号:{}, 通道:{}, 解析数据完成", m_oscNum, (int)chn); return true; } /* 设置零电压值和电压校准系数 */ void OneOscilloscope::setZeroVoltageAndCalibration(OscChannel chn, OscVoltageRange range) { if(chn == OscChannel::CH_A) { /* 电压幅值比 */ uint8_t altitudeByteA = 0; m_zeroVoltageA = m_mapChAZeroVoltage.value(range); altitudeByteA = m_mapChAVoltageAmplitudeRatio.value(range); m_diffVoltageA = 128 - m_zeroVoltageA; if(range == OscVoltageRange::CR_100MV) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 0.1 / 255.0; } else if(range == OscVoltageRange::CR_250MV) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 0.25 / 255.0; } else if(range == OscVoltageRange::CR_500MV) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 0.5 / 255.0; } else if(range == OscVoltageRange::CR_1V) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 1.0 / 255.0; } else if(range == OscVoltageRange::CR_2V5) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 2.5 / 255.0; } else if(range == OscVoltageRange::CR_5V) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 5.0 / 255.0; } else if(range == OscVoltageRange::CR_8V) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 8.0 / 255.0; } } else if(chn == OscChannel::CH_B) { /* 电压幅值比 */ uint8_t altitudeByteB = 0; m_zeroVoltageB = m_mapChBZeroVoltage.value(range); altitudeByteB = m_mapChBVoltageAmplitudeRatio.value(range); m_diffVoltageB = m_zeroVoltageB - 128; if(range == OscVoltageRange::CR_100MV) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 0.1 / 255.0; } else if(range == OscVoltageRange::CR_250MV) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 0.25 / 255.0; } else if(range == OscVoltageRange::CR_500MV) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 0.5 / 255.0; } else if(range == OscVoltageRange::CR_1V) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 1.0 / 255.0; } else if(range == OscVoltageRange::CR_2V5) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 2.5 / 255.0; } else if(range == OscVoltageRange::CR_5V) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 5.0 / 255.0; } else if(range == OscVoltageRange::CR_8V) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 8.0 / 255.0; } } // printZeroVoltage(chn); } /* 校准电压 */ double OneOscilloscope::calibrationVoltageA(uint8_t& data) { return m_voltageCalibrationA * m_rangeRatioA * (data - m_zeroVoltageA); } double OneOscilloscope::calibrationVoltageB(uint8_t& data) { return m_voltageCalibrationB * m_rangeRatioB * (data - m_zeroVoltageB); } /* 根据示波器编号获取示波器的数据矩阵指针 */ bool OneOscilloscope::initMatrixPtr() { int chnA = m_oscNum * 2 - 1; int chnB = m_oscNum * 2; m_chnNumA = static_cast(chnA); m_chnNumB = static_cast(chnB); bool ret = true; /* 初始化本地数据矩阵 */ if(m_dataMatrix_A == nullptr) { m_dataMatrix_A = new EyeDataMatrix(); m_dataMatrix_A->initEyeData(); } if(m_dataMatrix_B == nullptr) { m_dataMatrix_B = new EyeDataMatrix(); m_dataMatrix_B->initEyeData(); } /* 初始化本地颜色矩阵 */ if(m_colorMatrix_A == nullptr) { m_colorMatrix_A = new EyeColorMatrix(); m_colorMatrix_A->initEyeMapData(g_HorPixel, g_VerPixel); } if(m_colorMatrix_B == nullptr) { m_colorMatrix_B = new EyeColorMatrix(); m_colorMatrix_B->initEyeMapData(g_HorPixel, g_VerPixel); } return ret; } /* 等待所有线程退出,调用此函数之前,需要先设置线程运行标志为false,并发送所有的条件变量 */ void OneOscilloscope::waitAllThreadExit() { bool isRun = true; while (isRun) { isRun = false; /* 检查所有的线程运行状态 */ m_mutexThreadState.lock(); for(const auto& it : m_mapThreadState) { if(it.second) { /* 只要有一个正在运行就不再检查,直接退出 */ isRun = true; break; } isRun = false; } m_mutexThreadState.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } /* 复位线程运行状态位 */ m_mapThreadState.clear(); } /* 发送示波器在线或者离线状态 */ void OneOscilloscope::sendOscState(bool state) { if(state) { emit GOscDataInfo.signal_oscOnline(static_cast(m_chnNumA)); emit GOscDataInfo.signal_oscOnline(static_cast(m_chnNumB)); }else { emit GOscDataInfo.signal_oscOffline(static_cast(m_chnNumA)); emit GOscDataInfo.signal_oscOffline(static_cast(m_chnNumB)); } } /* 示波器离线了,重新连接 */ void OneOscilloscope::do_reconnectOsc() { m_isOpen = false; if(!m_timerConnect.isActive()) { /* 打开定时器 */ m_timerConnect.setTimerType(Qt::PreciseTimer); m_timerConnect.setSingleShot(false); m_timerConnect.start(1000); } if(m_runCapture) { /* 退出所有的线程 */ m_runCapture = false; m_condCapture.notify_all(); m_condBuffer_A.notify_all(); m_condBuffer_B.notify_all(); m_condCopyData_A.notify_all(); m_condCopyData_B.notify_all(); } /* 判断是否需要打开 */ if(!m_chnUsedA && !m_chnUsedB) { SPDLOG_LOGGER_INFO(m_logger, "示波器{}没有被使用,不需要打开!", m_oscNum); if(m_timerConnect.isActive()) { m_timerConnect.stop(); } return; } if(openOSC()) { SPDLOG_LOGGER_INFO(m_logger, "示波器{}重新连接成功!", m_oscNum); /* 停止定时器 */ if(m_timerConnect.isActive()) { m_timerConnect.stop(); } /* 检查所有的线程有没有退出 */ waitAllThreadExit(); /* 重新开启采集 */ startCapture(); /* 发送上线信号 */ sendOscState(true); } else { SPDLOG_LOGGER_ERROR(m_logger, "示波器{}重新连接失败!", m_oscNum); } }