Browse Source

V0.3
1、绘制缩放基本解决了
2、插帧还需要优化

Apple 4 months ago
parent
commit
010fbd64e4
8 changed files with 142 additions and 68 deletions
  1. 66 38
      EyeMap/OscData.cpp
  2. 18 3
      EyeMap/eyemap.cpp
  3. 8 1
      EyeMap/eyemap.h
  4. 17 9
      GlobalInfo/GlobalInfo.cpp
  5. 20 11
      GlobalInfo/GlobalInfo.h
  6. 10 4
      oscwidget.cpp
  7. 1 0
      oscwidget.h
  8. 2 2
      oscwidget.ui

+ 66 - 38
EyeMap/OscData.cpp

@@ -127,6 +127,7 @@ bool OscilloscopeData::startCapture()
     m_runCapture = true;
     CPPTP.add_task(&OscilloscopeData::threadCaptureData, this);
     CPPTP.add_task(&OscilloscopeData::threadProcessData, this);
+    CPPTP.add_task(&OscilloscopeData::threadAddColorBySample, this);
     return true;
 }
 
@@ -148,22 +149,27 @@ void OscilloscopeData::setSampleRate(OscSampleRate rate)
     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
     {
@@ -630,9 +636,8 @@ void OscilloscopeData::threadCaptureData()
 {
     SPDLOG_LOGGER_INFO(m_logger, "开始采集数据线程");
     m_isRunCapture = true;
-    uint64_t count = 0;
     // unsigned char* buffer = nullptr;
-    // while(m_runCapture)
+    while(m_runCapture)
     {
         // SPDLOG_LOGGER_DEBUG(m_logger, "开始采集数据");
         /* 开始采集数据 */
@@ -677,7 +682,7 @@ void OscilloscopeData::threadCaptureData()
 void OscilloscopeData::threadProcessData()
 {
     SPDLOG_LOGGER_INFO(m_logger, "开始处理数据线程");
-    // while(m_runCapture)
+    while(m_runCapture)
     {
         if(m_isCaptureData.load())
         {
@@ -691,7 +696,7 @@ void OscilloscopeData::threadProcessData()
             m_isCaptureData = false;
             m_mutexCaptureData.unlock();
             /* 处理数据 */
-            SPDLOG_LOGGER_DEBUG(m_logger, "开始处理数据,通道A数据: {}, 通道B数据: {}", m_bufferChnA[32000], m_bufferChnB[32000]);
+            // SPDLOG_LOGGER_DEBUG(m_logger, "开始处理数据,通道A数据: {}, 通道B数据: {}", m_bufferChnA[32000], m_bufferChnB[32000]);
             /* 矫正零电压值 */
         }
         /* 打印1000个数据 */
@@ -714,11 +719,14 @@ void OscilloscopeData::threadProcessData()
 /* 根据采样点数添加颜色 */
 void OscilloscopeData::threadAddColorBySample()
 {
-    // while(m_runCapture)
+    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));
     }
     
 }
@@ -765,18 +773,28 @@ void OscilloscopeData::parseEyeMapData(unsigned char* buffer, unsigned int size)
     /* ======================================================================== */
     /* 将采样点添加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++;
-    }
-    int num9 = (int)((double)oneGridTime * 0.25);       /* 1/4个时间格子长度 */
+    // 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 = ( (oneGridSa * 10) < OscParams.eyeMapWidth ) ? true : false;
+
+    int num9 = (int)((double)oneGridSa * 0.25);       /* 1/4个时间格子长度 */
     /* 记录buffer的值,并添加bool */
     std::vector<EyeDataT> vecData;
     int numMulti = 0;    /* 倍率,可能是1可能是30 */
-    if (num7 >= 1.0)
+    if (isNeedFrameInsertion == false)
     {
         /* 将数据放入到list中,带有bool标志位,全部启用 */
         for (int i = 0; i < bufferSize; i++)
@@ -813,8 +831,8 @@ void OscilloscopeData::parseEyeMapData(unsigned char* buffer, unsigned int size)
                 /* 四舍五入 */
                 b = std::round((num11 * (float)j) + (int)b2);
                 // flag2 = ((1 == random.Next(1)) ? true : false);
-                flag2 = ((1 == random->bounded(0, 1)) ? true : false);
-                vecData.push_back(EyeDataT(flag2, b));
+                // flag2 = ((1 == random->bounded(0, 1)) ? true : false);
+                vecData.push_back(EyeDataT(true, b));
             }
             vecData.push_back(EyeDataT(true, b3));
         }
@@ -825,13 +843,15 @@ void OscilloscopeData::parseEyeMapData(unsigned char* buffer, unsigned int size)
         return;
     }
     num9 *= numMulti;          /* 1/4个时间格子长度,乘以倍数 */
