Files

1518 lines
46 KiB
C

//Author: LabJack
//December 27, 2011
//Example U3 helper functions. Function descriptions are in the u3.h file.
#include "u3.h"
#include <stdlib.h>
u3CalibrationInfo U3_CALIBRATION_INFO_DEFAULT = {
3,
1.31,
0,
//Nominal Values
{ 0.000037231,
0.0,
0.000074463,
-2.44,
51.717,
0.0,
51.717,
0.0,
0.013021,
2.44,
3.66,
3.3,
0.000314,
0.000314,
0.000314,
0.000314,
-10.3,
-10.3,
-10.3,
-10.3}
};
void normalChecksum(uint8 *b, int n)
{
b[0] = normalChecksum8(b, n);
}
void extendedChecksum(uint8 *b, int n)
{
uint16 a;
a = extendedChecksum16(b, n);
b[4] = (uint8)(a & 0xFF);
b[5] = (uint8)((a/256) & 0xFF);
b[0] = extendedChecksum8(b);
}
uint8 normalChecksum8(uint8 *b, int n)
{
int i;
uint16 a, bb;
//Sums bytes 1 to n-1 unsigned to a 2 byte value. Sums quotient and
//remainder of 256 division. Again, sums quotient and remainder of
//256 division.
for( i = 1, a = 0; i < n; i++ )
a += (uint16)b[i];
bb = a / 256;
a = (a - 256*bb) + bb;
bb = a / 256;
return (uint8)((a - 256*bb) + bb);
}
uint16 extendedChecksum16(uint8 *b, int n)
{
int i, a = 0;
//Sums bytes 6 to n-1 to a unsigned 2 byte value
for( i = 6; i < n; i++ )
a += (uint16)b[i];
return a;
}
uint8 extendedChecksum8(uint8 *b)
{
int i, a, bb;
//Sums bytes 1 to 5. Sums quotient and remainder of 256 division. Again,
//sums quotient and remainder of 256 division.
for( i = 1, a = 0; i < 6; i++ )
a += (uint16)b[i];
bb=a / 256;
a=(a - 256*bb) + bb;
bb=a / 256;
return (uint8)((a - 256*bb) + bb);
}
HANDLE openUSBConnection(int localID)
{
uint8 buffer[38]; //send size of 26, receive size of 38
uint16 checksumTotal = 0;
uint32 numDevices = 0;
uint32 dev;
int i, serial;
HANDLE hDevice = 0;
numDevices = LJUSB_GetDevCount(U3_PRODUCT_ID);
if( numDevices == 0 )
{
printf("Open error: No U3 devices could be found\n");
return NULL;
}
for( dev = 1; dev <= numDevices; dev++ )
{
hDevice = LJUSB_OpenDevice(dev, 0, U3_PRODUCT_ID);
if( hDevice != NULL )
{
if( localID < 0 )
{
return hDevice;
}
else
{
checksumTotal = 0;
//Setting up a ConfigU3 command
buffer[1] = (uint8)(0xF8);
buffer[2] = (uint8)(0x0A);
buffer[3] = (uint8)(0x08);
for( i = 6; i < 38; i++ )
buffer[i] = (uint8)(0x00);
extendedChecksum(buffer, 26);
if( LJUSB_Write(hDevice, buffer, 26) != 26 )
goto locid_error;
if( LJUSB_Read(hDevice, buffer, 38) != 38 )
goto locid_error;
checksumTotal = extendedChecksum16(buffer, 38);
if( (uint8)((checksumTotal / 256) & 0xFF) != buffer[5] )
goto locid_error;
if( (uint8)(checksumTotal & 0xFF) != buffer[4] )
goto locid_error;
if( extendedChecksum8(buffer) != buffer[0] )
goto locid_error;
if( buffer[1] != (uint8)(0xF8) || buffer[2] != (uint8)(0x10) ||
buffer[3] != (uint8)(0x08) )
goto locid_error;
if( buffer[6] != 0 )
goto locid_error;
//Check local ID
if( (int)buffer[21] == localID )
return hDevice;
//Check serial number
serial = (int)(buffer[15] + buffer[16]*256 + buffer[17]*65536 +
buffer[18]*16777216);
if( serial == localID )
return hDevice;
//No matches, not our device
LJUSB_CloseDevice(hDevice);
} //else localID >= 0 end
} //if hDevice != NULL end
} //for end
printf("Open error: could not find a U3 with a local ID or serial number of %d\n", localID);
return NULL;
locid_error:
printf("Open error: problem when checking local ID\n");
return NULL;
}
void closeUSBConnection(HANDLE hDevice)
{
LJUSB_CloseDevice(hDevice);
}
long getTickCount()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}
long isCalibrationInfoValid(u3CalibrationInfo *caliInfo)
{
if( caliInfo == NULL )
goto invalid;
if( caliInfo->prodID != 3 )
goto invalid;
return 1;
invalid:
printf("Error: Invalid calibration info.\n");
return 0;
}
long isTdacCalibrationInfoValid(u3TdacCalibrationInfo *caliInfo)
{
if( caliInfo == NULL )
goto invalid;
if( caliInfo->prodID != 3 )
goto invalid;
return 1;
invalid:
printf("Error: Invalid LJTDAC calibration info.\n");
return 0;
}
long getCalibrationInfo(HANDLE hDevice, u3CalibrationInfo *caliInfo)
{
uint8 sendBuffer[8], recBuffer[40];
uint8 cU3SendBuffer[26], cU3RecBuffer[38];
int sentRec = 0, offset = 0, i = 0;
/* Sending ConfigU3 command to get hardware version and see if HV */
cU3SendBuffer[1] = (uint8)(0xF8); //Command byte
cU3SendBuffer[2] = (uint8)(0x0A); //Number of data words
cU3SendBuffer[3] = (uint8)(0x08); //Extended command number
//Setting WriteMask0 and all other bytes to 0 since we only want to read the
//response
for( i = 6; i < 26; i++ )
cU3SendBuffer[i] = 0;
extendedChecksum(cU3SendBuffer, 26);
sentRec = LJUSB_Write(hDevice, cU3SendBuffer, 26);
if( sentRec < 26 )
{
if( sentRec == 0 )
goto writeError0;
else
goto writeError1;
}
sentRec = LJUSB_Read(hDevice, cU3RecBuffer, 38);
if( sentRec < 38 )
{
if( sentRec == 0 )
goto readError0;
else
goto readError1;
}
if( cU3RecBuffer[1] != (uint8)(0xF8) || cU3RecBuffer[2] != (uint8)(0x10) ||
cU3RecBuffer[3] != (uint8)(0x08))
goto commandByteError;
caliInfo->hardwareVersion = cU3RecBuffer[14] + cU3RecBuffer[13]/100.0;
if( (cU3RecBuffer[37] & 18) == 18 )
caliInfo->highVoltage = 1;
else
caliInfo->highVoltage = 0;
for( i = 0; i < 5; i++ )
{
/* Reading block i from memory */
sendBuffer[1] = (uint8)(0xF8); //Command byte
sendBuffer[2] = (uint8)(0x01); //Cumber of data words
sendBuffer[3] = (uint8)(0x2D); //Extended command number
sendBuffer[6] = 0;
sendBuffer[7] = (uint8)i; //Blocknum = i
extendedChecksum(sendBuffer, 8);
sentRec = LJUSB_Write(hDevice, sendBuffer, 8);
if( sentRec < 8 )
{
if( sentRec == 0 )
goto writeError0;
else
goto writeError1;
}
sentRec = LJUSB_Read(hDevice, recBuffer, 40);
if( sentRec < 40 )
{
if( sentRec == 0 )
goto readError0;
else
goto readError1;
}
if( recBuffer[1] != (uint8)(0xF8) || recBuffer[2] != (uint8)(0x11) ||
recBuffer[3] != (uint8)(0x2D) )
goto commandByteError;
offset = i * 4;
//Block data starts on byte 8 of the buffer
caliInfo->ccConstants[offset] = FPuint8ArrayToFPDouble(recBuffer + 8, 0);
caliInfo->ccConstants[offset + 1] = FPuint8ArrayToFPDouble(recBuffer + 8, 8);
caliInfo->ccConstants[offset + 2] = FPuint8ArrayToFPDouble(recBuffer + 8, 16);
caliInfo->ccConstants[offset + 3] = FPuint8ArrayToFPDouble(recBuffer + 8, 24);
}
caliInfo->prodID = 3;
return 0;
writeError0:
printf("Error : getCalibrationInfo write failed\n");
return -1;
writeError1:
printf("Error : getCalibrationInfo did not write all of the buffer\n");
return -1;
readError0:
printf("Error : getCalibrationInfo read failed\n");
return -1;
readError1:
printf("Error : getCalibrationInfo did not read all of the buffer\n");
return -1;
commandByteError:
printf("Error : getCalibrationInfo received wrong command bytes for ReadMem\n");
return -1;
}
long getTdacCalibrationInfo( HANDLE hDevice, u3TdacCalibrationInfo *caliInfo, uint8 DIOAPinNum)
{
int err;
uint8 options, speedAdjust, sdaPinNum, sclPinNum;
uint8 address, numByteToSend, numBytesToRec, errorcode;
uint8 bytesComm[1], bytesResp[32];
uint8 ackArray[4];
err = 0;
//Setting up I2C command for LJTDAC
options = 0; //I2COptions : 0
speedAdjust = 0; //SpeedAdjust : 0 (for max communication speed of about
//130 kHz)
sdaPinNum = DIOAPinNum+1; //SDAPinNum : FIO channel connected to pin DIOB
sclPinNum = DIOAPinNum; //SCLPinNum : FIO channel connected to pin DIOA
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numByteToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToRec = 32; //NumI2CBytesToReceive : getting 32 bytes starting at
//EEPROM address specified in I2CByte0
bytesComm[0] = 64; //I2CByte0 : Memory Address (starting at address 64,
// DACA Slope)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum,
sclPinNum, address, numByteToSend, numBytesToRec,
bytesComm, &errorcode, ackArray, bytesResp);
if( errorcode != 0 )
{
printf("Getting LJTDAC calibration info error : received errorcode %d in response\n", errorcode);
err = -1;
}
if( err == -1 )
return err;
caliInfo->ccConstants[0] = FPuint8ArrayToFPDouble(bytesResp, 0);
caliInfo->ccConstants[1] = FPuint8ArrayToFPDouble(bytesResp, 8);
caliInfo->ccConstants[2] = FPuint8ArrayToFPDouble(bytesResp, 16);
caliInfo->ccConstants[3] = FPuint8ArrayToFPDouble(bytesResp, 24);
caliInfo->prodID = 3;
return err;
}
double FPuint8ArrayToFPDouble(uint8 *buffer, int startIndex)
{
uint32 resultDec = 0, resultWh = 0;
resultDec = (uint32)buffer[startIndex] |
((uint32)buffer[startIndex + 1] << 8) |
((uint32)buffer[startIndex + 2] << 16) |
((uint32)buffer[startIndex + 3] << 24);
resultWh = (uint32)buffer[startIndex + 4] |
((uint32)buffer[startIndex + 5] << 8) |
((uint32)buffer[startIndex + 6] << 16) |
((uint32)buffer[startIndex + 7] << 24);
return ( (double)((int)resultWh) + (double)(resultDec)/4294967296.0 );
}
long getAinVoltCalibrated(u3CalibrationInfo *caliInfo, int dacEnabled, uint8 negChannel, uint16 bytesVolt, double *analogVolt)
{
if( isCalibrationInfoValid(caliInfo) == 0 )
return -1;
if( caliInfo->hardwareVersion >= 1.30 )
{
if( caliInfo->highVoltage == 1 )
{
printf("getAinVoltCalibrated error: cannot handle U3-HV device. Please use getAinVoltCalibrated_hw130 function.\n");
return -1;
}
else
return getAinVoltCalibrated_hw130(caliInfo, 0, negChannel, bytesVolt, analogVolt);
}
if( negChannel <= 15 || negChannel == 30 )
{
if( dacEnabled == 0 )
*analogVolt = caliInfo->ccConstants[2]*((double)bytesVolt) + caliInfo->ccConstants[3];
else
*analogVolt = (bytesVolt/65536.0)*caliInfo->ccConstants[11]*2.0 - caliInfo->ccConstants[11];
}
else if( negChannel == 31 )
{
if( dacEnabled == 0 )
*analogVolt = caliInfo->ccConstants[0]*((double)bytesVolt) + caliInfo->ccConstants[1];
else
*analogVolt = (bytesVolt/65536.0)*caliInfo->ccConstants[11];
}
else
{
printf("getAinVoltCalibrated error: invalid negative channel.\n");
return -1;
}
return 0;
}
long getAinVoltCalibrated_hw130(u3CalibrationInfo *caliInfo, uint8 positiveChannel, uint8 negChannel, uint16 bytesVolt, double *analogVolt)
{
if( isCalibrationInfoValid(caliInfo) == 0 )
return -1;
if( caliInfo->hardwareVersion < 1.30 )
{
printf("getAinVoltCalibrated_hw130 error: cannot handle U3 hardware versions < 1.30 . Please use getAinVoltCalibrated function.\n");
return -1;
}
if( negChannel <= 15 || negChannel == 30 )
{
if( caliInfo->highVoltage == 0
|| (caliInfo->highVoltage == 1 && positiveChannel >= 4 && negChannel >= 4) )
{
*analogVolt = caliInfo->ccConstants[2]*((double)bytesVolt) + caliInfo->ccConstants[3];
}
else if( caliInfo->hardwareVersion >= 1.30 && caliInfo->highVoltage == 1 )
{
printf("getAinVoltCalibrated_hw130 error: invalid negative channel for U3-HV.\n");
return -1;
}
}
else if( negChannel == 31 )
{
if( caliInfo->highVoltage == 1 && positiveChannel < 4 )
*analogVolt = caliInfo->ccConstants[12+positiveChannel]*((double)bytesVolt) + caliInfo->ccConstants[16+positiveChannel];
else
*analogVolt = caliInfo->ccConstants[0]*((double)bytesVolt) + caliInfo->ccConstants[1];
}
else if( negChannel == 32 ) //Special range (binary value should be from a
//diff. AIN reading with negative channel 30)
{
if( caliInfo->highVoltage == 1 && positiveChannel < 4 )
{
*analogVolt = (caliInfo->ccConstants[2]*((double)bytesVolt) + caliInfo->ccConstants[3] + caliInfo->ccConstants[9]) * caliInfo->ccConstants[12 + positiveChannel] / caliInfo->ccConstants[0] +
caliInfo->ccConstants[16 + positiveChannel];
}
else
{
*analogVolt = caliInfo->ccConstants[2]*((double)bytesVolt) + caliInfo->ccConstants[3] + caliInfo->ccConstants[9];
}
}
else
{
printf("getAinVoltCalibrated_hw130 error: invalid negative channel.\n");
return -1;
}
return 0;
}
long getDacBinVoltCalibrated(u3CalibrationInfo *caliInfo, int dacNumber, double analogVolt, uint8 *bytesVolt)
{
return getDacBinVoltCalibrated8Bit(caliInfo, dacNumber, analogVolt, bytesVolt);
}
long getDacBinVoltCalibrated8Bit(u3CalibrationInfo *caliInfo, int dacNumber, double analogVolt, uint8 *bytesVolt8)
{
double tBytesVolt;
if( isCalibrationInfoValid(caliInfo) == 0 )
return -1;
if( dacNumber < 0 || dacNumber > 2 )
{
printf("getDacBinVoltCalibrated8Bit error: invalid channelNumber.\n");
return -1;
}
tBytesVolt = analogVolt*caliInfo->ccConstants[4 + dacNumber*2] + caliInfo->ccConstants[5 + dacNumber*2];
//Checking to make sure bytesVolt will be a value between 0 and 255. Too
//high of an analogVoltage (about 4.95 and above volts) or too low (below 0
//volts) will cause a value not between 0 and 255.
if( tBytesVolt < 0 )
tBytesVolt = 0;
else if( tBytesVolt > 255 && caliInfo->hardwareVersion < 1.30 )
tBytesVolt = 255;
*bytesVolt8 = (uint8)tBytesVolt;
return 0;
}
long getDacBinVoltCalibrated16Bit(u3CalibrationInfo *caliInfo, int dacNumber, double analogVolt, uint16 *bytesVolt16)
{
double tBytesVolt;
if( isCalibrationInfoValid(caliInfo) == 0 )
return -1;
if( dacNumber < 0 || dacNumber > 2 )
{
printf("getDacBinVoltCalibrated16Bit error: invalid channelNumber.\n");
return -1;
}
if( caliInfo->hardwareVersion < 1.30 )
tBytesVolt = analogVolt*caliInfo->ccConstants[4 + dacNumber*2] + caliInfo->ccConstants[5 + dacNumber*2];
else
tBytesVolt = analogVolt*caliInfo->ccConstants[4 + dacNumber*2]*256 + caliInfo->ccConstants[5 + dacNumber*2]*256;
//Checking to make sure bytesVolt will be a value between 0 and 255/65535.
//Too high of an analogVoltage (about 4.95 and above volts) or too low
//(below 0 volts) will cause a value not between 0 and 255/65535.
if( tBytesVolt < 0 )
tBytesVolt = 0;
if( tBytesVolt > 65535 && caliInfo->hardwareVersion >= 1.30 )
tBytesVolt = 65535;
else if( tBytesVolt > 255 && caliInfo->hardwareVersion < 1.30 )
tBytesVolt = 255;
*bytesVolt16 = (uint16)tBytesVolt;
return 0;
}
long getTdacBinVoltCalibrated(u3TdacCalibrationInfo *caliInfo, int dacNumber, double analogVolt, uint16 *bytesVolt)
{
uint32 tBytesVolt;
if( isTdacCalibrationInfoValid(caliInfo) == 0 )
return -1;
if( dacNumber < 0 || dacNumber > 2 )
{
printf("getTdacBinVoltCalibrated error: invalid channelNumber.\n");
return -1;
}
tBytesVolt = analogVolt*caliInfo->ccConstants[dacNumber*2] + caliInfo->ccConstants[dacNumber*2 + 1];
//Checking to make sure bytesVolt will be a value between 0 and 65535.
if( tBytesVolt > 65535 )
tBytesVolt = 65535;
*bytesVolt = (uint16)tBytesVolt;
return 0;
}
long getTempKCalibrated(u3CalibrationInfo *caliInfo, uint32 bytesTemp, double *kelvinTemp)
{
if( isCalibrationInfoValid(caliInfo) == 0 )
return -1;
*kelvinTemp = caliInfo->ccConstants[8]*((double)bytesTemp);
return 0;
}
long getAinVoltUncalibrated(int dacEnabled, uint8 negChannel, uint16 bytesVolt, double *analogVolt)
{
U3_CALIBRATION_INFO_DEFAULT.hardwareVersion = 1.20;
U3_CALIBRATION_INFO_DEFAULT.highVoltage = 0;
return getAinVoltCalibrated(&U3_CALIBRATION_INFO_DEFAULT, dacEnabled, negChannel, bytesVolt, analogVolt);
}
long getAinVoltUncalibrated_hw130(int highVoltage, uint8 positiveChannel, uint8 negChannel, uint16 bytesVolt, double *analogVolt)
{
U3_CALIBRATION_INFO_DEFAULT.hardwareVersion = 1.30;
U3_CALIBRATION_INFO_DEFAULT.highVoltage = highVoltage;
return getAinVoltCalibrated_hw130(&U3_CALIBRATION_INFO_DEFAULT, positiveChannel, negChannel, bytesVolt, analogVolt);
}
long getDacBinVoltUncalibrated(int dacNumber, double analogVolt, uint8 *bytesVolt)
{
U3_CALIBRATION_INFO_DEFAULT.hardwareVersion = 1.20;
U3_CALIBRATION_INFO_DEFAULT.highVoltage = 0;
return getDacBinVoltCalibrated(&U3_CALIBRATION_INFO_DEFAULT, dacNumber, analogVolt, bytesVolt);
}
long getDacBinVoltUncalibrated8Bit(int dacNumber, double analogVolt, uint8 *bytesVolt8)
{
U3_CALIBRATION_INFO_DEFAULT.hardwareVersion = 1.20;
U3_CALIBRATION_INFO_DEFAULT.highVoltage = 0;
return getDacBinVoltCalibrated8Bit(&U3_CALIBRATION_INFO_DEFAULT, dacNumber, analogVolt, bytesVolt8);
}
long getDacBinVoltUncalibrated16Bit(int dacNumber, double analogVolt, uint16 *bytesVolt16)
{
U3_CALIBRATION_INFO_DEFAULT.hardwareVersion = 1.30;
U3_CALIBRATION_INFO_DEFAULT.highVoltage = 0;
return getDacBinVoltCalibrated16Bit(&U3_CALIBRATION_INFO_DEFAULT, dacNumber, analogVolt, bytesVolt16);
}
long getTempKUncalibrated(uint16 bytesTemp, double *kelvinTemp)
{
U3_CALIBRATION_INFO_DEFAULT.hardwareVersion = 1.20;
U3_CALIBRATION_INFO_DEFAULT.highVoltage = 0;
return getTempKCalibrated(&U3_CALIBRATION_INFO_DEFAULT, bytesTemp, kelvinTemp);
}
long I2C(HANDLE hDevice, uint8 I2COptions, uint8 SpeedAdjust, uint8 SDAPinNum, uint8 SCLPinNum, uint8 Address, uint8 NumI2CBytesToSend, uint8 NumI2CBytesToReceive, uint8 *I2CBytesCommand, uint8 *Errorcode, uint8 *AckArray, uint8 *I2CBytesResponse)
{
uint8 *sendBuff, *recBuff;
uint16 checksumTotal = 0;
uint32 ackArrayTotal, expectedAckArray;
int sendChars, recChars, sendSize, recSize;
int i, ret;
*Errorcode = 0;
ret = 0;
sendSize = 6 + 8 + ((NumI2CBytesToSend%2 != 0)?(NumI2CBytesToSend + 1):(NumI2CBytesToSend));
recSize = 6 + 6 + ((NumI2CBytesToReceive%2 != 0)?(NumI2CBytesToReceive + 1):(NumI2CBytesToReceive));
sendBuff = (uint8 *)malloc(sizeof(uint8)*sendSize);
recBuff = (uint8 *)malloc(sizeof(uint8)*recSize);
sendBuff[sendSize - 1] = 0;
//I2C command
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (sendSize - 6) / 2; //Number of data words = 4 + NumI2CBytesToSend
sendBuff[3] = (uint8)(0x3B); //extended command number
sendBuff[6] = I2COptions; //I2COptions
sendBuff[7] = SpeedAdjust; //SpeedAdjust
sendBuff[8] = SDAPinNum; //SDAPinNum
sendBuff[9] = SCLPinNum; //SCLPinNum
sendBuff[10] = Address; //Address
sendBuff[11] = 0; //Reserved
sendBuff[12] = NumI2CBytesToSend; //NumI2CByteToSend
sendBuff[13] = NumI2CBytesToReceive; //NumI2CBytesToReceive
for( i = 0; i < NumI2CBytesToSend; i++ )
sendBuff[14 + i] = I2CBytesCommand[i]; //I2CByte
extendedChecksum(sendBuff, sendSize);
//Sending command to U3
sendChars = LJUSB_Write(hDevice, sendBuff, sendSize);
if( sendChars < sendSize )
{
if( sendChars == 0 )
printf("I2C Error : write failed\n");
else
printf("I2C Error : did not write all of the buffer\n");
ret = -1;
goto cleanmem;
}
//Reading response from U3
recChars = LJUSB_Read(hDevice, recBuff, recSize);
if( recChars < recSize )
{
if( recChars == 0 )
printf("I2C Error : read failed\n");
else
{
printf("I2C Error : did not read all of the buffer\n");
if( recChars >= 12 )
*Errorcode = recBuff[6];
}
ret = -1;
goto cleanmem;
}
*Errorcode = recBuff[6];
AckArray[0] = recBuff[8];
AckArray[1] = recBuff[9];
AckArray[2] = recBuff[10];
AckArray[3] = recBuff[11];
for( i = 0; i < NumI2CBytesToReceive; i++ )
I2CBytesResponse[i] = recBuff[12 + i];
if( (uint8)(extendedChecksum8(recBuff)) != recBuff[0] )
{
printf("I2C Error : read buffer has bad checksum (%d)\n", recBuff[0]);
ret = -1;
}
if( recBuff[1] != (uint8)(0xF8) )
{
printf("I2C Error : read buffer has incorrect command byte (%d)\n", recBuff[1]);
ret = -1;
}
if( recBuff[2] != (uint8)((recSize - 6)/2) )
{
printf("I2C Error : read buffer has incorrect number of data words (%d)\n", recBuff[2]);
ret = -1;
}
if( recBuff[3] != (uint8)(0x3B) )
{
printf("I2C Error : read buffer has incorrect extended command number (%d)\n", recBuff[3]);
ret = -1;
}
checksumTotal = extendedChecksum16(recBuff, recSize);
if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] || (uint8)(checksumTotal & 255) != recBuff[4])
{
printf("I2C error : read buffer has bad checksum16 (%u)\n", checksumTotal);
ret = -1;
}
//ackArray should ack the Address byte in the first ack bit, but did not
//until firmware 1.44
ackArrayTotal = AckArray[0] + AckArray[1]*256 + AckArray[2]*65536 + AckArray[3]*16777216;
expectedAckArray = pow(2.0, NumI2CBytesToSend+1)-1;
if( ackArrayTotal != expectedAckArray )
printf("I2C error : expected an ack of %u, but received %u\n", expectedAckArray, ackArrayTotal);
cleanmem:
free(sendBuff);
free(recBuff);
sendBuff = NULL;
recBuff = NULL;
return ret;
}
long eAIN(HANDLE Handle, u3CalibrationInfo *CalibrationInfo, long ConfigIO, long *DAC1Enable, long ChannelP, long ChannelN, double *Voltage, long Range, long Resolution, long Settling, long Binary, long Reserved1, long Reserved2)
{
uint8 sendDataBuff[3], recDataBuff[2];
uint8 FIOAnalog, EIOAnalog, curFIOAnalog, curEIOAnalog;
uint8 curTCConfig, settling, quicksample, Errorcode;
uint8 ErrorFrame, outDAC1Enable;
uint16 bytesVT;
int hv, isSpecialRange = 0;
long error;
double hwver;
if( isCalibrationInfoValid(CalibrationInfo) == 0 )
{
printf("eAIN error: calibration information is required");
return -1;
}
hwver = CalibrationInfo->hardwareVersion;
hv = CalibrationInfo->highVoltage;
if( ChannelP < 0 || (ChannelP > 15 && ChannelP != 30 && ChannelP != 31) )
{
printf("eAIN error: Invalid positive channel\n");
return -1;
}
if( ChannelN < 0 ||
(ChannelN > 15 && ChannelN != 30 && ChannelN != 31 && ChannelN != 32) ||
(hwver >= 1.30 && hv == 1 && ((ChannelP < 4 && ChannelN != 31 && ChannelN != 32) ||
ChannelN < 4)) )
{
printf("eAIN error: Invalid negative channel\n");
return -1;
}
if( ChannelN == 32 )
{
isSpecialRange = 1;
ChannelN = 30; //Set to 30 for the feedback packet. We'll set it back
//to 32 for conversion.
}
if( ConfigIO != 0 && !(hwver >= 1.30 && hv == 1 && ChannelP < 4) )
{
FIOAnalog = 0;
EIOAnalog = 0;
//Setting ChannelP and ChannelN channels to analog using FIOAnalog and
//EIOAnalog
if( ChannelP <= 7 )
FIOAnalog = pow(2, ChannelP);
else if( ChannelP <= 15 )
EIOAnalog = pow(2, (ChannelP - 8));
if( ChannelN <= 7 )
FIOAnalog = FIOAnalog | (int)pow(2, ChannelN);
else if( ChannelN <= 15 )
EIOAnalog = EIOAnalog | (int)pow(2, (ChannelN - 8));
//Using ConfigIO to get current FIOAnalog and EIOAnalog settings
if( (error = ehConfigIO(Handle, 0, 0, 0, 0, 0, &curTCConfig, &outDAC1Enable, &curFIOAnalog, &curEIOAnalog)) != 0 )
return error;
*DAC1Enable = outDAC1Enable;
if( !(FIOAnalog == curFIOAnalog && EIOAnalog == curEIOAnalog) )
{
//Creating new FIOAnalog and EIOAnalog settings
FIOAnalog = FIOAnalog | curFIOAnalog;
EIOAnalog = EIOAnalog | curEIOAnalog;
//Using ConfigIO to set new FIOAnalog and EIOAnalog settings
if( (error = ehConfigIO(Handle, 12, curTCConfig, 0, FIOAnalog, EIOAnalog, NULL, NULL, &curFIOAnalog, &curEIOAnalog)) != 0 )
return error;
}
}
/* Setting up Feedback command to read analog input */
sendDataBuff[0] = 1; //IOType is AIN
settling = (Settling != 0) ? 1 : 0;
quicksample = (Resolution != 0) ? 1 : 0;
sendDataBuff[1] = (uint8)ChannelP + settling*64 + quicksample*128; //Positive channel (bits 0-4), LongSettling (bit 6)
//QuickSample (bit 7)
sendDataBuff[2] = (uint8)ChannelN; //Negative channel
if( ehFeedback(Handle, sendDataBuff, 3, &Errorcode, &ErrorFrame, recDataBuff, 2) < 0 )
return -1;
if( Errorcode )
return (long)Errorcode;
bytesVT = recDataBuff[0] + recDataBuff[1]*256;
if( isSpecialRange )
{
ChannelN = 32; // Change the negative channel back to 32 from 30 for conversion.
}
if( Binary != 0 )
{
*Voltage = (double)bytesVT;
}
else
{
if( ChannelP == 30 )
{
if( getTempKCalibrated(CalibrationInfo, bytesVT, Voltage) < 0 )
return -1;
}
else
{
if( hwver < 1.30 )
error = getAinVoltCalibrated(CalibrationInfo, (int)(*DAC1Enable), ChannelN, bytesVT, Voltage);
else
error = getAinVoltCalibrated_hw130(CalibrationInfo, ChannelP, ChannelN, bytesVT, Voltage);
if( error < 0 )
return -1;
}
}
return 0;
}
long eDAC(HANDLE Handle, u3CalibrationInfo *CalibrationInfo, long ConfigIO, long Channel, double Voltage, long Binary, long Reserved1, long Reserved2)
{
uint8 sendDataBuff[3];
uint8 byteV, DAC1Enabled, Errorcode, ErrorFrame;
uint16 bytesV;
long error, sendSize;
if( isCalibrationInfoValid(CalibrationInfo) == 0 )
{
printf("eDAC error: calibration information is required");
return -1;
}
if( Channel < 0 || Channel > 1 )
{
printf("eDAC error: Invalid DAC channel\n");
return -1;
}
if( ConfigIO != 0 && Channel == 1 && CalibrationInfo->hardwareVersion < 1.30 )
{
//Using ConfigIO to enable DAC1
error = ehConfigIO(Handle, 2, 0, 1, 0, 0, NULL, &DAC1Enabled, NULL, NULL);
if( error != 0 )
return error;
}
/* Setting up Feedback command to set DAC */
if( CalibrationInfo->hardwareVersion < 1.30 )
{
sendSize = 2;
sendDataBuff[0] = 34 + Channel; //IOType is DAC0/1 (8 bit)
if( getDacBinVoltCalibrated8Bit(CalibrationInfo, (int)Channel, Voltage, &byteV) < 0 )
return -1;
sendDataBuff[1] = byteV; //Value
}
else
{
sendSize = 3;
sendDataBuff[0] = 38 + Channel; //IOType is DAC0/1 (16 bit)
if( getDacBinVoltCalibrated16Bit(CalibrationInfo, (int)Channel, Voltage, &bytesV) < 0 )
return -1;
sendDataBuff[1] = (uint8)(bytesV&255); //Value LSB
sendDataBuff[2] = (uint8)((bytesV&65280)/256); //Value MSB
}
if( ehFeedback(Handle, sendDataBuff, sendSize, &Errorcode, &ErrorFrame, NULL, 0) < 0 )
return -1;
if( Errorcode )
return (long)Errorcode;
return 0;
}
long eDI(HANDLE Handle, long ConfigIO, long Channel, long *State)
{
uint8 sendDataBuff[4], recDataBuff[1];
uint8 Errorcode, ErrorFrame, FIOAnalog, EIOAnalog;
uint8 curFIOAnalog, curEIOAnalog, curTCConfig;
long error;
if( Channel < 0 || Channel > 19 )
{
printf("eDI error: Invalid DI channel\n");
return -1;
}
if( ConfigIO != 0 && Channel <= 15 )
{
FIOAnalog = 255;
EIOAnalog = 255;
//Setting Channel to digital using FIOAnalog and EIOAnalog
if( Channel <= 7 )
FIOAnalog = 255 - pow(2, Channel);
else
EIOAnalog = 255 - pow(2, (Channel - 8));
//Using ConfigIO to get current FIOAnalog and EIOAnalog settings
error = ehConfigIO(Handle, 0, 0, 0, 0, 0, &curTCConfig, NULL, &curFIOAnalog, &curEIOAnalog);
if( error != 0 )
return error;
if( !(FIOAnalog == curFIOAnalog && EIOAnalog == curEIOAnalog) )
{
//Creating new FIOAnalog and EIOAnalog settings
FIOAnalog = FIOAnalog & curFIOAnalog;
EIOAnalog = EIOAnalog & curEIOAnalog;
//Using ConfigIO to set new FIOAnalog and EIOAnalog settings
error = ehConfigIO(Handle, 12, curTCConfig, 0, FIOAnalog, EIOAnalog, NULL, NULL, &curFIOAnalog, &curEIOAnalog);
if( error != 0 )
return error;
}
}
/* Setting up Feedback command to set digital Channel to input and to read from it */
sendDataBuff[0] = 13; //IOType is BitDirWrite
sendDataBuff[1] = Channel; //IONumber(bits 0-4) + Direction (bit 7)
sendDataBuff[2] = 10; //IOType is BitStateRead
sendDataBuff[3] = Channel; //IONumber
if( ehFeedback(Handle, sendDataBuff, 4, &Errorcode, &ErrorFrame, recDataBuff, 1) < 0 )
return -1;
if( Errorcode )
return (long)Errorcode;
*State = recDataBuff[0];
return 0;
}
long eDO(HANDLE Handle, long ConfigIO, long Channel, long State)
{
uint8 sendDataBuff[4];
uint8 Errorcode, ErrorFrame, FIOAnalog, EIOAnalog;
uint8 curFIOAnalog, curEIOAnalog, curTCConfig;
long error;
if( Channel < 0 || Channel > 19 )
{
printf("eD0 error: Invalid DI channel\n");
return -1;
}
if( ConfigIO != 0 && Channel <= 15 )
{
FIOAnalog = 255;
EIOAnalog = 255;
//Setting Channel to digital using FIOAnalog and EIOAnalog
if( Channel <= 7 )
FIOAnalog = 255 - pow(2, Channel);
else
EIOAnalog = 255 - pow(2, (Channel - 8));
//Using ConfigIO to get current FIOAnalog and EIOAnalog settings
error = ehConfigIO(Handle, 0, 0, 0, 0, 0, &curTCConfig, NULL, &curFIOAnalog, &curEIOAnalog);
if( error != 0 )
return error;
if( !(FIOAnalog == curFIOAnalog && EIOAnalog == curEIOAnalog) )
{
//Using ConfigIO to get current FIOAnalog and EIOAnalog settings
FIOAnalog = FIOAnalog & curFIOAnalog;
EIOAnalog = EIOAnalog & curEIOAnalog;
//Using ConfigIO to set new FIOAnalog and EIOAnalog settings
error = ehConfigIO(Handle, 12, curTCConfig, 0, FIOAnalog, EIOAnalog, NULL, NULL, &curFIOAnalog, &curEIOAnalog);
if( error != 0 )
return error;
}
}
/* Setting up Feedback command to set digital Channel to output and to set the state */
sendDataBuff[0] = 13; //IOType is BitDirWrite
sendDataBuff[1] = Channel + 128; //IONumber(bits 0-4) + Direction (bit 7)
sendDataBuff[2] = 11; //IOType is BitStateWrite
sendDataBuff[3] = Channel + 128*((State > 0) ? 1 : 0); //IONumber(bits 0-4) + State (bit 7)
if( ehFeedback(Handle, sendDataBuff, 4, &Errorcode, &ErrorFrame, NULL, 0) < 0 )
return -1;
if( Errorcode )
return (long)Errorcode;
return 0;
}
long eTCConfig(HANDLE Handle, long *aEnableTimers, long *aEnableCounters, long TCPinOffset, long TimerClockBaseIndex, long TimerClockDivisor, long *aTimerModes, double *aTimerValues, long Reserved1, long Reserved2)
{
uint8 sendDataBuff[8];
uint8 FIOAnalog, EIOAnalog, curFIOAnalog, curEIOAnalog;
uint8 TimerCounterConfig, curTimerCounterConfig, Errorcode, ErrorFrame;
int sendDataBuffSize, numTimers, numCounters, i;
long error;
if( TCPinOffset < 0 || TCPinOffset > 8 )
{
printf("eTCConfig error: Invalid TimerCounterPinOffset\n");
return -1;
}
/* ConfigTimerClock */
if( TimerClockBaseIndex == LJ_tc2MHZ || TimerClockBaseIndex == LJ_tc6MHZ ||
TimerClockBaseIndex == LJ_tc24MHZ || TimerClockBaseIndex == LJ_tc500KHZ_DIV ||
TimerClockBaseIndex == LJ_tc2MHZ_DIV || TimerClockBaseIndex == LJ_tc6MHZ_DIV ||
TimerClockBaseIndex == LJ_tc24MHZ_DIV)
{
TimerClockBaseIndex = TimerClockBaseIndex - 10;
}
else if( TimerClockBaseIndex == LJ_tc4MHZ || TimerClockBaseIndex == LJ_tc12MHZ ||
TimerClockBaseIndex == LJ_tc48MHZ || TimerClockBaseIndex == LJ_tc1MHZ_DIV ||
TimerClockBaseIndex == LJ_tc4MHZ_DIV || TimerClockBaseIndex == LJ_tc12MHZ_DIV ||
TimerClockBaseIndex == LJ_tc48MHZ_DIV)
{
TimerClockBaseIndex = TimerClockBaseIndex - 20;
}
error = ehConfigTimerClock(Handle, (uint8)(TimerClockBaseIndex + 128), (uint8)TimerClockDivisor, NULL, NULL);
if( error != 0 )
return error;
//Using ConfigIO to get current FIOAnalog and curEIOAnalog settings
error = ehConfigIO(Handle, 0, 0, 0, 0, 0, NULL, NULL, &curFIOAnalog, &curEIOAnalog);
if( error != 0 )
return error;
numTimers = 0;
numCounters = 0;
TimerCounterConfig = 0;
FIOAnalog = 255;
EIOAnalog = 255;
for( i = 0; i < 2; i++ )
{
if( aEnableTimers[i] != 0 )
numTimers++;
else
i = 999;
}
for( i = 0; i < 2; i++ )
{
if( aEnableCounters[i] != 0 )
{
numCounters++;
TimerCounterConfig += pow(2, (i+2));
}
}
TimerCounterConfig += numTimers + TCPinOffset*16;
for( i = 0; i < numCounters + numTimers; i++ )
{
if( i + TCPinOffset < 8 )
FIOAnalog = FIOAnalog - pow(2, i + TCPinOffset);
else
EIOAnalog = EIOAnalog - pow(2, (i + TCPinOffset - 8));
}
FIOAnalog = FIOAnalog & curFIOAnalog;
EIOAnalog = EIOAnalog & curEIOAnalog;
error = ehConfigIO(Handle, 13, TimerCounterConfig, 0, FIOAnalog, EIOAnalog, &curTimerCounterConfig, NULL, &curFIOAnalog, &curEIOAnalog);
if( error != 0 )
return error;
if( numTimers > 0 )
{
/* Feedback */
for( i = 0; i < 8; i++ )
sendDataBuff[i] = 0;
for( i = 0; i < numTimers; i++ )
{
sendDataBuff[i*4] = 43 + i*2; //TimerConfig
sendDataBuff[1 + i*4] = (uint8)aTimerModes[i]; //TimerMode
sendDataBuff[2 + i*4] = (uint8)(((long)aTimerValues[i])&0x00ff); //Value LSB
sendDataBuff[3 + i*4] = (uint8)((((long)aTimerValues[i])&0xff00)/256); //Value MSB
}
sendDataBuffSize = 4 * numTimers;
if( ehFeedback(Handle, sendDataBuff, sendDataBuffSize, &Errorcode, &ErrorFrame, NULL, 0) < 0 )
return -1;
if( Errorcode )
return (long)Errorcode;
}
return 0;
}
long eTCValues(HANDLE Handle, long *aReadTimers, long *aUpdateResetTimers, long *aReadCounters, long *aResetCounters, double *aTimerValues, double *aCounterValues, long Reserved1, long Reserved2)
{
uint8 sendDataBuff[12], recDataBuff[16], Errorcode, ErrorFrame;
int sendDataBuffSize, recDataBuffSize, i, j;
int numTimers, dataCountCounter, dataCountTimer;
/* Feedback */
numTimers = 0;
dataCountCounter = 0;
dataCountTimer = 0;
sendDataBuffSize = 0;
recDataBuffSize = 0;
for( i = 0; i < 2; i++ )
{
if( aReadTimers[i] != 0 || aUpdateResetTimers[i] != 0 )
{
sendDataBuff[sendDataBuffSize] = 42 + i*2; //Timer
sendDataBuff[1 + sendDataBuffSize] = ((aUpdateResetTimers[i] != 0) ? 1 : 0); //UpdateReset
sendDataBuff[2 + sendDataBuffSize] = (uint8)(((long)aTimerValues[i])&0x00ff); //Value LSB
sendDataBuff[3 + sendDataBuffSize] = (uint8)((((long)aTimerValues[i])&0xff00)/256); //Value MSB
sendDataBuffSize += 4;
recDataBuffSize += 4;
numTimers++;
}
}
for( i = 0; i < 2; i++ )
{
if( aReadCounters[i] != 0 || aResetCounters[i] != 0 )
{
sendDataBuff[sendDataBuffSize] = 54 + i; //Counter
sendDataBuff[1 + sendDataBuffSize] = ((aResetCounters[i] != 0) ? 1 : 0); //Reset
sendDataBuffSize += 2;
recDataBuffSize += 4;
}
}
if( ehFeedback(Handle, sendDataBuff, sendDataBuffSize, &Errorcode, &ErrorFrame, recDataBuff, recDataBuffSize) < 0 )
return -1;
if( Errorcode )
return (long)Errorcode;
for( i = 0; i < 2; i++ )
{
aTimerValues[i] = 0;
if( aReadTimers[i] != 0 )
{
for( j = 0; j < 4; j++ )
aTimerValues[i] += (double)((long)recDataBuff[j + dataCountTimer*4]*pow(2, 8*j));
}
if( aReadTimers[i] != 0 || aUpdateResetTimers[i] != 0 )
dataCountTimer++;
aCounterValues[i] = 0;
if( aReadCounters[i] != 0 )
{
for( j = 0; j < 4; j++ )
aCounterValues[i] += (double)((long)recDataBuff[j + numTimers*4 + dataCountCounter*4]*pow(2, 8*j));
}
if( aReadCounters[i] != 0 || aResetCounters[i] != 0 )
dataCountCounter++;
}
return 0;
}
long ehConfigIO(HANDLE hDevice, uint8 inWriteMask, uint8 inTimerCounterConfig, uint8 inDAC1Enable, uint8 inFIOAnalog, uint8 inEIOAnalog, uint8 *outTimerCounterConfig, uint8 *outDAC1Enable, uint8 *outFIOAnalog, uint8 *outEIOAnalog)
{
uint8 sendBuff[12], recBuff[12];
uint16 checksumTotal;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x03); //Number of data words
sendBuff[3] = (uint8)(0x0B); //Extended command number
sendBuff[6] = inWriteMask; //Writemask
sendBuff[7] = 0; //Reserved
sendBuff[8] = inTimerCounterConfig; //TimerCounterConfig
sendBuff[9] = inDAC1Enable; //DAC1 enable : not enabling
sendBuff[10] = inFIOAnalog; //FIOAnalog
sendBuff[11] = inEIOAnalog; //EIOAnalog
extendedChecksum(sendBuff, 12);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 12)) < 12 )
{
if( sendChars == 0 )
printf("ehConfigIO error : write failed\n");
else
printf("ehConfigIO error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 12)) < 12 )
{
if( recChars == 0 )
printf("ehConfigIO error : read failed\n");
else
printf("ehConfigIO error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 12);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("ehConfigIO error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("ehConfigIO error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ehConfigIO error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x03) || recBuff[3] != (uint8)(0x0B) )
{
printf("ehConfigIO error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ehConfigIO error : read buffer received errorcode %d\n", recBuff[6]);
return (int)recBuff[6];
}
if( outTimerCounterConfig != NULL )
*outTimerCounterConfig = recBuff[8];
if( outDAC1Enable != NULL )
*outDAC1Enable = recBuff[9];
if( outFIOAnalog != NULL )
*outFIOAnalog = recBuff[10];
if( outEIOAnalog != NULL )
*outEIOAnalog = recBuff[11];
return 0;
}
long ehConfigTimerClock(HANDLE hDevice, uint8 inTimerClockConfig, uint8 inTimerClockDivisor, uint8 *outTimerClockConfig, uint8 *outTimerClockDivisor)
{
uint8 sendBuff[10], recBuff[10];
uint16 checksumTotal;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x02); //Number of data words
sendBuff[3] = (uint8)(0x0A); //Extended command number
sendBuff[6] = 0; //Reserved
sendBuff[7] = 0; //Reserved
sendBuff[8] = inTimerClockConfig; //TimerClockConfig
sendBuff[9] = inTimerClockDivisor; //TimerClockDivisor
extendedChecksum(sendBuff, 10);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 10)) < 10 )
{
if( sendChars == 0 )
printf("ehConfigTimerClock error : write failed\n");
else
printf("ehConfigTimerClock error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 10)) < 10 )
{
if( recChars == 0 )
printf("ehConfigTimerClock error : read failed\n");
else
printf("ehConfigTimerClock error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 10);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("ehConfigTimerClock error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("ehConfigTimerClock error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ehConfigTimerClock error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x02) || recBuff[3] != (uint8)(0x0A) )
{
printf("ehConfigTimerClock error : read buffer has wrong command bytes\n");
return -1;
}
if( outTimerClockConfig != NULL )
*outTimerClockConfig = recBuff[8];
if( outTimerClockDivisor != NULL )
*outTimerClockDivisor = recBuff[9];
if( recBuff[6] != 0 )
{
printf("ehConfigTimerClock error : read buffer received errorcode %d\n", recBuff[6]);
return recBuff[6];
}
return 0;
}
long ehFeedback(HANDLE hDevice, uint8 *inIOTypesDataBuff, long inIOTypesDataSize, uint8 *outErrorcode, uint8 *outErrorFrame, uint8 *outDataBuff, long outDataSize)
{
uint8 *sendBuff, *recBuff;
uint16 checksumTotal;
int sendChars, recChars, sendDWSize, recDWSize;
int commandBytes, ret, i;
ret = 0;
commandBytes = 6;
if( ((sendDWSize = inIOTypesDataSize + 1)%2) != 0 )
sendDWSize++;
if( ((recDWSize = outDataSize + 3)%2) != 0 )
recDWSize++;
sendBuff = (uint8 *)malloc(sizeof(uint8)*(commandBytes + sendDWSize));
recBuff = (uint8 *)malloc(sizeof(uint8)*(commandBytes + recDWSize));
if( sendBuff == NULL || recBuff == NULL )
{
ret = -1;
goto cleanmem;
}
sendBuff[sendDWSize + commandBytes - 1] = 0;
/* Setting up Feedback command */
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = sendDWSize/2; //Number of data words (.5 word for echo, 1.5
// words for IOTypes)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
for( i = 0; i < inIOTypesDataSize; i++ )
sendBuff[i+commandBytes+1] = inIOTypesDataBuff[i];
extendedChecksum(sendBuff, (sendDWSize+commandBytes));
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, (sendDWSize+commandBytes))) < sendDWSize+commandBytes )
{
if( sendChars == 0 )
printf("ehFeedback error : write failed\n");
else
printf("ehFeedback error : did not write all of the buffer\n");
ret = -1;
goto cleanmem;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, (commandBytes+recDWSize))) < commandBytes+recDWSize )
{
if( recChars == -1 )
{
printf("ehFeedback error : read failed\n");
ret = -1;
goto cleanmem;
}
else if( recChars < 8 )
{
printf("ehFeedback error : response buffer is too small\n");
ret = -1;
goto cleanmem;
}
else
printf("ehFeedback error : did not read all of the expected buffer (received %d, expected %d )\n", recChars, commandBytes+recDWSize);
}
checksumTotal = extendedChecksum16(recBuff, recChars);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("ehFeedback error : read buffer has bad checksum16(MSB)\n");
ret = -1;
goto cleanmem;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("ehFeedback error : read buffer has bad checksum16(LBS)\n");
ret = -1;
goto cleanmem;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ehFeedback error : read buffer has bad checksum8\n");
ret = -1;
goto cleanmem;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) )
{
printf("ehFeedback error : read buffer has wrong command bytes \n");
ret = -1;
goto cleanmem;
}
*outErrorcode = recBuff[6];
*outErrorFrame = recBuff[7];
for( i = 0; i+commandBytes+3 < recChars && i < outDataSize; i++ )
outDataBuff[i] = recBuff[i+commandBytes+3];
cleanmem:
free(sendBuff);
free(recBuff);
sendBuff = NULL;
recBuff = NULL;
return ret;
}