www.pudn.com > communication-systems-using-MATLAB-m-files.rar > homopuls.c


/* $Revision: 1.23 $ */ 
/* 
 * HOMOPULS   A Simulink homonic pulse generator. 
 * 
 *           Syntax:  [sys, x0] = homopuls(t,x,u,flag,sample,divider,offset) 
 * 
 * Wes Wang  8/18/1994 revised 1/24/1996. 
 * Copyright 1996-2001 The MathWorks, Inc. 
 */ 
 
#define S_FUNCTION_NAME homopuls 
 
#ifdef MATLAB_MEX_FILE 
#include "mex.h"      /* needed for declaration of mexErrMsgTxt */ 
#endif 
 
/* 
 * need to include simstruc.h for the definition of the SimStruct and 
 * its associated macro definitions. 
 */ 
 
#include "simstruc.h" 
#include "tmwtypes.h" 
#include  
 
/* For RTW */ 
#if defined(RT) || defined(NRT)   
#undef  mexPrintf 
#define mexPrintf printf 
#endif 
 
/* 
 * Defines for easy access of the input parameters 
 */ 
 
#define NUM_ARGS     3 
#define SAMPLE_TIME       ssGetArg(S,0) 
#define DIVIDER_EACH      ssGetArg(S,1) 
#define OFFSET_EACH       ssGetArg(S,2) 
 
/* 
 * mdlInitializeSizes - called to initialize the sizes array stored in 
 *                      the SimStruct.  The sizes array defines the 
 *                      characteristics (number of inputs, outputs, 
 *                      states, etc.) of the S-Function. 
 */ 
 
static int_T isclose(real_T a, real_T b) 
{ 
#define EPS       4.656612875245797e-10    /*  reciprocal of 2^31-1 */ 
     real_T diff; 
 
#ifdef MATLAB_MEX_FILE 
    if (0) { 
      char_T err_msg[255]; 
      sprintf(err_msg, "a %f, b %f \n", a, b); 
      mexPrintf(err_msg); 
    }  
#endif 
     
     diff = fabs(a - b); 
     if (diff * 1.e-5 /(fabs(a) + EPS) < EPS) 
       return(1); 
     else 
       return(0); 
} 
 