-    /* oneGridTime2也是一个时间格子的长度,单位ns */
-    long oneGridTime2 = oneGridTime * numMulti;
+    /* oneJumpSa是一个跳变沿的采样点个数 */
+    // long oneJumpSa = oneGridSa * numMulti;
+    long oneJumpSa = saTotal * numMulti;
+    // long oneJumpSa = 1000;
     /* ======================================================================== */
     /* 寻找波形,找到上升沿和下降沿 */
     /* 存储下标 */
     std::vector<int> listSub;
-    int numDataSize = vecData.size() - num9;
+    size_t numDataSize = vecData.size() - num9;
     bool flag3 = true;
     /* 找到数组中的上升沿和下降沿,并记录其坐标
      * 这里寻找上升沿和下降沿是检测的中间值,是每个跳变沿的中部
@@ -871,33 +891,32 @@ void OscilloscopeData::parseEyeMapData(unsigned char* buffer, unsigned int size)
         return;
     }
     /* ======================================================================== */
+    /* 这里应该是根据跳变沿的中间值,取出完整的跳变沿
+     * 创建一个二维数组,每一行就是一个跳变沿 */
     std::vector<std::vector<EyeDataT>> vec2DEyeData;
     int jumpStart = 0;      /* 跳变沿起点 */
-    int jumpEnd = 0;        /* 跳变沿终点 */
-    int num16 = 0;
+    size_t jumpEnd = 0;        /* 跳变沿终点 */
     int num17 = 0;
-    size_t numSubSize = listSub.size();    /* 跳变沿下标的个数 */
-    num16 = (int)(oneGridTime2 / 3);           /*  */
+    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<EyeDataT> vecDataTmp(oneGridTime2, EyeDataT(false, 0));
+        std::vector<EyeDataT> vecDataTmp(oneJumpSa, EyeDataT(false, 0));
 
-        numSub1 = listSub[i];           /* 取出下标值 */
-        numSub2 = numSub1 - num16;      /* 下标往后倒退num16个值,是起点? */
+        numSub1 = listSub[i];               /* 取出下标值 */
+        numSub2 = numSub1 - oneThirdSa;     /* 下标往后倒退1/3个时间格子的采样点数,当作起点 */
         /* 判断是否小于0,这里是起点 */
         jumpStart = numSub2;
         if (jumpStart <= 0)
         {
             jumpStart = 0;
         }
-        /* 判断是否超出采样点的个数,这里是终点 */
-        jumpEnd = numSub1 + num16 * 2;
+        /* 终点往后2/3个时间格子的采样点数,当作终点 */
+        jumpEnd = numSub1 + oneThirdSa * 2;
         if (jumpEnd >= vecData.size())
         {
             jumpEnd = vecData.size() - 1;
@@ -918,10 +937,15 @@ void OscilloscopeData::parseEyeMapData(unsigned char* buffer, unsigned int size)
             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();
+    // listSub.clear();
+    // vecData.clear();
     if (vec2DEyeData.size() <= 0)
     {
         return;
@@ -930,16 +954,18 @@ void OscilloscopeData::parseEyeMapData(unsigned char* buffer, unsigned int size)
     int num18 = 0;
     float num20 = 0.0;
     /* 将数据拷贝到OscData的Matrix中 */
-    int numTmp = 0;
+    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<EyeDataT>& vecTmp = vec2DEyeData[i];
         numTmp = vecTmp.size();
-        num20 = numTmp / 1000.f;
-        g_eyeDataMatrix.mutexEyeData.lock();
+        num20 = numTmp / 1000.f;    /* x轴方向1000分 */
         for (int i = 0; i < numTmp; i++)
         {
             if (vecTmp[i].isEyeData)
@@ -950,12 +976,14 @@ void OscilloscopeData::parseEyeMapData(unsigned char* buffer, unsigned int size)
                 g_eyeDataMatrix.addData(num18, ValTmp);
             }
         }
-        g_eyeDataMatrix.mutexEyeData.unlock();
     }
+    
+
     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);

+ 18 - 3
EyeMap/eyemap.cpp

@@ -17,9 +17,16 @@ EyeMap::EyeMap(QWidget *parent) :
         return;
     }
     /* 自定义大小 */
-    setFixedSize(1920, 1080);
+    setFixedSize(1600, 900);
     /* 初始化全局数据 */
     g_eyeMapMatrix.initEyeMapData(this->width(), this->height());
+    /* 设置定时器 */
+    m_timer.setTimerType(Qt::PreciseTimer);
+    m_timer.setSingleShot(false);
+    m_timer.start(16);      /* 16ms刷新一次,大约120帧 */
+
+    connect(this, &EyeMap::signal_update, this, &EyeMap::do_update);
+    connect(&m_timer, &QTimer::timeout, this, &EyeMap::do_update);
 
     SPDLOG_LOGGER_INFO(m_logger, "EyeMap 初始化成功");
 
