why might an application copied into a subfolder of Program Files terminate abnormally, when it executes fine from other locations? i got nothing.
why might an application copied into a subfolder of Program Files terminate abnormally, when it executes fine from other locations? i got nothing.
Is it looking for a file with a relative path?
Perhaps it handles spaces in pathnames badly.
Perhaps it ... nevermind, post actual code which shows the problem and lets cut to the chase instead of playing 20 questions.
...
...
...
If you're using relative paths, and you move one thing, don't you think you would need to move the other so that the relative paths remain the same?
Whether relative paths+moving files or full paths+keeping the file in the same place always is the right choice we don't know, but you'll have to pick one.
> i can't tell the hell the problem is.
Well you could begin by adding more rigorous error checking to everywhere you open a file for example.
Or is that any error checking?
Code://---------------------------------------------------------------------------
#ifndef spectrometersH
#define spectrometersH
#include "filters.h"
#include "procObj.h"
#include "objIcon.h"
#include "input.h"
#include "classDefs.h"
#include "tasksAndRoutines.h"
#include <valarray.h>
#include <Classes.hpp>
//---------------------------------------------------------------------------
class spectrometer;
class spectrum;
class spectrometerIcon : public objIcon
{
public:
spectrometerIcon(spectrometer *owner,int h,int w);
spectrometer *owner;
void __fastcall initConns(bool b);
virtual void __fastcall draw();
};
class initSpectrometer : public routine
{
public:
initSpectrometer(spectrometer *Owner);
spectrometer *owner;
virtual void __fastcall Execute();
};
class spectrometer : public input
{
protected:
public:
spectroscopySuite *spectroscopyTool;
virtual int __fastcall connect()=0;
spectrometer(process *owner,String name,int addr,int samplingInterval,int h,int w,input *tempSensor);
input *tempSensor;
void __fastcall (__closure *onScan)();
virtual void __fastcall initSpectra();
void __fastcall makeIcon(int h,int w);
String storedSampleRef;
String storedDarkRef;
String storedLightRef;
virtual void __fastcall loadSample(String filename)
{
if(loadSpectrum(filename,sampleRef))
{
storedSampleRef = filename;
}
}
bool INITED;
virtual void __fastcall getPixelConv(){};
bool __fastcall loadSpectrum(String filename,spectrum *s);
bool __fastcall loadSpectrumFromString(String input,spectrum *s);
spectrum *__fastcall getRelAbs();
spectrum *relTrans;
spectrum *relAbs;
spectrum *darkRef;
spectrum *sample;
spectrum *sampleRef;
const unsigned int ARRSIZE;
unsigned short refAvg;
unsigned short sampleAvg;
virtual void __fastcall setArrSize(const unsigned int size);
__property unsigned int arrSize={read=ARRSIZE,write=setArrSize};
unsigned short iTime;
virtual void __fastcall getDarkRef()=0;
virtual void __fastcall getSampleRef()=0;
virtual int __fastcall avgSpec(spectrum *s, int points)=0;
virtual double __fastcall pixelToWavelength(int pixel)=0;
virtual double __fastcall wavelengthToPixel(double wl)=0;
double saturationThreshold;
DynamicArray<spectrum *>spectra;
unsigned int nextReferenceTime;
unsigned int referenceInterval;
virtual void __fastcall rereference()
{
getDarkRef();
}
String refFileName;
void __fastcall logReference(spectrum *ref);
double maxY;
virtual void __fastcall setConnected(bool state)=0;
virtual bool __fastcall getConnected()=0;
void __fastcall (__closure*setInited)(bool);
__property bool initialized={read=getInited};
virtual void __fastcall initialize()=0;
routine *initSpectrometer;
virtual int __fastcall getSpectrum()=0;
//
// virtual void __fastcall getState();
bool CONNECTED;
__property bool connected={read=getConnected,write=setConnected};
TprogressForm *progForm;
virtual void __fastcall makeNodes(TTreeNode *parent){}
bool *initCriteria;
unsigned int numInitCriteria;
virtual bool __fastcall getInited()
{
if(!INITED)
{
bool result=true;
int i=-1;
while(++i<numInitCriteria && result)
{
result &=initCriteria[i];
}
INITED = result;
if(setInited!=NULL)
{
setInited(result);
}
}
return INITED;
}
};
#endif
Code://---------------------------------------------------------------------------
#include "objConn.h"
#include "utils.h"
#include "dir.h"
#include "procMenu.h"
#include "objTasks.h"
#include "paramClasses.h"
#include "processClasses.h"
#include "spectroscopyTools.h"
#include "progForm.h"
#include "appMain.h"
#include "spectrum.h"
#include "flowPath.h"
#pragma hdrstop
#pragma package(smart_init)
#include "spectrometers.h"
initSpectrometer::initSpectrometer(spectrometer *Owner) : routine("Initialize "+Owner->name,Owner->owner)
{
owner = Owner;
}
void __fastcall initSpectrometer::Execute()
{
while(!Terminated)
{
owner->getDarkRef();
owner->getSampleRef();
}
}
bool __fastcall spectrometer::loadSpectrum(String fname,spectrum *s)
{
double test;
char l[65536];
FILE *f = fopen(fname.c_str(),"r");
DynamicArray<String>line;
bool ok = true;
while(fgets(l,65536,f)&&ok)
{
line = explode((String)l,",");
for(int i =0;i<line.Length;i++)
{
String str =Trim(line[i]);
if(!TryStrToFloat(str,test))
{
MessageDlg("Invalid Data Format",mtError,TMsgDlgButtons()<<mbOK,0);
ok=false;
i=line.Length;
}
}
}
fclose(f);
if(ok)
{
f = fopen(fname.c_str(),"r");
DynamicArray<String>line;
int d=0;
while(fgets(l,999999,f)&&ok&&d<arrSize)
{
line = explode((String)l,",");
for(int i =0;i<line.Length;i++)
{
double val;
String str =Trim(line[i]);
if(!TryStrToFloat(Trim(line[i]),val))
{
MessageDlg("Invalid Data Format",mtError,TMsgDlgButtons()<<mbOK,0);
ok=false;
i=line.Length;
}
else
{
s->data[d] = val;
}
d++;
}
}
}
return ok;
}
bool __fastcall spectrometer::loadSpectrumFromString(String input,spectrum *s)
{
double test;
bool ok;
int d =0;
DynamicArray<String>line;
line = explode((String)input,",");
if(line.Length!=arrSize)
{
MessageDlg("Array length mismatch - cannot load spectrum for "+s->title,mtError,TMsgDlgButtons()<<mbOK,0);
return false;
}
for(int i =0;i<line.Length;i++)
{
double val;
String str =Trim(line[i]);
if(!TryStrToFloat(Trim(line[i]),val))
{
MessageDlg("Invalid Data Format",mtError,TMsgDlgButtons()<<mbOK,0);
ok=false;
i=line.Length;
}
else
{
s->data[d] = val;
}
d++;
}
return ok;
}
spectrometer::spectrometer(process *owner,String name,int addr,int samplingInterval,int h,int w,input *TempSensor): input(owner,name,addr,samplingInterval),
INITED(false),
onScan(NULL),
numInitCriteria(0),
tempSensor(TempSensor)
{
arrSize=1;
relTrans= new spectrum(this,arrSize,"Relative Transmission");
relAbs= new spectrum(this,arrSize,"Relative Absorbance");
sample= new spectrum(this,arrSize,"Current Spectrum");
darkRef= new spectrum(this,arrSize,"Dark Reference");
sampleRef= new spectrum(this,arrSize,"Sample Reference");
CONNECTED=false;
refFileName = name+"\ References.csv";
initSpectra();
if((h+w)>0)
{
makeIcon(h,w);
owner->syncUpdateDisplays(this);
}
}
void __fastcall spectrometer::makeIcon(int h,int w)
{
icon=new spectrometerIcon(this,h,w);
loadPopup();
draw();
}
void __fastcall spectrometer::logReference(spectrum *ref)
{
String timeString;
DateTimeToString(timeString,"yyyy-mm-dd hh:nn:ss.zz",Now());
writeToFile(refFileName,ref->title+" "+timeString+"\n","a+");
writeToFile(refFileName,ref->asString()+"\n","a+");
}
/*
void __fastcall spectrometer::getState()
{
if(CONNECTED)
{
getSpectrum();
}
}
*/
void __fastcall spectrometer::setArrSize(const unsigned int size)
{
if(size!=ARRSIZE)
{
*(int *)&ARRSIZE=size;
initSpectra();
}
}
void __fastcall spectrometer::initSpectra()
{
for(int i=0;i<spectra.Length;++i)
{
spectra[i]->size=arrSize;
delete[] spectra[i]->data;
spectra[i]->data=new double[arrSize];
spectra[i]->fill(0);
}
}
spectrometerIcon::spectrometerIcon(spectrometer *Owner,int h,int w) : objIcon(Owner,h,w)
{
owner = Owner;
initConns(NULL);
}
void __fastcall spectrometerIcon::initConns(bool b)
{
conns.Length = 4;
conns[0]=new objConn(owner,Width/2,0);
conns[1]=new objConn(owner,Width,Height/2);
conns[2]=new objConn(owner,Width/2,Height);
conns[3]=new objConn(owner,0,Height/2);
}
void __fastcall spectrometerIcon::draw()
{
clear();
int th = Canvas->TextHeight(owner->name);
int tw = Canvas->TextWidth(owner->name);
int titleheight=0,specheight=0,border=2,specWidth=Width-2*border;
int tpos = (Width-tw)/border;
if(Height/4>2*border+th)
{
titleheight=2*border+th;
specheight=Height-titleheight-2*border;
}
Canvas->Brush->Color = clSilver;
Canvas->FillRect(TRect(0,0,Width,Height));
Canvas->Pen->Color = 0x00FFFFFF;
Canvas->MoveTo(0,Height);
Canvas->LineTo(0,0);
Canvas->LineTo(Width-1,0);
Canvas->Pen->Color = clDkGray;
Canvas->LineTo(Width-1,Height-1);
Canvas->LineTo(0,Height-1);
Canvas->Pen->Color = clMedGray;
Canvas->MoveTo(3,Height-border);
Canvas->LineTo(Width-border,Height-border);
Canvas->LineTo(Width-border,1);
Canvas->Brush->Color = 0x00FFFFFF;
Canvas->RoundRect(tpos-8,border,tpos+tw+8,titleheight-border,8,8);
Canvas->Brush->Style = bsClear;
Canvas->TextOut(tpos,(titleheight-th)/border,owner->name);
Canvas->Brush->Style = bsSolid;
int xo = 2*border;
Canvas->FillRect(TRect(xo,titleheight,Width-xo,Height-4));
Canvas->Pen->Color = clMedGray;
Canvas->MoveTo(xo,Height-3);
Canvas->LineTo(xo,titleheight);
Canvas->LineTo(Width-xo,titleheight);
if(owner->CONNECTED)
{
int r = owner->arrSize/specWidth;
int h= specheight-4;
Canvas->MoveTo(4,Height-3);
Canvas->Pen->Color = 0x00FF0000;
for(int i=0;i<specWidth;i++)
{
int v1 = owner->sample->data[(int)r*i]*h;
Canvas->LineTo(i+xo+1,Height-4-v1);
}
}
else
{
TColor color = Canvas->Font->Color;
Canvas->Font->Color=0x000000DF;
Canvas->Font->Style = TFontStyles()<< fsBold;
String msg = "NOT CONNECTED";
int tw = Canvas->TextWidth(msg);
int th = Canvas->TextHeight(msg);
Canvas->TextOut(xo+(Width-border*xo-tw)/2,(specheight-1+th)/2,msg);
Canvas->Font->Color=color;
Canvas->Font->Style = TFontStyles();
}
}
Code://---------------------------------------------------------------------------
#ifndef BWTEKUSBH
#define BWTEKUSBH
#include "spectrometers.h"
class bwTekUSB : public spectrometer
{
protected:
String dllPath;
public:
virtual int __fastcall bwtest();
virtual double __fastcall pixelToWavelength(int pixel);
virtual double __fastcall wavelengthToPixel(double wl);
virtual int __fastcall avgSpec(spectrum *s, int points);
typedef int _stdcall (*bwtekSetupChannel)(int channelNumber,int unknown);
virtual void __fastcall getPixelConv();
DynamicArray<double>pixelToWavelengthCoeffs;
DynamicArray<double>wavelengthToPixelCoeffs;
typedef int _stdcall (*bwtekTestUSB)
(
int nUSBTiming, // USB Interface timing option
int nPixelNo, // number of pixels of a detector to be readout
int nInputMode, // signal conditioning stage gain value
int nChannel, // channel to get data from
int pParam // extra setting parameters only for RS232
);
typedef long _stdcall (*bwtekSetTimeUSB)
(
long lTime, // integration time setting
int nChannel // channel to get data from
);
typedef int _stdcall (*bwtekDataReadUSB)
(
int nTriggerMode, // Base address for plug-in data acquisition board
unsigned short *pArray, // data value array from the read operation stored
int nChannel // channel to get data from
);
typedef int _stdcall (*bwtekReadResultUSB)
(
int nTriggerMode, // setting for trigger mode
int nAverage, // number of scans to be averaged
int nTypeSmoothing, // setting for smoothing type
int nValueSmoothing, // setting for smoothing parameter
unsigned short *pArray, // an array memory space for scan data
int nChannel=0 // setting for channel number
);
typedef int _stdcall (*bwtekCloseUSB)
(
int nchannel // channel to get data from
);
typedef int _stdcall (*bwtekReadEEPROMUSB)
(
char *OutFileName, // The filename in which data from EEPROM would be saved
int nChannel=0 // channel number to get data from
);
typedef int _stdcall (*bwtekSetTimingsUSB)
(
long lTriggerExit, // Setting external trigger timeout
int nMultiple, // A multifly factor for long integration time
int nChannel=0 //channel number to get data from
);
typedef int __stdcall (* bwtekPolyFit)
(
double *x, // Array of independent variables
double *y, // Array of dependent variables
int const numPts, // Number of points in independent and dependent arrays
double *coefs, // Pointer to array containing calculated coeffi cients [index from 0 to order]
int const order // Desired order of polynomial fi t
);
typedef void _stdcall (*bwtekPolyCalc)
(
double *coefs,
int const order,
int const x,
double *y
);
typedef int _stdcall (*bwtekGetExtStatus)
(
int nchannel //channel to get data from
);
typedef int _stdcall (*bwtekSetExtLaser)
(
int nOnOff, //switch for On/Off
int nchannel //channel to get data from
);
typedef int _stdcall (*bwtekSetExtShutter)
(
int nOnOff, // switch for On/Off
int nchannel // channel to get data from
);
typedef int _stdcall (*bwtekSetExtSync)
(
int nOnOff, //switch for On/Off
int nchannel //channel to get data from
);
typedef int _stdcall (*bwtekGatedMode)
(
int nGatedTime, // Gated Time between an External trigger and a CCD trigger
int nchannel // channel to get data from
);
typedef int _stdcall (*bwtekSetExtPulse)
(
int nOnOff, // switch to turn on or off pulse train
int nDelayTime, // delay time between the CCD trigger and the fi rst pulse
int nHigh, // time duration for high pulse width
int nLow, // time duration for low pulse width
int nPulse, // number of pulses to be generated
int nInverse, // pulse output will be inverted
int nChannel // channel to get data from
);
virtual void __fastcall rereference();
virtual void __fastcall maintMode(bool on);
virtual void __fastcall loadPopup();
typedef int _stdcall (*bwtekShutterOpen)(int);
// enum initializationCriteria{iTimeOK=1,darkOK=2,sampleOK=4,pixelConv=8,OK=15}inited;
const unsigned int iTimeOK;
const unsigned int darkOK;
const unsigned int sampleOK;
const unsigned int pixelConvOK;
void __fastcall processSpectrum();
void __fastcall checkRef();
typedef int _stdcall (*bwtekShutterClose)(int);
unsigned int iTimeOffset;
virtual void __fastcall initialize();
virtual void __fastcall autoSetITime();
virtual void __fastcall getRelTrans();
virtual int __fastcall getSpectrum();
int __fastcall connect();
void __fastcall setITime(int ITime);
int __fastcall setExtShutter(int state);
virtual void __fastcall getSampleRef();
virtual void __fastcall getDarkRef();
virtual int setShutter(unsigned short state);
void __fastcall loadDLL(String path);
void __fastcall initPix(const int size);
bwTekUSB(String name,process *Owner,int Channel,int arrSize ,int ADCTYPE,int TimingMode,bool connectNow,input *tempSensor,int h,int w);
int _stdcall (*bwTest)
(
int nUSBTiming, // USB Interface timing option
int nPixelNo, // number of pixels of a detector to be readout
int nInputMode, // signal conditioning stage gain value
int nChannel, // channel to get data from
int pParam // extra setting parameters only for RS232
);
int _stdcall (*readEeprom)
(
char *OutFileName, // The filename in which data from EEPROM would be saved
int nChannel=0 // channel number to get data from
);
int _stdcall (*setupChannel)(int channel,int unknown);
int _stdcall (*openShutter)(int);
int _stdcall (*closeShutter)(int);
long _stdcall (*bwSetTime)
(
long lTime, // integration time setting
int nChannel // channel to get data from
);
int _stdcall (*bwReadData)
(
int nTriggerMode, // Base address for plug-in data acquisition board
unsigned short *pArray, // data value array from the read operation stored
int nChannel // channel to get data from
);
int _stdcall (*bwClose)
(
int nchannel // channel to get data from
);
int _stdcall (*bwReadAvgResult)
(
int nTriggerMode, // setting for trigger mode
int nAverage, // number of scans to be averaged
int nTypeSmoothing, // setting for smoothing type
int nValueSmoothing, // setting for smoothing parameter
unsigned short *pArray, // an array memory space for scan data
int nChannel=0 // setting for channel number
);
int _stdcall (*bwReadEEPROM)
(
char *OutFileName, // The filename in which data from EEPROM would be saved
int nChannel=0 // channel number to get data from
);
int _stdcall (*bwSetTiming)
(
long lTriggerExit, // Setting external trigger timeout
int nMultiple, // A multifly factor for long integration time
int nChannel=0 //channel number to get data from
);
int _stdcall (*bwPolyFit)
(
double *x, // Array of independent variables
double *y, // Array of dependent variables
int const numPts, // Number of points in independent and dependent arrays
double *coefs, // Pointer to array containing calculated coeffi cients [index from 0 to order]
int const order // Desired order of polynomial fi t
);
void _stdcall (*bwPolyCalc)
(
double *coefs,
int const order,
int const x,
double *y
);
int _stdcall (*bwGetStatus)
(
int nchannel //channel to get data from
);
int _stdcall (*bwSetExtLaser)
(
int nOnOff, //switch for On/Off
int nchannel //channel to get data from
);
int _stdcall (*bwSetExtShutter)
(
int nOnOff, // switch for On/Off
int nchannel // channel to get data from
);
int _stdcall (*bwSetExtSync)
(
int nOnOff, //switch for On/Off
int nchannel //channel to get data from
);
int _stdcall (*bwGatedMode)
(
int nGatedTime, // Gated Time between an External trigger and a CCD trigger
int nchannel // channel to get data from
);
int _stdcall (*bwSetPulse)
(
int nOnOff, // switch to turn on or off pulse train
int nDelayTime, // delay time between the CCD trigger and the fi rst pulse
int nHigh, // time duration for high pulse width
int nLow, // time duration for low pulse width
int nPulse, // number of pulses to be generated
int nInverse, // pulse output will be inverted
int nChannel // channel to get data from
);
void __fastcall scanOnTimer(TObject *Sender);
unsigned short shutterState;
unsigned short timingMode;
unsigned short adcType;
double *tmp;
unsigned short *rawData;
double maxY;
void __fastcall setChannel(int chan);
virtual bool __fastcall getInited()
{
if(!INITED)
{
bool result=true;
int i=0;
while(i<numInitCriteria && result)
{
result &=initCriteria[i];
i++;
}
INITED = result;
if(setInited!=NULL)
{
setInited(result);
}
}
return INITED;
}
void __fastcall (__closure*setInited)(bool);
__property bool initialized={read=getInited};
virtual void __fastcall setConnected(bool state);
virtual bool __fastcall getConnected();
__property bool connected={read=getConnected,write=setConnected};
unsigned short shutterWait;
void __fastcall refreshIcon();
};
//---------------------------------------------------------------------------
class bwTek261E_512 : public bwTekUSB
{
public:
bwTek261E_512(String name,process *Owner,int chan,bool connectNow,input *tempSensor,int h, int w):bwTekUSB(name,Owner,chan,512,13,3,connectNow,tempSensor,h,w)
{
HINSTANCE HInst=LoadLibrary("BWTEKUSB.dll");
if( HInst>0 )
{
getMode=(bwtekGetInGaAsMode)GetProcAddress(HInst,"bwtekGetInGaAsMode");
setMode=(bwtekSetInGaAsMode) GetProcAddress(HInst,"bwtekSetInGaAsMode");
}
}
typedef int _stdcall (*bwtekGetInGaAsMode)
(
int *nMode, // select detector mode
int nChannel // channel to get data from
);
typedef int _stdcall (*bwtekSetInGaAsMode)
(
int nMode, // select feedback capacitor mode
int nChannel // channel to get data from
);
int _stdcall (*getMode)
(
int *nMode, // select detector mode
int nChannel // channel to get data from
);
int _stdcall (*setMode)
(
int nMode, // select feedback capacitor mode
int nChannel // channel to get data from
);
};
class initBwTekS255_256 : public initSpectrometer
{
public:
initBwTekS255_256(bwTekS255_256 *Owner);
bwTekS255_256 *owner;
virtual void __fastcall Execute();
};
class bwTekS255_256 : public bwTekUSB
{
public:
bwTekS255_256(process *Owner,String name, int chan,bool connectNow,input *tempSensor,int h,int w);
typedef int _stdcall (*bwtekShutterControl)
(
int sampleShutterState,
int referenceShutterState,
int channel
);
void __fastcall loadDark(String filename)
{
if(loadSpectrum(filename,dark0))
{
storedDarkRef = filename;
firstDark = false;
}
}
void __fastcall loadLight(String filename)
{
if(loadSpectrum(filename,ref0))
{
storedLightRef = filename;
firstLight = false;
}
}
virtual int __fastcall bwtest();
int _stdcall (*bwtekSetShutters)(int,int,int);
virtual int setShutter(unsigned short state);
unsigned short refShutterState;
virtual void __fastcall loadPopup();
void __fastcall setRefShutter(unsigned short state);
virtual void __fastcall autoSetITime();
virtual void __fastcall getDarkRef();
virtual void __fastcall getLightRef();
virtual void __fastcall getSampleRef();
virtual void __fastcall getRelTrans();
virtual void __fastcall initialize();
bool firstDark;
bool firstLight;
spectrum *ref0;
spectrum *dark0;
spectrum *lastRef;
virtual void __fastcall rereference();
};
//---------------------------------------------------------------------------
#endif
i am aware that i will be lambasted for this; it was written somewhat hastily and i haven't had time to rework it.Code://---------------------------------------------------------------------------
#include "vclUtils.h"
#include "permissionSet.h"
#include "utils.h"
#include "dir.h"
#include "procMenu.h"
#include "objTasks.h"
#include "paramClasses.h"
#include "processClasses.h"
#include "spectroscopyTools.h"
#include "progForm.h"
#include "spectrum.h"
#include "appMain.h"
#include "flowPath.h"
#include "tasksAndRoutines.h"
#pragma hdrstop
#include "BWTEKUSB.h"
#pragma package(smart_init)
bwTekUSB::bwTekUSB(String name,process *Owner,int Channel,int arrSize ,int ADCTYPE,int TimingMode,bool connectNow,input *tempSensor,int h, int w) :
spectrometer(Owner,name,Channel,iTime+10,h,w,tempSensor),
iTimeOK(0),
darkOK(1),
sampleOK(2),
pixelConvOK(3)
{
get->addTask(new vvPtrTask(name+" Check reference time",&checkRef));
int *returnCode = new int();
get->addTask(new avPtrTask<int>(name+" Get Spectrum",&getSpectrum,returnCode));
get->addTask(
new compare<int>(
name+" compare return code",
returnCode,">=",new int(0),
new vvPtrTask(name+" processSpectrum",&processSpectrum),
NULL
)
);
numInitCriteria = 4;
initCriteria = new bool[numInitCriteria];
for(int i=0;i<numInitCriteria;i++)
{
initCriteria[i]=false;
}
maxY=65535;
progForm = Owner->progForm;
connected=false;
int i=0;
referenceInterval = 3600*1000*4;
nextReferenceTime = GetTickCount()+referenceInterval;
shutterWait = 1000;
saturationThreshold = 0.91552734375;
// pathnode->state = NULL;
refAvg = 10;
iTime = 30;
iTimeOffset = 500;
sampleInterval = iTime+iTimeOffset;
shutterState =0;
adcType = ADCTYPE;
timingMode = TimingMode;
initPix(arrSize);
dllPath = "BWTEKUSB.dll";
loadDLL(dllPath);
if(connectNow)
{
connect();
}
intParam *ip = new intParam((int *)&refAvg,"Spectra to average in measurement",NULL,NULL,NULL);
params->add(ip);
ip = new intParam((int *)&referenceInterval,"Time between spectral references",NULL,NULL,NULL);
params->add(ip);
ip = new intParam((int *)&iTime,"Integration Time",new String("ms"),NULL,NULL);
ip->setFunc = &setITime;
params->add(ip);
params->add(new dblParam(&saturationThreshold,"Saturation Threshold",new String("%"),NULL,NULL));
ip= new intParam(&iAddr,"Channel Number",NULL,NULL,NULL);
ip->setFunc = &setChannel;
params->add(ip);
// draw();
}
void __fastcall bwTekUSB::setConnected(bool state)
{
CONNECTED = state;
}
bool __fastcall bwTekUSB::getConnected()
{
try
{
int i=setupChannel(iAddr,NULL);
if(i<=0)
{
connect();
}
}
catch(...)
{
}
return CONNECTED;
}
void __fastcall bwTekUSB::setChannel(int chan)
{
try
{
bwClose(iAddr);
iAddr = chan;
connect();
}
catch(...)
{
}
}
double __fastcall bwTekUSB::pixelToWavelength(int pixel)
{
double wl=0;
for(int j=0;j<pixelToWavelengthCoeffs.Length;j++)
{
double x=pixelToWavelengthCoeffs[j];
wl+=x*pow((double)pixel,j);
}
return wl;
}
double __fastcall bwTekUSB::wavelengthToPixel(double wl)
{
double pixel=0;
for(int j=0;j<wavelengthToPixelCoeffs.Length;j++)
{
double x=wavelengthToPixelCoeffs[j];
pixel+=x*pow(wl,j);
}
return pixel;
}
void __fastcall bwTekUSB::getPixelConv()
{
char cd[MAXPATH];
getcwd(cd,MAXPATH);
String fname = (String)cd+"\\bwtekCurrentSettings.ini";
int result = readEeprom(fname.c_str(),iAddr);
if(result>0)
{
TIniFile *f = new TIniFile(fname);
String cname = "coefs_";
String sname = "COMMON";
if(f->SectionExists(sname))
{
pixelToWavelengthCoeffs.Length=0;
bool ok = true;
for(int i=0;i<4;i++)
{
pixelToWavelengthCoeffs.Length++;
pixelToWavelengthCoeffs[i]=f->ReadFloat(sname,cname+"a"+(String)i,NULL);
wavelengthToPixelCoeffs.Length++;
wavelengthToPixelCoeffs[i]=f->ReadFloat(sname,cname+"b"+(String)i,NULL);
ok &= (pixelToWavelengthCoeffs[i]!=NULL && wavelengthToPixelCoeffs[i]!=NULL);
}
if(!ok)
{
MessageDlg("Pixel to wavelength coefficients not found in "+fname,mtError,TMsgDlgButtons()<<mbOK,0);
}
else
{
initCriteria[pixelConvOK]=true;
}
}
else
{
MessageDlg("Section "+sname+" does not exist in "+fname,mtError,TMsgDlgButtons()<<mbOK,0);
}
delete f;
}
else
{
if(result == -1)
{
MessageDlg("Communication error with "+name,mtError,TMsgDlgButtons()<<mbOK,0);
}
if(result ==-2)
{
MessageDlg("No data in "+name+" EEPROM",mtError,TMsgDlgButtons()<<mbOK,0);
}
}
bool b = initialized;
}
void __fastcall bwTekUSB::maintMode(bool on)
{
}
void __fastcall bwTekUSB::loadPopup()
{
procObj::loadPopup();
}
void __fastcall bwTekUSB::initPix(const int size)
{
arrSize = size;
tmp = new double[size];
rawData = new unsigned short[size];
for(int i =0;i<arrSize;i++)
{
tmp[i]=0;
rawData[i]=0;
}
}
void __fastcall bwTekUSB::loadDLL(String path)
{
HINSTANCE HInst=LoadLibrary(path.c_str());
if( HInst>0 )
{
readEeprom = (bwtekReadEEPROMUSB)GetProcAddress(HInst,"bwtekReadEEPROMUSB");
setupChannel=(bwtekSetupChannel)GetProcAddress(HInst,"bwtekSetupChannel");
bwTest=(bwtekTestUSB)GetProcAddress(HInst,"bwtekTestUSB");
bwSetTime=(bwtekSetTimeUSB) GetProcAddress(HInst,"bwtekSetTimeUSB");
bwReadData=(bwtekDataReadUSB)GetProcAddress(HInst,"bwtekDataReadUSB");
bwClose=(bwtekCloseUSB)GetProcAddress(HInst,"bwtekCloseUSB");
bwReadAvgResult=(bwtekReadResultUSB)GetProcAddress(HInst,"bwtekReadResultUSB");
bwPolyFit = (bwtekPolyFit)GetProcAddress(HInst,"bwtekPolyFit");
bwPolyCalc = (bwtekPolyCalc)GetProcAddress(HInst,"bwtekPolyCalc");
bwGetStatus = (bwtekGetExtStatus)GetProcAddress(HInst,"bwtekGetExtStatus");
bwSetExtLaser = (bwtekSetExtLaser)GetProcAddress(HInst,"bwtekSetExtLaser");
bwSetExtShutter = (bwtekSetExtShutter)GetProcAddress(HInst,"bwtekSetExtShutter");
bwSetExtSync = (bwtekSetExtSync)GetProcAddress(HInst,"bwtekSetExtSync");
bwGatedMode = (bwtekGatedMode)GetProcAddress(HInst,"bwtekGatedMode");
bwSetPulse = (bwtekSetExtPulse)GetProcAddress(HInst,"bwtekSetExtPulse");
closeShutter = (bwtekShutterOpen)GetProcAddress(HInst,"bwtekShutterOpen");
openShutter = (bwtekShutterClose)GetProcAddress(HInst,"bwtekShutterClose");
dllPath = path;
}
else
{
TFileOpen *o = new TFileOpen(owner);
o->Caption = "Please Locate File bwtekusb.dll";
o->Dialog->Filter ="Dynamically Linked Library (bwtekusb.dll)|BWTEKUSB.DLL";
o->Dialog->Title = "Please Locate File bwtekusb.dll";
open:
if(o->Dialog->Execute())
{
loadDLL(o->Dialog->FileName);
}
else
{
goto open;
}
delete o;
}
}
int bwTekUSB::setShutter(unsigned short state)
{
int i=0;
while(shutterState!=state && i<100)
{
if(state>0)
{
shutterState=openShutter(iAddr);
}
else
{
shutterState=closeShutter(iAddr);
shutterState^=1;
}
}
if(i==100&&shutterState!=state)
{
shutterState=-1;
}
return shutterState;
}
int __fastcall bwTekUSB::avgSpec(spectrum *s, int points)
{
if(connected)
{
for(int i =0;i<arrSize;i++)
{
tmp[i]=0;
}
for(int i= 0;i<points;i++)
{
bwReadData(0,rawData,iAddr);
for(int j=0;j<arrSize;j++)
{
tmp[j] = (double)(tmp[j]*i+rawData[j])/(double)(i+1);
}
}
unsigned short ti;
for(int i =0;i<arrSize;i++)
{
s->data[i] = (double)tmp[i]/maxY;
}
}
}
void __fastcall bwTekUSB::getDarkRef()
{
if(connected)
{
setShutter(0);
int then=GetTickCount()+shutterWait;
while(GetTickCount()<then){};
avgSpec(darkRef,refAvg);
logReference(darkRef);
setShutter(1);
}
}
void __fastcall bwTekUSB::getSampleRef()
{
if(connected)
{
setShutter(1);
avgSpec(sampleRef,refAvg);
logReference(sampleRef);
}
}
spectrum *__fastcall spectrometer::getRelAbs()
{
for(int i=0;i<arrSize;i++)
{
if(sample->data[i]==0)
{
relAbs->data[i]=0;
}
else
{
if(relTrans->data[i]==0)
{
relAbs->data[i]=65535;
}
else
{
try
{
relAbs->data[i]=-log10(relTrans->data[i]);
}
catch(...)
{
relAbs->data[i]=0;
}
}
}
}
return relAbs;
}
int __fastcall bwTekUSB::setExtShutter(int state)
{
if(connected)
{
return bwSetExtShutter(state,iAddr);
}
}
void __fastcall bwTekUSB::setITime(int ITime)
{
if(connected)
{
int result =bwSetTime(ITime,iAddr);
if(result==ITime)
{
iTime = ITime;
}
}
}
int __fastcall bwTekUSB::bwtest()
{
int returnCode = bwTest(timingMode,arrSize,adcType,iAddr,NULL);
if(returnCode>=0)
{
setShutter(shutterState);
}
return returnCode;
}
int __fastcall bwTekUSB::connect()
{
int returnCode = bwtest();
// int returnCode = -1;
if(returnCode>=0)
{
connected = true;
}
else
{
connected = false;
}
return CONNECTED;
}
int __fastcall bwTekUSB::getSpectrum()
{
if(connected)
{
try
{
if(this->shutterState!=1)
{
setShutter(1);
}
int returnCode = bwReadData(0,rawData,iAddr);
if(returnCode>=0)
{
for(int i =0;i<arrSize;i++)
{
sample->data[i]=(double)rawData[i]/65535;
}
}
return returnCode;
}
catch(...){}
}
}
void __fastcall bwTekUSB::checkRef()
{
if(GetTickCount()>=nextReferenceTime)
{
rereference();
nextReferenceTime = GetTickCount()+referenceInterval;
}
}
void __fastcall bwTekUSB::processSpectrum()
{
(*measNo)++;
getRelTrans();
getRelAbs();
if(onScan!=NULL)
{
onScan();
}
nextSampleTime=GetTickCount()+sampleInterval;
}
void __fastcall bwTekUSB::scanOnTimer(TObject *Sender)
{
getState();
}
void __fastcall bwTekUSB::getRelTrans()
{
for(int i =0;i<arrSize;i++)
{
if(darkRef->data[i]>=sample->data[i]||darkRef->data[i]>=sampleRef->data[i])
{
relTrans->data[i]=0;
}
else
{
float f =((sample->data[i]-darkRef->data[i]))/((sampleRef->data[i]-darkRef->data[i]));
if(f<1)
{
relTrans->data[i]=f;
}
else
{
relTrans->data[i]=1;
}
}
}
}
void __fastcall bwTekUSB::autoSetITime()
{
if(connected)
{
if(shutterState<1)
{
setShutter(1);
}
double tmax = saturationThreshold;
double imax =0;
int tm=tmax*100;
int im=imax*100;
int di = 0;
while(im!=tm)
{
di=0;
setITime(iTime);
avgSpec(sample,refAvg);
for(int i =0;i<arrSize-1;i++)
{
if(imax<sample->data[i])
{
imax = sample->data[i];
}
}
if(imax>tmax)
{
di =-1;
}
if(imax<tmax)
{
di = 1;
}
iTime+=di;
im=imax*100;
}
setITime(iTime);
sampleInterval = iTime+iTimeOffset;
initCriteria[iTimeOK]=true;
bool b = initialized;
}
}
void __fastcall bwTekUSB::initialize()
{
if(connected)
{
getPixelConv();
autoSetITime();
getDarkRef();
getSampleRef();
getState();
nextReferenceTime = GetTickCount()+referenceInterval;
bool b = initialized;
}
}
void __fastcall bwTekUSB::rereference()
{
getDarkRef();
}
void __fastcall bwTekUSB::refreshIcon()
{
int xo = (Width-128)/2;
icon->Canvas->FillRect(TRect(xo,Height/4,Width-xo,Height-4));
icon->Canvas->Pen->Color = clMedGray;
icon->Canvas->MoveTo(xo,Height-3);
icon->Canvas->LineTo(xo,Height/4);
icon->Canvas->LineTo(Width-xo,Height/4);
icon->Canvas->MoveTo(4,Height-3);
icon->Canvas->Pen->Color = 0x00FF0000;
int r = arrSize/128;
int h= 3*Height/4;
for(int i=0;i<128;i++)
{
int v1 = this->rawData[r*i]*h/maxY;
icon->Canvas->LineTo(i+xo+1,Height-4-v1);
}
pathnode->draw();
}
bwTekS255_256::bwTekS255_256(process *Owner,String name, int chan,bool connectNow,input *tempSensor,int h,int w) : bwTekUSB(name,Owner,chan,256,14,3,connectNow,tempSensor,h,w)
{
params->editable = false;
firstLight = true;
firstDark = true;
fileParam *fp = new fileParam(&storedSampleRef,"Sample Reference File");
fp->setFunc = &loadSample;
params->add(fp);
internalPerms->onLogin->addTask(new setVar<bool>("Set Sample Reference File Parameter Editable",¶ms->editable,new bool(true)));
internalPerms->onLogout->addTask(new setVar<bool>("Set Sample Reference File Parameter Editable",¶ms->editable,new bool(false)));
fp = new fileParam(&storedDarkRef,"Dark Reference File");
fp->setFunc = &loadDark;
params->add(fp);
fp = new fileParam(&storedLightRef,"Light Reference File");
fp->setFunc = &loadLight;
params->add(fp);
HINSTANCE HInst=LoadLibrary(dllPath.c_str());
if( HInst>0 )
{
bwtekSetShutters=(bwtekShutterControl)GetProcAddress(HInst,"bwtekShutterControl");
}
refShutterState = 0;
ref0=new spectrum(this,arrSize,"Original Reference Channel Spectrum");
dark0=new spectrum(this,arrSize,"Original Dark Reference Spectrum");
lastRef = new spectrum(this,arrSize,"Current Reference Channel Spectrum");
spectroscopyTool = new spectroscopySuite(owner->owner,name+" Tools",this);
MainForm->addProcess(spectroscopyTool);
internalPerms->onLogin->addTask(new twoArgPtrTask<void,TTabSheet *,bool>("Set Spectroscopy Tab Visible",&setVisible,spectroscopyTool->tab,true));
internalPerms->onLogout->addTask(new twoArgPtrTask<void,TTabSheet *,bool>("Set Spectroscopy Tab Visible",&setVisible,spectroscopyTool->tab,false));
internalPerms->onLogin->addTask(new twoArgPtrTask<void,TMenuItem *,bool>("Set Spectroscopy Tab Visible",&setVisible,spectroscopyTool->procMainMenu,true));
internalPerms->onLogout->addTask(new twoArgPtrTask<void,TMenuItem *,bool>("Set Spectroscopy Tab Visible",&setVisible,spectroscopyTool->procMainMenu,false));
internalPerms->onLogout->addTask(new twoArgPtrTask<void,TTimer *,bool>("Set Spectroscopy Tab Visible",&setEnabled,((TspectroscopyTool *)spectroscopyTool->PnID)->timer,false));
spectroscopyTool->tab->TabVisible = false;
spectroscopyTool->procMainMenu->Visible = false;
initSpectrometer = new initBwTekS255_256(this);
}
int bwTekS255_256::setShutter(unsigned short state)
{
if(connected)
{
try
{
if(bwtekSetShutters(state,-1,iAddr))
{
shutterState = state;
}
}
catch(...)
{
}
}
}
void __fastcall bwTekS255_256::setRefShutter(unsigned short state)
{
if(connected)
{
try
{
if(bwtekSetShutters(-1,state,iAddr))
{
refShutterState =state;
}
}
catch(...)
{
}
}
}
void __fastcall bwTekS255_256::autoSetITime()
{
if(connected)
{
setShutter(0);
setRefShutter(1);
double tmax = saturationThreshold;
double imax =0;
int di = 0;
double lastErr =tmax+1;
double err=tmax;
while(lastErr>=err&&imax!=tmax)
{
imax=0;
di=0;
lastErr = err;
setITime(iTime);
avgSpec(sample,refAvg);
for(int i =0;i<arrSize-1;i++)
{
if(imax<sample->data[i])
{
imax = sample->data[i];
}
}
if(imax>tmax)
{
di =-1;
}
if(imax<tmax)
{
di = 1;
}
err =fabs(tmax-imax);
if(err>lastErr)
{
di-=2*di;
}
if(imax==tmax)
{
di=0;
}
iTime+=di;
}
setITime(iTime);
sampleInterval = iTime+iTimeOffset;
initCriteria[iTimeOK]=true;
bool b = initialized;
}
}
void __fastcall bwTekS255_256::getLightRef()
{
if(connected)
{
setShutter(0);
setRefShutter(1);
int then=GetTickCount()+shutterWait;
while(GetTickCount()<then){}
avgSpec(lastRef,refAvg);
logReference(lastRef);
setRefShutter(0);
setShutter(1);
bool b = initialized;
if(firstLight)
{
firstLight = false;
for(int i=0;i<arrSize;i++)
{
ref0->data[i]=lastRef->data[i];
}
}
}
}
void __fastcall bwTekS255_256::getDarkRef()
{
if(connected)
{
setShutter(0);
setRefShutter(0);
int then=GetTickCount()+shutterWait;
while(GetTickCount()<then){}
avgSpec(darkRef,refAvg);
logReference(darkRef);
initCriteria[darkOK]=true;
setRefShutter(0);
setShutter(1);
bool b = initialized;
if(firstDark)
{
firstDark = false;
for(int i=0;i<arrSize;i++)
{
dark0->data[i]=darkRef->data[i];
}
}
}
}
void __fastcall bwTekS255_256::getSampleRef()
{
if(connected)
{
setShutter(1);
setRefShutter(0);
int then=GetTickCount()+shutterWait;
while(GetTickCount()<then){};
avgSpec(sampleRef,refAvg);
logReference(sampleRef);
setRefShutter(0);
setShutter(1);
initCriteria[sampleOK]=true;
bool b = initialized;
}
}
void __fastcall bwTekS255_256::initialize()
{
if(connected)
{
initSpectrometer->Resume();
}
}
void __fastcall bwTekS255_256::getRelTrans()
{
for(int i =0;i<arrSize;i++)
{
if(darkRef->data[i]>=sample->data[i]||darkRef->data[i]>=sampleRef->data[i]||darkRef->data[i]>=lastRef->data[i]||dark0->data[i]>=ref0->data[i])
{
relTrans->data[i]=0;
}
else
{
float f =((sample->data[i]-darkRef->data[i]))/((sampleRef->data[i]-dark0->data[i]))*((lastRef->data[i]-darkRef->data[i])/(ref0->data[i]-dark0->data[i]));
relTrans->data[i]=f;
}
}
}
void __fastcall bwTekS255_256::loadPopup()
{
bwTekUSB::loadPopup();
}
void __fastcall bwTekS255_256::rereference()
{
if(connected)
{
getDarkRef();
getLightRef();
}
}
int __fastcall bwTekS255_256::bwtest()
{
try
{
int returnCode = bwTest(timingMode,arrSize,adcType,iAddr,NULL);
if(returnCode>=0)
{
setShutter(shutterState);
setRefShutter(refShutterState);
}
return returnCode;
}
catch(...)
{
}
}
initBwTekS255_256::initBwTekS255_256(bwTekS255_256 *Owner) : initSpectrometer(Owner)
{
owner = Owner;
}
void __fastcall initBwTekS255_256::Execute()
{
while(!Terminated)
{
owner->progForm->progBar->POS=0;
owner->progForm->progBar->min=0;
owner->progForm->progBar->max = 5;
owner->progForm->labelCaption="Reading EEPROM";
Synchronize(owner->progForm->updateLabelCaption);
Synchronize(owner->getPixelConv);
owner->progForm->progBar->POS++;
Synchronize(owner->progForm->progBar->Paint);
owner->progForm->labelCaption="Detecting integration time...";
Synchronize(owner->progForm->updateLabelCaption);
Synchronize(owner->autoSetITime);
owner->progForm->progBar->POS++;
owner->progForm->labelCaption="Getting dark reference...";
Synchronize(owner->progForm->progBar->Paint);
Synchronize(owner->progForm->updateLabelCaption);
Synchronize(owner->getDarkRef);
owner->progForm->labelCaption="Getting light reference...";
Synchronize(owner->progForm->updateLabelCaption);
owner->progForm->progBar->POS++;
Synchronize(owner->progForm->progBar->Paint);
Synchronize(owner->getLightRef);
owner->progForm->labelCaption="Getting water background...";
Synchronize(owner->progForm->updateLabelCaption);
owner->progForm->progBar->POS++;
Synchronize(owner->progForm->progBar->Paint);
Synchronize(owner->getSampleRef);
owner->progForm->progBar->POS++;
Synchronize(owner->progForm->progBar->Paint);
owner->progForm->labelCaption="Finishing initialization";
Synchronize(owner->progForm->updateLabelCaption);
Synchronize(owner->getState);
for(int i=0;i<owner->arrSize;i++)
{
owner->ref0->data[i]=owner->lastRef->data[i];
owner->dark0->data[i]=owner->darkRef->data[i];
}
owner->nextReferenceTime = GetTickCount()+owner->referenceInterval;
owner->progForm->close();
Suspend();
}
}
//---------------------------------------------------------------------------
the derived object i'm using is S255_256
Code://---------------------------------------------------------------------------
#ifndef spectrometersH
#define spectrometersH
#include "filters.h"
#include "procObj.h"
#include "objIcon.h"
#include "input.h"
#include "classDefs.h"
#include "tasksAndRoutines.h"
#include <valarray.h>
#include <Classes.hpp>
//---------------------------------------------------------------------------
class spectrometer;
class spectrum;
class spectrometerIcon : public objIcon
{
public:
spectrometerIcon(spectrometer *owner,int h,int w);
spectrometer *owner;
void __fastcall initConns(bool b);
virtual void __fastcall draw();
};
class initSpectrometer : public routine
{
public:
initSpectrometer(spectrometer *Owner);
spectrometer *owner;
virtual void __fastcall Execute();
};
class spectrometer : public input
{
protected:
public:
spectroscopySuite *spectroscopyTool;
virtual int __fastcall connect()=0;
spectrometer(process *owner,String name,int addr,int samplingInterval,int h,int w,input *tempSensor);
input *tempSensor;
void __fastcall (__closure *onScan)();
virtual void __fastcall initSpectra();
void __fastcall makeIcon(int h,int w);
String storedSampleRef;
String storedDarkRef;
String storedLightRef;
virtual void __fastcall loadSample(String filename)
{
if(loadSpectrum(filename,sampleRef))
{
storedSampleRef = filename;
}
}
bool INITED;
virtual void __fastcall getPixelConv(){};
bool __fastcall loadSpectrum(String filename,spectrum *s);
bool __fastcall loadSpectrumFromString(String input,spectrum *s);
spectrum *__fastcall getRelAbs();
spectrum *relTrans;
spectrum *relAbs;
spectrum *darkRef;
spectrum *sample;
spectrum *sampleRef;
const unsigned int ARRSIZE;
unsigned short refAvg;
unsigned short sampleAvg;
virtual void __fastcall setArrSize(const unsigned int size);
__property unsigned int arrSize={read=ARRSIZE,write=setArrSize};
unsigned short iTime;
virtual void __fastcall getDarkRef()=0;
virtual void __fastcall getSampleRef()=0;
virtual int __fastcall avgSpec(spectrum *s, int points)=0;
virtual double __fastcall pixelToWavelength(int pixel)=0;
virtual double __fastcall wavelengthToPixel(double wl)=0;
double saturationThreshold;
DynamicArray<spectrum *>spectra;
unsigned int nextReferenceTime;
unsigned int referenceInterval;
virtual void __fastcall rereference()
{
getDarkRef();
}
String refFileName;
void __fastcall logReference(spectrum *ref);
double maxY;
virtual void __fastcall setConnected(bool state)=0;
virtual bool __fastcall getConnected()=0;
void __fastcall (__closure*setInited)(bool);
__property bool initialized={read=getInited};
virtual void __fastcall initialize()=0;
routine *initSpectrometer;
virtual int __fastcall getSpectrum()=0;
//
// virtual void __fastcall getState();
bool CONNECTED;
__property bool connected={read=getConnected,write=setConnected};
TprogressForm *progForm;
virtual void __fastcall makeNodes(TTreeNode *parent){}
bool *initCriteria;
unsigned int numInitCriteria;
virtual bool __fastcall getInited()
{
if(!INITED)
{
bool result=true;
int i=-1;
while(++i<numInitCriteria && result)
{
result &=initCriteria[i];
}
INITED = result;
if(setInited!=NULL)
{
setInited(result);
}
}
return INITED;
}
};
#endif
Code://---------------------------------------------------------------------------
#include "objConn.h"
#include "utils.h"
#include "dir.h"
#include "procMenu.h"
#include "objTasks.h"
#include "paramClasses.h"
#include "processClasses.h"
#include "spectroscopyTools.h"
#include "progForm.h"
#include "appMain.h"
#include "spectrum.h"
#include "flowPath.h"
#pragma hdrstop
#pragma package(smart_init)
#include "spectrometers.h"
initSpectrometer::initSpectrometer(spectrometer *Owner) : routine("Initialize "+Owner->name,Owner->owner)
{
owner = Owner;
}
void __fastcall initSpectrometer::Execute()
{
while(!Terminated)
{
owner->getDarkRef();
owner->getSampleRef();
}
}
bool __fastcall spectrometer::loadSpectrum(String fname,spectrum *s)
{
double test;
char l[65536];
FILE *f = fopen(fname.c_str(),"r");
DynamicArray<String>line;
bool ok = true;
while(fgets(l,65536,f)&&ok)
{
line = explode((String)l,",");
for(int i =0;i<line.Length;i++)
{
String str =Trim(line[i]);
if(!TryStrToFloat(str,test))
{
MessageDlg("Invalid Data Format",mtError,TMsgDlgButtons()<<mbOK,0);
ok=false;
i=line.Length;
}
}
}
fclose(f);
if(ok)
{
f = fopen(fname.c_str(),"r");
DynamicArray<String>line;
int d=0;
while(fgets(l,999999,f)&&ok&&d<arrSize)
{
line = explode((String)l,",");
for(int i =0;i<line.Length;i++)
{
double val;
String str =Trim(line[i]);
if(!TryStrToFloat(Trim(line[i]),val))
{
MessageDlg("Invalid Data Format",mtError,TMsgDlgButtons()<<mbOK,0);
ok=false;
i=line.Length;
}
else
{
s->data[d] = val;
}
d++;
}
}
}
return ok;
}
bool __fastcall spectrometer::loadSpectrumFromString(String input,spectrum *s)
{
double test;
bool ok;
int d =0;
DynamicArray<String>line;
line = explode((String)input,",");
if(line.Length!=arrSize)
{
MessageDlg("Array length mismatch - cannot load spectrum for "+s->title,mtError,TMsgDlgButtons()<<mbOK,0);
return false;
}
for(int i =0;i<line.Length;i++)
{
double val;
String str =Trim(line[i]);
if(!TryStrToFloat(Trim(line[i]),val))
{
MessageDlg("Invalid Data Format",mtError,TMsgDlgButtons()<<mbOK,0);
ok=false;
i=line.Length;
}
else
{
s->data[d] = val;
}
d++;
}
return ok;
}
spectrometer::spectrometer(process *owner,String name,int addr,int samplingInterval,int h,int w,input *TempSensor): input(owner,name,addr,samplingInterval),
INITED(false),
onScan(NULL),
numInitCriteria(0),
tempSensor(TempSensor)
{
arrSize=1;
relTrans= new spectrum(this,arrSize,"Relative Transmission");
relAbs= new spectrum(this,arrSize,"Relative Absorbance");
sample= new spectrum(this,arrSize,"Current Spectrum");
darkRef= new spectrum(this,arrSize,"Dark Reference");
sampleRef= new spectrum(this,arrSize,"Sample Reference");
CONNECTED=false;
refFileName = name+"\ References.csv";
initSpectra();
if((h+w)>0)
{
makeIcon(h,w);
owner->syncUpdateDisplays(this);
}
}
void __fastcall spectrometer::makeIcon(int h,int w)
{
icon=new spectrometerIcon(this,h,w);
loadPopup();
draw();
}
void __fastcall spectrometer::logReference(spectrum *ref)
{
String timeString;
DateTimeToString(timeString,"yyyy-mm-dd hh:nn:ss.zz",Now());
writeToFile(refFileName,ref->title+" "+timeString+"\n","a+");
writeToFile(refFileName,ref->asString()+"\n","a+");
}
/*
void __fastcall spectrometer::getState()
{
if(CONNECTED)
{
getSpectrum();
}
}
*/
void __fastcall spectrometer::setArrSize(const unsigned int size)
{
if(size!=ARRSIZE)
{
*(int *)&ARRSIZE=size;
initSpectra();
}
}
void __fastcall spectrometer::initSpectra()
{
for(int i=0;i<spectra.Length;++i)
{
spectra[i]->size=arrSize;
delete[] spectra[i]->data;
spectra[i]->data=new double[arrSize];
spectra[i]->fill(0);
}
}
spectrometerIcon::spectrometerIcon(spectrometer *Owner,int h,int w) : objIcon(Owner,h,w)
{
owner = Owner;
initConns(NULL);
}
void __fastcall spectrometerIcon::initConns(bool b)
{
conns.Length = 4;
conns[0]=new objConn(owner,Width/2,0);
conns[1]=new objConn(owner,Width,Height/2);
conns[2]=new objConn(owner,Width/2,Height);
conns[3]=new objConn(owner,0,Height/2);
}
void __fastcall spectrometerIcon::draw()
{
clear();
int th = Canvas->TextHeight(owner->name);
int tw = Canvas->TextWidth(owner->name);
int titleheight=0,specheight=0,border=2,specWidth=Width-2*border;
int tpos = (Width-tw)/border;
if(Height/4>2*border+th)
{
titleheight=2*border+th;
specheight=Height-titleheight-2*border;
}
Canvas->Brush->Color = clSilver;
Canvas->FillRect(TRect(0,0,Width,Height));
Canvas->Pen->Color = 0x00FFFFFF;
Canvas->MoveTo(0,Height);
Canvas->LineTo(0,0);
Canvas->LineTo(Width-1,0);
Canvas->Pen->Color = clDkGray;
Canvas->LineTo(Width-1,Height-1);
Canvas->LineTo(0,Height-1);
Canvas->Pen->Color = clMedGray;
Canvas->MoveTo(3,Height-border);
Canvas->LineTo(Width-border,Height-border);
Canvas->LineTo(Width-border,1);
Canvas->Brush->Color = 0x00FFFFFF;
Canvas->RoundRect(tpos-8,border,tpos+tw+8,titleheight-border,8,8);
Canvas->Brush->Style = bsClear;
Canvas->TextOut(tpos,(titleheight-th)/border,owner->name);
Canvas->Brush->Style = bsSolid;
int xo = 2*border;
Canvas->FillRect(TRect(xo,titleheight,Width-xo,Height-4));
Canvas->Pen->Color = clMedGray;
Canvas->MoveTo(xo,Height-3);
Canvas->LineTo(xo,titleheight);
Canvas->LineTo(Width-xo,titleheight);
if(owner->CONNECTED)
{
int r = owner->arrSize/specWidth;
int h= specheight-4;
Canvas->MoveTo(4,Height-3);
Canvas->Pen->Color = 0x00FF0000;
for(int i=0;i<specWidth;i++)
{
int v1 = owner->sample->data[(int)r*i]*h;
Canvas->LineTo(i+xo+1,Height-4-v1);
}
}
else
{
TColor color = Canvas->Font->Color;
Canvas->Font->Color=0x000000DF;
Canvas->Font->Style = TFontStyles()<< fsBold;
String msg = "NOT CONNECTED";
int tw = Canvas->TextWidth(msg);
int th = Canvas->TextHeight(msg);
Canvas->TextOut(xo+(Width-border*xo-tw)/2,(specheight-1+th)/2,msg);
Canvas->Font->Color=color;
Canvas->Font->Style = TFontStyles();
}
}
Code://---------------------------------------------------------------------------
#ifndef BWTEKUSBH
#define BWTEKUSBH
#include "spectrometers.h"
class bwTekUSB : public spectrometer
{
protected:
String dllPath;
public:
virtual int __fastcall bwtest();
virtual double __fastcall pixelToWavelength(int pixel);
virtual double __fastcall wavelengthToPixel(double wl);
virtual int __fastcall avgSpec(spectrum *s, int points);
typedef int _stdcall (*bwtekSetupChannel)(int channelNumber,int unknown);
virtual void __fastcall getPixelConv();
DynamicArray<double>pixelToWavelengthCoeffs;
DynamicArray<double>wavelengthToPixelCoeffs;
typedef int _stdcall (*bwtekTestUSB)
(
int nUSBTiming, // USB Interface timing option
int nPixelNo, // number of pixels of a detector to be readout
int nInputMode, // signal conditioning stage gain value
int nChannel, // channel to get data from
int pParam // extra setting parameters only for RS232
);
typedef long _stdcall (*bwtekSetTimeUSB)
(
long lTime, // integration time setting
int nChannel // channel to get data from
);
typedef int _stdcall (*bwtekDataReadUSB)
(
int nTriggerMode, // Base address for plug-in data acquisition board
unsigned short *pArray, // data value array from the read operation stored
int nChannel // channel to get data from
);
typedef int _stdcall (*bwtekReadResultUSB)
(
int nTriggerMode, // setting for trigger mode
int nAverage, // number of scans to be averaged
int nTypeSmoothing, // setting for smoothing type
int nValueSmoothing, // setting for smoothing parameter
unsigned short *pArray, // an array memory space for scan data
int nChannel=0 // setting for channel number
);
typedef int _stdcall (*bwtekCloseUSB)
(
int nchannel // channel to get data from
);
typedef int _stdcall (*bwtekReadEEPROMUSB)
(
char *OutFileName, // The filename in which data from EEPROM would be saved
int nChannel=0 // channel number to get data from
);
typedef int _stdcall (*bwtekSetTimingsUSB)
(
long lTriggerExit, // Setting external trigger timeout
int nMultiple, // A multifly factor for long integration time
int nChannel=0 //channel number to get data from
);
typedef int __stdcall (* bwtekPolyFit)
(
double *x, // Array of independent variables
double *y, // Array of dependent variables
int const numPts, // Number of points in independent and dependent arrays
double *coefs, // Pointer to array containing calculated coeffi cients [index from 0 to order]
int const order // Desired order of polynomial fi t
);
typedef void _stdcall (*bwtekPolyCalc)
(
double *coefs,
int const order,
int const x,
double *y
);
typedef int _stdcall (*bwtekGetExtStatus)
(
int nchannel //channel to get data from
);
typedef int _stdcall (*bwtekSetExtLaser)
(
int nOnOff, //switch for On/Off
int nchannel //channel to get data from
);
typedef int _stdcall (*bwtekSetExtShutter)
(
int nOnOff, // switch for On/Off
int nchannel // channel to get data from
);
typedef int _stdcall (*bwtekSetExtSync)
(
int nOnOff, //switch for On/Off
int nchannel //channel to get data from
);
typedef int _stdcall (*bwtekGatedMode)
(
int nGatedTime, // Gated Time between an External trigger and a CCD trigger
int nchannel // channel to get data from
);
typedef int _stdcall (*bwtekSetExtPulse)
(
int nOnOff, // switch to turn on or off pulse train
int nDelayTime, // delay time between the CCD trigger and the fi rst pulse
int nHigh, // time duration for high pulse width
int nLow, // time duration for low pulse width
int nPulse, // number of pulses to be generated
int nInverse, // pulse output will be inverted
int nChannel // channel to get data from
);
virtual void __fastcall rereference();
virtual void __fastcall maintMode(bool on);
virtual void __fastcall loadPopup();
typedef int _stdcall (*bwtekShutterOpen)(int);
// enum initializationCriteria{iTimeOK=1,darkOK=2,sampleOK=4,pixelConv=8,OK=15}inited;
const unsigned int iTimeOK;
const unsigned int darkOK;
const unsigned int sampleOK;
const unsigned int pixelConvOK;
void __fastcall processSpectrum();
void __fastcall checkRef();
typedef int _stdcall (*bwtekShutterClose)(int);
unsigned int iTimeOffset;
virtual void __fastcall initialize();
virtual void __fastcall autoSetITime();
virtual void __fastcall getRelTrans();
virtual int __fastcall getSpectrum();
int __fastcall connect();
void __fastcall setITime(int ITime);
int __fastcall setExtShutter(int state);
virtual void __fastcall getSampleRef();
virtual void __fastcall getDarkRef();
virtual int setShutter(unsigned short state);
void __fastcall loadDLL(String path);
void __fastcall initPix(const int size);
bwTekUSB(String name,process *Owner,int Channel,int arrSize ,int ADCTYPE,int TimingMode,bool connectNow,input *tempSensor,int h,int w);
int _stdcall (*bwTest)
(
int nUSBTiming, // USB Interface timing option
int nPixelNo, // number of pixels of a detector to be readout
int nInputMode, // signal conditioning stage gain value
int nChannel, // channel to get data from
int pParam // extra setting parameters only for RS232
);
int _stdcall (*readEeprom)
(
char *OutFileName, // The filename in which data from EEPROM would be saved
int nChannel=0 // channel number to get data from
);
int _stdcall (*setupChannel)(int channel,int unknown);
int _stdcall (*openShutter)(int);
int _stdcall (*closeShutter)(int);
long _stdcall (*bwSetTime)
(
long lTime, // integration time setting
int nChannel // channel to get data from
);
int _stdcall (*bwReadData)
(
int nTriggerMode, // Base address for plug-in data acquisition board
unsigned short *pArray, // data value array from the read operation stored
int nChannel // channel to get data from
);
int _stdcall (*bwClose)
(
int nchannel // channel to get data from
);
int _stdcall (*bwReadAvgResult)
(
int nTriggerMode, // setting for trigger mode
int nAverage, // number of scans to be averaged
int nTypeSmoothing, // setting for smoothing type
int nValueSmoothing, // setting for smoothing parameter
unsigned short *pArray, // an array memory space for scan data
int nChannel=0 // setting for channel number
);
int _stdcall (*bwReadEEPROM)
(
char *OutFileName, // The filename in which data from EEPROM would be saved
int nChannel=0 // channel number to get data from
);
int _stdcall (*bwSetTiming)
(
long lTriggerExit, // Setting external trigger timeout
int nMultiple, // A multifly factor for long integration time
int nChannel=0 //channel number to get data from
);
int _stdcall (*bwPolyFit)
(
double *x, // Array of independent variables
double *y, // Array of dependent variables
int const numPts, // Number of points in independent and dependent arrays
double *coefs, // Pointer to array containing calculated coeffi cients [index from 0 to order]
int const order // Desired order of polynomial fi t
);
void _stdcall (*bwPolyCalc)
(
double *coefs,
int const order,
int const x,
double *y
);
int _stdcall (*bwGetStatus)
(
int nchannel //channel to get data from
);
int _stdcall (*bwSetExtLaser)
(
int nOnOff, //switch for On/Off
int nchannel //channel to get data from
);
int _stdcall (*bwSetExtShutter)
(
int nOnOff, // switch for On/Off
int nchannel // channel to get data from
);
int _stdcall (*bwSetExtSync)
(
int nOnOff, //switch for On/Off
int nchannel //channel to get data from
);
int _stdcall (*bwGatedMode)
(
int nGatedTime, // Gated Time between an External trigger and a CCD trigger
int nchannel // channel to get data from
);
int _stdcall (*bwSetPulse)
(
int nOnOff, // switch to turn on or off pulse train
int nDelayTime, // delay time between the CCD trigger and the fi rst pulse
int nHigh, // time duration for high pulse width
int nLow, // time duration for low pulse width
int nPulse, // number of pulses to be generated
int nInverse, // pulse output will be inverted
int nChannel // channel to get data from
);
void __fastcall scanOnTimer(TObject *Sender);
unsigned short shutterState;
unsigned short timingMode;
unsigned short adcType;
double *tmp;
unsigned short *rawData;
double maxY;
void __fastcall setChannel(int chan);
virtual bool __fastcall getInited()
{
if(!INITED)
{
bool result=true;
int i=0;
while(i<numInitCriteria && result)
{
result &=initCriteria[i];
i++;
}
INITED = result;
if(setInited!=NULL)
{
setInited(result);
}
}
return INITED;
}
void __fastcall (__closure*setInited)(bool);
__property bool initialized={read=getInited};
virtual void __fastcall setConnected(bool state);
virtual bool __fastcall getConnected();
__property bool connected={read=getConnected,write=setConnected};
unsigned short shutterWait;
void __fastcall refreshIcon();
};
//---------------------------------------------------------------------------
class bwTek261E_512 : public bwTekUSB
{
public:
bwTek261E_512(String name,process *Owner,int chan,bool connectNow,input *tempSensor,int h, int w):bwTekUSB(name,Owner,chan,512,13,3,connectNow,tempSensor,h,w)
{
HINSTANCE HInst=LoadLibrary("BWTEKUSB.dll");
if( HInst>0 )
{
getMode=(bwtekGetInGaAsMode)GetProcAddress(HInst,"bwtekGetInGaAsMode");
setMode=(bwtekSetInGaAsMode) GetProcAddress(HInst,"bwtekSetInGaAsMode");
}
}
typedef int _stdcall (*bwtekGetInGaAsMode)
(
int *nMode, // select detector mode
int nChannel // channel to get data from
);
typedef int _stdcall (*bwtekSetInGaAsMode)
(
int nMode, // select feedback capacitor mode
int nChannel // channel to get data from
);
int _stdcall (*getMode)
(
int *nMode, // select detector mode
int nChannel // channel to get data from
);
int _stdcall (*setMode)
(
int nMode, // select feedback capacitor mode
int nChannel // channel to get data from
);
};
class initBwTekS255_256 : public initSpectrometer
{
public:
initBwTekS255_256(bwTekS255_256 *Owner);
bwTekS255_256 *owner;
virtual void __fastcall Execute();
};
class bwTekS255_256 : public bwTekUSB
{
public:
bwTekS255_256(process *Owner,String name, int chan,bool connectNow,input *tempSensor,int h,int w);
typedef int _stdcall (*bwtekShutterControl)
(
int sampleShutterState,
int referenceShutterState,
int channel
);
void __fastcall loadDark(String filename)
{
if(loadSpectrum(filename,dark0))
{
storedDarkRef = filename;
firstDark = false;
}
}
void __fastcall loadLight(String filename)
{
if(loadSpectrum(filename,ref0))
{
storedLightRef = filename;
firstLight = false;
}
}
virtual int __fastcall bwtest();
int _stdcall (*bwtekSetShutters)(int,int,int);
virtual int setShutter(unsigned short state);
unsigned short refShutterState;
virtual void __fastcall loadPopup();
void __fastcall setRefShutter(unsigned short state);
virtual void __fastcall autoSetITime();
virtual void __fastcall getDarkRef();
virtual void __fastcall getLightRef();
virtual void __fastcall getSampleRef();
virtual void __fastcall getRelTrans();
virtual void __fastcall initialize();
bool firstDark;
bool firstLight;
spectrum *ref0;
spectrum *dark0;
spectrum *lastRef;
virtual void __fastcall rereference();
};
//---------------------------------------------------------------------------
#endif
i am aware that i will be lambasted for this; it was written somewhat hastily and i haven't had time to rework it.Code://---------------------------------------------------------------------------
#include "vclUtils.h"
#include "permissionSet.h"
#include "utils.h"
#include "dir.h"
#include "procMenu.h"
#include "objTasks.h"
#include "paramClasses.h"
#include "processClasses.h"
#include "spectroscopyTools.h"
#include "progForm.h"
#include "spectrum.h"
#include "appMain.h"
#include "flowPath.h"
#include "tasksAndRoutines.h"
#pragma hdrstop
#include "BWTEKUSB.h"
#pragma package(smart_init)
bwTekUSB::bwTekUSB(String name,process *Owner,int Channel,int arrSize ,int ADCTYPE,int TimingMode,bool connectNow,input *tempSensor,int h, int w) :
spectrometer(Owner,name,Channel,iTime+10,h,w,tempSensor),
iTimeOK(0),
darkOK(1),
sampleOK(2),
pixelConvOK(3)
{
get->addTask(new vvPtrTask(name+" Check reference time",&checkRef));
int *returnCode = new int();
get->addTask(new avPtrTask<int>(name+" Get Spectrum",&getSpectrum,returnCode));
get->addTask(
new compare<int>(
name+" compare return code",
returnCode,">=",new int(0),
new vvPtrTask(name+" processSpectrum",&processSpectrum),
NULL
)
);
numInitCriteria = 4;
initCriteria = new bool[numInitCriteria];
for(int i=0;i<numInitCriteria;i++)
{
initCriteria[i]=false;
}
maxY=65535;
progForm = Owner->progForm;
connected=false;
int i=0;
referenceInterval = 3600*1000*4;
nextReferenceTime = GetTickCount()+referenceInterval;
shutterWait = 1000;
saturationThreshold = 0.91552734375;
// pathnode->state = NULL;
refAvg = 10;
iTime = 30;
iTimeOffset = 500;
sampleInterval = iTime+iTimeOffset;
shutterState =0;
adcType = ADCTYPE;
timingMode = TimingMode;
initPix(arrSize);
dllPath = "BWTEKUSB.dll";
loadDLL(dllPath);
if(connectNow)
{
connect();
}
intParam *ip = new intParam((int *)&refAvg,"Spectra to average in measurement",NULL,NULL,NULL);
params->add(ip);
ip = new intParam((int *)&referenceInterval,"Time between spectral references",NULL,NULL,NULL);
params->add(ip);
ip = new intParam((int *)&iTime,"Integration Time",new String("ms"),NULL,NULL);
ip->setFunc = &setITime;
params->add(ip);
params->add(new dblParam(&saturationThreshold,"Saturation Threshold",new String("%"),NULL,NULL));
ip= new intParam(&iAddr,"Channel Number",NULL,NULL,NULL);
ip->setFunc = &setChannel;
params->add(ip);
// draw();
}
void __fastcall bwTekUSB::setConnected(bool state)
{
CONNECTED = state;
}
bool __fastcall bwTekUSB::getConnected()
{
try
{
int i=setupChannel(iAddr,NULL);
if(i<=0)
{
connect();
}
}
catch(...)
{
}
return CONNECTED;
}
void __fastcall bwTekUSB::setChannel(int chan)
{
try
{
bwClose(iAddr);
iAddr = chan;
connect();
}
catch(...)
{
}
}
double __fastcall bwTekUSB::pixelToWavelength(int pixel)
{
double wl=0;
for(int j=0;j<pixelToWavelengthCoeffs.Length;j++)
{
double x=pixelToWavelengthCoeffs[j];
wl+=x*pow((double)pixel,j);
}
return wl;
}
double __fastcall bwTekUSB::wavelengthToPixel(double wl)
{
double pixel=0;
for(int j=0;j<wavelengthToPixelCoeffs.Length;j++)
{
double x=wavelengthToPixelCoeffs[j];
pixel+=x*pow(wl,j);
}
return pixel;
}
void __fastcall bwTekUSB::getPixelConv()
{
char cd[MAXPATH];
getcwd(cd,MAXPATH);
String fname = (String)cd+"\\bwtekCurrentSettings.ini";
int result = readEeprom(fname.c_str(),iAddr);
if(result>0)
{
TIniFile *f = new TIniFile(fname);
String cname = "coefs_";
String sname = "COMMON";
if(f->SectionExists(sname))
{
pixelToWavelengthCoeffs.Length=0;
bool ok = true;
for(int i=0;i<4;i++)
{
pixelToWavelengthCoeffs.Length++;
pixelToWavelengthCoeffs[i]=f->ReadFloat(sname,cname+"a"+(String)i,NULL);
wavelengthToPixelCoeffs.Length++;
wavelengthToPixelCoeffs[i]=f->ReadFloat(sname,cname+"b"+(String)i,NULL);
ok &= (pixelToWavelengthCoeffs[i]!=NULL && wavelengthToPixelCoeffs[i]!=NULL);
}
if(!ok)
{
MessageDlg("Pixel to wavelength coefficients not found in "+fname,mtError,TMsgDlgButtons()<<mbOK,0);
}
else
{
initCriteria[pixelConvOK]=true;
}
}
else
{
MessageDlg("Section "+sname+" does not exist in "+fname,mtError,TMsgDlgButtons()<<mbOK,0);
}
delete f;
}
else
{
if(result == -1)
{
MessageDlg("Communication error with "+name,mtError,TMsgDlgButtons()<<mbOK,0);
}
if(result ==-2)
{
MessageDlg("No data in "+name+" EEPROM",mtError,TMsgDlgButtons()<<mbOK,0);
}
}
bool b = initialized;
}
void __fastcall bwTekUSB::maintMode(bool on)
{
}
void __fastcall bwTekUSB::loadPopup()
{
procObj::loadPopup();
}
void __fastcall bwTekUSB::initPix(const int size)
{
arrSize = size;
tmp = new double[size];
rawData = new unsigned short[size];
for(int i =0;i<arrSize;i++)
{
tmp[i]=0;
rawData[i]=0;
}
}
void __fastcall bwTekUSB::loadDLL(String path)
{
HINSTANCE HInst=LoadLibrary(path.c_str());
if( HInst>0 )
{
readEeprom = (bwtekReadEEPROMUSB)GetProcAddress(HInst,"bwtekReadEEPROMUSB");
setupChannel=(bwtekSetupChannel)GetProcAddress(HInst,"bwtekSetupChannel");
bwTest=(bwtekTestUSB)GetProcAddress(HInst,"bwtekTestUSB");
bwSetTime=(bwtekSetTimeUSB) GetProcAddress(HInst,"bwtekSetTimeUSB");
bwReadData=(bwtekDataReadUSB)GetProcAddress(HInst,"bwtekDataReadUSB");
bwClose=(bwtekCloseUSB)GetProcAddress(HInst,"bwtekCloseUSB");
bwReadAvgResult=(bwtekReadResultUSB)GetProcAddress(HInst,"bwtekReadResultUSB");
bwPolyFit = (bwtekPolyFit)GetProcAddress(HInst,"bwtekPolyFit");
bwPolyCalc = (bwtekPolyCalc)GetProcAddress(HInst,"bwtekPolyCalc");
bwGetStatus = (bwtekGetExtStatus)GetProcAddress(HInst,"bwtekGetExtStatus");
bwSetExtLaser = (bwtekSetExtLaser)GetProcAddress(HInst,"bwtekSetExtLaser");
bwSetExtShutter = (bwtekSetExtShutter)GetProcAddress(HInst,"bwtekSetExtShutter");
bwSetExtSync = (bwtekSetExtSync)GetProcAddress(HInst,"bwtekSetExtSync");
bwGatedMode = (bwtekGatedMode)GetProcAddress(HInst,"bwtekGatedMode");
bwSetPulse = (bwtekSetExtPulse)GetProcAddress(HInst,"bwtekSetExtPulse");
closeShutter = (bwtekShutterOpen)GetProcAddress(HInst,"bwtekShutterOpen");
openShutter = (bwtekShutterClose)GetProcAddress(HInst,"bwtekShutterClose");
dllPath = path;
}
else
{
TFileOpen *o = new TFileOpen(owner);
o->Caption = "Please Locate File bwtekusb.dll";
o->Dialog->Filter ="Dynamically Linked Library (bwtekusb.dll)|BWTEKUSB.DLL";
o->Dialog->Title = "Please Locate File bwtekusb.dll";
open:
if(o->Dialog->Execute())
{
loadDLL(o->Dialog->FileName);
}
else
{
goto open;
}
delete o;
}
}
int bwTekUSB::setShutter(unsigned short state)
{
int i=0;
while(shutterState!=state && i<100)
{
if(state>0)
{
shutterState=openShutter(iAddr);
}
else
{
shutterState=closeShutter(iAddr);
shutterState^=1;
}
}
if(i==100&&shutterState!=state)
{
shutterState=-1;
}
return shutterState;
}
int __fastcall bwTekUSB::avgSpec(spectrum *s, int points)
{
if(connected)
{
for(int i =0;i<arrSize;i++)
{
tmp[i]=0;
}
for(int i= 0;i<points;i++)
{
bwReadData(0,rawData,iAddr);
for(int j=0;j<arrSize;j++)
{
tmp[j] = (double)(tmp[j]*i+rawData[j])/(double)(i+1);
}
}
unsigned short ti;
for(int i =0;i<arrSize;i++)
{
s->data[i] = (double)tmp[i]/maxY;
}
}
}
void __fastcall bwTekUSB::getDarkRef()
{
if(connected)
{
setShutter(0);
int then=GetTickCount()+shutterWait;
while(GetTickCount()<then){};
avgSpec(darkRef,refAvg);
logReference(darkRef);
setShutter(1);
}
}
void __fastcall bwTekUSB::getSampleRef()
{
if(connected)
{
setShutter(1);
avgSpec(sampleRef,refAvg);
logReference(sampleRef);
}
}
spectrum *__fastcall spectrometer::getRelAbs()
{
for(int i=0;i<arrSize;i++)
{
if(sample->data[i]==0)
{
relAbs->data[i]=0;
}
else
{
if(relTrans->data[i]==0)
{
relAbs->data[i]=65535;
}
else
{
try
{
relAbs->data[i]=-log10(relTrans->data[i]);
}
catch(...)
{
relAbs->data[i]=0;
}
}
}
}
return relAbs;
}
int __fastcall bwTekUSB::setExtShutter(int state)
{
if(connected)
{
return bwSetExtShutter(state,iAddr);
}
}
void __fastcall bwTekUSB::setITime(int ITime)
{
if(connected)
{
int result =bwSetTime(ITime,iAddr);
if(result==ITime)
{
iTime = ITime;
}
}
}
int __fastcall bwTekUSB::bwtest()
{
int returnCode = bwTest(timingMode,arrSize,adcType,iAddr,NULL);
if(returnCode>=0)
{
setShutter(shutterState);
}
return returnCode;
}
int __fastcall bwTekUSB::connect()
{
int returnCode = bwtest();
// int returnCode = -1;
if(returnCode>=0)
{
connected = true;
}
else
{
connected = false;
}
return CONNECTED;
}
int __fastcall bwTekUSB::getSpectrum()
{
if(connected)
{
try
{
if(this->shutterState!=1)
{
setShutter(1);
}
int returnCode = bwReadData(0,rawData,iAddr);
if(returnCode>=0)
{
for(int i =0;i<arrSize;i++)
{
sample->data[i]=(double)rawData[i]/65535;
}
}
return returnCode;
}
catch(...){}
}
}
void __fastcall bwTekUSB::checkRef()
{
if(GetTickCount()>=nextReferenceTime)
{
rereference();
nextReferenceTime = GetTickCount()+referenceInterval;
}
}
void __fastcall bwTekUSB::processSpectrum()
{
(*measNo)++;
getRelTrans();
getRelAbs();
if(onScan!=NULL)
{
onScan();
}
nextSampleTime=GetTickCount()+sampleInterval;
}
void __fastcall bwTekUSB::scanOnTimer(TObject *Sender)
{
getState();
}
void __fastcall bwTekUSB::getRelTrans()
{
for(int i =0;i<arrSize;i++)
{
if(darkRef->data[i]>=sample->data[i]||darkRef->data[i]>=sampleRef->data[i])
{
relTrans->data[i]=0;
}
else
{
float f =((sample->data[i]-darkRef->data[i]))/((sampleRef->data[i]-darkRef->data[i]));
if(f<1)
{
relTrans->data[i]=f;
}
else
{
relTrans->data[i]=1;
}
}
}
}
void __fastcall bwTekUSB::autoSetITime()
{
if(connected)
{
if(shutterState<1)
{
setShutter(1);
}
double tmax = saturationThreshold;
double imax =0;
int tm=tmax*100;
int im=imax*100;
int di = 0;
while(im!=tm)
{
di=0;
setITime(iTime);
avgSpec(sample,refAvg);
for(int i =0;i<arrSize-1;i++)
{
if(imax<sample->data[i])
{
imax = sample->data[i];
}
}
if(imax>tmax)
{
di =-1;
}
if(imax<tmax)
{
di = 1;
}
iTime+=di;
im=imax*100;
}
setITime(iTime);
sampleInterval = iTime+iTimeOffset;
initCriteria[iTimeOK]=true;
bool b = initialized;
}
}
void __fastcall bwTekUSB::initialize()
{
if(connected)
{
getPixelConv();
autoSetITime();
getDarkRef();
getSampleRef();
getState();
nextReferenceTime = GetTickCount()+referenceInterval;
bool b = initialized;
}
}
void __fastcall bwTekUSB::rereference()
{
getDarkRef();
}
void __fastcall bwTekUSB::refreshIcon()
{
int xo = (Width-128)/2;
icon->Canvas->FillRect(TRect(xo,Height/4,Width-xo,Height-4));
icon->Canvas->Pen->Color = clMedGray;
icon->Canvas->MoveTo(xo,Height-3);
icon->Canvas->LineTo(xo,Height/4);
icon->Canvas->LineTo(Width-xo,Height/4);
icon->Canvas->MoveTo(4,Height-3);
icon->Canvas->Pen->Color = 0x00FF0000;
int r = arrSize/128;
int h= 3*Height/4;
for(int i=0;i<128;i++)
{
int v1 = this->rawData[r*i]*h/maxY;
icon->Canvas->LineTo(i+xo+1,Height-4-v1);
}
pathnode->draw();
}
bwTekS255_256::bwTekS255_256(process *Owner,String name, int chan,bool connectNow,input *tempSensor,int h,int w) : bwTekUSB(name,Owner,chan,256,14,3,connectNow,tempSensor,h,w)
{
params->editable = false;
firstLight = true;
firstDark = true;
fileParam *fp = new fileParam(&storedSampleRef,"Sample Reference File");
fp->setFunc = &loadSample;
params->add(fp);
internalPerms->onLogin->addTask(new setVar<bool>("Set Sample Reference File Parameter Editable",¶ms->editable,new bool(true)));
internalPerms->onLogout->addTask(new setVar<bool>("Set Sample Reference File Parameter Editable",¶ms->editable,new bool(false)));
fp = new fileParam(&storedDarkRef,"Dark Reference File");
fp->setFunc = &loadDark;
params->add(fp);
fp = new fileParam(&storedLightRef,"Light Reference File");
fp->setFunc = &loadLight;
params->add(fp);
HINSTANCE HInst=LoadLibrary(dllPath.c_str());
if( HInst>0 )
{
bwtekSetShutters=(bwtekShutterControl)GetProcAddress(HInst,"bwtekShutterControl");
}
refShutterState = 0;
ref0=new spectrum(this,arrSize,"Original Reference Channel Spectrum");
dark0=new spectrum(this,arrSize,"Original Dark Reference Spectrum");
lastRef = new spectrum(this,arrSize,"Current Reference Channel Spectrum");
spectroscopyTool = new spectroscopySuite(owner->owner,name+" Tools",this);
MainForm->addProcess(spectroscopyTool);
internalPerms->onLogin->addTask(new twoArgPtrTask<void,TTabSheet *,bool>("Set Spectroscopy Tab Visible",&setVisible,spectroscopyTool->tab,true));
internalPerms->onLogout->addTask(new twoArgPtrTask<void,TTabSheet *,bool>("Set Spectroscopy Tab Visible",&setVisible,spectroscopyTool->tab,false));
internalPerms->onLogin->addTask(new twoArgPtrTask<void,TMenuItem *,bool>("Set Spectroscopy Tab Visible",&setVisible,spectroscopyTool->procMainMenu,true));
internalPerms->onLogout->addTask(new twoArgPtrTask<void,TMenuItem *,bool>("Set Spectroscopy Tab Visible",&setVisible,spectroscopyTool->procMainMenu,false));
internalPerms->onLogout->addTask(new twoArgPtrTask<void,TTimer *,bool>("Set Spectroscopy Tab Visible",&setEnabled,((TspectroscopyTool *)spectroscopyTool->PnID)->timer,false));
spectroscopyTool->tab->TabVisible = false;
spectroscopyTool->procMainMenu->Visible = false;
initSpectrometer = new initBwTekS255_256(this);
}
int bwTekS255_256::setShutter(unsigned short state)
{
if(connected)
{
try
{
if(bwtekSetShutters(state,-1,iAddr))
{
shutterState = state;
}
}
catch(...)
{
}
}
}
void __fastcall bwTekS255_256::setRefShutter(unsigned short state)
{
if(connected)
{
try
{
if(bwtekSetShutters(-1,state,iAddr))
{
refShutterState =state;
}
}
catch(...)
{
}
}
}
void __fastcall bwTekS255_256::autoSetITime()
{
if(connected)
{
setShutter(0);
setRefShutter(1);
double tmax = saturationThreshold;
double imax =0;
int di = 0;
double lastErr =tmax+1;
double err=tmax;
while(lastErr>=err&&imax!=tmax)
{
imax=0;
di=0;
lastErr = err;
setITime(iTime);
avgSpec(sample,refAvg);
for(int i =0;i<arrSize-1;i++)
{
if(imax<sample->data[i])
{
imax = sample->data[i];
}
}
if(imax>tmax)
{
di =-1;
}
if(imax<tmax)
{
di = 1;
}
err =fabs(tmax-imax);
if(err>lastErr)
{
di-=2*di;
}
if(imax==tmax)
{
di=0;
}
iTime+=di;
}
setITime(iTime);
sampleInterval = iTime+iTimeOffset;
initCriteria[iTimeOK]=true;
bool b = initialized;
}
}
void __fastcall bwTekS255_256::getLightRef()
{
if(connected)
{
setShutter(0);
setRefShutter(1);
int then=GetTickCount()+shutterWait;
while(GetTickCount()<then){}
avgSpec(lastRef,refAvg);
logReference(lastRef);
setRefShutter(0);
setShutter(1);
bool b = initialized;
if(firstLight)
{
firstLight = false;
for(int i=0;i<arrSize;i++)
{
ref0->data[i]=lastRef->data[i];
}
}
}
}
void __fastcall bwTekS255_256::getDarkRef()
{
if(connected)
{
setShutter(0);
setRefShutter(0);
int then=GetTickCount()+shutterWait;
while(GetTickCount()<then){}
avgSpec(darkRef,refAvg);
logReference(darkRef);
initCriteria[darkOK]=true;
setRefShutter(0);
setShutter(1);
bool b = initialized;
if(firstDark)
{
firstDark = false;
for(int i=0;i<arrSize;i++)
{
dark0->data[i]=darkRef->data[i];
}
}
}
}
void __fastcall bwTekS255_256::getSampleRef()
{
if(connected)
{
setShutter(1);
setRefShutter(0);
int then=GetTickCount()+shutterWait;
while(GetTickCount()<then){};
avgSpec(sampleRef,refAvg);
logReference(sampleRef);
setRefShutter(0);
setShutter(1);
initCriteria[sampleOK]=true;
bool b = initialized;
}
}
void __fastcall bwTekS255_256::initialize()
{
if(connected)
{
initSpectrometer->Resume();
}
}
void __fastcall bwTekS255_256::getRelTrans()
{
for(int i =0;i<arrSize;i++)
{
if(darkRef->data[i]>=sample->data[i]||darkRef->data[i]>=sampleRef->data[i]||darkRef->data[i]>=lastRef->data[i]||dark0->data[i]>=ref0->data[i])
{
relTrans->data[i]=0;
}
else
{
float f =((sample->data[i]-darkRef->data[i]))/((sampleRef->data[i]-dark0->data[i]))*((lastRef->data[i]-darkRef->data[i])/(ref0->data[i]-dark0->data[i]));
relTrans->data[i]=f;
}
}
}
void __fastcall bwTekS255_256::loadPopup()
{
bwTekUSB::loadPopup();
}
void __fastcall bwTekS255_256::rereference()
{
if(connected)
{
getDarkRef();
getLightRef();
}
}
int __fastcall bwTekS255_256::bwtest()
{
try
{
int returnCode = bwTest(timingMode,arrSize,adcType,iAddr,NULL);
if(returnCode>=0)
{
setShutter(shutterState);
setRefShutter(refShutterState);
}
return returnCode;
}
catch(...)
{
}
}
initBwTekS255_256::initBwTekS255_256(bwTekS255_256 *Owner) : initSpectrometer(Owner)
{
owner = Owner;
}
void __fastcall initBwTekS255_256::Execute()
{
while(!Terminated)
{
owner->progForm->progBar->POS=0;
owner->progForm->progBar->min=0;
owner->progForm->progBar->max = 5;
owner->progForm->labelCaption="Reading EEPROM";
Synchronize(owner->progForm->updateLabelCaption);
Synchronize(owner->getPixelConv);
owner->progForm->progBar->POS++;
Synchronize(owner->progForm->progBar->Paint);
owner->progForm->labelCaption="Detecting integration time...";
Synchronize(owner->progForm->updateLabelCaption);
Synchronize(owner->autoSetITime);
owner->progForm->progBar->POS++;
owner->progForm->labelCaption="Getting dark reference...";
Synchronize(owner->progForm->progBar->Paint);
Synchronize(owner->progForm->updateLabelCaption);
Synchronize(owner->getDarkRef);
owner->progForm->labelCaption="Getting light reference...";
Synchronize(owner->progForm->updateLabelCaption);
owner->progForm->progBar->POS++;
Synchronize(owner->progForm->progBar->Paint);
Synchronize(owner->getLightRef);
owner->progForm->labelCaption="Getting water background...";
Synchronize(owner->progForm->updateLabelCaption);
owner->progForm->progBar->POS++;
Synchronize(owner->progForm->progBar->Paint);
Synchronize(owner->getSampleRef);
owner->progForm->progBar->POS++;
Synchronize(owner->progForm->progBar->Paint);
owner->progForm->labelCaption="Finishing initialization";
Synchronize(owner->progForm->updateLabelCaption);
Synchronize(owner->getState);
for(int i=0;i<owner->arrSize;i++)
{
owner->ref0->data[i]=owner->lastRef->data[i];
owner->dark0->data[i]=owner->darkRef->data[i];
}
owner->nextReferenceTime = GetTickCount()+owner->referenceInterval;
owner->progForm->close();
Suspend();
}
}
//---------------------------------------------------------------------------
the derived object i'm using is S255_256
"/" sure as heck isn't the current working directory. However, I glanced through the code long enough to see that (at least once) you tacked "/stuff" on to the end of the cwd, and that is probably ok.
Anyway, are these two posts supposed to be different, and what is all this stuff, and I thought you had narrowed down the error but I didn't see, on a skim, you pointing anything out.
It's called the art of debugging. Use a debugger. Find out how to reproduce the problem, step through it in the debugger. Visual Studio has one very powerful and easy, visual debugger.
I prefer this - http://www.microsoft.com/whdc/devtoo...g/default.mspx
You can run and debug the program wherever it is, and not just inside your project.
Plus, there's lots of "power user" features in windbg.
Visual Studio also contains a very powerful, and if not easier, debugger.
You can get it for free at http://www.microsoft.com/Express/.
But you should try out for yourself if it's to your liking. No sense in using something that you don't like.
do i have to install the compile the app from source code to use it?
Yes, you would have to installing the IDE, then compile your source.
I'm not sure if or how you can debug apps with windbg with source code information. I'm not sure how that works and what compilers can produce the correct debug information...
compiling from source is not a viable option in the long term.
i don't know how windbg works either, as obviously i'm not familiar with it yet.
i expect it will not work 100% until i switch to MSVC++ since i use BCB, but it's better than nothing.
The debugger inside Visual Studio doesn't really require you to compile with the Visual C++ compiler per se... just as windbg, it works fine by attaching to executables.
However, I know the VS debugger requires program database files (aka debug files) for being able to properly debug (or you'll just get assembly output). Maybe this can be generated from other compilers too, but I don't know for sure.
Otherwise, VS is not a bad idea and VC++ is not a bad compiler, if you have the option to switch and try it out.
i would love to, but unfortunately i don't have that option as i don't have the available time to do the port
"Do the port"? I don't understand what you mean by that, but...
You do realize that standards compliant code will compile in any compliant compiler, yes?
Anyway, I'm going to trust you have your reasons. Unfortunately, the rest of how to make it work is beyond my knowledge.
i've made extensive use of features that i believe are specific to BCB, namely their GUI components.
Well isn't that just more or less their version of MFC? I am not qualified to answer that question on my own since I do not have a PhD in proprietary useless libraries. Which also means I am not welcome to work at Microsoft. Its listed as one of their basic requirements.
WinDbg has a very good help file.
Use it to run the program in it's current location, then just let it catch the exception when it crashes.
Then go looking to see where the problem is.
If you compile the project in visual studio, so that it also outputs a .pdb file, then you should have full source code as well.
He says his code cannot be easily moved over to VC++. I bet it may be easier than he suggests.
i'm pretty sure it's this now:
nm false hope :(
OH!
i omitted a critical detail
this only happens on a certain computer setup - they're a celeron Ms with XP embedded IIRC.
doesn't happen on my development PC.
Make sure that the account your application is running under can write to %ProgramFiles%, because normally, an application SHOULD NOT write to it's install directory. %ProgramFiles% could be write protected in your execution environment.
Use SHGetFolderPath to find a folder suitable for writing data. APPDATA or LOCAL_APPDATA comes to mind.
Such atrocities you're airing there!
GAAAK! What kind of obfuscation do you call this!:Fixed version that does the same thing:Code:open:
if(o->Dialog->Execute())
{
loadDLL(o->Dialog->FileName);
}
else
{
goto open;
}
Mind you, there's more levels of indirection there than I'm happy with too.Code:while(!o->Dialog->Execute())
{}
loadDLL(o->Dialog->FileName);
Catch all blocks that do nothing, not even logging - EEEK! You're really trying to make bugs hard to find huh!
You and the standard C++ library don't get along at all huh?
i know, i know :(
re: indirection - i got into a bit of a bad habit with that because BCB FORCES you to use pointers more than would otherwise be necessary. if you try to instantiate an object derived from a point their object library off the stack, it generates compile-time errors saying "VCL Style Classes must be instatntiated using operator new". it also commonly gripes about not being able to copy by value.
i will say though that their DynamicArray class is quite good, though i find vector's access methods far more convenient.
anyway, yes i would love a critique of the style and efficiency of the code, as it's probably the worst and most hastily written of anything i've done, but that's really not what's biting me right now.
there are more oddities going on:
if i change an unrelated part of the code, the location from which it will successfully execute changes.
yesterday i removed some system administration functions, part of which entailed enabling some menus that were enabled by default.
now, inexplicably, it will execute from C:\Program Files\AppDir or C:\AppDir and NOT the user's desktop, where I had worked previously. the failure still occurs if and only if the spectrometer is plugged in though. it managed to cough up an EAccess Violation message at me if executed from the user's desktop, but other attempts at resolving the problems would just give me abnormal termination.
also, re: writing to protected folders: the default account on these machines is the admin. we have no reason to restrict the user's permissions.
No it's not. Have a friend that knows nothing of MFC and works at MS on the kernel team.Quote:
Which also means I am not welcome to work at Microsoft. Its listed as one of their basic requirements.
And your statement is a bit wide-reaching since not everyone agrees that MFC or other so called 'useless' libraries are 'useless.'
You only need to post the source code that is related the error you are receiving. I sure do not feel like pouring over tons of source code to 'find' your error. Unless of course you would like to pay me to do so?
If you are relying on relative paths and are not sure if you have the right one I find that writing a test output file to the same relative path and then doing a search for it will save you a lot of pain. If the test output file is not in the right place then your relative path is incorrect.
well thanks for the feedback everyone, but i don't think this is anything i can do anything about.
this is all code that has been reused for this project, its been used before with no such instability issues, but apparently this particular hardware set does not like my spectrometer's USB driver.
i mean, this is really, really odd. one thing i noticed is that the exe title cannot be identical to the enclosing folder. i kid you not. changing the name of the exe would make it launch just fine! i could change it back and it would start crashing again. that, at least, was repeatable!
i may be a sophomoric programmer, but i definitely know enough to debug repeatable errors. anyway, i guess there was nothing anyone here could do afterall. i figured it was something that was wholly my fault, but at this point i'm writing this off , as i have had total success on several other systems that i've tested it out on. thanks anyway everyone.
i got this to happen on my laptop today while i was in the lab.
i got a more illustrative error message out of it:
i'm not using MSCTF.dll directly. apparently it has to do with MS text service. i have no idea how or where it is used.Quote:
Access violation at address 7475420A in module 'MSCTF.dll'. Read of address FFFFFFFF
i also found several other odd things that would make the program either functional or not in addition to the odd things described earlier:
changing the executable name to >16 characters will cause it to crash.
changing the name of the enclosing folder would cause a crash (from one with spaces to one with no spaces, btw)
when i changed the IDE project name to >16 characters (so that the exe title would be >16 chars) it would run no problems when executed through the compiler, but launching the application directly from the exe file caused it to crash.
the problem occurs when i call reference(). i can get data from the spectrometer otherwise, but for some reason this fails.
plz halp!
Run your app
Run WinDbg
Use WinDbg to attach to your app (you're now debugging it)
Use your app to invoke the function in question
WinDbg will catch the exception, and you can start looking around to see what the problem is.
when i tried that it complained about not having some standard charset and wouldn't initialize. i suppose in light of the new error message i got, that would be consistent with a problem with msctf
will try again and post more detailed results
windbg can't successfully open the app, even when i can launch it successfully through windows.
BCB uses OMF format, and the documentation says windbg can only evaluate symbols with files having COFF format, so i think all i'm going to get out of it is assembly that i don't know how to read.
i can attach the app to BCB tho, but again, all i get there is assembly.
i installed SP3 last night and now the error window reads "privileged instruction"
i'm not writing anywhere, the logging function i had built in has been commented out.
Assembly can be debugged, especially if you also have a way to get a map-file.
But if you get an "Privileged instruction" exception, it usually means that your code is jumping into non-code sections, which is caused by one of a few things:
1. Bad code generated by the compiler.
2. Writing garbage to code-memory (you shouldn't be able to do that in the first place).
3. Dynamically generated code that is not generated correctly (do you build code at runtime at all?)
4. Random garbage in function pointers (unintialized/overwritten with rubbish) [or in C++, you could overwrite the vtable of a class with rubbish to achieve the same thing, since the vtable is for all intents and purposes a set of function pointers].
5. Messing about with the return address so that the code returns to a random place in memory.
The last one is probably the most likely - overwriting the stack by one or two bytes can lead to very strange things indeed.
If you can debug in assembler mode, you should be able to see if the code looks like sane code, or if it's complete garbage (at least if you are a little bit used to reading assembler code).
--
Mats
not per se, but i do insert instances of functors into a container at runtime that determine how the app runsQuote:
3. Dynamically generated code that is not generated correctly (do you build code at runtime at all?)
That's not the type of "generate instrucitons at runtime" I was thinking of.
I would try to debug in assembler and see if you can get a stack-trace.
--
Mats
yeah i didn't think so. what i'm doing is not nearly as clever.
Quote:
4. Random garbage in function pointers (unintialized/overwritten with rubbish) [or in C++, you could overwrite the vtable of a class with rubbish to achieve the same thing, since the vtable is for all intents and purposes a set of function pointers].
looks like it was this! unitinitialized function ptr. i guess the big question is how the hell did i get away with this before!?!?
it started crashing through my compiler when i moved the source files into My Documents! lo and behold as soon as i could set breakpoints and step thru the code it was easy as pie to track it down :)
woot woot!
Either you lost the initialization at some point, or you didn't use that particular function pointer.
It is always a good idea to fill structures that have function pointers with some value that makes all it's pointers invalid before you fill them in (e.g. memset using 0, 0xCC or 0xDD would work). If you use such a pointer in Windows or Linux (from a 32-bit application), it will absolutely crash then and there, and usually the EIP value will show that you tried to execute at this "unfilled" place. On the other hand, if you just grab a chunk of stack memory, it may well contain addresses that are valid memory locations that can be "executed" such as return addresses to previous function calls or data addresses (strings execute quite well in x86 - it's all sorts of weird jumps that you wouldn't normally see in sensible code, but it will (most likely) not crash from running through ASCII text)
--
Mats
Just as a heads up, some debuggers (such as Visual Studio) will complain if you use uninitialized variables.
Actually, the debugger just catches the crash and identifies that it happend through an uninitialized variable - this is done by filling local stack-based variables with a pattern just like I described above, and when the data is being used as a pointer/index, it is detected as a "uninitialized data" error, rather than a random "got outside valid memory".
--
Mats
If you want to put it that way, sure.
There are always several ways to catch uninitialized variables.
Having a debugger do it for you is nice, I think.
Oh and some compiler will warn you if you try to use an uninitialized variable. I'm guessing GCC does and I know VC++ does.
Remember always to put your compiler warnings to maximum!