#include "OscData.h" #include #include #include "ThreadPool/ThreadPool.h" OscilloscopeData::OscilloscopeData() { } OscilloscopeData::~OscilloscopeData() { 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; } } /* 初始化示波器 */ void OscilloscopeData::initOsc() { m_logger = spdlog::get("OscData"); if(m_logger == nullptr) { SPDLOG_ERROR("获取 OscData logger 失败"); return; } m_usbInterface = std::make_shared(); if(!m_usbInterface->loadLib(QApplication::applicationDirPath())) { return; } /* 分配缓冲区内存 */ m_buffer = new unsigned char[BUFFER_SIZE]; m_bufferChnA = new unsigned char[BUFFER_SIZE / 2]; m_bufferChnB = new unsigned char[BUFFER_SIZE / 2]; } /* 打开示波器 */ bool OscilloscopeData::openOSC() { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return false; } /* 指定示波器设备型号,OSCA02是6 */ m_usbInterface->specifyDevId(6); auto ret = m_usbInterface->devOpen(); if(ret != 0) { SPDLOG_LOGGER_ERROR(m_logger, "打开示波器失败!"); return false; } /* 获取缓冲区首指针 */ m_devBuffer = m_usbInterface->bufferWR(-1); if(m_devBuffer == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "获取缓冲区指针失败!"); return false; } /* 设置硬件触发命令,关闭外部触发,好像是有的设备需要,有的不需要 */ 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(); m_isOpen = true; return true; } /* 关闭示波器 */ void OscilloscopeData::closeOSC() { if(m_runCapture) { stopCapture(); } if(m_usbInterface != nullptr) { m_usbInterface->devClose(); } m_isOpen = false; SPDLOG_INFO("示波器已关闭"); } /* 开始采集数据 */ bool OscilloscopeData::startCapture() { if(m_buffer == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "缓冲区指针为空!"); return false; } /* 启动子线程 */ m_runCapture = true; CPPTP.add_task(&OscilloscopeData::threadCaptureData, this); CPPTP.add_task(&OscilloscopeData::threadProcessData, this); CPPTP.add_task(&OscilloscopeData::threadAddColorBySample, this); return true; } /* 停止采集数据 */ void OscilloscopeData::stopCapture() { if(!m_runCapture) { return; } m_runCapture = false; while (m_isRunCapture) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); } SPDLOG_LOGGER_INFO(m_logger, "停止采集数据"); } /* 设置示波器的采样率 */ void OscilloscopeData::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; OscParams.SampleIntervalTime = 20408.16; } else if(rate == OscSampleRate::SR_96KHZ) { m_ctrlByte0 |= 0x04; OscParams.SampleIntervalTime = 10416.67; } else if(rate == OscSampleRate::SR_781KHZ) { m_ctrlByte0 |= 0x0c; OscParams.SampleIntervalTime = 1280.0; } else if(rate == OscSampleRate::SR_12_5MHZ) { m_ctrlByte0 |= 0x08; OscParams.SampleIntervalTime = 80.0; } else if(rate == OscSampleRate::SR_100MHZ) { m_ctrlByte0 |= 0x00; OscParams.SampleIntervalTime = 10; } else { SPDLOG_LOGGER_ERROR(m_logger, "采样率设置错误!"); return; } m_usbInterface->usbCtrlTrans(0x94, m_ctrlByte0); } /** * @brief 将示波器两个通道合并为一个通道 * 将AB两个通道的资源全部给A,B通道失效,A通道的采样率和带宽翻倍 * @param merge 是否合并 */ void OscilloscopeData::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 OscilloscopeData::setChannelARange(OscChannelRange range) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } m_ctrlByte1 &= 0xf7; if(range == OscChannelRange::CR_100MV) { m_usbInterface->usbCtrlTrans(0x22, 0x06); } else if(range == OscChannelRange::CR_250MV) { m_usbInterface->usbCtrlTrans(0x22, 0x04); } else if(range == OscChannelRange::CR_500MV) { m_usbInterface->usbCtrlTrans(0x22, 0x02); } else if(range == OscChannelRange::CR_1V) { m_ctrlByte1 |= 0x08; m_usbInterface->usbCtrlTrans(0x22, 0x06); } else if(range == OscChannelRange::CR_2V5) { m_ctrlByte1 |= 0x08; m_usbInterface->usbCtrlTrans(0x22, 0x04); } else if(range == OscChannelRange::CR_5V) { m_ctrlByte1 |= 0x08; m_usbInterface->usbCtrlTrans(0x22, 0x02); } else if(range == OscChannelRange::CR_8V) { m_ctrlByte1 |= 0x08; m_usbInterface->usbCtrlTrans(0x22, 0x00); } m_usbInterface->usbCtrlTrans(0x24, m_ctrlByte1); setZeroVoltageAndCalibration(OscChannel::CH_A, range); } /** * @brief 设置通道B输入量程 * * @param range */ void OscilloscopeData::setChannelBRange(OscChannelRange range) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } m_ctrlByte1 &= 0xf9; if(range == OscChannelRange::CR_100MV) { m_ctrlByte1 |= 0x06; m_usbInterface->usbCtrlTrans(0x23, 0x40); } else if(range == OscChannelRange::CR_250MV) { m_ctrlByte1 |= 0x04; m_usbInterface->usbCtrlTrans(0x23, 0x40); } else if(range == OscChannelRange::CR_500MV) { m_ctrlByte1 |= 0x02; m_usbInterface->usbCtrlTrans(0x23, 0x40); } else if(range == OscChannelRange::CR_1V) { m_ctrlByte1 |= 0x06; m_usbInterface->usbCtrlTrans(0x23, 0x00); } else if(range == OscChannelRange::CR_2V5) { m_ctrlByte1 |= 0x04; m_usbInterface->usbCtrlTrans(0x23, 0x00); } else if(range == OscChannelRange::CR_5V) { m_ctrlByte1 |= 0x02; m_usbInterface->usbCtrlTrans(0x23, 0x00); } else if(range == OscChannelRange::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); } /** * @brief 设置通道耦合方式 * * @param channel 通道 * @param coupling 耦合方式,DC或者AC */ void OscilloscopeData::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 OscilloscopeData::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 OscilloscopeData::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 OscilloscopeData::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 OscilloscopeData::setTriggerLevel(unsigned char level) { if(m_usbInterface == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "USBInterface指针为空!"); return; } m_usbInterface->usbCtrlTrans(0x16, level); } /* 设置触发灵敏度 */ void OscilloscopeData::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 OscilloscopeData::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 OscilloscopeData::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(OscChannelRange::CR_8V, zeroVoltage); /* 1V档位,正负5V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x01); m_mapChAZeroVoltage.insert(OscChannelRange::CR_5V, zeroVoltage); /* 500mV档位,正负2.5V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x0e); m_mapChAZeroVoltage.insert(OscChannelRange::CR_2V5, zeroVoltage); /* 200mV档位,正负1V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x14); m_mapChAZeroVoltage.insert(OscChannelRange::CR_1V, zeroVoltage); /* 100mV档位,正负500mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x12); m_mapChAZeroVoltage.insert(OscChannelRange::CR_500MV, zeroVoltage); /* 50mV档位,正负250mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x10); m_mapChAZeroVoltage.insert(OscChannelRange::CR_250MV, zeroVoltage); /* 20mV档位,正负100mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0xa0); m_mapChAZeroVoltage.insert(OscChannelRange::CR_100MV, zeroVoltage); /* 获取通道B零电压值 */ /* 2V档位,正负8V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x72); m_mapChBZeroVoltage.insert(OscChannelRange::CR_8V, zeroVoltage); /* 1V档位,正负5V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x02); m_mapChBZeroVoltage.insert(OscChannelRange::CR_5V, zeroVoltage); /* 500mV档位,正负2.5V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x0f); m_mapChBZeroVoltage.insert(OscChannelRange::CR_2V5, zeroVoltage); /* 200mV档位,正负1V量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x15); m_mapChBZeroVoltage.insert(OscChannelRange::CR_1V, zeroVoltage); /* 100mV档位,正负500mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x13); m_mapChBZeroVoltage.insert(OscChannelRange::CR_500MV, zeroVoltage); /* 50mV档位,正负250mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0x11); m_mapChBZeroVoltage.insert(OscChannelRange::CR_250MV, zeroVoltage); /* 20mV档位,正负100mV量程 */ zeroVoltage = m_usbInterface->usbCtrlTrans(0x90, 0xa1); m_mapChBZeroVoltage.insert(OscChannelRange::CR_100MV, zeroVoltage); } /* 打印出零电压值 */ void OscilloscopeData::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 OscilloscopeData::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(OscChannelRange::CR_8V, voltageCalibration); /* 1V档位,正负5V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x03); m_mapChAVoltageAmplitudeRatio.insert(OscChannelRange::CR_5V, voltageCalibration); /* 500mV档位,正负2.5V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x08); m_mapChAVoltageAmplitudeRatio.insert(OscChannelRange::CR_2V5, voltageCalibration); /* 200mV档位,正负1V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x06); m_mapChAVoltageAmplitudeRatio.insert(OscChannelRange::CR_1V, voltageCalibration); /* 100mV档位,正负500mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x09); m_mapChAVoltageAmplitudeRatio.insert(OscChannelRange::CR_500MV, voltageCalibration); /* 50mV档位,正负250mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x0a); m_mapChAVoltageAmplitudeRatio.insert(OscChannelRange::CR_250MV, voltageCalibration); /* 20mV档位,正负100mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x2a); m_mapChAVoltageAmplitudeRatio.insert(OscChannelRange::CR_100MV, voltageCalibration); /* 获取通道B电压校准系数 */ /* 2V档位,正负8V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0xd2); m_mapChBVoltageAmplitudeRatio.insert(OscChannelRange::CR_8V, voltageCalibration); /* 1V档位,正负5V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x04); m_mapChBVoltageAmplitudeRatio.insert(OscChannelRange::CR_5V, voltageCalibration); /* 500mV档位,正负2.5V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x0b); m_mapChBVoltageAmplitudeRatio.insert(OscChannelRange::CR_2V5, voltageCalibration); /* 200mV档位,正负1V量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x07); m_mapChBVoltageAmplitudeRatio.insert(OscChannelRange::CR_1V, voltageCalibration); /* 100mV档位,正负500mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x0c); m_mapChBVoltageAmplitudeRatio.insert(OscChannelRange::CR_500MV, voltageCalibration); /* 50mV档位,正负250mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x0d); m_mapChBVoltageAmplitudeRatio.insert(OscChannelRange::CR_250MV, voltageCalibration); /* 20mV档位,正负100mV量程 */ voltageCalibration = m_usbInterface->usbCtrlTrans(0x90, 0x2d); m_mapChBVoltageAmplitudeRatio.insert(OscChannelRange::CR_100MV, voltageCalibration); } /* 打印出电压校准系数 */ void OscilloscopeData::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; } } /** * @brief 采集数据,这个是子线程 * */ void OscilloscopeData::threadCaptureData() { SPDLOG_LOGGER_INFO(m_logger, "开始采集数据线程"); m_isRunCapture = true; // unsigned char* buffer = nullptr; while(m_runCapture) { // SPDLOG_LOGGER_DEBUG(m_logger, "开始采集数据"); /* 开始采集数据 */ m_usbInterface->usbCtrlTransSimple(0x33); /* 清空数据缓冲区 */ for(uint32_t i = 0; i < BUFFER_SIZE; i++) { m_buffer[i] = 0; } /* 查询数据是否采集完成(应该是填充满128KB的SRAM) * 注意,这里是十进制33,不是0x33 */ while(m_usbInterface->usbCtrlTransSimple(0x50) != 33) { std::this_thread::sleep_for(std::chrono::microseconds(10)); } // SPDLOG_LOGGER_DEBUG(m_logger, "硬件缓冲区已满"); /* 将数据从示波器的SRAM中拷贝到电脑内存中,1次传输完成,设置超时时间1ms */ 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传输完成"); /* 取出数据 */ // buffer = m_ringQueue.back(); m_mutexCaptureData.lock(); std::memcpy(m_buffer, m_devBuffer, BUFFER_SIZE); m_isCaptureData = true; m_mutexCaptureData.unlock(); /* 清空缓冲区 */ m_usbInterface->resetPipe(); // SPDLOG_LOGGER_DEBUG(m_logger, "count: {}", count++); } m_isRunCapture = false; SPDLOG_LOGGER_INFO(m_logger, "采集数据线程结束"); } /* 处理数据线程 */ void OscilloscopeData::threadProcessData() { SPDLOG_LOGGER_INFO(m_logger, "开始处理数据线程"); while(m_runCapture) { if(m_isCaptureData.load()) { m_mutexCaptureData.lock(); /* 分离通道AB的数据 */ 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]; } m_isCaptureData = false; m_mutexCaptureData.unlock(); /* 处理数据 */ // SPDLOG_LOGGER_DEBUG(m_logger, "开始处理数据,通道A数据: {}, 通道B数据: {}", m_bufferChnA[32000], m_bufferChnB[32000]); /* 矫正零电压值 */ for(uint32_t i = 0; i < BUFFER_SIZE / 2; i++) { m_bufferChnA[i] = m_bufferChnA[i] + m_diffVoltageA; // m_bufferChnB[i] = m_bufferChnB[i] + m_diffVoltageB; } } /* 打印1000个数据 */ // for(uint32_t i = 0; i < BUFFER_SIZE/2; i++) // { // if((m_bufferChnA[i] == 128) && (m_bufferChnB[i] == 128)) // continue; // SPDLOG_LOGGER_DEBUG(m_logger, "A: {}, B: {}", m_bufferChnA[i], m_bufferChnB[i]); // } // SPDLOG_LOGGER_DEBUG(m_logger, "输出完成"); /* 对零电平进行矫正 */ /* 处理眼图数据 */ parseEyeMapData(m_bufferChnA, BUFFER_SIZE / 2); std::this_thread::sleep_for(std::chrono::microseconds(10)); } SPDLOG_LOGGER_INFO(m_logger, "处理数据线程结束"); } /* 根据采样点数添加颜色 */ void OscilloscopeData::threadAddColorBySample() { SPDLOG_LOGGER_INFO(m_logger, "开始添加颜色线程"); while(m_runCapture) { g_eyeMapMatrix.mutexEyeData.lock(); g_eyeMapMatrix.addColorBySample(); g_eyeMapMatrix.mutexEyeData.unlock(); // SPDLOG_LOGGER_DEBUG(m_logger, "添加颜色完成"); /* 延时一下,让别的线程拿到锁 */ std::this_thread::sleep_for(std::chrono::microseconds(10)); } SPDLOG_LOGGER_INFO(m_logger, "添加颜色线程结束"); } /** * @brief 解析数据,眼图需要的数据,从C#代码中移植过来 * 1、采样率为100MHz的时候,采样点间隔时间是10ns * x轴时间是1000分度,当x轴整体时间是10us的时候,采样点和分辨率一一对应 * x轴时间大于10us,采样点比分辨率高,无需做什么操作 * x轴时间小于10us,采样点数量会小于1000,那么绘制的矩形小点间隔会比较长,这时候就需要进行插帧 * 2、屏幕中显示多少波形和波形的频率及时间屏幕可以现实的时间长度有关,波形的频率未知,所以这里只能通过调整时间长度来调整波形 * 在屏幕中显示的数目 * 3、当时间长度变小,小到整个屏幕的采样点数目不足1000的时候,就需要进行插值,插值到1000附近 * * @param buffer 数据缓冲区 * @param size 缓冲区大小,单位字节 */ void OscilloscopeData::parseEyeMapData(unsigned char* buffer, unsigned int size) { 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) { return; } /* 计算最大值和最小值的中间数 */ uint8_t vaMid = (vaMax + vaMin) / 2; /* ======================================================================== */ /* 将采样点添加bool值,如果时间很短,就进行插值,每个采样点之间插入30个值 */ /* 时间尺度,OscCurrentTimeScale = 100,num7 = 1.0,100MHz下每个采样点间距10ns */ // double num7 = OscParams.dataNumPerPixar * OscParams.OscCurrentTimeScale / 100.0; // /* num7 * OscOneGridTime是一个时间格子中采样点的个数 */ // long oneGridTime = num7 * OscParams.OscOneGridTime; // if (oneGridTime % 2 != 0L) // { // oneGridTime++; // } /* 采样率为100MHz的时候,采样点间隔时间是10ns * x轴时间是1000分度,当x轴整体时间是10us的时候,采样点和分辨率一一对应 * x轴时间大于10us,采样点比分辨率高,无需做什么操作 * x轴时间小于10us,采样点数量会小于1000,那么绘制的矩形小点间隔会比较长,这时候就需要进行插帧 */ /* 一个时间格子的采样率个数 */ int oneGridSa = OscParams.oneGridTime / OscParams.SampleIntervalTime; /* 当前一个格子中采样点的数目 */ int saTotal = oneGridSa * 10; /* 一个时间格子中采样点的总数 */ bool isNeedFrameInsertion = ( saTotal < OscParams.eyeMapWidth ) ? 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 = 1000.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) { return; } 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; for (int 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(i); /* 记录下标 */ flag3 = !flag3; /* 不再检测上升沿,检测下降沿 */ } } /* 下降沿 */ else if (vaPre >= vaMid && vaNext < vaMid) { listSub.push_back(i); flag3 = !flag3; } /* 采集到600个上升沿和下降沿 */ if (listSub.size() >= 600) { break; } } if (listSub.size() <= 0) { return; } /* ======================================================================== */ /* 这里应该是根据跳变沿的中间值,取出完整的跳变沿 * 创建一个二维数组,每一行就是一个跳变沿 */ std::vector> 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 (int i = 0; i < numSubSize; i++) { int 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(vecDataTmp); } // listSub.clear(); // vecData.clear(); if (vec2DEyeData.size() <= 0) { return; } /* ======================================================================== */ int num18 = 0; float num20 = 0.0; /* 将数据拷贝到OscData的Matrix中 */ size_t numTmp = 0; int ValTmp = 0; /* 将跳变沿数据放入到全局变量中,并根据坐标进行排列 * x轴是这个跳变沿根据时间平分1000份 * y轴是这个值 */ g_eyeDataMatrix.mutexEyeData.lock(); for (int i = 0; i < vec2DEyeData.size(); i++) { /* 取出一个跳变沿,将其分布在整个 1000 * 256像素的矩阵中 */ std::vector& vecTmp = vec2DEyeData[i]; numTmp = vecTmp.size(); num20 = numTmp / 1000.f; /* x轴方向1000分 */ for (int i = 0; i < numTmp; i++) { if (vecTmp[i].isEyeData) { ValTmp = vecTmp[i].value; num18 = (int)((float)i / num20); /* 将数据添加到眼图矩阵中 */ g_eyeDataMatrix.addData(num18, ValTmp); } } } g_eyeDataMatrix.eyeStatisticalWeight(); g_eyeDataMatrix.eyeLessenTheBurden(); vec2DEyeData.clear(); auto eyeData = g_eyeDataMatrix.eyeZoomOut(); g_eyeDataMatrix.mutexEyeData.unlock(); g_eyeMapMatrix.mutexEyeData.lock(); g_eyeMapMatrix.copyDataMatrix(*eyeData); g_eyeMapMatrix.mutexEyeData.unlock(); } /* 设置零电压值和电压校准系数 */ void OscilloscopeData::setZeroVoltageAndCalibration(OscChannel chn, OscChannelRange range) { if(chn == OscChannel::CH_A) { /* 电压幅值比 */ uint8_t altitudeByteA = 0; m_zeroVoltageA = m_mapChAZeroVoltage.value(range); altitudeByteA = m_mapChAVoltageAmplitudeRatio.value(range); m_diffVoltageA = m_zeroVoltageA - 128; if(range == OscChannelRange::CR_100MV) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 0.1 / 255.0; } else if(range == OscChannelRange::CR_250MV) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 0.25 / 255.0; } else if(range == OscChannelRange::CR_500MV) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 0.5 / 255.0; } else if(range == OscChannelRange::CR_1V) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 1.0 / 255.0; } else if(range == OscChannelRange::CR_2V5) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 2.5 / 255.0; } else if(range == OscChannelRange::CR_5V) { m_voltageCalibrationA = (altitudeByteA * 2) / 255.0; m_rangeRatioA = 5.0 / 255.0; } else if(range == OscChannelRange::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 == OscChannelRange::CR_100MV) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 0.1 / 255.0; } else if(range == OscChannelRange::CR_250MV) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 0.25 / 255.0; } else if(range == OscChannelRange::CR_500MV) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 0.5 / 255.0; } else if(range == OscChannelRange::CR_1V) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 1.0 / 255.0; } else if(range == OscChannelRange::CR_2V5) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 2.5 / 255.0; } else if(range == OscChannelRange::CR_5V) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 5.0 / 255.0; } else if(range == OscChannelRange::CR_8V) { m_voltageCalibrationB = (altitudeByteB * 2) / 255.0; m_rangeRatioB = 8.0 / 255.0; } } } /* 校准电压 */ double OscilloscopeData::calibrationVoltageA(uint8_t& data) { return m_voltageCalibrationA * m_rangeRatioA * (data - m_zeroVoltageA); } double OscilloscopeData::calibrationVoltageB(uint8_t& data) { return m_voltageCalibrationB * m_rangeRatioB * (data - m_zeroVoltageB); }