⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freeportcomms_rxd.c

📁 simulink real-time workshop for dragon12 development board from
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Function: mdlCheckParameters ===============================================
 *
 */
#define MDL_CHECK_PARAMETERS
#if defined(MDL_CHECK_PARAMETERS)
static void mdlCheckParameters(SimStruct *S)
{
	// check parameter: SAMPLE_TIME
	if (mxGetNumberOfElements(SAMPLE_TIME_ARG) != 1)					abort_LED(36);	// parameter must be a scalar
	if ((SAMPLE_TIME < 0) && (SAMPLE_TIME != INHERITED_SAMPLE_TIME))	abort_LED(36);	// invalid negative sample time

	// check parameter: CHANNEL_NO
	if (mxGetNumberOfElements(CHANNEL_NO_ARG) != 1)						abort_LED(37);	// parameter must be a scalar
	if ((CHANNEL_NO < 0) || (CHANNEL_NO >= MAX_FREECOM_CHANNELS))			abort_LED(37);	// invalid channel number

	// check parameter: NUM_ELEMENTS
	if (mxGetNumberOfElements(NUM_ELEMENTS_ARG) != 1)					abort_LED(38);	// parameter must be a scalar
	if ((NUM_ELEMENTS < 1) || 
		(BuiltInDTypeSize[DATA_TYPE-1] * NUM_ELEMENTS > MAX_FREECOM_BUF_SIZE))	abort_LED(38);	// inadmissible buffer size
}
#endif /* MDL_CHECK_PARAMETERS */



/* Function: mdlInitializeSizes ===============================================
 *
 */
static void mdlInitializeSizes (SimStruct *S) {

int_T	i;

	ssSetNumSFcnParams(S, NUMBER_OF_ARG);											// expected number of parameters
	if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S))  abort_LED(35);			// incorrect number of parameters
	else {

		#ifdef MDL_CHECK_PARAMETERS
		mdlCheckParameters(S);							// check all parameters
		#endif
	}


	/* setup sizes of both work vectors and state vectors */
	ssSetNumIWork (S, 1);						// instance-local integer value: channel number
	//ssSetNumRWork (S, 0);						// no instance-local real values
	ssSetNumPWork (S, 1);						// instance-local pointer: access to this channel's port access structure
	//ssSetNumDWork (S, 0);						// no instance-local user data types used
	//ssSetNumContStates (S, 0);				// width of the instance-local vector of continuous states
	//ssSetNumDiscStates (S, 0);				// width of the instance-local vector of discrete states
	

	/* define number of sample times used by this s-function */
	ssSetNumSampleTimes (S, 1);					// only 'one' sampletime in this S-Function

	// None of this s-functions's parameters are tunable during simulation (sample time, channel, buffer size, data type)
	for (i=0; i<NUMBER_OF_ARG; i++) ssSetSFcnParamNotTunable(S, i);


	if(!ssSetNumInputPorts(S, 0))	abort_LED(39);			// block has a single input...
	if(!ssSetNumOutputPorts(S, 1))	abort_LED(39);			// ... and no output (-> sink)

	ssSetOutputPortWidth(S, 0, NUM_ELEMENTS);				// block output width : number of elements
	ssSetOutputPortDataType(S, 0, DATA_TYPE);				// data type: '1' = 'single', '2' = 'int8_T', ... (no '0' -> no 'double')
}



/* Function: mdlInitializeSampleTimes =========================================
 *
 */
static void mdlInitializeSampleTimes (SimStruct *S) {

   ssSetSampleTime(S, 0, SAMPLE_TIME);				// this S-Function only has 'one' sampletime -> index '0'
   ssSetOffsetTime(S, 0, 0.0);

}



/* Function: mdlStart =========================================================
 *
 */
#define MDL_START
static void mdlStart(SimStruct *S) {
	
	/* make sure this instance relatest to a COM port -> host model (PORT = 3 -> COM1, PORT = 4 -> COM2, etc.) */
	if(PORT > 2) {

		void		**PWork = ssGetPWork(S);
		uint8_T		data_type = BuiltInDTypeSize[DATA_TYPE-1];		// first possible 'DATA_TYPE' is '1' ('sinle') -> map this to '0' (beginning of array)
		uint_T		buf_size = 	data_type * NUM_ELEMENTS;
		mxArray		*FreePortAdminVar;
		myCOMPort   **myPtr;
		myUsrBuf	*admin;
		myCOMPort   *adminP = NULL;
		uint_T      i, *IWork = ssGetIWork(S);
				

		#ifdef VERBOSE
		mexPrintf("freePortComms_rxd|mdlStart: IN\n");
		#endif /* VERBOSE */
		
		/* ensure we're using channel '0' for raw data transmissions */
		if(FORMAT == 1)  IWork[0] = 0;
		else             IWork[0] = CHANNEL_NO;
		
		/* create 'FreePortAdminVar' in the base workspace -- if required (first use) */
		if((FreePortAdminVar = mexGetVariable("base", "FreePortAdminVar")) == NULL) {

			/* 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 */
		}


		/* allocate memory for buffer (buf_size bytes) for channel 'IWork[0]' and its admin structure, returns the access pointer */
		if((admin = AllocateUserBuffer(IWork[0], buf_size, data_type)) == NULL) {
			mexErrMsgTxt("FreePortComms_rxd: Problem during memory allocation [insufficient memory, admin].\n");
		}
				
		/* store the access pointer in the global buffer contents variable */
		freecomTelBuf[IWork[0]] = admin;     /* IWork[0] = instance local channel number */
					

		/* only open port if it's not already open */
		if(myPtr[PORT-3] == NULL) {

			/* allocate memory for admin structure of this instance's COM port access */
			if((adminP = (myCOMPort *)calloc(1, sizeof(myCOMPort))) == NULL) {
				mexErrMsgTxt("FreePortComms_rxd: Problem during memory allocation [insufficient memory, adminP].\n");
			}
		
			/* initialize port access structure */
			adminP->access_count = 0;
			adminP->hCom = FreePortOpenConnection(S);

			/* store port access pointer in workspace variable */
			myPtr[PORT-3] = adminP;

		}

		/* initialize instance local pointer to the port access structure */
		PWork[0] = myPtr[PORT-3];

		/* increase port access pointer */
		myPtr[PORT-3]->access_count += 1;

		/* export variable FreePortAdminVar to the base workspace */
		mexPutVariable("base", "FreePortAdminVar", FreePortAdminVar);

		#ifdef VERBOSE
		mexPrintf("freePortComms_rxd|mdlStart: OUT\n");
		#endif /* VERBOSE */

	} /* COM port */

}