@@ -31,6 +38,12 @@ EyeMap::~EyeMap()
     delete ui;
 }
 
+/* 刷新页面 */
+void EyeMap::do_update()
+{
+    update();
+}
+
 /**
  * @brief 绘制图形
  * 
@@ -38,6 +51,8 @@ EyeMap::~EyeMap()
  */
 void EyeMap::paintEvent(QPaintEvent *event)
 {
+    g_eyeMapMatrix.mutexEyeData.lock();
+
     QPainter painter(this);
     
     QPen pen;
@@ -59,7 +74,6 @@ void EyeMap::paintEvent(QPaintEvent *event)
     
     /* 绘制眼图,就是绘制 1000 * 256 个矩形 */
     painter.setPen(QPen(Qt::NoPen));
-    g_eyeMapMatrix.mutexEyeData.lock();
     for(int i = 0; i < 1000; i++)
     {
         for(int j = 0; j < 256; j++)
@@ -68,7 +82,8 @@ void EyeMap::paintEvent(QPaintEvent *event)
             {
                 continue;
             }
-            painter.setBrush(QBrush(g_eyeMapMatrix.dataMatrix[i][j].color));
+            // painter.setBrush(QBrush(g_eyeMapMatrix.dataMatrix[i][j].color));
+            painter.setBrush(g_eyeMapMatrix.dataMatrix[i][j].brush);
             painter.drawRect(g_eyeMapMatrix.dataMatrix[i][j].rect);
         }
     }

+ 8 - 1
EyeMap/eyemap.h

@@ -3,6 +3,7 @@
 
 #include <QWidget>
 #include <memory>
+#include <QTimer>
 
 #include "spdlog/spdlog.h"
 
@@ -20,13 +21,19 @@ public:
     explicit EyeMap(QWidget *parent = nullptr);
     ~EyeMap();
 
+signals:
+    void signal_update();
+
+private slots:
+    void do_update();
+
 protected:
     void paintEvent(QPaintEvent *event) override;
 
 private:
     Ui::EyeMap *ui;
     std::shared_ptr<spdlog::logger> m_logger = nullptr;
-
+    QTimer m_timer;
 };
 
 #endif // EYEMAP_H

+ 17 - 9
GlobalInfo/GlobalInfo.cpp

@@ -22,7 +22,10 @@ void EyeDataMatrix::addData(int x, int y)
     }
 }
 
-
+/**
+ * @brief 比重统计,点数大于79999的个数比点数大于0的个数的比重超过0.25,就开始减慢颜色变化的速度
+ * 
+ */
 void EyeDataMatrix::eyeStatisticalWeight()
 {
     eyeIsLessenTheBurden = true;
@@ -30,10 +33,10 @@ void EyeDataMatrix::eyeStatisticalWeight()
     {
         return;
     }
-    int num = 0;
-    int num2 = 0;
+    int num = 0;            /* 点数大于0的个数 */
+    int num2 = 0;           /* 点数大于79999的个数 */
     double num3 = 0.0;
-    int num4 = 79999;
+    int numMax = 79999;
     for (int i = 0; i < 1000; i++)
     {
         for (int j = 0; j < 256; j++)
@@ -41,7 +44,7 @@ void EyeDataMatrix::eyeStatisticalWeight()
             if (dataMatrix[i][j].fCnt > 0.0)
             {
                 num++;
-                if (dataMatrix[i][j].fCnt >= (double)num4)
+                if (dataMatrix[i][j].fCnt >= (double)numMax)
                 {
                     num2++;
                 }
@@ -58,6 +61,10 @@ void EyeDataMatrix::eyeStatisticalWeight()
     }
 }
 
+/**
+ * @brief 眼图减慢颜色变化的速度
+ * 
+ */
 void EyeDataMatrix::eyeLessenTheBurden()
 {
 	if (eyeIsLessenTheBurden)
@@ -106,8 +113,8 @@ std::shared_ptr<Vec2D> EyeDataMatrix::eyeZoomOut()
 /* 初始化数据点 */
 void EyeMapMatrix::initEyeMapData(int width, int height)
 {
-    float saH = (float)height / 256.0;
-    float saW = (float)width / 1000.0;
+    double saH = height / 256.0;
+    double saW = width / 1000.0;
     for(int i = 0; i < 1000; i++)
     {
         for(int j = 0; j < 256; j++)
@@ -157,7 +164,7 @@ void EyeMapMatrix::addColorBySample()
             {
                 continue;
             }
-            if(dataMatrix[i][j].Count < 0)
+            if(dataMatrix[i][j].Count <= 0)
             {
                 dataMatrix[i][j].Count = 0;
                 continue;
@@ -222,7 +229,8 @@ void EyeMapMatrix::addColorBySample()
                 g = 0;
                 b = 0;
             }
-            dataMatrix[i][j].color = QColor(r, g, b);
+            // dataMatrix[i][j].color = QColor(r, g, b);
+            dataMatrix[i][j].brush = QBrush(QColor(r, g, b));
         }
     }
 }

+ 20 - 11
GlobalInfo/GlobalInfo.h

@@ -5,6 +5,7 @@
 #include <vector>
 #include <QRect>
 #include <QColor>
+#include <QBrush>
 
 /* 示波器通道 */
 enum class OscChannel
@@ -140,16 +141,20 @@ struct EyeMapDataSample
     int Count;      /* 像素点的个数(颜色深度),这里限制为799,不知道为什么 */
     unsigned char data;     /* 数据值 */
     QRect rect;     /* 像素点的矩形区域 */
-    QColor color;   /* 颜色 */
+    // QColor color;   /* 颜色 */
+    QBrush brush;   /* 颜色 */
 
-    EyeMapDataSample() : isDraw(false), x(0), y(0), Count(0), data(0), color(255, 255, 255) {}
+    // EyeMapDataSample() : isDraw(false), x(0), y(0), Count(0), data(0), color(255, 255, 255) {}
+    EyeMapDataSample() : isDraw(false), x(0), y(0), Count(0), data(0) {}
     EyeMapDataSample(EyeDataSample& data) : isDraw(false), x(data.x), y(data.y), Count(data.Cnt), data(data.data) {}
-    EyeMapDataSample& operator=(const EyeMapDataSample& data) {
-        x = data.x;
-        y = data.y;
-        Count = data.Count;
-        isDraw = data.isDraw;
-        rect = data.rect;
+    EyeMapDataSample& operator=(const EyeMapDataSample& other) {
+        x = other.x;
+        y = other.y;
+        Count = other.Count;
+        isDraw = other.isDraw;
+        rect = other.rect;
+        data = other.data;
+        brush = other.brush;
         return *this;
     }
 };
@@ -198,16 +203,20 @@ public:
     }
 
     /* 示波器相关参数 */
-    int OscCurrentTimeScale = 100;  /* 时间尺度,不知道啥意思,可能和采样率有关 */
-    int OscOneGridTime = 1000;      /* 每格子的时间(单位ns) */
+    // int OscCurrentTimeScale = 100;  /* 时间尺度,不知道啥意思,可能和采样率有关 */
+    // int OscOneGridTime = 1000;      /* 每格子的时间(单位ns) */
 
-    /* 显示相关 */
     int TimeGridNum = 10;           /* 10个时间格子 */
     int VolatileGridNum = 10;       /* 10个电压格子 */
+    int oneGridTime = 200;          /* 一个时间格子的时间长度(单位ns) */
+
+    double SampleIntervalTime = 0;     /* 采样点之间的时间间隔,单位ns(采样率的倒数,设置采样率的时候会设置) */
 
     /* 其他参数 */
     const int dataNumPerPixar = 1;  /* 这个是SetInfo的第一个参数,固定是1,在眼图中会使用 */
 
+    /* 眼图参数 */
+    int eyeMapWidth = 1000;         /* 眼图x轴宽度(像素矩形的个数) */
 };
 
 

+ 10 - 4
oscwidget.cpp

@@ -67,11 +67,17 @@ OscWidget::~OscWidget()
 
 void OscWidget::on_pBtn_capOne_clicked()
 {
-    OscParams.OscOneGridTime = 200;       /* 每格时间0.2us */
     SPDLOG_LOGGER_INFO(m_logger, "采集一次数据");
-    OscData.threadCaptureData();
-    OscData.threadProcessData();
-    OscData.threadAddColorBySample();
+    // OscData.threadCaptureData();
+    // OscData.threadProcessData();
+    // OscData.threadAddColorBySample();
     
     update();
 }
+
+void OscWidget::on_pBtn_startCap_clicked()
+{
+    SPDLOG_LOGGER_INFO(m_logger, "开始采集数据");
+    OscParams.oneGridTime = 200;       /* 每格时间0.2us */
+    OscData.startCapture();
+}

+ 1 - 0
oscwidget.h

@@ -19,6 +19,7 @@ public:
 
 private slots:
     void on_pBtn_capOne_clicked();
+    void on_pBtn_startCap_clicked();
 
 private:
     Ui::OscWidget *ui;

+ 2 - 2
oscwidget.ui

@@ -56,9 +56,9 @@
        </widget>
       </item>
       <item row="0" column="1">
-       <widget class="QPushButton" name="pushButton">
+       <widget class="QPushButton" name="pBtn_startCap">
         <property name="text">
-         <string>PushButton</string>
+         <string>开始采集</string>
         </property>
        </widget>
       </item>