regshift.c
Upload User: loeagle
Upload Date: 2013-03-02
Package Size: 1236k
Code Size: 8k
Development Platform:

Matlab

  1. /* $Revision: 1.21 $ */
  2. /*
  3.  * REGSHIFT   A Simulink triggered register_buff shift
  4.  *
  5.  *           Syntax:  [sys, x0] = regshift(t,x,u,flag,outDelay,tirgThreshold)
  6.  *  This function has two inputs and a number of outputs. The first input is
  7.  *  the signal to be stored and output. The second signal is the clock pulse.
  8.  *  The function refreshes its register_buff and outputs only at the rising 
  9.  *  edge of the clock pulse. The function assigns a maximum delay number in 
  10.  *  outDelay as its register numebr. When the function finishes refreshing all
  11.  *  registers, it is called a cycle.
  12.  *
  13.  *  outDelay is a scalar or vector which contains integers of desired delay
  14.  *           steps from the input. The size of the vector determines the
  15.  *           size of the output.
  16.  *  trigThreshold is the threshold in detecting the rising edge of the clock
  17.  *          pulse.
  18.  *  The size of the output of this function is the size of outDelay pulse one.
  19.  *  Each output element outputs the delay step as indicated in the corrsponding
  20.  *  value in outDelay. The last output is zero and is one only at the time when
  21.  *  the register_buff and output are triggered in a complete cycle (a cycle of
  22.  *  complete a refresh cycle). The pulse keeps the same length as the input
  23.  *  trigger pulse.
  24.  *
  25.  * Wes Wang  August 22, 1994
  26.  * Copyright 1996-2001 The MathWorks, Inc.
  27.  */
  28. #define S_FUNCTION_NAME regshift
  29. #ifdef MATLAB_MEX_FILE
  30. #include "mex.h"      /* needed for declaration of mexErrMsgTxt */
  31. #endif
  32. /*
  33.  * need to include simstruc.h for the definition of the SimStruct and
  34.  * its associated macro definitions.
  35.  */
  36. #include "simstruc.h"
  37. #include "tmwtypes.h"
  38. /* For RTW */
  39. #if defined(RT) || defined(NRT)  
  40. #undef  mexPrintf
  41. #define mexPrintf printf
  42. #endif
  43. /*
  44.  * Defines for easy access of the input parameters
  45.  */
  46. #define NUM_ARGS   2
  47. #define REGISTER_DELAY ssGetArg(S,0)
  48. #define TRIG_THRESHOLD     ssGetArg(S,1)
  49. /*
  50.  * mdlInitializeSizes - called to initialize the sizes array stored in
  51.  *                      the SimStruct.  The sizes array defines the
  52.  *                      characteristics (number of inputs, outputs,
  53.  *                      states, etc.) of the S-Function.
  54.  */
  55. static void mdlInitializeSizes(SimStruct *S)
  56. {
  57.     /*
  58.      * Set-up size information.
  59.      */ 
  60.     
  61.     if (ssGetNumArgs(S) == NUM_ARGS) {
  62.       int_T i, regDelay, numOutput, maxDelay;
  63.       numOutput = mxGetN(REGISTER_DELAY) * mxGetM(REGISTER_DELAY);
  64.       if (numOutput < 1) {
  65. #ifdef MATLAB_MEX_FILE
  66.         char_T err_msg[256];
  67.         sprintf(err_msg, "Output buffer is empty");
  68.         mexErrMsgTxt(err_msg);
  69. #endif  
  70.       }
  71.        
  72.       maxDelay = 1;
  73.       for(i=0; i<numOutput; i++) {
  74.         regDelay = (int_T)(mxGetPr(REGISTER_DELAY)[i]);
  75.         maxDelay = (maxDelay > regDelay) ? maxDelay : regDelay;
  76.       }
  77.       ssSetNumContStates(    S, 0);
  78.       ssSetNumDiscStates(    S, 0);
  79.       ssSetNumInputs(        S, 2);
  80.       ssSetNumOutputs(       S, 1 + numOutput);
  81.       ssSetDirectFeedThrough(S, 1);
  82.       ssSetNumInputArgs(     S, NUM_ARGS);
  83.       ssSetNumSampleTimes(   S, 1);
  84.       ssSetNumRWork(         S, maxDelay+1);
  85.       ssSetNumIWork(         S, 2);
  86.       ssSetNumPWork(         S, 0);
  87.     } else {
  88. #ifdef MATLAB_MEX_FILE
  89.       char_T err_msg[256];
  90.       sprintf(err_msg, "Wrong number of input arguments passed to S-function MEX-file.n"
  91.          "%d input arguments were passed in when expecting %d input arguments.n", ssGetNumArgs(S) + 4, NUM_ARGS + 4);
  92.       mexErrMsgTxt(err_msg);
  93. #endif
  94.    }
  95. }
  96. /*
  97.  * mdlInitializeSampleTimes - initializes the array of sample times stored in
  98.  *                            the SimStruct associated with this S-Function.
  99.  */
  100. static void mdlInitializeSampleTimes(SimStruct *S)
  101. {
  102.     /*
  103.      * Note, blocks that are continuous in nature should have a single
  104.      * sample time of 0.0.
  105.      */
  106.     ssSetSampleTimeEvent(S, 0, INHERITED_SAMPLE_TIME);
  107.     ssSetOffsetTimeEvent(S, 0, FIXED_IN_MINOR_STEP_OFFSET);
  108. }
  109. /*
  110.  * mdlInitializeConditions - initializes the states for the S-Function
  111.  */
  112. static void mdlInitializeConditions(real_T *x0, SimStruct *S)
  113. {
  114.     real_T *register_buff       = ssGetRWork(S);
  115.     int_T    *regIndex       = ssGetIWork(S);
  116.     int_T    *lastTrig       = ssGetIWork(S) + 1;    
  117.     int_T     numOutput      = ssGetNumOutputs(S);
  118.     int_T     maxDelay       = ssGetNumRWork(S) - 1;
  119.     
  120.     real_T *lastTime       = ssGetRWork(S) + maxDelay;
  121.     
  122.     int_T i;
  123.     
  124.     /* 
  125.      * Initialize the register_buff to all zeros.
  126.      */
  127.     
  128.     for (i = 0; i < maxDelay; i++)
  129.      *register_buff++ = 0.0;
  130.     /*
  131.      * Initialize the current buffer position and buffer start
  132.      */
  133.     
  134.     *regIndex       = 0;
  135.     *lastTrig       = 0;
  136.     *lastTime       = -1.0;
  137. }
  138. /*
  139.  * mdlOutputs - computes the outputs of the S-Function
  140.  */
  141. static void mdlOutputs(real_T *y, const real_T *x, const real_T *u, SimStruct *S, int_T tid)
  142. {
  143.     real_T *register_buff        = ssGetRWork(S);
  144.     real_T  trigThreshold   = mxGetPr(TRIG_THRESHOLD)[0];
  145.     int_T    *regIndex        = ssGetIWork(S);
  146.     int_T    *lastTrig        = ssGetIWork(S) + 1;    
  147.     int_T     numOutput       = ssGetNumOutputs(S) - 1;
  148.     int_T     maxDelay        = ssGetNumRWork(S) - 1;
  149.     real_T *lastTime        = ssGetRWork(S) + maxDelay;
  150.     
  151.     int_T     i, outnum;
  152.     real_T  currentTime     = ssGetT(S);
  153.     /*
  154.      * acquire the buffer data
  155.      */
  156.     if ((u[1] >= trigThreshold) & (*lastTrig == 0)) {
  157.       for (i = 0; i < numOutput; i++) {
  158.         outnum = (int_T)(mxGetPr(REGISTER_DELAY)[i]);
  159.         if (outnum == 0)
  160.           y[i] = *u;
  161.         else
  162.           y[i] = register_buff[(maxDelay + *regIndex - outnum) % maxDelay];
  163.       }
  164.       if (*regIndex == 0)
  165.         y[numOutput] = 1.0;
  166.       else
  167.         y[numOutput] = 0.0;
  168.         
  169.       register_buff[(*regIndex)++] = *u;
  170.       *regIndex %= maxDelay;
  171.       *lastTrig = 1;
  172.       *lastTime = currentTime;
  173.      } else {
  174.       if (currentTime <= 0.0) {
  175.         for (i = 0; i < numOutput; i++)
  176.           y[i] = 0.0;
  177.       } else if ((currentTime - *lastTime) / currentTime < 0.00000001) {
  178.         /* keep the most recent change in the buffer */
  179.         /* this is backup the case when there are tow calls at the same time.
  180.          * the two values of the same time are different.
  181.          * This is assume the time variable is always increasing
  182.          */
  183.         if (u[1] >= trigThreshold) {
  184.           int_T backIndex;
  185.           backIndex = *regIndex - 1;
  186.           if (backIndex < 0)
  187.             backIndex = maxDelay - 1;                
  188.           for (i = 0; i < numOutput; i++) {
  189.             outnum = (int_T)(mxGetPr(REGISTER_DELAY)[i]);
  190.             if (outnum == 0)
  191.               y[i] = *u;
  192.           }
  193.           if (backIndex == 0)
  194.             y[numOutput] = 1.0;
  195.           else
  196.             y[numOutput] = 0.0;         
  197.           register_buff[backIndex] = *u;
  198.         }
  199.       }
  200.       if (*lastTrig == 1) {
  201.         if (u[1] < trigThreshold) {
  202.           *lastTrig = 0;
  203.           y[numOutput] = 0.0;
  204.         }
  205.       }
  206.     }
  207. }
  208. /*
  209.  * mdlUpdate - computes the discrete states of the S-Function
  210.  */
  211. static void mdlUpdate(real_T *x, const real_T *u, SimStruct *S, int_T tid)
  212. {
  213. }
  214. /*
  215.  * mdlDerivatives - computes the derivatives of the S-Function
  216.  */
  217. static void mdlDerivatives(real_T *dx, const real_T *x, const real_T *u, SimStruct *S, int_T tid)
  218. {
  219. }
  220. /*
  221.  * mdlTerminate - called at termination of model execution.
  222.  */
  223. static void mdlTerminate(SimStruct *S)
  224. {
  225. }
  226. #ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
  227. #include "simulink.c"      /* MEX-File interface mechanism */
  228. #else
  229. #include "cg_sfun.h"       /* Code generation registration function */
  230. #endif