/*
 * mdlOutputs - compute the outputs
 *
 * In this function, you compute the outputs of your S-function
 * block.  The outputs are placed in the y variable.
 */
static void mdlOutputs(SimStruct *S, int_T tid) {

	/* make sure this instance relatest to a COM port -> host model (PORT = 3 -> COM1, PORT = 4 -> COM2, etc.) */
	if(PORT > 2) {

		uint_T    *IWork      = ssGetIWork(S);     /* channel number */
		uint16_T  channel;
		myUsrBuf  *admin;
		uint16_T  size;
		uint8_T   *buf;
		uint8_T   *blockOutput = (uint8_T *)ssGetOutputPortSignal(S, 0);
		myCOMPort *adminP = ssGetPWorkValue(S, 0);


		/* check COM port for newly arrived data */
		if(checkCOMforData(adminP->hCom) > 0) {

			if(FORMAT == 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("freePortComms_rxd: 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 -> take channel number from IWork[0] */
				channel = IWork[0];

			}

			/* all remaining parameters are independent of the telegram format */
			admin   = freecomTelBuf[channel];
			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("freePortComms_rxd: 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;

		} /* checkCOMforData() */

		
		/* check if output of this instance needs updated... */
		admin = freecomTelBuf[IWork[0]];       /* IWork[0] : channel number */

		if(admin->buffer_full) {

			/* new data available -> descramble */
			{
				
				unsigned int	fi;
				unsigned int	mydType = DATA_TYPE-1;
				unsigned char	*pbuf = receivebuf;

				for(fi=0; fi<NUM_ELEMENTS; 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 block outputs */
			#ifdef VERBOSE
			mexPrintf("Copying %d bytes to output of channel %d\n", admin->buf_size, IWork[0]);
			#endif

			/* new data available for this instance -> update output */
			memcpy(blockOutput, receivebuf, admin->buf_size);

			/* clear buffer full flag */
			admin->buffer_full = 0;

		} /* admin-buffer_full == 1 */

	}	/* COM port */

}



/*
 * mdlTerminate - called when the simulation is terminated.
 *
 * In this function, you should perform any actions that are necessary
 * at the termination of a simulation.  For example, if memory was allocated
 * in mdlInitializeConditions, this is the place to free it.
 */
static void mdlTerminate (SimStruct *S) {
	
	/* make sure this instance relatest to a COM port -> host model (PORT = 3 -> COM1, PORT = 4 -> COM2, etc.) */
	if(PORT > 2) {

		mxArray		*FreePortAdminVar;
		uint_T      *IWork = ssGetIWork(S);     /* channel number */

		/* update workspace variable 'FreePortAdminVar' */
		if((FreePortAdminVar = mexGetVariable("base", "FreePortAdminVar")) == NULL) {

			// do nothing, just exit
			mexErrMsgTxt("freePortComms_rxd: Error accessing workspace variable FreePortAdminVar (mdlTerminate).\n");
		
		}
		else {

			myUsrBuf	*admin = freecomTelBuf[IWork[0]];          /* IWork[0] : channel number */
			myCOMPort	**myPtr;
		
			/* yep -> close channel and free memory */
			free(admin->buf);
			free(admin);

			/* reset the channel specific access pointer */
			freecomTelBuf[IWork[0]] = NULL;                      /* IWork[0] : channel number */

			/* get FreePortAdminVar */
			myPtr = (myCOMPort **)mxGetPr(FreePortAdminVar);

			/* decrement port access pointer */
			myPtr[PORT-3]->access_count -= 1;
		
			/* check access counter */
			if(myPtr[PORT-3]->access_count == 0) {

				/* close port */
				FreePortCloseConnection(myPtr[PORT-3]->hCom);

				/* delete port access structure */
				free(myPtr[PORT-3]);
				myPtr[PORT-3] = NULL;

			}

			/* export variable FreePortAdminVar to the base workspace */
			mexPutVariable("base", "FreePortAdminVar", FreePortAdminVar);

		} /* FreePortAdminVar exists */

	} /* COM port */

}


// the define 'MATLAB_MEX_FILE' has to be specified when recompiling this module to a DLL.
// this is only required if the format of the call-up parameters is modified... (FW-06-01)
#ifdef MATLAB_MEX_FILE
   #include "simulink.c"
#else
# error "Attempt to use freePortComms_rxd.c as non-inlined S-function"
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -