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:
- 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:
#include "..\Oscilloscope\SharedBuffer.h"
SHARED_BUFFER *pSharedBuffer = NULL;
HANDLE hMapFile = NULL;
bool CreateMapFile(void)
{
TCHAR szMapName[] = L"MyFileMappingObject";
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(SHARED_BUFFER), szMapName);
if (!hMapFile)
{
MessageBox(NULL, L"Could not open file mapping object.",
L"Error", MB_OK | MB_ICONERROR);
return false;
}
pSharedBuffer = (SHARED_BUFFER *) MapViewOfFile(
hMapFile, FILE_MAP_ALL_ACCESS, 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()
{
if(pSharedBuffer)
UnmapViewOfFile(pSharedBuffer);
pSharedBuffer = NULL;
if(hMapFile)
CloseHandle(hMapFile);
hMapFile = NULL;
}
- 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.
- Run the oscilloscope to view the constellation. Add the following snippet to your code:
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);
- My oscilloscope will initialize
pSharedBuffer->hWnd
to point to itself. So, when you are finished working with the oscilloscope, you can close it easily:
PostMessage(pSharedBuffer->hWnd, WM_QUIT, 0, 0);
Remarks
- 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.
- 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.