⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 waveformdisplay.cpp

📁 一个简单示波器的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// WaveformDisplay.cpp : implementation file
//

#include "stdafx.h"
#define PACKED
#pragma pack(1)
#include "usb_protocol.h"
#pragma pack()
#include "scope_control.h"
#include "lmscope.h"
#include "WaveformDisplay.h"
#include "lmscopeDlg.h"

//***************************************************************************
//
// Macro converting from a millivolt measurement to a Y pixel coordinate
// given a voltage scaling factor.
//
//***************************************************************************

#define MV_TO_Y(mv, scale) (m_iGraticuleOriginY -                           \
                            (((mv) * m_iGraticuleSide) / (long)(scale)))

const COLORREF g_colWaveformColors[NUM_WAVEFORM_COLORS] =
{
    SCOPE_COLOR_BACKGROUND,
    SCOPE_COLOR_CHANNEL_1,
    SCOPE_COLOR_CHANNEL_2,
    SCOPE_COLOR_GRATICULE,
    SCOPE_COLOR_TRIG_POS,
    SCOPE_COLOR_TRIG_LEVEL
};

//***************************************************************************
//
// CWaveformDisplay class
//
//***************************************************************************
IMPLEMENT_DYNAMIC(CWaveformDisplay, CStatic)

CWaveformDisplay::~CWaveformDisplay()
{
}

void CWaveformDisplay::DoDataExchange(CDataExchange* pDX)
{
    CStatic::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CWaveformDisplay, CStatic)
END_MESSAGE_MAP()


//***************************************************************************
//
// CWaveform member functions.
//
//***************************************************************************
CWaveformDisplay::CWaveformDisplay() : CStatic()
{
    //
    // Set defaults for the waveform elements we will draw.
    //
    m_bShowGraticule = TRUE;
    m_bShowTrigLevel = TRUE;
    m_bShowTrigPos = TRUE;

    //
    // Set defaults for various fields we expect the client to set
    // later.
    //
    m_pScopeData = NULL;
    m_pSingleElement = NULL;
    m_pDualElement = NULL;
    m_iTriggerPos = 0;
    m_lTriggerLevelmV = 0;
    m_uluSPerDivision = 100;
    m_lVerticalOffsetmV[0] = 0;
    m_lVerticalOffsetmV[1] = 0;
    m_ulmVPerDivision[0] = 500;
    m_ulmVPerDivision[1] = 500;
}

//***************************************************************************
//
// Initialize the bitmap we use for offscreen drawing.
//
//***************************************************************************
void CWaveformDisplay::InitBitmap(void)
{
    CBitmap * pOldBitmap;
    CDC *pDC;
    CDC MemDC;
    CRect rectArea;

    //
    // Determine the size of the area we are going to be rendering into.
    //
    GetClientRect(&rectArea);
    m_sizeWaveform = rectArea.Size();

    m_iGraticuleSide = m_sizeWaveform.cx / NUM_HORIZONTAL_DIVISIONS;
    m_iGraticuleOriginY = (((m_sizeWaveform.cy / m_iGraticuleSide) / 2) *
                           m_iGraticuleSide);

    // Need a DC
    pDC = GetDC();

    // And a memory DC, set Map Mode
    MemDC.CreateCompatibleDC(pDC);

    // Create a bitmap big enough to hold the window's image
    m_bmpWaveform.CreateCompatibleBitmap(pDC, m_sizeWaveform.cx, m_sizeWaveform.cy);

    // Select the bitmap into the memory DC
    pOldBitmap = MemDC.SelectObject(&m_bmpWaveform);

    // Draw the initial waveform display (background and graticule only)
    DrawWaveform(&MemDC);

    // Select the original bitmap back in
    MemDC.SelectObject(pOldBitmap);

    // Clean up
    ReleaseDC(pDC);

    //
    // Associate the static picture control with our offscreen bitmap
    //
    SetBitmap((HBITMAP)m_bmpWaveform);
}

//***************************************************************************
//
// This function is called whenever new data is received from the
// oscilloscope. It renders the data into our offscreen bitmap then causes
// the picture control on the dialog box to be refreshed.
//
//***************************************************************************
void CWaveformDisplay::RenderWaveform(tScopeDataStart *pScopeData,
                                      int iElementOffset)
{
    //
    // If we already have a dataset, discard it.
    //
    if(m_pScopeData)
    {
        LocalFree(m_pScopeData);
    }

    //
    // Hold on to the new dataset.
    //
    m_pScopeData = pScopeData;

    //
    // Calculate pointers to the first data element in the dataset.
    // Even though the dataset can only be either single or dual
    // channel, we keep two pointers anyway.
    //
    m_pDualElement = (tScopeDualDataElement *)((char *)pScopeData +
                                               iElementOffset);
    m_pSingleElement = (tScopeDataElement *)((char *)pScopeData +
                                             iElementOffset);

    //
    // Call our internal function to render the new data.
    //
    InternalRenderWaveform();
}

