In any sampling system there is a requirement for the period between samples to remain constant within certain boundaries, the timing variation. Random noise on the timing is called the aperture jitter and the effect of it is to add noise on the digital samples; timing variation due to changes in the crystal oscillator frequency add a modulation artefact to the digital samples. These effects are shown in the following diagram.
The diagram shows that ts is the time of sampling the signal and it can be seen that if the time varies outside the limits shown by the arrows then the output will give the wrong digital value.
The range of analog converter performance requirements for different applications is very wide, ranging from 8 bits for instrumentation through 14 bits for telecommunications and control, 24 bits for pro-audio or seismic and sonar applications. So it is important that timing jitter and sinusiodal variations are managed to meet these requirements.
Any random component in the jitter can be removed by averaging however the sinusoidal component causes a modulation artefact that is often impossible to remove once present.
The timing variation artefact was was illustrated to me many years ago by a very experienced analog design engineer who hooked up the outputs of a dual frequency crystal oscillator to an oscilloscope set in X-Y mode. The display was setup in such a way that the Lissajou figure rotated slowly clockwise. He then proceeded to spray the oscillator with freezer spray and the scope display went crazy, finally slowing down to rotate in an anti-clockwise direction.
Why is this important ?
The main reason is that this sinusoidal component causes a modulation effect on the output of the ADC (or DAC) and this has serious implications in all DSP processing algorithms but especially those that perform any kind of modulation/demodulation or sample rate conversion.
Twice in my engineering career, once in a V.32 voiceband modem and secondly in a 3G mobile basestation, I have seen modems completely screwed up by using crystal oscillators that do not meet the required specification. The result was that the modems would work for a period of time and then fail with no apparent cause. In the case of the V.32 modem the failure only appeared to happen over night when the systems had been left running for many hours. Arriving at work in the morning was always a worrying time and caused a lot of stress for the team until the root-cause was found and fixed. We thought it might be temperature related (the modems at the bottom of the test rack ran for longer but all were within the temperature spec.), power surges, electrically noisy vacuum cleaners, the timing error detector algorithm, the Viterbi decoder etc in the end it turned out to be the crystal oscillator - some 100 ppm parts had been fitted instead of the specified 32 ppm version.
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Sunday, 27 April 2014
Accuracy And Precision
In my DSP classes I often cover the difference between precision and accuracy when measuring and processing input values from a transducer.
I recently came across an excellent little illustration of this on page 7 of the Keller-Druck Brochure : http://flipflashpages.uniflip.com/2/52802/96120/pub/#page7.
From a signal processing point of view the key points from this diagram are :
1/ When the measurements are very precise (as shown in diagram A) then accuracy can be improved by removing the offset via subtraction of the average of the samples.
2/ When measurements are more accurate but there is a larger deviation (as shown in diagram B) then the deviation can be reduced by oversampling and averaging the results.
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
I recently came across an excellent little illustration of this on page 7 of the Keller-Druck Brochure : http://flipflashpages.uniflip.com/2/52802/96120/pub/#page7.
From a signal processing point of view the key points from this diagram are :
1/ When the measurements are very precise (as shown in diagram A) then accuracy can be improved by removing the offset via subtraction of the average of the samples.
2/ When measurements are more accurate but there is a larger deviation (as shown in diagram B) then the deviation can be reduced by oversampling and averaging the results.
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Saturday, 29 March 2014
How Fast Are Our Digital Signal Processors ?
Since I started using DSPs in 1985 I been interested in how the clock speeds have been increasing. The very first DSPs appeared in the mid 1970s but I tracked the figures back to slightly pre-DSP days. This graph shows the Fixed-point DSP Mutiply Accumulate (MAC) Times (ns).
It is interesting to notice two particular elements of the graph :
1/ The reduction in cycle times around the turn of the century as we moved to modern VLIW/SIMD architectures.
2/ The squeeze on cycle times that has happened since the mid 2000s, in fact, if we were to put in 2014s figure it would be little different to the 0.8 of 2011.
Going forward it will be interesting to see if what technology, if anything, will come along that will allow future clock speed upgrades so that the DSP manufacturers don't just have to rely on parallel processing to provide increased performance.
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
![]() |
| General Purpose Fixed-point DSP MAC Times (ns) |
1/ The reduction in cycle times around the turn of the century as we moved to modern VLIW/SIMD architectures.
2/ The squeeze on cycle times that has happened since the mid 2000s, in fact, if we were to put in 2014s figure it would be little different to the 0.8 of 2011.
Going forward it will be interesting to see if what technology, if anything, will come along that will allow future clock speed upgrades so that the DSP manufacturers don't just have to rely on parallel processing to provide increased performance.
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Wednesday, 15 January 2014
Interfacing C/C++ to Gnuplot
Over the years I have used many different applications for plotting DSP and scientific data (Matplotlib, MathGL, Grace etc) all have their benefits and disadvantages but I have never strayed far from the excellent Gnuplot.
Back in the early 1990s I wrote a library that worked with both the Borland and Microsoft C compilers (The Numerix Host Library) for displaying DSP data on old VGA screens. This library included it's own graphical plotting functions but over the years I have rewritten most of the library to interface to Gnuplot via an API that I call Gnuplot/C.
Gnuplot/C uses pipes to send data from C/C++ to Gnuplot's much more powerful graphical front-end.
Late last year, while updating some class notes for the Oxford University DSP Course, with some graphs generated using Gnuplot/C, I realized that it was about time I finally got around to documenting the API and making it available to others.
This was a perfect project for the Christmas/New Year holiday period and while the majority of the code was written then, the documentation took a little longer ;-)
Gnuplot/C is available from http://www.numerix-dsp.com/files.
One day I will port this to Python but maybe that is for another holiday ;-)
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Back in the early 1990s I wrote a library that worked with both the Borland and Microsoft C compilers (The Numerix Host Library) for displaying DSP data on old VGA screens. This library included it's own graphical plotting functions but over the years I have rewritten most of the library to interface to Gnuplot via an API that I call Gnuplot/C.
Gnuplot/C uses pipes to send data from C/C++ to Gnuplot's much more powerful graphical front-end.
Late last year, while updating some class notes for the Oxford University DSP Course, with some graphs generated using Gnuplot/C, I realized that it was about time I finally got around to documenting the API and making it available to others.
This was a perfect project for the Christmas/New Year holiday period and while the majority of the code was written then, the documentation took a little longer ;-)
Gnuplot/C is available from http://www.numerix-dsp.com/files.
One day I will port this to Python but maybe that is for another holiday ;-)
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Monday, 23 December 2013
Arachnophobia !
This is just a little too freaky.
Dancing Robugtix T8 robot spider controlled by an XMOS xCORE device. :
http://www.youtube.com/watch?v=Yo2TUIEXJig
Enthusiastically reviewed by Adam Savage from Mythbusters :
http://www.youtube.com/watch?v=-vVblGlIMgw
Numerix-DSP Libraries : http://www.numerix-dsp.com/eval/
Dancing Robugtix T8 robot spider controlled by an XMOS xCORE device. :
http://www.youtube.com/watch?v=Yo2TUIEXJig
Enthusiastically reviewed by Adam Savage from Mythbusters :
http://www.youtube.com/watch?v=-vVblGlIMgw
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Numerix-DSP Libraries : http://www.numerix-dsp.com/eval/
Copyright © 2013 Delta Numerix
Sunday, 15 December 2013
How To Use MathGL Under Windows with the Microsoft Visual Studio 2010 64 bit compiler
Introduction
This solution is heavily based on the solution provided in the following tutorial : https://groups.google.com/forum/#!topic/mathgl/t-X9eg-5joU.My thanks to RK for helping me find a solution.
I have found some changes in the packages since RK's post and I also needed 64 bit GLUT libraries so I have made minor some changes to his procedures.
Note : While this solution worked, I found that the MathGL functionality didn't quite stack up to that available in GNUPlot, see here for further details : http://realgonegeek.blogspot.co.uk/2014/01/interfacing-cc-to-gnuplot.html.
Requirements
Microsoft Visual Studio 2010 : go.microsoft.com/fwlink/?LinkId=244366Microsoft SDK v7.1 64 bit compiler. Installation instructions are here : http://realgonegeek.blogspot.co.uk/2013/08/microsoft-visual-c-2010-sdk-v71-64-bit.html
MathGL 2.2 source code : http://sourceforge.net/projects/mathgl/files/mathgl/mathgl%202.2/mathgl-2.2.tar.gz/download
FreeGlut 2.8.1 (Martin Payne's Windows MSVC binaries : http://www.transmissionzero.co.uk/software/freeglut-devel/
CMake 2.8.11 : http://www.cmake.org/files/v2.8/cmake-2.8.12.1-win32-x86.exe
Procedures
1. Follow steps 1 to 3 in RK's tutorial except using freeglut instead of the original GLUT.
2. Before running CMake-gui ensure that you have configured the Microsoft Compiler environment using :
"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" amd64
3. Follow steps 4 to 6 in RK's tutorial and choose "Visual Studio 10 Win64" in step 6.
4. Tick the Advanced box in CMake-gui to view all of the requried entries (e.g GLUT_INCLUDE_DIR and GLUT_glut_LIBRARY)
5. Follow the rest of RK's tutorial
6. In your chosen source code folder create the following file (e.g. example.cpp) :
#pragma warning( disable: 4190 ) // Disable complex number warning
#include <mgl2/glut.h>
int sample(mglGraph *gr)
{
mglData dat (100);
for (long i = 0; i < 40; i++)
{
gr->NewFrame (); // start frame
gr->Box (); // some plotting
gr->Axis (); // draw axis
for (long j = 0; j < dat.nx; j++)
dat.a[j] = sin (M_PI*j/dat.nx+M_PI*0.05*i);
gr->Plot (dat, "b"); // "b" is colour ??
gr->EndFrame (); // end frame
gr->WriteFrame (); // save frame
}
return 0;
}
int main (int argc, char **argv)
{
mglGLUT gr (sample, "MathGL examples");
return 0;
}
7. Open a command window into your source folder and ensure the Microsoft Compiler environment is correctly configured, as per step 2. above.
8. Configure the compiler environment variables to locate the header and library files e.g. :
set INCLUDE=%INCLUDE%;c:\mathgl-2.2\include
set LIB=%LIB%;c:\mathgl_v2.2\src\Release;C:\mathgl_v2.2\widgets\Release
9. Compile example.cpp using the following command line :
cl /EHsc example.cpp mgl-glut.lib
10. Copy the required dlls to the current folder :
copy /Y C:\Users\johne2\Desktop\Graphics\mathgl\mathgl_v2.2\mathgl-2.2-cmake\src\Release\*.dll
copy /Y C:\Users\johne2\Desktop\Graphics\mathgl\mathgl_v2.2\mathgl-2.2-cmake\widgets\Release\*.dll
copy /Y C:\Users\johne2\Desktop\Graphics\mathgl\Glut\freeglut\bin\x64\*.dll
11. Execute example.exe and you should see a scrolling sine wave.
12. Play with MathGL :-)
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Friday, 13 September 2013
How To Access A Windows Library From Python, Using SWIG
In the previous blog (How To Build Windows Static And Dynamic Link Libraries) I described how to generate static and dynamic link libraries from C functions. This blog describes how to call these functions fom Python. In this example we will access the same VectorScalarMultiply function. We will use SWIG (http://www.swig.org) to provide the wrapper between Python and C. SWIG is a really useful tool for importing C libraries into almost all common scritping languages like Python, PERL, Java etc.
First off, we need to provide a SWIG interface file (Multiply.i) to tell SWIG about our library. SWIG is very powerful because it is able to obtain a lot of information from the library header file, for example, it can work out that Data_t is typedef'd to a double. However we do need to assist SWIG and tell it that we are going to be handling arrays of floating point data.
To do this we include the SWIG interface file "carrays.i" and tell SWIG we want to use the array_class interface. The complete interface file is shown here :
%module Multiply_wrap
%include "typemaps.i"
%include "carrays.i"
%array_class(double, doubleArray); /* Include support for "double *" functions */
%array_class(long, longArray); /* Include support for "long *" functions */
%{
#include "Multiply.h"
%}
%include "Multiply.h"
With this file we can now create the importable Python module that contains the functions we want to access. This is essentially a two stage process :
Configure SWIG
Compile the library into a Python importable module
Here is a complete batch file for creating a Python wrapper for accessing the library. Note that we are calling the new DLL (Multiply_wrap.dll) to differentiate it from Multiply.dll created in the earlier blog. Note that Python expects the file to be called Multiply_wrap.pyd so we will also rename it.
Please refer to the remarks for additional comments.
rem Delete the wrapper c file so that if it is not regenerated using swig then the compile will fail
rem this is helpful for development because if the you don't delete the old file then the compiler
rem will just process that, which might not be what you want !
del Multiply_wrap_wrap.c
c:\swig\swig -python -includeall Multiply_wrap.i
cl -Od -MD -DNDEBUG -DWIN32 -IC:\Anaconda\envs\py33\include -D_CONSOLE -DSTATIC_LIB=1 -DNO_STRICT Multiply_wrap_wrap.c /link user32.lib Multiply.lib C:\Anaconda\envs\py33\libs\python33.lib /DLL /out:Multiply_wrap.dll /NODEFAULTLIB:LIBCMT
rem The Python module should have extension .pyd
rem so we will delete the old one and rename the newly created dll
if exist _Multiply_wrap.pyd del /Q _Multiply_wrap.pyd
ren Multiply_wrap.dll _Multiply_wrap.pyd
Finally, we need to write a test script to access the C coded function.
This function includes some additional functionality that is not strictly necessary but this is to show some additional useful techniques such as :
Printing the attributes of the library
Converting Python lists to C arrays and back again
Accessing the values of C #define constants from Python
Here is the complete Test.py script :
import multiply_wrap # Note the module name must be lower case !
print ('')
print ('Library attributes :') # Print the attributes of the library
for a in dir(Multiply_wrap):
print (a)
print ('')
a = [1.2, 3.4, 5.6, 7.8, 9.0]
b = [1000.1, 100.2, 1000.3, 1000.4, 1000.5] # Destination array to put results into
print ('')
print ('PI = ') # Print a constant defined in C
print (Multiply_wrap.PI)
print ('')
p_a = Multiply_wrap.doubleArray (5)
p_b = Multiply_wrap.doubleArray (5)
for index, item in enumerate(a): # Copy data to array p_a
p_a[index] = item
print ('a = ') # Print contents of a
for i in range(0,5):
print(p_a[i])
print ('')
Multiply_wrap.VectorScalarMultiply (p_a, Multiply_wrap.TWO_PI, p_b, 5)
for i in range(0,5): # Copy data to b
b[i] = p_b[i]
print ('Scaled a = ')
print (b)
print ('')
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
First off, we need to provide a SWIG interface file (Multiply.i) to tell SWIG about our library. SWIG is very powerful because it is able to obtain a lot of information from the library header file, for example, it can work out that Data_t is typedef'd to a double. However we do need to assist SWIG and tell it that we are going to be handling arrays of floating point data.
To do this we include the SWIG interface file "carrays.i" and tell SWIG we want to use the array_class interface. The complete interface file is shown here :
%module Multiply_wrap
%include "typemaps.i"
%include "carrays.i"
%array_class(double, doubleArray); /* Include support for "double *" functions */
%array_class(long, longArray); /* Include support for "long *" functions */
%{
#include "Multiply.h"
%}
%include "Multiply.h"
With this file we can now create the importable Python module that contains the functions we want to access. This is essentially a two stage process :
Configure SWIG
Compile the library into a Python importable module
Here is a complete batch file for creating a Python wrapper for accessing the library. Note that we are calling the new DLL (Multiply_wrap.dll) to differentiate it from Multiply.dll created in the earlier blog. Note that Python expects the file to be called Multiply_wrap.pyd so we will also rename it.
Please refer to the remarks for additional comments.
rem Delete the wrapper c file so that if it is not regenerated using swig then the compile will fail
rem this is helpful for development because if the you don't delete the old file then the compiler
rem will just process that, which might not be what you want !
del Multiply_wrap_wrap.c
c:\swig\swig -python -includeall Multiply_wrap.i
cl -Od -MD -DNDEBUG -DWIN32 -IC:\Anaconda\envs\py33\include -D_CONSOLE -DSTATIC_LIB=1 -DNO_STRICT Multiply_wrap_wrap.c /link user32.lib Multiply.lib C:\Anaconda\envs\py33\libs\python33.lib /DLL /out:Multiply_wrap.dll /NODEFAULTLIB:LIBCMT
rem The Python module should have extension .pyd
rem so we will delete the old one and rename the newly created dll
if exist _Multiply_wrap.pyd del /Q _Multiply_wrap.pyd
ren Multiply_wrap.dll _Multiply_wrap.pyd
Finally, we need to write a test script to access the C coded function.
This function includes some additional functionality that is not strictly necessary but this is to show some additional useful techniques such as :
Printing the attributes of the library
Converting Python lists to C arrays and back again
Accessing the values of C #define constants from Python
Here is the complete Test.py script :
import multiply_wrap # Note the module name must be lower case !
print ('Library attributes :') # Print the attributes of the library
for a in dir(Multiply_wrap):
print (a)
print ('')
a = [1.2, 3.4, 5.6, 7.8, 9.0]
b = [1000.1, 100.2, 1000.3, 1000.4, 1000.5] # Destination array to put results into
print ('')
print ('PI = ') # Print a constant defined in C
print (Multiply_wrap.PI)
print ('')
p_a = Multiply_wrap.doubleArray (5)
p_b = Multiply_wrap.doubleArray (5)
for index, item in enumerate(a): # Copy data to array p_a
p_a[index] = item
print ('a = ') # Print contents of a
for i in range(0,5):
print(p_a[i])
print ('')
Multiply_wrap.VectorScalarMultiply (p_a, Multiply_wrap.TWO_PI, p_b, 5)
for i in range(0,5): # Copy data to b
b[i] = p_b[i]
print ('Scaled a = ')
print (b)
print ('')
If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Subscribe to:
Posts (Atom)
