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

📄 freeportcomms_txd.c

📁 simulink real-time workshop for dragon12 development board from
💻 C
📖 第 1 页 / 共 2 页
字号:
	}
	#endif /* VERBOSE */

	temp   = buf[0];
	buf[0] = buf[3];
	buf[3] = temp;
	temp   = buf[1];
	buf[1] = buf[2];
	buf[2] = temp;
	
	#ifdef VERBOSE
	{
		mexPrintf("%d:%d:%d:%d\n", buf[0], buf[1], buf[2], buf[3]);
	}
	#endif /* VERBOSE */
	
	return (void *)buf;
	
}


/* Function: ReverseOrder2 =================================================
 *
 *  Reverse the order of bytes in a 2-tuple
 */
void *ReverseOrder2(unsigned char *buf) {

unsigned char	temp;

	#ifdef VERBOSE
	{
		mexPrintf("ReverseOrder2 %d:%d >> ", buf[0], buf[1]);
	}
	#endif /* VERBOSE */

	temp   = buf[0];
	buf[0] = buf[1];
	buf[1] = temp;
	
	#ifdef VERBOSE
	{
		mexPrintf("%d:%d\n", buf[0], buf[1]);
	}
	#endif /* VERBOSE */
	
	return (void *)buf;
	
}



// ----------------------------------------------------------------------------------------------------
// S-Function methods
// ----------------------------------------------------------------------------------------------------

/* 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, 1))	abort_LED(39);			// block has a single input...
	if(!ssSetNumOutputPorts(S, 0))	abort_LED(39);			// ... and no output (-> sink)

	ssSetInputPortWidth(S, 0, NUM_ELEMENTS);				// input width: number of elements

	//mexPrintf("Data type: %d\n", DATA_TYPE);

	ssSetInputPortDataType(S, 0, DATA_TYPE);				// block initialization code (mbc_userteltxd.m) adjusts this to '1' ... (no '0' = 'double')
	ssSetInputPortDirectFeedThrough(S, 0, 1);				// direct feedthrough (only executs after update of inputs)
	ssSetInputPortRequiredContiguous(S, 0, 1);				// ports to be stored contiguously in memory

}



/* 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) {
	
	/* check if this instance relates 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' ('single') -> 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_txd|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;

		}
		else {

			/* 'FreePortAdminVar' already exists -> get pointer to data in FreePortAdminVar */
			myPtr = (myCOMPort **)mxGetPr(FreePortAdminVar);

		}


		/* 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_txd: 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_txd: 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_txd|mdlStart: OUT\n");
		#endif /* VERBOSE */

	}

}



/*
 * 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) {

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

		uint_T    *IWork      = ssGetIWork(S);     /* channel number */
		myUsrBuf  *admin      = freecomTelBuf[IWork[0]];
		uint_T    size        = admin->buf_size;
		uint8_T   *buf		  = admin->buf;
		uint8_T	  *blockInput = (uint8_T *)ssGetInputPortSignal(S, 0);
		myCOMPort *adminP     = ssGetPWorkValue(S, 0);

		/* buffer empty -> check if new user data has arrived */
		if(memcmp(buf+4, blockInput, (uint16_T)size) != 0) {

			/* new data available -> copy to data buffer */
			memcpy(buf+4, blockInput, (uint16_T)size);

			/* copy data to transmission buffer */
			{
				
				unsigned int	fi;
				unsigned int	mydType = DATA_TYPE-1;
				unsigned char	*pbuf = sendbuf;

				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+4);
							float	tData = (float)pData[fi];
							
							*((float *)pbuf) = *(float *)(ReverseOrder4((unsigned char *)&tData));
							pbuf += BuiltInDTypeSize[mydType];
						}
						break;
						
					case tINT8:
						
						*((int8_T *)pbuf) = (int8_T)(buf[4+fi]);
						pbuf += BuiltInDTypeSize[mydType];
						break;
						
					case tUINT8:
						
						*((uint8_T *)pbuf) = (uint8_T)(buf[4+fi]);
						pbuf += BuiltInDTypeSize[mydType];
						break;
						
					case tINT16:
						{
							int16_T	*pData = (int16_T *)(buf+4);
							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+4);
							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+4);
							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+4);
							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+4);
							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 */
				
			} /* copy elements to transmission buffer */
			

			
			/* download data to the target */
			if(FORMAT == 0) {

				/* formatted telegram */
				#ifdef VERBOSE
				{

					uint_T	i;
		
					mexPrintf("TxD > Channel[%d] ", IWork[0]);

					/* new buffer... */
					for(i=4; i<size+4; i++)
						mexPrintf(":%d", sendbuf[i]);
		
					mexPrintf(":\n");
		
				}
				#endif /* VERBOSE */

				
				#ifdef VERBOSE
				mexPrintf("Sending header... ");
				#endif /* VERBOSE */
				Send(adminP->hCom, buf, (DWORD)4, no_echo, &SendTimeoutFlag, with_to_messages);

			}

			/* raw data */
			#ifdef VERBOSE
			mexPrintf("sending data (%d bytes).\n", size);
			#endif /* VERBOSE */
			Send(adminP->hCom, sendbuf, (DWORD)size, no_echo, &SendTimeoutFlag, with_to_messages);

		} /* if : new user data available */

	} /* 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) {
	
	/* check if this instance relates 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_txd: 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_txd.c as non-inlined S-function"
#endif

⌨️ 快捷键说明

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