//Author: LabJack //May 25, 2011 //Example UE9 helper functions. Function descriptions are in ue9.h. #include "ue9.h" ue9CalibrationInfo UE9_CALIBRATION_INFO_DEFAULT = { 9, //Nominal Values { 0.000077503, -0.012, 0.000038736, -0.012, 0.000019353, -0.012, 0.0000096764, -0.012, 0.00015629, -5.176, 842.59, 0.0, 842.259, 0.0, 0.012968, 0.012968, 298.15, 2.43, 0.0, 1.215, 0.00009272, 0.000077503, -0.012, 0.00015629, -5.176} }; 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) { BYTE buffer[38]; uint16 checksumTotal = 0; uint32 numDevices = 0; uint32 dev; int i, serial; HANDLE hDevice = 0; numDevices = LJUSB_GetDevCount(UE9_PRODUCT_ID); if( numDevices == 0 ) { printf("Open error: No UE9 devices could be found\n"); return NULL; } for( dev = 1; dev <= numDevices; dev++ ) { hDevice = LJUSB_OpenDevice(dev, 0, UE9_PRODUCT_ID); if( hDevice != NULL ) { if( localID < 0 ) { return hDevice; } else { checksumTotal = 0; //Setting up a CommConfig command buffer[1] = (BYTE)(0x78); buffer[2] = (BYTE)(0x10); buffer[3] = (BYTE)(0x01); for( i = 6; i < 38; i++ ) buffer[i] = (BYTE)(0x00); extendedChecksum(buffer,38); if( LJUSB_Write(hDevice, buffer, 38) != 38 ) goto locid_error; for( i = 0; i < 38; i++ ) buffer[i] = 0; if( LJUSB_Read(hDevice, buffer, 38) != 38 ) goto locid_error; checksumTotal = extendedChecksum16(buffer, 38); if( (BYTE)((checksumTotal / 256) & 0xFF) != buffer[5] ) goto locid_error; if( (BYTE)(checksumTotal & 0xFF) != buffer[4] ) goto locid_error; if( extendedChecksum8(buffer) != buffer[0] ) goto locid_error; if( buffer[1] != (BYTE)(0x78) || buffer[2] != (BYTE)(0x10) || buffer[3] != (BYTE)(0x01) ) goto locid_error; //Check local ID if( (int)buffer[8] == localID ) return hDevice; //Check serial number serial = buffer[28] + buffer[29]*256 + buffer[30]*65536 + 0x10000000; 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 UE9 with a local ID or serial number of %d\n", localID); return NULL; locid_error: printf("Open error: problem when checking local ID and serial number\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 getCalibrationInfo(HANDLE hDevice, ue9CalibrationInfo *caliInfo) { BYTE sendBuffer[8], recBuffer[136]; int sentRec = 0, i = 0, j = 0, ccTotal = 0, count = 0; /* Setting up command */ sendBuffer[1] = (BYTE)(0xF8); //command byte sendBuffer[2] = (BYTE)(0x01); //number of data words sendBuffer[3] = (BYTE)(0x2A); //extended command number sendBuffer[6] = (BYTE)(0x00); for( i = 0; i < 5; i++ ) { /* Reading block 1 from memory */ sendBuffer[7] = (BYTE)i; //Blocknum = i extendedChecksum(sendBuffer, 8); sentRec = LJUSB_Write(hDevice, sendBuffer, 8); if( sentRec < 8 ) { if( sentRec == 0 ) printf("getCalibrationInfo error : write failed\n"); else printf("getCalibrationInfo error : did not write all of the buffer\n"); return -1; } sentRec = LJUSB_Read(hDevice, recBuffer, 136); if( sentRec < 136 ) { if( sentRec == 0 ) printf("getCalibrationInfo Error : read failed\n"); else printf("getCalibrationInfo Error : did not read all of the buffer\n"); } if( recBuffer[1] != (BYTE)(0xF8) || recBuffer[2] != (BYTE)(0x41) || recBuffer[3] != (BYTE)(0x2A) ) { printf("getCalibrationInfo error: incorrect command bytes for ReadMem response"); return -1; } //Reading out calbration constants if( i == 0 ) ccTotal = 8; if( i == 1 ) ccTotal = 2; if( i == 2 ) ccTotal = 13; if( i == 3 ) ccTotal = 2; if( i == 4 ) ccTotal = 2; for( j = 0; j < ccTotal; j++ ) { if( i != 2 || (i == 2 && j != 5 && j != 7) ) { //Block data starts on byte 8 of the buffer caliInfo->ccConstants[count] = FPuint8ArrayToFPDouble(recBuffer + 8, j*8); count++; } } } caliInfo->prodID = 9; return 0; } long getTdacCalibrationInfo(HANDLE hDevice, ue9TdacCalibrationInfo *caliInfo, uint8 DIOAPinNum) { int err; uint8 options, speedAdjust, sdaPinNum, sclPinNum; uint8 address, numByteToSend, numBytesToReceive, errorcode; uint8 bytesCommand[1]; uint8 bytesResponse[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 numBytesToReceive = 32; //NumI2CBytesToReceive : getting 32 bytes starting at EEPROM address specified in I2CByte0 bytesCommand[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, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 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(bytesResponse, 0); caliInfo->ccConstants[1] = FPuint8ArrayToFPDouble(bytesResponse, 8); caliInfo->ccConstants[2] = FPuint8ArrayToFPDouble(bytesResponse, 16); caliInfo->ccConstants[3] = FPuint8ArrayToFPDouble(bytesResponse, 24); caliInfo->prodID = 9; 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 isCalibrationInfoValid(ue9CalibrationInfo *caliInfo) { if( caliInfo == NULL ) goto invalid; if( caliInfo->prodID != 9 ) goto invalid; return 1; invalid: printf("Error: Invalid calibration info.\n"); return 0; } long isTdacCalibrationInfoValid(ue9TdacCalibrationInfo *caliInfo) { if( caliInfo == NULL ) goto invalid; if( caliInfo->prodID != 9 ) goto invalid; return 1; invalid: printf("Error: Invalid LJTDAC calibration info.\n"); return 0; } long getAinVoltCalibrated(ue9CalibrationInfo *caliInfo, uint8 gainBip, uint8 resolution, uint16 bytesVolt, double *analogVolt) { if( isCalibrationInfoValid(caliInfo) == 0 ) return -1; if( resolution < 18 ) { if( gainBip <= 3 || gainBip == 8 ) { if( gainBip == 8 ) gainBip = 4; //setting this for index purposes *analogVolt = (caliInfo->ccConstants[gainBip*2]*bytesVolt) + caliInfo->ccConstants[gainBip*2 + 1]; return 0; } else goto invalidGainBip; } else //UE9 Pro high res { if( gainBip == 0 || gainBip == 8 ) { if( gainBip == 8 ) gainBip = 1; //setting this for index purposes *analogVolt = (caliInfo->ccConstants[gainBip*2 + 21]*bytesVolt) + caliInfo->ccConstants[gainBip*2 + 22]; return 0; } else goto invalidGainBip; } invalidGainBip: printf("getAinVoltCalibrated error: invalid GainBip.\n"); return -1; } long getDacBinVoltCalibrated(ue9CalibrationInfo *caliInfo, int dacNumber, double analogVolt, uint16 *bytesVolt) { double tBytesVolt; if( isCalibrationInfoValid(caliInfo) == 0 ) return -1; if( dacNumber < 0 || dacNumber > 2 ) { printf("getDacBinVoltCalibrated error: invalid channelNumber.\n"); return -1; } tBytesVolt = analogVolt*caliInfo->ccConstants[10 + dacNumber*2] + caliInfo->ccConstants[11 + dacNumber*2]; //Checking to make sure bytesVoltage will be a value between 0 and 4095, or //that a uint16 overflow does not occur. A too high analogVoltage (above 5 //volts) or too low analogVoltage (below 0 volts) will cause a value not //between 0 and 4095. if( tBytesVolt < 0 ) tBytesVolt = 0; if( tBytesVolt > 4095 ) tBytesVolt = 4095; *bytesVolt = (uint16)tBytesVolt; return 0; } long getTdacBinVoltCalibrated(ue9TdacCalibrationInfo *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(ue9CalibrationInfo *caliInfo, int powerLevel, uint16 bytesTemp, double *kelvinTemp) { if( isCalibrationInfoValid(caliInfo) == 0 ) return -1; if( powerLevel == 0 || powerLevel == 1 ) { *kelvinTemp = caliInfo->ccConstants[14 + powerLevel]*bytesTemp; return 0; } else { printf("getTempKCalibrated error: invalid powerLevel.\n"); return -1; } } long getAinVoltUncalibrated(uint8 gainBip, uint8 resolution, uint16 bytesVolt, double *analogVolt) { return getAinVoltCalibrated(&UE9_CALIBRATION_INFO_DEFAULT, gainBip, resolution, bytesVolt, analogVolt); } long getDacBinVoltUncalibrated(int dacNumber, double analogVolt, uint16 *bytesVolt) { return getDacBinVoltCalibrated(&UE9_CALIBRATION_INFO_DEFAULT, dacNumber, analogVolt, bytesVolt); } long getTempKUncalibrated(int powerLevel, uint16 bytesTemp, double *kelvinTemp) { return getTempKCalibrated(&UE9_CALIBRATION_INFO_DEFAULT, powerLevel, 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, 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 UE9 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 UE9 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 & 0xFF) != 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 control firmware 1.84 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, ue9CalibrationInfo *CalibrationInfo, long ChannelP, long ChannelN, double *Voltage, long Range, long Resolution, long Settling, long Binary, long Reserved1, long Reserved2) { uint8 IOType, Channel, AINM, AINH, ainGain; uint16 bytesVT; if( isCalibrationInfoValid(CalibrationInfo) == 0 ) { printf("eAIN error: calibration information is required"); return -1; } if( Range == LJ_rgBIP5V ) ainGain = 8; else if( Range == LJ_rgUNI5V ) ainGain = 0; else if( Range == LJ_rgUNI2P5V ) ainGain = 1; else if( Range == LJ_rgUNI1P25V ) ainGain = 2; else if( Range == LJ_rgUNIP625V ) ainGain = 3; else { printf("eAIN error: Invalid Range\n"); return -1; } if( ehSingleIO(Handle, 4, (uint8)ChannelP, ainGain, (uint8)Resolution, (uint8)Settling, &IOType, &Channel, NULL, &AINM, &AINH) < 0 ) return -1; bytesVT = AINM + AINH*256; if( Binary != 0 ) { *Voltage = (double)bytesVT; } else { if( ChannelP == 133 || ChannelP == 141 ) { if( getTempKCalibrated(CalibrationInfo, 0, bytesVT, Voltage) < 0 ) return -1; } else { if( getAinVoltCalibrated(CalibrationInfo, ainGain, (uint8)Resolution, bytesVT, Voltage) < 0 ) return -1; } } return 0; } long eDAC(HANDLE Handle, ue9CalibrationInfo *CalibrationInfo, long Channel, double Voltage, long Binary, long Reserved1, long Reserved2) { uint8 IOType, channel; uint16 bytesVoltage; if( isCalibrationInfoValid(CalibrationInfo) == 0 ) { printf("eDAC error: calibration information is required"); return -1; } if( getDacBinVoltCalibrated(CalibrationInfo, (uint8)Channel, Voltage, &bytesVoltage) < 0 ) return -1; return ehSingleIO(Handle, 5, (uint8)Channel, (uint8)( bytesVoltage & (0x00FF) ), (uint8)(( bytesVoltage /256 ) + 192), 0, &IOType, &channel, NULL, NULL, NULL); } long eDI(HANDLE Handle, long Channel, long *State) { uint8 state; if( Channel > 22 ) { printf("eDI error: Invalid Channel"); return -1; } if( ehDIO_Feedback(Handle, (uint8)Channel, 0, &state) < 0 ) return -1; *State = state; return 0; } long eDO(HANDLE Handle, long Channel, long State) { uint8 state; state = (uint8)State; if( Channel > 22 ) { printf("eDO error: Invalid Channel"); return -1; } return ehDIO_Feedback(Handle, (uint8)Channel, 1, &state); } long eTCConfig(HANDLE Handle, long *aEnableTimers, long *aEnableCounters, long TCPinOffset, long TimerClockBaseIndex, long TimerClockDivisor, long *aTimerModes, double *aTimerValues, long Reserved1, long Reserved2) { uint8 enableMask, timerMode[6], counterMode[2]; uint16 timerValue[6]; int numTimers, numTimersStop, i; //Setting EnableMask enableMask = 128; //Bit 7: UpdateConfig if(aEnableCounters[1] != 0) enableMask += 16; //Bit 4: Enable Counter1 if(aEnableCounters[0] != 0) enableMask += 8; //Bit 3: Enable Counter0 numTimers = 0; numTimersStop = 0; for( i = 0; i < 6; i++ ) { if( aEnableTimers[i] != 0 && numTimersStop == 0 ) { numTimers++; timerMode[i] = (uint8)aTimerModes[i]; //TimerMode timerValue[i] = (uint16)aTimerValues[i]; //TimerValue } else { numTimersStop = 1; timerMode[i] = 0; timerValue[i] = 0; } } enableMask += numTimers; //Bits 2-0: Number of Timers counterMode[0] = 0; //Counter0Mode counterMode[1] = 0; //Counter1Mode return ehTimerCounter(Handle, (uint8)TimerClockDivisor, enableMask, (uint8)TimerClockBaseIndex, 0, timerMode, timerValue, counterMode, NULL, NULL); } long eTCValues(HANDLE Handle, long *aReadTimers, long *aUpdateResetTimers, long *aReadCounters, long *aResetCounters, double *aTimerValues, double *aCounterValues, long Reserved1, long Reserved2) { uint8 updateReset, timerMode[6], counterMode[2]; uint16 timerValue[6]; uint32 timer[6], counter[2]; int i; long errorcode; //UpdateReset updateReset = 0; for( i = 0; i < 6; i++ ) { updateReset += ((aUpdateResetTimers[i] != 0) ? pow(2, i) : 0); timerMode[i] = 0; timerValue[i] = 0; } for( i = 0; i < 2; i++ ) { updateReset += ((aResetCounters[i] != 0) ? pow(2, 6 + i) : 0); counterMode[i] = 0; } if( (errorcode = ehTimerCounter(Handle, 0, 0, 0, updateReset, timerMode, timerValue, counterMode, timer, counter)) != 0 ) return errorcode; for( i = 0; i < 6; i++ ) aTimerValues[i] = timer[i]; for( i = 0; i < 2; i++ ) aCounterValues[i] = counter[i]; return 0; } long ehSingleIO(HANDLE hDevice, uint8 inIOType, uint8 inChannel, uint8 inDirBipGainDACL, uint8 inStateResDACH, uint8 inSettlingTime, uint8 *outIOType, uint8 *outChannel, uint8 *outDirAINL, uint8 *outStateAINM, uint8 *outAINH) { BYTE sendBuff[8], recBuff[8]; int sendChars, recChars; sendBuff[1] = (BYTE)(0xA3); //Command byte sendBuff[2] = inIOType; //IOType sendBuff[3] = inChannel; //Channel sendBuff[4] = inDirBipGainDACL; //Dir/BipGain/DACL sendBuff[5] = inStateResDACH; //State/Resolution/DACH sendBuff[6] = inSettlingTime; //Settling time sendBuff[7] = 0; //Reserved sendBuff[0] = normalChecksum8(sendBuff, 8); //Sending command to UE9 sendChars = LJUSB_Write(hDevice, sendBuff, 8); if( sendChars < 8 ) { if( sendChars == 0 ) printf("SingleIO error : write failed\n"); else printf("SingleIO error : did not write all of the buffer\n"); return -1; } //Reading response from UE9 recChars = LJUSB_Read(hDevice, recBuff, 8); if( recChars < 8 ) { if( recChars == 0 ) printf("SingleIO error : read failed\n"); else printf("SingleIO error : did not read all of the buffer\n"); return -1; } if( (BYTE)(normalChecksum8(recBuff, 8)) != recBuff[0] ) { printf("SingleIO error : read buffer has bad checksum\n"); return -1; } if( recBuff[1] != (BYTE)(0xA3) ) { printf("SingleIO error : read buffer has wrong command byte\n"); return -1; } if( outIOType != NULL ) *outIOType = recBuff[2]; if( outChannel != NULL ) *outChannel = recBuff[3]; if( outDirAINL != NULL ) *outDirAINL = recBuff[4]; if( outStateAINM != NULL ) *outStateAINM = recBuff[5]; if( outAINH != NULL ) *outAINH = recBuff[6]; return 0; } long ehDIO_Feedback(HANDLE hDevice, uint8 channel, uint8 direction, uint8 *state) { BYTE sendBuff[34], recBuff[64]; BYTE tempDir, tempState, tempByte; uint16 checksumTotal; int sendChars, recChars, i; sendBuff[1] = (BYTE)(0xF8); //Command byte sendBuff[2] = (BYTE)(0x0E); //Number of data words sendBuff[3] = (BYTE)(0x00); //Extended command number for( i = 6; i < 34; i++ ) sendBuff[i] = 0; tempDir = ((direction < 1) ? 0 : 1); tempState = ((*state < 1) ? 0 : 1); if( channel <= 7 ) { tempByte = pow(2, channel); sendBuff[6] = tempByte; if( tempDir ) sendBuff[7] = tempByte; if( tempState ) sendBuff[8] = tempByte; } else if( channel <= 15 ) { tempByte = pow(2, (channel - 8)); sendBuff[9] = tempByte; if( tempDir ) sendBuff[10] = tempByte; if( tempState ) sendBuff[11] = tempByte; } else if( channel <= 19 ) { tempByte = pow(2, (channel - 16)); sendBuff[12] = tempByte; if( tempDir ) sendBuff[13] = tempByte*16; if( tempState ) sendBuff[13] += tempByte; } else if( channel <= 22 ) { tempByte = pow(2, (channel - 20)); sendBuff[14] = tempByte; if( tempDir ) sendBuff[15] = tempByte*16; if( tempState ) sendBuff[15] += tempByte; } else { printf("DIO Feedback error: Invalid Channel\n"); return -1; } extendedChecksum(sendBuff, 34); //Sending command to UE9 sendChars = LJUSB_Write(hDevice, sendBuff, 34); if( sendChars < 34 ) { if( sendChars == 0 ) printf("DIO Feedback error : write failed\n"); else printf("DIO Feedback error : did not write all of the buffer\n"); return -1; } //Reading response from UE9 recChars = LJUSB_Read(hDevice, recBuff, 64); if( recChars < 64 ) { if( recChars == 0 ) printf("DIO Feedback error : read failed\n"); else printf("DIO Feedback error : did not read all of the buffer\n"); return -1; } checksumTotal = extendedChecksum16(recBuff, 64); if( (BYTE)((checksumTotal / 256) & 0xFF) != recBuff[5] ) { printf("DIO Feedback error : read buffer has bad checksum16(MSB)\n"); return -1; } if( (BYTE)(checksumTotal & 0xFF) != recBuff[4] ) { printf("DIO Feedback error : read buffer has bad checksum16(LSB)\n"); return -1; } if( extendedChecksum8(recBuff) != recBuff[0] ) { printf("DIO Feedback error : read buffer has bad checksum8\n"); return -1; } if( recBuff[1] != (BYTE)(0xF8) || recBuff[2] != (BYTE)(0x1D) || recBuff[3] != (BYTE)(0x00) ) { printf("DIO Feedback error : read buffer has wrong command bytes\n"); return -1; } if( channel <= 7 ) *state = ((recBuff[7] & tempByte) ? 1 : 0); else if( channel <= 15 ) *state = ((recBuff[9] & tempByte) ? 1 : 0); else if( channel <= 19 ) *state = ((recBuff[10] & tempByte) ? 1 : 0); else if( channel <= 22 ) *state = ((recBuff[11] & tempByte) ? 1 : 0); return 0; } long ehTimerCounter(HANDLE hDevice, uint8 inTimerClockDivisor, uint8 inEnableMask, uint8 inTimerClockBase, uint8 inUpdateReset, uint8 *inTimerMode, uint16 *inTimerValue, uint8 *inCounterMode, uint32 *outTimer, uint32 *outCounter) { BYTE sendBuff[30], recBuff[40]; uint16 checksumTotal; int sendChars, recChars, i, j; sendBuff[1] = (BYTE)(0xF8); //Command byte sendBuff[2] = (BYTE)(0x0C); //Number of data words sendBuff[3] = (BYTE)(0x18); //Extended command number sendBuff[6] = inTimerClockDivisor; //TimerClockDivisor sendBuff[7] = inEnableMask; //EnableMask sendBuff[8] = inTimerClockBase; //TimerClockBase sendBuff[9] = inUpdateReset; //UpdateReset for( i = 0; i < 6; i++ ) { sendBuff[10 + i*3] = inTimerMode[i]; //TimerMode sendBuff[11 + i*3] = (BYTE)(inTimerValue[i] & 0x00FF); //TimerValue (low byte) sendBuff[12 + i*3] = (BYTE)((inTimerValue[i] & 0xFF00)/256); //TimerValue (high byte) } for( i = 0; i < 2; i++ ) sendBuff[28 + i] = inCounterMode[i]; //CounterMode extendedChecksum(sendBuff, 30); //Sending command to UE9 sendChars = LJUSB_Write(hDevice, sendBuff, 30); if( sendChars < 30 ) { if( sendChars == 0 ) printf("ehTimerCounter error : write failed\n"); else printf("ehTimerCounter error : did not write all of the buffer\n"); return -1; } //Reading response from UE9 recChars = LJUSB_Read(hDevice, recBuff, 40); if( recChars < 40 ) { if( recChars == 0 ) printf("ehTimerCounter error : read failed\n"); else printf("ehTimerCounter error : did not read all of the buffer\n"); return -1; } checksumTotal = extendedChecksum16(recBuff, 40); if( (BYTE)((checksumTotal / 256) & 0xFF) != recBuff[5] ) { printf("ehTimerCounter error : read buffer has bad checksum16(MSB)\n"); return -1; } if( (BYTE)(checksumTotal & 0xFF) != recBuff[4] ) { printf("ehTimerCounter error : read buffer has bad checksum16(LBS)\n"); return -1; } if( extendedChecksum8(recBuff) != recBuff[0] ) { printf("ehTimerCounter error : read buffer has bad checksum8\n"); return -1; } if( recBuff[1] != (BYTE)(0xF8) || recBuff[2] != (BYTE)(0x11) || recBuff[3] != (BYTE)(0x18) ) { printf("ehTimerCounter error : read buffer has wrong command bytes for TimerCounter\n"); return -1; } if( outTimer != NULL ) { for( i = 0; i < 6; i++ ) { outTimer[i] = 0; for( j = 0; j < 4; j++ ) outTimer[i] += recBuff[8 + j + i*4] * pow(2, 8*j); } } if( outCounter != NULL ) { for( i = 0; i < 2; i++ ) { outCounter[i] = 0; for( j = 0; j < 4; j++ ) outCounter[i] += recBuff[32 + j + i*4] * pow(2, 8*j); } } return recBuff[6]; }