C/C++ Developer's API usage examples

The following shows sample scan function for use with the following command  

CMND_MULTI_CHAN_DIGIN_CAL_SCAN  

for other scan types please go here and select one.






Function call prototypes and pointer casting from header file.
(only those used in following example shown)
see other protypes here

typedef BOOLEAN(*P_DLL_START_SCAN)
          (USHORT usDevID, PSCAN_OBJECT_DIO pScanObj_DIO, BYTE bStartMode );
          P_DLL_START_SCAN    pDLL_StartScan_DIO = NULL;

typedef BOOLEAN(*P_DLL_READ_SCAN_DATA_WITH_DIGIN)
          (USHORT usDevID, UINT* puiDataBuff, BYTE* pbDiginBuff, BYTE* pbCurChan,
          USHORT numPointsToRead, PSCAN_OBJECT_DIO pScanObj_DIO);
          P_DLL_READ_SCAN_DATA_WITH_DIGIN    pDLL_ReadScanDataWithDigin = NULL;

typedef BOOLEAN(*P_SP_END_SCAN)
          (USHORT usDevID);
          P_SP_END_SCAN    pSP_EndScan = NULL;








Variables declarations from header file (only those used in following example shown)
see other protypes here

Scan related
typedef struct _SCAN_OBJECT{      // NOTE:  Most commonly used members are underlined
BYTE SO_bScanType; // app writes (needed by DLL to start scan)
DOUBLE SO_dblDevRate; // app writes (needed by DLL to start scan)
UINT SO_uiTotalPointsReadByDrvr; // DLL writes (can be read by app)
UINT SO_uiPointsInBuffer; // DLL writes (app reads this to get num points available to be read)
UINT SO_uiStatus; // DLL writes (important scanning status information needed by app)
UINT SO_uiSizeVoltageArray; // No longer used (but must be present as placeholder)
UINT SO_uiCurHead; // DLL writes (can be read by app)
UINT SO_uiCurTail; // DLL writes (can be read by app)
BYTE SO_bDigitalInput; // DLL writes (can be read by app)
BYTE SO_bChecksum; // DLL writes (can be read by app)
BYTE SO_bDeviceDisconnect; // No longer used (but must be present as placeholder)
UINT SO_uiScanStartTime; // No longer used (app may use for convenience)
UINT SO_uiScanEndTime; // No longer used (app may use for convenience)
BYTE SO_bScanArg; // app writes (needed by DLL to start scan)
SCAN_OBJECT, *PSCAN_OBJECT;
'NOTE:  The following are possible bit settings for SO_Status shown above
#define SCAN_RUNNING    0x1 not currently used
#define SCAN_DATA_REQUEST_SUCCEEDED    0x2 not currently used
#define SCAN_ENDING    0x4 not currently used
#define SCAN_HALTED    0x8 if set, the device is no longer scanning
#define SCAN_CHECKSUM_ERROR    0x10 if set there has been a checksum error
#define SCAN_VOLTAGE_BUFFER_WRAP    0x20 indicates a wrap in the DLL's data buffer
#define SCAN_MICRO_CODE_BUFF_WRAP    0x40 indicates a wrap in the device's data buffer
#define SCAN_DEVICE_IO_ERROR    0x80 indicates I/O error
#define SCAN_DEVICE_DISCONNECTED    0x100 The device has been disconnected
#define SCAN_DEVICE_NOT_FOUND    0x200 not currently used


'NOTE:  The following are possible bit settings for SO_bScanType shown above
#define CMND_SINGLE_CHAN_SCAN    1 // single chan scan (normal)
#define CMND_SINGLE_CHAN_DIGIN_SCAN    2 // single chan with digin after every conversion
#define CMND_MULTI_CHAN_SCAN    3 // multi chan regular
#define CMND_MULTI_CHAN_CAL_SCAN    4 // multi chan with cal
#define CMND_MULTI_CHAN_DIGIN_SCAN    5 // multi chan with digin
#define CMND_MULTI_CHAN_DIGIN_CAL_SCAN    6 // multi chan with cal and digin











Function call example


Scanning -
Showing multi-chan-cal-digin scan (CMND_MULTI_CHAN_DIGIN_CAL_SCAN) - this scan includes digital in put in separate buffer with each conversion
Back to main source: - Shows complete initialization, misc functions, I/O, and CMND_SINGLE_CHAN_SCAN type scan

Links to other scan types:
     CMND_SINGLE_CHAN_DIGIN_SCAN single chan - includes digin in separate buffer with each conversion
     CMND_MULTI_CHAN_SCAN multi chan scan (normal)
     CMND_MULTI_CHAN_CAL_SCAN multi chan - includes chan 7 each scan
     CMND_MULTI_CHAN_DIGIN_SCAN multi chan - includes digin in separate buffer with each conversion

BOOLEAN DoScan(void)
{
NOTE: The following is just an overview of the CMND_MULTI_CHAN_DIGIN_SCAN scanning procedure.
Please see sample source code downloadable from web site for working example.

//Total channels to scan (1-8). Chan 6 is full scale and 7 (already included in this type of scan) is offset for calibration usage.
BYTE bNumMultiChanCnt = 5;
bCurListIndex = 0;

SCAN_OBJECT ScanObject;
PSCAN_OBJECT pScanObject = &ScanObject;

// only members required for this type of scan are initialized.
pScanObject->SO_uiStatus = 0;
pScanObject->SO_bScanType = CMND_MULTI_CHAN_DIGIN_CAL_SCAN;
pScanObject->SO_dblRate = padblRate[bCurListIndex];
pScanObject->SO_uiPointsInBuffer = 0;
pPSCAN_OBJECT->SO_bScanArg = bNumMultiChanCnt;
UINT SO_uiStatus_TEMP;

// Assign the various scan related function call pointers
pDLL_StartScan_DIO = (P_DLL_START_SCAN)GetProcAddress(hDLL, "DLL_StartScan_DIO");
if(!pDLL_StartScan_DIO) { /* do critical error handling here and exit */;   return FALSE; }
pDLL_ReadScanDataWithDigin = (P_DLL_READ_SCAN_DATA_WITH_DIGIN)GetProcAddress(hDLL, "DLL_ReadScanDataWithDigin");
if(!pDLL_ReadScanDataWithDigin) { /* do critical error handling here and exit */;   return FALSE; }
pSP_EndScan = (P_SP_END_SCAN)GetProcAddress(hDLL, "SP_EndScan");
if(!pSP_EndScan) { /* do critical error handling here and exit */;   return FALSE; }


//Make the following anything within reason. One scan consists of data for all channels set to scan.
BYTE bNumScans = 3;

USHORT usNumPointsToRead = bNumMultiChanCnt * bNumScans;

//If the number of channels being scanned in the multi-chan-cal-scan mode is less than 8 the calculation for the number
//of points to read in the call to the DLL_ReadScanDataWithDigin() won't be correct since each scan will also include
//the channel 7 (offset) voltage which the bNumMultiChanCnt varible doesn't yet know about under this circumstance.
if(bNumMultiChanCnt < 8) usNumPointsToRead = usNumPointsToRead + bNumScans;

UINT* pauiDataBuff = new UINT[usNumPointsToRead];
if(!pauiDataBuff) { /* do critical error handling here and exit (can't go further if this fails)
*/   return FALSE; }
memset(pauiDataBuff, 0, usNumPointsToRead);

BYTE* pabDiginBuff = new BYTE[usNumPointsToRead];
if(!pabDiginBuff) { /* do critical error handling here and exit (can't go further if this fails)
*/   return FALSE; }
memset(pabDiginBuff, 0, usNumPointsToRead);

// Start the scan
if(!pDLL_StartScan_DIO(pausDevList[bCurListIndex], pScanObject, 0)
{ /* do critical error handling here and exit
*/    return FALSE; }

char szBuff [2048],    szBuff_Temp[128];    sprintf(pBuff, "SCAN Voltages      Digital input\r\n\r\n");

double dblOffsetVoltage = 0;

//Always set the following to 0 for scans that include digital input.
bCurChan = 0;

BYTE bScanIndex = 0, bChanIndex = 0, bBuffIndex = 0;

DOUBLE dblTimeout = (double)usNumPointsToRead * 5 * (1.0 / padblRate[bCurListIndex]);
UINT uiTimeoutMultiplier = 2;   UINT uiTimeout = dblTimeout * 1000 * uiTimeoutMultiplier;
clock_t clkTimeout = clock() + uiTimeout;

NOTE: This scan will scan the number of channels passed in the pPSCAN_OBJECT->SO_bScanArg structure member, plus one more (channel 7 calibration channel) unless SO_bScanArg is already set to 8. The multi-channel scans only scan channel sequentially, so this type of scan is very useful if you want to scan less than 8 channels but still want the eighth channel included in the scan for calibration purposes. The digital input is returned for each point into a separate "mirrored" buffer. In other words, the offset of the digital ininput in one buffer matches the offset of the data point within the other buffer. See the C/C++ function call prototypes for more information concerning this type of scan.
while (TRUE)
{
     //Check to see if all of our scans are ready yet.
     //Calling this with usNumPointsToRead set to 0 updates pPSCAN_OBJECT->SO_uiPointsInBuffer

     pDLL_ReadScanDataWithDigin(pausDevList[bCurListIndex], pauiDataBuff, pabDiginBuff, &bCurChan, 0, pPSCAN_OBJECT);
     if (pPSCAN_OBJECT->SO_uiPointsInBuffer >= usNumPointsToRead)
     {
         // Read the data
         pDLL_ReadScanDataWithDigin(m_pausDevList[0], pauiDataBuff, pabDiginBuff, &bCurChan, usNumPointsToRead, pPSCAN_OBJECT);
         if(bNumMultiChanCnt == 8)   //This easy
         {
             //Get the offset voltage for use below
             dblOffsetVoltage = ((INT)pauiDataBuff[bScanIndex + 7] - 8388608) * 0.00000059604645

             for (bScanIndex; bScanIndex < bNumScans; bScanIndex++)
             {
                 for (bChanIndex = 0; bChanIndex < bNumMultiChanCnt; bChanIndex++)
                 {
                     sprintf(szBuff_Temp, "Chan: %d %2.3lf\t%x\r\n", bChanIndex,
                           (double)(((INT)pauiDataBuff[bBuffIndex] - 8388608) * 0.00000059604645) - dblOffsetVoltage, pabDiginBuff[bBuffIndex]);
                     strcat(pBuff, szBuff_Temp);
                     bBuffIndex++;
                 }
                 strcat(pBuff, "\r\n");
             }
         }
         else   //This is just a little more work
         {
             for (bScanIndex = 0; bScanIndex < bNumScansn; bScanIndex++)
             {
                 //Get the offset voltage for use below
                 dblOffsetVoltage = ((INT)pauiDataBuff[bScanIndex + bNumMultiChanCnt] - 8388608) * 0.00000059604645

                 for (bChanIndex = 0; bChanIndex < bNumMultiChanCnt + 1; bChanIndex++)
                 {
                     if(bChanIndex < (bNumMultiChanCnt))
                         sprintf(szBuff_Temp, "Chan: %d %2.5lf\t%X\r\n", bChanIndex,
                              (double)(((INT)pauiDataBuff[bBuffIndex] - 8388608) * 0.00000059604645) - dblOffsetVoltage, pabDiginBuff[bBuffIndex]);
                     else
                         // If bNumMultiChanCnt < 8 then there is an extra conversion (chan 7) in the buffer that we need to read now.
                         sprintf(szBuff_Temp, "Chan: %d %2.5lf\t%X\r\n", 7,
                              (double)(((INT)pauiDataBuff[bBuffIndex] - 8388608) * 0.00000059604645) - dblOffsetVoltage, pabDiginBuff[bBuffIndex]);
                     strcat(pBuff, szBuff_Temp);
                     bBuffIndex++;
                 }
                 strcat(pBuff, "\r\n");
             }
         }
         break;
     }
     else
     {
          // Do some kind of handling of error bits that may be set in pPSCAN_OBJECT->SO_uiStatus.
          // See possible bit settings above (Scan related variables). at least test for scan HALTED.

          SO_uiStatus_TEMP = pPSCAN_OBJECT->SO_uiStatus;   // easier to bit test as a fixed variable instead of a pointer.
          if(SO_uiStatus_TEMP & SCAN_HALTED)   break;
          if(clock() > clkScanTestTimeout) { sprintf(pBuff, "\r\rScan TIMEOUT ERROR\r\n");   break; }
          Sleep(50);
     }
}

// Always end the scan when finished
if(!pSP_EndScan(pausDevList[bCurListIndex]))
{ /* do critical error handling here
*/ }

// Display the data just using a simple MessageBox
MessageBox(GetForegroundWindow(), pBuff, " SCAN DATA --------", 0);

return TRUE;
}


back to main page Table of Contents     (use browser "back" button to go back to other locations)



lawsnlab@lawsonlabs.com
last reviewed/modified: 9-29-03 (Tim Van Dusen)