static void mdlInitializeSizes(SimStruct *S) 
{ 
  /* 
   * Set-up size information. 
   */  
  int_T NumSampleTime; 
 
  if (ssGetNumArgs(S) == NUM_ARGS) { 
    int_T dividerSize; 
    if ((mxGetN(SAMPLE_TIME) * mxGetM(SAMPLE_TIME)) > 1) { 
#ifdef MATLAB_MEX_FILE 
      mexErrMsgTxt("The sample time is a scalar."); 
#endif 
    } 
     
    if ((mxGetN(DIVIDER_EACH) != 1) && (mxGetM(DIVIDER_EACH) != 1)) { 
#ifdef MATLAB_MEX_FILE 
      mexErrMsgTxt("The divider must be a vector"); 
#endif 
    } 
                
    if ((mxGetN(OFFSET_EACH) != 1) && (mxGetM(OFFSET_EACH) != 1)) { 
#ifdef MATLAB_MEX_FILE 
      mexErrMsgTxt("The offset must be a vector"); 
#endif 
    } 
                
    if ((mxGetN(OFFSET_EACH) * (mxGetM(OFFSET_EACH))) != ((mxGetN(DIVIDER_EACH) * (mxGetM(DIVIDER_EACH))))) { 
#ifdef MATLAB_MEX_FILE 
      mexErrMsgTxt("Divider and Offset must have the same length"); 
#endif 
    } 
     
    dividerSize = mxGetN(DIVIDER_EACH) * mxGetM(DIVIDER_EACH); 
    NumSampleTime = dividerSize; 
    if (dividerSize > 0) { 
       real_T sampleTime, sampleTimeI, offsetTimeI; 
       int_T    adj, i; 
       real_T *past_sample, *past_offset; 
        
       past_sample = (real_T *)calloc(dividerSize, sizeof(real_T)); 
       past_offset = (real_T *)calloc(dividerSize, sizeof(real_T)); 
 
       sampleTime = mxGetPr(SAMPLE_TIME)[0]; 
       NumSampleTime = 0; 
       for (i=0; i < dividerSize; i++) { 
         offsetTimeI = mxGetPr(OFFSET_EACH)[i]; 
         sampleTimeI = sampleTime/2./mxGetPr(DIVIDER_EACH)[i]; 
         if (sampleTimeI <= 0) { 
#ifdef MATLAB_MEX_FILE 
	     mexErrMsgTxt("Sample time must be positive number."); 
#endif 
         } 
         while  (offsetTimeI < 0) 
            offsetTimeI += sampleTimeI; 
         adj = (int_T)(offsetTimeI / sampleTimeI); 
         offsetTimeI = offsetTimeI - ((real_T)adj) * sampleTimeI; 
 
#ifdef MATLAB_MEX_FILE 
         if (0) { 
           char_T err_msg[255]; 
           sprintf(err_msg, "Iteration %d, offsetTimeI %f, sampleTimeI %f \n", i, offsetTimeI, sampleTimeI); 
           mexPrintf(err_msg); 
         }      
#endif 
 
	 if ((isclose(offsetTimeI, 0.0)) || (isclose(offsetTimeI, sampleTimeI))) 
	   offsetTimeI = 0; 
	 if (i > 0) { 
	   int_T test_flag, ii; 
	   test_flag = 1; 
	   for (ii = 0; ii 0) { 
    real_T sampleTime, sampleTimeI, offsetTimeI; 
    int_T    adj, i; 
    real_T *past_sample, *past_offset; 
        
    past_sample = (real_T *)calloc(dividerSize, sizeof(real_T)); 
    past_offset = (real_T *)calloc(dividerSize, sizeof(real_T)); 
 
    sampleTime = mxGetPr(SAMPLE_TIME)[0]; 
    NumSampleTime = 0; 
    for (i=0; i < dividerSize; i++) { 
      offsetTimeI = mxGetPr(OFFSET_EACH)[i]; 
      sampleTimeI = sampleTime/2./mxGetPr(DIVIDER_EACH)[i]; 
      while  (offsetTimeI < 0) 
         offsetTimeI += sampleTimeI; 
 
      adj = (int_T)(offsetTimeI / sampleTimeI); 
      offsetTimeI = offsetTimeI - ((real_T)adj) * sampleTimeI; 
      if ((isclose(offsetTimeI, 0.0)) || (isclose(offsetTimeI, sampleTimeI))) 
	offsetTimeI = 0; 
      while  (offsetTimeI > sampleTimeI) 
        offsetTimeI -= sampleTimeI; 
      if (i > 0) { 
	int_T test_flag, ii; 
	test_flag = 1; 
	for (ii = 0; ii NumSmpTm) { 
#ifdef MATLAB_MEX_FILE 
        mexErrMsgTxt("Check your sample time and offset time. It is not consistant."); 
#endif 
      } 
    } 
    free(past_sample); 
    free(past_offset); 
  } 
#ifdef MATLAB_MEX_FILE 
  if (0) { 
      char_T err_msg[255]; 
      sprintf(err_msg, "NumSampleTime %d: \n", NumSampleTime); 
      mexPrintf(err_msg); 
  } 
#endif 
    ssSetNumContStates(    S, 0); 
    ssSetNumDiscStates(    S, 0); 
} 
 
/* 
 * mdlInitializeConditions - initializes the states for the S-Function 
 */ 
 
static void mdlInitializeConditions(real_T *x0, SimStruct *S) 
{ 
 
  int_T dividerSize = mxGetN(DIVIDER_EACH) * mxGetM(DIVIDER_EACH); 
  int_T offsetSize  = mxGetN(OFFSET_EACH) * mxGetM(OFFSET_EACH); 
 
  real_T *hit_base   = ssGetRWork(S); 
  real_T *next_hit   = ssGetRWork(S) + 1;     
  real_T *last_value = ssGetRWork(S) + dividerSize + 1; 
  real_T *increment  = ssGetRWork(S) + dividerSize * 2 + 1; 
  real_T *adj_offset = ssGetRWork(S) + dividerSize * 3 + 1; 
  real_T *tolerance  = ssGetRWork(S) + dividerSize * 4 + 1; 
  int_T  *reverse    = ssGetIWork(S);         
  real_T  sampleTime, offsetTime, offsetMin, tmp, tol; 
  int_T   i, adj; 
   
  dividerSize = (dividerSize < offsetSize) ? dividerSize : offsetSize; 
 
  offsetMin = mxGetPr(OFFSET_EACH)[0]; 
  sampleTime = mxGetPr(SAMPLE_TIME)[0]; 
  /*  
   * Initialize the last_accs to all zeros. 
   */ 
  tol = sampleTime; 
  for (i = 0; i < dividerSize; i++) { 
    *last_value++ = 0.; 
     
    offsetTime = mxGetPr(OFFSET_EACH)[i];         
    offsetMin = (offsetMin < offsetTime) ? offsetMin : offsetTime; 
     
    next_hit[i] = offsetTime; 
     
    tmp = sampleTime/2./mxGetPr(DIVIDER_EACH)[i]; 
    increment[i] = tmp; 
     
    tol = (tol < tmp) ? tol : tmp; 
     
    adj = (int_T)(offsetTime / tmp); 
    tmp = offsetTime - ((real_T)adj) * tmp; 
 
    /* 
    if (isclose(tmp, 0.0)) { 
      reverse[i] = 0; 
    } else if (isclose(tmp, offsetTime - ((real_T)(((int_T)(offsetTime/tmp/2)))) * tmp * 2)) { 
    mexPrintf("offsetTime=%f, increment[%d]=%f.",offsetTime,i,increment[i]); 
    */ 
 
    if (increment[i] > offsetTime - 2 * increment[i] * floor(offsetTime/2./increment[i])) { 
      reverse[i] = 0; 
    } else { 
      reverse[i] = 1; 
    } 
#ifdef MATLAB_MEX_FILE 
    if (0) { 
      char_T err_msg[255]; 
      sprintf(err_msg, "reverse[%d]=%d; \n", i, reverse[i]); 
      mexPrintf(err_msg); 
    } 
#endif 
    adj_offset[i] = tmp; 
    if (tmp > 0) 
      tol = (tol < tmp) ? tol : tmp;         
  } 
#ifdef MATLAB_MEX_FILE 
  if (0) { 
    char_T err_msg[255]; 
    sprintf(err_msg, "\n"); 
    mexPrintf(err_msg); 
  } 
#endif 
  *hit_base = offsetMin + sampleTime; 
  *hit_base = sampleTime; 
  *tolerance = tol / 100; 
} 
 
/* 
 * mdlOutputs - computes the outputs of the S-Function 
 */ 
 
static void mdlOutputs(real_T *y, const real_T *x, const real_T *u, SimStruct *S, int_T tid) 
{ 
  int_T dividerSize = mxGetN(DIVIDER_EACH) * mxGetM(DIVIDER_EACH); 
  real_T *hit_base      = ssGetRWork(S); 
  real_T *next_hit      = ssGetRWork(S) + 1;     
  real_T *last_value    = ssGetRWork(S) + dividerSize + 1; 
  real_T *increment     = ssGetRWork(S) + dividerSize * 2 + 1; 
  real_T *adj_offset    = ssGetRWork(S) + dividerSize * 3 + 1; 
  real_T *tolerance     = ssGetRWork(S) + dividerSize * 4 + 1; 
  int_T    *reverse = ssGetIWork(S); 
   
  real_T time_clock, tol; 
  int_T i; 
   
  tol = *tolerance; 
   
  time_clock = ssGetT(S) + tol; 
  for (i = 0; i < dividerSize; i++) { 
    if (time_clock >= next_hit[i]) { 
      int_T    num; 
      real_T sampleTime; 
       
      sampleTime = mxGetPr(SAMPLE_TIME)[0];         
      num = (int_T)((time_clock - *hit_base - adj_offset[i] - sampleTime) / increment[i]); 
      num = num%2; 
      if (num) 
	last_value[i] = 1.; 
      else 
	last_value[i] = 0.; 
#ifdef MATLAB_MEX_FILE 
      if (0) { 
	char_T err_msg[255]; 
	sprintf(err_msg, "reverse[%d]=%d; last_value=%d; \n", i, reverse[i], (int_T)last_value[i]); 
	mexPrintf(err_msg); 
      } 
#endif 
      if (reverse[i]) 
	last_value[i] = ((int_T)last_value[i] + 1) % 2; 
#ifdef MATLAB_MEX_FILE 
      if (0) { 
	char_T err_msg[255]; 
	sprintf(err_msg, "new_last_value=%d;\n ", (int_T)last_value[i]); 
	mexPrintf(err_msg); 
      } 
#endif 
      next_hit[i] = next_hit[i] + increment[i]; 
    } 
    y[i] = last_value[i]; 
  } 
   
  /*    sprintf(err_msg, "\n "); 
	mexPrintf(err_msg); 
	 
	for (i = 0; i < dividerSize; i++) { 
	sprintf(err_msg, "output_y[%d]= %f, \", i, y[i]); 
	mexPrintf(err_msg); 
	} 
	*/ 
  /* adjust the "current hit" every sample cycle.    */ 
  if (time_clock > *hit_base){ 
    real_T sampleTime; 
    sampleTime = mxGetPr(SAMPLE_TIME)[0];         
    for (i = 0; i < dividerSize; i++) { 
      if (time_clock > mxGetPr(OFFSET_EACH)[i]) { 
	 
	if (adj_offset[i] <= 0) { 
	  next_hit[i] = *hit_base + increment[i]; 
	} else { 
	  next_hit[i] = *hit_base + adj_offset[i]; 
	} 
      } 
    } 
    *hit_base = *hit_base +sampleTime;         
  }     
} 
 
/* 
 * mdlUpdate - computes the discrete states of the S-Function 
 */ 
 
static void mdlUpdate(real_T *x, const real_T *u, SimStruct *S, int_T tid) 
{ 
} 
 
/* 
 * mdlDerivatives - computes the derivatives of the S-Function 
 */ 
 
static void mdlDerivatives(real_T *dx, const real_T *x, const real_T *u, SimStruct *S, int_T tid) 
{ 
} 
 
/* 
 * mdlTerminate - called at termination of model execution. 
 */ 
 
static void mdlTerminate(SimStruct *S) 
{ 
} 
 
#ifdef     MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */ 
#include "simulink.c"      /* MEX-File interface mechanism */ 
#else 
#include "cg_sfun.h"       /* Code generation registration function */ 
#endif