📄 freeportreceive.c
字号:
mexErrMsgTxt("Parameter [baudrate] needs to be a scalar number.\n");
}
k = k + 1;
break;
case 2:
/* channel */
if(mxIsEmpty(prhs[k])) {
/* channel undefined -> raw data transmission */
myRawFlag = 1;
myChannel = 0; /* (ab)using 'channel 0' (admin) */
}
else {
/* channel defined -> formatted transmission */
myRawFlag = 0;
if(mxIsNumeric(prhs[k]) && !mxIsComplex(prhs[k])) {
/* get channel number */
myChannel = (unsigned int)mxGetScalar(prhs[k]);
if((myChannel < 0) || (myChannel > MAX_FREECOM_CHANNELS-1))
mexErrMsgTxt("Invalid channel number.\n");
}
else {
mexErrMsgTxt("Parameter [channel] needs to be a scalar number.\n");
}
}
#ifdef VERBOSE
mexPrintf("freePortReceive: Channel = %d\n", myChannel);
mexPrintf("freePortReceive: rawdata = %d\n", myRawFlag);
#endif /* VERBOSE */
k = k + 1;
break;
case 3:
/* number of elements */
if(mxIsNumeric(prhs[k]) && !mxIsComplex(prhs[k])) {
/* get number of elements */
myElements = (unsigned int)mxGetScalar(prhs[k]);
if((myElements <= 0) || (myElements > maxNUMELEMENTS))
mexErrMsgTxt("Invalid number of elements.\n");
/* set dimensions of the output array (n x 1) */
dims[0] = myElements;
dims[1] = 1;
}
else {
mexErrMsgTxt("Parameter [nElements] needs to be a scalar number.\n");
}
#ifdef VERBOSE
mexPrintf("freePortReceive: number of elements = %d\n", myElements);
#endif /* VERBOSE */
k = k + 1;
break;
case 4:
/* data type */
if(mxIsNumeric(prhs[k]) && !mxIsComplex(prhs[k])) {
/* get data type ID */
mydType = (unsigned char)mxGetScalar(prhs[k]);
if((mydType < 0) || (mydType > numDATATYPES-1))
mexErrMsgTxt("Invalid data type ID.\n");
}
else {
mexErrMsgTxt("Parameter [dataType] needs to be a scalar number.\n");
}
/* calculate telegram size */
buf_size = BuiltInDTypeSize[mydType] * myElements;
#ifdef VERBOSE
mexPrintf("freePortReceive: data type = %d\n", mydType);
#endif /* VERBOSE */
k = k + 1;
break;
case 5:
/* blockingFlag */
if(mxIsNumeric(prhs[k]) && !mxIsComplex(prhs[k])) {
/* get data type ID */
myBlockingFlag = (unsigned int)mxGetScalar(prhs[k]);
if((myBlockingFlag != 0) && (myBlockingFlag != 1))
mexErrMsgTxt("Invalid value of 'blockingFlag'.\n");
}
else {
mexErrMsgTxt("Parameter [blockingFlag] needs to be a scalar number.\n");
}
#ifdef VERBOSE
mexPrintf("freePortReceive: blockingFlag = %d\n", myBlockingFlag);
#endif /* VERBOSE */
k = k + 1;
break;
} /* switch */
} /* while [input paramters] */
#ifdef VERBOSE
mexPrintf("freePortReceive: Checked all inputs\n");
#endif /* VERBOSE */
/* prepare output array (1 column, 'nElements' rows) */
switch(mydType) {
case tSINGLE:
pArray = mxCreateNumericArray(2, (int const *)&dims[0], mxSINGLE_CLASS, mxREAL);
//mexPrintf("pArray created\n");
break;
case tINT8:
pArray = mxCreateNumericArray(2, (int const *)&dims[0], mxINT8_CLASS, mxREAL);
//mexPrintf("pArray created\n");
break;
case tUINT8:
pArray = mxCreateNumericArray(2, (int const *)&dims[0], mxUINT8_CLASS, mxREAL);
//mexPrintf("pArray created\n");
break;
case tINT16:
pArray = mxCreateNumericArray(2, (int const *)&dims[0], mxINT16_CLASS, mxREAL);
//mexPrintf("pArray created\n");
break;
case tUINT16:
pArray = mxCreateNumericArray(2, (int const *)&dims[0], mxUINT16_CLASS, mxREAL);
//mexPrintf("pArray created\n");
break;
case tINT32:
pArray = mxCreateNumericArray(2, (int const *)&dims[0], mxINT32_CLASS, mxREAL);
//mexPrintf("pArray created\n");
break;
case tUINT32:
pArray = mxCreateNumericArray(2, (int const *)&dims[0], mxUINT32_CLASS, mxREAL);
//mexPrintf("pArray created\n");
break;
case tBOOLEAN:
pArray = mxCreateNumericArray(2, (int const *)&dims[0], mxUINT32_CLASS, mxREAL);
//mexPrintf("pArray created\n");
break;
} /* switch(mydType) */
/* get pointer to output buffer */
outBuf = (unsigned char *)mxGetPr(pArray);
/* create output 'nElementsReceived' */
pArray2 = mxCreateDoubleMatrix(1, 1, mxREAL);
/* get pointer to output buffer */
outnEls = (double *)mxGetPr(pArray2);
/* initialize number of elements received */
*outnEls = 0.0;
#ifdef VERBOSE
mexPrintf("freePortReceive: Created output variables.\n");
#endif /* VERBOSE */
} /* else: syntax correct */
/* manage channels (workspace variable 'FreePortAdminVar') */
/* create 'FreePortAdminVar' in the base workspace -- if required (first use) */
if((FreePortAdminVar = mexGetVariable("base", "FreePortAdminVar")) == NULL) {
int i;
/* FreePortAdminVar doesn't exist -> create & initialise it */
FreePortAdminVar = mxCreateNumericMatrix(MAX_NUM_COM_PORTS, 1, mxUINT32_CLASS, mxREAL);
/* initialise the array to be stored in variable FreePortAdminVar */
myPtr = (myCOMPort **)mxGetPr(FreePortAdminVar);
/* initialise all COM port access pointers with NULL */
for(i=0; i<MAX_NUM_COM_PORTS; i++) myPtr[i] = NULL;
#ifdef VERBOSE
mexPrintf("FreePortAdminVar created\n");
#endif /* VERBOSE */
}
else {
/* 'FreePortAdminVar' already exists -> get pointer to data in FreePortAdminVar */
myPtr = (myCOMPort **)mxGetPr(FreePortAdminVar);
#ifdef VERBOSE
mexPrintf("FreePortAdminVar found in workspace.\n");
#endif /* VERBOSE */
}
/* open port */
/* only open port if it's not already open */
if(myPtr[myPort] == NULL) {
/* allocate memory for admin structure of this instance's COM port access */
if((adminP = (myCOMPort *)calloc(1, sizeof(myCOMPort))) == NULL) {
mexErrMsgTxt("freePortReceive: Problem during memory allocation [insufficient memory, adminP].\n");
}
/* initialize port access structure */
adminP->access_count = 1;
adminP->hCom = FreePortOpenConnection(myPort, myBaud);
/* store port access pointer in workspace variable */
myPtr[myPort] = adminP;
#ifdef VERBOSE
mexPrintf("freePortReceive: buffer size = %d\n", buf_size);
#endif /* VERBOSE */
}
/* export variable FreePortAdminVar to the base workspace */
mexPutVariable("base", "FreePortAdminVar", FreePortAdminVar);
#ifdef VERBOSE
mexPrintf("freePortReceive: All initialized -> checking COM buffer for data.\n");
#endif /* VERBOSE */
/* -------------------------------------------------------------------------------------------------- */
/* at this stage, the parameters have been checked and memory has been allocated -> wait for data ... */
/* -------------------------------------------------------------------------------------------------- */
/* myBlockingFlag */
do {
/* check COM port for newly arrived data */
if(checkCOMforData(adminP->hCom) > 0) {
#ifdef VERBOSE
mexPrintf("freePortReceive: Found data in COM buffer.\n");
#endif /* VERBOSE */
/* receive data... */
if(myRawFlag == 0) {
/* formatted telegrams -> receive header */
uint8_T myBuf[4];
#ifdef VERBOSE
mexPrintf("%d bytes in buffer\n", checkCOMforData(adminP->hCom));
#endif
/* receive first 4 data bytes from serial port buffer */
if (!Receive (adminP->hCom, myBuf, 4, &ReceiveTimeoutFlag, with_to_messages)) {
mexErrMsgTxt("freePortReceive: Error during reception of first 4 bytes.\n");
}
#ifdef VERBOSE
mexPrintf("Header: %d:%d:%d:%d\n", (uint16_T)myBuf[0], (uint16_T)myBuf[1], (uint16_T)myBuf[2], (uint16_T)myBuf[3]);
#endif /* VERBOSE */
/* determine telegram size, etc. */
channel = myBuf[1];
} else {
/* unformatted data -> channel number '0' (set above) */
channel = myChannel;
}
/* all remaining parameters are independent of the telegram format */
/* allocate memory for buffer (buf_size bytes) for the received channel and its admin structure, returns the access pointer */
if((admin = AllocateUserBuffer(channel, buf_size, mydType)) == NULL) {
mexErrMsgTxt("freePortReceive: Problem during memory allocation [insufficient memory, admin].\n");
}
/* store the access pointer in the global buffer contents variable */
freecomTelBuf[channel] = admin;
size = admin->buf_size;
buf = admin->buf;
/* receive remaining 'size' data bytes from serial port buffer */
if (!Receive (adminP->hCom, buf, size, &ReceiveTimeoutFlag, with_to_messages)) {
mexErrMsgTxt("freePortReceive: Error during reception of remaining bytes.\n");
}
#ifdef VERBOSE
/* host DLL -> echo... */
{
uint_T i;
mexPrintf("RxD < Channel[%d] ", channel);
/* new buffer... */
for(i=0; i<size; i++)
mexPrintf(":%d", (uint_T)buf[i]);
mexPrintf(":\n");
}
#endif /* VERBOSE */
/* indicate receipt of a telegram */
admin->buffer_full = 1;
/* break 'while' loop */
myBlockingFlag = 0;
} /* checkCOMforData() */
} while(myBlockingFlag == 1);
/* check if output of this instance needs updated... */
admin = freecomTelBuf[myChannel];
if(admin != NULL) {
if(admin->buffer_full) {
/* new data available -> descramble */
{
unsigned int fi;
unsigned char *pbuf = receivebuf;
for(fi=0; fi<myElements; fi++) {
/* single : ID = 0 */
/* int8 : ID = 1 */
/* uint8 : ID = 2 */
/* int16 : ID = 3 */
/* uint16 : ID = 4 */
/* int32 : ID = 5 */
/* uint32 : ID = 6 */
/* boolean : ID = 7 */
switch(mydType) {
case tSINGLE:
{
float *pData = (float *)buf;
float tData = (float)pData[fi];
*((float *)pbuf) = *(float *)(ReverseOrder4((unsigned char *)&tData));
pbuf += BuiltInDTypeSize[mydType];
}
break;
case tINT8:
*((int8_T *)pbuf) = (int8_T)(buf[fi]);
pbuf += BuiltInDTypeSize[mydType];
break;
case tUINT8:
*((uint8_T *)pbuf) = (uint8_T)(buf[fi]);
pbuf += BuiltInDTypeSize[mydType];
break;
case tINT16:
{
int16_T *pData = (int16_T *)buf;
int16_T tData = (int16_T)pData[fi];
*((int16_T *)pbuf) = *(int16_T *)(ReverseOrder2((unsigned char *)&tData));
pbuf += BuiltInDTypeSize[mydType];
}
break;
case tUINT16:
{
uint16_T *pData = (uint16_T *)buf;
uint16_T tData = (uint16_T)pData[fi];
*((uint16_T *)pbuf) = *(uint16_T *)(ReverseOrder2((unsigned char *)&tData));
pbuf += BuiltInDTypeSize[mydType];
}
break;
case tINT32:
{
int32_T *pData = (int32_T *)buf;
int32_T tData = (int32_T)pData[fi];
*((int32_T *)pbuf) = *(int32_T *)(ReverseOrder4((unsigned char *)&tData));
pbuf += BuiltInDTypeSize[mydType];
}
break;
case tUINT32:
{
uint32_T *pData = (uint32_T *)buf;
uint32_T tData = (uint32_T)pData[fi];
*((uint32_T *)pbuf) = *(uint32_T *)(ReverseOrder4((unsigned char *)&tData));
pbuf += BuiltInDTypeSize[mydType];
}
break;
case tBOOLEAN:
{
boolean_T *pData = (boolean_T *)buf;
boolean_T tData = (boolean_T)pData[fi];
*((boolean_T *)pbuf) = *(boolean_T *)(ReverseOrder2((unsigned char *)&tData));
pbuf += BuiltInDTypeSize[mydType];
}
//*((boolean *)pbuf) = (boolean)(pData[fi]);
//pbuf += BuiltInDTypeSize[mydType];
break;
} /* switch(mydType) */
} /* for */
} /* descramble */
/* new data might be for this instance -> copy appropriate data to the output array */
#ifdef VERBOSE
mexPrintf("freePortReceive: Copying %d bytes to output of channel %d\n", admin->buf_size, myChannel);
#endif
/* new data available for this instance -> update output */
memcpy(outBuf, receivebuf, admin->buf_size);
/* adjust number of elements received */
*outnEls = (double)myElements;
/* clear buffer full flag */
admin->buffer_full = 0;
} /* new data available for this instance */
} /* admin != NULL */
// TERMINATE, delete data buffers
#ifdef VERBOSE
mexPrintf("freePortReceive: Terminating - freeing buffers\n");
#endif
/* update workspace variable 'FreePortAdminVar' */
if((FreePortAdminVar = mexGetVariable("base", "FreePortAdminVar")) == NULL) {
// do nothing, just exit
mexErrMsgTxt("freePortReceive: Error accessing workspace variable FreePortAdminVar (terminating).\n");
}
else {
myUsrBuf *admin = freecomTelBuf[myChannel];
if(admin != NULL) {
/* yep -> close channel and free memory */
free(admin->buf);
free(admin);
/* reset the channel specific access pointer */
freecomTelBuf[myChannel] = NULL;
}
/* get FreePortAdminVar */
myPtr = (myCOMPort **)mxGetPr(FreePortAdminVar);
/* decrement port access pointer */
myPtr[myPort]->access_count -= 1;
/* check access counter */
if(myPtr[myPort]->access_count == 0) {
/* close port */
FreePortCloseConnection(myPtr[myPort]->hCom);
/* delete port access structure */
free(myPtr[myPort]);
myPtr[myPort] = NULL;
}
/* export variable FreePortAdminVar to the base workspace */
mexPutVariable("base", "FreePortAdminVar", FreePortAdminVar);
} /* FreeBufferAdminVar exists */
// return output array pointer (always)
#ifdef VERBOSE
mexPrintf("freePortReceive: Returning output array.\n");
#endif
plhs[0] = pArray;
plhs[1] = pArray2;
} /* end mexFunction */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -