Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / Win32

A Beautiful Oscilloscope Based on DirectX

Rate me:
Please Sign up or sign in to vote.
4.56/5 (6 votes)
1 Nov 2009CPOL2 min read 50.6K   3.4K   49   9
Fast, real, and easy to connect to your application.

The Oscilloscope, displaying demodulated QPSK data

Introduction

This project is a simple oscilloscope that can be connected to any application. The graphics of the software is based on Direct3D, which makes the scene similar to a physical oscilloscope; and instead of the CPU, much of the workload is performed by the GPU.

If your application deals with digital demodulation, this project is for you. To be specific, if your application demodulates the PSK data, then you can use this software oscilloscope to view the constellation of output data. The oscilloscope can display data of any rate. You just need to implant a little bunch of code to your application, and my executable oscilloscope will communicate with your application through Inter-Process Communication (IPC). If you don't know IPC, don't worry. You just need to copy and paste it to your own code.

Background

Before proceeding, I recommend you to download and run the demo application. This will help you to have a basic understanding of how the oscilloscope looks and how it connects to a data-source (i.e., your application). The demo application contains a data-source 'Signal Generation.exe' which generates the QPSK data and runs the oscilloscope to simultaneously show the constellation.

Using the Code

I'll explain how to work with the oscilloscope in four steps:

  1. Inside your code, create a shared buffer. This will be the memory to store the constellation data and the symbol rate. Your application will use this buffer to communicate with me. Add the following code to your application. Read the comments for more information:
  2. C++
    #include "..\Oscilloscope\SharedBuffer.h"
    // Specify the path to SharedBuffer.h
    
    // Global Variable
    SHARED_BUFFER *pSharedBuffer = NULL;
    HANDLE hMapFile = NULL;
    // Global Variable
    
    bool CreateMapFile(void)
    // Call this function from inside
    // the entry-point of your code. Must return true.
    {
        TCHAR szMapName[] = L"MyFileMappingObject";
    
        hMapFile = CreateFileMapping(
            INVALID_HANDLE_VALUE,    // use paging file
            NULL,            // default security 
            PAGE_READWRITE,        // read/write access
            0,            // max. object size 
            sizeof(SHARED_BUFFER),    // buffer size  
            szMapName);        // name of mapping object
    
        if (!hMapFile) 
        { 
            MessageBox(NULL, L"Could not open file mapping object.", 
                       L"Error", MB_OK | MB_ICONERROR);
            return false;
        } 
    
        pSharedBuffer = (SHARED_BUFFER *) MapViewOfFile(
            hMapFile,            // handle to mapping object
            FILE_MAP_ALL_ACCESS,    // read/write permission
            0,
            0,
            sizeof(SHARED_BUFFER));
    
        if (!pSharedBuffer) 
        { 
            MessageBox(NULL, L"Could not map view of file.", 
                             L"Error", MB_OK | MB_ICONERROR);
            return false;
        }
    
        return true;
    }
    
    void CloseMapFile()
    // Call this function just before the exit point of your code.
    {
        if(pSharedBuffer)
            UnmapViewOfFile(pSharedBuffer);
        pSharedBuffer = NULL;
    
        if(hMapFile)
            CloseHandle(hMapFile);
        hMapFile = NULL;
    }
  3. Now, it's your responsibility to store the constellation data (the X and Y components of the sample data) in the shared buffer in sync with the symbol rate. For example, having a symbol rate of 2000, you will have to store 1000 samples in the shared buffer every 0.5 seconds. Samples better be within the range [-1, 1]. pSharedBuffer->x and pSharedBuffer->y are circular buffers; i.e., whenever you reach the end of these buffers, you must wrap to the beginning of them. The oscilloscope also reads these buffers in a circular way. Buffer length is defined by BUFF_SIZE. The structure SHARED_BUFFER is declared in SharedBuffer.h.
  4. Run the oscilloscope to view the constellation. Add the following snippet to your code:
  5. C++
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    ZeroMemory(&pi, sizeof(pi));
    CreateProcess(L"Oscilloscope.exe", NULL, NULL, NULL, TRUE, NULL, 
                  NULL, NULL, &si, &pi);
  6. My oscilloscope will initialize pSharedBuffer->hWnd to point to itself. So, when you are finished working with the oscilloscope, you can close it easily:
  7. C++
    PostMessage(pSharedBuffer->hWnd, WM_QUIT, 0, 0);

Remarks

  1. To use the executable oscilloscope, no extra file or module is required. But if you want to customize the oscilloscope code, or compile and build it, you must have DirectX 9.0 SDK installed and integrated with Visual Studio.
  2. The first version is for demonstration, and is subject to change and improvements. Your ideas, suggestions, and experiences can help me make the application better. I'm looking forward to hearing from you.

History

  • November 1, 2009: First version uploaded. Waiting for feedback.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
Iran (Islamic Republic of) Iran (Islamic Republic of)
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralNot compiling yet Pin
Jay Bowden19-Oct-10 16:14
Jay Bowden19-Oct-10 16:14 
GeneralRe: Not compiling yet Pin
Ali Tavakol19-Oct-10 21:26
Ali Tavakol19-Oct-10 21:26 
GeneralRe: Not compiling yet (much improved, but..) Pin
Jay Bowden20-Oct-10 10:58
Jay Bowden20-Oct-10 10:58 
Thanks, taking out those two .h files allows it to compile OK,
and it runs to this point:

MessageBox(NULL, L"Could not open file mapping object.", L"Error", MB_OK | MB_ICONERROR);


I will study the code to see if I can figure out what it is trying to do here.

- Jay
GeneralRe: Not compiling yet (much improved, but..) Pin
Ali Tavakol20-Oct-10 22:26
Ali Tavakol20-Oct-10 22:26 
GeneralBache Goozoo Pin
HofstraProgrammer4-Nov-09 11:48
HofstraProgrammer4-Nov-09 11:48 
GeneralImprovements Pin
JamieFay1-Nov-09 14:32
JamieFay1-Nov-09 14:32 
GeneralRe: Improvements Pin
Ali Tavakol1-Nov-09 18:47
Ali Tavakol1-Nov-09 18:47 
GeneralOne question Pin
gaurav_verma_mca1-Nov-09 3:40
gaurav_verma_mca1-Nov-09 3:40 
GeneralRe: One question Pin
Ali Tavakol1-Nov-09 7:28
Ali Tavakol1-Nov-09 7:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.