//***************************************************************************
//
// This internal function is called to redraw the existing waveform dataset
// after a display parameter change or when new data has just been sent by
// the client.
//
//***************************************************************************
void CWaveformDisplay::InternalRenderWaveform(void)
{
    CBitmap * pOldBitmap;
    CDC *pDC;
    CDC MemDC;
    CRect rectArea;

    //
    // Get a device context.
    //
    pDC = GetDC();

    //
    // Create a memory DC compatible with the one we just got.
    //
    MemDC.CreateCompatibleDC(pDC);

    //
    // Select the bitmap into the memory DC
    //
    pOldBitmap = MemDC.SelectObject(&m_bmpWaveform);

    //
    // Draw the waveform display
    //
    DrawWaveform(&MemDC);

    //
    // Select the original bitmap back in.
    //
    MemDC.SelectObject(pOldBitmap);

    //
    // Clean up
    //
    ReleaseDC(pDC);

    //
    // Invalidate the rectangle associated with the waveform picture control.
    //
    Invalidate(FALSE);
}

//***************************************************************************
//
// Render the latest waveform data, if any, into our offscreen bitmap.
//
//***************************************************************************
void CWaveformDisplay::DrawWaveform(CDC *pDC)
{
    long lCenterOffset;
    long lY;
    long lX;
    COLORREF dwColor = SCOPE_COLOR_BACKGROUND;
    CPen cPenTrigPos(PS_SOLID, 1, SCOPE_COLOR_TRIG_POS);
    CPen cPenTrigLevel(PS_SOLID, 1, SCOPE_COLOR_TRIG_LEVEL);
    CPen *pOldPen;

    //
    // Fill the background of the bitmap with grey.
    //
    pDC->FillSolidRect(0, 0, m_sizeWaveform.cx, m_sizeWaveform.cy, dwColor);

    //
    // Draw the graticule if required.
    //
    if(m_bShowGraticule)
    {
        DrawGraticule(pDC);
    }

    //
    // Render the actual waveform itself.
    //
    if(m_pScopeData)
    {
        //
        // Determine the horizontal offset to apply to the waveform to ensure
        // that the trigger position is where we expect it to be (centered by
        // default).
        //
        lCenterOffset = GetCenterOffset();

        //
        // Draw a vertical line at the trigger point.
        //
        if(m_bShowTrigPos)
        {
            //
            // Select our pen into the DC.
            //
            pOldPen = pDC->SelectObject(&cPenTrigPos);

            //
            // Determine where on the display the trigger point falls
            //
            lY = m_pScopeData->ulTriggerIndex;

            //
            // Now determine where we need to draw the trigger position line.
            //
            lX = SampleIndexToX(lY, CHANNEL_1);

            //
            // If the trigger position is visible in the waveform area of the
            // screen, draw a vertical line there.
            //
            if((lX >= 0) && (lX < m_sizeWaveform.cx))
            {
                pDC->SetDCPenColor(SCOPE_COLOR_TRIG_POS);
                pDC->MoveTo(lX, 0);
                pDC->LineTo(lX, m_sizeWaveform.cy);
            }

            //
            // Revert to the previous pen.
            //
            pDC->SelectObject(pOldPen);
        }

        //
        // ...and a horizontal line at the trigger level.
        //
        if(m_bShowTrigLevel)
        {
            //
            // Convert the trigger level into a Y pixel offset.
            //
            lY = SampleToY((short)m_lTriggerLevelmV, (m_pScopeData->bCh2SampleFirst ?
                           CHANNEL_2 : CHANNEL_1));

            if((lY >= 0) && (lY <= m_sizeWaveform.cy))
            {
                //
                // Select our pen into the DC.
                //
                pOldPen = pDC->SelectObject(&cPenTrigLevel);

                //
                // Draw the line
                //
                pDC->MoveTo(0, lY);
                pDC->LineTo(m_sizeWaveform.cx, lY);

                //
                // Revert to the previous pen
                //
                pDC->SelectObject(pOldPen);
            }
        }

        //
        // Render the waveform for channel 1
        //
        DrawSingleWaveform(pDC, CHANNEL_1, SCOPE_COLOR_CHANNEL_1);

        //
        // Yes - render the waveform for channel 2
        //
        DrawSingleWaveform(pDC, CHANNEL_2, SCOPE_COLOR_CHANNEL_2);
    }
}


//***************************************************************************
//
// Draw the graticule lines on our offscreen bitmap.
//
//***************************************************************************
void CWaveformDisplay::DrawGraticule(CDC *pDC)
{
    int iX;
    int iY;
    CPen cPen(PS_SOLID, 1, SCOPE_COLOR_GRATICULE);
    CPen *pcPenOld;

    //
    // Set the pen color for the graticule lines.
    //
    pcPenOld = pDC->SelectObject(&cPen);

    //
    // Draw the vertical lines.
    //
    for(iX = m_iGraticuleSide; iX < m_sizeWaveform.cx; iX += m_iGraticuleSide)
    {
        pDC->MoveTo(iX, 0);
        pDC->LineTo(iX, m_sizeWaveform.cy);
    }

    //
    // Draw the horizontal lines.
    //
    for(iY = m_iGraticuleSide; iY < m_sizeWaveform.cy; iY += m_iGraticuleSide)
    {
        pDC->MoveTo(0, iY);
        pDC->LineTo(m_sizeWaveform.cx, iY);
    }

    //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -